Skip to content

Commit

Permalink
Refactor trait codegen javadoc integration to support member document…
Browse files Browse the repository at this point in the history
…ation (#2265)

Refactors the trait codegen javadoc integration to correctly support documentation on enum variants and structure members. Also moves the addition of annotations to a new AnnotationIntegration.
  • Loading branch information
hpmellema authored Apr 30, 2024
1 parent 4fb7ab7 commit 1805e51
Show file tree
Hide file tree
Showing 30 changed files with 881 additions and 369 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import software.amazon.smithy.model.traits.TraitDefinition;
import software.amazon.smithy.traitcodegen.SymbolProperties;
import software.amazon.smithy.traitcodegen.TraitCodegenUtils;
import software.amazon.smithy.traitcodegen.sections.BuilderClassSection;
import software.amazon.smithy.traitcodegen.writer.TraitCodegenWriter;
import software.amazon.smithy.utils.BuilderRef;
import software.amazon.smithy.utils.SmithyBuilder;
Expand Down Expand Up @@ -61,7 +60,7 @@ public void run() {
}

private void writeBuilderClass() {
writer.pushState(new BuilderClassSection(symbol));
writer.writeDocString(writer.format("Builder for {@link $T}.", symbol));
writer.writeInline("public static final class Builder $C", (Runnable) this::writeBuilderInterface);
writer.indent();
baseShape.accept(new BuilderPropertyGenerator());
Expand All @@ -72,7 +71,6 @@ private void writeBuilderClass() {
writer.openBlock("public $T build() {", "}", symbol,
() -> writer.write("return new $C;", (Runnable) this::writeBuilderReturn));
writer.dedent().write("}");
writer.popState();
writer.newLine();
}

Expand All @@ -99,10 +97,7 @@ private void writeBuilderReturn() {


private void writeToBuilderMethod() {
writer.openDocstring();
writer.writeDocStringContents("Creates a builder used to build a {@link $T}.", symbol);
writer.closeDocstring();
writer.override();
writer.writeDocString(writer.format("Creates a builder used to build a {@link $T}.", symbol));
writer.openBlock("public $T<$T> toBuilder() {", "}",
SmithyBuilder.class, symbol, () -> {
writer.writeInlineWithNoFormatting("return builder()");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,10 @@ private void writeConstructor(Symbol enumSymbol, TraitCodegenWriter writer) {
}

private void writeFromMethod(Symbol enumSymbol, TraitCodegenWriter writer) {
writer.openDocstring();
writer.writeDocStringContents("Create a {@code $B} from a value in a model.", enumSymbol);
writer.writeDocStringContents("");
writer.writeDocStringContents("<p> Any unknown value is returned as {@code UNKNOWN}.");
writer.writeDocStringContents("");
writer.writeDocStringContents("@param value Value to create enum from.");
writer.writeDocStringContents("@return Returns the {@link $B} enum value.", enumSymbol);
writer.closeDocstring();
writer.writeDocString(writer.format("Create a {@code $1B} from a value in a model.\n\n"
+ "<p>Any unknown value is returned as {@code UNKNOWN}.\n"
+ "@param value Value to create enum from.\n"
+ "@return Returns the {@link $1B} enum value.", enumSymbol));
writer.openBlock("public static $B from($T value) {", "}",
enumSymbol, getValueType(), () -> {
writer.write("$T.requireNonNull(value, \"Enum value should not be null.\");", Objects.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,11 @@ private void writeTimestampDeser() {
}

private void writeFromNodeJavaDoc() {
// Add docstring for method
writer.openDocstring();
writer.writeDocStringContents("Creates a {@link $T} from a {@link Node}.", symbol);
writer.writeDocStringContents("");
writer.writeDocStringContents("@param node Node to create the $T from.", symbol);
writer.writeDocStringContents("@return Returns the created $T.", symbol);
writer.writeDocStringContents("@throws $T if the given Node is invalid.",
ExpectationNotMetException.class);
writer.closeDocstring();
writer.writeDocString(writer.format("Creates a {@link $1T} from a {@link Node}.\n\n"
+ "@param node Node to create the $1T from.\n"
+ "@return Returns the created $1T.\n"
+ "@throws $2T if the given Node is invalid.\n",
symbol, ExpectationNotMetException.class));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,9 @@ protected Void numberShape(NumberShape shape) {
}

private void generateEnumValueGetterDocstring(Symbol symbol) {
writer.openDocstring();
writer.writeDocStringContents("Gets the {@code $1T} value as a {@code $1B} enum.", symbol);
writer.writeDocStringContents("");
writer.writeDocStringContents("@return Returns the {@code $B} enum.", symbol);
writer.closeDocstring();
writer.writeDocString(writer.format("Gets the {@code $1T} value as a {@code $1B} enum.\n\n"
+ "@return Returns the {@code $1B} enum.",
symbol));
}

private void generateValuesGetter(Shape shape) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.traitcodegen.integrations.annotations;

import java.util.List;
import software.amazon.smithy.traitcodegen.TraitCodegenContext;
import software.amazon.smithy.traitcodegen.integrations.TraitCodegenIntegration;
import software.amazon.smithy.traitcodegen.integrations.javadoc.JavaDocIntegration;
import software.amazon.smithy.traitcodegen.writer.TraitCodegenWriter;
import software.amazon.smithy.utils.CodeInterceptor;
import software.amazon.smithy.utils.CodeSection;
import software.amazon.smithy.utils.ListUtils;

/**
* Adds Java annotations to generated Java classes.
*/
public class AnnotationIntegration implements TraitCodegenIntegration {
@Override
public String name() {
return "annotations";
}

@Override
public List<String> runBefore() {
return ListUtils.of(JavaDocIntegration.NAME);
}

@Override
public List<? extends CodeInterceptor<? extends CodeSection, TraitCodegenWriter>> interceptors(
TraitCodegenContext codegenContext) {
return ListUtils.of(
new SmithyGeneratedAnnotationInterceptor(),
new DeprecatedAnnotationInterceptor(),
new UnstableAnnotationInterceptor()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.traitcodegen.integrations.annotations;

import software.amazon.smithy.model.traits.DeprecatedTrait;
import software.amazon.smithy.traitcodegen.sections.ClassSection;
import software.amazon.smithy.traitcodegen.sections.EnumVariantSection;
import software.amazon.smithy.traitcodegen.sections.GetterSection;
import software.amazon.smithy.traitcodegen.writer.TraitCodegenWriter;
import software.amazon.smithy.utils.CodeInterceptor;
import software.amazon.smithy.utils.CodeSection;

/**
* Adds the {@link Deprecated} annotation to generated code for shapes with the {@link DeprecatedTrait}.
*/
final class DeprecatedAnnotationInterceptor implements CodeInterceptor.Prepender<CodeSection, TraitCodegenWriter> {

@Override
public Class<CodeSection> sectionType() {
return CodeSection.class;
}

@Override
public boolean isIntercepted(CodeSection section) {
if (section instanceof ClassSection) {
return ((ClassSection) section).shape().hasTrait(DeprecatedTrait.class);
} else if (section instanceof GetterSection) {
return ((GetterSection) section).shape().hasTrait(DeprecatedTrait.class);
} else if (section instanceof EnumVariantSection) {
return ((EnumVariantSection) section).memberShape().hasTrait(DeprecatedTrait.class);
}
return false;
}

@Override
public void prepend(TraitCodegenWriter writer, CodeSection section) {
writer.write("@$T", Deprecated.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.traitcodegen.integrations.annotations;

import software.amazon.smithy.traitcodegen.sections.ClassSection;
import software.amazon.smithy.traitcodegen.writer.TraitCodegenWriter;
import software.amazon.smithy.utils.CodeInterceptor;
import software.amazon.smithy.utils.SmithyGenerated;

/**
* Adds the {@link software.amazon.smithy.utils.SmithyGenerated} annotation to all generated classes.
*/
final class SmithyGeneratedAnnotationInterceptor
implements CodeInterceptor.Prepender<ClassSection, TraitCodegenWriter> {
@Override
public Class<ClassSection> sectionType() {
return ClassSection.class;
}

@Override
public void prepend(TraitCodegenWriter writer, ClassSection section) {
writer.write("@$T", SmithyGenerated.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.traitcodegen.integrations.annotations;

import software.amazon.smithy.model.traits.UnstableTrait;
import software.amazon.smithy.traitcodegen.sections.ClassSection;
import software.amazon.smithy.traitcodegen.sections.EnumVariantSection;
import software.amazon.smithy.traitcodegen.sections.GetterSection;
import software.amazon.smithy.traitcodegen.writer.TraitCodegenWriter;
import software.amazon.smithy.utils.CodeInterceptor;
import software.amazon.smithy.utils.CodeSection;
import software.amazon.smithy.utils.SmithyUnstableApi;

/**
* Adds the {@link software.amazon.smithy.utils.SmithyUnstableApi} annotation to generated code for
* shapes with the {@link UnstableTrait}.
*/
final class UnstableAnnotationInterceptor implements CodeInterceptor.Prepender<CodeSection, TraitCodegenWriter> {
@Override
public Class<CodeSection> sectionType() {
return CodeSection.class;
}

@Override
public boolean isIntercepted(CodeSection section) {
if (section instanceof ClassSection) {
return ((ClassSection) section).shape().hasTrait(UnstableTrait.class);
} else if (section instanceof GetterSection) {
return ((GetterSection) section).shape().hasTrait(UnstableTrait.class);
} else if (section instanceof EnumVariantSection) {
return ((EnumVariantSection) section).memberShape().hasTrait(UnstableTrait.class);
}
return false;
}

@Override
public void prepend(TraitCodegenWriter writer, CodeSection section) {
writer.write("@$T", SmithyUnstableApi.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@

package software.amazon.smithy.traitcodegen.integrations.core;

import java.util.List;
import software.amazon.smithy.codegen.core.Symbol;
import software.amazon.smithy.codegen.core.SymbolProvider;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.shapes.MemberShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.traits.TraitDefinition;
import software.amazon.smithy.traitcodegen.SymbolProperties;
import software.amazon.smithy.traitcodegen.TraitCodegenContext;
import software.amazon.smithy.traitcodegen.TraitCodegenSettings;
import software.amazon.smithy.traitcodegen.TraitCodegenUtils;
import software.amazon.smithy.traitcodegen.integrations.TraitCodegenIntegration;
import software.amazon.smithy.traitcodegen.writer.TraitCodegenWriter;
import software.amazon.smithy.utils.CodeInterceptor;
import software.amazon.smithy.utils.CodeSection;
import software.amazon.smithy.utils.ListUtils;
import software.amazon.smithy.utils.SmithyInternalApi;

Expand Down Expand Up @@ -66,6 +71,13 @@ public String toMemberName(MemberShape shape) {
};
}

@Override
public List<? extends CodeInterceptor<? extends CodeSection, TraitCodegenWriter>> interceptors(
TraitCodegenContext codegenContext
) {
return ListUtils.of(new JavadocFormatterInterceptor());
}

private Symbol getTraitSymbol(TraitCodegenSettings settings, Shape shape, Symbol baseSymbol) {
String relativeNamespace = TraitCodegenUtils.mapNamespace(settings.smithyNamespace(),
shape.getId().getNamespace(), settings.packageName());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.traitcodegen.integrations.core;

import software.amazon.smithy.traitcodegen.sections.JavaDocSection;
import software.amazon.smithy.traitcodegen.writer.TraitCodegenWriter;
import software.amazon.smithy.utils.CodeInterceptor;

/**
* Formats any populated Javadoc comment sections as documentation comments.
*
* <p>This interceptor will run after all other Javadoc interceptors to ensure it picks up all content
* added to Jav doc sections. Javadoc sections with no content are discarded.
*/
public class JavadocFormatterInterceptor implements CodeInterceptor<JavaDocSection, TraitCodegenWriter> {

@Override
public Class<JavaDocSection> sectionType() {
return JavaDocSection.class;
}

@Override
public void write(TraitCodegenWriter writer, String previousText, JavaDocSection section) {
if (!previousText.isEmpty()) {
writer.writeDocString(previousText);
}
}
}

This file was deleted.

This file was deleted.

Loading

0 comments on commit 1805e51

Please sign in to comment.