-
Notifications
You must be signed in to change notification settings - Fork 18
Add support for markdown javadoc #433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -916,3 +916,44 @@ Which generates this: | |||||
| ``` | ||||||
|
|
||||||
| Use `$T` when referencing types in Javadoc to get automatic imports. | ||||||
|
|
||||||
| ### Markdown in Javadoc | ||||||
|
|
||||||
| To output Markdown styled Javadoc (see [JEP 467](https://openjdk.org/jeps/467)), | ||||||
| th method `useMarkdownJavadoc()` of the `JavaFile` builder has to be called: | ||||||
|
|
||||||
| ```java | ||||||
| TypeSpec emptyClass = TypeSpec.classBuilder("EmptyClass") | ||||||
| .addJavadoc("# Empty Class\n" | ||||||
| + "\n" | ||||||
| + "A representation of nothing: /* empty */\n") | ||||||
| .addJavadoc("\n") | ||||||
| .addJavadoc("This is not to be confused with the [$T] datatype which\n" | ||||||
| + "is an uninstantiable placeholder class to hold a reference\n" | ||||||
| + "to the *Class* object representing the Java keyword `void`.\n", Void.class) | ||||||
| .build(); | ||||||
|
|
||||||
| JavaFile javaFile = JavaFile.builder("com.example.empty", emptyClass) | ||||||
| .useMarkdownJavadoc() // sets the Markdown output flag | ||||||
| .build(); | ||||||
|
|
||||||
| javaFile.writeTo(System.out); | ||||||
| ``` | ||||||
|
|
||||||
| which outputs: | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: consistent wording
Suggested change
|
||||||
|
|
||||||
| ```java | ||||||
| package com.example.empty; | ||||||
|
|
||||||
| import java.lang.Void; | ||||||
|
|
||||||
| /// # Empty Class | ||||||
| /// | ||||||
| /// A representation of nothing: /* empty */ | ||||||
| /// | ||||||
| /// This is not to be confused with the [Void] datatype which | ||||||
| /// is an uninstantiable placeholder class to hold a reference | ||||||
| /// to the *Class* object representing the Java keyword `void`. | ||||||
| class EmptyClass { | ||||||
| } | ||||||
| ``` | ||||||
|
Comment on lines
+925
to
+959
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we update this to use the same example (or as similar as possible) as in the non-Markdown example? |
||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -42,6 +42,13 @@ | |||||
| * honors imports, indentation, and deferred variable names. | ||||||
| */ | ||||||
| final class CodeWriter { | ||||||
|
|
||||||
| private enum CommentType { | ||||||
| LINE, | ||||||
| JAVADOC, | ||||||
| MARKDOWN_JAVADOC | ||||||
| } | ||||||
|
|
||||||
| /** Sentinel value that indicates that no user-provided package has been set. */ | ||||||
| private static final String NO_PACKAGE = new String(); | ||||||
|
|
||||||
|
|
@@ -51,13 +58,13 @@ final class CodeWriter { | |||||
| private final LineWrapper out; | ||||||
| private int indentLevel; | ||||||
|
|
||||||
| private boolean javadoc = false; | ||||||
| private boolean comment = false; | ||||||
| private CommentType comment = null; | ||||||
| private String packageName = NO_PACKAGE; | ||||||
| private final List<TypeSpec> typeSpecStack = new ArrayList<>(); | ||||||
| private final Set<String> staticImportClassNames; | ||||||
| private final Set<String> staticImports; | ||||||
| private final Set<String> alwaysQualify; | ||||||
| private final boolean useMarkdownJavadoc; | ||||||
| private final Map<String, ClassName> importedTypes; | ||||||
| private final Map<String, ClassName> importableTypes = new LinkedHashMap<>(); | ||||||
| private final Set<String> referencedNames = new LinkedHashSet<>(); | ||||||
|
|
@@ -77,20 +84,22 @@ final class CodeWriter { | |||||
| } | ||||||
|
|
||||||
| CodeWriter(Appendable out, String indent, Set<String> staticImports, Set<String> alwaysQualify) { | ||||||
| this(out, indent, Collections.emptyMap(), staticImports, alwaysQualify); | ||||||
| this(out, indent, Collections.emptyMap(), staticImports, alwaysQualify, false); | ||||||
| } | ||||||
|
|
||||||
| CodeWriter( | ||||||
| Appendable out, | ||||||
| String indent, | ||||||
| Map<String, ClassName> importedTypes, | ||||||
| Set<String> staticImports, | ||||||
| Set<String> alwaysQualify) { | ||||||
| Set<String> alwaysQualify, | ||||||
| boolean useMarkdownJavadoc) { | ||||||
| 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.useMarkdownJavadoc = useMarkdownJavadoc; | ||||||
| this.staticImportClassNames = new LinkedHashSet<>(); | ||||||
| for (String signature : staticImports) { | ||||||
| staticImportClassNames.add(signature.substring(0, signature.lastIndexOf('.'))); | ||||||
|
|
@@ -144,12 +153,12 @@ public CodeWriter popType() { | |||||
|
|
||||||
| public void emitComment(CodeBlock codeBlock) throws IOException { | ||||||
| trailingNewline = true; // Force the '//' prefix for the comment. | ||||||
| comment = true; | ||||||
| comment = CommentType.LINE; | ||||||
| try { | ||||||
| emit(codeBlock); | ||||||
| emit("\n"); | ||||||
| } finally { | ||||||
| comment = false; | ||||||
| comment = null; | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -158,14 +167,22 @@ public void emitJavadoc(CodeBlock javadocCodeBlock) throws IOException { | |||||
| return; | ||||||
| } | ||||||
|
|
||||||
| emit("/**\n"); | ||||||
| javadoc = true; | ||||||
| if (useMarkdownJavadoc) { | ||||||
| emit("/// "); | ||||||
| comment = CommentType.MARKDOWN_JAVADOC; | ||||||
| } else { | ||||||
| emit("/**\n"); | ||||||
| comment = CommentType.JAVADOC; | ||||||
| } | ||||||
| try { | ||||||
| emit(javadocCodeBlock, true); | ||||||
| } finally { | ||||||
| javadoc = false; | ||||||
| comment = null; | ||||||
| } | ||||||
|
|
||||||
| if (!useMarkdownJavadoc) { | ||||||
| emit(" */\n"); | ||||||
| } | ||||||
| emit(" */\n"); | ||||||
| } | ||||||
|
|
||||||
| public void emitAnnotations(List<AnnotationSpec> annotations, boolean inline) throws IOException { | ||||||
|
|
@@ -497,9 +514,14 @@ CodeWriter emitAndIndent(String s) throws IOException { | |||||
| for (String line : LINE_BREAKING_PATTERN.split(s, -1)) { | ||||||
| // Emit a newline character. Make sure blank lines in Javadoc & comments look good. | ||||||
| if (!first) { | ||||||
| if ((javadoc || comment) && trailingNewline) { | ||||||
| if ((comment != null) && trailingNewline) { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| emitIndentation(); | ||||||
| out.append(javadoc ? " *" : "//"); | ||||||
| out.append( | ||||||
| switch (comment) { | ||||||
| case LINE -> "//"; | ||||||
| case JAVADOC -> " *"; | ||||||
| case MARKDOWN_JAVADOC -> "///"; | ||||||
| }); | ||||||
| } | ||||||
| out.append("\n"); | ||||||
| trailingNewline = true; | ||||||
|
|
@@ -519,10 +541,13 @@ CodeWriter emitAndIndent(String s) throws IOException { | |||||
| // Emit indentation and comment prefix if necessary. | ||||||
| if (trailingNewline) { | ||||||
| emitIndentation(); | ||||||
| if (javadoc) { | ||||||
| out.append(" * "); | ||||||
| } else if (comment) { | ||||||
| out.append("// "); | ||||||
| if (comment != null) { | ||||||
| out.append( | ||||||
| switch (comment) { | ||||||
| case LINE -> "// "; | ||||||
| case JAVADOC -> " * "; | ||||||
| case MARKDOWN_JAVADOC -> "/// "; | ||||||
| }); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,7 @@ | |
| import java.lang.annotation.ElementType; | ||
| import java.lang.annotation.Target; | ||
| import java.util.Arrays; | ||
| import java.util.Collections; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
@@ -354,6 +355,28 @@ void getTaco(double money, int count) { | |
| """); | ||
| } | ||
|
|
||
| @Test | ||
| public void withParameterMarkdownJavaDoc() throws IOException { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test feels somewhat arbitrary - we don't have similar tests for the other types which can contain Javadoc (ex I think we can just remove this test. It's sufficient to test |
||
| 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(); | ||
|
|
||
| StringBuilder out = new StringBuilder(); | ||
| methodSpec.emit(TestUtil.codeWriterWithMarkdownJavadoc(out), "Constructor", Collections.emptySet()); | ||
|
|
||
| assertThat(out.toString()).isEqualTo(""" | ||
| /// @param money the amount required to buy the taco. | ||
| /// @param count the number of Tacos to buy. | ||
| void getTaco(double money, int count) { | ||
| } | ||
| """); | ||
| } | ||
|
|
||
| @Test | ||
| public void duplicateExceptionsIgnored() { | ||
| ClassName ioException = ClassName.get(IOException.class); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.