Skip to content

Commit

Permalink
fix(metadata): emit metadata rooted at 'angular2'
Browse files Browse the repository at this point in the history
fixes #8144

closes #8147
  • Loading branch information
alexeagle authored and robertmesserle committed Apr 20, 2016
1 parent e69cb40 commit 9889c21
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 29 deletions.
11 changes: 10 additions & 1 deletion tools/broccoli/broccoli-typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,16 @@ 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();
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$/, '');
}
}
});
}


Expand Down
66 changes: 38 additions & 28 deletions tools/metadata/src/collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,37 +27,49 @@ function pathTo(from: string, to: string): string {
return result;
}

function moduleNameFromBaseName(moduleFileName: string, baseFileName: string): string {
// Remove the extension
moduleFileName = moduleFileName.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);
}

// Construct a simplified path from the file to the module
return pathTo(baseFileName, moduleFileName);
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;
}
};

/**
* Collect decorator metadata from a TypeScript module.
*/
export class MetadataCollector {
constructor() {}
constructor(private host: MetadataCollectorHost = nodeModuleResolutionHost) {}

/**
* Returns a JSON.stringify friendly form describing the decorators of the exported classes from
* the source file that is expected to correspond to a module.
*/
public getMetadata(sourceFile: ts.SourceFile, typeChecker: ts.TypeChecker): ModuleMetadata {
const locals = new Symbols();
const moduleNameOf = (fileName: string) =>
moduleNameFromBaseName(fileName, sourceFile.fileName);
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);

function objFromDecorator(decoratorNode: ts.Decorator): MetadataSymbolicExpression {
Expand Down Expand Up @@ -85,15 +97,13 @@ export class MetadataCollector {
}

function classMetadataOf(classDeclaration: ts.ClassDeclaration): ClassMetadata {
let result: ClassMetadata =
{ __symbolic: "class" }

function getDecorators(decorators: ts.Decorator[]):
MetadataSymbolicExpression[] {
if (decorators && decorators.length)
return decorators.map(decorator => objFromDecorator(decorator));
return undefined;
}
let result: ClassMetadata = {__symbolic: "class"};

function getDecorators(decorators: ts.Decorator[]): MetadataSymbolicExpression[] {
if (decorators && decorators.length)
return decorators.map(decorator => objFromDecorator(decorator));
return undefined;
}

// Add class decorators
if (classDeclaration.decorators) {
Expand Down Expand Up @@ -175,7 +185,7 @@ export class MetadataCollector {
const classDeclaration = <ts.ClassDeclaration>declaration;
if (classDeclaration.decorators) {
if (!metadata) metadata = {};
metadata[classDeclaration.name.text] = classMetadataOf(classDeclaration)
metadata[classDeclaration.name.text] = classMetadataOf(classDeclaration);
}
break;
case ts.SyntaxKind.VariableDeclaration:
Expand Down

0 comments on commit 9889c21

Please sign in to comment.