@typespec/compiler 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +9 -0
- package/cmd/tsp-server.js +3 -0
- package/cmd/tsp.js +3 -0
- package/dist/cmd/runner.d.ts +9 -0
- package/dist/cmd/runner.d.ts.map +1 -0
- package/dist/cmd/runner.js +62 -0
- package/dist/cmd/runner.js.map +1 -0
- package/dist/config/config-interpolation.d.ts +11 -0
- package/dist/config/config-interpolation.d.ts.map +1 -0
- package/dist/config/config-interpolation.js +109 -0
- package/dist/config/config-interpolation.js.map +1 -0
- package/dist/config/config-loader.d.ts +25 -0
- package/dist/config/config-loader.d.ts.map +1 -0
- package/dist/config/config-loader.js +182 -0
- package/dist/config/config-loader.js.map +1 -0
- package/dist/config/config-schema.d.ts +4 -0
- package/dist/config/config-schema.d.ts.map +1 -0
- package/dist/config/config-schema.js +84 -0
- package/dist/config/config-schema.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +79 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/core/binder.d.ts +29 -0
- package/dist/core/binder.d.ts.map +1 -0
- package/dist/core/binder.js +455 -0
- package/dist/core/binder.js.map +1 -0
- package/dist/core/charcode.d.ts +130 -0
- package/dist/core/charcode.d.ts.map +1 -0
- package/dist/core/charcode.js +115 -0
- package/dist/core/charcode.js.map +1 -0
- package/dist/core/checker.d.ts +138 -0
- package/dist/core/checker.d.ts.map +1 -0
- package/dist/core/checker.js +4070 -0
- package/dist/core/checker.js.map +1 -0
- package/dist/core/cli/args.d.ts +18 -0
- package/dist/core/cli/args.d.ts.map +1 -0
- package/dist/core/cli/args.js +108 -0
- package/dist/core/cli/args.js.map +1 -0
- package/dist/core/cli/cli.d.ts +2 -0
- package/dist/core/cli/cli.d.ts.map +1 -0
- package/dist/core/cli/cli.js +477 -0
- package/dist/core/cli/cli.js.map +1 -0
- package/dist/core/cli/index.d.ts +2 -0
- package/dist/core/cli/index.d.ts.map +1 -0
- package/dist/core/cli/index.js +2 -0
- package/dist/core/cli/index.js.map +1 -0
- package/dist/core/decorator-utils.d.ts +108 -0
- package/dist/core/decorator-utils.d.ts.map +1 -0
- package/dist/core/decorator-utils.js +326 -0
- package/dist/core/decorator-utils.js.map +1 -0
- package/dist/core/diagnostics.d.ts +93 -0
- package/dist/core/diagnostics.d.ts.map +1 -0
- package/dist/core/diagnostics.js +315 -0
- package/dist/core/diagnostics.js.map +1 -0
- package/dist/core/emitter-utils.d.ts +14 -0
- package/dist/core/emitter-utils.d.ts.map +1 -0
- package/dist/core/emitter-utils.js +16 -0
- package/dist/core/emitter-utils.js.map +1 -0
- package/dist/core/formatter-fs.d.ts +21 -0
- package/dist/core/formatter-fs.d.ts.map +1 -0
- package/dist/core/formatter-fs.js +79 -0
- package/dist/core/formatter-fs.js.map +1 -0
- package/dist/core/formatter.d.ts +10 -0
- package/dist/core/formatter.d.ts.map +1 -0
- package/dist/core/formatter.js +24 -0
- package/dist/core/formatter.js.map +1 -0
- package/dist/core/helpers/discriminator-utils.d.ts +14 -0
- package/dist/core/helpers/discriminator-utils.d.ts.map +1 -0
- package/dist/core/helpers/discriminator-utils.js +169 -0
- package/dist/core/helpers/discriminator-utils.js.map +1 -0
- package/dist/core/helpers/index.d.ts +6 -0
- package/dist/core/helpers/index.d.ts.map +1 -0
- package/dist/core/helpers/index.js +6 -0
- package/dist/core/helpers/index.js.map +1 -0
- package/dist/core/helpers/operation-utils.d.ts +15 -0
- package/dist/core/helpers/operation-utils.d.ts.map +1 -0
- package/dist/core/helpers/operation-utils.js +35 -0
- package/dist/core/helpers/operation-utils.js.map +1 -0
- package/dist/core/helpers/projected-names-utils.d.ts +20 -0
- package/dist/core/helpers/projected-names-utils.d.ts.map +1 -0
- package/dist/core/helpers/projected-names-utils.js +40 -0
- package/dist/core/helpers/projected-names-utils.js.map +1 -0
- package/dist/core/helpers/type-name-utils.d.ts +14 -0
- package/dist/core/helpers/type-name-utils.d.ts.map +1 -0
- package/dist/core/helpers/type-name-utils.js +122 -0
- package/dist/core/helpers/type-name-utils.js.map +1 -0
- package/dist/core/helpers/usage-resolver.d.ts +20 -0
- package/dist/core/helpers/usage-resolver.d.ts.map +1 -0
- package/dist/core/helpers/usage-resolver.js +108 -0
- package/dist/core/helpers/usage-resolver.js.map +1 -0
- package/dist/core/index.d.ts +26 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +26 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/install.d.ts +2 -0
- package/dist/core/install.d.ts.map +1 -0
- package/dist/core/install.js +26 -0
- package/dist/core/install.js.map +1 -0
- package/dist/core/library.d.ts +34 -0
- package/dist/core/library.d.ts.map +1 -0
- package/dist/core/library.js +100 -0
- package/dist/core/library.js.map +1 -0
- package/dist/core/logger/console-sink.browser.d.ts +4 -0
- package/dist/core/logger/console-sink.browser.d.ts.map +1 -0
- package/dist/core/logger/console-sink.browser.js +14 -0
- package/dist/core/logger/console-sink.browser.js.map +1 -0
- package/dist/core/logger/console-sink.d.ts +9 -0
- package/dist/core/logger/console-sink.d.ts.map +1 -0
- package/dist/core/logger/console-sink.js +81 -0
- package/dist/core/logger/console-sink.js.map +1 -0
- package/dist/core/logger/index.d.ts +3 -0
- package/dist/core/logger/index.d.ts.map +1 -0
- package/dist/core/logger/index.js +3 -0
- package/dist/core/logger/index.js.map +1 -0
- package/dist/core/logger/logger.d.ts +7 -0
- package/dist/core/logger/logger.d.ts.map +1 -0
- package/dist/core/logger/logger.js +32 -0
- package/dist/core/logger/logger.js.map +1 -0
- package/dist/core/logger/tracer.d.ts +3 -0
- package/dist/core/logger/tracer.d.ts.map +1 -0
- package/dist/core/logger/tracer.js +91 -0
- package/dist/core/logger/tracer.js.map +1 -0
- package/dist/core/manifest.d.ts +21 -0
- package/dist/core/manifest.d.ts.map +1 -0
- package/dist/core/manifest.js +8 -0
- package/dist/core/manifest.js.map +1 -0
- package/dist/core/messages.d.ts +2253 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.js +749 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/module-resolver.d.ts +84 -0
- package/dist/core/module-resolver.d.ts.map +1 -0
- package/dist/core/module-resolver.js +170 -0
- package/dist/core/module-resolver.js.map +1 -0
- package/dist/core/node-host.browser.d.ts +2 -0
- package/dist/core/node-host.browser.d.ts.map +1 -0
- package/dist/core/node-host.browser.js +2 -0
- package/dist/core/node-host.browser.js.map +1 -0
- package/dist/core/node-host.d.ts +7 -0
- package/dist/core/node-host.d.ts.map +1 -0
- package/dist/core/node-host.js +43 -0
- package/dist/core/node-host.js.map +1 -0
- package/dist/core/nonascii.d.ts +2 -0
- package/dist/core/nonascii.d.ts.map +1 -0
- package/dist/core/nonascii.js +712 -0
- package/dist/core/nonascii.js.map +1 -0
- package/dist/core/options.d.ts +46 -0
- package/dist/core/options.d.ts.map +1 -0
- package/dist/core/options.js +2 -0
- package/dist/core/options.js.map +1 -0
- package/dist/core/parser.d.ts +17 -0
- package/dist/core/parser.d.ts.map +1 -0
- package/dist/core/parser.js +2561 -0
- package/dist/core/parser.js.map +1 -0
- package/dist/core/path-utils.d.ts +193 -0
- package/dist/core/path-utils.d.ts.map +1 -0
- package/dist/core/path-utils.js +427 -0
- package/dist/core/path-utils.js.map +1 -0
- package/dist/core/program.d.ts +104 -0
- package/dist/core/program.d.ts.map +1 -0
- package/dist/core/program.js +898 -0
- package/dist/core/program.js.map +1 -0
- package/dist/core/projection-members.d.ts +8 -0
- package/dist/core/projection-members.d.ts.map +1 -0
- package/dist/core/projection-members.js +387 -0
- package/dist/core/projection-members.js.map +1 -0
- package/dist/core/projector.d.ts +26 -0
- package/dist/core/projector.d.ts.map +1 -0
- package/dist/core/projector.js +523 -0
- package/dist/core/projector.js.map +1 -0
- package/dist/core/scanner.d.ts +125 -0
- package/dist/core/scanner.d.ts.map +1 -0
- package/dist/core/scanner.js +1012 -0
- package/dist/core/scanner.js.map +1 -0
- package/dist/core/schema-validator.d.ts +6 -0
- package/dist/core/schema-validator.d.ts.map +1 -0
- package/dist/core/schema-validator.js +38 -0
- package/dist/core/schema-validator.js.map +1 -0
- package/dist/core/semantic-walker.d.ts +53 -0
- package/dist/core/semantic-walker.d.ts.map +1 -0
- package/dist/core/semantic-walker.js +355 -0
- package/dist/core/semantic-walker.js.map +1 -0
- package/dist/core/type-utils.d.ts +49 -0
- package/dist/core/type-utils.d.ts.map +1 -0
- package/dist/core/type-utils.js +95 -0
- package/dist/core/type-utils.js.map +1 -0
- package/dist/core/types.d.ts +1345 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +105 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/util.d.ts +150 -0
- package/dist/core/util.d.ts.map +1 -0
- package/dist/core/util.js +417 -0
- package/dist/core/util.js.map +1 -0
- package/dist/emitter-framework/asset-emitter.d.ts +5 -0
- package/dist/emitter-framework/asset-emitter.d.ts.map +1 -0
- package/dist/emitter-framework/asset-emitter.js +610 -0
- package/dist/emitter-framework/asset-emitter.js.map +1 -0
- package/dist/emitter-framework/builders/array-builder.d.ts +7 -0
- package/dist/emitter-framework/builders/array-builder.d.ts.map +1 -0
- package/dist/emitter-framework/builders/array-builder.js +45 -0
- package/dist/emitter-framework/builders/array-builder.js.map +1 -0
- package/dist/emitter-framework/builders/object-builder.d.ts +9 -0
- package/dist/emitter-framework/builders/object-builder.d.ts.map +1 -0
- package/dist/emitter-framework/builders/object-builder.js +30 -0
- package/dist/emitter-framework/builders/object-builder.js.map +1 -0
- package/dist/emitter-framework/builders/string-builder.d.ts +13 -0
- package/dist/emitter-framework/builders/string-builder.d.ts.map +1 -0
- package/dist/emitter-framework/builders/string-builder.js +98 -0
- package/dist/emitter-framework/builders/string-builder.js.map +1 -0
- package/dist/emitter-framework/custom-key-map.d.ts +29 -0
- package/dist/emitter-framework/custom-key-map.d.ts.map +1 -0
- package/dist/emitter-framework/custom-key-map.js +62 -0
- package/dist/emitter-framework/custom-key-map.js.map +1 -0
- package/dist/emitter-framework/index.d.ts +8 -0
- package/dist/emitter-framework/index.d.ts.map +1 -0
- package/dist/emitter-framework/index.js +8 -0
- package/dist/emitter-framework/index.js.map +1 -0
- package/dist/emitter-framework/placeholder.d.ts +12 -0
- package/dist/emitter-framework/placeholder.d.ts.map +1 -0
- package/dist/emitter-framework/placeholder.js +27 -0
- package/dist/emitter-framework/placeholder.js.map +1 -0
- package/dist/emitter-framework/type-emitter.d.ts +314 -0
- package/dist/emitter-framework/type-emitter.d.ts.map +1 -0
- package/dist/emitter-framework/type-emitter.js +612 -0
- package/dist/emitter-framework/type-emitter.js.map +1 -0
- package/dist/emitter-framework/types.d.ts +124 -0
- package/dist/emitter-framework/types.d.ts.map +1 -0
- package/dist/emitter-framework/types.js +39 -0
- package/dist/emitter-framework/types.js.map +1 -0
- package/dist/formatter/index.d.ts +11 -0
- package/dist/formatter/index.d.ts.map +1 -0
- package/dist/formatter/index.js +28 -0
- package/dist/formatter/index.js.map +1 -0
- package/dist/formatter/parser.d.ts +16 -0
- package/dist/formatter/parser.d.ts.map +1 -0
- package/dist/formatter/parser.js +23 -0
- package/dist/formatter/parser.js.map +1 -0
- package/dist/formatter/print/comment-handler.d.ts +7 -0
- package/dist/formatter/print/comment-handler.d.ts.map +1 -0
- package/dist/formatter/print/comment-handler.js +81 -0
- package/dist/formatter/print/comment-handler.js.map +1 -0
- package/dist/formatter/print/index.d.ts +3 -0
- package/dist/formatter/print/index.d.ts.map +1 -0
- package/dist/formatter/print/index.js +3 -0
- package/dist/formatter/print/index.js.map +1 -0
- package/dist/formatter/print/needs-parens.d.ts +10 -0
- package/dist/formatter/print/needs-parens.d.ts.map +1 -0
- package/dist/formatter/print/needs-parens.js +27 -0
- package/dist/formatter/print/needs-parens.js.map +1 -0
- package/dist/formatter/print/printer.d.ts +62 -0
- package/dist/formatter/print/printer.d.ts.map +1 -0
- package/dist/formatter/print/printer.js +1025 -0
- package/dist/formatter/print/printer.js.map +1 -0
- package/dist/formatter/print/types.d.ts +9 -0
- package/dist/formatter/print/types.d.ts.map +1 -0
- package/dist/formatter/print/types.js +2 -0
- package/dist/formatter/print/types.js.map +1 -0
- package/dist/init/index.d.ts +2 -0
- package/dist/init/index.d.ts.map +1 -0
- package/dist/init/index.js +2 -0
- package/dist/init/index.js.map +1 -0
- package/dist/init/init-template.d.ts +45 -0
- package/dist/init/init-template.d.ts.map +1 -0
- package/dist/init/init-template.js +45 -0
- package/dist/init/init-template.js.map +1 -0
- package/dist/init/init.d.ts +49 -0
- package/dist/init/init.d.ts.map +1 -0
- package/dist/init/init.js +224 -0
- package/dist/init/init.js.map +1 -0
- package/dist/lib/decorators.d.ts +222 -0
- package/dist/lib/decorators.d.ts.map +1 -0
- package/dist/lib/decorators.js +745 -0
- package/dist/lib/decorators.js.map +1 -0
- package/dist/lib/service.d.ts +38 -0
- package/dist/lib/service.d.ts.map +1 -0
- package/dist/lib/service.js +78 -0
- package/dist/lib/service.js.map +1 -0
- package/dist/manifest.js +4 -0
- package/dist/server/completion.d.ts +10 -0
- package/dist/server/completion.d.ts.map +1 -0
- package/dist/server/completion.js +207 -0
- package/dist/server/completion.js.map +1 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +3 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/language-config.d.ts +195 -0
- package/dist/server/language-config.d.ts.map +1 -0
- package/dist/server/language-config.js +102 -0
- package/dist/server/language-config.js.map +1 -0
- package/dist/server/server.d.ts +2 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +131 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/serverlib.d.ts +72 -0
- package/dist/server/serverlib.d.ts.map +1 -0
- package/dist/server/serverlib.js +1034 -0
- package/dist/server/serverlib.js.map +1 -0
- package/dist/server/symbol-structure.d.ts +4 -0
- package/dist/server/symbol-structure.d.ts.map +1 -0
- package/dist/server/symbol-structure.js +121 -0
- package/dist/server/symbol-structure.js.map +1 -0
- package/dist/server/tmlanguage.d.ts +3 -0
- package/dist/server/tmlanguage.d.ts.map +1 -0
- package/dist/server/tmlanguage.js +713 -0
- package/dist/server/tmlanguage.js.map +1 -0
- package/dist/server/type-details.d.ts +11 -0
- package/dist/server/type-details.d.ts.map +1 -0
- package/dist/server/type-details.js +72 -0
- package/dist/server/type-details.js.map +1 -0
- package/dist/server/type-signature.d.ts +2 -0
- package/dist/server/type-signature.d.ts.map +1 -0
- package/dist/server/type-signature.js +108 -0
- package/dist/server/type-signature.js.map +1 -0
- package/dist/testing/expect.d.ts +49 -0
- package/dist/testing/expect.d.ts.map +1 -0
- package/dist/testing/expect.js +83 -0
- package/dist/testing/expect.js.map +1 -0
- package/dist/testing/index.d.ts +6 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +6 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/test-host.d.ts +14 -0
- package/dist/testing/test-host.d.ts.map +1 -0
- package/dist/testing/test-host.js +271 -0
- package/dist/testing/test-host.js.map +1 -0
- package/dist/testing/test-server-host.d.ts +39 -0
- package/dist/testing/test-server-host.d.ts.map +1 -0
- package/dist/testing/test-server-host.js +112 -0
- package/dist/testing/test-server-host.js.map +1 -0
- package/dist/testing/test-utils.d.ts +22 -0
- package/dist/testing/test-utils.d.ts.map +1 -0
- package/dist/testing/test-utils.js +60 -0
- package/dist/testing/test-utils.js.map +1 -0
- package/dist/testing/types.d.ts +69 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing/types.js +7 -0
- package/dist/testing/types.js.map +1 -0
- package/dist/typespec.tmLanguage +1760 -0
- package/lib/decorators.tsp +420 -0
- package/lib/lib.tsp +158 -0
- package/lib/main.tsp +4 -0
- package/lib/projected-names.tsp +94 -0
- package/lib/reflection.tsp +10 -0
- package/package.json +119 -0
|
@@ -0,0 +1,745 @@
|
|
|
1
|
+
import { validateDecoratorNotOnType, validateDecoratorTarget, validateDecoratorTargetIntrinsic, } from "../core/decorator-utils.js";
|
|
2
|
+
import { getDiscriminatedUnion, getTypeName, validateDecoratorUniqueOnNode, } from "../core/index.js";
|
|
3
|
+
import { createDiagnostic, reportDiagnostic } from "../core/messages.js";
|
|
4
|
+
export * from "./service.js";
|
|
5
|
+
export const namespace = "TypeSpec";
|
|
6
|
+
function replaceTemplatedStringFromProperties(formatString, sourceObject) {
|
|
7
|
+
// Template parameters are not valid source objects, just skip them
|
|
8
|
+
if (sourceObject.kind === "TemplateParameter") {
|
|
9
|
+
return formatString;
|
|
10
|
+
}
|
|
11
|
+
return formatString.replace(/{(\w+)}/g, (_, propName) => {
|
|
12
|
+
return sourceObject[propName];
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function setTemplatedStringProperty(key, program, target, text, sourceObject) {
|
|
16
|
+
// If an object was passed in, use it to format the documentation string
|
|
17
|
+
if (sourceObject) {
|
|
18
|
+
text = replaceTemplatedStringFromProperties(text, sourceObject);
|
|
19
|
+
}
|
|
20
|
+
program.stateMap(key).set(target, text);
|
|
21
|
+
}
|
|
22
|
+
function createStateSymbol(name) {
|
|
23
|
+
return Symbol.for(`TypeSpec.${name}`);
|
|
24
|
+
}
|
|
25
|
+
const summaryKey = createStateSymbol("summary");
|
|
26
|
+
/**
|
|
27
|
+
* @summary attaches a documentation string. It is typically used to give a short, single-line
|
|
28
|
+
* description, and can be used in combination with or instead of @doc.
|
|
29
|
+
*
|
|
30
|
+
* The first argument to @summary is a string, which may contain template parameters, enclosed in braces,
|
|
31
|
+
* which are replaced with an attribute for the type (commonly "name") passed as the second (optional) argument.
|
|
32
|
+
*
|
|
33
|
+
* @summary can be specified on any language element -- a model, an operation, a namespace, etc.
|
|
34
|
+
*/
|
|
35
|
+
export function $summary(context, target, text, sourceObject) {
|
|
36
|
+
setTemplatedStringProperty(summaryKey, context.program, target, text, sourceObject);
|
|
37
|
+
}
|
|
38
|
+
export function getSummary(program, type) {
|
|
39
|
+
return program.stateMap(summaryKey).get(type);
|
|
40
|
+
}
|
|
41
|
+
const docsKey = createStateSymbol("docs");
|
|
42
|
+
/**
|
|
43
|
+
* @doc attaches a documentation string. Works great with multi-line string literals.
|
|
44
|
+
*
|
|
45
|
+
* The first argument to @doc is a string, which may contain template parameters, enclosed in braces,
|
|
46
|
+
* which are replaced with an attribute for the type (commonly "name") passed as the second (optional) argument.
|
|
47
|
+
*
|
|
48
|
+
* @doc can be specified on any language element -- a model, an operation, a namespace, etc.
|
|
49
|
+
*/
|
|
50
|
+
export function $doc(context, target, text, sourceObject) {
|
|
51
|
+
validateDecoratorUniqueOnNode(context, target, $doc);
|
|
52
|
+
setTemplatedStringProperty(docsKey, context.program, target, text, sourceObject);
|
|
53
|
+
}
|
|
54
|
+
export function getDoc(program, target) {
|
|
55
|
+
return program.stateMap(docsKey).get(target);
|
|
56
|
+
}
|
|
57
|
+
export function $inspectType(program, target, text) {
|
|
58
|
+
// eslint-disable-next-line no-console
|
|
59
|
+
if (text)
|
|
60
|
+
console.log(text);
|
|
61
|
+
// eslint-disable-next-line no-console
|
|
62
|
+
console.dir(target, { depth: 3 });
|
|
63
|
+
}
|
|
64
|
+
export function $inspectTypeName(program, target, text) {
|
|
65
|
+
// eslint-disable-next-line no-console
|
|
66
|
+
if (text)
|
|
67
|
+
console.log(text);
|
|
68
|
+
// eslint-disable-next-line no-console
|
|
69
|
+
console.log(getTypeName(target));
|
|
70
|
+
}
|
|
71
|
+
const indexTypeKey = createStateSymbol("index");
|
|
72
|
+
export function $indexer(context, target, key, value) {
|
|
73
|
+
const indexer = { key, value };
|
|
74
|
+
context.program.stateMap(indexTypeKey).set(target, indexer);
|
|
75
|
+
}
|
|
76
|
+
export function getIndexer(program, target) {
|
|
77
|
+
return program.stateMap(indexTypeKey).get(target);
|
|
78
|
+
}
|
|
79
|
+
export function isStringType(program, target) {
|
|
80
|
+
const coreType = program.checker.getStdType("string");
|
|
81
|
+
const stringType = target.projector ? target.projector.projectType(coreType) : coreType;
|
|
82
|
+
return (target.kind === "Scalar" && program.checker.isTypeAssignableTo(target, stringType, target)[0]);
|
|
83
|
+
}
|
|
84
|
+
export function isNumericType(program, target) {
|
|
85
|
+
const coreType = program.checker.getStdType("numeric");
|
|
86
|
+
const numericType = target.projector ? target.projector.projectType(coreType) : coreType;
|
|
87
|
+
return (target.kind === "Scalar" && program.checker.isTypeAssignableTo(target, numericType, target)[0]);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if a model is an array type.
|
|
91
|
+
* @param type Model type
|
|
92
|
+
*/
|
|
93
|
+
export function isArrayModelType(program, type) {
|
|
94
|
+
return Boolean(type.indexer && type.indexer.key.name === "integer");
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check if a model is an array type.
|
|
98
|
+
* @param type Model type
|
|
99
|
+
*/
|
|
100
|
+
export function isRecordModelType(program, type) {
|
|
101
|
+
return Boolean(type.indexer && type.indexer.key.name === "string");
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Return the type of the property or the model itself.
|
|
105
|
+
*/
|
|
106
|
+
export function getPropertyType(target) {
|
|
107
|
+
if (target.kind === "ModelProperty") {
|
|
108
|
+
return target.type;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return target;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// -- @error decorator ----------------------
|
|
115
|
+
const errorKey = createStateSymbol("error");
|
|
116
|
+
/**
|
|
117
|
+
* `@error` decorator marks a model as an error type.
|
|
118
|
+
*
|
|
119
|
+
* `@error` can only be specified on a model.
|
|
120
|
+
*/
|
|
121
|
+
export function $error(context, entity) {
|
|
122
|
+
validateDecoratorUniqueOnNode(context, entity, $error);
|
|
123
|
+
context.program.stateSet(errorKey).add(entity);
|
|
124
|
+
}
|
|
125
|
+
export function isErrorModel(program, target) {
|
|
126
|
+
return program.stateSet(errorKey).has(target);
|
|
127
|
+
}
|
|
128
|
+
// -- @format decorator ---------------------
|
|
129
|
+
const formatValuesKey = createStateSymbol("formatValues");
|
|
130
|
+
/**
|
|
131
|
+
* `@format` - specify the data format hint for a string type
|
|
132
|
+
*
|
|
133
|
+
* The first argument is a string that identifies the format that the string type expects. Any string
|
|
134
|
+
* can be entered here, but a TypeSpec emitter must know how to interpret
|
|
135
|
+
*
|
|
136
|
+
* For TypeSpec specs that will be used with an OpenAPI emitter, the OpenAPI specification describes possible
|
|
137
|
+
* valid values for a string type's format:
|
|
138
|
+
*
|
|
139
|
+
* https://github.com/OAI/OpenAPI-Specification/blob/3.0.3/versions/3.0.3.md#dataTypes
|
|
140
|
+
*
|
|
141
|
+
* `@format` can be specified on a type that extends from `string` or a `string`-typed model property.
|
|
142
|
+
*/
|
|
143
|
+
export function $format(context, target, format) {
|
|
144
|
+
validateDecoratorUniqueOnNode(context, target, $format);
|
|
145
|
+
if (!validateDecoratorTargetIntrinsic(context, target, "@format", ["string", "bytes"])) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
context.program.stateMap(formatValuesKey).set(target, format);
|
|
149
|
+
}
|
|
150
|
+
export function getFormat(program, target) {
|
|
151
|
+
return program.stateMap(formatValuesKey).get(target);
|
|
152
|
+
}
|
|
153
|
+
// -- @pattern decorator ---------------------
|
|
154
|
+
const patternValuesKey = createStateSymbol("patternValues");
|
|
155
|
+
export function $pattern(context, target, pattern) {
|
|
156
|
+
validateDecoratorUniqueOnNode(context, target, $pattern);
|
|
157
|
+
if (!validateDecoratorTargetIntrinsic(context, target, "@pattern", "string")) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
context.program.stateMap(patternValuesKey).set(target, pattern);
|
|
161
|
+
}
|
|
162
|
+
export function getPattern(program, target) {
|
|
163
|
+
return program.stateMap(patternValuesKey).get(target);
|
|
164
|
+
}
|
|
165
|
+
// -- @minLength decorator ---------------------
|
|
166
|
+
const minLengthValuesKey = createStateSymbol("minLengthValues");
|
|
167
|
+
export function $minLength(context, target, minLength) {
|
|
168
|
+
validateDecoratorUniqueOnNode(context, target, $minLength);
|
|
169
|
+
if (!validateDecoratorTargetIntrinsic(context, target, "@minLength", "string") ||
|
|
170
|
+
!validateRange(context, minLength, getMaxLength(context.program, target))) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
context.program.stateMap(minLengthValuesKey).set(target, minLength);
|
|
174
|
+
}
|
|
175
|
+
export function getMinLength(program, target) {
|
|
176
|
+
return program.stateMap(minLengthValuesKey).get(target);
|
|
177
|
+
}
|
|
178
|
+
// -- @maxLength decorator ---------------------
|
|
179
|
+
const maxLengthValuesKey = createStateSymbol("maxLengthValues");
|
|
180
|
+
export function $maxLength(context, target, maxLength) {
|
|
181
|
+
validateDecoratorUniqueOnNode(context, target, $maxLength);
|
|
182
|
+
if (!validateDecoratorTargetIntrinsic(context, target, "@maxLength", "string") ||
|
|
183
|
+
!validateRange(context, getMinLength(context.program, target), maxLength)) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
context.program.stateMap(maxLengthValuesKey).set(target, maxLength);
|
|
187
|
+
}
|
|
188
|
+
export function getMaxLength(program, target) {
|
|
189
|
+
return program.stateMap(maxLengthValuesKey).get(target);
|
|
190
|
+
}
|
|
191
|
+
// -- @minItems decorator ---------------------
|
|
192
|
+
const minItemsValuesKey = createStateSymbol("minItems");
|
|
193
|
+
export function $minItems(context, target, minItems) {
|
|
194
|
+
validateDecoratorUniqueOnNode(context, target, $minItems);
|
|
195
|
+
if (!isArrayModelType(context.program, target.kind === "Model" ? target : target.type)) {
|
|
196
|
+
reportDiagnostic(context.program, {
|
|
197
|
+
code: "decorator-wrong-target",
|
|
198
|
+
format: {
|
|
199
|
+
decorator: "@minItems",
|
|
200
|
+
to: `non Array type`,
|
|
201
|
+
},
|
|
202
|
+
target: context.decoratorTarget,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
if (!validateRange(context, minItems, getMaxItems(context.program, target))) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
context.program.stateMap(minItemsValuesKey).set(target, minItems);
|
|
209
|
+
}
|
|
210
|
+
export function getMinItems(program, target) {
|
|
211
|
+
return program.stateMap(minItemsValuesKey).get(target);
|
|
212
|
+
}
|
|
213
|
+
// -- @maxLength decorator ---------------------
|
|
214
|
+
const maxItemsValuesKey = createStateSymbol("maxItems");
|
|
215
|
+
export function $maxItems(context, target, maxItems) {
|
|
216
|
+
validateDecoratorUniqueOnNode(context, target, $maxItems);
|
|
217
|
+
if (!isArrayModelType(context.program, target.kind === "Model" ? target : target.type)) {
|
|
218
|
+
reportDiagnostic(context.program, {
|
|
219
|
+
code: "decorator-wrong-target",
|
|
220
|
+
format: {
|
|
221
|
+
decorator: "@maxItems",
|
|
222
|
+
to: `non Array type`,
|
|
223
|
+
},
|
|
224
|
+
target: context.decoratorTarget,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
if (!validateRange(context, getMinItems(context.program, target), maxItems)) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
context.program.stateMap(maxItemsValuesKey).set(target, maxItems);
|
|
231
|
+
}
|
|
232
|
+
export function getMaxItems(program, target) {
|
|
233
|
+
return program.stateMap(maxItemsValuesKey).get(target);
|
|
234
|
+
}
|
|
235
|
+
// -- @minValue decorator ---------------------
|
|
236
|
+
const minValuesKey = createStateSymbol("minValues");
|
|
237
|
+
export function $minValue(context, target, minValue) {
|
|
238
|
+
var _a;
|
|
239
|
+
validateDecoratorUniqueOnNode(context, target, $minValue);
|
|
240
|
+
validateDecoratorNotOnType(context, target, $minValueExclusive, $minValue);
|
|
241
|
+
const { program } = context;
|
|
242
|
+
if (!isNumericType(program, getPropertyType(target))) {
|
|
243
|
+
program.reportDiagnostic(createDiagnostic({
|
|
244
|
+
code: "decorator-wrong-target",
|
|
245
|
+
format: { decorator: "@minValue", to: "non-numeric type" },
|
|
246
|
+
target,
|
|
247
|
+
}));
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (!validateRange(context, minValue, (_a = getMaxValue(context.program, target)) !== null && _a !== void 0 ? _a : getMaxValueExclusive(context.program, target))) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
program.stateMap(minValuesKey).set(target, minValue);
|
|
254
|
+
}
|
|
255
|
+
export function getMinValue(program, target) {
|
|
256
|
+
return program.stateMap(minValuesKey).get(target);
|
|
257
|
+
}
|
|
258
|
+
// -- @maxValue decorator ---------------------
|
|
259
|
+
const maxValuesKey = createStateSymbol("maxValues");
|
|
260
|
+
export function $maxValue(context, target, maxValue) {
|
|
261
|
+
var _a;
|
|
262
|
+
validateDecoratorUniqueOnNode(context, target, $maxValue);
|
|
263
|
+
validateDecoratorNotOnType(context, target, $maxValueExclusive, $maxValue);
|
|
264
|
+
const { program } = context;
|
|
265
|
+
if (!isNumericType(program, getPropertyType(target))) {
|
|
266
|
+
program.reportDiagnostic(createDiagnostic({
|
|
267
|
+
code: "decorator-wrong-target",
|
|
268
|
+
format: { decorator: "@maxValue", to: "non-numeric type" },
|
|
269
|
+
target,
|
|
270
|
+
}));
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (!validateRange(context, (_a = getMinValue(context.program, target)) !== null && _a !== void 0 ? _a : getMinValueExclusive(context.program, target), maxValue)) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
program.stateMap(maxValuesKey).set(target, maxValue);
|
|
277
|
+
}
|
|
278
|
+
export function getMaxValue(program, target) {
|
|
279
|
+
return program.stateMap(maxValuesKey).get(target);
|
|
280
|
+
}
|
|
281
|
+
// -- @minValueExclusive decorator ---------------------
|
|
282
|
+
const minValueExclusiveKey = createStateSymbol("minValueExclusive");
|
|
283
|
+
export function $minValueExclusive(context, target, minValueExclusive) {
|
|
284
|
+
var _a;
|
|
285
|
+
validateDecoratorUniqueOnNode(context, target, $minValueExclusive);
|
|
286
|
+
validateDecoratorNotOnType(context, target, $minValue, $minValueExclusive);
|
|
287
|
+
const { program } = context;
|
|
288
|
+
if (!isNumericType(program, getPropertyType(target))) {
|
|
289
|
+
program.reportDiagnostic(createDiagnostic({
|
|
290
|
+
code: "decorator-wrong-target",
|
|
291
|
+
format: { decorator: "@minValueExclusive", to: "non-numeric type" },
|
|
292
|
+
target,
|
|
293
|
+
}));
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (!validateRange(context, minValueExclusive, (_a = getMaxValue(context.program, target)) !== null && _a !== void 0 ? _a : getMaxValueExclusive(context.program, target))) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
program.stateMap(minValueExclusiveKey).set(target, minValueExclusive);
|
|
300
|
+
}
|
|
301
|
+
export function getMinValueExclusive(program, target) {
|
|
302
|
+
return program.stateMap(minValueExclusiveKey).get(target);
|
|
303
|
+
}
|
|
304
|
+
// -- @maxValueExclusive decorator ---------------------
|
|
305
|
+
const maxValueExclusiveKey = createStateSymbol("maxValueExclusive");
|
|
306
|
+
export function $maxValueExclusive(context, target, maxValueExclusive) {
|
|
307
|
+
var _a;
|
|
308
|
+
validateDecoratorUniqueOnNode(context, target, $maxValueExclusive);
|
|
309
|
+
validateDecoratorNotOnType(context, target, $maxValue, $maxValueExclusive);
|
|
310
|
+
const { program } = context;
|
|
311
|
+
if (!isNumericType(program, getPropertyType(target))) {
|
|
312
|
+
program.reportDiagnostic(createDiagnostic({
|
|
313
|
+
code: "decorator-wrong-target",
|
|
314
|
+
format: { decorator: "@maxValue", to: "non-numeric type" },
|
|
315
|
+
target,
|
|
316
|
+
}));
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (!validateRange(context, (_a = getMinValue(context.program, target)) !== null && _a !== void 0 ? _a : getMinValueExclusive(context.program, target), maxValueExclusive)) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
program.stateMap(maxValueExclusiveKey).set(target, maxValueExclusive);
|
|
323
|
+
}
|
|
324
|
+
export function getMaxValueExclusive(program, target) {
|
|
325
|
+
return program.stateMap(maxValueExclusiveKey).get(target);
|
|
326
|
+
}
|
|
327
|
+
// -- @secret decorator ---------------------
|
|
328
|
+
const secretTypesKey = createStateSymbol("secretTypes");
|
|
329
|
+
/**
|
|
330
|
+
* Mark a string as a secret value that should be treated carefully to avoid exposure
|
|
331
|
+
* @param context Decorator context
|
|
332
|
+
* @param target Decorator target, either a string model or a property with type string.
|
|
333
|
+
*/
|
|
334
|
+
export function $secret(context, target) {
|
|
335
|
+
validateDecoratorUniqueOnNode(context, target, $secret);
|
|
336
|
+
if (!validateDecoratorTargetIntrinsic(context, target, "@secret", "string")) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
context.program.stateMap(secretTypesKey).set(target, true);
|
|
340
|
+
}
|
|
341
|
+
export function isSecret(program, target) {
|
|
342
|
+
return program.stateMap(secretTypesKey).get(target);
|
|
343
|
+
}
|
|
344
|
+
// -- @visibility decorator ---------------------
|
|
345
|
+
const visibilitySettingsKey = createStateSymbol("visibilitySettings");
|
|
346
|
+
export function $visibility(context, target, ...visibilities) {
|
|
347
|
+
validateDecoratorUniqueOnNode(context, target, $visibility);
|
|
348
|
+
context.program.stateMap(visibilitySettingsKey).set(target, visibilities);
|
|
349
|
+
}
|
|
350
|
+
export function getVisibility(program, target) {
|
|
351
|
+
return program.stateMap(visibilitySettingsKey).get(target);
|
|
352
|
+
}
|
|
353
|
+
export function $withVisibility(context, target, ...visibilities) {
|
|
354
|
+
filterModelPropertiesInPlace(target, (p) => isVisible(context.program, p, visibilities));
|
|
355
|
+
}
|
|
356
|
+
export function isVisible(program, property, visibilities) {
|
|
357
|
+
const propertyVisibilities = getVisibility(program, property);
|
|
358
|
+
return !propertyVisibilities || propertyVisibilities.some((v) => visibilities.includes(v));
|
|
359
|
+
}
|
|
360
|
+
function filterModelPropertiesInPlace(model, filter) {
|
|
361
|
+
for (const [key, prop] of model.properties) {
|
|
362
|
+
if (!filter(prop)) {
|
|
363
|
+
model.properties.delete(key);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
// -- @withOptionalProperties decorator ---------------------
|
|
368
|
+
export function $withOptionalProperties(context, target) {
|
|
369
|
+
// Make all properties of the target type optional
|
|
370
|
+
target.properties.forEach((p) => (p.optional = true));
|
|
371
|
+
}
|
|
372
|
+
// -- @withUpdateableProperties decorator ----------------------
|
|
373
|
+
export function $withUpdateableProperties(context, target) {
|
|
374
|
+
if (!validateDecoratorTarget(context, target, "@withUpdateableProperties", "Model")) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
filterModelPropertiesInPlace(target, (p) => isVisible(context.program, p, ["update"]));
|
|
378
|
+
}
|
|
379
|
+
// -- @withoutOmittedProperties decorator ----------------------
|
|
380
|
+
export function $withoutOmittedProperties(context, target, omitProperties) {
|
|
381
|
+
// Get the property or properties to omit
|
|
382
|
+
const omitNames = new Set();
|
|
383
|
+
if (typeof omitProperties === "string") {
|
|
384
|
+
omitNames.add(omitProperties);
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
for (const value of omitProperties.options) {
|
|
388
|
+
if (value.kind === "String") {
|
|
389
|
+
omitNames.add(value.value);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
// Remove all properties to be omitted
|
|
394
|
+
filterModelPropertiesInPlace(target, (prop) => !omitNames.has(prop.name));
|
|
395
|
+
}
|
|
396
|
+
// -- @withoutDefaultValues decorator ----------------------
|
|
397
|
+
export function $withoutDefaultValues(context, target) {
|
|
398
|
+
// remove all read-only properties from the target type
|
|
399
|
+
target.properties.forEach((p) => delete p.default);
|
|
400
|
+
}
|
|
401
|
+
// -- @list decorator ---------------------
|
|
402
|
+
const listPropertiesKey = createStateSymbol("listProperties");
|
|
403
|
+
export function $list(context, target, listedType) {
|
|
404
|
+
if (listedType && listedType.kind === "TemplateParameter") {
|
|
405
|
+
// Silently return because this is probably being used in a templated interface
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
if (listedType && listedType.kind !== "Model") {
|
|
409
|
+
reportDiagnostic(context.program, {
|
|
410
|
+
code: "list-type-not-model",
|
|
411
|
+
target: context.getArgumentTarget(0),
|
|
412
|
+
});
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
context.program.stateMap(listPropertiesKey).set(target, listedType);
|
|
416
|
+
}
|
|
417
|
+
export function getListOperationType(program, target) {
|
|
418
|
+
return program.stateMap(listPropertiesKey).get(target);
|
|
419
|
+
}
|
|
420
|
+
export function isListOperation(program, target) {
|
|
421
|
+
// The type stored for the operation
|
|
422
|
+
return program.stateMap(listPropertiesKey).has(target);
|
|
423
|
+
}
|
|
424
|
+
// -- @tag decorator ---------------------
|
|
425
|
+
const tagPropertiesKey = createStateSymbol("tagProperties");
|
|
426
|
+
// Set a tag on an operation, interface, or namespace. There can be multiple tags on an
|
|
427
|
+
// operation, interface, or namespace.
|
|
428
|
+
export function $tag(context, target, tag) {
|
|
429
|
+
const tags = context.program.stateMap(tagPropertiesKey).get(target);
|
|
430
|
+
if (tags) {
|
|
431
|
+
tags.push(tag);
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
context.program.stateMap(tagPropertiesKey).set(target, [tag]);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
// Return the tags set on an operation or namespace
|
|
438
|
+
export function getTags(program, target) {
|
|
439
|
+
return program.stateMap(tagPropertiesKey).get(target) || [];
|
|
440
|
+
}
|
|
441
|
+
// Merge the tags for a operation with the tags that are on the namespace or
|
|
442
|
+
// interface it resides within.
|
|
443
|
+
export function getAllTags(program, target) {
|
|
444
|
+
var _a;
|
|
445
|
+
const tags = new Set();
|
|
446
|
+
let current = target;
|
|
447
|
+
while (current !== undefined) {
|
|
448
|
+
for (const t of getTags(program, current)) {
|
|
449
|
+
tags.add(t);
|
|
450
|
+
}
|
|
451
|
+
// Move up to the parent
|
|
452
|
+
if (current.kind === "Operation") {
|
|
453
|
+
current = (_a = current.interface) !== null && _a !== void 0 ? _a : current.namespace;
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
// Type is a namespace or interface
|
|
457
|
+
current = current.namespace;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return tags.size > 0 ? Array.from(tags).reverse() : undefined;
|
|
461
|
+
}
|
|
462
|
+
// -- @friendlyName decorator ---------------------
|
|
463
|
+
const friendlyNamesKey = createStateSymbol("friendlyNames");
|
|
464
|
+
export function $friendlyName(context, target, friendlyName, sourceObject) {
|
|
465
|
+
// If an object was passed in, use it to format the friendly name
|
|
466
|
+
if (sourceObject) {
|
|
467
|
+
friendlyName = replaceTemplatedStringFromProperties(friendlyName, sourceObject);
|
|
468
|
+
}
|
|
469
|
+
context.program.stateMap(friendlyNamesKey).set(target, friendlyName);
|
|
470
|
+
}
|
|
471
|
+
export function getFriendlyName(program, target) {
|
|
472
|
+
return program.stateMap(friendlyNamesKey).get(target);
|
|
473
|
+
}
|
|
474
|
+
const knownValuesKey = createStateSymbol("knownValues");
|
|
475
|
+
/**
|
|
476
|
+
* `@knownValues` marks a string type with an enum that contains all known values
|
|
477
|
+
*
|
|
478
|
+
* The first parameter is a reference to an enum type that describes all possible values that the
|
|
479
|
+
* type accepts.
|
|
480
|
+
*
|
|
481
|
+
* `@knownValues` can only be applied to model types that extend `string`.
|
|
482
|
+
*
|
|
483
|
+
* @param target Decorator target. Must be a string. (model Foo extends string)
|
|
484
|
+
* @param knownValues Must be an enum.
|
|
485
|
+
*/
|
|
486
|
+
export function $knownValues(context, target, knownValues) {
|
|
487
|
+
if (!validateDecoratorTargetIntrinsic(context, target, "@knownValues", [
|
|
488
|
+
"string",
|
|
489
|
+
"int8",
|
|
490
|
+
"int16",
|
|
491
|
+
"int32",
|
|
492
|
+
"int64",
|
|
493
|
+
"float32",
|
|
494
|
+
"float64",
|
|
495
|
+
])) {
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
for (const member of knownValues.members.values()) {
|
|
499
|
+
const propertyType = getPropertyType(target);
|
|
500
|
+
if (!isEnumMemberAssignableToType(context.program, propertyType, member)) {
|
|
501
|
+
reportDiagnostic(context.program, {
|
|
502
|
+
code: "known-values-invalid-enum",
|
|
503
|
+
format: {
|
|
504
|
+
member: member.name,
|
|
505
|
+
type: context.program.checker.getTypeName(propertyType),
|
|
506
|
+
},
|
|
507
|
+
target,
|
|
508
|
+
});
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
context.program.stateMap(knownValuesKey).set(target, knownValues);
|
|
513
|
+
}
|
|
514
|
+
function isEnumMemberAssignableToType(program, typeName, member) {
|
|
515
|
+
const memberType = member.value !== undefined ? typeof member.value : "string";
|
|
516
|
+
switch (memberType) {
|
|
517
|
+
case "string":
|
|
518
|
+
return isStringType(program, typeName);
|
|
519
|
+
case "number":
|
|
520
|
+
return isNumericType(program, typeName);
|
|
521
|
+
default:
|
|
522
|
+
return false;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
export function getKnownValues(program, target) {
|
|
526
|
+
return program.stateMap(knownValuesKey).get(target);
|
|
527
|
+
}
|
|
528
|
+
const keyKey = createStateSymbol("key");
|
|
529
|
+
/**
|
|
530
|
+
* `@key` - mark a model property as the key to identify instances of that type
|
|
531
|
+
*
|
|
532
|
+
* The optional first argument accepts an alternate key name which may be used by emitters.
|
|
533
|
+
* Otherwise, the name of the target property will be used.
|
|
534
|
+
*
|
|
535
|
+
* `@key` can only be applied to model properties.
|
|
536
|
+
*/
|
|
537
|
+
export function $key(context, entity, altName) {
|
|
538
|
+
// Ensure that the key property is not marked as optional
|
|
539
|
+
if (entity.optional) {
|
|
540
|
+
reportDiagnostic(context.program, {
|
|
541
|
+
code: "no-optional-key",
|
|
542
|
+
format: { propertyName: entity.name },
|
|
543
|
+
target: entity,
|
|
544
|
+
});
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
// Register the key property
|
|
548
|
+
context.program.stateMap(keyKey).set(entity, altName || entity.name);
|
|
549
|
+
}
|
|
550
|
+
export function isKey(program, property) {
|
|
551
|
+
return program.stateMap(keyKey).has(property);
|
|
552
|
+
}
|
|
553
|
+
export function getKeyName(program, property) {
|
|
554
|
+
return program.stateMap(keyKey).get(property);
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* `@withDefaultKeyVisibility` - set the visibility of key properties in a model if not already set
|
|
558
|
+
*
|
|
559
|
+
* The first argument accepts a string representing the desired default
|
|
560
|
+
* visibility value. If a key property already has a `visibility` decorator
|
|
561
|
+
* then the default visibility is not applied.
|
|
562
|
+
*
|
|
563
|
+
* `@withDefaultKeyVisibility` can only be applied to model types.
|
|
564
|
+
*/
|
|
565
|
+
export function $withDefaultKeyVisibility(context, entity, visibility) {
|
|
566
|
+
const keyProperties = [];
|
|
567
|
+
entity.properties.forEach((prop) => {
|
|
568
|
+
// Keep track of any key property without a visibility
|
|
569
|
+
if (isKey(context.program, prop) && !getVisibility(context.program, prop)) {
|
|
570
|
+
keyProperties.push(prop);
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
// For each key property without a visibility, clone it and add the specified
|
|
574
|
+
// default visibility value
|
|
575
|
+
keyProperties.forEach((keyProp) => {
|
|
576
|
+
entity.properties.set(keyProp.name, context.program.checker.cloneType(keyProp, {
|
|
577
|
+
decorators: [
|
|
578
|
+
...keyProp.decorators,
|
|
579
|
+
{
|
|
580
|
+
decorator: $visibility,
|
|
581
|
+
args: [{ value: context.program.checker.createLiteralType(visibility) }],
|
|
582
|
+
},
|
|
583
|
+
],
|
|
584
|
+
}));
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Mark a type as deprecated
|
|
589
|
+
* @param context DecoratorContext
|
|
590
|
+
* @param target Decorator target
|
|
591
|
+
* @param message Deprecation target.
|
|
592
|
+
*
|
|
593
|
+
* @example
|
|
594
|
+
* ``` @deprecated("Foo is deprecated, use Bar instead.")
|
|
595
|
+
* model Foo {}
|
|
596
|
+
* ```
|
|
597
|
+
*/
|
|
598
|
+
export function $deprecated(context, target, message) {
|
|
599
|
+
return context.program.stateMap(deprecatedKey).set(target, message);
|
|
600
|
+
}
|
|
601
|
+
const deprecatedKey = createStateSymbol("deprecated");
|
|
602
|
+
/**
|
|
603
|
+
* Check if the given type is deprecated
|
|
604
|
+
* @param program Program
|
|
605
|
+
* @param type Type
|
|
606
|
+
*/
|
|
607
|
+
export function isDeprecated(program, type) {
|
|
608
|
+
return program.stateMap(deprecatedKey).has(type);
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Return the deprecated message or undefined if not deprecated
|
|
612
|
+
* @param program Program
|
|
613
|
+
* @param type Type
|
|
614
|
+
*/
|
|
615
|
+
export function getDeprecated(program, type) {
|
|
616
|
+
return program.stateMap(deprecatedKey).get(type);
|
|
617
|
+
}
|
|
618
|
+
const overloadedByKey = createStateSymbol("overloadedByKey");
|
|
619
|
+
const overloadsOperationKey = createStateSymbol("overloadsOperation");
|
|
620
|
+
/**
|
|
621
|
+
* `@overload` - Indicate that the target overloads (specializes) the overloads type.
|
|
622
|
+
* @param context DecoratorContext
|
|
623
|
+
* @param target The specializing operation declaration
|
|
624
|
+
* @param overloadBase The operation to be overloaded.
|
|
625
|
+
*/
|
|
626
|
+
export function $overload(context, target, overloadBase) {
|
|
627
|
+
// Ensure that the overloaded method arguments are a subtype of the original operation.
|
|
628
|
+
const [paramValid, paramDiagnostics] = context.program.checker.isTypeAssignableTo(target.parameters, overloadBase.parameters, target);
|
|
629
|
+
if (!paramValid)
|
|
630
|
+
context.program.reportDiagnostics(paramDiagnostics);
|
|
631
|
+
const [returnTypeValid, returnTypeDiagnostics] = context.program.checker.isTypeAssignableTo(target.returnType, overloadBase.returnType, target);
|
|
632
|
+
if (!returnTypeValid)
|
|
633
|
+
context.program.reportDiagnostics(returnTypeDiagnostics);
|
|
634
|
+
if (!areOperationsInSameContainer(target, overloadBase)) {
|
|
635
|
+
reportDiagnostic(context.program, {
|
|
636
|
+
code: "overload-same-parent",
|
|
637
|
+
target: context.decoratorTarget,
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
// Save the information about the overloaded operation
|
|
641
|
+
context.program.stateMap(overloadsOperationKey).set(target, overloadBase);
|
|
642
|
+
const existingOverloads = getOverloads(context.program, overloadBase) || new Array();
|
|
643
|
+
context.program.stateMap(overloadedByKey).set(overloadBase, existingOverloads.concat(target));
|
|
644
|
+
}
|
|
645
|
+
function areOperationsInSameContainer(op1, op2) {
|
|
646
|
+
return op1.interface || op2.interface
|
|
647
|
+
? op1.interface === op2.interface
|
|
648
|
+
: op1.namespace === op2.namespace;
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Get all operations that are marked as overloads of the given operation
|
|
652
|
+
* @param program Program
|
|
653
|
+
* @param operation Operation
|
|
654
|
+
* @returns An array of operations that overload the given operation.
|
|
655
|
+
*/
|
|
656
|
+
export function getOverloads(program, operation) {
|
|
657
|
+
return program.stateMap(overloadedByKey).get(operation);
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* If the given operation overloads another operation, return that operation.
|
|
661
|
+
* @param program Program
|
|
662
|
+
* @param operation The operation to check for an overload target.
|
|
663
|
+
* @returns The operation this operation overloads, if any.
|
|
664
|
+
*/
|
|
665
|
+
export function getOverloadedOperation(program, operation) {
|
|
666
|
+
return program.stateMap(overloadsOperationKey).get(operation);
|
|
667
|
+
}
|
|
668
|
+
const projectedNameKey = createStateSymbol("projectedNameKey");
|
|
669
|
+
/**
|
|
670
|
+
* `@projectedName` - Indicate that this entity should be renamed according to the given projection.
|
|
671
|
+
* @param context DecoratorContext
|
|
672
|
+
* @param target The that should have a different name.
|
|
673
|
+
* @param projectionName Name of the projection (e.g. "toJson", "toCSharp")
|
|
674
|
+
* @param projectedName Name of the type should have in the scope of the projection specified.
|
|
675
|
+
*/
|
|
676
|
+
export function $projectedName(context, target, projectionName, projectedName) {
|
|
677
|
+
let map = context.program.stateMap(projectedNameKey).get(target);
|
|
678
|
+
if (map === undefined) {
|
|
679
|
+
map = new Map();
|
|
680
|
+
context.program.stateMap(projectedNameKey).set(target, map);
|
|
681
|
+
}
|
|
682
|
+
map.set(projectionName, projectedName);
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* @param program Program
|
|
686
|
+
* @param target Target
|
|
687
|
+
* @returns Map of the projected names for the given entity.
|
|
688
|
+
*/
|
|
689
|
+
export function getProjectedNames(program, target) {
|
|
690
|
+
return program.stateMap(projectedNameKey).get(target);
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Get the projected name of the given entity for the given projection.
|
|
694
|
+
* @param program Program
|
|
695
|
+
* @param target Target
|
|
696
|
+
* @returns Projected name for the given projection
|
|
697
|
+
*/
|
|
698
|
+
export function getProjectedName(program, target, projectionName) {
|
|
699
|
+
var _a;
|
|
700
|
+
return (_a = getProjectedNames(program, target)) === null || _a === void 0 ? void 0 : _a.get(projectionName);
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Get the projected name of the given entity for the given projection.
|
|
704
|
+
* @param program Program
|
|
705
|
+
* @param target Target
|
|
706
|
+
* @returns Projected name for the given projection
|
|
707
|
+
*/
|
|
708
|
+
export function hasProjectedName(program, target, projectionName) {
|
|
709
|
+
var _a, _b;
|
|
710
|
+
return (_b = (_a = getProjectedNames(program, target)) === null || _a === void 0 ? void 0 : _a.has(projectionName)) !== null && _b !== void 0 ? _b : false;
|
|
711
|
+
}
|
|
712
|
+
function validateRange(context, min, max) {
|
|
713
|
+
if (min === undefined || max === undefined) {
|
|
714
|
+
return true;
|
|
715
|
+
}
|
|
716
|
+
if (min > max) {
|
|
717
|
+
reportDiagnostic(context.program, {
|
|
718
|
+
code: "invalid-range",
|
|
719
|
+
format: { start: min.toString(), end: max.toString() },
|
|
720
|
+
target: context.decoratorTarget,
|
|
721
|
+
});
|
|
722
|
+
return false;
|
|
723
|
+
}
|
|
724
|
+
return true;
|
|
725
|
+
}
|
|
726
|
+
const discriminatorKey = createStateSymbol("discriminator");
|
|
727
|
+
export function $discriminator(context, entity, propertyName) {
|
|
728
|
+
const discriminator = { propertyName };
|
|
729
|
+
if (entity.kind === "Union") {
|
|
730
|
+
// we can validate discriminator up front for unions. Models are validated in the accessor as we might not have the reference to all derived types at this time.
|
|
731
|
+
const [, diagnostics] = getDiscriminatedUnion(entity, discriminator);
|
|
732
|
+
if (diagnostics.length > 0) {
|
|
733
|
+
context.program.reportDiagnostics(diagnostics);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
context.program.stateMap(discriminatorKey).set(entity, discriminator);
|
|
738
|
+
}
|
|
739
|
+
export function getDiscriminator(program, entity) {
|
|
740
|
+
return program.stateMap(discriminatorKey).get(entity);
|
|
741
|
+
}
|
|
742
|
+
export function getDiscriminatedTypes(program) {
|
|
743
|
+
return [...program.stateMap(discriminatorKey).entries()];
|
|
744
|
+
}
|
|
745
|
+
//# sourceMappingURL=decorators.js.map
|