@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,2561 @@
|
|
|
1
|
+
import { trim } from "./charcode.js";
|
|
2
|
+
import { compilerAssert } from "./diagnostics.js";
|
|
3
|
+
import { createDiagnostic } from "./messages.js";
|
|
4
|
+
import { createScanner, isComment, isKeyword, isPunctuation, isStatementKeyword, isTrivia, Token, TokenDisplay, TokenFlags, } from "./scanner.js";
|
|
5
|
+
import { IdentifierKind, SyntaxKind, } from "./types.js";
|
|
6
|
+
import { isArray, mutate } from "./util.js";
|
|
7
|
+
/**
|
|
8
|
+
* The fixed set of options for each of the kinds of delimited lists in TypeSpec.
|
|
9
|
+
*/
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
11
|
+
var ListKind;
|
|
12
|
+
(function (ListKind) {
|
|
13
|
+
const PropertiesBase = {
|
|
14
|
+
allowEmpty: true,
|
|
15
|
+
toleratedDelimiterIsValid: true,
|
|
16
|
+
trailingDelimiterIsValid: true,
|
|
17
|
+
allowedStatementKeyword: Token.None,
|
|
18
|
+
};
|
|
19
|
+
ListKind.OperationParameters = {
|
|
20
|
+
...PropertiesBase,
|
|
21
|
+
open: Token.OpenParen,
|
|
22
|
+
close: Token.CloseParen,
|
|
23
|
+
delimiter: Token.Comma,
|
|
24
|
+
toleratedDelimiter: Token.Semicolon,
|
|
25
|
+
};
|
|
26
|
+
ListKind.DecoratorArguments = {
|
|
27
|
+
...ListKind.OperationParameters,
|
|
28
|
+
invalidAnnotationTarget: "expression",
|
|
29
|
+
};
|
|
30
|
+
ListKind.ModelProperties = {
|
|
31
|
+
...PropertiesBase,
|
|
32
|
+
open: Token.OpenBrace,
|
|
33
|
+
close: Token.CloseBrace,
|
|
34
|
+
delimiter: Token.Semicolon,
|
|
35
|
+
toleratedDelimiter: Token.Comma,
|
|
36
|
+
};
|
|
37
|
+
ListKind.InterfaceMembers = {
|
|
38
|
+
...PropertiesBase,
|
|
39
|
+
open: Token.OpenBrace,
|
|
40
|
+
close: Token.CloseBrace,
|
|
41
|
+
delimiter: Token.Semicolon,
|
|
42
|
+
toleratedDelimiter: Token.Comma,
|
|
43
|
+
toleratedDelimiterIsValid: false,
|
|
44
|
+
allowedStatementKeyword: Token.OpKeyword,
|
|
45
|
+
};
|
|
46
|
+
ListKind.UnionVariants = {
|
|
47
|
+
...PropertiesBase,
|
|
48
|
+
open: Token.OpenBrace,
|
|
49
|
+
close: Token.CloseBrace,
|
|
50
|
+
delimiter: Token.Semicolon,
|
|
51
|
+
toleratedDelimiter: Token.Comma,
|
|
52
|
+
toleratedDelimiterIsValid: true,
|
|
53
|
+
};
|
|
54
|
+
ListKind.EnumMembers = {
|
|
55
|
+
...ListKind.ModelProperties,
|
|
56
|
+
};
|
|
57
|
+
const ExpresionsBase = {
|
|
58
|
+
allowEmpty: true,
|
|
59
|
+
delimiter: Token.Comma,
|
|
60
|
+
toleratedDelimiter: Token.Semicolon,
|
|
61
|
+
toleratedDelimiterIsValid: false,
|
|
62
|
+
trailingDelimiterIsValid: false,
|
|
63
|
+
invalidAnnotationTarget: "expression",
|
|
64
|
+
allowedStatementKeyword: Token.None,
|
|
65
|
+
};
|
|
66
|
+
ListKind.TemplateParameters = {
|
|
67
|
+
...ExpresionsBase,
|
|
68
|
+
allowEmpty: false,
|
|
69
|
+
open: Token.LessThan,
|
|
70
|
+
close: Token.GreaterThan,
|
|
71
|
+
invalidAnnotationTarget: "template parameter",
|
|
72
|
+
};
|
|
73
|
+
ListKind.TemplateArguments = {
|
|
74
|
+
...ListKind.TemplateParameters,
|
|
75
|
+
};
|
|
76
|
+
ListKind.CallArguments = {
|
|
77
|
+
...ExpresionsBase,
|
|
78
|
+
allowEmpty: true,
|
|
79
|
+
open: Token.OpenParen,
|
|
80
|
+
close: Token.CloseParen,
|
|
81
|
+
};
|
|
82
|
+
ListKind.Heritage = {
|
|
83
|
+
...ExpresionsBase,
|
|
84
|
+
allowEmpty: false,
|
|
85
|
+
open: Token.None,
|
|
86
|
+
close: Token.None,
|
|
87
|
+
};
|
|
88
|
+
ListKind.Tuple = {
|
|
89
|
+
...ExpresionsBase,
|
|
90
|
+
allowEmpty: true,
|
|
91
|
+
open: Token.OpenBracket,
|
|
92
|
+
close: Token.CloseBracket,
|
|
93
|
+
};
|
|
94
|
+
ListKind.FunctionParameters = {
|
|
95
|
+
...ExpresionsBase,
|
|
96
|
+
allowEmpty: true,
|
|
97
|
+
open: Token.OpenParen,
|
|
98
|
+
close: Token.CloseParen,
|
|
99
|
+
invalidAnnotationTarget: "expression",
|
|
100
|
+
};
|
|
101
|
+
ListKind.ProjectionExpression = {
|
|
102
|
+
...ExpresionsBase,
|
|
103
|
+
allowEmpty: true,
|
|
104
|
+
open: Token.OpenParen,
|
|
105
|
+
close: Token.CloseParen,
|
|
106
|
+
};
|
|
107
|
+
ListKind.ProjectionParameter = {
|
|
108
|
+
...ExpresionsBase,
|
|
109
|
+
allowEmpty: true,
|
|
110
|
+
open: Token.OpenParen,
|
|
111
|
+
close: Token.CloseParen,
|
|
112
|
+
};
|
|
113
|
+
})(ListKind || (ListKind = {}));
|
|
114
|
+
export function parse(code, options = {}) {
|
|
115
|
+
const parser = createParser(code, options);
|
|
116
|
+
return parser.parseTypeSpecScript();
|
|
117
|
+
}
|
|
118
|
+
export function parseStandaloneTypeReference(code) {
|
|
119
|
+
const parser = createParser(code);
|
|
120
|
+
const node = parser.parseStandaloneReferenceExpression();
|
|
121
|
+
return [node, parser.parseDiagnostics];
|
|
122
|
+
}
|
|
123
|
+
function createParser(code, options = {}) {
|
|
124
|
+
let parseErrorInNextFinishedNode = false;
|
|
125
|
+
let previousTokenEnd = -1;
|
|
126
|
+
let realPositionOfLastError = -1;
|
|
127
|
+
let missingIdentifierCounter = 0;
|
|
128
|
+
let treePrintable = true;
|
|
129
|
+
let newLineIsTrivia = true;
|
|
130
|
+
let currentMode = 0 /* ParseMode.Syntax */;
|
|
131
|
+
const parseDiagnostics = [];
|
|
132
|
+
const scanner = createScanner(code, reportDiagnostic);
|
|
133
|
+
const comments = [];
|
|
134
|
+
let docRanges = [];
|
|
135
|
+
nextToken();
|
|
136
|
+
return {
|
|
137
|
+
parseDiagnostics,
|
|
138
|
+
parseTypeSpecScript,
|
|
139
|
+
parseStandaloneReferenceExpression,
|
|
140
|
+
};
|
|
141
|
+
function parseTypeSpecScript() {
|
|
142
|
+
const statements = parseTypeSpecScriptItemList();
|
|
143
|
+
return {
|
|
144
|
+
kind: SyntaxKind.TypeSpecScript,
|
|
145
|
+
statements,
|
|
146
|
+
file: scanner.file,
|
|
147
|
+
id: {
|
|
148
|
+
kind: SyntaxKind.Identifier,
|
|
149
|
+
sv: scanner.file.path,
|
|
150
|
+
pos: 0,
|
|
151
|
+
end: 0,
|
|
152
|
+
flags: 8 /* NodeFlags.Synthetic */,
|
|
153
|
+
},
|
|
154
|
+
namespaces: [],
|
|
155
|
+
usings: [],
|
|
156
|
+
locals: undefined,
|
|
157
|
+
inScopeNamespaces: [],
|
|
158
|
+
parseDiagnostics,
|
|
159
|
+
comments,
|
|
160
|
+
printable: treePrintable,
|
|
161
|
+
parseOptions: options,
|
|
162
|
+
...finishNode(0),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function parseTypeSpecScriptItemList() {
|
|
166
|
+
const stmts = [];
|
|
167
|
+
let seenBlocklessNs = false;
|
|
168
|
+
let seenDecl = false;
|
|
169
|
+
let seenUsing = false;
|
|
170
|
+
while (token() !== Token.EndOfFile) {
|
|
171
|
+
const [pos, docs] = parseDocList();
|
|
172
|
+
const directives = parseDirectiveList();
|
|
173
|
+
const decorators = parseDecoratorList();
|
|
174
|
+
const tok = token();
|
|
175
|
+
let item;
|
|
176
|
+
switch (tok) {
|
|
177
|
+
case Token.AtAt:
|
|
178
|
+
reportInvalidDecorators(decorators, "augment decorator statement");
|
|
179
|
+
item = parseAugmentDecorator();
|
|
180
|
+
break;
|
|
181
|
+
case Token.ImportKeyword:
|
|
182
|
+
reportInvalidDecorators(decorators, "import statement");
|
|
183
|
+
item = parseImportStatement();
|
|
184
|
+
break;
|
|
185
|
+
case Token.ModelKeyword:
|
|
186
|
+
item = parseModelStatement(pos, decorators);
|
|
187
|
+
break;
|
|
188
|
+
case Token.ScalarKeyword:
|
|
189
|
+
item = parseScalarStatement(pos, decorators);
|
|
190
|
+
break;
|
|
191
|
+
case Token.NamespaceKeyword:
|
|
192
|
+
item = parseNamespaceStatement(pos, decorators);
|
|
193
|
+
break;
|
|
194
|
+
case Token.InterfaceKeyword:
|
|
195
|
+
item = parseInterfaceStatement(pos, decorators);
|
|
196
|
+
break;
|
|
197
|
+
case Token.UnionKeyword:
|
|
198
|
+
item = parseUnionStatement(pos, decorators);
|
|
199
|
+
break;
|
|
200
|
+
case Token.OpKeyword:
|
|
201
|
+
item = parseOperationStatement(pos, decorators);
|
|
202
|
+
break;
|
|
203
|
+
case Token.EnumKeyword:
|
|
204
|
+
item = parseEnumStatement(pos, decorators);
|
|
205
|
+
break;
|
|
206
|
+
case Token.AliasKeyword:
|
|
207
|
+
reportInvalidDecorators(decorators, "alias statement");
|
|
208
|
+
item = parseAliasStatement(pos);
|
|
209
|
+
break;
|
|
210
|
+
case Token.UsingKeyword:
|
|
211
|
+
reportInvalidDecorators(decorators, "using statement");
|
|
212
|
+
item = parseUsingStatement(pos);
|
|
213
|
+
break;
|
|
214
|
+
case Token.ProjectionKeyword:
|
|
215
|
+
reportInvalidDecorators(decorators, "projection statement");
|
|
216
|
+
item = parseProjectionStatement(pos);
|
|
217
|
+
break;
|
|
218
|
+
case Token.Semicolon:
|
|
219
|
+
reportInvalidDecorators(decorators, "empty statement");
|
|
220
|
+
item = parseEmptyStatement(pos);
|
|
221
|
+
break;
|
|
222
|
+
// Start of declaration with modifiers
|
|
223
|
+
case Token.ExternKeyword:
|
|
224
|
+
case Token.FnKeyword:
|
|
225
|
+
case Token.DecKeyword:
|
|
226
|
+
item = parseDeclaration(pos);
|
|
227
|
+
break;
|
|
228
|
+
default:
|
|
229
|
+
item = parseInvalidStatement(pos, decorators);
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
mutate(item).directives = directives;
|
|
233
|
+
mutate(item).docs = docs;
|
|
234
|
+
if (isBlocklessNamespace(item)) {
|
|
235
|
+
if (seenBlocklessNs) {
|
|
236
|
+
error({ code: "multiple-blockless-namespace", target: item });
|
|
237
|
+
}
|
|
238
|
+
if (seenDecl) {
|
|
239
|
+
error({ code: "blockless-namespace-first", target: item });
|
|
240
|
+
}
|
|
241
|
+
seenBlocklessNs = true;
|
|
242
|
+
}
|
|
243
|
+
else if (item.kind === SyntaxKind.ImportStatement) {
|
|
244
|
+
if (seenDecl || seenBlocklessNs || seenUsing) {
|
|
245
|
+
error({ code: "import-first", target: item });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else if (item.kind === SyntaxKind.UsingStatement) {
|
|
249
|
+
seenUsing = true;
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
seenDecl = true;
|
|
253
|
+
}
|
|
254
|
+
stmts.push(item);
|
|
255
|
+
}
|
|
256
|
+
return stmts;
|
|
257
|
+
}
|
|
258
|
+
function parseStatementList() {
|
|
259
|
+
const stmts = [];
|
|
260
|
+
while (token() !== Token.CloseBrace) {
|
|
261
|
+
const [pos, docs] = parseDocList();
|
|
262
|
+
const directives = parseDirectiveList();
|
|
263
|
+
const decorators = parseDecoratorList();
|
|
264
|
+
const tok = token();
|
|
265
|
+
let item;
|
|
266
|
+
switch (tok) {
|
|
267
|
+
case Token.AtAt:
|
|
268
|
+
reportInvalidDecorators(decorators, "augment decorator statement");
|
|
269
|
+
item = parseAugmentDecorator();
|
|
270
|
+
break;
|
|
271
|
+
case Token.ImportKeyword:
|
|
272
|
+
reportInvalidDecorators(decorators, "import statement");
|
|
273
|
+
item = parseImportStatement();
|
|
274
|
+
error({ code: "import-first", messageId: "topLevel", target: item });
|
|
275
|
+
break;
|
|
276
|
+
case Token.ModelKeyword:
|
|
277
|
+
item = parseModelStatement(pos, decorators);
|
|
278
|
+
break;
|
|
279
|
+
case Token.ScalarKeyword:
|
|
280
|
+
item = parseScalarStatement(pos, decorators);
|
|
281
|
+
break;
|
|
282
|
+
case Token.NamespaceKeyword:
|
|
283
|
+
const ns = parseNamespaceStatement(pos, decorators);
|
|
284
|
+
if (!Array.isArray(ns.statements)) {
|
|
285
|
+
error({ code: "blockless-namespace-first", messageId: "topLevel", target: ns });
|
|
286
|
+
}
|
|
287
|
+
item = ns;
|
|
288
|
+
break;
|
|
289
|
+
case Token.InterfaceKeyword:
|
|
290
|
+
item = parseInterfaceStatement(pos, decorators);
|
|
291
|
+
break;
|
|
292
|
+
case Token.UnionKeyword:
|
|
293
|
+
item = parseUnionStatement(pos, decorators);
|
|
294
|
+
break;
|
|
295
|
+
case Token.OpKeyword:
|
|
296
|
+
item = parseOperationStatement(pos, decorators);
|
|
297
|
+
break;
|
|
298
|
+
case Token.EnumKeyword:
|
|
299
|
+
item = parseEnumStatement(pos, decorators);
|
|
300
|
+
break;
|
|
301
|
+
case Token.AliasKeyword:
|
|
302
|
+
reportInvalidDecorators(decorators, "alias statement");
|
|
303
|
+
item = parseAliasStatement(pos);
|
|
304
|
+
break;
|
|
305
|
+
case Token.UsingKeyword:
|
|
306
|
+
reportInvalidDecorators(decorators, "using statement");
|
|
307
|
+
item = parseUsingStatement(pos);
|
|
308
|
+
break;
|
|
309
|
+
case Token.ExternKeyword:
|
|
310
|
+
case Token.FnKeyword:
|
|
311
|
+
case Token.DecKeyword:
|
|
312
|
+
item = parseDeclaration(pos);
|
|
313
|
+
break;
|
|
314
|
+
case Token.ProjectionKeyword:
|
|
315
|
+
reportInvalidDecorators(decorators, "project statement");
|
|
316
|
+
item = parseProjectionStatement(pos);
|
|
317
|
+
break;
|
|
318
|
+
case Token.EndOfFile:
|
|
319
|
+
parseExpected(Token.CloseBrace);
|
|
320
|
+
return stmts;
|
|
321
|
+
case Token.Semicolon:
|
|
322
|
+
reportInvalidDecorators(decorators, "empty statement");
|
|
323
|
+
item = parseEmptyStatement(pos);
|
|
324
|
+
break;
|
|
325
|
+
default:
|
|
326
|
+
item = parseInvalidStatement(pos, decorators);
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
mutate(item).directives = directives;
|
|
330
|
+
mutate(item).docs = docs;
|
|
331
|
+
stmts.push(item);
|
|
332
|
+
}
|
|
333
|
+
return stmts;
|
|
334
|
+
}
|
|
335
|
+
function parseDecoratorList() {
|
|
336
|
+
const decorators = [];
|
|
337
|
+
while (token() === Token.At) {
|
|
338
|
+
decorators.push(parseDecoratorExpression());
|
|
339
|
+
}
|
|
340
|
+
return decorators;
|
|
341
|
+
}
|
|
342
|
+
function parseDirectiveList() {
|
|
343
|
+
const directives = [];
|
|
344
|
+
while (token() === Token.Hash) {
|
|
345
|
+
directives.push(parseDirectiveExpression());
|
|
346
|
+
}
|
|
347
|
+
return directives;
|
|
348
|
+
}
|
|
349
|
+
function parseNamespaceStatement(pos, decorators) {
|
|
350
|
+
parseExpected(Token.NamespaceKeyword);
|
|
351
|
+
let currentName = parseIdentifierOrMemberExpression();
|
|
352
|
+
const nsSegments = [];
|
|
353
|
+
while (currentName.kind !== SyntaxKind.Identifier) {
|
|
354
|
+
nsSegments.push(currentName.id);
|
|
355
|
+
currentName = currentName.base;
|
|
356
|
+
}
|
|
357
|
+
nsSegments.push(currentName);
|
|
358
|
+
const nextTok = parseExpectedOneOf(Token.Semicolon, Token.OpenBrace);
|
|
359
|
+
let statements;
|
|
360
|
+
if (nextTok === Token.OpenBrace) {
|
|
361
|
+
statements = parseStatementList();
|
|
362
|
+
parseExpected(Token.CloseBrace);
|
|
363
|
+
}
|
|
364
|
+
let outerNs = {
|
|
365
|
+
kind: SyntaxKind.NamespaceStatement,
|
|
366
|
+
decorators,
|
|
367
|
+
id: nsSegments[0],
|
|
368
|
+
locals: undefined,
|
|
369
|
+
statements,
|
|
370
|
+
...finishNode(pos),
|
|
371
|
+
};
|
|
372
|
+
for (let i = 1; i < nsSegments.length; i++) {
|
|
373
|
+
outerNs = {
|
|
374
|
+
kind: SyntaxKind.NamespaceStatement,
|
|
375
|
+
decorators: [],
|
|
376
|
+
id: nsSegments[i],
|
|
377
|
+
statements: outerNs,
|
|
378
|
+
locals: undefined,
|
|
379
|
+
...finishNode(pos),
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
return outerNs;
|
|
383
|
+
}
|
|
384
|
+
function parseInterfaceStatement(pos, decorators) {
|
|
385
|
+
parseExpected(Token.InterfaceKeyword);
|
|
386
|
+
const id = parseIdentifier();
|
|
387
|
+
const templateParameters = parseTemplateParameterList();
|
|
388
|
+
let extendList = [];
|
|
389
|
+
if (token() === Token.ExtendsKeyword) {
|
|
390
|
+
nextToken();
|
|
391
|
+
extendList = parseList(ListKind.Heritage, parseReferenceExpression);
|
|
392
|
+
}
|
|
393
|
+
else if (token() === Token.Identifier) {
|
|
394
|
+
error({ code: "token-expected", format: { token: "'extends' or '{'" } });
|
|
395
|
+
nextToken();
|
|
396
|
+
}
|
|
397
|
+
const operations = parseList(ListKind.InterfaceMembers, (pos, decorators) => parseOperationStatement(pos, decorators, true));
|
|
398
|
+
return {
|
|
399
|
+
kind: SyntaxKind.InterfaceStatement,
|
|
400
|
+
id,
|
|
401
|
+
templateParameters,
|
|
402
|
+
operations,
|
|
403
|
+
extends: extendList,
|
|
404
|
+
decorators,
|
|
405
|
+
...finishNode(pos),
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
function parseTemplateParameterList() {
|
|
409
|
+
const list = parseOptionalList(ListKind.TemplateParameters, parseTemplateParameter);
|
|
410
|
+
let setDefault = false;
|
|
411
|
+
for (const item of list) {
|
|
412
|
+
if (!item.default && setDefault) {
|
|
413
|
+
error({ code: "default-required", target: item });
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
if (item.default) {
|
|
417
|
+
setDefault = true;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return list;
|
|
421
|
+
}
|
|
422
|
+
function parseUnionStatement(pos, decorators) {
|
|
423
|
+
parseExpected(Token.UnionKeyword);
|
|
424
|
+
const id = parseIdentifier();
|
|
425
|
+
const templateParameters = parseTemplateParameterList();
|
|
426
|
+
const options = parseList(ListKind.UnionVariants, parseUnionVariant);
|
|
427
|
+
return {
|
|
428
|
+
kind: SyntaxKind.UnionStatement,
|
|
429
|
+
id,
|
|
430
|
+
templateParameters,
|
|
431
|
+
decorators,
|
|
432
|
+
options,
|
|
433
|
+
...finishNode(pos),
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
function parseUnionVariant(pos, decorators) {
|
|
437
|
+
const id = parseIdentifier({
|
|
438
|
+
message: "property",
|
|
439
|
+
allowStringLiteral: true,
|
|
440
|
+
});
|
|
441
|
+
parseExpected(Token.Colon);
|
|
442
|
+
const value = parseExpression();
|
|
443
|
+
return {
|
|
444
|
+
kind: SyntaxKind.UnionVariant,
|
|
445
|
+
id,
|
|
446
|
+
value,
|
|
447
|
+
decorators,
|
|
448
|
+
...finishNode(pos),
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
function parseUsingStatement(pos) {
|
|
452
|
+
parseExpected(Token.UsingKeyword);
|
|
453
|
+
const name = parseIdentifierOrMemberExpression(undefined, true);
|
|
454
|
+
parseExpected(Token.Semicolon);
|
|
455
|
+
return {
|
|
456
|
+
kind: SyntaxKind.UsingStatement,
|
|
457
|
+
name,
|
|
458
|
+
...finishNode(pos),
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
function parseOperationStatement(pos, decorators, inInterface) {
|
|
462
|
+
if (inInterface) {
|
|
463
|
+
parseOptional(Token.OpKeyword);
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
parseExpected(Token.OpKeyword);
|
|
467
|
+
}
|
|
468
|
+
const id = parseIdentifier();
|
|
469
|
+
const templateParameters = parseTemplateParameterList();
|
|
470
|
+
// Make sure the next token is one that is expected
|
|
471
|
+
const token = expectTokenIsOneOf(Token.OpenParen, Token.IsKeyword);
|
|
472
|
+
// Check if we're parsing a declaration or reuse of another operation
|
|
473
|
+
let signature;
|
|
474
|
+
const signaturePos = tokenPos();
|
|
475
|
+
if (token === Token.OpenParen) {
|
|
476
|
+
const parameters = parseOperationParameters();
|
|
477
|
+
parseExpected(Token.Colon);
|
|
478
|
+
const returnType = parseExpression();
|
|
479
|
+
signature = {
|
|
480
|
+
kind: SyntaxKind.OperationSignatureDeclaration,
|
|
481
|
+
parameters,
|
|
482
|
+
returnType,
|
|
483
|
+
...finishNode(signaturePos),
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
parseExpected(Token.IsKeyword);
|
|
488
|
+
const opReference = parseReferenceExpression();
|
|
489
|
+
signature = {
|
|
490
|
+
kind: SyntaxKind.OperationSignatureReference,
|
|
491
|
+
baseOperation: opReference,
|
|
492
|
+
...finishNode(signaturePos),
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
// The interface parser handles semicolon parsing between statements
|
|
496
|
+
if (!inInterface) {
|
|
497
|
+
parseExpected(Token.Semicolon);
|
|
498
|
+
}
|
|
499
|
+
return {
|
|
500
|
+
kind: SyntaxKind.OperationStatement,
|
|
501
|
+
id,
|
|
502
|
+
templateParameters,
|
|
503
|
+
signature,
|
|
504
|
+
decorators,
|
|
505
|
+
...finishNode(pos),
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function parseOperationParameters() {
|
|
509
|
+
const pos = tokenPos();
|
|
510
|
+
const properties = parseList(ListKind.OperationParameters, parseModelPropertyOrSpread);
|
|
511
|
+
const parameters = {
|
|
512
|
+
kind: SyntaxKind.ModelExpression,
|
|
513
|
+
properties,
|
|
514
|
+
...finishNode(pos),
|
|
515
|
+
};
|
|
516
|
+
return parameters;
|
|
517
|
+
}
|
|
518
|
+
function parseModelStatement(pos, decorators) {
|
|
519
|
+
parseExpected(Token.ModelKeyword);
|
|
520
|
+
const id = parseIdentifier();
|
|
521
|
+
const templateParameters = parseTemplateParameterList();
|
|
522
|
+
expectTokenIsOneOf(Token.OpenBrace, Token.Equals, Token.ExtendsKeyword, Token.IsKeyword);
|
|
523
|
+
const optionalExtends = parseOptionalModelExtends();
|
|
524
|
+
const optionalIs = optionalExtends ? undefined : parseOptionalModelIs();
|
|
525
|
+
let properties = [];
|
|
526
|
+
if (optionalIs) {
|
|
527
|
+
const tok = expectTokenIsOneOf(Token.Semicolon, Token.OpenBrace);
|
|
528
|
+
if (tok === Token.Semicolon) {
|
|
529
|
+
nextToken();
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
properties = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
properties = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
|
|
537
|
+
}
|
|
538
|
+
return {
|
|
539
|
+
kind: SyntaxKind.ModelStatement,
|
|
540
|
+
id,
|
|
541
|
+
extends: optionalExtends,
|
|
542
|
+
is: optionalIs,
|
|
543
|
+
templateParameters,
|
|
544
|
+
decorators,
|
|
545
|
+
properties,
|
|
546
|
+
...finishNode(pos),
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
function parseOptionalModelExtends() {
|
|
550
|
+
if (parseOptional(Token.ExtendsKeyword)) {
|
|
551
|
+
return parseExpression();
|
|
552
|
+
}
|
|
553
|
+
return undefined;
|
|
554
|
+
}
|
|
555
|
+
function parseOptionalModelIs() {
|
|
556
|
+
if (parseOptional(Token.IsKeyword)) {
|
|
557
|
+
return parseExpression();
|
|
558
|
+
}
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
function parseTemplateParameter() {
|
|
562
|
+
const pos = tokenPos();
|
|
563
|
+
const id = parseIdentifier();
|
|
564
|
+
let constraint;
|
|
565
|
+
if (parseOptional(Token.ExtendsKeyword)) {
|
|
566
|
+
constraint = parseExpression();
|
|
567
|
+
}
|
|
568
|
+
let def;
|
|
569
|
+
if (parseOptional(Token.Equals)) {
|
|
570
|
+
def = parseExpression();
|
|
571
|
+
}
|
|
572
|
+
return {
|
|
573
|
+
kind: SyntaxKind.TemplateParameterDeclaration,
|
|
574
|
+
id,
|
|
575
|
+
constraint,
|
|
576
|
+
default: def,
|
|
577
|
+
...finishNode(pos),
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
function parseModelPropertyOrSpread(pos, decorators) {
|
|
581
|
+
return token() === Token.Ellipsis
|
|
582
|
+
? parseModelSpreadProperty(pos, decorators)
|
|
583
|
+
: parseModelProperty(pos, decorators);
|
|
584
|
+
}
|
|
585
|
+
function parseModelSpreadProperty(pos, decorators) {
|
|
586
|
+
parseExpected(Token.Ellipsis);
|
|
587
|
+
reportInvalidDecorators(decorators, "spread property");
|
|
588
|
+
// This could be broadened to allow any type expression
|
|
589
|
+
const target = parseReferenceExpression();
|
|
590
|
+
return {
|
|
591
|
+
kind: SyntaxKind.ModelSpreadProperty,
|
|
592
|
+
target,
|
|
593
|
+
...finishNode(pos),
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
function parseModelProperty(pos, decorators) {
|
|
597
|
+
const id = parseIdentifier({
|
|
598
|
+
message: "property",
|
|
599
|
+
allowStringLiteral: true,
|
|
600
|
+
});
|
|
601
|
+
const optional = parseOptional(Token.Question);
|
|
602
|
+
parseExpected(Token.Colon);
|
|
603
|
+
const value = parseExpression();
|
|
604
|
+
const hasDefault = parseOptional(Token.Equals);
|
|
605
|
+
if (hasDefault && !optional) {
|
|
606
|
+
error({ code: "default-optional" });
|
|
607
|
+
}
|
|
608
|
+
const defaultValue = hasDefault ? parseExpression() : undefined;
|
|
609
|
+
return {
|
|
610
|
+
kind: SyntaxKind.ModelProperty,
|
|
611
|
+
id,
|
|
612
|
+
decorators,
|
|
613
|
+
value,
|
|
614
|
+
optional,
|
|
615
|
+
default: defaultValue,
|
|
616
|
+
...finishNode(pos),
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
function parseScalarStatement(pos, decorators) {
|
|
620
|
+
parseExpected(Token.ScalarKeyword);
|
|
621
|
+
const id = parseIdentifier();
|
|
622
|
+
const templateParameters = parseTemplateParameterList();
|
|
623
|
+
const optionalExtends = parseOptionalScalarExtends();
|
|
624
|
+
return {
|
|
625
|
+
kind: SyntaxKind.ScalarStatement,
|
|
626
|
+
id,
|
|
627
|
+
templateParameters,
|
|
628
|
+
extends: optionalExtends,
|
|
629
|
+
decorators,
|
|
630
|
+
...finishNode(pos),
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
function parseOptionalScalarExtends() {
|
|
634
|
+
if (parseOptional(Token.ExtendsKeyword)) {
|
|
635
|
+
return parseReferenceExpression();
|
|
636
|
+
}
|
|
637
|
+
return undefined;
|
|
638
|
+
}
|
|
639
|
+
function parseEnumStatement(pos, decorators) {
|
|
640
|
+
parseExpected(Token.EnumKeyword);
|
|
641
|
+
const id = parseIdentifier();
|
|
642
|
+
const members = parseList(ListKind.EnumMembers, parseEnumMemberOrSpread);
|
|
643
|
+
return {
|
|
644
|
+
kind: SyntaxKind.EnumStatement,
|
|
645
|
+
id,
|
|
646
|
+
decorators,
|
|
647
|
+
members,
|
|
648
|
+
...finishNode(pos),
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
function parseEnumMemberOrSpread(pos, decorators) {
|
|
652
|
+
return token() === Token.Ellipsis
|
|
653
|
+
? parseEnumSpreadMember(pos, decorators)
|
|
654
|
+
: parseEnumMember(pos, decorators);
|
|
655
|
+
}
|
|
656
|
+
function parseEnumSpreadMember(pos, decorators) {
|
|
657
|
+
parseExpected(Token.Ellipsis);
|
|
658
|
+
reportInvalidDecorators(decorators, "spread enum");
|
|
659
|
+
const target = parseReferenceExpression();
|
|
660
|
+
return {
|
|
661
|
+
kind: SyntaxKind.EnumSpreadMember,
|
|
662
|
+
target,
|
|
663
|
+
...finishNode(pos),
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
function parseEnumMember(pos, decorators) {
|
|
667
|
+
const id = parseIdentifier({
|
|
668
|
+
message: "enumMember",
|
|
669
|
+
allowStringLiteral: true,
|
|
670
|
+
});
|
|
671
|
+
let value;
|
|
672
|
+
if (parseOptional(Token.Colon)) {
|
|
673
|
+
const expr = parseExpression();
|
|
674
|
+
if (expr.kind === SyntaxKind.StringLiteral || expr.kind === SyntaxKind.NumericLiteral) {
|
|
675
|
+
value = expr;
|
|
676
|
+
}
|
|
677
|
+
else if (expr.kind === SyntaxKind.TypeReference &&
|
|
678
|
+
expr.target.flags & 2 /* NodeFlags.ThisNodeHasError */) {
|
|
679
|
+
parseErrorInNextFinishedNode = true;
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
error({ code: "token-expected", messageId: "numericOrStringLiteral", target: expr });
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
return {
|
|
686
|
+
kind: SyntaxKind.EnumMember,
|
|
687
|
+
id,
|
|
688
|
+
value,
|
|
689
|
+
decorators,
|
|
690
|
+
...finishNode(pos),
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
function parseAliasStatement(pos) {
|
|
694
|
+
parseExpected(Token.AliasKeyword);
|
|
695
|
+
const id = parseIdentifier();
|
|
696
|
+
const templateParameters = parseTemplateParameterList();
|
|
697
|
+
parseExpected(Token.Equals);
|
|
698
|
+
const value = parseExpression();
|
|
699
|
+
parseExpected(Token.Semicolon);
|
|
700
|
+
return {
|
|
701
|
+
kind: SyntaxKind.AliasStatement,
|
|
702
|
+
id,
|
|
703
|
+
templateParameters,
|
|
704
|
+
value,
|
|
705
|
+
...finishNode(pos),
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
function parseExpression() {
|
|
709
|
+
return parseUnionExpressionOrHigher();
|
|
710
|
+
}
|
|
711
|
+
function parseUnionExpressionOrHigher() {
|
|
712
|
+
const pos = tokenPos();
|
|
713
|
+
parseOptional(Token.Bar);
|
|
714
|
+
const node = parseIntersectionExpressionOrHigher();
|
|
715
|
+
if (token() !== Token.Bar) {
|
|
716
|
+
return node;
|
|
717
|
+
}
|
|
718
|
+
const options = [node];
|
|
719
|
+
while (parseOptional(Token.Bar)) {
|
|
720
|
+
const expr = parseIntersectionExpressionOrHigher();
|
|
721
|
+
options.push(expr);
|
|
722
|
+
}
|
|
723
|
+
return {
|
|
724
|
+
kind: SyntaxKind.UnionExpression,
|
|
725
|
+
options,
|
|
726
|
+
...finishNode(pos),
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
function parseIntersectionExpressionOrHigher() {
|
|
730
|
+
const pos = tokenPos();
|
|
731
|
+
parseOptional(Token.Ampersand);
|
|
732
|
+
const node = parseArrayExpressionOrHigher();
|
|
733
|
+
if (token() !== Token.Ampersand) {
|
|
734
|
+
return node;
|
|
735
|
+
}
|
|
736
|
+
const options = [node];
|
|
737
|
+
while (parseOptional(Token.Ampersand)) {
|
|
738
|
+
const expr = parseArrayExpressionOrHigher();
|
|
739
|
+
options.push(expr);
|
|
740
|
+
}
|
|
741
|
+
return {
|
|
742
|
+
kind: SyntaxKind.IntersectionExpression,
|
|
743
|
+
options,
|
|
744
|
+
...finishNode(pos),
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
function parseArrayExpressionOrHigher() {
|
|
748
|
+
const pos = tokenPos();
|
|
749
|
+
let expr = parsePrimaryExpression();
|
|
750
|
+
while (parseOptional(Token.OpenBracket)) {
|
|
751
|
+
parseExpected(Token.CloseBracket);
|
|
752
|
+
expr = {
|
|
753
|
+
kind: SyntaxKind.ArrayExpression,
|
|
754
|
+
elementType: expr,
|
|
755
|
+
...finishNode(pos),
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
return expr;
|
|
759
|
+
}
|
|
760
|
+
function parseStandaloneReferenceExpression() {
|
|
761
|
+
const expr = parseReferenceExpression();
|
|
762
|
+
if (parseDiagnostics.length === 0 && token() !== Token.EndOfFile) {
|
|
763
|
+
error({ code: "token-expected", messageId: "unexpected", format: { token: Token[token()] } });
|
|
764
|
+
}
|
|
765
|
+
return expr;
|
|
766
|
+
}
|
|
767
|
+
function parseReferenceExpression(message) {
|
|
768
|
+
const pos = tokenPos();
|
|
769
|
+
const target = parseIdentifierOrMemberExpression(message);
|
|
770
|
+
const args = parseOptionalList(ListKind.TemplateArguments, parseExpression);
|
|
771
|
+
return {
|
|
772
|
+
kind: SyntaxKind.TypeReference,
|
|
773
|
+
target,
|
|
774
|
+
arguments: args,
|
|
775
|
+
...finishNode(pos),
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
function parseAugmentDecorator() {
|
|
779
|
+
const pos = tokenPos();
|
|
780
|
+
parseExpected(Token.AtAt);
|
|
781
|
+
// Error recovery: false arg here means don't treat a keyword as an
|
|
782
|
+
// identifier. We want to parse `@ model Foo` as invalid decorator
|
|
783
|
+
// `@<missing identifier>` applied to `model Foo`, and not as `@model`
|
|
784
|
+
// applied to invalid statement `Foo`.
|
|
785
|
+
const target = parseIdentifierOrMemberExpression(undefined, false);
|
|
786
|
+
const args = parseOptionalList(ListKind.DecoratorArguments, parseExpression);
|
|
787
|
+
if (args.length === 0) {
|
|
788
|
+
error({ code: "augment-decorator-target" });
|
|
789
|
+
return {
|
|
790
|
+
kind: SyntaxKind.AugmentDecoratorStatement,
|
|
791
|
+
target,
|
|
792
|
+
targetType: {
|
|
793
|
+
kind: SyntaxKind.TypeReference,
|
|
794
|
+
target: createMissingIdentifier(),
|
|
795
|
+
arguments: [],
|
|
796
|
+
...finishNode(pos),
|
|
797
|
+
},
|
|
798
|
+
arguments: [],
|
|
799
|
+
...finishNode(pos),
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
let [targetEntity, ...decoratorArgs] = args;
|
|
803
|
+
if (targetEntity.kind !== SyntaxKind.TypeReference) {
|
|
804
|
+
error({ code: "augment-decorator-target", target: targetEntity });
|
|
805
|
+
targetEntity = {
|
|
806
|
+
kind: SyntaxKind.TypeReference,
|
|
807
|
+
target: createMissingIdentifier(),
|
|
808
|
+
arguments: [],
|
|
809
|
+
...finishNode(pos),
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
return {
|
|
813
|
+
kind: SyntaxKind.AugmentDecoratorStatement,
|
|
814
|
+
target,
|
|
815
|
+
targetType: targetEntity,
|
|
816
|
+
arguments: decoratorArgs,
|
|
817
|
+
...finishNode(pos),
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
function parseImportStatement() {
|
|
821
|
+
const pos = tokenPos();
|
|
822
|
+
parseExpected(Token.ImportKeyword);
|
|
823
|
+
const path = parseStringLiteral();
|
|
824
|
+
parseExpected(Token.Semicolon);
|
|
825
|
+
return {
|
|
826
|
+
kind: SyntaxKind.ImportStatement,
|
|
827
|
+
path,
|
|
828
|
+
...finishNode(pos),
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
function parseDecoratorExpression() {
|
|
832
|
+
const pos = tokenPos();
|
|
833
|
+
parseExpected(Token.At);
|
|
834
|
+
// Error recovery: false arg here means don't treat a keyword as an
|
|
835
|
+
// identifier. We want to parse `@ model Foo` as invalid decorator
|
|
836
|
+
// `@<missing identifier>` applied to `model Foo`, and not as `@model`
|
|
837
|
+
// applied to invalid statement `Foo`.
|
|
838
|
+
const target = parseIdentifierOrMemberExpression(undefined, false);
|
|
839
|
+
const args = parseOptionalList(ListKind.DecoratorArguments, parseExpression);
|
|
840
|
+
return {
|
|
841
|
+
kind: SyntaxKind.DecoratorExpression,
|
|
842
|
+
arguments: args,
|
|
843
|
+
target,
|
|
844
|
+
...finishNode(pos),
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
function parseDirectiveExpression() {
|
|
848
|
+
const pos = tokenPos();
|
|
849
|
+
parseExpected(Token.Hash);
|
|
850
|
+
const target = parseIdentifier();
|
|
851
|
+
if (target.sv !== "suppress") {
|
|
852
|
+
error({
|
|
853
|
+
code: "unknown-directive",
|
|
854
|
+
format: { id: target.sv },
|
|
855
|
+
target: { pos, end: pos + target.sv.length },
|
|
856
|
+
printable: true,
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
// The newline will mark the end of the directive.
|
|
860
|
+
newLineIsTrivia = false;
|
|
861
|
+
const args = [];
|
|
862
|
+
while (token() !== Token.NewLine && token() !== Token.EndOfFile) {
|
|
863
|
+
const param = parseDirectiveParameter();
|
|
864
|
+
if (param) {
|
|
865
|
+
args.push(param);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
newLineIsTrivia = true;
|
|
869
|
+
nextToken();
|
|
870
|
+
return {
|
|
871
|
+
kind: SyntaxKind.DirectiveExpression,
|
|
872
|
+
arguments: args,
|
|
873
|
+
target,
|
|
874
|
+
...finishNode(pos),
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
function parseDirectiveParameter() {
|
|
878
|
+
switch (token()) {
|
|
879
|
+
case Token.Identifier:
|
|
880
|
+
return parseIdentifier();
|
|
881
|
+
case Token.StringLiteral:
|
|
882
|
+
return parseStringLiteral();
|
|
883
|
+
default:
|
|
884
|
+
error({
|
|
885
|
+
code: "token-expected",
|
|
886
|
+
messageId: "unexpected",
|
|
887
|
+
format: { token: Token[token()] },
|
|
888
|
+
});
|
|
889
|
+
do {
|
|
890
|
+
nextToken();
|
|
891
|
+
} while (!isStatementKeyword(token()) &&
|
|
892
|
+
token() !== Token.NewLine &&
|
|
893
|
+
token() !== Token.At &&
|
|
894
|
+
token() !== Token.Semicolon &&
|
|
895
|
+
token() !== Token.EndOfFile);
|
|
896
|
+
return undefined;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
function parseIdentifierOrMemberExpression(message, recoverFromKeyword = true) {
|
|
900
|
+
const pos = tokenPos();
|
|
901
|
+
let base = parseIdentifier({
|
|
902
|
+
message,
|
|
903
|
+
recoverFromKeyword,
|
|
904
|
+
});
|
|
905
|
+
while (parseOptional(Token.Dot)) {
|
|
906
|
+
base = {
|
|
907
|
+
kind: SyntaxKind.MemberExpression,
|
|
908
|
+
base,
|
|
909
|
+
// Error recovery: false arg here means don't treat a keyword as an
|
|
910
|
+
// identifier after `.` in member expression. Otherwise we will
|
|
911
|
+
// parse `@Outer.<missing identifier> model M{}` as having decorator
|
|
912
|
+
// `@Outer.model` applied to invalid statement `M {}` instead of
|
|
913
|
+
// having incomplete decorator `@Outer.` applied to `model M {}`.
|
|
914
|
+
id: parseIdentifier({
|
|
915
|
+
recoverFromKeyword: false,
|
|
916
|
+
}),
|
|
917
|
+
...finishNode(pos),
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
return base;
|
|
921
|
+
}
|
|
922
|
+
function parsePrimaryExpression() {
|
|
923
|
+
while (true) {
|
|
924
|
+
switch (token()) {
|
|
925
|
+
case Token.Identifier:
|
|
926
|
+
return parseReferenceExpression();
|
|
927
|
+
case Token.StringLiteral:
|
|
928
|
+
return parseStringLiteral();
|
|
929
|
+
case Token.TrueKeyword:
|
|
930
|
+
case Token.FalseKeyword:
|
|
931
|
+
return parseBooleanLiteral();
|
|
932
|
+
case Token.NumericLiteral:
|
|
933
|
+
return parseNumericLiteral();
|
|
934
|
+
case Token.OpenBrace:
|
|
935
|
+
return parseModelExpression();
|
|
936
|
+
case Token.OpenBracket:
|
|
937
|
+
return parseTupleExpression();
|
|
938
|
+
case Token.OpenParen:
|
|
939
|
+
return parseParenthesizedExpression();
|
|
940
|
+
case Token.At:
|
|
941
|
+
const decorators = parseDecoratorList();
|
|
942
|
+
reportInvalidDecorators(decorators, "expression");
|
|
943
|
+
continue;
|
|
944
|
+
case Token.Hash:
|
|
945
|
+
const directives = parseDirectiveList();
|
|
946
|
+
reportInvalidDirective(directives, "expression");
|
|
947
|
+
continue;
|
|
948
|
+
case Token.VoidKeyword:
|
|
949
|
+
return parseVoidKeyword();
|
|
950
|
+
case Token.NeverKeyword:
|
|
951
|
+
return parseNeverKeyword();
|
|
952
|
+
case Token.UnknownKeyword:
|
|
953
|
+
return parseUnknownKeyword();
|
|
954
|
+
default:
|
|
955
|
+
return parseReferenceExpression("expression");
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
function parseExternKeyword() {
|
|
960
|
+
const pos = tokenPos();
|
|
961
|
+
parseExpected(Token.ExternKeyword);
|
|
962
|
+
return {
|
|
963
|
+
kind: SyntaxKind.ExternKeyword,
|
|
964
|
+
...finishNode(pos),
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
function parseVoidKeyword() {
|
|
968
|
+
const pos = tokenPos();
|
|
969
|
+
parseExpected(Token.VoidKeyword);
|
|
970
|
+
return {
|
|
971
|
+
kind: SyntaxKind.VoidKeyword,
|
|
972
|
+
...finishNode(pos),
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
function parseNeverKeyword() {
|
|
976
|
+
const pos = tokenPos();
|
|
977
|
+
parseExpected(Token.NeverKeyword);
|
|
978
|
+
return {
|
|
979
|
+
kind: SyntaxKind.NeverKeyword,
|
|
980
|
+
...finishNode(pos),
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
function parseUnknownKeyword() {
|
|
984
|
+
const pos = tokenPos();
|
|
985
|
+
parseExpected(Token.UnknownKeyword);
|
|
986
|
+
return {
|
|
987
|
+
kind: SyntaxKind.UnknownKeyword,
|
|
988
|
+
...finishNode(pos),
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
function parseParenthesizedExpression() {
|
|
992
|
+
const pos = tokenPos();
|
|
993
|
+
parseExpected(Token.OpenParen);
|
|
994
|
+
const expr = parseExpression();
|
|
995
|
+
parseExpected(Token.CloseParen);
|
|
996
|
+
return { ...expr, ...finishNode(pos) };
|
|
997
|
+
}
|
|
998
|
+
function parseTupleExpression() {
|
|
999
|
+
const pos = tokenPos();
|
|
1000
|
+
const values = parseList(ListKind.Tuple, parseExpression);
|
|
1001
|
+
return {
|
|
1002
|
+
kind: SyntaxKind.TupleExpression,
|
|
1003
|
+
values,
|
|
1004
|
+
...finishNode(pos),
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
function parseModelExpression() {
|
|
1008
|
+
const pos = tokenPos();
|
|
1009
|
+
const properties = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
|
|
1010
|
+
return {
|
|
1011
|
+
kind: SyntaxKind.ModelExpression,
|
|
1012
|
+
properties,
|
|
1013
|
+
...finishNode(pos),
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
function parseStringLiteral() {
|
|
1017
|
+
const pos = tokenPos();
|
|
1018
|
+
const value = tokenValue();
|
|
1019
|
+
parseExpected(Token.StringLiteral);
|
|
1020
|
+
return {
|
|
1021
|
+
kind: SyntaxKind.StringLiteral,
|
|
1022
|
+
value,
|
|
1023
|
+
...finishNode(pos),
|
|
1024
|
+
};
|
|
1025
|
+
}
|
|
1026
|
+
function parseNumericLiteral() {
|
|
1027
|
+
const pos = tokenPos();
|
|
1028
|
+
const text = tokenValue();
|
|
1029
|
+
const value = Number(text);
|
|
1030
|
+
parseExpected(Token.NumericLiteral);
|
|
1031
|
+
return {
|
|
1032
|
+
kind: SyntaxKind.NumericLiteral,
|
|
1033
|
+
value,
|
|
1034
|
+
...finishNode(pos),
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
function parseBooleanLiteral() {
|
|
1038
|
+
const pos = tokenPos();
|
|
1039
|
+
const token = parseExpectedOneOf(Token.TrueKeyword, Token.FalseKeyword);
|
|
1040
|
+
const value = token === Token.TrueKeyword;
|
|
1041
|
+
return {
|
|
1042
|
+
kind: SyntaxKind.BooleanLiteral,
|
|
1043
|
+
value,
|
|
1044
|
+
...finishNode(pos),
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
function parseIdentifier(options) {
|
|
1048
|
+
var _a;
|
|
1049
|
+
if ((options === null || options === void 0 ? void 0 : options.recoverFromKeyword) !== false && isKeyword(token())) {
|
|
1050
|
+
error({ code: "reserved-identifier" });
|
|
1051
|
+
}
|
|
1052
|
+
else if (token() !== Token.Identifier &&
|
|
1053
|
+
(!(options === null || options === void 0 ? void 0 : options.allowStringLiteral) || token() !== Token.StringLiteral)) {
|
|
1054
|
+
// Error recovery: when we fail to parse an identifier or expression,
|
|
1055
|
+
// we insert a synthesized identifier with a unique name.
|
|
1056
|
+
error({ code: "token-expected", messageId: (_a = options === null || options === void 0 ? void 0 : options.message) !== null && _a !== void 0 ? _a : "identifier" });
|
|
1057
|
+
return createMissingIdentifier();
|
|
1058
|
+
}
|
|
1059
|
+
const pos = tokenPos();
|
|
1060
|
+
const sv = tokenValue();
|
|
1061
|
+
nextToken();
|
|
1062
|
+
return {
|
|
1063
|
+
kind: SyntaxKind.Identifier,
|
|
1064
|
+
sv,
|
|
1065
|
+
...finishNode(pos),
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
function parseDeclaration(pos) {
|
|
1069
|
+
const modifiers = parseModifiers();
|
|
1070
|
+
switch (token()) {
|
|
1071
|
+
case Token.DecKeyword:
|
|
1072
|
+
return parseDecoratorDeclarationStatement(pos, modifiers);
|
|
1073
|
+
case Token.FnKeyword:
|
|
1074
|
+
return parseFunctionDeclarationStatement(pos, modifiers);
|
|
1075
|
+
}
|
|
1076
|
+
return parseInvalidStatement(pos, []);
|
|
1077
|
+
}
|
|
1078
|
+
function parseModifiers() {
|
|
1079
|
+
const modifiers = [];
|
|
1080
|
+
let modifier;
|
|
1081
|
+
while ((modifier = parseModifier())) {
|
|
1082
|
+
modifiers.push(modifier);
|
|
1083
|
+
}
|
|
1084
|
+
return modifiers;
|
|
1085
|
+
}
|
|
1086
|
+
function parseModifier() {
|
|
1087
|
+
switch (token()) {
|
|
1088
|
+
case Token.ExternKeyword:
|
|
1089
|
+
return parseExternKeyword();
|
|
1090
|
+
default:
|
|
1091
|
+
return undefined;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
function parseDecoratorDeclarationStatement(pos, modifiers) {
|
|
1095
|
+
const modifierFlags = modifiersToFlags(modifiers);
|
|
1096
|
+
parseExpected(Token.DecKeyword);
|
|
1097
|
+
const id = parseIdentifier();
|
|
1098
|
+
let [target, ...parameters] = parseFunctionParameters();
|
|
1099
|
+
if (target === undefined) {
|
|
1100
|
+
error({ code: "decorator-decl-target", target: { pos, end: previousTokenEnd } });
|
|
1101
|
+
target = {
|
|
1102
|
+
kind: SyntaxKind.FunctionParameter,
|
|
1103
|
+
id: createMissingIdentifier(),
|
|
1104
|
+
type: createMissingIdentifier(),
|
|
1105
|
+
optional: false,
|
|
1106
|
+
rest: false,
|
|
1107
|
+
...finishNode(pos),
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
if (target.optional) {
|
|
1111
|
+
error({ code: "decorator-decl-target", messageId: "required" });
|
|
1112
|
+
}
|
|
1113
|
+
parseExpected(Token.Semicolon);
|
|
1114
|
+
return {
|
|
1115
|
+
kind: SyntaxKind.DecoratorDeclarationStatement,
|
|
1116
|
+
modifiers,
|
|
1117
|
+
modifierFlags,
|
|
1118
|
+
id,
|
|
1119
|
+
target,
|
|
1120
|
+
parameters,
|
|
1121
|
+
...finishNode(pos),
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
function parseFunctionDeclarationStatement(pos, modifiers) {
|
|
1125
|
+
const modifierFlags = modifiersToFlags(modifiers);
|
|
1126
|
+
parseExpected(Token.FnKeyword);
|
|
1127
|
+
const id = parseIdentifier();
|
|
1128
|
+
const parameters = parseFunctionParameters();
|
|
1129
|
+
let returnType;
|
|
1130
|
+
if (parseOptional(Token.Colon)) {
|
|
1131
|
+
returnType = parseExpression();
|
|
1132
|
+
}
|
|
1133
|
+
parseExpected(Token.Semicolon);
|
|
1134
|
+
return {
|
|
1135
|
+
kind: SyntaxKind.FunctionDeclarationStatement,
|
|
1136
|
+
modifiers,
|
|
1137
|
+
modifierFlags,
|
|
1138
|
+
id,
|
|
1139
|
+
parameters,
|
|
1140
|
+
returnType,
|
|
1141
|
+
...finishNode(pos),
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
function parseFunctionParameters() {
|
|
1145
|
+
const parameters = parseList(ListKind.FunctionParameters, parseFunctionParameter);
|
|
1146
|
+
let foundOptional = false;
|
|
1147
|
+
for (const [index, item] of parameters.entries()) {
|
|
1148
|
+
if (!item.optional && foundOptional) {
|
|
1149
|
+
error({ code: "required-parameter-first", target: item });
|
|
1150
|
+
continue;
|
|
1151
|
+
}
|
|
1152
|
+
if (item.optional) {
|
|
1153
|
+
foundOptional = true;
|
|
1154
|
+
}
|
|
1155
|
+
if (item.rest && item.optional) {
|
|
1156
|
+
error({ code: "rest-parameter-required", target: item });
|
|
1157
|
+
}
|
|
1158
|
+
if (item.rest && index !== parameters.length - 1) {
|
|
1159
|
+
error({ code: "rest-parameter-last", target: item });
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
return parameters;
|
|
1163
|
+
}
|
|
1164
|
+
function parseFunctionParameter() {
|
|
1165
|
+
const pos = tokenPos();
|
|
1166
|
+
const rest = parseOptional(Token.Ellipsis);
|
|
1167
|
+
const id = parseIdentifier({ message: "property" });
|
|
1168
|
+
const optional = parseOptional(Token.Question);
|
|
1169
|
+
let type;
|
|
1170
|
+
if (parseOptional(Token.Colon)) {
|
|
1171
|
+
type = parseExpression();
|
|
1172
|
+
}
|
|
1173
|
+
return {
|
|
1174
|
+
kind: SyntaxKind.FunctionParameter,
|
|
1175
|
+
id,
|
|
1176
|
+
type,
|
|
1177
|
+
optional,
|
|
1178
|
+
rest,
|
|
1179
|
+
...finishNode(pos),
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
function modifiersToFlags(modifiers) {
|
|
1183
|
+
let flags = 0 /* ModifierFlags.None */;
|
|
1184
|
+
for (const modifier of modifiers) {
|
|
1185
|
+
switch (modifier.kind) {
|
|
1186
|
+
case SyntaxKind.ExternKeyword:
|
|
1187
|
+
flags |= 2 /* ModifierFlags.Extern */;
|
|
1188
|
+
break;
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
return flags;
|
|
1192
|
+
}
|
|
1193
|
+
function parseProjectionStatement(pos) {
|
|
1194
|
+
parseExpected(Token.ProjectionKeyword);
|
|
1195
|
+
const selector = parseProjectionSelector();
|
|
1196
|
+
parseExpected(Token.Hash);
|
|
1197
|
+
const id = parseIdentifier();
|
|
1198
|
+
parseExpected(Token.OpenBrace);
|
|
1199
|
+
let from, to;
|
|
1200
|
+
let proj1, proj2;
|
|
1201
|
+
if (token() === Token.Identifier) {
|
|
1202
|
+
proj1 = parseProjection();
|
|
1203
|
+
if (token() === Token.Identifier) {
|
|
1204
|
+
proj2 = parseProjection();
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
if (proj1 && proj2 && proj1.direction === proj2.direction) {
|
|
1208
|
+
error({ code: "duplicate-symbol", target: proj2, format: { name: "projection" } });
|
|
1209
|
+
}
|
|
1210
|
+
else if (proj1) {
|
|
1211
|
+
[to, from] = proj1.direction === "to" ? [proj1, proj2] : [proj2, proj1];
|
|
1212
|
+
}
|
|
1213
|
+
parseExpected(Token.CloseBrace);
|
|
1214
|
+
return {
|
|
1215
|
+
kind: SyntaxKind.ProjectionStatement,
|
|
1216
|
+
selector,
|
|
1217
|
+
from,
|
|
1218
|
+
to,
|
|
1219
|
+
id,
|
|
1220
|
+
...finishNode(pos),
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
function parseProjection() {
|
|
1224
|
+
const pos = tokenPos();
|
|
1225
|
+
const directionId = parseIdentifier({ message: "projectionDirection" });
|
|
1226
|
+
let direction;
|
|
1227
|
+
if (directionId.sv !== "from" && directionId.sv !== "to") {
|
|
1228
|
+
error({ code: "token-expected", messageId: "projectionDirection" });
|
|
1229
|
+
direction = "from";
|
|
1230
|
+
}
|
|
1231
|
+
else {
|
|
1232
|
+
direction = directionId.sv;
|
|
1233
|
+
}
|
|
1234
|
+
let parameters;
|
|
1235
|
+
if (token() === Token.OpenParen) {
|
|
1236
|
+
parameters = parseList(ListKind.ProjectionParameter, parseProjectionParameter);
|
|
1237
|
+
}
|
|
1238
|
+
else {
|
|
1239
|
+
parameters = [];
|
|
1240
|
+
}
|
|
1241
|
+
parseExpected(Token.OpenBrace);
|
|
1242
|
+
const body = parseProjectionStatementList();
|
|
1243
|
+
parseExpected(Token.CloseBrace);
|
|
1244
|
+
return {
|
|
1245
|
+
kind: SyntaxKind.Projection,
|
|
1246
|
+
body,
|
|
1247
|
+
direction,
|
|
1248
|
+
directionId,
|
|
1249
|
+
parameters,
|
|
1250
|
+
...finishNode(pos),
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
function parseProjectionParameter() {
|
|
1254
|
+
const pos = tokenPos();
|
|
1255
|
+
const id = parseIdentifier();
|
|
1256
|
+
return {
|
|
1257
|
+
kind: SyntaxKind.ProjectionParameterDeclaration,
|
|
1258
|
+
id,
|
|
1259
|
+
...finishNode(pos),
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
function parseProjectionStatementList() {
|
|
1263
|
+
const stmts = [];
|
|
1264
|
+
while (token() !== Token.CloseBrace) {
|
|
1265
|
+
const startPos = tokenPos();
|
|
1266
|
+
if (token() === Token.EndOfFile) {
|
|
1267
|
+
error({ code: "token-expected", messageId: "default", format: { token: "}" } });
|
|
1268
|
+
break;
|
|
1269
|
+
}
|
|
1270
|
+
const expr = parseProjectionExpressionStatement();
|
|
1271
|
+
stmts.push(expr);
|
|
1272
|
+
if (tokenPos() === startPos) {
|
|
1273
|
+
// we didn't manage to parse anything, so break out
|
|
1274
|
+
// and we'll report errors elsewhere.
|
|
1275
|
+
break;
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
return stmts;
|
|
1279
|
+
}
|
|
1280
|
+
function parseProjectionExpressionStatement() {
|
|
1281
|
+
const pos = tokenPos();
|
|
1282
|
+
const expr = parseProjectionExpression();
|
|
1283
|
+
parseExpected(Token.Semicolon);
|
|
1284
|
+
return {
|
|
1285
|
+
kind: SyntaxKind.ProjectionExpressionStatement,
|
|
1286
|
+
expr,
|
|
1287
|
+
...finishNode(pos),
|
|
1288
|
+
};
|
|
1289
|
+
}
|
|
1290
|
+
function parseProjectionExpression() {
|
|
1291
|
+
return parseProjectionReturnExpressionOrHigher();
|
|
1292
|
+
}
|
|
1293
|
+
function parseProjectionReturnExpressionOrHigher() {
|
|
1294
|
+
if (token() === Token.ReturnKeyword) {
|
|
1295
|
+
const pos = tokenPos();
|
|
1296
|
+
parseExpected(Token.ReturnKeyword);
|
|
1297
|
+
return {
|
|
1298
|
+
kind: SyntaxKind.Return,
|
|
1299
|
+
value: parseProjectionExpression(),
|
|
1300
|
+
...finishNode(pos),
|
|
1301
|
+
};
|
|
1302
|
+
}
|
|
1303
|
+
return parseProjectionLogicalOrExpressionOrHigher();
|
|
1304
|
+
}
|
|
1305
|
+
function parseProjectionLogicalOrExpressionOrHigher() {
|
|
1306
|
+
let expr = parseProjectionLogicalAndExpressionOrHigher();
|
|
1307
|
+
while (token() !== Token.EndOfFile) {
|
|
1308
|
+
const pos = expr.pos;
|
|
1309
|
+
if (parseOptional(Token.BarBar)) {
|
|
1310
|
+
expr = {
|
|
1311
|
+
kind: SyntaxKind.ProjectionLogicalExpression,
|
|
1312
|
+
op: "||",
|
|
1313
|
+
left: expr,
|
|
1314
|
+
right: parseProjectionLogicalAndExpressionOrHigher(),
|
|
1315
|
+
...finishNode(pos),
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
else {
|
|
1319
|
+
break;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
return expr;
|
|
1323
|
+
}
|
|
1324
|
+
function parseProjectionLogicalAndExpressionOrHigher() {
|
|
1325
|
+
let expr = parseProjectionEqualityExpressionOrHigher();
|
|
1326
|
+
while (token() !== Token.EndOfFile) {
|
|
1327
|
+
const pos = expr.pos;
|
|
1328
|
+
if (parseOptional(Token.AmpsersandAmpersand)) {
|
|
1329
|
+
expr = {
|
|
1330
|
+
kind: SyntaxKind.ProjectionLogicalExpression,
|
|
1331
|
+
op: "&&",
|
|
1332
|
+
left: expr,
|
|
1333
|
+
right: parseProjectionEqualityExpressionOrHigher(),
|
|
1334
|
+
...finishNode(pos),
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
else {
|
|
1338
|
+
break;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
return expr;
|
|
1342
|
+
}
|
|
1343
|
+
function parseProjectionEqualityExpressionOrHigher() {
|
|
1344
|
+
let expr = parseProjectionRelationalExpressionOrHigher();
|
|
1345
|
+
while (token() !== Token.EndOfFile) {
|
|
1346
|
+
const pos = expr.pos;
|
|
1347
|
+
const tok = token();
|
|
1348
|
+
if (tok === Token.EqualsEquals || tok === Token.ExclamationEquals) {
|
|
1349
|
+
const op = tokenValue();
|
|
1350
|
+
nextToken();
|
|
1351
|
+
expr = {
|
|
1352
|
+
kind: SyntaxKind.ProjectionEqualityExpression,
|
|
1353
|
+
op,
|
|
1354
|
+
left: expr,
|
|
1355
|
+
right: parseProjectionRelationalExpressionOrHigher(),
|
|
1356
|
+
...finishNode(pos),
|
|
1357
|
+
};
|
|
1358
|
+
}
|
|
1359
|
+
else {
|
|
1360
|
+
break;
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
return expr;
|
|
1364
|
+
}
|
|
1365
|
+
function parseProjectionRelationalExpressionOrHigher() {
|
|
1366
|
+
let expr = parseProjectionAdditiveExpressionOrHigher();
|
|
1367
|
+
while (token() !== Token.EndOfFile) {
|
|
1368
|
+
const pos = expr.pos;
|
|
1369
|
+
const tok = token();
|
|
1370
|
+
if (tok === Token.LessThan ||
|
|
1371
|
+
tok === Token.LessThanEquals ||
|
|
1372
|
+
tok === Token.GreaterThan ||
|
|
1373
|
+
tok === Token.GreaterThanEquals) {
|
|
1374
|
+
const op = tokenValue();
|
|
1375
|
+
nextToken();
|
|
1376
|
+
expr = {
|
|
1377
|
+
kind: SyntaxKind.ProjectionRelationalExpression,
|
|
1378
|
+
op,
|
|
1379
|
+
left: expr,
|
|
1380
|
+
right: parseProjectionAdditiveExpressionOrHigher(),
|
|
1381
|
+
...finishNode(pos),
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
else {
|
|
1385
|
+
break;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
return expr;
|
|
1389
|
+
}
|
|
1390
|
+
function parseProjectionAdditiveExpressionOrHigher() {
|
|
1391
|
+
let expr = parseProjectionMultiplicativeExpressionOrHigher();
|
|
1392
|
+
while (token() !== Token.EndOfFile) {
|
|
1393
|
+
const pos = expr.pos;
|
|
1394
|
+
const tok = token();
|
|
1395
|
+
if (tok === Token.Plus || tok === Token.Hyphen) {
|
|
1396
|
+
const op = tokenValue();
|
|
1397
|
+
nextToken();
|
|
1398
|
+
expr = {
|
|
1399
|
+
kind: SyntaxKind.ProjectionArithmeticExpression,
|
|
1400
|
+
op,
|
|
1401
|
+
left: expr,
|
|
1402
|
+
right: parseProjectionMultiplicativeExpressionOrHigher(),
|
|
1403
|
+
...finishNode(pos),
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
else {
|
|
1407
|
+
break;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
return expr;
|
|
1411
|
+
}
|
|
1412
|
+
function parseProjectionMultiplicativeExpressionOrHigher() {
|
|
1413
|
+
let expr = parseProjectionUnaryExpressionOrHigher();
|
|
1414
|
+
while (token() !== Token.EndOfFile) {
|
|
1415
|
+
const pos = expr.pos;
|
|
1416
|
+
const tok = token();
|
|
1417
|
+
if (tok === Token.ForwardSlash || tok === Token.Star) {
|
|
1418
|
+
const op = tokenValue();
|
|
1419
|
+
nextToken();
|
|
1420
|
+
expr = {
|
|
1421
|
+
kind: SyntaxKind.ProjectionArithmeticExpression,
|
|
1422
|
+
op,
|
|
1423
|
+
left: expr,
|
|
1424
|
+
right: parseProjectionUnaryExpressionOrHigher(),
|
|
1425
|
+
...finishNode(pos),
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
else {
|
|
1429
|
+
break;
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
return expr;
|
|
1433
|
+
}
|
|
1434
|
+
function parseProjectionUnaryExpressionOrHigher() {
|
|
1435
|
+
if (token() === Token.Exclamation) {
|
|
1436
|
+
const pos = tokenPos();
|
|
1437
|
+
nextToken();
|
|
1438
|
+
return {
|
|
1439
|
+
kind: SyntaxKind.ProjectionUnaryExpression,
|
|
1440
|
+
op: "!",
|
|
1441
|
+
target: parseProjectionUnaryExpressionOrHigher(),
|
|
1442
|
+
...finishNode(pos),
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1445
|
+
return parseProjectionCallExpressionOrHigher();
|
|
1446
|
+
}
|
|
1447
|
+
function parseProjectionCallExpressionOrHigher() {
|
|
1448
|
+
let expr = parseProjectionDecoratorReferenceExpressionOrHigher();
|
|
1449
|
+
while (token() !== Token.EndOfFile) {
|
|
1450
|
+
const pos = expr.pos;
|
|
1451
|
+
expr = parseProjectionMemberExpressionRest(expr, pos);
|
|
1452
|
+
if (token() === Token.OpenParen) {
|
|
1453
|
+
expr = {
|
|
1454
|
+
kind: SyntaxKind.ProjectionCallExpression,
|
|
1455
|
+
callKind: "method",
|
|
1456
|
+
target: expr,
|
|
1457
|
+
arguments: parseList(ListKind.CallArguments, parseProjectionExpression),
|
|
1458
|
+
...finishNode(pos),
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
else {
|
|
1462
|
+
break;
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
return expr;
|
|
1466
|
+
}
|
|
1467
|
+
function parseProjectionDecoratorReferenceExpressionOrHigher() {
|
|
1468
|
+
if (token() === Token.At) {
|
|
1469
|
+
const pos = tokenPos();
|
|
1470
|
+
nextToken();
|
|
1471
|
+
return {
|
|
1472
|
+
kind: SyntaxKind.ProjectionDecoratorReferenceExpression,
|
|
1473
|
+
target: parseIdentifierOrMemberExpression(undefined, true),
|
|
1474
|
+
...finishNode(pos),
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
return parseProjectionMemberExpressionOrHigher();
|
|
1478
|
+
}
|
|
1479
|
+
function parseProjectionMemberExpressionOrHigher() {
|
|
1480
|
+
const pos = tokenPos();
|
|
1481
|
+
let expr = parseProjectionPrimaryExpression();
|
|
1482
|
+
expr = parseProjectionMemberExpressionRest(expr, pos);
|
|
1483
|
+
return expr;
|
|
1484
|
+
}
|
|
1485
|
+
function parseProjectionMemberExpressionRest(expr, pos) {
|
|
1486
|
+
while (token() !== Token.EndOfFile) {
|
|
1487
|
+
if (parseOptional(Token.Dot)) {
|
|
1488
|
+
expr = {
|
|
1489
|
+
kind: SyntaxKind.ProjectionMemberExpression,
|
|
1490
|
+
base: expr,
|
|
1491
|
+
id: parseIdentifier(),
|
|
1492
|
+
selector: ".",
|
|
1493
|
+
...finishNode(pos),
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
else if (parseOptional(Token.ColonColon)) {
|
|
1497
|
+
expr = {
|
|
1498
|
+
kind: SyntaxKind.ProjectionMemberExpression,
|
|
1499
|
+
base: expr,
|
|
1500
|
+
id: parseIdentifier(),
|
|
1501
|
+
selector: "::",
|
|
1502
|
+
...finishNode(pos),
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
else {
|
|
1506
|
+
break;
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
return expr;
|
|
1510
|
+
}
|
|
1511
|
+
function parseProjectionPrimaryExpression() {
|
|
1512
|
+
switch (token()) {
|
|
1513
|
+
case Token.IfKeyword:
|
|
1514
|
+
return parseProjectionIfExpression();
|
|
1515
|
+
case Token.NumericLiteral:
|
|
1516
|
+
return parseNumericLiteral();
|
|
1517
|
+
case Token.StringLiteral:
|
|
1518
|
+
return parseStringLiteral();
|
|
1519
|
+
case Token.TrueKeyword:
|
|
1520
|
+
case Token.FalseKeyword:
|
|
1521
|
+
return parseBooleanLiteral();
|
|
1522
|
+
case Token.OpenBracket:
|
|
1523
|
+
return parseProjectionTupleExpression();
|
|
1524
|
+
case Token.OpenBrace:
|
|
1525
|
+
return parseProjectionModelExpression();
|
|
1526
|
+
case Token.OpenParen:
|
|
1527
|
+
return parseProjectionLambdaOrParenthesizedExpression();
|
|
1528
|
+
case Token.VoidKeyword:
|
|
1529
|
+
return parseVoidKeyword();
|
|
1530
|
+
case Token.NeverKeyword:
|
|
1531
|
+
return parseNeverKeyword();
|
|
1532
|
+
case Token.UnknownKeyword:
|
|
1533
|
+
return parseUnknownKeyword();
|
|
1534
|
+
default:
|
|
1535
|
+
return parseIdentifier({ message: "expression" });
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
function parseProjectionLambdaOrParenthesizedExpression() {
|
|
1539
|
+
const pos = tokenPos();
|
|
1540
|
+
const exprs = parseList(ListKind.ProjectionExpression, parseProjectionExpression);
|
|
1541
|
+
if (token() === Token.EqualsGreaterThan) {
|
|
1542
|
+
// unpack the exprs (which should be just identifiers) into a param list
|
|
1543
|
+
const params = [];
|
|
1544
|
+
for (const expr of exprs) {
|
|
1545
|
+
if (expr.kind === SyntaxKind.Identifier) {
|
|
1546
|
+
params.push(withSymbol({
|
|
1547
|
+
kind: SyntaxKind.ProjectionLambdaParameterDeclaration,
|
|
1548
|
+
id: expr,
|
|
1549
|
+
pos: expr.pos,
|
|
1550
|
+
end: expr.end,
|
|
1551
|
+
flags: 0 /* NodeFlags.None */,
|
|
1552
|
+
}));
|
|
1553
|
+
}
|
|
1554
|
+
else {
|
|
1555
|
+
error({ code: "token-expected", messageId: "identifier", target: expr });
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
return parseProjectionLambdaExpressionRest(pos, params);
|
|
1559
|
+
}
|
|
1560
|
+
else {
|
|
1561
|
+
if (exprs.length === 0) {
|
|
1562
|
+
error({
|
|
1563
|
+
code: "token-expected",
|
|
1564
|
+
messageId: "expression",
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1567
|
+
// verify we only have one entry
|
|
1568
|
+
for (let i = 1; i < exprs.length; i++) {
|
|
1569
|
+
error({
|
|
1570
|
+
code: "token-expected",
|
|
1571
|
+
messageId: "unexpected",
|
|
1572
|
+
format: { token: "expression" },
|
|
1573
|
+
target: exprs[i],
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1576
|
+
return exprs[0];
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
function parseProjectionLambdaExpressionRest(pos, parameters) {
|
|
1580
|
+
parseExpected(Token.EqualsGreaterThan);
|
|
1581
|
+
const body = parseProjectionBlockExpression();
|
|
1582
|
+
return {
|
|
1583
|
+
kind: SyntaxKind.ProjectionLambdaExpression,
|
|
1584
|
+
parameters,
|
|
1585
|
+
body,
|
|
1586
|
+
...finishNode(pos),
|
|
1587
|
+
};
|
|
1588
|
+
}
|
|
1589
|
+
function parseProjectionModelExpression() {
|
|
1590
|
+
const pos = tokenPos();
|
|
1591
|
+
const properties = parseList(ListKind.ModelProperties, parseProjectionModelPropertyOrSpread);
|
|
1592
|
+
return {
|
|
1593
|
+
kind: SyntaxKind.ProjectionModelExpression,
|
|
1594
|
+
properties,
|
|
1595
|
+
...finishNode(pos),
|
|
1596
|
+
};
|
|
1597
|
+
}
|
|
1598
|
+
function parseProjectionModelPropertyOrSpread(pos, decorators) {
|
|
1599
|
+
return token() === Token.Ellipsis
|
|
1600
|
+
? parseProjectionModelSpreadProperty(pos, decorators)
|
|
1601
|
+
: parseProjectionModelProperty(pos, decorators);
|
|
1602
|
+
}
|
|
1603
|
+
function parseProjectionModelSpreadProperty(pos, decorators) {
|
|
1604
|
+
parseExpected(Token.Ellipsis);
|
|
1605
|
+
reportInvalidDecorators(decorators, "spread property");
|
|
1606
|
+
const target = parseProjectionExpression();
|
|
1607
|
+
return {
|
|
1608
|
+
kind: SyntaxKind.ProjectionModelSpreadProperty,
|
|
1609
|
+
target,
|
|
1610
|
+
...finishNode(pos),
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
function parseProjectionModelProperty(pos, decorators) {
|
|
1614
|
+
const id = parseIdentifier({ message: "property", allowStringLiteral: true });
|
|
1615
|
+
const optional = parseOptional(Token.Question);
|
|
1616
|
+
parseExpected(Token.Colon);
|
|
1617
|
+
const value = parseProjectionExpression();
|
|
1618
|
+
const hasDefault = parseOptional(Token.Equals);
|
|
1619
|
+
if (hasDefault && !optional) {
|
|
1620
|
+
error({ code: "default-optional" });
|
|
1621
|
+
}
|
|
1622
|
+
const defaultValue = hasDefault ? parseProjectionExpression() : undefined;
|
|
1623
|
+
return {
|
|
1624
|
+
kind: SyntaxKind.ProjectionModelProperty,
|
|
1625
|
+
id,
|
|
1626
|
+
decorators,
|
|
1627
|
+
value,
|
|
1628
|
+
optional,
|
|
1629
|
+
default: defaultValue,
|
|
1630
|
+
...finishNode(pos),
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
function parseProjectionIfExpression() {
|
|
1634
|
+
const pos = tokenPos();
|
|
1635
|
+
parseExpected(Token.IfKeyword);
|
|
1636
|
+
const test = parseProjectionExpression();
|
|
1637
|
+
const consequent = parseProjectionBlockExpression();
|
|
1638
|
+
let alternate = undefined;
|
|
1639
|
+
if (parseOptional(Token.ElseKeyword)) {
|
|
1640
|
+
if (token() === Token.IfKeyword) {
|
|
1641
|
+
alternate = parseProjectionIfExpression();
|
|
1642
|
+
}
|
|
1643
|
+
else {
|
|
1644
|
+
alternate = parseProjectionBlockExpression();
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
return {
|
|
1648
|
+
kind: SyntaxKind.ProjectionIfExpression,
|
|
1649
|
+
test,
|
|
1650
|
+
consequent,
|
|
1651
|
+
alternate,
|
|
1652
|
+
...finishNode(pos),
|
|
1653
|
+
};
|
|
1654
|
+
}
|
|
1655
|
+
function parseProjectionBlockExpression() {
|
|
1656
|
+
const pos = tokenPos();
|
|
1657
|
+
parseExpected(Token.OpenBrace);
|
|
1658
|
+
const statements = parseProjectionStatementList();
|
|
1659
|
+
parseExpected(Token.CloseBrace);
|
|
1660
|
+
return {
|
|
1661
|
+
kind: SyntaxKind.ProjectionBlockExpression,
|
|
1662
|
+
statements,
|
|
1663
|
+
...finishNode(pos),
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
function parseProjectionTupleExpression() {
|
|
1667
|
+
const pos = tokenPos();
|
|
1668
|
+
const values = parseList(ListKind.Tuple, parseProjectionExpression);
|
|
1669
|
+
return {
|
|
1670
|
+
kind: SyntaxKind.ProjectionTupleExpression,
|
|
1671
|
+
values,
|
|
1672
|
+
...finishNode(pos),
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
function parseProjectionSelector() {
|
|
1676
|
+
const pos = tokenPos();
|
|
1677
|
+
const selectorTok = expectTokenIsOneOf(Token.Identifier, Token.ModelKeyword, Token.OpKeyword, Token.InterfaceKeyword, Token.UnionKeyword, Token.EnumKeyword);
|
|
1678
|
+
switch (selectorTok) {
|
|
1679
|
+
case Token.Identifier:
|
|
1680
|
+
return parseIdentifierOrMemberExpression(undefined, true);
|
|
1681
|
+
case Token.ModelKeyword:
|
|
1682
|
+
nextToken();
|
|
1683
|
+
return {
|
|
1684
|
+
kind: SyntaxKind.ProjectionModelSelector,
|
|
1685
|
+
...finishNode(pos),
|
|
1686
|
+
};
|
|
1687
|
+
case Token.OpKeyword:
|
|
1688
|
+
nextToken();
|
|
1689
|
+
return {
|
|
1690
|
+
kind: SyntaxKind.ProjectionOperationSelector,
|
|
1691
|
+
...finishNode(pos),
|
|
1692
|
+
};
|
|
1693
|
+
case Token.InterfaceKeyword:
|
|
1694
|
+
nextToken();
|
|
1695
|
+
return {
|
|
1696
|
+
kind: SyntaxKind.ProjectionInterfaceSelector,
|
|
1697
|
+
...finishNode(pos),
|
|
1698
|
+
};
|
|
1699
|
+
case Token.UnionKeyword:
|
|
1700
|
+
nextToken();
|
|
1701
|
+
return {
|
|
1702
|
+
kind: SyntaxKind.ProjectionUnionSelector,
|
|
1703
|
+
...finishNode(pos),
|
|
1704
|
+
};
|
|
1705
|
+
case Token.EnumKeyword:
|
|
1706
|
+
nextToken();
|
|
1707
|
+
return {
|
|
1708
|
+
kind: SyntaxKind.ProjectionEnumSelector,
|
|
1709
|
+
...finishNode(pos),
|
|
1710
|
+
};
|
|
1711
|
+
default:
|
|
1712
|
+
// recovery: return a missing identifier to use as the selector
|
|
1713
|
+
// we don't need to emit a diagnostic here as the `expectTokenOneOf` above
|
|
1714
|
+
// will have done so.
|
|
1715
|
+
return createMissingIdentifier();
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
function parseRange(mode, range, callback) {
|
|
1719
|
+
const savedMode = currentMode;
|
|
1720
|
+
const result = scanner.scanRange(range, () => {
|
|
1721
|
+
currentMode = mode;
|
|
1722
|
+
nextToken();
|
|
1723
|
+
return callback();
|
|
1724
|
+
});
|
|
1725
|
+
currentMode = savedMode;
|
|
1726
|
+
return result;
|
|
1727
|
+
}
|
|
1728
|
+
/** Remove leading slash-star-star and trailing star-slash (if terminated) from doc comment range. */
|
|
1729
|
+
function innerDocRange(range) {
|
|
1730
|
+
return {
|
|
1731
|
+
pos: range.pos + 3,
|
|
1732
|
+
end: tokenFlags() & TokenFlags.Unterminated ? range.end : range.end - 2,
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1735
|
+
function parseDocList() {
|
|
1736
|
+
if (docRanges.length === 0 || !options.docs) {
|
|
1737
|
+
return [tokenPos(), []];
|
|
1738
|
+
}
|
|
1739
|
+
const docs = [];
|
|
1740
|
+
for (const range of docRanges) {
|
|
1741
|
+
const doc = parseRange(1 /* ParseMode.Doc */, innerDocRange(range), parseDoc);
|
|
1742
|
+
docs.push(doc);
|
|
1743
|
+
}
|
|
1744
|
+
return [docRanges[0].pos, docs];
|
|
1745
|
+
}
|
|
1746
|
+
function parseDoc() {
|
|
1747
|
+
const pos = tokenPos();
|
|
1748
|
+
const content = [];
|
|
1749
|
+
const tags = [];
|
|
1750
|
+
loop: while (true) {
|
|
1751
|
+
switch (token()) {
|
|
1752
|
+
case Token.EndOfFile:
|
|
1753
|
+
break loop;
|
|
1754
|
+
case Token.At:
|
|
1755
|
+
const tag = parseDocTag();
|
|
1756
|
+
tags.push(tag);
|
|
1757
|
+
break;
|
|
1758
|
+
default:
|
|
1759
|
+
content.push(...parseDocContent());
|
|
1760
|
+
break;
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
return {
|
|
1764
|
+
kind: SyntaxKind.Doc,
|
|
1765
|
+
content,
|
|
1766
|
+
tags,
|
|
1767
|
+
...finishNode(pos),
|
|
1768
|
+
};
|
|
1769
|
+
}
|
|
1770
|
+
function parseDocContent() {
|
|
1771
|
+
const parts = [];
|
|
1772
|
+
const source = scanner.file.text;
|
|
1773
|
+
const pos = tokenPos();
|
|
1774
|
+
let start = pos;
|
|
1775
|
+
let inCodeFence = false;
|
|
1776
|
+
loop: while (true) {
|
|
1777
|
+
switch (token()) {
|
|
1778
|
+
case Token.DocCodeFenceDelimiter:
|
|
1779
|
+
inCodeFence = !inCodeFence;
|
|
1780
|
+
nextDocToken();
|
|
1781
|
+
break;
|
|
1782
|
+
case Token.NewLine:
|
|
1783
|
+
parts.push(source.substring(start, tokenPos()));
|
|
1784
|
+
parts.push("\n"); // normalize line endings
|
|
1785
|
+
nextDocToken();
|
|
1786
|
+
start = tokenPos();
|
|
1787
|
+
while (parseOptional(Token.Whitespace))
|
|
1788
|
+
;
|
|
1789
|
+
if (parseOptional(Token.Star)) {
|
|
1790
|
+
parseOptional(Token.Whitespace);
|
|
1791
|
+
start = tokenPos();
|
|
1792
|
+
break;
|
|
1793
|
+
}
|
|
1794
|
+
break;
|
|
1795
|
+
case Token.EndOfFile:
|
|
1796
|
+
break loop;
|
|
1797
|
+
case Token.At:
|
|
1798
|
+
if (!inCodeFence) {
|
|
1799
|
+
break loop;
|
|
1800
|
+
}
|
|
1801
|
+
nextDocToken();
|
|
1802
|
+
break;
|
|
1803
|
+
default:
|
|
1804
|
+
nextDocToken();
|
|
1805
|
+
break;
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
parts.push(source.substring(start, tokenPos()));
|
|
1809
|
+
const text = trim(parts.join(""));
|
|
1810
|
+
return [
|
|
1811
|
+
{
|
|
1812
|
+
kind: SyntaxKind.DocText,
|
|
1813
|
+
text,
|
|
1814
|
+
...finishNode(pos),
|
|
1815
|
+
},
|
|
1816
|
+
];
|
|
1817
|
+
}
|
|
1818
|
+
function parseDocTag() {
|
|
1819
|
+
const pos = tokenPos();
|
|
1820
|
+
parseExpected(Token.At);
|
|
1821
|
+
const tagName = parseDocIdentifier("tag");
|
|
1822
|
+
switch (tagName.sv) {
|
|
1823
|
+
case "param":
|
|
1824
|
+
return parseDocParamLikeTag(pos, tagName, SyntaxKind.DocParamTag, "param");
|
|
1825
|
+
case "template":
|
|
1826
|
+
return parseDocParamLikeTag(pos, tagName, SyntaxKind.DocTemplateTag, "templateParam");
|
|
1827
|
+
case "return":
|
|
1828
|
+
case "returns":
|
|
1829
|
+
return parseDocSimpleTag(pos, tagName, SyntaxKind.DocReturnsTag);
|
|
1830
|
+
default:
|
|
1831
|
+
return parseDocSimpleTag(pos, tagName, SyntaxKind.DocUnknownTag);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
function parseDocParamLikeTag(pos, tagName, kind, messageId) {
|
|
1835
|
+
const name = parseDocIdentifier(messageId);
|
|
1836
|
+
const content = parseDocContent();
|
|
1837
|
+
return {
|
|
1838
|
+
kind,
|
|
1839
|
+
tagName,
|
|
1840
|
+
paramName: name,
|
|
1841
|
+
content,
|
|
1842
|
+
...finishNode(pos),
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1845
|
+
function parseDocSimpleTag(pos, tagName, kind) {
|
|
1846
|
+
const content = parseDocContent();
|
|
1847
|
+
return {
|
|
1848
|
+
kind,
|
|
1849
|
+
tagName,
|
|
1850
|
+
content,
|
|
1851
|
+
...finishNode(pos),
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1854
|
+
function parseDocIdentifier(messageId) {
|
|
1855
|
+
// We don't allow whitespace between @ and tag name, but allow
|
|
1856
|
+
// whitespace before all other identifiers.
|
|
1857
|
+
if (messageId !== "tag") {
|
|
1858
|
+
while (parseOptional(Token.Whitespace))
|
|
1859
|
+
;
|
|
1860
|
+
}
|
|
1861
|
+
const pos = tokenPos();
|
|
1862
|
+
let sv;
|
|
1863
|
+
if (token() === Token.Identifier) {
|
|
1864
|
+
sv = tokenValue();
|
|
1865
|
+
nextDocToken();
|
|
1866
|
+
}
|
|
1867
|
+
else {
|
|
1868
|
+
sv = "";
|
|
1869
|
+
warning({ code: "doc-invalid-identifier", messageId });
|
|
1870
|
+
}
|
|
1871
|
+
return {
|
|
1872
|
+
kind: SyntaxKind.Identifier,
|
|
1873
|
+
sv,
|
|
1874
|
+
...finishNode(pos),
|
|
1875
|
+
};
|
|
1876
|
+
}
|
|
1877
|
+
// utility functions
|
|
1878
|
+
function token() {
|
|
1879
|
+
return scanner.token;
|
|
1880
|
+
}
|
|
1881
|
+
function tokenFlags() {
|
|
1882
|
+
return scanner.tokenFlags;
|
|
1883
|
+
}
|
|
1884
|
+
function tokenValue() {
|
|
1885
|
+
return scanner.getTokenValue();
|
|
1886
|
+
}
|
|
1887
|
+
function tokenPos() {
|
|
1888
|
+
return scanner.tokenPosition;
|
|
1889
|
+
}
|
|
1890
|
+
function tokenEnd() {
|
|
1891
|
+
return scanner.position;
|
|
1892
|
+
}
|
|
1893
|
+
function nextToken() {
|
|
1894
|
+
// keep track of the previous token end separately from the current scanner
|
|
1895
|
+
// position as these will differ when the previous token had trailing
|
|
1896
|
+
// trivia, and we don't want to squiggle the trivia.
|
|
1897
|
+
previousTokenEnd = scanner.position;
|
|
1898
|
+
return currentMode === 0 /* ParseMode.Syntax */ ? nextSyntaxToken() : nextDocToken();
|
|
1899
|
+
}
|
|
1900
|
+
function nextSyntaxToken() {
|
|
1901
|
+
docRanges = [];
|
|
1902
|
+
for (;;) {
|
|
1903
|
+
scanner.scan();
|
|
1904
|
+
if (isTrivia(token())) {
|
|
1905
|
+
if (!newLineIsTrivia && token() === Token.NewLine) {
|
|
1906
|
+
break;
|
|
1907
|
+
}
|
|
1908
|
+
if (tokenFlags() & TokenFlags.DocComment) {
|
|
1909
|
+
docRanges.push({
|
|
1910
|
+
pos: tokenPos(),
|
|
1911
|
+
end: tokenEnd(),
|
|
1912
|
+
});
|
|
1913
|
+
}
|
|
1914
|
+
if (options.comments && isComment(token())) {
|
|
1915
|
+
comments.push({
|
|
1916
|
+
kind: token() === Token.SingleLineComment
|
|
1917
|
+
? SyntaxKind.LineComment
|
|
1918
|
+
: SyntaxKind.BlockComment,
|
|
1919
|
+
pos: tokenPos(),
|
|
1920
|
+
end: tokenEnd(),
|
|
1921
|
+
});
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
else {
|
|
1925
|
+
break;
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
function nextDocToken() {
|
|
1930
|
+
// NOTE: trivia tokens are always significant in doc comments.
|
|
1931
|
+
scanner.scanDoc();
|
|
1932
|
+
}
|
|
1933
|
+
function createMissingIdentifier() {
|
|
1934
|
+
const pos = tokenPos();
|
|
1935
|
+
previousTokenEnd = pos;
|
|
1936
|
+
missingIdentifierCounter++;
|
|
1937
|
+
return {
|
|
1938
|
+
kind: SyntaxKind.Identifier,
|
|
1939
|
+
sv: "<missing identifier>" + missingIdentifierCounter,
|
|
1940
|
+
...finishNode(pos),
|
|
1941
|
+
};
|
|
1942
|
+
}
|
|
1943
|
+
function finishNode(pos) {
|
|
1944
|
+
const flags = parseErrorInNextFinishedNode ? 2 /* NodeFlags.ThisNodeHasError */ : 0 /* NodeFlags.None */;
|
|
1945
|
+
parseErrorInNextFinishedNode = false;
|
|
1946
|
+
return withSymbol({ pos, end: previousTokenEnd, flags });
|
|
1947
|
+
}
|
|
1948
|
+
// pretend to add as symbol property, likely to a node that is being created.
|
|
1949
|
+
function withSymbol(obj) {
|
|
1950
|
+
return obj;
|
|
1951
|
+
}
|
|
1952
|
+
/**
|
|
1953
|
+
* Parse a delimited list of elements, including the surrounding open and
|
|
1954
|
+
* close punctuation
|
|
1955
|
+
*
|
|
1956
|
+
* This shared driver function is used to share sensitive error recovery code.
|
|
1957
|
+
* In particular, error recovery by inserting tokens deemed missing is
|
|
1958
|
+
* susceptible to getting stalled in a loop iteration without making any
|
|
1959
|
+
* progress, and we guard against this in a shared place here.
|
|
1960
|
+
*
|
|
1961
|
+
* Note that statement and decorator lists do not have this issue. We always
|
|
1962
|
+
* consume at least a real '@' for a decorator and if the leading token of a
|
|
1963
|
+
* statement is not one of our statement keywords, ';', or '@', it is consumed
|
|
1964
|
+
* as part of a bad statement. As such, parsing of decorators and statements
|
|
1965
|
+
* do not go through here.
|
|
1966
|
+
*/
|
|
1967
|
+
function parseList(kind, parseItem) {
|
|
1968
|
+
if (kind.open !== Token.None) {
|
|
1969
|
+
parseExpected(kind.open);
|
|
1970
|
+
}
|
|
1971
|
+
if (kind.allowEmpty && parseOptional(kind.close)) {
|
|
1972
|
+
return [];
|
|
1973
|
+
}
|
|
1974
|
+
const items = [];
|
|
1975
|
+
while (true) {
|
|
1976
|
+
let pos = tokenPos();
|
|
1977
|
+
let docs;
|
|
1978
|
+
if (!kind.invalidAnnotationTarget) {
|
|
1979
|
+
[pos, docs] = parseDocList();
|
|
1980
|
+
}
|
|
1981
|
+
const directives = parseDirectiveList();
|
|
1982
|
+
const decorators = parseDecoratorList();
|
|
1983
|
+
if (kind.invalidAnnotationTarget) {
|
|
1984
|
+
reportInvalidDecorators(decorators, kind.invalidAnnotationTarget);
|
|
1985
|
+
reportInvalidDirective(directives, kind.invalidAnnotationTarget);
|
|
1986
|
+
}
|
|
1987
|
+
if (directives.length === 0 && decorators.length === 0 && atEndOfListWithError(kind)) {
|
|
1988
|
+
// Error recovery: end surrounded list at statement keyword or end
|
|
1989
|
+
// of file. Note, however, that we must parse a missing element if
|
|
1990
|
+
// there were directives or decorators as we cannot drop those from
|
|
1991
|
+
// the tree.
|
|
1992
|
+
parseExpected(kind.close);
|
|
1993
|
+
break;
|
|
1994
|
+
}
|
|
1995
|
+
let item;
|
|
1996
|
+
if (kind.invalidAnnotationTarget) {
|
|
1997
|
+
item = parseItem();
|
|
1998
|
+
}
|
|
1999
|
+
else {
|
|
2000
|
+
item = parseItem(pos, decorators);
|
|
2001
|
+
mutate(item).docs = docs;
|
|
2002
|
+
mutate(item).directives = directives;
|
|
2003
|
+
}
|
|
2004
|
+
items.push(item);
|
|
2005
|
+
const delimiter = token();
|
|
2006
|
+
const delimiterPos = tokenPos();
|
|
2007
|
+
if (parseOptionalDelimiter(kind)) {
|
|
2008
|
+
// Delimiter found: check if it's trailing.
|
|
2009
|
+
if (parseOptional(kind.close)) {
|
|
2010
|
+
if (!kind.trailingDelimiterIsValid) {
|
|
2011
|
+
error({
|
|
2012
|
+
code: "trailing-token",
|
|
2013
|
+
format: { token: TokenDisplay[delimiter] },
|
|
2014
|
+
target: {
|
|
2015
|
+
pos: delimiterPos,
|
|
2016
|
+
end: delimiterPos + 1,
|
|
2017
|
+
},
|
|
2018
|
+
});
|
|
2019
|
+
}
|
|
2020
|
+
// It was trailing and we've consumed the close token.
|
|
2021
|
+
break;
|
|
2022
|
+
}
|
|
2023
|
+
// Not trailing. We can safely skip the progress check below here
|
|
2024
|
+
// because we know that we consumed a real delimiter.
|
|
2025
|
+
continue;
|
|
2026
|
+
}
|
|
2027
|
+
else if (kind.close === Token.None) {
|
|
2028
|
+
// If a list is *not* surrounded by punctuation, then the list ends when
|
|
2029
|
+
// there's no delimiter after an item.
|
|
2030
|
+
break;
|
|
2031
|
+
}
|
|
2032
|
+
else if (parseOptional(kind.close)) {
|
|
2033
|
+
// If a list *is* surrounded by punctuation, then the list ends when we
|
|
2034
|
+
// reach the close token.
|
|
2035
|
+
break;
|
|
2036
|
+
}
|
|
2037
|
+
else if (atEndOfListWithError(kind)) {
|
|
2038
|
+
// Error recovery: If a list *is* surrounded by punctuation, then
|
|
2039
|
+
// the list ends at statement keyword or end-of-file under the
|
|
2040
|
+
// assumption that the closing delimiter is missing. This check is
|
|
2041
|
+
// duplicated from above to preempt the parseExpected(delimeter)
|
|
2042
|
+
// below.
|
|
2043
|
+
parseExpected(kind.close);
|
|
2044
|
+
break;
|
|
2045
|
+
}
|
|
2046
|
+
else {
|
|
2047
|
+
// Error recovery: if a list kind *is* surrounded by punctuation and we
|
|
2048
|
+
// find neither a delimiter nor a close token after an item, then we
|
|
2049
|
+
// assume there is a missing delimiter between items.
|
|
2050
|
+
//
|
|
2051
|
+
// Example: `model M { a: B <missing semicolon> c: D }
|
|
2052
|
+
parseExpected(kind.delimiter);
|
|
2053
|
+
}
|
|
2054
|
+
if (pos === tokenPos()) {
|
|
2055
|
+
// Error recovery: we've inserted everything during this loop iteration
|
|
2056
|
+
// and haven't made any progress. Assume that the current token is a bad
|
|
2057
|
+
// representation of the end of the the list that we're trying to get
|
|
2058
|
+
// through.
|
|
2059
|
+
//
|
|
2060
|
+
// Simple repro: `model M { ]` would loop forever without this check.
|
|
2061
|
+
//
|
|
2062
|
+
parseExpected(kind.close);
|
|
2063
|
+
nextToken();
|
|
2064
|
+
// remove the item that was entirely inserted by error recovery.
|
|
2065
|
+
items.pop();
|
|
2066
|
+
break;
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
return items;
|
|
2070
|
+
}
|
|
2071
|
+
/**
|
|
2072
|
+
* Parse a delimited list with surrounding open and close punctuation if the
|
|
2073
|
+
* open token is present. Otherwise, return an empty list.
|
|
2074
|
+
*/
|
|
2075
|
+
function parseOptionalList(kind, parseItem) {
|
|
2076
|
+
return token() === kind.open ? parseList(kind, parseItem) : [];
|
|
2077
|
+
}
|
|
2078
|
+
function parseOptionalDelimiter(kind) {
|
|
2079
|
+
if (parseOptional(kind.delimiter)) {
|
|
2080
|
+
return true;
|
|
2081
|
+
}
|
|
2082
|
+
if (token() === kind.toleratedDelimiter) {
|
|
2083
|
+
if (!kind.toleratedDelimiterIsValid) {
|
|
2084
|
+
parseExpected(kind.delimiter);
|
|
2085
|
+
}
|
|
2086
|
+
nextToken();
|
|
2087
|
+
return true;
|
|
2088
|
+
}
|
|
2089
|
+
return false;
|
|
2090
|
+
}
|
|
2091
|
+
function atEndOfListWithError(kind) {
|
|
2092
|
+
return (kind.close !== Token.None &&
|
|
2093
|
+
(isStatementKeyword(token()) || token() === Token.EndOfFile) &&
|
|
2094
|
+
token() !== kind.allowedStatementKeyword);
|
|
2095
|
+
}
|
|
2096
|
+
function parseEmptyStatement(pos) {
|
|
2097
|
+
parseExpected(Token.Semicolon);
|
|
2098
|
+
return { kind: SyntaxKind.EmptyStatement, ...finishNode(pos) };
|
|
2099
|
+
}
|
|
2100
|
+
function parseInvalidStatement(pos, decorators) {
|
|
2101
|
+
// Error recovery: avoid an avalanche of errors when we get cornered into
|
|
2102
|
+
// parsing statements where none exist. Skip until we find a statement
|
|
2103
|
+
// keyword or decorator and only report one error for a contiguous range of
|
|
2104
|
+
// neither.
|
|
2105
|
+
do {
|
|
2106
|
+
nextToken();
|
|
2107
|
+
} while (!isStatementKeyword(token()) &&
|
|
2108
|
+
token() !== Token.At &&
|
|
2109
|
+
token() !== Token.Semicolon &&
|
|
2110
|
+
token() !== Token.EndOfFile);
|
|
2111
|
+
error({
|
|
2112
|
+
code: "token-expected",
|
|
2113
|
+
messageId: "statement",
|
|
2114
|
+
target: { pos, end: previousTokenEnd },
|
|
2115
|
+
});
|
|
2116
|
+
return { kind: SyntaxKind.InvalidStatement, decorators, ...finishNode(pos) };
|
|
2117
|
+
}
|
|
2118
|
+
function error(report) {
|
|
2119
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2120
|
+
parseErrorInNextFinishedNode = true;
|
|
2121
|
+
const location = {
|
|
2122
|
+
file: scanner.file,
|
|
2123
|
+
pos: (_b = (_a = report.target) === null || _a === void 0 ? void 0 : _a.pos) !== null && _b !== void 0 ? _b : tokenPos(),
|
|
2124
|
+
end: (_d = (_c = report.target) === null || _c === void 0 ? void 0 : _c.end) !== null && _d !== void 0 ? _d : tokenEnd(),
|
|
2125
|
+
};
|
|
2126
|
+
if (!report.printable) {
|
|
2127
|
+
treePrintable = false;
|
|
2128
|
+
}
|
|
2129
|
+
// Error recovery: don't report more than 1 consecutive error at the same
|
|
2130
|
+
// position. The code path taken by error recovery after logging an error
|
|
2131
|
+
// can otherwise produce redundant and less decipherable errors, which this
|
|
2132
|
+
// suppresses.
|
|
2133
|
+
const realPos = (_f = (_e = report.target) === null || _e === void 0 ? void 0 : _e.realPos) !== null && _f !== void 0 ? _f : location.pos;
|
|
2134
|
+
if (realPositionOfLastError === realPos) {
|
|
2135
|
+
return;
|
|
2136
|
+
}
|
|
2137
|
+
realPositionOfLastError = realPos;
|
|
2138
|
+
const diagnostic = createDiagnostic({
|
|
2139
|
+
...report,
|
|
2140
|
+
target: location,
|
|
2141
|
+
});
|
|
2142
|
+
assert(diagnostic.severity === "error", "This function is for reporting errors. Use warning() for warnings.");
|
|
2143
|
+
parseDiagnostics.push(diagnostic);
|
|
2144
|
+
}
|
|
2145
|
+
function warning(report) {
|
|
2146
|
+
var _a, _b, _c, _d;
|
|
2147
|
+
const location = {
|
|
2148
|
+
file: scanner.file,
|
|
2149
|
+
pos: (_b = (_a = report.target) === null || _a === void 0 ? void 0 : _a.pos) !== null && _b !== void 0 ? _b : tokenPos(),
|
|
2150
|
+
end: (_d = (_c = report.target) === null || _c === void 0 ? void 0 : _c.end) !== null && _d !== void 0 ? _d : tokenEnd(),
|
|
2151
|
+
};
|
|
2152
|
+
const diagnostic = createDiagnostic({
|
|
2153
|
+
...report,
|
|
2154
|
+
target: location,
|
|
2155
|
+
});
|
|
2156
|
+
assert(diagnostic.severity === "warning", "This function is for reporting warnings only. Use error() for errors.");
|
|
2157
|
+
parseDiagnostics.push(diagnostic);
|
|
2158
|
+
}
|
|
2159
|
+
function reportDiagnostic(diagnostic) {
|
|
2160
|
+
if (diagnostic.severity === "error") {
|
|
2161
|
+
parseErrorInNextFinishedNode = true;
|
|
2162
|
+
treePrintable = false;
|
|
2163
|
+
}
|
|
2164
|
+
parseDiagnostics.push(diagnostic);
|
|
2165
|
+
}
|
|
2166
|
+
function assert(condition, message) {
|
|
2167
|
+
const location = {
|
|
2168
|
+
file: scanner.file,
|
|
2169
|
+
pos: tokenPos(),
|
|
2170
|
+
end: tokenEnd(),
|
|
2171
|
+
};
|
|
2172
|
+
compilerAssert(condition, message, location);
|
|
2173
|
+
}
|
|
2174
|
+
function reportInvalidDecorators(decorators, nodeName) {
|
|
2175
|
+
for (const decorator of decorators) {
|
|
2176
|
+
error({ code: "invalid-decorator-location", format: { nodeName }, target: decorator });
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
function reportInvalidDirective(directives, nodeName) {
|
|
2180
|
+
for (const directive of directives) {
|
|
2181
|
+
error({ code: "invalid-directive-location", format: { nodeName }, target: directive });
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
function parseExpected(expectedToken) {
|
|
2185
|
+
if (token() === expectedToken) {
|
|
2186
|
+
nextToken();
|
|
2187
|
+
return true;
|
|
2188
|
+
}
|
|
2189
|
+
const location = getAdjustedDefaultLocation(expectedToken);
|
|
2190
|
+
error({
|
|
2191
|
+
code: "token-expected",
|
|
2192
|
+
format: { token: TokenDisplay[expectedToken] },
|
|
2193
|
+
target: location,
|
|
2194
|
+
printable: isPunctuation(expectedToken),
|
|
2195
|
+
});
|
|
2196
|
+
return false;
|
|
2197
|
+
}
|
|
2198
|
+
function expectTokenIsOneOf(...args) {
|
|
2199
|
+
const tok = token();
|
|
2200
|
+
for (const expected of args) {
|
|
2201
|
+
if (expected === Token.None) {
|
|
2202
|
+
continue;
|
|
2203
|
+
}
|
|
2204
|
+
if (tok === expected) {
|
|
2205
|
+
return tok;
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
errorTokenIsNotOneOf(...args);
|
|
2209
|
+
return Token.None;
|
|
2210
|
+
}
|
|
2211
|
+
function parseExpectedOneOf(...args) {
|
|
2212
|
+
const tok = expectTokenIsOneOf(...args);
|
|
2213
|
+
if (tok !== Token.None) {
|
|
2214
|
+
nextToken();
|
|
2215
|
+
}
|
|
2216
|
+
return tok;
|
|
2217
|
+
}
|
|
2218
|
+
function errorTokenIsNotOneOf(...args) {
|
|
2219
|
+
const location = getAdjustedDefaultLocation(args[0]);
|
|
2220
|
+
const displayList = args.map((t, i) => {
|
|
2221
|
+
if (i === args.length - 1) {
|
|
2222
|
+
return `or ${TokenDisplay[t]}`;
|
|
2223
|
+
}
|
|
2224
|
+
return TokenDisplay[t];
|
|
2225
|
+
});
|
|
2226
|
+
error({ code: "token-expected", format: { token: displayList.join(", ") }, target: location });
|
|
2227
|
+
}
|
|
2228
|
+
function parseOptional(optionalToken) {
|
|
2229
|
+
if (token() === optionalToken) {
|
|
2230
|
+
nextToken();
|
|
2231
|
+
return true;
|
|
2232
|
+
}
|
|
2233
|
+
return false;
|
|
2234
|
+
}
|
|
2235
|
+
function getAdjustedDefaultLocation(token) {
|
|
2236
|
+
// Put the squiggly immediately after prior token when missing punctuation.
|
|
2237
|
+
// Avoids saying ';' is expected far away after a long comment, for example.
|
|
2238
|
+
// It's also confusing to squiggle the current token even if its nearby
|
|
2239
|
+
// in this case.
|
|
2240
|
+
return isPunctuation(token)
|
|
2241
|
+
? { pos: previousTokenEnd, end: previousTokenEnd + 1, realPos: tokenPos() }
|
|
2242
|
+
: undefined;
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
export function visitChildren(node, cb) {
|
|
2246
|
+
if (node.directives) {
|
|
2247
|
+
const result = visitEach(cb, node.directives);
|
|
2248
|
+
if (result)
|
|
2249
|
+
return result;
|
|
2250
|
+
}
|
|
2251
|
+
if (node.docs) {
|
|
2252
|
+
const result = visitEach(cb, node.docs);
|
|
2253
|
+
if (result)
|
|
2254
|
+
return result;
|
|
2255
|
+
}
|
|
2256
|
+
switch (node.kind) {
|
|
2257
|
+
case SyntaxKind.TypeSpecScript:
|
|
2258
|
+
return visitNode(cb, node.id) || visitEach(cb, node.statements);
|
|
2259
|
+
case SyntaxKind.ArrayExpression:
|
|
2260
|
+
return visitNode(cb, node.elementType);
|
|
2261
|
+
case SyntaxKind.AugmentDecoratorStatement:
|
|
2262
|
+
return (visitNode(cb, node.target) ||
|
|
2263
|
+
visitNode(cb, node.targetType) ||
|
|
2264
|
+
visitEach(cb, node.arguments));
|
|
2265
|
+
case SyntaxKind.DecoratorExpression:
|
|
2266
|
+
return visitNode(cb, node.target) || visitEach(cb, node.arguments);
|
|
2267
|
+
case SyntaxKind.DirectiveExpression:
|
|
2268
|
+
return visitNode(cb, node.target) || visitEach(cb, node.arguments);
|
|
2269
|
+
case SyntaxKind.ImportStatement:
|
|
2270
|
+
return visitNode(cb, node.path);
|
|
2271
|
+
case SyntaxKind.OperationStatement:
|
|
2272
|
+
return (visitEach(cb, node.decorators) ||
|
|
2273
|
+
visitNode(cb, node.id) ||
|
|
2274
|
+
visitEach(cb, node.templateParameters) ||
|
|
2275
|
+
visitNode(cb, node.signature));
|
|
2276
|
+
case SyntaxKind.OperationSignatureDeclaration:
|
|
2277
|
+
return visitNode(cb, node.parameters) || visitNode(cb, node.returnType);
|
|
2278
|
+
case SyntaxKind.OperationSignatureReference:
|
|
2279
|
+
return visitNode(cb, node.baseOperation);
|
|
2280
|
+
case SyntaxKind.NamespaceStatement:
|
|
2281
|
+
return (visitEach(cb, node.decorators) ||
|
|
2282
|
+
visitNode(cb, node.id) ||
|
|
2283
|
+
(isArray(node.statements) ? visitEach(cb, node.statements) : visitNode(cb, node.statements)));
|
|
2284
|
+
case SyntaxKind.InterfaceStatement:
|
|
2285
|
+
return (visitEach(cb, node.decorators) ||
|
|
2286
|
+
visitNode(cb, node.id) ||
|
|
2287
|
+
visitEach(cb, node.templateParameters) ||
|
|
2288
|
+
visitEach(cb, node.extends) ||
|
|
2289
|
+
visitEach(cb, node.operations));
|
|
2290
|
+
case SyntaxKind.UsingStatement:
|
|
2291
|
+
return visitNode(cb, node.name);
|
|
2292
|
+
case SyntaxKind.IntersectionExpression:
|
|
2293
|
+
return visitEach(cb, node.options);
|
|
2294
|
+
case SyntaxKind.MemberExpression:
|
|
2295
|
+
return visitNode(cb, node.base) || visitNode(cb, node.id);
|
|
2296
|
+
case SyntaxKind.ModelExpression:
|
|
2297
|
+
return visitEach(cb, node.properties);
|
|
2298
|
+
case SyntaxKind.ModelProperty:
|
|
2299
|
+
return (visitEach(cb, node.decorators) ||
|
|
2300
|
+
visitNode(cb, node.id) ||
|
|
2301
|
+
visitNode(cb, node.value) ||
|
|
2302
|
+
visitNode(cb, node.default));
|
|
2303
|
+
case SyntaxKind.ModelSpreadProperty:
|
|
2304
|
+
return visitNode(cb, node.target);
|
|
2305
|
+
case SyntaxKind.ModelStatement:
|
|
2306
|
+
return (visitEach(cb, node.decorators) ||
|
|
2307
|
+
visitNode(cb, node.id) ||
|
|
2308
|
+
visitEach(cb, node.templateParameters) ||
|
|
2309
|
+
visitNode(cb, node.extends) ||
|
|
2310
|
+
visitNode(cb, node.is) ||
|
|
2311
|
+
visitEach(cb, node.properties));
|
|
2312
|
+
case SyntaxKind.ScalarStatement:
|
|
2313
|
+
return (visitEach(cb, node.decorators) ||
|
|
2314
|
+
visitNode(cb, node.id) ||
|
|
2315
|
+
visitEach(cb, node.templateParameters) ||
|
|
2316
|
+
visitNode(cb, node.extends));
|
|
2317
|
+
case SyntaxKind.UnionStatement:
|
|
2318
|
+
return (visitEach(cb, node.decorators) ||
|
|
2319
|
+
visitNode(cb, node.id) ||
|
|
2320
|
+
visitEach(cb, node.templateParameters) ||
|
|
2321
|
+
visitEach(cb, node.options));
|
|
2322
|
+
case SyntaxKind.UnionVariant:
|
|
2323
|
+
return visitEach(cb, node.decorators) || visitNode(cb, node.id) || visitNode(cb, node.value);
|
|
2324
|
+
case SyntaxKind.EnumStatement:
|
|
2325
|
+
return (visitEach(cb, node.decorators) || visitNode(cb, node.id) || visitEach(cb, node.members));
|
|
2326
|
+
case SyntaxKind.EnumMember:
|
|
2327
|
+
return visitEach(cb, node.decorators) || visitNode(cb, node.id) || visitNode(cb, node.value);
|
|
2328
|
+
case SyntaxKind.EnumSpreadMember:
|
|
2329
|
+
return visitNode(cb, node.target);
|
|
2330
|
+
case SyntaxKind.AliasStatement:
|
|
2331
|
+
return (visitNode(cb, node.id) ||
|
|
2332
|
+
visitEach(cb, node.templateParameters) ||
|
|
2333
|
+
visitNode(cb, node.value));
|
|
2334
|
+
case SyntaxKind.DecoratorDeclarationStatement:
|
|
2335
|
+
return (visitEach(cb, node.modifiers) ||
|
|
2336
|
+
visitNode(cb, node.id) ||
|
|
2337
|
+
visitNode(cb, node.target) ||
|
|
2338
|
+
visitEach(cb, node.parameters));
|
|
2339
|
+
case SyntaxKind.FunctionDeclarationStatement:
|
|
2340
|
+
return (visitEach(cb, node.modifiers) ||
|
|
2341
|
+
visitNode(cb, node.id) ||
|
|
2342
|
+
visitEach(cb, node.parameters) ||
|
|
2343
|
+
visitNode(cb, node.returnType));
|
|
2344
|
+
case SyntaxKind.FunctionParameter:
|
|
2345
|
+
return visitNode(cb, node.id) || visitNode(cb, node.type);
|
|
2346
|
+
case SyntaxKind.TypeReference:
|
|
2347
|
+
return visitNode(cb, node.target) || visitEach(cb, node.arguments);
|
|
2348
|
+
case SyntaxKind.TupleExpression:
|
|
2349
|
+
return visitEach(cb, node.values);
|
|
2350
|
+
case SyntaxKind.UnionExpression:
|
|
2351
|
+
return visitEach(cb, node.options);
|
|
2352
|
+
case SyntaxKind.Projection:
|
|
2353
|
+
return (visitNode(cb, node.directionId) ||
|
|
2354
|
+
visitEach(cb, node.parameters) ||
|
|
2355
|
+
visitEach(cb, node.body));
|
|
2356
|
+
case SyntaxKind.ProjectionExpressionStatement:
|
|
2357
|
+
return visitNode(cb, node.expr);
|
|
2358
|
+
case SyntaxKind.ProjectionCallExpression:
|
|
2359
|
+
return visitNode(cb, node.target) || visitEach(cb, node.arguments);
|
|
2360
|
+
case SyntaxKind.ProjectionMemberExpression:
|
|
2361
|
+
return visitNode(cb, node.base) || visitNode(cb, node.id);
|
|
2362
|
+
// binops
|
|
2363
|
+
case SyntaxKind.ProjectionLogicalExpression:
|
|
2364
|
+
case SyntaxKind.ProjectionRelationalExpression:
|
|
2365
|
+
case SyntaxKind.ProjectionArithmeticExpression:
|
|
2366
|
+
case SyntaxKind.ProjectionEqualityExpression:
|
|
2367
|
+
return visitNode(cb, node.left) || visitNode(cb, node.right);
|
|
2368
|
+
case SyntaxKind.ProjectionUnaryExpression:
|
|
2369
|
+
return visitNode(cb, node.target);
|
|
2370
|
+
case SyntaxKind.ProjectionModelExpression:
|
|
2371
|
+
return visitEach(cb, node.properties);
|
|
2372
|
+
case SyntaxKind.ProjectionModelProperty:
|
|
2373
|
+
return (visitEach(cb, node.decorators) ||
|
|
2374
|
+
visitNode(cb, node.id) ||
|
|
2375
|
+
visitNode(cb, node.value) ||
|
|
2376
|
+
visitNode(cb, node.default));
|
|
2377
|
+
case SyntaxKind.ProjectionModelSpreadProperty:
|
|
2378
|
+
return visitNode(cb, node.target);
|
|
2379
|
+
case SyntaxKind.ProjectionTupleExpression:
|
|
2380
|
+
return visitEach(cb, node.values);
|
|
2381
|
+
case SyntaxKind.ProjectionBlockExpression:
|
|
2382
|
+
return visitEach(cb, node.statements);
|
|
2383
|
+
case SyntaxKind.ProjectionIfExpression:
|
|
2384
|
+
return (visitNode(cb, node.test) || visitNode(cb, node.consequent) || visitNode(cb, node.alternate));
|
|
2385
|
+
case SyntaxKind.ProjectionLambdaExpression:
|
|
2386
|
+
return visitEach(cb, node.parameters) || visitNode(cb, node.body);
|
|
2387
|
+
case SyntaxKind.ProjectionStatement:
|
|
2388
|
+
return (visitNode(cb, node.id) ||
|
|
2389
|
+
visitNode(cb, node.selector) ||
|
|
2390
|
+
visitNode(cb, node.from) ||
|
|
2391
|
+
visitNode(cb, node.to));
|
|
2392
|
+
case SyntaxKind.ProjectionDecoratorReferenceExpression:
|
|
2393
|
+
return visitNode(cb, node.target);
|
|
2394
|
+
case SyntaxKind.Return:
|
|
2395
|
+
return visitNode(cb, node.value);
|
|
2396
|
+
case SyntaxKind.InvalidStatement:
|
|
2397
|
+
return visitEach(cb, node.decorators);
|
|
2398
|
+
case SyntaxKind.TemplateParameterDeclaration:
|
|
2399
|
+
return (visitNode(cb, node.id) || visitNode(cb, node.constraint) || visitNode(cb, node.default));
|
|
2400
|
+
case SyntaxKind.ProjectionLambdaParameterDeclaration:
|
|
2401
|
+
return visitNode(cb, node.id);
|
|
2402
|
+
case SyntaxKind.ProjectionParameterDeclaration:
|
|
2403
|
+
return visitNode(cb, node.id);
|
|
2404
|
+
case SyntaxKind.Doc:
|
|
2405
|
+
return visitEach(cb, node.content) || visitEach(cb, node.tags);
|
|
2406
|
+
case SyntaxKind.DocParamTag:
|
|
2407
|
+
case SyntaxKind.DocTemplateTag:
|
|
2408
|
+
return (visitNode(cb, node.tagName) || visitNode(cb, node.paramName) || visitEach(cb, node.content));
|
|
2409
|
+
case SyntaxKind.DocReturnsTag:
|
|
2410
|
+
case SyntaxKind.DocUnknownTag:
|
|
2411
|
+
return visitNode(cb, node.tagName) || visitEach(cb, node.content);
|
|
2412
|
+
// no children for the rest of these.
|
|
2413
|
+
case SyntaxKind.StringLiteral:
|
|
2414
|
+
case SyntaxKind.NumericLiteral:
|
|
2415
|
+
case SyntaxKind.BooleanLiteral:
|
|
2416
|
+
case SyntaxKind.Identifier:
|
|
2417
|
+
case SyntaxKind.EmptyStatement:
|
|
2418
|
+
case SyntaxKind.ProjectionModelSelector:
|
|
2419
|
+
case SyntaxKind.ProjectionUnionSelector:
|
|
2420
|
+
case SyntaxKind.ProjectionInterfaceSelector:
|
|
2421
|
+
case SyntaxKind.ProjectionOperationSelector:
|
|
2422
|
+
case SyntaxKind.ProjectionEnumSelector:
|
|
2423
|
+
case SyntaxKind.VoidKeyword:
|
|
2424
|
+
case SyntaxKind.NeverKeyword:
|
|
2425
|
+
case SyntaxKind.ExternKeyword:
|
|
2426
|
+
case SyntaxKind.UnknownKeyword:
|
|
2427
|
+
case SyntaxKind.JsSourceFile:
|
|
2428
|
+
case SyntaxKind.DocText:
|
|
2429
|
+
return;
|
|
2430
|
+
default:
|
|
2431
|
+
// Dummy const to ensure we handle all node types.
|
|
2432
|
+
// If you get an error here, add a case for the new node type
|
|
2433
|
+
// you added..
|
|
2434
|
+
const _assertNever = node;
|
|
2435
|
+
return;
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
function visitNode(cb, node) {
|
|
2439
|
+
return node && cb(node);
|
|
2440
|
+
}
|
|
2441
|
+
function visitEach(cb, nodes) {
|
|
2442
|
+
if (!nodes) {
|
|
2443
|
+
return;
|
|
2444
|
+
}
|
|
2445
|
+
for (const node of nodes) {
|
|
2446
|
+
const result = cb(node);
|
|
2447
|
+
if (result) {
|
|
2448
|
+
return result;
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
return;
|
|
2452
|
+
}
|
|
2453
|
+
/**
|
|
2454
|
+
* Resolve the node in the syntax tree that that is at the given position.
|
|
2455
|
+
* @param script TypeSpec Script node
|
|
2456
|
+
* @param position Position
|
|
2457
|
+
* @param filter Filter if wanting to return a parent containing node early.
|
|
2458
|
+
*/
|
|
2459
|
+
export function getNodeAtPosition(script, position, filter = (node) => true) {
|
|
2460
|
+
return visit(script);
|
|
2461
|
+
function visit(node) {
|
|
2462
|
+
// We deliberately include the end position here because we need to hit
|
|
2463
|
+
// nodes when the cursor is positioned immediately after an identifier.
|
|
2464
|
+
// This is especially vital for completion. It's also generally OK
|
|
2465
|
+
// because the language doesn't (and should never) have syntax where you
|
|
2466
|
+
// could place the cursor ambiguously between two adjacent,
|
|
2467
|
+
// non-punctuation, non-trivia tokens that have no punctuation or trivia
|
|
2468
|
+
// separating them.
|
|
2469
|
+
if (node.pos <= position && position <= node.end) {
|
|
2470
|
+
// We only need to recursively visit children of nodes that satisfied
|
|
2471
|
+
// the condition above and therefore contain the given position. If a
|
|
2472
|
+
// node does not contain a position, then neither do its children.
|
|
2473
|
+
const child = visitChildren(node, visit);
|
|
2474
|
+
// A child match here is better than a self-match below as we want the
|
|
2475
|
+
// deepest (most specific) node. In other words, the search is depth
|
|
2476
|
+
// first. For example, consider `A<B<C>>`: If the cursor is on `B`,
|
|
2477
|
+
// then prefer B<C> over A<B<C>>.
|
|
2478
|
+
if (child) {
|
|
2479
|
+
return child;
|
|
2480
|
+
}
|
|
2481
|
+
if (filter(node)) {
|
|
2482
|
+
return node;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
return undefined;
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
export function hasParseError(node) {
|
|
2489
|
+
if (node.flags & 2 /* NodeFlags.ThisNodeHasError */) {
|
|
2490
|
+
return true;
|
|
2491
|
+
}
|
|
2492
|
+
checkForDescendantErrors(node);
|
|
2493
|
+
return node.flags & 4 /* NodeFlags.DescendantHasError */;
|
|
2494
|
+
}
|
|
2495
|
+
function checkForDescendantErrors(node) {
|
|
2496
|
+
if (node.flags & 1 /* NodeFlags.DescendantErrorsExamined */) {
|
|
2497
|
+
return;
|
|
2498
|
+
}
|
|
2499
|
+
mutate(node).flags |= 1 /* NodeFlags.DescendantErrorsExamined */;
|
|
2500
|
+
visitChildren(node, (child) => {
|
|
2501
|
+
if (child.flags & 2 /* NodeFlags.ThisNodeHasError */) {
|
|
2502
|
+
mutate(node).flags |= 4 /* NodeFlags.DescendantHasError */ | 1 /* NodeFlags.DescendantErrorsExamined */;
|
|
2503
|
+
return true;
|
|
2504
|
+
}
|
|
2505
|
+
checkForDescendantErrors(child);
|
|
2506
|
+
if (child.flags & 4 /* NodeFlags.DescendantHasError */) {
|
|
2507
|
+
mutate(node).flags |= 4 /* NodeFlags.DescendantHasError */ | 1 /* NodeFlags.DescendantErrorsExamined */;
|
|
2508
|
+
return true;
|
|
2509
|
+
}
|
|
2510
|
+
mutate(child).flags |= 1 /* NodeFlags.DescendantErrorsExamined */;
|
|
2511
|
+
return false;
|
|
2512
|
+
});
|
|
2513
|
+
}
|
|
2514
|
+
export function isImportStatement(node) {
|
|
2515
|
+
return node.kind === SyntaxKind.ImportStatement;
|
|
2516
|
+
}
|
|
2517
|
+
function isBlocklessNamespace(node) {
|
|
2518
|
+
if (node.kind !== SyntaxKind.NamespaceStatement) {
|
|
2519
|
+
return false;
|
|
2520
|
+
}
|
|
2521
|
+
while (!isArray(node.statements) && node.statements) {
|
|
2522
|
+
node = node.statements;
|
|
2523
|
+
}
|
|
2524
|
+
return node.statements === undefined;
|
|
2525
|
+
}
|
|
2526
|
+
export function getFirstAncestor(node, test) {
|
|
2527
|
+
for (let n = node.parent; n; n = n.parent) {
|
|
2528
|
+
if (test(n)) {
|
|
2529
|
+
return n;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
return undefined;
|
|
2533
|
+
}
|
|
2534
|
+
export function getIdentifierContext(id) {
|
|
2535
|
+
const node = getFirstAncestor(id, (n) => n.kind !== SyntaxKind.MemberExpression);
|
|
2536
|
+
compilerAssert(node, "Identifier with no non-member-expression ancestor.");
|
|
2537
|
+
let kind;
|
|
2538
|
+
switch (node.kind) {
|
|
2539
|
+
case SyntaxKind.TypeReference:
|
|
2540
|
+
kind = IdentifierKind.TypeReference;
|
|
2541
|
+
break;
|
|
2542
|
+
case SyntaxKind.AugmentDecoratorStatement:
|
|
2543
|
+
case SyntaxKind.DecoratorExpression:
|
|
2544
|
+
kind = IdentifierKind.Decorator;
|
|
2545
|
+
break;
|
|
2546
|
+
case SyntaxKind.ProjectionCallExpression:
|
|
2547
|
+
kind = IdentifierKind.Function;
|
|
2548
|
+
break;
|
|
2549
|
+
case SyntaxKind.UsingStatement:
|
|
2550
|
+
kind = IdentifierKind.Using;
|
|
2551
|
+
break;
|
|
2552
|
+
default:
|
|
2553
|
+
kind =
|
|
2554
|
+
id.parent.id === id
|
|
2555
|
+
? IdentifierKind.Declaration
|
|
2556
|
+
: IdentifierKind.Other;
|
|
2557
|
+
break;
|
|
2558
|
+
}
|
|
2559
|
+
return { node, kind };
|
|
2560
|
+
}
|
|
2561
|
+
//# sourceMappingURL=parser.js.map
|