@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 CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v12.1.0-next.4
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, obj, key) {
6532
+ constructor(span, sourceSpan, receiver, key) {
6534
6533
  super(span, sourceSpan);
6535
- this.obj = obj;
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, obj, key, value) {
6552
+ constructor(span, sourceSpan, receiver, key, value) {
6544
6553
  super(span, sourceSpan);
6545
- this.obj = obj;
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.obj, context);
6803
+ this.visit(ast.receiver, context);
6795
6804
  this.visit(ast.key, context);
6796
6805
  }
6797
6806
  visitKeyedWrite(ast, context) {
6798
- this.visit(ast.obj, context);
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.obj.visit(this), ast.key.visit(this));
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.obj.visit(this), ast.key.visit(this), ast.value.visit(this));
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.obj.visit(this);
7071
+ const obj = ast.receiver.visit(this);
7056
7072
  const key = ast.key.visit(this);
7057
- if (obj !== ast.obj || key !== ast.key) {
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.obj.visit(this);
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.obj || key !== ast.key || value !== ast.value) {
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.obj, _Mode.Expression).key(this._visit(ast.key, _Mode.Expression)));
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.obj, _Mode.Expression);
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.obj);
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._cursor.peek() === $LT || this._cursor.peek() === $EOF) {
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 true;
10208
+ return !unexpectedCloseTagDetected;
10147
10209
  }
10148
10210
  if (!this.getTagDefinition(el.name).closedByParent) {
10149
- return false;
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.parseAccessMemberOrMethodCall(result, start, true);
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.withContext(ParseContextFlags.Writable, () => {
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
- this.expectCharacter($COLON);
12785
- values.push(this.parsePipe());
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 = false) {
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.0-next.4');
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.0-next.4'));
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.0-next.4'));
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.0-next.4'));
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.0-next.4'));
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.0-next.4'));
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.0-next.4'));
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.0-next.4'));
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.0-next.4');
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, 7 /* UNKNOWN */);
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 === 7 /* UNKNOWN */;
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 /* UNKNOWN */:
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 (_b) {
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: (_a = template.interpolationConfig) !== null && _a !== void 0 ? _a : DEFAULT_INTERPOLATION_CONFIG, styles,
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
- return this.step.priorState.traitCompiler.recordsFor(sf);
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 visitTypeNode(type, {
33179
- visitTypeReferenceNode: type => canEmitTypeReference(type),
33180
- visitArrayTypeNode: type => canEmitTypeWorker(type.elementType),
33181
- visitKeywordType: () => true,
33182
- visitLiteralType: () => true,
33183
- visitOtherType: () => false,
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 without a owning module, consider the type not to be eligible for
33193
- // emitting.
33194
- if (reference instanceof Reference$1 && !reference.hasOwningModuleGuess) {
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
- return visitTypeNode(type, {
33238
- visitTypeReferenceNode: type => this.emitTypeReference(type),
33239
- visitArrayTypeNode: type => ts$1.updateArrayTypeNode(type, this.emitType(type.elementType)),
33240
- visitKeywordType: type => type,
33241
- visitLiteralType: type => type,
33242
- visitOtherType: () => {
33243
- throw new Error('Unable to emit a complex type');
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
- if (typeParam.constraint === undefined) {
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 */ typeParam.default);
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.obj));
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.obj));
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
- return ast.receiver.visit(VeSafeLhsInferenceBugDetector.SINGLETON);
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 === null ||
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 === undefined || tsSymbol.declarations.length === 0 || selector === null) {
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 === null ||
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
- if (pipeInstance === null || pipeInstance.tsSymbol === null) {
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 = findFirstMatchingNode(this.typeCheckBlock, { withSpan, filter: (n) => true });
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 === undefined) {
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 || (!ts$1.isPropertyDeclaration(decl) && !ts$1.isMethodDeclaration(decl)) ||
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) && 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 ((ast instanceof Element || ast instanceof Template) && ast.endSourceSpan) {
40295
- result.end = ast.endSourceSpan.end.offset;
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
- info = getTsSymbolDisplayInfo(this.tsLS, this.typeChecker, propertySymbol, completion.kind === AttributeCompletionKind.DirectiveInput ? DisplayInfoKind.PROPERTY :
40779
- DisplayInfoKind.EVENT, completion.directive.tsSymbol.name);
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
- return (_a = this.tsLS.getDefinitionAtPosition(shimPath, positionInShimFile)) !== null && _a !== void 0 ? _a : [];
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
- return this.tsLS.getRenameInfo(filePath, position);
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) {