@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 +478 -292
- package/bundles/language-service.js +62 -48
- package/ivy/adapters.d.ts +1 -0
- package/ivy/adapters.js +32 -4
- package/ivy/completions.d.ts +5 -0
- package/ivy/completions.js +60 -18
- package/ivy/references.js +2 -4
- package/ivy/utils.js +2 -2
- package/package.json +1 -1
package/bundles/ivy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v11.2.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
22259
|
-
const sf = getSourceFile(
|
|
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(
|
|
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 `
|
|
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.
|
|
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.
|
|
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,
|
|
27810
|
-
const
|
|
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,
|
|
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,
|
|
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.
|
|
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, {
|
|
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, {
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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(
|
|
28079
|
-
return
|
|
28080
|
-
|
|
28081
|
-
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
|
|
28262
|
-
|
|
28263
|
-
|
|
28298
|
+
const expr = new WrappedNodeExpr(valueRef.expression);
|
|
28299
|
+
if (valueRef.defaultImportStatement !== null) {
|
|
28300
|
+
attachDefaultImportDeclaration(expr, valueRef.defaultImportStatement);
|
|
28264
28301
|
}
|
|
28265
|
-
return
|
|
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,
|
|
28297
|
-
return validateConstructorDependencies(clazz, getConstructorDependencies(clazz, reflector,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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.
|
|
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.
|
|
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,
|
|
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,
|
|
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,
|
|
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.
|
|
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.
|
|
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,
|
|
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.
|
|
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.
|
|
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,
|
|
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.
|
|
31196
|
-
metadataStmt: generateSetClassMetadataCall(node, this.reflector, this.
|
|
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,
|
|
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,
|
|
31386
|
+
ctorDeps = getValidConstructorDependencies(clazz, reflector, isCore);
|
|
31354
31387
|
}
|
|
31355
31388
|
else {
|
|
31356
|
-
ctorDeps =
|
|
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,
|
|
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,
|
|
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.
|
|
31547
|
+
deps: getValidConstructorDependencies(clazz, this.reflector, this.isCore),
|
|
31515
31548
|
pure,
|
|
31516
31549
|
},
|
|
31517
|
-
metadataStmt: generateSetClassMetadataCall(clazz, this.reflector, this.
|
|
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
|
|
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
|
|
34724
|
-
*
|
|
34757
|
+
* Cache of completions for various levels of the template, including the root template (`null`).
|
|
34758
|
+
* Memoizes `getTemplateContextCompletions`.
|
|
34725
34759
|
*/
|
|
34726
|
-
this.
|
|
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
|
|
34743
|
-
|
|
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
|
-
|
|
34754
|
-
|
|
34755
|
-
|
|
34756
|
-
|
|
34757
|
-
|
|
34758
|
-
|
|
34759
|
-
|
|
34760
|
-
|
|
34761
|
-
|
|
34762
|
-
|
|
34763
|
-
|
|
34764
|
-
|
|
34765
|
-
|
|
34766
|
-
|
|
34767
|
-
|
|
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
|
-
|
|
34772
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 ?
|
|
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,
|
|
37876
|
-
|
|
37877
|
-
|
|
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
|
|
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 &&
|
|
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 (
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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,
|
|
40260
|
+
ivyTransformFactory(compilation.traitCompiler, compilation.reflector, importRewriter, defaultImportTracker, this.delegatingPerfRecorder, compilation.isCore, this.closureCompilerEnabled),
|
|
40125
40261
|
aliasTransformFactory(compilation.traitCompiler.exportStatements),
|
|
40126
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
40451
|
-
new InjectableDecoratorHandler(reflector,
|
|
40452
|
-
new NgModuleDecoratorHandler(reflector, evaluator, metaReader, metaRegistry, scopeRegistry, referencesRegistry, isCore, routeAnalyzer, refEmitter, this.adapter.factoryTracker,
|
|
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
|
|
42304
|
-
if (
|
|
42305
|
-
for (const tsCompletion of
|
|
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
|
}
|