@typespec/compiler 0.51.0-dev.9 → 0.52.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.
Files changed (72) hide show
  1. package/dist/manifest.js +2 -2
  2. package/dist/src/config/config-to-options.d.ts.map +1 -1
  3. package/dist/src/config/config-to-options.js +1 -0
  4. package/dist/src/config/config-to-options.js.map +1 -1
  5. package/dist/src/core/checker.d.ts.map +1 -1
  6. package/dist/src/core/checker.js +44 -1
  7. package/dist/src/core/checker.js.map +1 -1
  8. package/dist/src/core/helpers/index.d.ts +1 -0
  9. package/dist/src/core/helpers/index.d.ts.map +1 -1
  10. package/dist/src/core/helpers/index.js +1 -0
  11. package/dist/src/core/helpers/index.js.map +1 -1
  12. package/dist/src/core/helpers/string-template-utils.d.ts +11 -0
  13. package/dist/src/core/helpers/string-template-utils.d.ts.map +1 -0
  14. package/dist/src/core/helpers/string-template-utils.js +65 -0
  15. package/dist/src/core/helpers/string-template-utils.js.map +1 -0
  16. package/dist/src/core/helpers/type-name-utils.d.ts.map +1 -1
  17. package/dist/src/core/helpers/type-name-utils.js +2 -0
  18. package/dist/src/core/helpers/type-name-utils.js.map +1 -1
  19. package/dist/src/core/messages.d.ts +20 -2
  20. package/dist/src/core/messages.d.ts.map +1 -1
  21. package/dist/src/core/messages.js +6 -0
  22. package/dist/src/core/messages.js.map +1 -1
  23. package/dist/src/core/options.d.ts +1 -1
  24. package/dist/src/core/options.d.ts.map +1 -1
  25. package/dist/src/core/parser.d.ts.map +1 -1
  26. package/dist/src/core/parser.js +96 -0
  27. package/dist/src/core/parser.js.map +1 -1
  28. package/dist/src/core/program.d.ts.map +1 -1
  29. package/dist/src/core/program.js +8 -2
  30. package/dist/src/core/program.js.map +1 -1
  31. package/dist/src/core/scanner.d.ts +85 -66
  32. package/dist/src/core/scanner.d.ts.map +1 -1
  33. package/dist/src/core/scanner.js +229 -127
  34. package/dist/src/core/scanner.js.map +1 -1
  35. package/dist/src/core/schema-validator.d.ts.map +1 -1
  36. package/dist/src/core/schema-validator.js +42 -8
  37. package/dist/src/core/schema-validator.js.map +1 -1
  38. package/dist/src/core/semantic-walker.d.ts.map +1 -1
  39. package/dist/src/core/semantic-walker.js +22 -0
  40. package/dist/src/core/semantic-walker.js.map +1 -1
  41. package/dist/src/core/types.d.ts +99 -69
  42. package/dist/src/core/types.d.ts.map +1 -1
  43. package/dist/src/core/types.js +55 -50
  44. package/dist/src/core/types.js.map +1 -1
  45. package/dist/src/emitter-framework/asset-emitter.d.ts.map +1 -1
  46. package/dist/src/emitter-framework/asset-emitter.js +95 -66
  47. package/dist/src/emitter-framework/asset-emitter.js.map +1 -1
  48. package/dist/src/emitter-framework/type-emitter.d.ts +3 -1
  49. package/dist/src/emitter-framework/type-emitter.d.ts.map +1 -1
  50. package/dist/src/emitter-framework/type-emitter.js +6 -0
  51. package/dist/src/emitter-framework/type-emitter.js.map +1 -1
  52. package/dist/src/emitter-framework/types.d.ts +4 -1
  53. package/dist/src/emitter-framework/types.d.ts.map +1 -1
  54. package/dist/src/emitter-framework/types.js.map +1 -1
  55. package/dist/src/formatter/print/printer.d.ts +2 -1
  56. package/dist/src/formatter/print/printer.d.ts.map +1 -1
  57. package/dist/src/formatter/print/printer.js +17 -0
  58. package/dist/src/formatter/print/printer.js.map +1 -1
  59. package/dist/src/server/serverlib.d.ts.map +1 -1
  60. package/dist/src/server/serverlib.js +84 -6
  61. package/dist/src/server/serverlib.js.map +1 -1
  62. package/dist/src/server/tmlanguage.d.ts +1 -1
  63. package/dist/src/server/tmlanguage.d.ts.map +1 -1
  64. package/dist/src/server/tmlanguage.js +15 -2
  65. package/dist/src/server/tmlanguage.js.map +1 -1
  66. package/dist/src/server/type-signature.js +13 -0
  67. package/dist/src/server/type-signature.js.map +1 -1
  68. package/dist/src/yaml/types.d.ts +8 -0
  69. package/dist/src/yaml/types.d.ts.map +1 -1
  70. package/dist/typespec.tmLanguage +40 -0
  71. package/lib/reflection.tsp +1 -0
  72. package/package.json +4 -4
@@ -12,107 +12,110 @@ export var Token;
12
12
  Token[Token["Identifier"] = 3] = "Identifier";
13
13
  Token[Token["NumericLiteral"] = 4] = "NumericLiteral";
14
14
  Token[Token["StringLiteral"] = 5] = "StringLiteral";
15
+ Token[Token["StringTemplateHead"] = 6] = "StringTemplateHead";
16
+ Token[Token["StringTemplateMiddle"] = 7] = "StringTemplateMiddle";
17
+ Token[Token["StringTemplateTail"] = 8] = "StringTemplateTail";
15
18
  // Add new tokens above if they don't fit any of the categories below
16
19
  ///////////////////////////////////////////////////////////////
17
20
  // Trivia
18
- /**@internal */ Token[Token["__StartTrivia"] = 6] = "__StartTrivia";
19
- Token[Token["SingleLineComment"] = 6] = "SingleLineComment";
20
- Token[Token["MultiLineComment"] = 7] = "MultiLineComment";
21
- Token[Token["NewLine"] = 8] = "NewLine";
22
- Token[Token["Whitespace"] = 9] = "Whitespace";
23
- Token[Token["ConflictMarker"] = 10] = "ConflictMarker";
21
+ /**@internal */ Token[Token["__StartTrivia"] = 9] = "__StartTrivia";
22
+ Token[Token["SingleLineComment"] = 9] = "SingleLineComment";
23
+ Token[Token["MultiLineComment"] = 10] = "MultiLineComment";
24
+ Token[Token["NewLine"] = 11] = "NewLine";
25
+ Token[Token["Whitespace"] = 12] = "Whitespace";
26
+ Token[Token["ConflictMarker"] = 13] = "ConflictMarker";
24
27
  // Add new trivia above
25
- /** @internal */ Token[Token["__EndTrivia"] = 11] = "__EndTrivia";
28
+ /** @internal */ Token[Token["__EndTrivia"] = 14] = "__EndTrivia";
26
29
  ///////////////////////////////////////////////////////////////
27
30
  ///////////////////////////////////////////////////////////////
28
31
  // Doc comment content
29
- /** @internal */ Token[Token["__StartDocComment"] = 11] = "__StartDocComment";
30
- Token[Token["DocText"] = 11] = "DocText";
31
- Token[Token["DocCodeSpan"] = 12] = "DocCodeSpan";
32
- Token[Token["DocCodeFenceDelimiter"] = 13] = "DocCodeFenceDelimiter";
33
- /** @internal */ Token[Token["__EndDocComment"] = 14] = "__EndDocComment";
32
+ /** @internal */ Token[Token["__StartDocComment"] = 14] = "__StartDocComment";
33
+ Token[Token["DocText"] = 14] = "DocText";
34
+ Token[Token["DocCodeSpan"] = 15] = "DocCodeSpan";
35
+ Token[Token["DocCodeFenceDelimiter"] = 16] = "DocCodeFenceDelimiter";
36
+ /** @internal */ Token[Token["__EndDocComment"] = 17] = "__EndDocComment";
34
37
  ///////////////////////////////////////////////////////////////
35
38
  ///////////////////////////////////////////////////////////////
36
39
  // Punctuation
37
- /** @internal */ Token[Token["__StartPunctuation"] = 14] = "__StartPunctuation";
38
- Token[Token["OpenBrace"] = 14] = "OpenBrace";
39
- Token[Token["CloseBrace"] = 15] = "CloseBrace";
40
- Token[Token["OpenParen"] = 16] = "OpenParen";
41
- Token[Token["CloseParen"] = 17] = "CloseParen";
42
- Token[Token["OpenBracket"] = 18] = "OpenBracket";
43
- Token[Token["CloseBracket"] = 19] = "CloseBracket";
44
- Token[Token["Dot"] = 20] = "Dot";
45
- Token[Token["Ellipsis"] = 21] = "Ellipsis";
46
- Token[Token["Semicolon"] = 22] = "Semicolon";
47
- Token[Token["Comma"] = 23] = "Comma";
48
- Token[Token["LessThan"] = 24] = "LessThan";
49
- Token[Token["GreaterThan"] = 25] = "GreaterThan";
50
- Token[Token["Equals"] = 26] = "Equals";
51
- Token[Token["Ampersand"] = 27] = "Ampersand";
52
- Token[Token["Bar"] = 28] = "Bar";
53
- Token[Token["Question"] = 29] = "Question";
54
- Token[Token["Colon"] = 30] = "Colon";
55
- Token[Token["ColonColon"] = 31] = "ColonColon";
56
- Token[Token["At"] = 32] = "At";
57
- Token[Token["AtAt"] = 33] = "AtAt";
58
- Token[Token["Hash"] = 34] = "Hash";
59
- Token[Token["Star"] = 35] = "Star";
60
- Token[Token["ForwardSlash"] = 36] = "ForwardSlash";
61
- Token[Token["Plus"] = 37] = "Plus";
62
- Token[Token["Hyphen"] = 38] = "Hyphen";
63
- Token[Token["Exclamation"] = 39] = "Exclamation";
64
- Token[Token["LessThanEquals"] = 40] = "LessThanEquals";
65
- Token[Token["GreaterThanEquals"] = 41] = "GreaterThanEquals";
66
- Token[Token["AmpsersandAmpersand"] = 42] = "AmpsersandAmpersand";
67
- Token[Token["BarBar"] = 43] = "BarBar";
68
- Token[Token["EqualsEquals"] = 44] = "EqualsEquals";
69
- Token[Token["ExclamationEquals"] = 45] = "ExclamationEquals";
70
- Token[Token["EqualsGreaterThan"] = 46] = "EqualsGreaterThan";
40
+ /** @internal */ Token[Token["__StartPunctuation"] = 17] = "__StartPunctuation";
41
+ Token[Token["OpenBrace"] = 17] = "OpenBrace";
42
+ Token[Token["CloseBrace"] = 18] = "CloseBrace";
43
+ Token[Token["OpenParen"] = 19] = "OpenParen";
44
+ Token[Token["CloseParen"] = 20] = "CloseParen";
45
+ Token[Token["OpenBracket"] = 21] = "OpenBracket";
46
+ Token[Token["CloseBracket"] = 22] = "CloseBracket";
47
+ Token[Token["Dot"] = 23] = "Dot";
48
+ Token[Token["Ellipsis"] = 24] = "Ellipsis";
49
+ Token[Token["Semicolon"] = 25] = "Semicolon";
50
+ Token[Token["Comma"] = 26] = "Comma";
51
+ Token[Token["LessThan"] = 27] = "LessThan";
52
+ Token[Token["GreaterThan"] = 28] = "GreaterThan";
53
+ Token[Token["Equals"] = 29] = "Equals";
54
+ Token[Token["Ampersand"] = 30] = "Ampersand";
55
+ Token[Token["Bar"] = 31] = "Bar";
56
+ Token[Token["Question"] = 32] = "Question";
57
+ Token[Token["Colon"] = 33] = "Colon";
58
+ Token[Token["ColonColon"] = 34] = "ColonColon";
59
+ Token[Token["At"] = 35] = "At";
60
+ Token[Token["AtAt"] = 36] = "AtAt";
61
+ Token[Token["Hash"] = 37] = "Hash";
62
+ Token[Token["Star"] = 38] = "Star";
63
+ Token[Token["ForwardSlash"] = 39] = "ForwardSlash";
64
+ Token[Token["Plus"] = 40] = "Plus";
65
+ Token[Token["Hyphen"] = 41] = "Hyphen";
66
+ Token[Token["Exclamation"] = 42] = "Exclamation";
67
+ Token[Token["LessThanEquals"] = 43] = "LessThanEquals";
68
+ Token[Token["GreaterThanEquals"] = 44] = "GreaterThanEquals";
69
+ Token[Token["AmpsersandAmpersand"] = 45] = "AmpsersandAmpersand";
70
+ Token[Token["BarBar"] = 46] = "BarBar";
71
+ Token[Token["EqualsEquals"] = 47] = "EqualsEquals";
72
+ Token[Token["ExclamationEquals"] = 48] = "ExclamationEquals";
73
+ Token[Token["EqualsGreaterThan"] = 49] = "EqualsGreaterThan";
71
74
  // Add new punctuation above
72
- /** @internal */ Token[Token["__EndPunctuation"] = 47] = "__EndPunctuation";
75
+ /** @internal */ Token[Token["__EndPunctuation"] = 50] = "__EndPunctuation";
73
76
  ///////////////////////////////////////////////////////////////
74
77
  ///////////////////////////////////////////////////////////////
75
78
  // Statement keywords
76
- /** @internal */ Token[Token["__StartKeyword"] = 47] = "__StartKeyword";
77
- /** @internal */ Token[Token["__StartStatementKeyword"] = 47] = "__StartStatementKeyword";
78
- Token[Token["ImportKeyword"] = 47] = "ImportKeyword";
79
- Token[Token["ModelKeyword"] = 48] = "ModelKeyword";
80
- Token[Token["ScalarKeyword"] = 49] = "ScalarKeyword";
81
- Token[Token["NamespaceKeyword"] = 50] = "NamespaceKeyword";
82
- Token[Token["UsingKeyword"] = 51] = "UsingKeyword";
83
- Token[Token["OpKeyword"] = 52] = "OpKeyword";
84
- Token[Token["EnumKeyword"] = 53] = "EnumKeyword";
85
- Token[Token["AliasKeyword"] = 54] = "AliasKeyword";
86
- Token[Token["IsKeyword"] = 55] = "IsKeyword";
87
- Token[Token["InterfaceKeyword"] = 56] = "InterfaceKeyword";
88
- Token[Token["UnionKeyword"] = 57] = "UnionKeyword";
89
- Token[Token["ProjectionKeyword"] = 58] = "ProjectionKeyword";
90
- Token[Token["ElseKeyword"] = 59] = "ElseKeyword";
91
- Token[Token["IfKeyword"] = 60] = "IfKeyword";
92
- Token[Token["DecKeyword"] = 61] = "DecKeyword";
93
- Token[Token["FnKeyword"] = 62] = "FnKeyword";
94
- Token[Token["ValueOfKeyword"] = 63] = "ValueOfKeyword";
79
+ /** @internal */ Token[Token["__StartKeyword"] = 50] = "__StartKeyword";
80
+ /** @internal */ Token[Token["__StartStatementKeyword"] = 50] = "__StartStatementKeyword";
81
+ Token[Token["ImportKeyword"] = 50] = "ImportKeyword";
82
+ Token[Token["ModelKeyword"] = 51] = "ModelKeyword";
83
+ Token[Token["ScalarKeyword"] = 52] = "ScalarKeyword";
84
+ Token[Token["NamespaceKeyword"] = 53] = "NamespaceKeyword";
85
+ Token[Token["UsingKeyword"] = 54] = "UsingKeyword";
86
+ Token[Token["OpKeyword"] = 55] = "OpKeyword";
87
+ Token[Token["EnumKeyword"] = 56] = "EnumKeyword";
88
+ Token[Token["AliasKeyword"] = 57] = "AliasKeyword";
89
+ Token[Token["IsKeyword"] = 58] = "IsKeyword";
90
+ Token[Token["InterfaceKeyword"] = 59] = "InterfaceKeyword";
91
+ Token[Token["UnionKeyword"] = 60] = "UnionKeyword";
92
+ Token[Token["ProjectionKeyword"] = 61] = "ProjectionKeyword";
93
+ Token[Token["ElseKeyword"] = 62] = "ElseKeyword";
94
+ Token[Token["IfKeyword"] = 63] = "IfKeyword";
95
+ Token[Token["DecKeyword"] = 64] = "DecKeyword";
96
+ Token[Token["FnKeyword"] = 65] = "FnKeyword";
97
+ Token[Token["ValueOfKeyword"] = 66] = "ValueOfKeyword";
95
98
  // Add new statement keyword above
96
- /** @internal */ Token[Token["__EndStatementKeyword"] = 64] = "__EndStatementKeyword";
99
+ /** @internal */ Token[Token["__EndStatementKeyword"] = 67] = "__EndStatementKeyword";
97
100
  ///////////////////////////////////////////////////////////////
98
101
  ///////////////////////////////////////////////////////////////
99
- /** @internal */ Token[Token["__StartModifierKeyword"] = 64] = "__StartModifierKeyword";
100
- Token[Token["ExternKeyword"] = 64] = "ExternKeyword";
101
- /** @internal */ Token[Token["__EndModifierKeyword"] = 65] = "__EndModifierKeyword";
102
+ /** @internal */ Token[Token["__StartModifierKeyword"] = 67] = "__StartModifierKeyword";
103
+ Token[Token["ExternKeyword"] = 67] = "ExternKeyword";
104
+ /** @internal */ Token[Token["__EndModifierKeyword"] = 68] = "__EndModifierKeyword";
102
105
  ///////////////////////////////////////////////////////////////
103
106
  ///////////////////////////////////////////////////////////////
104
107
  // Other keywords
105
- Token[Token["ExtendsKeyword"] = 65] = "ExtendsKeyword";
106
- Token[Token["TrueKeyword"] = 66] = "TrueKeyword";
107
- Token[Token["FalseKeyword"] = 67] = "FalseKeyword";
108
- Token[Token["ReturnKeyword"] = 68] = "ReturnKeyword";
109
- Token[Token["VoidKeyword"] = 69] = "VoidKeyword";
110
- Token[Token["NeverKeyword"] = 70] = "NeverKeyword";
111
- Token[Token["UnknownKeyword"] = 71] = "UnknownKeyword";
108
+ Token[Token["ExtendsKeyword"] = 68] = "ExtendsKeyword";
109
+ Token[Token["TrueKeyword"] = 69] = "TrueKeyword";
110
+ Token[Token["FalseKeyword"] = 70] = "FalseKeyword";
111
+ Token[Token["ReturnKeyword"] = 71] = "ReturnKeyword";
112
+ Token[Token["VoidKeyword"] = 72] = "VoidKeyword";
113
+ Token[Token["NeverKeyword"] = 73] = "NeverKeyword";
114
+ Token[Token["UnknownKeyword"] = 74] = "UnknownKeyword";
112
115
  // Add new non-statement keyword above
113
- /** @internal */ Token[Token["__EndKeyword"] = 72] = "__EndKeyword";
116
+ /** @internal */ Token[Token["__EndKeyword"] = 75] = "__EndKeyword";
114
117
  ///////////////////////////////////////////////////////////////
115
- /** @internal */ Token[Token["__Count"] = 72] = "__Count";
118
+ /** @internal */ Token[Token["__Count"] = 75] = "__Count";
116
119
  })(Token || (Token = {}));
117
120
  /** @internal */
118
121
  export const TokenDisplay = getTokenDisplayTable([
@@ -124,6 +127,9 @@ export const TokenDisplay = getTokenDisplayTable([
124
127
  [Token.ConflictMarker, "conflict marker"],
125
128
  [Token.NumericLiteral, "numeric literal"],
126
129
  [Token.StringLiteral, "string literal"],
130
+ [Token.StringTemplateHead, "string template head"],
131
+ [Token.StringTemplateMiddle, "string template middle"],
132
+ [Token.StringTemplateTail, "string template tail"],
127
133
  [Token.NewLine, "newline"],
128
134
  [Token.Whitespace, "whitespace"],
129
135
  [Token.DocCodeFenceDelimiter, "doc code fence delimiter"],
@@ -274,6 +280,9 @@ export function createScanner(source, diagnosticHandler) {
274
280
  scan,
275
281
  scanRange,
276
282
  scanDoc,
283
+ reScanStringTemplate,
284
+ findTripleQuotedStringIndent,
285
+ unindentAndUnescapeTripleQuotedString,
277
286
  eof,
278
287
  getTokenText,
279
288
  getTokenValue,
@@ -287,7 +296,10 @@ export function createScanner(source, diagnosticHandler) {
287
296
  function getTokenValue() {
288
297
  switch (token) {
289
298
  case Token.StringLiteral:
290
- return getStringTokenValue();
299
+ case Token.StringTemplateHead:
300
+ case Token.StringTemplateMiddle:
301
+ case Token.StringTemplateTail:
302
+ return getStringTokenValue(token, tokenFlags);
291
303
  case Token.Identifier:
292
304
  return getIdentifierTokenValue();
293
305
  default:
@@ -411,8 +423,8 @@ export function createScanner(source, diagnosticHandler) {
411
423
  return lookAhead(1) === 124 /* CharCode.Bar */ ? next(Token.BarBar, 2) : next(Token.Bar);
412
424
  case 34 /* CharCode.DoubleQuote */:
413
425
  return lookAhead(1) === 34 /* CharCode.DoubleQuote */ && lookAhead(2) === 34 /* CharCode.DoubleQuote */
414
- ? scanTripleQuotedString()
415
- : scanString();
426
+ ? scanString(TokenFlags.TripleQuoted)
427
+ : scanString(TokenFlags.None);
416
428
  case 33 /* CharCode.Exclamation */:
417
429
  return lookAhead(1) === 61 /* CharCode.Equals */
418
430
  ? next(Token.ExclamationEquals, 2)
@@ -486,6 +498,11 @@ export function createScanner(source, diagnosticHandler) {
486
498
  }
487
499
  return (token = Token.EndOfFile);
488
500
  }
501
+ function reScanStringTemplate(lastTokenFlags) {
502
+ position = tokenPosition;
503
+ tokenFlags = TokenFlags.None;
504
+ return scanStringTemplateSpan(lastTokenFlags);
505
+ }
489
506
  function scanRange(range, callback) {
490
507
  const savedPosition = position;
491
508
  const savedEndPosition = endPosition;
@@ -535,10 +552,10 @@ export function createScanner(source, diagnosticHandler) {
535
552
  const codePoint = input.codePointAt(position);
536
553
  return (token = next(t, utf16CodeUnits(codePoint)));
537
554
  }
538
- function error(report) {
555
+ function error(report, pos, end) {
539
556
  const diagnostic = createDiagnostic({
540
557
  ...report,
541
- target: { file, pos: tokenPosition, end: position },
558
+ target: { file, pos: pos !== null && pos !== void 0 ? pos : tokenPosition, end: end !== null && end !== void 0 ? end : position },
542
559
  });
543
560
  diagnosticHandler(diagnostic);
544
561
  }
@@ -630,8 +647,22 @@ export function createScanner(source, diagnosticHandler) {
630
647
  }
631
648
  return unterminated(Token.DocCodeSpan);
632
649
  }
633
- function scanString() {
634
- position++; // consume '"'
650
+ function scanString(tokenFlags) {
651
+ if (tokenFlags & TokenFlags.TripleQuoted) {
652
+ position += 3; // consume '"""'
653
+ }
654
+ else {
655
+ position++; // consume '"'
656
+ }
657
+ return scanStringLiteralLike(tokenFlags, Token.StringTemplateHead, Token.StringLiteral);
658
+ }
659
+ function scanStringTemplateSpan(tokenFlags) {
660
+ position++; // consume '{'
661
+ return scanStringLiteralLike(tokenFlags, Token.StringTemplateMiddle, Token.StringTemplateTail);
662
+ }
663
+ function scanStringLiteralLike(requestedTokenFlags, template, tail) {
664
+ const multiLine = requestedTokenFlags & TokenFlags.TripleQuoted;
665
+ tokenFlags = requestedTokenFlags;
635
666
  loop: for (; !eof(); position++) {
636
667
  const ch = input.charCodeAt(position);
637
668
  switch (ch) {
@@ -643,35 +674,69 @@ export function createScanner(source, diagnosticHandler) {
643
674
  }
644
675
  continue;
645
676
  case 34 /* CharCode.DoubleQuote */:
646
- position++;
647
- return (token = Token.StringLiteral);
677
+ if (multiLine) {
678
+ if (lookAhead(1) === 34 /* CharCode.DoubleQuote */ && lookAhead(2) === 34 /* CharCode.DoubleQuote */) {
679
+ position += 3;
680
+ token = tail;
681
+ return tail;
682
+ }
683
+ else {
684
+ continue;
685
+ }
686
+ }
687
+ else {
688
+ position++;
689
+ token = tail;
690
+ return tail;
691
+ }
692
+ case 36 /* CharCode.$ */:
693
+ if (lookAhead(1) === 123 /* CharCode.OpenBrace */) {
694
+ position += 2;
695
+ token = template;
696
+ return template;
697
+ }
698
+ continue;
648
699
  case 13 /* CharCode.CarriageReturn */:
649
700
  case 10 /* CharCode.LineFeed */:
650
- break loop;
701
+ if (multiLine) {
702
+ continue;
703
+ }
704
+ else {
705
+ break loop;
706
+ }
651
707
  }
652
708
  }
653
- return unterminated(Token.StringLiteral);
709
+ return unterminated(tail);
654
710
  }
655
- function scanTripleQuotedString() {
656
- tokenFlags |= TokenFlags.TripleQuoted;
657
- position += 3; // consume '"""'
658
- for (; !eof(); position++) {
659
- if (input.charCodeAt(position) === 34 /* CharCode.DoubleQuote */ &&
660
- lookAhead(1) === 34 /* CharCode.DoubleQuote */ &&
661
- lookAhead(2) === 34 /* CharCode.DoubleQuote */) {
662
- position += 3;
663
- return (token = Token.StringLiteral);
664
- }
711
+ function getStringLiteralOffsetStart(token, tokenFlags) {
712
+ switch (token) {
713
+ case Token.StringLiteral:
714
+ case Token.StringTemplateHead:
715
+ return tokenFlags & TokenFlags.TripleQuoted ? 3 : 1; // """ or "
716
+ default:
717
+ return 1; // {
665
718
  }
666
- return unterminated(Token.StringLiteral);
667
719
  }
668
- function getStringTokenValue() {
669
- const quoteLength = tokenFlags & TokenFlags.TripleQuoted ? 3 : 1;
670
- const start = tokenPosition + quoteLength;
671
- const end = tokenFlags & TokenFlags.Unterminated ? position : position - quoteLength;
720
+ function getStringLiteralOffsetEnd(token, tokenFlags) {
721
+ switch (token) {
722
+ case Token.StringLiteral:
723
+ case Token.StringTemplateTail:
724
+ return tokenFlags & TokenFlags.TripleQuoted ? 3 : 1; // """ or "
725
+ default:
726
+ return 2; // ${
727
+ }
728
+ }
729
+ function getStringTokenValue(token, tokenFlags) {
672
730
  if (tokenFlags & TokenFlags.TripleQuoted) {
673
- return unindentAndUnescapeTripleQuotedString(start, end);
731
+ const start = tokenPosition;
732
+ const end = position;
733
+ const [indentationStart, indentationEnd] = findTripleQuotedStringIndent(start, end);
734
+ return unindentAndUnescapeTripleQuotedString(start, end, indentationStart, indentationEnd, token, tokenFlags);
674
735
  }
736
+ const startOffset = getStringLiteralOffsetStart(token, tokenFlags);
737
+ const endOffset = getStringLiteralOffsetEnd(token, tokenFlags);
738
+ const start = tokenPosition + startOffset;
739
+ const end = tokenFlags & TokenFlags.Unterminated ? position : position - endOffset;
675
740
  if (tokenFlags & TokenFlags.Escaped) {
676
741
  return unescapeString(start, end);
677
742
  }
@@ -688,21 +753,8 @@ export function createScanner(source, diagnosticHandler) {
688
753
  }
689
754
  return text;
690
755
  }
691
- function unindentAndUnescapeTripleQuotedString(start, end) {
692
- // ignore leading whitespace before required initial line break
693
- while (start < end && isWhiteSpaceSingleLine(input.charCodeAt(start))) {
694
- start++;
695
- }
696
- // remove required initial line break
697
- if (isLineBreak(input.charCodeAt(start))) {
698
- if (isCrlf(start, start, end)) {
699
- start++;
700
- }
701
- start++;
702
- }
703
- else {
704
- error({ code: "no-new-line-start-triple-quote" });
705
- }
756
+ function findTripleQuotedStringIndent(start, end) {
757
+ end = end - 3; // Remove the """
706
758
  // remove whitespace before closing delimiter and record it as required
707
759
  // indentation for all lines
708
760
  const indentationEnd = end;
@@ -712,7 +764,7 @@ export function createScanner(source, diagnosticHandler) {
712
764
  const indentationStart = end;
713
765
  // remove required final line break
714
766
  if (isLineBreak(input.charCodeAt(end - 1))) {
715
- if (isCrlf(end - 2, start, end)) {
767
+ if (isCrlf(end - 2, 0, end)) {
716
768
  end--;
717
769
  }
718
770
  end--;
@@ -720,13 +772,61 @@ export function createScanner(source, diagnosticHandler) {
720
772
  else {
721
773
  error({ code: "no-new-line-end-triple-quote" });
722
774
  }
775
+ return [indentationStart, indentationEnd];
776
+ }
777
+ function unindentAndUnescapeTripleQuotedString(start, end, indentationStart, indentationEnd, token, tokenFlags) {
778
+ const startOffset = getStringLiteralOffsetStart(token, tokenFlags);
779
+ const endOffset = getStringLiteralOffsetEnd(token, tokenFlags);
780
+ start = start + startOffset;
781
+ end = tokenFlags & TokenFlags.Unterminated ? end : end - endOffset;
782
+ if (token === Token.StringLiteral || token === Token.StringTemplateHead) {
783
+ // ignore leading whitespace before required initial line break
784
+ while (start < end && isWhiteSpaceSingleLine(input.charCodeAt(start))) {
785
+ start++;
786
+ }
787
+ // remove required initial line break
788
+ if (isLineBreak(input.charCodeAt(start))) {
789
+ if (isCrlf(start, start, end)) {
790
+ start++;
791
+ }
792
+ start++;
793
+ }
794
+ else {
795
+ error({ code: "no-new-line-start-triple-quote" });
796
+ }
797
+ }
798
+ if (token === Token.StringLiteral || token === Token.StringTemplateTail) {
799
+ while (end > start && isWhiteSpaceSingleLine(input.charCodeAt(end - 1))) {
800
+ end--;
801
+ }
802
+ // remove required final line break
803
+ if (isLineBreak(input.charCodeAt(end - 1))) {
804
+ if (isCrlf(end - 2, start, end)) {
805
+ end--;
806
+ }
807
+ end--;
808
+ }
809
+ else {
810
+ error({ code: "no-new-line-end-triple-quote" });
811
+ }
812
+ }
813
+ let skipUnindentOnce = false;
814
+ // We are resuming from the middle of a line so we want to keep text as it is from there.
815
+ if (token === Token.StringTemplateMiddle || token === Token.StringTemplateTail) {
816
+ skipUnindentOnce = true;
817
+ }
723
818
  // remove required matching indentation from each line and unescape in the
724
819
  // process of doing so
725
820
  let result = "";
726
821
  let pos = start;
727
822
  while (pos < end) {
728
- // skip indentation at start of line
729
- start = skipMatchingIndentation(pos, end, indentationStart, indentationEnd);
823
+ if (skipUnindentOnce) {
824
+ skipUnindentOnce = false;
825
+ }
826
+ else {
827
+ // skip indentation at start of line
828
+ start = skipMatchingIndentation(pos, end, indentationStart, indentationEnd);
829
+ }
730
830
  let ch;
731
831
  while (pos < end && !isLineBreak((ch = input.charCodeAt(pos)))) {
732
832
  if (ch !== 92 /* CharCode.Backslash */) {
@@ -735,7 +835,7 @@ export function createScanner(source, diagnosticHandler) {
735
835
  }
736
836
  result += input.substring(start, pos);
737
837
  if (pos === end - 1) {
738
- error({ code: "invalid-escape-sequence" });
838
+ error({ code: "invalid-escape-sequence" }, pos, pos);
739
839
  pos++;
740
840
  }
741
841
  else {
@@ -796,7 +896,7 @@ export function createScanner(source, diagnosticHandler) {
796
896
  continue;
797
897
  }
798
898
  if (pos === end - 1) {
799
- error({ code: "invalid-escape-sequence" });
899
+ error({ code: "invalid-escape-sequence" }, pos, pos);
800
900
  break;
801
901
  }
802
902
  result += input.substring(start, pos);
@@ -820,10 +920,12 @@ export function createScanner(source, diagnosticHandler) {
820
920
  return '"';
821
921
  case 92 /* CharCode.Backslash */:
822
922
  return "\\";
923
+ case 36 /* CharCode.$ */:
924
+ return "$";
823
925
  case 96 /* CharCode.Backtick */:
824
926
  return "`";
825
927
  default:
826
- error({ code: "invalid-escape-sequence" });
928
+ error({ code: "invalid-escape-sequence" }, pos, pos + 2);
827
929
  return String.fromCharCode(ch);
828
930
  }
829
931
  }