@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.
@@ -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
- extends: extendList,
470
+ bodyRange,
471
+ extends: extendList.items,
470
472
  decorators,
471
473
  ...finishNode(pos),
472
474
  };
473
475
  }
474
476
  function parseTemplateParameterList() {
475
- const list = parseOptionalList(ListKind.TemplateParameters, parseTemplateParameter);
477
+ const detail = parseOptionalList(ListKind.TemplateParameters, parseTemplateParameter);
476
478
  let setDefault = false;
477
- for (const item of list) {
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 list;
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 properties = [];
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
- properties = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
630
+ propDetail = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
626
631
  }
627
632
  }
628
633
  else {
629
- properties = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
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: parseList(ListKind.FunctionArguments, parseExpression),
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
- let [target, ...parameters] = parseFunctionParameters();
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
- parseExpected(kind.open);
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
- return [];
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 items;
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
- export function getNodeAtPositionDetail(script, position, filter) {
3031
- const node = getNodeAtPosition(script, position, filter);
3032
- if (!node)
3033
- return undefined;
3034
- const char = script.file.text.charCodeAt(position);
3035
- const preChar = position >= 0 ? script.file.text.charCodeAt(position - 1) : NaN;
3036
- const nextChar = position < script.file.text.length ? script.file.text.charCodeAt(position + 1) : NaN;
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
- position,
3102
+ node: cur,
3103
+ char,
3040
3104
  preChar,
3041
3105
  nextChar,
3042
- char,
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;