diff --git a/src/main/java/com/google/api/generator/engine/ast/AstNodeVisitor.java b/src/main/java/com/google/api/generator/engine/ast/AstNodeVisitor.java index 4f885f01d7..3a7e2020d3 100644 --- a/src/main/java/com/google/api/generator/engine/ast/AstNodeVisitor.java +++ b/src/main/java/com/google/api/generator/engine/ast/AstNodeVisitor.java @@ -93,4 +93,6 @@ public interface AstNodeVisitor { public void visit(MethodDefinition methodDefinition); public void visit(ClassDefinition classDefinition); + + public void visit(PackageInfoDefinition packageInfoDefinition); } diff --git a/src/main/java/com/google/api/generator/engine/ast/PackageInfoDefinition.java b/src/main/java/com/google/api/generator/engine/ast/PackageInfoDefinition.java new file mode 100644 index 0000000000..f20495dd11 --- /dev/null +++ b/src/main/java/com/google/api/generator/engine/ast/PackageInfoDefinition.java @@ -0,0 +1,70 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.engine.ast; + +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@AutoValue +public abstract class PackageInfoDefinition implements AstNode { + public abstract String pakkage(); + + public abstract ImmutableList fileHeader(); + + public abstract ImmutableList headerCommentStatements(); + + public abstract ImmutableList annotations(); + + @Override + public void accept(AstNodeVisitor visitor) { + visitor.visit(this); + } + + public static Builder builder() { + return new AutoValue_PackageInfoDefinition.Builder() + .setFileHeader(Collections.emptyList()) + .setHeaderCommentStatements(Collections.emptyList()) + .setAnnotations(Collections.emptyList()); + } + + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder setPakkage(String pakkage); + + public Builder setFileHeader(CommentStatement... headerComments) { + return setFileHeader(Arrays.asList(headerComments)); + } + + public abstract Builder setFileHeader(List fileHeader); + + public Builder setHeaderCommentStatements(CommentStatement... comments) { + return setHeaderCommentStatements(Arrays.asList(comments)); + } + + public abstract Builder setHeaderCommentStatements( + List headerCommentStatements); + + public Builder setAnnotations(AnnotationNode... annotations) { + return setAnnotations(Arrays.asList(annotations)); + } + + public abstract Builder setAnnotations(List annotations); + + public abstract PackageInfoDefinition build(); + } +} diff --git a/src/main/java/com/google/api/generator/engine/writer/ImportWriterVisitor.java b/src/main/java/com/google/api/generator/engine/writer/ImportWriterVisitor.java index ce56787cfc..af456a33db 100644 --- a/src/main/java/com/google/api/generator/engine/writer/ImportWriterVisitor.java +++ b/src/main/java/com/google/api/generator/engine/writer/ImportWriterVisitor.java @@ -40,6 +40,7 @@ import com.google.api.generator.engine.ast.MethodDefinition; import com.google.api.generator.engine.ast.MethodInvocationExpr; import com.google.api.generator.engine.ast.NewObjectExpr; +import com.google.api.generator.engine.ast.PackageInfoDefinition; import com.google.api.generator.engine.ast.Reference; import com.google.api.generator.engine.ast.ReferenceConstructorExpr; import com.google.api.generator.engine.ast.RelationalOperationExpr; @@ -56,12 +57,15 @@ import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.engine.ast.WhileStatement; import com.google.common.base.Preconditions; +import com.google.common.base.Strings; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class ImportWriterVisitor implements AstNodeVisitor { private static final String NEWLINE = "\n"; @@ -71,14 +75,19 @@ public class ImportWriterVisitor implements AstNodeVisitor { private final Set imports = new TreeSet<>(); private String currentPackage; - private String currentClassName; + @Nullable private String currentClassName; public void clear() { staticImports.clear(); imports.clear(); } - public void initialize(String currentPackage, String currentClassName) { + public void initialize(@Nonnull String currentPackage) { + this.currentPackage = currentPackage; + this.currentClassName = null; + } + + public void initialize(@Nonnull String currentPackage, @Nonnull String currentClassName) { this.currentPackage = currentPackage; this.currentClassName = currentClassName; } @@ -370,6 +379,11 @@ public void visit(ClassDefinition classDefinition) { } } + @Override + public void visit(PackageInfoDefinition packageInfoDefinition) { + annotations(packageInfoDefinition.annotations()); + } + /** =============================== PRIVATE HELPERS =============================== */ private void annotations(List annotations) { for (AnnotationNode annotation : annotations) { @@ -407,7 +421,9 @@ private void references(List refs) { continue; } - if (ref.isStaticImport() && ref.enclosingClassName().equals(currentClassName)) { + if (ref.isStaticImport() + && !Strings.isNullOrEmpty(currentClassName) + && ref.enclosingClassName().equals(currentClassName)) { continue; } diff --git a/src/main/java/com/google/api/generator/engine/writer/JavaWriterVisitor.java b/src/main/java/com/google/api/generator/engine/writer/JavaWriterVisitor.java index c3e238a085..7c0ddc87d4 100644 --- a/src/main/java/com/google/api/generator/engine/writer/JavaWriterVisitor.java +++ b/src/main/java/com/google/api/generator/engine/writer/JavaWriterVisitor.java @@ -41,6 +41,7 @@ import com.google.api.generator.engine.ast.MethodInvocationExpr; import com.google.api.generator.engine.ast.NewObjectExpr; import com.google.api.generator.engine.ast.OperatorKind; +import com.google.api.generator.engine.ast.PackageInfoDefinition; import com.google.api.generator.engine.ast.ReferenceConstructorExpr; import com.google.api.generator.engine.ast.RelationalOperationExpr; import com.google.api.generator.engine.ast.ReturnExpr; @@ -859,6 +860,26 @@ public void visit(ClassDefinition classDefinition) { } } + @Override + public void visit(PackageInfoDefinition packageInfoDefinition) { + statements(packageInfoDefinition.fileHeader().stream().collect(Collectors.toList())); + newline(); + statements( + packageInfoDefinition.headerCommentStatements().stream().collect(Collectors.toList())); + newline(); + + annotations(packageInfoDefinition.annotations()); + buffer.append(String.format("package %s;", packageInfoDefinition.pakkage())); + newline(); + + packageInfoDefinition.accept(importWriterVisitor); + importWriterVisitor.initialize(packageInfoDefinition.pakkage()); + buffer.append(importWriterVisitor.write()); + + // Format code. + buffer.replace(0, buffer.length(), JavaFormatter.format(buffer.toString())); + } + /** =============================== PRIVATE HELPERS =============================== */ private void annotations(List annotations) { for (AnnotationNode annotation : annotations) { diff --git a/src/test/java/com/google/api/generator/engine/writer/ImportWriterVisitorTest.java b/src/test/java/com/google/api/generator/engine/writer/ImportWriterVisitorTest.java index e9801aa6d6..5463ac76ad 100644 --- a/src/test/java/com/google/api/generator/engine/writer/ImportWriterVisitorTest.java +++ b/src/test/java/com/google/api/generator/engine/writer/ImportWriterVisitorTest.java @@ -19,12 +19,15 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; +import com.google.api.generator.engine.ast.AnnotationNode; import com.google.api.generator.engine.ast.AnonymousClassExpr; import com.google.api.generator.engine.ast.ArithmeticOperationExpr; import com.google.api.generator.engine.ast.AssignmentExpr; import com.google.api.generator.engine.ast.AstNode; +import com.google.api.generator.engine.ast.BlockComment; import com.google.api.generator.engine.ast.CastExpr; import com.google.api.generator.engine.ast.ClassDefinition; +import com.google.api.generator.engine.ast.CommentStatement; import com.google.api.generator.engine.ast.ConcreteReference; import com.google.api.generator.engine.ast.EmptyLineStatement; import com.google.api.generator.engine.ast.EnumRefExpr; @@ -32,11 +35,13 @@ import com.google.api.generator.engine.ast.ExprStatement; import com.google.api.generator.engine.ast.IfStatement; import com.google.api.generator.engine.ast.InstanceofExpr; +import com.google.api.generator.engine.ast.JavaDocComment; import com.google.api.generator.engine.ast.LogicalOperationExpr; import com.google.api.generator.engine.ast.MethodDefinition; import com.google.api.generator.engine.ast.MethodInvocationExpr; import com.google.api.generator.engine.ast.NewObjectExpr; import com.google.api.generator.engine.ast.NullObjectValue; +import com.google.api.generator.engine.ast.PackageInfoDefinition; import com.google.api.generator.engine.ast.Reference; import com.google.api.generator.engine.ast.ReferenceConstructorExpr; import com.google.api.generator.engine.ast.RelationalOperationExpr; @@ -64,6 +69,7 @@ import java.util.List; import java.util.Map; import java.util.stream.LongStream; +import javax.annotation.Generated; import org.junit.Before; import org.junit.Test; @@ -1029,6 +1035,27 @@ public void writeEmptyLineStatementImports() { assertThat(writerVisitor.write()).isEmpty(); } + @Test + public void writePackageInfoDefinitionImports() { + PackageInfoDefinition packageInfo = + PackageInfoDefinition.builder() + .setPakkage("com.google.example.library.v1") + .setAnnotations( + AnnotationNode.withType( + TypeNode.withReference(ConcreteReference.withClazz(Generated.class)))) + .setFileHeader( + CommentStatement.withComment( + BlockComment.withComment("Lorum ipsum dolor sit amet"))) + .setHeaderCommentStatements( + CommentStatement.withComment( + JavaDocComment.withComment("Consecteteur adipisping elit"))) + .build(); + + packageInfo.accept(writerVisitor); + assertEquals(writerVisitor.write(), "import javax.annotation.Generated;\n\n"); + } + + /** =============================== HELPERS =============================== */ private static TypeNode createType(Class clazz) { return TypeNode.withReference(ConcreteReference.withClazz(clazz)); } diff --git a/src/test/java/com/google/api/generator/engine/writer/JavaWriterVisitorTest.java b/src/test/java/com/google/api/generator/engine/writer/JavaWriterVisitorTest.java index c10b4b62ac..10a08f6811 100644 --- a/src/test/java/com/google/api/generator/engine/writer/JavaWriterVisitorTest.java +++ b/src/test/java/com/google/api/generator/engine/writer/JavaWriterVisitorTest.java @@ -44,6 +44,7 @@ import com.google.api.generator.engine.ast.MethodInvocationExpr; import com.google.api.generator.engine.ast.NewObjectExpr; import com.google.api.generator.engine.ast.NullObjectValue; +import com.google.api.generator.engine.ast.PackageInfoDefinition; import com.google.api.generator.engine.ast.PrimitiveValue; import com.google.api.generator.engine.ast.Reference; import com.google.api.generator.engine.ast.ReferenceConstructorExpr; @@ -73,6 +74,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.TimeoutException; +import javax.annotation.Generated; import org.junit.Before; import org.junit.Test; @@ -2242,6 +2244,39 @@ public void writeEmptyLineStatement() { assertEquals(writerVisitor.write(), "\n"); } + @Test + public void writePackageInfoDefinition() { + PackageInfoDefinition packageInfo = + PackageInfoDefinition.builder() + .setPakkage("com.google.example.library.v1") + .setAnnotations( + AnnotationNode.withType( + TypeNode.withReference(ConcreteReference.withClazz(Generated.class)))) + .setFileHeader( + CommentStatement.withComment( + BlockComment.withComment("Lorum ipsum dolor sit amet"))) + .setHeaderCommentStatements( + CommentStatement.withComment( + JavaDocComment.withComment("Consecteteur adipisping elit"))) + .build(); + + packageInfo.accept(writerVisitor); + assertEquals( + String.format( + createLines(9), + "/*\n", + " * Lorum ipsum dolor sit amet\n", + " */\n", + "\n", + "/** Consecteteur adipisping elit */\n", + "@Generated\n", + "package com.google.example.library.v1;\n", + "\n", + "import javax.annotation.Generated;\n"), + writerVisitor.write()); + } + + /** =============================== HELPERS =============================== */ private static String createLines(int numLines) { return new String(new char[numLines]).replace("\0", "%s"); }