Skip to content

Commit 91c6b12

Browse files
Split server codegen out into a separate plugin
1 parent a9fd0ef commit 91c6b12

File tree

6 files changed

+117
-54
lines changed

6 files changed

+117
-54
lines changed

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CodegenVisitor.java

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.ServiceLoader;
2626
import java.util.Set;
2727
import java.util.TreeSet;
28+
import java.util.function.BiFunction;
2829
import java.util.logging.Logger;
2930
import software.amazon.smithy.build.FileManifest;
3031
import software.amazon.smithy.build.PluginContext;
@@ -70,15 +71,18 @@ class CodegenVisitor extends ShapeVisitor.Default<Void> {
7071
private final ServiceShape service;
7172
private final FileManifest fileManifest;
7273
private final SymbolProvider symbolProvider;
73-
private final SymbolProvider serverSymbolProvider;
7474
private final Model nonTraits;
7575
private final TypeScriptDelegator writers;
7676
private final List<TypeScriptIntegration> integrations = new ArrayList<>();
7777
private final List<RuntimeClientPlugin> runtimePlugins = new ArrayList<>();
7878
private final ProtocolGenerator protocolGenerator;
7979
private final ApplicationProtocol applicationProtocol;
8080

81-
CodegenVisitor(PluginContext context) {
81+
CodegenVisitor(
82+
PluginContext context,
83+
BiFunction<Model, TypeScriptSettings, SymbolProvider> createSymbolProvider,
84+
TypeScriptSettings.ArtifactType artifactType
85+
) {
8286
// Load all integrations.
8387
ClassLoader loader = context.getPluginClassLoader().orElse(getClass().getClassLoader());
8488
LOGGER.info("Attempting to discover TypeScriptIntegration from the classpath...");
@@ -96,6 +100,7 @@ class CodegenVisitor extends ShapeVisitor.Default<Void> {
96100

97101
// Preprocess model using integrations.
98102
TypeScriptSettings typescriptSettings = TypeScriptSettings.from(context.getModel(), context.getSettings());
103+
typescriptSettings.setArtifactType(artifactType);
99104
for (TypeScriptIntegration integration : integrations) {
100105
Model modifiedModel = integration.preprocessModel(context, typescriptSettings);
101106
if (modifiedModel != context.getModel()) {
@@ -112,16 +117,11 @@ class CodegenVisitor extends ShapeVisitor.Default<Void> {
112117
settings.generateClient() ? "client" : "server", service.getId()));
113118

114119
// Decorate the symbol provider using integrations.
115-
SymbolProvider resolvedProvider = TypeScriptCodegenPlugin.createSymbolProvider(model, settings);
120+
SymbolProvider resolvedProvider = createSymbolProvider.apply(model, settings);
116121
for (TypeScriptIntegration integration : integrations) {
117122
resolvedProvider = integration.decorateSymbolProvider(settings, model, resolvedProvider);
118123
}
119124
symbolProvider = SymbolProvider.cache(resolvedProvider);
120-
if (settings.generateServerSdk()) {
121-
serverSymbolProvider = SymbolProvider.cache(new ServerSymbolVisitor(model, symbolProvider));
122-
} else {
123-
serverSymbolProvider = symbolProvider;
124-
}
125125

126126
// Resolve the nullable protocol generator and application protocol.
127127
protocolGenerator = resolveProtocolGenerator(integrations, service, settings);
@@ -204,14 +204,14 @@ void execute() {
204204

205205
if (settings.generateServerSdk()) {
206206
// Generate index for server
207-
IndexGenerator.writeServerIndex(settings, model, serverSymbolProvider, fileManifest);
207+
IndexGenerator.writeServerIndex(settings, model, symbolProvider, fileManifest);
208208
}
209209

210210
// Generate protocol tests IFF found in the model.
211211
if (protocolGenerator != null) {
212212
ShapeId protocol = protocolGenerator.getProtocol();
213213
new HttpProtocolTestGenerator(
214-
settings, model, protocol, symbolProvider, serverSymbolProvider, writers, protocolGenerator).run();
214+
settings, model, protocol, symbolProvider, writers, protocolGenerator).run();
215215
}
216216

217217
// Write each pending writer.
@@ -290,8 +290,8 @@ public Void stringShape(StringShape shape) {
290290
@Override
291291
public Void operationShape(OperationShape operation) {
292292
if (settings.generateServerSdk()) {
293-
writers.useShapeWriter(operation, serverSymbolProvider, w -> {
294-
ServerGenerator.generateOperationHandler(serverSymbolProvider, service, operation, w);
293+
writers.useShapeWriter(operation, symbolProvider, w -> {
294+
ServerGenerator.generateOperationHandler(symbolProvider, service, operation, w);
295295
});
296296
}
297297
return null;
@@ -334,15 +334,15 @@ public Void serviceShape(ServiceShape shape) {
334334
}
335335
if (context.getSettings().generateServerSdk()) {
336336
ProtocolGenerator.GenerationContext serverContext =
337-
context.withSymbolProvider(serverSymbolProvider);
337+
context.withSymbolProvider(symbolProvider);
338338
protocolGenerator.generateRequestDeserializers(serverContext);
339339
protocolGenerator.generateResponseSerializers(serverContext);
340340
protocolGenerator.generateFrameworkErrorSerializer(serverContext);
341-
writers.useShapeWriter(shape, serverSymbolProvider, w -> {
341+
writers.useShapeWriter(shape, symbolProvider, w -> {
342342
protocolGenerator.generateServiceHandlerFactory(serverContext.withWriter(w));
343343
});
344344
for (OperationShape operation: TopDownIndex.of(model).getContainedOperations(service)) {
345-
writers.useShapeWriter(operation, serverSymbolProvider, w -> {
345+
writers.useShapeWriter(operation, symbolProvider, w -> {
346346
protocolGenerator.generateOperationHandlerFactory(serverContext.withWriter(w), operation);
347347
});
348348
}
@@ -403,10 +403,10 @@ private void generateClient(ServiceShape shape) {
403403
private void generateServiceInterface(ServiceShape shape) {
404404
TopDownIndex topDownIndex = TopDownIndex.of(model);
405405
Set<OperationShape> operations = new TreeSet<>(topDownIndex.getContainedOperations(shape));
406-
writers.useShapeWriter(shape, serverSymbolProvider, writer -> {
407-
ServerGenerator.generateOperationsType(serverSymbolProvider, shape, operations, writer);
408-
ServerGenerator.generateServerInterfaces(serverSymbolProvider, shape, operations, writer);
409-
ServerGenerator.generateServiceHandler(serverSymbolProvider, shape, operations, writer);
406+
writers.useShapeWriter(shape, symbolProvider, writer -> {
407+
ServerGenerator.generateOperationsType(symbolProvider, shape, operations, writer);
408+
ServerGenerator.generateServerInterfaces(symbolProvider, shape, operations, writer);
409+
ServerGenerator.generateServiceHandler(symbolProvider, shape, operations, writer);
410410
});
411411
}
412412

@@ -418,8 +418,8 @@ private void generateServerErrors(ServiceShape service) {
418418
.distinct()
419419
.map(id -> model.expectShape(id).asStructureShape().orElseThrow(IllegalArgumentException::new))
420420
.sorted()
421-
.forEachOrdered(error -> writers.useShapeWriter(service, serverSymbolProvider, writer -> {
422-
new ServerErrorGenerator(settings, model, error, serverSymbolProvider, writer).run();
421+
.forEachOrdered(error -> writers.useShapeWriter(service, symbolProvider, writer -> {
422+
new ServerErrorGenerator(settings, model, error, symbolProvider, writer).run();
423423
}));
424424
}
425425

@@ -436,8 +436,8 @@ private void generateCommands(ServiceShape shape) {
436436
}
437437

438438
if (settings.generateServerSdk()) {
439-
writers.useShapeWriter(operation, serverSymbolProvider, commandWriter -> new ServerCommandGenerator(
440-
settings, model, operation, serverSymbolProvider, commandWriter,
439+
writers.useShapeWriter(operation, symbolProvider, commandWriter -> new ServerCommandGenerator(
440+
settings, model, operation, symbolProvider, commandWriter,
441441
protocolGenerator, applicationProtocol).run());
442442
}
443443
}

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/HttpProtocolTestGenerator.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ final class HttpProtocolTestGenerator implements Runnable {
9090
private final ServiceShape service;
9191
private final SymbolProvider symbolProvider;
9292
private final Symbol serviceSymbol;
93-
private final SymbolProvider serverSymbolProvider;
9493
private final Set<String> additionalStubs = new TreeSet<>();
9594
private final ProtocolGenerator protocolGenerator;
9695

@@ -105,7 +104,6 @@ final class HttpProtocolTestGenerator implements Runnable {
105104
Model model,
106105
ShapeId protocol,
107106
SymbolProvider symbolProvider,
108-
SymbolProvider serverSymbolProvider,
109107
TypeScriptDelegator delegator,
110108
ProtocolGenerator protocolGenerator
111109
) {
@@ -114,7 +112,6 @@ final class HttpProtocolTestGenerator implements Runnable {
114112
this.protocol = protocol;
115113
this.service = settings.getService(model);
116114
this.symbolProvider = symbolProvider;
117-
this.serverSymbolProvider = serverSymbolProvider;
118115
this.delegator = delegator;
119116
this.protocolGenerator = protocolGenerator;
120117
serviceSymbol = symbolProvider.toSymbol(service);
@@ -266,7 +263,7 @@ private void generateClientRequestTest(OperationShape operation, HttpRequestTest
266263
}
267264

268265
private void generateServerRequestTest(OperationShape operation, HttpRequestTestCase testCase) {
269-
Symbol operationSymbol = serverSymbolProvider.toSymbol(operation);
266+
Symbol operationSymbol = symbolProvider.toSymbol(operation);
270267

271268
// Lowercase all the headers we're expecting as this is what we'll get.
272269
Map<String, String> headers = testCase.getHeaders().entrySet().stream()
@@ -279,7 +276,7 @@ private void generateServerRequestTest(OperationShape operation, HttpRequestTest
279276
String testName = testCase.getId() + ":ServerRequest";
280277
testCase.getDocumentation().ifPresent(writer::writeDocs);
281278
writer.openBlock("it($S, async () => {", "});\n", testName, () -> {
282-
Symbol serviceSymbol = serverSymbolProvider.toSymbol(service);
279+
Symbol serviceSymbol = symbolProvider.toSymbol(service);
283280
Symbol handlerSymbol = serviceSymbol.expectProperty("handler", Symbol.class);
284281

285282
// Create a mock function to set in place of the server operation function so we can capture
@@ -480,8 +477,8 @@ private String registerBodyComparatorStub(String mediaType) {
480477
}
481478

482479
public void generateServerResponseTest(OperationShape operation, HttpResponseTestCase testCase) {
483-
Symbol serviceSymbol = serverSymbolProvider.toSymbol(service);
484-
Symbol operationSymbol = serverSymbolProvider.toSymbol(operation);
480+
Symbol serviceSymbol = symbolProvider.toSymbol(service);
481+
Symbol operationSymbol = symbolProvider.toSymbol(operation);
485482
testCase.getDocumentation().ifPresent(writer::writeDocs);
486483
String testName = testCase.getId() + ":ServerResponse";
487484
writer.openBlock("it($S, async () => {", "});\n", testName, () -> {
@@ -527,10 +524,10 @@ private void generateServerErrorResponseTest(
527524
StructureShape error,
528525
HttpResponseTestCase testCase
529526
) {
530-
Symbol serviceSymbol = serverSymbolProvider.toSymbol(service);
531-
Symbol operationSymbol = serverSymbolProvider.toSymbol(operation);
527+
Symbol serviceSymbol = symbolProvider.toSymbol(service);
528+
Symbol operationSymbol = symbolProvider.toSymbol(operation);
532529
Symbol outputType = operationSymbol.expectProperty("outputType", Symbol.class);
533-
Symbol errorSymbol = serverSymbolProvider.toSymbol(error);
530+
Symbol errorSymbol = symbolProvider.toSymbol(error);
534531
ErrorTrait errorTrait = error.expectTrait(ErrorTrait.class);
535532

536533
testCase.getDocumentation().ifPresent(writer::writeDocs);
@@ -565,8 +562,8 @@ private void generateServerErrorResponseTest(
565562
}
566563

567564
private void writeServerResponseTest(OperationShape operation, HttpResponseTestCase testCase) {
568-
Symbol serviceSymbol = serverSymbolProvider.toSymbol(service);
569-
Symbol operationSymbol = serverSymbolProvider.toSymbol(operation);
565+
Symbol serviceSymbol = symbolProvider.toSymbol(service);
566+
Symbol operationSymbol = symbolProvider.toSymbol(operation);
570567
Symbol handlerSymbol = serviceSymbol.expectProperty("handler", Symbol.class);
571568
Symbol serializerSymbol = operationSymbol.expectProperty("serializerType", Symbol.class);
572569
Symbol serviceOperationsSymbol = serviceSymbol.expectProperty("operations", Symbol.class);

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptCodegenPlugin.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import software.amazon.smithy.build.SmithyBuildPlugin;
2020
import software.amazon.smithy.codegen.core.SymbolProvider;
2121
import software.amazon.smithy.model.Model;
22+
import software.amazon.smithy.typescript.codegen.TypeScriptSettings.ArtifactType;
2223

2324
/**
2425
* Plugin to trigger TypeScript code generation.
@@ -32,7 +33,11 @@ public String getName() {
3233

3334
@Override
3435
public void execute(PluginContext context) {
35-
new CodegenVisitor(context).execute();
36+
new CodegenVisitor(
37+
context,
38+
TypeScriptCodegenPlugin::createSymbolProvider,
39+
ArtifactType.CLIENT
40+
).execute();
3641
}
3742

3843
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.smithy.typescript.codegen;
17+
18+
import software.amazon.smithy.build.PluginContext;
19+
import software.amazon.smithy.build.SmithyBuildPlugin;
20+
import software.amazon.smithy.codegen.core.SymbolProvider;
21+
import software.amazon.smithy.model.Model;
22+
import software.amazon.smithy.typescript.codegen.TypeScriptSettings.ArtifactType;
23+
24+
/**
25+
* Plugin to trigger TypeScript SSDK code generation.
26+
*/
27+
public class TypeScriptServerCodegenPlugin implements SmithyBuildPlugin {
28+
29+
@Override
30+
public String getName() {
31+
return "typescript-ssdk-codegen";
32+
}
33+
34+
@Override
35+
public void execute(PluginContext context) {
36+
new CodegenVisitor(
37+
context,
38+
TypeScriptServerCodegenPlugin::createSymbolProvider,
39+
ArtifactType.SSDK
40+
).execute();
41+
}
42+
43+
/**
44+
* Creates a TypeScript symbol provider.
45+
*
46+
* @param model Model to generate symbols for.
47+
* @param settings Settings used by the plugin.
48+
* @return Returns the created provider.
49+
*/
50+
public static SymbolProvider createSymbolProvider(Model model, TypeScriptSettings settings) {
51+
return new ServerSymbolVisitor(model, new SymbolVisitor(model, settings));
52+
}
53+
}

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptSettings.java

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ public final class TypeScriptSettings {
4747
private static final String SERVICE = "service";
4848
private static final String PROTOCOL = "protocol";
4949
private static final String PRIVATE = "private";
50-
private static final String GENERATE_CLIENT = "generateClient";
51-
private static final String GENERATE_SERVER_SDK = "generateServerSdk";
5250

5351
private String packageName;
5452
private String packageDescription = "";
@@ -58,8 +56,7 @@ public final class TypeScriptSettings {
5856
private ObjectNode pluginSettings = Node.objectNode();
5957
private ShapeId protocol;
6058
private boolean isPrivate;
61-
private boolean generateClient;
62-
private boolean generateServerSdk;
59+
private ArtifactType artifactType = ArtifactType.CLIENT;
6360

6461
/**
6562
* Create a settings object from a configuration object node.
@@ -72,7 +69,7 @@ public static TypeScriptSettings from(Model model, ObjectNode config) {
7269
TypeScriptSettings settings = new TypeScriptSettings();
7370
config.warnIfAdditionalProperties(Arrays.asList(
7471
PACKAGE, PACKAGE_DESCRIPTION, PACKAGE_JSON, PACKAGE_VERSION,
75-
SERVICE, PROTOCOL, TARGET_NAMESPACE, PRIVATE, GENERATE_CLIENT, GENERATE_SERVER_SDK));
72+
SERVICE, PROTOCOL, TARGET_NAMESPACE, PRIVATE));
7673

7774
// Get the service from the settings or infer one from the given model.
7875
settings.setService(config.getStringMember(SERVICE)
@@ -86,9 +83,6 @@ public static TypeScriptSettings from(Model model, ObjectNode config) {
8683
settings.packageJson = config.getObjectMember(PACKAGE_JSON).orElse(Node.objectNode());
8784
config.getStringMember(PROTOCOL).map(StringNode::getValue).map(ShapeId::from).ifPresent(settings::setProtocol);
8885
settings.setPrivate(config.getBooleanMember(PRIVATE).map(BooleanNode::getValue).orElse(false));
89-
settings.setGenerateClient(config.getBooleanMember(GENERATE_CLIENT).map(BooleanNode::getValue).orElse(true));
90-
settings.setGenerateServerSdk(
91-
config.getBooleanMember(GENERATE_SERVER_SDK).map(BooleanNode::getValue).orElse(false));
9286

9387
settings.setPluginSettings(config);
9488
return settings;
@@ -222,29 +216,34 @@ public void setPrivate(boolean isPrivate) {
222216
}
223217

224218
/**
225-
* Returns if the generated package will include a client.
219+
* Returns if the generated package will be a client.
226220
*
227221
* @return If the package will include a client.
228222
*/
229223
public boolean generateClient() {
230-
return generateClient;
231-
}
232-
233-
public void setGenerateClient(boolean generateClient) {
234-
this.generateClient = generateClient;
224+
return artifactType.equals(ArtifactType.CLIENT);
235225
}
236226

237227
/**
238-
* Returns if the generated package will include a server sdk.
228+
* Returns if the generated package will be a server sdk.
239229
*
240230
* @return If the package will include a server sdk.
241231
*/
242232
public boolean generateServerSdk() {
243-
return generateServerSdk;
233+
return artifactType.equals(ArtifactType.SSDK);
244234
}
245235

246-
public void setGenerateServerSdk(boolean generateServerSdk) {
247-
this.generateServerSdk = generateServerSdk;
236+
/**
237+
* Returns the type of artifact being generated, such as a client or ssdk.
238+
*
239+
* @return The artifact type.
240+
*/
241+
public ArtifactType getArtifactType() {
242+
return artifactType;
243+
}
244+
245+
public void setArtifactType(ArtifactType artifactType) {
246+
this.artifactType = artifactType;
248247
}
249248

250249
/**
@@ -313,4 +312,12 @@ public ShapeId resolveServiceProtocol(Model model, ServiceShape service, Set<Sha
313312
public void setProtocol(ShapeId protocol) {
314313
this.protocol = Objects.requireNonNull(protocol);
315314
}
315+
316+
/**
317+
* An enum indicating the type of artifact the code generator will produce.
318+
*/
319+
public enum ArtifactType {
320+
CLIENT,
321+
SSDK
322+
}
316323
}
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
software.amazon.smithy.typescript.codegen.TypeScriptCodegenPlugin
2+
software.amazon.smithy.typescript.codegen.TypeScriptServerCodegenPlugin

0 commit comments

Comments
 (0)