fix(ngc): Revert "fix(ngc): add an option to produce TS1.9-pathMapping imports (#10602)" (#10765)

This reverts commit beadf6167a.
This commit is contained in:
Alex Eagle 2016-08-12 17:38:29 -07:00 committed by vikerman
parent a235ae16ed
commit 9317056138
6 changed files with 80 additions and 127 deletions

View File

@ -13,6 +13,7 @@
"moduleResolution": "node", "moduleResolution": "node",
"rootDir": "", "rootDir": "",
"declaration": true, "declaration": true,
"lib": ["es6", "dom"] "lib": ["es6", "dom"],
"baseUrl": "."
} }
} }

View File

@ -18,12 +18,14 @@ import * as ts from 'typescript';
import {CompileMetadataResolver, DirectiveNormalizer, DomElementSchemaRegistry, HtmlParser, Lexer, NgModuleCompiler, Parser, StyleCompiler, TemplateParser, TypeScriptEmitter, ViewCompiler} from './compiler_private'; import {CompileMetadataResolver, DirectiveNormalizer, DomElementSchemaRegistry, HtmlParser, Lexer, NgModuleCompiler, Parser, StyleCompiler, TemplateParser, TypeScriptEmitter, ViewCompiler} from './compiler_private';
import {Console} from './core_private'; import {Console} from './core_private';
import {GENERATED_FILES, ReflectorHost, ReflectorHostContext} from './reflector_host'; import {ReflectorHost, ReflectorHostContext} from './reflector_host';
import {StaticAndDynamicReflectionCapabilities} from './static_reflection_capabilities'; import {StaticAndDynamicReflectionCapabilities} from './static_reflection_capabilities';
import {StaticReflector, StaticSymbol} from './static_reflector'; import {StaticReflector, StaticSymbol} from './static_reflector';
const nodeFs = require('fs'); const nodeFs = require('fs');
const GENERATED_FILES = /\.ngfactory\.ts$|\.css\.ts$|\.css\.shim\.ts$/;
const PREAMBLE = `/** const PREAMBLE = `/**
* This file is generated by the Angular 2 template compiler. * This file is generated by the Angular 2 template compiler.
* Do not edit. * Do not edit.

View File

@ -16,7 +16,8 @@ import {StaticReflectorHost, StaticSymbol} from './static_reflector';
const EXT = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/; const EXT = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/;
const DTS = /\.d\.ts$/; const DTS = /\.d\.ts$/;
export const GENERATED_FILES = /\.ngfactory\.ts$|\.css\.ts$|\.css\.shim\.ts$/; const NODE_MODULES = path.sep + 'node_modules' + path.sep;
const IS_GENERATED = /\.(ngfactory|css(\.shim)?)$/;
export interface ReflectorHostContext { export interface ReflectorHostContext {
fileExists(fileName: string): boolean; fileExists(fileName: string): boolean;
@ -57,9 +58,6 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator {
private resolve(m: string, containingFile: string) { private resolve(m: string, containingFile: string) {
const resolved = const resolved =
ts.resolveModuleName(m, containingFile, this.options, this.context).resolvedModule; ts.resolveModuleName(m, containingFile, this.options, this.context).resolvedModule;
if (this.options.traceResolution) {
console.log('resolve', m, containingFile, '=>', resolved);
}
return resolved ? resolved.resolvedFileName : null; return resolved ? resolved.resolvedFileName : null;
}; };
@ -81,8 +79,8 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator {
* These need to be in a form that system.js can load, so absolute file paths don't work. * These need to be in a form that system.js can load, so absolute file paths don't work.
* *
* The `containingFile` is always in the `genDir`, where as the `importedFile` can be in * The `containingFile` is always in the `genDir`, where as the `importedFile` can be in
* `genDir`, `node_module` or `rootDir`/`rootDirs`. * `genDir`, `node_module` or `basePath`. The `importedFile` is either a generated file or
* The `importedFile` is either a generated file or an existing file. * existing file.
* *
* | genDir | node_module | rootDir * | genDir | node_module | rootDir
* --------------+----------+-------------+---------- * --------------+----------+-------------+----------
@ -95,66 +93,67 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator {
importedFile = this.resolveAssetUrl(importedFile, containingFile); importedFile = this.resolveAssetUrl(importedFile, containingFile);
containingFile = this.resolveAssetUrl(containingFile, ''); containingFile = this.resolveAssetUrl(containingFile, '');
if (this.options.traceResolution) {
console.log(
'getImportPath from containingFile', containingFile, 'to importedFile', importedFile);
}
// If a file does not yet exist (because we compile it later), we still need to // If a file does not yet exist (because we compile it later), we still need to
// assume it exists it so that the `resolve` method works! // assume it exists it so that the `resolve` method works!
if (!this.compilerHost.fileExists(importedFile)) { if (!this.compilerHost.fileExists(importedFile)) {
this.context.assumeFileExists(importedFile); this.context.assumeFileExists(importedFile);
} }
let importModuleName = importedFile.replace(EXT, ''); containingFile = this.rewriteGenDirPath(containingFile);
const parts = importModuleName.split(path.sep).filter(p => !!p); const containingDir = path.dirname(containingFile);
let foundRelativeImport: string; // drop extension
for (let index = parts.length - 1; index >= 0; index--) { importedFile = importedFile.replace(EXT, '');
let candidate = parts.slice(index, parts.length).join(path.sep);
if (this.resolve(candidate, containingFile) === importedFile) { var nodeModulesIndex = importedFile.indexOf(NODE_MODULES);
return candidate; const importModule = nodeModulesIndex === -1 ?
} null :
candidate = '.' + path.sep + candidate; importedFile.substring(nodeModulesIndex + NODE_MODULES.length);
if (this.resolve(candidate, containingFile) === importedFile) { const isGeneratedFile = IS_GENERATED.test(importedFile);
if (this.options.writeImportsForRootDirs) {
foundRelativeImport = candidate; if (isGeneratedFile) {
// rewrite to genDir path
if (importModule) {
// it is generated, therefore we do a relative path to the factory
return this.dotRelative(containingDir, this.genDir + NODE_MODULES + importModule);
} else { } else {
foundRelativeImport = this.fixupGendirRelativePath(containingFile, importedFile); // assume that import is also in `genDir`
importedFile = this.rewriteGenDirPath(importedFile);
return this.dotRelative(containingDir, importedFile);
}
} else {
// user code import
if (importModule) {
return importModule;
} else {
if (!this.isGenDirChildOfRootDir) {
// assume that they are on top of each other.
importedFile = importedFile.replace(this.basePath, this.genDir);
}
return this.dotRelative(containingDir, importedFile);
} }
} }
} }
if (foundRelativeImport) return foundRelativeImport;
// Try a relative import
let candidate = path.relative(path.dirname(containingFile), importModuleName);
if (this.resolve(candidate, containingFile) === importedFile) {
return this.fixupGendirRelativePath(containingFile, importedFile);
}
throw new Error(
`Unable to find any resolvable import for ${importedFile} relative to ${containingFile}`);
}
private fixupGendirRelativePath(containingFile: string, importedFile: string) {
let importModuleName = importedFile.replace(EXT, '');
if (!this.options.writeImportsForRootDirs && this.isGenDirChildOfRootDir) {
if (GENERATED_FILES.test(importedFile)) {
importModuleName = importModuleName.replace(this.basePath, this.genDir);
}
if (GENERATED_FILES.test(containingFile)) {
containingFile = containingFile.replace(this.basePath, this.genDir);
}
}
return this.dotRelative(path.dirname(containingFile), importModuleName);
}
private dotRelative(from: string, to: string): string { private dotRelative(from: string, to: string): string {
var rPath: string = path.relative(from, to); var rPath: string = path.relative(from, to);
return rPath.startsWith('.') ? rPath : './' + rPath; return rPath.startsWith('.') ? rPath : './' + rPath;
} }
/**
* Moves the path into `genDir` folder while preserving the `node_modules` directory.
*/
private rewriteGenDirPath(filepath: string) {
var nodeModulesIndex = filepath.indexOf(NODE_MODULES);
if (nodeModulesIndex !== -1) {
// If we are in node_modulse, transplant them into `genDir`.
return path.join(this.genDir, filepath.substring(nodeModulesIndex));
} else {
// pretend that containing file is on top of the `genDir` to normalize the paths.
// we apply the `genDir` => `rootDir` delta through `rootDirPrefix` later.
return filepath.replace(this.basePath, this.genDir);
}
}
findDeclaration( findDeclaration(
module: string, symbolName: string, containingFile: string, module: string, symbolName: string, containingFile: string,
containingModule?: string): StaticSymbol { containingModule?: string): StaticSymbol {

View File

@ -17,8 +17,6 @@ export interface Directory { [name: string]: Entry; }
export class MockContext implements ReflectorHostContext { export class MockContext implements ReflectorHostContext {
constructor(public currentDirectory: string, private files: Entry) {} constructor(public currentDirectory: string, private files: Entry) {}
trace(s: string) { console.log(s); }
fileExists(fileName: string): boolean { return typeof this.getEntry(fileName) === 'string'; } fileExists(fileName: string): boolean { return typeof this.getEntry(fileName) === 'string'; }
directoryExists(path: string): boolean { return typeof this.getEntry(path) === 'object'; } directoryExists(path: string): boolean { return typeof this.getEntry(path) === 'object'; }

View File

@ -20,8 +20,6 @@ describe('reflector_host', () => {
var reflectorNestedGenDir: ReflectorHost; var reflectorNestedGenDir: ReflectorHost;
var reflectorSiblingGenDir: ReflectorHost; var reflectorSiblingGenDir: ReflectorHost;
const DEBUG = false;
beforeEach(() => { beforeEach(() => {
context = new MockContext('/tmp/src', clone(FILES)); context = new MockContext('/tmp/src', clone(FILES));
host = new MockCompilerHost(context); host = new MockCompilerHost(context);
@ -37,9 +35,8 @@ describe('reflector_host', () => {
} }
reflectorNestedGenDir = new ReflectorHost( reflectorNestedGenDir = new ReflectorHost(
program, host, { program, host, {
// Intentional trailing slash, check for regression of #10533 genDir: '/tmp/project/src/gen/',
genDir: '/tmp/src/gen/', basePath: '/tmp/project/src',
basePath: '/tmp/src',
skipMetadataEmit: false, skipMetadataEmit: false,
skipTemplateCodegen: false, skipTemplateCodegen: false,
trace: false trace: false
@ -47,97 +44,77 @@ describe('reflector_host', () => {
context); context);
reflectorSiblingGenDir = new ReflectorHost( reflectorSiblingGenDir = new ReflectorHost(
program, host, { program, host, {
genDir: '/tmp/gen', genDir: '/tmp/project/gen',
// Intentional trailing slash, check for regression of #10533 basePath: '/tmp/project/src/',
basePath: '/tmp/src/',
skipMetadataEmit: false, skipMetadataEmit: false,
skipTemplateCodegen: false, skipTemplateCodegen: false,
trace: false trace: false
}, },
context); context);
}); });
describe('path mapping', () => { describe('nestedGenDir', () => {
it('should use rootDirs for calculating relative imports', () => {
const reflectorHost = new ReflectorHost(
program, host, {
genDir: '/tmp/gen',
basePath: '/tmp/src/',
skipMetadataEmit: false,
skipTemplateCodegen: false,
trace: false,
traceResolution: DEBUG,
rootDirs: ['/tmp/src/', '/tmp/genfiles/'],
writeImportsForRootDirs: true,
},
context);
expect(reflectorHost.getImportPath(
'/tmp/src/pathmapping/bootstrap.ts', '/tmp/genfiles/pathmapping/comp.d.ts'))
.toEqual('./comp');
});
});
describe('nested genDir', () => {
it('should import node_module from factory', () => { it('should import node_module from factory', () => {
expect(reflectorNestedGenDir.getImportPath( expect(reflectorNestedGenDir.getImportPath(
'/tmp/src/gen/my.ngfactory.ts', '/tmp/src/node_modules/@angular/core.d.ts')) '/tmp/project/src/gen/my.ngfactory.ts',
'/tmp/project/node_modules/@angular/core.d.ts'))
.toEqual('@angular/core'); .toEqual('@angular/core');
}); });
it('should import factory from factory', () => { it('should import factory from factory', () => {
expect(reflectorNestedGenDir.getImportPath( expect(reflectorNestedGenDir.getImportPath(
'/tmp/src/my.ngfactory.ts', '/tmp/src/my.other.ngfactory.ts')) '/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/my.other.ngfactory.ts'))
.toEqual('./my.other.ngfactory'); .toEqual('./my.other.ngfactory');
expect(reflectorNestedGenDir.getImportPath( expect(reflectorNestedGenDir.getImportPath(
'/tmp/src/a/my.ngfactory.ts', '/tmp/src/my.other.css.ts')) '/tmp/project/src/a/my.ngfactory.ts', '/tmp/project/src/my.other.css.ts'))
.toEqual('../my.other.css'); .toEqual('../my.other.css');
expect(reflectorNestedGenDir.getImportPath( expect(reflectorNestedGenDir.getImportPath(
'/tmp/src/my.ngfactory.ts', '/tmp/src/a/my.other.css.shim.ts')) '/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/a/my.other.css.shim.ts'))
.toEqual('./a/my.other.css.shim'); .toEqual('./a/my.other.css.shim');
}); });
it('should import application from factory', () => { it('should import application from factory', () => {
expect( expect(reflectorNestedGenDir.getImportPath(
reflectorNestedGenDir.getImportPath('/tmp/src/my.ngfactory.ts', '/tmp/src/my.other.ts')) '/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/my.other.ts'))
.toEqual('../my.other'); .toEqual('../my.other');
expect( expect(reflectorNestedGenDir.getImportPath(
reflectorNestedGenDir.getImportPath('/tmp/src/a/my.ngfactory.ts', '/tmp/src/my.other.ts')) '/tmp/project/src/a/my.ngfactory.ts', '/tmp/project/src/my.other.ts'))
.toEqual('../../my.other'); .toEqual('../../my.other');
expect( expect(reflectorNestedGenDir.getImportPath(
reflectorNestedGenDir.getImportPath('/tmp/src/my.ngfactory.ts', '/tmp/src/a/my.other.ts')) '/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/a/my.other.ts'))
.toEqual('../a/my.other'); .toEqual('../a/my.other');
}); });
}); });
describe('sibling genDir', () => { describe('nestedGenDir', () => {
it('should import node_module from factory', () => { it('should import node_module from factory', () => {
expect(reflectorSiblingGenDir.getImportPath( expect(reflectorSiblingGenDir.getImportPath(
'/tmp/src/gen/my.ngfactory.ts', '/tmp/src/node_modules/@angular/core.d.ts')) '/tmp/project/src/gen/my.ngfactory.ts',
'/tmp/project/node_modules/@angular/core.d.ts'))
.toEqual('@angular/core'); .toEqual('@angular/core');
}); });
it('should import factory from factory', () => { it('should import factory from factory', () => {
expect(reflectorSiblingGenDir.getImportPath( expect(reflectorSiblingGenDir.getImportPath(
'/tmp/src/my.ngfactory.ts', '/tmp/src/my.other.ngfactory.ts')) '/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/my.other.ngfactory.ts'))
.toEqual('./my.other.ngfactory'); .toEqual('./my.other.ngfactory');
expect(reflectorSiblingGenDir.getImportPath( expect(reflectorSiblingGenDir.getImportPath(
'/tmp/src/a/my.ngfactory.ts', '/tmp/src/my.other.css.ts')) '/tmp/project/src/a/my.ngfactory.ts', '/tmp/project/src/my.other.css.ts'))
.toEqual('../my.other.css'); .toEqual('../my.other.css');
expect(reflectorSiblingGenDir.getImportPath( expect(reflectorSiblingGenDir.getImportPath(
'/tmp/src/my.ngfactory.ts', '/tmp/src/a/my.other.css.shim.ts')) '/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/a/my.other.css.shim.ts'))
.toEqual('./a/my.other.css.shim'); .toEqual('./a/my.other.css.shim');
}); });
it('should import application from factory', () => { it('should import application from factory', () => {
expect( expect(reflectorSiblingGenDir.getImportPath(
reflectorSiblingGenDir.getImportPath('/tmp/src/my.ngfactory.ts', '/tmp/src/my.other.ts')) '/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/my.other.ts'))
.toEqual('./my.other'); .toEqual('./my.other');
expect(reflectorSiblingGenDir.getImportPath( expect(reflectorSiblingGenDir.getImportPath(
'/tmp/src/a/my.ngfactory.ts', '/tmp/src/my.other.ts')) '/tmp/project/src/a/my.ngfactory.ts', '/tmp/project/src/my.other.ts'))
.toEqual('../my.other'); .toEqual('../my.other');
expect(reflectorSiblingGenDir.getImportPath( expect(reflectorSiblingGenDir.getImportPath(
'/tmp/src/my.ngfactory.ts', '/tmp/src/a/my.other.ts')) '/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/a/my.other.ts'))
.toEqual('./a/my.other'); .toEqual('./a/my.other');
}); });
}); });
@ -154,7 +131,7 @@ describe('reflector_host', () => {
it('should be able to produce an import from main @angular/core', () => { it('should be able to produce an import from main @angular/core', () => {
expect(reflectorNestedGenDir.getImportPath( expect(reflectorNestedGenDir.getImportPath(
'/tmp/src/main.ts', '/tmp/src/node_modules/@angular/core.d.ts')) '/tmp/project/src/main.ts', '/tmp/project/node_modules/@angular/core.d.ts'))
.toEqual('@angular/core'); .toEqual('@angular/core');
}); });
@ -322,11 +299,6 @@ const FILES: Entry = {
}) })
} }
}, },
'pathmapping': {'bootstrap.ts': `import {a} from './comp.d.ts';`},
'a': {
'my.other.css.shim.ts': dummyModule,
},
'my.other.ts': dummyModule,
'node_modules': { 'node_modules': {
'@angular': { '@angular': {
'core.d.ts': dummyModule, 'core.d.ts': dummyModule,
@ -338,13 +310,6 @@ const FILES: Entry = {
'empty.metadata.json': '[]', 'empty.metadata.json': '[]',
} }
} }
},
'genfiles': {
'pathmapping': {
'comp.d.ts': `
export declare let a: string;
`
}
} }
} }
}; };

View File

@ -18,18 +18,6 @@ interface Options extends ts.CompilerOptions {
// Whether to embed debug information in the compiled templates // Whether to embed debug information in the compiled templates
debug?: boolean; debug?: boolean;
// Starting with TypeScript 1.9, the 'rootDirs' option can be used
// to allow multiple source directories to have relative imports
// between them.
// This option causes generated code to use imports relative to the
// current directory, and requires you configure the 'rootDirs' to
// include both the genDir and rootDir.
// However, due to https://github.com/Microsoft/TypeScript/issues/8245
// note that using this option does not lay out into a flat directory
// with application and generated sources side-by-side, so you must
// teach your module loader how to resolve such imports as well.
writeImportsForRootDirs?: boolean;
} }
export default Options; export default Options;