Skip to content

Commit b8794c6

Browse files
Enable format selection
This adds the capability to select a doc format and add make new formats available via integrations.
1 parent b432928 commit b8794c6

File tree

7 files changed

+173
-8
lines changed

7 files changed

+173
-8
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package software.amazon.smithy.docgen.core;
7+
8+
import java.util.List;
9+
import software.amazon.smithy.docgen.core.writers.MarkdownWriter;
10+
import software.amazon.smithy.utils.SmithyInternalApi;
11+
12+
/**
13+
* Applies the built-in {@link DocFormat}s.
14+
*/
15+
@SmithyInternalApi
16+
public class BuiltInDocFormatsIntegration implements DocIntegration {
17+
@Override
18+
public List<DocFormat> docFormats(DocSettings settings) {
19+
return List.of(
20+
new DocFormat("markdown", ".md", new MarkdownWriter.Factory())
21+
);
22+
}
23+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package software.amazon.smithy.docgen.core;
7+
8+
import software.amazon.smithy.codegen.core.SymbolWriter;
9+
import software.amazon.smithy.docgen.core.writers.DocWriter;
10+
import software.amazon.smithy.utils.SmithyUnstableApi;
11+
12+
/**
13+
* A record containing information about a doc format.
14+
*
15+
* <p>Use {@link DocIntegration#docFormats} to make new formats available.
16+
*
17+
* @param name The name of the format. This will be the string that will be set as the
18+
* value of {@code format} in {@link DocSettings}.
19+
* @param extension The file extension to use by default for documentation files. This
20+
* will be set on the {@code Symbol}s automatically by
21+
* {@link software.amazon.smithy.docgen.core.DocSymbolProvider.FileExtensionDecorator}.
22+
* @param writerFactory A factory method for creating writers that write in this
23+
* format.
24+
*/
25+
@SmithyUnstableApi
26+
public record DocFormat(String name, String extension, SymbolWriter.Factory<DocWriter> writerFactory) {
27+
}

smithy-docgen-core/src/main/java/software/amazon/smithy/docgen/core/DocGenerationContext.java

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55

66
package software.amazon.smithy.docgen.core;
77

8+
import java.util.LinkedHashSet;
89
import java.util.List;
910
import software.amazon.smithy.build.FileManifest;
1011
import software.amazon.smithy.codegen.core.CodegenContext;
12+
import software.amazon.smithy.codegen.core.CodegenException;
1113
import software.amazon.smithy.codegen.core.SymbolProvider;
1214
import software.amazon.smithy.codegen.core.WriterDelegator;
15+
import software.amazon.smithy.docgen.core.DocSymbolProvider.FileExtensionDecorator;
1316
import software.amazon.smithy.docgen.core.writers.DocWriter;
14-
import software.amazon.smithy.docgen.core.writers.MarkdownWriter;
1517
import software.amazon.smithy.model.Model;
1618
import software.amazon.smithy.utils.SmithyUnstableApi;
1719

@@ -27,6 +29,7 @@ public final class DocGenerationContext implements CodegenContext<DocSettings, D
2729
private final FileManifest fileManifest;
2830
private final WriterDelegator<DocWriter> writerDelegator;
2931
private final List<DocIntegration> docIntegrations;
32+
private final DocFormat docFormat;
3033

3134
/**
3235
* Constructor.
@@ -46,11 +49,31 @@ public DocGenerationContext(
4649
) {
4750
this.model = model;
4851
this.docSettings = docSettings;
49-
this.symbolProvider = symbolProvider;
5052
this.fileManifest = fileManifest;
51-
// TODO: pull the factory from the integrations
52-
this.writerDelegator = new WriterDelegator<>(fileManifest, symbolProvider, new MarkdownWriter.Factory());
5353
this.docIntegrations = docIntegrations;
54+
55+
DocFormat resolvedFormat = null;
56+
var availableFormats = new LinkedHashSet<String>();
57+
for (var integration : docIntegrations) {
58+
for (var format : integration.docFormats(docSettings)) {
59+
if (format.name().equals(docSettings.format())) {
60+
resolvedFormat = format;
61+
symbolProvider = new FileExtensionDecorator(symbolProvider, resolvedFormat.extension());
62+
break;
63+
}
64+
availableFormats.add(format.name());
65+
}
66+
}
67+
if (resolvedFormat == null) {
68+
throw new CodegenException(String.format(
69+
"Unknown doc format `%s`. You may be missing a dependency. Currently available formats: [%s]",
70+
docSettings.format(), String.join(", ", availableFormats)
71+
));
72+
}
73+
74+
this.docFormat = resolvedFormat;
75+
this.symbolProvider = symbolProvider;
76+
this.writerDelegator = new WriterDelegator<>(fileManifest, symbolProvider, resolvedFormat.writerFactory());
5477
}
5578

5679
@Override
@@ -82,4 +105,11 @@ public WriterDelegator<DocWriter> writerDelegator() {
82105
public List<DocIntegration> integrations() {
83106
return docIntegrations;
84107
}
108+
109+
/**
110+
* @return Returns the selected format that documentation should be generated in.
111+
*/
112+
public DocFormat docFormat() {
113+
return this.docFormat;
114+
}
85115
}

smithy-docgen-core/src/main/java/software/amazon/smithy/docgen/core/DocIntegration.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package software.amazon.smithy.docgen.core;
77

8+
import java.util.List;
89
import software.amazon.smithy.codegen.core.SmithyIntegration;
910
import software.amazon.smithy.docgen.core.writers.DocWriter;
1011
import software.amazon.smithy.utils.SmithyUnstableApi;
@@ -20,4 +21,18 @@
2021
*/
2122
@SmithyUnstableApi
2223
public interface DocIntegration extends SmithyIntegration<DocSettings, DocWriter, DocGenerationContext> {
24+
25+
/**
26+
* Adds {@link DocFormat}s to the list of supported formats.
27+
*
28+
* <p>When resolving the format implementation, the first format found with a
29+
* matching name will be used. Use {@link #priority} to adjust which integration
30+
* is seen first.
31+
*
32+
* @param settings The documentation generation settings.
33+
* @return A list of formats to add.
34+
*/
35+
default List<DocFormat> docFormats(DocSettings settings) {
36+
return List.of();
37+
}
2338
}

smithy-docgen-core/src/main/java/software/amazon/smithy/docgen/core/DocSettings.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,21 @@
1515
* {@code smithy-build.json} configuration for this plugin.
1616
*
1717
* @param service The shape id of the service to generate documentation for.
18+
* @param format The format to generate documentation in. The default is markdown.
1819
*/
1920
@SmithyUnstableApi
20-
public record DocSettings(ShapeId service) {
21+
public record DocSettings(ShapeId service, String format) {
2122

2223
/**
2324
* Settings for documentation generation. These can be set in the
2425
* {@code smithy-build.json} configuration for this plugin.
2526
*
2627
* @param service The shape id of the service to generate documentation for.
28+
* @param format The format to generate documentation in. The default is markdown.
2729
*/
2830
public DocSettings {
2931
Objects.requireNonNull(service);
32+
Objects.requireNonNull(format);
3033
}
3134

3235
/**
@@ -36,6 +39,9 @@ public record DocSettings(ShapeId service) {
3639
* @return loaded settings based on the given node.
3740
*/
3841
public static DocSettings from(ObjectNode pluginSettings) {
39-
return new DocSettings(pluginSettings.expectStringMember("service").expectShapeId());
42+
return new DocSettings(
43+
pluginSettings.expectStringMember("service").expectShapeId(),
44+
pluginSettings.getStringMemberOrDefault("format", "markdown")
45+
);
4046
}
4147
}

smithy-docgen-core/src/main/java/software/amazon/smithy/docgen/core/DocSymbolProvider.java

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
import static java.lang.String.format;
99

1010
import java.util.Locale;
11+
import java.util.Objects;
1112
import java.util.logging.Logger;
1213
import software.amazon.smithy.codegen.core.Symbol;
1314
import software.amazon.smithy.codegen.core.SymbolProvider;
1415
import software.amazon.smithy.model.Model;
16+
import software.amazon.smithy.model.shapes.MemberShape;
1517
import software.amazon.smithy.model.shapes.ServiceShape;
1618
import software.amazon.smithy.model.shapes.Shape;
1719
import software.amazon.smithy.model.shapes.ShapeVisitor;
@@ -44,6 +46,10 @@
4446
* to the shape's definition might look like {@code https://example.com/shapes#foo}
4547
* for example. If this or {@code definitionFile} is empty, it is not possible to
4648
* link to the shape.
49+
* <li>{@link #ENABLE_DEFAULT_FILE_EXTENSION}: A named boolean property indicating
50+
* whether the symbol's definition file should have the default file extension
51+
* applied. If not present or set to {@code false}, the file extension will not be
52+
* applied.
4753
* </ul>
4854
*
4955
* <p>Decorators provided by {@link DocIntegration#decorateSymbolProvider} MUST set
@@ -80,6 +86,16 @@ public final class DocSymbolProvider extends ShapeVisitor.Default<Symbol> implem
8086
*/
8187
public static final String LINK_ID_PROPERTY = "linkId";
8288

89+
/**
90+
* A named boolean property indicating whether the symbol's definition file should
91+
* have the default file extension applied. If not present or set to {@code false},
92+
* the file extension will not be applied.
93+
*
94+
* <p>Use {@code symbol.getProperty(LINK_ID_PROPERTY, Boolean.class)} to access this
95+
* property.
96+
*/
97+
public static final String ENABLE_DEFAULT_FILE_EXTENSION = "enableDefaultFileExtension";
98+
8399
private static final Logger LOGGER = Logger.getLogger(DocSymbolProvider.class.getName());
84100

85101
private final Model model;
@@ -118,15 +134,16 @@ private Symbol.Builder getSymbolBuilder(Shape shape) {
118134
.name(name)
119135
.putProperty(SHAPE_PROPERTY, shape)
120136
.definitionFile(getDefinitionFile(serviceShape, shape))
121-
.putProperty(LINK_ID_PROPERTY, getLinkId(name));
137+
.putProperty(LINK_ID_PROPERTY, getLinkId(name))
138+
.putProperty(ENABLE_DEFAULT_FILE_EXTENSION, true);
122139
}
123140

124141
private String getDefinitionFile(ServiceShape serviceShape, Shape shape) {
125142
if (shape.isMemberShape()) {
126143
return getDefinitionFile(serviceShape, model.expectShape(shape.getId().withoutMember()));
127144
}
128145
return getDefinitionFile(
129-
getShapeName(serviceShape, shape).replaceAll("\\s+", "") + ".md"
146+
getShapeName(serviceShape, shape).replaceAll("\\s+", "")
130147
);
131148
}
132149

@@ -157,4 +174,50 @@ private String getLinkId(String shapeName) {
157174
protected Symbol getDefault(Shape shape) {
158175
return null;
159176
}
177+
178+
/**
179+
* Adds file extensions to symbol definition files. Used with {@link DocFormat}
180+
* by default.
181+
*
182+
* <p>Symbols can set {@link #ENABLE_DEFAULT_FILE_EXTENSION} to {@code false} to
183+
* disable this on a per-symbol basis.
184+
*/
185+
public static final class FileExtensionDecorator implements SymbolProvider {
186+
private final SymbolProvider wrapped;
187+
private final String extension;
188+
189+
/**
190+
* Constructor.
191+
* @param wrapped The symbol provider to wrap.
192+
* @param extension The file extension to add. This must include any necessary periods.
193+
*/
194+
public FileExtensionDecorator(SymbolProvider wrapped, String extension) {
195+
this.wrapped = Objects.requireNonNull(wrapped);
196+
this.extension = Objects.requireNonNull(extension);
197+
}
198+
199+
@Override
200+
public Symbol toSymbol(Shape shape) {
201+
var symbol = wrapped.toSymbol(shape);
202+
if (!symbol.getProperty(ENABLE_DEFAULT_FILE_EXTENSION, Boolean.class).orElse(false)) {
203+
return symbol;
204+
}
205+
return symbol.toBuilder()
206+
.definitionFile(addExtension(symbol.getDefinitionFile()))
207+
.declarationFile(addExtension(symbol.getDeclarationFile()))
208+
.build();
209+
}
210+
211+
private String addExtension(String path) {
212+
if (!path.endsWith(extension)) {
213+
path += extension;
214+
}
215+
return path;
216+
}
217+
218+
@Override
219+
public String toMemberName(MemberShape shape) {
220+
return wrapped.toMemberName(shape);
221+
}
222+
}
160223
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
software.amazon.smithy.docgen.core.BuiltInDocFormatsIntegration

0 commit comments

Comments
 (0)