@angular/language-service 11.1.2 → 11.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/ivy.js +483 -230
- package/bundles/language-service.js +54 -41
- package/ivy/definitions.js +2 -2
- package/ivy/language_service.d.ts +5 -0
- package/ivy/language_service.js +72 -3
- package/ivy/references.d.ts +33 -4
- package/ivy/references.js +313 -70
- package/ivy/ts_plugin.js +15 -6
- package/ivy/utils.d.ts +1 -1
- package/ivy/utils.js +2 -2
- package/package.json +1 -1
package/bundles/ivy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v11.
|
|
2
|
+
* @license Angular v11.2.0
|
|
3
3
|
* Copyright Google LLC All Rights Reserved.
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -11665,6 +11665,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11665
11665
|
return new Chain(this.span(start), this.sourceSpan(start), exprs);
|
|
11666
11666
|
}
|
|
11667
11667
|
parsePipe() {
|
|
11668
|
+
const start = this.inputIndex;
|
|
11668
11669
|
let result = this.parseExpression();
|
|
11669
11670
|
if (this.consumeOptionalOperator('|')) {
|
|
11670
11671
|
if (this.parseAction) {
|
|
@@ -11700,7 +11701,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11700
11701
|
// If there are additional expressions beyond the name, then the artificial end for the
|
|
11701
11702
|
// name is no longer relevant.
|
|
11702
11703
|
}
|
|
11703
|
-
const { start } = result.span;
|
|
11704
11704
|
result = new BindingPipe(this.span(start), this.sourceSpan(start, fullSpanEnd), result, nameId, args, nameSpan);
|
|
11705
11705
|
} while (this.consumeOptionalOperator('|'));
|
|
11706
11706
|
}
|
|
@@ -11732,26 +11732,27 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11732
11732
|
}
|
|
11733
11733
|
parseLogicalOr() {
|
|
11734
11734
|
// '||'
|
|
11735
|
+
const start = this.inputIndex;
|
|
11735
11736
|
let result = this.parseLogicalAnd();
|
|
11736
11737
|
while (this.consumeOptionalOperator('||')) {
|
|
11737
11738
|
const right = this.parseLogicalAnd();
|
|
11738
|
-
const { start } = result.span;
|
|
11739
11739
|
result = new Binary(this.span(start), this.sourceSpan(start), '||', result, right);
|
|
11740
11740
|
}
|
|
11741
11741
|
return result;
|
|
11742
11742
|
}
|
|
11743
11743
|
parseLogicalAnd() {
|
|
11744
11744
|
// '&&'
|
|
11745
|
+
const start = this.inputIndex;
|
|
11745
11746
|
let result = this.parseEquality();
|
|
11746
11747
|
while (this.consumeOptionalOperator('&&')) {
|
|
11747
11748
|
const right = this.parseEquality();
|
|
11748
|
-
const { start } = result.span;
|
|
11749
11749
|
result = new Binary(this.span(start), this.sourceSpan(start), '&&', result, right);
|
|
11750
11750
|
}
|
|
11751
11751
|
return result;
|
|
11752
11752
|
}
|
|
11753
11753
|
parseEquality() {
|
|
11754
11754
|
// '==','!=','===','!=='
|
|
11755
|
+
const start = this.inputIndex;
|
|
11755
11756
|
let result = this.parseRelational();
|
|
11756
11757
|
while (this.next.type == TokenType$1.Operator) {
|
|
11757
11758
|
const operator = this.next.strValue;
|
|
@@ -11762,7 +11763,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11762
11763
|
case '!==':
|
|
11763
11764
|
this.advance();
|
|
11764
11765
|
const right = this.parseRelational();
|
|
11765
|
-
const { start } = result.span;
|
|
11766
11766
|
result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
|
|
11767
11767
|
continue;
|
|
11768
11768
|
}
|
|
@@ -11772,6 +11772,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11772
11772
|
}
|
|
11773
11773
|
parseRelational() {
|
|
11774
11774
|
// '<', '>', '<=', '>='
|
|
11775
|
+
const start = this.inputIndex;
|
|
11775
11776
|
let result = this.parseAdditive();
|
|
11776
11777
|
while (this.next.type == TokenType$1.Operator) {
|
|
11777
11778
|
const operator = this.next.strValue;
|
|
@@ -11782,7 +11783,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11782
11783
|
case '>=':
|
|
11783
11784
|
this.advance();
|
|
11784
11785
|
const right = this.parseAdditive();
|
|
11785
|
-
const { start } = result.span;
|
|
11786
11786
|
result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
|
|
11787
11787
|
continue;
|
|
11788
11788
|
}
|
|
@@ -11792,6 +11792,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11792
11792
|
}
|
|
11793
11793
|
parseAdditive() {
|
|
11794
11794
|
// '+', '-'
|
|
11795
|
+
const start = this.inputIndex;
|
|
11795
11796
|
let result = this.parseMultiplicative();
|
|
11796
11797
|
while (this.next.type == TokenType$1.Operator) {
|
|
11797
11798
|
const operator = this.next.strValue;
|
|
@@ -11800,7 +11801,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11800
11801
|
case '-':
|
|
11801
11802
|
this.advance();
|
|
11802
11803
|
let right = this.parseMultiplicative();
|
|
11803
|
-
const { start } = result.span;
|
|
11804
11804
|
result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
|
|
11805
11805
|
continue;
|
|
11806
11806
|
}
|
|
@@ -11810,6 +11810,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11810
11810
|
}
|
|
11811
11811
|
parseMultiplicative() {
|
|
11812
11812
|
// '*', '%', '/'
|
|
11813
|
+
const start = this.inputIndex;
|
|
11813
11814
|
let result = this.parsePrefix();
|
|
11814
11815
|
while (this.next.type == TokenType$1.Operator) {
|
|
11815
11816
|
const operator = this.next.strValue;
|
|
@@ -11819,7 +11820,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11819
11820
|
case '/':
|
|
11820
11821
|
this.advance();
|
|
11821
11822
|
let right = this.parsePrefix();
|
|
11822
|
-
const { start } = result.span;
|
|
11823
11823
|
result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
|
|
11824
11824
|
continue;
|
|
11825
11825
|
}
|
|
@@ -11850,14 +11850,14 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11850
11850
|
return this.parseCallChain();
|
|
11851
11851
|
}
|
|
11852
11852
|
parseCallChain() {
|
|
11853
|
+
const start = this.inputIndex;
|
|
11853
11854
|
let result = this.parsePrimary();
|
|
11854
|
-
const resultStart = result.span.start;
|
|
11855
11855
|
while (true) {
|
|
11856
11856
|
if (this.consumeOptionalCharacter($PERIOD)) {
|
|
11857
|
-
result = this.parseAccessMemberOrMethodCall(result, false);
|
|
11857
|
+
result = this.parseAccessMemberOrMethodCall(result, start, false);
|
|
11858
11858
|
}
|
|
11859
11859
|
else if (this.consumeOptionalOperator('?.')) {
|
|
11860
|
-
result = this.parseAccessMemberOrMethodCall(result, true);
|
|
11860
|
+
result = this.parseAccessMemberOrMethodCall(result, start, true);
|
|
11861
11861
|
}
|
|
11862
11862
|
else if (this.consumeOptionalCharacter($LBRACKET)) {
|
|
11863
11863
|
this.withContext(ParseContextFlags.Writable, () => {
|
|
@@ -11870,11 +11870,10 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11870
11870
|
this.expectCharacter($RBRACKET);
|
|
11871
11871
|
if (this.consumeOptionalOperator('=')) {
|
|
11872
11872
|
const value = this.parseConditional();
|
|
11873
|
-
result = new KeyedWrite(this.span(
|
|
11873
|
+
result = new KeyedWrite(this.span(start), this.sourceSpan(start), result, key, value);
|
|
11874
11874
|
}
|
|
11875
11875
|
else {
|
|
11876
|
-
result =
|
|
11877
|
-
new KeyedRead(this.span(resultStart), this.sourceSpan(resultStart), result, key);
|
|
11876
|
+
result = new KeyedRead(this.span(start), this.sourceSpan(start), result, key);
|
|
11878
11877
|
}
|
|
11879
11878
|
});
|
|
11880
11879
|
}
|
|
@@ -11883,11 +11882,10 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11883
11882
|
const args = this.parseCallArguments();
|
|
11884
11883
|
this.rparensExpected--;
|
|
11885
11884
|
this.expectCharacter($RPAREN);
|
|
11886
|
-
result =
|
|
11887
|
-
new FunctionCall(this.span(resultStart), this.sourceSpan(resultStart), result, args);
|
|
11885
|
+
result = new FunctionCall(this.span(start), this.sourceSpan(start), result, args);
|
|
11888
11886
|
}
|
|
11889
11887
|
else if (this.consumeOptionalOperator('!')) {
|
|
11890
|
-
result = new NonNullAssert(this.span(
|
|
11888
|
+
result = new NonNullAssert(this.span(start), this.sourceSpan(start), result);
|
|
11891
11889
|
}
|
|
11892
11890
|
else {
|
|
11893
11891
|
return result;
|
|
@@ -11934,7 +11932,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11934
11932
|
return this.parseLiteralMap();
|
|
11935
11933
|
}
|
|
11936
11934
|
else if (this.next.isIdentifier()) {
|
|
11937
|
-
return this.parseAccessMemberOrMethodCall(new ImplicitReceiver(this.span(start), this.sourceSpan(start)), false);
|
|
11935
|
+
return this.parseAccessMemberOrMethodCall(new ImplicitReceiver(this.span(start), this.sourceSpan(start)), start, false);
|
|
11938
11936
|
}
|
|
11939
11937
|
else if (this.next.isNumber()) {
|
|
11940
11938
|
const value = this.next.toNumber();
|
|
@@ -11986,8 +11984,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
11986
11984
|
}
|
|
11987
11985
|
return new LiteralMap(this.span(start), this.sourceSpan(start), keys, values);
|
|
11988
11986
|
}
|
|
11989
|
-
parseAccessMemberOrMethodCall(receiver, isSafe = false) {
|
|
11990
|
-
const start = receiver.span.start;
|
|
11987
|
+
parseAccessMemberOrMethodCall(receiver, start, isSafe = false) {
|
|
11991
11988
|
const nameStart = this.inputIndex;
|
|
11992
11989
|
const id = this.withContext(ParseContextFlags.Writable, () => {
|
|
11993
11990
|
var _a;
|
|
@@ -13220,6 +13217,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
13220
13217
|
else if (identifier.length === 0) {
|
|
13221
13218
|
this.reportError(`Reference does not have a name`, sourceSpan);
|
|
13222
13219
|
}
|
|
13220
|
+
else if (references.some(reference => reference.name === identifier)) {
|
|
13221
|
+
this.reportError(`Reference "#${identifier}" is defined more than once`, sourceSpan);
|
|
13222
|
+
}
|
|
13223
13223
|
references.push(new Reference(identifier, value, sourceSpan, keySpan, valueSpan));
|
|
13224
13224
|
}
|
|
13225
13225
|
parseAssignmentEvent(name, expression, sourceSpan, valueSpan, targetMatchableAttrs, boundEvents, keySpan) {
|
|
@@ -17011,7 +17011,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
17011
17011
|
* Use of this source code is governed by an MIT-style license that can be
|
|
17012
17012
|
* found in the LICENSE file at https://angular.io/license
|
|
17013
17013
|
*/
|
|
17014
|
-
const VERSION$1 = new Version('11.
|
|
17014
|
+
const VERSION$1 = new Version('11.2.0');
|
|
17015
17015
|
|
|
17016
17016
|
/**
|
|
17017
17017
|
* @license
|
|
@@ -17668,7 +17668,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
17668
17668
|
*/
|
|
17669
17669
|
function createDirectiveDefinitionMap(meta) {
|
|
17670
17670
|
const definitionMap = new DefinitionMap();
|
|
17671
|
-
definitionMap.set('version', literal('11.
|
|
17671
|
+
definitionMap.set('version', literal('11.2.0'));
|
|
17672
17672
|
// e.g. `type: MyDirective`
|
|
17673
17673
|
definitionMap.set('type', meta.internalType);
|
|
17674
17674
|
// e.g. `selector: 'some-dir'`
|
|
@@ -21116,7 +21116,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
21116
21116
|
* Use of this source code is governed by an MIT-style license that can be
|
|
21117
21117
|
* found in the LICENSE file at https://angular.io/license
|
|
21118
21118
|
*/
|
|
21119
|
-
const VERSION$2 = new Version('11.
|
|
21119
|
+
const VERSION$2 = new Version('11.2.0');
|
|
21120
21120
|
|
|
21121
21121
|
/**
|
|
21122
21122
|
* @license
|
|
@@ -21212,6 +21212,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
21212
21212
|
* has been discovered.
|
|
21213
21213
|
*/
|
|
21214
21214
|
ErrorCode[ErrorCode["UNDECORATED_CLASS_USING_ANGULAR_FEATURES"] = 2007] = "UNDECORATED_CLASS_USING_ANGULAR_FEATURES";
|
|
21215
|
+
/**
|
|
21216
|
+
* Raised when an component cannot resolve an external resource, such as a template or a style
|
|
21217
|
+
* sheet.
|
|
21218
|
+
*/
|
|
21219
|
+
ErrorCode[ErrorCode["COMPONENT_RESOURCE_NOT_FOUND"] = 2008] = "COMPONENT_RESOURCE_NOT_FOUND";
|
|
21215
21220
|
ErrorCode[ErrorCode["SYMBOL_NOT_EXPORTED"] = 3001] = "SYMBOL_NOT_EXPORTED";
|
|
21216
21221
|
ErrorCode[ErrorCode["SYMBOL_EXPORTED_UNDER_DIFFERENT_NAME"] = 3002] = "SYMBOL_EXPORTED_UNDER_DIFFERENT_NAME";
|
|
21217
21222
|
ErrorCode[ErrorCode["CONFIG_FLAT_MODULE_NO_INDEX"] = 4001] = "CONFIG_FLAT_MODULE_NO_INDEX";
|
|
@@ -28558,31 +28563,35 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28558
28563
|
const meta = this._resolveLiteral(decorator);
|
|
28559
28564
|
const component = reflectObjectLiteral(meta);
|
|
28560
28565
|
const containingFile = node.getSourceFile().fileName;
|
|
28561
|
-
|
|
28562
|
-
|
|
28563
|
-
|
|
28564
|
-
const promise = this.resourceLoader.preload(resourceUrl);
|
|
28565
|
-
return promise || Promise.resolve();
|
|
28566
|
+
const resolveStyleUrl = (styleUrl, nodeForError, resourceType) => {
|
|
28567
|
+
const resourceUrl = this._resolveResourceOrThrow(styleUrl, containingFile, nodeForError, resourceType);
|
|
28568
|
+
return this.resourceLoader.preload(resourceUrl);
|
|
28566
28569
|
};
|
|
28567
28570
|
// A Promise that waits for the template and all <link>ed styles within it to be preloaded.
|
|
28568
|
-
const templateAndTemplateStyleResources = this._preloadAndParseTemplate(node, decorator, component, containingFile)
|
|
28571
|
+
const templateAndTemplateStyleResources = this._preloadAndParseTemplate(node, decorator, component, containingFile)
|
|
28572
|
+
.then((template) => {
|
|
28569
28573
|
if (template === null) {
|
|
28570
28574
|
return undefined;
|
|
28571
28575
|
}
|
|
28572
|
-
|
|
28573
|
-
|
|
28574
|
-
|
|
28576
|
+
const nodeForError = getTemplateDeclarationNodeForError(template.declaration);
|
|
28577
|
+
return Promise
|
|
28578
|
+
.all(template.styleUrls.map(styleUrl => resolveStyleUrl(styleUrl, nodeForError, 1 /* StylesheetFromTemplate */)))
|
|
28579
|
+
.then(() => undefined);
|
|
28575
28580
|
});
|
|
28576
28581
|
// Extract all the styleUrls in the decorator.
|
|
28577
|
-
const
|
|
28578
|
-
if (
|
|
28582
|
+
const componentStyleUrls = this._extractComponentStyleUrls(component);
|
|
28583
|
+
if (componentStyleUrls === null) {
|
|
28579
28584
|
// A fast path exists if there are no styleUrls, to just wait for
|
|
28580
28585
|
// templateAndTemplateStyleResources.
|
|
28581
28586
|
return templateAndTemplateStyleResources;
|
|
28582
28587
|
}
|
|
28583
28588
|
else {
|
|
28584
28589
|
// Wait for both the template and all styleUrl resources to resolve.
|
|
28585
|
-
return Promise
|
|
28590
|
+
return Promise
|
|
28591
|
+
.all([
|
|
28592
|
+
templateAndTemplateStyleResources,
|
|
28593
|
+
...componentStyleUrls.map(styleUrl => resolveStyleUrl(styleUrl.url, styleUrl.nodeForError, 2 /* StylesheetFromDecorator */))
|
|
28594
|
+
])
|
|
28586
28595
|
.then(() => undefined);
|
|
28587
28596
|
}
|
|
28588
28597
|
}
|
|
@@ -28651,20 +28660,20 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28651
28660
|
// Figure out the set of styles. The ordering here is important: external resources (styleUrls)
|
|
28652
28661
|
// precede inline styles, and styles defined in the template override styles defined in the
|
|
28653
28662
|
// component.
|
|
28654
|
-
let styles =
|
|
28663
|
+
let styles = [];
|
|
28655
28664
|
const styleResources = this._extractStyleResources(component, containingFile);
|
|
28656
|
-
const styleUrls =
|
|
28657
|
-
|
|
28658
|
-
|
|
28659
|
-
|
|
28660
|
-
|
|
28661
|
-
|
|
28662
|
-
|
|
28663
|
-
|
|
28664
|
-
|
|
28665
|
-
|
|
28666
|
-
|
|
28667
|
-
|
|
28665
|
+
const styleUrls = [
|
|
28666
|
+
...this._extractComponentStyleUrls(component), ...this._extractTemplateStyleUrls(template)
|
|
28667
|
+
];
|
|
28668
|
+
for (const styleUrl of styleUrls) {
|
|
28669
|
+
const resourceType = styleUrl.source === 2 /* StylesheetFromDecorator */ ?
|
|
28670
|
+
2 /* StylesheetFromDecorator */ :
|
|
28671
|
+
1 /* StylesheetFromTemplate */;
|
|
28672
|
+
const resourceUrl = this._resolveResourceOrThrow(styleUrl.url, containingFile, styleUrl.nodeForError, resourceType);
|
|
28673
|
+
const resourceStr = this.resourceLoader.load(resourceUrl);
|
|
28674
|
+
styles.push(resourceStr);
|
|
28675
|
+
if (this.depTracker !== null) {
|
|
28676
|
+
this.depTracker.addResourceDependency(node.getSourceFile(), absoluteFrom(resourceUrl));
|
|
28668
28677
|
}
|
|
28669
28678
|
}
|
|
28670
28679
|
let inlineStyles = null;
|
|
@@ -28672,21 +28681,11 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28672
28681
|
const litStyles = parseFieldArrayValue(component, 'styles', this.evaluator);
|
|
28673
28682
|
if (litStyles !== null) {
|
|
28674
28683
|
inlineStyles = [...litStyles];
|
|
28675
|
-
|
|
28676
|
-
styles = litStyles;
|
|
28677
|
-
}
|
|
28678
|
-
else {
|
|
28679
|
-
styles.push(...litStyles);
|
|
28680
|
-
}
|
|
28684
|
+
styles.push(...litStyles);
|
|
28681
28685
|
}
|
|
28682
28686
|
}
|
|
28683
28687
|
if (template.styles.length > 0) {
|
|
28684
|
-
|
|
28685
|
-
styles = template.styles;
|
|
28686
|
-
}
|
|
28687
|
-
else {
|
|
28688
|
-
styles.push(...template.styles);
|
|
28689
|
-
}
|
|
28688
|
+
styles.push(...template.styles);
|
|
28690
28689
|
}
|
|
28691
28690
|
const encapsulation = this._resolveEnumValue(component, 'encapsulation', 'ViewEncapsulation') || 0;
|
|
28692
28691
|
const changeDetection = this._resolveEnumValue(component, 'changeDetection', 'ChangeDetectionStrategy');
|
|
@@ -28702,7 +28701,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28702
28701
|
meta: Object.assign(Object.assign({}, metadata), { template: {
|
|
28703
28702
|
nodes: template.nodes,
|
|
28704
28703
|
ngContentSelectors: template.ngContentSelectors,
|
|
28705
|
-
}, encapsulation, interpolation: (_a = template.interpolationConfig) !== null && _a !== void 0 ? _a : DEFAULT_INTERPOLATION_CONFIG, styles
|
|
28704
|
+
}, encapsulation, interpolation: (_a = template.interpolationConfig) !== null && _a !== void 0 ? _a : DEFAULT_INTERPOLATION_CONFIG, styles,
|
|
28706
28705
|
// These will be replaced during the compilation step, after all `NgModule`s have been
|
|
28707
28706
|
// analyzed and the full compilation scope for the component can be realized.
|
|
28708
28707
|
animations, viewProviders: wrappedViewProviders, i18nUseExternalIds: this.i18nUseExternalIds, relativeContextFilePath }),
|
|
@@ -28893,7 +28892,10 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28893
28892
|
let styles = [];
|
|
28894
28893
|
if (analysis.styleUrls !== null) {
|
|
28895
28894
|
for (const styleUrl of analysis.styleUrls) {
|
|
28896
|
-
const
|
|
28895
|
+
const resourceType = styleUrl.source === 2 /* StylesheetFromDecorator */ ?
|
|
28896
|
+
2 /* StylesheetFromDecorator */ :
|
|
28897
|
+
1 /* StylesheetFromTemplate */;
|
|
28898
|
+
const resolvedStyleUrl = this._resolveResourceOrThrow(styleUrl.url, containingFile, styleUrl.nodeForError, resourceType);
|
|
28897
28899
|
const styleText = this.resourceLoader.load(resolvedStyleUrl);
|
|
28898
28900
|
styles.push(styleText);
|
|
28899
28901
|
}
|
|
@@ -28966,16 +28968,45 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28966
28968
|
}
|
|
28967
28969
|
return resolved;
|
|
28968
28970
|
}
|
|
28969
|
-
|
|
28971
|
+
_extractComponentStyleUrls(component) {
|
|
28970
28972
|
if (!component.has('styleUrls')) {
|
|
28971
|
-
return
|
|
28973
|
+
return [];
|
|
28972
28974
|
}
|
|
28973
|
-
|
|
28974
|
-
|
|
28975
|
-
|
|
28976
|
-
|
|
28975
|
+
return this._extractStyleUrlsFromExpression(component.get('styleUrls'));
|
|
28976
|
+
}
|
|
28977
|
+
_extractStyleUrlsFromExpression(styleUrlsExpr) {
|
|
28978
|
+
const styleUrls = [];
|
|
28979
|
+
if (ts$1.isArrayLiteralExpression(styleUrlsExpr)) {
|
|
28980
|
+
for (const styleUrlExpr of styleUrlsExpr.elements) {
|
|
28981
|
+
if (ts$1.isSpreadElement(styleUrlExpr)) {
|
|
28982
|
+
styleUrls.push(...this._extractStyleUrlsFromExpression(styleUrlExpr.expression));
|
|
28983
|
+
}
|
|
28984
|
+
else {
|
|
28985
|
+
const styleUrl = this.evaluator.evaluate(styleUrlExpr);
|
|
28986
|
+
if (typeof styleUrl !== 'string') {
|
|
28987
|
+
throw createValueHasWrongTypeError(styleUrlExpr, styleUrl, 'styleUrl must be a string');
|
|
28988
|
+
}
|
|
28989
|
+
styleUrls.push({
|
|
28990
|
+
url: styleUrl,
|
|
28991
|
+
source: 2 /* StylesheetFromDecorator */,
|
|
28992
|
+
nodeForError: styleUrlExpr,
|
|
28993
|
+
});
|
|
28994
|
+
}
|
|
28995
|
+
}
|
|
28996
|
+
}
|
|
28997
|
+
else {
|
|
28998
|
+
const evaluatedStyleUrls = this.evaluator.evaluate(styleUrlsExpr);
|
|
28999
|
+
if (!isStringArray(evaluatedStyleUrls)) {
|
|
29000
|
+
throw createValueHasWrongTypeError(styleUrlsExpr, evaluatedStyleUrls, 'styleUrls must be an array of strings');
|
|
29001
|
+
}
|
|
29002
|
+
for (const styleUrl of evaluatedStyleUrls) {
|
|
29003
|
+
styleUrls.push({
|
|
29004
|
+
url: styleUrl,
|
|
29005
|
+
source: 2 /* StylesheetFromDecorator */,
|
|
29006
|
+
nodeForError: styleUrlsExpr,
|
|
29007
|
+
});
|
|
29008
|
+
}
|
|
28977
29009
|
}
|
|
28978
|
-
styleUrls.push(...extraUrls);
|
|
28979
29010
|
return styleUrls;
|
|
28980
29011
|
}
|
|
28981
29012
|
_extractStyleResources(component, containingFile) {
|
|
@@ -28988,7 +29019,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28988
29019
|
const styleUrlsExpr = component.get('styleUrls');
|
|
28989
29020
|
if (styleUrlsExpr !== undefined && ts$1.isArrayLiteralExpression(styleUrlsExpr)) {
|
|
28990
29021
|
for (const expression of stringLiteralElements(styleUrlsExpr)) {
|
|
28991
|
-
const resourceUrl = this.
|
|
29022
|
+
const resourceUrl = this._resolveResourceOrThrow(expression.text, containingFile, expression, 2 /* StylesheetFromDecorator */);
|
|
28992
29023
|
styles.add({ path: absoluteFrom(resourceUrl), expression });
|
|
28993
29024
|
}
|
|
28994
29025
|
}
|
|
@@ -29008,7 +29039,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
29008
29039
|
if (typeof templateUrl !== 'string') {
|
|
29009
29040
|
throw createValueHasWrongTypeError(templateUrlExpr, templateUrl, 'templateUrl must be a string');
|
|
29010
29041
|
}
|
|
29011
|
-
const resourceUrl = this.
|
|
29042
|
+
const resourceUrl = this._resolveResourceOrThrow(templateUrl, containingFile, templateUrlExpr, 0 /* Template */);
|
|
29012
29043
|
const templatePromise = this.resourceLoader.preload(resourceUrl);
|
|
29013
29044
|
// If the preload worked, then actually load and parse the template, and wait for any style
|
|
29014
29045
|
// URLs to resolve.
|
|
@@ -29151,7 +29182,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
29151
29182
|
if (typeof templateUrl !== 'string') {
|
|
29152
29183
|
throw createValueHasWrongTypeError(templateUrlExpr, templateUrl, 'templateUrl must be a string');
|
|
29153
29184
|
}
|
|
29154
|
-
const resourceUrl = this.
|
|
29185
|
+
const resourceUrl = this._resolveResourceOrThrow(templateUrl, containingFile, templateUrlExpr, 0 /* Template */);
|
|
29155
29186
|
return {
|
|
29156
29187
|
isInline: false,
|
|
29157
29188
|
interpolationConfig,
|
|
@@ -29199,6 +29230,38 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
29199
29230
|
}
|
|
29200
29231
|
this.cycleAnalyzer.recordSyntheticImport(origin, imported);
|
|
29201
29232
|
}
|
|
29233
|
+
/**
|
|
29234
|
+
* Resolve the url of a resource relative to the file that contains the reference to it.
|
|
29235
|
+
*
|
|
29236
|
+
* Throws a FatalDiagnosticError when unable to resolve the file.
|
|
29237
|
+
*/
|
|
29238
|
+
_resolveResourceOrThrow(file, basePath, nodeForError, resourceType) {
|
|
29239
|
+
try {
|
|
29240
|
+
return this.resourceLoader.resolve(file, basePath);
|
|
29241
|
+
}
|
|
29242
|
+
catch (e) {
|
|
29243
|
+
let errorText;
|
|
29244
|
+
switch (resourceType) {
|
|
29245
|
+
case 0 /* Template */:
|
|
29246
|
+
errorText = `Could not find template file '${file}'.`;
|
|
29247
|
+
break;
|
|
29248
|
+
case 1 /* StylesheetFromTemplate */:
|
|
29249
|
+
errorText = `Could not find stylesheet file '${file}' linked from the template.`;
|
|
29250
|
+
break;
|
|
29251
|
+
case 2 /* StylesheetFromDecorator */:
|
|
29252
|
+
errorText = `Could not find stylesheet file '${file}'.`;
|
|
29253
|
+
break;
|
|
29254
|
+
}
|
|
29255
|
+
throw new FatalDiagnosticError(ErrorCode.COMPONENT_RESOURCE_NOT_FOUND, nodeForError, errorText);
|
|
29256
|
+
}
|
|
29257
|
+
}
|
|
29258
|
+
_extractTemplateStyleUrls(template) {
|
|
29259
|
+
if (template.styleUrls === null) {
|
|
29260
|
+
return [];
|
|
29261
|
+
}
|
|
29262
|
+
const nodeForError = getTemplateDeclarationNodeForError(template.declaration);
|
|
29263
|
+
return template.styleUrls.map(url => ({ url, source: 1 /* StylesheetFromTemplate */, nodeForError }));
|
|
29264
|
+
}
|
|
29202
29265
|
}
|
|
29203
29266
|
function getTemplateRange(templateExpr) {
|
|
29204
29267
|
const startPos = templateExpr.getStart() + 1;
|
|
@@ -29221,6 +29284,22 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
29221
29284
|
return resourceUrl;
|
|
29222
29285
|
}
|
|
29223
29286
|
}
|
|
29287
|
+
/** Determines if the result of an evaluation is a string array. */
|
|
29288
|
+
function isStringArray(resolvedValue) {
|
|
29289
|
+
return Array.isArray(resolvedValue) && resolvedValue.every(elem => typeof elem === 'string');
|
|
29290
|
+
}
|
|
29291
|
+
/** Determines the node to use for debugging purposes for the given TemplateDeclaration. */
|
|
29292
|
+
function getTemplateDeclarationNodeForError(declaration) {
|
|
29293
|
+
// TODO(zarend): Change this to if/else when that is compatible with g3. This uses a switch
|
|
29294
|
+
// because if/else fails to compile on g3. That is because g3 compiles this in non-strict mode
|
|
29295
|
+
// where type inference does not work correctly.
|
|
29296
|
+
switch (declaration.isInline) {
|
|
29297
|
+
case true:
|
|
29298
|
+
return declaration.expression;
|
|
29299
|
+
case false:
|
|
29300
|
+
return declaration.templateUrlExpression;
|
|
29301
|
+
}
|
|
29302
|
+
}
|
|
29224
29303
|
|
|
29225
29304
|
/**
|
|
29226
29305
|
* @license
|
|
@@ -34061,8 +34140,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
34061
34140
|
this.typeCtorStatements = [];
|
|
34062
34141
|
this.pipeInsts = new Map();
|
|
34063
34142
|
this.pipeInstStatements = [];
|
|
34064
|
-
this.outputHelperIdent = null;
|
|
34065
|
-
this.helperStatements = [];
|
|
34066
34143
|
}
|
|
34067
34144
|
/**
|
|
34068
34145
|
* Get an expression referring to a type constructor for the given directive.
|
|
@@ -34122,85 +34199,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
34122
34199
|
this.pipeInsts.set(ref.node, pipeInstId);
|
|
34123
34200
|
return pipeInstId;
|
|
34124
34201
|
}
|
|
34125
|
-
/**
|
|
34126
|
-
* Declares a helper function to be able to cast directive outputs of type `EventEmitter<T>` to
|
|
34127
|
-
* have an accurate `subscribe()` method that properly carries over the generic type `T` into the
|
|
34128
|
-
* listener function passed as argument to `subscribe`. This is done to work around a typing
|
|
34129
|
-
* deficiency in `EventEmitter.subscribe`, where the listener function is typed as any.
|
|
34130
|
-
*/
|
|
34131
|
-
declareOutputHelper() {
|
|
34132
|
-
if (this.outputHelperIdent !== null) {
|
|
34133
|
-
return this.outputHelperIdent;
|
|
34134
|
-
}
|
|
34135
|
-
const outputHelperIdent = ts$1.createIdentifier('_outputHelper');
|
|
34136
|
-
const genericTypeDecl = ts$1.createTypeParameterDeclaration('T');
|
|
34137
|
-
const genericTypeRef = ts$1.createTypeReferenceNode('T', /* typeParameters */ undefined);
|
|
34138
|
-
const eventEmitter = this.referenceExternalType('@angular/core', 'EventEmitter', [new ExpressionType(new WrappedNodeExpr(genericTypeRef))]);
|
|
34139
|
-
// Declare a type that has a `subscribe` method that carries over type `T` as parameter
|
|
34140
|
-
// into the callback. The below code generates the following type literal:
|
|
34141
|
-
// `{subscribe(cb: (event: T) => any): void;}`
|
|
34142
|
-
const observableLike = ts$1.createTypeLiteralNode([ts$1.createMethodSignature(
|
|
34143
|
-
/* typeParameters */ undefined,
|
|
34144
|
-
/* parameters */ [ts$1.createParameter(
|
|
34145
|
-
/* decorators */ undefined,
|
|
34146
|
-
/* modifiers */ undefined,
|
|
34147
|
-
/* dotDotDotToken */ undefined,
|
|
34148
|
-
/* name */ 'cb',
|
|
34149
|
-
/* questionToken */ undefined,
|
|
34150
|
-
/* type */
|
|
34151
|
-
ts$1.createFunctionTypeNode(
|
|
34152
|
-
/* typeParameters */ undefined,
|
|
34153
|
-
/* parameters */ [ts$1.createParameter(
|
|
34154
|
-
/* decorators */ undefined,
|
|
34155
|
-
/* modifiers */ undefined,
|
|
34156
|
-
/* dotDotDotToken */ undefined,
|
|
34157
|
-
/* name */ 'event',
|
|
34158
|
-
/* questionToken */ undefined,
|
|
34159
|
-
/* type */ genericTypeRef)],
|
|
34160
|
-
/* type */ ts$1.createKeywordTypeNode(ts$1.SyntaxKind.AnyKeyword)))],
|
|
34161
|
-
/* type */ ts$1.createKeywordTypeNode(ts$1.SyntaxKind.VoidKeyword),
|
|
34162
|
-
/* name */ 'subscribe',
|
|
34163
|
-
/* questionToken */ undefined)]);
|
|
34164
|
-
// Declares the first signature of `_outputHelper` that matches arguments of type
|
|
34165
|
-
// `EventEmitter`, to convert them into `observableLike` defined above. The following
|
|
34166
|
-
// statement is generated:
|
|
34167
|
-
// `declare function _outputHelper<T>(output: EventEmitter<T>): observableLike;`
|
|
34168
|
-
this.helperStatements.push(ts$1.createFunctionDeclaration(
|
|
34169
|
-
/* decorators */ undefined,
|
|
34170
|
-
/* modifiers */ [ts$1.createModifier(ts$1.SyntaxKind.DeclareKeyword)],
|
|
34171
|
-
/* asteriskToken */ undefined,
|
|
34172
|
-
/* name */ outputHelperIdent,
|
|
34173
|
-
/* typeParameters */ [genericTypeDecl],
|
|
34174
|
-
/* parameters */ [ts$1.createParameter(
|
|
34175
|
-
/* decorators */ undefined,
|
|
34176
|
-
/* modifiers */ undefined,
|
|
34177
|
-
/* dotDotDotToken */ undefined,
|
|
34178
|
-
/* name */ 'output',
|
|
34179
|
-
/* questionToken */ undefined,
|
|
34180
|
-
/* type */ eventEmitter)],
|
|
34181
|
-
/* type */ observableLike,
|
|
34182
|
-
/* body */ undefined));
|
|
34183
|
-
// Declares the second signature of `_outputHelper` that matches all other argument types,
|
|
34184
|
-
// i.e. ensures type identity for output types other than `EventEmitter`. This corresponds
|
|
34185
|
-
// with the following statement:
|
|
34186
|
-
// `declare function _outputHelper<T>(output: T): T;`
|
|
34187
|
-
this.helperStatements.push(ts$1.createFunctionDeclaration(
|
|
34188
|
-
/* decorators */ undefined,
|
|
34189
|
-
/* modifiers */ [ts$1.createModifier(ts$1.SyntaxKind.DeclareKeyword)],
|
|
34190
|
-
/* asteriskToken */ undefined,
|
|
34191
|
-
/* name */ outputHelperIdent,
|
|
34192
|
-
/* typeParameters */ [genericTypeDecl],
|
|
34193
|
-
/* parameters */ [ts$1.createParameter(
|
|
34194
|
-
/* decorators */ undefined,
|
|
34195
|
-
/* modifiers */ undefined,
|
|
34196
|
-
/* dotDotDotToken */ undefined,
|
|
34197
|
-
/* name */ 'output',
|
|
34198
|
-
/* questionToken */ undefined,
|
|
34199
|
-
/* type */ genericTypeRef)],
|
|
34200
|
-
/* type */ genericTypeRef,
|
|
34201
|
-
/* body */ undefined));
|
|
34202
|
-
return this.outputHelperIdent = outputHelperIdent;
|
|
34203
|
-
}
|
|
34204
34202
|
/**
|
|
34205
34203
|
* Generate a `ts.Expression` that references the given node.
|
|
34206
34204
|
*
|
|
@@ -34242,7 +34240,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
34242
34240
|
}
|
|
34243
34241
|
getPreludeStatements() {
|
|
34244
34242
|
return [
|
|
34245
|
-
...this.helperStatements,
|
|
34246
34243
|
...this.pipeInstStatements,
|
|
34247
34244
|
...this.typeCtorStatements,
|
|
34248
34245
|
];
|
|
@@ -35717,16 +35714,8 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
35717
35714
|
// For strict checking of directive events, generate a call to the `subscribe` method
|
|
35718
35715
|
// on the directive's output field to let type information flow into the handler function's
|
|
35719
35716
|
// `$event` parameter.
|
|
35720
|
-
//
|
|
35721
|
-
// Note that the `EventEmitter<T>` type from '@angular/core' that is typically used for
|
|
35722
|
-
// outputs has a typings deficiency in its `subscribe` method. The generic type `T` is not
|
|
35723
|
-
// carried into the handler function, which is vital for inference of the type of `$event`.
|
|
35724
|
-
// As a workaround, the directive's field is passed into a helper function that has a
|
|
35725
|
-
// specially crafted set of signatures, to effectively cast `EventEmitter<T>` to something
|
|
35726
|
-
// that has a `subscribe` method that properly carries the `T` into the handler function.
|
|
35727
35717
|
const handler = tcbCreateEventHandler(output, this.tcb, this.scope, 0 /* Infer */);
|
|
35728
|
-
const
|
|
35729
|
-
const subscribeFn = ts$1.createPropertyAccess(outputHelper, 'subscribe');
|
|
35718
|
+
const subscribeFn = ts$1.createPropertyAccess(outputField, 'subscribe');
|
|
35730
35719
|
const call = ts$1.createCall(subscribeFn, /* typeArguments */ undefined, [handler]);
|
|
35731
35720
|
addParseSpanInfo(call, output.sourceSpan);
|
|
35732
35721
|
this.scope.addStatement(ts$1.createExpressionStatement(call));
|
|
@@ -36634,9 +36623,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
36634
36623
|
'\n\n';
|
|
36635
36624
|
const printer = ts$1.createPrinter();
|
|
36636
36625
|
source += '\n';
|
|
36637
|
-
for (const stmt of this.helperStatements) {
|
|
36638
|
-
source += printer.printNode(ts$1.EmitHint.Unspecified, stmt, this.contextFile) + '\n';
|
|
36639
|
-
}
|
|
36640
36626
|
for (const stmt of this.pipeInstStatements) {
|
|
36641
36627
|
source += printer.printNode(ts$1.EmitHint.Unspecified, stmt, this.contextFile) + '\n';
|
|
36642
36628
|
}
|
|
@@ -37248,7 +37234,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37248
37234
|
return null;
|
|
37249
37235
|
}
|
|
37250
37236
|
// Outputs in the TCB look like one of the two:
|
|
37251
|
-
// *
|
|
37237
|
+
// * _t1["outputField"].subscribe(handler);
|
|
37252
37238
|
// * _t1.addEventListener(handler);
|
|
37253
37239
|
// Even with strict null checks disabled, we still produce the access as a separate statement
|
|
37254
37240
|
// so that it can be found here.
|
|
@@ -39303,7 +39289,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
39303
39289
|
}
|
|
39304
39290
|
function toTextSpan(span) {
|
|
39305
39291
|
let start, end;
|
|
39306
|
-
if (span instanceof AbsoluteSourceSpan) {
|
|
39292
|
+
if (span instanceof AbsoluteSourceSpan || span instanceof ParseSpan) {
|
|
39307
39293
|
start = span.start;
|
|
39308
39294
|
end = span.end;
|
|
39309
39295
|
}
|
|
@@ -41051,7 +41037,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41051
41037
|
const definitions = [];
|
|
41052
41038
|
for (const definitionMeta of definitionMetas) {
|
|
41053
41039
|
// The `$event` of event handlers would point to the $event parameter in the shim file, as in
|
|
41054
|
-
// `
|
|
41040
|
+
// `_t3["x"].subscribe(function ($event): any { $event }) ;`
|
|
41055
41041
|
// If we wanted to return something for this, it would be more appropriate for something like
|
|
41056
41042
|
// `getTypeDefinition`.
|
|
41057
41043
|
if (isDollarEvent(definitionMeta.node)) {
|
|
@@ -41487,37 +41473,173 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41487
41473
|
* Use of this source code is governed by an MIT-style license that can be
|
|
41488
41474
|
* found in the LICENSE file at https://angular.io/license
|
|
41489
41475
|
*/
|
|
41490
|
-
|
|
41476
|
+
function toFilePosition(shimLocation) {
|
|
41477
|
+
return { fileName: shimLocation.shimPath, position: shimLocation.positionInShimFile };
|
|
41478
|
+
}
|
|
41479
|
+
var RequestKind;
|
|
41480
|
+
(function (RequestKind) {
|
|
41481
|
+
RequestKind[RequestKind["Template"] = 0] = "Template";
|
|
41482
|
+
RequestKind[RequestKind["TypeScript"] = 1] = "TypeScript";
|
|
41483
|
+
})(RequestKind || (RequestKind = {}));
|
|
41484
|
+
class ReferencesAndRenameBuilder {
|
|
41491
41485
|
constructor(strategy, tsLS, compiler) {
|
|
41492
41486
|
this.strategy = strategy;
|
|
41493
41487
|
this.tsLS = tsLS;
|
|
41494
41488
|
this.compiler = compiler;
|
|
41495
41489
|
this.ttc = this.compiler.getTemplateTypeChecker();
|
|
41496
41490
|
}
|
|
41497
|
-
|
|
41491
|
+
getRenameInfo(filePath, position) {
|
|
41492
|
+
const templateInfo = getTemplateInfoAtPosition(filePath, position, this.compiler);
|
|
41493
|
+
// We could not get a template at position so we assume the request came from outside the
|
|
41494
|
+
// template.
|
|
41495
|
+
if (templateInfo === undefined) {
|
|
41496
|
+
return this.tsLS.getRenameInfo(filePath, position);
|
|
41497
|
+
}
|
|
41498
|
+
const allTargetDetails = this.getTargetDetailsAtTemplatePosition(templateInfo, position);
|
|
41499
|
+
if (allTargetDetails === null) {
|
|
41500
|
+
return { canRename: false, localizedErrorMessage: 'Could not find template node at position.' };
|
|
41501
|
+
}
|
|
41502
|
+
const { templateTarget } = allTargetDetails[0];
|
|
41503
|
+
const templateTextAndSpan = getRenameTextAndSpanAtPosition(templateTarget, position);
|
|
41504
|
+
if (templateTextAndSpan === null) {
|
|
41505
|
+
return { canRename: false, localizedErrorMessage: 'Could not determine template node text.' };
|
|
41506
|
+
}
|
|
41507
|
+
const { text, span } = templateTextAndSpan;
|
|
41508
|
+
return {
|
|
41509
|
+
canRename: true,
|
|
41510
|
+
displayName: text,
|
|
41511
|
+
fullDisplayName: text,
|
|
41512
|
+
triggerSpan: span,
|
|
41513
|
+
};
|
|
41514
|
+
}
|
|
41515
|
+
findRenameLocations(filePath, position) {
|
|
41498
41516
|
this.ttc.generateAllTypeCheckBlocks();
|
|
41499
41517
|
const templateInfo = getTemplateInfoAtPosition(filePath, position, this.compiler);
|
|
41500
|
-
|
|
41501
|
-
|
|
41502
|
-
|
|
41518
|
+
// We could not get a template at position so we assume the request came from outside the
|
|
41519
|
+
// template.
|
|
41520
|
+
if (templateInfo === undefined) {
|
|
41521
|
+
const requestNode = this.getTsNodeAtPosition(filePath, position);
|
|
41522
|
+
if (requestNode === null) {
|
|
41523
|
+
return undefined;
|
|
41524
|
+
}
|
|
41525
|
+
const requestOrigin = { kind: RequestKind.TypeScript, requestNode };
|
|
41526
|
+
return this.findRenameLocationsAtTypescriptPosition(filePath, position, requestOrigin);
|
|
41527
|
+
}
|
|
41528
|
+
return this.findRenameLocationsAtTemplatePosition(templateInfo, position);
|
|
41503
41529
|
}
|
|
41504
|
-
|
|
41505
|
-
|
|
41530
|
+
findRenameLocationsAtTemplatePosition(templateInfo, position) {
|
|
41531
|
+
const allTargetDetails = this.getTargetDetailsAtTemplatePosition(templateInfo, position);
|
|
41532
|
+
if (allTargetDetails === null) {
|
|
41533
|
+
return undefined;
|
|
41534
|
+
}
|
|
41535
|
+
const allRenameLocations = [];
|
|
41536
|
+
for (const targetDetails of allTargetDetails) {
|
|
41537
|
+
const requestOrigin = {
|
|
41538
|
+
kind: RequestKind.Template,
|
|
41539
|
+
requestNode: targetDetails.templateTarget,
|
|
41540
|
+
position,
|
|
41541
|
+
};
|
|
41542
|
+
for (const location of targetDetails.typescriptLocations) {
|
|
41543
|
+
const locations = this.findRenameLocationsAtTypescriptPosition(location.fileName, location.position, requestOrigin);
|
|
41544
|
+
// If we couldn't find rename locations for _any_ result, we should not allow renaming to
|
|
41545
|
+
// proceed instead of having a partially complete rename.
|
|
41546
|
+
if (locations === undefined) {
|
|
41547
|
+
return undefined;
|
|
41548
|
+
}
|
|
41549
|
+
allRenameLocations.push(...locations);
|
|
41550
|
+
}
|
|
41551
|
+
}
|
|
41552
|
+
return allRenameLocations.length > 0 ? allRenameLocations : undefined;
|
|
41553
|
+
}
|
|
41554
|
+
getTsNodeAtPosition(filePath, position) {
|
|
41555
|
+
var _a;
|
|
41556
|
+
const sf = this.strategy.getProgram().getSourceFile(filePath);
|
|
41557
|
+
if (!sf) {
|
|
41558
|
+
return null;
|
|
41559
|
+
}
|
|
41560
|
+
return (_a = findTightestNode(sf, position)) !== null && _a !== void 0 ? _a : null;
|
|
41561
|
+
}
|
|
41562
|
+
findRenameLocationsAtTypescriptPosition(filePath, position, requestOrigin) {
|
|
41563
|
+
let originalNodeText;
|
|
41564
|
+
if (requestOrigin.kind === RequestKind.TypeScript) {
|
|
41565
|
+
originalNodeText = requestOrigin.requestNode.getText();
|
|
41566
|
+
}
|
|
41567
|
+
else {
|
|
41568
|
+
const templateNodeText = getRenameTextAndSpanAtPosition(requestOrigin.requestNode, requestOrigin.position);
|
|
41569
|
+
if (templateNodeText === null) {
|
|
41570
|
+
return undefined;
|
|
41571
|
+
}
|
|
41572
|
+
originalNodeText = templateNodeText.text;
|
|
41573
|
+
}
|
|
41574
|
+
const locations = this.tsLS.findRenameLocations(filePath, position, /*findInStrings*/ false, /*findInComments*/ false);
|
|
41575
|
+
if (locations === undefined) {
|
|
41576
|
+
return undefined;
|
|
41577
|
+
}
|
|
41578
|
+
const entries = new Map();
|
|
41579
|
+
for (const location of locations) {
|
|
41580
|
+
// TODO(atscott): Determine if a file is a shim file in a more robust way and make the API
|
|
41581
|
+
// available in an appropriate location.
|
|
41582
|
+
if (this.ttc.isTrackedTypeCheckFile(absoluteFrom(location.fileName))) {
|
|
41583
|
+
const entry = this.convertToTemplateDocumentSpan(location, this.ttc, originalNodeText);
|
|
41584
|
+
// There is no template node whose text matches the original rename request. Bail on
|
|
41585
|
+
// renaming completely rather than providing incomplete results.
|
|
41586
|
+
if (entry === null) {
|
|
41587
|
+
return undefined;
|
|
41588
|
+
}
|
|
41589
|
+
entries.set(createLocationKey(entry), entry);
|
|
41590
|
+
}
|
|
41591
|
+
else {
|
|
41592
|
+
// Ensure we only allow renaming a TS result with matching text
|
|
41593
|
+
const refNode = this.getTsNodeAtPosition(location.fileName, location.textSpan.start);
|
|
41594
|
+
if (refNode === null || refNode.getText() !== originalNodeText) {
|
|
41595
|
+
return undefined;
|
|
41596
|
+
}
|
|
41597
|
+
entries.set(createLocationKey(location), location);
|
|
41598
|
+
}
|
|
41599
|
+
}
|
|
41600
|
+
return Array.from(entries.values());
|
|
41601
|
+
}
|
|
41602
|
+
getReferencesAtPosition(filePath, position) {
|
|
41603
|
+
this.ttc.generateAllTypeCheckBlocks();
|
|
41604
|
+
const templateInfo = getTemplateInfoAtPosition(filePath, position, this.compiler);
|
|
41605
|
+
if (templateInfo === undefined) {
|
|
41606
|
+
return this.getReferencesAtTypescriptPosition(filePath, position);
|
|
41607
|
+
}
|
|
41608
|
+
return this.getReferencesAtTemplatePosition(templateInfo, position);
|
|
41609
|
+
}
|
|
41610
|
+
getReferencesAtTemplatePosition(templateInfo, position) {
|
|
41611
|
+
const allTargetDetails = this.getTargetDetailsAtTemplatePosition(templateInfo, position);
|
|
41612
|
+
if (allTargetDetails === null) {
|
|
41613
|
+
return undefined;
|
|
41614
|
+
}
|
|
41615
|
+
const allReferences = [];
|
|
41616
|
+
for (const targetDetails of allTargetDetails) {
|
|
41617
|
+
for (const location of targetDetails.typescriptLocations) {
|
|
41618
|
+
const refs = this.getReferencesAtTypescriptPosition(location.fileName, location.position);
|
|
41619
|
+
if (refs !== undefined) {
|
|
41620
|
+
allReferences.push(...refs);
|
|
41621
|
+
}
|
|
41622
|
+
}
|
|
41623
|
+
}
|
|
41624
|
+
return allReferences.length > 0 ? allReferences : undefined;
|
|
41625
|
+
}
|
|
41626
|
+
getTargetDetailsAtTemplatePosition({ template, component }, position) {
|
|
41506
41627
|
// Find the AST node in the template at the position.
|
|
41507
41628
|
const positionDetails = getTargetAtPosition(template, position);
|
|
41508
41629
|
if (positionDetails === null) {
|
|
41509
|
-
return
|
|
41630
|
+
return null;
|
|
41510
41631
|
}
|
|
41511
41632
|
const nodes = positionDetails.context.kind === TargetNodeKind.TwoWayBindingContext ?
|
|
41512
41633
|
positionDetails.context.nodes :
|
|
41513
41634
|
[positionDetails.context.node];
|
|
41514
|
-
const
|
|
41635
|
+
const details = [];
|
|
41515
41636
|
for (const node of nodes) {
|
|
41516
41637
|
// Get the information about the TCB at the template position.
|
|
41517
41638
|
const symbol = this.ttc.getSymbolOfNode(node, component);
|
|
41518
41639
|
if (symbol === null) {
|
|
41519
41640
|
continue;
|
|
41520
41641
|
}
|
|
41642
|
+
const templateTarget = node;
|
|
41521
41643
|
switch (symbol.kind) {
|
|
41522
41644
|
case SymbolKind.Directive:
|
|
41523
41645
|
case SymbolKind.Template:
|
|
@@ -41526,7 +41648,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41526
41648
|
break;
|
|
41527
41649
|
case SymbolKind.Element: {
|
|
41528
41650
|
const matches = getDirectiveMatchesForElementTag(symbol.templateNode, symbol.directives);
|
|
41529
|
-
|
|
41651
|
+
details.push({ typescriptLocations: this.getPositionsForDirectives(matches), templateTarget });
|
|
41530
41652
|
break;
|
|
41531
41653
|
}
|
|
41532
41654
|
case SymbolKind.DomBinding: {
|
|
@@ -41534,116 +41656,170 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41534
41656
|
// have a shim location. This means we can't match dom bindings to their lib.dom
|
|
41535
41657
|
// reference, but we can still see if they match to a directive.
|
|
41536
41658
|
if (!(node instanceof TextAttribute) && !(node instanceof BoundAttribute)) {
|
|
41537
|
-
|
|
41659
|
+
return null;
|
|
41538
41660
|
}
|
|
41539
41661
|
const directives = getDirectiveMatchesForAttribute(node.name, symbol.host.templateNode, symbol.host.directives);
|
|
41540
|
-
|
|
41662
|
+
details.push({
|
|
41663
|
+
typescriptLocations: this.getPositionsForDirectives(directives),
|
|
41664
|
+
templateTarget,
|
|
41665
|
+
});
|
|
41541
41666
|
break;
|
|
41542
41667
|
}
|
|
41543
41668
|
case SymbolKind.Reference: {
|
|
41544
|
-
|
|
41545
|
-
|
|
41669
|
+
details.push({
|
|
41670
|
+
typescriptLocations: [toFilePosition(symbol.referenceVarLocation)],
|
|
41671
|
+
templateTarget,
|
|
41672
|
+
});
|
|
41546
41673
|
break;
|
|
41547
41674
|
}
|
|
41548
41675
|
case SymbolKind.Variable: {
|
|
41549
|
-
|
|
41550
|
-
|
|
41551
|
-
|
|
41552
|
-
if (node.valueSpan !== undefined && isWithin(position, node.valueSpan)) {
|
|
41676
|
+
if ((templateTarget instanceof Variable)) {
|
|
41677
|
+
if (templateTarget.valueSpan !== undefined &&
|
|
41678
|
+
isWithin(position, templateTarget.valueSpan)) {
|
|
41553
41679
|
// In the valueSpan of the variable, we want to get the reference of the initializer.
|
|
41554
|
-
|
|
41680
|
+
details.push({
|
|
41681
|
+
typescriptLocations: [toFilePosition(symbol.initializerLocation)],
|
|
41682
|
+
templateTarget,
|
|
41683
|
+
});
|
|
41555
41684
|
}
|
|
41556
|
-
else if (isWithin(position,
|
|
41685
|
+
else if (isWithin(position, templateTarget.keySpan)) {
|
|
41557
41686
|
// In the keySpan of the variable, we want to get the reference of the local variable.
|
|
41558
|
-
|
|
41687
|
+
details.push({
|
|
41688
|
+
typescriptLocations: [toFilePosition(symbol.localVarLocation)],
|
|
41689
|
+
templateTarget,
|
|
41690
|
+
});
|
|
41559
41691
|
}
|
|
41560
41692
|
}
|
|
41561
41693
|
else {
|
|
41562
|
-
// If the templateNode is not the `TmplAstVariable`, it must be a usage of the
|
|
41563
|
-
// somewhere in the template.
|
|
41564
|
-
|
|
41694
|
+
// If the templateNode is not the `TmplAstVariable`, it must be a usage of the
|
|
41695
|
+
// variable somewhere in the template.
|
|
41696
|
+
details.push({
|
|
41697
|
+
typescriptLocations: [toFilePosition(symbol.localVarLocation)],
|
|
41698
|
+
templateTarget,
|
|
41699
|
+
});
|
|
41565
41700
|
}
|
|
41566
41701
|
break;
|
|
41567
41702
|
}
|
|
41568
41703
|
case SymbolKind.Input:
|
|
41569
41704
|
case SymbolKind.Output: {
|
|
41570
|
-
|
|
41571
|
-
|
|
41572
|
-
|
|
41705
|
+
details.push({
|
|
41706
|
+
typescriptLocations: symbol.bindings.map(binding => toFilePosition(binding.shimLocation)),
|
|
41707
|
+
templateTarget,
|
|
41708
|
+
});
|
|
41573
41709
|
break;
|
|
41574
41710
|
}
|
|
41575
41711
|
case SymbolKind.Pipe:
|
|
41576
41712
|
case SymbolKind.Expression: {
|
|
41577
|
-
|
|
41578
|
-
references.push(...(_h = this.getReferencesAtTypescriptPosition(shimPath, positionInShimFile)) !== null && _h !== void 0 ? _h : []);
|
|
41713
|
+
details.push({ typescriptLocations: [toFilePosition(symbol.shimLocation)], templateTarget });
|
|
41579
41714
|
break;
|
|
41580
41715
|
}
|
|
41581
41716
|
}
|
|
41582
41717
|
}
|
|
41583
|
-
|
|
41584
|
-
return undefined;
|
|
41585
|
-
}
|
|
41586
|
-
return references;
|
|
41718
|
+
return details.length > 0 ? details : null;
|
|
41587
41719
|
}
|
|
41588
|
-
|
|
41589
|
-
const
|
|
41720
|
+
getPositionsForDirectives(directives) {
|
|
41721
|
+
const allDirectives = [];
|
|
41590
41722
|
for (const dir of directives.values()) {
|
|
41591
41723
|
const dirClass = dir.tsSymbol.valueDeclaration;
|
|
41592
41724
|
if (dirClass === undefined || !ts$1.isClassDeclaration(dirClass) ||
|
|
41593
41725
|
dirClass.name === undefined) {
|
|
41594
41726
|
continue;
|
|
41595
41727
|
}
|
|
41596
|
-
const
|
|
41597
|
-
const
|
|
41598
|
-
|
|
41599
|
-
if (directiveRefs !== undefined) {
|
|
41600
|
-
allDirectiveRefs.push(...directiveRefs);
|
|
41601
|
-
}
|
|
41728
|
+
const { fileName } = dirClass.getSourceFile();
|
|
41729
|
+
const position = dirClass.name.getStart();
|
|
41730
|
+
allDirectives.push({ fileName, position });
|
|
41602
41731
|
}
|
|
41603
|
-
return
|
|
41732
|
+
return allDirectives;
|
|
41604
41733
|
}
|
|
41605
41734
|
getReferencesAtTypescriptPosition(fileName, position) {
|
|
41606
41735
|
const refs = this.tsLS.getReferencesAtPosition(fileName, position);
|
|
41607
41736
|
if (refs === undefined) {
|
|
41608
41737
|
return undefined;
|
|
41609
41738
|
}
|
|
41610
|
-
const entries =
|
|
41739
|
+
const entries = new Map();
|
|
41611
41740
|
for (const ref of refs) {
|
|
41612
41741
|
if (this.ttc.isTrackedTypeCheckFile(absoluteFrom(ref.fileName))) {
|
|
41613
|
-
const entry = this.
|
|
41742
|
+
const entry = this.convertToTemplateDocumentSpan(ref, this.ttc);
|
|
41614
41743
|
if (entry !== null) {
|
|
41615
|
-
entries.
|
|
41744
|
+
entries.set(createLocationKey(entry), entry);
|
|
41616
41745
|
}
|
|
41617
41746
|
}
|
|
41618
41747
|
else {
|
|
41619
|
-
entries.
|
|
41748
|
+
entries.set(createLocationKey(ref), ref);
|
|
41620
41749
|
}
|
|
41621
41750
|
}
|
|
41622
|
-
return entries;
|
|
41751
|
+
return Array.from(entries.values());
|
|
41623
41752
|
}
|
|
41624
|
-
|
|
41625
|
-
const sf = this.strategy.getProgram().getSourceFile(
|
|
41753
|
+
convertToTemplateDocumentSpan(shimDocumentSpan, templateTypeChecker, requiredNodeText) {
|
|
41754
|
+
const sf = this.strategy.getProgram().getSourceFile(shimDocumentSpan.fileName);
|
|
41626
41755
|
if (sf === undefined) {
|
|
41627
41756
|
return null;
|
|
41628
41757
|
}
|
|
41629
|
-
const tcbNode = findTightestNode(sf,
|
|
41758
|
+
const tcbNode = findTightestNode(sf, shimDocumentSpan.textSpan.start);
|
|
41630
41759
|
if (tcbNode === undefined ||
|
|
41631
41760
|
hasExpressionIdentifier(sf, tcbNode, ExpressionIdentifier.EVENT_PARAMETER)) {
|
|
41632
|
-
// If the reference result is the $event parameter in the subscribe/addEventListener
|
|
41633
|
-
// in the TCB, we want to filter this result out of the references. We really only
|
|
41634
|
-
// return references to the parameter in the template itself.
|
|
41761
|
+
// If the reference result is the $event parameter in the subscribe/addEventListener
|
|
41762
|
+
// function in the TCB, we want to filter this result out of the references. We really only
|
|
41763
|
+
// want to return references to the parameter in the template itself.
|
|
41635
41764
|
return null;
|
|
41636
41765
|
}
|
|
41637
41766
|
// TODO(atscott): Determine how to consistently resolve paths. i.e. with the project
|
|
41638
41767
|
// serverHost or LSParseConfigHost in the adapter. We should have a better defined way to
|
|
41639
41768
|
// normalize paths.
|
|
41640
|
-
const mapping = getTemplateLocationFromShimLocation(templateTypeChecker, absoluteFrom(
|
|
41769
|
+
const mapping = getTemplateLocationFromShimLocation(templateTypeChecker, absoluteFrom(shimDocumentSpan.fileName), shimDocumentSpan.textSpan.start);
|
|
41641
41770
|
if (mapping === null) {
|
|
41642
41771
|
return null;
|
|
41643
41772
|
}
|
|
41644
41773
|
const { span, templateUrl } = mapping;
|
|
41645
|
-
|
|
41774
|
+
if (requiredNodeText !== undefined && span.toString() !== requiredNodeText) {
|
|
41775
|
+
return null;
|
|
41776
|
+
}
|
|
41777
|
+
return Object.assign(Object.assign({}, shimDocumentSpan), { fileName: templateUrl, textSpan: toTextSpan(span) });
|
|
41778
|
+
}
|
|
41779
|
+
}
|
|
41780
|
+
function getRenameTextAndSpanAtPosition(node, position) {
|
|
41781
|
+
if (node instanceof BoundAttribute || node instanceof TextAttribute ||
|
|
41782
|
+
node instanceof BoundEvent) {
|
|
41783
|
+
if (node.keySpan === undefined) {
|
|
41784
|
+
return null;
|
|
41785
|
+
}
|
|
41786
|
+
return { text: node.name, span: toTextSpan(node.keySpan) };
|
|
41787
|
+
}
|
|
41788
|
+
else if (node instanceof Variable || node instanceof Reference) {
|
|
41789
|
+
if (isWithin(position, node.keySpan)) {
|
|
41790
|
+
return { text: node.keySpan.toString(), span: toTextSpan(node.keySpan) };
|
|
41791
|
+
}
|
|
41792
|
+
else if (node.valueSpan && isWithin(position, node.valueSpan)) {
|
|
41793
|
+
return { text: node.valueSpan.toString(), span: toTextSpan(node.valueSpan) };
|
|
41794
|
+
}
|
|
41795
|
+
}
|
|
41796
|
+
if (node instanceof BindingPipe) {
|
|
41797
|
+
// TODO(atscott): Add support for renaming pipes
|
|
41798
|
+
return null;
|
|
41646
41799
|
}
|
|
41800
|
+
if (node instanceof PropertyRead || node instanceof MethodCall || node instanceof PropertyWrite ||
|
|
41801
|
+
node instanceof SafePropertyRead || node instanceof SafeMethodCall) {
|
|
41802
|
+
return { text: node.name, span: toTextSpan(node.nameSpan) };
|
|
41803
|
+
}
|
|
41804
|
+
else if (node instanceof LiteralPrimitive) {
|
|
41805
|
+
const span = toTextSpan(node.sourceSpan);
|
|
41806
|
+
const text = node.value;
|
|
41807
|
+
if (typeof text === 'string') {
|
|
41808
|
+
// The span of a string literal includes the quotes but they should be removed for renaming.
|
|
41809
|
+
span.start += 1;
|
|
41810
|
+
span.length -= 2;
|
|
41811
|
+
}
|
|
41812
|
+
return { text, span };
|
|
41813
|
+
}
|
|
41814
|
+
return null;
|
|
41815
|
+
}
|
|
41816
|
+
/**
|
|
41817
|
+
* Creates a "key" for a rename/reference location by concatenating file name, span start, and span
|
|
41818
|
+
* length. This allows us to de-duplicate template results when an item may appear several times
|
|
41819
|
+
* in the TCB but map back to the same template location.
|
|
41820
|
+
*/
|
|
41821
|
+
function createLocationKey(ds) {
|
|
41822
|
+
return ds.fileName + ds.textSpan.start + ds.textSpan.length;
|
|
41647
41823
|
}
|
|
41648
41824
|
|
|
41649
41825
|
/**
|
|
@@ -41724,7 +41900,28 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41724
41900
|
}
|
|
41725
41901
|
getReferencesAtPosition(fileName, position) {
|
|
41726
41902
|
const compiler = this.compilerFactory.getOrCreate();
|
|
41727
|
-
const results = new
|
|
41903
|
+
const results = new ReferencesAndRenameBuilder(this.strategy, this.tsLS, compiler)
|
|
41904
|
+
.getReferencesAtPosition(fileName, position);
|
|
41905
|
+
this.compilerFactory.registerLastKnownProgram();
|
|
41906
|
+
return results;
|
|
41907
|
+
}
|
|
41908
|
+
getRenameInfo(fileName, position) {
|
|
41909
|
+
var _a, _b, _c;
|
|
41910
|
+
const compiler = this.compilerFactory.getOrCreate();
|
|
41911
|
+
const renameInfo = new ReferencesAndRenameBuilder(this.strategy, this.tsLS, compiler)
|
|
41912
|
+
.getRenameInfo(absoluteFrom(fileName), position);
|
|
41913
|
+
if (!renameInfo.canRename) {
|
|
41914
|
+
return renameInfo;
|
|
41915
|
+
}
|
|
41916
|
+
const quickInfo = (_a = this.getQuickInfoAtPosition(fileName, position)) !== null && _a !== void 0 ? _a : this.tsLS.getQuickInfoAtPosition(fileName, position);
|
|
41917
|
+
const kind = (_b = quickInfo === null || quickInfo === void 0 ? void 0 : quickInfo.kind) !== null && _b !== void 0 ? _b : ts.ScriptElementKind.unknown;
|
|
41918
|
+
const kindModifiers = (_c = quickInfo === null || quickInfo === void 0 ? void 0 : quickInfo.kindModifiers) !== null && _c !== void 0 ? _c : ts.ScriptElementKind.unknown;
|
|
41919
|
+
return Object.assign(Object.assign({}, renameInfo), { kind, kindModifiers });
|
|
41920
|
+
}
|
|
41921
|
+
findRenameLocations(fileName, position) {
|
|
41922
|
+
const compiler = this.compilerFactory.getOrCreate();
|
|
41923
|
+
const results = new ReferencesAndRenameBuilder(this.strategy, this.tsLS, compiler)
|
|
41924
|
+
.findRenameLocations(fileName, position);
|
|
41728
41925
|
this.compilerFactory.registerLastKnownProgram();
|
|
41729
41926
|
return results;
|
|
41730
41927
|
}
|
|
@@ -41772,6 +41969,53 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41772
41969
|
this.compilerFactory.registerLastKnownProgram();
|
|
41773
41970
|
return result;
|
|
41774
41971
|
}
|
|
41972
|
+
getTcb(fileName, position) {
|
|
41973
|
+
return this.withCompiler(compiler => {
|
|
41974
|
+
const templateInfo = getTemplateInfoAtPosition(fileName, position, compiler);
|
|
41975
|
+
if (templateInfo === undefined) {
|
|
41976
|
+
return undefined;
|
|
41977
|
+
}
|
|
41978
|
+
const tcb = compiler.getTemplateTypeChecker().getTypeCheckBlock(templateInfo.component);
|
|
41979
|
+
if (tcb === null) {
|
|
41980
|
+
return undefined;
|
|
41981
|
+
}
|
|
41982
|
+
const sf = tcb.getSourceFile();
|
|
41983
|
+
let selections = [];
|
|
41984
|
+
const target = getTargetAtPosition(templateInfo.template, position);
|
|
41985
|
+
if (target !== null) {
|
|
41986
|
+
let selectionSpans;
|
|
41987
|
+
if ('nodes' in target.context) {
|
|
41988
|
+
selectionSpans = target.context.nodes.map(n => n.sourceSpan);
|
|
41989
|
+
}
|
|
41990
|
+
else {
|
|
41991
|
+
selectionSpans = [target.context.node.sourceSpan];
|
|
41992
|
+
}
|
|
41993
|
+
const selectionNodes = selectionSpans
|
|
41994
|
+
.map(s => findFirstMatchingNode(tcb, {
|
|
41995
|
+
withSpan: s,
|
|
41996
|
+
filter: (node) => true,
|
|
41997
|
+
}))
|
|
41998
|
+
.filter((n) => n !== null);
|
|
41999
|
+
selections = selectionNodes.map(n => {
|
|
42000
|
+
return {
|
|
42001
|
+
start: n.getStart(sf),
|
|
42002
|
+
length: n.getEnd() - n.getStart(sf),
|
|
42003
|
+
};
|
|
42004
|
+
});
|
|
42005
|
+
}
|
|
42006
|
+
return {
|
|
42007
|
+
fileName: sf.fileName,
|
|
42008
|
+
content: sf.getFullText(),
|
|
42009
|
+
selections,
|
|
42010
|
+
};
|
|
42011
|
+
});
|
|
42012
|
+
}
|
|
42013
|
+
withCompiler(p) {
|
|
42014
|
+
const compiler = this.compilerFactory.getOrCreate();
|
|
42015
|
+
const result = p(compiler);
|
|
42016
|
+
this.compilerFactory.registerLastKnownProgram();
|
|
42017
|
+
return result;
|
|
42018
|
+
}
|
|
41775
42019
|
getCompilerOptionsDiagnostics() {
|
|
41776
42020
|
const project = this.project;
|
|
41777
42021
|
if (!(project instanceof ts.server.ConfiguredProject)) {
|
|
@@ -41961,8 +42205,16 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41961
42205
|
return ngLS.getReferencesAtPosition(fileName, position);
|
|
41962
42206
|
}
|
|
41963
42207
|
function findRenameLocations(fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename) {
|
|
41964
|
-
//
|
|
41965
|
-
|
|
42208
|
+
// Most operations combine results from all extensions. However, rename locations are exclusive
|
|
42209
|
+
// (results from only one extension are used) so our rename locations are a superset of the TS
|
|
42210
|
+
// rename locations. As a result, we do not check the `angularOnly` flag here because we always
|
|
42211
|
+
// want to include results at TS locations as well as locations in templates.
|
|
42212
|
+
return ngLS.findRenameLocations(fileName, position);
|
|
42213
|
+
}
|
|
42214
|
+
function getRenameInfo(fileName, position) {
|
|
42215
|
+
// See the comment in `findRenameLocations` explaining why we don't check the `angularOnly`
|
|
42216
|
+
// flag.
|
|
42217
|
+
return ngLS.getRenameInfo(fileName, position);
|
|
41966
42218
|
}
|
|
41967
42219
|
function getCompletionsAtPosition(fileName, position, options) {
|
|
41968
42220
|
var _a;
|
|
@@ -42006,7 +42258,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
42006
42258
|
return diagnostics;
|
|
42007
42259
|
}
|
|
42008
42260
|
function getTcb(fileName, position) {
|
|
42009
|
-
return
|
|
42261
|
+
return ngLS.getTcb(fileName, position);
|
|
42010
42262
|
}
|
|
42011
42263
|
return Object.assign(Object.assign({}, tsLS), { getSemanticDiagnostics,
|
|
42012
42264
|
getTypeDefinitionAtPosition,
|
|
@@ -42014,11 +42266,12 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
42014
42266
|
getDefinitionAndBoundSpan,
|
|
42015
42267
|
getReferencesAtPosition,
|
|
42016
42268
|
findRenameLocations,
|
|
42269
|
+
getRenameInfo,
|
|
42017
42270
|
getCompletionsAtPosition,
|
|
42018
42271
|
getCompletionEntryDetails,
|
|
42019
42272
|
getCompletionEntrySymbol,
|
|
42020
|
-
|
|
42021
|
-
|
|
42273
|
+
getTcb,
|
|
42274
|
+
getCompilerOptionsDiagnostics });
|
|
42022
42275
|
}
|
|
42023
42276
|
function getExternalFiles(project) {
|
|
42024
42277
|
if (!project.hasRoots()) {
|