Merge pull request #34403 from microsoft/commandlinePath

Make sure commandline options are absolute paths so they dont conflict with options from tsbuild info
This commit is contained in:
Sheetal Nandi
2019-10-15 08:28:33 -07:00
committed by GitHub
11 changed files with 206 additions and 44 deletions

View File

@@ -1118,7 +1118,7 @@ namespace ts {
const state: ReusableBuilderProgramState = {
fileInfos,
compilerOptions: convertFromReusableCompilerOptions(program.options, toAbsolutePath),
compilerOptions: convertToOptionsWithAbsolutePaths(program.options, toAbsolutePath),
referencedMap: getMapOfReferencedSet(program.referencedMap, toPath),
exportedModulesMap: getMapOfReferencedSet(program.exportedModulesMap, toPath),
semanticDiagnosticsPerFile: program.semanticDiagnosticsPerFile && arrayToMap(program.semanticDiagnosticsPerFile, value => toPath(isString(value) ? value : value[0]), value => isString(value) ? emptyArray : value[1]),
@@ -1156,40 +1156,6 @@ namespace ts {
}
}
function convertFromReusableCompilerOptions(options: CompilerOptions, toAbsolutePath: (path: string) => string) {
const result: CompilerOptions = {};
const optionsNameMap = getOptionNameMap().optionNameMap;
for (const name in options) {
if (hasProperty(options, name)) {
result[name] = convertFromReusableCompilerOptionValue(
optionsNameMap.get(name.toLowerCase()),
options[name] as CompilerOptionsValue,
toAbsolutePath
);
}
}
if (result.configFilePath) {
result.configFilePath = toAbsolutePath(result.configFilePath);
}
return result;
}
function convertFromReusableCompilerOptionValue(option: CommandLineOption | undefined, value: CompilerOptionsValue, toAbsolutePath: (path: string) => string) {
if (option) {
if (option.type === "list") {
const values = value as readonly (string | number)[];
if (option.element.isFilePath && values.length) {
return values.map(toAbsolutePath);
}
}
else if (option.isFilePath) {
return toAbsolutePath(value as string);
}
}
return value;
}
export function createRedirectedBuilderProgram(state: { program: Program | undefined; compilerOptions: CompilerOptions; }, configFileParsingDiagnostics: readonly Diagnostic[]): BuilderProgram {
return {
getState: notImplemented,

View File

@@ -2041,6 +2041,41 @@ namespace ts {
}
}
/* @internal */
export function convertToOptionsWithAbsolutePaths(options: CompilerOptions, toAbsolutePath: (path: string) => string) {
const result: CompilerOptions = {};
const optionsNameMap = getOptionNameMap().optionNameMap;
for (const name in options) {
if (hasProperty(options, name)) {
result[name] = convertToOptionValueWithAbsolutePaths(
optionsNameMap.get(name.toLowerCase()),
options[name] as CompilerOptionsValue,
toAbsolutePath
);
}
}
if (result.configFilePath) {
result.configFilePath = toAbsolutePath(result.configFilePath);
}
return result;
}
function convertToOptionValueWithAbsolutePaths(option: CommandLineOption | undefined, value: CompilerOptionsValue, toAbsolutePath: (path: string) => string) {
if (option) {
if (option.type === "list") {
const values = value as readonly (string | number)[];
if (option.element.isFilePath && values.length) {
return values.map(toAbsolutePath);
}
}
else if (option.isFilePath) {
return toAbsolutePath(value as string);
}
}
return value;
}
/**
* Parse the contents of a config file (tsconfig.json).
* @param json The contents of the config file to parse

View File

@@ -524,7 +524,7 @@ ${indentText}${text}`;
export const version = "FakeTSVersion";
export function patchSolutionBuilderHost(host: ts.SolutionBuilderHost<ts.BuilderProgram>, sys: System) {
export function patchHostForBuildInfoReadWrite(host: ts.CompilerHost | ts.SolutionBuilderHost<ts.BuilderProgram>) {
const originalReadFile = host.readFile;
host.readFile = (path, encoding) => {
const value = originalReadFile.call(host, path, encoding);
@@ -537,7 +537,7 @@ ${indentText}${text}`;
if (host.writeFile) {
const originalWriteFile = host.writeFile;
host.writeFile = (fileName, content, writeByteOrderMark) => {
host.writeFile = (fileName: string, content: string, writeByteOrderMark: boolean) => {
if (!ts.isBuildInfoFile(fileName)) return originalWriteFile.call(host, fileName, content, writeByteOrderMark);
const buildInfo = ts.getBuildInfo(content);
sanitizeBuildInfoProgram(buildInfo);
@@ -545,6 +545,10 @@ ${indentText}${text}`;
originalWriteFile.call(host, fileName, ts.getBuildInfoText(buildInfo), writeByteOrderMark);
};
}
}
export function patchSolutionBuilderHost(host: ts.SolutionBuilderHost<ts.BuilderProgram>, sys: System) {
patchHostForBuildInfoReadWrite(host);
ts.Debug.assert(host.now === undefined);
host.now = () => new Date(sys.vfs.time());

View File

@@ -113,6 +113,7 @@
"unittests/tsbuild/watchEnvironment.ts",
"unittests/tsbuild/watchMode.ts",
"unittests/tsc/declarationEmit.ts",
"unittests/tsc/incremental.ts",
"unittests/tscWatch/consoleClearing.ts",
"unittests/tscWatch/emit.ts",
"unittests/tscWatch/emitAndErrorUpdates.ts",

View File

@@ -290,7 +290,7 @@ interface Symbol {
baselineSourceMap, modifyFs, baselineReadFileCalls,
incrementalScenarios
}: VerifyTsBuildInput) {
describe(`tsc --b ${scenario}:: ${subScenario}`, () => {
describe(`tsc ${commandLineArgs.join(" ")} ${scenario}:: ${subScenario}`, () => {
let tick: () => void;
let sys: TscCompileSystem;
before(() => {

View File

@@ -50,8 +50,15 @@ namespace ts {
Debug.assert(commandLine.fileNames.length !== 0 || !!configFileName);
const currentDirectory = sys.getCurrentDirectory();
const getCanonicalFileName = createGetCanonicalFileName(sys.useCaseSensitiveFileNames);
const commandLineOptions = convertToOptionsWithAbsolutePaths(
commandLine.options,
fileName => toPath(fileName, currentDirectory, getCanonicalFileName)
);
if (configFileName) {
const configParseResult = Debug.assertDefined(parseConfigFileWithSystem(configFileName, commandLine.options, sys, reportDiagnostic));
const configParseResult = Debug.assertDefined(parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic));
if (isIncrementalCompilation(configParseResult.options)) {
performIncrementalCompilation(sys, configParseResult);
}
@@ -61,10 +68,16 @@ namespace ts {
}
else {
if (isIncrementalCompilation(commandLine.options)) {
performIncrementalCompilation(sys, commandLine);
performIncrementalCompilation(sys, {
...commandLine,
options: commandLineOptions
});
}
else {
performCompilation(sys, commandLine);
performCompilation(sys, {
...commandLine,
options: commandLineOptions
});
}
}
}
@@ -79,6 +92,7 @@ namespace ts {
const { fileNames, options, projectReferences } = config;
const reportDiagnostic = createDiagnosticReporter(sys, options.pretty);
const host = createCompilerHostWorker(options, /*setParentPos*/ undefined, sys);
fakes.patchHostForBuildInfoReadWrite(host);
const currentDirectory = host.getCurrentDirectory();
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName));
@@ -102,7 +116,10 @@ namespace ts {
function performIncrementalCompilation(sys: TscCompileSystem, config: ParsedCommandLine) {
const reportDiagnostic = createDiagnosticReporter(sys, config.options.pretty);
const { options, fileNames, projectReferences } = config;
const host = createIncrementalCompilerHost(options, sys);
fakes.patchHostForBuildInfoReadWrite(host);
const exitCode = ts.performIncrementalCompilation({
host,
system: sys,
rootNames: fileNames,
options,

View File

@@ -0,0 +1,42 @@
namespace ts {
describe("unittests:: tsc:: incremental::", () => {
verifyTscIncrementalEdits({
scenario: "incremental",
subScenario: "when passing filename for buildinfo on commandline",
fs: () => loadProjectFromFiles({
"/src/project/src/main.ts": "export const x = 10;",
"/src/project/tsconfig.json": utils.dedent`
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
},
"include": [
"src/**/*.ts"
]
}`,
}),
commandLineArgs: ["--incremental", "--p", "src/project", "--tsBuildInfoFile", "src/project/.tsbuildinfo"],
incrementalScenarios: [{
buildKind: BuildKind.IncrementalDtsUnchanged,
modifyFs: noop,
}]
});
verifyTsc({
scenario: "incremental",
subScenario: "when passing rootDir from commandline",
fs: () => loadProjectFromFiles({
"/src/project/src/main.ts": "export const x = 10;",
"/src/project/tsconfig.json": utils.dedent`
{
"compilerOptions": {
"incremental": true,
"outDir": "dist",
},
}`,
}),
commandLineArgs: ["--p", "src/project", "--rootDir", "src/project/src"],
});
});
}

View File

@@ -120,7 +120,12 @@ namespace ts {
return sys.exit(ExitStatus.Success);
}
const commandLineOptions = commandLine.options;
const currentDirectory = sys.getCurrentDirectory();
const getCanonicalFileName = createGetCanonicalFileName(sys.useCaseSensitiveFileNames);
const commandLineOptions = convertToOptionsWithAbsolutePaths(
commandLine.options,
fileName => toPath(fileName, currentDirectory, getCanonicalFileName)
);
if (configFileName) {
const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic)!; // TODO: GH#18217
if (commandLineOptions.showConfig) {
@@ -148,7 +153,7 @@ namespace ts {
else {
if (commandLineOptions.showConfig) {
// eslint-disable-next-line no-null/no-null
sys.write(JSON.stringify(convertToTSConfig(commandLine, combinePaths(sys.getCurrentDirectory(), "tsconfig.json"), sys), null, 4) + sys.newLine);
sys.write(JSON.stringify(convertToTSConfig(commandLine, combinePaths(currentDirectory, "tsconfig.json"), sys), null, 4) + sys.newLine);
return sys.exit(ExitStatus.Success);
}
updateReportDiagnostic(commandLineOptions);
@@ -157,7 +162,10 @@ namespace ts {
createWatchOfFilesAndCompilerOptions(commandLine.fileNames, commandLineOptions);
}
else if (isIncrementalCompilation(commandLineOptions)) {
performIncrementalCompilation(commandLine);
performIncrementalCompilation({
...commandLine,
options: commandLineOptions
});
}
else {
performCompilation(commandLine.fileNames, /*references*/ undefined, commandLineOptions);

View File

@@ -0,0 +1,6 @@
//// [/lib/incremental-declaration-doesnt-changeOutput.txt]
/lib/tsc --incremental --p src/project --tsBuildInfoFile src/project/.tsbuildinfo
exitCode:: 0
//// [/src/project/.tsbuildinfo] file written with same contents

View File

@@ -0,0 +1,42 @@
//// [/lib/initial-buildOutput.txt]
/lib/tsc --incremental --p src/project --tsBuildInfoFile src/project/.tsbuildinfo
exitCode:: 0
//// [/src/project/.tsbuildinfo]
{
"program": {
"fileInfos": {
"../../lib/lib.d.ts": {
"version": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };",
"signature": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };"
},
"./src/main.ts": {
"version": "-10726455937-export const x = 10;",
"signature": "-6057683066-export declare const x = 10;\r\n"
}
},
"options": {
"target": 1,
"module": 1,
"incremental": true,
"project": "./",
"tsBuildInfoFile": "./.tsbuildinfo",
"configFilePath": "./tsconfig.json"
},
"referencedMap": {},
"exportedModulesMap": {},
"semanticDiagnosticsPerFile": [
"../../lib/lib.d.ts",
"./src/main.ts"
]
},
"version": "FakeTSVersion"
}
//// [/src/project/src/main.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.x = 10;

View File

@@ -0,0 +1,41 @@
//// [/lib/initial-buildOutput.txt]
/lib/tsc --p src/project --rootDir src/project/src
exitCode:: 0
//// [/src/project/dist/main.js]
"use strict";
exports.__esModule = true;
exports.x = 10;
//// [/src/project/tsconfig.tsbuildinfo]
{
"program": {
"fileInfos": {
"../../lib/lib.d.ts": {
"version": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };",
"signature": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };"
},
"./src/main.ts": {
"version": "-10726455937-export const x = 10;",
"signature": "-6057683066-export declare const x = 10;\r\n"
}
},
"options": {
"incremental": true,
"outDir": "./dist",
"project": "./",
"rootDir": "./src",
"configFilePath": "./tsconfig.json"
},
"referencedMap": {},
"exportedModulesMap": {},
"semanticDiagnosticsPerFile": [
"../../lib/lib.d.ts",
"./src/main.ts"
]
},
"version": "FakeTSVersion"
}