@typespec/compiler 0.57.0-dev.8 → 0.58.0-dev.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/dist/generated-defs/TypeSpec.d.ts +30 -24
- package/dist/generated-defs/TypeSpec.d.ts.map +1 -1
- package/dist/generated-defs/TypeSpec.ts-test.js +2 -1
- package/dist/generated-defs/TypeSpec.ts-test.js.map +1 -1
- package/dist/manifest.js +2 -2
- package/dist/src/config/config-schema.d.ts +1 -1
- package/dist/src/config/config-schema.d.ts.map +1 -1
- package/dist/src/core/charcode.d.ts +4 -1
- package/dist/src/core/charcode.d.ts.map +1 -1
- package/dist/src/core/charcode.js +4 -4
- package/dist/src/core/charcode.js.map +1 -1
- package/dist/src/core/checker.d.ts.map +1 -1
- package/dist/src/core/checker.js +284 -18
- package/dist/src/core/checker.js.map +1 -1
- package/dist/src/core/cli/utils.d.ts.map +1 -1
- package/dist/src/core/cli/utils.js +1 -0
- package/dist/src/core/cli/utils.js.map +1 -1
- package/dist/src/core/index.d.ts +1 -0
- package/dist/src/core/index.d.ts.map +1 -1
- package/dist/src/core/index.js +1 -0
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/core/linter.d.ts +5 -1
- package/dist/src/core/linter.d.ts.map +1 -1
- package/dist/src/core/linter.js +32 -13
- package/dist/src/core/linter.js.map +1 -1
- package/dist/src/core/messages.d.ts +5 -0
- package/dist/src/core/messages.d.ts.map +1 -1
- package/dist/src/core/messages.js +1 -0
- package/dist/src/core/messages.js.map +1 -1
- package/dist/src/core/parser.d.ts +11 -2
- package/dist/src/core/parser.d.ts.map +1 -1
- package/dist/src/core/parser.js +216 -60
- package/dist/src/core/parser.js.map +1 -1
- package/dist/src/core/program.d.ts.map +1 -1
- package/dist/src/core/program.js +4 -2
- package/dist/src/core/program.js.map +1 -1
- package/dist/src/core/scanner.d.ts +17 -1
- package/dist/src/core/scanner.d.ts.map +1 -1
- package/dist/src/core/scanner.js +97 -1
- package/dist/src/core/scanner.js.map +1 -1
- package/dist/src/core/schema-validator.js +1 -1
- package/dist/src/core/schema-validator.js.map +1 -1
- package/dist/src/core/types.d.ts +103 -50
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/core/types.js +50 -46
- package/dist/src/core/types.js.map +1 -1
- package/dist/src/emitter-framework/asset-emitter.js +2 -2
- package/dist/src/emitter-framework/asset-emitter.js.map +1 -1
- package/dist/src/emitter-framework/type-emitter.d.ts +1 -1
- package/dist/src/emitter-framework/type-emitter.js +1 -1
- package/dist/src/formatter/print/printer.d.ts +1 -1
- package/dist/src/formatter/print/printer.d.ts.map +1 -1
- package/dist/src/formatter/print/printer.js +91 -12
- package/dist/src/formatter/print/printer.js.map +1 -1
- package/dist/src/init/init-template.d.ts +1 -1
- package/dist/src/init/init-template.d.ts.map +1 -1
- package/dist/src/lib/decorators.d.ts +2 -1
- package/dist/src/lib/decorators.d.ts.map +1 -1
- package/dist/src/lib/decorators.js +17 -0
- package/dist/src/lib/decorators.js.map +1 -1
- package/dist/src/server/classify.d.ts.map +1 -1
- package/dist/src/server/classify.js +4 -0
- package/dist/src/server/classify.js.map +1 -1
- package/dist/src/server/compile-service.d.ts +2 -2
- package/dist/src/server/compile-service.d.ts.map +1 -1
- package/dist/src/server/compile-service.js +26 -1
- package/dist/src/server/compile-service.js.map +1 -1
- package/dist/src/server/completion.d.ts +2 -2
- package/dist/src/server/completion.d.ts.map +1 -1
- package/dist/src/server/completion.js +136 -9
- package/dist/src/server/completion.js.map +1 -1
- package/dist/src/server/file-system-cache.d.ts +3 -1
- package/dist/src/server/file-system-cache.d.ts.map +1 -1
- package/dist/src/server/file-system-cache.js +13 -2
- package/dist/src/server/file-system-cache.js.map +1 -1
- package/dist/src/server/server.js +35 -8
- package/dist/src/server/server.js.map +1 -1
- package/dist/src/server/serverlib.d.ts.map +1 -1
- package/dist/src/server/serverlib.js +13 -31
- package/dist/src/server/serverlib.js.map +1 -1
- package/dist/src/server/tmlanguage.d.ts.map +1 -1
- package/dist/src/server/tmlanguage.js +1 -1
- package/dist/src/server/tmlanguage.js.map +1 -1
- package/dist/src/server/type-details.js +14 -6
- package/dist/src/server/type-details.js.map +1 -1
- package/dist/src/server/types.d.ts +9 -3
- package/dist/src/server/types.d.ts.map +1 -1
- package/dist/src/server/types.js.map +1 -1
- package/dist/src/testing/test-server-host.js +2 -2
- package/dist/src/testing/test-server-host.js.map +1 -1
- package/dist/typespec.tmLanguage +1 -1
- package/lib/std/decorators.tsp +6 -0
- package/lib/std/types.tsp +12 -0
- package/package.json +11 -11
- package/templates/scaffolding.json +4 -4
package/dist/src/core/parser.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isArray, mutate } from "../utils/misc.js";
|
|
2
|
-
import { trim } from "./charcode.js";
|
|
2
|
+
import { codePointBefore, isIdentifierContinue, trim } from "./charcode.js";
|
|
3
3
|
import { compilerAssert } from "./diagnostics.js";
|
|
4
4
|
import { createDiagnostic } from "./messages.js";
|
|
5
|
-
import { Token, TokenDisplay, TokenFlags, createScanner, isComment, isKeyword, isPunctuation, isStatementKeyword, isTrivia, } from "./scanner.js";
|
|
5
|
+
import { Token, TokenDisplay, TokenFlags, createScanner, isComment, isKeyword, isPunctuation, isStatementKeyword, isTrivia, skipContinuousIdentifier, skipTrivia, skipTriviaBackward, } from "./scanner.js";
|
|
6
6
|
import { IdentifierKind, SyntaxKind, } from "./types.js";
|
|
7
7
|
/**
|
|
8
8
|
* The fixed set of options for each of the kinds of delimited lists in TypeSpec.
|
|
@@ -450,8 +450,8 @@ function createParser(code, options = {}) {
|
|
|
450
450
|
function parseInterfaceStatement(pos, decorators) {
|
|
451
451
|
parseExpected(Token.InterfaceKeyword);
|
|
452
452
|
const id = parseIdentifier();
|
|
453
|
-
const templateParameters = parseTemplateParameterList();
|
|
454
|
-
let extendList =
|
|
453
|
+
const { items: templateParameters, range: templateParametersRange } = parseTemplateParameterList();
|
|
454
|
+
let extendList = createEmptyList();
|
|
455
455
|
if (token() === Token.ExtendsKeyword) {
|
|
456
456
|
nextToken();
|
|
457
457
|
extendList = parseList(ListKind.Heritage, parseReferenceExpression);
|
|
@@ -460,21 +460,23 @@ function createParser(code, options = {}) {
|
|
|
460
460
|
error({ code: "token-expected", format: { token: "'extends' or '{'" } });
|
|
461
461
|
nextToken();
|
|
462
462
|
}
|
|
463
|
-
const operations = parseList(ListKind.InterfaceMembers, (pos, decorators) => parseOperationStatement(pos, decorators, true));
|
|
463
|
+
const { items: operations, range: bodyRange } = parseList(ListKind.InterfaceMembers, (pos, decorators) => parseOperationStatement(pos, decorators, true));
|
|
464
464
|
return {
|
|
465
465
|
kind: SyntaxKind.InterfaceStatement,
|
|
466
466
|
id,
|
|
467
467
|
templateParameters,
|
|
468
|
+
templateParametersRange,
|
|
468
469
|
operations,
|
|
469
|
-
|
|
470
|
+
bodyRange,
|
|
471
|
+
extends: extendList.items,
|
|
470
472
|
decorators,
|
|
471
473
|
...finishNode(pos),
|
|
472
474
|
};
|
|
473
475
|
}
|
|
474
476
|
function parseTemplateParameterList() {
|
|
475
|
-
const
|
|
477
|
+
const detail = parseOptionalList(ListKind.TemplateParameters, parseTemplateParameter);
|
|
476
478
|
let setDefault = false;
|
|
477
|
-
for (const item of
|
|
479
|
+
for (const item of detail.items) {
|
|
478
480
|
if (!item.default && setDefault) {
|
|
479
481
|
error({ code: "default-required", target: item });
|
|
480
482
|
continue;
|
|
@@ -483,17 +485,18 @@ function createParser(code, options = {}) {
|
|
|
483
485
|
setDefault = true;
|
|
484
486
|
}
|
|
485
487
|
}
|
|
486
|
-
return
|
|
488
|
+
return detail;
|
|
487
489
|
}
|
|
488
490
|
function parseUnionStatement(pos, decorators) {
|
|
489
491
|
parseExpected(Token.UnionKeyword);
|
|
490
492
|
const id = parseIdentifier();
|
|
491
|
-
const templateParameters = parseTemplateParameterList();
|
|
492
|
-
const options = parseList(ListKind.UnionVariants, parseUnionVariant);
|
|
493
|
+
const { items: templateParameters, range: templateParametersRange } = parseTemplateParameterList();
|
|
494
|
+
const { items: options } = parseList(ListKind.UnionVariants, parseUnionVariant);
|
|
493
495
|
return {
|
|
494
496
|
kind: SyntaxKind.UnionStatement,
|
|
495
497
|
id,
|
|
496
498
|
templateParameters,
|
|
499
|
+
templateParametersRange,
|
|
497
500
|
decorators,
|
|
498
501
|
options,
|
|
499
502
|
...finishNode(pos),
|
|
@@ -559,7 +562,7 @@ function createParser(code, options = {}) {
|
|
|
559
562
|
parseExpected(Token.OpKeyword);
|
|
560
563
|
}
|
|
561
564
|
const id = parseIdentifier();
|
|
562
|
-
const templateParameters = parseTemplateParameterList();
|
|
565
|
+
const { items: templateParameters, range: templateParametersRange } = parseTemplateParameterList();
|
|
563
566
|
// Make sure the next token is one that is expected
|
|
564
567
|
const token = expectTokenIsOneOf(Token.OpenParen, Token.IsKeyword);
|
|
565
568
|
// Check if we're parsing a declaration or reuse of another operation
|
|
@@ -593,6 +596,7 @@ function createParser(code, options = {}) {
|
|
|
593
596
|
kind: SyntaxKind.OperationStatement,
|
|
594
597
|
id,
|
|
595
598
|
templateParameters,
|
|
599
|
+
templateParametersRange,
|
|
596
600
|
signature,
|
|
597
601
|
decorators,
|
|
598
602
|
...finishNode(pos),
|
|
@@ -600,10 +604,11 @@ function createParser(code, options = {}) {
|
|
|
600
604
|
}
|
|
601
605
|
function parseOperationParameters() {
|
|
602
606
|
const pos = tokenPos();
|
|
603
|
-
const properties = parseList(ListKind.OperationParameters, parseModelPropertyOrSpread);
|
|
607
|
+
const { items: properties, range: bodyRange } = parseList(ListKind.OperationParameters, parseModelPropertyOrSpread);
|
|
604
608
|
const parameters = {
|
|
605
609
|
kind: SyntaxKind.ModelExpression,
|
|
606
610
|
properties,
|
|
611
|
+
bodyRange,
|
|
607
612
|
...finishNode(pos),
|
|
608
613
|
};
|
|
609
614
|
return parameters;
|
|
@@ -611,22 +616,22 @@ function createParser(code, options = {}) {
|
|
|
611
616
|
function parseModelStatement(pos, decorators) {
|
|
612
617
|
parseExpected(Token.ModelKeyword);
|
|
613
618
|
const id = parseIdentifier();
|
|
614
|
-
const templateParameters = parseTemplateParameterList();
|
|
619
|
+
const { items: templateParameters, range: templateParametersRange } = parseTemplateParameterList();
|
|
615
620
|
expectTokenIsOneOf(Token.OpenBrace, Token.Equals, Token.ExtendsKeyword, Token.IsKeyword);
|
|
616
621
|
const optionalExtends = parseOptionalModelExtends();
|
|
617
622
|
const optionalIs = optionalExtends ? undefined : parseOptionalModelIs();
|
|
618
|
-
let
|
|
623
|
+
let propDetail = createEmptyList();
|
|
619
624
|
if (optionalIs) {
|
|
620
625
|
const tok = expectTokenIsOneOf(Token.Semicolon, Token.OpenBrace);
|
|
621
626
|
if (tok === Token.Semicolon) {
|
|
622
627
|
nextToken();
|
|
623
628
|
}
|
|
624
629
|
else {
|
|
625
|
-
|
|
630
|
+
propDetail = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
|
|
626
631
|
}
|
|
627
632
|
}
|
|
628
633
|
else {
|
|
629
|
-
|
|
634
|
+
propDetail = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
|
|
630
635
|
}
|
|
631
636
|
return {
|
|
632
637
|
kind: SyntaxKind.ModelStatement,
|
|
@@ -634,8 +639,10 @@ function createParser(code, options = {}) {
|
|
|
634
639
|
extends: optionalExtends,
|
|
635
640
|
is: optionalIs,
|
|
636
641
|
templateParameters,
|
|
642
|
+
templateParametersRange,
|
|
637
643
|
decorators,
|
|
638
|
-
properties,
|
|
644
|
+
properties: propDetail.items,
|
|
645
|
+
bodyRange: propDetail.range,
|
|
639
646
|
...finishNode(pos),
|
|
640
647
|
};
|
|
641
648
|
}
|
|
@@ -767,15 +774,17 @@ function createParser(code, options = {}) {
|
|
|
767
774
|
function parseScalarStatement(pos, decorators) {
|
|
768
775
|
parseExpected(Token.ScalarKeyword);
|
|
769
776
|
const id = parseIdentifier();
|
|
770
|
-
const templateParameters = parseTemplateParameterList();
|
|
777
|
+
const { items: templateParameters, range: templateParametersRange } = parseTemplateParameterList();
|
|
771
778
|
const optionalExtends = parseOptionalScalarExtends();
|
|
772
|
-
const members = parseScalarMembers();
|
|
779
|
+
const { items: members, range: bodyRange } = parseScalarMembers();
|
|
773
780
|
return {
|
|
774
781
|
kind: SyntaxKind.ScalarStatement,
|
|
775
782
|
id,
|
|
776
783
|
templateParameters,
|
|
784
|
+
templateParametersRange,
|
|
777
785
|
extends: optionalExtends,
|
|
778
786
|
members,
|
|
787
|
+
bodyRange,
|
|
779
788
|
decorators,
|
|
780
789
|
...finishNode(pos),
|
|
781
790
|
};
|
|
@@ -789,7 +798,7 @@ function createParser(code, options = {}) {
|
|
|
789
798
|
function parseScalarMembers() {
|
|
790
799
|
if (token() === Token.Semicolon) {
|
|
791
800
|
nextToken();
|
|
792
|
-
return
|
|
801
|
+
return createEmptyList();
|
|
793
802
|
}
|
|
794
803
|
else {
|
|
795
804
|
return parseList(ListKind.ScalarMembers, parseScalarMember);
|
|
@@ -799,7 +808,7 @@ function createParser(code, options = {}) {
|
|
|
799
808
|
reportInvalidDecorators(decorators, "scalar member");
|
|
800
809
|
parseExpected(Token.InitKeyword);
|
|
801
810
|
const id = parseIdentifier();
|
|
802
|
-
const parameters = parseFunctionParameters();
|
|
811
|
+
const { items: parameters } = parseFunctionParameters();
|
|
803
812
|
return {
|
|
804
813
|
kind: SyntaxKind.ScalarConstructor,
|
|
805
814
|
id,
|
|
@@ -810,7 +819,7 @@ function createParser(code, options = {}) {
|
|
|
810
819
|
function parseEnumStatement(pos, decorators) {
|
|
811
820
|
parseExpected(Token.EnumKeyword);
|
|
812
821
|
const id = parseIdentifier();
|
|
813
|
-
const members = parseList(ListKind.EnumMembers, parseEnumMemberOrSpread);
|
|
822
|
+
const { items: members } = parseList(ListKind.EnumMembers, parseEnumMemberOrSpread);
|
|
814
823
|
return {
|
|
815
824
|
kind: SyntaxKind.EnumStatement,
|
|
816
825
|
id,
|
|
@@ -864,7 +873,7 @@ function createParser(code, options = {}) {
|
|
|
864
873
|
function parseAliasStatement(pos) {
|
|
865
874
|
parseExpected(Token.AliasKeyword);
|
|
866
875
|
const id = parseIdentifier();
|
|
867
|
-
const templateParameters = parseTemplateParameterList();
|
|
876
|
+
const { items: templateParameters, range: templateParametersRange } = parseTemplateParameterList();
|
|
868
877
|
parseExpected(Token.Equals);
|
|
869
878
|
const value = parseExpression();
|
|
870
879
|
parseExpected(Token.Semicolon);
|
|
@@ -872,6 +881,7 @@ function createParser(code, options = {}) {
|
|
|
872
881
|
kind: SyntaxKind.AliasStatement,
|
|
873
882
|
id,
|
|
874
883
|
templateParameters,
|
|
884
|
+
templateParametersRange,
|
|
875
885
|
value,
|
|
876
886
|
...finishNode(pos),
|
|
877
887
|
};
|
|
@@ -1011,17 +1021,18 @@ function createParser(code, options = {}) {
|
|
|
1011
1021
|
const pos = tokenPos();
|
|
1012
1022
|
const target = parseIdentifierOrMemberExpression(message);
|
|
1013
1023
|
if (token() === Token.OpenParen) {
|
|
1024
|
+
const { items: args } = parseList(ListKind.FunctionArguments, parseExpression);
|
|
1014
1025
|
return {
|
|
1015
1026
|
kind: SyntaxKind.CallExpression,
|
|
1016
1027
|
target,
|
|
1017
|
-
arguments:
|
|
1028
|
+
arguments: args,
|
|
1018
1029
|
...finishNode(pos),
|
|
1019
1030
|
};
|
|
1020
1031
|
}
|
|
1021
1032
|
return parseReferenceExpressionInternal(target, pos);
|
|
1022
1033
|
}
|
|
1023
1034
|
function parseReferenceExpressionInternal(target, pos) {
|
|
1024
|
-
const args = parseOptionalList(ListKind.TemplateArguments, parseTemplateArgument);
|
|
1035
|
+
const { items: args } = parseOptionalList(ListKind.TemplateArguments, parseTemplateArgument);
|
|
1025
1036
|
return {
|
|
1026
1037
|
kind: SyntaxKind.TypeReference,
|
|
1027
1038
|
target,
|
|
@@ -1072,29 +1083,31 @@ function createParser(code, options = {}) {
|
|
|
1072
1083
|
// `@<missing identifier>` applied to `model Foo`, and not as `@model`
|
|
1073
1084
|
// applied to invalid statement `Foo`.
|
|
1074
1085
|
const target = parseIdentifierOrMemberExpression(undefined, false);
|
|
1075
|
-
const args = parseOptionalList(ListKind.DecoratorArguments, parseExpression);
|
|
1086
|
+
const { items: args } = parseOptionalList(ListKind.DecoratorArguments, parseExpression);
|
|
1076
1087
|
if (args.length === 0) {
|
|
1077
1088
|
error({ code: "augment-decorator-target" });
|
|
1089
|
+
const emptyList = createEmptyList();
|
|
1078
1090
|
return {
|
|
1079
1091
|
kind: SyntaxKind.AugmentDecoratorStatement,
|
|
1080
1092
|
target,
|
|
1081
1093
|
targetType: {
|
|
1082
1094
|
kind: SyntaxKind.TypeReference,
|
|
1083
1095
|
target: createMissingIdentifier(),
|
|
1084
|
-
arguments:
|
|
1096
|
+
arguments: emptyList.items,
|
|
1085
1097
|
...finishNode(pos),
|
|
1086
1098
|
},
|
|
1087
|
-
arguments:
|
|
1099
|
+
arguments: args,
|
|
1088
1100
|
...finishNode(pos),
|
|
1089
1101
|
};
|
|
1090
1102
|
}
|
|
1091
1103
|
let [targetEntity, ...decoratorArgs] = args;
|
|
1092
1104
|
if (targetEntity.kind !== SyntaxKind.TypeReference) {
|
|
1093
1105
|
error({ code: "augment-decorator-target", target: targetEntity });
|
|
1106
|
+
const emptyList = createEmptyList();
|
|
1094
1107
|
targetEntity = {
|
|
1095
1108
|
kind: SyntaxKind.TypeReference,
|
|
1096
1109
|
target: createMissingIdentifier(),
|
|
1097
|
-
arguments:
|
|
1110
|
+
arguments: emptyList.items,
|
|
1098
1111
|
...finishNode(pos),
|
|
1099
1112
|
};
|
|
1100
1113
|
}
|
|
@@ -1126,7 +1139,7 @@ function createParser(code, options = {}) {
|
|
|
1126
1139
|
// `@<missing identifier>` applied to `model Foo`, and not as `@model`
|
|
1127
1140
|
// applied to invalid statement `Foo`.
|
|
1128
1141
|
const target = parseIdentifierOrMemberExpression(undefined, false);
|
|
1129
|
-
const args = parseOptionalList(ListKind.DecoratorArguments, parseExpression);
|
|
1142
|
+
const { items: args } = parseOptionalList(ListKind.DecoratorArguments, parseExpression);
|
|
1130
1143
|
return {
|
|
1131
1144
|
kind: SyntaxKind.DecoratorExpression,
|
|
1132
1145
|
arguments: args,
|
|
@@ -1310,7 +1323,7 @@ function createParser(code, options = {}) {
|
|
|
1310
1323
|
}
|
|
1311
1324
|
function parseTupleExpression() {
|
|
1312
1325
|
const pos = tokenPos();
|
|
1313
|
-
const values = parseList(ListKind.Tuple, parseExpression);
|
|
1326
|
+
const { items: values } = parseList(ListKind.Tuple, parseExpression);
|
|
1314
1327
|
return {
|
|
1315
1328
|
kind: SyntaxKind.TupleExpression,
|
|
1316
1329
|
values,
|
|
@@ -1319,25 +1332,27 @@ function createParser(code, options = {}) {
|
|
|
1319
1332
|
}
|
|
1320
1333
|
function parseModelExpression() {
|
|
1321
1334
|
const pos = tokenPos();
|
|
1322
|
-
const properties = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
|
|
1335
|
+
const { items: properties, range: bodyRange } = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
|
|
1323
1336
|
return {
|
|
1324
1337
|
kind: SyntaxKind.ModelExpression,
|
|
1325
1338
|
properties,
|
|
1339
|
+
bodyRange,
|
|
1326
1340
|
...finishNode(pos),
|
|
1327
1341
|
};
|
|
1328
1342
|
}
|
|
1329
1343
|
function parseObjectLiteral() {
|
|
1330
1344
|
const pos = tokenPos();
|
|
1331
|
-
const properties = parseList(ListKind.ObjectLiteralProperties, parseObjectLiteralPropertyOrSpread);
|
|
1345
|
+
const { items: properties, range: bodyRange } = parseList(ListKind.ObjectLiteralProperties, parseObjectLiteralPropertyOrSpread);
|
|
1332
1346
|
return {
|
|
1333
1347
|
kind: SyntaxKind.ObjectLiteral,
|
|
1334
1348
|
properties,
|
|
1349
|
+
bodyRange,
|
|
1335
1350
|
...finishNode(pos),
|
|
1336
1351
|
};
|
|
1337
1352
|
}
|
|
1338
1353
|
function parseArrayLiteral() {
|
|
1339
1354
|
const pos = tokenPos();
|
|
1340
|
-
const values = parseList(ListKind.ArrayLiteral, parseExpression);
|
|
1355
|
+
const { items: values } = parseList(ListKind.ArrayLiteral, parseExpression);
|
|
1341
1356
|
return {
|
|
1342
1357
|
kind: SyntaxKind.ArrayLiteral,
|
|
1343
1358
|
values,
|
|
@@ -1510,7 +1525,8 @@ function createParser(code, options = {}) {
|
|
|
1510
1525
|
const modifierFlags = modifiersToFlags(modifiers);
|
|
1511
1526
|
parseExpected(Token.DecKeyword);
|
|
1512
1527
|
const id = parseIdentifier();
|
|
1513
|
-
|
|
1528
|
+
const allParamListDetail = parseFunctionParameters();
|
|
1529
|
+
let [target, ...parameters] = allParamListDetail.items;
|
|
1514
1530
|
if (target === undefined) {
|
|
1515
1531
|
error({ code: "decorator-decl-target", target: { pos, end: previousTokenEnd } });
|
|
1516
1532
|
target = {
|
|
@@ -1540,7 +1556,7 @@ function createParser(code, options = {}) {
|
|
|
1540
1556
|
const modifierFlags = modifiersToFlags(modifiers);
|
|
1541
1557
|
parseExpected(Token.FnKeyword);
|
|
1542
1558
|
const id = parseIdentifier();
|
|
1543
|
-
const parameters = parseFunctionParameters();
|
|
1559
|
+
const { items: parameters } = parseFunctionParameters();
|
|
1544
1560
|
let returnType;
|
|
1545
1561
|
if (parseOptional(Token.Colon)) {
|
|
1546
1562
|
returnType = parseExpression();
|
|
@@ -1559,7 +1575,7 @@ function createParser(code, options = {}) {
|
|
|
1559
1575
|
function parseFunctionParameters() {
|
|
1560
1576
|
const parameters = parseList(ListKind.FunctionParameters, parseFunctionParameter);
|
|
1561
1577
|
let foundOptional = false;
|
|
1562
|
-
for (const [index, item] of parameters.entries()) {
|
|
1578
|
+
for (const [index, item] of parameters.items.entries()) {
|
|
1563
1579
|
if (!item.optional && foundOptional) {
|
|
1564
1580
|
error({ code: "required-parameter-first", target: item });
|
|
1565
1581
|
continue;
|
|
@@ -1570,7 +1586,7 @@ function createParser(code, options = {}) {
|
|
|
1570
1586
|
if (item.rest && item.optional) {
|
|
1571
1587
|
error({ code: "rest-parameter-required", target: item });
|
|
1572
1588
|
}
|
|
1573
|
-
if (item.rest && index !== parameters.length - 1) {
|
|
1589
|
+
if (item.rest && index !== parameters.items.length - 1) {
|
|
1574
1590
|
error({ code: "rest-parameter-last", target: item });
|
|
1575
1591
|
}
|
|
1576
1592
|
}
|
|
@@ -1662,7 +1678,7 @@ function createParser(code, options = {}) {
|
|
|
1662
1678
|
}
|
|
1663
1679
|
let parameters;
|
|
1664
1680
|
if (token() === Token.OpenParen) {
|
|
1665
|
-
parameters = parseList(ListKind.ProjectionParameter, parseProjectionParameter);
|
|
1681
|
+
parameters = parseList(ListKind.ProjectionParameter, parseProjectionParameter).items;
|
|
1666
1682
|
}
|
|
1667
1683
|
else {
|
|
1668
1684
|
parameters = [];
|
|
@@ -1884,7 +1900,7 @@ function createParser(code, options = {}) {
|
|
|
1884
1900
|
kind: SyntaxKind.ProjectionCallExpression,
|
|
1885
1901
|
callKind: "method",
|
|
1886
1902
|
target: expr,
|
|
1887
|
-
arguments: parseList(ListKind.CallArguments, parseProjectionExpression),
|
|
1903
|
+
arguments: parseList(ListKind.CallArguments, parseProjectionExpression).items,
|
|
1888
1904
|
...finishNode(pos),
|
|
1889
1905
|
};
|
|
1890
1906
|
}
|
|
@@ -1967,7 +1983,7 @@ function createParser(code, options = {}) {
|
|
|
1967
1983
|
}
|
|
1968
1984
|
function parseProjectionLambdaOrParenthesizedExpression() {
|
|
1969
1985
|
const pos = tokenPos();
|
|
1970
|
-
const exprs = parseList(ListKind.ProjectionExpression, parseProjectionExpression);
|
|
1986
|
+
const exprs = parseList(ListKind.ProjectionExpression, parseProjectionExpression).items;
|
|
1971
1987
|
if (token() === Token.EqualsGreaterThan) {
|
|
1972
1988
|
// unpack the exprs (which should be just identifiers) into a param list
|
|
1973
1989
|
const params = [];
|
|
@@ -2018,7 +2034,7 @@ function createParser(code, options = {}) {
|
|
|
2018
2034
|
}
|
|
2019
2035
|
function parseProjectionModelExpression() {
|
|
2020
2036
|
const pos = tokenPos();
|
|
2021
|
-
const properties = parseList(ListKind.ModelProperties, parseProjectionModelPropertyOrSpread);
|
|
2037
|
+
const { items: properties } = parseList(ListKind.ModelProperties, parseProjectionModelPropertyOrSpread);
|
|
2022
2038
|
return {
|
|
2023
2039
|
kind: SyntaxKind.ProjectionModelExpression,
|
|
2024
2040
|
properties,
|
|
@@ -2092,7 +2108,7 @@ function createParser(code, options = {}) {
|
|
|
2092
2108
|
}
|
|
2093
2109
|
function parseProjectionTupleExpression() {
|
|
2094
2110
|
const pos = tokenPos();
|
|
2095
|
-
const values = parseList(ListKind.Tuple, parseProjectionExpression);
|
|
2111
|
+
const { items: values } = parseList(ListKind.Tuple, parseProjectionExpression);
|
|
2096
2112
|
return {
|
|
2097
2113
|
kind: SyntaxKind.ProjectionTupleExpression,
|
|
2098
2114
|
values,
|
|
@@ -2242,11 +2258,31 @@ function createParser(code, options = {}) {
|
|
|
2242
2258
|
start = tokenPos();
|
|
2243
2259
|
while (parseOptional(Token.Whitespace))
|
|
2244
2260
|
;
|
|
2245
|
-
if (parseOptional(Token.Star)) {
|
|
2261
|
+
if (!parseOptional(Token.Star)) {
|
|
2262
|
+
break;
|
|
2263
|
+
}
|
|
2264
|
+
if (!inCodeFence) {
|
|
2246
2265
|
parseOptional(Token.Whitespace);
|
|
2247
2266
|
start = tokenPos();
|
|
2248
2267
|
break;
|
|
2249
2268
|
}
|
|
2269
|
+
// If we are in a code fence we want to preserve the leading whitespace
|
|
2270
|
+
// except for the first space after the star which is used as indentation.
|
|
2271
|
+
const whitespaceStart = tokenPos();
|
|
2272
|
+
parseOptional(Token.Whitespace);
|
|
2273
|
+
// This `min` handles the case when there is no whitespace after the
|
|
2274
|
+
// star e.g. a case like this:
|
|
2275
|
+
//
|
|
2276
|
+
// /**
|
|
2277
|
+
// *```
|
|
2278
|
+
// *foo-bar
|
|
2279
|
+
// *```
|
|
2280
|
+
// */
|
|
2281
|
+
//
|
|
2282
|
+
// Not having space after the star isn't idiomatic, but we support this.
|
|
2283
|
+
// `whitespaceStart + 1` strips the first space before `foo-bar` if there
|
|
2284
|
+
// is a space after the star (the idiomatic case).
|
|
2285
|
+
start = Math.min(whitespaceStart + 1, tokenPos());
|
|
2250
2286
|
break;
|
|
2251
2287
|
case Token.EndOfFile:
|
|
2252
2288
|
break loop;
|
|
@@ -2256,6 +2292,12 @@ function createParser(code, options = {}) {
|
|
|
2256
2292
|
}
|
|
2257
2293
|
nextToken();
|
|
2258
2294
|
break;
|
|
2295
|
+
case Token.DocText:
|
|
2296
|
+
parts.push(source.substring(start, tokenPos()));
|
|
2297
|
+
parts.push(tokenValue());
|
|
2298
|
+
nextToken();
|
|
2299
|
+
start = tokenPos();
|
|
2300
|
+
break;
|
|
2259
2301
|
default:
|
|
2260
2302
|
nextToken();
|
|
2261
2303
|
break;
|
|
@@ -2285,6 +2327,8 @@ function createParser(code, options = {}) {
|
|
|
2285
2327
|
return parseDocParamLikeTag(pos, tagName, SyntaxKind.DocParamTag, "param");
|
|
2286
2328
|
case "template":
|
|
2287
2329
|
return parseDocParamLikeTag(pos, tagName, SyntaxKind.DocTemplateTag, "templateParam");
|
|
2330
|
+
case "prop":
|
|
2331
|
+
return parseDocPropTag(pos, tagName);
|
|
2288
2332
|
case "return":
|
|
2289
2333
|
case "returns":
|
|
2290
2334
|
return parseDocSimpleTag(pos, tagName, SyntaxKind.DocReturnsTag);
|
|
@@ -2299,9 +2343,7 @@ function createParser(code, options = {}) {
|
|
|
2299
2343
|
* For example, `@param` and `@template`.
|
|
2300
2344
|
*/
|
|
2301
2345
|
function parseDocParamLikeTag(pos, tagName, kind, messageId) {
|
|
2302
|
-
const name =
|
|
2303
|
-
parseOptionalHyphenDocParamLikeTag();
|
|
2304
|
-
const content = parseDocContent();
|
|
2346
|
+
const { name, content } = parseDocParamLikeTagInternal(messageId);
|
|
2305
2347
|
return {
|
|
2306
2348
|
kind,
|
|
2307
2349
|
tagName,
|
|
@@ -2310,6 +2352,22 @@ function createParser(code, options = {}) {
|
|
|
2310
2352
|
...finishNode(pos),
|
|
2311
2353
|
};
|
|
2312
2354
|
}
|
|
2355
|
+
function parseDocPropTag(pos, tagName) {
|
|
2356
|
+
const { name, content } = parseDocParamLikeTagInternal("prop");
|
|
2357
|
+
return {
|
|
2358
|
+
kind: SyntaxKind.DocPropTag,
|
|
2359
|
+
tagName,
|
|
2360
|
+
propName: name,
|
|
2361
|
+
content,
|
|
2362
|
+
...finishNode(pos),
|
|
2363
|
+
};
|
|
2364
|
+
}
|
|
2365
|
+
function parseDocParamLikeTagInternal(messageId) {
|
|
2366
|
+
const name = parseDocIdentifier(messageId);
|
|
2367
|
+
parseOptionalHyphenDocParamLikeTag();
|
|
2368
|
+
const content = parseDocContent();
|
|
2369
|
+
return { name, content };
|
|
2370
|
+
}
|
|
2313
2371
|
/**
|
|
2314
2372
|
* Handles the optional hyphen in param-like documentation comment tags.
|
|
2315
2373
|
*
|
|
@@ -2434,10 +2492,11 @@ function createParser(code, options = {}) {
|
|
|
2434
2492
|
}
|
|
2435
2493
|
function createMissingTypeReference() {
|
|
2436
2494
|
const pos = tokenPos();
|
|
2495
|
+
const { items: args } = createEmptyList();
|
|
2437
2496
|
return {
|
|
2438
2497
|
kind: SyntaxKind.TypeReference,
|
|
2439
2498
|
target: createMissingIdentifier(),
|
|
2440
|
-
arguments:
|
|
2499
|
+
arguments: args,
|
|
2441
2500
|
...finishNode(pos),
|
|
2442
2501
|
};
|
|
2443
2502
|
}
|
|
@@ -2450,6 +2509,12 @@ function createParser(code, options = {}) {
|
|
|
2450
2509
|
function withSymbol(obj) {
|
|
2451
2510
|
return obj;
|
|
2452
2511
|
}
|
|
2512
|
+
function createEmptyList(range = { pos: -1, end: -1 }) {
|
|
2513
|
+
return {
|
|
2514
|
+
items: [],
|
|
2515
|
+
range,
|
|
2516
|
+
};
|
|
2517
|
+
}
|
|
2453
2518
|
/**
|
|
2454
2519
|
* Parse a delimited list of elements, including the surrounding open and
|
|
2455
2520
|
* close punctuation
|
|
@@ -2466,13 +2531,17 @@ function createParser(code, options = {}) {
|
|
|
2466
2531
|
* do not go through here.
|
|
2467
2532
|
*/
|
|
2468
2533
|
function parseList(kind, parseItem) {
|
|
2534
|
+
const r = createEmptyList();
|
|
2469
2535
|
if (kind.open !== Token.None) {
|
|
2470
|
-
|
|
2536
|
+
const t = tokenPos();
|
|
2537
|
+
if (parseExpected(kind.open)) {
|
|
2538
|
+
mutate(r.range).pos = t;
|
|
2539
|
+
}
|
|
2471
2540
|
}
|
|
2472
2541
|
if (kind.allowEmpty && parseOptional(kind.close)) {
|
|
2473
|
-
|
|
2542
|
+
mutate(r.range).end = previousTokenEnd;
|
|
2543
|
+
return r;
|
|
2474
2544
|
}
|
|
2475
|
-
const items = [];
|
|
2476
2545
|
while (true) {
|
|
2477
2546
|
const startingPos = tokenPos();
|
|
2478
2547
|
const { pos, docs, directives, decorators } = parseAnnotations({
|
|
@@ -2487,7 +2556,9 @@ function createParser(code, options = {}) {
|
|
|
2487
2556
|
// of file. Note, however, that we must parse a missing element if
|
|
2488
2557
|
// there were directives or decorators as we cannot drop those from
|
|
2489
2558
|
// the tree.
|
|
2490
|
-
parseExpected(kind.close)
|
|
2559
|
+
if (parseExpected(kind.close)) {
|
|
2560
|
+
mutate(r.range).end = previousTokenEnd;
|
|
2561
|
+
}
|
|
2491
2562
|
break;
|
|
2492
2563
|
}
|
|
2493
2564
|
let item;
|
|
@@ -2499,12 +2570,13 @@ function createParser(code, options = {}) {
|
|
|
2499
2570
|
mutate(item).docs = docs;
|
|
2500
2571
|
mutate(item).directives = directives;
|
|
2501
2572
|
}
|
|
2502
|
-
items.push(item);
|
|
2573
|
+
r.items.push(item);
|
|
2503
2574
|
const delimiter = token();
|
|
2504
2575
|
const delimiterPos = tokenPos();
|
|
2505
2576
|
if (parseOptionalDelimiter(kind)) {
|
|
2506
2577
|
// Delimiter found: check if it's trailing.
|
|
2507
2578
|
if (parseOptional(kind.close)) {
|
|
2579
|
+
mutate(r.range).end = previousTokenEnd;
|
|
2508
2580
|
if (!kind.trailingDelimiterIsValid) {
|
|
2509
2581
|
error({
|
|
2510
2582
|
code: "trailing-token",
|
|
@@ -2528,6 +2600,7 @@ function createParser(code, options = {}) {
|
|
|
2528
2600
|
break;
|
|
2529
2601
|
}
|
|
2530
2602
|
else if (parseOptional(kind.close)) {
|
|
2603
|
+
mutate(r.range).end = previousTokenEnd;
|
|
2531
2604
|
// If a list *is* surrounded by punctuation, then the list ends when we
|
|
2532
2605
|
// reach the close token.
|
|
2533
2606
|
break;
|
|
@@ -2538,7 +2611,9 @@ function createParser(code, options = {}) {
|
|
|
2538
2611
|
// assumption that the closing delimiter is missing. This check is
|
|
2539
2612
|
// duplicated from above to preempt the parseExpected(delimeter)
|
|
2540
2613
|
// below.
|
|
2541
|
-
parseExpected(kind.close)
|
|
2614
|
+
if (parseExpected(kind.close)) {
|
|
2615
|
+
mutate(r.range).end = previousTokenEnd;
|
|
2616
|
+
}
|
|
2542
2617
|
break;
|
|
2543
2618
|
}
|
|
2544
2619
|
else {
|
|
@@ -2557,21 +2632,23 @@ function createParser(code, options = {}) {
|
|
|
2557
2632
|
//
|
|
2558
2633
|
// Simple repro: `model M { ]` would loop forever without this check.
|
|
2559
2634
|
//
|
|
2560
|
-
parseExpected(kind.close)
|
|
2635
|
+
if (parseExpected(kind.close)) {
|
|
2636
|
+
mutate(r.range).end = previousTokenEnd;
|
|
2637
|
+
}
|
|
2561
2638
|
nextToken();
|
|
2562
2639
|
// remove the item that was entirely inserted by error recovery.
|
|
2563
|
-
items.pop();
|
|
2640
|
+
r.items.pop();
|
|
2564
2641
|
break;
|
|
2565
2642
|
}
|
|
2566
2643
|
}
|
|
2567
|
-
return
|
|
2644
|
+
return r;
|
|
2568
2645
|
}
|
|
2569
2646
|
/**
|
|
2570
2647
|
* Parse a delimited list with surrounding open and close punctuation if the
|
|
2571
2648
|
* open token is present. Otherwise, return an empty list.
|
|
2572
2649
|
*/
|
|
2573
2650
|
function parseOptionalList(kind, parseItem) {
|
|
2574
|
-
return token() === kind.open ? parseList(kind, parseItem) :
|
|
2651
|
+
return token() === kind.open ? parseList(kind, parseItem) : createEmptyList();
|
|
2575
2652
|
}
|
|
2576
2653
|
function parseOptionalDelimiter(kind) {
|
|
2577
2654
|
if (parseOptional(kind.delimiter)) {
|
|
@@ -2918,6 +2995,8 @@ export function visitChildren(node, cb) {
|
|
|
2918
2995
|
case SyntaxKind.DocParamTag:
|
|
2919
2996
|
case SyntaxKind.DocTemplateTag:
|
|
2920
2997
|
return (visitNode(cb, node.tagName) || visitNode(cb, node.paramName) || visitEach(cb, node.content));
|
|
2998
|
+
case SyntaxKind.DocPropTag:
|
|
2999
|
+
return (visitNode(cb, node.tagName) || visitNode(cb, node.propName) || visitEach(cb, node.content));
|
|
2921
3000
|
case SyntaxKind.DocReturnsTag:
|
|
2922
3001
|
case SyntaxKind.DocErrorsTag:
|
|
2923
3002
|
case SyntaxKind.DocUnknownTag:
|
|
@@ -2983,6 +3062,60 @@ function visitEach(cb, nodes) {
|
|
|
2983
3062
|
}
|
|
2984
3063
|
return;
|
|
2985
3064
|
}
|
|
3065
|
+
/**
|
|
3066
|
+
* check whether a position belongs to a range (excluding the start and end pos)
|
|
3067
|
+
* i.e. <range.pos>{<start to return true>...<end to return true>}<range.end>
|
|
3068
|
+
*
|
|
3069
|
+
* remark: if range.pos is -1 means no start point found, so return false
|
|
3070
|
+
* if range.end is -1 means no end point found, so return true if position is greater than range.pos
|
|
3071
|
+
*/
|
|
3072
|
+
export function positionInRange(position, range) {
|
|
3073
|
+
return range.pos >= 0 && position > range.pos && (range.end === -1 || position < range.end);
|
|
3074
|
+
}
|
|
3075
|
+
export function getNodeAtPositionDetail(script, position, filter = () => true) {
|
|
3076
|
+
const cur = getNodeAtPosition(script, position, (n) => filter(n, "cur"));
|
|
3077
|
+
const input = script.file.text;
|
|
3078
|
+
const char = input.charCodeAt(position);
|
|
3079
|
+
const preChar = position >= 0 ? input.charCodeAt(position - 1) : NaN;
|
|
3080
|
+
const nextChar = position < input.length ? input.charCodeAt(position + 1) : NaN;
|
|
3081
|
+
let inTrivia = false;
|
|
3082
|
+
let triviaStart;
|
|
3083
|
+
let triviaEnd;
|
|
3084
|
+
if (!cur || cur.kind !== SyntaxKind.StringLiteral) {
|
|
3085
|
+
const { char: cp } = codePointBefore(input, position);
|
|
3086
|
+
if (!cp || !isIdentifierContinue(cp)) {
|
|
3087
|
+
triviaEnd = skipTrivia(input, position);
|
|
3088
|
+
triviaStart = skipTriviaBackward(script, position) + 1;
|
|
3089
|
+
inTrivia = triviaEnd !== position;
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
if (!inTrivia) {
|
|
3093
|
+
const beforeId = skipContinuousIdentifier(input, position, true /*isBackward*/);
|
|
3094
|
+
triviaStart = skipTriviaBackward(script, beforeId) + 1;
|
|
3095
|
+
const afterId = skipContinuousIdentifier(input, position, false /*isBackward*/);
|
|
3096
|
+
triviaEnd = skipTrivia(input, afterId);
|
|
3097
|
+
}
|
|
3098
|
+
if (triviaStart === undefined || triviaEnd === undefined) {
|
|
3099
|
+
compilerAssert(false, "unexpected, triviaStart and triviaEnd should be defined");
|
|
3100
|
+
}
|
|
3101
|
+
return {
|
|
3102
|
+
node: cur,
|
|
3103
|
+
char,
|
|
3104
|
+
preChar,
|
|
3105
|
+
nextChar,
|
|
3106
|
+
position,
|
|
3107
|
+
inTrivia,
|
|
3108
|
+
triviaStartPosition: triviaStart,
|
|
3109
|
+
triviaEndPosition: triviaEnd,
|
|
3110
|
+
getPositionDetailBeforeTrivia: () => {
|
|
3111
|
+
// getNodeAtPosition will also include the 'node.end' position which is the triviaStart pos
|
|
3112
|
+
return getNodeAtPositionDetail(script, triviaStart, (n) => filter(n, "pre"));
|
|
3113
|
+
},
|
|
3114
|
+
getPositionDetailAfterTrivia: () => {
|
|
3115
|
+
return getNodeAtPositionDetail(script, triviaEnd, (n) => filter(n, "post"));
|
|
3116
|
+
},
|
|
3117
|
+
};
|
|
3118
|
+
}
|
|
2986
3119
|
export function getNodeAtPosition(script, position, filter = (node) => true) {
|
|
2987
3120
|
return visit(script);
|
|
2988
3121
|
function visit(node) {
|
|
@@ -3050,7 +3183,10 @@ function isBlocklessNamespace(node) {
|
|
|
3050
3183
|
}
|
|
3051
3184
|
return node.statements === undefined;
|
|
3052
3185
|
}
|
|
3053
|
-
export function getFirstAncestor(node, test) {
|
|
3186
|
+
export function getFirstAncestor(node, test, includeSelf = false) {
|
|
3187
|
+
if (includeSelf && test(node)) {
|
|
3188
|
+
return node;
|
|
3189
|
+
}
|
|
3054
3190
|
for (let n = node.parent; n; n = n.parent) {
|
|
3055
3191
|
if (test(n)) {
|
|
3056
3192
|
return n;
|
|
@@ -3079,6 +3215,26 @@ export function getIdentifierContext(id) {
|
|
|
3079
3215
|
case SyntaxKind.TemplateArgument:
|
|
3080
3216
|
kind = IdentifierKind.TemplateArgument;
|
|
3081
3217
|
break;
|
|
3218
|
+
case SyntaxKind.ObjectLiteralProperty:
|
|
3219
|
+
kind = IdentifierKind.ObjectLiteralProperty;
|
|
3220
|
+
break;
|
|
3221
|
+
case SyntaxKind.ModelProperty:
|
|
3222
|
+
switch (node.parent?.kind) {
|
|
3223
|
+
case SyntaxKind.ModelExpression:
|
|
3224
|
+
kind = IdentifierKind.ModelExpressionProperty;
|
|
3225
|
+
break;
|
|
3226
|
+
case SyntaxKind.ModelStatement:
|
|
3227
|
+
kind = IdentifierKind.ModelStatementProperty;
|
|
3228
|
+
break;
|
|
3229
|
+
default:
|
|
3230
|
+
compilerAssert("false", "ModelProperty with unexpected parent kind.");
|
|
3231
|
+
kind =
|
|
3232
|
+
id.parent.id === id
|
|
3233
|
+
? IdentifierKind.Declaration
|
|
3234
|
+
: IdentifierKind.Other;
|
|
3235
|
+
break;
|
|
3236
|
+
}
|
|
3237
|
+
break;
|
|
3082
3238
|
default:
|
|
3083
3239
|
kind =
|
|
3084
3240
|
id.parent.id === id
|