Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 5 additions & 45 deletions core/src/main/java/com/google/googlejavaformat/java/Formatter.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@

package com.google.googlejavaformat.java;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Range;
import com.google.common.collect.RangeSet;
Expand All @@ -31,25 +29,14 @@
import com.google.googlejavaformat.Newlines;
import com.google.googlejavaformat.Op;
import com.google.googlejavaformat.OpsBuilder;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.parser.JavacParser;
import com.sun.tools.javac.parser.ParserFactory;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Options;
import java.io.IOError;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardLocation;

/**
* This is google-java-format, a new Java formatter that follows the Google Java Style Guide quite
Expand Down Expand Up @@ -112,40 +99,13 @@ public Formatter(JavaFormatterOptions options) {
static void format(final JavaInput javaInput, JavaOutput javaOutput, JavaFormatterOptions options)
throws FormatterException {
Context context = new Context();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
context.put(DiagnosticListener.class, diagnostics);
Options.instance(context).put("allowStringFolding", "false");
Options.instance(context).put("--enable-preview", "true");
JCCompilationUnit unit;
JavacFileManager fileManager = new JavacFileManager(context, true, UTF_8);
try {
fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, ImmutableList.of());
} catch (IOException e) {
// impossible
throw new IOError(e);
}
SimpleJavaFileObject source =
new SimpleJavaFileObject(URI.create("source"), JavaFileObject.Kind.SOURCE) {
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return javaInput.getText();
}
};
Log.instance(context).useSource(source);
ParserFactory parserFactory = ParserFactory.instance(context);
JavacParser parser =
parserFactory.newParser(
javaInput.getText(),
/* keepDocComments= */ true,
/* keepEndPos= */ true,
/* keepLineMap= */ true);
unit = parser.parseCompilationUnit();
unit.sourcefile = source;
List<Diagnostic<? extends JavaFileObject>> errorDiagnostics = new ArrayList<>();
JCCompilationUnit unit =
Trees.parse(
context, errorDiagnostics, /* allowStringFolding= */ false, javaInput.getText());

javaInput.setCompilationUnit(unit);
Iterable<Diagnostic<? extends JavaFileObject>> errorDiagnostics =
Iterables.filter(diagnostics.getDiagnostics(), Formatter::errorDiagnostic);
if (!Iterables.isEmpty(errorDiagnostics)) {
if (!errorDiagnostics.isEmpty()) {
throw FormatterException.fromJavacDiagnostics(errorDiagnostics);
}
OpsBuilder builder = new OpsBuilder(javaInput, javaOutput);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@

package com.google.googlejavaformat.java;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.Locale.ENGLISH;

import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.googlejavaformat.FormatterDiagnostic;
import java.util.List;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -49,9 +49,11 @@ public List<FormatterDiagnostic> diagnostics() {
}

public static FormatterException fromJavacDiagnostics(
Iterable<Diagnostic<? extends JavaFileObject>> diagnostics) {
List<Diagnostic<? extends JavaFileObject>> diagnostics) {
return new FormatterException(
Iterables.transform(diagnostics, FormatterException::toFormatterDiagnostic));
diagnostics.stream()
.map(FormatterException::toFormatterDiagnostic)
.collect(toImmutableList()));
}

private static FormatterDiagnostic toFormatterDiagnostic(Diagnostic<?> input) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,9 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.googlejavaformat.java.Trees.getEndPosition;
import static java.lang.Math.max;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.CharMatcher;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Range;
import com.google.common.collect.RangeMap;
Expand All @@ -43,32 +40,21 @@
import com.sun.source.util.TreePathScanner;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.parser.JavacParser;
import com.sun.tools.javac.parser.ParserFactory;
import com.sun.tools.javac.tree.DCTree;
import com.sun.tools.javac.tree.DCTree.DCReference;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCImport;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Options;
import java.io.IOError;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardLocation;
import org.jspecify.annotations.Nullable;

/**
Expand Down Expand Up @@ -231,38 +217,10 @@ public static String removeUnusedImports(final String contents) throws Formatter

private static JCCompilationUnit parse(Context context, String javaInput)
throws FormatterException {
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
context.put(DiagnosticListener.class, diagnostics);
Options.instance(context).put("--enable-preview", "true");
Options.instance(context).put("allowStringFolding", "false");
JCCompilationUnit unit;
JavacFileManager fileManager = new JavacFileManager(context, true, UTF_8);
try {
fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, ImmutableList.of());
} catch (IOException e) {
// impossible
throw new IOError(e);
}
SimpleJavaFileObject source =
new SimpleJavaFileObject(URI.create("source"), JavaFileObject.Kind.SOURCE) {
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return javaInput;
}
};
Log.instance(context).useSource(source);
ParserFactory parserFactory = ParserFactory.instance(context);
JavacParser parser =
parserFactory.newParser(
javaInput,
/* keepDocComments= */ true,
/* keepEndPos= */ true,
/* keepLineMap= */ true);
unit = parser.parseCompilationUnit();
unit.sourcefile = source;
Iterable<Diagnostic<? extends JavaFileObject>> errorDiagnostics =
Iterables.filter(diagnostics.getDiagnostics(), Formatter::errorDiagnostic);
if (!Iterables.isEmpty(errorDiagnostics)) {
List<Diagnostic<? extends JavaFileObject>> errorDiagnostics = new ArrayList<>();
JCTree.JCCompilationUnit unit =
Trees.parse(context, errorDiagnostics, /* allowStringFolding= */ false, javaInput);
if (!errorDiagnostics.isEmpty()) {
// error handling is done during formatting
throw FormatterException.fromJavacDiagnostics(errorDiagnostics);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@
import static com.google.googlejavaformat.java.Trees.getEndPosition;
import static com.google.googlejavaformat.java.Trees.getStartPosition;
import static java.lang.Math.min;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.joining;

import com.google.common.base.CharMatcher;
import com.google.common.base.Strings;
import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Range;
import com.google.common.collect.TreeRangeMap;
import com.google.googlejavaformat.Newlines;
Expand All @@ -37,17 +35,9 @@
import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.TreePath;
import com.sun.source.util.TreePathScanner;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.parser.JavacParser;
import com.sun.tools.javac.parser.ParserFactory;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Options;
import com.sun.tools.javac.util.Position;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URI;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
Expand All @@ -56,11 +46,7 @@
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardLocation;

/** Wraps string literals that exceed the column limit. */
public final class StringWrapper {
Expand Down Expand Up @@ -480,34 +466,11 @@ private static boolean needWrapping(int columnLimit, String input) {
/** Parses the given Java source. */
private static JCTree.JCCompilationUnit parse(String source, boolean allowStringFolding)
throws FormatterException {
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
List<Diagnostic<? extends JavaFileObject>> errorDiagnostics = new ArrayList<>();
Context context = new Context();
context.put(DiagnosticListener.class, diagnostics);
Options.instance(context).put("--enable-preview", "true");
Options.instance(context).put("allowStringFolding", Boolean.toString(allowStringFolding));
JavacFileManager fileManager = new JavacFileManager(context, true, UTF_8);
try {
fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, ImmutableList.of());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
SimpleJavaFileObject sjfo =
new SimpleJavaFileObject(URI.create("source"), JavaFileObject.Kind.SOURCE) {
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return source;
}
};
Log.instance(context).useSource(sjfo);
ParserFactory parserFactory = ParserFactory.instance(context);
JavacParser parser =
parserFactory.newParser(
source, /* keepDocComments= */ true, /* keepEndPos= */ true, /* keepLineMap= */ true);
JCTree.JCCompilationUnit unit = parser.parseCompilationUnit();
unit.sourcefile = sjfo;
Iterable<Diagnostic<? extends JavaFileObject>> errorDiagnostics =
Iterables.filter(diagnostics.getDiagnostics(), Formatter::errorDiagnostic);
if (!Iterables.isEmpty(errorDiagnostics)) {
JCTree.JCCompilationUnit unit =
Trees.parse(context, errorDiagnostics, allowStringFolding, source);
if (!errorDiagnostics.isEmpty()) {
// error handling is done during formatting
throw FormatterException.fromJavacDiagnostics(errorDiagnostics);
}
Expand Down
68 changes: 68 additions & 0 deletions core/src/main/java/com/google/googlejavaformat/java/Trees.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@

package com.google.googlejavaformat.java;

import static com.google.googlejavaformat.java.Trees.getEndPosition;
import static com.google.googlejavaformat.java.Trees.getStartPosition;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.CompoundAssignmentTree;
Expand All @@ -24,13 +29,26 @@
import com.sun.source.tree.ParenthesizedTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.parser.JavacParser;
import com.sun.tools.javac.parser.ParserFactory;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.Pretty;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Options;
import java.io.IOError;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import javax.lang.model.element.Name;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardLocation;

/** Utilities for working with {@link Tree}s. */
class Trees {
Expand Down Expand Up @@ -118,4 +136,54 @@ static ClassTree getEnclosingTypeDeclaration(TreePath path) {
static ExpressionTree skipParen(ExpressionTree node) {
return ((ParenthesizedTree) node).getExpression();
}

static JCCompilationUnit parse(
Context context,
List<Diagnostic<? extends JavaFileObject>> errorDiagnostics,
boolean allowStringFolding,
String javaInput) {
DiagnosticListener<JavaFileObject> diagnostics =
diagnostic -> {
if (errorDiagnostic(diagnostic)) {
errorDiagnostics.add(diagnostic);
}
};
context.put(DiagnosticListener.class, diagnostics);
Options.instance(context).put("--enable-preview", "true");
Options.instance(context).put("allowStringFolding", Boolean.toString(allowStringFolding));
JavacFileManager fileManager = new JavacFileManager(context, /* register= */ true, UTF_8);
try {
fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, ImmutableList.of());
} catch (IOException e) {
// impossible
throw new IOError(e);
}
SimpleJavaFileObject source =
new SimpleJavaFileObject(URI.create("source"), JavaFileObject.Kind.SOURCE) {
@Override
public String getCharContent(boolean ignoreEncodingErrors) {
return javaInput;
}
};
Log.instance(context).useSource(source);
ParserFactory parserFactory = ParserFactory.instance(context);
JavacParser parser =
parserFactory.newParser(
javaInput,
/* keepDocComments= */ true,
/* keepEndPos= */ true,
/* keepLineMap= */ true);
JCCompilationUnit unit = parser.parseCompilationUnit();
unit.sourcefile = source;
return unit;
}

private static boolean errorDiagnostic(Diagnostic<?> input) {
if (input.getKind() != Diagnostic.Kind.ERROR) {
return false;
}
// accept constructor-like method declarations that don't match the name of their
// enclosing class
return !input.getCode().equals("compiler.err.invalid.meth.decl.ret.type.req");
}
}