@typespec/compiler 0.57.0-dev.27 → 0.57.0-dev.28
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/manifest.js +2 -2
- 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/parser.d.ts +11 -3
- package/dist/src/core/parser.d.ts.map +1 -1
- package/dist/src/core/parser.js +143 -66
- package/dist/src/core/parser.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 +57 -1
- package/dist/src/core/scanner.js.map +1 -1
- package/dist/src/core/types.d.ts +30 -1
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/core/types.js.map +1 -1
- package/dist/src/server/completion.d.ts +1 -1
- package/dist/src/server/completion.d.ts.map +1 -1
- package/dist/src/server/completion.js +119 -31
- package/dist/src/server/completion.js.map +1 -1
- package/dist/src/server/serverlib.js +1 -17
- package/dist/src/server/serverlib.js.map +1 -1
- package/package.json +1 -1
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,
|
|
@@ -2476,10 +2492,11 @@ function createParser(code, options = {}) {
|
|
|
2476
2492
|
}
|
|
2477
2493
|
function createMissingTypeReference() {
|
|
2478
2494
|
const pos = tokenPos();
|
|
2495
|
+
const { items: args } = createEmptyList();
|
|
2479
2496
|
return {
|
|
2480
2497
|
kind: SyntaxKind.TypeReference,
|
|
2481
2498
|
target: createMissingIdentifier(),
|
|
2482
|
-
arguments:
|
|
2499
|
+
arguments: args,
|
|
2483
2500
|
...finishNode(pos),
|
|
2484
2501
|
};
|
|
2485
2502
|
}
|
|
@@ -2492,6 +2509,12 @@ function createParser(code, options = {}) {
|
|
|
2492
2509
|
function withSymbol(obj) {
|
|
2493
2510
|
return obj;
|
|
2494
2511
|
}
|
|
2512
|
+
function createEmptyList(range = { pos: -1, end: -1 }) {
|
|
2513
|
+
return {
|
|
2514
|
+
items: [],
|
|
2515
|
+
range,
|
|
2516
|
+
};
|
|
2517
|
+
}
|
|
2495
2518
|
/**
|
|
2496
2519
|
* Parse a delimited list of elements, including the surrounding open and
|
|
2497
2520
|
* close punctuation
|
|
@@ -2508,13 +2531,17 @@ function createParser(code, options = {}) {
|
|
|
2508
2531
|
* do not go through here.
|
|
2509
2532
|
*/
|
|
2510
2533
|
function parseList(kind, parseItem) {
|
|
2534
|
+
const r = createEmptyList();
|
|
2511
2535
|
if (kind.open !== Token.None) {
|
|
2512
|
-
|
|
2536
|
+
const t = tokenPos();
|
|
2537
|
+
if (parseExpected(kind.open)) {
|
|
2538
|
+
mutate(r.range).pos = t;
|
|
2539
|
+
}
|
|
2513
2540
|
}
|
|
2514
2541
|
if (kind.allowEmpty && parseOptional(kind.close)) {
|
|
2515
|
-
|
|
2542
|
+
mutate(r.range).end = previousTokenEnd;
|
|
2543
|
+
return r;
|
|
2516
2544
|
}
|
|
2517
|
-
const items = [];
|
|
2518
2545
|
while (true) {
|
|
2519
2546
|
const startingPos = tokenPos();
|
|
2520
2547
|
const { pos, docs, directives, decorators } = parseAnnotations({
|
|
@@ -2529,7 +2556,9 @@ function createParser(code, options = {}) {
|
|
|
2529
2556
|
// of file. Note, however, that we must parse a missing element if
|
|
2530
2557
|
// there were directives or decorators as we cannot drop those from
|
|
2531
2558
|
// the tree.
|
|
2532
|
-
parseExpected(kind.close)
|
|
2559
|
+
if (parseExpected(kind.close)) {
|
|
2560
|
+
mutate(r.range).end = previousTokenEnd;
|
|
2561
|
+
}
|
|
2533
2562
|
break;
|
|
2534
2563
|
}
|
|
2535
2564
|
let item;
|
|
@@ -2541,12 +2570,13 @@ function createParser(code, options = {}) {
|
|
|
2541
2570
|
mutate(item).docs = docs;
|
|
2542
2571
|
mutate(item).directives = directives;
|
|
2543
2572
|
}
|
|
2544
|
-
items.push(item);
|
|
2573
|
+
r.items.push(item);
|
|
2545
2574
|
const delimiter = token();
|
|
2546
2575
|
const delimiterPos = tokenPos();
|
|
2547
2576
|
if (parseOptionalDelimiter(kind)) {
|
|
2548
2577
|
// Delimiter found: check if it's trailing.
|
|
2549
2578
|
if (parseOptional(kind.close)) {
|
|
2579
|
+
mutate(r.range).end = previousTokenEnd;
|
|
2550
2580
|
if (!kind.trailingDelimiterIsValid) {
|
|
2551
2581
|
error({
|
|
2552
2582
|
code: "trailing-token",
|
|
@@ -2570,6 +2600,7 @@ function createParser(code, options = {}) {
|
|
|
2570
2600
|
break;
|
|
2571
2601
|
}
|
|
2572
2602
|
else if (parseOptional(kind.close)) {
|
|
2603
|
+
mutate(r.range).end = previousTokenEnd;
|
|
2573
2604
|
// If a list *is* surrounded by punctuation, then the list ends when we
|
|
2574
2605
|
// reach the close token.
|
|
2575
2606
|
break;
|
|
@@ -2580,7 +2611,9 @@ function createParser(code, options = {}) {
|
|
|
2580
2611
|
// assumption that the closing delimiter is missing. This check is
|
|
2581
2612
|
// duplicated from above to preempt the parseExpected(delimeter)
|
|
2582
2613
|
// below.
|
|
2583
|
-
parseExpected(kind.close)
|
|
2614
|
+
if (parseExpected(kind.close)) {
|
|
2615
|
+
mutate(r.range).end = previousTokenEnd;
|
|
2616
|
+
}
|
|
2584
2617
|
break;
|
|
2585
2618
|
}
|
|
2586
2619
|
else {
|
|
@@ -2599,21 +2632,23 @@ function createParser(code, options = {}) {
|
|
|
2599
2632
|
//
|
|
2600
2633
|
// Simple repro: `model M { ]` would loop forever without this check.
|
|
2601
2634
|
//
|
|
2602
|
-
parseExpected(kind.close)
|
|
2635
|
+
if (parseExpected(kind.close)) {
|
|
2636
|
+
mutate(r.range).end = previousTokenEnd;
|
|
2637
|
+
}
|
|
2603
2638
|
nextToken();
|
|
2604
2639
|
// remove the item that was entirely inserted by error recovery.
|
|
2605
|
-
items.pop();
|
|
2640
|
+
r.items.pop();
|
|
2606
2641
|
break;
|
|
2607
2642
|
}
|
|
2608
2643
|
}
|
|
2609
|
-
return
|
|
2644
|
+
return r;
|
|
2610
2645
|
}
|
|
2611
2646
|
/**
|
|
2612
2647
|
* Parse a delimited list with surrounding open and close punctuation if the
|
|
2613
2648
|
* open token is present. Otherwise, return an empty list.
|
|
2614
2649
|
*/
|
|
2615
2650
|
function parseOptionalList(kind, parseItem) {
|
|
2616
|
-
return token() === kind.open ? parseList(kind, parseItem) :
|
|
2651
|
+
return token() === kind.open ? parseList(kind, parseItem) : createEmptyList();
|
|
2617
2652
|
}
|
|
2618
2653
|
function parseOptionalDelimiter(kind) {
|
|
2619
2654
|
if (parseOptional(kind.delimiter)) {
|
|
@@ -3027,19 +3062,58 @@ function visitEach(cb, nodes) {
|
|
|
3027
3062
|
}
|
|
3028
3063
|
return;
|
|
3029
3064
|
}
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
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
|
+
}
|
|
3037
3101
|
return {
|
|
3038
|
-
node,
|
|
3039
|
-
|
|
3102
|
+
node: cur,
|
|
3103
|
+
char,
|
|
3040
3104
|
preChar,
|
|
3041
3105
|
nextChar,
|
|
3042
|
-
|
|
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
|
+
},
|
|
3043
3117
|
};
|
|
3044
3118
|
}
|
|
3045
3119
|
export function getNodeAtPosition(script, position, filter = (node) => true) {
|
|
@@ -3109,7 +3183,10 @@ function isBlocklessNamespace(node) {
|
|
|
3109
3183
|
}
|
|
3110
3184
|
return node.statements === undefined;
|
|
3111
3185
|
}
|
|
3112
|
-
export function getFirstAncestor(node, test) {
|
|
3186
|
+
export function getFirstAncestor(node, test, includeSelf = false) {
|
|
3187
|
+
if (includeSelf && test(node)) {
|
|
3188
|
+
return node;
|
|
3189
|
+
}
|
|
3113
3190
|
for (let n = node.parent; n; n = n.parent) {
|
|
3114
3191
|
if (test(n)) {
|
|
3115
3192
|
return n;
|