@angular/language-service 11.2.9 → 11.2.13

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 v11.2.9
2
+ * @license Angular v11.2.13
3
3
  * Copyright Google LLC All Rights Reserved.
4
4
  * License: MIT
5
5
  */
@@ -11099,6 +11099,34 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
11099
11099
  rule.selector.startsWith('@page') || rule.selector.startsWith('@document')) {
11100
11100
  content = this._scopeSelectors(rule.content, scopeSelector, hostSelector);
11101
11101
  }
11102
+ else if (rule.selector.startsWith('@font-face')) {
11103
+ content = this._stripScopingSelectors(rule.content, scopeSelector, hostSelector);
11104
+ }
11105
+ return new CssRule(selector, content);
11106
+ });
11107
+ }
11108
+ /**
11109
+ * Handle a css text that is within a rule that should not contain scope selectors by simply
11110
+ * removing them! An example of such a rule is `@font-face`.
11111
+ *
11112
+ * `@font-face` rules cannot contain nested selectors. Nor can they be nested under a selector.
11113
+ * Normally this would be a syntax error by the author of the styles. But in some rare cases, such
11114
+ * as importing styles from a library, and applying `:host ::ng-deep` to the imported styles, we
11115
+ * can end up with broken css if the imported styles happen to contain @font-face rules.
11116
+ *
11117
+ * For example:
11118
+ *
11119
+ * ```
11120
+ * :host ::ng-deep {
11121
+ * import 'some/lib/containing/font-face';
11122
+ * }
11123
+ * ```
11124
+ */
11125
+ _stripScopingSelectors(cssText, scopeSelector, hostSelector) {
11126
+ return processRules(cssText, rule => {
11127
+ const selector = rule.selector.replace(_shadowDeepSelectors, ' ')
11128
+ .replace(_polyfillHostNoCombinatorRe, ' ');
11129
+ const content = this._scopeSelectors(rule.content, scopeSelector, hostSelector);
11102
11130
  return new CssRule(selector, content);
11103
11131
  });
11104
11132
  }
@@ -20399,7 +20427,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
20399
20427
  * Use of this source code is governed by an MIT-style license that can be
20400
20428
  * found in the LICENSE file at https://angular.io/license
20401
20429
  */
20402
- const VERSION$1 = new Version('11.2.9');
20430
+ const VERSION$1 = new Version('11.2.13');
20403
20431
 
20404
20432
  /**
20405
20433
  * @license
@@ -21056,7 +21084,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
21056
21084
  */
21057
21085
  function createDirectiveDefinitionMap(meta) {
21058
21086
  const definitionMap = new DefinitionMap();
21059
- definitionMap.set('version', literal('11.2.9'));
21087
+ definitionMap.set('version', literal('11.2.13'));
21060
21088
  // e.g. `type: MyDirective`
21061
21089
  definitionMap.set('type', meta.internalType);
21062
21090
  // e.g. `selector: 'some-dir'`
@@ -21277,7 +21305,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
21277
21305
  */
21278
21306
  function createPipeDefinitionMap(meta) {
21279
21307
  const definitionMap = new DefinitionMap();
21280
- definitionMap.set('version', literal('11.2.9'));
21308
+ definitionMap.set('version', literal('11.2.13'));
21281
21309
  definitionMap.set('ngImport', importExpr(Identifiers$1.core));
21282
21310
  // e.g. `type: MyPipe`
21283
21311
  definitionMap.set('type', meta.internalType);
@@ -21309,7 +21337,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
21309
21337
  * Use of this source code is governed by an MIT-style license that can be
21310
21338
  * found in the LICENSE file at https://angular.io/license
21311
21339
  */
21312
- const VERSION$2 = new Version('11.2.9');
21340
+ const VERSION$2 = new Version('11.2.13');
21313
21341
 
21314
21342
  /**
21315
21343
  * @license
@@ -21459,6 +21487,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
21459
21487
  * Raised when a directive/pipe is part of the declarations of two or more NgModules.
21460
21488
  */
21461
21489
  ErrorCode[ErrorCode["NGMODULE_DECLARATION_NOT_UNIQUE"] = 6007] = "NGMODULE_DECLARATION_NOT_UNIQUE";
21490
+ /**
21491
+ * Not actually raised by the compiler, but reserved for documentation of a View Engine error when
21492
+ * a View Engine build depends on an Ivy-compiled NgModule.
21493
+ */
21494
+ ErrorCode[ErrorCode["NGMODULE_VE_DEPENDENCY_ON_IVY_LIB"] = 6999] = "NGMODULE_VE_DEPENDENCY_ON_IVY_LIB";
21462
21495
  /**
21463
21496
  * An element name failed validation against the DOM schema.
21464
21497
  */
@@ -21704,6 +21737,16 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
21704
21737
  function isAssignment(node) {
21705
21738
  return ts$1.isBinaryExpression(node) && node.operatorToken.kind === ts$1.SyntaxKind.EqualsToken;
21706
21739
  }
21740
+ /**
21741
+ * Obtains the non-redirected source file for `sf`.
21742
+ */
21743
+ function toUnredirectedSourceFile(sf) {
21744
+ const redirectInfo = sf.redirectInfo;
21745
+ if (redirectInfo === undefined) {
21746
+ return sf;
21747
+ }
21748
+ return redirectInfo.unredirected;
21749
+ }
21707
21750
 
21708
21751
  /**
21709
21752
  * @license
@@ -22212,6 +22255,22 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
22212
22255
  * Use of this source code is governed by an MIT-style license that can be
22213
22256
  * found in the LICENSE file at https://angular.io/license
22214
22257
  */
22258
+ const DefaultImportDeclaration = Symbol('DefaultImportDeclaration');
22259
+ /**
22260
+ * Attaches a default import declaration to `expr` to indicate the dependency of `expr` on the
22261
+ * default import.
22262
+ */
22263
+ function attachDefaultImportDeclaration(expr, importDecl) {
22264
+ expr[DefaultImportDeclaration] = importDecl;
22265
+ }
22266
+ /**
22267
+ * Obtains the default import declaration that `expr` depends on, or `null` if there is no such
22268
+ * dependency.
22269
+ */
22270
+ function getDefaultImportDeclaration(expr) {
22271
+ var _a;
22272
+ return (_a = expr[DefaultImportDeclaration]) !== null && _a !== void 0 ? _a : null;
22273
+ }
22215
22274
  /**
22216
22275
  * TypeScript has trouble with generating default imports inside of transformers for some module
22217
22276
  * formats. The issue is that for the statement:
@@ -22244,47 +22303,25 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
22244
22303
  */
22245
22304
  class DefaultImportTracker {
22246
22305
  constructor() {
22247
- /**
22248
- * A `Map` which tracks the `Map` of default import `ts.Identifier`s to their
22249
- * `ts.ImportDeclaration`s. These declarations are not guaranteed to be used.
22250
- */
22251
- this.sourceFileToImportMap = new Map();
22252
22306
  /**
22253
22307
  * A `Map` which tracks the `Set` of `ts.ImportDeclaration`s for default imports that were used in
22254
22308
  * a given `ts.SourceFile` and need to be preserved.
22255
22309
  */
22256
22310
  this.sourceFileToUsedImports = new Map();
22257
22311
  }
22258
- recordImportedIdentifier(id, decl) {
22259
- const sf = getSourceFile(id);
22260
- if (!this.sourceFileToImportMap.has(sf)) {
22261
- this.sourceFileToImportMap.set(sf, new Map());
22262
- }
22263
- this.sourceFileToImportMap.get(sf).set(id, decl);
22264
- }
22265
- recordUsedIdentifier(id) {
22266
- const sf = getSourceFile(id);
22267
- if (!this.sourceFileToImportMap.has(sf)) {
22268
- // The identifier's source file has no registered default imports at all.
22269
- return;
22270
- }
22271
- const identiferToDeclaration = this.sourceFileToImportMap.get(sf);
22272
- if (!identiferToDeclaration.has(id)) {
22273
- // The identifier isn't from a registered default import.
22274
- return;
22275
- }
22276
- const decl = identiferToDeclaration.get(id);
22312
+ recordUsedImport(importDecl) {
22313
+ const sf = getSourceFile(importDecl);
22277
22314
  // Add the default import declaration to the set of used import declarations for the file.
22278
22315
  if (!this.sourceFileToUsedImports.has(sf)) {
22279
22316
  this.sourceFileToUsedImports.set(sf, new Set());
22280
22317
  }
22281
- this.sourceFileToUsedImports.get(sf).add(decl);
22318
+ this.sourceFileToUsedImports.get(sf).add(importDecl);
22282
22319
  }
22283
22320
  /**
22284
22321
  * Get a `ts.TransformerFactory` which will preserve default imports that were previously marked
22285
22322
  * as used.
22286
22323
  *
22287
- * This transformer must run after any other transformers which call `recordUsedIdentifier`.
22324
+ * This transformer must run after any other transformers which call `recordUsedImport`.
22288
22325
  */
22289
22326
  importPreservingTransformer() {
22290
22327
  return (context) => {
@@ -22339,7 +22376,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
22339
22376
  });
22340
22377
  // Save memory - there's no need to keep these around once the transform has run for the given
22341
22378
  // file.
22342
- this.sourceFileToImportMap.delete(originalSf);
22343
22379
  this.sourceFileToUsedImports.delete(originalSf);
22344
22380
  return ts$1.updateSourceFileNode(sf, statements);
22345
22381
  }
@@ -26719,7 +26755,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
26719
26755
  this.imports = imports;
26720
26756
  this.downlevelTaggedTemplates = options.downlevelTaggedTemplates === true;
26721
26757
  this.downlevelVariableDeclarations = options.downlevelVariableDeclarations === true;
26722
- this.recordWrappedNodeExpr = options.recordWrappedNodeExpr || (() => { });
26758
+ this.recordWrappedNode = options.recordWrappedNode || (() => { });
26723
26759
  }
26724
26760
  visitDeclareVarStmt(stmt, context) {
26725
26761
  var _a;
@@ -26947,7 +26983,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
26947
26983
  throw new Error('Method not implemented.');
26948
26984
  }
26949
26985
  visitWrappedNodeExpr(ast, _context) {
26950
- this.recordWrappedNodeExpr(ast.node);
26986
+ this.recordWrappedNode(ast);
26951
26987
  return ast.node;
26952
26988
  }
26953
26989
  visitTypeofExpr(ast, context) {
@@ -27806,11 +27842,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
27806
27842
  */
27807
27843
  const NO_DECORATORS = new Set();
27808
27844
  const CLOSURE_FILE_OVERVIEW_REGEXP = /\s+@fileoverview\s+/i;
27809
- function ivyTransformFactory(compilation, reflector, importRewriter, defaultImportRecorder, perf, isCore, isClosureCompilerEnabled) {
27810
- const recordWrappedNodeExpr = createRecorderFn(defaultImportRecorder);
27845
+ function ivyTransformFactory(compilation, reflector, importRewriter, defaultImportTracker, perf, isCore, isClosureCompilerEnabled) {
27846
+ const recordWrappedNode = createRecorderFn(defaultImportTracker);
27811
27847
  return (context) => {
27812
27848
  return (file) => {
27813
- return perf.inPhase(PerfPhase.Compile, () => transformIvySourceFile(compilation, context, reflector, importRewriter, file, isCore, isClosureCompilerEnabled, recordWrappedNodeExpr));
27849
+ return perf.inPhase(PerfPhase.Compile, () => transformIvySourceFile(compilation, context, reflector, importRewriter, file, isCore, isClosureCompilerEnabled, recordWrappedNode));
27814
27850
  };
27815
27851
  };
27816
27852
  }
@@ -27841,13 +27877,13 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
27841
27877
  * compilation results (provided as an argument).
27842
27878
  */
27843
27879
  class IvyTransformationVisitor extends Visitor {
27844
- constructor(compilation, classCompilationMap, reflector, importManager, recordWrappedNodeExpr, isClosureCompilerEnabled, isCore) {
27880
+ constructor(compilation, classCompilationMap, reflector, importManager, recordWrappedNode, isClosureCompilerEnabled, isCore) {
27845
27881
  super();
27846
27882
  this.compilation = compilation;
27847
27883
  this.classCompilationMap = classCompilationMap;
27848
27884
  this.reflector = reflector;
27849
27885
  this.importManager = importManager;
27850
- this.recordWrappedNodeExpr = recordWrappedNodeExpr;
27886
+ this.recordWrappedNode = recordWrappedNode;
27851
27887
  this.isClosureCompilerEnabled = isClosureCompilerEnabled;
27852
27888
  this.isCore = isCore;
27853
27889
  }
@@ -27862,7 +27898,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
27862
27898
  const members = [...node.members];
27863
27899
  for (const field of this.classCompilationMap.get(node)) {
27864
27900
  // Translate the initializer for the field into TS nodes.
27865
- const exprNode = translateExpression(field.initializer, this.importManager, { recordWrappedNodeExpr: this.recordWrappedNodeExpr });
27901
+ const exprNode = translateExpression(field.initializer, this.importManager, { recordWrappedNode: this.recordWrappedNode });
27866
27902
  // Create a static property declaration for the new field.
27867
27903
  const property = ts$1.createProperty(undefined, [ts$1.createToken(ts$1.SyntaxKind.StaticKeyword)], field.name, undefined, undefined, exprNode);
27868
27904
  if (this.isClosureCompilerEnabled) {
@@ -27874,7 +27910,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
27874
27910
  /* hasTrailingNewLine */ false);
27875
27911
  }
27876
27912
  field.statements
27877
- .map(stmt => translateStatement(stmt, this.importManager, { recordWrappedNodeExpr: this.recordWrappedNodeExpr }))
27913
+ .map(stmt => translateStatement(stmt, this.importManager, { recordWrappedNode: this.recordWrappedNode }))
27878
27914
  .forEach(stmt => statements.push(stmt));
27879
27915
  members.push(property);
27880
27916
  }
@@ -27978,7 +28014,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
27978
28014
  /**
27979
28015
  * A transformer which operates on ts.SourceFiles and applies changes from an `IvyCompilation`.
27980
28016
  */
27981
- function transformIvySourceFile(compilation, context, reflector, importRewriter, file, isCore, isClosureCompilerEnabled, recordWrappedNodeExpr) {
28017
+ function transformIvySourceFile(compilation, context, reflector, importRewriter, file, isCore, isClosureCompilerEnabled, recordWrappedNode) {
27982
28018
  const constantPool = new ConstantPool(isClosureCompilerEnabled);
27983
28019
  const importManager = new ImportManager(importRewriter);
27984
28020
  // The transformation process consists of 2 steps:
@@ -27995,13 +28031,13 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
27995
28031
  visit(file, compilationVisitor, context);
27996
28032
  // Step 2. Scan through the AST again and perform transformations based on Ivy compilation
27997
28033
  // results obtained at Step 1.
27998
- const transformationVisitor = new IvyTransformationVisitor(compilation, compilationVisitor.classCompilationMap, reflector, importManager, recordWrappedNodeExpr, isClosureCompilerEnabled, isCore);
28034
+ const transformationVisitor = new IvyTransformationVisitor(compilation, compilationVisitor.classCompilationMap, reflector, importManager, recordWrappedNode, isClosureCompilerEnabled, isCore);
27999
28035
  let sf = visit(file, transformationVisitor, context);
28000
28036
  // Generate the constant statements first, as they may involve adding additional imports
28001
28037
  // to the ImportManager.
28002
28038
  const downlevelTranslatedCode = getLocalizeCompileTarget(context) < ts$1.ScriptTarget.ES2015;
28003
28039
  const constants = constantPool.statements.map(stmt => translateStatement(stmt, importManager, {
28004
- recordWrappedNodeExpr,
28040
+ recordWrappedNode,
28005
28041
  downlevelTaggedTemplates: downlevelTranslatedCode,
28006
28042
  downlevelVariableDeclarations: downlevelTranslatedCode,
28007
28043
  }));
@@ -28075,10 +28111,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
28075
28111
  function isFromAngularCore(decorator) {
28076
28112
  return decorator.import !== null && decorator.import.from === '@angular/core';
28077
28113
  }
28078
- function createRecorderFn(defaultImportRecorder) {
28079
- return expr => {
28080
- if (ts$1.isIdentifier(expr)) {
28081
- defaultImportRecorder.recordUsedIdentifier(expr);
28114
+ function createRecorderFn(defaultImportTracker) {
28115
+ return node => {
28116
+ const importDecl = getDefaultImportDeclaration(node);
28117
+ if (importDecl !== null) {
28118
+ defaultImportTracker.recordUsedImport(importDecl);
28082
28119
  }
28083
28120
  };
28084
28121
  }
@@ -28173,7 +28210,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
28173
28210
  * Use of this source code is governed by an MIT-style license that can be
28174
28211
  * found in the LICENSE file at https://angular.io/license
28175
28212
  */
28176
- function getConstructorDependencies(clazz, reflector, defaultImportRecorder, isCore) {
28213
+ function getConstructorDependencies(clazz, reflector, isCore) {
28177
28214
  const deps = [];
28178
28215
  const errors = [];
28179
28216
  let ctorParams = reflector.getConstructorParameters(clazz);
@@ -28186,7 +28223,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
28186
28223
  }
28187
28224
  }
28188
28225
  ctorParams.forEach((param, idx) => {
28189
- let token = valueReferenceToExpression(param.typeValueReference, defaultImportRecorder);
28226
+ let token = valueReferenceToExpression(param.typeValueReference);
28190
28227
  let attribute = null;
28191
28228
  let optional = false, self = false, skipSelf = false, host = false;
28192
28229
  let resolved = R3ResolvedDependencyType.Token;
@@ -28253,16 +28290,16 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
28253
28290
  return { deps: null, errors };
28254
28291
  }
28255
28292
  }
28256
- function valueReferenceToExpression(valueRef, defaultImportRecorder) {
28293
+ function valueReferenceToExpression(valueRef) {
28257
28294
  if (valueRef.kind === 2 /* UNAVAILABLE */) {
28258
28295
  return null;
28259
28296
  }
28260
28297
  else if (valueRef.kind === 0 /* LOCAL */) {
28261
- if (defaultImportRecorder !== null && valueRef.defaultImportStatement !== null &&
28262
- ts$1.isIdentifier(valueRef.expression)) {
28263
- defaultImportRecorder.recordImportedIdentifier(valueRef.expression, valueRef.defaultImportStatement);
28298
+ const expr = new WrappedNodeExpr(valueRef.expression);
28299
+ if (valueRef.defaultImportStatement !== null) {
28300
+ attachDefaultImportDeclaration(expr, valueRef.defaultImportStatement);
28264
28301
  }
28265
- return new WrappedNodeExpr(valueRef.expression);
28302
+ return expr;
28266
28303
  }
28267
28304
  else {
28268
28305
  let importExpr = new ExternalExpr({ moduleName: valueRef.moduleName, name: valueRef.importedName });
@@ -28293,8 +28330,8 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'os', 'typescript', 'fs', '
28293
28330
  return 'invalid';
28294
28331
  }
28295
28332
  }
28296
- function getValidConstructorDependencies(clazz, reflector, defaultImportRecorder, isCore) {
28297
- return validateConstructorDependencies(clazz, getConstructorDependencies(clazz, reflector, defaultImportRecorder, isCore));
28333
+ function getValidConstructorDependencies(clazz, reflector, isCore) {
28334
+ return validateConstructorDependencies(clazz, getConstructorDependencies(clazz, reflector, isCore));
28298
28335
  }
28299
28336
  /**
28300
28337
  * Validate that `ConstructorDeps` does not have any invalid dependencies and convert them into the
@@ -28802,7 +28839,7 @@ Either add the @Injectable() decorator to '${provider.node.name
28802
28839
  * If no such metadata is present, this function returns `null`. Otherwise, the call is returned
28803
28840
  * as a `Statement` for inclusion along with the class.
28804
28841
  */
28805
- function generateSetClassMetadataCall(clazz, reflection, defaultImportRecorder, isCore, annotateForClosureCompiler) {
28842
+ function generateSetClassMetadataCall(clazz, reflection, isCore, annotateForClosureCompiler) {
28806
28843
  if (!reflection.isClass(clazz)) {
28807
28844
  return null;
28808
28845
  }
@@ -28829,7 +28866,7 @@ Either add the @Injectable() decorator to '${provider.node.name
28829
28866
  let metaCtorParameters = new LiteralExpr(null);
28830
28867
  const classCtorParameters = reflection.getConstructorParameters(clazz);
28831
28868
  if (classCtorParameters !== null) {
28832
- const ctorParameters = classCtorParameters.map(param => ctorParameterToMetadata(param, defaultImportRecorder, isCore));
28869
+ const ctorParameters = classCtorParameters.map(param => ctorParameterToMetadata(param, isCore));
28833
28870
  metaCtorParameters = new FunctionExpr([], [
28834
28871
  new ReturnStatement(new LiteralArrayExpr(ctorParameters)),
28835
28872
  ]);
@@ -28866,11 +28903,11 @@ Either add the @Injectable() decorator to '${provider.node.name
28866
28903
  /**
28867
28904
  * Convert a reflected constructor parameter to metadata.
28868
28905
  */
28869
- function ctorParameterToMetadata(param, defaultImportRecorder, isCore) {
28906
+ function ctorParameterToMetadata(param, isCore) {
28870
28907
  // Parameters sometimes have a type that can be referenced. If so, then use it, otherwise
28871
28908
  // its type is undefined.
28872
28909
  const type = param.typeValueReference.kind !== 2 /* UNAVAILABLE */ ?
28873
- valueReferenceToExpression(param.typeValueReference, defaultImportRecorder) :
28910
+ valueReferenceToExpression(param.typeValueReference) :
28874
28911
  new LiteralExpr(undefined);
28875
28912
  const mapEntries = [
28876
28913
  { key: 'type', value: type, quoted: false },
@@ -29057,13 +29094,12 @@ Either add the @Injectable() decorator to '${provider.node.name
29057
29094
  return isSymbolEqual(current, previous);
29058
29095
  }
29059
29096
  class DirectiveDecoratorHandler {
29060
- constructor(reflector, evaluator, metaRegistry, scopeRegistry, metaReader, defaultImportRecorder, injectableRegistry, isCore, semanticDepGraphUpdater, annotateForClosureCompiler, compileUndecoratedClassesWithAngularFeatures, perf) {
29097
+ constructor(reflector, evaluator, metaRegistry, scopeRegistry, metaReader, injectableRegistry, isCore, semanticDepGraphUpdater, annotateForClosureCompiler, compileUndecoratedClassesWithAngularFeatures, perf) {
29061
29098
  this.reflector = reflector;
29062
29099
  this.evaluator = evaluator;
29063
29100
  this.metaRegistry = metaRegistry;
29064
29101
  this.scopeRegistry = scopeRegistry;
29065
29102
  this.metaReader = metaReader;
29066
- this.defaultImportRecorder = defaultImportRecorder;
29067
29103
  this.injectableRegistry = injectableRegistry;
29068
29104
  this.isCore = isCore;
29069
29105
  this.semanticDepGraphUpdater = semanticDepGraphUpdater;
@@ -29097,7 +29133,7 @@ Either add the @Injectable() decorator to '${provider.node.name
29097
29133
  return { diagnostics: [getUndecoratedClassWithAngularFeaturesDiagnostic(node)] };
29098
29134
  }
29099
29135
  this.perf.eventCount(PerfEvent.AnalyzeDirective);
29100
- const directiveResult = extractDirectiveMetadata(node, decorator, this.reflector, this.evaluator, this.defaultImportRecorder, this.isCore, flags, this.annotateForClosureCompiler);
29136
+ const directiveResult = extractDirectiveMetadata(node, decorator, this.reflector, this.evaluator, this.isCore, flags, this.annotateForClosureCompiler);
29101
29137
  if (directiveResult === undefined) {
29102
29138
  return {};
29103
29139
  }
@@ -29111,7 +29147,7 @@ Either add the @Injectable() decorator to '${provider.node.name
29111
29147
  inputs: directiveResult.inputs,
29112
29148
  outputs: directiveResult.outputs,
29113
29149
  meta: analysis,
29114
- metadataStmt: generateSetClassMetadataCall(node, this.reflector, this.defaultImportRecorder, this.isCore, this.annotateForClosureCompiler),
29150
+ metadataStmt: generateSetClassMetadataCall(node, this.reflector, this.isCore, this.annotateForClosureCompiler),
29115
29151
  baseClass: readBaseClass$1(node, this.reflector, this.evaluator),
29116
29152
  typeCheckMeta: extractDirectiveTypeCheckMeta(node, directiveResult.inputs, this.reflector),
29117
29153
  providersRequiringFactory,
@@ -29194,7 +29230,7 @@ Either add the @Injectable() decorator to '${provider.node.name
29194
29230
  * appear in the declarations of an `NgModule` and additional verification is done when processing
29195
29231
  * the module.
29196
29232
  */
29197
- function extractDirectiveMetadata(clazz, decorator, reflector, evaluator, defaultImportRecorder, isCore, flags, annotateForClosureCompiler, defaultSelector = null) {
29233
+ function extractDirectiveMetadata(clazz, decorator, reflector, evaluator, isCore, flags, annotateForClosureCompiler, defaultSelector = null) {
29198
29234
  let directive;
29199
29235
  if (decorator === null || decorator.args === null || decorator.args.length === 0) {
29200
29236
  directive = new Map();
@@ -29272,7 +29308,7 @@ Either add the @Injectable() decorator to '${provider.node.name
29272
29308
  }
29273
29309
  exportAs = resolved.split(',').map(part => part.trim());
29274
29310
  }
29275
- const rawCtorDeps = getConstructorDependencies(clazz, reflector, defaultImportRecorder, isCore);
29311
+ const rawCtorDeps = getConstructorDependencies(clazz, reflector, isCore);
29276
29312
  let ctorDeps;
29277
29313
  // Non-abstract directives (those with a selector) require valid constructor dependencies, whereas
29278
29314
  // abstract directives are allowed to have invalid dependencies, given that a subclass may call
@@ -29694,7 +29730,7 @@ Either add the @Injectable() decorator to '${provider.node.name
29694
29730
  * Compiles @NgModule annotations to ngModuleDef fields.
29695
29731
  */
29696
29732
  class NgModuleDecoratorHandler {
29697
- constructor(reflector, evaluator, metaReader, metaRegistry, scopeRegistry, referencesRegistry, isCore, routeAnalyzer, refEmitter, factoryTracker, defaultImportRecorder, annotateForClosureCompiler, injectableRegistry, perf, localeId) {
29733
+ constructor(reflector, evaluator, metaReader, metaRegistry, scopeRegistry, referencesRegistry, isCore, routeAnalyzer, refEmitter, factoryTracker, annotateForClosureCompiler, injectableRegistry, perf, localeId) {
29698
29734
  this.reflector = reflector;
29699
29735
  this.evaluator = evaluator;
29700
29736
  this.metaReader = metaReader;
@@ -29705,7 +29741,6 @@ Either add the @Injectable() decorator to '${provider.node.name
29705
29741
  this.routeAnalyzer = routeAnalyzer;
29706
29742
  this.refEmitter = refEmitter;
29707
29743
  this.factoryTracker = factoryTracker;
29708
- this.defaultImportRecorder = defaultImportRecorder;
29709
29744
  this.annotateForClosureCompiler = annotateForClosureCompiler;
29710
29745
  this.injectableRegistry = injectableRegistry;
29711
29746
  this.perf = perf;
@@ -29883,7 +29918,7 @@ Either add the @Injectable() decorator to '${provider.node.name
29883
29918
  schemas: schemas,
29884
29919
  mod: ngModuleDef,
29885
29920
  inj: ngInjectorDef,
29886
- deps: getValidConstructorDependencies(node, this.reflector, this.defaultImportRecorder, this.isCore),
29921
+ deps: getValidConstructorDependencies(node, this.reflector, this.isCore),
29887
29922
  declarations: declarationRefs,
29888
29923
  rawDeclarations,
29889
29924
  imports: importRefs,
@@ -29892,7 +29927,7 @@ Either add the @Injectable() decorator to '${provider.node.name
29892
29927
  providersRequiringFactory: rawProviders ?
29893
29928
  resolveProvidersRequiringFactory(rawProviders, this.reflector, this.evaluator) :
29894
29929
  null,
29895
- metadataStmt: generateSetClassMetadataCall(node, this.reflector, this.defaultImportRecorder, this.isCore, this.annotateForClosureCompiler),
29930
+ metadataStmt: generateSetClassMetadataCall(node, this.reflector, this.isCore, this.annotateForClosureCompiler),
29896
29931
  factorySymbolName: node.name.text,
29897
29932
  },
29898
29933
  };
@@ -30223,7 +30258,7 @@ Either add the @Injectable() decorator to '${provider.node.name
30223
30258
  * `DecoratorHandler` which handles the `@Component` annotation.
30224
30259
  */
30225
30260
  class ComponentDecoratorHandler {
30226
- constructor(reflector, evaluator, metaRegistry, metaReader, scopeReader, scopeRegistry, typeCheckScopeRegistry, resourceRegistry, isCore, resourceLoader, rootDirs, defaultPreserveWhitespaces, i18nUseExternalIds, enableI18nLegacyMessageIdFormat, usePoisonedData, i18nNormalizeLineEndingsInICUs, moduleResolver, cycleAnalyzer, cycleHandlingStrategy, refEmitter, defaultImportRecorder, depTracker, injectableRegistry, semanticDepGraphUpdater, annotateForClosureCompiler, perf) {
30261
+ constructor(reflector, evaluator, metaRegistry, metaReader, scopeReader, scopeRegistry, typeCheckScopeRegistry, resourceRegistry, isCore, resourceLoader, rootDirs, defaultPreserveWhitespaces, i18nUseExternalIds, enableI18nLegacyMessageIdFormat, usePoisonedData, i18nNormalizeLineEndingsInICUs, moduleResolver, cycleAnalyzer, cycleHandlingStrategy, refEmitter, depTracker, injectableRegistry, semanticDepGraphUpdater, annotateForClosureCompiler, perf) {
30227
30262
  this.reflector = reflector;
30228
30263
  this.evaluator = evaluator;
30229
30264
  this.metaRegistry = metaRegistry;
@@ -30244,7 +30279,6 @@ Either add the @Injectable() decorator to '${provider.node.name
30244
30279
  this.cycleAnalyzer = cycleAnalyzer;
30245
30280
  this.cycleHandlingStrategy = cycleHandlingStrategy;
30246
30281
  this.refEmitter = refEmitter;
30247
- this.defaultImportRecorder = defaultImportRecorder;
30248
30282
  this.depTracker = depTracker;
30249
30283
  this.injectableRegistry = injectableRegistry;
30250
30284
  this.semanticDepGraphUpdater = semanticDepGraphUpdater;
@@ -30341,7 +30375,7 @@ Either add the @Injectable() decorator to '${provider.node.name
30341
30375
  let isPoisoned = false;
30342
30376
  // @Component inherits @Directive, so begin by extracting the @Directive metadata and building
30343
30377
  // on it.
30344
- const directiveResult = extractDirectiveMetadata(node, decorator, this.reflector, this.evaluator, this.defaultImportRecorder, this.isCore, flags, this.annotateForClosureCompiler, this.elementSchemaRegistry.getDefaultComponentElementName());
30378
+ const directiveResult = extractDirectiveMetadata(node, decorator, this.reflector, this.evaluator, this.isCore, flags, this.annotateForClosureCompiler, this.elementSchemaRegistry.getDefaultComponentElementName());
30345
30379
  if (directiveResult === undefined) {
30346
30380
  // `extractDirectiveMetadata` returns undefined when the @Directive has `jit: true`. In this
30347
30381
  // case, compilation of the decorator is skipped. Returning an empty object signifies
@@ -30455,7 +30489,7 @@ Either add the @Injectable() decorator to '${provider.node.name
30455
30489
  // analyzed and the full compilation scope for the component can be realized.
30456
30490
  animations, viewProviders: wrappedViewProviders, i18nUseExternalIds: this.i18nUseExternalIds, relativeContextFilePath }),
30457
30491
  typeCheckMeta: extractDirectiveTypeCheckMeta(node, inputs, this.reflector),
30458
- metadataStmt: generateSetClassMetadataCall(node, this.reflector, this.defaultImportRecorder, this.isCore, this.annotateForClosureCompiler),
30492
+ metadataStmt: generateSetClassMetadataCall(node, this.reflector, this.isCore, this.annotateForClosureCompiler),
30459
30493
  template,
30460
30494
  providersRequiringFactory,
30461
30495
  viewProvidersRequiringFactory,
@@ -31151,7 +31185,7 @@ Either add the @Injectable() decorator to '${provider.node.name
31151
31185
  * Adapts the `compileIvyInjectable` compiler for `@Injectable` decorators to the Ivy compiler.
31152
31186
  */
31153
31187
  class InjectableDecoratorHandler {
31154
- constructor(reflector, defaultImportRecorder, isCore, strictCtorDeps, injectableRegistry, perf,
31188
+ constructor(reflector, isCore, strictCtorDeps, injectableRegistry, perf,
31155
31189
  /**
31156
31190
  * What to do if the injectable already contains a ɵprov property.
31157
31191
  *
@@ -31160,7 +31194,6 @@ Either add the @Injectable() decorator to '${provider.node.name
31160
31194
  */
31161
31195
  errorOnDuplicateProv = true) {
31162
31196
  this.reflector = reflector;
31163
- this.defaultImportRecorder = defaultImportRecorder;
31164
31197
  this.isCore = isCore;
31165
31198
  this.strictCtorDeps = strictCtorDeps;
31166
31199
  this.injectableRegistry = injectableRegistry;
@@ -31192,8 +31225,8 @@ Either add the @Injectable() decorator to '${provider.node.name
31192
31225
  return {
31193
31226
  analysis: {
31194
31227
  meta,
31195
- ctorDeps: extractInjectableCtorDeps(node, meta, decorator, this.reflector, this.defaultImportRecorder, this.isCore, this.strictCtorDeps),
31196
- metadataStmt: generateSetClassMetadataCall(node, this.reflector, this.defaultImportRecorder, this.isCore),
31228
+ ctorDeps: extractInjectableCtorDeps(node, meta, decorator, this.reflector, this.isCore, this.strictCtorDeps),
31229
+ metadataStmt: generateSetClassMetadataCall(node, this.reflector, this.isCore),
31197
31230
  // Avoid generating multiple factories if a class has
31198
31231
  // more Angular decorators, apart from Injectable.
31199
31232
  needsFactory: !decorators ||
@@ -31335,7 +31368,7 @@ Either add the @Injectable() decorator to '${provider.node.name
31335
31368
  throw new FatalDiagnosticError(ErrorCode.DECORATOR_ARITY_WRONG, decorator.args[2], 'Too many arguments to @Injectable');
31336
31369
  }
31337
31370
  }
31338
- function extractInjectableCtorDeps(clazz, meta, decorator, reflector, defaultImportRecorder, isCore, strictCtorDeps) {
31371
+ function extractInjectableCtorDeps(clazz, meta, decorator, reflector, isCore, strictCtorDeps) {
31339
31372
  if (decorator.args === null) {
31340
31373
  throw new FatalDiagnosticError(ErrorCode.DECORATOR_NOT_CALLED, Decorator.nodeForError(decorator), '@Injectable must be called');
31341
31374
  }
@@ -31350,15 +31383,16 @@ Either add the @Injectable() decorator to '${provider.node.name
31350
31383
  // constructor signature does not work for DI then a factory definition (ɵfac) that throws is
31351
31384
  // generated.
31352
31385
  if (strictCtorDeps) {
31353
- ctorDeps = getValidConstructorDependencies(clazz, reflector, defaultImportRecorder, isCore);
31386
+ ctorDeps = getValidConstructorDependencies(clazz, reflector, isCore);
31354
31387
  }
31355
31388
  else {
31356
- ctorDeps = unwrapConstructorDependencies(getConstructorDependencies(clazz, reflector, defaultImportRecorder, isCore));
31389
+ ctorDeps =
31390
+ unwrapConstructorDependencies(getConstructorDependencies(clazz, reflector, isCore));
31357
31391
  }
31358
31392
  return ctorDeps;
31359
31393
  }
31360
31394
  else if (decorator.args.length === 1) {
31361
- const rawCtorDeps = getConstructorDependencies(clazz, reflector, defaultImportRecorder, isCore);
31395
+ const rawCtorDeps = getConstructorDependencies(clazz, reflector, isCore);
31362
31396
  if (strictCtorDeps && meta.useValue === undefined && meta.useExisting === undefined &&
31363
31397
  meta.useClass === undefined && meta.useFactory === undefined) {
31364
31398
  // Since use* was not provided, validate the deps according to strictCtorDeps.
@@ -31442,12 +31476,11 @@ Either add the @Injectable() decorator to '${provider.node.name
31442
31476
  }
31443
31477
  }
31444
31478
  class PipeDecoratorHandler {
31445
- constructor(reflector, evaluator, metaRegistry, scopeRegistry, defaultImportRecorder, injectableRegistry, isCore, perf) {
31479
+ constructor(reflector, evaluator, metaRegistry, scopeRegistry, injectableRegistry, isCore, perf) {
31446
31480
  this.reflector = reflector;
31447
31481
  this.evaluator = evaluator;
31448
31482
  this.metaRegistry = metaRegistry;
31449
31483
  this.scopeRegistry = scopeRegistry;
31450
- this.defaultImportRecorder = defaultImportRecorder;
31451
31484
  this.injectableRegistry = injectableRegistry;
31452
31485
  this.isCore = isCore;
31453
31486
  this.perf = perf;
@@ -31511,10 +31544,10 @@ Either add the @Injectable() decorator to '${provider.node.name
31511
31544
  internalType,
31512
31545
  typeArgumentCount: this.reflector.getGenericArityOfClass(clazz) || 0,
31513
31546
  pipeName,
31514
- deps: getValidConstructorDependencies(clazz, this.reflector, this.defaultImportRecorder, this.isCore),
31547
+ deps: getValidConstructorDependencies(clazz, this.reflector, this.isCore),
31515
31548
  pure,
31516
31549
  },
31517
- metadataStmt: generateSetClassMetadataCall(clazz, this.reflector, this.defaultImportRecorder, this.isCore),
31550
+ metadataStmt: generateSetClassMetadataCall(clazz, this.reflector, this.isCore),
31518
31551
  },
31519
31552
  };
31520
31553
  }
@@ -32148,10 +32181,11 @@ Either add the @Injectable() decorator to '${provider.node.name
32148
32181
  // since the previous compilation). These need to be removed from the state tracking to
32149
32182
  // avoid leaking memory.
32150
32183
  // All files in the old program, for easy detection of changes.
32151
- const oldFiles = new Set(oldProgram.getSourceFiles());
32184
+ const oldFiles = new Set(oldProgram.getSourceFiles().map(toUnredirectedSourceFile));
32152
32185
  // Assume all the old files were deleted to begin with. Only TS files are tracked.
32153
32186
  const deletedTsPaths = new Set(tsOnlyFiles(oldProgram).map(sf => sf.fileName));
32154
- for (const newFile of newProgram.getSourceFiles()) {
32187
+ for (const possiblyRedirectedNewFile of newProgram.getSourceFiles()) {
32188
+ const newFile = toUnredirectedSourceFile(possiblyRedirectedNewFile);
32155
32189
  if (!newFile.isDeclarationFile) {
32156
32190
  // This file exists in the new program, so remove it from `deletedTsPaths`.
32157
32191
  deletedTsPaths.delete(newFile.fileName);
@@ -32932,7 +32966,7 @@ Either add the @Injectable() decorator to '${provider.node.name
32932
32966
  resolve(url, fromFile) {
32933
32967
  let resolvedUrl = null;
32934
32968
  if (this.adapter.resourceNameToFileName) {
32935
- resolvedUrl = this.adapter.resourceNameToFileName(url, fromFile);
32969
+ resolvedUrl = this.adapter.resourceNameToFileName(url, fromFile, (url, fromFile) => this.fallbackResolve(url, fromFile));
32936
32970
  }
32937
32971
  else {
32938
32972
  resolvedUrl = this.fallbackResolve(url, fromFile);
@@ -34720,56 +34754,63 @@ Either add the @Injectable() decorator to '${provider.node.name
34720
34754
  this.data = data;
34721
34755
  this.shimPath = shimPath;
34722
34756
  /**
34723
- * Cache of `GlobalCompletion`s for various levels of the template, including the root template
34724
- * (`null`).
34757
+ * Cache of completions for various levels of the template, including the root template (`null`).
34758
+ * Memoizes `getTemplateContextCompletions`.
34725
34759
  */
34726
- this.globalCompletionCache = new Map();
34760
+ this.templateContextCache = new Map();
34727
34761
  this.expressionCompletionCache = new Map();
34728
- }
34729
- /**
34730
- * Get global completions within the given template context - either a `TmplAstTemplate` embedded
34731
- * view, or `null` for the root template context.
34732
- */
34733
- getGlobalCompletions(context) {
34734
- if (this.globalCompletionCache.has(context)) {
34735
- return this.globalCompletionCache.get(context);
34736
- }
34737
34762
  // Find the component completion expression within the TCB. This looks like: `ctx. /* ... */;`
34738
34763
  const globalRead = findFirstMatchingNode(this.tcb, {
34739
34764
  filter: ts$1.isPropertyAccessExpression,
34740
34765
  withExpressionIdentifier: ExpressionIdentifier.COMPONENT_COMPLETION
34741
34766
  });
34742
- if (globalRead === null) {
34743
- return null;
34744
- }
34745
- const completion = {
34746
- componentContext: {
34767
+ if (globalRead !== null) {
34768
+ this.componentContext = {
34747
34769
  shimPath: this.shimPath,
34748
34770
  // `globalRead.name` is an empty `ts.Identifier`, so its start position immediately follows
34749
34771
  // the `.` in `ctx.`. TS autocompletion APIs can then be used to access completion results
34750
34772
  // for the component context.
34751
34773
  positionInShimFile: globalRead.name.getStart(),
34752
- },
34753
- templateContext: new Map(),
34754
- };
34755
- // The bound template already has details about the references and variables in scope in the
34756
- // `context` template - they just need to be converted to `Completion`s.
34757
- for (const node of this.data.boundTarget.getEntitiesInTemplateScope(context)) {
34758
- if (node instanceof Reference) {
34759
- completion.templateContext.set(node.name, {
34760
- kind: CompletionKind.Reference,
34761
- node,
34762
- });
34763
- }
34764
- else {
34765
- completion.templateContext.set(node.name, {
34766
- kind: CompletionKind.Variable,
34767
- node,
34768
- });
34774
+ };
34775
+ }
34776
+ else {
34777
+ this.componentContext = null;
34778
+ }
34779
+ }
34780
+ /**
34781
+ * Get global completions within the given template context and AST node.
34782
+ *
34783
+ * @param context the given template context - either a `TmplAstTemplate` embedded view, or `null`
34784
+ * for the root
34785
+ * template context.
34786
+ * @param node the given AST node
34787
+ */
34788
+ getGlobalCompletions(context, node) {
34789
+ if (this.componentContext === null) {
34790
+ return null;
34791
+ }
34792
+ const templateContext = this.getTemplateContextCompletions(context);
34793
+ if (templateContext === null) {
34794
+ return null;
34795
+ }
34796
+ let nodeContext = null;
34797
+ if (node instanceof EmptyExpr) {
34798
+ const nodeLocation = findFirstMatchingNode(this.tcb, {
34799
+ filter: ts$1.isIdentifier,
34800
+ withSpan: node.sourceSpan,
34801
+ });
34802
+ if (nodeLocation !== null) {
34803
+ nodeContext = {
34804
+ shimPath: this.shimPath,
34805
+ positionInShimFile: nodeLocation.getStart(),
34806
+ };
34769
34807
  }
34770
34808
  }
34771
- this.globalCompletionCache.set(context, completion);
34772
- return completion;
34809
+ return {
34810
+ componentContext: this.componentContext,
34811
+ templateContext,
34812
+ nodeContext,
34813
+ };
34773
34814
  }
34774
34815
  getExpressionCompletionLocation(expr) {
34775
34816
  if (this.expressionCompletionCache.has(expr)) {
@@ -34814,6 +34855,34 @@ Either add the @Injectable() decorator to '${provider.node.name
34814
34855
  this.expressionCompletionCache.set(expr, res);
34815
34856
  return res;
34816
34857
  }
34858
+ /**
34859
+ * Get global completions within the given template context - either a `TmplAstTemplate` embedded
34860
+ * view, or `null` for the root context.
34861
+ */
34862
+ getTemplateContextCompletions(context) {
34863
+ if (this.templateContextCache.has(context)) {
34864
+ return this.templateContextCache.get(context);
34865
+ }
34866
+ const templateContext = new Map();
34867
+ // The bound template already has details about the references and variables in scope in the
34868
+ // `context` template - they just need to be converted to `Completion`s.
34869
+ for (const node of this.data.boundTarget.getEntitiesInTemplateScope(context)) {
34870
+ if (node instanceof Reference) {
34871
+ templateContext.set(node.name, {
34872
+ kind: CompletionKind.Reference,
34873
+ node,
34874
+ });
34875
+ }
34876
+ else {
34877
+ templateContext.set(node.name, {
34878
+ kind: CompletionKind.Variable,
34879
+ node,
34880
+ });
34881
+ }
34882
+ }
34883
+ this.templateContextCache.set(context, templateContext);
34884
+ return templateContext;
34885
+ }
34817
34886
  }
34818
34887
 
34819
34888
  /**
@@ -35143,12 +35212,6 @@ Either add the @Injectable() decorator to '${provider.node.name
35143
35212
  }
35144
35213
  return false;
35145
35214
  }
35146
- function checkIfGenericTypesAreUnbound(node) {
35147
- if (node.typeParameters === undefined) {
35148
- return true;
35149
- }
35150
- return node.typeParameters.every(param => param.constraint === undefined);
35151
- }
35152
35215
  function isAccessExpression(node) {
35153
35216
  return ts$1.isPropertyAccessExpression(node) || ts$1.isElementAccessExpression(node);
35154
35217
  }
@@ -35368,6 +35431,136 @@ Either add the @Injectable() decorator to '${provider.node.name
35368
35431
  }
35369
35432
  }
35370
35433
 
35434
+ /**
35435
+ * @license
35436
+ * Copyright Google LLC All Rights Reserved.
35437
+ *
35438
+ * Use of this source code is governed by an MIT-style license that can be
35439
+ * found in the LICENSE file at https://angular.io/license
35440
+ */
35441
+ /**
35442
+ * Indicates whether a particular component requires an inline type check block.
35443
+ *
35444
+ * This is not a boolean state as inlining might only be required to get the best possible
35445
+ * type-checking, but the component could theoretically still be checked without it.
35446
+ */
35447
+ var TcbInliningRequirement;
35448
+ (function (TcbInliningRequirement) {
35449
+ /**
35450
+ * There is no way to type check this component without inlining.
35451
+ */
35452
+ TcbInliningRequirement[TcbInliningRequirement["MustInline"] = 0] = "MustInline";
35453
+ /**
35454
+ * Inlining should be used due to the component's generic bounds, but a non-inlining fallback
35455
+ * method can be used if that's not possible.
35456
+ */
35457
+ TcbInliningRequirement[TcbInliningRequirement["ShouldInlineForGenericBounds"] = 1] = "ShouldInlineForGenericBounds";
35458
+ /**
35459
+ * There is no requirement for this component's TCB to be inlined.
35460
+ */
35461
+ TcbInliningRequirement[TcbInliningRequirement["None"] = 2] = "None";
35462
+ })(TcbInliningRequirement || (TcbInliningRequirement = {}));
35463
+ function requiresInlineTypeCheckBlock(node, usedPipes, reflector) {
35464
+ // In order to qualify for a declared TCB (not inline) two conditions must be met:
35465
+ // 1) the class must be exported
35466
+ // 2) it must not have contextual generic type bounds
35467
+ if (!checkIfClassIsExported(node)) {
35468
+ // Condition 1 is false, the class is not exported.
35469
+ return TcbInliningRequirement.MustInline;
35470
+ }
35471
+ else if (!checkIfGenericTypeBoundsAreContextFree(node, reflector)) {
35472
+ // Condition 2 is false, the class has constrained generic types. It should be checked with an
35473
+ // inline TCB if possible, but can potentially use fallbacks to avoid inlining if not.
35474
+ return TcbInliningRequirement.ShouldInlineForGenericBounds;
35475
+ }
35476
+ else if (Array.from(usedPipes.values())
35477
+ .some(pipeRef => !checkIfClassIsExported(pipeRef.node))) {
35478
+ // If one of the pipes used by the component is not exported, a non-inline TCB will not be able
35479
+ // to import it, so this requires an inline TCB.
35480
+ return TcbInliningRequirement.MustInline;
35481
+ }
35482
+ else {
35483
+ return TcbInliningRequirement.None;
35484
+ }
35485
+ }
35486
+ /** Maps a shim position back to a template location. */
35487
+ function getTemplateMapping(shimSf, position, resolver, isDiagnosticRequest) {
35488
+ const node = getTokenAtPosition(shimSf, position);
35489
+ const sourceLocation = findSourceLocation(node, shimSf, isDiagnosticRequest);
35490
+ if (sourceLocation === null) {
35491
+ return null;
35492
+ }
35493
+ const mapping = resolver.getSourceMapping(sourceLocation.id);
35494
+ const span = resolver.toParseSourceSpan(sourceLocation.id, sourceLocation.span);
35495
+ if (span === null) {
35496
+ return null;
35497
+ }
35498
+ // TODO(atscott): Consider adding a context span by walking up from `node` until we get a
35499
+ // different span.
35500
+ return { sourceLocation, templateSourceMapping: mapping, span };
35501
+ }
35502
+ function findTypeCheckBlock(file, id, isDiagnosticRequest) {
35503
+ for (const stmt of file.statements) {
35504
+ if (ts$1.isFunctionDeclaration(stmt) && getTemplateId$1(stmt, file, isDiagnosticRequest) === id) {
35505
+ return stmt;
35506
+ }
35507
+ }
35508
+ return null;
35509
+ }
35510
+ /**
35511
+ * Traverses up the AST starting from the given node to extract the source location from comments
35512
+ * that have been emitted into the TCB. If the node does not exist within a TCB, or if an ignore
35513
+ * marker comment is found up the tree (and this is part of a diagnostic request), this function
35514
+ * returns null.
35515
+ */
35516
+ function findSourceLocation(node, sourceFile, isDiagnosticsRequest) {
35517
+ // Search for comments until the TCB's function declaration is encountered.
35518
+ while (node !== undefined && !ts$1.isFunctionDeclaration(node)) {
35519
+ if (hasIgnoreForDiagnosticsMarker(node, sourceFile) && isDiagnosticsRequest) {
35520
+ // There's an ignore marker on this node, so the diagnostic should not be reported.
35521
+ return null;
35522
+ }
35523
+ const span = readSpanComment(node, sourceFile);
35524
+ if (span !== null) {
35525
+ // Once the positional information has been extracted, search further up the TCB to extract
35526
+ // the unique id that is attached with the TCB's function declaration.
35527
+ const id = getTemplateId$1(node, sourceFile, isDiagnosticsRequest);
35528
+ if (id === null) {
35529
+ return null;
35530
+ }
35531
+ return { id, span };
35532
+ }
35533
+ node = node.parent;
35534
+ }
35535
+ return null;
35536
+ }
35537
+ function getTemplateId$1(node, sourceFile, isDiagnosticRequest) {
35538
+ // Walk up to the function declaration of the TCB, the file information is attached there.
35539
+ while (!ts$1.isFunctionDeclaration(node)) {
35540
+ if (hasIgnoreForDiagnosticsMarker(node, sourceFile) && isDiagnosticRequest) {
35541
+ // There's an ignore marker on this node, so the diagnostic should not be reported.
35542
+ return null;
35543
+ }
35544
+ node = node.parent;
35545
+ // Bail once we have reached the root.
35546
+ if (node === undefined) {
35547
+ return null;
35548
+ }
35549
+ }
35550
+ const start = node.getFullStart();
35551
+ return ts$1.forEachLeadingCommentRange(sourceFile.text, start, (pos, end, kind) => {
35552
+ if (kind !== ts$1.SyntaxKind.MultiLineCommentTrivia) {
35553
+ return null;
35554
+ }
35555
+ const commentText = sourceFile.text.substring(pos + 2, end - 2);
35556
+ return commentText;
35557
+ }) || null;
35558
+ }
35559
+ function checkIfGenericTypeBoundsAreContextFree(node, reflector) {
35560
+ // Generic type parameters are considered context free if they can be emitted into any context.
35561
+ return new TypeParameterEmitter(node.typeParameters, reflector).canEmit();
35562
+ }
35563
+
35371
35564
  /**
35372
35565
  * @license
35373
35566
  * Copyright Google LLC All Rights Reserved.
@@ -35532,10 +35725,6 @@ Either add the @Injectable() decorator to '${provider.node.name
35532
35725
  // emitted into a different context.
35533
35726
  return !checkIfGenericTypeBoundsAreContextFree(node, host);
35534
35727
  }
35535
- function checkIfGenericTypeBoundsAreContextFree(node, reflector) {
35536
- // Generic type parameters are considered context free if they can be emitted into any context.
35537
- return new TypeParameterEmitter(node.typeParameters, reflector).canEmit();
35538
- }
35539
35728
  /**
35540
35729
  * Add a default `= any` to type parameters that don't have a default value already.
35541
35730
  *
@@ -35844,109 +36033,6 @@ Either add the @Injectable() decorator to '${provider.node.name
35844
36033
  return Object.assign(Object.assign({}, makeDiagnostic(code, node, messageText, relatedInformation)), { componentFile: node.getSourceFile(), templateId });
35845
36034
  }
35846
36035
 
35847
- /**
35848
- * @license
35849
- * Copyright Google LLC All Rights Reserved.
35850
- *
35851
- * Use of this source code is governed by an MIT-style license that can be
35852
- * found in the LICENSE file at https://angular.io/license
35853
- */
35854
- function requiresInlineTypeCheckBlock(node, usedPipes) {
35855
- // In order to qualify for a declared TCB (not inline) two conditions must be met:
35856
- // 1) the class must be exported
35857
- // 2) it must not have constrained generic types
35858
- if (!checkIfClassIsExported(node)) {
35859
- // Condition 1 is false, the class is not exported.
35860
- return true;
35861
- }
35862
- else if (!checkIfGenericTypesAreUnbound(node)) {
35863
- // Condition 2 is false, the class has constrained generic types
35864
- return true;
35865
- }
35866
- else if (Array.from(usedPipes.values())
35867
- .some(pipeRef => !checkIfClassIsExported(pipeRef.node))) {
35868
- // If one of the pipes used by the component is not exported, a non-inline TCB will not be able
35869
- // to import it, so this requires an inline TCB.
35870
- return true;
35871
- }
35872
- else {
35873
- return false;
35874
- }
35875
- }
35876
- /** Maps a shim position back to a template location. */
35877
- function getTemplateMapping(shimSf, position, resolver, isDiagnosticRequest) {
35878
- const node = getTokenAtPosition(shimSf, position);
35879
- const sourceLocation = findSourceLocation(node, shimSf, isDiagnosticRequest);
35880
- if (sourceLocation === null) {
35881
- return null;
35882
- }
35883
- const mapping = resolver.getSourceMapping(sourceLocation.id);
35884
- const span = resolver.toParseSourceSpan(sourceLocation.id, sourceLocation.span);
35885
- if (span === null) {
35886
- return null;
35887
- }
35888
- // TODO(atscott): Consider adding a context span by walking up from `node` until we get a
35889
- // different span.
35890
- return { sourceLocation, templateSourceMapping: mapping, span };
35891
- }
35892
- function findTypeCheckBlock(file, id, isDiagnosticRequest) {
35893
- for (const stmt of file.statements) {
35894
- if (ts$1.isFunctionDeclaration(stmt) && getTemplateId$1(stmt, file, isDiagnosticRequest) === id) {
35895
- return stmt;
35896
- }
35897
- }
35898
- return null;
35899
- }
35900
- /**
35901
- * Traverses up the AST starting from the given node to extract the source location from comments
35902
- * that have been emitted into the TCB. If the node does not exist within a TCB, or if an ignore
35903
- * marker comment is found up the tree (and this is part of a diagnostic request), this function
35904
- * returns null.
35905
- */
35906
- function findSourceLocation(node, sourceFile, isDiagnosticsRequest) {
35907
- // Search for comments until the TCB's function declaration is encountered.
35908
- while (node !== undefined && !ts$1.isFunctionDeclaration(node)) {
35909
- if (hasIgnoreForDiagnosticsMarker(node, sourceFile) && isDiagnosticsRequest) {
35910
- // There's an ignore marker on this node, so the diagnostic should not be reported.
35911
- return null;
35912
- }
35913
- const span = readSpanComment(node, sourceFile);
35914
- if (span !== null) {
35915
- // Once the positional information has been extracted, search further up the TCB to extract
35916
- // the unique id that is attached with the TCB's function declaration.
35917
- const id = getTemplateId$1(node, sourceFile, isDiagnosticsRequest);
35918
- if (id === null) {
35919
- return null;
35920
- }
35921
- return { id, span };
35922
- }
35923
- node = node.parent;
35924
- }
35925
- return null;
35926
- }
35927
- function getTemplateId$1(node, sourceFile, isDiagnosticRequest) {
35928
- // Walk up to the function declaration of the TCB, the file information is attached there.
35929
- while (!ts$1.isFunctionDeclaration(node)) {
35930
- if (hasIgnoreForDiagnosticsMarker(node, sourceFile) && isDiagnosticRequest) {
35931
- // There's an ignore marker on this node, so the diagnostic should not be reported.
35932
- return null;
35933
- }
35934
- node = node.parent;
35935
- // Bail once we have reached the root.
35936
- if (node === undefined) {
35937
- return null;
35938
- }
35939
- }
35940
- const start = node.getFullStart();
35941
- return ts$1.forEachLeadingCommentRange(sourceFile.text, start, (pos, end, kind) => {
35942
- if (kind !== ts$1.SyntaxKind.MultiLineCommentTrivia) {
35943
- return null;
35944
- }
35945
- const commentText = sourceFile.text.substring(pos + 2, end - 2);
35946
- return commentText;
35947
- }) || null;
35948
- }
35949
-
35950
36036
  /**
35951
36037
  * @license
35952
36038
  * Copyright Google LLC All Rights Reserved.
@@ -36091,7 +36177,9 @@ Either add the @Injectable() decorator to '${provider.node.name
36091
36177
  }
36092
36178
  // The `EmptyExpr` doesn't have a dedicated method on `AstVisitor`, so it's special cased here.
36093
36179
  if (ast instanceof EmptyExpr) {
36094
- return UNDEFINED;
36180
+ const res = ts$1.factory.createIdentifier('undefined');
36181
+ addParseSpanInfo(res, ast.sourceSpan);
36182
+ return res;
36095
36183
  }
36096
36184
  // First attempt to let any custom resolution logic provide a translation for the given node.
36097
36185
  const resolved = this.maybeResolve(ast);
@@ -36455,6 +36543,32 @@ Either add the @Injectable() decorator to '${provider.node.name
36455
36543
  * Use of this source code is governed by an MIT-style license that can be
36456
36544
  * found in the LICENSE file at https://angular.io/license
36457
36545
  */
36546
+ /**
36547
+ * Controls how generics for the component context class will be handled during TCB generation.
36548
+ */
36549
+ var TcbGenericContextBehavior;
36550
+ (function (TcbGenericContextBehavior) {
36551
+ /**
36552
+ * References to generic parameter bounds will be emitted via the `TypeParameterEmitter`.
36553
+ *
36554
+ * The caller must verify that all parameter bounds are emittable in order to use this mode.
36555
+ */
36556
+ TcbGenericContextBehavior[TcbGenericContextBehavior["UseEmitter"] = 0] = "UseEmitter";
36557
+ /**
36558
+ * Generic parameter declarations will be copied directly from the `ts.ClassDeclaration` of the
36559
+ * component class.
36560
+ *
36561
+ * The caller must only use the generated TCB code in a context where such copies will still be
36562
+ * valid, such as an inline type check block.
36563
+ */
36564
+ TcbGenericContextBehavior[TcbGenericContextBehavior["CopyClassNodes"] = 1] = "CopyClassNodes";
36565
+ /**
36566
+ * Any generic parameters for the component context class will be set to `any`.
36567
+ *
36568
+ * Produces a less useful type, but is always safe to use.
36569
+ */
36570
+ TcbGenericContextBehavior[TcbGenericContextBehavior["FallbackToAny"] = 2] = "FallbackToAny";
36571
+ })(TcbGenericContextBehavior || (TcbGenericContextBehavior = {}));
36458
36572
  /**
36459
36573
  * Given a `ts.ClassDeclaration` for a component, and metadata regarding that component, compose a
36460
36574
  * "type check block" function.
@@ -36476,15 +36590,39 @@ Either add the @Injectable() decorator to '${provider.node.name
36476
36590
  * and bindings.
36477
36591
  * @param oobRecorder used to record errors regarding template elements which could not be correctly
36478
36592
  * translated into types during TCB generation.
36593
+ * @param genericContextBehavior controls how generic parameters (especially parameters with generic
36594
+ * bounds) will be referenced from the generated TCB code.
36479
36595
  */
36480
- function generateTypeCheckBlock(env, ref, name, meta, domSchemaChecker, oobRecorder) {
36596
+ function generateTypeCheckBlock(env, ref, name, meta, domSchemaChecker, oobRecorder, genericContextBehavior) {
36481
36597
  const tcb = new Context$1(env, domSchemaChecker, oobRecorder, meta.id, meta.boundTarget, meta.pipes, meta.schemas);
36482
36598
  const scope = Scope$1.forNodes(tcb, null, tcb.boundTarget.target.template, /* guard */ null);
36483
36599
  const ctxRawType = env.referenceType(ref);
36484
36600
  if (!ts$1.isTypeReferenceNode(ctxRawType)) {
36485
36601
  throw new Error(`Expected TypeReferenceNode when referencing the ctx param for ${ref.debugName}`);
36486
36602
  }
36487
- const paramList = [tcbCtxParam(ref.node, ctxRawType.typeName, env.config.useContextGenericType)];
36603
+ let typeParameters = undefined;
36604
+ let typeArguments = undefined;
36605
+ if (ref.node.typeParameters !== undefined) {
36606
+ if (!env.config.useContextGenericType) {
36607
+ genericContextBehavior = TcbGenericContextBehavior.FallbackToAny;
36608
+ }
36609
+ switch (genericContextBehavior) {
36610
+ case TcbGenericContextBehavior.UseEmitter:
36611
+ // Guaranteed to emit type parameters since we checked that the class has them above.
36612
+ typeParameters = new TypeParameterEmitter(ref.node.typeParameters, env.reflector)
36613
+ .emit(typeRef => env.referenceType(typeRef));
36614
+ typeArguments = typeParameters.map(param => ts$1.factory.createTypeReferenceNode(param.name));
36615
+ break;
36616
+ case TcbGenericContextBehavior.CopyClassNodes:
36617
+ typeParameters = [...ref.node.typeParameters];
36618
+ typeArguments = typeParameters.map(param => ts$1.factory.createTypeReferenceNode(param.name));
36619
+ break;
36620
+ case TcbGenericContextBehavior.FallbackToAny:
36621
+ typeArguments = ref.node.typeParameters.map(() => ts$1.factory.createKeywordTypeNode(ts$1.SyntaxKind.AnyKeyword));
36622
+ break;
36623
+ }
36624
+ }
36625
+ const paramList = [tcbCtxParam(ref.node, ctxRawType.typeName, typeArguments)];
36488
36626
  const scopeStatements = scope.render();
36489
36627
  const innerBody = ts$1.createBlock([
36490
36628
  ...env.getPreludeStatements(),
@@ -36498,7 +36636,7 @@ Either add the @Injectable() decorator to '${provider.node.name
36498
36636
  /* modifiers */ undefined,
36499
36637
  /* asteriskToken */ undefined,
36500
36638
  /* name */ name,
36501
- /* typeParameters */ env.config.useContextGenericType ? ref.node.typeParameters : undefined,
36639
+ /* typeParameters */ env.config.useContextGenericType ? typeParameters : undefined,
36502
36640
  /* parameters */ paramList,
36503
36641
  /* type */ undefined,
36504
36642
  /* body */ body);
@@ -37867,26 +38005,11 @@ Either add the @Injectable() decorator to '${provider.node.name
37867
38005
  }
37868
38006
  }
37869
38007
  /**
37870
- * Create the `ctx` parameter to the top-level TCB function.
37871
- *
37872
- * This is a parameter with a type equivalent to the component type, with all generic type
37873
- * parameters listed (without their generic bounds).
38008
+ * Create the `ctx` parameter to the top-level TCB function, with the given generic type arguments.
37874
38009
  */
37875
- function tcbCtxParam(node, name, useGenericType) {
37876
- let typeArguments = undefined;
37877
- // Check if the component is generic, and pass generic type parameters if so.
37878
- if (node.typeParameters !== undefined) {
37879
- if (useGenericType) {
37880
- typeArguments =
37881
- node.typeParameters.map(param => ts$1.createTypeReferenceNode(param.name, undefined));
37882
- }
37883
- else {
37884
- typeArguments =
37885
- node.typeParameters.map(() => ts$1.createKeywordTypeNode(ts$1.SyntaxKind.AnyKeyword));
37886
- }
37887
- }
37888
- const type = ts$1.createTypeReferenceNode(name, typeArguments);
37889
- return ts$1.createParameter(
38010
+ function tcbCtxParam(node, name, typeArguments) {
38011
+ const type = ts$1.factory.createTypeReferenceNode(name, typeArguments);
38012
+ return ts$1.factory.createParameterDeclaration(
37890
38013
  /* decorators */ undefined,
37891
38014
  /* modifiers */ undefined,
37892
38015
  /* dotDotDotToken */ undefined,
@@ -38197,9 +38320,9 @@ Either add the @Injectable() decorator to '${provider.node.name
38197
38320
  this.nextTcbId = 1;
38198
38321
  this.tcbStatements = [];
38199
38322
  }
38200
- addTypeCheckBlock(ref, meta, domSchemaChecker, oobRecorder) {
38323
+ addTypeCheckBlock(ref, meta, domSchemaChecker, oobRecorder, genericContextBehavior) {
38201
38324
  const fnId = ts$1.createIdentifier(`_tcb${this.nextTcbId++}`);
38202
- const fn = generateTypeCheckBlock(this, ref, fnId, meta, domSchemaChecker, oobRecorder);
38325
+ const fn = generateTypeCheckBlock(this, ref, fnId, meta, domSchemaChecker, oobRecorder, genericContextBehavior);
38203
38326
  this.tcbStatements.push(fn);
38204
38327
  }
38205
38328
  render(removeComments) {
@@ -38331,10 +38454,11 @@ Either add the @Injectable() decorator to '${provider.node.name
38331
38454
  boundTarget,
38332
38455
  templateDiagnostics,
38333
38456
  });
38334
- const tcbRequiresInline = requiresInlineTypeCheckBlock(ref.node, pipes);
38457
+ const inliningRequirement = requiresInlineTypeCheckBlock(ref.node, pipes, this.reflector);
38335
38458
  // If inlining is not supported, but is required for either the TCB or one of its directive
38336
38459
  // dependencies, then exit here with an error.
38337
- if (this.inlining === InliningMode.Error && tcbRequiresInline) {
38460
+ if (this.inlining === InliningMode.Error &&
38461
+ inliningRequirement === TcbInliningRequirement.MustInline) {
38338
38462
  // This template cannot be supported because the underlying strategy does not support inlining
38339
38463
  // and inlining would be required.
38340
38464
  // Record diagnostics to indicate the issues with this template.
@@ -38350,14 +38474,23 @@ Either add the @Injectable() decorator to '${provider.node.name
38350
38474
  schemas,
38351
38475
  };
38352
38476
  this.perf.eventCount(PerfEvent.GenerateTcb);
38353
- if (tcbRequiresInline) {
38477
+ if (inliningRequirement !== TcbInliningRequirement.None &&
38478
+ this.inlining === InliningMode.InlineOps) {
38354
38479
  // This class didn't meet the requirements for external type checking, so generate an inline
38355
38480
  // TCB for the class.
38356
38481
  this.addInlineTypeCheckBlock(fileData, shimData, ref, meta);
38357
38482
  }
38483
+ else if (inliningRequirement === TcbInliningRequirement.ShouldInlineForGenericBounds &&
38484
+ this.inlining === InliningMode.Error) {
38485
+ // It's suggested that this TCB should be generated inline due to the component's generic
38486
+ // bounds, but inlining is not supported by the current environment. Use a non-inline type
38487
+ // check block, but fall back to `any` generic parameters since the generic bounds can't be
38488
+ // referenced in that context. This will infer a less useful type for the component, but allow
38489
+ // for type-checking it in an environment where that would not be possible otherwise.
38490
+ shimData.file.addTypeCheckBlock(ref, meta, shimData.domSchemaChecker, shimData.oobRecorder, TcbGenericContextBehavior.FallbackToAny);
38491
+ }
38358
38492
  else {
38359
- // The class can be type-checked externally as normal.
38360
- shimData.file.addTypeCheckBlock(ref, meta, shimData.domSchemaChecker, shimData.oobRecorder);
38493
+ shimData.file.addTypeCheckBlock(ref, meta, shimData.domSchemaChecker, shimData.oobRecorder, TcbGenericContextBehavior.UseEmitter);
38361
38494
  }
38362
38495
  }
38363
38496
  /**
@@ -38447,7 +38580,7 @@ Either add the @Injectable() decorator to '${provider.node.name
38447
38580
  this.opMap.set(sf, []);
38448
38581
  }
38449
38582
  const ops = this.opMap.get(sf);
38450
- ops.push(new TcbOp$1(ref, tcbMeta, this.config, this.reflector, shimData.domSchemaChecker, shimData.oobRecorder));
38583
+ ops.push(new InlineTcbOp(ref, tcbMeta, this.config, this.reflector, shimData.domSchemaChecker, shimData.oobRecorder));
38451
38584
  fileData.hasInlines = true;
38452
38585
  }
38453
38586
  pendingShimForComponent(node) {
@@ -38490,9 +38623,9 @@ Either add the @Injectable() decorator to '${provider.node.name
38490
38623
  }
38491
38624
  }
38492
38625
  /**
38493
- * A type check block operation which produces type check code for a particular component.
38626
+ * A type check block operation which produces inline type check code for a particular component.
38494
38627
  */
38495
- class TcbOp$1 {
38628
+ class InlineTcbOp {
38496
38629
  constructor(ref, meta, config, reflector, domSchemaChecker, oobRecorder) {
38497
38630
  this.ref = ref;
38498
38631
  this.meta = meta;
@@ -38510,7 +38643,9 @@ Either add the @Injectable() decorator to '${provider.node.name
38510
38643
  execute(im, sf, refEmitter, printer) {
38511
38644
  const env = new Environment(this.config, im, refEmitter, this.reflector, sf);
38512
38645
  const fnName = ts$1.createIdentifier(`_tcb_${this.ref.node.pos}`);
38513
- const fn = generateTypeCheckBlock(env, this.ref, fnName, this.meta, this.domSchemaChecker, this.oobRecorder);
38646
+ // Inline TCBs should copy any generic type parameter nodes directly, as the TCB code is inlined
38647
+ // into the class in a context where that will always be legal.
38648
+ const fn = generateTypeCheckBlock(env, this.ref, fnName, this.meta, this.domSchemaChecker, this.oobRecorder, TcbGenericContextBehavior.CopyClassNodes);
38514
38649
  return printer.printNode(ts$1.EmitHint.Unspecified, fn, sf);
38515
38650
  }
38516
38651
  }
@@ -39339,12 +39474,12 @@ Either add the @Injectable() decorator to '${provider.node.name
39339
39474
  getTypeCheckBlock(component) {
39340
39475
  return this.getLatestComponentState(component).tcb;
39341
39476
  }
39342
- getGlobalCompletions(context, component) {
39477
+ getGlobalCompletions(context, component, node) {
39343
39478
  const engine = this.getOrCreateCompletionEngine(component);
39344
39479
  if (engine === null) {
39345
39480
  return null;
39346
39481
  }
39347
- return this.perf.inPhase(PerfPhase.TtcAutocompletion, () => engine.getGlobalCompletions(context));
39482
+ return this.perf.inPhase(PerfPhase.TtcAutocompletion, () => engine.getGlobalCompletions(context, node));
39348
39483
  }
39349
39484
  getExpressionCompletionLocation(ast, component) {
39350
39485
  const engine = this.getOrCreateCompletionEngine(component);
@@ -40120,10 +40255,11 @@ Either add the @Injectable() decorator to '${provider.node.name
40120
40255
  else {
40121
40256
  importRewriter = new NoopImportRewriter();
40122
40257
  }
40258
+ const defaultImportTracker = new DefaultImportTracker();
40123
40259
  const before = [
40124
- ivyTransformFactory(compilation.traitCompiler, compilation.reflector, importRewriter, compilation.defaultImportTracker, this.delegatingPerfRecorder, compilation.isCore, this.closureCompilerEnabled),
40260
+ ivyTransformFactory(compilation.traitCompiler, compilation.reflector, importRewriter, defaultImportTracker, this.delegatingPerfRecorder, compilation.isCore, this.closureCompilerEnabled),
40125
40261
  aliasTransformFactory(compilation.traitCompiler.exportStatements),
40126
- compilation.defaultImportTracker.importPreservingTransformer(),
40262
+ defaultImportTracker.importPreservingTransformer(),
40127
40263
  ];
40128
40264
  const afterDeclarations = [];
40129
40265
  if (compilation.dtsTransforms !== null) {
@@ -40428,7 +40564,6 @@ Either add the @Injectable() decorator to '${provider.node.name
40428
40564
  const dtsTransforms = new DtsTransformRegistry();
40429
40565
  const mwpScanner = new ModuleWithProvidersScanner(reflector, evaluator, refEmitter);
40430
40566
  const isCore = isAngularCorePackage(this.tsProgram);
40431
- const defaultImportTracker = new DefaultImportTracker();
40432
40567
  const resourceRegistry = new ResourceRegistry();
40433
40568
  const compilationMode = this.options.compilationMode === 'partial' ? CompilationMode.PARTIAL : CompilationMode.FULL;
40434
40569
  // Cycles are handled in full compilation mode by "remote scoping".
@@ -40439,17 +40574,17 @@ Either add the @Injectable() decorator to '${provider.node.name
40439
40574
  1 /* Error */;
40440
40575
  // Set up the IvyCompilation, which manages state for the Ivy transformer.
40441
40576
  const handlers = [
40442
- new ComponentDecoratorHandler(reflector, evaluator, metaRegistry, metaReader, scopeReader, scopeRegistry, typeCheckScopeRegistry, resourceRegistry, isCore, this.resourceManager, this.adapter.rootDirs, this.options.preserveWhitespaces || false, this.options.i18nUseExternalIds !== false, this.options.enableI18nLegacyMessageIdFormat !== false, this.usePoisonedData, this.options.i18nNormalizeLineEndingsInICUs, this.moduleResolver, this.cycleAnalyzer, cycleHandlingStrategy, refEmitter, defaultImportTracker, this.incrementalDriver.depGraph, injectableRegistry, semanticDepGraphUpdater, this.closureCompilerEnabled, this.delegatingPerfRecorder),
40577
+ new ComponentDecoratorHandler(reflector, evaluator, metaRegistry, metaReader, scopeReader, scopeRegistry, typeCheckScopeRegistry, resourceRegistry, isCore, this.resourceManager, this.adapter.rootDirs, this.options.preserveWhitespaces || false, this.options.i18nUseExternalIds !== false, this.options.enableI18nLegacyMessageIdFormat !== false, this.usePoisonedData, this.options.i18nNormalizeLineEndingsInICUs, this.moduleResolver, this.cycleAnalyzer, cycleHandlingStrategy, refEmitter, this.incrementalDriver.depGraph, injectableRegistry, semanticDepGraphUpdater, this.closureCompilerEnabled, this.delegatingPerfRecorder),
40443
40578
  // TODO(alxhub): understand why the cast here is necessary (something to do with `null`
40444
40579
  // not being assignable to `unknown` when wrapped in `Readonly`).
40445
40580
  // clang-format off
40446
- new DirectiveDecoratorHandler(reflector, evaluator, metaRegistry, scopeRegistry, metaReader, defaultImportTracker, injectableRegistry, isCore, semanticDepGraphUpdater, this.closureCompilerEnabled, compileUndecoratedClassesWithAngularFeatures, this.delegatingPerfRecorder),
40581
+ new DirectiveDecoratorHandler(reflector, evaluator, metaRegistry, scopeRegistry, metaReader, injectableRegistry, isCore, semanticDepGraphUpdater, this.closureCompilerEnabled, compileUndecoratedClassesWithAngularFeatures, this.delegatingPerfRecorder),
40447
40582
  // clang-format on
40448
40583
  // Pipe handler must be before injectable handler in list so pipe factories are printed
40449
40584
  // before injectable factories (so injectable factories can delegate to them)
40450
- new PipeDecoratorHandler(reflector, evaluator, metaRegistry, scopeRegistry, defaultImportTracker, injectableRegistry, isCore, this.delegatingPerfRecorder),
40451
- new InjectableDecoratorHandler(reflector, defaultImportTracker, isCore, this.options.strictInjectionParameters || false, injectableRegistry, this.delegatingPerfRecorder),
40452
- new NgModuleDecoratorHandler(reflector, evaluator, metaReader, metaRegistry, scopeRegistry, referencesRegistry, isCore, routeAnalyzer, refEmitter, this.adapter.factoryTracker, defaultImportTracker, this.closureCompilerEnabled, injectableRegistry, this.delegatingPerfRecorder, this.options.i18nInLocale),
40585
+ new PipeDecoratorHandler(reflector, evaluator, metaRegistry, scopeRegistry, injectableRegistry, isCore, this.delegatingPerfRecorder),
40586
+ new InjectableDecoratorHandler(reflector, isCore, this.options.strictInjectionParameters || false, injectableRegistry, this.delegatingPerfRecorder),
40587
+ new NgModuleDecoratorHandler(reflector, evaluator, metaReader, metaRegistry, scopeRegistry, referencesRegistry, isCore, routeAnalyzer, refEmitter, this.adapter.factoryTracker, this.closureCompilerEnabled, injectableRegistry, this.delegatingPerfRecorder, this.options.i18nInLocale),
40453
40588
  ];
40454
40589
  const traitCompiler = new TraitCompiler(handlers, reflector, this.delegatingPerfRecorder, this.incrementalDriver, this.options.compileNonExportedClasses !== false, compilationMode, dtsTransforms, semanticDepGraphUpdater);
40455
40590
  const templateTypeChecker = new TemplateTypeCheckerImpl(this.tsProgram, this.typeCheckingProgramStrategy, traitCompiler, this.getTypeCheckingConfig(), refEmitter, reflector, this.adapter, this.incrementalDriver, scopeRegistry, typeCheckScopeRegistry, this.delegatingPerfRecorder);
@@ -40464,7 +40599,6 @@ Either add the @Injectable() decorator to '${provider.node.name
40464
40599
  mwpScanner,
40465
40600
  metaReader,
40466
40601
  typeCheckScopeRegistry,
40467
- defaultImportTracker,
40468
40602
  aliasingHost,
40469
40603
  refEmitter,
40470
40604
  templateTypeChecker,
@@ -41039,7 +41173,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
41039
41173
  */
41040
41174
  function toAttributeString(attribute) {
41041
41175
  var _a, _b;
41042
- if (attribute instanceof BoundEvent) {
41176
+ if (attribute instanceof BoundEvent || attribute instanceof BoundAttribute) {
41043
41177
  return `[${attribute.name}]`;
41044
41178
  }
41045
41179
  else {
@@ -41217,6 +41351,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
41217
41351
  * Use of this source code is governed by an MIT-style license that can be
41218
41352
  * found in the LICENSE file at https://angular.io/license
41219
41353
  */
41354
+ const PRE_COMPILED_STYLE_EXTENSIONS = ['.scss', '.sass', '.less', '.styl'];
41220
41355
  class LanguageServiceAdapter {
41221
41356
  constructor(project) {
41222
41357
  this.project = project;
@@ -41233,6 +41368,22 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
41233
41368
  this.lastReadResourceVersion = new Map();
41234
41369
  this.rootDirs = getRootDirs(this, project.getCompilationSettings());
41235
41370
  }
41371
+ resourceNameToFileName(url, fromFile, fallbackResolve) {
41372
+ var _a;
41373
+ // If we are trying to resolve a `.css` file, see if we can find a pre-compiled file with the
41374
+ // same name instead. That way, we can provide go-to-definition for the pre-compiled files which
41375
+ // would generally be the desired behavior.
41376
+ if (url.endsWith('.css')) {
41377
+ const styleUrl = path.resolve(fromFile, '..', url);
41378
+ for (const ext of PRE_COMPILED_STYLE_EXTENSIONS) {
41379
+ const precompiledFileUrl = styleUrl.replace(/\.css$/, ext);
41380
+ if (this.fileExists(precompiledFileUrl)) {
41381
+ return precompiledFileUrl;
41382
+ }
41383
+ }
41384
+ }
41385
+ return (_a = fallbackResolve === null || fallbackResolve === void 0 ? void 0 : fallbackResolve(url, fromFile)) !== null && _a !== void 0 ? _a : null;
41386
+ }
41236
41387
  isShim(sf) {
41237
41388
  return isShim(sf);
41238
41389
  }
@@ -42292,17 +42443,17 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
42292
42443
  * Get completions for a property expression in a global context (e.g. `{{y|}}`).
42293
42444
  */
42294
42445
  getGlobalPropertyExpressionCompletion(options) {
42295
- const completions = this.templateTypeChecker.getGlobalCompletions(this.template, this.component);
42446
+ const completions = this.templateTypeChecker.getGlobalCompletions(this.template, this.component, this.node);
42296
42447
  if (completions === null) {
42297
42448
  return undefined;
42298
42449
  }
42299
- const { componentContext, templateContext } = completions;
42450
+ const { componentContext, templateContext, nodeContext: astContext } = completions;
42300
42451
  const replacementSpan = makeReplacementSpanFromAst(this.node);
42301
42452
  // Merge TS completion results with results from the template scope.
42302
42453
  let entries = [];
42303
- const tsLsCompletions = this.tsLS.getCompletionsAtPosition(componentContext.shimPath, componentContext.positionInShimFile, options);
42304
- if (tsLsCompletions !== undefined) {
42305
- for (const tsCompletion of tsLsCompletions.entries) {
42454
+ const componentCompletions = this.tsLS.getCompletionsAtPosition(componentContext.shimPath, componentContext.positionInShimFile, options);
42455
+ if (componentCompletions !== undefined) {
42456
+ for (const tsCompletion of componentCompletions.entries) {
42306
42457
  // Skip completions that are shadowed by a template entity definition.
42307
42458
  if (templateContext.has(tsCompletion.name)) {
42308
42459
  continue;
@@ -42313,6 +42464,20 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
42313
42464
  replacementSpan }));
42314
42465
  }
42315
42466
  }
42467
+ // Merge TS completion results with results from the ast context.
42468
+ if (astContext !== null) {
42469
+ const nodeCompletions = this.tsLS.getCompletionsAtPosition(astContext.shimPath, astContext.positionInShimFile, options);
42470
+ if (nodeCompletions !== undefined) {
42471
+ for (const tsCompletion of nodeCompletions.entries) {
42472
+ if (this.isValidNodeContextCompletion(tsCompletion)) {
42473
+ entries.push(Object.assign(Object.assign({}, tsCompletion), {
42474
+ // Substitute the TS completion's `replacementSpan` (which uses offsets within the
42475
+ // TCB) with the `replacementSpan` within the template source.
42476
+ replacementSpan }));
42477
+ }
42478
+ }
42479
+ }
42480
+ }
42316
42481
  for (const [name, entity] of templateContext) {
42317
42482
  entries.push({
42318
42483
  name,
@@ -42338,7 +42503,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
42338
42503
  * `{{y|}}`).
42339
42504
  */
42340
42505
  getGlobalPropertyExpressionCompletionDetails(entryName, formatOptions, preferences) {
42341
- const completions = this.templateTypeChecker.getGlobalCompletions(this.template, this.component);
42506
+ const completions = this.templateTypeChecker.getGlobalCompletions(this.template, this.component, this.node);
42342
42507
  if (completions === null) {
42343
42508
  return undefined;
42344
42509
  }
@@ -42371,7 +42536,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
42371
42536
  * `{{y|}}`).
42372
42537
  */
42373
42538
  getGlobalPropertyExpressionCompletionSymbol(entryName) {
42374
- const completions = this.templateTypeChecker.getGlobalCompletions(this.template, this.component);
42539
+ const completions = this.templateTypeChecker.getGlobalCompletions(this.template, this.component, this.node);
42375
42540
  if (completions === null) {
42376
42541
  return undefined;
42377
42542
  }
@@ -42643,6 +42808,24 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
42643
42808
  isNewIdentifierLocation: false,
42644
42809
  };
42645
42810
  }
42811
+ /**
42812
+ * From the AST node of the cursor position, include completion of string literals, number
42813
+ * literals, `true`, `false`, `null`, and `undefined`.
42814
+ */
42815
+ isValidNodeContextCompletion(completion) {
42816
+ if (completion.kind === ts$1.ScriptElementKind.string) {
42817
+ // 'string' kind includes both string literals and number literals
42818
+ return true;
42819
+ }
42820
+ if (completion.kind === ts$1.ScriptElementKind.keyword) {
42821
+ return completion.name === 'true' || completion.name === 'false' ||
42822
+ completion.name === 'null';
42823
+ }
42824
+ if (completion.kind === ts$1.ScriptElementKind.variableElement) {
42825
+ return completion.name === 'undefined';
42826
+ }
42827
+ return false;
42828
+ }
42646
42829
  }
42647
42830
  function makeReplacementSpanFromParseSourceSpan(span) {
42648
42831
  return {
@@ -43460,6 +43643,9 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`,
43460
43643
  entries.set(createLocationKey(entry), entry);
43461
43644
  }
43462
43645
  }
43646
+ else {
43647
+ entries.set(createLocationKey(ref), ref);
43648
+ }
43463
43649
  }
43464
43650
  return Array.from(entries.values());
43465
43651
  }