Skip to content
This repository has been archived by the owner on Oct 10, 2024. It is now read-only.

Fix #718 Added support for multiline comments by "//" #876

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/main/java/com/squareup/javapoet/MethodSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,16 @@ public Builder addCode(CodeBlock codeBlock) {
}

public Builder addComment(String format, Object... args) {
code.add("// " + format + "\n", args);
return this;
String[] lines = format.split("\\R");
if(lines.length==1){
code.add("// " + format + "\n", args);
return this;
}else {
for (String line : lines) {
code.add("// " + line + "\n");
}
return this;
}
}

public Builder defaultValue(String format, Object... args) {
Expand Down
245 changes: 139 additions & 106 deletions src/test/java/com/squareup/javapoet/MethodSpecTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private TypeElement getElement(Class<?> clazz) {

abstract static class Everything {
@Deprecated protected abstract <T extends Runnable & Closeable> Runnable everything(
@Nullable String thing, List<? extends T> things) throws IOException, SecurityException;
@Nullable String thing, List<? extends T> things) throws IOException, SecurityException;
}

abstract static class Generics {
Expand All @@ -123,7 +123,7 @@ interface Throws<R extends RuntimeException> {
}

interface ExtendsOthers extends Callable<Integer>, Comparable<ExtendsOthers>,
Throws<IllegalStateException> {
Throws<IllegalStateException> {
}

interface ExtendsIterableWithDefaultMethods extends Iterable<Object> {
Expand All @@ -150,35 +150,35 @@ static void staticMethod() {
ExecutableElement methodElement = getOnlyElement(methodsIn(classElement.getEnclosedElements()));
MethodSpec method = MethodSpec.overriding(methodElement).build();
assertThat(method.toString()).isEqualTo(""
+ "@java.lang.Override\n"
+ "protected <T extends java.lang.Runnable & java.io.Closeable> java.lang.Runnable "
+ "everything(\n"
+ " java.lang.String arg0, java.util.List<? extends T> arg1) throws java.io.IOException,\n"
+ " java.lang.SecurityException {\n"
+ "}\n");
+ "@java.lang.Override\n"
+ "protected <T extends java.lang.Runnable & java.io.Closeable> java.lang.Runnable "
+ "everything(\n"
+ " java.lang.String arg0, java.util.List<? extends T> arg1) throws java.io.IOException,\n"
+ " java.lang.SecurityException {\n"
+ "}\n");
}

@Test public void overrideGenerics() {
TypeElement classElement = getElement(Generics.class);
ExecutableElement methodElement = getOnlyElement(methodsIn(classElement.getEnclosedElements()));
MethodSpec method = MethodSpec.overriding(methodElement)
.addStatement("return null")
.build();
.addStatement("return null")
.build();
assertThat(method.toString()).isEqualTo(""
+ "@java.lang.Override\n"
+ "<T, R, V extends java.lang.Throwable> T run(R param) throws V {\n"
+ " return null;\n"
+ "}\n");
+ "@java.lang.Override\n"
+ "<T, R, V extends java.lang.Throwable> T run(R param) throws V {\n"
+ " return null;\n"
+ "}\n");
}

@Test public void overrideDoesNotCopyOverrideAnnotation() {
TypeElement classElement = getElement(HasAnnotation.class);
ExecutableElement exec = getOnlyElement(methodsIn(classElement.getEnclosedElements()));
MethodSpec method = MethodSpec.overriding(exec).build();
assertThat(method.toString()).isEqualTo(""
+ "@java.lang.Override\n"
+ "public java.lang.String toString() {\n"
+ "}\n");
+ "@java.lang.Override\n"
+ "public java.lang.String toString() {\n"
+ "}\n");
}

@Test public void overrideDoesNotCopyDefaultModifier() {
Expand All @@ -188,9 +188,9 @@ static void staticMethod() {
ExecutableElement exec = findFirst(methods, "spliterator");
MethodSpec method = MethodSpec.overriding(exec, classType, types).build();
assertThat(method.toString()).isEqualTo(""
+ "@java.lang.Override\n"
+ "public java.util.Spliterator<java.lang.Object> spliterator() {\n"
+ "}\n");
+ "@java.lang.Override\n"
+ "public java.util.Spliterator<java.lang.Object> spliterator() {\n"
+ "}\n");
}

@Test public void overrideExtendsOthersWorksWithActualTypeParameters() {
Expand All @@ -200,21 +200,21 @@ static void staticMethod() {
ExecutableElement exec = findFirst(methods, "call");
MethodSpec method = MethodSpec.overriding(exec, classType, types).build();
assertThat(method.toString()).isEqualTo(""
+ "@java.lang.Override\n"
+ "public java.lang.Integer call() throws java.lang.Exception {\n"
+ "}\n");
+ "@java.lang.Override\n"
+ "public java.lang.Integer call() throws java.lang.Exception {\n"
+ "}\n");
exec = findFirst(methods, "compareTo");
method = MethodSpec.overriding(exec, classType, types).build();
assertThat(method.toString()).isEqualTo(""
+ "@java.lang.Override\n"
+ "public int compareTo(" + ExtendsOthers.class.getCanonicalName() + " arg0) {\n"
+ "}\n");
+ "@java.lang.Override\n"
+ "public int compareTo(" + ExtendsOthers.class.getCanonicalName() + " arg0) {\n"
+ "}\n");
exec = findFirst(methods, "fail");
method = MethodSpec.overriding(exec, classType, types).build();
assertThat(method.toString()).isEqualTo(""
+ "@java.lang.Override\n"
+ "public void fail() throws java.lang.IllegalStateException {\n"
+ "}\n");
+ "@java.lang.Override\n"
+ "public void fail() throws java.lang.IllegalStateException {\n"
+ "}\n");
}

@Test public void overrideFinalClassMethod() {
Expand All @@ -225,7 +225,7 @@ static void staticMethod() {
fail();
} catch (IllegalArgumentException expected) {
assertThat(expected).hasMessageThat().isEqualTo(
"Cannot override method on final class com.squareup.javapoet.MethodSpecTest.FinalClass");
"Cannot override method on final class com.squareup.javapoet.MethodSpecTest.FinalClass");
}
}

Expand Down Expand Up @@ -291,69 +291,69 @@ abstract static class AbstractClassWithPrivateAnnotation {

@Test public void withoutParameterJavaDoc() {
MethodSpec methodSpec = MethodSpec.methodBuilder("getTaco")
.addModifiers(Modifier.PRIVATE)
.addParameter(TypeName.DOUBLE, "money")
.addJavadoc("Gets the best Taco\n")
.build();
.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");
+ "/**\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();
.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");
+ "/**\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();
.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");
+ "/**\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);
MethodSpec methodSpec = MethodSpec.methodBuilder("duplicateExceptions")
.addException(ioException)
.addException(timeoutException)
.addException(timeoutException)
.addException(ioException)
.build();
.addException(ioException)
.addException(timeoutException)
.addException(timeoutException)
.addException(ioException)
.build();
assertThat(methodSpec.exceptions).isEqualTo(Arrays.asList(ioException, timeoutException));
assertThat(methodSpec.toBuilder().addException(ioException).build().exceptions)
.isEqualTo(Arrays.asList(ioException, timeoutException));
.isEqualTo(Arrays.asList(ioException, timeoutException));
}

@Test public void nullIsNotAValidMethodName() {
Expand All @@ -377,10 +377,10 @@ abstract static class AbstractClassWithPrivateAnnotation {

@Test public void modifyMethodName() {
MethodSpec methodSpec = MethodSpec.methodBuilder("initialMethod")
.build()
.toBuilder()
.setName("revisedMethod")
.build();
.build()
.toBuilder()
.setName("revisedMethod")
.build();

assertThat(methodSpec.toString()).isEqualTo("" + "void revisedMethod() {\n" + "}\n");
}
Expand Down Expand Up @@ -422,25 +422,25 @@ abstract static class AbstractClassWithPrivateAnnotation {

@Test public void ensureTrailingNewline() {
MethodSpec methodSpec = MethodSpec.methodBuilder("method")
.addCode("codeWithNoNewline();")
.build();
.addCode("codeWithNoNewline();")
.build();

assertThat(methodSpec.toString()).isEqualTo(""
+ "void method() {\n"
+ " codeWithNoNewline();\n"
+ "}\n");
+ "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();
.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");
+ "void method() {\n"
+ " codeWithNoNewline();\n"
+ "}\n");
}

@Test public void controlFlowWithNamedCodeBlocks() {
Expand All @@ -449,17 +449,17 @@ abstract static class AbstractClassWithPrivateAnnotation {
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();
.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");
+ "void method() {\n"
+ " if (valueField > 5) {\n"
+ " } else if (valueField == 5) {\n"
+ " }\n"
+ "}\n");
}

@Test public void doWhileWithNamedCodeBlocks() {
Expand All @@ -468,21 +468,54 @@ abstract static class AbstractClassWithPrivateAnnotation {
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();
.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");
+ "void method() {\n" +
" do {\n" +
" valueField--;\n" +
" } while (valueField > 5);\n" +
"}\n");
}

private static CodeBlock named(String format, Map<String, ?> args){
return CodeBlock.builder().addNamed(format, args).build();
}
@Test public void multilineComments() {
MethodSpec main = MethodSpec.methodBuilder("main")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(void.class)
.addParameter(String[].class, "args")
.addComment("Hello\nmultiline\ncomments!")
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
.build();

assertThat(main.toString()).isEqualTo("" +
"public static void main(java.lang.String[] args) {\n" +
" // Hello\n" +
" // multiline\n" +
" // comments!\n" +
" java.lang.System.out.println(\"Hello, JavaPoet!\");\n" +
"}\n");
}

@Test public void singleLineComments() {
MethodSpec main = MethodSpec.methodBuilder("main")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(void.class)
.addParameter(String[].class, "args")
.addComment("Hello single line comments!")
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
.build();

assertThat(main.toString()).isEqualTo("" +
"public static void main(java.lang.String[] args) {\n" +
" // Hello single line comments!\n" +
" java.lang.System.out.println(\"Hello, JavaPoet!\");\n" +
"}\n");
}

}