@angular/language-service 12.2.6 → 12.2.7

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,5 +1,5 @@
1
1
  /**
2
- * @license Angular v12.2.6
2
+ * @license Angular v12.2.7
3
3
  * Copyright Google LLC All Rights Reserved.
4
4
  * License: MIT
5
5
  */
@@ -8086,7 +8086,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
8086
8086
  const _polyfillHostRe = /-shadowcsshost/gim;
8087
8087
  const _colonHostRe = /:host/gim;
8088
8088
  const _colonHostContextRe = /:host-context/gim;
8089
- const _commentRe = /\/\*\s*[\s\S]*?\*\//g;
8089
+ const _commentRe = /\/\*[\s\S]*?\*\//g;
8090
8090
  function stripComments(input) {
8091
8091
  return input.replace(_commentRe, '');
8092
8092
  }
@@ -8677,9 +8677,10 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
8677
8677
  }
8678
8678
  }
8679
8679
  class Text$2 extends NodeWithI18n {
8680
- constructor(value, sourceSpan, i18n) {
8680
+ constructor(value, sourceSpan, tokens, i18n) {
8681
8681
  super(sourceSpan, i18n);
8682
8682
  this.value = value;
8683
+ this.tokens = tokens;
8683
8684
  }
8684
8685
  visit(visitor, context) {
8685
8686
  return visitor.visitText(this, context);
@@ -8710,12 +8711,13 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
8710
8711
  }
8711
8712
  }
8712
8713
  class Attribute extends NodeWithI18n {
8713
- constructor(name, value, sourceSpan, keySpan, valueSpan, i18n) {
8714
+ constructor(name, value, sourceSpan, keySpan, valueSpan, valueTokens, i18n) {
8714
8715
  super(sourceSpan, i18n);
8715
8716
  this.name = name;
8716
8717
  this.value = value;
8717
8718
  this.keySpan = keySpan;
8718
8719
  this.valueSpan = valueSpan;
8720
+ this.valueTokens = valueTokens;
8719
8721
  }
8720
8722
  visit(visitor, context) {
8721
8723
  return visitor.visitAttribute(this, context);
@@ -10935,38 +10937,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
10935
10937
  * Use of this source code is governed by an MIT-style license that can be
10936
10938
  * found in the LICENSE file at https://angular.io/license
10937
10939
  */
10938
- var TokenType;
10939
- (function (TokenType) {
10940
- TokenType[TokenType["TAG_OPEN_START"] = 0] = "TAG_OPEN_START";
10941
- TokenType[TokenType["TAG_OPEN_END"] = 1] = "TAG_OPEN_END";
10942
- TokenType[TokenType["TAG_OPEN_END_VOID"] = 2] = "TAG_OPEN_END_VOID";
10943
- TokenType[TokenType["TAG_CLOSE"] = 3] = "TAG_CLOSE";
10944
- TokenType[TokenType["INCOMPLETE_TAG_OPEN"] = 4] = "INCOMPLETE_TAG_OPEN";
10945
- TokenType[TokenType["TEXT"] = 5] = "TEXT";
10946
- TokenType[TokenType["ESCAPABLE_RAW_TEXT"] = 6] = "ESCAPABLE_RAW_TEXT";
10947
- TokenType[TokenType["RAW_TEXT"] = 7] = "RAW_TEXT";
10948
- TokenType[TokenType["COMMENT_START"] = 8] = "COMMENT_START";
10949
- TokenType[TokenType["COMMENT_END"] = 9] = "COMMENT_END";
10950
- TokenType[TokenType["CDATA_START"] = 10] = "CDATA_START";
10951
- TokenType[TokenType["CDATA_END"] = 11] = "CDATA_END";
10952
- TokenType[TokenType["ATTR_NAME"] = 12] = "ATTR_NAME";
10953
- TokenType[TokenType["ATTR_QUOTE"] = 13] = "ATTR_QUOTE";
10954
- TokenType[TokenType["ATTR_VALUE"] = 14] = "ATTR_VALUE";
10955
- TokenType[TokenType["DOC_TYPE"] = 15] = "DOC_TYPE";
10956
- TokenType[TokenType["EXPANSION_FORM_START"] = 16] = "EXPANSION_FORM_START";
10957
- TokenType[TokenType["EXPANSION_CASE_VALUE"] = 17] = "EXPANSION_CASE_VALUE";
10958
- TokenType[TokenType["EXPANSION_CASE_EXP_START"] = 18] = "EXPANSION_CASE_EXP_START";
10959
- TokenType[TokenType["EXPANSION_CASE_EXP_END"] = 19] = "EXPANSION_CASE_EXP_END";
10960
- TokenType[TokenType["EXPANSION_FORM_END"] = 20] = "EXPANSION_FORM_END";
10961
- TokenType[TokenType["EOF"] = 21] = "EOF";
10962
- })(TokenType || (TokenType = {}));
10963
- class Token {
10964
- constructor(type, parts, sourceSpan) {
10965
- this.type = type;
10966
- this.parts = parts;
10967
- this.sourceSpan = sourceSpan;
10968
- }
10969
- }
10970
10940
  class TokenError extends ParseError {
10971
10941
  constructor(errorMsg, tokenType, span) {
10972
10942
  super(span, errorMsg);
@@ -11073,14 +11043,16 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11073
11043
  }
11074
11044
  }
11075
11045
  else if (!(this._tokenizeIcu && this._tokenizeExpansionForm())) {
11076
- this._consumeText();
11046
+ // In (possibly interpolated) text the end of the text is given by `isTextEnd()`, while
11047
+ // the premature end of an interpolation is given by the start of a new HTML element.
11048
+ this._consumeWithInterpolation(5 /* TEXT */, 8 /* INTERPOLATION */, () => this._isTextEnd(), () => this._isTagStart());
11077
11049
  }
11078
11050
  }
11079
11051
  catch (e) {
11080
11052
  this.handleError(e);
11081
11053
  }
11082
11054
  }
11083
- this._beginToken(TokenType.EOF);
11055
+ this._beginToken(24 /* EOF */);
11084
11056
  this._endToken([]);
11085
11057
  }
11086
11058
  /**
@@ -11119,7 +11091,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11119
11091
  if (this._currentTokenType === null) {
11120
11092
  throw new TokenError('Programming error - attempted to end a token which has no token type', null, this._cursor.getSpan(this._currentTokenStart));
11121
11093
  }
11122
- const token = new Token(this._currentTokenType, parts, this._cursor.getSpan(this._currentTokenStart, this._leadingTriviaCodePoints));
11094
+ const token = {
11095
+ type: this._currentTokenType,
11096
+ parts,
11097
+ sourceSpan: (end !== null && end !== void 0 ? end : this._cursor).getSpan(this._currentTokenStart, this._leadingTriviaCodePoints),
11098
+ };
11123
11099
  this.tokens.push(token);
11124
11100
  this._currentTokenStart = null;
11125
11101
  this._currentTokenType = null;
@@ -11212,19 +11188,15 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11212
11188
  this._cursor.advance();
11213
11189
  }
11214
11190
  }
11215
- _readChar(decodeEntities) {
11216
- if (decodeEntities && this._cursor.peek() === $AMPERSAND) {
11217
- return this._decodeEntity();
11218
- }
11219
- else {
11220
- // Don't rely upon reading directly from `_input` as the actual char value
11221
- // may have been generated from an escape sequence.
11222
- const char = String.fromCodePoint(this._cursor.peek());
11223
- this._cursor.advance();
11224
- return char;
11225
- }
11191
+ _readChar() {
11192
+ // Don't rely upon reading directly from `_input` as the actual char value
11193
+ // may have been generated from an escape sequence.
11194
+ const char = String.fromCodePoint(this._cursor.peek());
11195
+ this._cursor.advance();
11196
+ return char;
11226
11197
  }
11227
- _decodeEntity() {
11198
+ _consumeEntity(textTokenType) {
11199
+ this._beginToken(9 /* ENCODED_ENTITY */);
11228
11200
  const start = this._cursor.clone();
11229
11201
  this._cursor.advance();
11230
11202
  if (this._attemptCharCode($HASH)) {
@@ -11242,7 +11214,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11242
11214
  this._cursor.advance();
11243
11215
  try {
11244
11216
  const charCode = parseInt(strNum, isHex ? 16 : 10);
11245
- return String.fromCharCode(charCode);
11217
+ this._endToken([String.fromCharCode(charCode), this._cursor.getChars(start)]);
11246
11218
  }
11247
11219
  catch (_a) {
11248
11220
  throw this._createError(_unknownEntityErrorMsg(this._cursor.getChars(start)), this._cursor.getSpan());
@@ -11252,20 +11224,25 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11252
11224
  const nameStart = this._cursor.clone();
11253
11225
  this._attemptCharCodeUntilFn(isNamedEntityEnd);
11254
11226
  if (this._cursor.peek() != $SEMICOLON) {
11227
+ // No semicolon was found so abort the encoded entity token that was in progress, and treat
11228
+ // this as a text token
11229
+ this._beginToken(textTokenType, start);
11255
11230
  this._cursor = nameStart;
11256
- return '&';
11231
+ this._endToken(['&']);
11257
11232
  }
11258
- const name = this._cursor.getChars(nameStart);
11259
- this._cursor.advance();
11260
- const char = NAMED_ENTITIES[name];
11261
- if (!char) {
11262
- throw this._createError(_unknownEntityErrorMsg(name), this._cursor.getSpan(start));
11233
+ else {
11234
+ const name = this._cursor.getChars(nameStart);
11235
+ this._cursor.advance();
11236
+ const char = NAMED_ENTITIES[name];
11237
+ if (!char) {
11238
+ throw this._createError(_unknownEntityErrorMsg(name), this._cursor.getSpan(start));
11239
+ }
11240
+ this._endToken([char, `&${name};`]);
11263
11241
  }
11264
- return char;
11265
11242
  }
11266
11243
  }
11267
- _consumeRawText(decodeEntities, endMarkerPredicate) {
11268
- this._beginToken(decodeEntities ? TokenType.ESCAPABLE_RAW_TEXT : TokenType.RAW_TEXT);
11244
+ _consumeRawText(consumeEntities, endMarkerPredicate) {
11245
+ this._beginToken(consumeEntities ? 6 /* ESCAPABLE_RAW_TEXT */ : 7 /* RAW_TEXT */);
11269
11246
  const parts = [];
11270
11247
  while (true) {
11271
11248
  const tagCloseStart = this._cursor.clone();
@@ -11274,30 +11251,38 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11274
11251
  if (foundEndMarker) {
11275
11252
  break;
11276
11253
  }
11277
- parts.push(this._readChar(decodeEntities));
11254
+ if (consumeEntities && this._cursor.peek() === $AMPERSAND) {
11255
+ this._endToken([this._processCarriageReturns(parts.join(''))]);
11256
+ parts.length = 0;
11257
+ this._consumeEntity(6 /* ESCAPABLE_RAW_TEXT */);
11258
+ this._beginToken(6 /* ESCAPABLE_RAW_TEXT */);
11259
+ }
11260
+ else {
11261
+ parts.push(this._readChar());
11262
+ }
11278
11263
  }
11279
- return this._endToken([this._processCarriageReturns(parts.join(''))]);
11264
+ this._endToken([this._processCarriageReturns(parts.join(''))]);
11280
11265
  }
11281
11266
  _consumeComment(start) {
11282
- this._beginToken(TokenType.COMMENT_START, start);
11267
+ this._beginToken(10 /* COMMENT_START */, start);
11283
11268
  this._requireCharCode($MINUS);
11284
11269
  this._endToken([]);
11285
11270
  this._consumeRawText(false, () => this._attemptStr('-->'));
11286
- this._beginToken(TokenType.COMMENT_END);
11271
+ this._beginToken(11 /* COMMENT_END */);
11287
11272
  this._requireStr('-->');
11288
11273
  this._endToken([]);
11289
11274
  }
11290
11275
  _consumeCdata(start) {
11291
- this._beginToken(TokenType.CDATA_START, start);
11276
+ this._beginToken(12 /* CDATA_START */, start);
11292
11277
  this._requireStr('CDATA[');
11293
11278
  this._endToken([]);
11294
11279
  this._consumeRawText(false, () => this._attemptStr(']]>'));
11295
- this._beginToken(TokenType.CDATA_END);
11280
+ this._beginToken(13 /* CDATA_END */);
11296
11281
  this._requireStr(']]>');
11297
11282
  this._endToken([]);
11298
11283
  }
11299
11284
  _consumeDocType(start) {
11300
- this._beginToken(TokenType.DOC_TYPE, start);
11285
+ this._beginToken(18 /* DOC_TYPE */, start);
11301
11286
  const contentStart = this._cursor.clone();
11302
11287
  this._attemptUntilChar($GT);
11303
11288
  const content = this._cursor.getChars(contentStart);
@@ -11351,12 +11336,12 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11351
11336
  if (e instanceof _ControlFlowError) {
11352
11337
  if (openTagToken) {
11353
11338
  // We errored before we could close the opening tag, so it is incomplete.
11354
- openTagToken.type = TokenType.INCOMPLETE_TAG_OPEN;
11339
+ openTagToken.type = 4 /* INCOMPLETE_TAG_OPEN */;
11355
11340
  }
11356
11341
  else {
11357
11342
  // When the start tag is invalid, assume we want a "<" as text.
11358
11343
  // Back to back text tokens are merged at the end.
11359
- this._beginToken(TokenType.TEXT, start);
11344
+ this._beginToken(5 /* TEXT */, start);
11360
11345
  this._endToken(['<']);
11361
11346
  }
11362
11347
  return;
@@ -11371,8 +11356,8 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11371
11356
  this._consumeRawTextWithTagClose(prefix, tagName, true);
11372
11357
  }
11373
11358
  }
11374
- _consumeRawTextWithTagClose(prefix, tagName, decodeEntities) {
11375
- this._consumeRawText(decodeEntities, () => {
11359
+ _consumeRawTextWithTagClose(prefix, tagName, consumeEntities) {
11360
+ this._consumeRawText(consumeEntities, () => {
11376
11361
  if (!this._attemptCharCode($LT))
11377
11362
  return false;
11378
11363
  if (!this._attemptCharCode($SLASH))
@@ -11383,13 +11368,13 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11383
11368
  this._attemptCharCodeUntilFn(isNotWhitespace);
11384
11369
  return this._attemptCharCode($GT);
11385
11370
  });
11386
- this._beginToken(TokenType.TAG_CLOSE);
11371
+ this._beginToken(3 /* TAG_CLOSE */);
11387
11372
  this._requireCharCodeUntilFn(code => code === $GT, 3);
11388
11373
  this._cursor.advance(); // Consume the `>`
11389
11374
  this._endToken([prefix, tagName]);
11390
11375
  }
11391
11376
  _consumeTagOpenStart(start) {
11392
- this._beginToken(TokenType.TAG_OPEN_START, start);
11377
+ this._beginToken(0 /* TAG_OPEN_START */, start);
11393
11378
  const parts = this._consumePrefixAndName();
11394
11379
  return this._endToken(parts);
11395
11380
  }
@@ -11398,44 +11383,38 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11398
11383
  if (attrNameStart === $SQ || attrNameStart === $DQ) {
11399
11384
  throw this._createError(_unexpectedCharacterErrorMsg(attrNameStart), this._cursor.getSpan());
11400
11385
  }
11401
- this._beginToken(TokenType.ATTR_NAME);
11386
+ this._beginToken(14 /* ATTR_NAME */);
11402
11387
  const prefixAndName = this._consumePrefixAndName();
11403
11388
  this._endToken(prefixAndName);
11404
11389
  }
11405
11390
  _consumeAttributeValue() {
11406
- let value;
11407
11391
  if (this._cursor.peek() === $SQ || this._cursor.peek() === $DQ) {
11408
- this._beginToken(TokenType.ATTR_QUOTE);
11409
11392
  const quoteChar = this._cursor.peek();
11410
- this._cursor.advance();
11411
- this._endToken([String.fromCodePoint(quoteChar)]);
11412
- this._beginToken(TokenType.ATTR_VALUE);
11413
- const parts = [];
11414
- while (this._cursor.peek() !== quoteChar) {
11415
- parts.push(this._readChar(true));
11416
- }
11417
- value = parts.join('');
11418
- this._endToken([this._processCarriageReturns(value)]);
11419
- this._beginToken(TokenType.ATTR_QUOTE);
11420
- this._cursor.advance();
11421
- this._endToken([String.fromCodePoint(quoteChar)]);
11393
+ this._consumeQuote(quoteChar);
11394
+ // In an attribute then end of the attribute value and the premature end to an interpolation
11395
+ // are both triggered by the `quoteChar`.
11396
+ const endPredicate = () => this._cursor.peek() === quoteChar;
11397
+ this._consumeWithInterpolation(16 /* ATTR_VALUE_TEXT */, 17 /* ATTR_VALUE_INTERPOLATION */, endPredicate, endPredicate);
11398
+ this._consumeQuote(quoteChar);
11422
11399
  }
11423
11400
  else {
11424
- this._beginToken(TokenType.ATTR_VALUE);
11425
- const valueStart = this._cursor.clone();
11426
- this._requireCharCodeUntilFn(isNameEnd, 1);
11427
- value = this._cursor.getChars(valueStart);
11428
- this._endToken([this._processCarriageReturns(value)]);
11401
+ const endPredicate = () => isNameEnd(this._cursor.peek());
11402
+ this._consumeWithInterpolation(16 /* ATTR_VALUE_TEXT */, 17 /* ATTR_VALUE_INTERPOLATION */, endPredicate, endPredicate);
11429
11403
  }
11430
11404
  }
11405
+ _consumeQuote(quoteChar) {
11406
+ this._beginToken(15 /* ATTR_QUOTE */);
11407
+ this._requireCharCode(quoteChar);
11408
+ this._endToken([String.fromCodePoint(quoteChar)]);
11409
+ }
11431
11410
  _consumeTagOpenEnd() {
11432
- const tokenType = this._attemptCharCode($SLASH) ? TokenType.TAG_OPEN_END_VOID : TokenType.TAG_OPEN_END;
11411
+ const tokenType = this._attemptCharCode($SLASH) ? 2 /* TAG_OPEN_END_VOID */ : 1 /* TAG_OPEN_END */;
11433
11412
  this._beginToken(tokenType);
11434
11413
  this._requireCharCode($GT);
11435
11414
  this._endToken([]);
11436
11415
  }
11437
11416
  _consumeTagClose(start) {
11438
- this._beginToken(TokenType.TAG_CLOSE, start);
11417
+ this._beginToken(3 /* TAG_CLOSE */, start);
11439
11418
  this._attemptCharCodeUntilFn(isNotWhitespace);
11440
11419
  const prefixAndName = this._consumePrefixAndName();
11441
11420
  this._attemptCharCodeUntilFn(isNotWhitespace);
@@ -11443,11 +11422,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11443
11422
  this._endToken(prefixAndName);
11444
11423
  }
11445
11424
  _consumeExpansionFormStart() {
11446
- this._beginToken(TokenType.EXPANSION_FORM_START);
11425
+ this._beginToken(19 /* EXPANSION_FORM_START */);
11447
11426
  this._requireCharCode($LBRACE);
11448
11427
  this._endToken([]);
11449
- this._expansionCaseStack.push(TokenType.EXPANSION_FORM_START);
11450
- this._beginToken(TokenType.RAW_TEXT);
11428
+ this._expansionCaseStack.push(19 /* EXPANSION_FORM_START */);
11429
+ this._beginToken(7 /* RAW_TEXT */);
11451
11430
  const condition = this._readUntil($COMMA);
11452
11431
  const normalizedCondition = this._processCarriageReturns(condition);
11453
11432
  if (this._i18nNormalizeLineEndingsInICUs) {
@@ -11463,59 +11442,139 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11463
11442
  }
11464
11443
  this._requireCharCode($COMMA);
11465
11444
  this._attemptCharCodeUntilFn(isNotWhitespace);
11466
- this._beginToken(TokenType.RAW_TEXT);
11445
+ this._beginToken(7 /* RAW_TEXT */);
11467
11446
  const type = this._readUntil($COMMA);
11468
11447
  this._endToken([type]);
11469
11448
  this._requireCharCode($COMMA);
11470
11449
  this._attemptCharCodeUntilFn(isNotWhitespace);
11471
11450
  }
11472
11451
  _consumeExpansionCaseStart() {
11473
- this._beginToken(TokenType.EXPANSION_CASE_VALUE);
11452
+ this._beginToken(20 /* EXPANSION_CASE_VALUE */);
11474
11453
  const value = this._readUntil($LBRACE).trim();
11475
11454
  this._endToken([value]);
11476
11455
  this._attemptCharCodeUntilFn(isNotWhitespace);
11477
- this._beginToken(TokenType.EXPANSION_CASE_EXP_START);
11456
+ this._beginToken(21 /* EXPANSION_CASE_EXP_START */);
11478
11457
  this._requireCharCode($LBRACE);
11479
11458
  this._endToken([]);
11480
11459
  this._attemptCharCodeUntilFn(isNotWhitespace);
11481
- this._expansionCaseStack.push(TokenType.EXPANSION_CASE_EXP_START);
11460
+ this._expansionCaseStack.push(21 /* EXPANSION_CASE_EXP_START */);
11482
11461
  }
11483
11462
  _consumeExpansionCaseEnd() {
11484
- this._beginToken(TokenType.EXPANSION_CASE_EXP_END);
11463
+ this._beginToken(22 /* EXPANSION_CASE_EXP_END */);
11485
11464
  this._requireCharCode($RBRACE);
11486
11465
  this._endToken([]);
11487
11466
  this._attemptCharCodeUntilFn(isNotWhitespace);
11488
11467
  this._expansionCaseStack.pop();
11489
11468
  }
11490
11469
  _consumeExpansionFormEnd() {
11491
- this._beginToken(TokenType.EXPANSION_FORM_END);
11470
+ this._beginToken(23 /* EXPANSION_FORM_END */);
11492
11471
  this._requireCharCode($RBRACE);
11493
11472
  this._endToken([]);
11494
11473
  this._expansionCaseStack.pop();
11495
11474
  }
11496
- _consumeText() {
11497
- const start = this._cursor.clone();
11498
- this._beginToken(TokenType.TEXT, start);
11475
+ /**
11476
+ * Consume a string that may contain interpolation expressions.
11477
+ *
11478
+ * The first token consumed will be of `tokenType` and then there will be alternating
11479
+ * `interpolationTokenType` and `tokenType` tokens until the `endPredicate()` returns true.
11480
+ *
11481
+ * If an interpolation token ends prematurely it will have no end marker in its `parts` array.
11482
+ *
11483
+ * @param textTokenType the kind of tokens to interleave around interpolation tokens.
11484
+ * @param interpolationTokenType the kind of tokens that contain interpolation.
11485
+ * @param endPredicate a function that should return true when we should stop consuming.
11486
+ * @param endInterpolation a function that should return true if there is a premature end to an
11487
+ * interpolation expression - i.e. before we get to the normal interpolation closing marker.
11488
+ */
11489
+ _consumeWithInterpolation(textTokenType, interpolationTokenType, endPredicate, endInterpolation) {
11490
+ this._beginToken(textTokenType);
11499
11491
  const parts = [];
11500
- do {
11492
+ while (!endPredicate()) {
11493
+ const current = this._cursor.clone();
11501
11494
  if (this._interpolationConfig && this._attemptStr(this._interpolationConfig.start)) {
11502
- parts.push(this._interpolationConfig.start);
11503
- this._inInterpolation = true;
11495
+ this._endToken([this._processCarriageReturns(parts.join(''))], current);
11496
+ parts.length = 0;
11497
+ this._consumeInterpolation(interpolationTokenType, current, endInterpolation);
11498
+ this._beginToken(textTokenType);
11504
11499
  }
11505
- else if (this._interpolationConfig && this._inInterpolation &&
11506
- this._attemptStr(this._interpolationConfig.end)) {
11507
- parts.push(this._interpolationConfig.end);
11508
- this._inInterpolation = false;
11500
+ else if (this._cursor.peek() === $AMPERSAND) {
11501
+ this._endToken([this._processCarriageReturns(parts.join(''))]);
11502
+ parts.length = 0;
11503
+ this._consumeEntity(textTokenType);
11504
+ this._beginToken(textTokenType);
11509
11505
  }
11510
11506
  else {
11511
- parts.push(this._readChar(true));
11507
+ parts.push(this._readChar());
11512
11508
  }
11513
- } while (!this._isTextEnd());
11509
+ }
11514
11510
  // It is possible that an interpolation was started but not ended inside this text token.
11515
11511
  // Make sure that we reset the state of the lexer correctly.
11516
11512
  this._inInterpolation = false;
11517
11513
  this._endToken([this._processCarriageReturns(parts.join(''))]);
11518
11514
  }
11515
+ /**
11516
+ * Consume a block of text that has been interpreted as an Angular interpolation.
11517
+ *
11518
+ * @param interpolationTokenType the type of the interpolation token to generate.
11519
+ * @param interpolationStart a cursor that points to the start of this interpolation.
11520
+ * @param prematureEndPredicate a function that should return true if the next characters indicate
11521
+ * an end to the interpolation before its normal closing marker.
11522
+ */
11523
+ _consumeInterpolation(interpolationTokenType, interpolationStart, prematureEndPredicate) {
11524
+ const parts = [];
11525
+ this._beginToken(interpolationTokenType, interpolationStart);
11526
+ parts.push(this._interpolationConfig.start);
11527
+ // Find the end of the interpolation, ignoring content inside quotes.
11528
+ const expressionStart = this._cursor.clone();
11529
+ let inQuote = null;
11530
+ let inComment = false;
11531
+ while (this._cursor.peek() !== $EOF &&
11532
+ (prematureEndPredicate === null || !prematureEndPredicate())) {
11533
+ const current = this._cursor.clone();
11534
+ if (this._isTagStart()) {
11535
+ // We are starting what looks like an HTML element in the middle of this interpolation.
11536
+ // Reset the cursor to before the `<` character and end the interpolation token.
11537
+ // (This is actually wrong but here for backward compatibility).
11538
+ this._cursor = current;
11539
+ parts.push(this._getProcessedChars(expressionStart, current));
11540
+ this._endToken(parts);
11541
+ return;
11542
+ }
11543
+ if (inQuote === null) {
11544
+ if (this._attemptStr(this._interpolationConfig.end)) {
11545
+ // We are not in a string, and we hit the end interpolation marker
11546
+ parts.push(this._getProcessedChars(expressionStart, current));
11547
+ parts.push(this._interpolationConfig.end);
11548
+ this._endToken(parts);
11549
+ return;
11550
+ }
11551
+ else if (this._attemptStr('//')) {
11552
+ // Once we are in a comment we ignore any quotes
11553
+ inComment = true;
11554
+ }
11555
+ }
11556
+ const char = this._cursor.peek();
11557
+ this._cursor.advance();
11558
+ if (char === $BACKSLASH) {
11559
+ // Skip the next character because it was escaped.
11560
+ this._cursor.advance();
11561
+ }
11562
+ else if (char === inQuote) {
11563
+ // Exiting the current quoted string
11564
+ inQuote = null;
11565
+ }
11566
+ else if (!inComment && inQuote === null && isQuote(char)) {
11567
+ // Entering a new quoted string
11568
+ inQuote = char;
11569
+ }
11570
+ }
11571
+ // We hit EOF without finding a closing interpolation marker
11572
+ parts.push(this._getProcessedChars(expressionStart, this._cursor));
11573
+ this._endToken(parts);
11574
+ }
11575
+ _getProcessedChars(start, end) {
11576
+ return this._processCarriageReturns(end.getChars(start));
11577
+ }
11519
11578
  _isTextEnd() {
11520
11579
  if (this._isTagStart() || this._cursor.peek() === $EOF) {
11521
11580
  return true;
@@ -11558,12 +11617,12 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11558
11617
  _isInExpansionCase() {
11559
11618
  return this._expansionCaseStack.length > 0 &&
11560
11619
  this._expansionCaseStack[this._expansionCaseStack.length - 1] ===
11561
- TokenType.EXPANSION_CASE_EXP_START;
11620
+ 21 /* EXPANSION_CASE_EXP_START */;
11562
11621
  }
11563
11622
  _isInExpansionForm() {
11564
11623
  return this._expansionCaseStack.length > 0 &&
11565
11624
  this._expansionCaseStack[this._expansionCaseStack.length - 1] ===
11566
- TokenType.EXPANSION_FORM_START;
11625
+ 19 /* EXPANSION_FORM_START */;
11567
11626
  }
11568
11627
  isExpansionFormStart() {
11569
11628
  if (this._cursor.peek() !== $LBRACE) {
@@ -11610,7 +11669,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11610
11669
  let lastDstToken = undefined;
11611
11670
  for (let i = 0; i < srcTokens.length; i++) {
11612
11671
  const token = srcTokens[i];
11613
- if (lastDstToken && lastDstToken.type === TokenType.TEXT && token.type === TokenType.TEXT) {
11672
+ if ((lastDstToken && lastDstToken.type === 5 /* TEXT */ && token.type === 5 /* TEXT */) ||
11673
+ (lastDstToken && lastDstToken.type === 16 /* ATTR_VALUE_TEXT */ &&
11674
+ token.type === 16 /* ATTR_VALUE_TEXT */)) {
11614
11675
  lastDstToken.parts[0] += token.parts[0];
11615
11676
  lastDstToken.sourceSpan.end = token.sourceSpan.end;
11616
11677
  }
@@ -11903,28 +11964,28 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11903
11964
  this._advance();
11904
11965
  }
11905
11966
  build() {
11906
- while (this._peek.type !== TokenType.EOF) {
11907
- if (this._peek.type === TokenType.TAG_OPEN_START ||
11908
- this._peek.type === TokenType.INCOMPLETE_TAG_OPEN) {
11967
+ while (this._peek.type !== 24 /* EOF */) {
11968
+ if (this._peek.type === 0 /* TAG_OPEN_START */ ||
11969
+ this._peek.type === 4 /* INCOMPLETE_TAG_OPEN */) {
11909
11970
  this._consumeStartTag(this._advance());
11910
11971
  }
11911
- else if (this._peek.type === TokenType.TAG_CLOSE) {
11972
+ else if (this._peek.type === 3 /* TAG_CLOSE */) {
11912
11973
  this._consumeEndTag(this._advance());
11913
11974
  }
11914
- else if (this._peek.type === TokenType.CDATA_START) {
11975
+ else if (this._peek.type === 12 /* CDATA_START */) {
11915
11976
  this._closeVoidElement();
11916
11977
  this._consumeCdata(this._advance());
11917
11978
  }
11918
- else if (this._peek.type === TokenType.COMMENT_START) {
11979
+ else if (this._peek.type === 10 /* COMMENT_START */) {
11919
11980
  this._closeVoidElement();
11920
11981
  this._consumeComment(this._advance());
11921
11982
  }
11922
- else if (this._peek.type === TokenType.TEXT || this._peek.type === TokenType.RAW_TEXT ||
11923
- this._peek.type === TokenType.ESCAPABLE_RAW_TEXT) {
11983
+ else if (this._peek.type === 5 /* TEXT */ || this._peek.type === 7 /* RAW_TEXT */ ||
11984
+ this._peek.type === 6 /* ESCAPABLE_RAW_TEXT */) {
11924
11985
  this._closeVoidElement();
11925
11986
  this._consumeText(this._advance());
11926
11987
  }
11927
- else if (this._peek.type === TokenType.EXPANSION_FORM_START) {
11988
+ else if (this._peek.type === 19 /* EXPANSION_FORM_START */) {
11928
11989
  this._consumeExpansion(this._advance());
11929
11990
  }
11930
11991
  else {
@@ -11950,11 +12011,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11950
12011
  }
11951
12012
  _consumeCdata(_startToken) {
11952
12013
  this._consumeText(this._advance());
11953
- this._advanceIf(TokenType.CDATA_END);
12014
+ this._advanceIf(13 /* CDATA_END */);
11954
12015
  }
11955
12016
  _consumeComment(token) {
11956
- const text = this._advanceIf(TokenType.RAW_TEXT);
11957
- this._advanceIf(TokenType.COMMENT_END);
12017
+ const text = this._advanceIf(7 /* RAW_TEXT */);
12018
+ this._advanceIf(11 /* COMMENT_END */);
11958
12019
  const value = text != null ? text.parts[0].trim() : null;
11959
12020
  this._addToParent(new Comment$1(value, token.sourceSpan));
11960
12021
  }
@@ -11963,14 +12024,14 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11963
12024
  const type = this._advance();
11964
12025
  const cases = [];
11965
12026
  // read =
11966
- while (this._peek.type === TokenType.EXPANSION_CASE_VALUE) {
12027
+ while (this._peek.type === 20 /* EXPANSION_CASE_VALUE */) {
11967
12028
  const expCase = this._parseExpansionCase();
11968
12029
  if (!expCase)
11969
12030
  return; // error
11970
12031
  cases.push(expCase);
11971
12032
  }
11972
12033
  // read the final }
11973
- if (this._peek.type !== TokenType.EXPANSION_FORM_END) {
12034
+ if (this._peek.type !== 23 /* EXPANSION_FORM_END */) {
11974
12035
  this.errors.push(TreeError.create(null, this._peek.sourceSpan, `Invalid ICU message. Missing '}'.`));
11975
12036
  return;
11976
12037
  }
@@ -11981,7 +12042,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11981
12042
  _parseExpansionCase() {
11982
12043
  const value = this._advance();
11983
12044
  // read {
11984
- if (this._peek.type !== TokenType.EXPANSION_CASE_EXP_START) {
12045
+ if (this._peek.type !== 21 /* EXPANSION_CASE_EXP_START */) {
11985
12046
  this.errors.push(TreeError.create(null, this._peek.sourceSpan, `Invalid ICU message. Missing '{'.`));
11986
12047
  return null;
11987
12048
  }
@@ -11991,7 +12052,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
11991
12052
  if (!exp)
11992
12053
  return null;
11993
12054
  const end = this._advance();
11994
- exp.push(new Token(TokenType.EOF, [], end.sourceSpan));
12055
+ exp.push({ type: 24 /* EOF */, parts: [], sourceSpan: end.sourceSpan });
11995
12056
  // parse everything in between { and }
11996
12057
  const expansionCaseParser = new _TreeBuilder(exp, this.getTagDefinition);
11997
12058
  expansionCaseParser.build();
@@ -12005,14 +12066,14 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12005
12066
  }
12006
12067
  _collectExpansionExpTokens(start) {
12007
12068
  const exp = [];
12008
- const expansionFormStack = [TokenType.EXPANSION_CASE_EXP_START];
12069
+ const expansionFormStack = [21 /* EXPANSION_CASE_EXP_START */];
12009
12070
  while (true) {
12010
- if (this._peek.type === TokenType.EXPANSION_FORM_START ||
12011
- this._peek.type === TokenType.EXPANSION_CASE_EXP_START) {
12071
+ if (this._peek.type === 19 /* EXPANSION_FORM_START */ ||
12072
+ this._peek.type === 21 /* EXPANSION_CASE_EXP_START */) {
12012
12073
  expansionFormStack.push(this._peek.type);
12013
12074
  }
12014
- if (this._peek.type === TokenType.EXPANSION_CASE_EXP_END) {
12015
- if (lastOnStack(expansionFormStack, TokenType.EXPANSION_CASE_EXP_START)) {
12075
+ if (this._peek.type === 22 /* EXPANSION_CASE_EXP_END */) {
12076
+ if (lastOnStack(expansionFormStack, 21 /* EXPANSION_CASE_EXP_START */)) {
12016
12077
  expansionFormStack.pop();
12017
12078
  if (expansionFormStack.length === 0)
12018
12079
  return exp;
@@ -12022,8 +12083,8 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12022
12083
  return null;
12023
12084
  }
12024
12085
  }
12025
- if (this._peek.type === TokenType.EXPANSION_FORM_END) {
12026
- if (lastOnStack(expansionFormStack, TokenType.EXPANSION_FORM_START)) {
12086
+ if (this._peek.type === 23 /* EXPANSION_FORM_END */) {
12087
+ if (lastOnStack(expansionFormStack, 19 /* EXPANSION_FORM_START */)) {
12027
12088
  expansionFormStack.pop();
12028
12089
  }
12029
12090
  else {
@@ -12031,7 +12092,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12031
12092
  return null;
12032
12093
  }
12033
12094
  }
12034
- if (this._peek.type === TokenType.EOF) {
12095
+ if (this._peek.type === 24 /* EOF */) {
12035
12096
  this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
12036
12097
  return null;
12037
12098
  }
@@ -12039,16 +12100,38 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12039
12100
  }
12040
12101
  }
12041
12102
  _consumeText(token) {
12103
+ const tokens = [token];
12104
+ const startSpan = token.sourceSpan;
12042
12105
  let text = token.parts[0];
12043
12106
  if (text.length > 0 && text[0] === '\n') {
12044
12107
  const parent = this._getParentElement();
12045
12108
  if (parent != null && parent.children.length === 0 &&
12046
12109
  this.getTagDefinition(parent.name).ignoreFirstLf) {
12047
12110
  text = text.substring(1);
12111
+ tokens[0] = { type: token.type, sourceSpan: token.sourceSpan, parts: [text] };
12112
+ }
12113
+ }
12114
+ while (this._peek.type === 8 /* INTERPOLATION */ || this._peek.type === 5 /* TEXT */ ||
12115
+ this._peek.type === 9 /* ENCODED_ENTITY */) {
12116
+ token = this._advance();
12117
+ tokens.push(token);
12118
+ if (token.type === 8 /* INTERPOLATION */) {
12119
+ // For backward compatibility we decode HTML entities that appear in interpolation
12120
+ // expressions. This is arguably a bug, but it could be a considerable breaking change to
12121
+ // fix it. It should be addressed in a larger project to refactor the entire parser/lexer
12122
+ // chain after View Engine has been removed.
12123
+ text += token.parts.join('').replace(/&([^;]+);/g, decodeEntity);
12124
+ }
12125
+ else if (token.type === 9 /* ENCODED_ENTITY */) {
12126
+ text += token.parts[0];
12127
+ }
12128
+ else {
12129
+ text += token.parts.join('');
12048
12130
  }
12049
12131
  }
12050
12132
  if (text.length > 0) {
12051
- this._addToParent(new Text$2(text, token.sourceSpan));
12133
+ const endSpan = token.sourceSpan;
12134
+ this._addToParent(new Text$2(text, new ParseSourceSpan(startSpan.start, endSpan.end, startSpan.fullStart, startSpan.details), tokens));
12052
12135
  }
12053
12136
  }
12054
12137
  _closeVoidElement() {
@@ -12060,14 +12143,14 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12060
12143
  _consumeStartTag(startTagToken) {
12061
12144
  const [prefix, name] = startTagToken.parts;
12062
12145
  const attrs = [];
12063
- while (this._peek.type === TokenType.ATTR_NAME) {
12146
+ while (this._peek.type === 14 /* ATTR_NAME */) {
12064
12147
  attrs.push(this._consumeAttr(this._advance()));
12065
12148
  }
12066
12149
  const fullName = this._getElementFullName(prefix, name, this._getParentElement());
12067
12150
  let selfClosing = false;
12068
12151
  // Note: There could have been a tokenizer error
12069
12152
  // so that we don't get a token for the end tag...
12070
- if (this._peek.type === TokenType.TAG_OPEN_END_VOID) {
12153
+ if (this._peek.type === 2 /* TAG_OPEN_END_VOID */) {
12071
12154
  this._advance();
12072
12155
  selfClosing = true;
12073
12156
  const tagDef = this.getTagDefinition(fullName);
@@ -12075,7 +12158,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12075
12158
  this.errors.push(TreeError.create(fullName, startTagToken.sourceSpan, `Only void and foreign elements can be self closed "${startTagToken.parts[1]}"`));
12076
12159
  }
12077
12160
  }
12078
- else if (this._peek.type === TokenType.TAG_OPEN_END) {
12161
+ else if (this._peek.type === 1 /* TAG_OPEN_END */) {
12079
12162
  this._advance();
12080
12163
  selfClosing = false;
12081
12164
  }
@@ -12090,7 +12173,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12090
12173
  // element start tag also represents the end tag.
12091
12174
  this._popElement(fullName, span);
12092
12175
  }
12093
- else if (startTagToken.type === TokenType.INCOMPLETE_TAG_OPEN) {
12176
+ else if (startTagToken.type === 4 /* INCOMPLETE_TAG_OPEN */) {
12094
12177
  // We already know the opening tag is not complete, so it is unlikely it has a corresponding
12095
12178
  // close tag. Let's optimistically parse it as a full element and emit an error.
12096
12179
  this._popElement(fullName, null);
@@ -12145,24 +12228,53 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12145
12228
  }
12146
12229
  _consumeAttr(attrName) {
12147
12230
  const fullName = mergeNsAndName(attrName.parts[0], attrName.parts[1]);
12148
- let end = attrName.sourceSpan.end;
12149
- let value = '';
12150
- let valueSpan = undefined;
12151
- if (this._peek.type === TokenType.ATTR_QUOTE) {
12231
+ let attrEnd = attrName.sourceSpan.end;
12232
+ // Consume any quote
12233
+ if (this._peek.type === 15 /* ATTR_QUOTE */) {
12152
12234
  this._advance();
12153
12235
  }
12154
- if (this._peek.type === TokenType.ATTR_VALUE) {
12155
- const valueToken = this._advance();
12156
- value = valueToken.parts[0];
12157
- end = valueToken.sourceSpan.end;
12158
- valueSpan = valueToken.sourceSpan;
12236
+ // Consume the attribute value
12237
+ let value = '';
12238
+ const valueTokens = [];
12239
+ let valueStartSpan = undefined;
12240
+ let valueEnd = undefined;
12241
+ // NOTE: We need to use a new variable `nextTokenType` here to hide the actual type of
12242
+ // `_peek.type` from TS. Otherwise TS will narrow the type of `_peek.type` preventing it from
12243
+ // being able to consider `ATTR_VALUE_INTERPOLATION` as an option. This is because TS is not
12244
+ // able to see that `_advance()` will actually mutate `_peek`.
12245
+ const nextTokenType = this._peek.type;
12246
+ if (nextTokenType === 16 /* ATTR_VALUE_TEXT */) {
12247
+ valueStartSpan = this._peek.sourceSpan;
12248
+ valueEnd = this._peek.sourceSpan.end;
12249
+ while (this._peek.type === 16 /* ATTR_VALUE_TEXT */ ||
12250
+ this._peek.type === 17 /* ATTR_VALUE_INTERPOLATION */ ||
12251
+ this._peek.type === 9 /* ENCODED_ENTITY */) {
12252
+ const valueToken = this._advance();
12253
+ valueTokens.push(valueToken);
12254
+ if (valueToken.type === 17 /* ATTR_VALUE_INTERPOLATION */) {
12255
+ // For backward compatibility we decode HTML entities that appear in interpolation
12256
+ // expressions. This is arguably a bug, but it could be a considerable breaking change to
12257
+ // fix it. It should be addressed in a larger project to refactor the entire parser/lexer
12258
+ // chain after View Engine has been removed.
12259
+ value += valueToken.parts.join('').replace(/&([^;]+);/g, decodeEntity);
12260
+ }
12261
+ else if (valueToken.type === 9 /* ENCODED_ENTITY */) {
12262
+ value += valueToken.parts[0];
12263
+ }
12264
+ else {
12265
+ value += valueToken.parts.join('');
12266
+ }
12267
+ valueEnd = attrEnd = valueToken.sourceSpan.end;
12268
+ }
12159
12269
  }
12160
- if (this._peek.type === TokenType.ATTR_QUOTE) {
12270
+ // Consume any quote
12271
+ if (this._peek.type === 15 /* ATTR_QUOTE */) {
12161
12272
  const quoteToken = this._advance();
12162
- end = quoteToken.sourceSpan.end;
12273
+ attrEnd = quoteToken.sourceSpan.end;
12163
12274
  }
12164
- const keySpan = new ParseSourceSpan(attrName.sourceSpan.start, attrName.sourceSpan.end);
12165
- return new Attribute(fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, end, attrName.sourceSpan.fullStart), keySpan, valueSpan);
12275
+ const valueSpan = valueStartSpan && valueEnd &&
12276
+ new ParseSourceSpan(valueStartSpan.start, valueEnd, valueStartSpan.fullStart);
12277
+ return new Attribute(fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, attrEnd, attrName.sourceSpan.fullStart), attrName.sourceSpan, valueSpan, valueTokens.length > 0 ? valueTokens : undefined, undefined);
12166
12278
  }
12167
12279
  _getParentElement() {
12168
12280
  return this._elementStack.length > 0 ? this._elementStack[this._elementStack.length - 1] : null;
@@ -12193,6 +12305,23 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12193
12305
  function lastOnStack(stack, element) {
12194
12306
  return stack.length > 0 && stack[stack.length - 1] === element;
12195
12307
  }
12308
+ /**
12309
+ * Decode the `entity` string, which we believe is the contents of an HTML entity.
12310
+ *
12311
+ * If the string is not actually a valid/known entity then just return the original `match` string.
12312
+ */
12313
+ function decodeEntity(match, entity) {
12314
+ if (NAMED_ENTITIES[entity] !== undefined) {
12315
+ return NAMED_ENTITIES[entity] || match;
12316
+ }
12317
+ if (/^#x[a-f0-9]+$/i.test(entity)) {
12318
+ return String.fromCodePoint(parseInt(entity.slice(2), 16));
12319
+ }
12320
+ if (/^#\d+$/.test(entity)) {
12321
+ return String.fromCodePoint(parseInt(entity.slice(1), 10));
12322
+ }
12323
+ return match;
12324
+ }
12196
12325
 
12197
12326
  /**
12198
12327
  * @license
@@ -12268,7 +12397,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12268
12397
  const hasExpansionSibling = context &&
12269
12398
  (context.prev instanceof Expansion || context.next instanceof Expansion);
12270
12399
  if (isNotBlank || hasExpansionSibling) {
12271
- return new Text$2(replaceNgsp(text.value).replace(WS_REPLACE_REGEXP, ' '), text.sourceSpan, text.i18n);
12400
+ // Process the whitespace in the tokens of this Text node
12401
+ const tokens = text.tokens.map(token => token.type === 5 /* TEXT */ ? createWhitespaceProcessedTextToken(token) : token);
12402
+ // Process the whitespace of the value of this Text node
12403
+ const value = processWhitespace(text.value);
12404
+ return new Text$2(value, text.sourceSpan, tokens, text.i18n);
12272
12405
  }
12273
12406
  return null;
12274
12407
  }
@@ -12282,6 +12415,12 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12282
12415
  return expansionCase;
12283
12416
  }
12284
12417
  }
12418
+ function createWhitespaceProcessedTextToken({ type, parts, sourceSpan }) {
12419
+ return { type, parts: [processWhitespace(parts[0])], sourceSpan };
12420
+ }
12421
+ function processWhitespace(text) {
12422
+ return replaceNgsp(text).replace(WS_REPLACE_REGEXP, ' ');
12423
+ }
12285
12424
  function removeWhitespaces(htmlAstWithErrors) {
12286
12425
  return new ParseTreeResult(visitAll$1(new WhitespaceVisitor(), htmlAstWithErrors.rootNodes), htmlAstWithErrors.errors);
12287
12426
  }
@@ -12384,9 +12523,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12384
12523
  }
12385
12524
  const expansionResult = expandNodes(c.expression);
12386
12525
  errors.push(...expansionResult.errors);
12387
- return new Element$1(`ng-template`, [new Attribute('ngPluralCase', `${c.value}`, c.valueSourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* i18n */)], expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
12526
+ return new Element$1(`ng-template`, [new Attribute('ngPluralCase', `${c.value}`, c.valueSourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */)], expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
12388
12527
  });
12389
- const switchAttr = new Attribute('[ngPlural]', ast.switchValue, ast.switchValueSourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* i18n */);
12528
+ const switchAttr = new Attribute('[ngPlural]', ast.switchValue, ast.switchValueSourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */);
12390
12529
  return new Element$1('ng-container', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
12391
12530
  }
12392
12531
  // ICU messages (excluding plural form) are expanded to `NgSwitch` and `NgSwitchCase`s
@@ -12396,11 +12535,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
12396
12535
  errors.push(...expansionResult.errors);
12397
12536
  if (c.value === 'other') {
12398
12537
  // other is the default case when no values match
12399
- return new Element$1(`ng-template`, [new Attribute('ngSwitchDefault', '', c.valueSourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* i18n */)], expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
12538
+ return new Element$1(`ng-template`, [new Attribute('ngSwitchDefault', '', c.valueSourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */)], expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
12400
12539
  }
12401
- return new Element$1(`ng-template`, [new Attribute('ngSwitchCase', `${c.value}`, c.valueSourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* i18n */)], expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
12540
+ return new Element$1(`ng-template`, [new Attribute('ngSwitchCase', `${c.value}`, c.valueSourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */)], expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
12402
12541
  });
12403
- const switchAttr = new Attribute('[ngSwitch]', ast.switchValue, ast.switchValueSourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* i18n */);
12542
+ const switchAttr = new Attribute('[ngSwitch]', ast.switchValue, ast.switchValueSourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */);
12404
12543
  return new Element$1('ng-container', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
12405
12544
  }
12406
12545
 
@@ -15018,7 +15157,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
15018
15157
  * Use of this source code is governed by an MIT-style license that can be
15019
15158
  * found in the LICENSE file at https://angular.io/license
15020
15159
  */
15021
- var TokenType$1;
15160
+ var TokenType;
15022
15161
  (function (TokenType) {
15023
15162
  TokenType[TokenType["Character"] = 0] = "Character";
15024
15163
  TokenType[TokenType["Identifier"] = 1] = "Identifier";
@@ -15028,7 +15167,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
15028
15167
  TokenType[TokenType["Operator"] = 5] = "Operator";
15029
15168
  TokenType[TokenType["Number"] = 6] = "Number";
15030
15169
  TokenType[TokenType["Error"] = 7] = "Error";
15031
- })(TokenType$1 || (TokenType$1 = {}));
15170
+ })(TokenType || (TokenType = {}));
15032
15171
  const KEYWORDS = ['var', 'let', 'as', 'null', 'undefined', 'true', 'false', 'if', 'else', 'this'];
15033
15172
  class Lexer {
15034
15173
  tokenize(text) {
@@ -15042,7 +15181,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
15042
15181
  return tokens;
15043
15182
  }
15044
15183
  }
15045
- class Token$1 {
15184
+ class Token {
15046
15185
  constructor(index, end, type, numValue, strValue) {
15047
15186
  this.index = index;
15048
15187
  this.end = end;
@@ -15051,64 +15190,64 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
15051
15190
  this.strValue = strValue;
15052
15191
  }
15053
15192
  isCharacter(code) {
15054
- return this.type == TokenType$1.Character && this.numValue == code;
15193
+ return this.type == TokenType.Character && this.numValue == code;
15055
15194
  }
15056
15195
  isNumber() {
15057
- return this.type == TokenType$1.Number;
15196
+ return this.type == TokenType.Number;
15058
15197
  }
15059
15198
  isString() {
15060
- return this.type == TokenType$1.String;
15199
+ return this.type == TokenType.String;
15061
15200
  }
15062
15201
  isOperator(operator) {
15063
- return this.type == TokenType$1.Operator && this.strValue == operator;
15202
+ return this.type == TokenType.Operator && this.strValue == operator;
15064
15203
  }
15065
15204
  isIdentifier() {
15066
- return this.type == TokenType$1.Identifier;
15205
+ return this.type == TokenType.Identifier;
15067
15206
  }
15068
15207
  isPrivateIdentifier() {
15069
- return this.type == TokenType$1.PrivateIdentifier;
15208
+ return this.type == TokenType.PrivateIdentifier;
15070
15209
  }
15071
15210
  isKeyword() {
15072
- return this.type == TokenType$1.Keyword;
15211
+ return this.type == TokenType.Keyword;
15073
15212
  }
15074
15213
  isKeywordLet() {
15075
- return this.type == TokenType$1.Keyword && this.strValue == 'let';
15214
+ return this.type == TokenType.Keyword && this.strValue == 'let';
15076
15215
  }
15077
15216
  isKeywordAs() {
15078
- return this.type == TokenType$1.Keyword && this.strValue == 'as';
15217
+ return this.type == TokenType.Keyword && this.strValue == 'as';
15079
15218
  }
15080
15219
  isKeywordNull() {
15081
- return this.type == TokenType$1.Keyword && this.strValue == 'null';
15220
+ return this.type == TokenType.Keyword && this.strValue == 'null';
15082
15221
  }
15083
15222
  isKeywordUndefined() {
15084
- return this.type == TokenType$1.Keyword && this.strValue == 'undefined';
15223
+ return this.type == TokenType.Keyword && this.strValue == 'undefined';
15085
15224
  }
15086
15225
  isKeywordTrue() {
15087
- return this.type == TokenType$1.Keyword && this.strValue == 'true';
15226
+ return this.type == TokenType.Keyword && this.strValue == 'true';
15088
15227
  }
15089
15228
  isKeywordFalse() {
15090
- return this.type == TokenType$1.Keyword && this.strValue == 'false';
15229
+ return this.type == TokenType.Keyword && this.strValue == 'false';
15091
15230
  }
15092
15231
  isKeywordThis() {
15093
- return this.type == TokenType$1.Keyword && this.strValue == 'this';
15232
+ return this.type == TokenType.Keyword && this.strValue == 'this';
15094
15233
  }
15095
15234
  isError() {
15096
- return this.type == TokenType$1.Error;
15235
+ return this.type == TokenType.Error;
15097
15236
  }
15098
15237
  toNumber() {
15099
- return this.type == TokenType$1.Number ? this.numValue : -1;
15238
+ return this.type == TokenType.Number ? this.numValue : -1;
15100
15239
  }
15101
15240
  toString() {
15102
15241
  switch (this.type) {
15103
- case TokenType$1.Character:
15104
- case TokenType$1.Identifier:
15105
- case TokenType$1.Keyword:
15106
- case TokenType$1.Operator:
15107
- case TokenType$1.PrivateIdentifier:
15108
- case TokenType$1.String:
15109
- case TokenType$1.Error:
15242
+ case TokenType.Character:
15243
+ case TokenType.Identifier:
15244
+ case TokenType.Keyword:
15245
+ case TokenType.Operator:
15246
+ case TokenType.PrivateIdentifier:
15247
+ case TokenType.String:
15248
+ case TokenType.Error:
15110
15249
  return this.strValue;
15111
- case TokenType$1.Number:
15250
+ case TokenType.Number:
15112
15251
  return this.numValue.toString();
15113
15252
  default:
15114
15253
  return null;
@@ -15116,30 +15255,30 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
15116
15255
  }
15117
15256
  }
15118
15257
  function newCharacterToken(index, end, code) {
15119
- return new Token$1(index, end, TokenType$1.Character, code, String.fromCharCode(code));
15258
+ return new Token(index, end, TokenType.Character, code, String.fromCharCode(code));
15120
15259
  }
15121
15260
  function newIdentifierToken(index, end, text) {
15122
- return new Token$1(index, end, TokenType$1.Identifier, 0, text);
15261
+ return new Token(index, end, TokenType.Identifier, 0, text);
15123
15262
  }
15124
15263
  function newPrivateIdentifierToken(index, end, text) {
15125
- return new Token$1(index, end, TokenType$1.PrivateIdentifier, 0, text);
15264
+ return new Token(index, end, TokenType.PrivateIdentifier, 0, text);
15126
15265
  }
15127
15266
  function newKeywordToken(index, end, text) {
15128
- return new Token$1(index, end, TokenType$1.Keyword, 0, text);
15267
+ return new Token(index, end, TokenType.Keyword, 0, text);
15129
15268
  }
15130
15269
  function newOperatorToken(index, end, text) {
15131
- return new Token$1(index, end, TokenType$1.Operator, 0, text);
15270
+ return new Token(index, end, TokenType.Operator, 0, text);
15132
15271
  }
15133
15272
  function newStringToken(index, end, text) {
15134
- return new Token$1(index, end, TokenType$1.String, 0, text);
15273
+ return new Token(index, end, TokenType.String, 0, text);
15135
15274
  }
15136
15275
  function newNumberToken(index, end, n) {
15137
- return new Token$1(index, end, TokenType$1.Number, n, '');
15276
+ return new Token(index, end, TokenType.Number, n, '');
15138
15277
  }
15139
15278
  function newErrorToken(index, end, message) {
15140
- return new Token$1(index, end, TokenType$1.Error, 0, message);
15279
+ return new Token(index, end, TokenType.Error, 0, message);
15141
15280
  }
15142
- const EOF = new Token$1(-1, -1, TokenType$1.Character, 0, '');
15281
+ const EOF = new Token(-1, -1, TokenType.Character, 0, '');
15143
15282
  class _Scanner {
15144
15283
  constructor(input) {
15145
15284
  this.input = input;
@@ -16046,7 +16185,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
16046
16185
  // '==','!=','===','!=='
16047
16186
  const start = this.inputIndex;
16048
16187
  let result = this.parseRelational();
16049
- while (this.next.type == TokenType$1.Operator) {
16188
+ while (this.next.type == TokenType.Operator) {
16050
16189
  const operator = this.next.strValue;
16051
16190
  switch (operator) {
16052
16191
  case '==':
@@ -16066,7 +16205,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
16066
16205
  // '<', '>', '<=', '>='
16067
16206
  const start = this.inputIndex;
16068
16207
  let result = this.parseAdditive();
16069
- while (this.next.type == TokenType$1.Operator) {
16208
+ while (this.next.type == TokenType.Operator) {
16070
16209
  const operator = this.next.strValue;
16071
16210
  switch (operator) {
16072
16211
  case '<':
@@ -16086,7 +16225,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
16086
16225
  // '+', '-'
16087
16226
  const start = this.inputIndex;
16088
16227
  let result = this.parseMultiplicative();
16089
- while (this.next.type == TokenType$1.Operator) {
16228
+ while (this.next.type == TokenType.Operator) {
16090
16229
  const operator = this.next.strValue;
16091
16230
  switch (operator) {
16092
16231
  case '+':
@@ -16104,7 +16243,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
16104
16243
  // '*', '%', '/'
16105
16244
  const start = this.inputIndex;
16106
16245
  let result = this.parsePrefix();
16107
- while (this.next.type == TokenType$1.Operator) {
16246
+ while (this.next.type == TokenType.Operator) {
16108
16247
  const operator = this.next.strValue;
16109
16248
  switch (operator) {
16110
16249
  case '*':
@@ -16120,7 +16259,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
16120
16259
  return result;
16121
16260
  }
16122
16261
  parsePrefix() {
16123
- if (this.next.type == TokenType$1.Operator) {
16262
+ if (this.next.type == TokenType.Operator) {
16124
16263
  const start = this.inputIndex;
16125
16264
  const operator = this.next.strValue;
16126
16265
  let result;
@@ -18052,11 +18191,15 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
18052
18191
  return context.visitNodeFn(el, node);
18053
18192
  }
18054
18193
  visitAttribute(attribute, context) {
18055
- const node = this._visitTextWithInterpolation(attribute.value, attribute.valueSpan || attribute.sourceSpan, context, attribute.i18n);
18194
+ const node = attribute.valueTokens === undefined || attribute.valueTokens.length === 1 ?
18195
+ new Text$1(attribute.value, attribute.valueSpan || attribute.sourceSpan) :
18196
+ this._visitTextWithInterpolation(attribute.valueTokens, attribute.valueSpan || attribute.sourceSpan, context, attribute.i18n);
18056
18197
  return context.visitNodeFn(attribute, node);
18057
18198
  }
18058
18199
  visitText(text, context) {
18059
- const node = this._visitTextWithInterpolation(text.value, text.sourceSpan, context, text.i18n);
18200
+ const node = text.tokens.length === 1 ?
18201
+ new Text$1(text.value, text.sourceSpan) :
18202
+ this._visitTextWithInterpolation(text.tokens, text.sourceSpan, context, text.i18n);
18060
18203
  return context.visitNodeFn(text, node);
18061
18204
  }
18062
18205
  visitComment(comment, context) {
@@ -18095,61 +18238,58 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
18095
18238
  throw new Error('Unreachable code');
18096
18239
  }
18097
18240
  /**
18098
- * Split the, potentially interpolated, text up into text and placeholder pieces.
18241
+ * Convert, text and interpolated tokens up into text and placeholder pieces.
18099
18242
  *
18100
- * @param text The potentially interpolated string to be split.
18243
+ * @param tokens The text and interpolated tokens.
18101
18244
  * @param sourceSpan The span of the whole of the `text` string.
18102
18245
  * @param context The current context of the visitor, used to compute and store placeholders.
18103
18246
  * @param previousI18n Any i18n metadata associated with this `text` from a previous pass.
18104
18247
  */
18105
- _visitTextWithInterpolation(text, sourceSpan, context, previousI18n) {
18106
- const { strings, expressions } = this._expressionParser.splitInterpolation(text, sourceSpan.start.toString(), this._interpolationConfig);
18107
- // No expressions, return a single text.
18108
- if (expressions.length === 0) {
18109
- return new Text$1(text, sourceSpan);
18110
- }
18248
+ _visitTextWithInterpolation(tokens, sourceSpan, context, previousI18n) {
18111
18249
  // Return a sequence of `Text` and `Placeholder` nodes grouped in a `Container`.
18112
18250
  const nodes = [];
18113
- for (let i = 0; i < strings.length - 1; i++) {
18114
- this._addText(nodes, strings[i], sourceSpan);
18115
- this._addPlaceholder(nodes, context, expressions[i], sourceSpan);
18251
+ // We will only create a container if there are actually interpolations,
18252
+ // so this flag tracks that.
18253
+ let hasInterpolation = false;
18254
+ for (const token of tokens) {
18255
+ switch (token.type) {
18256
+ case 8 /* INTERPOLATION */:
18257
+ case 17 /* ATTR_VALUE_INTERPOLATION */:
18258
+ hasInterpolation = true;
18259
+ const expression = token.parts[1];
18260
+ const baseName = extractPlaceholderName(expression) || 'INTERPOLATION';
18261
+ const phName = context.placeholderRegistry.getPlaceholderName(baseName, expression);
18262
+ context.placeholderToContent[phName] = {
18263
+ text: token.parts.join(''),
18264
+ sourceSpan: token.sourceSpan
18265
+ };
18266
+ nodes.push(new Placeholder(expression, phName, token.sourceSpan));
18267
+ break;
18268
+ default:
18269
+ if (token.parts[0].length > 0) {
18270
+ // This token is text or an encoded entity.
18271
+ // If it is following on from a previous text node then merge it into that node
18272
+ // Otherwise, if it is following an interpolation, then add a new node.
18273
+ const previous = nodes[nodes.length - 1];
18274
+ if (previous instanceof Text$1) {
18275
+ previous.value += token.parts[0];
18276
+ previous.sourceSpan = new ParseSourceSpan(previous.sourceSpan.start, token.sourceSpan.end, previous.sourceSpan.fullStart, previous.sourceSpan.details);
18277
+ }
18278
+ else {
18279
+ nodes.push(new Text$1(token.parts[0], token.sourceSpan));
18280
+ }
18281
+ }
18282
+ break;
18283
+ }
18116
18284
  }
18117
- // The last index contains no expression
18118
- this._addText(nodes, strings[strings.length - 1], sourceSpan);
18119
- // Whitespace removal may have invalidated the interpolation source-spans.
18120
- reusePreviousSourceSpans(nodes, previousI18n);
18121
- return new Container(nodes, sourceSpan);
18122
- }
18123
- /**
18124
- * Create a new `Text` node from the `textPiece` and add it to the `nodes` collection.
18125
- *
18126
- * @param nodes The nodes to which the created `Text` node should be added.
18127
- * @param textPiece The text and relative span information for this `Text` node.
18128
- * @param interpolationSpan The span of the whole interpolated text.
18129
- */
18130
- _addText(nodes, textPiece, interpolationSpan) {
18131
- if (textPiece.text.length > 0) {
18132
- // No need to add empty strings
18133
- const stringSpan = getOffsetSourceSpan(interpolationSpan, textPiece);
18134
- nodes.push(new Text$1(textPiece.text, stringSpan));
18285
+ if (hasInterpolation) {
18286
+ // Whitespace removal may have invalidated the interpolation source-spans.
18287
+ reusePreviousSourceSpans(nodes, previousI18n);
18288
+ return new Container(nodes, sourceSpan);
18289
+ }
18290
+ else {
18291
+ return nodes[0];
18135
18292
  }
18136
- }
18137
- /**
18138
- * Create a new `Placeholder` node from the `expression` and add it to the `nodes` collection.
18139
- *
18140
- * @param nodes The nodes to which the created `Text` node should be added.
18141
- * @param context The current context of the visitor, used to compute and store placeholders.
18142
- * @param expression The expression text and relative span information for this `Placeholder`
18143
- * node.
18144
- * @param interpolationSpan The span of the whole interpolated text.
18145
- */
18146
- _addPlaceholder(nodes, context, expression, interpolationSpan) {
18147
- const sourceSpan = getOffsetSourceSpan(interpolationSpan, expression);
18148
- const baseName = extractPlaceholderName(expression.text) || 'INTERPOLATION';
18149
- const phName = context.placeholderRegistry.getPlaceholderName(baseName, expression.text);
18150
- const text = this._interpolationConfig.start + expression.text + this._interpolationConfig.end;
18151
- context.placeholderToContent[phName] = { text, sourceSpan };
18152
- nodes.push(new Placeholder(expression.text, phName, sourceSpan));
18153
18293
  }
18154
18294
  }
18155
18295
  /**
@@ -18171,7 +18311,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
18171
18311
  }
18172
18312
  if (previousI18n instanceof Container) {
18173
18313
  // The `previousI18n` is a `Container`, which means that this is a second i18n extraction pass
18174
- // after whitespace has been removed from the AST ndoes.
18314
+ // after whitespace has been removed from the AST nodes.
18175
18315
  assertEquivalentNodes(previousI18n.children, nodes);
18176
18316
  // Reuse the source-spans from the first pass.
18177
18317
  for (let i = 0; i < nodes.length; i++) {
@@ -18200,12 +18340,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
18200
18340
  throw new Error('The types of the i18n message children changed between first and second pass.');
18201
18341
  }
18202
18342
  }
18203
- /**
18204
- * Create a new `ParseSourceSpan` from the `sourceSpan`, offset by the `start` and `end` values.
18205
- */
18206
- function getOffsetSourceSpan(sourceSpan, { start, end }) {
18207
- return new ParseSourceSpan(sourceSpan.fullStart.moveBy(start), sourceSpan.fullStart.moveBy(end));
18208
- }
18209
18343
  const _CUSTOM_PH_EXP = /\/\/[\s\S]*i18n[\s\S]*\([\s\S]*ph[\s\S]*=[\s\S]*("|')([\s\S]*?)\1[\s\S]*\)/g;
18210
18344
  function extractPlaceholderName(input) {
18211
18345
  return input.split(_CUSTOM_PH_EXP)[2];
@@ -18525,7 +18659,8 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
18525
18659
  context[context.length - 1].text += text.value;
18526
18660
  }
18527
18661
  else {
18528
- context.push(new LiteralPiece(text.value, text.sourceSpan));
18662
+ const sourceSpan = new ParseSourceSpan(text.sourceSpan.fullStart, text.sourceSpan.end, text.sourceSpan.fullStart, text.sourceSpan.details);
18663
+ context.push(new LiteralPiece(text.value, sourceSpan));
18529
18664
  }
18530
18665
  }
18531
18666
  visitContainer(container, context) {
@@ -18569,7 +18704,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
18569
18704
  function getSourceSpan(message) {
18570
18705
  const startNode = message.nodes[0];
18571
18706
  const endNode = message.nodes[message.nodes.length - 1];
18572
- return new ParseSourceSpan(startNode.sourceSpan.start, endNode.sourceSpan.end, startNode.sourceSpan.fullStart, startNode.sourceSpan.details);
18707
+ return new ParseSourceSpan(startNode.sourceSpan.fullStart, endNode.sourceSpan.end, startNode.sourceSpan.fullStart, startNode.sourceSpan.details);
18573
18708
  }
18574
18709
  /**
18575
18710
  * Convert the list of serialized MessagePieces into two arrays.
@@ -21475,7 +21610,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
21475
21610
  * Use of this source code is governed by an MIT-style license that can be
21476
21611
  * found in the LICENSE file at https://angular.io/license
21477
21612
  */
21478
- const VERSION$1 = new Version('12.2.6');
21613
+ const VERSION$1 = new Version('12.2.7');
21479
21614
 
21480
21615
  /**
21481
21616
  * @license
@@ -36690,7 +36825,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
36690
36825
  /**
36691
36826
  * @publicApi
36692
36827
  */
36693
- const VERSION$2 = new Version$1('12.2.6');
36828
+ const VERSION$2 = new Version$1('12.2.7');
36694
36829
 
36695
36830
  /**
36696
36831
  * @license