@angular/language-service 12.1.0-next.4 → 12.1.1
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 +737 -590
- package/bundles/language-service.js +180 -51
- package/package.json +1 -1
package/bundles/ivy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v12.1.
|
|
2
|
+
* @license Angular v12.1.1
|
|
3
3
|
* Copyright Google LLC All Rights Reserved.
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -5092,8 +5092,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
5092
5092
|
// There is a base factory variable so wrap its declaration along with the factory function into
|
|
5093
5093
|
// an IIFE.
|
|
5094
5094
|
factoryFn = fn([], [
|
|
5095
|
-
new DeclareVarStmt(baseFactoryVar.name),
|
|
5096
|
-
new ReturnStatement(factoryFn)
|
|
5095
|
+
new DeclareVarStmt(baseFactoryVar.name), new ReturnStatement(factoryFn)
|
|
5097
5096
|
]).callFn([], /* sourceSpan */ undefined, /* pure */ true);
|
|
5098
5097
|
}
|
|
5099
5098
|
return {
|
|
@@ -6530,19 +6529,29 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
6530
6529
|
}
|
|
6531
6530
|
}
|
|
6532
6531
|
class KeyedRead extends AST {
|
|
6533
|
-
constructor(span, sourceSpan,
|
|
6532
|
+
constructor(span, sourceSpan, receiver, key) {
|
|
6534
6533
|
super(span, sourceSpan);
|
|
6535
|
-
this.
|
|
6534
|
+
this.receiver = receiver;
|
|
6536
6535
|
this.key = key;
|
|
6537
6536
|
}
|
|
6538
6537
|
visit(visitor, context = null) {
|
|
6539
6538
|
return visitor.visitKeyedRead(this, context);
|
|
6540
6539
|
}
|
|
6541
6540
|
}
|
|
6541
|
+
class SafeKeyedRead extends AST {
|
|
6542
|
+
constructor(span, sourceSpan, receiver, key) {
|
|
6543
|
+
super(span, sourceSpan);
|
|
6544
|
+
this.receiver = receiver;
|
|
6545
|
+
this.key = key;
|
|
6546
|
+
}
|
|
6547
|
+
visit(visitor, context = null) {
|
|
6548
|
+
return visitor.visitSafeKeyedRead(this, context);
|
|
6549
|
+
}
|
|
6550
|
+
}
|
|
6542
6551
|
class KeyedWrite extends AST {
|
|
6543
|
-
constructor(span, sourceSpan,
|
|
6552
|
+
constructor(span, sourceSpan, receiver, key, value) {
|
|
6544
6553
|
super(span, sourceSpan);
|
|
6545
|
-
this.
|
|
6554
|
+
this.receiver = receiver;
|
|
6546
6555
|
this.key = key;
|
|
6547
6556
|
this.value = value;
|
|
6548
6557
|
}
|
|
@@ -6791,11 +6800,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
6791
6800
|
this.visitAll(ast.expressions, context);
|
|
6792
6801
|
}
|
|
6793
6802
|
visitKeyedRead(ast, context) {
|
|
6794
|
-
this.visit(ast.
|
|
6803
|
+
this.visit(ast.receiver, context);
|
|
6795
6804
|
this.visit(ast.key, context);
|
|
6796
6805
|
}
|
|
6797
6806
|
visitKeyedWrite(ast, context) {
|
|
6798
|
-
this.visit(ast.
|
|
6807
|
+
this.visit(ast.receiver, context);
|
|
6799
6808
|
this.visit(ast.key, context);
|
|
6800
6809
|
this.visit(ast.value, context);
|
|
6801
6810
|
}
|
|
@@ -6830,6 +6839,10 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
6830
6839
|
this.visit(ast.receiver, context);
|
|
6831
6840
|
this.visitAll(ast.args, context);
|
|
6832
6841
|
}
|
|
6842
|
+
visitSafeKeyedRead(ast, context) {
|
|
6843
|
+
this.visit(ast.receiver, context);
|
|
6844
|
+
this.visit(ast.key, context);
|
|
6845
|
+
}
|
|
6833
6846
|
visitQuote(ast, context) { }
|
|
6834
6847
|
// This is not part of the AstVisitor interface, just a helper method
|
|
6835
6848
|
visitAll(asts, context) {
|
|
@@ -6901,10 +6914,10 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
6901
6914
|
return new BindingPipe(ast.span, ast.sourceSpan, ast.exp.visit(this), ast.name, this.visitAll(ast.args), ast.nameSpan);
|
|
6902
6915
|
}
|
|
6903
6916
|
visitKeyedRead(ast, context) {
|
|
6904
|
-
return new KeyedRead(ast.span, ast.sourceSpan, ast.
|
|
6917
|
+
return new KeyedRead(ast.span, ast.sourceSpan, ast.receiver.visit(this), ast.key.visit(this));
|
|
6905
6918
|
}
|
|
6906
6919
|
visitKeyedWrite(ast, context) {
|
|
6907
|
-
return new KeyedWrite(ast.span, ast.sourceSpan, ast.
|
|
6920
|
+
return new KeyedWrite(ast.span, ast.sourceSpan, ast.receiver.visit(this), ast.key.visit(this), ast.value.visit(this));
|
|
6908
6921
|
}
|
|
6909
6922
|
visitAll(asts) {
|
|
6910
6923
|
const res = [];
|
|
@@ -6919,6 +6932,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
6919
6932
|
visitQuote(ast, context) {
|
|
6920
6933
|
return new Quote(ast.span, ast.sourceSpan, ast.prefix, ast.uninterpretedExpression, ast.location);
|
|
6921
6934
|
}
|
|
6935
|
+
visitSafeKeyedRead(ast, context) {
|
|
6936
|
+
return new SafeKeyedRead(ast.span, ast.sourceSpan, ast.receiver.visit(this), ast.key.visit(this));
|
|
6937
|
+
}
|
|
6922
6938
|
}
|
|
6923
6939
|
// A transformer that only creates new nodes if the transformer makes a change or
|
|
6924
6940
|
// a change is made a child node.
|
|
@@ -7052,18 +7068,18 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
7052
7068
|
return ast;
|
|
7053
7069
|
}
|
|
7054
7070
|
visitKeyedRead(ast, context) {
|
|
7055
|
-
const obj = ast.
|
|
7071
|
+
const obj = ast.receiver.visit(this);
|
|
7056
7072
|
const key = ast.key.visit(this);
|
|
7057
|
-
if (obj !== ast.
|
|
7073
|
+
if (obj !== ast.receiver || key !== ast.key) {
|
|
7058
7074
|
return new KeyedRead(ast.span, ast.sourceSpan, obj, key);
|
|
7059
7075
|
}
|
|
7060
7076
|
return ast;
|
|
7061
7077
|
}
|
|
7062
7078
|
visitKeyedWrite(ast, context) {
|
|
7063
|
-
const obj = ast.
|
|
7079
|
+
const obj = ast.receiver.visit(this);
|
|
7064
7080
|
const key = ast.key.visit(this);
|
|
7065
7081
|
const value = ast.value.visit(this);
|
|
7066
|
-
if (obj !== ast.
|
|
7082
|
+
if (obj !== ast.receiver || key !== ast.key || value !== ast.value) {
|
|
7067
7083
|
return new KeyedWrite(ast.span, ast.sourceSpan, obj, key, value);
|
|
7068
7084
|
}
|
|
7069
7085
|
return ast;
|
|
@@ -7089,6 +7105,14 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
7089
7105
|
visitQuote(ast, context) {
|
|
7090
7106
|
return ast;
|
|
7091
7107
|
}
|
|
7108
|
+
visitSafeKeyedRead(ast, context) {
|
|
7109
|
+
const obj = ast.receiver.visit(this);
|
|
7110
|
+
const key = ast.key.visit(this);
|
|
7111
|
+
if (obj !== ast.receiver || key !== ast.key) {
|
|
7112
|
+
return new SafeKeyedRead(ast.span, ast.sourceSpan, obj, key);
|
|
7113
|
+
}
|
|
7114
|
+
return ast;
|
|
7115
|
+
}
|
|
7092
7116
|
}
|
|
7093
7117
|
// Bindings
|
|
7094
7118
|
class ParsedProperty {
|
|
@@ -7647,13 +7671,16 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
7647
7671
|
return this.convertSafeAccess(ast, leftMostSafe, mode);
|
|
7648
7672
|
}
|
|
7649
7673
|
else {
|
|
7650
|
-
return convertToStatementIfNeeded(mode, this._visit(ast.
|
|
7674
|
+
return convertToStatementIfNeeded(mode, this._visit(ast.receiver, _Mode.Expression).key(this._visit(ast.key, _Mode.Expression)));
|
|
7651
7675
|
}
|
|
7652
7676
|
}
|
|
7653
7677
|
visitKeyedWrite(ast, mode) {
|
|
7654
|
-
const obj = this._visit(ast.
|
|
7678
|
+
const obj = this._visit(ast.receiver, _Mode.Expression);
|
|
7655
7679
|
const key = this._visit(ast.key, _Mode.Expression);
|
|
7656
7680
|
const value = this._visit(ast.value, _Mode.Expression);
|
|
7681
|
+
if (obj === this._implicitReceiver) {
|
|
7682
|
+
this._localResolver.maybeRestoreView(0, false);
|
|
7683
|
+
}
|
|
7657
7684
|
return convertToStatementIfNeeded(mode, obj.key(key).set(value));
|
|
7658
7685
|
}
|
|
7659
7686
|
visitLiteralArray(ast, mode) {
|
|
@@ -7779,6 +7806,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
7779
7806
|
visitSafeMethodCall(ast, mode) {
|
|
7780
7807
|
return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);
|
|
7781
7808
|
}
|
|
7809
|
+
visitSafeKeyedRead(ast, mode) {
|
|
7810
|
+
return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);
|
|
7811
|
+
}
|
|
7782
7812
|
visitAll(asts, mode) {
|
|
7783
7813
|
return asts.map(ast => this._visit(ast, mode));
|
|
7784
7814
|
}
|
|
@@ -7845,6 +7875,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
7845
7875
|
if (leftMostSafe instanceof SafeMethodCall) {
|
|
7846
7876
|
this._nodeMap.set(leftMostSafe, new MethodCall(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.nameSpan, leftMostSafe.receiver, leftMostSafe.name, leftMostSafe.args, leftMostSafe.argumentSpan));
|
|
7847
7877
|
}
|
|
7878
|
+
else if (leftMostSafe instanceof SafeKeyedRead) {
|
|
7879
|
+
this._nodeMap.set(leftMostSafe, new KeyedRead(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.receiver, leftMostSafe.key));
|
|
7880
|
+
}
|
|
7848
7881
|
else {
|
|
7849
7882
|
this._nodeMap.set(leftMostSafe, new PropertyRead(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.nameSpan, leftMostSafe.receiver, leftMostSafe.name));
|
|
7850
7883
|
}
|
|
@@ -7911,7 +7944,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
7911
7944
|
return null;
|
|
7912
7945
|
},
|
|
7913
7946
|
visitKeyedRead(ast) {
|
|
7914
|
-
return visit(this, ast.
|
|
7947
|
+
return visit(this, ast.receiver);
|
|
7915
7948
|
},
|
|
7916
7949
|
visitKeyedWrite(ast) {
|
|
7917
7950
|
return null;
|
|
@@ -7951,6 +7984,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
7951
7984
|
},
|
|
7952
7985
|
visitSafePropertyRead(ast) {
|
|
7953
7986
|
return visit(this, ast.receiver) || ast;
|
|
7987
|
+
},
|
|
7988
|
+
visitSafeKeyedRead(ast) {
|
|
7989
|
+
return visit(this, ast.receiver) || ast;
|
|
7954
7990
|
}
|
|
7955
7991
|
});
|
|
7956
7992
|
}
|
|
@@ -8030,6 +8066,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
8030
8066
|
},
|
|
8031
8067
|
visitSafePropertyRead(ast) {
|
|
8032
8068
|
return false;
|
|
8069
|
+
},
|
|
8070
|
+
visitSafeKeyedRead(ast) {
|
|
8071
|
+
return false;
|
|
8033
8072
|
}
|
|
8034
8073
|
});
|
|
8035
8074
|
}
|
|
@@ -8086,6 +8125,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
8086
8125
|
this.globals = globals;
|
|
8087
8126
|
}
|
|
8088
8127
|
notifyImplicitReceiverUse() { }
|
|
8128
|
+
maybeRestoreView() { }
|
|
8089
8129
|
getLocal(name) {
|
|
8090
8130
|
if (name === EventHandlerVars.event.name) {
|
|
8091
8131
|
return EventHandlerVars.event;
|
|
@@ -9544,10 +9584,13 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
9544
9584
|
parts.push(this._readChar(true));
|
|
9545
9585
|
}
|
|
9546
9586
|
} while (!this._isTextEnd());
|
|
9587
|
+
// It is possible that an interpolation was started but not ended inside this text token.
|
|
9588
|
+
// Make sure that we reset the state of the lexer correctly.
|
|
9589
|
+
this._inInterpolation = false;
|
|
9547
9590
|
this._endToken([this._processCarriageReturns(parts.join(''))]);
|
|
9548
9591
|
}
|
|
9549
9592
|
_isTextEnd() {
|
|
9550
|
-
if (this.
|
|
9593
|
+
if (this._isTagStart() || this._cursor.peek() === $EOF) {
|
|
9551
9594
|
return true;
|
|
9552
9595
|
}
|
|
9553
9596
|
if (this._tokenizeIcu && !this._inInterpolation) {
|
|
@@ -9562,6 +9605,24 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
9562
9605
|
}
|
|
9563
9606
|
return false;
|
|
9564
9607
|
}
|
|
9608
|
+
/**
|
|
9609
|
+
* Returns true if the current cursor is pointing to the start of a tag
|
|
9610
|
+
* (opening/closing/comments/cdata/etc).
|
|
9611
|
+
*/
|
|
9612
|
+
_isTagStart() {
|
|
9613
|
+
if (this._cursor.peek() === $LT) {
|
|
9614
|
+
// We assume that `<` followed by whitespace is not the start of an HTML element.
|
|
9615
|
+
const tmp = this._cursor.clone();
|
|
9616
|
+
tmp.advance();
|
|
9617
|
+
// If the next character is alphabetic, ! nor / then it is a tag start
|
|
9618
|
+
const code = tmp.peek();
|
|
9619
|
+
if (($a <= code && code <= $z) || ($A <= code && code <= $Z) ||
|
|
9620
|
+
code === $SLASH || code === $BANG) {
|
|
9621
|
+
return true;
|
|
9622
|
+
}
|
|
9623
|
+
}
|
|
9624
|
+
return false;
|
|
9625
|
+
}
|
|
9565
9626
|
_readUntil(char) {
|
|
9566
9627
|
const start = this._cursor.clone();
|
|
9567
9628
|
this._attemptUntilChar(char);
|
|
@@ -10134,6 +10195,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
10134
10195
|
* opening tag is recovered).
|
|
10135
10196
|
*/
|
|
10136
10197
|
_popElement(fullName, endSourceSpan) {
|
|
10198
|
+
let unexpectedCloseTagDetected = false;
|
|
10137
10199
|
for (let stackIndex = this._elementStack.length - 1; stackIndex >= 0; stackIndex--) {
|
|
10138
10200
|
const el = this._elementStack[stackIndex];
|
|
10139
10201
|
if (el.name == fullName) {
|
|
@@ -10143,10 +10205,13 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
10143
10205
|
el.endSourceSpan = endSourceSpan;
|
|
10144
10206
|
el.sourceSpan.end = endSourceSpan !== null ? endSourceSpan.end : el.sourceSpan.end;
|
|
10145
10207
|
this._elementStack.splice(stackIndex, this._elementStack.length - stackIndex);
|
|
10146
|
-
return
|
|
10208
|
+
return !unexpectedCloseTagDetected;
|
|
10147
10209
|
}
|
|
10148
10210
|
if (!this.getTagDefinition(el.name).closedByParent) {
|
|
10149
|
-
|
|
10211
|
+
// Note that we encountered an unexpected close tag but continue processing the element
|
|
10212
|
+
// stack so we can assign an `endSourceSpan` if there is a corresponding start tag for this
|
|
10213
|
+
// end tag in the stack.
|
|
10214
|
+
unexpectedCloseTagDetected = true;
|
|
10150
10215
|
}
|
|
10151
10216
|
}
|
|
10152
10217
|
return false;
|
|
@@ -12658,25 +12723,12 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
12658
12723
|
result = this.parseAccessMemberOrMethodCall(result, start, false);
|
|
12659
12724
|
}
|
|
12660
12725
|
else if (this.consumeOptionalOperator('?.')) {
|
|
12661
|
-
result = this.
|
|
12726
|
+
result = this.consumeOptionalCharacter($LBRACKET) ?
|
|
12727
|
+
this.parseKeyedReadOrWrite(result, start, true) :
|
|
12728
|
+
this.parseAccessMemberOrMethodCall(result, start, true);
|
|
12662
12729
|
}
|
|
12663
12730
|
else if (this.consumeOptionalCharacter($LBRACKET)) {
|
|
12664
|
-
this.
|
|
12665
|
-
this.rbracketsExpected++;
|
|
12666
|
-
const key = this.parsePipe();
|
|
12667
|
-
if (key instanceof EmptyExpr) {
|
|
12668
|
-
this.error(`Key access cannot be empty`);
|
|
12669
|
-
}
|
|
12670
|
-
this.rbracketsExpected--;
|
|
12671
|
-
this.expectCharacter($RBRACKET);
|
|
12672
|
-
if (this.consumeOptionalOperator('=')) {
|
|
12673
|
-
const value = this.parseConditional();
|
|
12674
|
-
result = new KeyedWrite(this.span(start), this.sourceSpan(start), result, key, value);
|
|
12675
|
-
}
|
|
12676
|
-
else {
|
|
12677
|
-
result = new KeyedRead(this.span(start), this.sourceSpan(start), result, key);
|
|
12678
|
-
}
|
|
12679
|
-
});
|
|
12731
|
+
result = this.parseKeyedReadOrWrite(result, start, false);
|
|
12680
12732
|
}
|
|
12681
12733
|
else if (this.consumeOptionalCharacter($LPAREN)) {
|
|
12682
12734
|
this.rparensExpected++;
|
|
@@ -12778,18 +12830,30 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
12778
12830
|
if (!this.consumeOptionalCharacter($RBRACE)) {
|
|
12779
12831
|
this.rbracesExpected++;
|
|
12780
12832
|
do {
|
|
12833
|
+
const keyStart = this.inputIndex;
|
|
12781
12834
|
const quoted = this.next.isString();
|
|
12782
12835
|
const key = this.expectIdentifierOrKeywordOrString();
|
|
12783
12836
|
keys.push({ key, quoted });
|
|
12784
|
-
|
|
12785
|
-
|
|
12837
|
+
// Properties with quoted keys can't use the shorthand syntax.
|
|
12838
|
+
if (quoted) {
|
|
12839
|
+
this.expectCharacter($COLON);
|
|
12840
|
+
values.push(this.parsePipe());
|
|
12841
|
+
}
|
|
12842
|
+
else if (this.consumeOptionalCharacter($COLON)) {
|
|
12843
|
+
values.push(this.parsePipe());
|
|
12844
|
+
}
|
|
12845
|
+
else {
|
|
12846
|
+
const span = this.span(keyStart);
|
|
12847
|
+
const sourceSpan = this.sourceSpan(keyStart);
|
|
12848
|
+
values.push(new PropertyRead(span, sourceSpan, sourceSpan, new ImplicitReceiver(span, sourceSpan), key));
|
|
12849
|
+
}
|
|
12786
12850
|
} while (this.consumeOptionalCharacter($COMMA));
|
|
12787
12851
|
this.rbracesExpected--;
|
|
12788
12852
|
this.expectCharacter($RBRACE);
|
|
12789
12853
|
}
|
|
12790
12854
|
return new LiteralMap(this.span(start), this.sourceSpan(start), keys, values);
|
|
12791
12855
|
}
|
|
12792
|
-
parseAccessMemberOrMethodCall(receiver, start, isSafe
|
|
12856
|
+
parseAccessMemberOrMethodCall(receiver, start, isSafe) {
|
|
12793
12857
|
const nameStart = this.inputIndex;
|
|
12794
12858
|
const id = this.withContext(ParseContextFlags.Writable, () => {
|
|
12795
12859
|
var _a;
|
|
@@ -12924,6 +12988,31 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
12924
12988
|
}
|
|
12925
12989
|
return new TemplateBindingParseResult(bindings, [] /* warnings */, this.errors);
|
|
12926
12990
|
}
|
|
12991
|
+
parseKeyedReadOrWrite(receiver, start, isSafe) {
|
|
12992
|
+
return this.withContext(ParseContextFlags.Writable, () => {
|
|
12993
|
+
this.rbracketsExpected++;
|
|
12994
|
+
const key = this.parsePipe();
|
|
12995
|
+
if (key instanceof EmptyExpr) {
|
|
12996
|
+
this.error(`Key access cannot be empty`);
|
|
12997
|
+
}
|
|
12998
|
+
this.rbracketsExpected--;
|
|
12999
|
+
this.expectCharacter($RBRACKET);
|
|
13000
|
+
if (this.consumeOptionalOperator('=')) {
|
|
13001
|
+
if (isSafe) {
|
|
13002
|
+
this.error('The \'?.\' operator cannot be used in the assignment');
|
|
13003
|
+
}
|
|
13004
|
+
else {
|
|
13005
|
+
const value = this.parseConditional();
|
|
13006
|
+
return new KeyedWrite(this.span(start), this.sourceSpan(start), receiver, key, value);
|
|
13007
|
+
}
|
|
13008
|
+
}
|
|
13009
|
+
else {
|
|
13010
|
+
return isSafe ? new SafeKeyedRead(this.span(start), this.sourceSpan(start), receiver, key) :
|
|
13011
|
+
new KeyedRead(this.span(start), this.sourceSpan(start), receiver, key);
|
|
13012
|
+
}
|
|
13013
|
+
return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
|
13014
|
+
});
|
|
13015
|
+
}
|
|
12927
13016
|
/**
|
|
12928
13017
|
* Parse a directive keyword, followed by a mandatory expression.
|
|
12929
13018
|
* For example, "of items", "trackBy: func".
|
|
@@ -13131,6 +13220,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
13131
13220
|
}
|
|
13132
13221
|
visitChain(ast, context) { }
|
|
13133
13222
|
visitQuote(ast, context) { }
|
|
13223
|
+
visitSafeKeyedRead(ast, context) { }
|
|
13134
13224
|
}
|
|
13135
13225
|
/**
|
|
13136
13226
|
* This class implements SimpleExpressionChecker used in View Engine and performs more strict checks
|
|
@@ -15319,6 +15409,10 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
15319
15409
|
notifyImplicitReceiverUse() {
|
|
15320
15410
|
this._bindingScope.notifyImplicitReceiverUse();
|
|
15321
15411
|
}
|
|
15412
|
+
// LocalResolver
|
|
15413
|
+
maybeRestoreView(retrievalLevel, localRefLookup) {
|
|
15414
|
+
this._bindingScope.maybeRestoreView(retrievalLevel, localRefLookup);
|
|
15415
|
+
}
|
|
15322
15416
|
i18nTranslate(message, params = {}, ref, transformFn) {
|
|
15323
15417
|
const _ref = ref || this.i18nGenerateMainBlockVar();
|
|
15324
15418
|
// Closure Compiler requires const names to start with `MSG_` but disallows any other const to
|
|
@@ -17959,7 +18053,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
17959
18053
|
* Use of this source code is governed by an MIT-style license that can be
|
|
17960
18054
|
* found in the LICENSE file at https://angular.io/license
|
|
17961
18055
|
*/
|
|
17962
|
-
const VERSION$1 = new Version('12.1.
|
|
18056
|
+
const VERSION$1 = new Version('12.1.1');
|
|
17963
18057
|
|
|
17964
18058
|
/**
|
|
17965
18059
|
* @license
|
|
@@ -18598,7 +18692,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
18598
18692
|
function compileDeclareClassMetadata(metadata) {
|
|
18599
18693
|
const definitionMap = new DefinitionMap();
|
|
18600
18694
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
18601
|
-
definitionMap.set('version', literal('12.1.
|
|
18695
|
+
definitionMap.set('version', literal('12.1.1'));
|
|
18602
18696
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
18603
18697
|
definitionMap.set('type', metadata.type);
|
|
18604
18698
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -18638,7 +18732,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
18638
18732
|
function createDirectiveDefinitionMap(meta) {
|
|
18639
18733
|
const definitionMap = new DefinitionMap();
|
|
18640
18734
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
18641
|
-
definitionMap.set('version', literal('12.1.
|
|
18735
|
+
definitionMap.set('version', literal('12.1.1'));
|
|
18642
18736
|
// e.g. `type: MyDirective`
|
|
18643
18737
|
definitionMap.set('type', meta.internalType);
|
|
18644
18738
|
// e.g. `selector: 'some-dir'`
|
|
@@ -18855,7 +18949,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
18855
18949
|
function compileDeclareFactoryFunction(meta) {
|
|
18856
18950
|
const definitionMap = new DefinitionMap();
|
|
18857
18951
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
18858
|
-
definitionMap.set('version', literal('12.1.
|
|
18952
|
+
definitionMap.set('version', literal('12.1.1'));
|
|
18859
18953
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
18860
18954
|
definitionMap.set('type', meta.internalType);
|
|
18861
18955
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -18897,7 +18991,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
18897
18991
|
function createInjectableDefinitionMap(meta) {
|
|
18898
18992
|
const definitionMap = new DefinitionMap();
|
|
18899
18993
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
18900
|
-
definitionMap.set('version', literal('12.1.
|
|
18994
|
+
definitionMap.set('version', literal('12.1.1'));
|
|
18901
18995
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
18902
18996
|
definitionMap.set('type', meta.internalType);
|
|
18903
18997
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -18976,7 +19070,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
18976
19070
|
function createInjectorDefinitionMap(meta) {
|
|
18977
19071
|
const definitionMap = new DefinitionMap();
|
|
18978
19072
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
18979
|
-
definitionMap.set('version', literal('12.1.
|
|
19073
|
+
definitionMap.set('version', literal('12.1.1'));
|
|
18980
19074
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
18981
19075
|
definitionMap.set('type', meta.internalType);
|
|
18982
19076
|
definitionMap.set('providers', meta.providers);
|
|
@@ -19013,7 +19107,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
19013
19107
|
function createNgModuleDefinitionMap(meta) {
|
|
19014
19108
|
const definitionMap = new DefinitionMap();
|
|
19015
19109
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
|
|
19016
|
-
definitionMap.set('version', literal('12.1.
|
|
19110
|
+
definitionMap.set('version', literal('12.1.1'));
|
|
19017
19111
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
19018
19112
|
definitionMap.set('type', meta.internalType);
|
|
19019
19113
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -19071,7 +19165,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
19071
19165
|
function createPipeDefinitionMap(meta) {
|
|
19072
19166
|
const definitionMap = new DefinitionMap();
|
|
19073
19167
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
19074
|
-
definitionMap.set('version', literal('12.1.
|
|
19168
|
+
definitionMap.set('version', literal('12.1.1'));
|
|
19075
19169
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
19076
19170
|
// e.g. `type: MyPipe`
|
|
19077
19171
|
definitionMap.set('type', meta.internalType);
|
|
@@ -19103,7 +19197,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
19103
19197
|
* Use of this source code is governed by an MIT-style license that can be
|
|
19104
19198
|
* found in the LICENSE file at https://angular.io/license
|
|
19105
19199
|
*/
|
|
19106
|
-
const VERSION$2 = new Version('12.1.
|
|
19200
|
+
const VERSION$2 = new Version('12.1.1');
|
|
19107
19201
|
|
|
19108
19202
|
/**
|
|
19109
19203
|
* @license
|
|
@@ -19204,6 +19298,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
19204
19298
|
* sheet.
|
|
19205
19299
|
*/
|
|
19206
19300
|
ErrorCode[ErrorCode["COMPONENT_RESOURCE_NOT_FOUND"] = 2008] = "COMPONENT_RESOURCE_NOT_FOUND";
|
|
19301
|
+
/**
|
|
19302
|
+
* Raised when a component uses `ShadowDom` view encapsulation, but its selector
|
|
19303
|
+
* does not match the shadow DOM tag name requirements.
|
|
19304
|
+
*/
|
|
19305
|
+
ErrorCode[ErrorCode["COMPONENT_INVALID_SHADOW_DOM_SELECTOR"] = 2009] = "COMPONENT_INVALID_SHADOW_DOM_SELECTOR";
|
|
19207
19306
|
ErrorCode[ErrorCode["SYMBOL_NOT_EXPORTED"] = 3001] = "SYMBOL_NOT_EXPORTED";
|
|
19208
19307
|
ErrorCode[ErrorCode["SYMBOL_EXPORTED_UNDER_DIFFERENT_NAME"] = 3002] = "SYMBOL_EXPORTED_UNDER_DIFFERENT_NAME";
|
|
19209
19308
|
/**
|
|
@@ -19344,6 +19443,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
19344
19443
|
ErrorCode.SCHEMA_INVALID_ELEMENT,
|
|
19345
19444
|
ErrorCode.SCHEMA_INVALID_ATTRIBUTE,
|
|
19346
19445
|
ErrorCode.MISSING_REFERENCE_TARGET,
|
|
19446
|
+
ErrorCode.COMPONENT_INVALID_SHADOW_DOM_SELECTOR,
|
|
19347
19447
|
]);
|
|
19348
19448
|
/**
|
|
19349
19449
|
* @internal
|
|
@@ -19406,6 +19506,13 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
19406
19506
|
* found in the LICENSE file at https://angular.io/license
|
|
19407
19507
|
*/
|
|
19408
19508
|
const D_TS = /\.d\.ts$/i;
|
|
19509
|
+
function isSymbolWithValueDeclaration(symbol) {
|
|
19510
|
+
// If there is a value declaration set, then the `declarations` property is never undefined. We
|
|
19511
|
+
// still check for the property to exist as this matches with the type that `symbol` is narrowed
|
|
19512
|
+
// to.
|
|
19513
|
+
return symbol != null && symbol.valueDeclaration !== undefined &&
|
|
19514
|
+
symbol.declarations !== undefined;
|
|
19515
|
+
}
|
|
19409
19516
|
function isDtsPath(filePath) {
|
|
19410
19517
|
return D_TS.test(filePath);
|
|
19411
19518
|
}
|
|
@@ -21272,7 +21379,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
21272
21379
|
return null;
|
|
21273
21380
|
}
|
|
21274
21381
|
const namespaceSymbol = this.checker.getSymbolAtLocation(namespaceIdentifier);
|
|
21275
|
-
if (!namespaceSymbol) {
|
|
21382
|
+
if (!namespaceSymbol || namespaceSymbol.declarations === undefined) {
|
|
21276
21383
|
return null;
|
|
21277
21384
|
}
|
|
21278
21385
|
const declaration = namespaceSymbol.declarations.length === 1 ? namespaceSymbol.declarations[0] : null;
|
|
@@ -22360,8 +22467,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
22360
22467
|
static fromComplexFunctionCall(node, fn) {
|
|
22361
22468
|
return new DynamicValue(node, fn, 6 /* COMPLEX_FUNCTION_CALL */);
|
|
22362
22469
|
}
|
|
22470
|
+
static fromDynamicType(node) {
|
|
22471
|
+
return new DynamicValue(node, undefined, 7 /* DYNAMIC_TYPE */);
|
|
22472
|
+
}
|
|
22363
22473
|
static fromUnknown(node) {
|
|
22364
|
-
return new DynamicValue(node, undefined,
|
|
22474
|
+
return new DynamicValue(node, undefined, 8 /* UNKNOWN */);
|
|
22365
22475
|
}
|
|
22366
22476
|
isFromDynamicInput() {
|
|
22367
22477
|
return this.code === 0 /* DYNAMIC_INPUT */;
|
|
@@ -22384,8 +22494,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
22384
22494
|
isFromComplexFunctionCall() {
|
|
22385
22495
|
return this.code === 6 /* COMPLEX_FUNCTION_CALL */;
|
|
22386
22496
|
}
|
|
22497
|
+
isFromDynamicType() {
|
|
22498
|
+
return this.code === 7 /* DYNAMIC_TYPE */;
|
|
22499
|
+
}
|
|
22387
22500
|
isFromUnknown() {
|
|
22388
|
-
return this.code ===
|
|
22501
|
+
return this.code === 8 /* UNKNOWN */;
|
|
22389
22502
|
}
|
|
22390
22503
|
accept(visitor) {
|
|
22391
22504
|
switch (this.code) {
|
|
@@ -22403,7 +22516,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
22403
22516
|
return visitor.visitInvalidExpressionType(this);
|
|
22404
22517
|
case 6 /* COMPLEX_FUNCTION_CALL */:
|
|
22405
22518
|
return visitor.visitComplexFunctionCall(this);
|
|
22406
|
-
case 7 /*
|
|
22519
|
+
case 7 /* DYNAMIC_TYPE */:
|
|
22520
|
+
return visitor.visitDynamicType(this);
|
|
22521
|
+
case 8 /* UNKNOWN */:
|
|
22407
22522
|
return visitor.visitUnknown(this);
|
|
22408
22523
|
}
|
|
22409
22524
|
}
|
|
@@ -22571,6 +22686,9 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
22571
22686
|
visitUnknownIdentifier(value) {
|
|
22572
22687
|
return [makeRelatedInformation(value.node, 'Unknown reference.')];
|
|
22573
22688
|
}
|
|
22689
|
+
visitDynamicType(value) {
|
|
22690
|
+
return [makeRelatedInformation(value.node, 'Dynamic type.')];
|
|
22691
|
+
}
|
|
22574
22692
|
visitUnsupportedSyntax(value) {
|
|
22575
22693
|
return [makeRelatedInformation(value.node, 'This syntax is not supported.')];
|
|
22576
22694
|
}
|
|
@@ -23060,6 +23178,23 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
23060
23178
|
return this.visitExpression(value, context);
|
|
23061
23179
|
}
|
|
23062
23180
|
else if (isVariableDeclarationDeclared(node)) {
|
|
23181
|
+
// If the declaration has a literal type that can be statically reduced to a value, resolve to
|
|
23182
|
+
// that value. If not, the historical behavior for variable declarations is to return a
|
|
23183
|
+
// `Reference` to the variable, as the consumer could use it in a context where knowing its
|
|
23184
|
+
// static value is not necessary.
|
|
23185
|
+
//
|
|
23186
|
+
// Arguably, since the value cannot be statically determined, we should return a
|
|
23187
|
+
// `DynamicValue`. This returns a `Reference` because it's the same behavior as before
|
|
23188
|
+
// `visitType` was introduced.
|
|
23189
|
+
//
|
|
23190
|
+
// TODO(zarend): investigate switching to a `DynamicValue` and verify this won't break any
|
|
23191
|
+
// use cases, especially in ngcc
|
|
23192
|
+
if (node.type !== undefined) {
|
|
23193
|
+
const evaluatedType = this.visitType(node.type, context);
|
|
23194
|
+
if (!(evaluatedType instanceof DynamicValue)) {
|
|
23195
|
+
return evaluatedType;
|
|
23196
|
+
}
|
|
23197
|
+
}
|
|
23063
23198
|
return this.getReference(node, context);
|
|
23064
23199
|
}
|
|
23065
23200
|
else {
|
|
@@ -23417,6 +23552,25 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
23417
23552
|
getReference(node, context) {
|
|
23418
23553
|
return new Reference$1(node, owningModule(context));
|
|
23419
23554
|
}
|
|
23555
|
+
visitType(node, context) {
|
|
23556
|
+
if (ts$1.isLiteralTypeNode(node)) {
|
|
23557
|
+
return this.visitExpression(node.literal, context);
|
|
23558
|
+
}
|
|
23559
|
+
else if (ts$1.isTupleTypeNode(node)) {
|
|
23560
|
+
return this.visitTupleType(node, context);
|
|
23561
|
+
}
|
|
23562
|
+
else if (ts$1.isNamedTupleMember(node)) {
|
|
23563
|
+
return this.visitType(node.type, context);
|
|
23564
|
+
}
|
|
23565
|
+
return DynamicValue.fromDynamicType(node);
|
|
23566
|
+
}
|
|
23567
|
+
visitTupleType(node, context) {
|
|
23568
|
+
const res = [];
|
|
23569
|
+
for (const elem of node.elements) {
|
|
23570
|
+
res.push(this.visitType(elem, context));
|
|
23571
|
+
}
|
|
23572
|
+
return res;
|
|
23573
|
+
}
|
|
23420
23574
|
}
|
|
23421
23575
|
function isFunctionOrMethodReference(ref) {
|
|
23422
23576
|
return ts$1.isFunctionDeclaration(ref.node) || ts$1.isMethodDeclaration(ref.node) ||
|
|
@@ -24200,6 +24354,17 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
24200
24354
|
}
|
|
24201
24355
|
return records;
|
|
24202
24356
|
}
|
|
24357
|
+
getAnalyzedRecords() {
|
|
24358
|
+
const result = new Map();
|
|
24359
|
+
for (const [sf, classes] of this.fileToClasses) {
|
|
24360
|
+
const records = [];
|
|
24361
|
+
for (const clazz of classes) {
|
|
24362
|
+
records.push(this.classes.get(clazz));
|
|
24363
|
+
}
|
|
24364
|
+
result.set(sf, records);
|
|
24365
|
+
}
|
|
24366
|
+
return result;
|
|
24367
|
+
}
|
|
24203
24368
|
/**
|
|
24204
24369
|
* Import a `ClassRecord` from a previous compilation.
|
|
24205
24370
|
*
|
|
@@ -24481,6 +24646,24 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
24481
24646
|
}
|
|
24482
24647
|
}
|
|
24483
24648
|
}
|
|
24649
|
+
xi18n(bundle) {
|
|
24650
|
+
for (const clazz of this.classes.keys()) {
|
|
24651
|
+
const record = this.classes.get(clazz);
|
|
24652
|
+
for (const trait of record.traits) {
|
|
24653
|
+
if (trait.state !== TraitState.Analyzed && trait.state !== TraitState.Resolved) {
|
|
24654
|
+
// Skip traits that haven't been analyzed successfully.
|
|
24655
|
+
continue;
|
|
24656
|
+
}
|
|
24657
|
+
else if (trait.handler.xi18n === undefined) {
|
|
24658
|
+
// Skip traits that don't support xi18n.
|
|
24659
|
+
continue;
|
|
24660
|
+
}
|
|
24661
|
+
if (trait.analysis !== null) {
|
|
24662
|
+
trait.handler.xi18n(bundle, clazz, trait.analysis);
|
|
24663
|
+
}
|
|
24664
|
+
}
|
|
24665
|
+
}
|
|
24666
|
+
}
|
|
24484
24667
|
updateResources(clazz) {
|
|
24485
24668
|
if (!this.reflector.isClass(clazz) || !this.classes.has(clazz)) {
|
|
24486
24669
|
return;
|
|
@@ -25460,7 +25643,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
25460
25643
|
class DtsTransformRegistry {
|
|
25461
25644
|
constructor() {
|
|
25462
25645
|
this.ivyDeclarationTransforms = new Map();
|
|
25463
|
-
this.returnTypeTransforms = new Map();
|
|
25464
25646
|
}
|
|
25465
25647
|
getIvyDeclarationTransform(sf) {
|
|
25466
25648
|
if (!this.ivyDeclarationTransforms.has(sf)) {
|
|
@@ -25468,12 +25650,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
25468
25650
|
}
|
|
25469
25651
|
return this.ivyDeclarationTransforms.get(sf);
|
|
25470
25652
|
}
|
|
25471
|
-
getReturnTypeTransform(sf) {
|
|
25472
|
-
if (!this.returnTypeTransforms.has(sf)) {
|
|
25473
|
-
this.returnTypeTransforms.set(sf, new ReturnTypeTransform());
|
|
25474
|
-
}
|
|
25475
|
-
return this.returnTypeTransforms.get(sf);
|
|
25476
|
-
}
|
|
25477
25653
|
/**
|
|
25478
25654
|
* Gets the dts transforms to be applied for the given source file, or `null` if no transform is
|
|
25479
25655
|
* necessary.
|
|
@@ -25492,10 +25668,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
25492
25668
|
transforms = [];
|
|
25493
25669
|
transforms.push(this.ivyDeclarationTransforms.get(originalSf));
|
|
25494
25670
|
}
|
|
25495
|
-
if (this.returnTypeTransforms.has(originalSf)) {
|
|
25496
|
-
transforms = transforms || [];
|
|
25497
|
-
transforms.push(this.returnTypeTransforms.get(originalSf));
|
|
25498
|
-
}
|
|
25499
25671
|
return transforms;
|
|
25500
25672
|
}
|
|
25501
25673
|
}
|
|
@@ -25635,44 +25807,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
|
|
|
25635
25807
|
ts$1.setEmitFlags(node, ts$1.EmitFlags.SingleLine);
|
|
25636
25808
|
ts$1.forEachChild(node, markForEmitAsSingleLine);
|
|
25637
25809
|
}
|
|
25638
|
-
class ReturnTypeTransform {
|
|
25639
|
-
constructor() {
|
|
25640
|
-
this.typeReplacements = new Map();
|
|
25641
|
-
}
|
|
25642
|
-
addTypeReplacement(declaration, type) {
|
|
25643
|
-
this.typeReplacements.set(declaration, type);
|
|
25644
|
-
}
|
|
25645
|
-
transformClassElement(element, imports) {
|
|
25646
|
-
if (ts$1.isMethodDeclaration(element)) {
|
|
25647
|
-
const original = ts$1.getOriginalNode(element, ts$1.isMethodDeclaration);
|
|
25648
|
-
if (!this.typeReplacements.has(original)) {
|
|
25649
|
-
return element;
|
|
25650
|
-
}
|
|
25651
|
-
const returnType = this.typeReplacements.get(original);
|
|
25652
|
-
const tsReturnType = translateType(returnType, imports);
|
|
25653
|
-
return ts$1.updateMethod(element, element.decorators, element.modifiers, element.asteriskToken, element.name, element.questionToken, element.typeParameters, element.parameters, tsReturnType, element.body);
|
|
25654
|
-
}
|
|
25655
|
-
return element;
|
|
25656
|
-
}
|
|
25657
|
-
transformFunctionDeclaration(element, imports) {
|
|
25658
|
-
const original = ts$1.getOriginalNode(element);
|
|
25659
|
-
if (!this.typeReplacements.has(original)) {
|
|
25660
|
-
return element;
|
|
25661
|
-
}
|
|
25662
|
-
const returnType = this.typeReplacements.get(original);
|
|
25663
|
-
const tsReturnType = translateType(returnType, imports);
|
|
25664
|
-
return ts$1.updateFunctionDeclaration(
|
|
25665
|
-
/* node */ element,
|
|
25666
|
-
/* decorators */ element.decorators,
|
|
25667
|
-
/* modifiers */ element.modifiers,
|
|
25668
|
-
/* asteriskToken */ element.asteriskToken,
|
|
25669
|
-
/* name */ element.name,
|
|
25670
|
-
/* typeParameters */ element.typeParameters,
|
|
25671
|
-
/* parameters */ element.parameters,
|
|
25672
|
-
/* type */ tsReturnType,
|
|
25673
|
-
/* body */ element.body);
|
|
25674
|
-
}
|
|
25675
|
-
}
|
|
25676
25810
|
|
|
25677
25811
|
/**
|
|
25678
25812
|
* @license
|
|
@@ -28283,7 +28417,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28283
28417
|
.then(() => undefined);
|
|
28284
28418
|
}
|
|
28285
28419
|
analyze(node, decorator, flags = HandlerFlags.NONE) {
|
|
28286
|
-
var _a;
|
|
28420
|
+
var _a, _b;
|
|
28287
28421
|
this.perf.eventCount(PerfEvent.AnalyzeComponent);
|
|
28288
28422
|
const containingFile = node.getSourceFile().fileName;
|
|
28289
28423
|
this.literalCache.delete(decorator);
|
|
@@ -28300,6 +28434,12 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28300
28434
|
}
|
|
28301
28435
|
// Next, read the `@Component`-specific fields.
|
|
28302
28436
|
const { decorator: component, metadata, inputs, outputs } = directiveResult;
|
|
28437
|
+
const encapsulation = (_a = this._resolveEnumValue(component, 'encapsulation', 'ViewEncapsulation')) !== null && _a !== void 0 ? _a : ViewEncapsulation.Emulated;
|
|
28438
|
+
const changeDetection = this._resolveEnumValue(component, 'changeDetection', 'ChangeDetectionStrategy');
|
|
28439
|
+
let animations = null;
|
|
28440
|
+
if (component.has('animations')) {
|
|
28441
|
+
animations = new WrappedNodeExpr(component.get('animations'));
|
|
28442
|
+
}
|
|
28303
28443
|
// Go through the root directories for this project, and select the one with the smallest
|
|
28304
28444
|
// relative path representation.
|
|
28305
28445
|
const relativeContextFilePath = this.rootDirs.reduce((previous, rootDir) => {
|
|
@@ -28364,7 +28504,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28364
28504
|
this.depTracker.addResourceDependency(node.getSourceFile(), absoluteFrom(resourceUrl));
|
|
28365
28505
|
}
|
|
28366
28506
|
}
|
|
28367
|
-
catch (
|
|
28507
|
+
catch (_c) {
|
|
28368
28508
|
if (diagnostics === undefined) {
|
|
28369
28509
|
diagnostics = [];
|
|
28370
28510
|
}
|
|
@@ -28375,6 +28515,15 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28375
28515
|
.toDiagnostic());
|
|
28376
28516
|
}
|
|
28377
28517
|
}
|
|
28518
|
+
if (encapsulation === ViewEncapsulation.ShadowDom && metadata.selector !== null) {
|
|
28519
|
+
const selectorError = checkCustomElementSelectorForErrors(metadata.selector);
|
|
28520
|
+
if (selectorError !== null) {
|
|
28521
|
+
if (diagnostics === undefined) {
|
|
28522
|
+
diagnostics = [];
|
|
28523
|
+
}
|
|
28524
|
+
diagnostics.push(makeDiagnostic(ErrorCode.COMPONENT_INVALID_SHADOW_DOM_SELECTOR, component.get('selector'), selectorError));
|
|
28525
|
+
}
|
|
28526
|
+
}
|
|
28378
28527
|
// If inline styles were preprocessed use those
|
|
28379
28528
|
let inlineStyles = null;
|
|
28380
28529
|
if (this.preanalyzeStylesCache.has(node)) {
|
|
@@ -28403,12 +28552,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28403
28552
|
if (template.styles.length > 0) {
|
|
28404
28553
|
styles.push(...template.styles);
|
|
28405
28554
|
}
|
|
28406
|
-
const encapsulation = this._resolveEnumValue(component, 'encapsulation', 'ViewEncapsulation') || 0;
|
|
28407
|
-
const changeDetection = this._resolveEnumValue(component, 'changeDetection', 'ChangeDetectionStrategy');
|
|
28408
|
-
let animations = null;
|
|
28409
|
-
if (component.has('animations')) {
|
|
28410
|
-
animations = new WrappedNodeExpr(component.get('animations'));
|
|
28411
|
-
}
|
|
28412
28555
|
const output = {
|
|
28413
28556
|
analysis: {
|
|
28414
28557
|
baseClass: readBaseClass$1(node, this.reflector, this.evaluator),
|
|
@@ -28417,7 +28560,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28417
28560
|
meta: Object.assign(Object.assign({}, metadata), { template: {
|
|
28418
28561
|
nodes: template.nodes,
|
|
28419
28562
|
ngContentSelectors: template.ngContentSelectors,
|
|
28420
|
-
}, encapsulation, interpolation: (
|
|
28563
|
+
}, encapsulation, interpolation: (_b = template.interpolationConfig) !== null && _b !== void 0 ? _b : DEFAULT_INTERPOLATION_CONFIG, styles,
|
|
28421
28564
|
// These will be replaced during the compilation step, after all `NgModule`s have been
|
|
28422
28565
|
// analyzed and the full compilation scope for the component can be realized.
|
|
28423
28566
|
animations, viewProviders: wrappedViewProviders, i18nUseExternalIds: this.i18nUseExternalIds, relativeContextFilePath }),
|
|
@@ -28651,6 +28794,10 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
28651
28794
|
}
|
|
28652
28795
|
return { data };
|
|
28653
28796
|
}
|
|
28797
|
+
xi18n(ctx, node, analysis) {
|
|
28798
|
+
var _a;
|
|
28799
|
+
ctx.updateFromTemplate(analysis.template.content, analysis.template.declaration.resolvedTemplateUrl, (_a = analysis.template.interpolationConfig) !== null && _a !== void 0 ? _a : DEFAULT_INTERPOLATION_CONFIG);
|
|
28800
|
+
}
|
|
28654
28801
|
updateResources(node, analysis) {
|
|
28655
28802
|
const containingFile = node.getSourceFile().fileName;
|
|
28656
28803
|
// If the template is external, re-parse it.
|
|
@@ -29101,6 +29248,28 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
29101
29248
|
const message = `The ${type} '${name}' is used in the template but importing it would create a cycle: `;
|
|
29102
29249
|
return makeRelatedInformation(ref.node, message + path);
|
|
29103
29250
|
}
|
|
29251
|
+
/**
|
|
29252
|
+
* Checks whether a selector is a valid custom element tag name.
|
|
29253
|
+
* Based loosely on https://github.com/sindresorhus/validate-element-name.
|
|
29254
|
+
*/
|
|
29255
|
+
function checkCustomElementSelectorForErrors(selector) {
|
|
29256
|
+
// Avoid flagging components with an attribute or class selector. This isn't bulletproof since it
|
|
29257
|
+
// won't catch cases like `foo[]bar`, but we don't need it to be. This is mainly to avoid flagging
|
|
29258
|
+
// something like `foo-bar[baz]` incorrectly.
|
|
29259
|
+
if (selector.includes('.') || (selector.includes('[') && selector.includes(']'))) {
|
|
29260
|
+
return null;
|
|
29261
|
+
}
|
|
29262
|
+
if (!(/^[a-z]/.test(selector))) {
|
|
29263
|
+
return 'Selector of a ShadowDom-encapsulated component must start with a lower case letter.';
|
|
29264
|
+
}
|
|
29265
|
+
if (/[A-Z]/.test(selector)) {
|
|
29266
|
+
return 'Selector of a ShadowDom-encapsulated component must all be in lower case.';
|
|
29267
|
+
}
|
|
29268
|
+
if (!selector.includes('-')) {
|
|
29269
|
+
return 'Selector of a component that uses ViewEncapsulation.ShadowDom must contain a hyphen.';
|
|
29270
|
+
}
|
|
29271
|
+
return null;
|
|
29272
|
+
}
|
|
29104
29273
|
|
|
29105
29274
|
/**
|
|
29106
29275
|
* @license
|
|
@@ -29667,6 +29836,12 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
29667
29836
|
stmt.moduleSpecifier === undefined) {
|
|
29668
29837
|
continue;
|
|
29669
29838
|
}
|
|
29839
|
+
if (ts$1.isImportDeclaration(stmt) && stmt.importClause !== undefined &&
|
|
29840
|
+
stmt.importClause.isTypeOnly) {
|
|
29841
|
+
// Exclude type-only imports as they are always elided, so they don't contribute to
|
|
29842
|
+
// cycles.
|
|
29843
|
+
continue;
|
|
29844
|
+
}
|
|
29670
29845
|
const symbol = this.checker.getSymbolAtLocation(stmt.moduleSpecifier);
|
|
29671
29846
|
if (symbol === undefined || symbol.valueDeclaration === undefined) {
|
|
29672
29847
|
// No symbol could be found to skip over this import/export.
|
|
@@ -30210,7 +30385,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
30210
30385
|
versions: this.versions,
|
|
30211
30386
|
depGraph: this.depGraph,
|
|
30212
30387
|
semanticDepGraph: newGraph,
|
|
30213
|
-
traitCompiler,
|
|
30388
|
+
priorAnalysis: traitCompiler.getAnalyzedRecords(),
|
|
30214
30389
|
typeCheckResults: null,
|
|
30215
30390
|
emitted,
|
|
30216
30391
|
};
|
|
@@ -30245,7 +30420,11 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
30245
30420
|
if (this.step.logicallyChangedTsFiles.has(sfPath)) {
|
|
30246
30421
|
return null;
|
|
30247
30422
|
}
|
|
30248
|
-
|
|
30423
|
+
const priorAnalysis = this.step.priorState.priorAnalysis;
|
|
30424
|
+
if (!priorAnalysis.has(sf)) {
|
|
30425
|
+
return null;
|
|
30426
|
+
}
|
|
30427
|
+
return priorAnalysis.get(sf);
|
|
30249
30428
|
}
|
|
30250
30429
|
priorTypeCheckingResultsFor(sf) {
|
|
30251
30430
|
if (this.phase.kind !== PhaseKind.TypeCheckAndEmit) {
|
|
@@ -30733,145 +30912,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
30733
30912
|
return analysis;
|
|
30734
30913
|
}
|
|
30735
30914
|
|
|
30736
|
-
/**
|
|
30737
|
-
* @license
|
|
30738
|
-
* Copyright Google LLC All Rights Reserved.
|
|
30739
|
-
*
|
|
30740
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
30741
|
-
* found in the LICENSE file at https://angular.io/license
|
|
30742
|
-
*/
|
|
30743
|
-
class ModuleWithProvidersScanner {
|
|
30744
|
-
constructor(host, evaluator, emitter) {
|
|
30745
|
-
this.host = host;
|
|
30746
|
-
this.evaluator = evaluator;
|
|
30747
|
-
this.emitter = emitter;
|
|
30748
|
-
}
|
|
30749
|
-
scan(sf, dts) {
|
|
30750
|
-
for (const stmt of sf.statements) {
|
|
30751
|
-
this.visitStatement(dts, stmt);
|
|
30752
|
-
}
|
|
30753
|
-
}
|
|
30754
|
-
visitStatement(dts, stmt) {
|
|
30755
|
-
// Detect whether a statement is exported, which is used as one of the hints whether to look
|
|
30756
|
-
// more closely at possible MWP functions within. This is a syntactic check, not a semantic
|
|
30757
|
-
// check, so it won't detect cases like:
|
|
30758
|
-
//
|
|
30759
|
-
// var X = ...;
|
|
30760
|
-
// export {X}
|
|
30761
|
-
//
|
|
30762
|
-
// This is intentional, because the alternative is slow and this will catch 99% of the cases we
|
|
30763
|
-
// need to handle.
|
|
30764
|
-
const isExported = stmt.modifiers !== undefined &&
|
|
30765
|
-
stmt.modifiers.some(mod => mod.kind === ts$1.SyntaxKind.ExportKeyword);
|
|
30766
|
-
if (!isExported) {
|
|
30767
|
-
return;
|
|
30768
|
-
}
|
|
30769
|
-
if (ts$1.isClassDeclaration(stmt)) {
|
|
30770
|
-
for (const member of stmt.members) {
|
|
30771
|
-
if (!ts$1.isMethodDeclaration(member) || !isStatic(member)) {
|
|
30772
|
-
continue;
|
|
30773
|
-
}
|
|
30774
|
-
this.visitFunctionOrMethodDeclaration(dts, member);
|
|
30775
|
-
}
|
|
30776
|
-
}
|
|
30777
|
-
else if (ts$1.isFunctionDeclaration(stmt)) {
|
|
30778
|
-
this.visitFunctionOrMethodDeclaration(dts, stmt);
|
|
30779
|
-
}
|
|
30780
|
-
}
|
|
30781
|
-
visitFunctionOrMethodDeclaration(dts, decl) {
|
|
30782
|
-
// First, some sanity. This should have a method body with a single return statement.
|
|
30783
|
-
if (decl.body === undefined || decl.body.statements.length !== 1) {
|
|
30784
|
-
return;
|
|
30785
|
-
}
|
|
30786
|
-
const retStmt = decl.body.statements[0];
|
|
30787
|
-
if (!ts$1.isReturnStatement(retStmt) || retStmt.expression === undefined) {
|
|
30788
|
-
return;
|
|
30789
|
-
}
|
|
30790
|
-
const retValue = retStmt.expression;
|
|
30791
|
-
// Now, look at the return type of the method. Maybe bail if the type is already marked, or if
|
|
30792
|
-
// it's incompatible with a MWP function.
|
|
30793
|
-
const returnType = this.returnTypeOf(decl);
|
|
30794
|
-
if (returnType === ReturnType.OTHER || returnType === ReturnType.MWP_WITH_TYPE) {
|
|
30795
|
-
// Don't process this declaration, it either already declares the right return type, or an
|
|
30796
|
-
// incompatible one.
|
|
30797
|
-
return;
|
|
30798
|
-
}
|
|
30799
|
-
const value = this.evaluator.evaluate(retValue);
|
|
30800
|
-
if (!(value instanceof Map) || !value.has('ngModule')) {
|
|
30801
|
-
// The return value does not provide sufficient information to be able to add a generic type.
|
|
30802
|
-
return;
|
|
30803
|
-
}
|
|
30804
|
-
if (returnType === ReturnType.INFERRED && !isModuleWithProvidersType(value)) {
|
|
30805
|
-
// The return type is inferred but the returned object is not of the correct shape, so we
|
|
30806
|
-
// shouldn's modify the return type to become `ModuleWithProviders`.
|
|
30807
|
-
return;
|
|
30808
|
-
}
|
|
30809
|
-
// The return type has been verified to represent the `ModuleWithProviders` type, but either the
|
|
30810
|
-
// return type is inferred or the generic type argument is missing. In both cases, a new return
|
|
30811
|
-
// type is created where the `ngModule` type is included as generic type argument.
|
|
30812
|
-
const ngModule = value.get('ngModule');
|
|
30813
|
-
if (!(ngModule instanceof Reference$1) || !ts$1.isClassDeclaration(ngModule.node)) {
|
|
30814
|
-
return;
|
|
30815
|
-
}
|
|
30816
|
-
const ngModuleExpr = this.emitter.emit(ngModule, decl.getSourceFile(), ImportFlags.ForceNewImport);
|
|
30817
|
-
const ngModuleType = new ExpressionType(ngModuleExpr.expression);
|
|
30818
|
-
const mwpNgType = new ExpressionType(new ExternalExpr(Identifiers.ModuleWithProviders), [ /* modifiers */], [ngModuleType]);
|
|
30819
|
-
dts.addTypeReplacement(decl, mwpNgType);
|
|
30820
|
-
}
|
|
30821
|
-
returnTypeOf(decl) {
|
|
30822
|
-
if (decl.type === undefined) {
|
|
30823
|
-
return ReturnType.INFERRED;
|
|
30824
|
-
}
|
|
30825
|
-
else if (!ts$1.isTypeReferenceNode(decl.type)) {
|
|
30826
|
-
return ReturnType.OTHER;
|
|
30827
|
-
}
|
|
30828
|
-
// Try to figure out if the type is of a familiar form, something that looks like it was
|
|
30829
|
-
// imported.
|
|
30830
|
-
let typeId;
|
|
30831
|
-
if (ts$1.isIdentifier(decl.type.typeName)) {
|
|
30832
|
-
// def: ModuleWithProviders
|
|
30833
|
-
typeId = decl.type.typeName;
|
|
30834
|
-
}
|
|
30835
|
-
else if (ts$1.isQualifiedName(decl.type.typeName) && ts$1.isIdentifier(decl.type.typeName.left)) {
|
|
30836
|
-
// def: i0.ModuleWithProviders
|
|
30837
|
-
typeId = decl.type.typeName.right;
|
|
30838
|
-
}
|
|
30839
|
-
else {
|
|
30840
|
-
return ReturnType.OTHER;
|
|
30841
|
-
}
|
|
30842
|
-
const importDecl = this.host.getImportOfIdentifier(typeId);
|
|
30843
|
-
if (importDecl === null || importDecl.from !== '@angular/core' ||
|
|
30844
|
-
importDecl.name !== 'ModuleWithProviders') {
|
|
30845
|
-
return ReturnType.OTHER;
|
|
30846
|
-
}
|
|
30847
|
-
if (decl.type.typeArguments === undefined || decl.type.typeArguments.length === 0) {
|
|
30848
|
-
// The return type is indeed ModuleWithProviders, but no generic type parameter was found.
|
|
30849
|
-
return ReturnType.MWP_NO_TYPE;
|
|
30850
|
-
}
|
|
30851
|
-
else {
|
|
30852
|
-
// The return type is ModuleWithProviders, and the user has already specified a generic type.
|
|
30853
|
-
return ReturnType.MWP_WITH_TYPE;
|
|
30854
|
-
}
|
|
30855
|
-
}
|
|
30856
|
-
}
|
|
30857
|
-
var ReturnType;
|
|
30858
|
-
(function (ReturnType) {
|
|
30859
|
-
ReturnType[ReturnType["INFERRED"] = 0] = "INFERRED";
|
|
30860
|
-
ReturnType[ReturnType["MWP_NO_TYPE"] = 1] = "MWP_NO_TYPE";
|
|
30861
|
-
ReturnType[ReturnType["MWP_WITH_TYPE"] = 2] = "MWP_WITH_TYPE";
|
|
30862
|
-
ReturnType[ReturnType["OTHER"] = 3] = "OTHER";
|
|
30863
|
-
})(ReturnType || (ReturnType = {}));
|
|
30864
|
-
/** Whether the resolved value map represents a ModuleWithProviders object */
|
|
30865
|
-
function isModuleWithProvidersType(value) {
|
|
30866
|
-
const ngModule = value.has('ngModule');
|
|
30867
|
-
const providers = value.has('providers');
|
|
30868
|
-
return ngModule && (value.size === 1 || (providers && value.size === 2));
|
|
30869
|
-
}
|
|
30870
|
-
function isStatic(node) {
|
|
30871
|
-
return node.modifiers !== undefined &&
|
|
30872
|
-
node.modifiers.some(mod => mod.kind === ts$1.SyntaxKind.StaticKeyword);
|
|
30873
|
-
}
|
|
30874
|
-
|
|
30875
30915
|
/**
|
|
30876
30916
|
* @license
|
|
30877
30917
|
* Copyright Google LLC All Rights Reserved.
|
|
@@ -31519,6 +31559,9 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
31519
31559
|
if (alias === null) {
|
|
31520
31560
|
return dirOrPipe;
|
|
31521
31561
|
}
|
|
31562
|
+
// TypeScript incorrectly narrows the type here:
|
|
31563
|
+
// https://github.com/microsoft/TypeScript/issues/43966.
|
|
31564
|
+
// TODO: Remove/Update once https://github.com/microsoft/TypeScript/issues/43966 is resolved.
|
|
31522
31565
|
return Object.assign(Object.assign({}, dirOrPipe), { ref: ref.cloneWithAlias(alias) });
|
|
31523
31566
|
}
|
|
31524
31567
|
}
|
|
@@ -33164,6 +33207,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
33164
33207
|
* Use of this source code is governed by an MIT-style license that can be
|
|
33165
33208
|
* found in the LICENSE file at https://angular.io/license
|
|
33166
33209
|
*/
|
|
33210
|
+
const INELIGIBLE = {};
|
|
33167
33211
|
/**
|
|
33168
33212
|
* Determines whether the provided type can be emitted, which means that it can be safely emitted
|
|
33169
33213
|
* into a different location.
|
|
@@ -33175,13 +33219,24 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
33175
33219
|
function canEmitType(type, resolver) {
|
|
33176
33220
|
return canEmitTypeWorker(type);
|
|
33177
33221
|
function canEmitTypeWorker(type) {
|
|
33178
|
-
return
|
|
33179
|
-
|
|
33180
|
-
|
|
33181
|
-
|
|
33182
|
-
|
|
33183
|
-
|
|
33184
|
-
|
|
33222
|
+
return visitNode(type) !== INELIGIBLE;
|
|
33223
|
+
}
|
|
33224
|
+
// To determine whether a type can be emitted, we have to recursively look through all type nodes.
|
|
33225
|
+
// If a type reference node is found at any position within the type and that type reference
|
|
33226
|
+
// cannot be emitted, then the `INELIGIBLE` constant is returned to stop the recursive walk as
|
|
33227
|
+
// the type as a whole cannot be emitted in that case. Otherwise, the result of visiting all child
|
|
33228
|
+
// nodes determines the result. If no ineligible type reference node is found then the walk
|
|
33229
|
+
// returns `undefined`, indicating that no type node was visited that could not be emitted.
|
|
33230
|
+
function visitNode(node) {
|
|
33231
|
+
// Emitting a type reference node in a different context requires that an import for the type
|
|
33232
|
+
// can be created. If a type reference node cannot be emitted, `INELIGIBLE` is returned to stop
|
|
33233
|
+
// the walk.
|
|
33234
|
+
if (ts$1.isTypeReferenceNode(node) && !canEmitTypeReference(node)) {
|
|
33235
|
+
return INELIGIBLE;
|
|
33236
|
+
}
|
|
33237
|
+
else {
|
|
33238
|
+
return ts$1.forEachChild(node, visitNode);
|
|
33239
|
+
}
|
|
33185
33240
|
}
|
|
33186
33241
|
function canEmitTypeReference(type) {
|
|
33187
33242
|
const reference = resolver(type);
|
|
@@ -33189,10 +33244,9 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
33189
33244
|
if (reference === null) {
|
|
33190
33245
|
return false;
|
|
33191
33246
|
}
|
|
33192
|
-
// If the type is a reference
|
|
33193
|
-
|
|
33194
|
-
|
|
33195
|
-
return false;
|
|
33247
|
+
// If the type is a reference, consider the type to be eligible for emitting.
|
|
33248
|
+
if (reference instanceof Reference$1) {
|
|
33249
|
+
return true;
|
|
33196
33250
|
}
|
|
33197
33251
|
// The type can be emitted if either it does not have any type arguments, or all of them can be
|
|
33198
33252
|
// emitted.
|
|
@@ -33234,15 +33288,18 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
33234
33288
|
this.emitReference = emitReference;
|
|
33235
33289
|
}
|
|
33236
33290
|
emitType(type) {
|
|
33237
|
-
|
|
33238
|
-
|
|
33239
|
-
|
|
33240
|
-
|
|
33241
|
-
|
|
33242
|
-
|
|
33243
|
-
|
|
33244
|
-
|
|
33245
|
-
|
|
33291
|
+
const typeReferenceTransformer = context => {
|
|
33292
|
+
const visitNode = (node) => {
|
|
33293
|
+
if (ts$1.isTypeReferenceNode(node)) {
|
|
33294
|
+
return this.emitTypeReference(node);
|
|
33295
|
+
}
|
|
33296
|
+
else {
|
|
33297
|
+
return ts$1.visitEachChild(node, visitNode, context);
|
|
33298
|
+
}
|
|
33299
|
+
};
|
|
33300
|
+
return node => ts$1.visitNode(node, visitNode);
|
|
33301
|
+
};
|
|
33302
|
+
return ts$1.transform(type, [typeReferenceTransformer]).transformed[0];
|
|
33246
33303
|
}
|
|
33247
33304
|
emitTypeReference(type) {
|
|
33248
33305
|
// Determine the reference that the type corresponds with.
|
|
@@ -33258,9 +33315,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
33258
33315
|
// Emit the type name.
|
|
33259
33316
|
let typeName = type.typeName;
|
|
33260
33317
|
if (reference instanceof Reference$1) {
|
|
33261
|
-
if (!reference.hasOwningModuleGuess) {
|
|
33262
|
-
throw new Error('A type reference to emit must be imported from an absolute module');
|
|
33263
|
-
}
|
|
33264
33318
|
const emittedType = this.emitReference(reference);
|
|
33265
33319
|
if (!ts$1.isTypeReferenceNode(emittedType)) {
|
|
33266
33320
|
throw new Error(`Expected TypeReferenceNode for emitted reference, got ${ts$1.SyntaxKind[emittedType.kind]}`);
|
|
@@ -33270,30 +33324,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
33270
33324
|
return ts$1.updateTypeReferenceNode(type, typeName, typeArguments);
|
|
33271
33325
|
}
|
|
33272
33326
|
}
|
|
33273
|
-
function visitTypeNode(type, visitor) {
|
|
33274
|
-
if (ts$1.isTypeReferenceNode(type)) {
|
|
33275
|
-
return visitor.visitTypeReferenceNode(type);
|
|
33276
|
-
}
|
|
33277
|
-
else if (ts$1.isArrayTypeNode(type)) {
|
|
33278
|
-
return visitor.visitArrayTypeNode(type);
|
|
33279
|
-
}
|
|
33280
|
-
else if (ts$1.isLiteralTypeNode(type)) {
|
|
33281
|
-
return visitor.visitLiteralType(type);
|
|
33282
|
-
}
|
|
33283
|
-
switch (type.kind) {
|
|
33284
|
-
case ts$1.SyntaxKind.AnyKeyword:
|
|
33285
|
-
case ts$1.SyntaxKind.UnknownKeyword:
|
|
33286
|
-
case ts$1.SyntaxKind.NumberKeyword:
|
|
33287
|
-
case ts$1.SyntaxKind.ObjectKeyword:
|
|
33288
|
-
case ts$1.SyntaxKind.BooleanKeyword:
|
|
33289
|
-
case ts$1.SyntaxKind.StringKeyword:
|
|
33290
|
-
case ts$1.SyntaxKind.UndefinedKeyword:
|
|
33291
|
-
case ts$1.SyntaxKind.NullKeyword:
|
|
33292
|
-
return visitor.visitKeywordType(type);
|
|
33293
|
-
default:
|
|
33294
|
-
return visitor.visitOtherType(type);
|
|
33295
|
-
}
|
|
33296
|
-
}
|
|
33297
33327
|
|
|
33298
33328
|
/**
|
|
33299
33329
|
* @license
|
|
@@ -33320,12 +33350,15 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
33320
33350
|
return true;
|
|
33321
33351
|
}
|
|
33322
33352
|
return this.typeParameters.every(typeParam => {
|
|
33323
|
-
|
|
33324
|
-
return true;
|
|
33325
|
-
}
|
|
33326
|
-
return canEmitType(typeParam.constraint, type => this.resolveTypeReference(type));
|
|
33353
|
+
return this.canEmitType(typeParam.constraint) && this.canEmitType(typeParam.default);
|
|
33327
33354
|
});
|
|
33328
33355
|
}
|
|
33356
|
+
canEmitType(type) {
|
|
33357
|
+
if (type === undefined) {
|
|
33358
|
+
return true;
|
|
33359
|
+
}
|
|
33360
|
+
return canEmitType(type, typeReference => this.resolveTypeReference(typeReference));
|
|
33361
|
+
}
|
|
33329
33362
|
/**
|
|
33330
33363
|
* Emits the type parameters using the provided emitter function for `Reference`s.
|
|
33331
33364
|
*/
|
|
@@ -33336,11 +33369,12 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
33336
33369
|
const emitter = new TypeEmitter(type => this.resolveTypeReference(type), emitReference);
|
|
33337
33370
|
return this.typeParameters.map(typeParam => {
|
|
33338
33371
|
const constraint = typeParam.constraint !== undefined ? emitter.emitType(typeParam.constraint) : undefined;
|
|
33372
|
+
const defaultType = typeParam.default !== undefined ? emitter.emitType(typeParam.default) : undefined;
|
|
33339
33373
|
return ts$1.updateTypeParameterDeclaration(
|
|
33340
33374
|
/* node */ typeParam,
|
|
33341
33375
|
/* name */ typeParam.name,
|
|
33342
33376
|
/* constraint */ constraint,
|
|
33343
|
-
/* defaultType */
|
|
33377
|
+
/* defaultType */ defaultType);
|
|
33344
33378
|
});
|
|
33345
33379
|
}
|
|
33346
33380
|
resolveTypeReference(type) {
|
|
@@ -33363,8 +33397,16 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
33363
33397
|
resolutionContext: type.getSourceFile().fileName,
|
|
33364
33398
|
};
|
|
33365
33399
|
}
|
|
33400
|
+
// If no owning module is known, the reference needs to be exported to be able to emit an import
|
|
33401
|
+
// statement for it. If the declaration is not exported, null is returned to prevent emit.
|
|
33402
|
+
if (owningModule === null && !this.isStaticallyExported(declaration.node)) {
|
|
33403
|
+
return null;
|
|
33404
|
+
}
|
|
33366
33405
|
return new Reference$1(declaration.node, owningModule);
|
|
33367
33406
|
}
|
|
33407
|
+
isStaticallyExported(decl) {
|
|
33408
|
+
return isNamedClassDeclaration(decl) && this.reflector.isStaticallyExported(decl);
|
|
33409
|
+
}
|
|
33368
33410
|
isLocalTypeParameter(decl) {
|
|
33369
33411
|
// Checking for local type parameters only occurs during resolution of type parameters, so it is
|
|
33370
33412
|
// guaranteed that type parameters are present.
|
|
@@ -34227,14 +34269,14 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
34227
34269
|
return ast.expressions.reduce((lhs, ast) => ts$1.createBinary(lhs, ts$1.SyntaxKind.PlusToken, wrapForTypeChecker(this.translate(ast))), ts$1.createLiteral(''));
|
|
34228
34270
|
}
|
|
34229
34271
|
visitKeyedRead(ast) {
|
|
34230
|
-
const receiver = wrapForDiagnostics(this.translate(ast.
|
|
34272
|
+
const receiver = wrapForDiagnostics(this.translate(ast.receiver));
|
|
34231
34273
|
const key = this.translate(ast.key);
|
|
34232
34274
|
const node = ts$1.createElementAccess(receiver, key);
|
|
34233
34275
|
addParseSpanInfo(node, ast.sourceSpan);
|
|
34234
34276
|
return node;
|
|
34235
34277
|
}
|
|
34236
34278
|
visitKeyedWrite(ast) {
|
|
34237
|
-
const receiver = wrapForDiagnostics(this.translate(ast.
|
|
34279
|
+
const receiver = wrapForDiagnostics(this.translate(ast.receiver));
|
|
34238
34280
|
const left = ts$1.createElementAccess(receiver, this.translate(ast.key));
|
|
34239
34281
|
// TODO(joost): annotate `left` with the span of the element access, which is not currently
|
|
34240
34282
|
// available on `ast`.
|
|
@@ -34393,6 +34435,30 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
34393
34435
|
addParseSpanInfo(node, ast.sourceSpan);
|
|
34394
34436
|
return node;
|
|
34395
34437
|
}
|
|
34438
|
+
visitSafeKeyedRead(ast) {
|
|
34439
|
+
const receiver = wrapForDiagnostics(this.translate(ast.receiver));
|
|
34440
|
+
const key = this.translate(ast.key);
|
|
34441
|
+
let node;
|
|
34442
|
+
// The form of safe property reads depends on whether strictness is in use.
|
|
34443
|
+
if (this.config.strictSafeNavigationTypes) {
|
|
34444
|
+
// "a?.[...]" becomes (null as any ? a![...] : undefined)
|
|
34445
|
+
const expr = ts$1.createElementAccess(ts$1.createNonNullExpression(receiver), key);
|
|
34446
|
+
addParseSpanInfo(expr, ast.sourceSpan);
|
|
34447
|
+
node = ts$1.createParen(ts$1.createConditional(NULL_AS_ANY, expr, UNDEFINED));
|
|
34448
|
+
}
|
|
34449
|
+
else if (VeSafeLhsInferenceBugDetector.veWillInferAnyFor(ast)) {
|
|
34450
|
+
// "a?.[...]" becomes (a as any)[...]
|
|
34451
|
+
node = ts$1.createElementAccess(tsCastToAny(receiver), key);
|
|
34452
|
+
}
|
|
34453
|
+
else {
|
|
34454
|
+
// "a?.[...]" becomes (a!.[...] as any)
|
|
34455
|
+
const expr = ts$1.createElementAccess(ts$1.createNonNullExpression(receiver), key);
|
|
34456
|
+
addParseSpanInfo(expr, ast.sourceSpan);
|
|
34457
|
+
node = tsCastToAny(expr);
|
|
34458
|
+
}
|
|
34459
|
+
addParseSpanInfo(node, ast.sourceSpan);
|
|
34460
|
+
return node;
|
|
34461
|
+
}
|
|
34396
34462
|
}
|
|
34397
34463
|
/**
|
|
34398
34464
|
* Checks whether View Engine will infer a type of 'any' for the left-hand side of a safe navigation
|
|
@@ -34409,7 +34475,8 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
34409
34475
|
*/
|
|
34410
34476
|
class VeSafeLhsInferenceBugDetector {
|
|
34411
34477
|
static veWillInferAnyFor(ast) {
|
|
34412
|
-
|
|
34478
|
+
const visitor = VeSafeLhsInferenceBugDetector.SINGLETON;
|
|
34479
|
+
return ast instanceof SafeKeyedRead ? ast.receiver.visit(visitor) : ast.receiver.visit(visitor);
|
|
34413
34480
|
}
|
|
34414
34481
|
visitUnary(ast) {
|
|
34415
34482
|
return ast.expr.visit(this);
|
|
@@ -34477,6 +34544,9 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
34477
34544
|
visitSafePropertyRead(ast) {
|
|
34478
34545
|
return false;
|
|
34479
34546
|
}
|
|
34547
|
+
visitSafeKeyedRead(ast) {
|
|
34548
|
+
return false;
|
|
34549
|
+
}
|
|
34480
34550
|
}
|
|
34481
34551
|
VeSafeLhsInferenceBugDetector.SINGLETON = new VeSafeLhsInferenceBugDetector();
|
|
34482
34552
|
|
|
@@ -36889,8 +36959,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
36889
36959
|
.map(node => {
|
|
36890
36960
|
var _a;
|
|
36891
36961
|
const symbol = this.getSymbolOfTsNode(node.parent);
|
|
36892
|
-
if (symbol === null || symbol.tsSymbol
|
|
36893
|
-
symbol.tsSymbol.valueDeclaration === undefined ||
|
|
36962
|
+
if (symbol === null || !isSymbolWithValueDeclaration(symbol.tsSymbol) ||
|
|
36894
36963
|
!ts$1.isClassDeclaration(symbol.tsSymbol.valueDeclaration)) {
|
|
36895
36964
|
return null;
|
|
36896
36965
|
}
|
|
@@ -37046,7 +37115,8 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37046
37115
|
// In either case, `_t1["index"]` or `_t1.index`, `node.expression` is _t1.
|
|
37047
37116
|
// The retrieved symbol for _t1 will be the variable declaration.
|
|
37048
37117
|
const tsSymbol = this.getTypeChecker().getSymbolAtLocation(node.expression);
|
|
37049
|
-
if (tsSymbol ===
|
|
37118
|
+
if ((tsSymbol === null || tsSymbol === void 0 ? void 0 : tsSymbol.declarations) === undefined || tsSymbol.declarations.length === 0 ||
|
|
37119
|
+
selector === null) {
|
|
37050
37120
|
return null;
|
|
37051
37121
|
}
|
|
37052
37122
|
const [declaration] = tsSymbol.declarations;
|
|
@@ -37058,8 +37128,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37058
37128
|
return null;
|
|
37059
37129
|
}
|
|
37060
37130
|
const symbol = this.getSymbolOfTsNode(declaration);
|
|
37061
|
-
if (symbol === null || symbol.tsSymbol
|
|
37062
|
-
symbol.tsSymbol.valueDeclaration === undefined ||
|
|
37131
|
+
if (symbol === null || !isSymbolWithValueDeclaration(symbol.tsSymbol) ||
|
|
37063
37132
|
!ts$1.isClassDeclaration(symbol.tsSymbol.valueDeclaration)) {
|
|
37064
37133
|
return null;
|
|
37065
37134
|
}
|
|
@@ -37159,7 +37228,10 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37159
37228
|
return null;
|
|
37160
37229
|
}
|
|
37161
37230
|
const pipeInstance = this.getSymbolOfTsNode(pipeDeclaration.valueDeclaration);
|
|
37162
|
-
|
|
37231
|
+
// The instance should never be null, nor should the symbol lack a value declaration. This
|
|
37232
|
+
// is because the node used to look for the `pipeInstance` symbol info is a value
|
|
37233
|
+
// declaration of another symbol (i.e. the `pipeDeclaration` symbol).
|
|
37234
|
+
if (pipeInstance === null || !isSymbolWithValueDeclaration(pipeInstance.tsSymbol)) {
|
|
37163
37235
|
return null;
|
|
37164
37236
|
}
|
|
37165
37237
|
const symbolInfo = this.getSymbolOfTsNode(methodAccess);
|
|
@@ -37181,7 +37253,16 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37181
37253
|
const withSpan = (expression instanceof PropertyWrite || expression instanceof MethodCall) ?
|
|
37182
37254
|
expression.nameSpan :
|
|
37183
37255
|
expression.sourceSpan;
|
|
37184
|
-
let node =
|
|
37256
|
+
let node = null;
|
|
37257
|
+
// Property reads in templates usually map to a `PropertyAccessExpression`
|
|
37258
|
+
// (e.g. `ctx.foo`) so try looking for one first.
|
|
37259
|
+
if (expression instanceof PropertyRead) {
|
|
37260
|
+
node = findFirstMatchingNode(this.typeCheckBlock, { withSpan, filter: ts$1.isPropertyAccessExpression });
|
|
37261
|
+
}
|
|
37262
|
+
// Otherwise fall back to searching for any AST node.
|
|
37263
|
+
if (node === null) {
|
|
37264
|
+
node = findFirstMatchingNode(this.typeCheckBlock, { withSpan, filter: anyNodeFilter });
|
|
37265
|
+
}
|
|
37185
37266
|
if (node === null) {
|
|
37186
37267
|
return null;
|
|
37187
37268
|
}
|
|
@@ -37255,6 +37336,10 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37255
37336
|
}
|
|
37256
37337
|
}
|
|
37257
37338
|
}
|
|
37339
|
+
/** Filter predicate function that matches any AST node. */
|
|
37340
|
+
function anyNodeFilter(n) {
|
|
37341
|
+
return true;
|
|
37342
|
+
}
|
|
37258
37343
|
|
|
37259
37344
|
/**
|
|
37260
37345
|
* @license
|
|
@@ -37694,7 +37779,7 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
37694
37779
|
continue;
|
|
37695
37780
|
}
|
|
37696
37781
|
const tsSymbol = typeChecker.getSymbolAtLocation(dir.ref.node.name);
|
|
37697
|
-
if (tsSymbol
|
|
37782
|
+
if (!isSymbolWithValueDeclaration(tsSymbol)) {
|
|
37698
37783
|
continue;
|
|
37699
37784
|
}
|
|
37700
37785
|
let ngModule = null;
|
|
@@ -38190,7 +38275,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
38190
38275
|
continue;
|
|
38191
38276
|
}
|
|
38192
38277
|
let analysisPromise = this.compilation.traitCompiler.analyzeAsync(sf);
|
|
38193
|
-
this.scanForMwp(sf);
|
|
38194
38278
|
if (analysisPromise !== undefined) {
|
|
38195
38279
|
promises.push(analysisPromise);
|
|
38196
38280
|
}
|
|
@@ -38280,6 +38364,15 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
38280
38364
|
compilation.traitCompiler.index(context);
|
|
38281
38365
|
return generateAnalysis(context);
|
|
38282
38366
|
}
|
|
38367
|
+
/**
|
|
38368
|
+
* Collect i18n messages into the `Xi18nContext`.
|
|
38369
|
+
*/
|
|
38370
|
+
xi18n(ctx) {
|
|
38371
|
+
// Note that the 'resolve' phase is not strictly necessary for xi18n, but this is not currently
|
|
38372
|
+
// optimized.
|
|
38373
|
+
const compilation = this.ensureAnalyzed();
|
|
38374
|
+
compilation.traitCompiler.xi18n(ctx);
|
|
38375
|
+
}
|
|
38283
38376
|
ensureAnalyzed() {
|
|
38284
38377
|
if (this.compilation === null) {
|
|
38285
38378
|
this.analyzeSync();
|
|
@@ -38294,7 +38387,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
38294
38387
|
continue;
|
|
38295
38388
|
}
|
|
38296
38389
|
this.compilation.traitCompiler.analyzeSync(sf);
|
|
38297
|
-
this.scanForMwp(sf);
|
|
38298
38390
|
}
|
|
38299
38391
|
this.perfRecorder.memory(PerfCheckpoint.Analysis);
|
|
38300
38392
|
this.resolveCompilation(this.compilation.traitCompiler);
|
|
@@ -38465,15 +38557,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
38465
38557
|
}
|
|
38466
38558
|
return this.nonTemplateDiagnostics;
|
|
38467
38559
|
}
|
|
38468
|
-
scanForMwp(sf) {
|
|
38469
|
-
this.compilation.mwpScanner.scan(sf, {
|
|
38470
|
-
addTypeReplacement: (node, type) => {
|
|
38471
|
-
// Only obtain the return type transform for the source file once there's a type to replace,
|
|
38472
|
-
// so that no transform is allocated when there's nothing to do.
|
|
38473
|
-
this.compilation.dtsTransforms.getReturnTypeTransform(sf).addTypeReplacement(node, type);
|
|
38474
|
-
}
|
|
38475
|
-
});
|
|
38476
|
-
}
|
|
38477
38560
|
makeCompilation() {
|
|
38478
38561
|
const checker = this.inputProgram.getTypeChecker();
|
|
38479
38562
|
const reflector = new TypeScriptReflectionHost(checker);
|
|
@@ -38556,7 +38639,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
38556
38639
|
}
|
|
38557
38640
|
const routeAnalyzer = new NgModuleRouteAnalyzer(this.moduleResolver, evaluator);
|
|
38558
38641
|
const dtsTransforms = new DtsTransformRegistry();
|
|
38559
|
-
const mwpScanner = new ModuleWithProvidersScanner(reflector, evaluator, refEmitter);
|
|
38560
38642
|
const isCore = isAngularCorePackage(this.inputProgram);
|
|
38561
38643
|
const resourceRegistry = new ResourceRegistry();
|
|
38562
38644
|
const compilationMode = this.options.compilationMode === 'partial' ? CompilationMode.PARTIAL : CompilationMode.FULL;
|
|
@@ -38596,7 +38678,6 @@ Either add the @Injectable() decorator to '${provider.node.name
|
|
|
38596
38678
|
dtsTransforms,
|
|
38597
38679
|
exportReferenceGraph,
|
|
38598
38680
|
routeAnalyzer,
|
|
38599
|
-
mwpScanner,
|
|
38600
38681
|
metaReader,
|
|
38601
38682
|
typeCheckScopeRegistry,
|
|
38602
38683
|
aliasingHost,
|
|
@@ -38984,7 +39065,9 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
38984
39065
|
}
|
|
38985
39066
|
function getTsSymbolDisplayInfo(tsLS, checker, symbol, kind, ownerName) {
|
|
38986
39067
|
const decl = symbol.valueDeclaration;
|
|
38987
|
-
if (decl === undefined ||
|
|
39068
|
+
if (decl === undefined ||
|
|
39069
|
+
(!ts$1.isPropertyDeclaration(decl) && !ts$1.isMethodDeclaration(decl) &&
|
|
39070
|
+
!isNamedClassDeclaration(decl)) ||
|
|
38988
39071
|
!ts$1.isIdentifier(decl.name)) {
|
|
38989
39072
|
return null;
|
|
38990
39073
|
}
|
|
@@ -39084,7 +39167,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
39084
39167
|
const members = [];
|
|
39085
39168
|
const apparentProps = typeChecker.getTypeAtLocation(clazz).getApparentProperties();
|
|
39086
39169
|
for (const prop of apparentProps) {
|
|
39087
|
-
if (ts$1.isMethodDeclaration(prop.valueDeclaration)
|
|
39170
|
+
if (prop.valueDeclaration && ts$1.isMethodDeclaration(prop.valueDeclaration)) {
|
|
39088
39171
|
members.push(prop.valueDeclaration);
|
|
39089
39172
|
}
|
|
39090
39173
|
}
|
|
@@ -40157,7 +40240,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40157
40240
|
}
|
|
40158
40241
|
visit(node) {
|
|
40159
40242
|
const { start, end } = getSpanIncludingEndTag(node);
|
|
40160
|
-
if (!isWithin(this.position, { start, end })) {
|
|
40243
|
+
if (end !== null && !isWithin(this.position, { start, end })) {
|
|
40161
40244
|
return;
|
|
40162
40245
|
}
|
|
40163
40246
|
const last = this.path[this.path.length - 1];
|
|
@@ -40291,8 +40374,15 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40291
40374
|
// the end of the closing tag. Otherwise, for situation like
|
|
40292
40375
|
// <my-component></my-comp¦onent> where the cursor is in the closing tag
|
|
40293
40376
|
// we will not be able to return any information.
|
|
40294
|
-
if (
|
|
40295
|
-
|
|
40377
|
+
if (ast instanceof Element || ast instanceof Template) {
|
|
40378
|
+
if (ast.endSourceSpan) {
|
|
40379
|
+
result.end = ast.endSourceSpan.end.offset;
|
|
40380
|
+
}
|
|
40381
|
+
else if (ast.children.length > 0) {
|
|
40382
|
+
// If the AST has children but no end source span, then it is an unclosed element with an end
|
|
40383
|
+
// that should be the end of the last child.
|
|
40384
|
+
result.end = getSpanIncludingEndTag(ast.children[ast.children.length - 1]).end;
|
|
40385
|
+
}
|
|
40296
40386
|
}
|
|
40297
40387
|
return result;
|
|
40298
40388
|
}
|
|
@@ -40361,9 +40451,9 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40361
40451
|
/**
|
|
40362
40452
|
* Analogue for `ts.LanguageService.getCompletionEntryDetails`.
|
|
40363
40453
|
*/
|
|
40364
|
-
getCompletionEntryDetails(entryName, formatOptions, preferences) {
|
|
40454
|
+
getCompletionEntryDetails(entryName, formatOptions, preferences, data) {
|
|
40365
40455
|
if (this.isPropertyExpressionCompletion()) {
|
|
40366
|
-
return this.getPropertyExpressionCompletionDetails(entryName, formatOptions, preferences);
|
|
40456
|
+
return this.getPropertyExpressionCompletionDetails(entryName, formatOptions, preferences, data);
|
|
40367
40457
|
}
|
|
40368
40458
|
else if (this.isElementTagCompletion()) {
|
|
40369
40459
|
return this.getElementTagCompletionDetails(entryName);
|
|
@@ -40431,12 +40521,11 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40431
40521
|
/**
|
|
40432
40522
|
* Get the details of a specific completion for a property expression.
|
|
40433
40523
|
*/
|
|
40434
|
-
getPropertyExpressionCompletionDetails(entryName, formatOptions, preferences) {
|
|
40524
|
+
getPropertyExpressionCompletionDetails(entryName, formatOptions, preferences, data) {
|
|
40435
40525
|
let details = undefined;
|
|
40436
40526
|
if (this.node instanceof EmptyExpr || this.node instanceof BoundEvent ||
|
|
40437
40527
|
this.node.receiver instanceof ImplicitReceiver) {
|
|
40438
|
-
details =
|
|
40439
|
-
this.getGlobalPropertyExpressionCompletionDetails(entryName, formatOptions, preferences);
|
|
40528
|
+
details = this.getGlobalPropertyExpressionCompletionDetails(entryName, formatOptions, preferences, data);
|
|
40440
40529
|
}
|
|
40441
40530
|
else {
|
|
40442
40531
|
const location = this.compiler.getTemplateTypeChecker().getExpressionCompletionLocation(this.node, this.component);
|
|
@@ -40444,7 +40533,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40444
40533
|
return undefined;
|
|
40445
40534
|
}
|
|
40446
40535
|
details = this.tsLS.getCompletionEntryDetails(location.shimPath, location.positionInShimFile, entryName, formatOptions,
|
|
40447
|
-
/* source */ undefined, preferences);
|
|
40536
|
+
/* source */ undefined, preferences, data);
|
|
40448
40537
|
}
|
|
40449
40538
|
if (details !== undefined) {
|
|
40450
40539
|
details.displayParts = filterAliasImports(details.displayParts);
|
|
@@ -40530,7 +40619,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40530
40619
|
* Get the details of a specific completion for a property expression in a global context (e.g.
|
|
40531
40620
|
* `{{y|}}`).
|
|
40532
40621
|
*/
|
|
40533
|
-
getGlobalPropertyExpressionCompletionDetails(entryName, formatOptions, preferences) {
|
|
40622
|
+
getGlobalPropertyExpressionCompletionDetails(entryName, formatOptions, preferences, data) {
|
|
40534
40623
|
const completions = this.templateTypeChecker.getGlobalCompletions(this.template, this.component, this.node);
|
|
40535
40624
|
if (completions === null) {
|
|
40536
40625
|
return undefined;
|
|
@@ -40555,7 +40644,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40555
40644
|
}
|
|
40556
40645
|
else {
|
|
40557
40646
|
return this.tsLS.getCompletionEntryDetails(componentContext.shimPath, componentContext.positionInShimFile, entryName, formatOptions,
|
|
40558
|
-
/* source */ undefined, preferences);
|
|
40647
|
+
/* source */ undefined, preferences, data);
|
|
40559
40648
|
}
|
|
40560
40649
|
}
|
|
40561
40650
|
/**
|
|
@@ -40769,14 +40858,24 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40769
40858
|
displayParts = info.displayParts;
|
|
40770
40859
|
documentation = info.documentation;
|
|
40771
40860
|
break;
|
|
40861
|
+
case AttributeCompletionKind.StructuralDirectiveAttribute:
|
|
40772
40862
|
case AttributeCompletionKind.DirectiveInput:
|
|
40773
40863
|
case AttributeCompletionKind.DirectiveOutput:
|
|
40774
40864
|
const propertySymbol = getAttributeCompletionSymbol(completion, this.typeChecker);
|
|
40775
40865
|
if (propertySymbol === null) {
|
|
40776
40866
|
return undefined;
|
|
40777
40867
|
}
|
|
40778
|
-
|
|
40779
|
-
|
|
40868
|
+
let kind;
|
|
40869
|
+
if (completion.kind === AttributeCompletionKind.DirectiveInput) {
|
|
40870
|
+
kind = DisplayInfoKind.PROPERTY;
|
|
40871
|
+
}
|
|
40872
|
+
else if (completion.kind === AttributeCompletionKind.DirectiveOutput) {
|
|
40873
|
+
kind = DisplayInfoKind.EVENT;
|
|
40874
|
+
}
|
|
40875
|
+
else {
|
|
40876
|
+
kind = DisplayInfoKind.DIRECTIVE;
|
|
40877
|
+
}
|
|
40878
|
+
info = getTsSymbolDisplayInfo(this.tsLS, this.typeChecker, propertySymbol, kind, completion.directive.tsSymbol.name);
|
|
40780
40879
|
if (info === null) {
|
|
40781
40880
|
return undefined;
|
|
40782
40881
|
}
|
|
@@ -40787,7 +40886,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40787
40886
|
name: entryName,
|
|
40788
40887
|
kind: unsafeCastDisplayInfoKindToScriptElementKind(kind),
|
|
40789
40888
|
kindModifiers: ts$1.ScriptElementKindModifier.none,
|
|
40790
|
-
displayParts
|
|
40889
|
+
displayParts,
|
|
40791
40890
|
documentation,
|
|
40792
40891
|
};
|
|
40793
40892
|
}
|
|
@@ -40920,6 +41019,240 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40920
41019
|
}
|
|
40921
41020
|
}
|
|
40922
41021
|
|
|
41022
|
+
/**
|
|
41023
|
+
* @license
|
|
41024
|
+
* Copyright Google LLC All Rights Reserved.
|
|
41025
|
+
*
|
|
41026
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
41027
|
+
* found in the LICENSE file at https://angular.io/license
|
|
41028
|
+
*/
|
|
41029
|
+
/**
|
|
41030
|
+
* Converts a `ShimLocation` to a more genericly named `FilePosition`.
|
|
41031
|
+
*/
|
|
41032
|
+
function toFilePosition(shimLocation) {
|
|
41033
|
+
return { fileName: shimLocation.shimPath, position: shimLocation.positionInShimFile };
|
|
41034
|
+
}
|
|
41035
|
+
/**
|
|
41036
|
+
* Takes a position in a template and finds equivalent targets in TS files as well as details about
|
|
41037
|
+
* the targeted template node.
|
|
41038
|
+
*/
|
|
41039
|
+
function getTargetDetailsAtTemplatePosition({ template, component }, position, templateTypeChecker) {
|
|
41040
|
+
// Find the AST node in the template at the position.
|
|
41041
|
+
const positionDetails = getTargetAtPosition(template, position);
|
|
41042
|
+
if (positionDetails === null) {
|
|
41043
|
+
return null;
|
|
41044
|
+
}
|
|
41045
|
+
const nodes = positionDetails.context.kind === TargetNodeKind.TwoWayBindingContext ?
|
|
41046
|
+
positionDetails.context.nodes :
|
|
41047
|
+
[positionDetails.context.node];
|
|
41048
|
+
const details = [];
|
|
41049
|
+
for (const node of nodes) {
|
|
41050
|
+
// Get the information about the TCB at the template position.
|
|
41051
|
+
const symbol = templateTypeChecker.getSymbolOfNode(node, component);
|
|
41052
|
+
if (symbol === null) {
|
|
41053
|
+
continue;
|
|
41054
|
+
}
|
|
41055
|
+
const templateTarget = node;
|
|
41056
|
+
switch (symbol.kind) {
|
|
41057
|
+
case SymbolKind.Directive:
|
|
41058
|
+
case SymbolKind.Template:
|
|
41059
|
+
// References to elements, templates, and directives will be through template references
|
|
41060
|
+
// (#ref). They shouldn't be used directly for a Language Service reference request.
|
|
41061
|
+
break;
|
|
41062
|
+
case SymbolKind.Element: {
|
|
41063
|
+
const matches = getDirectiveMatchesForElementTag(symbol.templateNode, symbol.directives);
|
|
41064
|
+
details.push({
|
|
41065
|
+
typescriptLocations: getPositionsForDirectives(matches),
|
|
41066
|
+
templateTarget,
|
|
41067
|
+
symbol,
|
|
41068
|
+
});
|
|
41069
|
+
break;
|
|
41070
|
+
}
|
|
41071
|
+
case SymbolKind.DomBinding: {
|
|
41072
|
+
// Dom bindings aren't currently type-checked (see `checkTypeOfDomBindings`) so they don't
|
|
41073
|
+
// have a shim location. This means we can't match dom bindings to their lib.dom
|
|
41074
|
+
// reference, but we can still see if they match to a directive.
|
|
41075
|
+
if (!(node instanceof TextAttribute) && !(node instanceof BoundAttribute)) {
|
|
41076
|
+
return null;
|
|
41077
|
+
}
|
|
41078
|
+
const directives = getDirectiveMatchesForAttribute(node.name, symbol.host.templateNode, symbol.host.directives);
|
|
41079
|
+
details.push({
|
|
41080
|
+
typescriptLocations: getPositionsForDirectives(directives),
|
|
41081
|
+
templateTarget,
|
|
41082
|
+
symbol,
|
|
41083
|
+
});
|
|
41084
|
+
break;
|
|
41085
|
+
}
|
|
41086
|
+
case SymbolKind.Reference: {
|
|
41087
|
+
details.push({
|
|
41088
|
+
typescriptLocations: [toFilePosition(symbol.referenceVarLocation)],
|
|
41089
|
+
templateTarget,
|
|
41090
|
+
symbol,
|
|
41091
|
+
});
|
|
41092
|
+
break;
|
|
41093
|
+
}
|
|
41094
|
+
case SymbolKind.Variable: {
|
|
41095
|
+
if ((templateTarget instanceof Variable)) {
|
|
41096
|
+
if (templateTarget.valueSpan !== undefined &&
|
|
41097
|
+
isWithin(position, templateTarget.valueSpan)) {
|
|
41098
|
+
// In the valueSpan of the variable, we want to get the reference of the initializer.
|
|
41099
|
+
details.push({
|
|
41100
|
+
typescriptLocations: [toFilePosition(symbol.initializerLocation)],
|
|
41101
|
+
templateTarget,
|
|
41102
|
+
symbol,
|
|
41103
|
+
});
|
|
41104
|
+
}
|
|
41105
|
+
else if (isWithin(position, templateTarget.keySpan)) {
|
|
41106
|
+
// In the keySpan of the variable, we want to get the reference of the local variable.
|
|
41107
|
+
details.push({
|
|
41108
|
+
typescriptLocations: [toFilePosition(symbol.localVarLocation)],
|
|
41109
|
+
templateTarget,
|
|
41110
|
+
symbol,
|
|
41111
|
+
});
|
|
41112
|
+
}
|
|
41113
|
+
}
|
|
41114
|
+
else {
|
|
41115
|
+
// If the templateNode is not the `TmplAstVariable`, it must be a usage of the
|
|
41116
|
+
// variable somewhere in the template.
|
|
41117
|
+
details.push({
|
|
41118
|
+
typescriptLocations: [toFilePosition(symbol.localVarLocation)],
|
|
41119
|
+
templateTarget,
|
|
41120
|
+
symbol,
|
|
41121
|
+
});
|
|
41122
|
+
}
|
|
41123
|
+
break;
|
|
41124
|
+
}
|
|
41125
|
+
case SymbolKind.Input:
|
|
41126
|
+
case SymbolKind.Output: {
|
|
41127
|
+
details.push({
|
|
41128
|
+
typescriptLocations: symbol.bindings.map(binding => toFilePosition(binding.shimLocation)),
|
|
41129
|
+
templateTarget,
|
|
41130
|
+
symbol,
|
|
41131
|
+
});
|
|
41132
|
+
break;
|
|
41133
|
+
}
|
|
41134
|
+
case SymbolKind.Pipe:
|
|
41135
|
+
case SymbolKind.Expression: {
|
|
41136
|
+
details.push({
|
|
41137
|
+
typescriptLocations: [toFilePosition(symbol.shimLocation)],
|
|
41138
|
+
templateTarget,
|
|
41139
|
+
symbol,
|
|
41140
|
+
});
|
|
41141
|
+
break;
|
|
41142
|
+
}
|
|
41143
|
+
}
|
|
41144
|
+
}
|
|
41145
|
+
return details.length > 0 ? details : null;
|
|
41146
|
+
}
|
|
41147
|
+
/**
|
|
41148
|
+
* Given a set of `DirectiveSymbol`s, finds the equivalent `FilePosition` of the class declaration.
|
|
41149
|
+
*/
|
|
41150
|
+
function getPositionsForDirectives(directives) {
|
|
41151
|
+
const allDirectives = [];
|
|
41152
|
+
for (const dir of directives.values()) {
|
|
41153
|
+
const dirClass = dir.tsSymbol.valueDeclaration;
|
|
41154
|
+
if (dirClass === undefined || !ts$1.isClassDeclaration(dirClass) || dirClass.name === undefined) {
|
|
41155
|
+
continue;
|
|
41156
|
+
}
|
|
41157
|
+
const { fileName } = dirClass.getSourceFile();
|
|
41158
|
+
const position = dirClass.name.getStart();
|
|
41159
|
+
allDirectives.push({ fileName, position });
|
|
41160
|
+
}
|
|
41161
|
+
return allDirectives;
|
|
41162
|
+
}
|
|
41163
|
+
/**
|
|
41164
|
+
* Creates a "key" for a rename/reference location by concatenating file name, span start, and span
|
|
41165
|
+
* length. This allows us to de-duplicate template results when an item may appear several times
|
|
41166
|
+
* in the TCB but map back to the same template location.
|
|
41167
|
+
*/
|
|
41168
|
+
function createLocationKey(ds) {
|
|
41169
|
+
return ds.fileName + ds.textSpan.start + ds.textSpan.length;
|
|
41170
|
+
}
|
|
41171
|
+
/**
|
|
41172
|
+
* Converts a given `ts.DocumentSpan` in a shim file to its equivalent `ts.DocumentSpan` in the
|
|
41173
|
+
* template.
|
|
41174
|
+
*
|
|
41175
|
+
* You can optionally provide a `requiredNodeText` that ensures the equivalent template node's text
|
|
41176
|
+
* matches. If it does not, this function will return `null`.
|
|
41177
|
+
*/
|
|
41178
|
+
function convertToTemplateDocumentSpan(shimDocumentSpan, templateTypeChecker, program, requiredNodeText) {
|
|
41179
|
+
const sf = program.getSourceFile(shimDocumentSpan.fileName);
|
|
41180
|
+
if (sf === undefined) {
|
|
41181
|
+
return null;
|
|
41182
|
+
}
|
|
41183
|
+
const tcbNode = findTightestNode(sf, shimDocumentSpan.textSpan.start);
|
|
41184
|
+
if (tcbNode === undefined ||
|
|
41185
|
+
hasExpressionIdentifier(sf, tcbNode, ExpressionIdentifier.EVENT_PARAMETER)) {
|
|
41186
|
+
// If the reference result is the $event parameter in the subscribe/addEventListener
|
|
41187
|
+
// function in the TCB, we want to filter this result out of the references. We really only
|
|
41188
|
+
// want to return references to the parameter in the template itself.
|
|
41189
|
+
return null;
|
|
41190
|
+
}
|
|
41191
|
+
// TODO(atscott): Determine how to consistently resolve paths. i.e. with the project
|
|
41192
|
+
// serverHost or LSParseConfigHost in the adapter. We should have a better defined way to
|
|
41193
|
+
// normalize paths.
|
|
41194
|
+
const mapping = getTemplateLocationFromShimLocation(templateTypeChecker, absoluteFrom(shimDocumentSpan.fileName), shimDocumentSpan.textSpan.start);
|
|
41195
|
+
if (mapping === null) {
|
|
41196
|
+
return null;
|
|
41197
|
+
}
|
|
41198
|
+
const { span, templateUrl } = mapping;
|
|
41199
|
+
if (requiredNodeText !== undefined && span.toString() !== requiredNodeText) {
|
|
41200
|
+
return null;
|
|
41201
|
+
}
|
|
41202
|
+
return Object.assign(Object.assign({}, shimDocumentSpan), { fileName: templateUrl, textSpan: toTextSpan(span),
|
|
41203
|
+
// Specifically clear other text span values because we do not have enough knowledge to
|
|
41204
|
+
// convert these to spans in the template.
|
|
41205
|
+
contextSpan: undefined, originalContextSpan: undefined, originalTextSpan: undefined });
|
|
41206
|
+
}
|
|
41207
|
+
/**
|
|
41208
|
+
* Finds the text and `ts.TextSpan` for the node at a position in a template.
|
|
41209
|
+
*/
|
|
41210
|
+
function getRenameTextAndSpanAtPosition(node, position) {
|
|
41211
|
+
if (node instanceof BoundAttribute || node instanceof TextAttribute ||
|
|
41212
|
+
node instanceof BoundEvent) {
|
|
41213
|
+
if (node.keySpan === undefined) {
|
|
41214
|
+
return null;
|
|
41215
|
+
}
|
|
41216
|
+
return { text: node.name, span: toTextSpan(node.keySpan) };
|
|
41217
|
+
}
|
|
41218
|
+
else if (node instanceof Variable || node instanceof Reference) {
|
|
41219
|
+
if (isWithin(position, node.keySpan)) {
|
|
41220
|
+
return { text: node.keySpan.toString(), span: toTextSpan(node.keySpan) };
|
|
41221
|
+
}
|
|
41222
|
+
else if (node.valueSpan && isWithin(position, node.valueSpan)) {
|
|
41223
|
+
return { text: node.valueSpan.toString(), span: toTextSpan(node.valueSpan) };
|
|
41224
|
+
}
|
|
41225
|
+
}
|
|
41226
|
+
if (node instanceof PropertyRead || node instanceof MethodCall || node instanceof PropertyWrite ||
|
|
41227
|
+
node instanceof SafePropertyRead || node instanceof SafeMethodCall ||
|
|
41228
|
+
node instanceof BindingPipe) {
|
|
41229
|
+
return { text: node.name, span: toTextSpan(node.nameSpan) };
|
|
41230
|
+
}
|
|
41231
|
+
else if (node instanceof LiteralPrimitive) {
|
|
41232
|
+
const span = toTextSpan(node.sourceSpan);
|
|
41233
|
+
const text = node.value;
|
|
41234
|
+
if (typeof text === 'string') {
|
|
41235
|
+
// The span of a string literal includes the quotes but they should be removed for renaming.
|
|
41236
|
+
span.start += 1;
|
|
41237
|
+
span.length -= 2;
|
|
41238
|
+
}
|
|
41239
|
+
return { text, span };
|
|
41240
|
+
}
|
|
41241
|
+
return null;
|
|
41242
|
+
}
|
|
41243
|
+
/**
|
|
41244
|
+
* Retrives the `PipeMeta` or `DirectiveMeta` of the given `ts.Node`'s parent class.
|
|
41245
|
+
*
|
|
41246
|
+
* Returns `null` if the node has no parent class or there is no meta associated with the class.
|
|
41247
|
+
*/
|
|
41248
|
+
function getParentClassMeta(requestNode, compiler) {
|
|
41249
|
+
const parentClass = getParentClassDeclaration(requestNode);
|
|
41250
|
+
if (parentClass === undefined) {
|
|
41251
|
+
return null;
|
|
41252
|
+
}
|
|
41253
|
+
return compiler.getMeta(parentClass);
|
|
41254
|
+
}
|
|
41255
|
+
|
|
40923
41256
|
/**
|
|
40924
41257
|
* @license
|
|
40925
41258
|
* Copyright Google LLC All Rights Reserved.
|
|
@@ -40928,9 +41261,11 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
40928
41261
|
* found in the LICENSE file at https://angular.io/license
|
|
40929
41262
|
*/
|
|
40930
41263
|
class DefinitionBuilder {
|
|
40931
|
-
constructor(tsLS, compiler) {
|
|
41264
|
+
constructor(tsLS, compiler, driver) {
|
|
40932
41265
|
this.tsLS = tsLS;
|
|
40933
41266
|
this.compiler = compiler;
|
|
41267
|
+
this.driver = driver;
|
|
41268
|
+
this.ttc = this.compiler.getTemplateTypeChecker();
|
|
40934
41269
|
}
|
|
40935
41270
|
getDefinitionAndBoundSpan(fileName, position) {
|
|
40936
41271
|
var _a;
|
|
@@ -41025,11 +41360,34 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41025
41360
|
}
|
|
41026
41361
|
getDefinitionsForSymbols(...symbols) {
|
|
41027
41362
|
return flatMap(symbols, ({ shimLocation }) => {
|
|
41028
|
-
var _a;
|
|
41029
41363
|
const { shimPath, positionInShimFile } = shimLocation;
|
|
41030
|
-
|
|
41364
|
+
const definitionInfos = this.tsLS.getDefinitionAtPosition(shimPath, positionInShimFile);
|
|
41365
|
+
if (definitionInfos === undefined) {
|
|
41366
|
+
return [];
|
|
41367
|
+
}
|
|
41368
|
+
return this.mapShimResultsToTemplates(definitionInfos);
|
|
41031
41369
|
});
|
|
41032
41370
|
}
|
|
41371
|
+
/**
|
|
41372
|
+
* Converts and definition info result that points to a template typecheck file to a reference to
|
|
41373
|
+
* the corresponding location in the template.
|
|
41374
|
+
*/
|
|
41375
|
+
mapShimResultsToTemplates(definitionInfos) {
|
|
41376
|
+
const result = [];
|
|
41377
|
+
for (const info of definitionInfos) {
|
|
41378
|
+
if (this.ttc.isTrackedTypeCheckFile(absoluteFrom(info.fileName))) {
|
|
41379
|
+
const templateDefinitionInfo = convertToTemplateDocumentSpan(info, this.ttc, this.driver.getProgram());
|
|
41380
|
+
if (templateDefinitionInfo === null) {
|
|
41381
|
+
continue;
|
|
41382
|
+
}
|
|
41383
|
+
result.push(templateDefinitionInfo);
|
|
41384
|
+
}
|
|
41385
|
+
else {
|
|
41386
|
+
result.push(info);
|
|
41387
|
+
}
|
|
41388
|
+
}
|
|
41389
|
+
return result;
|
|
41390
|
+
}
|
|
41033
41391
|
getTypeDefinitionsAtPosition(fileName, position) {
|
|
41034
41392
|
const templateInfo = getTemplateInfoAtPosition(fileName, position, this.compiler);
|
|
41035
41393
|
if (templateInfo === undefined) {
|
|
@@ -41380,240 +41738,6 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41380
41738
|
};
|
|
41381
41739
|
}
|
|
41382
41740
|
|
|
41383
|
-
/**
|
|
41384
|
-
* @license
|
|
41385
|
-
* Copyright Google LLC All Rights Reserved.
|
|
41386
|
-
*
|
|
41387
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
41388
|
-
* found in the LICENSE file at https://angular.io/license
|
|
41389
|
-
*/
|
|
41390
|
-
/**
|
|
41391
|
-
* Converts a `ShimLocation` to a more genericly named `FilePosition`.
|
|
41392
|
-
*/
|
|
41393
|
-
function toFilePosition(shimLocation) {
|
|
41394
|
-
return { fileName: shimLocation.shimPath, position: shimLocation.positionInShimFile };
|
|
41395
|
-
}
|
|
41396
|
-
/**
|
|
41397
|
-
* Takes a position in a template and finds equivalent targets in TS files as well as details about
|
|
41398
|
-
* the targeted template node.
|
|
41399
|
-
*/
|
|
41400
|
-
function getTargetDetailsAtTemplatePosition({ template, component }, position, templateTypeChecker) {
|
|
41401
|
-
// Find the AST node in the template at the position.
|
|
41402
|
-
const positionDetails = getTargetAtPosition(template, position);
|
|
41403
|
-
if (positionDetails === null) {
|
|
41404
|
-
return null;
|
|
41405
|
-
}
|
|
41406
|
-
const nodes = positionDetails.context.kind === TargetNodeKind.TwoWayBindingContext ?
|
|
41407
|
-
positionDetails.context.nodes :
|
|
41408
|
-
[positionDetails.context.node];
|
|
41409
|
-
const details = [];
|
|
41410
|
-
for (const node of nodes) {
|
|
41411
|
-
// Get the information about the TCB at the template position.
|
|
41412
|
-
const symbol = templateTypeChecker.getSymbolOfNode(node, component);
|
|
41413
|
-
if (symbol === null) {
|
|
41414
|
-
continue;
|
|
41415
|
-
}
|
|
41416
|
-
const templateTarget = node;
|
|
41417
|
-
switch (symbol.kind) {
|
|
41418
|
-
case SymbolKind.Directive:
|
|
41419
|
-
case SymbolKind.Template:
|
|
41420
|
-
// References to elements, templates, and directives will be through template references
|
|
41421
|
-
// (#ref). They shouldn't be used directly for a Language Service reference request.
|
|
41422
|
-
break;
|
|
41423
|
-
case SymbolKind.Element: {
|
|
41424
|
-
const matches = getDirectiveMatchesForElementTag(symbol.templateNode, symbol.directives);
|
|
41425
|
-
details.push({
|
|
41426
|
-
typescriptLocations: getPositionsForDirectives(matches),
|
|
41427
|
-
templateTarget,
|
|
41428
|
-
symbol,
|
|
41429
|
-
});
|
|
41430
|
-
break;
|
|
41431
|
-
}
|
|
41432
|
-
case SymbolKind.DomBinding: {
|
|
41433
|
-
// Dom bindings aren't currently type-checked (see `checkTypeOfDomBindings`) so they don't
|
|
41434
|
-
// have a shim location. This means we can't match dom bindings to their lib.dom
|
|
41435
|
-
// reference, but we can still see if they match to a directive.
|
|
41436
|
-
if (!(node instanceof TextAttribute) && !(node instanceof BoundAttribute)) {
|
|
41437
|
-
return null;
|
|
41438
|
-
}
|
|
41439
|
-
const directives = getDirectiveMatchesForAttribute(node.name, symbol.host.templateNode, symbol.host.directives);
|
|
41440
|
-
details.push({
|
|
41441
|
-
typescriptLocations: getPositionsForDirectives(directives),
|
|
41442
|
-
templateTarget,
|
|
41443
|
-
symbol,
|
|
41444
|
-
});
|
|
41445
|
-
break;
|
|
41446
|
-
}
|
|
41447
|
-
case SymbolKind.Reference: {
|
|
41448
|
-
details.push({
|
|
41449
|
-
typescriptLocations: [toFilePosition(symbol.referenceVarLocation)],
|
|
41450
|
-
templateTarget,
|
|
41451
|
-
symbol,
|
|
41452
|
-
});
|
|
41453
|
-
break;
|
|
41454
|
-
}
|
|
41455
|
-
case SymbolKind.Variable: {
|
|
41456
|
-
if ((templateTarget instanceof Variable)) {
|
|
41457
|
-
if (templateTarget.valueSpan !== undefined &&
|
|
41458
|
-
isWithin(position, templateTarget.valueSpan)) {
|
|
41459
|
-
// In the valueSpan of the variable, we want to get the reference of the initializer.
|
|
41460
|
-
details.push({
|
|
41461
|
-
typescriptLocations: [toFilePosition(symbol.initializerLocation)],
|
|
41462
|
-
templateTarget,
|
|
41463
|
-
symbol,
|
|
41464
|
-
});
|
|
41465
|
-
}
|
|
41466
|
-
else if (isWithin(position, templateTarget.keySpan)) {
|
|
41467
|
-
// In the keySpan of the variable, we want to get the reference of the local variable.
|
|
41468
|
-
details.push({
|
|
41469
|
-
typescriptLocations: [toFilePosition(symbol.localVarLocation)],
|
|
41470
|
-
templateTarget,
|
|
41471
|
-
symbol,
|
|
41472
|
-
});
|
|
41473
|
-
}
|
|
41474
|
-
}
|
|
41475
|
-
else {
|
|
41476
|
-
// If the templateNode is not the `TmplAstVariable`, it must be a usage of the
|
|
41477
|
-
// variable somewhere in the template.
|
|
41478
|
-
details.push({
|
|
41479
|
-
typescriptLocations: [toFilePosition(symbol.localVarLocation)],
|
|
41480
|
-
templateTarget,
|
|
41481
|
-
symbol,
|
|
41482
|
-
});
|
|
41483
|
-
}
|
|
41484
|
-
break;
|
|
41485
|
-
}
|
|
41486
|
-
case SymbolKind.Input:
|
|
41487
|
-
case SymbolKind.Output: {
|
|
41488
|
-
details.push({
|
|
41489
|
-
typescriptLocations: symbol.bindings.map(binding => toFilePosition(binding.shimLocation)),
|
|
41490
|
-
templateTarget,
|
|
41491
|
-
symbol,
|
|
41492
|
-
});
|
|
41493
|
-
break;
|
|
41494
|
-
}
|
|
41495
|
-
case SymbolKind.Pipe:
|
|
41496
|
-
case SymbolKind.Expression: {
|
|
41497
|
-
details.push({
|
|
41498
|
-
typescriptLocations: [toFilePosition(symbol.shimLocation)],
|
|
41499
|
-
templateTarget,
|
|
41500
|
-
symbol,
|
|
41501
|
-
});
|
|
41502
|
-
break;
|
|
41503
|
-
}
|
|
41504
|
-
}
|
|
41505
|
-
}
|
|
41506
|
-
return details.length > 0 ? details : null;
|
|
41507
|
-
}
|
|
41508
|
-
/**
|
|
41509
|
-
* Given a set of `DirectiveSymbol`s, finds the equivalent `FilePosition` of the class declaration.
|
|
41510
|
-
*/
|
|
41511
|
-
function getPositionsForDirectives(directives) {
|
|
41512
|
-
const allDirectives = [];
|
|
41513
|
-
for (const dir of directives.values()) {
|
|
41514
|
-
const dirClass = dir.tsSymbol.valueDeclaration;
|
|
41515
|
-
if (dirClass === undefined || !ts$1.isClassDeclaration(dirClass) || dirClass.name === undefined) {
|
|
41516
|
-
continue;
|
|
41517
|
-
}
|
|
41518
|
-
const { fileName } = dirClass.getSourceFile();
|
|
41519
|
-
const position = dirClass.name.getStart();
|
|
41520
|
-
allDirectives.push({ fileName, position });
|
|
41521
|
-
}
|
|
41522
|
-
return allDirectives;
|
|
41523
|
-
}
|
|
41524
|
-
/**
|
|
41525
|
-
* Creates a "key" for a rename/reference location by concatenating file name, span start, and span
|
|
41526
|
-
* length. This allows us to de-duplicate template results when an item may appear several times
|
|
41527
|
-
* in the TCB but map back to the same template location.
|
|
41528
|
-
*/
|
|
41529
|
-
function createLocationKey(ds) {
|
|
41530
|
-
return ds.fileName + ds.textSpan.start + ds.textSpan.length;
|
|
41531
|
-
}
|
|
41532
|
-
/**
|
|
41533
|
-
* Converts a given `ts.DocumentSpan` in a shim file to its equivalent `ts.DocumentSpan` in the
|
|
41534
|
-
* template.
|
|
41535
|
-
*
|
|
41536
|
-
* You can optionally provide a `requiredNodeText` that ensures the equivalent template node's text
|
|
41537
|
-
* matches. If it does not, this function will return `null`.
|
|
41538
|
-
*/
|
|
41539
|
-
function convertToTemplateDocumentSpan(shimDocumentSpan, templateTypeChecker, program, requiredNodeText) {
|
|
41540
|
-
const sf = program.getSourceFile(shimDocumentSpan.fileName);
|
|
41541
|
-
if (sf === undefined) {
|
|
41542
|
-
return null;
|
|
41543
|
-
}
|
|
41544
|
-
const tcbNode = findTightestNode(sf, shimDocumentSpan.textSpan.start);
|
|
41545
|
-
if (tcbNode === undefined ||
|
|
41546
|
-
hasExpressionIdentifier(sf, tcbNode, ExpressionIdentifier.EVENT_PARAMETER)) {
|
|
41547
|
-
// If the reference result is the $event parameter in the subscribe/addEventListener
|
|
41548
|
-
// function in the TCB, we want to filter this result out of the references. We really only
|
|
41549
|
-
// want to return references to the parameter in the template itself.
|
|
41550
|
-
return null;
|
|
41551
|
-
}
|
|
41552
|
-
// TODO(atscott): Determine how to consistently resolve paths. i.e. with the project
|
|
41553
|
-
// serverHost or LSParseConfigHost in the adapter. We should have a better defined way to
|
|
41554
|
-
// normalize paths.
|
|
41555
|
-
const mapping = getTemplateLocationFromShimLocation(templateTypeChecker, absoluteFrom(shimDocumentSpan.fileName), shimDocumentSpan.textSpan.start);
|
|
41556
|
-
if (mapping === null) {
|
|
41557
|
-
return null;
|
|
41558
|
-
}
|
|
41559
|
-
const { span, templateUrl } = mapping;
|
|
41560
|
-
if (requiredNodeText !== undefined && span.toString() !== requiredNodeText) {
|
|
41561
|
-
return null;
|
|
41562
|
-
}
|
|
41563
|
-
return Object.assign(Object.assign({}, shimDocumentSpan), { fileName: templateUrl, textSpan: toTextSpan(span),
|
|
41564
|
-
// Specifically clear other text span values because we do not have enough knowledge to
|
|
41565
|
-
// convert these to spans in the template.
|
|
41566
|
-
contextSpan: undefined, originalContextSpan: undefined, originalTextSpan: undefined });
|
|
41567
|
-
}
|
|
41568
|
-
/**
|
|
41569
|
-
* Finds the text and `ts.TextSpan` for the node at a position in a template.
|
|
41570
|
-
*/
|
|
41571
|
-
function getRenameTextAndSpanAtPosition(node, position) {
|
|
41572
|
-
if (node instanceof BoundAttribute || node instanceof TextAttribute ||
|
|
41573
|
-
node instanceof BoundEvent) {
|
|
41574
|
-
if (node.keySpan === undefined) {
|
|
41575
|
-
return null;
|
|
41576
|
-
}
|
|
41577
|
-
return { text: node.name, span: toTextSpan(node.keySpan) };
|
|
41578
|
-
}
|
|
41579
|
-
else if (node instanceof Variable || node instanceof Reference) {
|
|
41580
|
-
if (isWithin(position, node.keySpan)) {
|
|
41581
|
-
return { text: node.keySpan.toString(), span: toTextSpan(node.keySpan) };
|
|
41582
|
-
}
|
|
41583
|
-
else if (node.valueSpan && isWithin(position, node.valueSpan)) {
|
|
41584
|
-
return { text: node.valueSpan.toString(), span: toTextSpan(node.valueSpan) };
|
|
41585
|
-
}
|
|
41586
|
-
}
|
|
41587
|
-
if (node instanceof PropertyRead || node instanceof MethodCall || node instanceof PropertyWrite ||
|
|
41588
|
-
node instanceof SafePropertyRead || node instanceof SafeMethodCall ||
|
|
41589
|
-
node instanceof BindingPipe) {
|
|
41590
|
-
return { text: node.name, span: toTextSpan(node.nameSpan) };
|
|
41591
|
-
}
|
|
41592
|
-
else if (node instanceof LiteralPrimitive) {
|
|
41593
|
-
const span = toTextSpan(node.sourceSpan);
|
|
41594
|
-
const text = node.value;
|
|
41595
|
-
if (typeof text === 'string') {
|
|
41596
|
-
// The span of a string literal includes the quotes but they should be removed for renaming.
|
|
41597
|
-
span.start += 1;
|
|
41598
|
-
span.length -= 2;
|
|
41599
|
-
}
|
|
41600
|
-
return { text, span };
|
|
41601
|
-
}
|
|
41602
|
-
return null;
|
|
41603
|
-
}
|
|
41604
|
-
/**
|
|
41605
|
-
* Retrives the `PipeMeta` or `DirectiveMeta` of the given `ts.Node`'s parent class.
|
|
41606
|
-
*
|
|
41607
|
-
* Returns `null` if the node has no parent class or there is no meta associated with the class.
|
|
41608
|
-
*/
|
|
41609
|
-
function getParentClassMeta(requestNode, compiler) {
|
|
41610
|
-
const parentClass = getParentClassDeclaration(requestNode);
|
|
41611
|
-
if (parentClass === undefined) {
|
|
41612
|
-
return null;
|
|
41613
|
-
}
|
|
41614
|
-
return compiler.getMeta(parentClass);
|
|
41615
|
-
}
|
|
41616
|
-
|
|
41617
41741
|
class ReferencesBuilder {
|
|
41618
41742
|
constructor(driver, tsLS, compiler) {
|
|
41619
41743
|
this.driver = driver;
|
|
@@ -41689,7 +41813,30 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
41689
41813
|
// We could not get a template at position so we assume the request came from outside the
|
|
41690
41814
|
// template.
|
|
41691
41815
|
if (templateInfo === undefined) {
|
|
41692
|
-
|
|
41816
|
+
const renameRequest = this.buildRenameRequestAtTypescriptPosition(filePath, position);
|
|
41817
|
+
if (renameRequest === null) {
|
|
41818
|
+
return {
|
|
41819
|
+
canRename: false,
|
|
41820
|
+
localizedErrorMessage: 'Could not determine rename info at typescript position.',
|
|
41821
|
+
};
|
|
41822
|
+
}
|
|
41823
|
+
if (renameRequest.type === RequestKind.PipeName) {
|
|
41824
|
+
const pipeName = renameRequest.pipeNameExpr.text;
|
|
41825
|
+
return {
|
|
41826
|
+
canRename: true,
|
|
41827
|
+
displayName: pipeName,
|
|
41828
|
+
fullDisplayName: pipeName,
|
|
41829
|
+
triggerSpan: {
|
|
41830
|
+
length: pipeName.length,
|
|
41831
|
+
// Offset the pipe name by 1 to account for start of string '/`/"
|
|
41832
|
+
start: renameRequest.pipeNameExpr.getStart() + 1,
|
|
41833
|
+
},
|
|
41834
|
+
};
|
|
41835
|
+
}
|
|
41836
|
+
else {
|
|
41837
|
+
// TODO(atscott): Add support for other special indirect renames from typescript files.
|
|
41838
|
+
return this.tsLS.getRenameInfo(filePath, position);
|
|
41839
|
+
}
|
|
41693
41840
|
}
|
|
41694
41841
|
const allTargetDetails = getTargetDetailsAtTemplatePosition(templateInfo, position, this.ttc);
|
|
41695
41842
|
if (allTargetDetails === null) {
|
|
@@ -42088,7 +42235,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
42088
42235
|
if (!isInAngularContext(compiler.getCurrentProgram(), fileName, position)) {
|
|
42089
42236
|
return undefined;
|
|
42090
42237
|
}
|
|
42091
|
-
return new DefinitionBuilder(this.tsLS, compiler)
|
|
42238
|
+
return new DefinitionBuilder(this.tsLS, compiler, this.programDriver)
|
|
42092
42239
|
.getDefinitionAndBoundSpan(fileName, position);
|
|
42093
42240
|
});
|
|
42094
42241
|
}
|
|
@@ -42097,7 +42244,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
42097
42244
|
if (!isTemplateContext(compiler.getCurrentProgram(), fileName, position)) {
|
|
42098
42245
|
return undefined;
|
|
42099
42246
|
}
|
|
42100
|
-
return new DefinitionBuilder(this.tsLS, compiler)
|
|
42247
|
+
return new DefinitionBuilder(this.tsLS, compiler, this.programDriver)
|
|
42101
42248
|
.getTypeDefinitionsAtPosition(fileName, position);
|
|
42102
42249
|
});
|
|
42103
42250
|
}
|
|
@@ -42185,7 +42332,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
42185
42332
|
}
|
|
42186
42333
|
return builder.getCompletionsAtPosition(options);
|
|
42187
42334
|
}
|
|
42188
|
-
getCompletionEntryDetails(fileName, position, entryName, formatOptions, preferences) {
|
|
42335
|
+
getCompletionEntryDetails(fileName, position, entryName, formatOptions, preferences, data) {
|
|
42189
42336
|
return this.withCompilerAndPerfTracing(PerfPhase.LsCompletions, (compiler) => {
|
|
42190
42337
|
if (!isTemplateContext(compiler.getCurrentProgram(), fileName, position)) {
|
|
42191
42338
|
return undefined;
|
|
@@ -42194,7 +42341,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
42194
42341
|
if (builder === null) {
|
|
42195
42342
|
return undefined;
|
|
42196
42343
|
}
|
|
42197
|
-
return builder.getCompletionEntryDetails(entryName, formatOptions, preferences);
|
|
42344
|
+
return builder.getCompletionEntryDetails(entryName, formatOptions, preferences, data);
|
|
42198
42345
|
});
|
|
42199
42346
|
}
|
|
42200
42347
|
getSignatureHelpItems(fileName, position, options) {
|
|
@@ -42541,14 +42688,14 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
|
|
|
42541
42688
|
return (_a = tsLS.getCompletionsAtPosition(fileName, position, options)) !== null && _a !== void 0 ? _a : ngLS.getCompletionsAtPosition(fileName, position, options);
|
|
42542
42689
|
}
|
|
42543
42690
|
}
|
|
42544
|
-
function getCompletionEntryDetails(fileName, position, entryName, formatOptions, source, preferences) {
|
|
42691
|
+
function getCompletionEntryDetails(fileName, position, entryName, formatOptions, source, preferences, data) {
|
|
42545
42692
|
var _a;
|
|
42546
42693
|
if (angularOnly) {
|
|
42547
|
-
return ngLS.getCompletionEntryDetails(fileName, position, entryName, formatOptions, preferences);
|
|
42694
|
+
return ngLS.getCompletionEntryDetails(fileName, position, entryName, formatOptions, preferences, data);
|
|
42548
42695
|
}
|
|
42549
42696
|
else {
|
|
42550
42697
|
// If TS could answer the query, then return that result. Otherwise, return from Angular LS.
|
|
42551
|
-
return (_a = tsLS.getCompletionEntryDetails(fileName, position, entryName, formatOptions, source, preferences)) !== null && _a !== void 0 ? _a : ngLS.getCompletionEntryDetails(fileName, position, entryName, formatOptions, preferences);
|
|
42698
|
+
return (_a = tsLS.getCompletionEntryDetails(fileName, position, entryName, formatOptions, source, preferences, data)) !== null && _a !== void 0 ? _a : ngLS.getCompletionEntryDetails(fileName, position, entryName, formatOptions, preferences, data);
|
|
42552
42699
|
}
|
|
42553
42700
|
}
|
|
42554
42701
|
function getCompletionEntrySymbol(fileName, position, name, source) {
|