Skip to content

Commit c9d407b

Browse files
authored
Merge pull request microsoft#34403 from microsoft/commandlinePath
Make sure commandline options are absolute paths so they dont conflict with options from tsbuild info
2 parents b7c85c7 + 758bd99 commit c9d407b

File tree

11 files changed

+206
-44
lines changed

11 files changed

+206
-44
lines changed

src/compiler/builder.ts

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,7 +1118,7 @@ namespace ts {
11181118

11191119
const state: ReusableBuilderProgramState = {
11201120
fileInfos,
1121-
compilerOptions: convertFromReusableCompilerOptions(program.options, toAbsolutePath),
1121+
compilerOptions: convertToOptionsWithAbsolutePaths(program.options, toAbsolutePath),
11221122
referencedMap: getMapOfReferencedSet(program.referencedMap, toPath),
11231123
exportedModulesMap: getMapOfReferencedSet(program.exportedModulesMap, toPath),
11241124
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 {
11561156
}
11571157
}
11581158

1159-
function convertFromReusableCompilerOptions(options: CompilerOptions, toAbsolutePath: (path: string) => string) {
1160-
const result: CompilerOptions = {};
1161-
const optionsNameMap = getOptionNameMap().optionNameMap;
1162-
1163-
for (const name in options) {
1164-
if (hasProperty(options, name)) {
1165-
result[name] = convertFromReusableCompilerOptionValue(
1166-
optionsNameMap.get(name.toLowerCase()),
1167-
options[name] as CompilerOptionsValue,
1168-
toAbsolutePath
1169-
);
1170-
}
1171-
}
1172-
if (result.configFilePath) {
1173-
result.configFilePath = toAbsolutePath(result.configFilePath);
1174-
}
1175-
return result;
1176-
}
1177-
1178-
function convertFromReusableCompilerOptionValue(option: CommandLineOption | undefined, value: CompilerOptionsValue, toAbsolutePath: (path: string) => string) {
1179-
if (option) {
1180-
if (option.type === "list") {
1181-
const values = value as readonly (string | number)[];
1182-
if (option.element.isFilePath && values.length) {
1183-
return values.map(toAbsolutePath);
1184-
}
1185-
}
1186-
else if (option.isFilePath) {
1187-
return toAbsolutePath(value as string);
1188-
}
1189-
}
1190-
return value;
1191-
}
1192-
11931159
export function createRedirectedBuilderProgram(state: { program: Program | undefined; compilerOptions: CompilerOptions; }, configFileParsingDiagnostics: readonly Diagnostic[]): BuilderProgram {
11941160
return {
11951161
getState: notImplemented,

src/compiler/commandLineParser.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,6 +2041,41 @@ namespace ts {
20412041
}
20422042
}
20432043

2044+
/* @internal */
2045+
export function convertToOptionsWithAbsolutePaths(options: CompilerOptions, toAbsolutePath: (path: string) => string) {
2046+
const result: CompilerOptions = {};
2047+
const optionsNameMap = getOptionNameMap().optionNameMap;
2048+
2049+
for (const name in options) {
2050+
if (hasProperty(options, name)) {
2051+
result[name] = convertToOptionValueWithAbsolutePaths(
2052+
optionsNameMap.get(name.toLowerCase()),
2053+
options[name] as CompilerOptionsValue,
2054+
toAbsolutePath
2055+
);
2056+
}
2057+
}
2058+
if (result.configFilePath) {
2059+
result.configFilePath = toAbsolutePath(result.configFilePath);
2060+
}
2061+
return result;
2062+
}
2063+
2064+
function convertToOptionValueWithAbsolutePaths(option: CommandLineOption | undefined, value: CompilerOptionsValue, toAbsolutePath: (path: string) => string) {
2065+
if (option) {
2066+
if (option.type === "list") {
2067+
const values = value as readonly (string | number)[];
2068+
if (option.element.isFilePath && values.length) {
2069+
return values.map(toAbsolutePath);
2070+
}
2071+
}
2072+
else if (option.isFilePath) {
2073+
return toAbsolutePath(value as string);
2074+
}
2075+
}
2076+
return value;
2077+
}
2078+
20442079
/**
20452080
* Parse the contents of a config file (tsconfig.json).
20462081
* @param json The contents of the config file to parse

src/harness/fakes.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ ${indentText}${text}`;
524524

525525
export const version = "FakeTSVersion";
526526

527-
export function patchSolutionBuilderHost(host: ts.SolutionBuilderHost<ts.BuilderProgram>, sys: System) {
527+
export function patchHostForBuildInfoReadWrite(host: ts.CompilerHost | ts.SolutionBuilderHost<ts.BuilderProgram>) {
528528
const originalReadFile = host.readFile;
529529
host.readFile = (path, encoding) => {
530530
const value = originalReadFile.call(host, path, encoding);
@@ -537,14 +537,18 @@ ${indentText}${text}`;
537537

538538
if (host.writeFile) {
539539
const originalWriteFile = host.writeFile;
540-
host.writeFile = (fileName, content, writeByteOrderMark) => {
540+
host.writeFile = (fileName: string, content: string, writeByteOrderMark: boolean) => {
541541
if (!ts.isBuildInfoFile(fileName)) return originalWriteFile.call(host, fileName, content, writeByteOrderMark);
542542
const buildInfo = ts.getBuildInfo(content);
543543
sanitizeBuildInfoProgram(buildInfo);
544544
buildInfo.version = version;
545545
originalWriteFile.call(host, fileName, ts.getBuildInfoText(buildInfo), writeByteOrderMark);
546546
};
547547
}
548+
}
549+
550+
export function patchSolutionBuilderHost(host: ts.SolutionBuilderHost<ts.BuilderProgram>, sys: System) {
551+
patchHostForBuildInfoReadWrite(host);
548552

549553
ts.Debug.assert(host.now === undefined);
550554
host.now = () => new Date(sys.vfs.time());

src/testRunner/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
"unittests/tsbuild/watchEnvironment.ts",
114114
"unittests/tsbuild/watchMode.ts",
115115
"unittests/tsc/declarationEmit.ts",
116+
"unittests/tsc/incremental.ts",
116117
"unittests/tscWatch/consoleClearing.ts",
117118
"unittests/tscWatch/emit.ts",
118119
"unittests/tscWatch/emitAndErrorUpdates.ts",

src/testRunner/unittests/tsbuild/helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ interface Symbol {
290290
baselineSourceMap, modifyFs, baselineReadFileCalls,
291291
incrementalScenarios
292292
}: VerifyTsBuildInput) {
293-
describe(`tsc --b ${scenario}:: ${subScenario}`, () => {
293+
describe(`tsc ${commandLineArgs.join(" ")} ${scenario}:: ${subScenario}`, () => {
294294
let tick: () => void;
295295
let sys: TscCompileSystem;
296296
before(() => {

src/testRunner/unittests/tsc/helpers.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,15 @@ namespace ts {
5050

5151
Debug.assert(commandLine.fileNames.length !== 0 || !!configFileName);
5252

53+
const currentDirectory = sys.getCurrentDirectory();
54+
const getCanonicalFileName = createGetCanonicalFileName(sys.useCaseSensitiveFileNames);
55+
const commandLineOptions = convertToOptionsWithAbsolutePaths(
56+
commandLine.options,
57+
fileName => toPath(fileName, currentDirectory, getCanonicalFileName)
58+
);
59+
5360
if (configFileName) {
54-
const configParseResult = Debug.assertDefined(parseConfigFileWithSystem(configFileName, commandLine.options, sys, reportDiagnostic));
61+
const configParseResult = Debug.assertDefined(parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic));
5562
if (isIncrementalCompilation(configParseResult.options)) {
5663
performIncrementalCompilation(sys, configParseResult);
5764
}
@@ -61,10 +68,16 @@ namespace ts {
6168
}
6269
else {
6370
if (isIncrementalCompilation(commandLine.options)) {
64-
performIncrementalCompilation(sys, commandLine);
71+
performIncrementalCompilation(sys, {
72+
...commandLine,
73+
options: commandLineOptions
74+
});
6575
}
6676
else {
67-
performCompilation(sys, commandLine);
77+
performCompilation(sys, {
78+
...commandLine,
79+
options: commandLineOptions
80+
});
6881
}
6982
}
7083
}
@@ -79,6 +92,7 @@ namespace ts {
7992
const { fileNames, options, projectReferences } = config;
8093
const reportDiagnostic = createDiagnosticReporter(sys, options.pretty);
8194
const host = createCompilerHostWorker(options, /*setParentPos*/ undefined, sys);
95+
fakes.patchHostForBuildInfoReadWrite(host);
8296
const currentDirectory = host.getCurrentDirectory();
8397
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
8498
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName));
@@ -102,7 +116,10 @@ namespace ts {
102116
function performIncrementalCompilation(sys: TscCompileSystem, config: ParsedCommandLine) {
103117
const reportDiagnostic = createDiagnosticReporter(sys, config.options.pretty);
104118
const { options, fileNames, projectReferences } = config;
119+
const host = createIncrementalCompilerHost(options, sys);
120+
fakes.patchHostForBuildInfoReadWrite(host);
105121
const exitCode = ts.performIncrementalCompilation({
122+
host,
106123
system: sys,
107124
rootNames: fileNames,
108125
options,
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
namespace ts {
2+
describe("unittests:: tsc:: incremental::", () => {
3+
verifyTscIncrementalEdits({
4+
scenario: "incremental",
5+
subScenario: "when passing filename for buildinfo on commandline",
6+
fs: () => loadProjectFromFiles({
7+
"/src/project/src/main.ts": "export const x = 10;",
8+
"/src/project/tsconfig.json": utils.dedent`
9+
{
10+
"compilerOptions": {
11+
"target": "es5",
12+
"module": "commonjs",
13+
},
14+
"include": [
15+
"src/**/*.ts"
16+
]
17+
}`,
18+
}),
19+
commandLineArgs: ["--incremental", "--p", "src/project", "--tsBuildInfoFile", "src/project/.tsbuildinfo"],
20+
incrementalScenarios: [{
21+
buildKind: BuildKind.IncrementalDtsUnchanged,
22+
modifyFs: noop,
23+
}]
24+
});
25+
26+
verifyTsc({
27+
scenario: "incremental",
28+
subScenario: "when passing rootDir from commandline",
29+
fs: () => loadProjectFromFiles({
30+
"/src/project/src/main.ts": "export const x = 10;",
31+
"/src/project/tsconfig.json": utils.dedent`
32+
{
33+
"compilerOptions": {
34+
"incremental": true,
35+
"outDir": "dist",
36+
},
37+
}`,
38+
}),
39+
commandLineArgs: ["--p", "src/project", "--rootDir", "src/project/src"],
40+
});
41+
});
42+
}

src/tsc/tsc.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,12 @@ namespace ts {
120120
return sys.exit(ExitStatus.Success);
121121
}
122122

123-
const commandLineOptions = commandLine.options;
123+
const currentDirectory = sys.getCurrentDirectory();
124+
const getCanonicalFileName = createGetCanonicalFileName(sys.useCaseSensitiveFileNames);
125+
const commandLineOptions = convertToOptionsWithAbsolutePaths(
126+
commandLine.options,
127+
fileName => toPath(fileName, currentDirectory, getCanonicalFileName)
128+
);
124129
if (configFileName) {
125130
const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic)!; // TODO: GH#18217
126131
if (commandLineOptions.showConfig) {
@@ -148,7 +153,7 @@ namespace ts {
148153
else {
149154
if (commandLineOptions.showConfig) {
150155
// eslint-disable-next-line no-null/no-null
151-
sys.write(JSON.stringify(convertToTSConfig(commandLine, combinePaths(sys.getCurrentDirectory(), "tsconfig.json"), sys), null, 4) + sys.newLine);
156+
sys.write(JSON.stringify(convertToTSConfig(commandLine, combinePaths(currentDirectory, "tsconfig.json"), sys), null, 4) + sys.newLine);
152157
return sys.exit(ExitStatus.Success);
153158
}
154159
updateReportDiagnostic(commandLineOptions);
@@ -157,7 +162,10 @@ namespace ts {
157162
createWatchOfFilesAndCompilerOptions(commandLine.fileNames, commandLineOptions);
158163
}
159164
else if (isIncrementalCompilation(commandLineOptions)) {
160-
performIncrementalCompilation(commandLine);
165+
performIncrementalCompilation({
166+
...commandLine,
167+
options: commandLineOptions
168+
});
161169
}
162170
else {
163171
performCompilation(commandLine.fileNames, /*references*/ undefined, commandLineOptions);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//// [/lib/incremental-declaration-doesnt-changeOutput.txt]
2+
/lib/tsc --incremental --p src/project --tsBuildInfoFile src/project/.tsbuildinfo
3+
exitCode:: 0
4+
5+
6+
//// [/src/project/.tsbuildinfo] file written with same contents
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//// [/lib/initial-buildOutput.txt]
2+
/lib/tsc --incremental --p src/project --tsBuildInfoFile src/project/.tsbuildinfo
3+
exitCode:: 0
4+
5+
6+
//// [/src/project/.tsbuildinfo]
7+
{
8+
"program": {
9+
"fileInfos": {
10+
"../../lib/lib.d.ts": {
11+
"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; };",
12+
"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; };"
13+
},
14+
"./src/main.ts": {
15+
"version": "-10726455937-export const x = 10;",
16+
"signature": "-6057683066-export declare const x = 10;\r\n"
17+
}
18+
},
19+
"options": {
20+
"target": 1,
21+
"module": 1,
22+
"incremental": true,
23+
"project": "./",
24+
"tsBuildInfoFile": "./.tsbuildinfo",
25+
"configFilePath": "./tsconfig.json"
26+
},
27+
"referencedMap": {},
28+
"exportedModulesMap": {},
29+
"semanticDiagnosticsPerFile": [
30+
"../../lib/lib.d.ts",
31+
"./src/main.ts"
32+
]
33+
},
34+
"version": "FakeTSVersion"
35+
}
36+
37+
//// [/src/project/src/main.js]
38+
"use strict";
39+
Object.defineProperty(exports, "__esModule", { value: true });
40+
exports.x = 10;
41+
42+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//// [/lib/initial-buildOutput.txt]
2+
/lib/tsc --p src/project --rootDir src/project/src
3+
exitCode:: 0
4+
5+
6+
//// [/src/project/dist/main.js]
7+
"use strict";
8+
exports.__esModule = true;
9+
exports.x = 10;
10+
11+
12+
//// [/src/project/tsconfig.tsbuildinfo]
13+
{
14+
"program": {
15+
"fileInfos": {
16+
"../../lib/lib.d.ts": {
17+
"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; };",
18+
"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; };"
19+
},
20+
"./src/main.ts": {
21+
"version": "-10726455937-export const x = 10;",
22+
"signature": "-6057683066-export declare const x = 10;\r\n"
23+
}
24+
},
25+
"options": {
26+
"incremental": true,
27+
"outDir": "./dist",
28+
"project": "./",
29+
"rootDir": "./src",
30+
"configFilePath": "./tsconfig.json"
31+
},
32+
"referencedMap": {},
33+
"exportedModulesMap": {},
34+
"semanticDiagnosticsPerFile": [
35+
"../../lib/lib.d.ts",
36+
"./src/main.ts"
37+
]
38+
},
39+
"version": "FakeTSVersion"
40+
}
41+

0 commit comments

Comments
 (0)