Skip to content

Commit bbdb091

Browse files
authored
codegen: use service closure to cache shape queries in schema generation (#1803)
* codegen: use service closure to cache shape queries in schema generation * handle conflicting synthetic base exception name
1 parent 7b82c53 commit bbdb091

File tree

13 files changed

+246
-489
lines changed

13 files changed

+246
-489
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ generate-protocol-tests:
2222
yarn turbo run build -F="./private/*" --only
2323

2424
test-protocols:
25-
(cd ./private/smithy-rpcv2-cbor && npx vitest run --globals)
26-
(cd ./private/smithy-rpcv2-cbor-schema && npx vitest run --globals)
25+
(cd ./private/smithy-rpcv2-cbor && npx vitest run --globals && yarn test:index)
26+
(cd ./private/smithy-rpcv2-cbor-schema && npx vitest run --globals && yarn test:index)
2727

2828
test-unit:
2929
yarn g:vitest run -c vitest.config.mts

private/my-local-model-schema/test/index-objects.spec.mjs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import {
2+
CodedThrottlingError,
23
GetNumbersCommand,
4+
HaltError,
5+
MysteryThrottlingError,
6+
RetryableError,
37
TradeEventStreamCommand,
48
XYZService,
59
XYZServiceClient,
610
XYZServiceServiceException,
11+
XYZServiceSyntheticServiceException,
712
} from "../dist-cjs/index.js";
813
import assert from "node:assert";
914
// clients
@@ -13,5 +18,10 @@ assert(typeof XYZService === "function");
1318
assert(typeof GetNumbersCommand === "function");
1419
assert(typeof TradeEventStreamCommand === "function");
1520
// errors
16-
assert(XYZServiceServiceException.prototype instanceof Error);
21+
assert(CodedThrottlingError.prototype instanceof XYZServiceSyntheticServiceException);
22+
assert(HaltError.prototype instanceof XYZServiceSyntheticServiceException);
23+
assert(MysteryThrottlingError.prototype instanceof XYZServiceSyntheticServiceException);
24+
assert(RetryableError.prototype instanceof XYZServiceSyntheticServiceException);
25+
assert(XYZServiceServiceException.prototype instanceof XYZServiceSyntheticServiceException);
26+
assert(XYZServiceSyntheticServiceException.prototype instanceof Error);
1727
console.log(`XYZService index test passed.`);

private/my-local-model-schema/test/index-types.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ export type {
1414
TradeEvents,
1515
TradeEventStreamRequest,
1616
TradeEventStreamResponse,
17-
Unit,
17+
CodedThrottlingError,
18+
HaltError,
19+
MysteryThrottlingError,
20+
RetryableError,
1821
XYZServiceServiceException,
22+
XYZServiceSyntheticServiceException,
1923
} from "../dist-types/index.d";

private/smithy-rpcv2-cbor-schema/test/index-objects.spec.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import {
2+
ComplexError,
23
EmptyInputOutputCommand,
34
Float16Command,
45
FooEnum,
56
FractionalSecondsCommand,
67
GreetingWithErrorsCommand,
78
IntegerEnum,
9+
InvalidGreeting,
810
NoInputOutputCommand,
911
OperationWithDefaultsCommand,
1012
OptionalInputOutputCommand,
@@ -19,6 +21,7 @@ import {
1921
SparseNullsOperationCommand,
2022
TestEnum,
2123
TestIntEnum,
24+
ValidationException,
2225
} from "../dist-cjs/index.js";
2326
import assert from "node:assert";
2427
// clients
@@ -44,5 +47,8 @@ assert(typeof TestIntEnum === "object");
4447
assert(typeof FooEnum === "object");
4548
assert(typeof IntegerEnum === "object");
4649
// errors
50+
assert(ValidationException.prototype instanceof RpcV2ProtocolServiceException);
51+
assert(ComplexError.prototype instanceof RpcV2ProtocolServiceException);
52+
assert(InvalidGreeting.prototype instanceof RpcV2ProtocolServiceException);
4753
assert(RpcV2ProtocolServiceException.prototype instanceof Error);
4854
console.log(`RpcV2Protocol index test passed.`);

private/smithy-rpcv2-cbor-schema/test/index-types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ export type {
4545
TestIntEnum,
4646
FooEnum,
4747
IntegerEnum,
48+
ValidationExceptionField,
4849
ClientOptionalDefaults,
50+
ComplexNestedErrorData,
4951
Defaults,
5052
EmptyStructure,
5153
Float16Output,
@@ -64,5 +66,8 @@ export type {
6466
SparseNullsOperationInputOutput,
6567
StructureListMember,
6668
GreetingStruct,
69+
ValidationException,
70+
ComplexError,
71+
InvalidGreeting,
6772
RpcV2ProtocolServiceException,
6873
} from "../dist-types/index.d";

private/smithy-rpcv2-cbor/test/index-objects.spec.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import {
2+
ComplexError,
23
EmptyInputOutputCommand,
34
Float16Command,
45
FooEnum,
56
FractionalSecondsCommand,
67
GreetingWithErrorsCommand,
78
IntegerEnum,
9+
InvalidGreeting,
810
NoInputOutputCommand,
911
OperationWithDefaultsCommand,
1012
OptionalInputOutputCommand,
@@ -19,6 +21,7 @@ import {
1921
SparseNullsOperationCommand,
2022
TestEnum,
2123
TestIntEnum,
24+
ValidationException,
2225
} from "../dist-cjs/index.js";
2326
import assert from "node:assert";
2427
// clients
@@ -44,5 +47,8 @@ assert(typeof TestIntEnum === "object");
4447
assert(typeof FooEnum === "object");
4548
assert(typeof IntegerEnum === "object");
4649
// errors
50+
assert(ValidationException.prototype instanceof RpcV2ProtocolServiceException);
51+
assert(ComplexError.prototype instanceof RpcV2ProtocolServiceException);
52+
assert(InvalidGreeting.prototype instanceof RpcV2ProtocolServiceException);
4753
assert(RpcV2ProtocolServiceException.prototype instanceof Error);
4854
console.log(`RpcV2Protocol index test passed.`);

private/smithy-rpcv2-cbor/test/index-types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ export type {
4545
TestIntEnum,
4646
FooEnum,
4747
IntegerEnum,
48+
ValidationExceptionField,
4849
ClientOptionalDefaults,
50+
ComplexNestedErrorData,
4951
Defaults,
5052
EmptyStructure,
5153
Float16Output,
@@ -64,5 +66,8 @@ export type {
6466
SparseNullsOperationInputOutput,
6567
StructureListMember,
6668
GreetingStruct,
69+
ValidationException,
70+
ComplexError,
71+
InvalidGreeting,
6772
RpcV2ProtocolServiceException,
6873
} from "../dist-types/index.d";

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

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public final class PackageApiValidationGenerator {
3030
private final TypeScriptSettings settings;
3131
private final Model model;
3232
private final SymbolProvider symbolProvider;
33-
private final ServiceClosure serviceClosure;
33+
private final ServiceClosure closure;
3434

3535
public PackageApiValidationGenerator(
3636
TypeScriptWriter writer,
@@ -42,7 +42,7 @@ public PackageApiValidationGenerator(
4242
this.settings = settings;
4343
this.model = model;
4444
this.symbolProvider = symbolProvider;
45-
serviceClosure = ServiceClosure.of(model, settings.getService(model));
45+
closure = ServiceClosure.of(model, settings.getService(model));
4646
}
4747

4848
/**
@@ -75,31 +75,32 @@ public void writeTypeIndexTest() {
7575
}
7676

7777
// enums
78-
TreeSet<Shape> enumShapes = serviceClosure.getEnums();
78+
TreeSet<Shape> enumShapes = closure.getEnums();
7979
for (Shape enumShape : enumShapes) {
8080
writer.write("$L,", symbolProvider.toSymbol(enumShape).getName());
8181
}
8282

8383
// structure & union types & modeled errors
84-
TreeSet<Shape> structuralShapes = serviceClosure.getStructuralNonErrorShapes();
84+
TreeSet<Shape> structuralShapes = closure.getStructuralNonErrorShapes();
8585
for (Shape structuralShape : structuralShapes) {
8686
writer.write("$L,", symbolProvider.toSymbol(structuralShape).getName());
8787
}
8888

89-
TreeSet<Shape> errorShapes = serviceClosure.getErrorShapes();
89+
TreeSet<Shape> errorShapes = closure.getErrorShapes();
9090
for (Shape errorShape : errorShapes) {
9191
writer.write("$L,", symbolProvider.toSymbol(errorShape).getName());
9292
}
9393

9494
// synthetic base exception
95-
writer.write("$L,", aggregateClientName + "ServiceException");
95+
String baseExceptionName = CodegenUtils.getSyntheticBaseExceptionName(aggregateClientName, model);
96+
writer.write("$L,", baseExceptionName);
9697

9798
// waiters
98-
serviceClosure.getWaiterNames().forEach(waiter -> {
99+
closure.getWaiterNames().forEach(waiter -> {
99100
writer.write("$L,", waiter);
100101
});
101102
// paginators
102-
serviceClosure.getPaginatorNames().forEach(paginator -> {
103+
closure.getPaginatorNames().forEach(paginator -> {
103104
writer.write("$L,", paginator);
104105
});
105106
}
@@ -150,7 +151,7 @@ public void writeRuntimeIndexTest() {
150151

151152
// string shapes with enum trait do not generate anything if
152153
// any enum value does not have a name.
153-
TreeSet<Shape> enumShapes = serviceClosure.getEnums().stream()
154+
TreeSet<Shape> enumShapes = closure.getEnums().stream()
154155
.filter(shape -> shape
155156
.getTrait(EnumTrait.class)
156157
.map(EnumTrait::hasNames)
@@ -169,11 +170,11 @@ public void writeRuntimeIndexTest() {
169170
);
170171
}
171172

172-
String baseExceptionName = aggregateClientName + "ServiceException";
173+
String baseExceptionName = CodegenUtils.getSyntheticBaseExceptionName(aggregateClientName, model);
173174

174175
// modeled errors and synthetic base error
175176
writer.write("// errors");
176-
TreeSet<Shape> errors = serviceClosure.getErrorShapes();
177+
TreeSet<Shape> errors = closure.getErrorShapes();
177178
for (Shape error : errors) {
178179
Symbol errorSymbol = symbolProvider.toSymbol(error);
179180
writer.addRelativeImport(errorSymbol.getName(), null, cjsIndex);
@@ -187,7 +188,7 @@ public void writeRuntimeIndexTest() {
187188
writer.write("assert($L.prototype instanceof Error);", baseExceptionName);
188189

189190
// waiters & paginators
190-
TreeSet<String> waiterNames = serviceClosure.getWaiterNames();
191+
TreeSet<String> waiterNames = closure.getWaiterNames();
191192
if (!waiterNames.isEmpty()) {
192193
writer.write("// waiters");
193194
}
@@ -198,7 +199,7 @@ public void writeRuntimeIndexTest() {
198199
waiter
199200
);
200201
});
201-
TreeSet<String> paginatorNames = serviceClosure.getPaginatorNames();
202+
TreeSet<String> paginatorNames = closure.getPaginatorNames();
202203
if (!paginatorNames.isEmpty()) {
203204
writer.write("// paginators");
204205
}

0 commit comments

Comments
 (0)