From 0accd1e68dc1c5b386a4531bc9c99f18b930ddfd Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Tue, 29 Sep 2020 20:42:20 +0100 Subject: [PATCH] refactor(compiler-cli): implement `DeclarationNode` node type (#38959) Previously the `ConcreteDeclaration` and `InlineDeclaration` had different properties for the underlying node type. And the `InlineDeclaration` did not store a value that represented its declaration. It turns out that a natural declaration node for an inline type is the expression. For example in UMD/CommonJS this would be the `exports.` property access node. So this expression is now used for the `node` of `InlineDeclaration` types and the `expression` property is dropped. To support this the codebase has been refactored to use a new `DeclarationNode` type which is a union of `ts.Declaration|ts.Expression` instead of `ts.Declaration` throughout. PR Close #38959 --- .../module_with_providers_analyzer.ts | 6 +- .../src/analysis/ngcc_references_registry.ts | 10 +-- .../analysis/private_declarations_analyzer.ts | 6 +- .../ngcc/src/host/commonjs_host.ts | 6 +- .../ngcc/src/host/delegating_host.ts | 6 +- .../ngcc/src/host/esm2015_host.ts | 64 ++++++++--------- .../compiler-cli/ngcc/src/host/esm5_host.ts | 6 +- .../compiler-cli/ngcc/src/host/umd_host.ts | 50 +++++++------- .../missing_injectable_migration.ts | 2 +- .../undecorated_parent_migration.ts | 2 +- .../compiler-cli/ngcc/src/migrations/utils.ts | 2 +- packages/compiler-cli/ngcc/src/utils.ts | 6 +- .../test/analysis/decoration_analyzer_spec.ts | 12 ++-- .../module_with_providers_analyzer_spec.ts | 4 +- .../test/analysis/references_registry_spec.ts | 4 +- .../ngcc/test/host/commonjs_host_spec.ts | 19 +++--- .../ngcc/test/host/esm2015_host_spec.ts | 6 +- .../ngcc/test/host/esm5_host_spec.ts | 11 +-- .../ngcc/test/host/umd_host_spec.ts | 21 +++--- .../src/ngtsc/annotations/src/component.ts | 4 +- .../src/ngtsc/annotations/src/metadata.ts | 7 +- .../src/ngtsc/annotations/src/ng_module.ts | 8 +-- .../annotations/src/references_registry.ts | 6 +- .../src/ngtsc/core/src/compiler.ts | 8 +-- .../src/ngtsc/entry_point/BUILD.bazel | 1 + .../entry_point/src/private_export_checker.ts | 13 ++-- .../ngtsc/entry_point/src/reference_graph.ts | 4 +- .../src/ngtsc/imports/src/emitter.ts | 18 ++--- .../compiler-cli/src/ngtsc/indexer/src/api.ts | 5 +- .../src/ngtsc/indexer/src/transform.ts | 8 +-- .../src/ngtsc/indexer/test/util.ts | 2 +- .../partial_evaluator/src/interpreter.ts | 26 ++----- .../partial_evaluator/test/evaluator_spec.ts | 9 +-- .../compiler-cli/src/ngtsc/perf/BUILD.bazel | 1 + .../compiler-cli/src/ngtsc/perf/src/api.ts | 7 +- .../compiler-cli/src/ngtsc/perf/src/noop.ts | 13 ++-- .../src/ngtsc/perf/src/tracking.ts | 9 ++- packages/compiler-cli/src/ngtsc/program.ts | 3 +- .../src/ngtsc/reflection/src/host.ts | 68 ++++++++++++------- .../src/ngtsc/reflection/src/typescript.ts | 10 +-- .../src/ngtsc/reflection/test/ts_host_spec.ts | 4 +- .../compiler-cli/src/ngtsc/scope/src/local.ts | 22 +++--- .../src/ngtsc/testing/BUILD.bazel | 1 + .../src/ngtsc/testing/src/utils.ts | 7 +- .../src/ngtsc/transform/src/compilation.ts | 4 +- .../ngtsc/typecheck/diagnostics/BUILD.bazel | 1 + .../src/ngtsc/typecheck/diagnostics/src/id.ts | 3 +- .../typecheck/src/type_parameter_emitter.ts | 4 +- .../compiler-cli/src/ngtsc/util/BUILD.bazel | 1 + .../src/ngtsc/util/src/typescript.ts | 3 +- packages/compiler-cli/test/ngtsc/BUILD.bazel | 1 + packages/compiler-cli/test/ngtsc/env.ts | 3 +- packages/language-service/ivy/BUILD.bazel | 1 + packages/language-service/ivy/utils.ts | 3 +- 54 files changed, 276 insertions(+), 255 deletions(-) diff --git a/packages/compiler-cli/ngcc/src/analysis/module_with_providers_analyzer.ts b/packages/compiler-cli/ngcc/src/analysis/module_with_providers_analyzer.ts index 955bafe116..598823faea 100644 --- a/packages/compiler-cli/ngcc/src/analysis/module_with_providers_analyzer.ts +++ b/packages/compiler-cli/ngcc/src/analysis/module_with_providers_analyzer.ts @@ -10,7 +10,7 @@ import * as ts from 'typescript'; import {ReferencesRegistry} from '../../../src/ngtsc/annotations'; import {Reference} from '../../../src/ngtsc/imports'; import {PartialEvaluator} from '../../../src/ngtsc/partial_evaluator'; -import {ClassDeclaration, isNamedClassDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; +import {ClassDeclaration, DeclarationNode, isNamedClassDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; import {NgccReflectionHost} from '../host/ngcc_host'; import {hasNameIdentifier, isDefined} from '../utils'; @@ -30,7 +30,7 @@ export interface ModuleWithProvidersInfo { /** * Declaration of the containing class (if this is a method) */ - container: ts.Declaration|null; + container: DeclarationNode|null; /** * The declaration of the class that the `ngModule` property on the `ModuleWithProviders` object * refers to. @@ -125,7 +125,7 @@ export class ModuleWithProvidersAnalyzer { */ private parseForModuleWithProviders( name: string, node: ts.Node|null, implementation: ts.Node|null = node, - container: ts.Declaration|null = null): ModuleWithProvidersInfo|null { + container: DeclarationNode|null = null): ModuleWithProvidersInfo|null { if (implementation === null || (!ts.isFunctionDeclaration(implementation) && !ts.isMethodDeclaration(implementation) && !ts.isFunctionExpression(implementation))) { diff --git a/packages/compiler-cli/ngcc/src/analysis/ngcc_references_registry.ts b/packages/compiler-cli/ngcc/src/analysis/ngcc_references_registry.ts index 6d8beb4fb5..198e5659b8 100644 --- a/packages/compiler-cli/ngcc/src/analysis/ngcc_references_registry.ts +++ b/packages/compiler-cli/ngcc/src/analysis/ngcc_references_registry.ts @@ -9,7 +9,7 @@ import * as ts from 'typescript'; import {ReferencesRegistry} from '../../../src/ngtsc/annotations'; import {Reference} from '../../../src/ngtsc/imports'; -import {ConcreteDeclaration, ReflectionHost} from '../../../src/ngtsc/reflection'; +import {Declaration, DeclarationNode, ReflectionHost} from '../../../src/ngtsc/reflection'; import {hasNameIdentifier} from '../utils'; /** @@ -20,7 +20,7 @@ import {hasNameIdentifier} from '../utils'; * from libraries that are compiled by ngcc. */ export class NgccReferencesRegistry implements ReferencesRegistry { - private map = new Map(); + private map = new Map(); constructor(private host: ReflectionHost) {} @@ -29,12 +29,12 @@ export class NgccReferencesRegistry implements ReferencesRegistry { * Only `ResolveReference` references are stored. Other types are ignored. * @param references A collection of references to register. */ - add(source: ts.Declaration, ...references: Reference[]): void { + add(source: DeclarationNode, ...references: Reference[]): void { references.forEach(ref => { // Only store relative references. We are not interested in literals. if (ref.bestGuessOwningModule === null && hasNameIdentifier(ref.node)) { const declaration = this.host.getDeclarationOfIdentifier(ref.node.name); - if (declaration && declaration.node !== null && hasNameIdentifier(declaration.node)) { + if (declaration && hasNameIdentifier(declaration.node)) { this.map.set(declaration.node.name, declaration); } } @@ -45,7 +45,7 @@ export class NgccReferencesRegistry implements ReferencesRegistry { * Create and return a mapping for the registered resolved references. * @returns A map of reference identifiers to reference declarations. */ - getDeclarationMap(): Map { + getDeclarationMap(): Map { return this.map; } } diff --git a/packages/compiler-cli/ngcc/src/analysis/private_declarations_analyzer.ts b/packages/compiler-cli/ngcc/src/analysis/private_declarations_analyzer.ts index c03e7f9402..4dcbf9461c 100644 --- a/packages/compiler-cli/ngcc/src/analysis/private_declarations_analyzer.ts +++ b/packages/compiler-cli/ngcc/src/analysis/private_declarations_analyzer.ts @@ -8,7 +8,7 @@ import * as ts from 'typescript'; import {absoluteFromSourceFile, AbsoluteFsPath} from '../../../src/ngtsc/file_system'; -import {ConcreteDeclaration} from '../../../src/ngtsc/reflection'; +import {Declaration} from '../../../src/ngtsc/reflection'; import {NgccReflectionHost} from '../host/ngcc_host'; import {hasNameIdentifier, isDefined} from '../utils'; @@ -40,8 +40,8 @@ export class PrivateDeclarationsAnalyzer { private getPrivateDeclarations( rootFiles: ts.SourceFile[], - declarations: Map): PrivateDeclarationsAnalyses { - const privateDeclarations: Map = new Map(declarations); + declarations: Map): PrivateDeclarationsAnalyses { + const privateDeclarations: Map = new Map(declarations); rootFiles.forEach(f => { const exports = this.host.getExportsOfModule(f); diff --git a/packages/compiler-cli/ngcc/src/host/commonjs_host.ts b/packages/compiler-cli/ngcc/src/host/commonjs_host.ts index a2f8012b0a..bec9985b30 100644 --- a/packages/compiler-cli/ngcc/src/host/commonjs_host.ts +++ b/packages/compiler-cli/ngcc/src/host/commonjs_host.ts @@ -10,7 +10,7 @@ import * as ts from 'typescript'; import {absoluteFrom} from '../../../src/ngtsc/file_system'; import {Logger} from '../../../src/ngtsc/logging'; -import {Declaration, Import} from '../../../src/ngtsc/reflection'; +import {Declaration, DeclarationKind, Import} from '../../../src/ngtsc/reflection'; import {BundleProgram} from '../packages/bundle_program'; import {FactoryMap, isDefined} from '../utils'; @@ -181,7 +181,7 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost { } else { return { name, - declaration: {node: null, known: null, expression, viaModule: null}, + declaration: {node: expression, known: null, kind: DeclarationKind.Inline, viaModule: null}, }; } } @@ -204,7 +204,7 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost { return null; } const viaModule = isExternalImport(importPath) ? importPath : null; - return {node: module, known: null, viaModule, identity: null}; + return {node: module, known: null, viaModule, identity: null, kind: DeclarationKind.Concrete}; } private resolveModuleName(moduleName: string, containingFile: ts.SourceFile): ts.SourceFile diff --git a/packages/compiler-cli/ngcc/src/host/delegating_host.ts b/packages/compiler-cli/ngcc/src/host/delegating_host.ts index 907433fabd..e72a40a94d 100644 --- a/packages/compiler-cli/ngcc/src/host/delegating_host.ts +++ b/packages/compiler-cli/ngcc/src/host/delegating_host.ts @@ -8,7 +8,7 @@ import * as ts from 'typescript'; -import {ClassDeclaration, ClassMember, CtorParameter, Declaration, Decorator, FunctionDefinition, Import, ReflectionHost} from '../../../src/ngtsc/reflection'; +import {ClassDeclaration, ClassMember, CtorParameter, Declaration, DeclarationNode, Decorator, FunctionDefinition, Import, ReflectionHost} from '../../../src/ngtsc/reflection'; import {isFromDtsFile} from '../../../src/ngtsc/util/src/typescript'; import {NgccClassSymbol, NgccReflectionHost, SwitchableVariableDeclaration} from './ngcc_host'; @@ -38,7 +38,7 @@ export class DelegatingReflectionHost implements NgccReflectionHost { return this.ngccHost.getDeclarationOfIdentifier(id); } - getDecoratorsOfDeclaration(declaration: ts.Declaration): Decorator[]|null { + getDecoratorsOfDeclaration(declaration: DeclarationNode): Decorator[]|null { if (isFromDtsFile(declaration)) { return this.tsHost.getDecoratorsOfDeclaration(declaration); } @@ -52,7 +52,7 @@ export class DelegatingReflectionHost implements NgccReflectionHost { return this.ngccHost.getDefinitionOfFunction(fn); } - getDtsDeclaration(declaration: ts.Declaration): ts.Declaration|null { + getDtsDeclaration(declaration: DeclarationNode): ts.Declaration|null { if (isFromDtsFile(declaration)) { return this.tsHost.getDtsDeclaration(declaration); } diff --git a/packages/compiler-cli/ngcc/src/host/esm2015_host.ts b/packages/compiler-cli/ngcc/src/host/esm2015_host.ts index f360c082c5..ddf9954803 100644 --- a/packages/compiler-cli/ngcc/src/host/esm2015_host.ts +++ b/packages/compiler-cli/ngcc/src/host/esm2015_host.ts @@ -10,7 +10,7 @@ import * as ts from 'typescript'; import {absoluteFromSourceFile} from '../../../src/ngtsc/file_system'; import {Logger} from '../../../src/ngtsc/logging'; -import {ClassDeclaration, ClassMember, ClassMemberKind, CtorParameter, Declaration, Decorator, EnumMember, Import, isDecoratorIdentifier, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration, KnownDeclaration, reflectObjectLiteral, SpecialDeclarationKind, TypeScriptReflectionHost, TypeValueReference, TypeValueReferenceKind, ValueUnavailableKind} from '../../../src/ngtsc/reflection'; +import {ClassDeclaration, ClassMember, ClassMemberKind, CtorParameter, Declaration, DeclarationNode, Decorator, EnumMember, Import, isConcreteDeclaration, isDecoratorIdentifier, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration, KnownDeclaration, reflectObjectLiteral, SpecialDeclarationKind, TypeScriptReflectionHost, TypeValueReference, TypeValueReferenceKind, ValueUnavailableKind} from '../../../src/ngtsc/reflection'; import {isWithinPackage} from '../analysis/util'; import {BundleProgram} from '../packages/bundle_program'; import {findAll, getNameText, hasNameIdentifier, isDefined, stripDollarSuffix} from '../utils'; @@ -58,7 +58,7 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N * tree. Note that by definition the key and value declarations will not be in the same TS * program. */ - protected publicDtsDeclarationMap: Map|null = null; + protected publicDtsDeclarationMap: Map|null = null; /** * A mapping from source declarations to typings declarations, which are not publicly exported. * @@ -66,7 +66,7 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N * the same name in both the source and the dts file. Note that by definition the key and value * declarations will not be in the same TS program. */ - protected privateDtsDeclarationMap: Map|null = null; + protected privateDtsDeclarationMap: Map|null = null; /** * The set of source files that have already been preprocessed. @@ -88,7 +88,7 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N * * This map is populated during the preprocessing of each source file. */ - protected aliasedClassDeclarations = new Map(); + protected aliasedClassDeclarations = new Map(); /** * Caches the information of the decorators on a class, as the work involved with extracting @@ -140,16 +140,17 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N * Examine a declaration (for example, of a class or function) and return metadata about any * decorators present on the declaration. * - * @param declaration a TypeScript `ts.Declaration` node representing the class or function over - * which to reflect. For example, if the intent is to reflect the decorators of a class and the - * source is in ES6 format, this will be a `ts.ClassDeclaration` node. If the source is in ES5 - * format, this might be a `ts.VariableDeclaration` as classes in ES5 are represented as the - * result of an IIFE execution. + * @param declaration a TypeScript node representing the class or function over which to reflect. + * For example, if the intent is to reflect the decorators of a class and the source is in ES6 + * format, this will be a `ts.ClassDeclaration` node. If the source is in ES5 format, this + * might be a `ts.VariableDeclaration` as classes in ES5 are represented as the result of an + * IIFE execution. * * @returns an array of `Decorator` metadata if decorators are present on the declaration, or - * `null` if either no decorators were present or if the declaration is not of a decoratable type. + * `null` if either no decorators were present or if the declaration is not of a decoratable + * type. */ - getDecoratorsOfDeclaration(declaration: ts.Declaration): Decorator[]|null { + getDecoratorsOfDeclaration(declaration: DeclarationNode): Decorator[]|null { const symbol = this.getClassSymbol(declaration); if (!symbol) { return null; @@ -280,13 +281,14 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N getDeclarationOfIdentifier(id: ts.Identifier): Declaration|null { const superDeclaration = super.getDeclarationOfIdentifier(id); - // If no declaration was found or it's an inline declaration, return as is. - if (superDeclaration === null || superDeclaration.node === null) { + // If no declaration was found, return. + if (superDeclaration === null) { return superDeclaration; } // If the declaration already has traits assigned to it, return as is. - if (superDeclaration.known !== null || superDeclaration.identity !== null) { + if (superDeclaration.known !== null || + isConcreteDeclaration(superDeclaration) && superDeclaration.identity !== null) { return superDeclaration; } @@ -302,7 +304,8 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N const declaration = outerNode !== null && isNamedVariableDeclaration(outerNode) ? this.getDeclarationOfIdentifier(outerNode.name) : superDeclaration; - if (declaration === null || declaration.node === null || declaration.known !== null) { + if (declaration === null || declaration.known !== null || + isConcreteDeclaration(declaration) && declaration.identity !== null) { return declaration; } @@ -314,7 +317,7 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N } // Variable declarations may represent an enum declaration, so attempt to resolve its members. - if (ts.isVariableDeclaration(declaration.node)) { + if (isConcreteDeclaration(declaration) && ts.isVariableDeclaration(declaration.node)) { const enumMembers = this.resolveEnumMembers(declaration.node); if (enumMembers !== null) { declaration.identity = {kind: SpecialDeclarationKind.DownleveledEnum, enumMembers}; @@ -450,7 +453,7 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N * Note that the `ts.ClassDeclaration` returned from this function may not be from the same * `ts.Program` as the input declaration. */ - getDtsDeclaration(declaration: ts.Declaration): ts.Declaration|null { + getDtsDeclaration(declaration: DeclarationNode): ts.Declaration|null { if (this.dts === null) { return null; } @@ -777,7 +780,7 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N * @returns The original identifier that the given class declaration resolves to, or `undefined` * if the declaration does not represent an aliased class. */ - protected resolveAliasedClassIdentifier(declaration: ts.Declaration): ts.Identifier|null { + protected resolveAliasedClassIdentifier(declaration: DeclarationNode): ts.Identifier|null { this.ensurePreprocessed(declaration.getSourceFile()); return this.aliasedClassDeclarations.has(declaration) ? this.aliasedClassDeclarations.get(declaration)! : @@ -829,7 +832,7 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N const aliasedIdentifier = initializer.left; const aliasedDeclaration = this.getDeclarationOfIdentifier(aliasedIdentifier); - if (aliasedDeclaration === null || aliasedDeclaration.node === null) { + if (aliasedDeclaration === null) { throw new Error( `Unable to locate declaration of ${aliasedIdentifier.text} in "${statement.getText()}"`); } @@ -1628,7 +1631,7 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N const imp = this.getImportOfExpression(typeExpression); const decl = this.getDeclarationOfExpression(typeExpression); - if (imp === null || decl === null || decl.node === null) { + if (imp === null || decl === null) { return { kind: TypeValueReferenceKind.LOCAL, expression: typeExpression, @@ -1788,8 +1791,8 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N * @returns a map of source declarations to typings declarations. */ protected computePublicDtsDeclarationMap(src: BundleProgram, dts: BundleProgram): - Map { - const declarationMap = new Map(); + Map { + const declarationMap = new Map(); const dtsDeclarationMap = new Map(); const rootDts = getRootFileOrFail(dts); this.collectDtsExportedDeclarations(dtsDeclarationMap, rootDts, dts.program.getTypeChecker()); @@ -1812,8 +1815,8 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N * @returns a map of source declarations to typings declarations. */ protected computePrivateDtsDeclarationMap(src: BundleProgram, dts: BundleProgram): - Map { - const declarationMap = new Map(); + Map { + const declarationMap = new Map(); const dtsDeclarationMap = new Map(); const typeChecker = dts.program.getTypeChecker(); @@ -1855,13 +1858,13 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N protected collectSrcExportedDeclarations( - declarationMap: Map, + declarationMap: Map, dtsDeclarationMap: Map, srcFile: ts.SourceFile): void { const fileExports = this.getExportsOfModule(srcFile); if (fileExports !== null) { - for (const [exportName, {node: declaration}] of fileExports) { - if (declaration !== null && dtsDeclarationMap.has(exportName)) { - declarationMap.set(declaration, dtsDeclarationMap.get(exportName)!); + for (const [exportName, {node: declarationNode}] of fileExports) { + if (dtsDeclarationMap.has(exportName)) { + declarationMap.set(declarationNode, dtsDeclarationMap.get(exportName)!); } } } @@ -1877,7 +1880,7 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N } const namespaceDecl = this.getDeclarationOfIdentifier(expression.expression); - if (!namespaceDecl || namespaceDecl.node === null || !ts.isSourceFile(namespaceDecl.node)) { + if (!namespaceDecl || !ts.isSourceFile(namespaceDecl.node)) { return null; } @@ -1896,9 +1899,6 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N /** Checks if the specified declaration resolves to the known JavaScript global `Object`. */ protected isJavaScriptObjectDeclaration(decl: Declaration): boolean { - if (decl.node === null) { - return false; - } const node = decl.node; // The default TypeScript library types the global `Object` variable through // a variable declaration with a type reference resolving to `ObjectConstructor`. diff --git a/packages/compiler-cli/ngcc/src/host/esm5_host.ts b/packages/compiler-cli/ngcc/src/host/esm5_host.ts index 89decab694..5af9c9f123 100644 --- a/packages/compiler-cli/ngcc/src/host/esm5_host.ts +++ b/packages/compiler-cli/ngcc/src/host/esm5_host.ts @@ -8,7 +8,7 @@ import * as ts from 'typescript'; -import {ClassDeclaration, ClassMember, ClassMemberKind, Declaration, Decorator, FunctionDefinition, isNamedFunctionDeclaration, KnownDeclaration, Parameter, reflectObjectLiteral} from '../../../src/ngtsc/reflection'; +import {ClassDeclaration, ClassMember, ClassMemberKind, Declaration, DeclarationKind, Decorator, FunctionDefinition, isNamedFunctionDeclaration, KnownDeclaration, Parameter, reflectObjectLiteral} from '../../../src/ngtsc/reflection'; import {getTsHelperFnFromDeclaration, getTsHelperFnFromIdentifier, hasNameIdentifier} from '../utils'; import {Esm2015ReflectionHost, getOuterNodeFromInnerDeclaration, getPropertyValueFromSymbol, isAssignmentStatement, ParamInfo} from './esm2015_host'; @@ -82,9 +82,9 @@ export class Esm5ReflectionHost extends Esm2015ReflectionHost { // `importHelpers: false` (the default). This is, for example, the case with // `@nativescript/angular@9.0.0-next-2019-11-12-155500-01`. return { - expression: id, + kind: DeclarationKind.Inline, + node: id, known: nonEmittedNorImportedTsHelperDeclaration, - node: null, viaModule: null, }; } diff --git a/packages/compiler-cli/ngcc/src/host/umd_host.ts b/packages/compiler-cli/ngcc/src/host/umd_host.ts index e3a0965c9e..ec934ffaff 100644 --- a/packages/compiler-cli/ngcc/src/host/umd_host.ts +++ b/packages/compiler-cli/ngcc/src/host/umd_host.ts @@ -10,7 +10,7 @@ import * as ts from 'typescript'; import {absoluteFrom} from '../../../src/ngtsc/file_system'; import {Logger} from '../../../src/ngtsc/logging'; -import {Declaration, Import} from '../../../src/ngtsc/reflection'; +import {Declaration, DeclarationKind, Import} from '../../../src/ngtsc/reflection'; import {BundleProgram} from '../packages/bundle_program'; import {FactoryMap, getTsHelperFnFromIdentifier, stripExtension} from '../utils'; @@ -172,17 +172,8 @@ export class UmdReflectionHost extends Esm5ReflectionHost { const viaModule = stripExtension(importedFile.fileName); const reexports: ExportDeclaration[] = []; - importedExports.forEach((decl, name) => { - if (decl.node !== null) { - reexports.push({ - name, - declaration: {node: decl.node, known: null, viaModule, identity: decl.identity} - }); - } else { - reexports.push( - {name, declaration: {node: null, known: null, expression: decl.expression, viaModule}}); - } - }); + importedExports.forEach( + (decl, name) => reexports.push({name, declaration: {...decl, viaModule}})); return reexports; } @@ -204,7 +195,7 @@ export class UmdReflectionHost extends Esm5ReflectionHost { } return { name, - declaration: {node: null, known: null, expression, viaModule: null}, + declaration: {kind: DeclarationKind.Inline, node: expression, known: null, viaModule: null}, }; } @@ -255,22 +246,31 @@ export class UmdReflectionHost extends Esm5ReflectionHost { return null; } - // Sadly, in the case of `exports.foo = bar`, we can't use `this.findUmdImportParameter(id)` to - // check whether this `exports` is from the IIFE body arguments, because - // `this.checker.getSymbolAtLocation(id)` will return the symbol for the `foo` identifier rather - // than the `exports` identifier. + // Sadly, in the case of `exports.foo = bar`, we can't use `this.findUmdImportParameter(id)` + // to check whether this `exports` is from the IIFE body arguments, because + // `this.checker.getSymbolAtLocation(id)` will return the symbol for the `foo` identifier + // rather than the `exports` identifier. // // Instead we search the symbols in the current local scope. const exportsSymbol = this.checker.getSymbolsInScope(id, ts.SymbolFlags.Variable) .find(symbol => symbol.name === 'exports'); - if (exportsSymbol !== undefined && - !ts.isFunctionExpression(exportsSymbol.valueDeclaration.parent)) { - // There is an `exports` symbol in the local scope that is not a function parameter. - // So this `exports` identifier must be a local variable and does not represent the module. - return {node: exportsSymbol.valueDeclaration, viaModule: null, known: null, identity: null}; - } - return {node: id.getSourceFile(), viaModule: null, known: null, identity: null}; + const node = exportsSymbol !== undefined && + !ts.isFunctionExpression(exportsSymbol.valueDeclaration.parent) ? + // There is a locally defined `exports` variable that is not a function parameter. + // So this `exports` identifier must be a local variable and does not represent the module. + exportsSymbol.valueDeclaration : + // There is no local symbol or it is a parameter of an IIFE. + // So this `exports` represents the current "module". + id.getSourceFile(); + + return { + kind: DeclarationKind.Concrete, + node, + viaModule: null, + known: null, + identity: null, + }; } private getUmdModuleDeclaration(id: ts.Identifier): Declaration|null { @@ -285,7 +285,7 @@ export class UmdReflectionHost extends Esm5ReflectionHost { } const viaModule = isExternalImport(importPath) ? importPath : null; - return {node: module, viaModule, known: null, identity: null}; + return {kind: DeclarationKind.Concrete, node: module, viaModule, known: null, identity: null}; } private getImportPathFromParameter(id: ts.Identifier): string|null { diff --git a/packages/compiler-cli/ngcc/src/migrations/missing_injectable_migration.ts b/packages/compiler-cli/ngcc/src/migrations/missing_injectable_migration.ts index f1fd7ec3d7..2ee3a33252 100644 --- a/packages/compiler-cli/ngcc/src/migrations/missing_injectable_migration.ts +++ b/packages/compiler-cli/ngcc/src/migrations/missing_injectable_migration.ts @@ -151,7 +151,7 @@ function migrateProviderClass(provider: ResolvedValue, host: MigrationHost): voi return; } - const clazz = provider.node as ts.Declaration; + const clazz = provider.node; if (isClassDeclaration(clazz) && host.isInScope(clazz) && needsInjectableDecorator(clazz, host)) { host.injectSyntheticDecorator(clazz, createInjectableDecorator(clazz)); } diff --git a/packages/compiler-cli/ngcc/src/migrations/undecorated_parent_migration.ts b/packages/compiler-cli/ngcc/src/migrations/undecorated_parent_migration.ts index 6bd6b06c5f..d1e9edfb96 100644 --- a/packages/compiler-cli/ngcc/src/migrations/undecorated_parent_migration.ts +++ b/packages/compiler-cli/ngcc/src/migrations/undecorated_parent_migration.ts @@ -101,7 +101,7 @@ function determineBaseClass( } const baseClass = host.evaluator.evaluate(baseClassExpr); - if (!(baseClass instanceof Reference) || !isClassDeclaration(baseClass.node as ts.Declaration)) { + if (!(baseClass instanceof Reference) || !isClassDeclaration(baseClass.node)) { return null; } diff --git a/packages/compiler-cli/ngcc/src/migrations/utils.ts b/packages/compiler-cli/ngcc/src/migrations/utils.ts index ccf16f9f2e..16a6ccddf7 100644 --- a/packages/compiler-cli/ngcc/src/migrations/utils.ts +++ b/packages/compiler-cli/ngcc/src/migrations/utils.ts @@ -10,7 +10,7 @@ import {Reference} from '../../../src/ngtsc/imports'; import {ClassDeclaration, Decorator, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; import {MigrationHost} from './migration'; -export function isClassDeclaration(clazz: ts.Declaration): clazz is ClassDeclaration { +export function isClassDeclaration(clazz: ts.Node): clazz is ClassDeclaration { return isNamedClassDeclaration(clazz) || isNamedFunctionDeclaration(clazz) || isNamedVariableDeclaration(clazz); } diff --git a/packages/compiler-cli/ngcc/src/utils.ts b/packages/compiler-cli/ngcc/src/utils.ts index 7a67e5049b..de8b4c3193 100644 --- a/packages/compiler-cli/ngcc/src/utils.ts +++ b/packages/compiler-cli/ngcc/src/utils.ts @@ -8,7 +8,7 @@ import * as ts from 'typescript'; import {absoluteFrom, AbsoluteFsPath, FileSystem, isRooted} from '../../src/ngtsc/file_system'; -import {KnownDeclaration} from '../../src/ngtsc/reflection'; +import {DeclarationNode, KnownDeclaration} from '../../src/ngtsc/reflection'; /** * A list (`Array`) of partially ordered `T` items. @@ -71,7 +71,7 @@ export function findAll(node: ts.Node, test: (node: ts.Node) => node is ts.No * @param declaration The declaration to test. * @returns true if the declaration has an identifier for a name. */ -export function hasNameIdentifier(declaration: ts.Node): declaration is ts.Declaration& +export function hasNameIdentifier(declaration: ts.Node): declaration is DeclarationNode& {name: ts.Identifier} { const namedDeclaration: ts.Node&{name?: ts.Node} = declaration; return namedDeclaration.name !== undefined && ts.isIdentifier(namedDeclaration.name); @@ -136,7 +136,7 @@ export function resolveFileWithPostfixes( * Determine whether a function declaration corresponds with a TypeScript helper function, returning * its kind if so or null if the declaration does not seem to correspond with such a helper. */ -export function getTsHelperFnFromDeclaration(decl: ts.Declaration): KnownDeclaration|null { +export function getTsHelperFnFromDeclaration(decl: DeclarationNode): KnownDeclaration|null { if (!ts.isFunctionDeclaration(decl) && !ts.isVariableDeclaration(decl)) { return null; } diff --git a/packages/compiler-cli/ngcc/test/analysis/decoration_analyzer_spec.ts b/packages/compiler-cli/ngcc/test/analysis/decoration_analyzer_spec.ts index 6acdb86a57..6324909414 100644 --- a/packages/compiler-cli/ngcc/test/analysis/decoration_analyzer_spec.ts +++ b/packages/compiler-cli/ngcc/test/analysis/decoration_analyzer_spec.ts @@ -11,7 +11,7 @@ import {FatalDiagnosticError, makeDiagnostic} from '../../../src/ngtsc/diagnosti import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; import {MockLogger} from '../../../src/ngtsc/logging/testing'; -import {ClassDeclaration, Decorator} from '../../../src/ngtsc/reflection'; +import {ClassDeclaration, DeclarationNode, Decorator} from '../../../src/ngtsc/reflection'; import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from '../../../src/ngtsc/transform'; import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer'; @@ -52,7 +52,7 @@ runInEachFileSystem(() => { ]); // Only detect the Component and Directive decorators handler.detect.and.callFake( - (node: ts.Declaration, decorators: Decorator[]|null): DetectResult| + (node: DeclarationNode, decorators: Decorator[]|null): DetectResult| undefined => { const className = (node as any).name.text; if (decorators === null) { @@ -76,7 +76,7 @@ runInEachFileSystem(() => { } }); // The "test" analysis is an object with the name of the decorator being analyzed - handler.analyze.and.callFake((decl: ts.Declaration, dec: Decorator) => { + handler.analyze.and.callFake((decl: DeclarationNode, dec: Decorator) => { logs.push(`analyze: ${(decl as any).name.text}@${dec.name}`); return { analysis: {decoratorName: dec.name}, @@ -85,7 +85,7 @@ runInEachFileSystem(() => { }; }); // The "test" resolution is just setting `resolved: true` on the analysis - handler.resolve.and.callFake((decl: ts.Declaration, analysis: any) => { + handler.resolve.and.callFake((decl: DeclarationNode, analysis: any) => { logs.push(`resolve: ${(decl as any).name.text}@${analysis.decoratorName}`); analysis.resolved = true; return { @@ -95,10 +95,10 @@ runInEachFileSystem(() => { }); // The "test" compilation result is just the name of the decorator being compiled // (suffixed with `(compiled)`) - (handler.compileFull as any).and.callFake((decl: ts.Declaration, analysis: any) => { + handler.compileFull.and.callFake((decl: DeclarationNode, analysis: any) => { logs.push(`compile: ${(decl as any).name.text}@${analysis.decoratorName} (resolved: ${ analysis.resolved})`); - return `@${analysis.decoratorName} (compiled)`; + return `@${analysis.decoratorName} (compiled)` as any; }); return handler; }; diff --git a/packages/compiler-cli/ngcc/test/analysis/module_with_providers_analyzer_spec.ts b/packages/compiler-cli/ngcc/test/analysis/module_with_providers_analyzer_spec.ts index 5280fcb551..8dbbf5007b 100644 --- a/packages/compiler-cli/ngcc/test/analysis/module_with_providers_analyzer_spec.ts +++ b/packages/compiler-cli/ngcc/test/analysis/module_with_providers_analyzer_spec.ts @@ -10,7 +10,7 @@ import * as ts from 'typescript'; import {absoluteFrom, AbsoluteFsPath, getSourceFileOrError} from '../../../src/ngtsc/file_system'; import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; import {MockLogger} from '../../../src/ngtsc/logging/testing'; -import {isNamedClassDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; +import {DeclarationNode, isNamedClassDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; import {getDeclaration} from '../../../src/ngtsc/testing'; import {loadTestFiles} from '../../../test/helpers'; import {ModuleWithProvidersAnalyses, ModuleWithProvidersAnalyzer} from '../../src/analysis/module_with_providers_analyzer'; @@ -660,7 +660,7 @@ runInEachFileSystem(() => { []; } - function getName(node: ts.Declaration|null): string { + function getName(node: DeclarationNode|null): string { return node && (isNamedVariableDeclaration(node) || isNamedClassDeclaration(node)) ? `${node.name.text}.` : ''; diff --git a/packages/compiler-cli/ngcc/test/analysis/references_registry_spec.ts b/packages/compiler-cli/ngcc/test/analysis/references_registry_spec.ts index 9bb668ae08..dbd10a0177 100644 --- a/packages/compiler-cli/ngcc/test/analysis/references_registry_spec.ts +++ b/packages/compiler-cli/ngcc/test/analysis/references_registry_spec.ts @@ -11,7 +11,7 @@ import {absoluteFrom} from '../../../src/ngtsc/file_system'; import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; import {Reference} from '../../../src/ngtsc/imports'; import {PartialEvaluator} from '../../../src/ngtsc/partial_evaluator'; -import {TypeScriptReflectionHost} from '../../../src/ngtsc/reflection'; +import {DeclarationNode, TypeScriptReflectionHost} from '../../../src/ngtsc/reflection'; import {getDeclaration} from '../../../src/ngtsc/testing'; import {loadTestFiles} from '../../../test/helpers'; import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry'; @@ -61,7 +61,7 @@ runInEachFileSystem(() => { }); }); - function isReference(ref: any): ref is Reference { + function isReference(ref: any): ref is Reference { return ref instanceof Reference; } }); diff --git a/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts b/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts index 0558cb7e93..01e9c3fc92 100644 --- a/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts @@ -10,7 +10,7 @@ import * as ts from 'typescript'; import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; import {MockLogger} from '../../../src/ngtsc/logging/testing'; -import {ClassMemberKind, ConcreteDeclaration, CtorParameter, DownleveledEnum, InlineDeclaration, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration, KnownDeclaration, TypeScriptReflectionHost, TypeValueReferenceKind} from '../../../src/ngtsc/reflection'; +import {ClassMemberKind, ConcreteDeclaration, CtorParameter, DeclarationKind, DownleveledEnum, InlineDeclaration, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration, KnownDeclaration, TypeScriptReflectionHost, TypeValueReferenceKind} from '../../../src/ngtsc/reflection'; import {getDeclaration} from '../../../src/ngtsc/testing'; import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; import {CommonJsReflectionHost} from '../../src/host/commonjs_host'; @@ -1840,6 +1840,7 @@ exports.MissingClass2 = MissingClass2; const helperDeclaration = host.getDeclarationOfIdentifier(helperIdentifier); expect(helperDeclaration).toEqual({ + kind: DeclarationKind.Concrete, known: knownAs, node: getHelperDeclaration(helperName), viaModule, @@ -2163,9 +2164,9 @@ exports.MissingClass2 = MissingClass2; const helperDeclaration = host.getDeclarationOfIdentifier(helperIdentifier); expect(helperDeclaration).toEqual({ + kind: DeclarationKind.Inline, known: knownAs, - expression: helperIdentifier, - node: null, + node: helperIdentifier, viaModule: null, }); }; @@ -2197,9 +2198,9 @@ exports.MissingClass2 = MissingClass2; const helperDeclaration = host.getDeclarationOfIdentifier(helperIdentifier); expect(helperDeclaration).toEqual({ + kind: DeclarationKind.Inline, known: knownAs, - expression: helperIdentifier, - node: null, + node: helperIdentifier, viaModule: null, }); }; @@ -2421,10 +2422,10 @@ exports.MissingClass2 = MissingClass2; const file = getSourceFileOrError(bundle.program, _('/inline_export.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBeNull(); - const decl = exportDeclarations!.get('directives') as InlineDeclaration; - expect(decl).not.toBeUndefined(); - expect(decl.node).toBeNull(); - expect(decl.expression).toBeDefined(); + const decl = exportDeclarations!.get('directives')!; + expect(decl).toBeDefined(); + expect(decl.node).toBeDefined(); + expect(decl.kind).toEqual(DeclarationKind.Inline); }); it('should recognize declarations of known TypeScript helpers', () => { diff --git a/packages/compiler-cli/ngcc/test/host/esm2015_host_spec.ts b/packages/compiler-cli/ngcc/test/host/esm2015_host_spec.ts index d0c209f871..a33dda88ae 100644 --- a/packages/compiler-cli/ngcc/test/host/esm2015_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/esm2015_host_spec.ts @@ -2076,7 +2076,8 @@ runInEachFileSystem(() => { } expect(classSymbol.name).toEqual('DecoratedWrappedClass'); expect(classSymbol.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol.implementation.valueDeclaration).toBe(innerNodes[0]); + expect(classSymbol.implementation.valueDeclaration) + .toBe(innerNodes[0] as ts.Declaration); if (classSymbol.adjacent === undefined || !isNamedVariableDeclaration(classSymbol.adjacent.valueDeclaration)) { @@ -2112,7 +2113,8 @@ runInEachFileSystem(() => { } expect(classSymbol.name).toEqual('DecoratedWrappedClass'); expect(classSymbol.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol.implementation.valueDeclaration).toBe(innerNodes[0]); + expect(classSymbol.implementation.valueDeclaration) + .toBe(innerNodes[0] as ts.Declaration); if (classSymbol.adjacent === undefined || !isNamedVariableDeclaration(classSymbol.adjacent.valueDeclaration)) { diff --git a/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts b/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts index 801fd6552c..46d7c5a18f 100644 --- a/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts @@ -11,7 +11,7 @@ import * as ts from 'typescript'; import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; import {MockLogger} from '../../../src/ngtsc/logging/testing'; -import {ClassMemberKind, ConcreteDeclaration, CtorParameter, Decorator, DownleveledEnum, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration, KnownDeclaration, TypeScriptReflectionHost, TypeValueReferenceKind} from '../../../src/ngtsc/reflection'; +import {ClassMemberKind, ConcreteDeclaration, CtorParameter, DeclarationKind, Decorator, DownleveledEnum, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration, KnownDeclaration, TypeScriptReflectionHost, TypeValueReferenceKind} from '../../../src/ngtsc/reflection'; import {getDeclaration} from '../../../src/ngtsc/testing'; import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; import {DelegatingReflectionHost} from '../../src/host/delegating_host'; @@ -1858,6 +1858,7 @@ runInEachFileSystem(() => { const helperDeclaration = host.getDeclarationOfIdentifier(helperIdentifier); expect(helperDeclaration).toEqual({ + kind: DeclarationKind.Concrete, known: knownAs, node: getHelperDeclaration(helperName), viaModule, @@ -2253,9 +2254,9 @@ runInEachFileSystem(() => { const helperDeclaration = host.getDeclarationOfIdentifier(helperIdentifier); expect(helperDeclaration).toEqual({ + kind: DeclarationKind.Inline, known: knownAs, - expression: helperIdentifier, - node: null, + node: helperIdentifier, viaModule: null, }); }; @@ -2284,9 +2285,9 @@ runInEachFileSystem(() => { const helperDeclaration = host.getDeclarationOfIdentifier(helperIdentifier); expect(helperDeclaration).toEqual({ + kind: DeclarationKind.Inline, known: knownAs, - expression: helperIdentifier, - node: null, + node: helperIdentifier, viaModule: null, }); }; diff --git a/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts b/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts index e66053060c..fe06ec14b5 100644 --- a/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts @@ -11,7 +11,7 @@ import * as ts from 'typescript'; import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; import {MockLogger} from '../../../src/ngtsc/logging/testing'; -import {ClassMemberKind, ConcreteDeclaration, CtorParameter, DownleveledEnum, Import, InlineDeclaration, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration, KnownDeclaration, TypeScriptReflectionHost, TypeValueReferenceKind} from '../../../src/ngtsc/reflection'; +import {ClassMemberKind, ConcreteDeclaration, CtorParameter, DeclarationKind, DownleveledEnum, Import, InlineDeclaration, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration, KnownDeclaration, TypeScriptReflectionHost, TypeValueReferenceKind} from '../../../src/ngtsc/reflection'; import {getDeclaration} from '../../../src/ngtsc/testing'; import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; import {isExportsStatement} from '../../src/host/commonjs_umd_utils'; @@ -2003,6 +2003,7 @@ runInEachFileSystem(() => { const helperDeclaration = host.getDeclarationOfIdentifier(helperIdentifier); expect(helperDeclaration).toEqual({ + kind: DeclarationKind.Concrete, known: knownAs, node: getHelperDeclaration(factoryFn, helperName), viaModule, @@ -2410,9 +2411,9 @@ runInEachFileSystem(() => { const helperDeclaration = host.getDeclarationOfIdentifier(helperIdentifier); expect(helperDeclaration).toEqual({ + kind: DeclarationKind.Inline, known: knownAs, - expression: helperIdentifier, - node: null, + node: helperIdentifier, viaModule: null, }); }; @@ -2449,9 +2450,9 @@ runInEachFileSystem(() => { const helperDeclaration = host.getDeclarationOfIdentifier(helperIdentifier); expect(helperDeclaration).toEqual({ + kind: DeclarationKind.Inline, known: knownAs, - expression: helperIdentifier, - node: null, + node: helperIdentifier, viaModule: null, }); }; @@ -2697,10 +2698,10 @@ runInEachFileSystem(() => { const file = getSourceFileOrError(bundle.program, INLINE_EXPORT_FILE.name); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - const decl = exportDeclarations!.get('directives') as InlineDeclaration; - expect(decl).not.toBeUndefined(); - expect(decl.node).toBeNull(); - expect(decl.expression).toBeDefined(); + const decl = exportDeclarations!.get('directives')!; + expect(decl).toBeDefined(); + expect(decl.node).toBeDefined(); + expect(decl.kind).toEqual(DeclarationKind.Inline); }); it('should recognize declarations of known TypeScript helpers', () => { @@ -2901,7 +2902,7 @@ runInEachFileSystem(() => { const classSymbol = host.getClassSymbol(outerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode as any); expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/component.ts b/packages/compiler-cli/src/ngtsc/annotations/src/component.ts index d968020011..74c5c73b83 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/src/component.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/src/component.ts @@ -17,7 +17,7 @@ import {DependencyTracker} from '../../incremental/api'; import {IndexingContext} from '../../indexer'; import {ClassPropertyMapping, DirectiveMeta, DirectiveTypeCheckMeta, extractDirectiveTypeCheckMeta, InjectableClassRegistry, MetadataReader, MetadataRegistry, TemplateMapping} from '../../metadata'; import {EnumValue, PartialEvaluator} from '../../partial_evaluator'; -import {ClassDeclaration, Decorator, ReflectionHost, reflectObjectLiteral} from '../../reflection'; +import {ClassDeclaration, DeclarationNode, Decorator, ReflectionHost, reflectObjectLiteral} from '../../reflection'; import {ComponentScopeReader, LocalModuleScopeRegistry} from '../../scope'; import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerFlags, HandlerPrecedence, ResolveResult} from '../../transform'; import {TemplateSourceMapping, TypeCheckContext} from '../../typecheck/api'; @@ -103,7 +103,7 @@ export class ComponentDecoratorHandler implements * any potential tags which might need to be loaded. This cache ensures that work is not * thrown away, and the parsed template is reused during the analyze phase. */ - private preanalyzeTemplateCache = new Map(); + private preanalyzeTemplateCache = new Map(); readonly precedence = HandlerPrecedence.PRIMARY; readonly name = ComponentDecoratorHandler.name; diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/metadata.ts b/packages/compiler-cli/src/ngtsc/annotations/src/metadata.ts index ce1a358c8a..e0ac434c4b 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/src/metadata.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/src/metadata.ts @@ -10,7 +10,7 @@ import {Expression, ExternalExpr, FunctionExpr, Identifiers, InvokeFunctionExpr, import * as ts from 'typescript'; import {DefaultImportRecorder} from '../../imports'; -import {CtorParameter, Decorator, ReflectionHost, TypeValueReferenceKind} from '../../reflection'; +import {CtorParameter, DeclarationNode, Decorator, ReflectionHost, TypeValueReferenceKind} from '../../reflection'; import {valueReferenceToExpression, wrapFunctionExpressionsInParens} from './util'; @@ -23,8 +23,9 @@ import {valueReferenceToExpression, wrapFunctionExpressionsInParens} from './uti * as a `Statement` for inclusion along with the class. */ export function generateSetClassMetadataCall( - clazz: ts.Declaration, reflection: ReflectionHost, defaultImportRecorder: DefaultImportRecorder, - isCore: boolean, annotateForClosureCompiler?: boolean): Statement|null { + clazz: DeclarationNode, reflection: ReflectionHost, + defaultImportRecorder: DefaultImportRecorder, isCore: boolean, + annotateForClosureCompiler?: boolean): Statement|null { if (!reflection.isClass(clazz)) { return null; } diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/ng_module.ts b/packages/compiler-cli/src/ngtsc/annotations/src/ng_module.ts index d57b6e6ea4..37afa3b8fc 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/src/ng_module.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/src/ng_module.ts @@ -13,7 +13,7 @@ import {ErrorCode, FatalDiagnosticError, makeDiagnostic, makeRelatedInformation} import {DefaultImportRecorder, Reference, ReferenceEmitter} from '../../imports'; import {InjectableClassRegistry, MetadataReader, MetadataRegistry} from '../../metadata'; import {PartialEvaluator, ResolvedValue} from '../../partial_evaluator'; -import {ClassDeclaration, Decorator, ReflectionHost, reflectObjectLiteral, typeNodeToValueExpr} from '../../reflection'; +import {ClassDeclaration, DeclarationNode, Decorator, isNamedClassDeclaration, ReflectionHost, reflectObjectLiteral, typeNodeToValueExpr} from '../../reflection'; import {NgModuleRouteAnalyzer} from '../../routing'; import {LocalModuleScopeRegistry, ScopeData} from '../../scope'; import {FactoryTracker} from '../../shims/api'; @@ -434,14 +434,14 @@ export class NgModuleDecoratorHandler implements } private _toR3Reference( - valueRef: Reference, valueContext: ts.SourceFile, + valueRef: Reference, valueContext: ts.SourceFile, typeContext: ts.SourceFile): R3Reference { if (valueRef.hasOwningModuleGuess) { return toR3Reference(valueRef, valueRef, valueContext, valueContext, this.refEmitter); } else { let typeRef = valueRef; let typeNode = this.reflector.getDtsDeclaration(typeRef.node); - if (typeNode !== null && ts.isClassDeclaration(typeNode)) { + if (typeNode !== null && isNamedClassDeclaration(typeNode)) { typeRef = new Reference(typeNode); } return toR3Reference(valueRef, typeRef, valueContext, typeContext, this.refEmitter); @@ -539,7 +539,7 @@ export class NgModuleDecoratorHandler implements return null; } - // Verify that a `ts.Declaration` reference is a `ClassDeclaration` reference. + // Verify that a "Declaration" reference is a `ClassDeclaration` reference. private isClassDeclarationReference(ref: Reference): ref is Reference { return this.reflector.isClass(ref.node); } diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/references_registry.ts b/packages/compiler-cli/src/ngtsc/annotations/src/references_registry.ts index 7198f1c42b..65cf099608 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/src/references_registry.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/src/references_registry.ts @@ -6,8 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import * as ts from 'typescript'; import {Reference} from '../../imports'; +import {DeclarationNode} from '../../reflection'; /** * Implement this interface if you want DecoratorHandlers to register @@ -18,7 +18,7 @@ export interface ReferencesRegistry { * Register one or more references in the registry. * @param references A collection of references to register. */ - add(source: ts.Declaration, ...references: Reference[]): void; + add(source: DeclarationNode, ...references: Reference[]): void; } /** @@ -27,5 +27,5 @@ export interface ReferencesRegistry { * The ngcc tool implements a working version for its purposes. */ export class NoopReferencesRegistry implements ReferencesRegistry { - add(source: ts.Declaration, ...references: Reference[]): void {} + add(source: DeclarationNode, ...references: Reference[]): void {} } diff --git a/packages/compiler-cli/src/ngtsc/core/src/compiler.ts b/packages/compiler-cli/src/ngtsc/core/src/compiler.ts index 1fc88bb792..0350590747 100644 --- a/packages/compiler-cli/src/ngtsc/core/src/compiler.ts +++ b/packages/compiler-cli/src/ngtsc/core/src/compiler.ts @@ -21,7 +21,7 @@ import {CompoundMetadataReader, CompoundMetadataRegistry, DtsMetadataReader, Inj import {ModuleWithProvidersScanner} from '../../modulewithproviders'; import {PartialEvaluator} from '../../partial_evaluator'; import {NOOP_PERF_RECORDER, PerfRecorder} from '../../perf'; -import {ClassDeclaration, TypeScriptReflectionHost} from '../../reflection'; +import {DeclarationNode, TypeScriptReflectionHost} from '../../reflection'; import {AdapterResourceLoader} from '../../resource'; import {entryPointKeyFor, NgModuleRouteAnalyzer} from '../../routing'; import {ComponentScopeReader, LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope'; @@ -238,7 +238,7 @@ export class NgCompiler { /** * Retrieves the `ts.Declaration`s for any component(s) which use the given template file. */ - getComponentsWithTemplateFile(templateFilePath: string): ReadonlySet { + getComponentsWithTemplateFile(templateFilePath: string): ReadonlySet { const {templateMapping} = this.ensureAnalyzed(); return templateMapping.getComponentsWithTemplate(resolve(templateFilePath)); } @@ -378,7 +378,7 @@ export class NgCompiler { * * See the `indexing` package for more details. */ - getIndexedComponents(): Map { + getIndexedComponents(): Map { const compilation = this.ensureAnalyzed(); const context = new IndexingContext(); compilation.traitCompiler.index(context); @@ -880,7 +880,7 @@ https://v9.angular.io/guide/template-typecheck#template-type-checking`, class ReferenceGraphAdapter implements ReferencesRegistry { constructor(private graph: ReferenceGraph) {} - add(source: ts.Declaration, ...references: Reference[]): void { + add(source: DeclarationNode, ...references: Reference[]): void { for (const {node} of references) { let sourceFile = node.getSourceFile(); if (sourceFile === undefined) { diff --git a/packages/compiler-cli/src/ngtsc/entry_point/BUILD.bazel b/packages/compiler-cli/src/ngtsc/entry_point/BUILD.bazel index 0bc6323756..6c22d2b902 100644 --- a/packages/compiler-cli/src/ngtsc/entry_point/BUILD.bazel +++ b/packages/compiler-cli/src/ngtsc/entry_point/BUILD.bazel @@ -11,6 +11,7 @@ ts_library( deps = [ "//packages/compiler-cli/src/ngtsc/diagnostics", "//packages/compiler-cli/src/ngtsc/file_system", + "//packages/compiler-cli/src/ngtsc/reflection", "//packages/compiler-cli/src/ngtsc/shims:api", "//packages/compiler-cli/src/ngtsc/util", "@npm//@types/node", diff --git a/packages/compiler-cli/src/ngtsc/entry_point/src/private_export_checker.ts b/packages/compiler-cli/src/ngtsc/entry_point/src/private_export_checker.ts index 307e454303..3dd66134d6 100644 --- a/packages/compiler-cli/src/ngtsc/entry_point/src/private_export_checker.ts +++ b/packages/compiler-cli/src/ngtsc/entry_point/src/private_export_checker.ts @@ -9,6 +9,7 @@ import * as ts from 'typescript'; import {ErrorCode, ngErrorCode} from '../../diagnostics'; +import {DeclarationNode} from '../../reflection'; import {ReferenceGraph} from './reference_graph'; @@ -39,7 +40,7 @@ export function checkForPrivateExports( const diagnostics: ts.Diagnostic[] = []; // Firstly, compute the exports of the entry point. These are all the Exported classes. - const topLevelExports = new Set(); + const topLevelExports = new Set(); // Do this via `ts.TypeChecker.getExportsOfModule`. const moduleSymbol = checker.getSymbolAtLocation(entryPoint); @@ -63,7 +64,7 @@ export function checkForPrivateExports( // Next, go through each exported class and expand it to the set of classes it makes Visible, // using the `ReferenceGraph`. For each Visible class, verify that it's also Exported, and queue // an error if it isn't. `checkedSet` ensures only one error is queued per class. - const checkedSet = new Set(); + const checkedSet = new Set(); // Loop through each Exported class. // TODO(alxhub): use proper iteration when the legacy build is removed. (#27762) @@ -110,7 +111,7 @@ export function checkForPrivateExports( return diagnostics; } -function getPosOfDeclaration(decl: ts.Declaration): {start: number, length: number} { +function getPosOfDeclaration(decl: DeclarationNode): {start: number, length: number} { const node: ts.Node = getIdentifierOfDeclaration(decl) || decl; return { start: node.getStart(), @@ -118,7 +119,7 @@ function getPosOfDeclaration(decl: ts.Declaration): {start: number, length: numb }; } -function getIdentifierOfDeclaration(decl: ts.Declaration): ts.Identifier|null { +function getIdentifierOfDeclaration(decl: DeclarationNode): ts.Identifier|null { if ((ts.isClassDeclaration(decl) || ts.isVariableDeclaration(decl) || ts.isFunctionDeclaration(decl)) && decl.name !== undefined && ts.isIdentifier(decl.name)) { @@ -128,12 +129,12 @@ function getIdentifierOfDeclaration(decl: ts.Declaration): ts.Identifier|null { } } -function getNameOfDeclaration(decl: ts.Declaration): string { +function getNameOfDeclaration(decl: DeclarationNode): string { const id = getIdentifierOfDeclaration(decl); return id !== null ? id.text : '(unnamed)'; } -function getDescriptorOfDeclaration(decl: ts.Declaration): string { +function getDescriptorOfDeclaration(decl: DeclarationNode): string { switch (decl.kind) { case ts.SyntaxKind.ClassDeclaration: return 'class'; diff --git a/packages/compiler-cli/src/ngtsc/entry_point/src/reference_graph.ts b/packages/compiler-cli/src/ngtsc/entry_point/src/reference_graph.ts index 4063c437b5..168943cf6a 100644 --- a/packages/compiler-cli/src/ngtsc/entry_point/src/reference_graph.ts +++ b/packages/compiler-cli/src/ngtsc/entry_point/src/reference_graph.ts @@ -6,9 +6,9 @@ * found in the LICENSE file at https://angular.io/license */ -import * as ts from 'typescript'; +import {DeclarationNode} from '../../reflection'; -export class ReferenceGraph { +export class ReferenceGraph { private references = new Map>(); add(from: T, to: T): void { diff --git a/packages/compiler-cli/src/ngtsc/imports/src/emitter.ts b/packages/compiler-cli/src/ngtsc/imports/src/emitter.ts index 2fa42012c8..4835935d0c 100644 --- a/packages/compiler-cli/src/ngtsc/imports/src/emitter.ts +++ b/packages/compiler-cli/src/ngtsc/imports/src/emitter.ts @@ -11,7 +11,7 @@ import * as ts from 'typescript'; import {UnifiedModulesHost} from '../../core/api'; import {absoluteFromSourceFile, dirname, LogicalFileSystem, LogicalProjectPath, relative, toRelativeImport} from '../../file_system'; import {stripExtension} from '../../file_system/src/util'; -import {ReflectionHost} from '../../reflection'; +import {DeclarationNode, isConcreteDeclaration, ReflectionHost} from '../../reflection'; import {getSourceFile, isDeclaration, isTypeDeclaration, nodeNameForError} from '../../util/src/typescript'; import {findExportedNameOfNode} from './find_export'; @@ -136,7 +136,7 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy { * A cache of the exports of specific modules, because resolving a module to its exports is a * costly operation. */ - private moduleExportsCache = new Map|null>(); + private moduleExportsCache = new Map|null>(); constructor( protected program: ts.Program, protected checker: ts.TypeChecker, @@ -170,7 +170,7 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy { return new ExternalExpr(new ExternalReference(specifier, symbolName)); } - private resolveImportName(moduleName: string, target: ts.Declaration, fromFile: string): string + private resolveImportName(moduleName: string, target: DeclarationNode, fromFile: string): string |null { const exports = this.getExportsOfModule(moduleName, fromFile); if (exports !== null && exports.has(target)) { @@ -181,7 +181,7 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy { } private getExportsOfModule(moduleName: string, fromFile: string): - Map|null { + Map|null { if (!this.moduleExportsCache.has(moduleName)) { this.moduleExportsCache.set(moduleName, this.enumerateExportsOfModule(moduleName, fromFile)); } @@ -189,7 +189,7 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy { } protected enumerateExportsOfModule(specifier: string, fromFile: string): - Map|null { + Map|null { // First, resolve the module specifier to its entry point, and get the ts.Symbol for it. const entryPointFile = this.moduleResolver.resolveModule(specifier, fromFile); if (entryPointFile === null) { @@ -200,13 +200,9 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy { if (exports === null) { return null; } - const exportMap = new Map(); + const exportMap = new Map(); exports.forEach((declaration, name) => { - // It's okay to skip inline declarations, since by definition they're not target-able with a - // ts.Declaration anyway. - if (declaration.node !== null) { - exportMap.set(declaration.node, name); - } + exportMap.set(declaration.node, name); }); return exportMap; } diff --git a/packages/compiler-cli/src/ngtsc/indexer/src/api.ts b/packages/compiler-cli/src/ngtsc/indexer/src/api.ts index 9948c69211..515b286fe6 100644 --- a/packages/compiler-cli/src/ngtsc/indexer/src/api.ts +++ b/packages/compiler-cli/src/ngtsc/indexer/src/api.ts @@ -7,8 +7,7 @@ */ import {ParseSourceFile} from '@angular/compiler'; -import * as ts from 'typescript'; -import {ClassDeclaration} from '../../reflection'; +import {ClassDeclaration, DeclarationNode} from '../../reflection'; /** * Describes the kind of identifier found in a template. @@ -129,7 +128,7 @@ export interface IndexedComponent { file: ParseSourceFile; template: { identifiers: Set, - usedComponents: Set, + usedComponents: Set, isInline: boolean, file: ParseSourceFile; }; diff --git a/packages/compiler-cli/src/ngtsc/indexer/src/transform.ts b/packages/compiler-cli/src/ngtsc/indexer/src/transform.ts index e5d3f7774b..d968461800 100644 --- a/packages/compiler-cli/src/ngtsc/indexer/src/transform.ts +++ b/packages/compiler-cli/src/ngtsc/indexer/src/transform.ts @@ -7,7 +7,7 @@ */ import {ParseSourceFile} from '@angular/compiler'; -import * as ts from 'typescript'; +import {DeclarationNode} from '../../reflection'; import {IndexedComponent} from './api'; import {IndexingContext} from './context'; import {getTemplateIdentifiers} from './template'; @@ -18,13 +18,13 @@ import {getTemplateIdentifiers} from './template'; * * The context must be populated before `generateAnalysis` is called. */ -export function generateAnalysis(context: IndexingContext): Map { - const analysis = new Map(); +export function generateAnalysis(context: IndexingContext): Map { + const analysis = new Map(); context.components.forEach(({declaration, selector, boundTemplate, templateMeta}) => { const name = declaration.name.getText(); - const usedComponents = new Set(); + const usedComponents = new Set(); const usedDirs = boundTemplate.getUsedDirectives(); usedDirs.forEach(dir => { if (dir.isComponent) { diff --git a/packages/compiler-cli/src/ngtsc/indexer/test/util.ts b/packages/compiler-cli/src/ngtsc/indexer/test/util.ts index 5013f4652c..7986cab520 100644 --- a/packages/compiler-cli/src/ngtsc/indexer/test/util.ts +++ b/packages/compiler-cli/src/ngtsc/indexer/test/util.ts @@ -29,7 +29,7 @@ export function getComponentDeclaration(componentStr: string, className: string) return getDeclaration( program.program, getTestFilePath(), className, - (value: ts.Declaration): value is ClassDeclaration => ts.isClassDeclaration(value)); + (value: ts.Node): value is ClassDeclaration => ts.isClassDeclaration(value)); } /** diff --git a/packages/compiler-cli/src/ngtsc/partial_evaluator/src/interpreter.ts b/packages/compiler-cli/src/ngtsc/partial_evaluator/src/interpreter.ts index af20342297..fa75646407 100644 --- a/packages/compiler-cli/src/ngtsc/partial_evaluator/src/interpreter.ts +++ b/packages/compiler-cli/src/ngtsc/partial_evaluator/src/interpreter.ts @@ -11,7 +11,7 @@ import * as ts from 'typescript'; import {Reference} from '../../imports'; import {OwningModule} from '../../imports/src/references'; import {DependencyTracker} from '../../incremental/api'; -import {ConcreteDeclaration, Declaration, EnumMember, FunctionDefinition, InlineDeclaration, ReflectionHost, SpecialDeclarationKind} from '../../reflection'; +import {Declaration, DeclarationNode, EnumMember, FunctionDefinition, isConcreteDeclaration, ReflectionHost, SpecialDeclarationKind} from '../../reflection'; import {isDeclaration} from '../../util/src/typescript'; import {ArrayConcatBuiltinFn, ArraySliceBuiltinFn} from './builtin'; @@ -231,12 +231,7 @@ export class StaticInterpreter { return this.getResolvedEnum(decl.node, decl.identity.enumMembers, context); } const declContext = {...context, ...joinModuleContext(context, node, decl)}; - // The identifier's declaration is either concrete (a ts.Declaration exists for it) or inline - // (a direct reference to a ts.Expression). - // TODO(alxhub): remove cast once TS is upgraded in g3. - const result = decl.node !== null ? - this.visitDeclaration(decl.node, declContext) : - this.visitExpression((decl as InlineDeclaration).expression, declContext); + const result = this.visitDeclaration(decl.node, declContext); if (result instanceof Reference) { // Only record identifiers to non-synthetic references. Synthetic references may not have the // same value at runtime as they do at compile time, so it's not legal to refer to them by the @@ -250,7 +245,7 @@ export class StaticInterpreter { return result; } - private visitDeclaration(node: ts.Declaration, context: Context): ResolvedValue { + private visitDeclaration(node: DeclarationNode, context: Context): ResolvedValue { if (this.dependencyTracker !== null) { this.dependencyTracker.addDependency(context.originatingFile, node.getSourceFile()); } @@ -342,10 +337,7 @@ export class StaticInterpreter { }; // Visit both concrete and inline declarations. - // TODO(alxhub): remove cast once TS is upgraded in g3. - return decl.node !== null ? - this.visitDeclaration(decl.node, declContext) : - this.visitExpression((decl as InlineDeclaration).expression, declContext); + return this.visitDeclaration(decl.node, declContext); }); } @@ -667,7 +659,7 @@ export class StaticInterpreter { return map; } - private getReference(node: T, context: Context): Reference { + private getReference(node: T, context: Context): Reference { return new Reference(node, owningModule(context)); } } @@ -733,11 +725,3 @@ function owningModule(context: Context, override: OwningModule|null = null): Own return null; } } - -/** - * Helper type guard to workaround a narrowing limitation in g3, where testing for - * `decl.node !== null` would not narrow `decl` to be of type `ConcreteDeclaration`. - */ -function isConcreteDeclaration(decl: Declaration): decl is ConcreteDeclaration { - return decl.node !== null; -} diff --git a/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts b/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts index 7c8d53e925..0f728bae44 100644 --- a/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts +++ b/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts @@ -11,7 +11,7 @@ import {absoluteFrom, getSourceFileOrError} from '../../file_system'; import {runInEachFileSystem} from '../../file_system/testing'; import {Reference} from '../../imports'; import {DependencyTracker} from '../../incremental/api'; -import {Declaration, KnownDeclaration, SpecialDeclarationKind, TypeScriptReflectionHost} from '../../reflection'; +import {Declaration, DeclarationKind, isConcreteDeclaration, KnownDeclaration, SpecialDeclarationKind, TypeScriptReflectionHost} from '../../reflection'; import {getDeclaration, makeProgram} from '../../testing'; import {DynamicValue} from '../src/dynamic'; import {PartialEvaluator} from '../src/interface'; @@ -920,7 +920,7 @@ runInEachFileSystem(() => { class DownleveledEnumReflectionHost extends TypeScriptReflectionHost { getDeclarationOfIdentifier(id: ts.Identifier): Declaration|null { const declaration = super.getDeclarationOfIdentifier(id); - if (declaration !== null && declaration.node !== null) { + if (declaration !== null && isConcreteDeclaration(declaration)) { const enumMembers = [ {name: ts.createStringLiteral('ValueA'), initializer: ts.createStringLiteral('a')}, {name: ts.createStringLiteral('ValueB'), initializer: ts.createStringLiteral('b')}, @@ -961,6 +961,7 @@ runInEachFileSystem(() => { node: id, viaModule: null, identity: null, + kind: DeclarationKind.Concrete, }; } @@ -968,8 +969,8 @@ runInEachFileSystem(() => { } } - function getTsHelperFn(node: ts.Declaration): KnownDeclaration|null { - const id = (node as ts.Declaration & {name?: ts.Identifier}).name || null; + function getTsHelperFn(node: ts.Node): KnownDeclaration|null { + const id = (node as ts.Node & {name?: ts.Identifier}).name || null; const name = id && id.text; switch (name) { diff --git a/packages/compiler-cli/src/ngtsc/perf/BUILD.bazel b/packages/compiler-cli/src/ngtsc/perf/BUILD.bazel index dd609410fd..f51e6b0a56 100644 --- a/packages/compiler-cli/src/ngtsc/perf/BUILD.bazel +++ b/packages/compiler-cli/src/ngtsc/perf/BUILD.bazel @@ -10,6 +10,7 @@ ts_library( deps = [ "//packages:types", "//packages/compiler-cli/src/ngtsc/file_system", + "//packages/compiler-cli/src/ngtsc/reflection", "@npm//@types/node", "@npm//typescript", ], diff --git a/packages/compiler-cli/src/ngtsc/perf/src/api.ts b/packages/compiler-cli/src/ngtsc/perf/src/api.ts index 73875e88cb..a717808324 100644 --- a/packages/compiler-cli/src/ngtsc/perf/src/api.ts +++ b/packages/compiler-cli/src/ngtsc/perf/src/api.ts @@ -6,13 +6,12 @@ * found in the LICENSE file at https://angular.io/license */ -import * as ts from 'typescript'; +import {DeclarationNode} from '../../reflection'; export interface PerfRecorder { readonly enabled: boolean; - mark(name: string, node?: ts.SourceFile|ts.Declaration, category?: string, detail?: string): void; - start(name: string, node?: ts.SourceFile|ts.Declaration, category?: string, detail?: string): - number; + mark(name: string, node?: DeclarationNode, category?: string, detail?: string): void; + start(name: string, node?: DeclarationNode, category?: string, detail?: string): number; stop(span: number): void; } diff --git a/packages/compiler-cli/src/ngtsc/perf/src/noop.ts b/packages/compiler-cli/src/ngtsc/perf/src/noop.ts index 151a1af7ee..73f4384dde 100644 --- a/packages/compiler-cli/src/ngtsc/perf/src/noop.ts +++ b/packages/compiler-cli/src/ngtsc/perf/src/noop.ts @@ -5,18 +5,15 @@ * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ - -import * as ts from 'typescript'; +import {DeclarationNode} from '../../reflection'; import {PerfRecorder} from './api'; export const NOOP_PERF_RECORDER: PerfRecorder = { enabled: false, - mark: (name: string, node: ts.SourceFile|ts.Declaration, category?: string, detail?: string): - void => {}, - start: (name: string, node: ts.SourceFile|ts.Declaration, category?: string, detail?: string): - number => { - return 0; - }, + mark: (name: string, node: DeclarationNode, category?: string, detail?: string): void => {}, + start: (name: string, node: DeclarationNode, category?: string, detail?: string): number => { + return 0; + }, stop: (span: number|false): void => {}, }; diff --git a/packages/compiler-cli/src/ngtsc/perf/src/tracking.ts b/packages/compiler-cli/src/ngtsc/perf/src/tracking.ts index e1d8a4a6f3..732c8f0367 100644 --- a/packages/compiler-cli/src/ngtsc/perf/src/tracking.ts +++ b/packages/compiler-cli/src/ngtsc/perf/src/tracking.ts @@ -9,6 +9,7 @@ import * as fs from 'fs'; import * as ts from 'typescript'; import {resolve} from '../../file_system'; +import {DeclarationNode} from '../../reflection'; import {PerfRecorder} from './api'; import {HrTime, mark, timeSinceInMicros} from './clock'; @@ -24,14 +25,12 @@ export class PerfTracker implements PerfRecorder { return new PerfTracker(mark()); } - mark(name: string, node?: ts.SourceFile|ts.Declaration, category?: string, detail?: string): - void { + mark(name: string, node?: DeclarationNode, category?: string, detail?: string): void { const msg = this.makeLogMessage(PerfLogEventType.MARK, name, node, category, detail, undefined); this.log.push(msg); } - start(name: string, node?: ts.SourceFile|ts.Declaration, category?: string, detail?: string): - number { + start(name: string, node?: DeclarationNode, category?: string, detail?: string): number { const span = this.nextSpanId++; const msg = this.makeLogMessage(PerfLogEventType.SPAN_OPEN, name, node, category, detail, span); this.log.push(msg); @@ -47,7 +46,7 @@ export class PerfTracker implements PerfRecorder { } private makeLogMessage( - type: PerfLogEventType, name: string, node: ts.SourceFile|ts.Declaration|undefined, + type: PerfLogEventType, name: string, node: DeclarationNode|undefined, category: string|undefined, detail: string|undefined, span: number|undefined): PerfLogEvent { const msg: PerfLogEvent = { type, diff --git a/packages/compiler-cli/src/ngtsc/program.ts b/packages/compiler-cli/src/ngtsc/program.ts index cc277e0d97..13e209fc0a 100644 --- a/packages/compiler-cli/src/ngtsc/program.ts +++ b/packages/compiler-cli/src/ngtsc/program.ts @@ -17,6 +17,7 @@ import {NgCompilerOptions} from './core/api'; import {TrackedIncrementalBuildStrategy} from './incremental'; import {IndexedComponent} from './indexer'; import {NOOP_PERF_RECORDER, PerfRecorder, PerfTracker} from './perf'; +import {DeclarationNode} from './reflection'; import {retagAllTsFiles, untagAllTsFiles} from './shims'; import {ReusedProgramStrategy} from './typecheck'; @@ -276,7 +277,7 @@ export class NgtscProgram implements api.Program { return ((opts && opts.mergeEmitResultsCallback) || mergeEmitResults)(emitResults); } - getIndexedComponents(): Map { + getIndexedComponents(): Map { return this.compiler.getIndexedComponents(); } diff --git a/packages/compiler-cli/src/ngtsc/reflection/src/host.ts b/packages/compiler-cli/src/ngtsc/reflection/src/host.ts index 8ad56ce32c..af979422ff 100644 --- a/packages/compiler-cli/src/ngtsc/reflection/src/host.ts +++ b/packages/compiler-cli/src/ngtsc/reflection/src/host.ts @@ -113,7 +113,7 @@ export function isDecoratorIdentifier(exp: ts.Expression): exp is DecoratorIdent * For `ReflectionHost` purposes, a class declaration should always have a `name` identifier, * because we need to be able to reference it in other parts of the program. */ -export type ClassDeclaration = T&{name: ts.Identifier}; +export type ClassDeclaration = T&{name: ts.Identifier}; /** * An enumeration of possible kinds of class members. @@ -275,7 +275,7 @@ export interface ImportedTypeValueReference { */ nestedPath: string[]|null; - valueDeclaration: ts.Declaration; + valueDeclaration: DeclarationNode; } /** @@ -530,10 +530,38 @@ export interface EnumMember { initializer: ts.Expression; } +/** + * A type that is used to identify a declaration. + * + * Declarations are normally `ts.Declaration` types such as variable declarations, class + * declarations, function declarations etc. + * But in some cases there is no `ts.Declaration` that can be used for a declaration, such + * as when they are declared inline as part of an exported expression. Then we must use a + * `ts.Expression` as the declaration. + * An example of this is `exports.someVar = 42` where the declaration expression would be + * `exports.someVar`. + */ +export type DeclarationNode = ts.Declaration|ts.Expression; + +/** + * The type of a Declaration - whether its node is concrete (ts.Declaration) or inline + * (ts.Expression). See `ConcreteDeclaration`, `InlineDeclaration` and `DeclarationNode` for more + * information about this. + */ +export const enum DeclarationKind { + Concrete, + Inline, +} + /** * Base type for all `Declaration`s. */ -export interface BaseDeclaration { +export interface BaseDeclaration { + /** + * The type of the underlying `node`. + */ + kind: DeclarationKind; + /** * The absolute module path from which the symbol was imported into the application, if the symbol * was imported via an absolute module (even through a chain of re-exports). If the symbol is part @@ -544,7 +572,7 @@ export interface BaseDeclaration { /** * TypeScript reference to the declaration itself, if one exists. */ - node: T|null; + node: T; /** * If set, describes the type of the known declaration this declaration resolves to. @@ -553,13 +581,16 @@ export interface BaseDeclaration { } /** - * A declaration that has an associated TypeScript `ts.Declaration`. - * - * The alternative is an `InlineDeclaration`. + * Returns true if the `decl` is a `ConcreteDeclaration` (ie. that its `node` property is a + * `ts.Declaration`). */ +export function isConcreteDeclaration(decl: Declaration): decl is ConcreteDeclaration { + return decl.kind === DeclarationKind.Concrete; +} + export interface ConcreteDeclaration extends BaseDeclaration { - node: T; + kind: DeclarationKind.Concrete; /** * Optionally represents a special identity of the declaration, or `null` if the declaration @@ -585,29 +616,20 @@ export interface DownleveledEnum { } /** - * A declaration that does not have an associated TypeScript `ts.Declaration`, only a - * `ts.Expression`. + * A declaration that does not have an associated TypeScript `ts.Declaration`. * * This can occur in some downlevelings when an `export const VAR = ...;` (a `ts.Declaration`) is * transpiled to an assignment statement (e.g. `exports.VAR = ...;`). There is no `ts.Declaration` * associated with `VAR` in that case, only an expression. */ -export interface InlineDeclaration extends BaseDeclaration { - node: null; - - /** - * The `ts.Expression` which constitutes the value of the declaration. - */ - expression: ts.Expression; +export interface InlineDeclaration extends + BaseDeclaration> { + kind: DeclarationKind.Inline; } /** * The declaration of a symbol, along with information about how it was imported into the * application. - * - * This can either be a `ConcreteDeclaration` if the underlying TypeScript node for the symbol is an - * actual `ts.Declaration`, or an `InlineDeclaration` if the declaration was transpiled in certain - * downlevelings to a `ts.Expression` instead. */ export type Declaration = ConcreteDeclaration|InlineDeclaration; @@ -637,7 +659,7 @@ export interface ReflectionHost { * @returns an array of `Decorator` metadata if decorators are present on the declaration, or * `null` if either no decorators were present or if the declaration is not of a decoratable type. */ - getDecoratorsOfDeclaration(declaration: ts.Declaration): Decorator[]|null; + getDecoratorsOfDeclaration(declaration: DeclarationNode): Decorator[]|null; /** * Examine a declaration which should be of a class, and return metadata about the members of the @@ -802,7 +824,7 @@ export interface ReflectionHost { * Note that the `ts.Declaration` returned from this function may not be from the same * `ts.Program` as the input declaration. */ - getDtsDeclaration(declaration: ts.Declaration): ts.Declaration|null; + getDtsDeclaration(declaration: DeclarationNode): ts.Declaration|null; /** * Get a `ts.Identifier` for a given `ClassDeclaration` which can be used to refer to the class diff --git a/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts b/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts index 202a4c43b3..72a8f54139 100644 --- a/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts +++ b/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts @@ -8,7 +8,7 @@ import * as ts from 'typescript'; -import {ClassDeclaration, ClassMember, ClassMemberKind, CtorParameter, Declaration, Decorator, FunctionDefinition, Import, isDecoratorIdentifier, ReflectionHost} from './host'; +import {ClassDeclaration, ClassMember, ClassMemberKind, CtorParameter, Declaration, DeclarationKind, DeclarationNode, Decorator, FunctionDefinition, Import, isDecoratorIdentifier, ReflectionHost} from './host'; import {typeToValue} from './type_to_value'; import {isNamedClassDeclaration} from './util'; @@ -19,7 +19,7 @@ import {isNamedClassDeclaration} from './util'; export class TypeScriptReflectionHost implements ReflectionHost { constructor(protected checker: ts.TypeChecker) {} - getDecoratorsOfDeclaration(declaration: ts.Declaration): Decorator[]|null { + getDecoratorsOfDeclaration(declaration: DeclarationNode): Decorator[]|null { if (declaration.decorators === undefined || declaration.decorators.length === 0) { return null; } @@ -187,7 +187,7 @@ export class TypeScriptReflectionHost implements ReflectionHost { return declaration.initializer || null; } - getDtsDeclaration(_: ts.Declaration): ts.Declaration|null { + getDtsDeclaration(_: ClassDeclaration): ts.Declaration|null { return null; } @@ -207,7 +207,7 @@ export class TypeScriptReflectionHost implements ReflectionHost { return null; } - const decl: ts.Declaration = symbol.declarations[0]; + const decl = symbol.declarations[0]; const importDecl = getContainingImportDeclaration(decl); // Ignore declarations that are defined locally (not imported). @@ -318,6 +318,7 @@ export class TypeScriptReflectionHost implements ReflectionHost { known: null, viaModule, identity: null, + kind: DeclarationKind.Concrete, }; } else if (symbol.declarations !== undefined && symbol.declarations.length > 0) { return { @@ -325,6 +326,7 @@ export class TypeScriptReflectionHost implements ReflectionHost { known: null, viaModule, identity: null, + kind: DeclarationKind.Concrete, }; } else { return null; diff --git a/packages/compiler-cli/src/ngtsc/reflection/test/ts_host_spec.ts b/packages/compiler-cli/src/ngtsc/reflection/test/ts_host_spec.ts index f4cfd540ac..d298d2441c 100644 --- a/packages/compiler-cli/src/ngtsc/reflection/test/ts_host_spec.ts +++ b/packages/compiler-cli/src/ngtsc/reflection/test/ts_host_spec.ts @@ -9,7 +9,7 @@ import * as ts from 'typescript'; import {absoluteFrom, getSourceFileOrError} from '../../file_system'; import {runInEachFileSystem} from '../../file_system/testing'; import {getDeclaration, makeProgram} from '../../testing'; -import {ClassMember, ClassMemberKind, CtorParameter, TypeValueReferenceKind} from '../src/host'; +import {ClassMember, ClassMemberKind, CtorParameter, DeclarationKind, TypeValueReferenceKind} from '../src/host'; import {TypeScriptReflectionHost} from '../src/typescript'; import {isNamedClassDeclaration} from '../src/util'; @@ -360,6 +360,7 @@ runInEachFileSystem(() => { const Target = foo.type.typeName; const decl = host.getDeclarationOfIdentifier(Target); expect(decl).toEqual({ + kind: DeclarationKind.Concrete, node: targetDecl, known: null, viaModule: 'absolute', @@ -395,6 +396,7 @@ runInEachFileSystem(() => { known: null, viaModule: 'absolute', identity: null, + kind: DeclarationKind.Concrete }); }); }); diff --git a/packages/compiler-cli/src/ngtsc/scope/src/local.ts b/packages/compiler-cli/src/ngtsc/scope/src/local.ts index da7f3aa939..42990227ab 100644 --- a/packages/compiler-cli/src/ngtsc/scope/src/local.ts +++ b/packages/compiler-cli/src/ngtsc/scope/src/local.ts @@ -12,7 +12,7 @@ import * as ts from 'typescript'; import {ErrorCode, makeDiagnostic, makeRelatedInformation} from '../../diagnostics'; import {AliasingHost, Reexport, Reference, ReferenceEmitter} from '../../imports'; import {DirectiveMeta, MetadataReader, MetadataRegistry, NgModuleMeta, PipeMeta} from '../../metadata'; -import {ClassDeclaration} from '../../reflection'; +import {ClassDeclaration, DeclarationNode} from '../../reflection'; import {identifierOfNode, nodeNameForError} from '../../util/src/typescript'; import {ExportScope, ScopeData} from './api'; @@ -293,14 +293,14 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop // - the directives and pipes which are exported to any NgModules which import this one. // Directives and pipes in the compilation scope. - const compilationDirectives = new Map(); - const compilationPipes = new Map(); + const compilationDirectives = new Map(); + const compilationPipes = new Map(); - const declared = new Set(); + const declared = new Set(); // Directives and pipes exported to any importing NgModules. - const exportDirectives = new Map(); - const exportPipes = new Map(); + const exportDirectives = new Map(); + const exportPipes = new Map(); // The algorithm is as follows: // 1) Add all of the directives/pipes from each NgModule imported into the current one to the @@ -477,7 +477,7 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop */ private getExportedScope( ref: Reference, diagnostics: ts.Diagnostic[], - ownerForErrors: ts.Declaration, type: 'import'|'export'): ExportScope|null|undefined { + ownerForErrors: DeclarationNode, type: 'import'|'export'): ExportScope|null|undefined { if (ref.node.getSourceFile().isDeclarationFile) { // The NgModule is declared in a .d.ts file. Resolve it with the `DependencyScopeReader`. if (!ts.isClassDeclaration(ref.node)) { @@ -499,7 +499,7 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop } private getReexports( - ngModule: NgModuleMeta, ref: Reference, declared: Set, + ngModule: NgModuleMeta, ref: Reference, declared: Set, exported: {directives: DirectiveMeta[], pipes: PipeMeta[]}, diagnostics: ts.Diagnostic[]): Reexport[]|null { let reexports: Reexport[]|null = null; @@ -569,7 +569,7 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop * Produce a `ts.Diagnostic` for an invalid import or export from an NgModule. */ function invalidRef( - clazz: ts.Declaration, decl: Reference, + clazz: DeclarationNode, decl: Reference, type: 'import'|'export'): ts.Diagnostic { const code = type === 'import' ? ErrorCode.NGMODULE_INVALID_IMPORT : ErrorCode.NGMODULE_INVALID_EXPORT; @@ -607,7 +607,7 @@ function invalidRef( * Produce a `ts.Diagnostic` for an import or export which itself has errors. */ function invalidTransitiveNgModuleRef( - clazz: ts.Declaration, decl: Reference, + clazz: DeclarationNode, decl: Reference, type: 'import'|'export'): ts.Diagnostic { const code = type === 'import' ? ErrorCode.NGMODULE_INVALID_IMPORT : ErrorCode.NGMODULE_INVALID_EXPORT; @@ -620,7 +620,7 @@ function invalidTransitiveNgModuleRef( * Produce a `ts.Diagnostic` for an exported directive or pipe which was not declared or imported * by the NgModule in question. */ -function invalidReexport(clazz: ts.Declaration, decl: Reference): ts.Diagnostic { +function invalidReexport(clazz: DeclarationNode, decl: Reference): ts.Diagnostic { return makeDiagnostic( ErrorCode.NGMODULE_INVALID_REEXPORT, identifierOfNode(decl.node) || decl.node, `Present in the NgModule.exports of ${ diff --git a/packages/compiler-cli/src/ngtsc/testing/BUILD.bazel b/packages/compiler-cli/src/ngtsc/testing/BUILD.bazel index e28599e6ae..2fe8466d92 100644 --- a/packages/compiler-cli/src/ngtsc/testing/BUILD.bazel +++ b/packages/compiler-cli/src/ngtsc/testing/BUILD.bazel @@ -11,6 +11,7 @@ ts_library( deps = [ "//packages:types", "//packages/compiler-cli/src/ngtsc/file_system", + "//packages/compiler-cli/src/ngtsc/reflection", "@npm//typescript", ], ) diff --git a/packages/compiler-cli/src/ngtsc/testing/src/utils.ts b/packages/compiler-cli/src/ngtsc/testing/src/utils.ts index fa339eefce..cfaa5cba85 100644 --- a/packages/compiler-cli/src/ngtsc/testing/src/utils.ts +++ b/packages/compiler-cli/src/ngtsc/testing/src/utils.ts @@ -11,6 +11,7 @@ import * as ts from 'typescript'; import {AbsoluteFsPath, dirname, getFileSystem, getSourceFileOrError, NgtscCompilerHost} from '../../file_system'; +import {DeclarationNode} from '../../reflection'; export function makeProgram( files: {name: AbsoluteFsPath, contents: string, isRoot?: boolean}[], @@ -57,7 +58,7 @@ export function makeProgram( * An error will be thrown if there is not at least one AST node with the given `name` and passes * the `predicate` test. */ -export function getDeclaration( +export function getDeclaration( program: ts.Program, fileName: AbsoluteFsPath, name: string, assert: (value: any) => value is T): T { const sf = getSourceFileOrError(program, fileName); @@ -78,8 +79,8 @@ export function getDeclaration( /** * Walk the AST tree from the `rootNode` looking for a declaration that has the given `name`. */ -export function walkForDeclarations(name: string, rootNode: ts.Node): ts.Declaration[] { - const chosenDecls: ts.Declaration[] = []; +export function walkForDeclarations(name: string, rootNode: ts.Node): DeclarationNode[] { + const chosenDecls: DeclarationNode[] = []; rootNode.forEachChild(node => { if (ts.isVariableStatement(node)) { node.declarationList.declarations.forEach(decl => { diff --git a/packages/compiler-cli/src/ngtsc/transform/src/compilation.ts b/packages/compiler-cli/src/ngtsc/transform/src/compilation.ts index ec479bc32d..01415026c3 100644 --- a/packages/compiler-cli/src/ngtsc/transform/src/compilation.ts +++ b/packages/compiler-cli/src/ngtsc/transform/src/compilation.ts @@ -13,7 +13,7 @@ import {ErrorCode, FatalDiagnosticError} from '../../diagnostics'; import {IncrementalBuild} from '../../incremental/api'; import {IndexingContext} from '../../indexer'; import {PerfRecorder} from '../../perf'; -import {ClassDeclaration, Decorator, ReflectionHost} from '../../reflection'; +import {ClassDeclaration, DeclarationNode, Decorator, ReflectionHost} from '../../reflection'; import {ProgramTypeCheckAdapter, TypeCheckContext} from '../../typecheck/api'; import {getSourceFile, isExported} from '../../util/src/typescript'; @@ -463,7 +463,7 @@ export class TraitCompiler implements ProgramTypeCheckAdapter { } } - compile(clazz: ts.Declaration, constantPool: ConstantPool): CompileResult[]|null { + compile(clazz: DeclarationNode, constantPool: ConstantPool): CompileResult[]|null { const original = ts.getOriginalNode(clazz) as typeof clazz; if (!this.reflector.isClass(clazz) || !this.reflector.isClass(original) || !this.classes.has(original)) { diff --git a/packages/compiler-cli/src/ngtsc/typecheck/diagnostics/BUILD.bazel b/packages/compiler-cli/src/ngtsc/typecheck/diagnostics/BUILD.bazel index e9c8b1e10b..535b5a64c8 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/diagnostics/BUILD.bazel +++ b/packages/compiler-cli/src/ngtsc/typecheck/diagnostics/BUILD.bazel @@ -9,6 +9,7 @@ ts_library( deps = [ "//packages:types", "//packages/compiler", + "//packages/compiler-cli/src/ngtsc/reflection", "//packages/compiler-cli/src/ngtsc/typecheck/api", "@npm//typescript", ], diff --git a/packages/compiler-cli/src/ngtsc/typecheck/diagnostics/src/id.ts b/packages/compiler-cli/src/ngtsc/typecheck/diagnostics/src/id.ts index b7ae05a833..22043f73a4 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/diagnostics/src/id.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/diagnostics/src/id.ts @@ -7,6 +7,7 @@ */ import * as ts from 'typescript'; +import {DeclarationNode} from '../../../reflection'; import {TemplateId} from '../../api'; @@ -22,7 +23,7 @@ interface HasNextTemplateId { [NEXT_TEMPLATE_ID]: number; } -export function getTemplateId(clazz: ts.Declaration): TemplateId { +export function getTemplateId(clazz: DeclarationNode): TemplateId { const node = clazz as ts.Declaration & Partial; if (node[TEMPLATE_ID] === undefined) { node[TEMPLATE_ID] = allocateTemplateId(node.getSourceFile()); diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/type_parameter_emitter.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/type_parameter_emitter.ts index 968043b89b..c973742cea 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/src/type_parameter_emitter.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/src/type_parameter_emitter.ts @@ -8,7 +8,7 @@ import * as ts from 'typescript'; import {OwningModule, Reference} from '../../imports'; -import {ReflectionHost} from '../../reflection'; +import {DeclarationNode, ReflectionHost} from '../../reflection'; import {canEmitType, ResolvedTypeReference, TypeEmitter} from './type_emitter'; @@ -89,7 +89,7 @@ export class TypeParameterEmitter { return new Reference(declaration.node, owningModule); } - private isLocalTypeParameter(decl: ts.Declaration): boolean { + private isLocalTypeParameter(decl: DeclarationNode): boolean { // Checking for local type parameters only occurs during resolution of type parameters, so it is // guaranteed that type parameters are present. return this.typeParameters!.some(param => param === decl); diff --git a/packages/compiler-cli/src/ngtsc/util/BUILD.bazel b/packages/compiler-cli/src/ngtsc/util/BUILD.bazel index 59bcee2797..cb06267fdb 100644 --- a/packages/compiler-cli/src/ngtsc/util/BUILD.bazel +++ b/packages/compiler-cli/src/ngtsc/util/BUILD.bazel @@ -11,6 +11,7 @@ ts_library( "//packages:types", "//packages/compiler-cli/src/ngtsc/file_system", "//packages/compiler-cli/src/ngtsc/incremental:api", + "//packages/compiler-cli/src/ngtsc/reflection", "@npm//@types/node", "@npm//typescript", ], diff --git a/packages/compiler-cli/src/ngtsc/util/src/typescript.ts b/packages/compiler-cli/src/ngtsc/util/src/typescript.ts index 346c47773f..c7bf5eed6b 100644 --- a/packages/compiler-cli/src/ngtsc/util/src/typescript.ts +++ b/packages/compiler-cli/src/ngtsc/util/src/typescript.ts @@ -11,6 +11,7 @@ const D_TS = /\.d\.ts$/i; import * as ts from 'typescript'; import {AbsoluteFsPath, absoluteFrom} from '../../file_system'; +import {DeclarationNode} from '../../reflection'; export function isDtsPath(filePath: string): boolean { return D_TS.test(filePath); @@ -82,7 +83,7 @@ export function isTypeDeclaration(node: ts.Node): node is ts.EnumDeclaration| ts.isInterfaceDeclaration(node); } -export function isExported(node: ts.Declaration): boolean { +export function isExported(node: DeclarationNode): boolean { let topLevel: ts.Node = node; if (ts.isVariableDeclaration(node) && ts.isVariableDeclarationList(node.parent)) { topLevel = node.parent.parent; diff --git a/packages/compiler-cli/test/ngtsc/BUILD.bazel b/packages/compiler-cli/test/ngtsc/BUILD.bazel index 96e2a67c9e..20359c531c 100644 --- a/packages/compiler-cli/test/ngtsc/BUILD.bazel +++ b/packages/compiler-cli/test/ngtsc/BUILD.bazel @@ -11,6 +11,7 @@ ts_library( "//packages/compiler-cli/src/ngtsc/file_system", "//packages/compiler-cli/src/ngtsc/file_system/testing", "//packages/compiler-cli/src/ngtsc/indexer", + "//packages/compiler-cli/src/ngtsc/reflection", "//packages/compiler-cli/src/ngtsc/routing", "//packages/compiler-cli/src/ngtsc/testing", "//packages/compiler-cli/src/ngtsc/util", diff --git a/packages/compiler-cli/test/ngtsc/env.ts b/packages/compiler-cli/test/ngtsc/env.ts index 869a22e1fc..9cf9c48dfd 100644 --- a/packages/compiler-cli/test/ngtsc/env.ts +++ b/packages/compiler-cli/test/ngtsc/env.ts @@ -16,6 +16,7 @@ import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem, NgtscCompilerHo import {Folder, MockFileSystem} from '../../src/ngtsc/file_system/testing'; import {IndexedComponent} from '../../src/ngtsc/indexer'; import {NgtscProgram} from '../../src/ngtsc/program'; +import {DeclarationNode} from '../../src/ngtsc/reflection'; import {LazyRoute} from '../../src/ngtsc/routing'; import {setWrapHostForTest} from '../../src/transformers/compiler_host'; import {getCachedSourceFile} from '../helpers'; @@ -259,7 +260,7 @@ export class NgtscTestEnvironment { return program.listLazyRoutes(entryPoint); } - driveIndexer(): Map { + driveIndexer(): Map { const {rootNames, options} = readNgcCommandLineAndConfiguration(['-p', this.basePath]); const host = createCompilerHost({options}); const program = createProgram({rootNames, host, options}); diff --git a/packages/language-service/ivy/BUILD.bazel b/packages/language-service/ivy/BUILD.bazel index e5886aacd9..d9c4434b73 100644 --- a/packages/language-service/ivy/BUILD.bazel +++ b/packages/language-service/ivy/BUILD.bazel @@ -12,6 +12,7 @@ ts_library( "//packages/compiler-cli/src/ngtsc/core:api", "//packages/compiler-cli/src/ngtsc/file_system", "//packages/compiler-cli/src/ngtsc/incremental", + "//packages/compiler-cli/src/ngtsc/reflection", "//packages/compiler-cli/src/ngtsc/shims", "//packages/compiler-cli/src/ngtsc/typecheck", "//packages/compiler-cli/src/ngtsc/typecheck/api", diff --git a/packages/language-service/ivy/utils.ts b/packages/language-service/ivy/utils.ts index 110e655a28..1e5c4107d6 100644 --- a/packages/language-service/ivy/utils.ts +++ b/packages/language-service/ivy/utils.ts @@ -7,6 +7,7 @@ */ import {AbsoluteSourceSpan, CssSelector, ParseSourceSpan, SelectorMatcher} from '@angular/compiler'; import {NgCompiler} from '@angular/compiler-cli/src/ngtsc/core'; +import {DeclarationNode} from '@angular/compiler-cli/src/ngtsc/reflection'; import {DirectiveSymbol} from '@angular/compiler-cli/src/ngtsc/typecheck/api'; import * as e from '@angular/compiler/src/expression_parser/ast'; // e for expression AST import * as t from '@angular/compiler/src/render3/r3_ast'; // t for template AST @@ -81,7 +82,7 @@ export function getTemplateInfoAtPosition( * First, attempt to sort component declarations by file name. * If the files are the same, sort by start location of the declaration. */ -function tsDeclarationSortComparator(a: ts.Declaration, b: ts.Declaration): number { +function tsDeclarationSortComparator(a: DeclarationNode, b: DeclarationNode): number { const aFile = a.getSourceFile().fileName; const bFile = b.getSourceFile().fileName; if (aFile < bFile) {