@angular/language-service 11.1.0-next.5 → 11.1.2
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/api.d.ts +39 -0
- package/api.js +20 -0
- package/bundles/ivy.js +590 -335
- package/bundles/language-service.js +295 -164
- package/index.d.ts +2 -1
- package/index.js +7 -3
- package/ivy/adapters.d.ts +12 -2
- package/ivy/adapters.js +35 -7
- package/ivy/compiler_factory.d.ts +0 -9
- package/ivy/compiler_factory.js +19 -52
- package/ivy/completions.js +7 -7
- package/ivy/definitions.js +15 -10
- package/ivy/language_service.d.ts +2 -0
- package/ivy/language_service.js +32 -8
- package/ivy/references.js +6 -21
- package/ivy/ts_plugin.d.ts +2 -1
- package/ivy/ts_plugin.js +18 -2
- package/ivy/utils.d.ts +10 -1
- package/ivy/utils.js +30 -3
- package/package.json +1 -1
- package/src/language_service.js +1 -1
- package/src/ts_plugin.d.ts +2 -1
- package/src/ts_plugin.js +7 -2
- package/src/typescript_host.d.ts +7 -6
- package/src/typescript_host.js +10 -15
- package/language-service.d.ts +0 -17
- package/language-service.js +0 -34
package/bundles/ivy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v11.1.
|
|
2
|
+
* @license Angular v11.1.2
|
|
3
3
|
* Copyright Google LLC All Rights Reserved.
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -827,6 +827,10 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
827
827
|
* Use of this source code is governed by an MIT-style license that can be
|
|
828
828
|
* found in the LICENSE file at https://angular.io/license
|
|
829
829
|
*/
|
|
830
|
+
// Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not
|
|
831
|
+
// explicitly set. This value will be changed to `true` in v12.
|
|
832
|
+
// TODO(misko): switch the default in v12 to `true`. See: packages/core/src/metadata/di.ts
|
|
833
|
+
const emitDistinctChangesOnlyDefaultValue = false;
|
|
830
834
|
var ViewEncapsulation;
|
|
831
835
|
(function (ViewEncapsulation) {
|
|
832
836
|
ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated";
|
|
@@ -2655,8 +2659,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
2655
2659
|
Identifiers$1.definePipe = { name: 'ɵɵdefinePipe', moduleName: CORE$1 };
|
|
2656
2660
|
Identifiers$1.queryRefresh = { name: 'ɵɵqueryRefresh', moduleName: CORE$1 };
|
|
2657
2661
|
Identifiers$1.viewQuery = { name: 'ɵɵviewQuery', moduleName: CORE$1 };
|
|
2658
|
-
Identifiers$1.staticViewQuery = { name: 'ɵɵstaticViewQuery', moduleName: CORE$1 };
|
|
2659
|
-
Identifiers$1.staticContentQuery = { name: 'ɵɵstaticContentQuery', moduleName: CORE$1 };
|
|
2660
2662
|
Identifiers$1.loadQuery = { name: 'ɵɵloadQuery', moduleName: CORE$1 };
|
|
2661
2663
|
Identifiers$1.contentQuery = { name: 'ɵɵcontentQuery', moduleName: CORE$1 };
|
|
2662
2664
|
Identifiers$1.NgOnChangesFeature = { name: 'ɵɵNgOnChangesFeature', moduleName: CORE$1 };
|
|
@@ -9355,7 +9357,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
9355
9357
|
this._advance();
|
|
9356
9358
|
selfClosing = false;
|
|
9357
9359
|
}
|
|
9358
|
-
const end = this._peek.sourceSpan.
|
|
9360
|
+
const end = this._peek.sourceSpan.fullStart;
|
|
9359
9361
|
const span = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
|
|
9360
9362
|
// Create a separate `startSpan` because `span` will be modified when there is an `end` span.
|
|
9361
9363
|
const startSpan = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
|
|
@@ -9687,8 +9689,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
9687
9689
|
}
|
|
9688
9690
|
parseInterpolation(value, sourceSpan) {
|
|
9689
9691
|
const sourceInfo = sourceSpan.start.toString();
|
|
9692
|
+
const absoluteOffset = sourceSpan.fullStart.offset;
|
|
9690
9693
|
try {
|
|
9691
|
-
const ast = this._exprParser.parseInterpolation(value, sourceInfo,
|
|
9694
|
+
const ast = this._exprParser.parseInterpolation(value, sourceInfo, absoluteOffset, this._interpolationConfig);
|
|
9692
9695
|
if (ast)
|
|
9693
9696
|
this._reportExpressionParserErrors(ast.errors, sourceSpan);
|
|
9694
9697
|
this._checkPipes(ast, sourceSpan);
|
|
@@ -9696,7 +9699,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
9696
9699
|
}
|
|
9697
9700
|
catch (e) {
|
|
9698
9701
|
this._reportError(`${e}`, sourceSpan);
|
|
9699
|
-
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo,
|
|
9702
|
+
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
|
|
9700
9703
|
}
|
|
9701
9704
|
}
|
|
9702
9705
|
/**
|
|
@@ -9706,8 +9709,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
9706
9709
|
*/
|
|
9707
9710
|
parseInterpolationExpression(expression, sourceSpan) {
|
|
9708
9711
|
const sourceInfo = sourceSpan.start.toString();
|
|
9712
|
+
const absoluteOffset = sourceSpan.start.offset;
|
|
9709
9713
|
try {
|
|
9710
|
-
const ast = this._exprParser.parseInterpolationExpression(expression, sourceInfo,
|
|
9714
|
+
const ast = this._exprParser.parseInterpolationExpression(expression, sourceInfo, absoluteOffset);
|
|
9711
9715
|
if (ast)
|
|
9712
9716
|
this._reportExpressionParserErrors(ast.errors, sourceSpan);
|
|
9713
9717
|
this._checkPipes(ast, sourceSpan);
|
|
@@ -9715,7 +9719,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
9715
9719
|
}
|
|
9716
9720
|
catch (e) {
|
|
9717
9721
|
this._reportError(`${e}`, sourceSpan);
|
|
9718
|
-
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo,
|
|
9722
|
+
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
|
|
9719
9723
|
}
|
|
9720
9724
|
}
|
|
9721
9725
|
/**
|
|
@@ -9795,6 +9799,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
9795
9799
|
targetProps, keySpan) {
|
|
9796
9800
|
if (isAnimationLabel(name)) {
|
|
9797
9801
|
name = name.substring(1);
|
|
9802
|
+
if (keySpan !== undefined) {
|
|
9803
|
+
keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + 1, keySpan.end.offset));
|
|
9804
|
+
}
|
|
9798
9805
|
if (value) {
|
|
9799
9806
|
this._reportError(`Assigning animation triggers via @prop="exp" attributes with an expression is invalid.` +
|
|
9800
9807
|
` Use property bindings (e.g. [@prop]="exp") or use an attribute without a value (e.g. @prop) instead.`, sourceSpan, ParseErrorLevel.ERROR);
|
|
@@ -9816,10 +9823,16 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
9816
9823
|
if (name.startsWith(ANIMATE_PROP_PREFIX)) {
|
|
9817
9824
|
isAnimationProp = true;
|
|
9818
9825
|
name = name.substring(ANIMATE_PROP_PREFIX.length);
|
|
9826
|
+
if (keySpan !== undefined) {
|
|
9827
|
+
keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + ANIMATE_PROP_PREFIX.length, keySpan.end.offset));
|
|
9828
|
+
}
|
|
9819
9829
|
}
|
|
9820
9830
|
else if (isAnimationLabel(name)) {
|
|
9821
9831
|
isAnimationProp = true;
|
|
9822
9832
|
name = name.substring(1);
|
|
9833
|
+
if (keySpan !== undefined) {
|
|
9834
|
+
keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + 1, keySpan.end.offset));
|
|
9835
|
+
}
|
|
9823
9836
|
}
|
|
9824
9837
|
if (isAnimationProp) {
|
|
9825
9838
|
this._parseAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps);
|
|
@@ -9926,6 +9939,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
9926
9939
|
}
|
|
9927
9940
|
if (isAnimationLabel(name)) {
|
|
9928
9941
|
name = name.substr(1);
|
|
9942
|
+
if (keySpan !== undefined) {
|
|
9943
|
+
keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + 1, keySpan.end.offset));
|
|
9944
|
+
}
|
|
9929
9945
|
this._parseAnimationEvent(name, expression, sourceSpan, handlerSpan, targetEvents, keySpan);
|
|
9930
9946
|
}
|
|
9931
9947
|
else {
|
|
@@ -11340,13 +11356,10 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11340
11356
|
}
|
|
11341
11357
|
const fullEnd = exprEnd + interpEnd.length;
|
|
11342
11358
|
const text = input.substring(exprStart, exprEnd);
|
|
11343
|
-
if (text.trim().length
|
|
11344
|
-
expressions.push({ text, start: fullStart, end: fullEnd });
|
|
11345
|
-
}
|
|
11346
|
-
else {
|
|
11359
|
+
if (text.trim().length === 0) {
|
|
11347
11360
|
this._reportError('Blank expressions are not allowed in interpolated strings', input, `at column ${i} in`, location);
|
|
11348
|
-
expressions.push({ text: '$implicit', start: fullStart, end: fullEnd });
|
|
11349
11361
|
}
|
|
11362
|
+
expressions.push({ text, start: fullStart, end: fullEnd });
|
|
11350
11363
|
offsets.push(exprStart);
|
|
11351
11364
|
i = fullEnd;
|
|
11352
11365
|
atInterpolation = false;
|
|
@@ -11529,13 +11542,25 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11529
11542
|
get currentAbsoluteOffset() {
|
|
11530
11543
|
return this.absoluteOffset + this.inputIndex;
|
|
11531
11544
|
}
|
|
11532
|
-
|
|
11533
|
-
|
|
11545
|
+
/**
|
|
11546
|
+
* Retrieve a `ParseSpan` from `start` to the current position (or to `artificialEndIndex` if
|
|
11547
|
+
* provided).
|
|
11548
|
+
*
|
|
11549
|
+
* @param start Position from which the `ParseSpan` will start.
|
|
11550
|
+
* @param artificialEndIndex Optional ending index to be used if provided (and if greater than the
|
|
11551
|
+
* natural ending index)
|
|
11552
|
+
*/
|
|
11553
|
+
span(start, artificialEndIndex) {
|
|
11554
|
+
let endIndex = this.currentEndIndex;
|
|
11555
|
+
if (artificialEndIndex !== undefined && artificialEndIndex > this.currentEndIndex) {
|
|
11556
|
+
endIndex = artificialEndIndex;
|
|
11557
|
+
}
|
|
11558
|
+
return new ParseSpan(start, endIndex);
|
|
11534
11559
|
}
|
|
11535
|
-
sourceSpan(start) {
|
|
11536
|
-
const serial = `${start}@${this.inputIndex}`;
|
|
11560
|
+
sourceSpan(start, artificialEndIndex) {
|
|
11561
|
+
const serial = `${start}@${this.inputIndex}:${artificialEndIndex}`;
|
|
11537
11562
|
if (!this.sourceSpanCache.has(serial)) {
|
|
11538
|
-
this.sourceSpanCache.set(serial, this.span(start).toAbsolute(this.absoluteOffset));
|
|
11563
|
+
this.sourceSpanCache.set(serial, this.span(start, artificialEndIndex).toAbsolute(this.absoluteOffset));
|
|
11539
11564
|
}
|
|
11540
11565
|
return this.sourceSpanCache.get(serial);
|
|
11541
11566
|
}
|
|
@@ -11598,7 +11623,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11598
11623
|
const n = this.next;
|
|
11599
11624
|
if (!n.isIdentifier() && !n.isKeyword()) {
|
|
11600
11625
|
this.error(`Unexpected ${this.prettyPrintToken(n)}, expected identifier or keyword`);
|
|
11601
|
-
return
|
|
11626
|
+
return null;
|
|
11602
11627
|
}
|
|
11603
11628
|
this.advance();
|
|
11604
11629
|
return n.toString();
|
|
@@ -11629,8 +11654,12 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11629
11654
|
this.error(`Unexpected token '${this.next}'`);
|
|
11630
11655
|
}
|
|
11631
11656
|
}
|
|
11632
|
-
if (exprs.length == 0)
|
|
11633
|
-
|
|
11657
|
+
if (exprs.length == 0) {
|
|
11658
|
+
// We have no expressions so create an empty expression that spans the entire input length
|
|
11659
|
+
const artificialStart = this.offset;
|
|
11660
|
+
const artificialEnd = this.offset + this.inputLength;
|
|
11661
|
+
return new EmptyExpr(this.span(artificialStart, artificialEnd), this.sourceSpan(artificialStart, artificialEnd));
|
|
11662
|
+
}
|
|
11634
11663
|
if (exprs.length == 1)
|
|
11635
11664
|
return exprs[0];
|
|
11636
11665
|
return new Chain(this.span(start), this.sourceSpan(start), exprs);
|
|
@@ -11643,15 +11672,36 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11643
11672
|
}
|
|
11644
11673
|
do {
|
|
11645
11674
|
const nameStart = this.inputIndex;
|
|
11646
|
-
|
|
11647
|
-
|
|
11675
|
+
let nameId = this.expectIdentifierOrKeyword();
|
|
11676
|
+
let nameSpan;
|
|
11677
|
+
let fullSpanEnd = undefined;
|
|
11678
|
+
if (nameId !== null) {
|
|
11679
|
+
nameSpan = this.sourceSpan(nameStart);
|
|
11680
|
+
}
|
|
11681
|
+
else {
|
|
11682
|
+
// No valid identifier was found, so we'll assume an empty pipe name ('').
|
|
11683
|
+
nameId = '';
|
|
11684
|
+
// However, there may have been whitespace present between the pipe character and the next
|
|
11685
|
+
// token in the sequence (or the end of input). We want to track this whitespace so that
|
|
11686
|
+
// the `BindingPipe` we produce covers not just the pipe character, but any trailing
|
|
11687
|
+
// whitespace beyond it. Another way of thinking about this is that the zero-length name
|
|
11688
|
+
// is assumed to be at the end of any whitespace beyond the pipe character.
|
|
11689
|
+
//
|
|
11690
|
+
// Therefore, we push the end of the `ParseSpan` for this pipe all the way up to the
|
|
11691
|
+
// beginning of the next token, or until the end of input if the next token is EOF.
|
|
11692
|
+
fullSpanEnd = this.next.index !== -1 ? this.next.index : this.inputLength + this.offset;
|
|
11693
|
+
// The `nameSpan` for an empty pipe name is zero-length at the end of any whitespace
|
|
11694
|
+
// beyond the pipe character.
|
|
11695
|
+
nameSpan = new ParseSpan(fullSpanEnd, fullSpanEnd).toAbsolute(this.absoluteOffset);
|
|
11696
|
+
}
|
|
11648
11697
|
const args = [];
|
|
11649
11698
|
while (this.consumeOptionalCharacter($COLON)) {
|
|
11650
11699
|
args.push(this.parseExpression());
|
|
11700
|
+
// If there are additional expressions beyond the name, then the artificial end for the
|
|
11701
|
+
// name is no longer relevant.
|
|
11651
11702
|
}
|
|
11652
11703
|
const { start } = result.span;
|
|
11653
|
-
result =
|
|
11654
|
-
new BindingPipe(this.span(start), this.sourceSpan(start), result, name, args, nameSpan);
|
|
11704
|
+
result = new BindingPipe(this.span(start), this.sourceSpan(start, fullSpanEnd), result, nameId, args, nameSpan);
|
|
11655
11705
|
} while (this.consumeOptionalOperator('|'));
|
|
11656
11706
|
}
|
|
11657
11707
|
return result;
|
|
@@ -11940,7 +11990,8 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11940
11990
|
const start = receiver.span.start;
|
|
11941
11991
|
const nameStart = this.inputIndex;
|
|
11942
11992
|
const id = this.withContext(ParseContextFlags.Writable, () => {
|
|
11943
|
-
|
|
11993
|
+
var _a;
|
|
11994
|
+
const id = (_a = this.expectIdentifierOrKeyword()) !== null && _a !== void 0 ? _a : '';
|
|
11944
11995
|
if (id.length === 0) {
|
|
11945
11996
|
this.error(`Expected identifier for property access`, receiver.span.end);
|
|
11946
11997
|
}
|
|
@@ -16169,12 +16220,21 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
16169
16220
|
}
|
|
16170
16221
|
}
|
|
16171
16222
|
function prepareQueryParams(query, constantPool) {
|
|
16172
|
-
const parameters = [getQueryPredicate(query, constantPool), literal(query
|
|
16223
|
+
const parameters = [getQueryPredicate(query, constantPool), literal(toQueryFlags(query))];
|
|
16173
16224
|
if (query.read) {
|
|
16174
16225
|
parameters.push(query.read);
|
|
16175
16226
|
}
|
|
16176
16227
|
return parameters;
|
|
16177
16228
|
}
|
|
16229
|
+
/**
|
|
16230
|
+
* Translates query flags into `TQueryFlags` type in packages/core/src/render3/interfaces/query.ts
|
|
16231
|
+
* @param query
|
|
16232
|
+
*/
|
|
16233
|
+
function toQueryFlags(query) {
|
|
16234
|
+
return (query.descendants ? 1 /* descendants */ : 0 /* none */) |
|
|
16235
|
+
(query.static ? 2 /* isStatic */ : 0 /* none */) |
|
|
16236
|
+
(query.emitDistinctChangesOnly ? 4 /* emitDistinctChangesOnly */ : 0 /* none */);
|
|
16237
|
+
}
|
|
16178
16238
|
function convertAttributesToExpressions(attributes) {
|
|
16179
16239
|
const values = [];
|
|
16180
16240
|
for (let key of Object.getOwnPropertyNames(attributes)) {
|
|
@@ -16189,9 +16249,8 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
16189
16249
|
const updateStatements = [];
|
|
16190
16250
|
const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);
|
|
16191
16251
|
for (const query of queries) {
|
|
16192
|
-
const queryInstruction = query.static ? Identifiers$1.staticContentQuery : Identifiers$1.contentQuery;
|
|
16193
16252
|
// creation, e.g. r3.contentQuery(dirIndex, somePredicate, true, null);
|
|
16194
|
-
createStatements.push(importExpr(
|
|
16253
|
+
createStatements.push(importExpr(Identifiers$1.contentQuery)
|
|
16195
16254
|
.callFn([variable('dirIndex'), ...prepareQueryParams(query, constantPool)])
|
|
16196
16255
|
.toStmt());
|
|
16197
16256
|
// update, e.g. (r3.queryRefresh(tmp = r3.loadQuery()) && (ctx.someDir = tmp));
|
|
@@ -16257,9 +16316,8 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
16257
16316
|
const updateStatements = [];
|
|
16258
16317
|
const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);
|
|
16259
16318
|
viewQueries.forEach((query) => {
|
|
16260
|
-
const queryInstruction = query.static ? Identifiers$1.staticViewQuery : Identifiers$1.viewQuery;
|
|
16261
16319
|
// creation, e.g. r3.viewQuery(somePredicate, true);
|
|
16262
|
-
const queryDefinition = importExpr(
|
|
16320
|
+
const queryDefinition = importExpr(Identifiers$1.viewQuery).callFn(prepareQueryParams(query, constantPool));
|
|
16263
16321
|
createStatements.push(queryDefinition.toStmt());
|
|
16264
16322
|
// update, e.g. (r3.queryRefresh(tmp = r3.loadQuery()) && (ctx.someDir = tmp));
|
|
16265
16323
|
const temporary = tempAllocator();
|
|
@@ -16738,10 +16796,10 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
16738
16796
|
};
|
|
16739
16797
|
function convertToR3QueryMetadata(facade) {
|
|
16740
16798
|
return Object.assign(Object.assign({}, facade), { predicate: Array.isArray(facade.predicate) ? facade.predicate :
|
|
16741
|
-
new WrappedNodeExpr(facade.predicate), read: facade.read ? new WrappedNodeExpr(facade.read) : null, static: facade.static });
|
|
16799
|
+
new WrappedNodeExpr(facade.predicate), read: facade.read ? new WrappedNodeExpr(facade.read) : null, static: facade.static, emitDistinctChangesOnly: facade.emitDistinctChangesOnly });
|
|
16742
16800
|
}
|
|
16743
16801
|
function convertQueryDeclarationToMetadata(declaration) {
|
|
16744
|
-
var _a, _b, _c;
|
|
16802
|
+
var _a, _b, _c, _d;
|
|
16745
16803
|
return {
|
|
16746
16804
|
propertyName: declaration.propertyName,
|
|
16747
16805
|
first: (_a = declaration.first) !== null && _a !== void 0 ? _a : false,
|
|
@@ -16750,6 +16808,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
16750
16808
|
descendants: (_b = declaration.descendants) !== null && _b !== void 0 ? _b : false,
|
|
16751
16809
|
read: declaration.read ? new WrappedNodeExpr(declaration.read) : null,
|
|
16752
16810
|
static: (_c = declaration.static) !== null && _c !== void 0 ? _c : false,
|
|
16811
|
+
emitDistinctChangesOnly: (_d = declaration.emitDistinctChangesOnly) !== null && _d !== void 0 ? _d : true,
|
|
16753
16812
|
};
|
|
16754
16813
|
}
|
|
16755
16814
|
function convertDirectiveFacadeToMetadata(facade) {
|
|
@@ -16952,7 +17011,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
16952
17011
|
* Use of this source code is governed by an MIT-style license that can be
|
|
16953
17012
|
* found in the LICENSE file at https://angular.io/license
|
|
16954
17013
|
*/
|
|
16955
|
-
const VERSION$1 = new Version('11.1.
|
|
17014
|
+
const VERSION$1 = new Version('11.1.2');
|
|
16956
17015
|
|
|
16957
17016
|
/**
|
|
16958
17017
|
* @license
|
|
@@ -17609,7 +17668,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
17609
17668
|
*/
|
|
17610
17669
|
function createDirectiveDefinitionMap(meta) {
|
|
17611
17670
|
const definitionMap = new DefinitionMap();
|
|
17612
|
-
definitionMap.set('version', literal('11.1.
|
|
17671
|
+
definitionMap.set('version', literal('11.1.2'));
|
|
17613
17672
|
// e.g. `type: MyDirective`
|
|
17614
17673
|
definitionMap.set('type', meta.internalType);
|
|
17615
17674
|
// e.g. `selector: 'some-dir'`
|
|
@@ -17649,6 +17708,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
17649
17708
|
meta.set('first', literal(true));
|
|
17650
17709
|
}
|
|
17651
17710
|
meta.set('predicate', Array.isArray(query.predicate) ? asLiteral(query.predicate) : query.predicate);
|
|
17711
|
+
if (!query.emitDistinctChangesOnly) {
|
|
17712
|
+
// `emitDistinctChangesOnly` is special because in future we expect it to be `true`. For this
|
|
17713
|
+
// reason the absence should be interpreted as `true`.
|
|
17714
|
+
meta.set('emitDistinctChangesOnly', literal(false));
|
|
17715
|
+
}
|
|
17652
17716
|
if (query.descendants) {
|
|
17653
17717
|
meta.set('descendants', literal(true));
|
|
17654
17718
|
}
|
|
@@ -21052,7 +21116,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
21052
21116
|
* Use of this source code is governed by an MIT-style license that can be
|
|
21053
21117
|
* found in the LICENSE file at https://angular.io/license
|
|
21054
21118
|
*/
|
|
21055
|
-
const VERSION$2 = new Version('11.1.
|
|
21119
|
+
const VERSION$2 = new Version('11.1.2');
|
|
21056
21120
|
|
|
21057
21121
|
/**
|
|
21058
21122
|
* @license
|
|
@@ -21244,7 +21308,34 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
21244
21308
|
* An injectable already has a `ɵprov` property.
|
|
21245
21309
|
*/
|
|
21246
21310
|
ErrorCode[ErrorCode["INJECTABLE_DUPLICATE_PROV"] = 9001] = "INJECTABLE_DUPLICATE_PROV";
|
|
21311
|
+
// 10XXX error codes are reserved for diagnostics with category
|
|
21312
|
+
// `ts.DiagnosticCategory.Suggestion`. These diagnostics are generated by
|
|
21313
|
+
// language service.
|
|
21314
|
+
/**
|
|
21315
|
+
* Suggest users to enable `strictTemplates` to make use of full capabilities
|
|
21316
|
+
* provided by Angular language service.
|
|
21317
|
+
*/
|
|
21318
|
+
ErrorCode[ErrorCode["SUGGEST_STRICT_TEMPLATES"] = 10001] = "SUGGEST_STRICT_TEMPLATES";
|
|
21247
21319
|
})(ErrorCode || (ErrorCode = {}));
|
|
21320
|
+
/**
|
|
21321
|
+
* @internal
|
|
21322
|
+
* Base URL for the error details page.
|
|
21323
|
+
* Keep this value in sync with a similar const in
|
|
21324
|
+
* `packages/core/src/render3/error_code.ts`.
|
|
21325
|
+
*/
|
|
21326
|
+
const ERROR_DETAILS_PAGE_BASE_URL = 'https://angular.io/errors';
|
|
21327
|
+
/**
|
|
21328
|
+
* @internal
|
|
21329
|
+
* Contains a set of error messages that have detailed guides at angular.io.
|
|
21330
|
+
* Full list of available error guides can be found at https://angular.io/errors
|
|
21331
|
+
*/
|
|
21332
|
+
const COMPILER_ERRORS_WITH_GUIDES = new Set([
|
|
21333
|
+
ErrorCode.DECORATOR_ARG_NOT_LITERAL,
|
|
21334
|
+
ErrorCode.PARAM_MISSING_TOKEN,
|
|
21335
|
+
ErrorCode.SCHEMA_INVALID_ELEMENT,
|
|
21336
|
+
ErrorCode.SCHEMA_INVALID_ATTRIBUTE,
|
|
21337
|
+
ErrorCode.MISSING_REFERENCE_TARGET,
|
|
21338
|
+
]);
|
|
21248
21339
|
/**
|
|
21249
21340
|
* @internal
|
|
21250
21341
|
*/
|
|
@@ -25399,6 +25490,18 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
25399
25490
|
}
|
|
25400
25491
|
}
|
|
25401
25492
|
}
|
|
25493
|
+
updateResources(clazz) {
|
|
25494
|
+
if (!this.reflector.isClass(clazz) || !this.classes.has(clazz)) {
|
|
25495
|
+
return;
|
|
25496
|
+
}
|
|
25497
|
+
const record = this.classes.get(clazz);
|
|
25498
|
+
for (const trait of record.traits) {
|
|
25499
|
+
if (trait.state !== TraitState.Resolved || trait.handler.updateResources === undefined) {
|
|
25500
|
+
continue;
|
|
25501
|
+
}
|
|
25502
|
+
trait.handler.updateResources(clazz, trait.analysis, trait.resolution);
|
|
25503
|
+
}
|
|
25504
|
+
}
|
|
25402
25505
|
compile(clazz, constantPool) {
|
|
25403
25506
|
const original = ts$1.getOriginalNode(clazz);
|
|
25404
25507
|
if (!this.reflector.isClass(clazz) || !this.reflector.isClass(original) ||
|
|
@@ -28101,6 +28204,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28101
28204
|
let read = null;
|
|
28102
28205
|
// The default value for descendants is true for every decorator except @ContentChildren.
|
|
28103
28206
|
let descendants = name !== 'ContentChildren';
|
|
28207
|
+
let emitDistinctChangesOnly = emitDistinctChangesOnlyDefaultValue;
|
|
28104
28208
|
if (args.length === 2) {
|
|
28105
28209
|
const optionsExpr = unwrapExpression(args[1]);
|
|
28106
28210
|
if (!ts$1.isObjectLiteralExpression(optionsExpr)) {
|
|
@@ -28118,6 +28222,14 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28118
28222
|
}
|
|
28119
28223
|
descendants = descendantsValue;
|
|
28120
28224
|
}
|
|
28225
|
+
if (options.has('emitDistinctChangesOnly')) {
|
|
28226
|
+
const emitDistinctChangesOnlyExpr = options.get('emitDistinctChangesOnly');
|
|
28227
|
+
const emitDistinctChangesOnlyValue = evaluator.evaluate(emitDistinctChangesOnlyExpr);
|
|
28228
|
+
if (typeof emitDistinctChangesOnlyValue !== 'boolean') {
|
|
28229
|
+
throw createValueHasWrongTypeError(emitDistinctChangesOnlyExpr, emitDistinctChangesOnlyValue, `@${name} options.emitDistinctChangesOnlys must be a boolean`);
|
|
28230
|
+
}
|
|
28231
|
+
emitDistinctChangesOnly = emitDistinctChangesOnlyValue;
|
|
28232
|
+
}
|
|
28121
28233
|
if (options.has('static')) {
|
|
28122
28234
|
const staticValue = evaluator.evaluate(options.get('static'));
|
|
28123
28235
|
if (typeof staticValue !== 'boolean') {
|
|
@@ -28137,6 +28249,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28137
28249
|
descendants,
|
|
28138
28250
|
read,
|
|
28139
28251
|
static: isStatic,
|
|
28252
|
+
emitDistinctChangesOnly,
|
|
28140
28253
|
};
|
|
28141
28254
|
}
|
|
28142
28255
|
function extractQueriesFromDecorator(queryData, reflector, evaluator, isCore) {
|
|
@@ -28528,24 +28641,13 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28528
28641
|
template = preanalyzed;
|
|
28529
28642
|
}
|
|
28530
28643
|
else {
|
|
28531
|
-
|
|
28532
|
-
|
|
28533
|
-
const templateUrlExpr = component.get('templateUrl');
|
|
28534
|
-
const templateUrl = this.evaluator.evaluate(templateUrlExpr);
|
|
28535
|
-
if (typeof templateUrl !== 'string') {
|
|
28536
|
-
throw createValueHasWrongTypeError(templateUrlExpr, templateUrl, 'templateUrl must be a string');
|
|
28537
|
-
}
|
|
28538
|
-
const resourceUrl = this.resourceLoader.resolve(templateUrl, containingFile);
|
|
28539
|
-
template = this._extractExternalTemplate(node, component, templateUrlExpr, resourceUrl);
|
|
28540
|
-
}
|
|
28541
|
-
else {
|
|
28542
|
-
// Expect an inline template to be present.
|
|
28543
|
-
template = this._extractInlineTemplate(node, decorator, component, containingFile);
|
|
28544
|
-
}
|
|
28644
|
+
const templateDecl = this.parseTemplateDeclaration(decorator, component, containingFile);
|
|
28645
|
+
template = this.extractTemplate(node, templateDecl);
|
|
28545
28646
|
}
|
|
28546
|
-
const templateResource = template.isInline ?
|
|
28547
|
-
|
|
28548
|
-
|
|
28647
|
+
const templateResource = template.isInline ? { path: null, expression: component.get('template') } : {
|
|
28648
|
+
path: absoluteFrom(template.declaration.resolvedTemplateUrl),
|
|
28649
|
+
expression: template.sourceMapping.node
|
|
28650
|
+
};
|
|
28549
28651
|
// Figure out the set of styles. The ordering here is important: external resources (styleUrls)
|
|
28550
28652
|
// precede inline styles, and styles defined in the template override styles defined in the
|
|
28551
28653
|
// component.
|
|
@@ -28565,9 +28667,11 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28565
28667
|
}
|
|
28566
28668
|
}
|
|
28567
28669
|
}
|
|
28670
|
+
let inlineStyles = null;
|
|
28568
28671
|
if (component.has('styles')) {
|
|
28569
28672
|
const litStyles = parseFieldArrayValue(component, 'styles', this.evaluator);
|
|
28570
28673
|
if (litStyles !== null) {
|
|
28674
|
+
inlineStyles = [...litStyles];
|
|
28571
28675
|
if (styles === null) {
|
|
28572
28676
|
styles = litStyles;
|
|
28573
28677
|
}
|
|
@@ -28607,6 +28711,8 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28607
28711
|
template,
|
|
28608
28712
|
providersRequiringFactory,
|
|
28609
28713
|
viewProvidersRequiringFactory,
|
|
28714
|
+
inlineStyles,
|
|
28715
|
+
styleUrls,
|
|
28610
28716
|
resources: {
|
|
28611
28717
|
styles: styleResources,
|
|
28612
28718
|
template: templateResource,
|
|
@@ -28775,6 +28881,33 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28775
28881
|
}
|
|
28776
28882
|
return { data };
|
|
28777
28883
|
}
|
|
28884
|
+
updateResources(node, analysis) {
|
|
28885
|
+
const containingFile = node.getSourceFile().fileName;
|
|
28886
|
+
// If the template is external, re-parse it.
|
|
28887
|
+
const templateDecl = analysis.template.declaration;
|
|
28888
|
+
if (!templateDecl.isInline) {
|
|
28889
|
+
analysis.template = this.extractTemplate(node, templateDecl);
|
|
28890
|
+
}
|
|
28891
|
+
// Update any external stylesheets and rebuild the combined 'styles' list.
|
|
28892
|
+
// TODO(alxhub): write tests for styles when the primary compiler uses the updateResources path
|
|
28893
|
+
let styles = [];
|
|
28894
|
+
if (analysis.styleUrls !== null) {
|
|
28895
|
+
for (const styleUrl of analysis.styleUrls) {
|
|
28896
|
+
const resolvedStyleUrl = this.resourceLoader.resolve(styleUrl, containingFile);
|
|
28897
|
+
const styleText = this.resourceLoader.load(resolvedStyleUrl);
|
|
28898
|
+
styles.push(styleText);
|
|
28899
|
+
}
|
|
28900
|
+
}
|
|
28901
|
+
if (analysis.inlineStyles !== null) {
|
|
28902
|
+
for (const styleText of analysis.inlineStyles) {
|
|
28903
|
+
styles.push(styleText);
|
|
28904
|
+
}
|
|
28905
|
+
}
|
|
28906
|
+
for (const styleText of analysis.template.styles) {
|
|
28907
|
+
styles.push(styleText);
|
|
28908
|
+
}
|
|
28909
|
+
analysis.meta.styles = styles;
|
|
28910
|
+
}
|
|
28778
28911
|
compileFull(node, analysis, resolution, pool) {
|
|
28779
28912
|
if (analysis.template.errors !== null && analysis.template.errors.length > 0) {
|
|
28780
28913
|
return [];
|
|
@@ -28881,7 +29014,8 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28881
29014
|
// URLs to resolve.
|
|
28882
29015
|
if (templatePromise !== undefined) {
|
|
28883
29016
|
return templatePromise.then(() => {
|
|
28884
|
-
const
|
|
29017
|
+
const templateDecl = this.parseTemplateDeclaration(decorator, component, containingFile);
|
|
29018
|
+
const template = this.extractTemplate(node, templateDecl);
|
|
28885
29019
|
this.preanalyzeTemplateCache.set(node, template);
|
|
28886
29020
|
return template;
|
|
28887
29021
|
});
|
|
@@ -28891,125 +29025,157 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28891
29025
|
}
|
|
28892
29026
|
}
|
|
28893
29027
|
else {
|
|
28894
|
-
const
|
|
29028
|
+
const templateDecl = this.parseTemplateDeclaration(decorator, component, containingFile);
|
|
29029
|
+
const template = this.extractTemplate(node, templateDecl);
|
|
28895
29030
|
this.preanalyzeTemplateCache.set(node, template);
|
|
28896
29031
|
return Promise.resolve(template);
|
|
28897
29032
|
}
|
|
28898
29033
|
}
|
|
28899
|
-
|
|
28900
|
-
|
|
28901
|
-
|
|
28902
|
-
|
|
28903
|
-
|
|
28904
|
-
|
|
28905
|
-
|
|
28906
|
-
|
|
28907
|
-
|
|
28908
|
-
|
|
28909
|
-
|
|
28910
|
-
node
|
|
28911
|
-
|
|
28912
|
-
|
|
28913
|
-
|
|
28914
|
-
|
|
28915
|
-
|
|
28916
|
-
|
|
28917
|
-
|
|
28918
|
-
|
|
28919
|
-
|
|
28920
|
-
|
|
28921
|
-
let templateLiteral = null;
|
|
28922
|
-
let templateUrl = '';
|
|
28923
|
-
let templateRange = undefined;
|
|
28924
|
-
let sourceMapping;
|
|
28925
|
-
let escapedString = false;
|
|
28926
|
-
// We only support SourceMaps for inline templates that are simple string literals.
|
|
28927
|
-
if (ts$1.isStringLiteral(templateExpr) || ts$1.isNoSubstitutionTemplateLiteral(templateExpr)) {
|
|
28928
|
-
// the start and end of the `templateExpr` node includes the quotation marks, which we
|
|
28929
|
-
// must
|
|
28930
|
-
// strip
|
|
28931
|
-
templateRange = getTemplateRange(templateExpr);
|
|
28932
|
-
templateStr = templateExpr.getSourceFile().text;
|
|
28933
|
-
templateLiteral = templateExpr;
|
|
28934
|
-
templateUrl = containingFile;
|
|
28935
|
-
escapedString = true;
|
|
28936
|
-
sourceMapping = {
|
|
28937
|
-
type: 'direct',
|
|
28938
|
-
node: templateExpr,
|
|
28939
|
-
};
|
|
28940
|
-
}
|
|
28941
|
-
else {
|
|
28942
|
-
const resolvedTemplate = this.evaluator.evaluate(templateExpr);
|
|
28943
|
-
if (typeof resolvedTemplate !== 'string') {
|
|
28944
|
-
throw createValueHasWrongTypeError(templateExpr, resolvedTemplate, 'template must be a string');
|
|
28945
|
-
}
|
|
28946
|
-
templateStr = resolvedTemplate;
|
|
28947
|
-
sourceMapping = {
|
|
28948
|
-
type: 'indirect',
|
|
28949
|
-
node: templateExpr,
|
|
28950
|
-
componentClass: node,
|
|
28951
|
-
template: templateStr,
|
|
28952
|
-
};
|
|
28953
|
-
}
|
|
28954
|
-
const template = this._parseTemplate(component, templateStr, templateLiteral, templateUrl, templateRange, escapedString);
|
|
28955
|
-
return Object.assign(Object.assign({}, template), { sourceMapping });
|
|
28956
|
-
}
|
|
28957
|
-
_parseTemplate(component, templateStr, templateLiteral, templateUrl, templateRange, escapedString) {
|
|
28958
|
-
let preserveWhitespaces = this.defaultPreserveWhitespaces;
|
|
28959
|
-
if (component.has('preserveWhitespaces')) {
|
|
28960
|
-
const expr = component.get('preserveWhitespaces');
|
|
28961
|
-
const value = this.evaluator.evaluate(expr);
|
|
28962
|
-
if (typeof value !== 'boolean') {
|
|
28963
|
-
throw createValueHasWrongTypeError(expr, value, 'preserveWhitespaces must be a boolean');
|
|
29034
|
+
extractTemplate(node, template) {
|
|
29035
|
+
if (template.isInline) {
|
|
29036
|
+
let templateStr;
|
|
29037
|
+
let templateLiteral = null;
|
|
29038
|
+
let templateUrl = '';
|
|
29039
|
+
let templateRange = null;
|
|
29040
|
+
let sourceMapping;
|
|
29041
|
+
let escapedString = false;
|
|
29042
|
+
// We only support SourceMaps for inline templates that are simple string literals.
|
|
29043
|
+
if (ts$1.isStringLiteral(template.expression) ||
|
|
29044
|
+
ts$1.isNoSubstitutionTemplateLiteral(template.expression)) {
|
|
29045
|
+
// the start and end of the `templateExpr` node includes the quotation marks, which we must
|
|
29046
|
+
// strip
|
|
29047
|
+
templateRange = getTemplateRange(template.expression);
|
|
29048
|
+
templateStr = template.expression.getSourceFile().text;
|
|
29049
|
+
templateLiteral = template.expression;
|
|
29050
|
+
templateUrl = template.templateUrl;
|
|
29051
|
+
escapedString = true;
|
|
29052
|
+
sourceMapping = {
|
|
29053
|
+
type: 'direct',
|
|
29054
|
+
node: template.expression,
|
|
29055
|
+
};
|
|
28964
29056
|
}
|
|
28965
|
-
|
|
28966
|
-
|
|
28967
|
-
|
|
28968
|
-
|
|
28969
|
-
|
|
28970
|
-
|
|
28971
|
-
|
|
28972
|
-
|
|
28973
|
-
|
|
29057
|
+
else {
|
|
29058
|
+
const resolvedTemplate = this.evaluator.evaluate(template.expression);
|
|
29059
|
+
if (typeof resolvedTemplate !== 'string') {
|
|
29060
|
+
throw createValueHasWrongTypeError(template.expression, resolvedTemplate, 'template must be a string');
|
|
29061
|
+
}
|
|
29062
|
+
templateStr = resolvedTemplate;
|
|
29063
|
+
sourceMapping = {
|
|
29064
|
+
type: 'indirect',
|
|
29065
|
+
node: template.expression,
|
|
29066
|
+
componentClass: node,
|
|
29067
|
+
template: templateStr,
|
|
29068
|
+
};
|
|
28974
29069
|
}
|
|
28975
|
-
|
|
29070
|
+
return Object.assign(Object.assign({}, this._parseTemplate(template, templateStr, templateRange, escapedString)), { sourceMapping, declaration: template });
|
|
28976
29071
|
}
|
|
29072
|
+
else {
|
|
29073
|
+
const templateStr = this.resourceLoader.load(template.resolvedTemplateUrl);
|
|
29074
|
+
if (this.depTracker !== null) {
|
|
29075
|
+
this.depTracker.addResourceDependency(node.getSourceFile(), absoluteFrom(template.resolvedTemplateUrl));
|
|
29076
|
+
}
|
|
29077
|
+
return Object.assign(Object.assign({}, this._parseTemplate(template, templateStr, /* templateRange */ null,
|
|
29078
|
+
/* escapedString */ false)), { sourceMapping: {
|
|
29079
|
+
type: 'external',
|
|
29080
|
+
componentClass: node,
|
|
29081
|
+
// TODO(alxhub): TS in g3 is unable to make this inference on its own, so cast it here
|
|
29082
|
+
// until g3 is able to figure this out.
|
|
29083
|
+
node: template.templateUrlExpression,
|
|
29084
|
+
template: templateStr,
|
|
29085
|
+
templateUrl: template.resolvedTemplateUrl,
|
|
29086
|
+
}, declaration: template });
|
|
29087
|
+
}
|
|
29088
|
+
}
|
|
29089
|
+
_parseTemplate(template, templateStr, templateRange, escapedString) {
|
|
28977
29090
|
// We always normalize line endings if the template has been escaped (i.e. is inline).
|
|
28978
29091
|
const i18nNormalizeLineEndingsInICUs = escapedString || this.i18nNormalizeLineEndingsInICUs;
|
|
28979
|
-
const
|
|
28980
|
-
|
|
28981
|
-
|
|
28982
|
-
|
|
28983
|
-
range: templateRange,
|
|
29092
|
+
const parsedTemplate = parseTemplate(templateStr, template.sourceMapUrl, {
|
|
29093
|
+
preserveWhitespaces: template.preserveWhitespaces,
|
|
29094
|
+
interpolationConfig: template.interpolationConfig,
|
|
29095
|
+
range: templateRange !== null && templateRange !== void 0 ? templateRange : undefined,
|
|
28984
29096
|
escapedString,
|
|
28985
29097
|
enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat,
|
|
28986
29098
|
i18nNormalizeLineEndingsInICUs,
|
|
28987
|
-
isInline,
|
|
29099
|
+
isInline: template.isInline,
|
|
28988
29100
|
});
|
|
28989
29101
|
// Unfortunately, the primary parse of the template above may not contain accurate source map
|
|
28990
29102
|
// information. If used directly, it would result in incorrect code locations in template
|
|
28991
|
-
// errors, etc. There are
|
|
29103
|
+
// errors, etc. There are three main problems:
|
|
28992
29104
|
//
|
|
28993
29105
|
// 1. `preserveWhitespaces: false` annihilates the correctness of template source mapping, as
|
|
28994
29106
|
// the whitespace transformation changes the contents of HTML text nodes before they're
|
|
28995
29107
|
// parsed into Angular expressions.
|
|
28996
|
-
// 2.
|
|
29108
|
+
// 2. `preserveLineEndings: false` causes growing misalignments in templates that use '\r\n'
|
|
29109
|
+
// line endings, by normalizing them to '\n'.
|
|
29110
|
+
// 3. By default, the template parser strips leading trivia characters (like spaces, tabs, and
|
|
28997
29111
|
// newlines). This also destroys source mapping information.
|
|
28998
29112
|
//
|
|
28999
29113
|
// In order to guarantee the correctness of diagnostics, templates are parsed a second time
|
|
29000
29114
|
// with the above options set to preserve source mappings.
|
|
29001
|
-
const { nodes: diagNodes } = parseTemplate(templateStr,
|
|
29115
|
+
const { nodes: diagNodes } = parseTemplate(templateStr, template.sourceMapUrl, {
|
|
29002
29116
|
preserveWhitespaces: true,
|
|
29003
|
-
|
|
29004
|
-
|
|
29117
|
+
preserveLineEndings: true,
|
|
29118
|
+
interpolationConfig: template.interpolationConfig,
|
|
29119
|
+
range: templateRange !== null && templateRange !== void 0 ? templateRange : undefined,
|
|
29005
29120
|
escapedString,
|
|
29006
29121
|
enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat,
|
|
29007
29122
|
i18nNormalizeLineEndingsInICUs,
|
|
29008
29123
|
leadingTriviaChars: [],
|
|
29009
|
-
isInline,
|
|
29124
|
+
isInline: template.isInline,
|
|
29010
29125
|
});
|
|
29011
|
-
return Object.assign(Object.assign({}, parsedTemplate), { diagNodes, template:
|
|
29012
|
-
|
|
29126
|
+
return Object.assign(Object.assign({}, parsedTemplate), { diagNodes, template: template.isInline ? new WrappedNodeExpr(template.expression) : templateStr, templateUrl: template.resolvedTemplateUrl, isInline: template.isInline, file: new ParseSourceFile(templateStr, template.resolvedTemplateUrl) });
|
|
29127
|
+
}
|
|
29128
|
+
parseTemplateDeclaration(decorator, component, containingFile) {
|
|
29129
|
+
let preserveWhitespaces = this.defaultPreserveWhitespaces;
|
|
29130
|
+
if (component.has('preserveWhitespaces')) {
|
|
29131
|
+
const expr = component.get('preserveWhitespaces');
|
|
29132
|
+
const value = this.evaluator.evaluate(expr);
|
|
29133
|
+
if (typeof value !== 'boolean') {
|
|
29134
|
+
throw createValueHasWrongTypeError(expr, value, 'preserveWhitespaces must be a boolean');
|
|
29135
|
+
}
|
|
29136
|
+
preserveWhitespaces = value;
|
|
29137
|
+
}
|
|
29138
|
+
let interpolationConfig = DEFAULT_INTERPOLATION_CONFIG;
|
|
29139
|
+
if (component.has('interpolation')) {
|
|
29140
|
+
const expr = component.get('interpolation');
|
|
29141
|
+
const value = this.evaluator.evaluate(expr);
|
|
29142
|
+
if (!Array.isArray(value) || value.length !== 2 ||
|
|
29143
|
+
!value.every(element => typeof element === 'string')) {
|
|
29144
|
+
throw createValueHasWrongTypeError(expr, value, 'interpolation must be an array with 2 elements of string type');
|
|
29145
|
+
}
|
|
29146
|
+
interpolationConfig = InterpolationConfig.fromArray(value);
|
|
29147
|
+
}
|
|
29148
|
+
if (component.has('templateUrl')) {
|
|
29149
|
+
const templateUrlExpr = component.get('templateUrl');
|
|
29150
|
+
const templateUrl = this.evaluator.evaluate(templateUrlExpr);
|
|
29151
|
+
if (typeof templateUrl !== 'string') {
|
|
29152
|
+
throw createValueHasWrongTypeError(templateUrlExpr, templateUrl, 'templateUrl must be a string');
|
|
29153
|
+
}
|
|
29154
|
+
const resourceUrl = this.resourceLoader.resolve(templateUrl, containingFile);
|
|
29155
|
+
return {
|
|
29156
|
+
isInline: false,
|
|
29157
|
+
interpolationConfig,
|
|
29158
|
+
preserveWhitespaces,
|
|
29159
|
+
templateUrl,
|
|
29160
|
+
templateUrlExpression: templateUrlExpr,
|
|
29161
|
+
resolvedTemplateUrl: resourceUrl,
|
|
29162
|
+
sourceMapUrl: sourceMapUrl(resourceUrl),
|
|
29163
|
+
};
|
|
29164
|
+
}
|
|
29165
|
+
else if (component.has('template')) {
|
|
29166
|
+
return {
|
|
29167
|
+
isInline: true,
|
|
29168
|
+
interpolationConfig,
|
|
29169
|
+
preserveWhitespaces,
|
|
29170
|
+
expression: component.get('template'),
|
|
29171
|
+
templateUrl: containingFile,
|
|
29172
|
+
resolvedTemplateUrl: containingFile,
|
|
29173
|
+
sourceMapUrl: containingFile,
|
|
29174
|
+
};
|
|
29175
|
+
}
|
|
29176
|
+
else {
|
|
29177
|
+
throw new FatalDiagnosticError(ErrorCode.COMPONENT_MISSING_TEMPLATE, Decorator.nodeForError(decorator), 'component is missing a template');
|
|
29178
|
+
}
|
|
29013
29179
|
}
|
|
29014
29180
|
_expressionToImportedFile(expr, origin) {
|
|
29015
29181
|
if (!(expr instanceof ExternalExpr)) {
|
|
@@ -31252,6 +31418,12 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
31252
31418
|
this.cache.set(resolvedUrl, result);
|
|
31253
31419
|
return result;
|
|
31254
31420
|
}
|
|
31421
|
+
/**
|
|
31422
|
+
* Invalidate the entire resource cache.
|
|
31423
|
+
*/
|
|
31424
|
+
invalidate() {
|
|
31425
|
+
this.cache.clear();
|
|
31426
|
+
}
|
|
31255
31427
|
/**
|
|
31256
31428
|
* Attempt to resolve `url` in the context of `fromFile`, while respecting the rootDirs
|
|
31257
31429
|
* option from the tsconfig. First, normalize the file name.
|
|
@@ -36547,12 +36719,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
36547
36719
|
const shimData = this.pendingShimForComponent(ref.node);
|
|
36548
36720
|
const templateId = fileData.sourceManager.getTemplateId(ref.node);
|
|
36549
36721
|
const templateDiagnostics = [];
|
|
36550
|
-
const sfPath = absoluteFromSourceFile(ref.node.getSourceFile());
|
|
36551
|
-
const overrideTemplate = this.host.getTemplateOverride(sfPath, ref.node);
|
|
36552
|
-
if (overrideTemplate !== null) {
|
|
36553
|
-
template = overrideTemplate.nodes;
|
|
36554
|
-
parseErrors = overrideTemplate.errors;
|
|
36555
|
-
}
|
|
36556
36722
|
if (parseErrors !== null) {
|
|
36557
36723
|
templateDiagnostics.push(...this.getTemplateDiagnostics(parseErrors, templateId, sourceMapping));
|
|
36558
36724
|
}
|
|
@@ -37459,38 +37625,22 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37459
37625
|
/**
|
|
37460
37626
|
* Stores directives and pipes that are in scope for each component.
|
|
37461
37627
|
*
|
|
37462
|
-
* Unlike other caches, the scope of a component is not affected by its template
|
|
37463
|
-
*
|
|
37464
|
-
*
|
|
37465
|
-
* replaced.
|
|
37628
|
+
* Unlike other caches, the scope of a component is not affected by its template. It will be
|
|
37629
|
+
* destroyed when the `ts.Program` changes and the `TemplateTypeCheckerImpl` as a whole is
|
|
37630
|
+
* destroyed and replaced.
|
|
37466
37631
|
*/
|
|
37467
37632
|
this.scopeCache = new Map();
|
|
37468
37633
|
/**
|
|
37469
37634
|
* Stores potential element tags for each component (a union of DOM tags as well as directive
|
|
37470
37635
|
* tags).
|
|
37471
37636
|
*
|
|
37472
|
-
* Unlike other caches, the scope of a component is not affected by its template
|
|
37473
|
-
*
|
|
37474
|
-
*
|
|
37475
|
-
* replaced.
|
|
37637
|
+
* Unlike other caches, the scope of a component is not affected by its template. It will be
|
|
37638
|
+
* destroyed when the `ts.Program` changes and the `TemplateTypeCheckerImpl` as a whole is
|
|
37639
|
+
* destroyed and replaced.
|
|
37476
37640
|
*/
|
|
37477
37641
|
this.elementTagCache = new Map();
|
|
37478
37642
|
this.isComplete = false;
|
|
37479
37643
|
}
|
|
37480
|
-
resetOverrides() {
|
|
37481
|
-
for (const fileRecord of this.state.values()) {
|
|
37482
|
-
if (fileRecord.templateOverrides !== null) {
|
|
37483
|
-
fileRecord.templateOverrides = null;
|
|
37484
|
-
fileRecord.shimData.clear();
|
|
37485
|
-
fileRecord.isComplete = false;
|
|
37486
|
-
}
|
|
37487
|
-
}
|
|
37488
|
-
// Ideally only those components with overridden templates would have their caches invalidated,
|
|
37489
|
-
// but the `TemplateTypeCheckerImpl` does not track the class for components with overrides. As
|
|
37490
|
-
// a quick workaround, clear the entire cache instead.
|
|
37491
|
-
this.completionCache.clear();
|
|
37492
|
-
this.symbolBuilderCache.clear();
|
|
37493
|
-
}
|
|
37494
37644
|
getTemplate(component) {
|
|
37495
37645
|
const { data } = this.getLatestComponentState(component);
|
|
37496
37646
|
if (data === null) {
|
|
@@ -37527,28 +37677,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37527
37677
|
}
|
|
37528
37678
|
return { data, tcb, shimPath };
|
|
37529
37679
|
}
|
|
37530
|
-
overrideComponentTemplate(component, template) {
|
|
37531
|
-
const { nodes, errors } = parseTemplate(template, 'override.html', {
|
|
37532
|
-
preserveWhitespaces: true,
|
|
37533
|
-
leadingTriviaChars: [],
|
|
37534
|
-
});
|
|
37535
|
-
const filePath = absoluteFromSourceFile(component.getSourceFile());
|
|
37536
|
-
const fileRecord = this.getFileData(filePath);
|
|
37537
|
-
const id = fileRecord.sourceManager.getTemplateId(component);
|
|
37538
|
-
if (fileRecord.templateOverrides === null) {
|
|
37539
|
-
fileRecord.templateOverrides = new Map();
|
|
37540
|
-
}
|
|
37541
|
-
fileRecord.templateOverrides.set(id, { nodes, errors });
|
|
37542
|
-
// Clear data for the shim in question, so it'll be regenerated on the next request.
|
|
37543
|
-
const shimFile = this.typeCheckingStrategy.shimPathForComponent(component);
|
|
37544
|
-
fileRecord.shimData.delete(shimFile);
|
|
37545
|
-
fileRecord.isComplete = false;
|
|
37546
|
-
this.isComplete = false;
|
|
37547
|
-
// Overriding a component's template invalidates its cached results.
|
|
37548
|
-
this.completionCache.delete(component);
|
|
37549
|
-
this.symbolBuilderCache.delete(component);
|
|
37550
|
-
return { nodes, errors };
|
|
37551
|
-
}
|
|
37552
37680
|
isTrackedTypeCheckFile(filePath) {
|
|
37553
37681
|
return this.getFileAndShimRecordsForPath(filePath) !== null;
|
|
37554
37682
|
}
|
|
@@ -37648,6 +37776,20 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37648
37776
|
}
|
|
37649
37777
|
return engine.getExpressionCompletionLocation(ast);
|
|
37650
37778
|
}
|
|
37779
|
+
invalidateClass(clazz) {
|
|
37780
|
+
this.completionCache.delete(clazz);
|
|
37781
|
+
this.symbolBuilderCache.delete(clazz);
|
|
37782
|
+
this.scopeCache.delete(clazz);
|
|
37783
|
+
this.elementTagCache.delete(clazz);
|
|
37784
|
+
const sf = clazz.getSourceFile();
|
|
37785
|
+
const sfPath = absoluteFromSourceFile(sf);
|
|
37786
|
+
const shimPath = this.typeCheckingStrategy.shimPathForComponent(clazz);
|
|
37787
|
+
const fileData = this.getFileData(sfPath);
|
|
37788
|
+
const templateId = fileData.sourceManager.getTemplateId(clazz);
|
|
37789
|
+
fileData.shimData.delete(shimPath);
|
|
37790
|
+
fileData.isComplete = false;
|
|
37791
|
+
this.isComplete = false;
|
|
37792
|
+
}
|
|
37651
37793
|
getOrCreateCompletionEngine(component) {
|
|
37652
37794
|
if (this.completionCache.has(component)) {
|
|
37653
37795
|
return this.completionCache.get(component);
|
|
@@ -37664,18 +37806,13 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37664
37806
|
const sfPath = absoluteFromSourceFile(sf);
|
|
37665
37807
|
if (this.state.has(sfPath)) {
|
|
37666
37808
|
const existingResults = this.state.get(sfPath);
|
|
37667
|
-
if (existingResults.templateOverrides !== null) {
|
|
37668
|
-
// Cannot adopt prior results if template overrides have been requested.
|
|
37669
|
-
return;
|
|
37670
|
-
}
|
|
37671
37809
|
if (existingResults.isComplete) {
|
|
37672
37810
|
// All data for this file has already been generated, so no need to adopt anything.
|
|
37673
37811
|
return;
|
|
37674
37812
|
}
|
|
37675
37813
|
}
|
|
37676
37814
|
const previousResults = this.priorBuild.priorTypeCheckingResultsFor(sf);
|
|
37677
|
-
if (previousResults === null || !previousResults.isComplete
|
|
37678
|
-
previousResults.templateOverrides !== null) {
|
|
37815
|
+
if (previousResults === null || !previousResults.isComplete) {
|
|
37679
37816
|
return;
|
|
37680
37817
|
}
|
|
37681
37818
|
this.state.set(sfPath, previousResults);
|
|
@@ -37766,7 +37903,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37766
37903
|
if (!this.state.has(path)) {
|
|
37767
37904
|
this.state.set(path, {
|
|
37768
37905
|
hasInlines: false,
|
|
37769
|
-
templateOverrides: null,
|
|
37770
37906
|
sourceManager: new TemplateSourceManager(),
|
|
37771
37907
|
isComplete: false,
|
|
37772
37908
|
shimData: new Map(),
|
|
@@ -37919,17 +38055,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37919
38055
|
// The component needs to be checked unless the shim which would contain it already exists.
|
|
37920
38056
|
return !fileData.shimData.has(shimPath);
|
|
37921
38057
|
}
|
|
37922
|
-
getTemplateOverride(sfPath, node) {
|
|
37923
|
-
const fileData = this.impl.getFileData(sfPath);
|
|
37924
|
-
if (fileData.templateOverrides === null) {
|
|
37925
|
-
return null;
|
|
37926
|
-
}
|
|
37927
|
-
const templateId = fileData.sourceManager.getTemplateId(node);
|
|
37928
|
-
if (fileData.templateOverrides.has(templateId)) {
|
|
37929
|
-
return fileData.templateOverrides.get(templateId);
|
|
37930
|
-
}
|
|
37931
|
-
return null;
|
|
37932
|
-
}
|
|
37933
38058
|
recordShimData(sfPath, data) {
|
|
37934
38059
|
const fileData = this.impl.getFileData(sfPath);
|
|
37935
38060
|
fileData.shimData.set(data.path, data);
|
|
@@ -37969,17 +38094,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37969
38094
|
// Only need to generate a TCB for the class if no shim exists for it currently.
|
|
37970
38095
|
return !this.fileData.shimData.has(shimPath);
|
|
37971
38096
|
}
|
|
37972
|
-
getTemplateOverride(sfPath, node) {
|
|
37973
|
-
this.assertPath(sfPath);
|
|
37974
|
-
if (this.fileData.templateOverrides === null) {
|
|
37975
|
-
return null;
|
|
37976
|
-
}
|
|
37977
|
-
const templateId = this.fileData.sourceManager.getTemplateId(node);
|
|
37978
|
-
if (this.fileData.templateOverrides.has(templateId)) {
|
|
37979
|
-
return this.fileData.templateOverrides.get(templateId);
|
|
37980
|
-
}
|
|
37981
|
-
return null;
|
|
37982
|
-
}
|
|
37983
38097
|
recordShimData(sfPath, data) {
|
|
37984
38098
|
this.assertPath(sfPath);
|
|
37985
38099
|
// Previous type-checking state may have required the use of inlines (assuming they were
|
|
@@ -38033,6 +38147,61 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
38033
38147
|
* Use of this source code is governed by an MIT-style license that can be
|
|
38034
38148
|
* found in the LICENSE file at https://angular.io/license
|
|
38035
38149
|
*/
|
|
38150
|
+
/**
|
|
38151
|
+
* Discriminant type for a `CompilationTicket`.
|
|
38152
|
+
*/
|
|
38153
|
+
var CompilationTicketKind;
|
|
38154
|
+
(function (CompilationTicketKind) {
|
|
38155
|
+
CompilationTicketKind[CompilationTicketKind["Fresh"] = 0] = "Fresh";
|
|
38156
|
+
CompilationTicketKind[CompilationTicketKind["IncrementalTypeScript"] = 1] = "IncrementalTypeScript";
|
|
38157
|
+
CompilationTicketKind[CompilationTicketKind["IncrementalResource"] = 2] = "IncrementalResource";
|
|
38158
|
+
})(CompilationTicketKind || (CompilationTicketKind = {}));
|
|
38159
|
+
/**
|
|
38160
|
+
* Create a `CompilationTicket` for a brand new compilation, using no prior state.
|
|
38161
|
+
*/
|
|
38162
|
+
function freshCompilationTicket(tsProgram, options, incrementalBuildStrategy, typeCheckingProgramStrategy, enableTemplateTypeChecker, usePoisonedData) {
|
|
38163
|
+
return {
|
|
38164
|
+
kind: CompilationTicketKind.Fresh,
|
|
38165
|
+
tsProgram,
|
|
38166
|
+
options,
|
|
38167
|
+
incrementalBuildStrategy,
|
|
38168
|
+
typeCheckingProgramStrategy,
|
|
38169
|
+
enableTemplateTypeChecker,
|
|
38170
|
+
usePoisonedData,
|
|
38171
|
+
};
|
|
38172
|
+
}
|
|
38173
|
+
/**
|
|
38174
|
+
* Create a `CompilationTicket` as efficiently as possible, based on a previous `NgCompiler`
|
|
38175
|
+
* instance and a new `ts.Program`.
|
|
38176
|
+
*/
|
|
38177
|
+
function incrementalFromCompilerTicket(oldCompiler, newProgram, incrementalBuildStrategy, typeCheckingProgramStrategy, modifiedResourceFiles) {
|
|
38178
|
+
const oldProgram = oldCompiler.getNextProgram();
|
|
38179
|
+
const oldDriver = oldCompiler.incrementalStrategy.getIncrementalDriver(oldProgram);
|
|
38180
|
+
if (oldDriver === null) {
|
|
38181
|
+
// No incremental step is possible here, since no IncrementalDriver was found for the old
|
|
38182
|
+
// program.
|
|
38183
|
+
return freshCompilationTicket(newProgram, oldCompiler.options, incrementalBuildStrategy, typeCheckingProgramStrategy, oldCompiler.enableTemplateTypeChecker, oldCompiler.usePoisonedData);
|
|
38184
|
+
}
|
|
38185
|
+
const newDriver = IncrementalDriver.reconcile(oldProgram, oldDriver, newProgram, modifiedResourceFiles);
|
|
38186
|
+
return {
|
|
38187
|
+
kind: CompilationTicketKind.IncrementalTypeScript,
|
|
38188
|
+
enableTemplateTypeChecker: oldCompiler.enableTemplateTypeChecker,
|
|
38189
|
+
usePoisonedData: oldCompiler.usePoisonedData,
|
|
38190
|
+
options: oldCompiler.options,
|
|
38191
|
+
incrementalBuildStrategy,
|
|
38192
|
+
typeCheckingProgramStrategy,
|
|
38193
|
+
newDriver,
|
|
38194
|
+
oldProgram,
|
|
38195
|
+
newProgram,
|
|
38196
|
+
};
|
|
38197
|
+
}
|
|
38198
|
+
function resourceChangeTicket(compiler, modifiedResourceFiles) {
|
|
38199
|
+
return {
|
|
38200
|
+
kind: CompilationTicketKind.IncrementalResource,
|
|
38201
|
+
compiler,
|
|
38202
|
+
modifiedResourceFiles,
|
|
38203
|
+
};
|
|
38204
|
+
}
|
|
38036
38205
|
/**
|
|
38037
38206
|
* The heart of the Angular Ivy compiler.
|
|
38038
38207
|
*
|
|
@@ -38046,12 +38215,13 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
38046
38215
|
* See the README.md for more information.
|
|
38047
38216
|
*/
|
|
38048
38217
|
class NgCompiler {
|
|
38049
|
-
constructor(adapter, options, tsProgram, typeCheckingProgramStrategy, incrementalStrategy, enableTemplateTypeChecker, usePoisonedData,
|
|
38218
|
+
constructor(adapter, options, tsProgram, typeCheckingProgramStrategy, incrementalStrategy, incrementalDriver, enableTemplateTypeChecker, usePoisonedData, perfRecorder = NOOP_PERF_RECORDER) {
|
|
38050
38219
|
this.adapter = adapter;
|
|
38051
38220
|
this.options = options;
|
|
38052
38221
|
this.tsProgram = tsProgram;
|
|
38053
38222
|
this.typeCheckingProgramStrategy = typeCheckingProgramStrategy;
|
|
38054
38223
|
this.incrementalStrategy = incrementalStrategy;
|
|
38224
|
+
this.incrementalDriver = incrementalDriver;
|
|
38055
38225
|
this.enableTemplateTypeChecker = enableTemplateTypeChecker;
|
|
38056
38226
|
this.usePoisonedData = usePoisonedData;
|
|
38057
38227
|
this.perfRecorder = perfRecorder;
|
|
@@ -38095,31 +38265,55 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
38095
38265
|
new ModuleResolver(tsProgram, this.options, this.adapter, moduleResolutionCache);
|
|
38096
38266
|
this.resourceManager = new AdapterResourceLoader(adapter, this.options);
|
|
38097
38267
|
this.cycleAnalyzer = new CycleAnalyzer(new ImportGraph(this.moduleResolver));
|
|
38098
|
-
let modifiedResourceFiles = null;
|
|
38099
|
-
if (this.adapter.getModifiedResourceFiles !== undefined) {
|
|
38100
|
-
modifiedResourceFiles = this.adapter.getModifiedResourceFiles() || null;
|
|
38101
|
-
}
|
|
38102
|
-
if (oldProgram === null) {
|
|
38103
|
-
this.incrementalDriver = IncrementalDriver.fresh(tsProgram);
|
|
38104
|
-
}
|
|
38105
|
-
else {
|
|
38106
|
-
const oldDriver = this.incrementalStrategy.getIncrementalDriver(oldProgram);
|
|
38107
|
-
if (oldDriver !== null) {
|
|
38108
|
-
this.incrementalDriver =
|
|
38109
|
-
IncrementalDriver.reconcile(oldProgram, oldDriver, tsProgram, modifiedResourceFiles);
|
|
38110
|
-
}
|
|
38111
|
-
else {
|
|
38112
|
-
// A previous ts.Program was used to create the current one, but it wasn't from an
|
|
38113
|
-
// `NgCompiler`. That doesn't hurt anything, but the Angular analysis will have to start
|
|
38114
|
-
// from a fresh state.
|
|
38115
|
-
this.incrementalDriver = IncrementalDriver.fresh(tsProgram);
|
|
38116
|
-
}
|
|
38117
|
-
}
|
|
38118
38268
|
this.incrementalStrategy.setIncrementalDriver(this.incrementalDriver, tsProgram);
|
|
38119
38269
|
this.ignoreForDiagnostics =
|
|
38120
38270
|
new Set(tsProgram.getSourceFiles().filter(sf => this.adapter.isShim(sf)));
|
|
38121
38271
|
this.ignoreForEmit = this.adapter.ignoreForEmit;
|
|
38122
38272
|
}
|
|
38273
|
+
/**
|
|
38274
|
+
* Convert a `CompilationTicket` into an `NgCompiler` instance for the requested compilation.
|
|
38275
|
+
*
|
|
38276
|
+
* Depending on the nature of the compilation request, the `NgCompiler` instance may be reused
|
|
38277
|
+
* from a previous compilation and updated with any changes, it may be a new instance which
|
|
38278
|
+
* incrementally reuses state from a previous compilation, or it may represent a fresh compilation
|
|
38279
|
+
* entirely.
|
|
38280
|
+
*/
|
|
38281
|
+
static fromTicket(ticket, adapter, perfRecorder) {
|
|
38282
|
+
switch (ticket.kind) {
|
|
38283
|
+
case CompilationTicketKind.Fresh:
|
|
38284
|
+
return new NgCompiler(adapter, ticket.options, ticket.tsProgram, ticket.typeCheckingProgramStrategy, ticket.incrementalBuildStrategy, IncrementalDriver.fresh(ticket.tsProgram), ticket.enableTemplateTypeChecker, ticket.usePoisonedData, perfRecorder);
|
|
38285
|
+
case CompilationTicketKind.IncrementalTypeScript:
|
|
38286
|
+
return new NgCompiler(adapter, ticket.options, ticket.newProgram, ticket.typeCheckingProgramStrategy, ticket.incrementalBuildStrategy, ticket.newDriver, ticket.enableTemplateTypeChecker, ticket.usePoisonedData, perfRecorder);
|
|
38287
|
+
case CompilationTicketKind.IncrementalResource:
|
|
38288
|
+
const compiler = ticket.compiler;
|
|
38289
|
+
compiler.updateWithChangedResources(ticket.modifiedResourceFiles);
|
|
38290
|
+
return compiler;
|
|
38291
|
+
}
|
|
38292
|
+
}
|
|
38293
|
+
updateWithChangedResources(changedResources) {
|
|
38294
|
+
if (this.compilation === null) {
|
|
38295
|
+
// Analysis hasn't happened yet, so no update is necessary - any changes to resources will be
|
|
38296
|
+
// captured by the inital analysis pass itself.
|
|
38297
|
+
return;
|
|
38298
|
+
}
|
|
38299
|
+
this.resourceManager.invalidate();
|
|
38300
|
+
const classesToUpdate = new Set();
|
|
38301
|
+
for (const resourceFile of changedResources) {
|
|
38302
|
+
for (const templateClass of this.getComponentsWithTemplateFile(resourceFile)) {
|
|
38303
|
+
classesToUpdate.add(templateClass);
|
|
38304
|
+
}
|
|
38305
|
+
for (const styleClass of this.getComponentsWithStyleFile(resourceFile)) {
|
|
38306
|
+
classesToUpdate.add(styleClass);
|
|
38307
|
+
}
|
|
38308
|
+
}
|
|
38309
|
+
for (const clazz of classesToUpdate) {
|
|
38310
|
+
this.compilation.traitCompiler.updateResources(clazz);
|
|
38311
|
+
if (!ts$1.isClassDeclaration(clazz)) {
|
|
38312
|
+
continue;
|
|
38313
|
+
}
|
|
38314
|
+
this.compilation.templateTypeChecker.invalidateClass(clazz);
|
|
38315
|
+
}
|
|
38316
|
+
}
|
|
38123
38317
|
/**
|
|
38124
38318
|
* Get the resource dependencies of a file.
|
|
38125
38319
|
*
|
|
@@ -38133,7 +38327,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
38133
38327
|
* Get all Angular-related diagnostics for this compilation.
|
|
38134
38328
|
*/
|
|
38135
38329
|
getDiagnostics() {
|
|
38136
|
-
return [...this.getNonTemplateDiagnostics(), ...this.getTemplateDiagnostics()];
|
|
38330
|
+
return this.addMessageTextDetails([...this.getNonTemplateDiagnostics(), ...this.getTemplateDiagnostics()]);
|
|
38137
38331
|
}
|
|
38138
38332
|
/**
|
|
38139
38333
|
* Get all Angular-related diagnostics for this compilation.
|
|
@@ -38141,10 +38335,22 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
38141
38335
|
* If a `ts.SourceFile` is passed, only diagnostics related to that file are returned.
|
|
38142
38336
|
*/
|
|
38143
38337
|
getDiagnosticsForFile(file, optimizeFor) {
|
|
38144
|
-
return [
|
|
38338
|
+
return this.addMessageTextDetails([
|
|
38145
38339
|
...this.getNonTemplateDiagnostics().filter(diag => diag.file === file),
|
|
38146
38340
|
...this.getTemplateDiagnosticsForFile(file, optimizeFor)
|
|
38147
|
-
];
|
|
38341
|
+
]);
|
|
38342
|
+
}
|
|
38343
|
+
/**
|
|
38344
|
+
* Add Angular.io error guide links to diagnostics for this compilation.
|
|
38345
|
+
*/
|
|
38346
|
+
addMessageTextDetails(diagnostics) {
|
|
38347
|
+
return diagnostics.map(diag => {
|
|
38348
|
+
if (diag.code && COMPILER_ERRORS_WITH_GUIDES.has(ngErrorCode(diag.code))) {
|
|
38349
|
+
return Object.assign(Object.assign({}, diag), { messageText: diag.messageText +
|
|
38350
|
+
`. Find more at ${ERROR_DETAILS_PAGE_BASE_URL}/NG${ngErrorCode(diag.code)}` });
|
|
38351
|
+
}
|
|
38352
|
+
return diag;
|
|
38353
|
+
});
|
|
38148
38354
|
}
|
|
38149
38355
|
/**
|
|
38150
38356
|
* Get all setup-related diagnostics for this compilation.
|
|
@@ -38734,7 +38940,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
38734
38940
|
}
|
|
38735
38941
|
/**
|
|
38736
38942
|
* Since "strictTemplates" is a true superset of type checking capabilities compared to
|
|
38737
|
-
* "
|
|
38943
|
+
* "fullTemplateTypeCheck", it is required that the latter is not explicitly disabled if the
|
|
38738
38944
|
* former is enabled.
|
|
38739
38945
|
*/
|
|
38740
38946
|
function verifyCompatibleTypeCheckOptions(options) {
|
|
@@ -39328,9 +39534,6 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
39328
39534
|
function isTypeScriptFile(fileName) {
|
|
39329
39535
|
return fileName.endsWith('.ts');
|
|
39330
39536
|
}
|
|
39331
|
-
function isExternalTemplate(fileName) {
|
|
39332
|
-
return !isTypeScriptFile(fileName);
|
|
39333
|
-
}
|
|
39334
39537
|
function isWithin(position, span) {
|
|
39335
39538
|
let start, end;
|
|
39336
39539
|
if (span instanceof ParseSourceSpan) {
|
|
@@ -39345,6 +39548,31 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
39345
39548
|
// like ¦start and end¦ where ¦ is the cursor.
|
|
39346
39549
|
return start <= position && position <= end;
|
|
39347
39550
|
}
|
|
39551
|
+
/**
|
|
39552
|
+
* For a given location in a shim file, retrieves the corresponding file url for the template and
|
|
39553
|
+
* the span in the template.
|
|
39554
|
+
*/
|
|
39555
|
+
function getTemplateLocationFromShimLocation(templateTypeChecker, shimPath, positionInShimFile) {
|
|
39556
|
+
const mapping = templateTypeChecker.getTemplateMappingAtShimLocation({ shimPath, positionInShimFile });
|
|
39557
|
+
if (mapping === null) {
|
|
39558
|
+
return null;
|
|
39559
|
+
}
|
|
39560
|
+
const { templateSourceMapping, span } = mapping;
|
|
39561
|
+
let templateUrl;
|
|
39562
|
+
if (templateSourceMapping.type === 'direct') {
|
|
39563
|
+
templateUrl = absoluteFromSourceFile(templateSourceMapping.node.getSourceFile());
|
|
39564
|
+
}
|
|
39565
|
+
else if (templateSourceMapping.type === 'external') {
|
|
39566
|
+
templateUrl = absoluteFrom(templateSourceMapping.templateUrl);
|
|
39567
|
+
}
|
|
39568
|
+
else {
|
|
39569
|
+
// This includes indirect mappings, which are difficult to map directly to the code
|
|
39570
|
+
// location. Diagnostics similarly return a synthetic template string for this case rather
|
|
39571
|
+
// than a real location.
|
|
39572
|
+
return null;
|
|
39573
|
+
}
|
|
39574
|
+
return { templateUrl, span };
|
|
39575
|
+
}
|
|
39348
39576
|
|
|
39349
39577
|
/**
|
|
39350
39578
|
* @license
|
|
@@ -39361,7 +39589,12 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
39361
39589
|
this.ignoreForEmit = new Set();
|
|
39362
39590
|
this.factoryTracker = null; // no .ngfactory shims
|
|
39363
39591
|
this.unifiedModulesHost = null; // only used in Bazel
|
|
39364
|
-
|
|
39592
|
+
/**
|
|
39593
|
+
* Map of resource filenames to the version of the file last read via `readResource`.
|
|
39594
|
+
*
|
|
39595
|
+
* Used to implement `getModifiedResourceFiles`.
|
|
39596
|
+
*/
|
|
39597
|
+
this.lastReadResourceVersion = new Map();
|
|
39365
39598
|
this.rootDirs = getRootDirs(this, project.getCompilationSettings());
|
|
39366
39599
|
}
|
|
39367
39600
|
isShim(sf) {
|
|
@@ -39379,6 +39612,14 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
39379
39612
|
getCanonicalFileName(fileName) {
|
|
39380
39613
|
return this.project.projectService.toCanonicalFileName(fileName);
|
|
39381
39614
|
}
|
|
39615
|
+
/**
|
|
39616
|
+
* Return the real path of a symlink. This method is required in order to
|
|
39617
|
+
* resolve symlinks in node_modules.
|
|
39618
|
+
*/
|
|
39619
|
+
realpath(path) {
|
|
39620
|
+
var _a, _b, _c;
|
|
39621
|
+
return (_c = (_b = (_a = this.project).realpath) === null || _b === void 0 ? void 0 : _b.call(_a, path)) !== null && _c !== void 0 ? _c : path;
|
|
39622
|
+
}
|
|
39382
39623
|
/**
|
|
39383
39624
|
* readResource() is an Angular-specific method for reading files that are not
|
|
39384
39625
|
* managed by the TS compiler host, namely templates and stylesheets.
|
|
@@ -39401,13 +39642,17 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
39401
39642
|
throw new Error(`Failed to get script snapshot while trying to read ${fileName}`);
|
|
39402
39643
|
}
|
|
39403
39644
|
const version = this.project.getScriptVersion(fileName);
|
|
39404
|
-
this.
|
|
39645
|
+
this.lastReadResourceVersion.set(fileName, version);
|
|
39405
39646
|
return snapshot.getText(0, snapshot.getLength());
|
|
39406
39647
|
}
|
|
39407
|
-
|
|
39408
|
-
const
|
|
39409
|
-
const
|
|
39410
|
-
|
|
39648
|
+
getModifiedResourceFiles() {
|
|
39649
|
+
const modifiedFiles = new Set();
|
|
39650
|
+
for (const [fileName, oldVersion] of this.lastReadResourceVersion) {
|
|
39651
|
+
if (this.project.getScriptVersion(fileName) !== oldVersion) {
|
|
39652
|
+
modifiedFiles.add(fileName);
|
|
39653
|
+
}
|
|
39654
|
+
}
|
|
39655
|
+
return modifiedFiles.size > 0 ? modifiedFiles : undefined;
|
|
39411
39656
|
}
|
|
39412
39657
|
}
|
|
39413
39658
|
/**
|
|
@@ -39487,46 +39732,27 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
39487
39732
|
this.lastKnownProgram = null;
|
|
39488
39733
|
}
|
|
39489
39734
|
getOrCreate() {
|
|
39735
|
+
var _a;
|
|
39490
39736
|
const program = this.programStrategy.getProgram();
|
|
39491
|
-
|
|
39492
|
-
|
|
39493
|
-
|
|
39494
|
-
|
|
39495
|
-
|
|
39496
|
-
|
|
39497
|
-
|
|
39498
|
-
|
|
39499
|
-
return this.compiler;
|
|
39500
|
-
}
|
|
39501
|
-
/**
|
|
39502
|
-
* Create a new instance of the Ivy compiler if the program has changed since
|
|
39503
|
-
* the last time the compiler was instantiated. If the program has not changed,
|
|
39504
|
-
* return the existing instance.
|
|
39505
|
-
* @param fileName override the template if this is an external template file
|
|
39506
|
-
* @param options angular compiler options
|
|
39507
|
-
*/
|
|
39508
|
-
getOrCreateWithChangedFile(fileName) {
|
|
39509
|
-
const compiler = this.getOrCreate();
|
|
39510
|
-
if (isExternalTemplate(fileName)) {
|
|
39511
|
-
this.overrideTemplate(fileName, compiler);
|
|
39737
|
+
const modifiedResourceFiles = (_a = this.adapter.getModifiedResourceFiles()) !== null && _a !== void 0 ? _a : new Set();
|
|
39738
|
+
if (this.compiler !== null && program === this.lastKnownProgram) {
|
|
39739
|
+
if (modifiedResourceFiles.size > 0) {
|
|
39740
|
+
// Only resource files have changed since the last NgCompiler was created.
|
|
39741
|
+
const ticket = resourceChangeTicket(this.compiler, modifiedResourceFiles);
|
|
39742
|
+
this.compiler = NgCompiler.fromTicket(ticket, this.adapter);
|
|
39743
|
+
}
|
|
39744
|
+
return this.compiler;
|
|
39512
39745
|
}
|
|
39513
|
-
|
|
39514
|
-
|
|
39515
|
-
|
|
39516
|
-
if (!this.adapter.isTemplateDirty(fileName)) {
|
|
39517
|
-
return;
|
|
39746
|
+
let ticket;
|
|
39747
|
+
if (this.compiler === null || this.lastKnownProgram === null) {
|
|
39748
|
+
ticket = freshCompilationTicket(program, this.options, this.incrementalStrategy, this.programStrategy, true, true);
|
|
39518
39749
|
}
|
|
39519
|
-
|
|
39520
|
-
|
|
39521
|
-
// 2. Find all components that use the template
|
|
39522
|
-
const ttc = compiler.getTemplateTypeChecker();
|
|
39523
|
-
const components = compiler.getComponentsWithTemplateFile(fileName);
|
|
39524
|
-
// 3. Update component template
|
|
39525
|
-
for (const component of components) {
|
|
39526
|
-
if (ts.isClassDeclaration(component)) {
|
|
39527
|
-
ttc.overrideComponentTemplate(component, latestTemplate);
|
|
39528
|
-
}
|
|
39750
|
+
else {
|
|
39751
|
+
ticket = incrementalFromCompilerTicket(this.compiler, program, this.incrementalStrategy, this.programStrategy, modifiedResourceFiles);
|
|
39529
39752
|
}
|
|
39753
|
+
this.compiler = NgCompiler.fromTicket(ticket, this.adapter);
|
|
39754
|
+
this.lastKnownProgram = program;
|
|
39755
|
+
return this.compiler;
|
|
39530
39756
|
}
|
|
39531
39757
|
registerLastKnownProgram() {
|
|
39532
39758
|
this.lastKnownProgram = this.programStrategy.getProgram();
|
|
@@ -40137,12 +40363,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40137
40363
|
return undefined;
|
|
40138
40364
|
}
|
|
40139
40365
|
const { componentContext, templateContext } = completions;
|
|
40140
|
-
|
|
40141
|
-
// Non-empty nodes get replaced with the completion.
|
|
40142
|
-
if (!(this.node instanceof EmptyExpr || this.node instanceof LiteralPrimitive ||
|
|
40143
|
-
this.node instanceof BoundEvent)) {
|
|
40144
|
-
replacementSpan = makeReplacementSpanFromAst(this.node);
|
|
40145
|
-
}
|
|
40366
|
+
const replacementSpan = makeReplacementSpanFromAst(this.node);
|
|
40146
40367
|
// Merge TS completion results with results from the template scope.
|
|
40147
40368
|
let entries = [];
|
|
40148
40369
|
const tsLsCompletions = this.tsLS.getCompletionsAtPosition(componentContext.shimPath, componentContext.positionInShimFile, options);
|
|
@@ -40473,6 +40694,11 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40473
40694
|
};
|
|
40474
40695
|
}
|
|
40475
40696
|
function makeReplacementSpanFromAst(node) {
|
|
40697
|
+
if ((node instanceof EmptyExpr || node instanceof LiteralPrimitive ||
|
|
40698
|
+
node instanceof BoundEvent)) {
|
|
40699
|
+
// empty nodes do not replace any existing text
|
|
40700
|
+
return undefined;
|
|
40701
|
+
}
|
|
40476
40702
|
return {
|
|
40477
40703
|
start: node.nameSpan.start,
|
|
40478
40704
|
length: node.nameSpan.end - node.nameSpan.start,
|
|
@@ -40872,15 +41098,20 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40872
41098
|
case SymbolKind.Reference: {
|
|
40873
41099
|
const definitions = [];
|
|
40874
41100
|
if (symbol.declaration !== node) {
|
|
40875
|
-
|
|
40876
|
-
|
|
40877
|
-
|
|
40878
|
-
|
|
40879
|
-
|
|
40880
|
-
|
|
40881
|
-
|
|
40882
|
-
|
|
40883
|
-
|
|
41101
|
+
const shimLocation = symbol.kind === SymbolKind.Variable ? symbol.localVarLocation :
|
|
41102
|
+
symbol.referenceVarLocation;
|
|
41103
|
+
const mapping = getTemplateLocationFromShimLocation(this.compiler.getTemplateTypeChecker(), shimLocation.shimPath, shimLocation.positionInShimFile);
|
|
41104
|
+
if (mapping !== null) {
|
|
41105
|
+
definitions.push({
|
|
41106
|
+
name: symbol.declaration.name,
|
|
41107
|
+
containerName: '',
|
|
41108
|
+
containerKind: ts$1.ScriptElementKind.unknown,
|
|
41109
|
+
kind: ts$1.ScriptElementKind.variableElement,
|
|
41110
|
+
textSpan: getTextSpanOfNode(symbol.declaration),
|
|
41111
|
+
contextSpan: toTextSpan(symbol.declaration.sourceSpan),
|
|
41112
|
+
fileName: mapping.templateUrl,
|
|
41113
|
+
});
|
|
41114
|
+
}
|
|
40884
41115
|
}
|
|
40885
41116
|
if (symbol.kind === SymbolKind.Variable) {
|
|
40886
41117
|
definitions.push(...this.getDefinitionsForSymbols({ shimLocation: symbol.initializerLocation }));
|
|
@@ -41403,29 +41634,14 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41403
41634
|
// return references to the parameter in the template itself.
|
|
41404
41635
|
return null;
|
|
41405
41636
|
}
|
|
41406
|
-
// TODO(atscott): Determine how to consistently resolve paths. i.e. with the project
|
|
41407
|
-
// or LSParseConfigHost in the adapter. We should have a better defined way to
|
|
41408
|
-
|
|
41409
|
-
|
|
41410
|
-
positionInShimFile: shimReferenceEntry.textSpan.start,
|
|
41411
|
-
});
|
|
41637
|
+
// TODO(atscott): Determine how to consistently resolve paths. i.e. with the project
|
|
41638
|
+
// serverHost or LSParseConfigHost in the adapter. We should have a better defined way to
|
|
41639
|
+
// normalize paths.
|
|
41640
|
+
const mapping = getTemplateLocationFromShimLocation(templateTypeChecker, absoluteFrom(shimReferenceEntry.fileName), shimReferenceEntry.textSpan.start);
|
|
41412
41641
|
if (mapping === null) {
|
|
41413
41642
|
return null;
|
|
41414
41643
|
}
|
|
41415
|
-
const {
|
|
41416
|
-
let templateUrl;
|
|
41417
|
-
if (templateSourceMapping.type === 'direct') {
|
|
41418
|
-
templateUrl = absoluteFromSourceFile(templateSourceMapping.node.getSourceFile());
|
|
41419
|
-
}
|
|
41420
|
-
else if (templateSourceMapping.type === 'external') {
|
|
41421
|
-
templateUrl = absoluteFrom(templateSourceMapping.templateUrl);
|
|
41422
|
-
}
|
|
41423
|
-
else {
|
|
41424
|
-
// This includes indirect mappings, which are difficult to map directly to the code location.
|
|
41425
|
-
// Diagnostics similarly return a synthetic template string for this case rather than a real
|
|
41426
|
-
// location.
|
|
41427
|
-
return null;
|
|
41428
|
-
}
|
|
41644
|
+
const { span, templateUrl } = mapping;
|
|
41429
41645
|
return Object.assign(Object.assign({}, shimReferenceEntry), { fileName: templateUrl, textSpan: toTextSpan(span) });
|
|
41430
41646
|
}
|
|
41431
41647
|
}
|
|
@@ -41439,6 +41655,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41439
41655
|
*/
|
|
41440
41656
|
class LanguageService {
|
|
41441
41657
|
constructor(project, tsLS) {
|
|
41658
|
+
this.project = project;
|
|
41442
41659
|
this.tsLS = tsLS;
|
|
41443
41660
|
this.parseConfigHost = new LSParseConfigHost(project.projectService.host);
|
|
41444
41661
|
this.options = parseNgCompilerOptions(project, this.parseConfigHost);
|
|
@@ -41452,7 +41669,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41452
41669
|
return this.options;
|
|
41453
41670
|
}
|
|
41454
41671
|
getSemanticDiagnostics(fileName) {
|
|
41455
|
-
const compiler = this.compilerFactory.
|
|
41672
|
+
const compiler = this.compilerFactory.getOrCreate();
|
|
41456
41673
|
const ttc = compiler.getTemplateTypeChecker();
|
|
41457
41674
|
const diagnostics = [];
|
|
41458
41675
|
if (isTypeScriptFile(fileName)) {
|
|
@@ -41474,19 +41691,19 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41474
41691
|
return diagnostics;
|
|
41475
41692
|
}
|
|
41476
41693
|
getDefinitionAndBoundSpan(fileName, position) {
|
|
41477
|
-
const compiler = this.compilerFactory.
|
|
41694
|
+
const compiler = this.compilerFactory.getOrCreate();
|
|
41478
41695
|
const results = new DefinitionBuilder(this.tsLS, compiler).getDefinitionAndBoundSpan(fileName, position);
|
|
41479
41696
|
this.compilerFactory.registerLastKnownProgram();
|
|
41480
41697
|
return results;
|
|
41481
41698
|
}
|
|
41482
41699
|
getTypeDefinitionAtPosition(fileName, position) {
|
|
41483
|
-
const compiler = this.compilerFactory.
|
|
41700
|
+
const compiler = this.compilerFactory.getOrCreate();
|
|
41484
41701
|
const results = new DefinitionBuilder(this.tsLS, compiler).getTypeDefinitionsAtPosition(fileName, position);
|
|
41485
41702
|
this.compilerFactory.registerLastKnownProgram();
|
|
41486
41703
|
return results;
|
|
41487
41704
|
}
|
|
41488
41705
|
getQuickInfoAtPosition(fileName, position) {
|
|
41489
|
-
const compiler = this.compilerFactory.
|
|
41706
|
+
const compiler = this.compilerFactory.getOrCreate();
|
|
41490
41707
|
const templateInfo = getTemplateInfoAtPosition(fileName, position, compiler);
|
|
41491
41708
|
if (templateInfo === undefined) {
|
|
41492
41709
|
return undefined;
|
|
@@ -41506,13 +41723,13 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41506
41723
|
return results;
|
|
41507
41724
|
}
|
|
41508
41725
|
getReferencesAtPosition(fileName, position) {
|
|
41509
|
-
const compiler = this.compilerFactory.
|
|
41726
|
+
const compiler = this.compilerFactory.getOrCreate();
|
|
41510
41727
|
const results = new ReferenceBuilder(this.strategy, this.tsLS, compiler).get(fileName, position);
|
|
41511
41728
|
this.compilerFactory.registerLastKnownProgram();
|
|
41512
41729
|
return results;
|
|
41513
41730
|
}
|
|
41514
41731
|
getCompletionBuilder(fileName, position) {
|
|
41515
|
-
const compiler = this.compilerFactory.
|
|
41732
|
+
const compiler = this.compilerFactory.getOrCreate();
|
|
41516
41733
|
const templateInfo = getTemplateInfoAtPosition(fileName, position, compiler);
|
|
41517
41734
|
if (templateInfo === undefined) {
|
|
41518
41735
|
return null;
|
|
@@ -41555,6 +41772,28 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41555
41772
|
this.compilerFactory.registerLastKnownProgram();
|
|
41556
41773
|
return result;
|
|
41557
41774
|
}
|
|
41775
|
+
getCompilerOptionsDiagnostics() {
|
|
41776
|
+
const project = this.project;
|
|
41777
|
+
if (!(project instanceof ts.server.ConfiguredProject)) {
|
|
41778
|
+
return [];
|
|
41779
|
+
}
|
|
41780
|
+
const diagnostics = [];
|
|
41781
|
+
const configSourceFile = ts.readJsonConfigFile(project.getConfigFilePath(), (path) => project.readFile(path));
|
|
41782
|
+
if (!this.options.strictTemplates && !this.options.fullTemplateTypeCheck) {
|
|
41783
|
+
diagnostics.push({
|
|
41784
|
+
messageText: 'Some language features are not available. ' +
|
|
41785
|
+
'To access all features, enable `strictTemplates` in `angularCompilerOptions`.',
|
|
41786
|
+
category: ts.DiagnosticCategory.Suggestion,
|
|
41787
|
+
code: ngErrorCode(ErrorCode.SUGGEST_STRICT_TEMPLATES),
|
|
41788
|
+
file: configSourceFile,
|
|
41789
|
+
start: undefined,
|
|
41790
|
+
length: undefined,
|
|
41791
|
+
});
|
|
41792
|
+
}
|
|
41793
|
+
const compiler = this.compilerFactory.getOrCreate();
|
|
41794
|
+
diagnostics.push(...compiler.getOptionDiagnostics());
|
|
41795
|
+
return diagnostics;
|
|
41796
|
+
}
|
|
41558
41797
|
watchConfigFile(project) {
|
|
41559
41798
|
// TODO: Check the case when the project is disposed. An InferredProject
|
|
41560
41799
|
// could be disposed when a tsconfig.json is added to the workspace,
|
|
@@ -41755,6 +41994,20 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41755
41994
|
return (_a = tsLS.getCompletionEntrySymbol(fileName, position, name, source)) !== null && _a !== void 0 ? _a : ngLS.getCompletionEntrySymbol(fileName, position, name);
|
|
41756
41995
|
}
|
|
41757
41996
|
}
|
|
41997
|
+
/**
|
|
41998
|
+
* Gets global diagnostics related to the program configuration and compiler options.
|
|
41999
|
+
*/
|
|
42000
|
+
function getCompilerOptionsDiagnostics() {
|
|
42001
|
+
const diagnostics = [];
|
|
42002
|
+
if (!angularOnly) {
|
|
42003
|
+
diagnostics.push(...tsLS.getCompilerOptionsDiagnostics());
|
|
42004
|
+
}
|
|
42005
|
+
diagnostics.push(...ngLS.getCompilerOptionsDiagnostics());
|
|
42006
|
+
return diagnostics;
|
|
42007
|
+
}
|
|
42008
|
+
function getTcb(fileName, position) {
|
|
42009
|
+
return undefined;
|
|
42010
|
+
}
|
|
41758
42011
|
return Object.assign(Object.assign({}, tsLS), { getSemanticDiagnostics,
|
|
41759
42012
|
getTypeDefinitionAtPosition,
|
|
41760
42013
|
getQuickInfoAtPosition,
|
|
@@ -41763,7 +42016,9 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41763
42016
|
findRenameLocations,
|
|
41764
42017
|
getCompletionsAtPosition,
|
|
41765
42018
|
getCompletionEntryDetails,
|
|
41766
|
-
getCompletionEntrySymbol
|
|
42019
|
+
getCompletionEntrySymbol,
|
|
42020
|
+
getCompilerOptionsDiagnostics,
|
|
42021
|
+
getTcb });
|
|
41767
42022
|
}
|
|
41768
42023
|
function getExternalFiles(project) {
|
|
41769
42024
|
if (!project.hasRoots()) {
|