fix(compiler): make sure our out path calculation is correct
This commit is contained in:
parent
ec2be5dccb
commit
2f6ae527d1
|
@ -210,7 +210,15 @@ class AngularCompilerProgram implements Program {
|
||||||
return emitResult;
|
return emitResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
const srcToOutPath = this.createSrcToOutPathMapper(outSrcMapping);
|
|
||||||
|
let sampleSrcFileName: string|undefined;
|
||||||
|
let sampleOutFileName: string|undefined;
|
||||||
|
if (outSrcMapping.length) {
|
||||||
|
sampleSrcFileName = outSrcMapping[0].sourceFile.fileName;
|
||||||
|
sampleOutFileName = outSrcMapping[0].outFileName;
|
||||||
|
}
|
||||||
|
const srcToOutPath =
|
||||||
|
createSrcToOutPathMapper(this.options.outDir, sampleSrcFileName, sampleOutFileName);
|
||||||
if (emitFlags & EmitFlags.Codegen) {
|
if (emitFlags & EmitFlags.Codegen) {
|
||||||
genFiles.forEach(gf => {
|
genFiles.forEach(gf => {
|
||||||
if (gf.source) {
|
if (gf.source) {
|
||||||
|
@ -287,29 +295,6 @@ class AngularCompilerProgram implements Program {
|
||||||
return {before: beforeTs, after: afterTs};
|
return {before: beforeTs, after: afterTs};
|
||||||
}
|
}
|
||||||
|
|
||||||
private createSrcToOutPathMapper(outSrcMappings:
|
|
||||||
Array<{sourceFile: ts.SourceFile, outFileName: string}>):
|
|
||||||
(srcFileName: string) => string {
|
|
||||||
let srcToOutPath: (srcFileName: string) => string;
|
|
||||||
if (this.options.outDir) {
|
|
||||||
// TODO(tbosch): talk to TypeScript team to expose their logic for calculating the `rootDir`
|
|
||||||
// if none was specified.
|
|
||||||
if (outSrcMappings.length === 0) {
|
|
||||||
throw new Error(`Can't calculate the rootDir without at least one outSrcMapping. `);
|
|
||||||
}
|
|
||||||
const firstEntry = outSrcMappings[0];
|
|
||||||
const entrySrcDir = path.dirname(firstEntry.sourceFile.fileName);
|
|
||||||
const entryOutDir = path.dirname(firstEntry.outFileName);
|
|
||||||
const commonSuffix = longestCommonSuffix(entrySrcDir, entryOutDir);
|
|
||||||
const rootDir = entrySrcDir.substring(0, entrySrcDir.length - commonSuffix.length);
|
|
||||||
srcToOutPath = (srcFileName) =>
|
|
||||||
path.resolve(this.options.outDir, path.relative(rootDir, srcFileName));
|
|
||||||
} else {
|
|
||||||
srcToOutPath = (srcFileName) => srcFileName;
|
|
||||||
}
|
|
||||||
return srcToOutPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
private initSync() {
|
private initSync() {
|
||||||
if (this._analyzedModules) {
|
if (this._analyzedModules) {
|
||||||
return;
|
return;
|
||||||
|
@ -567,12 +552,42 @@ function getNgOptionDiagnostics(options: CompilerOptions): Diagnostic[] {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function longestCommonSuffix(a: string, b: string): string {
|
/**
|
||||||
let len = 0;
|
* Returns a function that can adjust a path from source path to out path,
|
||||||
while (a.charCodeAt(a.length - 1 - len) === b.charCodeAt(b.length - 1 - len)) {
|
* based on an existing mapping from source to out path.
|
||||||
len++;
|
*
|
||||||
|
* TODO(tbosch): talk to the TypeScript team to expose their logic for calculating the `rootDir`
|
||||||
|
* if none was specified.
|
||||||
|
*
|
||||||
|
* @param outDir
|
||||||
|
* @param outSrcMappings
|
||||||
|
*/
|
||||||
|
export function createSrcToOutPathMapper(
|
||||||
|
outDir: string | undefined, sampleSrcFileName: string | undefined,
|
||||||
|
sampleOutFileName: string | undefined): (srcFileName: string) => string {
|
||||||
|
let srcToOutPath: (srcFileName: string) => string;
|
||||||
|
if (outDir) {
|
||||||
|
if (sampleSrcFileName == null || sampleOutFileName == null) {
|
||||||
|
throw new Error(`Can't calculate the rootDir without a sample srcFileName / outFileName. `);
|
||||||
}
|
}
|
||||||
return a.substring(a.length - len);
|
const srcFileDir = path.dirname(sampleSrcFileName);
|
||||||
|
const outFileDir = path.dirname(sampleOutFileName);
|
||||||
|
if (srcFileDir === outFileDir) {
|
||||||
|
return (srcFileName) => srcFileName;
|
||||||
|
}
|
||||||
|
const srcDirParts = srcFileDir.split(path.sep);
|
||||||
|
const outDirParts = outFileDir.split(path.sep);
|
||||||
|
// calculate the common suffix
|
||||||
|
let i = 0;
|
||||||
|
while (i < Math.min(srcDirParts.length, outDirParts.length) &&
|
||||||
|
srcDirParts[srcDirParts.length - 1 - i] === outDirParts[outDirParts.length - 1 - i])
|
||||||
|
i++;
|
||||||
|
const rootDir = srcDirParts.slice(0, srcDirParts.length - i).join(path.sep);
|
||||||
|
srcToOutPath = (srcFileName) => path.resolve(outDir, path.relative(rootDir, srcFileName));
|
||||||
|
} else {
|
||||||
|
srcToOutPath = (srcFileName) => srcFileName;
|
||||||
|
}
|
||||||
|
return srcToOutPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function i18nExtract(
|
export function i18nExtract(
|
||||||
|
|
|
@ -12,6 +12,7 @@ import * as path from 'path';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {CompilerHost} from '../../src/transformers/api';
|
import {CompilerHost} from '../../src/transformers/api';
|
||||||
|
import {createSrcToOutPathMapper} from '../../src/transformers/program';
|
||||||
import {GENERATED_FILES, StructureIsReused, tsStructureIsReused} from '../../src/transformers/util';
|
import {GENERATED_FILES, StructureIsReused, tsStructureIsReused} from '../../src/transformers/util';
|
||||||
import {TestSupport, expectNoDiagnosticsInProgram, setup} from '../test_support';
|
import {TestSupport, expectNoDiagnosticsInProgram, setup} from '../test_support';
|
||||||
|
|
||||||
|
@ -361,4 +362,26 @@ describe('ng program', () => {
|
||||||
testSupport.shouldNotExist('build/node_modules/lib/index.ngfactory.d.ts');
|
testSupport.shouldNotExist('build/node_modules/lib/index.ngfactory.d.ts');
|
||||||
testSupport.shouldNotExist('build/node_modules/lib/index.ngsummary.json');
|
testSupport.shouldNotExist('build/node_modules/lib/index.ngsummary.json');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('createSrcToOutPathMapper', () => {
|
||||||
|
it('should return identity mapping if no outDir is present', () => {
|
||||||
|
const mapper = createSrcToOutPathMapper(undefined, undefined, undefined);
|
||||||
|
expect(mapper('/tmp/b/y.js')).toBe('/tmp/b/y.js');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return identity mapping if first src and out fileName have same dir', () => {
|
||||||
|
const mapper = createSrcToOutPathMapper('/tmp', '/tmp/a/x.ts', '/tmp/a/x.js');
|
||||||
|
expect(mapper('/tmp/b/y.js')).toBe('/tmp/b/y.js');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should adjust the filename if the outDir is inside of the rootDir', () => {
|
||||||
|
const mapper = createSrcToOutPathMapper('/tmp/out', '/tmp/a/x.ts', '/tmp/out/a/x.js');
|
||||||
|
expect(mapper('/tmp/b/y.js')).toBe('/tmp/out/b/y.js');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should adjust the filename if the outDir is outside of the rootDir', () => {
|
||||||
|
const mapper = createSrcToOutPathMapper('/out', '/tmp/a/x.ts', '/a/x.js');
|
||||||
|
expect(mapper('/tmp/b/y.js')).toBe('/out/b/y.js');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue