From f4a9f5dae865ee54f2c830e7fa4a62c44c1c5353 Mon Sep 17 00:00:00 2001 From: Alex Rickabaugh Date: Mon, 17 Dec 2018 16:17:38 -0800 Subject: [PATCH] refactor(ivy): prep ngtsc and ngcc for upcoming import resolution work (#27743) Upcoming work to implement import resolution will change the dependencies of some higher-level classes in ngtsc & ngcc. This necessitates changes in how these classes are created and the lifecycle of the ts.Program in ngtsc & ngcc. To avoid complicating the implementation work with refactoring as a result of the new dependencies, the refactoring is performed in this commit as a separate prepatory step. In ngtsc, the testing harness is modified to allow easier access to some aspects of the ts.Program. In ngcc, the main change is that the DecorationAnalyzer is created with the ts.Program as a constructor parameter. This is not a lifecycle change, as it was previously created with the ts.TypeChecker which is derived from the ts.Program anyways. This change requires some reorganization in ngcc to accommodate, especially in testing harnesses where DecorationAnalyzer is created manually in a number of specs. PR Close #27743 --- .../ngcc/src/analysis/decoration_analyzer.ts | 36 ++--- .../src/ngcc/src/packages/bundle_program.ts | 4 +- .../src/ngcc/src/packages/transformer.ts | 5 +- .../test/analysis/decoration_analyzer_spec.ts | 42 +++--- .../src/ngcc/test/helpers/utils.ts | 15 ++- .../test/rendering/esm2015_renderer_spec.ts | 7 +- .../ngcc/test/rendering/esm5_renderer_spec.ts | 7 +- .../src/ngcc/test/rendering/renderer_spec.ts | 7 +- .../partial_evaluator/test/evaluator_spec.ts | 124 +++++++----------- .../src/ngtsc/testing/in_memory_typescript.ts | 19 ++- 10 files changed, 127 insertions(+), 139 deletions(-) diff --git a/packages/compiler-cli/src/ngcc/src/analysis/decoration_analyzer.ts b/packages/compiler-cli/src/ngcc/src/analysis/decoration_analyzer.ts index 656a3400e9..c24f698fc9 100644 --- a/packages/compiler-cli/src/ngcc/src/analysis/decoration_analyzer.ts +++ b/packages/compiler-cli/src/ngcc/src/analysis/decoration_analyzer.ts @@ -59,34 +59,38 @@ export class FileResourceLoader implements ResourceLoader { */ export class DecorationAnalyzer { resourceLoader = new FileResourceLoader(); - scopeRegistry = new SelectorScopeRegistry(this.typeChecker, this.host); - evaluator = new PartialEvaluator(this.host, this.typeChecker); + scopeRegistry = new SelectorScopeRegistry(this.typeChecker, this.reflectionHost); + evaluator = new PartialEvaluator(this.reflectionHost, this.typeChecker); handlers: DecoratorHandler[] = [ - new BaseDefDecoratorHandler(this.host, this.evaluator), + new BaseDefDecoratorHandler(this.reflectionHost, this.evaluator), new ComponentDecoratorHandler( - this.host, this.evaluator, this.scopeRegistry, this.isCore, this.resourceLoader, + this.reflectionHost, this.evaluator, this.scopeRegistry, this.isCore, this.resourceLoader, this.rootDirs, /* defaultPreserveWhitespaces */ false, /* i18nUseExternalIds */ true), - new DirectiveDecoratorHandler(this.host, this.evaluator, this.scopeRegistry, this.isCore), - new InjectableDecoratorHandler(this.host, this.isCore), + new DirectiveDecoratorHandler( + this.reflectionHost, this.evaluator, this.scopeRegistry, this.isCore), + new InjectableDecoratorHandler(this.reflectionHost, this.isCore), new NgModuleDecoratorHandler( - this.host, this.evaluator, this.scopeRegistry, this.referencesRegistry, this.isCore), - new PipeDecoratorHandler(this.host, this.evaluator, this.scopeRegistry, this.isCore), + this.reflectionHost, this.evaluator, this.scopeRegistry, this.referencesRegistry, + this.isCore), + new PipeDecoratorHandler(this.reflectionHost, this.evaluator, this.scopeRegistry, this.isCore), ]; constructor( - private typeChecker: ts.TypeChecker, private host: NgccReflectionHost, - private referencesRegistry: ReferencesRegistry, private rootDirs: string[], - private isCore: boolean) {} + private program: ts.Program, private options: ts.CompilerOptions, + private host: ts.CompilerHost, private typeChecker: ts.TypeChecker, + private reflectionHost: NgccReflectionHost, private referencesRegistry: ReferencesRegistry, + private rootDirs: string[], private isCore: boolean) {} /** * Analyze a program to find all the decorated files should be transformed. - * @param program The program whose files should be analysed. + * * @returns a map of the source files to the analysis for those files. */ - analyzeProgram(program: ts.Program): DecorationAnalyses { + analyzeProgram(): DecorationAnalyses { const decorationAnalyses = new DecorationAnalyses(); - const analysedFiles = - program.getSourceFiles().map(sourceFile => this.analyzeFile(sourceFile)).filter(isDefined); + const analysedFiles = this.program.getSourceFiles() + .map(sourceFile => this.analyzeFile(sourceFile)) + .filter(isDefined); const compiledFiles = analysedFiles.map(analysedFile => this.compileFile(analysedFile)); compiledFiles.forEach( compiledFile => decorationAnalyses.set(compiledFile.sourceFile, compiledFile)); @@ -94,7 +98,7 @@ export class DecorationAnalyzer { } protected analyzeFile(sourceFile: ts.SourceFile): AnalyzedFile|undefined { - const decoratedClasses = this.host.findDecoratedClasses(sourceFile); + const decoratedClasses = this.reflectionHost.findDecoratedClasses(sourceFile); return decoratedClasses.length ? { sourceFile, analyzedClasses: decoratedClasses.map(clazz => this.analyzeClass(clazz)).filter(isDefined) diff --git a/packages/compiler-cli/src/ngcc/src/packages/bundle_program.ts b/packages/compiler-cli/src/ngcc/src/packages/bundle_program.ts index 9bbcd8abb8..5c8ba5eeb3 100644 --- a/packages/compiler-cli/src/ngcc/src/packages/bundle_program.ts +++ b/packages/compiler-cli/src/ngcc/src/packages/bundle_program.ts @@ -19,6 +19,8 @@ import * as ts from 'typescript'; */ export interface BundleProgram { program: ts.Program; + options: ts.CompilerOptions; + host: ts.CompilerHost; path: string; file: ts.SourceFile; r3SymbolsPath: string|null; @@ -37,7 +39,7 @@ export function makeBundleProgram( const file = program.getSourceFile(path) !; const r3SymbolsFile = r3SymbolsPath && program.getSourceFile(r3SymbolsPath) || null; - return {program, path, file, r3SymbolsPath, r3SymbolsFile}; + return {program, options, host, path, file, r3SymbolsPath, r3SymbolsFile}; } /** diff --git a/packages/compiler-cli/src/ngcc/src/packages/transformer.ts b/packages/compiler-cli/src/ngcc/src/packages/transformer.ts index e2bf4a57a8..fb1ff94ebc 100644 --- a/packages/compiler-cli/src/ngcc/src/packages/transformer.ts +++ b/packages/compiler-cli/src/ngcc/src/packages/transformer.ts @@ -110,8 +110,9 @@ export class Transformer { const switchMarkerAnalyses = switchMarkerAnalyzer.analyzeProgram(bundle.src.program); const decorationAnalyzer = new DecorationAnalyzer( - typeChecker, reflectionHost, referencesRegistry, bundle.rootDirs, isCore); - const decorationAnalyses = decorationAnalyzer.analyzeProgram(bundle.src.program); + bundle.src.program, bundle.src.options, bundle.src.host, typeChecker, reflectionHost, + referencesRegistry, bundle.rootDirs, isCore); + const decorationAnalyses = decorationAnalyzer.analyzeProgram(); const moduleWithProvidersAnalyzer = bundle.dts && new ModuleWithProvidersAnalyzer(reflectionHost, referencesRegistry); diff --git a/packages/compiler-cli/src/ngcc/test/analysis/decoration_analyzer_spec.ts b/packages/compiler-cli/src/ngcc/test/analysis/decoration_analyzer_spec.ts index 56ec22c88c..e4a145825f 100644 --- a/packages/compiler-cli/src/ngcc/test/analysis/decoration_analyzer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/analysis/decoration_analyzer_spec.ts @@ -12,8 +12,7 @@ import {DecoratorHandler} from '../../../ngtsc/transform'; import {DecorationAnalyses, DecorationAnalyzer} from '../../src/analysis/decoration_analyzer'; import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry'; import {Esm2015ReflectionHost} from '../../src/host/esm2015_host'; - -import {makeTestProgram} from '../helpers/utils'; +import {makeTestBundleProgram} from '../helpers/utils'; const TEST_PROGRAM = { name: 'test.js', @@ -84,14 +83,17 @@ describe('DecorationAnalyzer', () => { let result: DecorationAnalyses; beforeEach(() => { - program = makeTestProgram(TEST_PROGRAM); - const host = new Esm2015ReflectionHost(false, program.getTypeChecker()); - const referencesRegistry = new NgccReferencesRegistry(host); - const analyzer = - new DecorationAnalyzer(program.getTypeChecker(), host, referencesRegistry, [''], false); + const {options, host, ...bundle} = makeTestBundleProgram([TEST_PROGRAM]); + program = bundle.program; + + const reflectionHost = new Esm2015ReflectionHost(false, program.getTypeChecker()); + const referencesRegistry = new NgccReferencesRegistry(reflectionHost); + const analyzer = new DecorationAnalyzer( + program, options, host, program.getTypeChecker(), reflectionHost, referencesRegistry, + [''], false); testHandler = createTestHandler(); analyzer.handlers = [testHandler]; - result = analyzer.analyzeProgram(program); + result = analyzer.analyzeProgram(); }); it('should return an object containing a reference to the original source file', () => { @@ -127,14 +129,15 @@ describe('DecorationAnalyzer', () => { // is not yet solved. it('should analyze an internally imported component, which is not publicly exported from the entry-point', () => { - const program = makeTestProgram(...INTERNAL_COMPONENT_PROGRAM); - const host = new Esm2015ReflectionHost(false, program.getTypeChecker()); - const referencesRegistry = new NgccReferencesRegistry(host); + const {program, options, host} = makeTestBundleProgram(INTERNAL_COMPONENT_PROGRAM); + const reflectionHost = new Esm2015ReflectionHost(false, program.getTypeChecker()); + const referencesRegistry = new NgccReferencesRegistry(reflectionHost); const analyzer = new DecorationAnalyzer( - program.getTypeChecker(), host, referencesRegistry, [''], false); + program, options, host, program.getTypeChecker(), reflectionHost, referencesRegistry, + [''], false); const testHandler = createTestHandler(); analyzer.handlers = [testHandler]; - const result = analyzer.analyzeProgram(program); + const result = analyzer.analyzeProgram(); const file = program.getSourceFile('component.js') !; const analysis = result.get(file) !; expect(analysis).toBeDefined(); @@ -144,14 +147,15 @@ describe('DecorationAnalyzer', () => { }); it('should analyze an internally defined component, which is not exported at all', () => { - const program = makeTestProgram(...INTERNAL_COMPONENT_PROGRAM); - const host = new Esm2015ReflectionHost(false, program.getTypeChecker()); - const referencesRegistry = new NgccReferencesRegistry(host); - const analyzer = - new DecorationAnalyzer(program.getTypeChecker(), host, referencesRegistry, [''], false); + const {program, options, host} = makeTestBundleProgram(INTERNAL_COMPONENT_PROGRAM); + const reflectionHost = new Esm2015ReflectionHost(false, program.getTypeChecker()); + const referencesRegistry = new NgccReferencesRegistry(reflectionHost); + const analyzer = new DecorationAnalyzer( + program, options, host, program.getTypeChecker(), reflectionHost, referencesRegistry, + [''], false); const testHandler = createTestHandler(); analyzer.handlers = [testHandler]; - const result = analyzer.analyzeProgram(program); + const result = analyzer.analyzeProgram(); const file = program.getSourceFile('entrypoint.js') !; const analysis = result.get(file) !; expect(analysis).toBeDefined(); diff --git a/packages/compiler-cli/src/ngcc/test/helpers/utils.ts b/packages/compiler-cli/src/ngcc/test/helpers/utils.ts index 3b5656ffab..68e3f5c9b0 100644 --- a/packages/compiler-cli/src/ngcc/test/helpers/utils.ts +++ b/packages/compiler-cli/src/ngcc/test/helpers/utils.ts @@ -35,20 +35,27 @@ export function makeTestEntryPointBundle( * @param files The source files of the bundle program. */ export function makeTestBundleProgram(files: {name: string, contents: string}[]): BundleProgram { - const program = makeTestProgram(...files); + const {program, options, host} = makeTestProgramInternal(...files); const path = files[0].name; const file = program.getSourceFile(path) !; const r3SymbolsInfo = files.find(file => file.name.indexOf('r3_symbols') !== -1) || null; const r3SymbolsPath = r3SymbolsInfo && r3SymbolsInfo.name; const r3SymbolsFile = r3SymbolsPath && program.getSourceFile(r3SymbolsPath) || null; - return {program, path, file, r3SymbolsPath, r3SymbolsFile}; + return {program, options, host, path, file, r3SymbolsPath, r3SymbolsFile}; } +function makeTestProgramInternal( + ...files: {name: string, contents: string, isRoot?: boolean | undefined}[]): { + program: ts.Program, + host: ts.CompilerHost, + options: ts.CompilerOptions, +} { + return makeProgram([getFakeCore(), getFakeTslib(), ...files], {allowJs: true, checkJs: false}); +} export function makeTestProgram( ...files: {name: string, contents: string, isRoot?: boolean | undefined}[]): ts.Program { - return makeProgram([getFakeCore(), getFakeTslib(), ...files], {allowJs: true, checkJs: false}) - .program; + return makeTestProgramInternal(...files).program; } // TODO: unify this with the //packages/compiler-cli/test/ngtsc/fake_core package diff --git a/packages/compiler-cli/src/ngcc/test/rendering/esm2015_renderer_spec.ts b/packages/compiler-cli/src/ngcc/test/rendering/esm2015_renderer_spec.ts index 8e91618073..bce94403d7 100644 --- a/packages/compiler-cli/src/ngcc/test/rendering/esm2015_renderer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/rendering/esm2015_renderer_spec.ts @@ -21,9 +21,10 @@ function setup(file: {name: string, contents: string}) { const typeChecker = bundle.src.program.getTypeChecker(); const host = new Esm2015ReflectionHost(false, typeChecker); const referencesRegistry = new NgccReferencesRegistry(host); - const decorationAnalyses = - new DecorationAnalyzer(typeChecker, host, referencesRegistry, [''], false) - .analyzeProgram(bundle.src.program); + const decorationAnalyses = new DecorationAnalyzer( + bundle.src.program, bundle.src.options, bundle.src.host, + typeChecker, host, referencesRegistry, [''], false) + .analyzeProgram(); const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(bundle.src.program); const renderer = new EsmRenderer(host, false, bundle, dir, dir); return { diff --git a/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts b/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts index 2642653f62..ccc4299f3d 100644 --- a/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts @@ -21,9 +21,10 @@ function setup(file: {name: string, contents: string}) { const typeChecker = bundle.src.program.getTypeChecker(); const host = new Esm5ReflectionHost(false, typeChecker); const referencesRegistry = new NgccReferencesRegistry(host); - const decorationAnalyses = - new DecorationAnalyzer(typeChecker, host, referencesRegistry, [''], false) - .analyzeProgram(bundle.src.program); + const decorationAnalyses = new DecorationAnalyzer( + bundle.src.program, bundle.src.options, bundle.src.host, + typeChecker, host, referencesRegistry, [''], false) + .analyzeProgram(); const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(bundle.src.program); const renderer = new Esm5Renderer(host, false, bundle, dir, dir); return { diff --git a/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts b/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts index ca4151e524..0c582c52f1 100644 --- a/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts @@ -54,9 +54,10 @@ function createTestRenderer( const typeChecker = bundle.src.program.getTypeChecker(); const host = new Esm2015ReflectionHost(isCore, typeChecker, bundle.dts); const referencesRegistry = new NgccReferencesRegistry(host); - const decorationAnalyses = - new DecorationAnalyzer(typeChecker, host, referencesRegistry, bundle.rootDirs, isCore) - .analyzeProgram(bundle.src.program); + const decorationAnalyses = new DecorationAnalyzer( + bundle.src.program, bundle.src.options, bundle.src.host, + typeChecker, host, referencesRegistry, bundle.rootDirs, isCore) + .analyzeProgram(); const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(bundle.src.program); const moduleWithProvidersAnalyses = new ModuleWithProvidersAnalyzer(host, referencesRegistry).analyzeProgram(bundle.src.program); 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 6f6f82cf2f..0e380e8cef 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 @@ -20,47 +20,50 @@ function makeSimpleProgram(contents: string): ts.Program { } function makeExpression( - code: string, expr: string): {expression: ts.Expression, checker: ts.TypeChecker} { - const {program} = - makeProgram([{name: 'entry.ts', contents: `${code}; const target$ = ${expr};`}]); + code: string, expr: string, supportingFiles: {name: string, contents: string}[] = []): { + expression: ts.Expression, + host: ts.CompilerHost, + checker: ts.TypeChecker, + program: ts.Program, + options: ts.CompilerOptions +} { + const {program, options, host} = makeProgram( + [{name: 'entry.ts', contents: `${code}; const target$ = ${expr};`}, ...supportingFiles]); const checker = program.getTypeChecker(); const decl = getDeclaration(program, 'entry.ts', 'target$', ts.isVariableDeclaration); return { expression: decl.initializer !, + host, + options, checker, + program, }; } -function evaluate(code: string, expr: string): T { - const {expression, checker} = makeExpression(code, expr); - const host = new TypeScriptReflectionHost(checker); - const evaluator = new PartialEvaluator(host, checker); +function evaluate( + code: string, expr: string, supportingFiles: {name: string, contents: string}[] = []): T { + const {expression, checker} = makeExpression(code, expr, supportingFiles); + const reflectionHost = new TypeScriptReflectionHost(checker); + const evaluator = new PartialEvaluator(reflectionHost, checker); return evaluator.evaluate(expression) as T; } describe('ngtsc metadata', () => { it('reads a file correctly', () => { - const {program} = makeProgram([ - { - name: 'entry.ts', - contents: ` - import {Y} from './other'; - const A = Y; - export const X = A; - ` - }, - { - name: 'other.ts', - contents: ` + const value = evaluate( + ` + import {Y} from './other'; + const A = Y; + `, + 'A', [ + { + name: 'other.ts', + contents: ` export const Y = 'test'; ` - } - ]); - const decl = getDeclaration(program, 'entry.ts', 'X', ts.isVariableDeclaration); - const host = new TypeScriptReflectionHost(program.getTypeChecker()); - const evaluator = new PartialEvaluator(host, program.getTypeChecker()); + }, + ]); - const value = evaluator.evaluate(decl.initializer !); expect(value).toEqual('test'); }); @@ -143,10 +146,10 @@ describe('ngtsc metadata', () => { }, ]); const checker = program.getTypeChecker(); - const host = new TypeScriptReflectionHost(checker); + const reflectionHost = new TypeScriptReflectionHost(checker); const result = getDeclaration(program, 'entry.ts', 'target$', ts.isVariableDeclaration); const expr = result.initializer !; - const evaluator = new PartialEvaluator(host, checker); + const evaluator = new PartialEvaluator(reflectionHost, checker); const resolved = evaluator.evaluate(expr); if (!(resolved instanceof Reference)) { return fail('Expected expression to resolve to a reference'); @@ -175,10 +178,10 @@ describe('ngtsc metadata', () => { }, ]); const checker = program.getTypeChecker(); - const host = new TypeScriptReflectionHost(checker); + const reflectionHost = new TypeScriptReflectionHost(checker); const result = getDeclaration(program, 'entry.ts', 'target$', ts.isVariableDeclaration); const expr = result.initializer !; - const evaluator = new PartialEvaluator(host, checker); + const evaluator = new PartialEvaluator(reflectionHost, checker); const resolved = evaluator.evaluate(expr); if (!(resolved instanceof AbsoluteReference)) { return fail('Expected expression to resolve to an absolute reference'); @@ -197,60 +200,31 @@ describe('ngtsc metadata', () => { }); it('reads values from default exports', () => { - const {program} = makeProgram([ - {name: 'second.ts', contents: 'export default {property: "test"}'}, - { - name: 'entry.ts', - contents: ` - import mod from './second'; - const target$ = mod.property; - ` - }, - ]); - const checker = program.getTypeChecker(); - const host = new TypeScriptReflectionHost(checker); - const result = getDeclaration(program, 'entry.ts', 'target$', ts.isVariableDeclaration); - const expr = result.initializer !; - const evaluator = new PartialEvaluator(host, checker); - expect(evaluator.evaluate(expr)).toEqual('test'); + const value = evaluate( + ` + import mod from './second'; + `, + 'mod.property', [ + {name: 'second.ts', contents: 'export default {property: "test"}'}, + ]); + expect(value).toEqual('test'); }); it('reads values from named exports', () => { - const {program} = makeProgram([ + const value = evaluate(`import * as mod from './second';`, 'mod.a.property', [ {name: 'second.ts', contents: 'export const a = {property: "test"};'}, - { - name: 'entry.ts', - contents: ` - import * as mod from './second'; - const target$ = mod.a.property; - ` - }, ]); - const checker = program.getTypeChecker(); - const host = new TypeScriptReflectionHost(checker); - const result = getDeclaration(program, 'entry.ts', 'target$', ts.isVariableDeclaration); - const expr = result.initializer !; - const evaluator = new PartialEvaluator(host, checker); - expect(evaluator.evaluate(expr)).toEqual('test'); + expect(value).toEqual('test'); }); it('chain of re-exports works', () => { - const {program} = makeProgram([ + const value = evaluate(`import * as mod from './direct-reexport';`, 'mod.value.property', [ {name: 'const.ts', contents: 'export const value = {property: "test"};'}, {name: 'def.ts', contents: `import {value} from './const'; export default value;`}, {name: 'indirect-reexport.ts', contents: `import value from './def'; export {value};`}, {name: 'direct-reexport.ts', contents: `export {value} from './indirect-reexport';`}, - { - name: 'entry.ts', - contents: `import * as mod from './direct-reexport'; const target$ = mod.value.property;` - }, ]); - const checker = program.getTypeChecker(); - const host = new TypeScriptReflectionHost(checker); - const result = getDeclaration(program, 'entry.ts', 'target$', ts.isVariableDeclaration); - const expr = result.initializer !; - const evaluator = new PartialEvaluator(host, checker); - expect(evaluator.evaluate(expr)).toEqual('test'); + expect(value).toEqual('test'); }); it('map spread works', () => { @@ -299,15 +273,9 @@ describe('ngtsc metadata', () => { }); it('variable declaration resolution works', () => { - const {program} = makeProgram([ + const value = evaluate(`import {value} from './decl';`, 'value', [ {name: 'decl.d.ts', contents: 'export declare let value: number;'}, - {name: 'entry.ts', contents: `import {value} from './decl'; const target$ = value;`}, ]); - const checker = program.getTypeChecker(); - const host = new TypeScriptReflectionHost(checker); - const result = getDeclaration(program, 'entry.ts', 'target$', ts.isVariableDeclaration); - const evaluator = new PartialEvaluator(host, checker); - const res = evaluator.evaluate(result.initializer !); - expect(res instanceof Reference).toBe(true); + expect(value instanceof Reference).toBe(true); }); }); diff --git a/packages/compiler-cli/src/ngtsc/testing/in_memory_typescript.ts b/packages/compiler-cli/src/ngtsc/testing/in_memory_typescript.ts index 36a5b90b0d..9bbdf1f2c2 100644 --- a/packages/compiler-cli/src/ngtsc/testing/in_memory_typescript.ts +++ b/packages/compiler-cli/src/ngtsc/testing/in_memory_typescript.ts @@ -13,19 +13,18 @@ import * as ts from 'typescript'; export function makeProgram( files: {name: string, contents: string, isRoot?: boolean}[], options?: ts.CompilerOptions, - host: ts.CompilerHost = new InMemoryHost(), - checkForErrors: boolean = true): {program: ts.Program, host: ts.CompilerHost} { + host: ts.CompilerHost = new InMemoryHost(), checkForErrors: boolean = true): + {program: ts.Program, host: ts.CompilerHost, options: ts.CompilerOptions} { files.forEach(file => host.writeFile(file.name, file.contents, false, undefined, [])); const rootNames = files.filter(file => file.isRoot !== false).map(file => host.getCanonicalFileName(file.name)); - const program = ts.createProgram( - rootNames, { - noLib: true, - experimentalDecorators: true, - moduleResolution: ts.ModuleResolutionKind.NodeJs, ...options - }, - host); + const compilerOptions = { + noLib: true, + experimentalDecorators: true, + moduleResolution: ts.ModuleResolutionKind.NodeJs, ...options + }; + const program = ts.createProgram(rootNames, compilerOptions, host); if (checkForErrors) { const diags = [...program.getSyntacticDiagnostics(), ...program.getSemanticDiagnostics()]; if (diags.length > 0) { @@ -41,7 +40,7 @@ export function makeProgram( throw new Error(`Typescript diagnostics failed! ${errors.join(', ')}`); } } - return {program, host}; + return {program, host, options: compilerOptions}; } export class InMemoryHost implements ts.CompilerHost {