Skip to content

Commit 82bc7c2

Browse files
author
Orta Therox
authored
Merge pull request #2110 from jablko/patch-14
Add allowed values for list options
2 parents 94f2ad2 + fdccf60 commit 82bc7c2

File tree

1 file changed

+64
-38
lines changed

1 file changed

+64
-38
lines changed

packages/tsconfig-reference/scripts/tsconfigRules.ts

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,24 @@ import * as remark from "remark";
33
import * as remarkHTML from "remark-html";
44
import * as ts from "typescript";
55

6+
interface CommandLineOption {
7+
name: string;
8+
type:
9+
| "string"
10+
| "number"
11+
| "boolean"
12+
| "object"
13+
| "list"
14+
| Map<string, number | string>;
15+
defaultValueDescription?: string | number | boolean | ts.DiagnosticMessage;
16+
element: CommandLineOption;
17+
}
18+
19+
declare module "typescript" {
20+
const optionDeclarations: CommandLineOption[];
21+
const optionsForWatch: CommandLineOption[];
22+
}
23+
624
/**
725
* Changes to these rules should be reflected in the following files:
826
* https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/tsconfig.json
@@ -173,26 +191,17 @@ function trueIf(name: string) {
173191
];
174192
}
175193

176-
// Number/boolean options without explicit default are 0/false
177-
const defaultDefaults = { number: "0", boolean: "false" };
178194
export const defaultsForOptions = {
179195
...Object.fromEntries(
180-
ts.optionDeclarations
181-
.filter(
182-
(option) =>
183-
("defaultValueDescription" in option &&
184-
option.defaultValueDescription !== "n/a") ||
185-
option.type in defaultDefaults
186-
)
187-
.map((option) => [
188-
option.name,
189-
!("defaultValueDescription" in option) ||
190-
option.defaultValueDescription === "n/a"
191-
? defaultDefaults[option.type]
192-
: typeof option.defaultValueDescription === "string"
193-
? option.defaultValueDescription
194-
: option.defaultValueDescription.message,
195-
])
196+
ts.optionDeclarations.map((option) => [
197+
option.name,
198+
typeof option.defaultValueDescription === "object"
199+
? option.defaultValueDescription.message
200+
: formatDefaultValue(
201+
option.defaultValueDescription,
202+
option.type === "list" ? option.element.type : option.type
203+
),
204+
])
196205
),
197206
allowSyntheticDefaultImports: [
198207
"`true` if [`module`](#module) is `system`, or [`esModuleInterop`](#esModuleInterop) and [`module`](#module) is not `es6`/`es2015` or `esnext`,",
@@ -222,7 +231,7 @@ export const defaultsForOptions = {
222231
newLine: "Platform specific.",
223232
noImplicitAny: trueIf("strict"),
224233
noImplicitThis: trueIf("strict"),
225-
preserveConstEnums: "false",
234+
preserveConstEnums: trueIf("isolatedModules"),
226235
reactNamespace: "React",
227236
rootDir: "Computed from the list of input files.",
228237
rootDirs: "Computed from the list of input files.",
@@ -238,31 +247,48 @@ export const defaultsForOptions = {
238247
],
239248
};
240249

250+
function formatDefaultValue(
251+
defaultValue: CommandLineOption["defaultValueDescription"],
252+
type: CommandLineOption["type"]
253+
) {
254+
if (defaultValue === undefined || typeof type !== "object")
255+
return defaultValue;
256+
// e.g. ScriptTarget.ES2015 -> "es6/es2015"
257+
const synonyms = [...type]
258+
.filter(([, value]) => value === defaultValue)
259+
.map(([name]) => name);
260+
return synonyms.length > 1
261+
? synonyms.map((name) => `\`${name}\``).join("/")
262+
: synonyms[0];
263+
}
264+
241265
export const allowedValues = {
242266
...Object.fromEntries(
243-
[...ts.optionDeclarations, ...ts.optionsForWatch]
244-
.filter((option) => typeof option.type === "object")
245-
.map((option) => {
246-
// Group and format synonyms: `es6`/`es2015`
247-
const byValue: { [value: number]: string[] } = {};
248-
for (const [name, value] of option.type instanceof Map
249-
? option.type.entries()
250-
: Object.entries(option.type)) {
251-
(byValue[value] ||= []).push(name);
252-
}
253-
return [
254-
option.name,
255-
Object.values(byValue).map((synonyms) =>
256-
synonyms.length > 1
257-
? synonyms.map((name) => `\`${name}\``).join("/")
258-
: synonyms[0]
259-
),
260-
];
261-
})
267+
[...ts.optionDeclarations, ...ts.optionsForWatch].map((option) => [
268+
option.name,
269+
formatAllowedValues(
270+
option.type === "list" ? option.element.type : option.type
271+
),
272+
])
262273
),
263274
jsxFactory: ["Any identifier or dotted identifier."],
275+
lib: undefined,
264276
};
265277

278+
function formatAllowedValues(type: CommandLineOption["type"]) {
279+
if (typeof type !== "object") return;
280+
// Group and format synonyms: `es6`/`es2015`
281+
const inverted: { [value: string]: string[] } = {};
282+
for (const [name, value] of type) {
283+
(inverted[value] ||= []).push(name);
284+
}
285+
return Object.values(inverted).map((synonyms) =>
286+
synonyms.length > 1
287+
? synonyms.map((name) => `\`${name}\``).join("/")
288+
: synonyms[0]
289+
);
290+
}
291+
266292
export const releaseToConfigsMap: { [key: string]: AnOption[] } = {
267293
"4.5": ["preserveValueImports"],
268294
"4.4": ["exactOptionalPropertyTypes", "useUnknownInCatchVariables"],

0 commit comments

Comments
 (0)