Skip to content

Commit

Permalink
Add initial support for Java 14 language features
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=303367644
  • Loading branch information
cushon authored and nick-someone committed Mar 30, 2020
1 parent b810032 commit 4ddb914
Show file tree
Hide file tree
Showing 13 changed files with 439 additions and 36 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ notifications:

jdk:
- openjdk11
- openjdk14
- openjdk-ea

matrix:
Expand Down
28 changes: 28 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -256,4 +256,32 @@
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>jdk11</id>
<activation>
<jdk>(,14)</jdk>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/Java14InputAstVisitor.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<excludePackageNames>com.google.googlejavaformat.java.java14</excludePackageNames>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

package com.google.googlejavaformat.java;

import static com.google.common.base.StandardSystemProperty.JAVA_CLASS_VERSION;
import static com.google.common.base.StandardSystemProperty.JAVA_SPECIFICATION_VERSION;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
Expand All @@ -40,6 +42,7 @@
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.Collection;
Expand Down Expand Up @@ -115,6 +118,7 @@ static void format(final JavaInput javaInput, JavaOutput javaOutput, JavaFormatt
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 {
Expand Down Expand Up @@ -149,7 +153,21 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept
}
OpsBuilder builder = new OpsBuilder(javaInput, javaOutput);
// Output the compilation unit.
new JavaInputAstVisitor(builder, options.indentationMultiplier()).scan(unit, null);
JavaInputAstVisitor visitor;
if (getMajor() >= 14) {
try {
visitor =
Class.forName("com.google.googlejavaformat.java.java14.Java14InputAstVisitor")
.asSubclass(JavaInputAstVisitor.class)
.getConstructor(OpsBuilder.class, int.class)
.newInstance(builder, options.indentationMultiplier());
} catch (ReflectiveOperationException e) {
throw new LinkageError(e.getMessage(), e);
}
} else {
visitor = new JavaInputAstVisitor(builder, options.indentationMultiplier());
}
visitor.scan(unit, null);
builder.sync(javaInput.getText().length());
builder.drain();
Doc doc = new DocBuilder().withOps(builder.build()).build();
Expand All @@ -158,6 +176,23 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept
javaOutput.flush();
}

// Runtime.Version was added in JDK 9, so use reflection to access it to preserve source
// compatibility with Java 8.
private static int getMajor() {
try {
Method versionMethod = Runtime.class.getMethod("version");
Object version = versionMethod.invoke(null);
return (int) version.getClass().getMethod("major").invoke(version);
} catch (Exception e) {
// continue below
}
int version = (int) Double.parseDouble(JAVA_CLASS_VERSION.value());
if (49 <= version && version <= 52) {
return version - (49 - 5);
}
throw new IllegalStateException("Unknown Java version: " + JAVA_SPECIFICATION_VERSION.value());
}

static boolean errorDiagnostic(Diagnostic<?> input) {
if (input.getKind() != Diagnostic.Kind.ERROR) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Log.DeferredDiagnosticHandler;
import com.sun.tools.javac.util.Options;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
Expand Down Expand Up @@ -347,6 +348,7 @@ static ImmutableList<Tok> buildToks(String text, ImmutableSet<TokenKind> stopTok
throws FormatterException {
stopTokens = ImmutableSet.<TokenKind>builder().addAll(stopTokens).add(TokenKind.EOF).build();
Context context = new Context();
Options.instance(context).put("--enable-preview", "true");
new JavacFileManager(context, true, UTF_8);
DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>();
context.put(DiagnosticListener.class, diagnosticCollector);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
import com.sun.source.util.TreePathScanner;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.TreeScanner;
import java.util.ArrayDeque;
import java.util.ArrayList;
Expand All @@ -154,10 +155,10 @@
* An AST visitor that builds a stream of {@link Op}s to format from the given {@link
* CompilationUnitTree}.
*/
public final class JavaInputAstVisitor extends TreePathScanner<Void, Void> {
public class JavaInputAstVisitor extends TreePathScanner<Void, Void> {

/** Direction for Annotations (usually VERTICAL). */
enum Direction {
protected enum Direction {
VERTICAL,
HORIZONTAL;

Expand Down Expand Up @@ -211,7 +212,7 @@ static AllowTrailingBlankLine valueOf(boolean b) {
}

/** Whether to include braces. */
enum BracesOrNot {
protected enum BracesOrNot {
YES,
NO;

Expand Down Expand Up @@ -259,7 +260,7 @@ boolean isYes() {
}

/** Whether these declarations are the first in the block. */
enum FirstDeclarationsOrNot {
protected enum FirstDeclarationsOrNot {
YES,
NO;

Expand All @@ -268,14 +269,14 @@ boolean isYes() {
}
}

private final OpsBuilder builder;
protected final OpsBuilder builder;

private static final Indent.Const ZERO = Indent.Const.ZERO;
private final int indentMultiplier;
private final Indent.Const minusTwo;
private final Indent.Const minusFour;
private final Indent.Const plusTwo;
private final Indent.Const plusFour;
protected static final Indent.Const ZERO = Indent.Const.ZERO;
protected final int indentMultiplier;
protected final Indent.Const minusTwo;
protected final Indent.Const minusFour;
protected final Indent.Const plusTwo;
protected final Indent.Const plusFour;

private static final ImmutableList<Op> breakList(Optional<BreakTag> breakTag) {
return ImmutableList.of(Doc.Break.make(Doc.FillMode.UNIFIED, " ", ZERO, breakTag));
Expand Down Expand Up @@ -382,7 +383,7 @@ public Void visitCompilationUnit(CompilationUnitTree node, Void unused) {
}

/** Skips over extra semi-colons at the top-level, or in a class member declaration lists. */
private void dropEmptyDeclarations() {
protected void dropEmptyDeclarations() {
if (builder.peekToken().equals(Optional.of(";"))) {
while (builder.peekToken().equals(Optional.of(";"))) {
builder.forcedBreak();
Expand Down Expand Up @@ -1331,12 +1332,19 @@ public Void visitAnnotatedType(AnnotatedTypeTree node, Void unused) {
return null;
}

// TODO(cushon): Use Flags.COMPACT_RECORD_CONSTRUCTOR once if/when we drop support for Java 11
protected static final long COMPACT_RECORD_CONSTRUCTOR = 1L << 51;

@Override
public Void visitMethod(MethodTree node, Void unused) {
sync(node);
List<? extends AnnotationTree> annotations = node.getModifiers().getAnnotations();
List<? extends AnnotationTree> returnTypeAnnotations = ImmutableList.of();

boolean isRecordConstructor =
(((JCMethodDecl) node).mods.flags & COMPACT_RECORD_CONSTRUCTOR)
== COMPACT_RECORD_CONSTRUCTOR;

if (!node.getTypeParameters().isEmpty() && !annotations.isEmpty()) {
int typeParameterStart = getStartPosition(node.getTypeParameters().get(0));
for (int i = 0; i < annotations.size(); i++) {
Expand Down Expand Up @@ -1406,7 +1414,9 @@ public Void visitMethod(MethodTree node, Void unused) {
name = builder.peekToken().get();
}
token(name);
token("(");
if (!isRecordConstructor) {
token("(");
}
// end of name and type scope
builder.close();
}
Expand All @@ -1416,12 +1426,14 @@ public Void visitMethod(MethodTree node, Void unused) {
builder.open(Indent.If.make(breakBeforeType, plusFour, ZERO));
builder.open(ZERO);
{
if (!node.getParameters().isEmpty() || node.getReceiverParameter() != null) {
// Break before args.
builder.breakToFill("");
visitFormals(Optional.ofNullable(node.getReceiverParameter()), node.getParameters());
if (!isRecordConstructor) {
if (!node.getParameters().isEmpty() || node.getReceiverParameter() != null) {
// Break before args.
builder.breakToFill("");
visitFormals(Optional.ofNullable(node.getReceiverParameter()), node.getParameters());
}
token(")");
}
token(")");
if (dims != null) {
maybeAddDims(dims);
}
Expand Down Expand Up @@ -1795,17 +1807,22 @@ public Void visitCase(CaseTree node, Void unused) {
@Override
public Void visitSwitch(SwitchTree node, Void unused) {
sync(node);
visitSwitch(node.getExpression(), node.getCases());
return null;
}

protected void visitSwitch(ExpressionTree expression, List<? extends CaseTree> cases) {
token("switch");
builder.space();
token("(");
scan(skipParen(node.getExpression()), null);
scan(skipParen(expression), null);
token(")");
builder.space();
tokenBreakTrailingComment("{", plusTwo);
builder.blankLineWanted(BlankLineWanted.NO);
builder.open(plusTwo);
boolean first = true;
for (CaseTree caseTree : node.getCases()) {
for (CaseTree caseTree : cases) {
if (!first) {
builder.blankLineWanted(BlankLineWanted.PRESERVE);
}
Expand All @@ -1816,7 +1833,6 @@ public Void visitSwitch(SwitchTree node, Void unused) {
builder.forcedBreak();
builder.blankLineWanted(BlankLineWanted.NO);
token("}", plusFour);
return null;
}

@Override
Expand Down Expand Up @@ -2126,7 +2142,7 @@ private void visitStatement(
}
}

private void visitStatements(List<? extends StatementTree> statements) {
protected void visitStatements(List<? extends StatementTree> statements) {
boolean first = true;
PeekingIterator<StatementTree> it = Iterators.peekingIterator(statements.iterator());
dropEmptyDeclarations();
Expand Down Expand Up @@ -2164,15 +2180,15 @@ public Void visitModifiers(ModifiersTree node, Void unused) {
}

/** Output combined modifiers and annotations and returns the trailing break. */
private List<Op> visitModifiers(
protected List<Op> visitModifiers(
ModifiersTree modifiersTree,
Direction annotationsDirection,
Optional<BreakTag> declarationAnnotationBreak) {
return visitModifiers(
modifiersTree.getAnnotations(), annotationsDirection, declarationAnnotationBreak);
}

private List<Op> visitModifiers(
protected List<Op> visitModifiers(
List<? extends AnnotationTree> annotationTrees,
Direction annotationsDirection,
Optional<BreakTag> declarationAnnotationBreak) {
Expand Down Expand Up @@ -2339,7 +2355,7 @@ private static void walkInfix(
}
}

private void visitFormals(
protected void visitFormals(
Optional<VariableTree> receiver, List<? extends VariableTree> parameters) {
if (!receiver.isPresent() && parameters.isEmpty()) {
return;
Expand Down Expand Up @@ -2559,7 +2575,7 @@ private void visitToDeclare(
}

/** Does not omit the leading '<', which should be associated with the type name. */
private void typeParametersRest(
protected void typeParametersRest(
List<? extends TypeParameterTree> typeParameters, Indent plusIndent) {
builder.open(plusIndent);
builder.breakOp();
Expand Down Expand Up @@ -3446,7 +3462,7 @@ private void declareMany(List<VariableTree> fragments, Direction annotationDirec
}

/** Add a list of declarations. */
void addBodyDeclarations(
protected void addBodyDeclarations(
List<? extends Tree> bodyDeclarations, BracesOrNot braces, FirstDeclarationsOrNot first0) {
if (bodyDeclarations.isEmpty()) {
if (braces.isYes()) {
Expand Down Expand Up @@ -3592,7 +3608,7 @@ private Direction fieldAnnotationDirection(ModifiersTree modifiers) {
*
* @param token the {@link String} to wrap in a {@link Doc.Token}
*/
final void token(String token) {
protected final void token(String token) {
builder.token(
token,
Doc.Token.RealOrImaginary.REAL,
Expand All @@ -3606,7 +3622,7 @@ final void token(String token) {
* @param token the {@link String} to wrap in a {@link Doc.Token}
* @param plusIndentCommentsBefore extra indent for comments before this token
*/
final void token(String token, Indent plusIndentCommentsBefore) {
protected final void token(String token, Indent plusIndentCommentsBefore) {
builder.token(
token,
Doc.Token.RealOrImaginary.REAL,
Expand All @@ -3620,7 +3636,7 @@ final void tokenBreakTrailingComment(String token, Indent breakAndIndentTrailing
token, Doc.Token.RealOrImaginary.REAL, ZERO, Optional.of(breakAndIndentTrailingComment));
}

private void markForPartialFormat() {
protected void markForPartialFormat() {
if (!inExpression()) {
builder.markForPartialFormat();
}
Expand All @@ -3632,7 +3648,7 @@ private void markForPartialFormat() {
*
* @param node the ASTNode holding the input position
*/
final void sync(Tree node) {
protected final void sync(Tree node) {
builder.sync(((JCTree) node).getStartPosition());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ private static JCTree.JCCompilationUnit parse(String source, boolean allowString
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
Context context = new Context();
context.put(DiagnosticListener.class, diagnostics);
Options.instance(context).put("--enable-preview", "true");
Options.instance(context).put("allowStringFolding", Boolean.toString(allowStringFolding));
JCTree.JCCompilationUnit unit;
JavacFileManager fileManager = new JavacFileManager(context, true, UTF_8);
Expand Down
Loading

0 comments on commit 4ddb914

Please sign in to comment.