From 2001f6e58aee3ab61d373da64dab308bb1f63d16 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Mon, 25 Apr 2016 21:29:06 -0700 Subject: [PATCH] fix(static reflector): Use only relative/absolute paths as module IDs. The filename contains the module name as resolved by users. Fixes #8225 --- .../angular2/src/compiler/static_reflector.ts | 70 +++-------- .../test/compiler/static_reflector_spec.ts | 118 +++++++++++------- tools/broccoli/broccoli-typescript.ts | 11 +- tools/metadata/src/collector.ts | 56 ++------- tools/metadata/src/evaluator.ts | 9 +- tools/metadata/src/schema.ts | 34 +++-- tools/metadata/test/evaluator.spec.ts | 2 +- 7 files changed, 117 insertions(+), 183 deletions(-) diff --git a/modules/angular2/src/compiler/static_reflector.ts b/modules/angular2/src/compiler/static_reflector.ts index 413f2a4f7d25..7092ef120fcc 100644 --- a/modules/angular2/src/compiler/static_reflector.ts +++ b/modules/angular2/src/compiler/static_reflector.ts @@ -1,12 +1,8 @@ -import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection'; +import {StringMapWrapper} from 'angular2/src/facade/collection'; import { isArray, - isBlank, - isNumber, isPresent, isPrimitive, - isString, - Type } from 'angular2/src/facade/lang'; import { AttributeMetadata, @@ -35,13 +31,19 @@ import {ReflectorReader} from 'angular2/src/core/reflection/reflector_reader'; */ export interface StaticReflectorHost { /** - * Return a ModuleMetadata for the give module. + * Return a ModuleMetadata for the given module. * - * @param moduleId is a string identifier for a module in the form that would expected in a - * module import of an import statement. + * @param moduleId is a string identifier for a module as an absolute path. * @returns the metadata for the given module. */ getMetadataFor(moduleId: string): {[key: string]: any}; + + /** + * Resolve a module from an import statement form to an absolute path. + * @param moduleName the location imported from + * @param containingFile for relative imports, the path of the file containing the import + */ + resolveModule(moduleName: string, containingFile?: string): string; } /** @@ -68,10 +70,10 @@ export class StaticReflector implements ReflectorReader { importUri(typeOrFunc: any): string { return (typeOrFunc).moduleId; } /** - * getStatictype produces a Type whose metadata is known but whose implementation is not loaded. + * getStaticType produces a Type whose metadata is known but whose implementation is not loaded. * All types passed to the StaticResolver should be pseudo-types returned by this method. * - * @param moduleId the module identifier as would be passed to an import statement. + * @param moduleId the module identifier as an absolute path. * @param name the name of the type. */ public getStaticType(moduleId: string, name: string): StaticType { @@ -137,7 +139,7 @@ export class StaticReflector implements ReflectorReader { private conversionMap = new Map any>(); private initializeConversionMap(): any { - let core_metadata = 'angular2/src/core/metadata'; + let core_metadata = this.host.resolveModule('angular2/src/core/metadata'); let conversionMap = this.conversionMap; conversionMap.set(this.getStaticType(core_metadata, 'Directive'), (moduleContext, expression) => { @@ -272,7 +274,7 @@ export class StaticReflector implements ReflectorReader { if (isMetadataSymbolicCallExpression(expression)) { let target = expression['expression']; if (isMetadataSymbolicReferenceExpression(target)) { - let moduleId = this.normalizeModuleName(moduleContext, target['module']); + let moduleId = this.host.resolveModule(target['module'], moduleContext); return this.getStaticType(moduleId, target['name']); } } @@ -417,7 +419,7 @@ export class StaticReflector implements ReflectorReader { return null; case "reference": let referenceModuleName = - _this.normalizeModuleName(moduleContext, expression['module']); + _this.host.resolveModule(expression['module'], moduleContext); let referenceModule = _this.getModuleMetadata(referenceModuleName); let referenceValue = referenceModule['metadata'][expression['name']]; if (isClassMetadata(referenceValue)) { @@ -440,6 +442,9 @@ export class StaticReflector implements ReflectorReader { return simplify(value); } + /** + * @param module an absolute path to a module file. + */ public getModuleMetadata(module: string): {[key: string]: any} { let moduleMetadata = this.metadataCache.get(module); if (!isPresent(moduleMetadata)) { @@ -460,13 +465,6 @@ export class StaticReflector implements ReflectorReader { } return result; } - - private normalizeModuleName(from: string, to: string): string { - if (to.startsWith('.')) { - return pathTo(from, to); - } - return to; - } } function isMetadataSymbolicCallExpression(expression: any): boolean { @@ -481,35 +479,3 @@ function isMetadataSymbolicReferenceExpression(expression: any): boolean { function isClassMetadata(expression: any): boolean { return !isPrimitive(expression) && !isArray(expression) && expression['__symbolic'] == 'class'; } - -function splitPath(path: string): string[] { - return path.split(/\/|\\/g); -} - -function resolvePath(pathParts: string[]): string { - let result = []; - ListWrapper.forEachWithIndex(pathParts, (part, index) => { - switch (part) { - case '': - case '.': - if (index > 0) return; - break; - case '..': - if (index > 0 && result.length != 0) result.pop(); - return; - } - result.push(part); - }); - return result.join('/'); -} - -function pathTo(from: string, to: string): string { - let result = to; - if (to.startsWith('.')) { - let fromParts = splitPath(from); - fromParts.pop(); // remove the file name. - let toParts = splitPath(to); - result = resolvePath(fromParts.concat(toParts)); - } - return result; -} diff --git a/modules/angular2/test/compiler/static_reflector_spec.ts b/modules/angular2/test/compiler/static_reflector_spec.ts index e9ce0868f98f..db4ebf939df2 100644 --- a/modules/angular2/test/compiler/static_reflector_spec.ts +++ b/modules/angular2/test/compiler/static_reflector_spec.ts @@ -1,27 +1,20 @@ import { - ddescribe, describe, - xdescribe, it, - iit, - xit, expect, - beforeEach, - afterEach, - AsyncTestCompleter, - inject, - beforeEachProviders } from 'angular2/testing_internal'; +import {ListWrapper} from 'angular2/src/facade/collection'; import {StaticReflector, StaticReflectorHost} from 'angular2/src/compiler/static_reflector'; export function main() { - describe('StaticRefelector', () => { + describe('StaticReflector', () => { it('should get annotations for NgFor', () => { let host = new MockReflectorHost(); let reflector = new StaticReflector(host); - let NgFor = reflector.getStaticType('angular2/src/common/directives/ng_for', 'NgFor'); + let NgFor = reflector.getStaticType( + host.resolveModule('angular2/src/common/directives/ng_for'), 'NgFor'); let annotations = reflector.annotations(NgFor); expect(annotations.length).toEqual(1); let annotation = annotations[0]; @@ -33,15 +26,18 @@ export function main() { let host = new MockReflectorHost(); let reflector = new StaticReflector(host); - let NgFor = reflector.getStaticType('angular2/src/common/directives/ng_for', 'NgFor'); - let ViewContainerRef = reflector.getStaticType('angular2/src/core/linker/view_container_ref', - 'ViewContainerRef'); - let TemplateRef = - reflector.getStaticType('angular2/src/core/linker/template_ref', 'TemplateRef'); + let NgFor = reflector.getStaticType( + host.resolveModule('angular2/src/common/directives/ng_for'), 'NgFor'); + let ViewContainerRef = reflector.getStaticType( + host.resolveModule('angular2/src/core/linker/view_container_ref'), 'ViewContainerRef'); + let TemplateRef = reflector.getStaticType( + host.resolveModule('angular2/src/core/linker/template_ref'), 'TemplateRef'); let IterableDiffers = reflector.getStaticType( - 'angular2/src/core/change_detection/differs/iterable_differs', 'IterableDiffers'); + host.resolveModule('angular2/src/core/change_detection/differs/iterable_differs'), + 'IterableDiffers'); let ChangeDetectorRef = reflector.getStaticType( - 'angular2/src/core/change_detection/change_detector_ref', 'ChangeDetectorRef'); + host.resolveModule('angular2/src/core/change_detection/change_detector_ref'), + 'ChangeDetectorRef'); let parameters = reflector.parameters(NgFor); expect(parameters) @@ -53,7 +49,7 @@ export function main() { let reflector = new StaticReflector(host); let HeroDetailComponent = - reflector.getStaticType('./app/hero-detail.component', 'HeroDetailComponent'); + reflector.getStaticType('/src/app/hero-detail.component.ts', 'HeroDetailComponent'); let annotations = reflector.annotations(HeroDetailComponent); expect(annotations.length).toEqual(1); let annotation = annotations[0]; @@ -64,7 +60,7 @@ export function main() { let host = new MockReflectorHost(); let reflector = new StaticReflector(host); - let UnknownClass = reflector.getStaticType('./app/app.component', 'UnknownClass'); + let UnknownClass = reflector.getStaticType('/src/app/app.component.ts', 'UnknownClass'); let annotations = reflector.annotations(UnknownClass); expect(annotations).toEqual([]); }); @@ -74,7 +70,7 @@ export function main() { let reflector = new StaticReflector(host); let HeroDetailComponent = - reflector.getStaticType('./app/hero-detail.component', 'HeroDetailComponent'); + reflector.getStaticType('/src/app/hero-detail.component.ts', 'HeroDetailComponent'); let props = reflector.propMetadata(HeroDetailComponent); expect(props['hero']).toBeTruthy(); }); @@ -83,7 +79,7 @@ export function main() { let host = new MockReflectorHost(); let reflector = new StaticReflector(host); - let UnknownClass = reflector.getStaticType('./app/app.component', 'UnknownClass'); + let UnknownClass = reflector.getStaticType('/src/app/app.component.ts', 'UnknownClass'); let properties = reflector.propMetadata(UnknownClass); expect(properties).toEqual({}); }); @@ -92,7 +88,7 @@ export function main() { let host = new MockReflectorHost(); let reflector = new StaticReflector(host); - let UnknownClass = reflector.getStaticType('./app/app.component', 'UnknownClass'); + let UnknownClass = reflector.getStaticType('/src/app/app.component.ts', 'UnknownClass'); let parameters = reflector.parameters(UnknownClass); expect(parameters).toEqual([]); }); @@ -301,7 +297,7 @@ export function main() { expect(reflector.simplify('', ({ __symbolic: 'pre', operator: '!', operand: false}))).toBe(!false); }); - it('should simpify an array index', () => { + it('should simplify an array index', () => { let host = new MockReflectorHost(); let reflector = new StaticReflector(host); @@ -320,20 +316,56 @@ export function main() { let host = new MockReflectorHost(); let reflector = new StaticReflector(host); - expect( - reflector.simplify('./cases', ({__symbolic: "reference", module: "./extern", name: "s"}))) + expect(reflector.simplify('/src/cases', + ({__symbolic: "reference", module: "./extern", name: "s"}))) .toEqual("s"); }); }); } class MockReflectorHost implements StaticReflectorHost { + resolveModule(moduleName: string, containingFile?: string): string { + function splitPath(path: string): string[] { return path.split(/\/|\\/g); } + + function resolvePath(pathParts: string[]): string { + let result = []; + ListWrapper.forEachWithIndex(pathParts, (part, index) => { + switch (part) { + case '': + case '.': + if (index > 0) return; + break; + case '..': + if (index > 0 && result.length != 0) result.pop(); + return; + } + result.push(part); + }); + return result.join('/'); + } + + function pathTo(from: string, to: string): string { + let result = to; + if (to.startsWith('.')) { + let fromParts = splitPath(from); + fromParts.pop(); // remove the file name. + let toParts = splitPath(to); + result = resolvePath(fromParts.concat(toParts)); + } + return result; + } + + if (moduleName.indexOf('.') === 0) { + return pathTo(containingFile, moduleName) + '.d.ts'; + } + return '/tmp/' + moduleName + '.d.ts'; + } + getMetadataFor(moduleId: string): any { return { - 'angular2/src/common/directives/ng_for': + '/tmp/angular2/src/common/directives/ng_for.d.ts': { "__symbolic": "module", - "module": "./ng_for", "metadata": { "NgFor": @@ -393,27 +425,17 @@ class MockReflectorHost implements StaticReflectorHost { } } }, - 'angular2/src/core/linker/view_container_ref': - { - "module": "./view_container_ref", - "metadata": {"ViewContainerRef": {"__symbolic": "class"}} - }, - 'angular2/src/core/linker/template_ref': + '/tmp/angular2/src/core/linker/view_container_ref.d.ts': + {"metadata": {"ViewContainerRef": {"__symbolic": "class"}}}, + '/tmp/angular2/src/core/linker/template_ref.d.ts': {"module": "./template_ref", "metadata": {"TemplateRef": {"__symbolic": "class"}}}, - 'angular2/src/core/change_detection/differs/iterable_differs': - { - "module": "./iterable_differs", - "metadata": {"IterableDiffers": {"__symbolic": "class"}} - }, - 'angular2/src/core/change_detection/change_detector_ref': - { - "module": "./change_detector_ref", - "metadata": {"ChangeDetectorRef": {"__symbolic": "class"}} - }, - './app/hero-detail.component': + '/tmp/angular2/src/core/change_detection/differs/iterable_differs.d.ts': + {"metadata": {"IterableDiffers": {"__symbolic": "class"}}}, + '/tmp/angular2/src/core/change_detection/change_detector_ref.d.ts': + {"metadata": {"ChangeDetectorRef": {"__symbolic": "class"}}}, + '/src/app/hero-detail.component.ts': { "__symbolic": "module", - "module": "./hero-detail.component", "metadata": { "HeroDetailComponent": @@ -459,8 +481,8 @@ class MockReflectorHost implements StaticReflectorHost { } } }, - './extern': { - "__symbolic": "module", module: './extern', metadata: { s: "s" } + '/src/extern.d.ts': { + "__symbolic": "module", metadata: { s: "s" } } } [moduleId]; diff --git a/tools/broccoli/broccoli-typescript.ts b/tools/broccoli/broccoli-typescript.ts index 9d4ff9f4de5e..637b519a0561 100644 --- a/tools/broccoli/broccoli-typescript.ts +++ b/tools/broccoli/broccoli-typescript.ts @@ -88,16 +88,7 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin { this.tsServiceHost = new CustomLanguageServiceHost(this.tsOpts, this.rootFilePaths, this.fileRegistry, this.inputPath); this.tsService = ts.createLanguageService(this.tsServiceHost, ts.createDocumentRegistry()); - this.metadataCollector = new MetadataCollector({ - // Since our code isn't under a node_modules directory, we need to reverse the module - // resolution to get metadata rooted at 'angular2'. - // see https://github.com/angular/angular/issues/8144 - reverseModuleResolution(fileName: string) { - if (/\.tmp\/angular2/.test(fileName)) { - return fileName.substr(fileName.lastIndexOf('.tmp/angular2/') + 5).replace(/\.ts$/, ''); - } - } - }); + this.metadataCollector = new MetadataCollector(); } diff --git a/tools/metadata/src/collector.ts b/tools/metadata/src/collector.ts index 49a349a71577..aff47406d27e 100644 --- a/tools/metadata/src/collector.ts +++ b/tools/metadata/src/collector.ts @@ -1,4 +1,5 @@ import * as ts from 'typescript'; +import {relative} from 'path'; import {Evaluator} from './evaluator'; import {Symbols} from './symbols'; import { @@ -13,46 +14,13 @@ import { MethodMetadata } from './schema'; -import * as path from 'path'; - -const EXT_REGEX = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/; -const NODE_MODULES = '/node_modules/'; -const NODE_MODULES_PREFIX = 'node_modules/'; - -function pathTo(from: string, to: string): string { - var result = path.relative(path.dirname(from), to); - if (path.dirname(result) === '.') { - result = '.' + path.sep + result; - } - return result; -} - -export interface MetadataCollectorHost { - reverseModuleResolution: (moduleFileName: string) => string; -} - -const nodeModuleResolutionHost: MetadataCollectorHost = { - // Reverse moduleResolution=node for packages resolved in node_modules - reverseModuleResolution(fileName: string) { - // Remove the extension - const moduleFileName = fileName.replace(EXT_REGEX, ''); - // Check for node_modules - const nodeModulesIndex = moduleFileName.lastIndexOf(NODE_MODULES); - if (nodeModulesIndex >= 0) { - return moduleFileName.substr(nodeModulesIndex + NODE_MODULES.length); - } - if (moduleFileName.lastIndexOf(NODE_MODULES_PREFIX, NODE_MODULES_PREFIX.length) !== -1) { - return moduleFileName.substr(NODE_MODULES_PREFIX.length); - } - return null; - } -}; +const EXT = /(\.d)?\.ts$/; /** * Collect decorator metadata from a TypeScript module. */ export class MetadataCollector { - constructor(private host: MetadataCollectorHost = nodeModuleResolutionHost) {} + constructor() {} /** * Returns a JSON.stringify friendly form describing the decorators of the exported classes from @@ -60,17 +28,7 @@ export class MetadataCollector { */ public getMetadata(sourceFile: ts.SourceFile, typeChecker: ts.TypeChecker): ModuleMetadata { const locals = new Symbols(); - const moduleNameOf = (fileName: string) => { - // If the module was resolved with TS moduleResolution, reverse that mapping - const hostResolved = this.host.reverseModuleResolution(fileName); - if (hostResolved) { - return hostResolved; - } - // Construct a simplified path from the file to the module - return pathTo(sourceFile.fileName, fileName).replace(EXT_REGEX, ''); - }; - - const evaluator = new Evaluator(typeChecker, locals, moduleNameOf); + const evaluator = new Evaluator(typeChecker, locals, sourceFile.fileName); function objFromDecorator(decoratorNode: ts.Decorator): MetadataSymbolicExpression { return evaluator.evaluateNode(decoratorNode.expression); @@ -85,10 +43,10 @@ export class MetadataCollector { } if (symbol.declarations.length) { const declaration = symbol.declarations[0]; - const sourceFile = declaration.getSourceFile(); return { __symbolic: "reference", - module: moduleNameOf(sourceFile.fileName), + module: relative(sourceFile.fileName, declaration.getSourceFile().fileName) + .replace(EXT, ''), name: symbol.name }; } @@ -206,6 +164,6 @@ export class MetadataCollector { } } } - return metadata && {__symbolic: "module", module: moduleNameOf(sourceFile.fileName), metadata}; + return metadata && {__symbolic: "module", metadata}; } } diff --git a/tools/metadata/src/evaluator.ts b/tools/metadata/src/evaluator.ts index d654b9514082..ce356fee905d 100644 --- a/tools/metadata/src/evaluator.ts +++ b/tools/metadata/src/evaluator.ts @@ -1,9 +1,9 @@ import * as ts from 'typescript'; +import {relative} from 'path'; import {Symbols} from './symbols'; import { MetadataValue, - MetadataObject, MetadataSymbolicCallExpression, MetadataSymbolicReferenceExpression } from './schema'; @@ -58,13 +58,14 @@ function isDefined(obj: any): boolean { return obj !== undefined; } +const EXT = /(\.d)?\.ts$/; /** * Produce a symbolic representation of an expression folding values into their final value when * possible. */ export class Evaluator { constructor(private typeChecker: ts.TypeChecker, private symbols: Symbols, - private moduleNameOf: (fileName: string) => string) {} + private containingFile: string) {} // TODO: Determine if the first declaration is deterministic. private symbolFileName(symbol: ts.Symbol): string { @@ -86,7 +87,7 @@ export class Evaluator { private symbolReference(symbol: ts.Symbol): MetadataSymbolicReferenceExpression { if (symbol) { const name = symbol.name; - const module = this.moduleNameOf(this.symbolFileName(symbol)); + const module = relative(this.containingFile, this.symbolFileName(symbol)).replace(EXT, ''); return {__symbolic: "reference", name, module}; } } @@ -129,7 +130,7 @@ export class Evaluator { return everyNodeChild(node, child => { if (child.kind === ts.SyntaxKind.PropertyAssignment) { const propertyAssignment = child; - return this.isFoldableWorker(propertyAssignment.initializer, folding) + return this.isFoldableWorker(propertyAssignment.initializer, folding); } return false; }); diff --git a/tools/metadata/src/schema.ts b/tools/metadata/src/schema.ts index 746c4d6d98bb..f6bd27f113db 100644 --- a/tools/metadata/src/schema.ts +++ b/tools/metadata/src/schema.ts @@ -1,8 +1,5 @@ -// TODO: fix typings for __symbolic once angular moves to 1.8 - export interface ModuleMetadata { - __symbolic: string; // "module"; - module: string; + __symbolic: "module"; metadata: {[name: string]: (ClassMetadata | MetadataValue)}; } export function isModuleMetadata(value: any): value is ModuleMetadata { @@ -10,7 +7,7 @@ export function isModuleMetadata(value: any): value is ModuleMetadata { } export interface ClassMetadata { - __symbolic: string; // "class"; + __symbolic: "class"; decorators?: MetadataSymbolicExpression[]; members?: MetadataMap; } @@ -21,7 +18,7 @@ export function isClassMetadata(value: any): value is ClassMetadata { export interface MetadataMap { [name: string]: MemberMetadata[]; } export interface MemberMetadata { - __symbolic: string; // "constructor" | "method" | "property"; + __symbolic: "constructor" | "method" | "property"; decorators?: MetadataSymbolicExpression[]; } export function isMemberMetadata(value: any): value is MemberMetadata { @@ -37,7 +34,7 @@ export function isMemberMetadata(value: any): value is MemberMetadata { } export interface MethodMetadata extends MemberMetadata { - // __symbolic: "constructor" | "method"; + __symbolic: "constructor" | "method"; parameterDecorators?: MetadataSymbolicExpression[][]; } export function isMethodMetadata(value: any): value is MemberMetadata { @@ -45,7 +42,7 @@ export function isMethodMetadata(value: any): value is MemberMetadata { } export interface ConstructorMetadata extends MethodMetadata { - // __symbolic: "constructor"; + __symbolic: "constructor"; parameters?: MetadataSymbolicExpression[]; } export function isConstructorMetadata(value: any): value is ConstructorMetadata { @@ -60,7 +57,7 @@ export interface MetadataObject { [name: string]: MetadataValue; } export interface MetadataArray { [name: number]: MetadataValue; } export interface MetadataSymbolicExpression { - __symbolic: string; // "binary" | "call" | "index" | "pre" | "reference" | "select" + __symbolic: "binary" | "call" | "index" | "pre" | "reference" | "select" } export function isMetadataSymbolicExpression(value: any): value is MetadataSymbolicExpression { if (value) { @@ -78,10 +75,9 @@ export function isMetadataSymbolicExpression(value: any): value is MetadataSymbo } export interface MetadataSymbolicBinaryExpression extends MetadataSymbolicExpression { - // __symbolic: "binary"; - operator: string; // "&&" | "||" | "|" | "^" | "&" | "==" | "!=" | "===" | "!==" | "<" | ">" | - // "<=" | ">=" | "instanceof" | "in" | "as" | "<<" | ">>" | ">>>" | "+" | "-" | - // "*" | "/" | "%" | "**"; + __symbolic: "binary"; + operator: "&&" | "||" | "|" | "^" | "&" | "==" | "!=" | "===" | "!==" | "<" | ">" | "<=" | ">=" | + "instanceof" | "in" | "as" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "**"; left: MetadataValue; right: MetadataValue; } @@ -91,7 +87,7 @@ export function isMetadataSymbolicBinaryExpression( } export interface MetadataSymbolicIndexExpression extends MetadataSymbolicExpression { - // __symbolic: "index"; + __symbolic: "index"; expression: MetadataValue; index: MetadataValue; } @@ -101,7 +97,7 @@ export function isMetadataSymbolicIndexExpression( } export interface MetadataSymbolicCallExpression extends MetadataSymbolicExpression { - // __symbolic: "call"; + __symbolic: "call"; expression: MetadataValue; arguments?: MetadataValue[]; } @@ -111,8 +107,8 @@ export function isMetadataSymbolicCallExpression( } export interface MetadataSymbolicPrefixExpression extends MetadataSymbolicExpression { - // __symbolic: "pre"; - operator: string; // "+" | "-" | "~" | "!"; + __symbolic: "pre"; + operator: "+" | "-" | "~" | "!"; operand: MetadataValue; } export function isMetadataSymbolicPrefixExpression( @@ -121,7 +117,7 @@ export function isMetadataSymbolicPrefixExpression( } export interface MetadataSymbolicReferenceExpression extends MetadataSymbolicExpression { - // __symbolic: "reference"; + __symbolic: "reference"; name: string; module: string; } @@ -131,7 +127,7 @@ export function isMetadataSymbolicReferenceExpression( } export interface MetadataSymbolicSelectExpression extends MetadataSymbolicExpression { - // __symbolic: "select"; + __symbolic: "select"; expression: MetadataValue; name: string; } diff --git a/tools/metadata/test/evaluator.spec.ts b/tools/metadata/test/evaluator.spec.ts index f52a03982bfd..aaa77c3a4f95 100644 --- a/tools/metadata/test/evaluator.spec.ts +++ b/tools/metadata/test/evaluator.spec.ts @@ -18,7 +18,7 @@ describe('Evaluator', () => { program = service.getProgram(); typeChecker = program.getTypeChecker(); symbols = new Symbols(); - evaluator = new Evaluator(typeChecker, symbols, f => f); + evaluator = new Evaluator(typeChecker, symbols, '/tmp/source.ts'); }); it('should not have typescript errors in test data', () => {