fix(metadata): emit metadata rooted at 'angular2'
fixes #8144 closes #8147
This commit is contained in:
parent
e69cb40de3
commit
9889c21aaa
|
@ -88,7 +88,16 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
|
||||||
this.tsServiceHost = new CustomLanguageServiceHost(this.tsOpts, this.rootFilePaths,
|
this.tsServiceHost = new CustomLanguageServiceHost(this.tsOpts, this.rootFilePaths,
|
||||||
this.fileRegistry, this.inputPath);
|
this.fileRegistry, this.inputPath);
|
||||||
this.tsService = ts.createLanguageService(this.tsServiceHost, ts.createDocumentRegistry());
|
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$/, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,28 +27,32 @@ function pathTo(from: string, to: string): string {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function moduleNameFromBaseName(moduleFileName: string, baseFileName: string): string {
|
export interface MetadataCollectorHost {
|
||||||
// Remove the extension
|
reverseModuleResolution: (moduleFileName: string) => string;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
* Collect decorator metadata from a TypeScript module.
|
||||||
*/
|
*/
|
||||||
export class MetadataCollector {
|
export class MetadataCollector {
|
||||||
constructor() {}
|
constructor(private host: MetadataCollectorHost = nodeModuleResolutionHost) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a JSON.stringify friendly form describing the decorators of the exported classes from
|
* Returns a JSON.stringify friendly form describing the decorators of the exported classes from
|
||||||
|
@ -56,8 +60,16 @@ export class MetadataCollector {
|
||||||
*/
|
*/
|
||||||
public getMetadata(sourceFile: ts.SourceFile, typeChecker: ts.TypeChecker): ModuleMetadata {
|
public getMetadata(sourceFile: ts.SourceFile, typeChecker: ts.TypeChecker): ModuleMetadata {
|
||||||
const locals = new Symbols();
|
const locals = new Symbols();
|
||||||
const moduleNameOf = (fileName: string) =>
|
const moduleNameOf = (fileName: string) => {
|
||||||
moduleNameFromBaseName(fileName, sourceFile.fileName);
|
// 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, moduleNameOf);
|
||||||
|
|
||||||
function objFromDecorator(decoratorNode: ts.Decorator): MetadataSymbolicExpression {
|
function objFromDecorator(decoratorNode: ts.Decorator): MetadataSymbolicExpression {
|
||||||
|
@ -85,15 +97,13 @@ export class MetadataCollector {
|
||||||
}
|
}
|
||||||
|
|
||||||
function classMetadataOf(classDeclaration: ts.ClassDeclaration): ClassMetadata {
|
function classMetadataOf(classDeclaration: ts.ClassDeclaration): ClassMetadata {
|
||||||
let result: ClassMetadata =
|
let result: ClassMetadata = {__symbolic: "class"};
|
||||||
{ __symbolic: "class" }
|
|
||||||
|
|
||||||
function getDecorators(decorators: ts.Decorator[]):
|
function getDecorators(decorators: ts.Decorator[]): MetadataSymbolicExpression[] {
|
||||||
MetadataSymbolicExpression[] {
|
if (decorators && decorators.length)
|
||||||
if (decorators && decorators.length)
|
return decorators.map(decorator => objFromDecorator(decorator));
|
||||||
return decorators.map(decorator => objFromDecorator(decorator));
|
return undefined;
|
||||||
return undefined;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Add class decorators
|
// Add class decorators
|
||||||
if (classDeclaration.decorators) {
|
if (classDeclaration.decorators) {
|
||||||
|
@ -175,7 +185,7 @@ export class MetadataCollector {
|
||||||
const classDeclaration = <ts.ClassDeclaration>declaration;
|
const classDeclaration = <ts.ClassDeclaration>declaration;
|
||||||
if (classDeclaration.decorators) {
|
if (classDeclaration.decorators) {
|
||||||
if (!metadata) metadata = {};
|
if (!metadata) metadata = {};
|
||||||
metadata[classDeclaration.name.text] = classMetadataOf(classDeclaration)
|
metadata[classDeclaration.name.text] = classMetadataOf(classDeclaration);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ts.SyntaxKind.VariableDeclaration:
|
case ts.SyntaxKind.VariableDeclaration:
|
||||||
|
|
Loading…
Reference in New Issue