From 564f37f35f1dd85bcc22e775b9eb3631d865bdee Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Wed, 16 May 2018 11:19:49 -0400 Subject: [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a531637..9ef844c 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.squareup javapoet - 1.11.1 + 1.12.0-SNAPSHOT JavaPoet Use beautiful Java code to generate beautiful Java code. -- cgit v1.2.3 From 46a6a6e2db009e98fed755ecf95bc5264635840d Mon Sep 17 00:00:00 2001 From: Peter Donald Date: Wed, 11 Jul 2018 13:19:09 +1000 Subject: Replace incorrect usage of anonymousInnerClass --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1dffbad..788ce48 100644 --- a/README.md +++ b/README.md @@ -674,7 +674,7 @@ public enum Roshambo { ### Anonymous Inner Classes -In the enum code, we used `Types.anonymousInnerClass()`. Anonymous inner classes can also be used in +In the enum code, we used `TypeSpec.anonymousInnerClass()`. Anonymous inner classes can also be used in code blocks. They are values that can be referenced with `$L`: ```java -- cgit v1.2.3 From 4a7857e873c4d5f249bee373187289c2e1fa35ba Mon Sep 17 00:00:00 2001 From: Ron Shapiro Date: Wed, 1 Aug 2018 16:21:44 -0400 Subject: `java.lang.List` has no `size()` method ... but `java.util.List` does :) --- src/main/java/com/squareup/javapoet/TypeName.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/squareup/javapoet/TypeName.java b/src/main/java/com/squareup/javapoet/TypeName.java index 38877f7..c0986bb 100644 --- a/src/main/java/com/squareup/javapoet/TypeName.java +++ b/src/main/java/com/squareup/javapoet/TypeName.java @@ -44,7 +44,7 @@ import javax.lang.model.util.SimpleTypeVisitor8; * identifies composite types like {@code char[]} and {@code Set}. * *

Type names are dumb identifiers only and do not model the values they name. For example, the - * type name for {@code java.lang.List} doesn't know about the {@code size()} method, the fact that + * type name for {@code java.util.List} doesn't know about the {@code size()} method, the fact that * lists are collections, or even that it accepts a single type parameter. * *

Instances of this class are immutable value objects that implement {@code equals()} and {@code -- cgit v1.2.3 From dfb5bc6c4e0c33f0d40d02c9702089da8a848d2f Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Sun, 19 Aug 2018 23:10:39 +0200 Subject: Switch back to Travis CI managed "jdk" installations (#672) * Switch back to Travis CI managed "jdk" installations * Add openjdk-ea and update maven-compiler-plugin to 3.8.0 --- .travis.yml | 24 +++++++----------------- pom.xml | 2 +- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4e0a881..131324c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,27 +2,17 @@ language: java matrix: include: - - env: JDK='Oracle JDK 8' - jdk: oraclejdk8 - - env: JDK='Oracle JDK 9' - jdk: oraclejdk9 - - env: JDK='Oracle JDK 10' - install: . ./install-jdk.sh -F 10 -L BCL - - env: JDK='OpenJDK 10' - install: . ./install-jdk.sh -F 10 -L GPL - - env: JDK='Oracle JDK 11' - install: . ./install-jdk.sh -F 11 -L BCL - - env: JDK='OpenJDK 11' - install: . ./install-jdk.sh -F 11 -L GPL + - jdk: oraclejdk8 + - jdk: openjdk10 + - jdk: openjdk11 + - jdk: openjdk-ea allow_failures: - # ErrorProne/javac is not yet working on JDK 11 - - env: JDK='Oracle JDK 11' - - env: JDK='OpenJDK 11' + # ErrorProne/javac is not yet working on JDK 11 nor 12 (current -ea) + - jdk: openjdk11 + - jdk: openjdk-ea -# Direct usage of `install-jdk.sh` might be superseded by https://github.com/travis-ci/travis-build/pull/1347 before_install: - unset _JAVA_OPTIONS - - wget https://github.com/sormuras/bach/raw/1.0.1/install-jdk.sh after_success: - .buildscript/deploy_snapshot.sh diff --git a/pom.xml b/pom.xml index 9ef844c..15c1b77 100644 --- a/pom.xml +++ b/pom.xml @@ -94,7 +94,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.7.0 + 3.8.0 javac-with-errorprone true -- cgit v1.2.3 From 077bd8c26b4b509807bb3af96cc429e34982d927 Mon Sep 17 00:00:00 2001 From: danglotb Date: Fri, 10 Aug 2018 09:47:04 +0200 Subject: test: specify more toJavaIdentifier --- src/test/java/com/squareup/javapoet/NameAllocatorTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/com/squareup/javapoet/NameAllocatorTest.java b/src/test/java/com/squareup/javapoet/NameAllocatorTest.java index 1840107..71402c6 100644 --- a/src/test/java/com/squareup/javapoet/NameAllocatorTest.java +++ b/src/test/java/com/squareup/javapoet/NameAllocatorTest.java @@ -18,9 +18,11 @@ package com.squareup.javapoet; import org.junit.Test; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; public final class NameAllocatorTest { + @Test public void usage() throws Exception { NameAllocator nameAllocator = new NameAllocator(); assertThat(nameAllocator.newName("foo", 1)).isEqualTo("foo"); @@ -59,6 +61,7 @@ public final class NameAllocatorTest { @Test public void characterMappingInvalidStartButValidPart() throws Exception { NameAllocator nameAllocator = new NameAllocator(); assertThat(nameAllocator.newName("1ab", 1)).isEqualTo("_1ab"); + assertThat(nameAllocator.newName("a-1", 2)).isEqualTo("a_1"); } @Test public void characterMappingInvalidStartIsInvalidPart() throws Exception { -- cgit v1.2.3 From f1600e5cc03fcc8bc6757fd115e3de89c7dad6fd Mon Sep 17 00:00:00 2001 From: danglotb Date: Fri, 10 Aug 2018 10:25:36 +0200 Subject: test: improve test by checking the toString() of ParameterSpec implementation --- src/test/java/com/squareup/javapoet/ParameterSpecTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/com/squareup/javapoet/ParameterSpecTest.java b/src/test/java/com/squareup/javapoet/ParameterSpecTest.java index 2f81866..7ae4502 100644 --- a/src/test/java/com/squareup/javapoet/ParameterSpecTest.java +++ b/src/test/java/com/squareup/javapoet/ParameterSpecTest.java @@ -28,10 +28,12 @@ public class ParameterSpecTest { ParameterSpec b = ParameterSpec.builder(int.class, "foo").build(); assertThat(a.equals(b)).isTrue(); assertThat(a.hashCode()).isEqualTo(b.hashCode()); + assertThat(a.toString()).isEqualTo(b.toString()); a = ParameterSpec.builder(int.class, "i").addModifiers(Modifier.STATIC).build(); b = ParameterSpec.builder(int.class, "i").addModifiers(Modifier.STATIC).build(); assertThat(a.equals(b)).isTrue(); assertThat(a.hashCode()).isEqualTo(b.hashCode()); + assertThat(a.toString()).isEqualTo(b.toString()); } @Test public void nullAnnotationsAddition() { -- cgit v1.2.3 From 0cbc16df9213d64e6dfe389a2d164ab6f007121b Mon Sep 17 00:00:00 2001 From: danglotb Date: Fri, 10 Aug 2018 10:18:28 +0200 Subject: test: improve test by checking the toString() of FieldSpec implementation --- src/test/java/com/squareup/javapoet/FieldSpecTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/com/squareup/javapoet/FieldSpecTest.java b/src/test/java/com/squareup/javapoet/FieldSpecTest.java index 63f7aa8..51d093e 100644 --- a/src/test/java/com/squareup/javapoet/FieldSpecTest.java +++ b/src/test/java/com/squareup/javapoet/FieldSpecTest.java @@ -28,10 +28,12 @@ public class FieldSpecTest { FieldSpec b = FieldSpec.builder(int.class, "foo").build(); assertThat(a.equals(b)).isTrue(); assertThat(a.hashCode()).isEqualTo(b.hashCode()); + assertThat(a.toString()).isEqualTo(b.toString()); a = FieldSpec.builder(int.class, "FOO", Modifier.PUBLIC, Modifier.STATIC).build(); b = FieldSpec.builder(int.class, "FOO", Modifier.PUBLIC, Modifier.STATIC).build(); assertThat(a.equals(b)).isTrue(); assertThat(a.hashCode()).isEqualTo(b.hashCode()); + assertThat(a.toString()).isEqualTo(b.toString()); } @Test public void nullAnnotationsAddition() { -- cgit v1.2.3 From b879b58254804b953c6280d05d7882a89ec3b7c8 Mon Sep 17 00:00:00 2001 From: Ron Shapiro Date: Tue, 21 Aug 2018 21:12:33 -0400 Subject: Qualify types masked by type variables (#657) * Use fully qualified names if a type variable masks a type name, even if it is in the same package * Add a makeshift multiset to handle https://github.com/square/javapoet/pull/657\#discussion_r205514292 --- .../java/com/squareup/javapoet/CodeWriter.java | 37 +++++++++++- .../java/com/squareup/javapoet/MethodSpec.java | 1 + src/main/java/com/squareup/javapoet/TypeSpec.java | 1 + .../java/com/squareup/javapoet/TypeSpecTest.java | 68 ++++++++++++++++++++++ 4 files changed, 106 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/squareup/javapoet/CodeWriter.java b/src/main/java/com/squareup/javapoet/CodeWriter.java index 542f434..ac8178f 100644 --- a/src/main/java/com/squareup/javapoet/CodeWriter.java +++ b/src/main/java/com/squareup/javapoet/CodeWriter.java @@ -57,6 +57,7 @@ final class CodeWriter { private final Map importedTypes; private final Map importableTypes = new LinkedHashMap<>(); private final Set referencedNames = new LinkedHashSet<>(); + private final Multiset currentTypeVariables = new Multiset<>(); private boolean trailingNewline; /** @@ -187,6 +188,8 @@ final class CodeWriter { public void emitTypeVariables(List typeVariables) throws IOException { if (typeVariables.isEmpty()) return; + typeVariables.forEach(typeVariable -> currentTypeVariables.add(typeVariable.name)); + emit("<"); boolean firstTypeVariable = true; for (TypeVariableName typeVariable : typeVariables) { @@ -203,6 +206,10 @@ final class CodeWriter { emit(">"); } + public void popTypeVariables(List typeVariables) throws IOException { + typeVariables.forEach(typeVariable -> currentTypeVariables.remove(typeVariable.name)); + } + public CodeWriter emit(String s) throws IOException { return emitAndIndent(s); } @@ -353,6 +360,12 @@ final class CodeWriter { * names visible due to inheritance. */ String lookupName(ClassName className) { + // If the top level simple name is masked by a current type variable, use the canonical name. + String topLevelSimpleName = className.topLevelClassName().simpleName(); + if (currentTypeVariables.contains(topLevelSimpleName)) { + return className.canonicalName; + } + // Find the shortest suffix of className that resolves to className. This uses both local type // names (so `Entry` in `Map` refers to `Map.Entry`). Also uses imports. boolean nameResolved = false; @@ -374,7 +387,7 @@ final class CodeWriter { // If the class is in the same package, we're done. if (Objects.equals(packageName, className.packageName())) { - referencedNames.add(className.topLevelClassName().simpleName()); + referencedNames.add(topLevelSimpleName); return join(".", className.simpleNames()); } @@ -494,4 +507,26 @@ final class CodeWriter { result.keySet().removeAll(referencedNames); return result; } + + // A makeshift multi-set implementation + private static final class Multiset { + private final Map map = new LinkedHashMap<>(); + + void add(T t) { + int count = map.getOrDefault(t, 0); + map.put(t, count + 1); + } + + void remove(T t) { + int count = map.getOrDefault(t, 0); + if (count == 0) { + throw new IllegalStateException(t + " is not in the multiset"); + } + map.put(t, count - 1); + } + + boolean contains(T t) { + return map.getOrDefault(t, 0) > 0; + } + } } diff --git a/src/main/java/com/squareup/javapoet/MethodSpec.java b/src/main/java/com/squareup/javapoet/MethodSpec.java index a2c7c43..52b41e7 100644 --- a/src/main/java/com/squareup/javapoet/MethodSpec.java +++ b/src/main/java/com/squareup/javapoet/MethodSpec.java @@ -137,6 +137,7 @@ public final class MethodSpec { codeWriter.emit("}\n"); } + codeWriter.popTypeVariables(typeVariables); } public boolean hasModifier(Modifier modifier) { diff --git a/src/main/java/com/squareup/javapoet/TypeSpec.java b/src/main/java/com/squareup/javapoet/TypeSpec.java index 46de3a5..c315579 100644 --- a/src/main/java/com/squareup/javapoet/TypeSpec.java +++ b/src/main/java/com/squareup/javapoet/TypeSpec.java @@ -316,6 +316,7 @@ public final class TypeSpec { codeWriter.unindent(); codeWriter.popType(); + codeWriter.popTypeVariables(typeVariables); codeWriter.emit("}"); if (enumName == null && anonymousTypeArguments == null) { diff --git a/src/test/java/com/squareup/javapoet/TypeSpecTest.java b/src/test/java/com/squareup/javapoet/TypeSpecTest.java index 9cd22c2..733483b 100644 --- a/src/test/java/com/squareup/javapoet/TypeSpecTest.java +++ b/src/test/java/com/squareup/javapoet/TypeSpecTest.java @@ -985,6 +985,74 @@ public final class TypeSpecTest { + "}\n"); } + @Test public void simpleNameConflictsWithTypeVariable() { + ClassName inPackage = ClassName.get("com.squareup.tacos", "InPackage"); + ClassName otherType = ClassName.get("com.other", "OtherType"); + ClassName methodInPackage = ClassName.get("com.squareup.tacos", "MethodInPackage"); + ClassName methodOtherType = ClassName.get("com.other", "MethodOtherType"); + TypeSpec gen = TypeSpec.classBuilder("Gen") + .addTypeVariable(TypeVariableName.get("InPackage")) + .addTypeVariable(TypeVariableName.get("OtherType")) + .addField(FieldSpec.builder(inPackage, "inPackage").build()) + .addField(FieldSpec.builder(otherType, "otherType").build()) + .addMethod(MethodSpec.methodBuilder("withTypeVariables") + .addTypeVariable(TypeVariableName.get("MethodInPackage")) + .addTypeVariable(TypeVariableName.get("MethodOtherType")) + .addStatement("$T inPackage = null", methodInPackage) + .addStatement("$T otherType = null", methodOtherType) + .build()) + .addMethod(MethodSpec.methodBuilder("withoutTypeVariables") + .addStatement("$T inPackage = null", methodInPackage) + .addStatement("$T otherType = null", methodOtherType) + .build()) + .addMethod(MethodSpec.methodBuilder("againWithTypeVariables") + .addTypeVariable(TypeVariableName.get("MethodInPackage")) + .addTypeVariable(TypeVariableName.get("MethodOtherType")) + .addStatement("$T inPackage = null", methodInPackage) + .addStatement("$T otherType = null", methodOtherType) + .build()) + // https://github.com/square/javapoet/pull/657#discussion_r205514292 + .addMethod(MethodSpec.methodBuilder("masksEnclosingTypeVariable") + .addTypeVariable(TypeVariableName.get("InPackage")) + .build()) + .addMethod(MethodSpec.methodBuilder("hasSimpleNameThatWasPreviouslyMasked") + .addStatement("$T inPackage = null", inPackage) + .build()) + .build(); + assertThat(toString(gen)).isEqualTo("" + + "package com.squareup.tacos;\n" + + "\n" + + "import com.other.MethodOtherType;\n" + + "\n" + + "class Gen {\n" + + " com.squareup.tacos.InPackage inPackage;\n" + + "\n" + + " com.other.OtherType otherType;\n" + + "\n" + + " void withTypeVariables() {\n" + + " com.squareup.tacos.MethodInPackage inPackage = null;\n" + + " com.other.MethodOtherType otherType = null;\n" + + " }\n" + + "\n" + + " void withoutTypeVariables() {\n" + + " MethodInPackage inPackage = null;\n" + + " MethodOtherType otherType = null;\n" + + " }\n" + + "\n" + + " void againWithTypeVariables() {\n" + + " com.squareup.tacos.MethodInPackage inPackage = null;\n" + + " com.other.MethodOtherType otherType = null;\n" + + " }\n" + + "\n" + + " void masksEnclosingTypeVariable() {\n" + + " }\n" + + "\n" + + " void hasSimpleNameThatWasPreviouslyMasked() {\n" + + " com.squareup.tacos.InPackage inPackage = null;\n" + + " }\n" + + "}\n"); + } + @Test public void originatingElementsIncludesThoseOfNestedTypes() { Element outerElement = Mockito.mock(Element.class); Element innerElement = Mockito.mock(Element.class); -- cgit v1.2.3 From c93bfa88c30940d4f9bda88cac322ebbb83703a6 Mon Sep 17 00:00:00 2001 From: Shaishav Gandhi Date: Wed, 3 Oct 2018 19:57:36 -0700 Subject: Check parameter Modifiers (#678) * Check parameter modifiers for non final modifiers Signed-off-by: shaishavgandhi05 * Add extra line Signed-off-by: shaishavgandhi05 * Fix formatting Signed-off-by: shaishavgandhi05 --- src/main/java/com/squareup/javapoet/ParameterSpec.java | 3 +++ .../java/com/squareup/javapoet/ParameterSpecTest.java | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/squareup/javapoet/ParameterSpec.java b/src/main/java/com/squareup/javapoet/ParameterSpec.java index 63da3f2..e30cb0f 100644 --- a/src/main/java/com/squareup/javapoet/ParameterSpec.java +++ b/src/main/java/com/squareup/javapoet/ParameterSpec.java @@ -160,6 +160,9 @@ public final class ParameterSpec { public Builder addModifiers(Iterable modifiers) { checkNotNull(modifiers, "modifiers == null"); for (Modifier modifier : modifiers) { + if (!modifier.equals(Modifier.FINAL)) { + throw new IllegalStateException("unexpected parameter modifier: " + modifier); + } this.modifiers.add(modifier); } return this; diff --git a/src/test/java/com/squareup/javapoet/ParameterSpecTest.java b/src/test/java/com/squareup/javapoet/ParameterSpecTest.java index 7ae4502..f66850b 100644 --- a/src/test/java/com/squareup/javapoet/ParameterSpecTest.java +++ b/src/test/java/com/squareup/javapoet/ParameterSpecTest.java @@ -15,6 +15,8 @@ */ package com.squareup.javapoet; +import java.util.ArrayList; +import java.util.List; import org.junit.Test; import static com.google.common.truth.Truth.assertThat; @@ -45,4 +47,18 @@ public class ParameterSpecTest { .isEqualTo("annotationSpecs == null"); } } -} \ No newline at end of file + + @Test public void addNonFinalModifier() { + List modifiers = new ArrayList<>(); + modifiers.add(Modifier.FINAL); + modifiers.add(Modifier.PUBLIC); + + try { + ParameterSpec.builder(int.class, "foo").addModifiers(modifiers); + fail(); + } catch (Exception e) { + assertThat(e.getMessage()) + .isEqualTo("unexpected parameter modifier: public"); + } + } +} -- cgit v1.2.3 From ea7a02ee88f8a3aa9afd3a9268390f4f9fee4b59 Mon Sep 17 00:00:00 2001 From: Shaishav Gandhi Date: Wed, 3 Oct 2018 19:59:30 -0700 Subject: Add Javadoc to ParameterSpec (#676) * Add Javadoc to ParameterSpec Signed-off-by: shaishavgandhi05 * Move emission to same CodeBlock Signed-off-by: shaishavgandhi05 * Remove eager javadoc addition and fallback to adding doc when emitting Signed-off-by: shaishavgandhi05 * Fix formatting Signed-off-by: shaishavgandhi05 * Add new line before emitting parameter javadoc Signed-off-by: shaishavgandhi05 * Emit new line before @param only if method javadoc is present Signed-off-by: shaishavgandhi05 --- .../java/com/squareup/javapoet/MethodSpec.java | 16 ++++++- .../java/com/squareup/javapoet/ParameterSpec.java | 13 ++++++ .../java/com/squareup/javapoet/MethodSpecTest.java | 53 ++++++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/squareup/javapoet/MethodSpec.java b/src/main/java/com/squareup/javapoet/MethodSpec.java index 52b41e7..0bfdd1b 100644 --- a/src/main/java/com/squareup/javapoet/MethodSpec.java +++ b/src/main/java/com/squareup/javapoet/MethodSpec.java @@ -82,7 +82,7 @@ public final class MethodSpec { void emit(CodeWriter codeWriter, String enclosingName, Set implicitModifiers) throws IOException { - codeWriter.emitJavadoc(javadoc); + codeWriter.emitJavadoc(javadocWithParameters()); codeWriter.emitAnnotations(annotations, false); codeWriter.emitModifiers(modifiers, implicitModifiers); @@ -140,6 +140,20 @@ public final class MethodSpec { codeWriter.popTypeVariables(typeVariables); } + private CodeBlock javadocWithParameters() { + CodeBlock.Builder builder = javadoc.toBuilder(); + boolean emitTagNewline = true; + for (ParameterSpec parameterSpec : parameters) { + if (!parameterSpec.javadoc.isEmpty()) { + // Emit a new line before @param section only if the method javadoc is present. + if (emitTagNewline && !javadoc.isEmpty()) builder.add("\n"); + emitTagNewline = false; + builder.add("@param $L $L", parameterSpec.name, parameterSpec.javadoc); + } + } + return builder.build(); + } + public boolean hasModifier(Modifier modifier) { return modifiers.contains(modifier); } diff --git a/src/main/java/com/squareup/javapoet/ParameterSpec.java b/src/main/java/com/squareup/javapoet/ParameterSpec.java index e30cb0f..e98b99e 100644 --- a/src/main/java/com/squareup/javapoet/ParameterSpec.java +++ b/src/main/java/com/squareup/javapoet/ParameterSpec.java @@ -35,12 +35,14 @@ public final class ParameterSpec { public final List annotations; public final Set modifiers; public final TypeName type; + public final CodeBlock javadoc; private ParameterSpec(Builder builder) { this.name = checkNotNull(builder.name, "name == null"); this.annotations = Util.immutableList(builder.annotations); this.modifiers = Util.immutableSet(builder.modifiers); this.type = checkNotNull(builder.type, "type == null"); + this.javadoc = builder.javadoc.build(); } public boolean hasModifier(Modifier modifier) { @@ -121,6 +123,7 @@ public final class ParameterSpec { public static final class Builder { private final TypeName type; private final String name; + private final CodeBlock.Builder javadoc = CodeBlock.builder(); private final List annotations = new ArrayList<>(); private final List modifiers = new ArrayList<>(); @@ -130,6 +133,16 @@ public final class ParameterSpec { this.name = name; } + public Builder addJavadoc(String format, Object... args) { + javadoc.add(format, args); + return this; + } + + public Builder addJavadoc(CodeBlock block) { + javadoc.add(block); + return this; + } + public Builder addAnnotations(Iterable annotationSpecs) { checkArgument(annotationSpecs != null, "annotationSpecs == null"); for (AnnotationSpec annotationSpec : annotationSpecs) { diff --git a/src/test/java/com/squareup/javapoet/MethodSpecTest.java b/src/test/java/com/squareup/javapoet/MethodSpecTest.java index 5dfabaa..c6e05c6 100644 --- a/src/test/java/com/squareup/javapoet/MethodSpecTest.java +++ b/src/test/java/com/squareup/javapoet/MethodSpecTest.java @@ -270,6 +270,59 @@ public final class MethodSpecTest { assertThat(a.hashCode()).isEqualTo(b.hashCode()); } + @Test public void withoutParameterJavaDoc() { + MethodSpec methodSpec = MethodSpec.methodBuilder("getTaco") + .addModifiers(Modifier.PRIVATE) + .addParameter(TypeName.DOUBLE, "money") + .addJavadoc("Gets the best Taco\n") + .build(); + assertThat(methodSpec.toString()).isEqualTo("" + + "/**\n" + + " * Gets the best Taco\n" + + " */\n" + + "private void getTaco(double money) {\n" + + "}\n"); + } + + @Test public void withParameterJavaDoc() { + MethodSpec methodSpec = MethodSpec.methodBuilder("getTaco") + .addParameter(ParameterSpec.builder(TypeName.DOUBLE, "money") + .addJavadoc("the amount required to buy the taco.\n") + .build()) + .addParameter(ParameterSpec.builder(TypeName.INT, "count") + .addJavadoc("the number of Tacos to buy.\n") + .build()) + .addJavadoc("Gets the best Taco money can buy.\n") + .build(); + assertThat(methodSpec.toString()).isEqualTo("" + + "/**\n" + + " * Gets the best Taco money can buy.\n" + + " *\n" + + " * @param money the amount required to buy the taco.\n" + + " * @param count the number of Tacos to buy.\n" + + " */\n" + + "void getTaco(double money, int count) {\n" + + "}\n"); + } + + @Test public void withParameterJavaDocAndWithoutMethodJavadoc() { + MethodSpec methodSpec = MethodSpec.methodBuilder("getTaco") + .addParameter(ParameterSpec.builder(TypeName.DOUBLE, "money") + .addJavadoc("the amount required to buy the taco.\n") + .build()) + .addParameter(ParameterSpec.builder(TypeName.INT, "count") + .addJavadoc("the number of Tacos to buy.\n") + .build()) + .build(); + assertThat(methodSpec.toString()).isEqualTo("" + + "/**\n" + + " * @param money the amount required to buy the taco.\n" + + " * @param count the number of Tacos to buy.\n" + + " */\n" + + "void getTaco(double money, int count) {\n" + + "}\n"); + } + @Test public void duplicateExceptionsIgnored() { ClassName ioException = ClassName.get(IOException.class); ClassName timeoutException = ClassName.get(TimeoutException.class); -- cgit v1.2.3 From 30a8bdaa2224f224be04261b9fceea6cd7048cd5 Mon Sep 17 00:00:00 2001 From: Daniil Popov Date: Mon, 12 Nov 2018 07:32:46 +0300 Subject: Public getter for canonical name of ClassName (#687) --- src/main/java/com/squareup/javapoet/ClassName.java | 8 ++++++++ src/test/java/com/squareup/javapoet/ClassNameTest.java | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/main/java/com/squareup/javapoet/ClassName.java b/src/main/java/com/squareup/javapoet/ClassName.java index 99c4ed2..e044985 100644 --- a/src/main/java/com/squareup/javapoet/ClassName.java +++ b/src/main/java/com/squareup/javapoet/ClassName.java @@ -138,6 +138,14 @@ public final class ClassName extends TypeName implements Comparable { return simpleName; } + /** + * Returns the full class name of this class. + * Like {@code "java.util.Map.Entry"} for {@link Map.Entry}. + * */ + public String canonicalName() { + return canonicalName; + } + public static ClassName get(Class clazz) { checkNotNull(clazz, "clazz == null"); checkArgument(!clazz.isPrimitive(), "primitive types cannot be represented as a ClassName"); diff --git a/src/test/java/com/squareup/javapoet/ClassNameTest.java b/src/test/java/com/squareup/javapoet/ClassNameTest.java index e2cc55e..590ad5d 100644 --- a/src/test/java/com/squareup/javapoet/ClassNameTest.java +++ b/src/test/java/com/squareup/javapoet/ClassNameTest.java @@ -193,4 +193,14 @@ public final class ClassNameTest { assertEquals("Foo$Bar$Baz", ClassName.get("", "Foo", "Bar", "Baz").reflectionName()); assertEquals("a.b.c.Foo$Bar$Baz", ClassName.get("a.b.c", "Foo", "Bar", "Baz").reflectionName()); } + + @Test + public void canonicalName() { + assertEquals("java.lang.Object", TypeName.OBJECT.canonicalName()); + assertEquals("java.lang.Thread.State", ClassName.get(Thread.State.class).canonicalName()); + assertEquals("java.util.Map.Entry", ClassName.get(Map.Entry.class).canonicalName()); + assertEquals("Foo", ClassName.get("", "Foo").canonicalName()); + assertEquals("Foo.Bar.Baz", ClassName.get("", "Foo", "Bar", "Baz").canonicalName()); + assertEquals("a.b.c.Foo.Bar.Baz", ClassName.get("a.b.c", "Foo", "Bar", "Baz").canonicalName()); + } } -- cgit v1.2.3 From 274bb56141c18eb39308af60e9f490d0dfce570f Mon Sep 17 00:00:00 2001 From: Shaishav Gandhi Date: Tue, 27 Nov 2018 20:14:23 -0800 Subject: Remove sudo:false from travis config --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 131324c..c4a315d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,8 +29,6 @@ branches: notifications: email: false -sudo: false - cache: directories: - $HOME/.m2 -- cgit v1.2.3 From 53cfc840f2b860e88e8b0aecd7026901ee76399e Mon Sep 17 00:00:00 2001 From: Shaishav Gandhi Date: Mon, 4 Feb 2019 07:06:39 -0800 Subject: Allow setting method name on MethodSpec.Builder (#702) * Allow setting method name on MethodSpec.Builder * Fix indentation --- src/main/java/com/squareup/javapoet/MethodSpec.java | 7 ++++++- src/test/java/com/squareup/javapoet/MethodSpecTest.java | 13 +++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/squareup/javapoet/MethodSpec.java b/src/main/java/com/squareup/javapoet/MethodSpec.java index 0bfdd1b..850e537 100644 --- a/src/main/java/com/squareup/javapoet/MethodSpec.java +++ b/src/main/java/com/squareup/javapoet/MethodSpec.java @@ -292,7 +292,7 @@ public final class MethodSpec { } public static final class Builder { - private final String name; + private String name; private final CodeBlock.Builder javadoc = CodeBlock.builder(); private final List annotations = new ArrayList<>(); @@ -306,11 +306,16 @@ public final class MethodSpec { private CodeBlock defaultValue; private Builder(String name) { + setName(name); + } + + public Builder setName(String name) { checkNotNull(name, "name == null"); checkArgument(name.equals(CONSTRUCTOR) || SourceVersion.isName(name), "not a valid name: %s", name); this.name = name; this.returnType = name.equals(CONSTRUCTOR) ? null : TypeName.VOID; + return this; } public Builder addJavadoc(String format, Object... args) { diff --git a/src/test/java/com/squareup/javapoet/MethodSpecTest.java b/src/test/java/com/squareup/javapoet/MethodSpecTest.java index c6e05c6..b2c7106 100644 --- a/src/test/java/com/squareup/javapoet/MethodSpecTest.java +++ b/src/test/java/com/squareup/javapoet/MethodSpecTest.java @@ -37,6 +37,7 @@ import org.junit.Test; import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.truth.Truth.assertThat; +import static com.squareup.javapoet.MethodSpec.CONSTRUCTOR; import static javax.lang.model.util.ElementFilter.methodsIn; import static org.junit.Assert.fail; @@ -355,4 +356,16 @@ public final class MethodSpecTest { assertThat(e.getMessage()).isEqualTo("modifiers == null"); } } + + @Test public void modifyMethodName() { + MethodSpec methodSpec = MethodSpec.methodBuilder("initialMethod") + .build() + .toBuilder() + .setName("revisedMethod") + .build(); + + assertThat(methodSpec.toString()).isEqualTo("" + + "void revisedMethod() {\n" + + "}\n"); + } } -- cgit v1.2.3 From dc30890a5002fc65eefb94a570ff4aff2d6f8577 Mon Sep 17 00:00:00 2001 From: Ron Shapiro Date: Tue, 5 Feb 2019 16:47:03 -0500 Subject: Remove n^2 algorithm in CodeWriter.resolve() by precomputing all of the nested simple names of a TypeSpec For one large (100K lines) file, this saved 3.5s/build --- src/main/java/com/squareup/javapoet/CodeWriter.java | 6 ++---- src/main/java/com/squareup/javapoet/TypeSpec.java | 6 ++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/squareup/javapoet/CodeWriter.java b/src/main/java/com/squareup/javapoet/CodeWriter.java index ac8178f..b2b088b 100644 --- a/src/main/java/com/squareup/javapoet/CodeWriter.java +++ b/src/main/java/com/squareup/javapoet/CodeWriter.java @@ -420,10 +420,8 @@ final class CodeWriter { // Match a child of the current (potentially nested) class. for (int i = typeSpecStack.size() - 1; i >= 0; i--) { TypeSpec typeSpec = typeSpecStack.get(i); - for (TypeSpec visibleChild : typeSpec.typeSpecs) { - if (Objects.equals(visibleChild.name, simpleName)) { - return stackClassName(i, simpleName); - } + if (typeSpec.nestedTypesSimpleNames.contains(simpleName)) { + return stackClassName(i, simpleName); } } diff --git a/src/main/java/com/squareup/javapoet/TypeSpec.java b/src/main/java/com/squareup/javapoet/TypeSpec.java index c315579..3346763 100644 --- a/src/main/java/com/squareup/javapoet/TypeSpec.java +++ b/src/main/java/com/squareup/javapoet/TypeSpec.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -53,6 +54,7 @@ public final class TypeSpec { public final CodeBlock initializerBlock; public final List methodSpecs; public final List typeSpecs; + final Set nestedTypesSimpleNames; public final List originatingElements; private TypeSpec(Builder builder) { @@ -72,11 +74,14 @@ public final class TypeSpec { this.methodSpecs = Util.immutableList(builder.methodSpecs); this.typeSpecs = Util.immutableList(builder.typeSpecs); + nestedTypesSimpleNames = new HashSet<>(builder.typeSpecs.size()); List originatingElementsMutable = new ArrayList<>(); originatingElementsMutable.addAll(builder.originatingElements); for (TypeSpec typeSpec : builder.typeSpecs) { + nestedTypesSimpleNames.add(typeSpec.name); originatingElementsMutable.addAll(typeSpec.originatingElements); } + this.originatingElements = Util.immutableList(originatingElementsMutable); } @@ -102,6 +107,7 @@ public final class TypeSpec { this.methodSpecs = Collections.emptyList(); this.typeSpecs = Collections.emptyList(); this.originatingElements = Collections.emptyList(); + this.nestedTypesSimpleNames = Collections.emptySet(); } public boolean hasModifier(Modifier modifier) { -- cgit v1.2.3 From c054ce927191205b4a870b40eecfe63dffaba0e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Galder=20Zamarren=CC=83o?= Date: Wed, 30 Jan 2019 17:11:41 +0100 Subject: Add documentation on nextControlFlow to README #693 --- README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/README.md b/README.md index 788ce48..8574eae 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,60 @@ int multiply10to20() { Methods generating methods! And since JavaPoet generates source instead of bytecode, you can read through it to make sure it's right. +Some control flow statements, such as `if/else`, can have unlimited control flow possibilities. +You can handle those options using `nextControlFlow()`: + +```java +MethodSpec main = MethodSpec.methodBuilder("main") + .addStatement("long now = $T.currentTimeMillis()", System.class) + .beginControlFlow("if ($T.currentTimeMillis() < now)", System.class) + .addStatement("$T.out.println($S)", System.class, "Time travelling, woo hoo!") + .nextControlFlow("else if ($T.currentTimeMillis() == now)", System.class) + .addStatement("$T.out.println($S)", System.class, "Time stood still!") + .nextControlFlow("else") + .addStatement("$T.out.println($S)", System.class, "Ok, time still moving forward") + .endControlFlow() + .build(); +``` + +Which generates: + +```java +void main() { + long now = System.currentTimeMillis(); + if (System.currentTimeMillis() < now) { + System.out.println("Time travelling, woo hoo!"); + } else if (System.currentTimeMillis() == now) { + System.out.println("Time stood still!"); + } else { + System.out.println("Ok, time still moving forward"); + } +} +``` + +Catching exceptions using `try/catch` is also a use case for `nextControlFlow()`: + +```java +MethodSpec main = MethodSpec.methodBuilder("main") + .beginControlFlow("try") + .addStatement("throw new Exception($S)", "Failed") + .nextControlFlow("catch ($T e)", Exception.class) + .addStatement("throw new $T(e)", RuntimeException.class) + .endControlFlow() + .build(); +``` + +Which produces: + +```java +void main() { + try { + throw new Exception("Failed"); + } catch (Exception e) { + throw new RuntimeException(e); + } +} +``` ### $L for Literals -- cgit v1.2.3 From a481d9d4c8e6e0b54887265b560b02946c318230 Mon Sep 17 00:00:00 2001 From: Egor Andreevici Date: Thu, 14 Mar 2019 12:40:44 -0400 Subject: Checkstyle 8.18 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 15c1b77..34c03e7 100644 --- a/pom.xml +++ b/pom.xml @@ -123,7 +123,7 @@ com.puppycrawl.tools checkstyle - 8.7 + 8.18 -- cgit v1.2.3 From e79bb2f09d29678ece0abfb50abe3e4a855aee4f Mon Sep 17 00:00:00 2001 From: Jake Wharton Date: Mon, 25 Mar 2019 11:03:39 -0400 Subject: Remove argument whose value isn't needed The single-argument overload will use the end of the String as the end index automatically. --- src/main/java/com/squareup/javapoet/CodeBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/squareup/javapoet/CodeBlock.java b/src/main/java/com/squareup/javapoet/CodeBlock.java index 33e3846..47c6ff7 100644 --- a/src/main/java/com/squareup/javapoet/CodeBlock.java +++ b/src/main/java/com/squareup/javapoet/CodeBlock.java @@ -189,7 +189,7 @@ public final class CodeBlock { while (p < format.length()) { int nextP = format.indexOf("$", p); if (nextP == -1) { - formatParts.add(format.substring(p, format.length())); + formatParts.add(format.substring(p)); break; } -- cgit v1.2.3 From 02ece26b2e05f3b1306f67aacc3a8932a3e51d51 Mon Sep 17 00:00:00 2001 From: Ron Shapiro Date: Tue, 16 Apr 2019 15:30:11 -0400 Subject: Memoize ClassName.simpleNames() In addition to being used repeatedly in CodeWriter.lookupName(), the current implementation is N^2 (albeit for a usually low N) since it recursively calls itself on the enclosing class name. This should get rid of some of the garbage created in code writing. --- src/main/java/com/squareup/javapoet/ClassName.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/squareup/javapoet/ClassName.java b/src/main/java/com/squareup/javapoet/ClassName.java index e044985..b8dbd31 100644 --- a/src/main/java/com/squareup/javapoet/ClassName.java +++ b/src/main/java/com/squareup/javapoet/ClassName.java @@ -41,6 +41,8 @@ public final class ClassName extends TypeName implements Comparable { /** This class name, like "Entry" for java.util.Map.Entry. */ final String simpleName; + private List simpleNames; + /** The full class name like "java.util.Map.Entry". */ final String canonicalName; @@ -108,11 +110,18 @@ public final class ClassName extends TypeName implements Comparable { } public List simpleNames() { - List simpleNames = new ArrayList<>(); - if (enclosingClassName != null) { - simpleNames.addAll(enclosingClassName().simpleNames()); + if (simpleNames != null) { + return simpleNames; + } + + if (enclosingClassName == null) { + simpleNames = Collections.singletonList(simpleName); + } else { + List mutableNames = new ArrayList<>(); + mutableNames.addAll(enclosingClassName().simpleNames()); + mutableNames.add(simpleName); + simpleNames = Collections.unmodifiableList(mutableNames); } - simpleNames.add(simpleName); return simpleNames; } -- cgit v1.2.3 From 3829f2ca6f03a4b941fea41a1e2f4eead8f37bc1 Mon Sep 17 00:00:00 2001 From: Almog Gavra Date: Fri, 26 Apr 2019 16:15:29 -0700 Subject: Fix an issue where ClassName could not handle classes in the default (empty) package --- src/main/java/com/squareup/javapoet/ClassName.java | 10 +++++-- src/test/java/ClassNameNoPackageTest.java | 33 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 src/test/java/ClassNameNoPackageTest.java diff --git a/src/main/java/com/squareup/javapoet/ClassName.java b/src/main/java/com/squareup/javapoet/ClassName.java index b8dbd31..4bef49d 100644 --- a/src/main/java/com/squareup/javapoet/ClassName.java +++ b/src/main/java/com/squareup/javapoet/ClassName.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.lang.model.element.Element; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; @@ -32,6 +33,9 @@ import static com.squareup.javapoet.Util.checkNotNull; public final class ClassName extends TypeName implements Comparable { public static final ClassName OBJECT = ClassName.get(Object.class); + /** The name representing the default Java package. */ + private static final String NO_PACKAGE = ""; + /** The package name of this class, or "" if this is in the default package. */ final String packageName; @@ -53,7 +57,7 @@ public final class ClassName extends TypeName implements Comparable { private ClassName(String packageName, ClassName enclosingClassName, String simpleName, List annotations) { super(annotations); - this.packageName = packageName; + this.packageName = Objects.requireNonNull(packageName, "packageName == null"); this.enclosingClassName = enclosingClassName; this.simpleName = simpleName; this.canonicalName = enclosingClassName != null @@ -172,7 +176,7 @@ public final class ClassName extends TypeName implements Comparable { if (clazz.getEnclosingClass() == null) { // Avoid unreliable Class.getPackage(). https://github.com/square/javapoet/issues/295 int lastDot = clazz.getName().lastIndexOf('.'); - String packageName = (lastDot != -1) ? clazz.getName().substring(0, lastDot) : null; + String packageName = (lastDot != -1) ? clazz.getName().substring(0, lastDot) : NO_PACKAGE; return new ClassName(packageName, null, name); } @@ -194,7 +198,7 @@ public final class ClassName extends TypeName implements Comparable { p = classNameString.indexOf('.', p) + 1; checkArgument(p != 0, "couldn't make a guess for %s", classNameString); } - String packageName = p == 0 ? "" : classNameString.substring(0, p - 1); + String packageName = p == 0 ? NO_PACKAGE : classNameString.substring(0, p - 1); // Add class names like "Map" and "Entry". ClassName className = null; diff --git a/src/test/java/ClassNameNoPackageTest.java b/src/test/java/ClassNameNoPackageTest.java new file mode 100644 index 0000000..8b8545d --- /dev/null +++ b/src/test/java/ClassNameNoPackageTest.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2019 Square, Inc. + * + * 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. + */ + +import static com.google.common.truth.Truth.assertThat; + +import com.squareup.javapoet.ClassName; +import org.junit.Test; + +/** + * Since it is impossible to import classes from the default package into other + * modules, this test must live in this package. + */ +public final class ClassNameNoPackageTest { + @Test public void shouldSupportClassInDefaultPackage() { + ClassName className = ClassName.get(ClassNameNoPackageTest.class); + assertThat(className.packageName()).isEqualTo(""); + assertThat(className.simpleName()).isEqualTo("ClassNameNoPackageTest"); + assertThat(className.toString()).isEqualTo("ClassNameNoPackageTest"); + } +} -- cgit v1.2.3 From 8bc90713f5efe4f827cb4af5aa558e170073ed27 Mon Sep 17 00:00:00 2001 From: Ron Shapiro Date: Fri, 3 May 2019 14:58:24 -0400 Subject: Nit: Simplify a CodeBlock --- src/main/java/com/squareup/javapoet/TypeSpec.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/squareup/javapoet/TypeSpec.java b/src/main/java/com/squareup/javapoet/TypeSpec.java index 3346763..cf65bcf 100644 --- a/src/main/java/com/squareup/javapoet/TypeSpec.java +++ b/src/main/java/com/squareup/javapoet/TypeSpec.java @@ -139,9 +139,7 @@ public final class TypeSpec { } public static Builder anonymousClassBuilder(String typeArgumentsFormat, Object... args) { - return anonymousClassBuilder(CodeBlock.builder() - .add(typeArgumentsFormat, args) - .build()); + return anonymousClassBuilder(CodeBlock.of(typeArgumentsFormat, args)); } public static Builder anonymousClassBuilder(CodeBlock typeArguments) { -- cgit v1.2.3 From a03c97888d3afeeaa92e8ee8eaaffb19fccbaba1 Mon Sep 17 00:00:00 2001 From: Rene Fischer Date: Tue, 4 Jun 2019 19:07:29 +0200 Subject: easier_way_provide_encoding (#712) * provide an easier way for an other encoding than UTF-8 * formatting * no final on argument and fix for javadoc * checkstyle line length checkstyle line length --- src/main/java/com/squareup/javapoet/JavaFile.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/squareup/javapoet/JavaFile.java b/src/main/java/com/squareup/javapoet/JavaFile.java index e7662dd..41f6439 100644 --- a/src/main/java/com/squareup/javapoet/JavaFile.java +++ b/src/main/java/com/squareup/javapoet/JavaFile.java @@ -22,6 +22,7 @@ import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.net.URI; +import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; @@ -83,6 +84,14 @@ public final class JavaFile { /** Writes this to {@code directory} as UTF-8 using the standard directory structure. */ public void writeTo(Path directory) throws IOException { + writeTo(directory, UTF_8); + } + + /** + * Writes this to {@code directory} with the provided {@code charset} + * using the standard directory structure. + */ + public void writeTo(Path directory, Charset charset) throws IOException { checkArgument(Files.notExists(directory) || Files.isDirectory(directory), "path %s exists but is not a directory.", directory); Path outputDirectory = directory; @@ -94,7 +103,7 @@ public final class JavaFile { } Path outputPath = outputDirectory.resolve(typeSpec.name + ".java"); - try (Writer writer = new OutputStreamWriter(Files.newOutputStream(outputPath), UTF_8)) { + try (Writer writer = new OutputStreamWriter(Files.newOutputStream(outputPath), charset)) { writeTo(writer); } } -- cgit v1.2.3 From d13cf256ecdad39a556c0ae7224e25e0fc30bd6f Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Wed, 7 Aug 2019 23:00:45 -0400 Subject: Switch to openjdk8 for CI --- .buildscript/deploy_snapshot.sh | 2 +- .travis.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.buildscript/deploy_snapshot.sh b/.buildscript/deploy_snapshot.sh index 395a873..f25e18d 100755 --- a/.buildscript/deploy_snapshot.sh +++ b/.buildscript/deploy_snapshot.sh @@ -6,7 +6,7 @@ # https://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/ SLUG="square/javapoet" -JDK="oraclejdk8" +JDK="openjdk8" BRANCH="master" set -e diff --git a/.travis.yml b/.travis.yml index c4a315d..2d08e65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: java matrix: include: - - jdk: oraclejdk8 + - jdk: openjdk8 - jdk: openjdk10 - jdk: openjdk11 - jdk: openjdk-ea -- cgit v1.2.3 From 4e8f72f6a989ffbf99f0df4bbf0ab408ba412887 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sat, 10 Aug 2019 22:37:45 -0400 Subject: Add CodeBlock.Builder#clear() method Analogous to the change added in KotlinPoet --- src/main/java/com/squareup/javapoet/CodeBlock.java | 6 ++++++ src/test/java/com/squareup/javapoet/CodeBlockTest.java | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/src/main/java/com/squareup/javapoet/CodeBlock.java b/src/main/java/com/squareup/javapoet/CodeBlock.java index 47c6ff7..02542f5 100644 --- a/src/main/java/com/squareup/javapoet/CodeBlock.java +++ b/src/main/java/com/squareup/javapoet/CodeBlock.java @@ -424,6 +424,12 @@ public final class CodeBlock { return this; } + public Builder clear() { + formatParts.clear(); + args.clear(); + return this; + } + public CodeBlock build() { return new CodeBlock(this); } diff --git a/src/test/java/com/squareup/javapoet/CodeBlockTest.java b/src/test/java/com/squareup/javapoet/CodeBlockTest.java index 2862809..11b75fa 100644 --- a/src/test/java/com/squareup/javapoet/CodeBlockTest.java +++ b/src/test/java/com/squareup/javapoet/CodeBlockTest.java @@ -339,4 +339,13 @@ public final class CodeBlockTest { CodeBlock joined = codeBlocks.stream().collect(CodeBlock.joining(" || ", "start {", "} end")); assertThat(joined.toString()).isEqualTo("start {\"hello\" || world.World || need tacos} end"); } + + @Test public void clear() { + CodeBlock block = CodeBlock.builder() + .addStatement("$S", "Test string") + .clear() + .build(); + + assertThat(block.toString()).isEmpty(); + } } -- cgit v1.2.3 From a0eadbbf0e7b70f0fbbc66043536e4328c3808fd Mon Sep 17 00:00:00 2001 From: Shaishav Gandhi Date: Sat, 21 Dec 2019 05:39:33 -0800 Subject: Add checks to ParameterSpec with VariableElement + copy over annotations (#681) * Add checks to ParameterSpec with VariableElement + copy over annotations Signed-off-by: shaishavgandhi05 * Add test for variable element Signed-off-by: shaishavgandhi05 * Extract util methods into TestUtil * Fix formatting * Make findFirst more generic Co-authored-by: Egor Andreevich --- .../java/com/squareup/javapoet/ParameterSpec.java | 11 +++++ .../java/com/squareup/javapoet/MethodSpecTest.java | 18 +++---- .../com/squareup/javapoet/ParameterSpecTest.java | 55 ++++++++++++++++++++++ src/test/java/com/squareup/javapoet/TestUtil.java | 17 +++++++ 4 files changed, 89 insertions(+), 12 deletions(-) create mode 100644 src/test/java/com/squareup/javapoet/TestUtil.java diff --git a/src/main/java/com/squareup/javapoet/ParameterSpec.java b/src/main/java/com/squareup/javapoet/ParameterSpec.java index e98b99e..386ed1a 100644 --- a/src/main/java/com/squareup/javapoet/ParameterSpec.java +++ b/src/main/java/com/squareup/javapoet/ParameterSpec.java @@ -21,7 +21,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import javax.lang.model.SourceVersion; +import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.VariableElement; @@ -83,10 +85,19 @@ public final class ParameterSpec { } public static ParameterSpec get(VariableElement element) { + checkArgument(element.getKind().equals(ElementKind.PARAMETER), "element is not a parameter"); + + // Copy over any annotations from element. + List annotations = element.getAnnotationMirrors() + .stream() + .map((mirror) -> AnnotationSpec.get(mirror)) + .collect(Collectors.toList()); + TypeName type = TypeName.get(element.asType()); String name = element.getSimpleName().toString(); return ParameterSpec.builder(type, name) .addModifiers(element.getModifiers()) + .addAnnotations(annotations) .build(); } diff --git a/src/test/java/com/squareup/javapoet/MethodSpecTest.java b/src/test/java/com/squareup/javapoet/MethodSpecTest.java index b2c7106..3db519c 100644 --- a/src/test/java/com/squareup/javapoet/MethodSpecTest.java +++ b/src/test/java/com/squareup/javapoet/MethodSpecTest.java @@ -38,6 +38,7 @@ import org.junit.Test; import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.truth.Truth.assertThat; import static com.squareup.javapoet.MethodSpec.CONSTRUCTOR; +import static com.squareup.javapoet.TestUtil.findFirst; import static javax.lang.model.util.ElementFilter.methodsIn; import static org.junit.Assert.fail; @@ -56,15 +57,6 @@ public final class MethodSpecTest { return elements.getTypeElement(clazz.getCanonicalName()); } - private ExecutableElement findFirst(Collection elements, String name) { - for (ExecutableElement executableElement : elements) { - if (executableElement.getSimpleName().toString().equals(name)) { - return executableElement; - } - } - throw new IllegalArgumentException(name + " not found in " + elements); - } - @Test public void nullAnnotationsAddition() { try { MethodSpec.methodBuilder("doSomething").addAnnotations(null); @@ -155,8 +147,8 @@ public final class MethodSpecTest { + "@java.lang.Override\n" + "protected java.lang.Runnable " + "everything(\n" - + " java.lang.String arg0, java.util.List arg1) throws java.io.IOException,\n" - + " java.lang.SecurityException {\n" + + " @com.squareup.javapoet.MethodSpecTest.Nullable java.lang.String arg0,\n" + + " java.util.List arg1) throws java.io.IOException, java.lang.SecurityException {\n" + "}\n"); } @@ -187,7 +179,9 @@ public final class MethodSpecTest { TypeElement classElement = getElement(ExtendsIterableWithDefaultMethods.class); DeclaredType classType = (DeclaredType) classElement.asType(); List methods = methodsIn(elements.getAllMembers(classElement)); - ExecutableElement exec = findFirst(methods, "spliterator"); + ExecutableElement exec = + + (methods, "spliterator"); MethodSpec method = MethodSpec.overriding(exec, classType, types).build(); assertThat(method.toString()).isEqualTo("" + "@java.lang.Override\n" diff --git a/src/test/java/com/squareup/javapoet/ParameterSpecTest.java b/src/test/java/com/squareup/javapoet/ParameterSpecTest.java index f66850b..954db39 100644 --- a/src/test/java/com/squareup/javapoet/ParameterSpecTest.java +++ b/src/test/java/com/squareup/javapoet/ParameterSpecTest.java @@ -15,16 +15,39 @@ */ package com.squareup.javapoet; +import com.google.testing.compile.CompilationRule; import java.util.ArrayList; import java.util.List; +import javax.annotation.Nullable; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.util.Elements; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import static com.google.common.truth.Truth.assertThat; +import static com.squareup.javapoet.TestUtil.findFirst; +import static javax.lang.model.util.ElementFilter.fieldsIn; +import static javax.lang.model.util.ElementFilter.methodsIn; import static org.junit.Assert.fail; import javax.lang.model.element.Modifier; public class ParameterSpecTest { + @Rule public final CompilationRule compilation = new CompilationRule(); + + private Elements elements; + + @Before public void setUp() { + elements = compilation.getElements(); + } + + private TypeElement getElement(Class clazz) { + return elements.getTypeElement(clazz.getCanonicalName()); + } + @Test public void equalsAndHashCode() { ParameterSpec a = ParameterSpec.builder(int.class, "foo").build(); ParameterSpec b = ParameterSpec.builder(int.class, "foo").build(); @@ -48,6 +71,38 @@ public class ParameterSpecTest { } } + final class VariableElementFieldClass { + String name; + } + + @Test public void fieldVariableElement() { + TypeElement classElement = getElement(VariableElementFieldClass.class); + List methods = fieldsIn(elements.getAllMembers(classElement)); + VariableElement element = findFirst(methods, "name"); + + try { + ParameterSpec.get(element); + fail(); + } catch (IllegalArgumentException exception) { + assertThat(exception).hasMessageThat().isEqualTo("element is not a parameter"); + } + } + + final class VariableElementParameterClass { + public void foo(@Nullable final String bar) { + } + } + + @Test public void parameterVariableElement() { + TypeElement classElement = getElement(VariableElementParameterClass.class); + List methods = methodsIn(elements.getAllMembers(classElement)); + ExecutableElement element = findFirst(methods, "foo"); + VariableElement parameterElement = element.getParameters().get(0); + + assertThat(ParameterSpec.get(parameterElement).toString()) + .isEqualTo("@javax.annotation.Nullable java.lang.String arg0"); + } + @Test public void addNonFinalModifier() { List modifiers = new ArrayList<>(); modifiers.add(Modifier.FINAL); diff --git a/src/test/java/com/squareup/javapoet/TestUtil.java b/src/test/java/com/squareup/javapoet/TestUtil.java new file mode 100644 index 0000000..f773d50 --- /dev/null +++ b/src/test/java/com/squareup/javapoet/TestUtil.java @@ -0,0 +1,17 @@ +package com.squareup.javapoet; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import java.util.Collection; + +final class TestUtil { + static E findFirst(Collection elements, String name) { + for (E element : elements) { + if (element.getSimpleName().toString().equals(name)) { + return element; + } + } + throw new IllegalArgumentException(name + " not found in " + elements); + } +} -- cgit v1.2.3 From e6993cc2af1a2db55c134e45dc324148d76b3993 Mon Sep 17 00:00:00 2001 From: Egor Andreevici Date: Sun, 22 Dec 2019 09:45:11 -0500 Subject: Fix broken merge --- src/test/java/com/squareup/javapoet/MethodSpecTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/java/com/squareup/javapoet/MethodSpecTest.java b/src/test/java/com/squareup/javapoet/MethodSpecTest.java index 3db519c..98fd8f6 100644 --- a/src/test/java/com/squareup/javapoet/MethodSpecTest.java +++ b/src/test/java/com/squareup/javapoet/MethodSpecTest.java @@ -179,9 +179,7 @@ public final class MethodSpecTest { TypeElement classElement = getElement(ExtendsIterableWithDefaultMethods.class); DeclaredType classType = (DeclaredType) classElement.asType(); List methods = methodsIn(elements.getAllMembers(classElement)); - ExecutableElement exec = - - (methods, "spliterator"); + ExecutableElement exec = findFirst(methods, "spliterator"); MethodSpec method = MethodSpec.overriding(exec, classType, types).build(); assertThat(method.toString()).isEqualTo("" + "@java.lang.Override\n" -- cgit v1.2.3 From 2d6680b249a6188d719e72d9dad9a9ee8a84c3b8 Mon Sep 17 00:00:00 2001 From: Egor Andreevici Date: Sun, 22 Dec 2019 09:47:09 -0500 Subject: Remove non-LTS JDK versions from Travis config --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2d08e65..af37274 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,13 +3,9 @@ language: java matrix: include: - jdk: openjdk8 - - jdk: openjdk10 - jdk: openjdk11 - - jdk: openjdk-ea allow_failures: - # ErrorProne/javac is not yet working on JDK 11 nor 12 (current -ea) - jdk: openjdk11 - - jdk: openjdk-ea before_install: - unset _JAVA_OPTIONS -- cgit v1.2.3 From 4272265a319a562bceaa537fc1b9b6b40236a881 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Wed, 1 Jan 2020 08:37:31 -0500 Subject: Mutable builder list fields (#650) * Make modifiers and annotations in FieldSpec public * Make AnnotationSpec members public * Make JavaFile staticImports public * Make modifiers and annotations in parameterspec public * Make methodspec modifiers, params, typevars, and annotations public * Make typespec builder lists public * Move TypeSpec.Builder validations to build() where appropriate * Move AnnotationSpec.Builder validations to build() where appropriate * Fix line length style --- .../java/com/squareup/javapoet/AnnotationSpec.java | 9 +- src/main/java/com/squareup/javapoet/FieldSpec.java | 5 +- src/main/java/com/squareup/javapoet/JavaFile.java | 3 +- .../java/com/squareup/javapoet/MethodSpec.java | 9 +- .../java/com/squareup/javapoet/ParameterSpec.java | 4 +- src/main/java/com/squareup/javapoet/TypeSpec.java | 122 +++++++++++++-------- .../com/squareup/javapoet/AnnotationSpecTest.java | 12 ++ .../java/com/squareup/javapoet/FieldSpecTest.java | 19 +++- .../java/com/squareup/javapoet/JavaFileTest.java | 21 ++++ .../java/com/squareup/javapoet/MethodSpecTest.java | 39 ++++++- .../com/squareup/javapoet/ParameterSpecTest.java | 26 ++++- .../java/com/squareup/javapoet/TypeSpecTest.java | 104 +++++++++++++++++- 12 files changed, 300 insertions(+), 73 deletions(-) diff --git a/src/main/java/com/squareup/javapoet/AnnotationSpec.java b/src/main/java/com/squareup/javapoet/AnnotationSpec.java index d1c5e53..5525d7b 100644 --- a/src/main/java/com/squareup/javapoet/AnnotationSpec.java +++ b/src/main/java/com/squareup/javapoet/AnnotationSpec.java @@ -192,7 +192,8 @@ public final class AnnotationSpec { public static final class Builder { private final TypeName type; - private final Map> members = new LinkedHashMap<>(); + + public final Map> members = new LinkedHashMap<>(); private Builder(TypeName type) { this.type = type; @@ -203,8 +204,6 @@ public final class AnnotationSpec { } public Builder addMember(String name, CodeBlock codeBlock) { - checkNotNull(name, "name == null"); - checkArgument(SourceVersion.isName(name), "not a valid name: %s", name); List values = members.computeIfAbsent(name, k -> new ArrayList<>()); values.add(codeBlock); return this; @@ -238,6 +237,10 @@ public final class AnnotationSpec { } public AnnotationSpec build() { + for (String name : members.keySet()) { + checkNotNull(name, "name == null"); + checkArgument(SourceVersion.isName(name), "not a valid name: %s", name); + } return new AnnotationSpec(this); } } diff --git a/src/main/java/com/squareup/javapoet/FieldSpec.java b/src/main/java/com/squareup/javapoet/FieldSpec.java index 851b36d..f530d6e 100644 --- a/src/main/java/com/squareup/javapoet/FieldSpec.java +++ b/src/main/java/com/squareup/javapoet/FieldSpec.java @@ -111,10 +111,11 @@ public final class FieldSpec { private final String name; private final CodeBlock.Builder javadoc = CodeBlock.builder(); - private final List annotations = new ArrayList<>(); - private final List modifiers = new ArrayList<>(); private CodeBlock initializer = null; + public final List annotations = new ArrayList<>(); + public final List modifiers = new ArrayList<>(); + private Builder(TypeName type, String name) { this.type = type; this.name = name; diff --git a/src/main/java/com/squareup/javapoet/JavaFile.java b/src/main/java/com/squareup/javapoet/JavaFile.java index 41f6439..d5747a8 100644 --- a/src/main/java/com/squareup/javapoet/JavaFile.java +++ b/src/main/java/com/squareup/javapoet/JavaFile.java @@ -225,10 +225,11 @@ public final class JavaFile { private final String packageName; private final TypeSpec typeSpec; private final CodeBlock.Builder fileComment = CodeBlock.builder(); - private final Set staticImports = new TreeSet<>(); private boolean skipJavaLangImports; private String indent = " "; + public final Set staticImports = new TreeSet<>(); + private Builder(String packageName, TypeSpec typeSpec) { this.packageName = packageName; this.typeSpec = typeSpec; diff --git a/src/main/java/com/squareup/javapoet/MethodSpec.java b/src/main/java/com/squareup/javapoet/MethodSpec.java index 850e537..b06290f 100644 --- a/src/main/java/com/squareup/javapoet/MethodSpec.java +++ b/src/main/java/com/squareup/javapoet/MethodSpec.java @@ -295,16 +295,17 @@ public final class MethodSpec { private String name; private final CodeBlock.Builder javadoc = CodeBlock.builder(); - private final List annotations = new ArrayList<>(); - private final List modifiers = new ArrayList<>(); - private List typeVariables = new ArrayList<>(); private TypeName returnType; - private final List parameters = new ArrayList<>(); private final Set exceptions = new LinkedHashSet<>(); private final CodeBlock.Builder code = CodeBlock.builder(); private boolean varargs; private CodeBlock defaultValue; + public final List typeVariables = new ArrayList<>(); + public final List annotations = new ArrayList<>(); + public final List modifiers = new ArrayList<>(); + public final List parameters = new ArrayList<>(); + private Builder(String name) { setName(name); } diff --git a/src/main/java/com/squareup/javapoet/ParameterSpec.java b/src/main/java/com/squareup/javapoet/ParameterSpec.java index 386ed1a..b8f3129 100644 --- a/src/main/java/com/squareup/javapoet/ParameterSpec.java +++ b/src/main/java/com/squareup/javapoet/ParameterSpec.java @@ -136,8 +136,8 @@ public final class ParameterSpec { private final String name; private final CodeBlock.Builder javadoc = CodeBlock.builder(); - private final List annotations = new ArrayList<>(); - private final List modifiers = new ArrayList<>(); + public final List annotations = new ArrayList<>(); + public final List modifiers = new ArrayList<>(); private Builder(TypeName type, String name) { this.type = type; diff --git a/src/main/java/com/squareup/javapoet/TypeSpec.java b/src/main/java/com/squareup/javapoet/TypeSpec.java index cf65bcf..2b695c2 100644 --- a/src/main/java/com/squareup/javapoet/TypeSpec.java +++ b/src/main/java/com/squareup/javapoet/TypeSpec.java @@ -400,18 +400,19 @@ public final class TypeSpec { private final CodeBlock anonymousTypeArguments; private final CodeBlock.Builder javadoc = CodeBlock.builder(); - private final List annotations = new ArrayList<>(); - private final List modifiers = new ArrayList<>(); - private final List typeVariables = new ArrayList<>(); private TypeName superclass = ClassName.OBJECT; - private final List superinterfaces = new ArrayList<>(); - private final Map enumConstants = new LinkedHashMap<>(); - private final List fieldSpecs = new ArrayList<>(); private final CodeBlock.Builder staticBlock = CodeBlock.builder(); private final CodeBlock.Builder initializerBlock = CodeBlock.builder(); - private final List methodSpecs = new ArrayList<>(); - private final List typeSpecs = new ArrayList<>(); - private final List originatingElements = new ArrayList<>(); + + public final Map enumConstants = new LinkedHashMap<>(); + public final List annotations = new ArrayList<>(); + public final List modifiers = new ArrayList<>(); + public final List typeVariables = new ArrayList<>(); + public final List superinterfaces = new ArrayList<>(); + public final List fieldSpecs = new ArrayList<>(); + public final List methodSpecs = new ArrayList<>(); + public final List typeSpecs = new ArrayList<>(); + public final List originatingElements = new ArrayList<>(); private Builder(Kind kind, String name, CodeBlock anonymousTypeArguments) { @@ -454,16 +455,11 @@ public final class TypeSpec { } public Builder addModifiers(Modifier... modifiers) { - checkState(anonymousTypeArguments == null, "forbidden on anonymous types."); - for (Modifier modifier : modifiers) { - checkArgument(modifier != null, "modifiers contain null"); - this.modifiers.add(modifier); - } + Collections.addAll(this.modifiers, modifiers); return this; } public Builder addTypeVariables(Iterable typeVariables) { - checkState(anonymousTypeArguments == null, "forbidden on anonymous types."); checkArgument(typeVariables != null, "typeVariables == null"); for (TypeVariableName typeVariable : typeVariables) { this.typeVariables.add(typeVariable); @@ -472,7 +468,6 @@ public final class TypeSpec { } public Builder addTypeVariable(TypeVariableName typeVariable) { - checkState(anonymousTypeArguments == null, "forbidden on anonymous types."); typeVariables.add(typeVariable); return this; } @@ -513,10 +508,6 @@ public final class TypeSpec { } public Builder addEnumConstant(String name, TypeSpec typeSpec) { - checkState(kind == Kind.ENUM, "%s is not enum", this.name); - checkArgument(typeSpec.anonymousTypeArguments != null, - "enum constants must have anonymous type arguments"); - checkArgument(SourceVersion.isName(name), "not a valid enum constant: %s", name); enumConstants.put(name, typeSpec); return this; } @@ -530,12 +521,6 @@ public final class TypeSpec { } public Builder addField(FieldSpec fieldSpec) { - if (kind == Kind.INTERFACE || kind == Kind.ANNOTATION) { - requireExactlyOneOf(fieldSpec.modifiers, Modifier.PUBLIC, Modifier.PRIVATE); - Set check = EnumSet.of(Modifier.STATIC, Modifier.FINAL); - checkState(fieldSpec.modifiers.containsAll(check), "%s %s.%s requires modifiers %s", - kind, name, fieldSpec.name, check); - } fieldSpecs.add(fieldSpec); return this; } @@ -574,23 +559,6 @@ public final class TypeSpec { } public Builder addMethod(MethodSpec methodSpec) { - if (kind == Kind.INTERFACE) { - requireExactlyOneOf(methodSpec.modifiers, Modifier.ABSTRACT, Modifier.STATIC, - Modifier.DEFAULT); - requireExactlyOneOf(methodSpec.modifiers, Modifier.PUBLIC, Modifier.PRIVATE); - } else if (kind == Kind.ANNOTATION) { - checkState(methodSpec.modifiers.equals(kind.implicitMethodModifiers), - "%s %s.%s requires modifiers %s", - kind, name, methodSpec.name, kind.implicitMethodModifiers); - } - if (kind != Kind.ANNOTATION) { - checkState(methodSpec.defaultValue == null, "%s %s.%s cannot have a default value", - kind, name, methodSpec.name); - } - if (kind != Kind.INTERFACE) { - checkState(!methodSpec.hasModifier(Modifier.DEFAULT), "%s %s.%s cannot be default", - kind, name, methodSpec.name); - } methodSpecs.add(methodSpec); return this; } @@ -604,9 +572,6 @@ public final class TypeSpec { } public Builder addType(TypeSpec typeSpec) { - checkArgument(typeSpec.modifiers.containsAll(kind.implicitTypeModifiers), - "%s %s.%s requires modifiers %s", kind, name, typeSpec.name, - kind.implicitTypeModifiers); typeSpecs.add(typeSpec); return this; } @@ -617,9 +582,74 @@ public final class TypeSpec { } public TypeSpec build() { + for (AnnotationSpec annotationSpec : annotations) { + checkNotNull(annotationSpec, "annotationSpec == null"); + } + + if (!modifiers.isEmpty()) { + checkState(anonymousTypeArguments == null, "forbidden on anonymous types."); + for (Modifier modifier : modifiers) { + checkArgument(modifier != null, "modifiers contain null"); + } + } + checkArgument(kind != Kind.ENUM || !enumConstants.isEmpty(), "at least one enum constant is required for %s", name); + for (TypeName superinterface : superinterfaces) { + checkArgument(superinterface != null, "superinterfaces contains null"); + } + + if (!typeVariables.isEmpty()) { + checkState(anonymousTypeArguments == null, + "typevariables are forbidden on anonymous types."); + for (TypeVariableName typeVariableName : typeVariables) { + checkArgument(typeVariableName != null, "typeVariables contain null"); + } + } + + for (Map.Entry enumConstant : enumConstants.entrySet()) { + checkState(kind == Kind.ENUM, "%s is not enum", this.name); + checkArgument(enumConstant.getValue().anonymousTypeArguments != null, + "enum constants must have anonymous type arguments"); + checkArgument(SourceVersion.isName(name), "not a valid enum constant: %s", name); + } + + for (FieldSpec fieldSpec : fieldSpecs) { + if (kind == Kind.INTERFACE || kind == Kind.ANNOTATION) { + requireExactlyOneOf(fieldSpec.modifiers, Modifier.PUBLIC, Modifier.PRIVATE); + Set check = EnumSet.of(Modifier.STATIC, Modifier.FINAL); + checkState(fieldSpec.modifiers.containsAll(check), "%s %s.%s requires modifiers %s", + kind, name, fieldSpec.name, check); + } + } + + for (MethodSpec methodSpec : methodSpecs) { + if (kind == Kind.INTERFACE) { + requireExactlyOneOf(methodSpec.modifiers, Modifier.ABSTRACT, Modifier.STATIC, + Modifier.DEFAULT); + requireExactlyOneOf(methodSpec.modifiers, Modifier.PUBLIC, Modifier.PRIVATE); + } else if (kind == Kind.ANNOTATION) { + checkState(methodSpec.modifiers.equals(kind.implicitMethodModifiers), + "%s %s.%s requires modifiers %s", + kind, name, methodSpec.name, kind.implicitMethodModifiers); + } + if (kind != Kind.ANNOTATION) { + checkState(methodSpec.defaultValue == null, "%s %s.%s cannot have a default value", + kind, name, methodSpec.name); + } + if (kind != Kind.INTERFACE) { + checkState(!methodSpec.hasModifier(Modifier.DEFAULT), "%s %s.%s cannot be default", + kind, name, methodSpec.name); + } + } + + for (TypeSpec typeSpec : typeSpecs) { + checkArgument(typeSpec.modifiers.containsAll(kind.implicitTypeModifiers), + "%s %s.%s requires modifiers %s", kind, name, typeSpec.name, + kind.implicitTypeModifiers); + } + boolean isAbstract = modifiers.contains(Modifier.ABSTRACT) || kind != Kind.CLASS; for (MethodSpec methodSpec : methodSpecs) { checkArgument(isAbstract || !methodSpec.hasModifier(Modifier.ABSTRACT), diff --git a/src/test/java/com/squareup/javapoet/AnnotationSpecTest.java b/src/test/java/com/squareup/javapoet/AnnotationSpecTest.java index 49606c7..97c1e6e 100644 --- a/src/test/java/com/squareup/javapoet/AnnotationSpecTest.java +++ b/src/test/java/com/squareup/javapoet/AnnotationSpecTest.java @@ -20,6 +20,8 @@ import java.lang.annotation.Annotation; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; + import javax.lang.model.element.TypeElement; import org.junit.Rule; import org.junit.Test; @@ -371,6 +373,16 @@ public final class AnnotationSpecTest { } } + @Test public void modifyMembers() { + AnnotationSpec.Builder builder = AnnotationSpec.builder(SuppressWarnings.class) + .addMember("value", "$S", "Foo"); + + builder.members.clear(); + builder.members.put("value", Arrays.asList(CodeBlock.of("$S", "Bar"))); + + assertThat(builder.build().toString()).isEqualTo("@java.lang.SuppressWarnings(\"Bar\")"); + } + private String toString(TypeSpec typeSpec) { return JavaFile.builder("com.squareup.tacos", typeSpec).build().toString(); } diff --git a/src/test/java/com/squareup/javapoet/FieldSpecTest.java b/src/test/java/com/squareup/javapoet/FieldSpecTest.java index 51d093e..bc68f6f 100644 --- a/src/test/java/com/squareup/javapoet/FieldSpecTest.java +++ b/src/test/java/com/squareup/javapoet/FieldSpecTest.java @@ -46,4 +46,21 @@ public class FieldSpecTest { .isEqualTo("annotationSpecs == null"); } } -} \ No newline at end of file + + @Test public void modifyAnnotations() { + FieldSpec.Builder builder = FieldSpec.builder(int.class, "foo") + .addAnnotation(Override.class) + .addAnnotation(SuppressWarnings.class); + + builder.annotations.remove(1); + assertThat(builder.build().annotations).hasSize(1); + } + + @Test public void modifyModifiers() { + FieldSpec.Builder builder = FieldSpec.builder(int.class, "foo") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC); + + builder.modifiers.remove(1); + assertThat(builder.build().modifiers).containsExactly(Modifier.PUBLIC); + } +} diff --git a/src/test/java/com/squareup/javapoet/JavaFileTest.java b/src/test/java/com/squareup/javapoet/JavaFileTest.java index e056116..f7583f1 100644 --- a/src/test/java/com/squareup/javapoet/JavaFileTest.java +++ b/src/test/java/com/squareup/javapoet/JavaFileTest.java @@ -15,6 +15,7 @@ */ package com.squareup.javapoet; +import java.io.File; import java.util.Collections; import java.util.Date; import java.util.List; @@ -689,4 +690,24 @@ public final class JavaFileTest { + " A a;\n" + "}\n"); } + + @Test public void modifyStaticImports() throws Exception { + JavaFile.Builder builder = JavaFile.builder("com.squareup.tacos", + TypeSpec.classBuilder("Taco") + .build()) + .addStaticImport(File.class, "separator"); + + builder.staticImports.clear(); + builder.staticImports.add(File.class.getCanonicalName() + ".separatorChar"); + + String source = builder.build().toString(); + + assertThat(source).isEqualTo("" + + "package com.squareup.tacos;\n" + + "\n" + + "import static java.io.File.separatorChar;\n" + + "\n" + + "class Taco {\n" + + "}\n"); + } } diff --git a/src/test/java/com/squareup/javapoet/MethodSpecTest.java b/src/test/java/com/squareup/javapoet/MethodSpecTest.java index 98fd8f6..789661d 100644 --- a/src/test/java/com/squareup/javapoet/MethodSpecTest.java +++ b/src/test/java/com/squareup/javapoet/MethodSpecTest.java @@ -356,8 +356,41 @@ public final class MethodSpecTest { .setName("revisedMethod") .build(); - assertThat(methodSpec.toString()).isEqualTo("" - + "void revisedMethod() {\n" - + "}\n"); + assertThat(methodSpec.toString()).isEqualTo("" + "void revisedMethod() {\n" + "}\n"); + } + + @Test public void modifyAnnotations() { + MethodSpec.Builder builder = MethodSpec.methodBuilder("foo") + .addAnnotation(Override.class) + .addAnnotation(SuppressWarnings.class); + + builder.annotations.remove(1); + assertThat(builder.build().annotations).hasSize(1); + } + + @Test public void modifyModifiers() { + MethodSpec.Builder builder = MethodSpec.methodBuilder("foo") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC); + + builder.modifiers.remove(1); + assertThat(builder.build().modifiers).containsExactly(Modifier.PUBLIC); + } + + @Test public void modifyParameters() { + MethodSpec.Builder builder = MethodSpec.methodBuilder("foo") + .addParameter(int.class, "source"); + + builder.parameters.remove(0); + assertThat(builder.build().parameters).isEmpty(); + } + + @Test public void modifyTypeVariables() { + TypeVariableName t = TypeVariableName.get("T"); + MethodSpec.Builder builder = MethodSpec.methodBuilder("foo") + .addTypeVariable(t) + .addTypeVariable(TypeVariableName.get("V")); + + builder.typeVariables.remove(1); + assertThat(builder.build().typeVariables).containsExactly(t); } } diff --git a/src/test/java/com/squareup/javapoet/ParameterSpecTest.java b/src/test/java/com/squareup/javapoet/ParameterSpecTest.java index 954db39..c3effca 100644 --- a/src/test/java/com/squareup/javapoet/ParameterSpecTest.java +++ b/src/test/java/com/squareup/javapoet/ParameterSpecTest.java @@ -25,6 +25,7 @@ import javax.lang.model.element.VariableElement; import javax.lang.model.util.Elements; import org.junit.Before; import org.junit.Rule; +import javax.lang.model.element.Modifier; import org.junit.Test; import static com.google.common.truth.Truth.assertThat; @@ -33,8 +34,6 @@ import static javax.lang.model.util.ElementFilter.fieldsIn; import static javax.lang.model.util.ElementFilter.methodsIn; import static org.junit.Assert.fail; -import javax.lang.model.element.Modifier; - public class ParameterSpecTest { @Rule public final CompilationRule compilation = new CompilationRule(); @@ -109,11 +108,28 @@ public class ParameterSpecTest { modifiers.add(Modifier.PUBLIC); try { - ParameterSpec.builder(int.class, "foo").addModifiers(modifiers); + ParameterSpec.builder(int.class, "foo") + .addModifiers(modifiers); fail(); } catch (Exception e) { - assertThat(e.getMessage()) - .isEqualTo("unexpected parameter modifier: public"); + assertThat(e.getMessage()).isEqualTo("unexpected parameter modifier: public"); } } + + @Test public void modifyAnnotations() { + ParameterSpec.Builder builder = ParameterSpec.builder(int.class, "foo") + .addAnnotation(Override.class) + .addAnnotation(SuppressWarnings.class); + + builder.annotations.remove(1); + assertThat(builder.build().annotations).hasSize(1); + } + + @Test public void modifyModifiers() { + ParameterSpec.Builder builder = ParameterSpec.builder(int.class, "foo") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC); + + builder.modifiers.remove(1); + assertThat(builder.build().modifiers).containsExactly(Modifier.PUBLIC); + } } diff --git a/src/test/java/com/squareup/javapoet/TypeSpecTest.java b/src/test/java/com/squareup/javapoet/TypeSpecTest.java index 733483b..6175607 100644 --- a/src/test/java/com/squareup/javapoet/TypeSpecTest.java +++ b/src/test/java/com/squareup/javapoet/TypeSpecTest.java @@ -17,6 +17,14 @@ package com.squareup.javapoet; import com.google.common.collect.ImmutableMap; import com.google.testing.compile.CompilationRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mockito; + +import java.io.File; import java.io.IOException; import java.io.Serializable; import java.math.BigDecimal; @@ -31,15 +39,11 @@ import java.util.Locale; import java.util.Map; import java.util.Random; import java.util.concurrent.Callable; + import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; @@ -1907,7 +1911,7 @@ public final class TypeSpecTest { @Test public void nullModifiersAddition() { try { - TypeSpec.classBuilder("Taco").addModifiers((Modifier) null); + TypeSpec.classBuilder("Taco").addModifiers((Modifier) null).build(); fail(); } catch(IllegalArgumentException expected) { assertThat(expected.getMessage()) @@ -2424,4 +2428,92 @@ public final class TypeSpecTest { assertThat(TypeSpec.enumBuilder(className).addEnumConstant("A").build().name).isEqualTo("Example"); assertThat(TypeSpec.annotationBuilder(className).build().name).isEqualTo("Example"); } + + @Test + public void modifyAnnotations() { + TypeSpec.Builder builder = + TypeSpec.classBuilder("Taco") + .addAnnotation(Override.class) + .addAnnotation(SuppressWarnings.class); + + builder.annotations.remove(1); + assertThat(builder.build().annotations).hasSize(1); + } + + @Test + public void modifyModifiers() { + TypeSpec.Builder builder = + TypeSpec.classBuilder("Taco").addModifiers(Modifier.PUBLIC, Modifier.FINAL); + + builder.modifiers.remove(1); + assertThat(builder.build().modifiers).containsExactly(Modifier.PUBLIC); + } + + @Test + public void modifyFields() { + TypeSpec.Builder builder = TypeSpec.classBuilder("Taco") + .addField(int.class, "source"); + + builder.fieldSpecs.remove(0); + assertThat(builder.build().fieldSpecs).isEmpty(); + } + + @Test + public void modifyTypeVariables() { + TypeVariableName t = TypeVariableName.get("T"); + TypeSpec.Builder builder = + TypeSpec.classBuilder("Taco") + .addTypeVariable(t) + .addTypeVariable(TypeVariableName.get("V")); + + builder.typeVariables.remove(1); + assertThat(builder.build().typeVariables).containsExactly(t); + } + + @Test + public void modifySuperinterfaces() { + TypeSpec.Builder builder = TypeSpec.classBuilder("Taco") + .addSuperinterface(File.class); + + builder.superinterfaces.clear(); + assertThat(builder.build().superinterfaces).isEmpty(); + } + + @Test + public void modifyMethods() { + TypeSpec.Builder builder = TypeSpec.classBuilder("Taco") + .addMethod(MethodSpec.methodBuilder("bell").build()); + + builder.methodSpecs.clear(); + assertThat(builder.build().methodSpecs).isEmpty(); + } + + @Test + public void modifyTypes() { + TypeSpec.Builder builder = TypeSpec.classBuilder("Taco") + .addType(TypeSpec.classBuilder("Bell").build()); + + builder.typeSpecs.clear(); + assertThat(builder.build().typeSpecs).isEmpty(); + } + + @Test + public void modifyEnumConstants() { + TypeSpec constantType = TypeSpec.anonymousClassBuilder("").build(); + TypeSpec.Builder builder = TypeSpec.enumBuilder("Taco") + .addEnumConstant("BELL", constantType) + .addEnumConstant("WUT", TypeSpec.anonymousClassBuilder("").build()); + + builder.enumConstants.remove("WUT"); + assertThat(builder.build().enumConstants).containsExactly("BELL", constantType); + } + + @Test + public void modifyOriginatingElements() { + TypeSpec.Builder builder = TypeSpec.classBuilder("Taco") + .addOriginatingElement(Mockito.mock(Element.class)); + + builder.originatingElements.clear(); + assertThat(builder.build().originatingElements).isEmpty(); + } } -- cgit v1.2.3 From e2ed025d5936a65836f1a6f79c750a3197f290e9 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Wed, 1 Jan 2020 08:40:39 -0500 Subject: Ensure trailing newlines in javadocs and method bodies (#732) * Add RecordingAppendable in LineWrapper for tracking last emitted char * Check lastChar in javadoc emission to emit newline if necessary Resolves #731 * Move trailing newline check to emit() overload for reuse Allows using from anywhere emitting a CodeBlock * Ensure trailing newlines in method bodies Resolves #722 * Add dedicated trailing newline in javadoc test * Fix modifier ordering * Fix rebase conflict Co-authored-by: Egor Andreevich --- .../java/com/squareup/javapoet/CodeWriter.java | 9 ++++- .../java/com/squareup/javapoet/LineWrapper.java | 38 ++++++++++++++++++++-- .../java/com/squareup/javapoet/MethodSpec.java | 2 +- .../java/com/squareup/javapoet/MethodSpecTest.java | 23 +++++++++++++ .../java/com/squareup/javapoet/TypeSpecTest.java | 33 ++++++++++++++++++- 5 files changed, 100 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/squareup/javapoet/CodeWriter.java b/src/main/java/com/squareup/javapoet/CodeWriter.java index b2b088b..b2bc3d3 100644 --- a/src/main/java/com/squareup/javapoet/CodeWriter.java +++ b/src/main/java/com/squareup/javapoet/CodeWriter.java @@ -149,7 +149,7 @@ final class CodeWriter { emit("/**\n"); javadoc = true; try { - emit(javadocCodeBlock); + emit(javadocCodeBlock, true); } finally { javadoc = false; } @@ -219,6 +219,10 @@ final class CodeWriter { } public CodeWriter emit(CodeBlock codeBlock) throws IOException { + return emit(codeBlock, false); + } + + public CodeWriter emit(CodeBlock codeBlock, boolean ensureTrailingNewline) throws IOException { int a = 0; ClassName deferredTypeName = null; // used by "import static" logic ListIterator partIterator = codeBlock.formatParts.listIterator(); @@ -307,6 +311,9 @@ final class CodeWriter { break; } } + if (ensureTrailingNewline && out.lastChar() != '\n') { + emit("\n"); + } return this; } diff --git a/src/main/java/com/squareup/javapoet/LineWrapper.java b/src/main/java/com/squareup/javapoet/LineWrapper.java index 6aa3131..928d9f4 100644 --- a/src/main/java/com/squareup/javapoet/LineWrapper.java +++ b/src/main/java/com/squareup/javapoet/LineWrapper.java @@ -24,7 +24,7 @@ import static com.squareup.javapoet.Util.checkNotNull; * or soft-wrapping spaces using {@link #wrappingSpace}. */ final class LineWrapper { - private final Appendable out; + private final RecordingAppendable out; private final String indent; private final int columnLimit; private boolean closed; @@ -47,11 +47,16 @@ final class LineWrapper { LineWrapper(Appendable out, String indent, int columnLimit) { checkNotNull(out, "out == null"); - this.out = out; + this.out = new RecordingAppendable(out); this.indent = indent; this.columnLimit = columnLimit; } + /** @return the last emitted char or {@link Character#MIN_VALUE} if nothing emitted yet. */ + char lastChar() { + return out.lastChar; + } + /** Emit {@code s}. This may be buffered to permit line wraps to be inserted. */ void append(String s) throws IOException { if (closed) throw new IllegalStateException("closed"); @@ -134,4 +139,33 @@ final class LineWrapper { private enum FlushType { WRAP, SPACE, EMPTY; } + + /** A delegating {@link Appendable} that records info about the chars passing through it. */ + static final class RecordingAppendable implements Appendable { + private final Appendable delegate; + + char lastChar = Character.MIN_VALUE; + + RecordingAppendable(Appendable delegate) { + this.delegate = delegate; + } + + @Override public Appendable append(CharSequence csq) throws IOException { + int length = csq.length(); + if (length != 0) { + lastChar = csq.charAt(length - 1); + } + return delegate.append(csq); + } + + @Override public Appendable append(CharSequence csq, int start, int end) throws IOException { + CharSequence sub = csq.subSequence(start, end); + return append(sub); + } + + @Override public Appendable append(char c) throws IOException { + lastChar = c; + return delegate.append(c); + } + } } diff --git a/src/main/java/com/squareup/javapoet/MethodSpec.java b/src/main/java/com/squareup/javapoet/MethodSpec.java index b06290f..2f9be0e 100644 --- a/src/main/java/com/squareup/javapoet/MethodSpec.java +++ b/src/main/java/com/squareup/javapoet/MethodSpec.java @@ -132,7 +132,7 @@ public final class MethodSpec { codeWriter.emit(" {\n"); codeWriter.indent(); - codeWriter.emit(code); + codeWriter.emit(code, true); codeWriter.unindent(); codeWriter.emit("}\n"); diff --git a/src/test/java/com/squareup/javapoet/MethodSpecTest.java b/src/test/java/com/squareup/javapoet/MethodSpecTest.java index 789661d..8704ec1 100644 --- a/src/test/java/com/squareup/javapoet/MethodSpecTest.java +++ b/src/test/java/com/squareup/javapoet/MethodSpecTest.java @@ -393,4 +393,27 @@ public final class MethodSpecTest { builder.typeVariables.remove(1); assertThat(builder.build().typeVariables).containsExactly(t); } + + @Test public void ensureTrailingNewline() { + MethodSpec methodSpec = MethodSpec.methodBuilder("method") + .addCode("codeWithNoNewline();") + .build(); + + assertThat(methodSpec.toString()).isEqualTo("" + + "void method() {\n" + + " codeWithNoNewline();\n" + + "}\n"); + } + + /** Ensures that we don't add a duplicate newline if one is already present. */ + @Test public void ensureTrailingNewlineWithExistingNewline() { + MethodSpec methodSpec = MethodSpec.methodBuilder("method") + .addCode("codeWithNoNewline();\n") // Have a newline already, so ensure we're not adding one + .build(); + + assertThat(methodSpec.toString()).isEqualTo("" + + "void method() {\n" + + " codeWithNoNewline();\n" + + "}\n"); + } } diff --git a/src/test/java/com/squareup/javapoet/TypeSpecTest.java b/src/test/java/com/squareup/javapoet/TypeSpecTest.java index 6175607..f76e6f0 100644 --- a/src/test/java/com/squareup/javapoet/TypeSpecTest.java +++ b/src/test/java/com/squareup/javapoet/TypeSpecTest.java @@ -1852,7 +1852,8 @@ public final class TypeSpecTest { + " }\n" + "\n" + " /**\n" - + " * chosen by fair dice roll ;) */\n" + + " * chosen by fair dice roll ;)\n" + + " */\n" + " public int getRandomQuantity() {\n" + " return 4;\n" + " }\n" @@ -2516,4 +2517,34 @@ public final class TypeSpecTest { builder.originatingElements.clear(); assertThat(builder.build().originatingElements).isEmpty(); } + + @Test public void javadocWithTrailingLineDoesNotAddAnother() { + TypeSpec spec = TypeSpec.classBuilder("Taco") + .addJavadoc("Some doc with a newline\n") + .build(); + + assertThat(toString(spec)).isEqualTo("" + + "package com.squareup.tacos;\n" + + "\n" + + "/**\n" + + " * Some doc with a newline\n" + + " */\n" + + "class Taco {\n" + + "}\n"); + } + + @Test public void javadocEnsuresTrailingLine() { + TypeSpec spec = TypeSpec.classBuilder("Taco") + .addJavadoc("Some doc with a newline") + .build(); + + assertThat(toString(spec)).isEqualTo("" + + "package com.squareup.tacos;\n" + + "\n" + + "/**\n" + + " * Some doc with a newline\n" + + " */\n" + + "class Taco {\n" + + "}\n"); + } } -- cgit v1.2.3 From 1225800fdbd05d6a2b069fc1e4949f6461a7236b Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Wed, 1 Jan 2020 17:31:32 -0500 Subject: Copy originating elements in toBuilder() as well (#750) * Copy originating elements in toBuilder() as well Fixes #749 * Add test --- src/main/java/com/squareup/javapoet/TypeSpec.java | 1 + src/test/java/com/squareup/javapoet/TypeSpecTest.java | 17 +++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/squareup/javapoet/TypeSpec.java b/src/main/java/com/squareup/javapoet/TypeSpec.java index 2b695c2..2395213 100644 --- a/src/main/java/com/squareup/javapoet/TypeSpec.java +++ b/src/main/java/com/squareup/javapoet/TypeSpec.java @@ -168,6 +168,7 @@ public final class TypeSpec { builder.typeSpecs.addAll(typeSpecs); builder.initializerBlock.add(initializerBlock); builder.staticBlock.add(staticBlock); + builder.originatingElements.addAll(originatingElements); return builder; } diff --git a/src/test/java/com/squareup/javapoet/TypeSpecTest.java b/src/test/java/com/squareup/javapoet/TypeSpecTest.java index f76e6f0..4943fc9 100644 --- a/src/test/java/com/squareup/javapoet/TypeSpecTest.java +++ b/src/test/java/com/squareup/javapoet/TypeSpecTest.java @@ -17,13 +17,6 @@ package com.squareup.javapoet; import com.google.common.collect.ImmutableMap; import com.google.testing.compile.CompilationRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - import java.io.File; import java.io.IOException; import java.io.Serializable; @@ -39,11 +32,15 @@ import java.util.Locale; import java.util.Map; import java.util.Random; import java.util.concurrent.Callable; - import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mockito; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; @@ -2269,6 +2266,7 @@ public final class TypeSpecTest { @Test public void initializersToBuilder() { // Tests if toBuilder() contains correct static and instance initializers + Element originatingElement = getElement(TypeSpecTest.class); TypeSpec taco = TypeSpec.classBuilder("Taco") .addField(String.class, "foo", Modifier.PRIVATE) .addField(String.class, "FOO", Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) @@ -2285,10 +2283,13 @@ public final class TypeSpecTest { .addInitializerBlock(CodeBlock.builder() .addStatement("foo = $S", "FOO") .build()) + .addOriginatingElement(originatingElement) .build(); TypeSpec recreatedTaco = taco.toBuilder().build(); assertThat(toString(taco)).isEqualTo(toString(recreatedTaco)); + assertThat(taco.originatingElements) + .containsExactlyElementsIn(recreatedTaco.originatingElements); TypeSpec initializersAdded = taco.toBuilder() .addInitializerBlock(CodeBlock.builder() -- cgit v1.2.3 From 3d65852a482185e464c4986b862394691ac197da Mon Sep 17 00:00:00 2001 From: Vlad Topala Date: Thu, 2 Jan 2020 15:18:32 +0200 Subject: Hardcoded line separator bug (#684) * Use regex for new line character to cover both dos and unix endings when calling emitAndIndent - fixes #552 * Update CodeWriter to use linebreak matcher instead of \r\n --- .../java/com/squareup/javapoet/CodeWriter.java | 2 +- .../java/com/squareup/javapoet/CodeWriterTest.java | 23 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/squareup/javapoet/CodeWriterTest.java diff --git a/src/main/java/com/squareup/javapoet/CodeWriter.java b/src/main/java/com/squareup/javapoet/CodeWriter.java index b2bc3d3..2c634b5 100644 --- a/src/main/java/com/squareup/javapoet/CodeWriter.java +++ b/src/main/java/com/squareup/javapoet/CodeWriter.java @@ -461,7 +461,7 @@ final class CodeWriter { */ CodeWriter emitAndIndent(String s) throws IOException { boolean first = true; - for (String line : s.split("\n", -1)) { + for (String line : s.split("\\R", -1)) { // Emit a newline character. Make sure blank lines in Javadoc & comments look good. if (!first) { if ((javadoc || comment) && trailingNewline) { diff --git a/src/test/java/com/squareup/javapoet/CodeWriterTest.java b/src/test/java/com/squareup/javapoet/CodeWriterTest.java new file mode 100644 index 0000000..331d000 --- /dev/null +++ b/src/test/java/com/squareup/javapoet/CodeWriterTest.java @@ -0,0 +1,23 @@ +package com.squareup.javapoet; + +import org.junit.Test; + +import java.io.IOException; + +import static com.google.common.truth.Truth.assertThat; + +public class CodeWriterTest { + + @Test + public void emptyLineInJavaDocDosEndings() throws IOException { + CodeBlock javadocCodeBlock = CodeBlock.of("A\r\n\r\nB\r\n"); + StringBuilder out = new StringBuilder(); + new CodeWriter(out).emitJavadoc(javadocCodeBlock); + assertThat(out.toString()).isEqualTo( + "/**\n" + + " * A\n" + + " *\n" + + " * B\n" + + " */\n"); + } +} \ No newline at end of file -- cgit v1.2.3 From 25d19845b866c04a2fb3e11ce3d43ccb2e7b98cd Mon Sep 17 00:00:00 2001 From: Florian Enner Date: Sat, 4 Jan 2020 18:10:32 +0100 Subject: added convenience overloads for code blocks in control flow (#752) * added convenience overloads for code blocks in control flow * added javadoc and test * added test for do while block * fixed continuation space count --- .../java/com/squareup/javapoet/MethodSpec.java | 24 +++++++++++ .../java/com/squareup/javapoet/MethodSpecTest.java | 46 +++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/squareup/javapoet/MethodSpec.java b/src/main/java/com/squareup/javapoet/MethodSpec.java index 2f9be0e..67722c7 100644 --- a/src/main/java/com/squareup/javapoet/MethodSpec.java +++ b/src/main/java/com/squareup/javapoet/MethodSpec.java @@ -474,6 +474,14 @@ public final class MethodSpec { return this; } + /** + * @param codeBlock the control flow construct and its code, such as "if (foo == 5)". + * Shouldn't contain braces or newline characters. + */ + public Builder beginControlFlow(CodeBlock codeBlock) { + return beginControlFlow("$L", codeBlock); + } + /** * @param controlFlow the control flow construct and its code, such as "else if (foo == 10)". * Shouldn't contain braces or newline characters. @@ -483,6 +491,14 @@ public final class MethodSpec { return this; } + /** + * @param codeBlock the control flow construct and its code, such as "else if (foo == 10)". + * Shouldn't contain braces or newline characters. + */ + public Builder nextControlFlow(CodeBlock codeBlock) { + return nextControlFlow("$L", codeBlock); + } + public Builder endControlFlow() { code.endControlFlow(); return this; @@ -497,6 +513,14 @@ public final class MethodSpec { return this; } + /** + * @param codeBlock the optional control flow construct and its code, such as + * "while(foo == 20)". Only used for "do/while" control flows. + */ + public Builder endControlFlow(CodeBlock codeBlock) { + return endControlFlow("$L", codeBlock); + } + public Builder addStatement(String format, Object... args) { code.addStatement(format, args); return this; diff --git a/src/test/java/com/squareup/javapoet/MethodSpecTest.java b/src/test/java/com/squareup/javapoet/MethodSpecTest.java index 8704ec1..5d3a434 100644 --- a/src/test/java/com/squareup/javapoet/MethodSpecTest.java +++ b/src/test/java/com/squareup/javapoet/MethodSpecTest.java @@ -21,8 +21,9 @@ import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Target; import java.util.Arrays; -import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.TimeoutException; import javax.lang.model.element.ExecutableElement; @@ -416,4 +417,47 @@ public final class MethodSpecTest { + " codeWithNoNewline();\n" + "}\n"); } + + @Test public void controlFlowWithNamedCodeBlocks() { + Map m = new HashMap<>(); + m.put("field", "valueField"); + m.put("threshold", "5"); + + MethodSpec methodSpec = MethodSpec.methodBuilder("method") + .beginControlFlow(named("if ($field:N > $threshold:L)", m)) + .nextControlFlow(named("else if ($field:N == $threshold:L)", m)) + .endControlFlow() + .build(); + + assertThat(methodSpec.toString()).isEqualTo("" + + "void method() {\n" + + " if (valueField > 5) {\n" + + " } else if (valueField == 5) {\n" + + " }\n" + + "}\n"); + } + + @Test public void doWhileWithNamedCodeBlocks() { + Map m = new HashMap<>(); + m.put("field", "valueField"); + m.put("threshold", "5"); + + MethodSpec methodSpec = MethodSpec.methodBuilder("method") + .beginControlFlow("do") + .addStatement(named("$field:N--", m)) + .endControlFlow(named("while ($field:N > $threshold:L)", m)) + .build(); + + assertThat(methodSpec.toString()).isEqualTo("" + + "void method() {\n" + + " do {\n" + + " valueField--;\n" + + " } while (valueField > 5);\n" + + "}\n"); + } + + private static CodeBlock named(String format, Map args){ + return CodeBlock.builder().addNamed(format, args).build(); + } + } -- cgit v1.2.3 From 80ddc99409399bd15b06509a6e3e75cb4117b8d2 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 6 Jan 2020 14:01:52 -0500 Subject: Add alwaysQualify() API to avoid collisions with known colliding types (#734) * Add alwaysQualify() API to avoid collisions with known colliding types Implementation based on https://github.com/square/javapoet/issues/77#issuecomment-507387399 Resolves #77 CC @eamonnmcmanus * Add utility avoidClashesWithNestedClasses methods for Class/TypeElement * Fix style issues * Move scope to TypeSpecs * Check superclasses and superinterfaces * Add superclass and superinterface overloads * Style fixes * Add qualified names to toBuilder test * Add Map.Entry test + doc regression tests --- .../java/com/squareup/javapoet/CodeWriter.java | 18 +- src/main/java/com/squareup/javapoet/JavaFile.java | 30 +- src/main/java/com/squareup/javapoet/TypeSpec.java | 173 +++++++++++- .../java/com/squareup/javapoet/JavaFileTest.java | 301 +++++++++++++++++++++ .../java/com/squareup/javapoet/TypeSpecTest.java | 3 + 5 files changed, 515 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/squareup/javapoet/CodeWriter.java b/src/main/java/com/squareup/javapoet/CodeWriter.java index 2c634b5..3b2f188 100644 --- a/src/main/java/com/squareup/javapoet/CodeWriter.java +++ b/src/main/java/com/squareup/javapoet/CodeWriter.java @@ -54,6 +54,7 @@ final class CodeWriter { private final List typeSpecStack = new ArrayList<>(); private final Set staticImportClassNames; private final Set staticImports; + private final Set alwaysQualify; private final Map importedTypes; private final Map importableTypes = new LinkedHashMap<>(); private final Set referencedNames = new LinkedHashSet<>(); @@ -68,19 +69,23 @@ final class CodeWriter { int statementLine = -1; CodeWriter(Appendable out) { - this(out, " ", Collections.emptySet()); + this(out, " ", Collections.emptySet(), Collections.emptySet()); } - CodeWriter(Appendable out, String indent, Set staticImports) { - this(out, indent, Collections.emptyMap(), staticImports); + CodeWriter(Appendable out, String indent, Set staticImports, Set alwaysQualify) { + this(out, indent, Collections.emptyMap(), staticImports, alwaysQualify); } - CodeWriter(Appendable out, String indent, Map importedTypes, - Set staticImports) { + CodeWriter(Appendable out, + String indent, + Map importedTypes, + Set staticImports, + Set alwaysQualify) { this.out = new LineWrapper(out, indent, 100); this.indent = checkNotNull(indent, "indent == null"); this.importedTypes = checkNotNull(importedTypes, "importedTypes == null"); this.staticImports = checkNotNull(staticImports, "staticImports == null"); + this.alwaysQualify = checkNotNull(alwaysQualify, "alwaysQualify == null"); this.staticImportClassNames = new LinkedHashSet<>(); for (String signature : staticImports) { staticImportClassNames.add(signature.substring(0, signature.lastIndexOf('.'))); @@ -409,6 +414,9 @@ final class CodeWriter { private void importableType(ClassName className) { if (className.packageName().isEmpty()) { return; + } else if (alwaysQualify.contains(className.simpleName)) { + // TODO what about nested types like java.util.Map.Entry? + return; } ClassName topLevelClassName = className.topLevelClassName(); String simpleName = topLevelClassName.simpleName(); diff --git a/src/main/java/com/squareup/javapoet/JavaFile.java b/src/main/java/com/squareup/javapoet/JavaFile.java index d5747a8..a419801 100644 --- a/src/main/java/com/squareup/javapoet/JavaFile.java +++ b/src/main/java/com/squareup/javapoet/JavaFile.java @@ -27,6 +27,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -60,6 +61,7 @@ public final class JavaFile { public final TypeSpec typeSpec; public final boolean skipJavaLangImports; private final Set staticImports; + private final Set alwaysQualify; private final String indent; private JavaFile(Builder builder) { @@ -69,16 +71,33 @@ public final class JavaFile { this.skipJavaLangImports = builder.skipJavaLangImports; this.staticImports = Util.immutableSet(builder.staticImports); this.indent = builder.indent; + + Set alwaysQualifiedNames = new LinkedHashSet<>(); + fillAlwaysQualifiedNames(builder.typeSpec, alwaysQualifiedNames); + this.alwaysQualify = Util.immutableSet(alwaysQualifiedNames); + } + + private void fillAlwaysQualifiedNames(TypeSpec spec, Set alwaysQualifiedNames) { + alwaysQualifiedNames.addAll(spec.alwaysQualifiedNames); + for (TypeSpec nested : spec.typeSpecs) { + fillAlwaysQualifiedNames(nested, alwaysQualifiedNames); + } } public void writeTo(Appendable out) throws IOException { // First pass: emit the entire class, just to collect the types we'll need to import. - CodeWriter importsCollector = new CodeWriter(NULL_APPENDABLE, indent, staticImports); + CodeWriter importsCollector = new CodeWriter( + NULL_APPENDABLE, + indent, + staticImports, + alwaysQualify + ); emit(importsCollector); Map suggestedImports = importsCollector.suggestedImports(); // Second pass: write the code, taking advantage of the imports. - CodeWriter codeWriter = new CodeWriter(out, indent, suggestedImports, staticImports); + CodeWriter codeWriter + = new CodeWriter(out, indent, suggestedImports, staticImports, alwaysQualify); emit(codeWriter); } @@ -153,7 +172,12 @@ public final class JavaFile { int importedTypesCount = 0; for (ClassName className : new TreeSet<>(codeWriter.importedTypes().values())) { - if (skipJavaLangImports && className.packageName().equals("java.lang")) continue; + // TODO what about nested types like java.util.Map.Entry? + if (skipJavaLangImports + && className.packageName().equals("java.lang") + && !alwaysQualify.contains(className.simpleName)) { + continue; + } codeWriter.emit("import $L;\n", className.withoutAnnotations()); importedTypesCount++; } diff --git a/src/main/java/com/squareup/javapoet/TypeSpec.java b/src/main/java/com/squareup/javapoet/TypeSpec.java index 2395213..5fb2bb3 100644 --- a/src/main/java/com/squareup/javapoet/TypeSpec.java +++ b/src/main/java/com/squareup/javapoet/TypeSpec.java @@ -16,6 +16,7 @@ package com.squareup.javapoet; import java.io.IOException; +import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; @@ -24,6 +25,7 @@ import java.util.EnumSet; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -31,6 +33,11 @@ import java.util.Set; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.NoType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; import static com.squareup.javapoet.Util.checkArgument; import static com.squareup.javapoet.Util.checkNotNull; @@ -56,6 +63,7 @@ public final class TypeSpec { public final List typeSpecs; final Set nestedTypesSimpleNames; public final List originatingElements; + public final Set alwaysQualifiedNames; private TypeSpec(Builder builder) { this.kind = builder.kind; @@ -73,6 +81,7 @@ public final class TypeSpec { this.initializerBlock = builder.initializerBlock.build(); this.methodSpecs = Util.immutableList(builder.methodSpecs); this.typeSpecs = Util.immutableList(builder.typeSpecs); + this.alwaysQualifiedNames = Util.immutableSet(builder.alwaysQualifiedNames); nestedTypesSimpleNames = new HashSet<>(builder.typeSpecs.size()); List originatingElementsMutable = new ArrayList<>(); @@ -108,6 +117,7 @@ public final class TypeSpec { this.typeSpecs = Collections.emptyList(); this.originatingElements = Collections.emptyList(); this.nestedTypesSimpleNames = Collections.emptySet(); + this.alwaysQualifiedNames = Collections.emptySet(); } public boolean hasModifier(Modifier modifier) { @@ -169,6 +179,7 @@ public final class TypeSpec { builder.initializerBlock.add(initializerBlock); builder.staticBlock.add(staticBlock); builder.originatingElements.addAll(originatingElements); + builder.alwaysQualifiedNames.addAll(alwaysQualifiedNames); return builder; } @@ -414,6 +425,7 @@ public final class TypeSpec { public final List methodSpecs = new ArrayList<>(); public final List typeSpecs = new ArrayList<>(); public final List originatingElements = new ArrayList<>(); + public final Set alwaysQualifiedNames = new LinkedHashSet<>(); private Builder(Kind kind, String name, CodeBlock anonymousTypeArguments) { @@ -483,7 +495,32 @@ public final class TypeSpec { } public Builder superclass(Type superclass) { - return superclass(TypeName.get(superclass)); + return superclass(superclass, true); + } + + public Builder superclass(Type superclass, boolean avoidNestedTypeNameClashes) { + superclass(TypeName.get(superclass)); + if (avoidNestedTypeNameClashes) { + Class clazz = getRawType(superclass); + if (clazz != null) { + avoidClashesWithNestedClasses(clazz); + } + } + return this; + } + + public Builder superclass(TypeMirror superclass) { + return superclass(superclass, true); + } + + public Builder superclass(TypeMirror superclass, boolean avoidNestedTypeNameClashes) { + superclass(TypeName.get(superclass)); + if (avoidNestedTypeNameClashes && superclass instanceof DeclaredType) { + TypeElement superInterfaceElement = + (TypeElement) ((DeclaredType) superclass).asElement(); + avoidClashesWithNestedClasses(superInterfaceElement); + } + return this; } public Builder addSuperinterfaces(Iterable superinterfaces) { @@ -501,7 +538,43 @@ public final class TypeSpec { } public Builder addSuperinterface(Type superinterface) { - return addSuperinterface(TypeName.get(superinterface)); + return addSuperinterface(superinterface, true); + } + + public Builder addSuperinterface(Type superinterface, boolean avoidNestedTypeNameClashes) { + addSuperinterface(TypeName.get(superinterface)); + if (avoidNestedTypeNameClashes) { + Class clazz = getRawType(superinterface); + if (clazz != null) { + avoidClashesWithNestedClasses(clazz); + } + } + return this; + } + + private Class getRawType(Type type) { + if (type instanceof Class) { + return (Class) type; + } else if (type instanceof ParameterizedType) { + return getRawType(((ParameterizedType) type).getRawType()); + } else { + return null; + } + } + + public Builder addSuperinterface(TypeMirror superinterface) { + return addSuperinterface(superinterface, true); + } + + public Builder addSuperinterface(TypeMirror superinterface, + boolean avoidNestedTypeNameClashes) { + addSuperinterface(TypeName.get(superinterface)); + if (avoidNestedTypeNameClashes && superinterface instanceof DeclaredType) { + TypeElement superInterfaceElement = + (TypeElement) ((DeclaredType) superinterface).asElement(); + avoidClashesWithNestedClasses(superInterfaceElement); + } + return this; } public Builder addEnumConstant(String name) { @@ -582,6 +655,102 @@ public final class TypeSpec { return this; } + public Builder alwaysQualify(String... simpleNames) { + checkArgument(simpleNames != null, "simpleNames == null"); + for (String name : simpleNames) { + checkArgument( + name != null, + "null entry in simpleNames array: %s", + Arrays.toString(simpleNames) + ); + alwaysQualifiedNames.add(name); + } + return this; + } + + /** + * Call this to always fully qualify any types that would conflict with possibly nested types of + * this {@code typeElement}. For example - if the following type was passed in as the + * typeElement: + * + *


+     *   class Foo {
+     *     class NestedTypeA {
+     *
+     *     }
+     *     class NestedTypeB {
+     *
+     *     }
+     *   }
+     * 
+ * + *

+ * Then this would add {@code "NestedTypeA"} and {@code "NestedTypeB"} as names that should + * always be qualified via {@link #alwaysQualify(String...)}. This way they would avoid + * possible import conflicts when this JavaFile is written. + * + * @param typeElement the {@link TypeElement} with nested types to avoid clashes with. + * @return this builder instance. + */ + public Builder avoidClashesWithNestedClasses(TypeElement typeElement) { + checkArgument(typeElement != null, "typeElement == null"); + for (TypeElement nestedType : ElementFilter.typesIn(typeElement.getEnclosedElements())) { + alwaysQualify(nestedType.getSimpleName().toString()); + } + TypeMirror superclass = typeElement.getSuperclass(); + if (!(superclass instanceof NoType) && superclass instanceof DeclaredType) { + TypeElement superclassElement = (TypeElement) ((DeclaredType) superclass).asElement(); + avoidClashesWithNestedClasses(superclassElement); + } + for (TypeMirror superinterface : typeElement.getInterfaces()) { + if (superinterface instanceof DeclaredType) { + TypeElement superinterfaceElement + = (TypeElement) ((DeclaredType) superinterface).asElement(); + avoidClashesWithNestedClasses(superinterfaceElement); + } + } + return this; + } + + /** + * Call this to always fully qualify any types that would conflict with possibly nested types of + * this {@code typeElement}. For example - if the following type was passed in as the + * typeElement: + * + *


+     *   class Foo {
+     *     class NestedTypeA {
+     *
+     *     }
+     *     class NestedTypeB {
+     *
+     *     }
+     *   }
+     * 
+ * + *

+ * Then this would add {@code "NestedTypeA"} and {@code "NestedTypeB"} as names that should + * always be qualified via {@link #alwaysQualify(String...)}. This way they would avoid + * possible import conflicts when this JavaFile is written. + * + * @param clazz the {@link Class} with nested types to avoid clashes with. + * @return this builder instance. + */ + public Builder avoidClashesWithNestedClasses(Class clazz) { + checkArgument(clazz != null, "clazz == null"); + for (Class nestedType : clazz.getDeclaredClasses()) { + alwaysQualify(nestedType.getSimpleName()); + } + Class superclass = clazz.getSuperclass(); + if (superclass != null && !Object.class.equals(superclass)) { + avoidClashesWithNestedClasses(superclass); + } + for (Class superinterface : clazz.getInterfaces()) { + avoidClashesWithNestedClasses(superinterface); + } + return this; + } + public TypeSpec build() { for (AnnotationSpec annotationSpec : annotations) { checkNotNull(annotationSpec, "annotationSpec == null"); diff --git a/src/test/java/com/squareup/javapoet/JavaFileTest.java b/src/test/java/com/squareup/javapoet/JavaFileTest.java index f7583f1..e75a019 100644 --- a/src/test/java/com/squareup/javapoet/JavaFileTest.java +++ b/src/test/java/com/squareup/javapoet/JavaFileTest.java @@ -16,12 +16,18 @@ package com.squareup.javapoet; import java.io.File; +import com.google.testing.compile.CompilationRule; import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -30,6 +36,13 @@ import static com.google.common.truth.Truth.assertThat; @RunWith(JUnit4.class) public final class JavaFileTest { + + @Rule public final CompilationRule compilation = new CompilationRule(); + + private TypeElement getElement(Class clazz) { + return compilation.getElements().getTypeElement(clazz.getCanonicalName()); + } + @Test public void importStaticReadmeExample() { ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard"); ClassName namedBoards = ClassName.get("com.mattel", "Hoverboard", "Boards"); @@ -710,4 +723,292 @@ public final class JavaFileTest { + "class Taco {\n" + "}\n"); } + + @Test public void alwaysQualifySimple() { + String source = JavaFile.builder("com.squareup.tacos", + TypeSpec.classBuilder("Taco") + .addField(Thread.class, "thread") + .alwaysQualify("Thread") + .build()) + .build() + .toString(); + assertThat(source).isEqualTo("" + + "package com.squareup.tacos;\n" + + "\n" + + "class Taco {\n" + + " java.lang.Thread thread;\n" + + "}\n"); + } + + @Test public void alwaysQualifySupersedesJavaLangImports() { + String source = JavaFile.builder("com.squareup.tacos", + TypeSpec.classBuilder("Taco") + .addField(Thread.class, "thread") + .alwaysQualify("Thread") + .build()) + .skipJavaLangImports(true) + .build() + .toString(); + assertThat(source).isEqualTo("" + + "package com.squareup.tacos;\n" + + "\n" + + "class Taco {\n" + + " java.lang.Thread thread;\n" + + "}\n"); + } + + @Test public void avoidClashesWithNestedClasses_viaClass() { + String source = JavaFile.builder("com.squareup.tacos", + TypeSpec.classBuilder("Taco") + // These two should get qualified + .addField(ClassName.get("other", "NestedTypeA"), "nestedA") + .addField(ClassName.get("other", "NestedTypeB"), "nestedB") + // This one shouldn't since it's not a nested type of Foo + .addField(ClassName.get("other", "NestedTypeC"), "nestedC") + // This one shouldn't since we only look at nested types + .addField(ClassName.get("other", "Foo"), "foo") + .avoidClashesWithNestedClasses(Foo.class) + .build()) + .build() + .toString(); + assertThat(source).isEqualTo("" + + "package com.squareup.tacos;\n" + + "\n" + + "import other.Foo;\n" + + "import other.NestedTypeC;\n" + + "\n" + + "class Taco {\n" + + " other.NestedTypeA nestedA;\n" + + "\n" + + " other.NestedTypeB nestedB;\n" + + "\n" + + " NestedTypeC nestedC;\n" + + "\n" + + " Foo foo;\n" + + "}\n"); + } + + @Test public void avoidClashesWithNestedClasses_viaTypeElement() { + String source = JavaFile.builder("com.squareup.tacos", + TypeSpec.classBuilder("Taco") + // These two should get qualified + .addField(ClassName.get("other", "NestedTypeA"), "nestedA") + .addField(ClassName.get("other", "NestedTypeB"), "nestedB") + // This one shouldn't since it's not a nested type of Foo + .addField(ClassName.get("other", "NestedTypeC"), "nestedC") + // This one shouldn't since we only look at nested types + .addField(ClassName.get("other", "Foo"), "foo") + .avoidClashesWithNestedClasses(getElement(Foo.class)) + .build()) + .build() + .toString(); + assertThat(source).isEqualTo("" + + "package com.squareup.tacos;\n" + + "\n" + + "import other.Foo;\n" + + "import other.NestedTypeC;\n" + + "\n" + + "class Taco {\n" + + " other.NestedTypeA nestedA;\n" + + "\n" + + " other.NestedTypeB nestedB;\n" + + "\n" + + " NestedTypeC nestedC;\n" + + "\n" + + " Foo foo;\n" + + "}\n"); + } + + @Test public void avoidClashesWithNestedClasses_viaSuperinterfaceType() { + String source = JavaFile.builder("com.squareup.tacos", + TypeSpec.classBuilder("Taco") + // These two should get qualified + .addField(ClassName.get("other", "NestedTypeA"), "nestedA") + .addField(ClassName.get("other", "NestedTypeB"), "nestedB") + // This one shouldn't since it's not a nested type of Foo + .addField(ClassName.get("other", "NestedTypeC"), "nestedC") + // This one shouldn't since we only look at nested types + .addField(ClassName.get("other", "Foo"), "foo") + .addType(TypeSpec.classBuilder("NestedTypeA").build()) + .addType(TypeSpec.classBuilder("NestedTypeB").build()) + .addSuperinterface(FooInterface.class) + .build()) + .build() + .toString(); + assertThat(source).isEqualTo("package com.squareup.tacos;\n" + + "\n" + + "import com.squareup.javapoet.JavaFileTest;\n" + + "import other.Foo;\n" + + "import other.NestedTypeC;\n" + + "\n" + + "class Taco implements JavaFileTest.FooInterface {\n" + + " other.NestedTypeA nestedA;\n" + + "\n" + + " other.NestedTypeB nestedB;\n" + + "\n" + + " NestedTypeC nestedC;\n" + + "\n" + + " Foo foo;\n" + + "\n" + + " class NestedTypeA {\n" + + " }\n" + + "\n" + + " class NestedTypeB {\n" + + " }\n" + + "}\n"); + } + + static class Foo { + static class NestedTypeA { + + } + static class NestedTypeB { + + } + } + + interface FooInterface { + class NestedTypeA { + + } + class NestedTypeB { + + } + } + + private TypeSpec.Builder childTypeBuilder() { + return TypeSpec.classBuilder("Child") + .addMethod(MethodSpec.methodBuilder("optionalString") + .returns(ParameterizedTypeName.get(Optional.class, String.class)) + .addStatement("return $T.empty()", Optional.class) + .build()) + .addMethod(MethodSpec.methodBuilder("pattern") + .returns(Pattern.class) + .addStatement("return null") + .build()); + } + + @Test + public void avoidClashes_parentChild_superclass_type() { + String source = JavaFile.builder("com.squareup.javapoet", + childTypeBuilder().superclass(Parent.class).build()) + .build() + .toString(); + assertThat(source).isEqualTo("package com.squareup.javapoet;\n" + + "\n" + + "import java.lang.String;\n" + + "\n" + + "class Child extends JavaFileTest.Parent {\n" + + " java.util.Optional optionalString() {\n" + + " return java.util.Optional.empty();\n" + + " }\n" + + "\n" + + " java.util.regex.Pattern pattern() {\n" + + " return null;\n" + + " }\n" + + "}\n"); + } + + @Test + public void avoidClashes_parentChild_superclass_typeMirror() { + String source = JavaFile.builder("com.squareup.javapoet", + childTypeBuilder().superclass(getElement(Parent.class).asType()).build()) + .build() + .toString(); + assertThat(source).isEqualTo("package com.squareup.javapoet;\n" + + "\n" + + "import java.lang.String;\n" + + "\n" + + "class Child extends JavaFileTest.Parent {\n" + + " java.util.Optional optionalString() {\n" + + " return java.util.Optional.empty();\n" + + " }\n" + + "\n" + + " java.util.regex.Pattern pattern() {\n" + + " return null;\n" + + " }\n" + + "}\n"); + } + + @Test + public void avoidClashes_parentChild_superinterface_type() { + String source = JavaFile.builder("com.squareup.javapoet", + childTypeBuilder().addSuperinterface(ParentInterface.class).build()) + .build() + .toString(); + assertThat(source).isEqualTo("package com.squareup.javapoet;\n" + + "\n" + + "import java.lang.String;\n" + + "import java.util.regex.Pattern;\n" + + "\n" + + "class Child implements JavaFileTest.ParentInterface {\n" + + " java.util.Optional optionalString() {\n" + + " return java.util.Optional.empty();\n" + + " }\n" + + "\n" + + " Pattern pattern() {\n" + + " return null;\n" + + " }\n" + + "}\n"); + } + + @Test + public void avoidClashes_parentChild_superinterface_typeMirror() { + String source = JavaFile.builder("com.squareup.javapoet", + childTypeBuilder().addSuperinterface(getElement(ParentInterface.class).asType()).build()) + .build() + .toString(); + assertThat(source).isEqualTo("package com.squareup.javapoet;\n" + + "\n" + + "import java.lang.String;\n" + + "import java.util.regex.Pattern;\n" + + "\n" + + "class Child implements JavaFileTest.ParentInterface {\n" + + " java.util.Optional optionalString() {\n" + + " return java.util.Optional.empty();\n" + + " }\n" + + "\n" + + " Pattern pattern() {\n" + + " return null;\n" + + " }\n" + + "}\n"); + } + + // Regression test for https://github.com/square/javapoet/issues/77 + // This covers class and inheritance + static class Parent implements ParentInterface { + static class Pattern { + + } + } + + interface ParentInterface { + class Optional { + + } + } + + // Regression test for case raised here: https://github.com/square/javapoet/issues/77#issuecomment-519972404 + @Test + public void avoidClashes_mapEntry() { + String source = JavaFile.builder("com.squareup.javapoet", + TypeSpec.classBuilder("MapType") + .addMethod(MethodSpec.methodBuilder("optionalString") + .returns(ClassName.get("com.foo", "Entry")) + .addStatement("return null") + .build()) + .addSuperinterface(Map.class) + .build()) + .build() + .toString(); + assertThat(source).isEqualTo("package com.squareup.javapoet;\n" + + "\n" + + "import java.util.Map;\n" + + "\n" + + "class MapType implements Map {\n" + + " com.foo.Entry optionalString() {\n" + + " return null;\n" + + " }\n" + + "}\n"); + } } diff --git a/src/test/java/com/squareup/javapoet/TypeSpecTest.java b/src/test/java/com/squareup/javapoet/TypeSpecTest.java index 4943fc9..0f67c5c 100644 --- a/src/test/java/com/squareup/javapoet/TypeSpecTest.java +++ b/src/test/java/com/squareup/javapoet/TypeSpecTest.java @@ -2284,12 +2284,15 @@ public final class TypeSpecTest { .addStatement("foo = $S", "FOO") .build()) .addOriginatingElement(originatingElement) + .alwaysQualify("com.example.AlwaysQualified") .build(); TypeSpec recreatedTaco = taco.toBuilder().build(); assertThat(toString(taco)).isEqualTo(toString(recreatedTaco)); assertThat(taco.originatingElements) .containsExactlyElementsIn(recreatedTaco.originatingElements); + assertThat(taco.alwaysQualifiedNames) + .containsExactlyElementsIn(recreatedTaco.alwaysQualifiedNames); TypeSpec initializersAdded = taco.toBuilder() .addInitializerBlock(CodeBlock.builder() -- cgit v1.2.3 From dc64ed1f9bf362e68451d75f302e6e656a114066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Galder=20Zamarren=CC=83o?= Date: Tue, 29 Jan 2019 08:44:01 +0100 Subject: Add writeTo methods returning Path/File written to #691 --- src/main/java/com/squareup/javapoet/JavaFile.java | 31 ++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/squareup/javapoet/JavaFile.java b/src/main/java/com/squareup/javapoet/JavaFile.java index a419801..d7fa6df 100644 --- a/src/main/java/com/squareup/javapoet/JavaFile.java +++ b/src/main/java/com/squareup/javapoet/JavaFile.java @@ -103,14 +103,30 @@ public final class JavaFile { /** Writes this to {@code directory} as UTF-8 using the standard directory structure. */ public void writeTo(Path directory) throws IOException { - writeTo(directory, UTF_8); + writeToPath(directory); } /** - * Writes this to {@code directory} with the provided {@code charset} - * using the standard directory structure. + * Writes this to {@code directory} with the provided {@code charset} using the standard directory + * structure. */ public void writeTo(Path directory, Charset charset) throws IOException { + writeToPath(directory, charset); + } + + /** + * Writes this to {@code directory} as UTF-8 using the standard directory structure. + * Returns the {@link Path} instance to which source is actually written. + * */ + public Path writeToPath(Path directory) throws IOException { + return writeToPath(directory, UTF_8); + } + + /** + * Writes this to {@code directory} with the provided {@code charset} using the standard directory + * structure. + * Returns the {@link Path} instance to which source is actually written. */ + public Path writeToPath(Path directory, Charset charset) throws IOException { checkArgument(Files.notExists(directory) || Files.isDirectory(directory), "path %s exists but is not a directory.", directory); Path outputDirectory = directory; @@ -125,6 +141,8 @@ public final class JavaFile { try (Writer writer = new OutputStreamWriter(Files.newOutputStream(outputPath), charset)) { writeTo(writer); } + + return outputPath; } /** Writes this to {@code directory} as UTF-8 using the standard directory structure. */ @@ -132,6 +150,13 @@ public final class JavaFile { writeTo(directory.toPath()); } + /** Writes this to {@code directory} as UTF-8 using the standard directory structure. + * Returns the {@link File} instance to which source is actually written. */ + public File writeToFile(File directory) throws IOException { + final Path outputPath = writeToPath(directory.toPath()); + return outputPath.toFile(); + } + /** Writes this to {@code filer}. */ public void writeTo(Filer filer) throws IOException { String fileName = packageName.isEmpty() -- cgit v1.2.3 From eff1ee43296678eb0b0588faf4f18c34d8be4baf Mon Sep 17 00:00:00 2001 From: Egor Andreevici Date: Mon, 6 Jan 2020 14:42:40 -0500 Subject: Test for JavaFile.writeToPath --- src/main/java/com/squareup/javapoet/JavaFile.java | 11 +++++++---- src/test/java/com/squareup/javapoet/FileWritingTest.java | 7 +++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/squareup/javapoet/JavaFile.java b/src/main/java/com/squareup/javapoet/JavaFile.java index d7fa6df..da3dd86 100644 --- a/src/main/java/com/squareup/javapoet/JavaFile.java +++ b/src/main/java/com/squareup/javapoet/JavaFile.java @@ -117,7 +117,7 @@ public final class JavaFile { /** * Writes this to {@code directory} as UTF-8 using the standard directory structure. * Returns the {@link Path} instance to which source is actually written. - * */ + */ public Path writeToPath(Path directory) throws IOException { return writeToPath(directory, UTF_8); } @@ -125,7 +125,8 @@ public final class JavaFile { /** * Writes this to {@code directory} with the provided {@code charset} using the standard directory * structure. - * Returns the {@link Path} instance to which source is actually written. */ + * Returns the {@link Path} instance to which source is actually written. + */ public Path writeToPath(Path directory, Charset charset) throws IOException { checkArgument(Files.notExists(directory) || Files.isDirectory(directory), "path %s exists but is not a directory.", directory); @@ -150,8 +151,10 @@ public final class JavaFile { writeTo(directory.toPath()); } - /** Writes this to {@code directory} as UTF-8 using the standard directory structure. - * Returns the {@link File} instance to which source is actually written. */ + /** + * Writes this to {@code directory} as UTF-8 using the standard directory structure. + * Returns the {@link File} instance to which source is actually written. + */ public File writeToFile(File directory) throws IOException { final Path outputPath = writeToPath(directory.toPath()); return outputPath.toFile(); diff --git a/src/test/java/com/squareup/javapoet/FileWritingTest.java b/src/test/java/com/squareup/javapoet/FileWritingTest.java index f817ddb..58e5b62 100644 --- a/src/test/java/com/squareup/javapoet/FileWritingTest.java +++ b/src/test/java/com/squareup/javapoet/FileWritingTest.java @@ -216,4 +216,11 @@ public final class FileWritingTest { + "class Taco {\n" + "}\n"); } + + @Test public void writeToPathReturnsPath() throws IOException { + JavaFile javaFile = JavaFile.builder("foo", TypeSpec.classBuilder("Taco").build()).build(); + Path filePath = javaFile.writeToPath(fsRoot); + // Cast to avoid ambiguity between assertThat(Path) and assertThat(Iterable) + assertThat((Iterable) filePath).isEqualTo(fsRoot.resolve(fs.getPath("foo", "Taco.java"))); + } } -- cgit v1.2.3 From 8b5db1a19db6366841a9ce31d526482c8b35e745 Mon Sep 17 00:00:00 2001 From: Egor Andreevici Date: Thu, 9 Jan 2020 11:27:58 -0500 Subject: [maven-release-plugin] prepare release javapoet-1.12.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 34c03e7..38df901 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.squareup javapoet - 1.12.0-SNAPSHOT + 1.12.0 JavaPoet Use beautiful Java code to generate beautiful Java code. -- cgit v1.2.3 From 1ef324c43fe5371e4d0c63dfe4d52c14c0c01631 Mon Sep 17 00:00:00 2001 From: Egor Andreevici Date: Thu, 9 Jan 2020 11:28:05 -0500 Subject: [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 38df901..1b04f78 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.squareup javapoet - 1.12.0 + 1.13.0-SNAPSHOT JavaPoet Use beautiful Java code to generate beautiful Java code. -- cgit v1.2.3 From 0d25ea100a4387c28b5ef12e44fbffc0b22b5343 Mon Sep 17 00:00:00 2001 From: Egor Andreevici Date: Thu, 9 Jan 2020 11:32:42 -0500 Subject: Changelog for 1.12.0 --- CHANGELOG.md | 24 ++++++++++++++++++++++++ README.md | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3933dd0..08ed40e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,30 @@ Change Log ========== +JavaPoet 1.12.0 *(2020-01-09)* +----------------------------- + + * New: Add `JavaFile.writeToPath()` and `JavaFile.writeToFile()` methods that return paths to the + generated file as `Path` and `File` respectively. + * New: Add `TypeSpec.alwaysQualify()` API to avoid clashes involving nested type names. + * New: Add overloads accepting `CodeBlock`s to `MethodSpec`'s control flow methods. + * New: Make list fields of all `Builder` types mutable. + * New: Add `CodeBlock.clear()`. + * New: Allow passing a custom `Charset` to `JavaFile.writeTo()`. + * New: Improved performance of `ClassName.simpleNames()` by memoizing results. + * New: Significant performance improvements for `CodeWriter.resolve()` as all nested simple names + of a `TypeSpec` get pre-computed. + * New: Add `TypeName.Builder.setName()` to allow overriding names passed in the constructor. + * New: Add `TypeName.canonicalName()`. + * Fix: Use `\\R` instead of `\n` as line separator in `CodeWriter.emitAndIndent()`. + * Fix: Copy originating elements in `TypeSpec.toBuilder()`. + * Fix: Ensure trailing newlines in Javadocs and method bodies. + * Fix: Copy annotations when creating a `ParameterSpec` from a `VariableElement`. + * Fix: Properly handle classes located in empty packages in `ClassName`. + * Fix: Disallow `final` modifier on a `ParameterSpec`. + * Fix: Use fully-qualified names for type names that are masked by type variable names. + + JavaPoet 1.11.1 *(2018-05-16)* ----------------------------- diff --git a/README.md b/README.md index 8574eae..0b627aa 100644 --- a/README.md +++ b/README.md @@ -892,12 +892,12 @@ Download [the latest .jar][dl] or depend via Maven: com.squareup javapoet - 1.11.1 + 1.12.0 ``` or Gradle: ```groovy -compile 'com.squareup:javapoet:1.11.1' +compile 'com.squareup:javapoet:1.12.0' ``` Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap]. -- cgit v1.2.3 From d3eef47161d7aea57273f1fe0b80fbb9068e785b Mon Sep 17 00:00:00 2001 From: Egor Andreevici Date: Thu, 9 Jan 2020 13:10:00 -0500 Subject: Fix changelog for 1.12.0 "Disallow final modifier on ParameterSpec" -> "Only allow final modifier on ParameterSpec" --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08ed40e..e02a975 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ JavaPoet 1.12.0 *(2020-01-09)* * Fix: Ensure trailing newlines in Javadocs and method bodies. * Fix: Copy annotations when creating a `ParameterSpec` from a `VariableElement`. * Fix: Properly handle classes located in empty packages in `ClassName`. - * Fix: Disallow `final` modifier on a `ParameterSpec`. + * Fix: Only allow `final` modifier on a `ParameterSpec`. * Fix: Use fully-qualified names for type names that are masked by type variable names. -- cgit v1.2.3 From 5a6c842a37a8c71f079ad2ce6063a70a9dee9e31 Mon Sep 17 00:00:00 2001 From: Egor Andreevici Date: Mon, 13 Jan 2020 07:41:01 -0600 Subject: Remove parameter annotations in MethodSpec.overriding - Change to not copy parameter annotations was first introduced in 9505ad0e027a1f125b5352ac722ea141831fbf1c. - Change to properly copy mirror annotations in ParameterSpec.get was introduced in a0eadbbf0e7b70f0fbbc66043536e4328c3808fd, breaking the behavior of MethodSpec.overriding. - This change preserves the correct behavior of ParameterSpec.get while also removing annotations in MethodSpec.overriding. --- src/main/java/com/squareup/javapoet/MethodSpec.java | 10 +++++++++- src/test/java/com/squareup/javapoet/MethodSpecTest.java | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/squareup/javapoet/MethodSpec.java b/src/main/java/com/squareup/javapoet/MethodSpec.java index 67722c7..b1e61c4 100644 --- a/src/main/java/com/squareup/javapoet/MethodSpec.java +++ b/src/main/java/com/squareup/javapoet/MethodSpec.java @@ -24,6 +24,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; @@ -232,7 +233,14 @@ public final class MethodSpec { } methodBuilder.returns(TypeName.get(method.getReturnType())); - methodBuilder.addParameters(ParameterSpec.parametersOf(method)); + methodBuilder.addParameters(ParameterSpec.parametersOf(method) + .stream() + .map(parameterSpec -> { + ParameterSpec.Builder builder = parameterSpec.toBuilder(); + builder.annotations.clear(); + return builder.build(); + }) + .collect(Collectors.toList())); methodBuilder.varargs(method.isVarArgs()); for (TypeMirror thrownType : method.getThrownTypes()) { diff --git a/src/test/java/com/squareup/javapoet/MethodSpecTest.java b/src/test/java/com/squareup/javapoet/MethodSpecTest.java index 5d3a434..b768351 100644 --- a/src/test/java/com/squareup/javapoet/MethodSpecTest.java +++ b/src/test/java/com/squareup/javapoet/MethodSpecTest.java @@ -148,8 +148,8 @@ public final class MethodSpecTest { + "@java.lang.Override\n" + "protected java.lang.Runnable " + "everything(\n" - + " @com.squareup.javapoet.MethodSpecTest.Nullable java.lang.String arg0,\n" - + " java.util.List arg1) throws java.io.IOException, java.lang.SecurityException {\n" + + " java.lang.String arg0, java.util.List arg1) throws java.io.IOException,\n" + + " java.lang.SecurityException {\n" + "}\n"); } -- cgit v1.2.3 From ecfcfca2781e1edd2a98a8508294ea0ad40e88a6 Mon Sep 17 00:00:00 2001 From: Egor Andreevici Date: Tue, 14 Jan 2020 07:25:08 -0600 Subject: Add a comment about dropping parameter annotations in MethodSpec.overriding --- src/main/java/com/squareup/javapoet/MethodSpec.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/squareup/javapoet/MethodSpec.java b/src/main/java/com/squareup/javapoet/MethodSpec.java index b1e61c4..2284ef5 100644 --- a/src/main/java/com/squareup/javapoet/MethodSpec.java +++ b/src/main/java/com/squareup/javapoet/MethodSpec.java @@ -233,6 +233,8 @@ public final class MethodSpec { } methodBuilder.returns(TypeName.get(method.getReturnType())); + // Copying parameter annotations from the overridden method can be incorrect so we're + // deliberately dropping them. See https://github.com/square/javapoet/issues/482. methodBuilder.addParameters(ParameterSpec.parametersOf(method) .stream() .map(parameterSpec -> { -- cgit v1.2.3 From 9451a362adee16bbf7be382c2a95772fae2c48d1 Mon Sep 17 00:00:00 2001 From: Egor Andreevici Date: Mon, 20 Jan 2020 08:53:47 -0600 Subject: [maven-release-plugin] prepare release javapoet-1.12.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1b04f78..6011c8d 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.squareup javapoet - 1.13.0-SNAPSHOT + 1.12.1 JavaPoet Use beautiful Java code to generate beautiful Java code. -- cgit v1.2.3