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;
|
||||
}
|
||||
|
||||
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) {
|
||||
genFiles.forEach(gf => {
|
||||
if (gf.source) {
|
||||
|
@ -287,29 +295,6 @@ class AngularCompilerProgram implements Program {
|
|||
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() {
|
||||
if (this._analyzedModules) {
|
||||
return;
|
||||
|
@ -567,12 +552,42 @@ function getNgOptionDiagnostics(options: CompilerOptions): Diagnostic[] {
|
|||
return [];
|
||||
}
|
||||
|
||||
function longestCommonSuffix(a: string, b: string): string {
|
||||
let len = 0;
|
||||
while (a.charCodeAt(a.length - 1 - len) === b.charCodeAt(b.length - 1 - len)) {
|
||||
len++;
|
||||
/**
|
||||
* Returns a function that can adjust a path from source path to out path,
|
||||
* based on an existing mapping from source to out path.
|
||||
*
|
||||
* 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. `);
|
||||
}
|
||||
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 a.substring(a.length - len);
|
||||
return srcToOutPath;
|
||||
}
|
||||
|
||||
export function i18nExtract(
|
||||
|
|
|
@ -12,6 +12,7 @@ import * as path from 'path';
|
|||
import * as ts from 'typescript';
|
||||
|
||||
import {CompilerHost} from '../../src/transformers/api';
|
||||
import {createSrcToOutPathMapper} from '../../src/transformers/program';
|
||||
import {GENERATED_FILES, StructureIsReused, tsStructureIsReused} from '../../src/transformers/util';
|
||||
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.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