@angular/language-service 12.2.0-rc.0 → 12.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/ivy.js +516 -310
- package/bundles/language-service.js +617 -623
- package/package.json +1 -1
package/bundles/ivy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v12.2.
|
|
2
|
+
* @license Angular v12.2.3
|
|
3
3
|
* Copyright Google LLC All Rights Reserved.
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -455,7 +455,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
455
455
|
return [null, elementName];
|
|
456
456
|
}
|
|
457
457
|
const colonIndex = elementName.indexOf(':', 1);
|
|
458
|
-
if (colonIndex
|
|
458
|
+
if (colonIndex === -1) {
|
|
459
459
|
throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
|
|
460
460
|
}
|
|
461
461
|
return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
|
|
@@ -506,7 +506,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
506
506
|
}
|
|
507
507
|
getContentType(prefix) {
|
|
508
508
|
if (typeof this.contentType === 'object') {
|
|
509
|
-
const overrideType = prefix
|
|
509
|
+
const overrideType = prefix === undefined ? undefined : this.contentType[prefix];
|
|
510
510
|
return overrideType !== null && overrideType !== void 0 ? overrideType : this.contentType.default;
|
|
511
511
|
}
|
|
512
512
|
return this.contentType;
|
|
@@ -2871,11 +2871,15 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
2871
2871
|
class RecursiveVisitor {
|
|
2872
2872
|
visitElement(element) {
|
|
2873
2873
|
visitAll(this, element.attributes);
|
|
2874
|
+
visitAll(this, element.inputs);
|
|
2875
|
+
visitAll(this, element.outputs);
|
|
2874
2876
|
visitAll(this, element.children);
|
|
2875
2877
|
visitAll(this, element.references);
|
|
2876
2878
|
}
|
|
2877
2879
|
visitTemplate(template) {
|
|
2878
2880
|
visitAll(this, template.attributes);
|
|
2881
|
+
visitAll(this, template.inputs);
|
|
2882
|
+
visitAll(this, template.outputs);
|
|
2879
2883
|
visitAll(this, template.children);
|
|
2880
2884
|
visitAll(this, template.references);
|
|
2881
2885
|
visitAll(this, template.variables);
|
|
@@ -4736,13 +4740,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
4736
4740
|
return shouldForwardDeclare ? fn([], [new ReturnStatement(values)]) : values;
|
|
4737
4741
|
}
|
|
4738
4742
|
|
|
4739
|
-
/**
|
|
4740
|
-
* @license
|
|
4741
|
-
* Copyright Google LLC All Rights Reserved.
|
|
4742
|
-
*
|
|
4743
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
4744
|
-
* found in the LICENSE file at https://angular.io/license
|
|
4745
|
-
*/
|
|
4746
4743
|
var R3FactoryDelegateType;
|
|
4747
4744
|
(function (R3FactoryDelegateType) {
|
|
4748
4745
|
R3FactoryDelegateType[R3FactoryDelegateType["Class"] = 0] = "Class";
|
|
@@ -5141,8 +5138,249 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
5141
5138
|
* Use of this source code is governed by an MIT-style license that can be
|
|
5142
5139
|
* found in the LICENSE file at https://angular.io/license
|
|
5143
5140
|
*/
|
|
5144
|
-
|
|
5145
|
-
|
|
5141
|
+
const $EOF = 0;
|
|
5142
|
+
const $BSPACE = 8;
|
|
5143
|
+
const $TAB = 9;
|
|
5144
|
+
const $LF = 10;
|
|
5145
|
+
const $VTAB = 11;
|
|
5146
|
+
const $FF = 12;
|
|
5147
|
+
const $CR = 13;
|
|
5148
|
+
const $SPACE = 32;
|
|
5149
|
+
const $BANG = 33;
|
|
5150
|
+
const $DQ = 34;
|
|
5151
|
+
const $HASH = 35;
|
|
5152
|
+
const $$ = 36;
|
|
5153
|
+
const $PERCENT = 37;
|
|
5154
|
+
const $AMPERSAND = 38;
|
|
5155
|
+
const $SQ = 39;
|
|
5156
|
+
const $LPAREN = 40;
|
|
5157
|
+
const $RPAREN = 41;
|
|
5158
|
+
const $STAR = 42;
|
|
5159
|
+
const $PLUS = 43;
|
|
5160
|
+
const $COMMA = 44;
|
|
5161
|
+
const $MINUS = 45;
|
|
5162
|
+
const $PERIOD = 46;
|
|
5163
|
+
const $SLASH = 47;
|
|
5164
|
+
const $COLON = 58;
|
|
5165
|
+
const $SEMICOLON = 59;
|
|
5166
|
+
const $LT = 60;
|
|
5167
|
+
const $EQ = 61;
|
|
5168
|
+
const $GT = 62;
|
|
5169
|
+
const $QUESTION = 63;
|
|
5170
|
+
const $0 = 48;
|
|
5171
|
+
const $7 = 55;
|
|
5172
|
+
const $9 = 57;
|
|
5173
|
+
const $A = 65;
|
|
5174
|
+
const $E = 69;
|
|
5175
|
+
const $F = 70;
|
|
5176
|
+
const $X = 88;
|
|
5177
|
+
const $Z = 90;
|
|
5178
|
+
const $LBRACKET = 91;
|
|
5179
|
+
const $BACKSLASH = 92;
|
|
5180
|
+
const $RBRACKET = 93;
|
|
5181
|
+
const $CARET = 94;
|
|
5182
|
+
const $_ = 95;
|
|
5183
|
+
const $a = 97;
|
|
5184
|
+
const $b = 98;
|
|
5185
|
+
const $e = 101;
|
|
5186
|
+
const $f = 102;
|
|
5187
|
+
const $n = 110;
|
|
5188
|
+
const $r = 114;
|
|
5189
|
+
const $t = 116;
|
|
5190
|
+
const $u = 117;
|
|
5191
|
+
const $v = 118;
|
|
5192
|
+
const $x = 120;
|
|
5193
|
+
const $z = 122;
|
|
5194
|
+
const $LBRACE = 123;
|
|
5195
|
+
const $BAR = 124;
|
|
5196
|
+
const $RBRACE = 125;
|
|
5197
|
+
const $NBSP = 160;
|
|
5198
|
+
const $BT = 96;
|
|
5199
|
+
function isWhitespace(code) {
|
|
5200
|
+
return (code >= $TAB && code <= $SPACE) || (code == $NBSP);
|
|
5201
|
+
}
|
|
5202
|
+
function isDigit(code) {
|
|
5203
|
+
return $0 <= code && code <= $9;
|
|
5204
|
+
}
|
|
5205
|
+
function isAsciiLetter(code) {
|
|
5206
|
+
return code >= $a && code <= $z || code >= $A && code <= $Z;
|
|
5207
|
+
}
|
|
5208
|
+
function isAsciiHexDigit(code) {
|
|
5209
|
+
return code >= $a && code <= $f || code >= $A && code <= $F || isDigit(code);
|
|
5210
|
+
}
|
|
5211
|
+
function isNewLine(code) {
|
|
5212
|
+
return code === $LF || code === $CR;
|
|
5213
|
+
}
|
|
5214
|
+
function isOctalDigit(code) {
|
|
5215
|
+
return $0 <= code && code <= $7;
|
|
5216
|
+
}
|
|
5217
|
+
function isQuote(code) {
|
|
5218
|
+
return code === $SQ || code === $DQ || code === $BT;
|
|
5219
|
+
}
|
|
5220
|
+
|
|
5221
|
+
/**
|
|
5222
|
+
* @license
|
|
5223
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5224
|
+
*
|
|
5225
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
5226
|
+
* found in the LICENSE file at https://angular.io/license
|
|
5227
|
+
*/
|
|
5228
|
+
class ParseLocation {
|
|
5229
|
+
constructor(file, offset, line, col) {
|
|
5230
|
+
this.file = file;
|
|
5231
|
+
this.offset = offset;
|
|
5232
|
+
this.line = line;
|
|
5233
|
+
this.col = col;
|
|
5234
|
+
}
|
|
5235
|
+
toString() {
|
|
5236
|
+
return this.offset != null ? `${this.file.url}@${this.line}:${this.col}` : this.file.url;
|
|
5237
|
+
}
|
|
5238
|
+
moveBy(delta) {
|
|
5239
|
+
const source = this.file.content;
|
|
5240
|
+
const len = source.length;
|
|
5241
|
+
let offset = this.offset;
|
|
5242
|
+
let line = this.line;
|
|
5243
|
+
let col = this.col;
|
|
5244
|
+
while (offset > 0 && delta < 0) {
|
|
5245
|
+
offset--;
|
|
5246
|
+
delta++;
|
|
5247
|
+
const ch = source.charCodeAt(offset);
|
|
5248
|
+
if (ch == $LF) {
|
|
5249
|
+
line--;
|
|
5250
|
+
const priorLine = source.substr(0, offset - 1).lastIndexOf(String.fromCharCode($LF));
|
|
5251
|
+
col = priorLine > 0 ? offset - priorLine : offset;
|
|
5252
|
+
}
|
|
5253
|
+
else {
|
|
5254
|
+
col--;
|
|
5255
|
+
}
|
|
5256
|
+
}
|
|
5257
|
+
while (offset < len && delta > 0) {
|
|
5258
|
+
const ch = source.charCodeAt(offset);
|
|
5259
|
+
offset++;
|
|
5260
|
+
delta--;
|
|
5261
|
+
if (ch == $LF) {
|
|
5262
|
+
line++;
|
|
5263
|
+
col = 0;
|
|
5264
|
+
}
|
|
5265
|
+
else {
|
|
5266
|
+
col++;
|
|
5267
|
+
}
|
|
5268
|
+
}
|
|
5269
|
+
return new ParseLocation(this.file, offset, line, col);
|
|
5270
|
+
}
|
|
5271
|
+
// Return the source around the location
|
|
5272
|
+
// Up to `maxChars` or `maxLines` on each side of the location
|
|
5273
|
+
getContext(maxChars, maxLines) {
|
|
5274
|
+
const content = this.file.content;
|
|
5275
|
+
let startOffset = this.offset;
|
|
5276
|
+
if (startOffset != null) {
|
|
5277
|
+
if (startOffset > content.length - 1) {
|
|
5278
|
+
startOffset = content.length - 1;
|
|
5279
|
+
}
|
|
5280
|
+
let endOffset = startOffset;
|
|
5281
|
+
let ctxChars = 0;
|
|
5282
|
+
let ctxLines = 0;
|
|
5283
|
+
while (ctxChars < maxChars && startOffset > 0) {
|
|
5284
|
+
startOffset--;
|
|
5285
|
+
ctxChars++;
|
|
5286
|
+
if (content[startOffset] == '\n') {
|
|
5287
|
+
if (++ctxLines == maxLines) {
|
|
5288
|
+
break;
|
|
5289
|
+
}
|
|
5290
|
+
}
|
|
5291
|
+
}
|
|
5292
|
+
ctxChars = 0;
|
|
5293
|
+
ctxLines = 0;
|
|
5294
|
+
while (ctxChars < maxChars && endOffset < content.length - 1) {
|
|
5295
|
+
endOffset++;
|
|
5296
|
+
ctxChars++;
|
|
5297
|
+
if (content[endOffset] == '\n') {
|
|
5298
|
+
if (++ctxLines == maxLines) {
|
|
5299
|
+
break;
|
|
5300
|
+
}
|
|
5301
|
+
}
|
|
5302
|
+
}
|
|
5303
|
+
return {
|
|
5304
|
+
before: content.substring(startOffset, this.offset),
|
|
5305
|
+
after: content.substring(this.offset, endOffset + 1),
|
|
5306
|
+
};
|
|
5307
|
+
}
|
|
5308
|
+
return null;
|
|
5309
|
+
}
|
|
5310
|
+
}
|
|
5311
|
+
class ParseSourceFile {
|
|
5312
|
+
constructor(content, url) {
|
|
5313
|
+
this.content = content;
|
|
5314
|
+
this.url = url;
|
|
5315
|
+
}
|
|
5316
|
+
}
|
|
5317
|
+
class ParseSourceSpan {
|
|
5318
|
+
/**
|
|
5319
|
+
* Create an object that holds information about spans of tokens/nodes captured during
|
|
5320
|
+
* lexing/parsing of text.
|
|
5321
|
+
*
|
|
5322
|
+
* @param start
|
|
5323
|
+
* The location of the start of the span (having skipped leading trivia).
|
|
5324
|
+
* Skipping leading trivia makes source-spans more "user friendly", since things like HTML
|
|
5325
|
+
* elements will appear to begin at the start of the opening tag, rather than at the start of any
|
|
5326
|
+
* leading trivia, which could include newlines.
|
|
5327
|
+
*
|
|
5328
|
+
* @param end
|
|
5329
|
+
* The location of the end of the span.
|
|
5330
|
+
*
|
|
5331
|
+
* @param fullStart
|
|
5332
|
+
* The start of the token without skipping the leading trivia.
|
|
5333
|
+
* This is used by tooling that splits tokens further, such as extracting Angular interpolations
|
|
5334
|
+
* from text tokens. Such tooling creates new source-spans relative to the original token's
|
|
5335
|
+
* source-span. If leading trivia characters have been skipped then the new source-spans may be
|
|
5336
|
+
* incorrectly offset.
|
|
5337
|
+
*
|
|
5338
|
+
* @param details
|
|
5339
|
+
* Additional information (such as identifier names) that should be associated with the span.
|
|
5340
|
+
*/
|
|
5341
|
+
constructor(start, end, fullStart = start, details = null) {
|
|
5342
|
+
this.start = start;
|
|
5343
|
+
this.end = end;
|
|
5344
|
+
this.fullStart = fullStart;
|
|
5345
|
+
this.details = details;
|
|
5346
|
+
}
|
|
5347
|
+
toString() {
|
|
5348
|
+
return this.start.file.content.substring(this.start.offset, this.end.offset);
|
|
5349
|
+
}
|
|
5350
|
+
}
|
|
5351
|
+
var ParseErrorLevel;
|
|
5352
|
+
(function (ParseErrorLevel) {
|
|
5353
|
+
ParseErrorLevel[ParseErrorLevel["WARNING"] = 0] = "WARNING";
|
|
5354
|
+
ParseErrorLevel[ParseErrorLevel["ERROR"] = 1] = "ERROR";
|
|
5355
|
+
})(ParseErrorLevel || (ParseErrorLevel = {}));
|
|
5356
|
+
class ParseError {
|
|
5357
|
+
constructor(span, msg, level = ParseErrorLevel.ERROR) {
|
|
5358
|
+
this.span = span;
|
|
5359
|
+
this.msg = msg;
|
|
5360
|
+
this.level = level;
|
|
5361
|
+
}
|
|
5362
|
+
contextualMessage() {
|
|
5363
|
+
const ctx = this.span.start.getContext(100, 3);
|
|
5364
|
+
return ctx ? `${this.msg} ("${ctx.before}[${ParseErrorLevel[this.level]} ->]${ctx.after}")` :
|
|
5365
|
+
this.msg;
|
|
5366
|
+
}
|
|
5367
|
+
toString() {
|
|
5368
|
+
const details = this.span.details ? `, ${this.span.details}` : '';
|
|
5369
|
+
return `${this.contextualMessage()}: ${this.span.start}${details}`;
|
|
5370
|
+
}
|
|
5371
|
+
}
|
|
5372
|
+
/**
|
|
5373
|
+
* Generates Source Span object for a given R3 Type for JIT mode.
|
|
5374
|
+
*
|
|
5375
|
+
* @param kind Component or Directive.
|
|
5376
|
+
* @param typeName name of the Component or Directive.
|
|
5377
|
+
* @param sourceUrl reference to Component or Directive source.
|
|
5378
|
+
* @returns instance of ParseSourceSpan that represent a given Component or Directive.
|
|
5379
|
+
*/
|
|
5380
|
+
function r3JitTypeSourceSpan(kind, typeName, sourceUrl) {
|
|
5381
|
+
const sourceFileName = `in ${kind} ${typeName} in ${sourceUrl}`;
|
|
5382
|
+
const sourceFile = new ParseSourceFile('', sourceFileName);
|
|
5383
|
+
return new ParseSourceSpan(new ParseLocation(sourceFile, -1, -1, -1), new ParseLocation(sourceFile, -1, -1, -1));
|
|
5146
5384
|
}
|
|
5147
5385
|
let _anonymousTypeIndex = 0;
|
|
5148
5386
|
function identifierName(compileIdentifier) {
|
|
@@ -5172,18 +5410,8 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
5172
5410
|
}
|
|
5173
5411
|
return identifier;
|
|
5174
5412
|
}
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
CompileSummaryKind[CompileSummaryKind["Pipe"] = 0] = "Pipe";
|
|
5178
|
-
CompileSummaryKind[CompileSummaryKind["Directive"] = 1] = "Directive";
|
|
5179
|
-
CompileSummaryKind[CompileSummaryKind["NgModule"] = 2] = "NgModule";
|
|
5180
|
-
CompileSummaryKind[CompileSummaryKind["Injectable"] = 3] = "Injectable";
|
|
5181
|
-
})(CompileSummaryKind || (CompileSummaryKind = {}));
|
|
5182
|
-
function flatten(list) {
|
|
5183
|
-
return list.reduce((flat, item) => {
|
|
5184
|
-
const flatItem = Array.isArray(item) ? flatten(item) : item;
|
|
5185
|
-
return flat.concat(flatItem);
|
|
5186
|
-
}, []);
|
|
5413
|
+
function sanitizeIdentifier(name) {
|
|
5414
|
+
return name.replace(/\W/g, '_');
|
|
5187
5415
|
}
|
|
5188
5416
|
|
|
5189
5417
|
/**
|
|
@@ -5639,255 +5867,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
5639
5867
|
return statement.isEquivalent(literal('use strict').toStmt());
|
|
5640
5868
|
}
|
|
5641
5869
|
|
|
5642
|
-
/**
|
|
5643
|
-
* @license
|
|
5644
|
-
* Copyright Google LLC All Rights Reserved.
|
|
5645
|
-
*
|
|
5646
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
5647
|
-
* found in the LICENSE file at https://angular.io/license
|
|
5648
|
-
*/
|
|
5649
|
-
const $EOF = 0;
|
|
5650
|
-
const $BSPACE = 8;
|
|
5651
|
-
const $TAB = 9;
|
|
5652
|
-
const $LF = 10;
|
|
5653
|
-
const $VTAB = 11;
|
|
5654
|
-
const $FF = 12;
|
|
5655
|
-
const $CR = 13;
|
|
5656
|
-
const $SPACE = 32;
|
|
5657
|
-
const $BANG = 33;
|
|
5658
|
-
const $DQ = 34;
|
|
5659
|
-
const $HASH = 35;
|
|
5660
|
-
const $$ = 36;
|
|
5661
|
-
const $PERCENT = 37;
|
|
5662
|
-
const $AMPERSAND = 38;
|
|
5663
|
-
const $SQ = 39;
|
|
5664
|
-
const $LPAREN = 40;
|
|
5665
|
-
const $RPAREN = 41;
|
|
5666
|
-
const $STAR = 42;
|
|
5667
|
-
const $PLUS = 43;
|
|
5668
|
-
const $COMMA = 44;
|
|
5669
|
-
const $MINUS = 45;
|
|
5670
|
-
const $PERIOD = 46;
|
|
5671
|
-
const $SLASH = 47;
|
|
5672
|
-
const $COLON = 58;
|
|
5673
|
-
const $SEMICOLON = 59;
|
|
5674
|
-
const $LT = 60;
|
|
5675
|
-
const $EQ = 61;
|
|
5676
|
-
const $GT = 62;
|
|
5677
|
-
const $QUESTION = 63;
|
|
5678
|
-
const $0 = 48;
|
|
5679
|
-
const $7 = 55;
|
|
5680
|
-
const $9 = 57;
|
|
5681
|
-
const $A = 65;
|
|
5682
|
-
const $E = 69;
|
|
5683
|
-
const $F = 70;
|
|
5684
|
-
const $X = 88;
|
|
5685
|
-
const $Z = 90;
|
|
5686
|
-
const $LBRACKET = 91;
|
|
5687
|
-
const $BACKSLASH = 92;
|
|
5688
|
-
const $RBRACKET = 93;
|
|
5689
|
-
const $CARET = 94;
|
|
5690
|
-
const $_ = 95;
|
|
5691
|
-
const $a = 97;
|
|
5692
|
-
const $b = 98;
|
|
5693
|
-
const $e = 101;
|
|
5694
|
-
const $f = 102;
|
|
5695
|
-
const $n = 110;
|
|
5696
|
-
const $r = 114;
|
|
5697
|
-
const $t = 116;
|
|
5698
|
-
const $u = 117;
|
|
5699
|
-
const $v = 118;
|
|
5700
|
-
const $x = 120;
|
|
5701
|
-
const $z = 122;
|
|
5702
|
-
const $LBRACE = 123;
|
|
5703
|
-
const $BAR = 124;
|
|
5704
|
-
const $RBRACE = 125;
|
|
5705
|
-
const $NBSP = 160;
|
|
5706
|
-
const $BT = 96;
|
|
5707
|
-
function isWhitespace(code) {
|
|
5708
|
-
return (code >= $TAB && code <= $SPACE) || (code == $NBSP);
|
|
5709
|
-
}
|
|
5710
|
-
function isDigit(code) {
|
|
5711
|
-
return $0 <= code && code <= $9;
|
|
5712
|
-
}
|
|
5713
|
-
function isAsciiLetter(code) {
|
|
5714
|
-
return code >= $a && code <= $z || code >= $A && code <= $Z;
|
|
5715
|
-
}
|
|
5716
|
-
function isAsciiHexDigit(code) {
|
|
5717
|
-
return code >= $a && code <= $f || code >= $A && code <= $F || isDigit(code);
|
|
5718
|
-
}
|
|
5719
|
-
function isNewLine(code) {
|
|
5720
|
-
return code === $LF || code === $CR;
|
|
5721
|
-
}
|
|
5722
|
-
function isOctalDigit(code) {
|
|
5723
|
-
return $0 <= code && code <= $7;
|
|
5724
|
-
}
|
|
5725
|
-
|
|
5726
|
-
/**
|
|
5727
|
-
* @license
|
|
5728
|
-
* Copyright Google LLC All Rights Reserved.
|
|
5729
|
-
*
|
|
5730
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
5731
|
-
* found in the LICENSE file at https://angular.io/license
|
|
5732
|
-
*/
|
|
5733
|
-
class ParseLocation {
|
|
5734
|
-
constructor(file, offset, line, col) {
|
|
5735
|
-
this.file = file;
|
|
5736
|
-
this.offset = offset;
|
|
5737
|
-
this.line = line;
|
|
5738
|
-
this.col = col;
|
|
5739
|
-
}
|
|
5740
|
-
toString() {
|
|
5741
|
-
return this.offset != null ? `${this.file.url}@${this.line}:${this.col}` : this.file.url;
|
|
5742
|
-
}
|
|
5743
|
-
moveBy(delta) {
|
|
5744
|
-
const source = this.file.content;
|
|
5745
|
-
const len = source.length;
|
|
5746
|
-
let offset = this.offset;
|
|
5747
|
-
let line = this.line;
|
|
5748
|
-
let col = this.col;
|
|
5749
|
-
while (offset > 0 && delta < 0) {
|
|
5750
|
-
offset--;
|
|
5751
|
-
delta++;
|
|
5752
|
-
const ch = source.charCodeAt(offset);
|
|
5753
|
-
if (ch == $LF) {
|
|
5754
|
-
line--;
|
|
5755
|
-
const priorLine = source.substr(0, offset - 1).lastIndexOf(String.fromCharCode($LF));
|
|
5756
|
-
col = priorLine > 0 ? offset - priorLine : offset;
|
|
5757
|
-
}
|
|
5758
|
-
else {
|
|
5759
|
-
col--;
|
|
5760
|
-
}
|
|
5761
|
-
}
|
|
5762
|
-
while (offset < len && delta > 0) {
|
|
5763
|
-
const ch = source.charCodeAt(offset);
|
|
5764
|
-
offset++;
|
|
5765
|
-
delta--;
|
|
5766
|
-
if (ch == $LF) {
|
|
5767
|
-
line++;
|
|
5768
|
-
col = 0;
|
|
5769
|
-
}
|
|
5770
|
-
else {
|
|
5771
|
-
col++;
|
|
5772
|
-
}
|
|
5773
|
-
}
|
|
5774
|
-
return new ParseLocation(this.file, offset, line, col);
|
|
5775
|
-
}
|
|
5776
|
-
// Return the source around the location
|
|
5777
|
-
// Up to `maxChars` or `maxLines` on each side of the location
|
|
5778
|
-
getContext(maxChars, maxLines) {
|
|
5779
|
-
const content = this.file.content;
|
|
5780
|
-
let startOffset = this.offset;
|
|
5781
|
-
if (startOffset != null) {
|
|
5782
|
-
if (startOffset > content.length - 1) {
|
|
5783
|
-
startOffset = content.length - 1;
|
|
5784
|
-
}
|
|
5785
|
-
let endOffset = startOffset;
|
|
5786
|
-
let ctxChars = 0;
|
|
5787
|
-
let ctxLines = 0;
|
|
5788
|
-
while (ctxChars < maxChars && startOffset > 0) {
|
|
5789
|
-
startOffset--;
|
|
5790
|
-
ctxChars++;
|
|
5791
|
-
if (content[startOffset] == '\n') {
|
|
5792
|
-
if (++ctxLines == maxLines) {
|
|
5793
|
-
break;
|
|
5794
|
-
}
|
|
5795
|
-
}
|
|
5796
|
-
}
|
|
5797
|
-
ctxChars = 0;
|
|
5798
|
-
ctxLines = 0;
|
|
5799
|
-
while (ctxChars < maxChars && endOffset < content.length - 1) {
|
|
5800
|
-
endOffset++;
|
|
5801
|
-
ctxChars++;
|
|
5802
|
-
if (content[endOffset] == '\n') {
|
|
5803
|
-
if (++ctxLines == maxLines) {
|
|
5804
|
-
break;
|
|
5805
|
-
}
|
|
5806
|
-
}
|
|
5807
|
-
}
|
|
5808
|
-
return {
|
|
5809
|
-
before: content.substring(startOffset, this.offset),
|
|
5810
|
-
after: content.substring(this.offset, endOffset + 1),
|
|
5811
|
-
};
|
|
5812
|
-
}
|
|
5813
|
-
return null;
|
|
5814
|
-
}
|
|
5815
|
-
}
|
|
5816
|
-
class ParseSourceFile {
|
|
5817
|
-
constructor(content, url) {
|
|
5818
|
-
this.content = content;
|
|
5819
|
-
this.url = url;
|
|
5820
|
-
}
|
|
5821
|
-
}
|
|
5822
|
-
class ParseSourceSpan {
|
|
5823
|
-
/**
|
|
5824
|
-
* Create an object that holds information about spans of tokens/nodes captured during
|
|
5825
|
-
* lexing/parsing of text.
|
|
5826
|
-
*
|
|
5827
|
-
* @param start
|
|
5828
|
-
* The location of the start of the span (having skipped leading trivia).
|
|
5829
|
-
* Skipping leading trivia makes source-spans more "user friendly", since things like HTML
|
|
5830
|
-
* elements will appear to begin at the start of the opening tag, rather than at the start of any
|
|
5831
|
-
* leading trivia, which could include newlines.
|
|
5832
|
-
*
|
|
5833
|
-
* @param end
|
|
5834
|
-
* The location of the end of the span.
|
|
5835
|
-
*
|
|
5836
|
-
* @param fullStart
|
|
5837
|
-
* The start of the token without skipping the leading trivia.
|
|
5838
|
-
* This is used by tooling that splits tokens further, such as extracting Angular interpolations
|
|
5839
|
-
* from text tokens. Such tooling creates new source-spans relative to the original token's
|
|
5840
|
-
* source-span. If leading trivia characters have been skipped then the new source-spans may be
|
|
5841
|
-
* incorrectly offset.
|
|
5842
|
-
*
|
|
5843
|
-
* @param details
|
|
5844
|
-
* Additional information (such as identifier names) that should be associated with the span.
|
|
5845
|
-
*/
|
|
5846
|
-
constructor(start, end, fullStart = start, details = null) {
|
|
5847
|
-
this.start = start;
|
|
5848
|
-
this.end = end;
|
|
5849
|
-
this.fullStart = fullStart;
|
|
5850
|
-
this.details = details;
|
|
5851
|
-
}
|
|
5852
|
-
toString() {
|
|
5853
|
-
return this.start.file.content.substring(this.start.offset, this.end.offset);
|
|
5854
|
-
}
|
|
5855
|
-
}
|
|
5856
|
-
var ParseErrorLevel;
|
|
5857
|
-
(function (ParseErrorLevel) {
|
|
5858
|
-
ParseErrorLevel[ParseErrorLevel["WARNING"] = 0] = "WARNING";
|
|
5859
|
-
ParseErrorLevel[ParseErrorLevel["ERROR"] = 1] = "ERROR";
|
|
5860
|
-
})(ParseErrorLevel || (ParseErrorLevel = {}));
|
|
5861
|
-
class ParseError {
|
|
5862
|
-
constructor(span, msg, level = ParseErrorLevel.ERROR) {
|
|
5863
|
-
this.span = span;
|
|
5864
|
-
this.msg = msg;
|
|
5865
|
-
this.level = level;
|
|
5866
|
-
}
|
|
5867
|
-
contextualMessage() {
|
|
5868
|
-
const ctx = this.span.start.getContext(100, 3);
|
|
5869
|
-
return ctx ? `${this.msg} ("${ctx.before}[${ParseErrorLevel[this.level]} ->]${ctx.after}")` :
|
|
5870
|
-
this.msg;
|
|
5871
|
-
}
|
|
5872
|
-
toString() {
|
|
5873
|
-
const details = this.span.details ? `, ${this.span.details}` : '';
|
|
5874
|
-
return `${this.contextualMessage()}: ${this.span.start}${details}`;
|
|
5875
|
-
}
|
|
5876
|
-
}
|
|
5877
|
-
/**
|
|
5878
|
-
* Generates Source Span object for a given R3 Type for JIT mode.
|
|
5879
|
-
*
|
|
5880
|
-
* @param kind Component or Directive.
|
|
5881
|
-
* @param typeName name of the Component or Directive.
|
|
5882
|
-
* @param sourceUrl reference to Component or Directive source.
|
|
5883
|
-
* @returns instance of ParseSourceSpan that represent a given Component or Directive.
|
|
5884
|
-
*/
|
|
5885
|
-
function r3JitTypeSourceSpan(kind, typeName, sourceUrl) {
|
|
5886
|
-
const sourceFileName = `in ${kind} ${typeName} in ${sourceUrl}`;
|
|
5887
|
-
const sourceFile = new ParseSourceFile('', sourceFileName);
|
|
5888
|
-
return new ParseSourceSpan(new ParseLocation(sourceFile, -1, -1, -1), new ParseLocation(sourceFile, -1, -1, -1));
|
|
5889
|
-
}
|
|
5890
|
-
|
|
5891
5870
|
/**
|
|
5892
5871
|
* @license
|
|
5893
5872
|
* Copyright Google LLC All Rights Reserved.
|
|
@@ -8460,7 +8439,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
8460
8439
|
// Support for `>>>`, `deep`, `::ng-deep` is then also deprecated and will be removed in the future.
|
|
8461
8440
|
// see https://github.com/angular/angular/pull/17677
|
|
8462
8441
|
const _shadowDeepSelectors = /(?:>>>)|(?:\/deep\/)|(?:::ng-deep)/g;
|
|
8463
|
-
const _selectorReSuffix = '([>\\s
|
|
8442
|
+
const _selectorReSuffix = '([>\\s~+[.,{:][\\s\\S]*)?$';
|
|
8464
8443
|
const _polyfillHostRe = /-shadowcsshost/gim;
|
|
8465
8444
|
const _colonHostRe = /:host/gim;
|
|
8466
8445
|
const _colonHostContextRe = /:host-context/gim;
|
|
@@ -8629,6 +8608,27 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
8629
8608
|
}
|
|
8630
8609
|
}
|
|
8631
8610
|
|
|
8611
|
+
/**
|
|
8612
|
+
* @license
|
|
8613
|
+
* Copyright Google LLC All Rights Reserved.
|
|
8614
|
+
*
|
|
8615
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
8616
|
+
* found in the LICENSE file at https://angular.io/license
|
|
8617
|
+
*/
|
|
8618
|
+
var CompileSummaryKind;
|
|
8619
|
+
(function (CompileSummaryKind) {
|
|
8620
|
+
CompileSummaryKind[CompileSummaryKind["Pipe"] = 0] = "Pipe";
|
|
8621
|
+
CompileSummaryKind[CompileSummaryKind["Directive"] = 1] = "Directive";
|
|
8622
|
+
CompileSummaryKind[CompileSummaryKind["NgModule"] = 2] = "NgModule";
|
|
8623
|
+
CompileSummaryKind[CompileSummaryKind["Injectable"] = 3] = "Injectable";
|
|
8624
|
+
})(CompileSummaryKind || (CompileSummaryKind = {}));
|
|
8625
|
+
function flatten(list) {
|
|
8626
|
+
return list.reduce((flat, item) => {
|
|
8627
|
+
const flatItem = Array.isArray(item) ? flatten(item) : item;
|
|
8628
|
+
return flat.concat(flatItem);
|
|
8629
|
+
}, []);
|
|
8630
|
+
}
|
|
8631
|
+
|
|
8632
8632
|
/**
|
|
8633
8633
|
* @license
|
|
8634
8634
|
* Copyright Google LLC All Rights Reserved.
|
|
@@ -11540,16 +11540,16 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11540
11540
|
(code < $0 || code > $9);
|
|
11541
11541
|
}
|
|
11542
11542
|
function isDigitEntityEnd(code) {
|
|
11543
|
-
return code
|
|
11543
|
+
return code === $SEMICOLON || code === $EOF || !isAsciiHexDigit(code);
|
|
11544
11544
|
}
|
|
11545
11545
|
function isNamedEntityEnd(code) {
|
|
11546
|
-
return code
|
|
11546
|
+
return code === $SEMICOLON || code === $EOF || !isAsciiLetter(code);
|
|
11547
11547
|
}
|
|
11548
11548
|
function isExpansionCaseStart(peek) {
|
|
11549
11549
|
return peek !== $RBRACE;
|
|
11550
11550
|
}
|
|
11551
11551
|
function compareCharCodeCaseInsensitive(code1, code2) {
|
|
11552
|
-
return toUpperCaseCharCode(code1)
|
|
11552
|
+
return toUpperCaseCharCode(code1) === toUpperCaseCharCode(code2);
|
|
11553
11553
|
}
|
|
11554
11554
|
function toUpperCaseCharCode(code) {
|
|
11555
11555
|
return code >= $a && code <= $z ? code - $a + $A : code;
|
|
@@ -11559,7 +11559,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11559
11559
|
let lastDstToken = undefined;
|
|
11560
11560
|
for (let i = 0; i < srcTokens.length; i++) {
|
|
11561
11561
|
const token = srcTokens[i];
|
|
11562
|
-
if (lastDstToken && lastDstToken.type
|
|
11562
|
+
if (lastDstToken && lastDstToken.type === TokenType.TEXT && token.type === TokenType.TEXT) {
|
|
11563
11563
|
lastDstToken.parts[0] += token.parts[0];
|
|
11564
11564
|
lastDstToken.sourceSpan.end = token.sourceSpan.end;
|
|
11565
11565
|
}
|
|
@@ -11963,7 +11963,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11963
11963
|
if (this._peek.type === TokenType.EXPANSION_CASE_EXP_END) {
|
|
11964
11964
|
if (lastOnStack(expansionFormStack, TokenType.EXPANSION_CASE_EXP_START)) {
|
|
11965
11965
|
expansionFormStack.pop();
|
|
11966
|
-
if (expansionFormStack.length
|
|
11966
|
+
if (expansionFormStack.length === 0)
|
|
11967
11967
|
return exp;
|
|
11968
11968
|
}
|
|
11969
11969
|
else {
|
|
@@ -11989,9 +11989,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11989
11989
|
}
|
|
11990
11990
|
_consumeText(token) {
|
|
11991
11991
|
let text = token.parts[0];
|
|
11992
|
-
if (text.length > 0 && text[0]
|
|
11992
|
+
if (text.length > 0 && text[0] === '\n') {
|
|
11993
11993
|
const parent = this._getParentElement();
|
|
11994
|
-
if (parent != null && parent.children.length
|
|
11994
|
+
if (parent != null && parent.children.length === 0 &&
|
|
11995
11995
|
this.getTagDefinition(parent.name).ignoreFirstLf) {
|
|
11996
11996
|
text = text.substring(1);
|
|
11997
11997
|
}
|
|
@@ -12074,7 +12074,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
12074
12074
|
let unexpectedCloseTagDetected = false;
|
|
12075
12075
|
for (let stackIndex = this._elementStack.length - 1; stackIndex >= 0; stackIndex--) {
|
|
12076
12076
|
const el = this._elementStack[stackIndex];
|
|
12077
|
-
if (el.name
|
|
12077
|
+
if (el.name === fullName) {
|
|
12078
12078
|
// Record the parse span with the element that is being closed. Any elements that are
|
|
12079
12079
|
// removed from the element stack at this point are closed implicitly, so they won't get
|
|
12080
12080
|
// an end source span (as there is no explicit closing element).
|
|
@@ -13866,9 +13866,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
13866
13866
|
function isExponentSign(code) {
|
|
13867
13867
|
return code == $MINUS || code == $PLUS;
|
|
13868
13868
|
}
|
|
13869
|
-
function isQuote(code) {
|
|
13870
|
-
return code === $SQ || code === $DQ || code === $BT;
|
|
13871
|
-
}
|
|
13872
13869
|
function unescape(code) {
|
|
13873
13870
|
switch (code) {
|
|
13874
13871
|
case $n:
|
|
@@ -19941,7 +19938,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
19941
19938
|
* Use of this source code is governed by an MIT-style license that can be
|
|
19942
19939
|
* found in the LICENSE file at https://angular.io/license
|
|
19943
19940
|
*/
|
|
19944
|
-
const VERSION$1 = new Version('12.2.
|
|
19941
|
+
const VERSION$1 = new Version('12.2.3');
|
|
19945
19942
|
|
|
19946
19943
|
/**
|
|
19947
19944
|
* @license
|
|
@@ -20580,7 +20577,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
20580
20577
|
function compileDeclareClassMetadata(metadata) {
|
|
20581
20578
|
const definitionMap = new DefinitionMap();
|
|
20582
20579
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
20583
|
-
definitionMap.set('version', literal('12.2.
|
|
20580
|
+
definitionMap.set('version', literal('12.2.3'));
|
|
20584
20581
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
20585
20582
|
definitionMap.set('type', metadata.type);
|
|
20586
20583
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -20620,7 +20617,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
20620
20617
|
function createDirectiveDefinitionMap(meta) {
|
|
20621
20618
|
const definitionMap = new DefinitionMap();
|
|
20622
20619
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
20623
|
-
definitionMap.set('version', literal('12.2.
|
|
20620
|
+
definitionMap.set('version', literal('12.2.3'));
|
|
20624
20621
|
// e.g. `type: MyDirective`
|
|
20625
20622
|
definitionMap.set('type', meta.internalType);
|
|
20626
20623
|
// e.g. `selector: 'some-dir'`
|
|
@@ -20837,7 +20834,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
20837
20834
|
function compileDeclareFactoryFunction(meta) {
|
|
20838
20835
|
const definitionMap = new DefinitionMap();
|
|
20839
20836
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
20840
|
-
definitionMap.set('version', literal('12.2.
|
|
20837
|
+
definitionMap.set('version', literal('12.2.3'));
|
|
20841
20838
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
20842
20839
|
definitionMap.set('type', meta.internalType);
|
|
20843
20840
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -20879,7 +20876,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
20879
20876
|
function createInjectableDefinitionMap(meta) {
|
|
20880
20877
|
const definitionMap = new DefinitionMap();
|
|
20881
20878
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
20882
|
-
definitionMap.set('version', literal('12.2.
|
|
20879
|
+
definitionMap.set('version', literal('12.2.3'));
|
|
20883
20880
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
20884
20881
|
definitionMap.set('type', meta.internalType);
|
|
20885
20882
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -20958,7 +20955,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
20958
20955
|
function createInjectorDefinitionMap(meta) {
|
|
20959
20956
|
const definitionMap = new DefinitionMap();
|
|
20960
20957
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
20961
|
-
definitionMap.set('version', literal('12.2.
|
|
20958
|
+
definitionMap.set('version', literal('12.2.3'));
|
|
20962
20959
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
20963
20960
|
definitionMap.set('type', meta.internalType);
|
|
20964
20961
|
definitionMap.set('providers', meta.providers);
|
|
@@ -20995,7 +20992,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
20995
20992
|
function createNgModuleDefinitionMap(meta) {
|
|
20996
20993
|
const definitionMap = new DefinitionMap();
|
|
20997
20994
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
|
|
20998
|
-
definitionMap.set('version', literal('12.2.
|
|
20995
|
+
definitionMap.set('version', literal('12.2.3'));
|
|
20999
20996
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
21000
20997
|
definitionMap.set('type', meta.internalType);
|
|
21001
20998
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -21053,7 +21050,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
21053
21050
|
function createPipeDefinitionMap(meta) {
|
|
21054
21051
|
const definitionMap = new DefinitionMap();
|
|
21055
21052
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
21056
|
-
definitionMap.set('version', literal('12.2.
|
|
21053
|
+
definitionMap.set('version', literal('12.2.3'));
|
|
21057
21054
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
21058
21055
|
// e.g. `type: MyPipe`
|
|
21059
21056
|
definitionMap.set('type', meta.internalType);
|
|
@@ -21085,7 +21082,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
21085
21082
|
* Use of this source code is governed by an MIT-style license that can be
|
|
21086
21083
|
* found in the LICENSE file at https://angular.io/license
|
|
21087
21084
|
*/
|
|
21088
|
-
const VERSION$2 = new Version('12.2.
|
|
21085
|
+
const VERSION$2 = new Version('12.2.3');
|
|
21089
21086
|
|
|
21090
21087
|
/**
|
|
21091
21088
|
* @license
|
|
@@ -21288,6 +21285,15 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
21288
21285
|
* in which the input and output are going to different places.
|
|
21289
21286
|
*/
|
|
21290
21287
|
ErrorCode[ErrorCode["SPLIT_TWO_WAY_BINDING"] = 8007] = "SPLIT_TWO_WAY_BINDING";
|
|
21288
|
+
/**
|
|
21289
|
+
* A two way binding in a template has an incorrect syntax,
|
|
21290
|
+
* parentheses outside brackets. For example:
|
|
21291
|
+
*
|
|
21292
|
+
* ```
|
|
21293
|
+
* <div ([foo])="bar" />
|
|
21294
|
+
* ```
|
|
21295
|
+
*/
|
|
21296
|
+
ErrorCode[ErrorCode["INVALID_BANANA_IN_BOX"] = 8101] = "INVALID_BANANA_IN_BOX";
|
|
21291
21297
|
/**
|
|
21292
21298
|
* The template type-checking engine would need to generate an inline type check block for a
|
|
21293
21299
|
* component, but the current type-checking environment doesn't support it.
|
|
@@ -26540,6 +26546,26 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
26540
26546
|
}
|
|
26541
26547
|
}
|
|
26542
26548
|
}
|
|
26549
|
+
extendedTemplateCheck(sf, extendedTemplateChecker) {
|
|
26550
|
+
const classes = this.fileToClasses.get(sf);
|
|
26551
|
+
if (classes === undefined) {
|
|
26552
|
+
return [];
|
|
26553
|
+
}
|
|
26554
|
+
const diagnostics = [];
|
|
26555
|
+
for (const clazz of classes) {
|
|
26556
|
+
if (!isNamedClassDeclaration(clazz)) {
|
|
26557
|
+
continue;
|
|
26558
|
+
}
|
|
26559
|
+
const record = this.classes.get(clazz);
|
|
26560
|
+
for (const trait of record.traits) {
|
|
26561
|
+
if (trait.handler.extendedTemplateCheck === undefined) {
|
|
26562
|
+
continue;
|
|
26563
|
+
}
|
|
26564
|
+
diagnostics.push(...trait.handler.extendedTemplateCheck(clazz, extendedTemplateChecker));
|
|
26565
|
+
}
|
|
26566
|
+
}
|
|
26567
|
+
return diagnostics;
|
|
26568
|
+
}
|
|
26543
26569
|
index(ctx) {
|
|
26544
26570
|
for (const clazz of this.classes.keys()) {
|
|
26545
26571
|
const record = this.classes.get(clazz);
|
|
@@ -30547,6 +30573,9 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
30547
30573
|
const binder = new R3TargetBinder(scope.matcher);
|
|
30548
30574
|
ctx.addTemplate(new Reference$1(node), binder, meta.template.diagNodes, scope.pipes, scope.schemas, meta.template.sourceMapping, meta.template.file, meta.template.errors);
|
|
30549
30575
|
}
|
|
30576
|
+
extendedTemplateCheck(component, extendedTemplateChecker) {
|
|
30577
|
+
return extendedTemplateChecker.getDiagnosticsForComponent(component);
|
|
30578
|
+
}
|
|
30550
30579
|
resolve(node, analysis, symbol) {
|
|
30551
30580
|
if (this.semanticDepGraphUpdater !== null && analysis.baseClass instanceof Reference$1) {
|
|
30552
30581
|
symbol.baseClass = this.semanticDepGraphUpdater.getSymbol(analysis.baseClass.node);
|
|
@@ -34899,6 +34928,18 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
34899
34928
|
};
|
|
34900
34929
|
}
|
|
34901
34930
|
}
|
|
34931
|
+
if (node instanceof PropertyRead && node.receiver instanceof ImplicitReceiver) {
|
|
34932
|
+
const nodeLocation = findFirstMatchingNode(this.tcb, {
|
|
34933
|
+
filter: ts$1.isPropertyAccessExpression,
|
|
34934
|
+
withSpan: node.sourceSpan,
|
|
34935
|
+
});
|
|
34936
|
+
if (nodeLocation) {
|
|
34937
|
+
nodeContext = {
|
|
34938
|
+
shimPath: this.shimPath,
|
|
34939
|
+
positionInShimFile: nodeLocation.getStart(),
|
|
34940
|
+
};
|
|
34941
|
+
}
|
|
34942
|
+
}
|
|
34902
34943
|
return {
|
|
34903
34944
|
componentContext: this.componentContext,
|
|
34904
34945
|
templateContext,
|
|
@@ -39713,7 +39754,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
39713
39754
|
const fileRecord = this.state.get(sfPath);
|
|
39714
39755
|
const templateId = fileRecord.sourceManager.getTemplateId(clazz);
|
|
39715
39756
|
const mapping = fileRecord.sourceManager.getSourceMapping(templateId);
|
|
39716
|
-
return makeTemplateDiagnostic(templateId, mapping, sourceSpan, category, errorCode, message, relatedInformation);
|
|
39757
|
+
return Object.assign(Object.assign({}, makeTemplateDiagnostic(templateId, mapping, sourceSpan, category, ngErrorCode(errorCode), message, relatedInformation)), { __ngCode: errorCode });
|
|
39717
39758
|
}
|
|
39718
39759
|
getOrCreateCompletionEngine(component) {
|
|
39719
39760
|
if (this.completionCache.has(component)) {
|
|
@@ -40082,13 +40123,133 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
40082
40123
|
* Use of this source code is governed by an MIT-style license that can be
|
|
40083
40124
|
* found in the LICENSE file at https://angular.io/license
|
|
40084
40125
|
*/
|
|
40085
|
-
|
|
40086
|
-
|
|
40087
|
-
|
|
40088
|
-
|
|
40089
|
-
|
|
40090
|
-
|
|
40091
|
-
|
|
40126
|
+
class ExtendedTemplateCheckerImpl {
|
|
40127
|
+
constructor(templateTypeChecker, typeChecker, templateChecks) {
|
|
40128
|
+
this.templateTypeChecker = templateTypeChecker;
|
|
40129
|
+
this.typeChecker = typeChecker;
|
|
40130
|
+
this.templateChecks = templateChecks;
|
|
40131
|
+
}
|
|
40132
|
+
getDiagnosticsForComponent(component) {
|
|
40133
|
+
const template = this.templateTypeChecker.getTemplate(component);
|
|
40134
|
+
// Skip checks if component has no template. This can happen if the user writes a
|
|
40135
|
+
// `@Component()` but doesn't add the template, could happen in the language service
|
|
40136
|
+
// when users are in the middle of typing code.
|
|
40137
|
+
if (template === null) {
|
|
40138
|
+
return [];
|
|
40139
|
+
}
|
|
40140
|
+
const diagnostics = [];
|
|
40141
|
+
const ctx = {
|
|
40142
|
+
templateTypeChecker: this.templateTypeChecker,
|
|
40143
|
+
typeChecker: this.typeChecker,
|
|
40144
|
+
component
|
|
40145
|
+
};
|
|
40146
|
+
for (const check of this.templateChecks) {
|
|
40147
|
+
diagnostics.push(...deduplicateDiagnostics(check.run(ctx, template)));
|
|
40148
|
+
}
|
|
40149
|
+
return diagnostics;
|
|
40150
|
+
}
|
|
40151
|
+
}
|
|
40152
|
+
// Filter out duplicated diagnostics, this is possible due to the way the compiler
|
|
40153
|
+
// handles desugaring and produces `AST`s. Ex.
|
|
40154
|
+
//
|
|
40155
|
+
// ```
|
|
40156
|
+
// <div *ngIf="true" (foo)="bar">test</div>
|
|
40157
|
+
// ```
|
|
40158
|
+
//
|
|
40159
|
+
// Would result in the following AST:
|
|
40160
|
+
//
|
|
40161
|
+
// ```
|
|
40162
|
+
// Template {
|
|
40163
|
+
// outputs: [
|
|
40164
|
+
// BoundEvent {
|
|
40165
|
+
// name: 'foo',
|
|
40166
|
+
// /.../
|
|
40167
|
+
// }
|
|
40168
|
+
// ],
|
|
40169
|
+
// children: [
|
|
40170
|
+
// Element {
|
|
40171
|
+
// outputs: [
|
|
40172
|
+
// BoundEvent {
|
|
40173
|
+
// name: 'foo',
|
|
40174
|
+
// /.../
|
|
40175
|
+
// }
|
|
40176
|
+
// ]
|
|
40177
|
+
// }
|
|
40178
|
+
// ],
|
|
40179
|
+
// /.../
|
|
40180
|
+
// }
|
|
40181
|
+
// ```
|
|
40182
|
+
//
|
|
40183
|
+
// In this case a duplicated diagnostic could be generated for the output `foo`.
|
|
40184
|
+
// TODO(danieltrevino): handle duplicated diagnostics when they are being generated
|
|
40185
|
+
// to avoid extra work (could be directly in the visitor).
|
|
40186
|
+
// https://github.com/angular/angular/pull/42984#discussion_r684823926
|
|
40187
|
+
function deduplicateDiagnostics(diagnostics) {
|
|
40188
|
+
const result = [];
|
|
40189
|
+
for (const newDiag of diagnostics) {
|
|
40190
|
+
const isDuplicateDiag = result.some(existingDiag => areDiagnosticsEqual(newDiag, existingDiag));
|
|
40191
|
+
if (!isDuplicateDiag) {
|
|
40192
|
+
result.push(newDiag);
|
|
40193
|
+
}
|
|
40194
|
+
}
|
|
40195
|
+
return result;
|
|
40196
|
+
}
|
|
40197
|
+
function areDiagnosticsEqual(first, second) {
|
|
40198
|
+
var _a, _b;
|
|
40199
|
+
return ((_a = first.file) === null || _a === void 0 ? void 0 : _a.fileName) === ((_b = second.file) === null || _b === void 0 ? void 0 : _b.fileName) && first.start === second.start &&
|
|
40200
|
+
first.length === second.length && first.code === second.code;
|
|
40201
|
+
}
|
|
40202
|
+
|
|
40203
|
+
/**
|
|
40204
|
+
* @license
|
|
40205
|
+
* Copyright Google LLC All Rights Reserved.
|
|
40206
|
+
*
|
|
40207
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
40208
|
+
* found in the LICENSE file at https://angular.io/license
|
|
40209
|
+
*/
|
|
40210
|
+
/**
|
|
40211
|
+
* Ensures the two-way binding syntax is correct.
|
|
40212
|
+
* Parentheses should be inside the brackets "[()]".
|
|
40213
|
+
* Will return diagnostic information when "([])" is found.
|
|
40214
|
+
*/
|
|
40215
|
+
class InvalidBananaInBoxCheck {
|
|
40216
|
+
constructor() {
|
|
40217
|
+
this.code = 8101;
|
|
40218
|
+
}
|
|
40219
|
+
run(ctx, template) {
|
|
40220
|
+
const visitor = new BananaVisitor(ctx);
|
|
40221
|
+
return visitor.getDiagnostics(template);
|
|
40222
|
+
}
|
|
40223
|
+
}
|
|
40224
|
+
class BananaVisitor extends RecursiveVisitor {
|
|
40225
|
+
constructor(ctx) {
|
|
40226
|
+
super();
|
|
40227
|
+
this.ctx = ctx;
|
|
40228
|
+
this.diagnostics = [];
|
|
40229
|
+
}
|
|
40230
|
+
/**
|
|
40231
|
+
* Check for outputs with names surrounded in brackets "[]".
|
|
40232
|
+
* The syntax '([foo])="bar"' would be interpreted as an @Output()
|
|
40233
|
+
* with name '[foo]'. Just like '(foo)="bar"' would have the name 'foo'.
|
|
40234
|
+
* Generate diagnostic information for the cases found.
|
|
40235
|
+
*/
|
|
40236
|
+
visitBoundEvent(boundEvent) {
|
|
40237
|
+
const name = boundEvent.name;
|
|
40238
|
+
if (name.startsWith('[') && name.endsWith(']')) {
|
|
40239
|
+
const boundSyntax = boundEvent.sourceSpan.toString();
|
|
40240
|
+
const expectedBoundSyntax = boundSyntax.replace(`(${name})`, `[(${name.slice(1, -1)})]`);
|
|
40241
|
+
this.diagnostics.push(this.ctx.templateTypeChecker.makeTemplateDiagnostic(this.ctx.component, boundEvent.sourceSpan, ts$1.DiagnosticCategory.Warning, ErrorCode.INVALID_BANANA_IN_BOX, `In the two-way binding syntax the parentheses should be inside the brackets, ex. '${expectedBoundSyntax}'.
|
|
40242
|
+
Find more at https://angular.io/guide/two-way-binding`));
|
|
40243
|
+
}
|
|
40244
|
+
}
|
|
40245
|
+
getDiagnostics(template) {
|
|
40246
|
+
this.diagnostics = [];
|
|
40247
|
+
for (const node of template) {
|
|
40248
|
+
node.visit(this);
|
|
40249
|
+
}
|
|
40250
|
+
return this.diagnostics;
|
|
40251
|
+
}
|
|
40252
|
+
}
|
|
40092
40253
|
|
|
40093
40254
|
/**
|
|
40094
40255
|
* @license
|
|
@@ -40206,6 +40367,10 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
40206
40367
|
* with each fresh compilation.
|
|
40207
40368
|
*/
|
|
40208
40369
|
this.delegatingPerfRecorder = new DelegatingPerfRecorder(this.perfRecorder);
|
|
40370
|
+
if (this.options._extendedTemplateDiagnostics === true &&
|
|
40371
|
+
this.options.strictTemplates === false) {
|
|
40372
|
+
throw new Error('The \'_extendedTemplateDiagnostics\' option requires \'strictTemplates\' to also be enabled.');
|
|
40373
|
+
}
|
|
40209
40374
|
this.constructionDiagnostics.push(...this.adapter.constructionDiagnostics);
|
|
40210
40375
|
const incompatibleTypeCheckOptionsDiagnostic = verifyCompatibleTypeCheckOptions(this.options);
|
|
40211
40376
|
if (incompatibleTypeCheckOptionsDiagnostic !== null) {
|
|
@@ -40315,7 +40480,12 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
40315
40480
|
* Get all Angular-related diagnostics for this compilation.
|
|
40316
40481
|
*/
|
|
40317
40482
|
getDiagnostics() {
|
|
40318
|
-
|
|
40483
|
+
const diagnostics = [];
|
|
40484
|
+
diagnostics.push(...this.getNonTemplateDiagnostics(), ...this.getTemplateDiagnostics());
|
|
40485
|
+
if (this.options._extendedTemplateDiagnostics) {
|
|
40486
|
+
diagnostics.push(...this.getExtendedTemplateDiagnostics());
|
|
40487
|
+
}
|
|
40488
|
+
return this.addMessageTextDetails(diagnostics);
|
|
40319
40489
|
}
|
|
40320
40490
|
/**
|
|
40321
40491
|
* Get all Angular-related diagnostics for this compilation.
|
|
@@ -40323,10 +40493,26 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
40323
40493
|
* If a `ts.SourceFile` is passed, only diagnostics related to that file are returned.
|
|
40324
40494
|
*/
|
|
40325
40495
|
getDiagnosticsForFile(file, optimizeFor) {
|
|
40326
|
-
|
|
40327
|
-
|
|
40328
|
-
|
|
40329
|
-
|
|
40496
|
+
const diagnostics = [];
|
|
40497
|
+
diagnostics.push(...this.getNonTemplateDiagnostics().filter(diag => diag.file === file), ...this.getTemplateDiagnosticsForFile(file, optimizeFor));
|
|
40498
|
+
if (this.options._extendedTemplateDiagnostics) {
|
|
40499
|
+
diagnostics.push(...this.getExtendedTemplateDiagnostics(file));
|
|
40500
|
+
}
|
|
40501
|
+
return this.addMessageTextDetails(diagnostics);
|
|
40502
|
+
}
|
|
40503
|
+
/**
|
|
40504
|
+
* Get all `ts.Diagnostic`s currently available that pertain to the given component.
|
|
40505
|
+
*/
|
|
40506
|
+
getDiagnosticsForComponent(component) {
|
|
40507
|
+
const compilation = this.ensureAnalyzed();
|
|
40508
|
+
const ttc = compilation.templateTypeChecker;
|
|
40509
|
+
const diagnostics = [];
|
|
40510
|
+
diagnostics.push(...ttc.getDiagnosticsForComponent(component));
|
|
40511
|
+
if (this.options._extendedTemplateDiagnostics) {
|
|
40512
|
+
const extendedTemplateChecker = compilation.extendedTemplateChecker;
|
|
40513
|
+
diagnostics.push(...extendedTemplateChecker.getDiagnosticsForComponent(component));
|
|
40514
|
+
}
|
|
40515
|
+
return this.addMessageTextDetails(diagnostics);
|
|
40330
40516
|
}
|
|
40331
40517
|
/**
|
|
40332
40518
|
* Add Angular.io error guide links to diagnostics for this compilation.
|
|
@@ -40716,6 +40902,24 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
40716
40902
|
}
|
|
40717
40903
|
return this.nonTemplateDiagnostics;
|
|
40718
40904
|
}
|
|
40905
|
+
/**
|
|
40906
|
+
* Calls the `extendedTemplateCheck` phase of the trait compiler
|
|
40907
|
+
* @param sf optional parameter to get diagnostics for a certain file
|
|
40908
|
+
* or all files in the program if `sf` is undefined
|
|
40909
|
+
* @returns generated extended template diagnostics
|
|
40910
|
+
*/
|
|
40911
|
+
getExtendedTemplateDiagnostics(sf) {
|
|
40912
|
+
const diagnostics = [];
|
|
40913
|
+
const compilation = this.ensureAnalyzed();
|
|
40914
|
+
const extendedTemplateChecker = compilation.extendedTemplateChecker;
|
|
40915
|
+
if (sf !== undefined) {
|
|
40916
|
+
return compilation.traitCompiler.extendedTemplateCheck(sf, extendedTemplateChecker);
|
|
40917
|
+
}
|
|
40918
|
+
for (const sf of this.inputProgram.getSourceFiles()) {
|
|
40919
|
+
diagnostics.push(...compilation.traitCompiler.extendedTemplateCheck(sf, extendedTemplateChecker));
|
|
40920
|
+
}
|
|
40921
|
+
return diagnostics;
|
|
40922
|
+
}
|
|
40719
40923
|
makeCompilation() {
|
|
40720
40924
|
const checker = this.inputProgram.getTypeChecker();
|
|
40721
40925
|
const reflector = new TypeScriptReflectionHost(checker);
|
|
@@ -40813,7 +41017,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
40813
41017
|
// TODO(alxhub): understand why the cast here is necessary (something to do with `null`
|
|
40814
41018
|
// not being assignable to `unknown` when wrapped in `Readonly`).
|
|
40815
41019
|
// clang-format off
|
|
40816
|
-
new DirectiveDecoratorHandler(reflector, evaluator, metaRegistry, scopeRegistry, metaReader, injectableRegistry, isCore, semanticDepGraphUpdater, this.closureCompilerEnabled, compileUndecoratedClassesWithAngularFeatures, this.delegatingPerfRecorder),
|
|
41020
|
+
new DirectiveDecoratorHandler(reflector, evaluator, metaRegistry, scopeRegistry, metaReader, injectableRegistry, isCore, semanticDepGraphUpdater, this.closureCompilerEnabled, /** compileUndecoratedClassesWithAngularFeatures */ false, this.delegatingPerfRecorder),
|
|
40817
41021
|
// clang-format on
|
|
40818
41022
|
// Pipe handler must be before injectable handler in list so pipe factories are printed
|
|
40819
41023
|
// before injectable factories (so injectable factories can delegate to them)
|
|
@@ -40829,6 +41033,8 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
40829
41033
|
this.currentProgram = program;
|
|
40830
41034
|
});
|
|
40831
41035
|
const templateTypeChecker = new TemplateTypeCheckerImpl(this.inputProgram, notifyingDriver, traitCompiler, this.getTypeCheckingConfig(), refEmitter, reflector, this.adapter, this.incrementalCompilation, scopeRegistry, typeCheckScopeRegistry, this.delegatingPerfRecorder);
|
|
41036
|
+
const templateChecks = [new InvalidBananaInBoxCheck()];
|
|
41037
|
+
const extendedTemplateChecker = new ExtendedTemplateCheckerImpl(templateTypeChecker, checker, templateChecks);
|
|
40832
41038
|
return {
|
|
40833
41039
|
isCore,
|
|
40834
41040
|
traitCompiler,
|
|
@@ -40843,6 +41049,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
40843
41049
|
refEmitter,
|
|
40844
41050
|
templateTypeChecker,
|
|
40845
41051
|
resourceRegistry,
|
|
41052
|
+
extendedTemplateChecker
|
|
40846
41053
|
};
|
|
40847
41054
|
}
|
|
40848
41055
|
}
|
|
@@ -44406,7 +44613,6 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
44406
44613
|
}
|
|
44407
44614
|
getSemanticDiagnostics(fileName) {
|
|
44408
44615
|
return this.withCompilerAndPerfTracing(PerfPhase.LsDiagnostics, (compiler) => {
|
|
44409
|
-
const ttc = compiler.getTemplateTypeChecker();
|
|
44410
44616
|
const diagnostics = [];
|
|
44411
44617
|
if (isTypeScriptFile(fileName)) {
|
|
44412
44618
|
const program = compiler.getCurrentProgram();
|
|
@@ -44442,7 +44648,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
44442
44648
|
const components = compiler.getComponentsWithTemplateFile(fileName);
|
|
44443
44649
|
for (const component of components) {
|
|
44444
44650
|
if (ts.isClassDeclaration(component)) {
|
|
44445
|
-
diagnostics.push(...
|
|
44651
|
+
diagnostics.push(...compiler.getDiagnosticsForComponent(component));
|
|
44446
44652
|
}
|
|
44447
44653
|
}
|
|
44448
44654
|
}
|