Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 172 additions & 55 deletions src/compiler/commandLineParser.ts

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6598,7 +6598,7 @@ namespace ts {
/* @internal */
export interface CommandLineOptionBase {
name: string;
type: "string" | "number" | "boolean" | "object" | "list" | ESMap<string, number | string>; // a value of a primitive type, or an object literal mapping named values to actual values
type: "string" | "number" | "boolean" | "object" | "list" | "listOrElement" | ESMap<string, number | string> ; // a value of a primitive type, or an object literal mapping named values to actual values
isFilePath?: boolean; // True if option value is a path or fileName
shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help'
description?: DiagnosticMessage; // The message describing what the command line switch does.
Expand Down Expand Up @@ -6669,7 +6669,7 @@ namespace ts {

/* @internal */
export interface CommandLineOptionOfListType extends CommandLineOptionBase {
type: "list";
type: "list" | "listOrElement";
element: CommandLineOptionOfCustomType | CommandLineOptionOfStringType | CommandLineOptionOfNumberType | CommandLineOptionOfBooleanType | TsConfigOnlyOption;
listPreserveFalsyValues?: boolean;
}
Expand Down
8 changes: 8 additions & 0 deletions src/executeCommandLine/executeCommandLine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,14 @@ namespace ts {
// TODO: check infinite loop
possibleValues = getPossibleValues(option.element);
break;
case "listOrElement":
if (option.element.type === "string"){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (option.element.type === "string"){
if (option.element.type === "string") {

possibleValues = option.type;
}
else {
possibleValues = getPossibleValues(option.element);
}
break;
case "object":
possibleValues = "";
break;
Expand Down
79 changes: 76 additions & 3 deletions src/testRunner/unittests/config/configurationExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,46 @@ namespace ts {
"dev/tests/unit/spec.ts": "",
"dev/tests/utils.ts": "",
"dev/tests/scenarios/first.json": "",
"dev/tests/baselines/first/output.ts": ""
"dev/tests/baselines/first/output.ts": "",
"dev/configs/extendsArrayFirst.json": JSON.stringify({
compilerOptions: {
allowJs: true,
noImplicitAny: true,
strictNullChecks: true
}
}),
"dev/configs/extendsArraySecond.json": JSON.stringify({
compilerOptions: {
module: "amd"
},
include: ["../supplemental.*"]
}),
"dev/configs/extendsArrayThird.json": JSON.stringify({
compilerOptions: {
module: null, // eslint-disable-line no-null/no-null
noImplicitAny: false
},
include: ["../supplemental.*"]
}),
"dev/configs/extendsArrayFourth.json": JSON.stringify({
compilerOptions: {
module: "system",
strictNullChecks: false
},
include: null, // eslint-disable-line no-null/no-null
files: ["../main.ts"]
}),
"dev/configs/extendsArrayFifth.json": JSON.stringify({
extends: ["./extendsArrayFirst", "./extendsArraySecond", "./extendsArrayThird", "./extendsArrayFourth"],
files: [],
}),
"dev/extendsArrayFails.json": JSON.stringify({
extends: [""],
compilerOptions: {
types: []
}
}),
"dev/extendsArrayFails2.json": JSON.stringify({ extends: [42] }),
}
}
});
Expand Down Expand Up @@ -292,9 +331,9 @@ namespace ts {
messageText: `Unknown option 'excludes'. Did you mean 'exclude'?`
}]);

testFailure("can error when 'extends' is not a string", "extends.json", [{
testFailure("can error when 'extends' is not a string or Array", "extends.json", [{
code: 5024,
messageText: `Compiler option 'extends' requires a value of type string.`
messageText: `Compiler option 'extends' requires a value of type string or Array.`
}]);

testSuccess("can overwrite compiler options using extended 'null'", "configs/third.json", {
Expand Down Expand Up @@ -349,6 +388,40 @@ namespace ts {
assert.deepEqual(sourceFile.extendedSourceFiles, expected);
});
});

describe(testName, () => {
it("adds extendedSourceFiles from an array only once", () => {
const sourceFile = readJsonConfigFile("configs/extendsArrayFifth.json", (path) => host.readFile(path));
const dir = combinePaths(basePath, "configs");
const expected = [
combinePaths(dir, "extendsArrayFirst.json"),
combinePaths(dir, "extendsArraySecond.json"),
combinePaths(dir, "extendsArrayThird.json"),
combinePaths(dir, "extendsArrayFourth.json"),
];
parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, "extendsArrayFifth.json");
assert.deepEqual(sourceFile.extendedSourceFiles, expected);
parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, "extendsArrayFifth.json");
assert.deepEqual(sourceFile.extendedSourceFiles, expected);
});

testSuccess("can overwrite top-level compilerOptions", "configs/extendsArrayFifth.json", {
allowJs: true,
noImplicitAny: false,
strictNullChecks: false,
module: ModuleKind.System
}, []);

testFailure("can report missing configurations", "extendsArrayFails.json", [{
code: 6053,
messageText: `File '' not found.`
}]);

testFailure("can error when 'extends' is not a string or Array2", "extendsArrayFails2.json", [{
code: 5024,
messageText: `Compiler option 'extends' requires a value of type string.`
}]);
});
});
});
}
20 changes: 20 additions & 0 deletions src/testRunner/unittests/config/showConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,26 @@ namespace ts {
}
break;
}
case "listOrElement": {
if (option.isTSConfigOnly) {
args = ["-p", "tsconfig.json"];
if(option.element.type === "string"){
optionValue = { [option.name]: "someString" };
}
else{
optionValue = { [option.name]: [] };
}
}
else {
if(option.element.type === "string"){
args = [`--${option.name}`, "someString"];
}
else{
args = [`--${option.name}`];
}
}
break;
}
case "string": {
if (option.isTSConfigOnly) {
args = ["-p", "tsconfig.json"];
Expand Down
57 changes: 55 additions & 2 deletions src/testRunner/unittests/tsbuildWatch/programUpdates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ export function someFn() { }`),
verifyTscWatch({
scenario: "programUpdates",
subScenario: "works with extended source files",
commandLineArgs: ["-b", "-w", "-v", "project1.tsconfig.json", "project2.tsconfig.json"],
commandLineArgs: ["-b", "-w", "-v", "project1.tsconfig.json", "project2.tsconfig.json", "project3.tsconfig.json"],
sys: () => {
const alphaExtendedConfigFile: File = {
path: "/a/b/alpha.tsconfig.json",
Expand Down Expand Up @@ -602,10 +602,49 @@ export function someFn() { }`),
files: [otherFile.path]
})
};
const otherFile2: File = {
path: "/a/b/other2.ts",
content: "let k = 0;",
};
const extendsConfigFile1: File = {
path: "/a/b/extendsConfig1.tsconfig.json",
content: JSON.stringify({
compilerOptions: {
composite: true,
}
})
};
const extendsConfigFile2: File = {
path: "/a/b/extendsConfig2.tsconfig.json",
content: JSON.stringify({
compilerOptions: {
strictNullChecks: false,
}
})
};
const extendsConfigFile3: File = {
path: "/a/b/extendsConfig3.tsconfig.json",
content: JSON.stringify({
compilerOptions: {
noImplicitAny: true,
}
})
};
const project3Config: File = {
path: "/a/b/project3.tsconfig.json",
content: JSON.stringify({
extends: ["./extendsCnfig1.tsconfig.json", "./extendsConfig2.tsconfig.json", "./extendsConfig3.tsconfig.json"],
compilerOptions: {
composite: false,
},
files: [otherFile.path]
})
};
return createWatchedSystem([
libFile,
alphaExtendedConfigFile, project1Config, commonFile1, commonFile2,
bravoExtendedConfigFile, project2Config, otherFile
bravoExtendedConfigFile, project2Config, otherFile, otherFile2,
extendsConfigFile1, extendsConfigFile2, extendsConfigFile3, project3Config
], { currentDirectory: "/a/b" });
},
changes: [
Expand Down Expand Up @@ -646,6 +685,20 @@ export function someFn() { }`),
change: noop,
timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout // Build project2
},
{
caption: "Modify extendsConfigFile2",
change: sys => sys.writeFile("/a/b/extendsConfig2.tsconfig.json", JSON.stringify({
compilerOptions: { strictNullChecks: true }
})),
timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout // Build project1
},
{
caption: "Modify project 3",
change: sys => sys.writeFile("/a/b/project3.tsconfig.json", JSON.stringify({
extends: ["./extendsConfig1.tsconfig.json", "./extendsConfig2.tsconfig.json"],
})),
timeouts: checkSingleTimeoutQueueLengthAndRun // Build project1
},
]
});

Expand Down
Loading