diff --git a/Herebyfile.mjs b/Herebyfile.mjs index 33ae679c70fc9..9ddcbdec35820 100644 --- a/Herebyfile.mjs +++ b/Herebyfile.mjs @@ -6,6 +6,7 @@ import { task } from "hereby"; import assert from "node:assert"; import crypto from "node:crypto"; import fs from "node:fs"; +import { createRequire } from "node:module"; import os from "node:os"; import path from "node:path"; import url from "node:url"; @@ -472,10 +473,18 @@ export const generateChecker = goGenerateTask("generate:checker", [ stringerGenerator("tsc/internal/checker/types.go", "SignatureKind", "stringer_generated.go"), ]); -export const generateCompilerOptions = goGenerateTask("generate:compileroptions", [ - stringerGenerator("tsc/internal/core/compileroptions.go", "ModuleKind", "modulekind_stringer_generated.go", "ModuleKind"), - stringerGenerator("tsc/internal/core/compileroptions.go", "ScriptTarget", "scripttarget_stringer_generated.go", "ScriptTarget"), -]); +async function runGenerateOptionDefinitions() { + const { default: generate } = await import("./tools/scripts/tsc/generate-options.ts"); + await generate(!!options.force); +} + +export const generateCompilerOptions = goGenerateTask("generate:compileroptions", async () => { + await runGenerateOptionDefinitions(); + await runGoGenerator("generate:compileroptions", stringerGenerator("tsc/internal/core/options_generated.go", "ModuleKind", "modulekind_stringer_generated.go", "ModuleKind")); + await runGoGenerator("generate:compileroptions", stringerGenerator("tsc/internal/core/options_generated.go", "ScriptTarget", "scripttarget_stringer_generated.go", "ScriptTarget")); + await runGenerateEnums(); + await runGenerateAPI(); +}); export const generateLanguageVariant = goGenerateTask("generate:languagevariant", [ stringerGenerator("tsc/internal/core/languagevariant.go", "LanguageVariant", "languagevariant_stringer_generated.go"), @@ -628,7 +637,7 @@ async function runGenerateEnums() { export const generateEnums = task({ name: "generate:enums", - description: "Generates TypeScript enum files from Go source. Pass --force to regenerate unchanged files.", + description: "Generates TypeScript enums from metadata and Go source. Pass --force to regenerate unchanged files.", run: runGenerateEnums, }); @@ -656,6 +665,7 @@ export const generateSync = task({ }); async function runGenerateAPI() { + await runGenerateOptionDefinitions(); await runGoGenerator("generate:api", { file: "tsc/internal/api/proto.go", cwd: __dirname, @@ -668,7 +678,7 @@ async function runGenerateAPI() { "tsc/internal/tspath/path.go", "tools/gen-proto/*.go", ], - exclude: ["**/*_test.go", "**/*_generated.go"], + exclude: ["**/*_test.go"], envInputs: [], outputs: ["packages/typescript/src/api/proto.generated.ts"], commands: [ @@ -964,7 +974,7 @@ export const testCodegen = task({ description: "Runs incremental codegen tests.", run: async () => { await run("go", ["-C", "tsc", "mod", "download"]); - await run("node", ["--test", "--test-concurrency=1", "./tools/scripts/gen/*.test.mts"]); + await run("node", ["--test", "--test-concurrency=1", "./tools/scripts/gen/*.test.mts", "./tools/scripts/tsc/*.test.ts"]); }, }); @@ -1170,6 +1180,9 @@ export const validate = task({ } if (options.all) { await runValidation("test:tools", runTestTools); + await runValidation("test:options", async () => { + await run("node", ["--test", "./tools/scripts/tsc/options.test.ts"]); + }); await runValidation("test:smoke", runSmokeTest); // in CI this is run with `--race` } await runValidation("lint", runLint); @@ -2237,6 +2250,7 @@ async function runBuildNativePreviewPackages() { // Copy package contents excluding node_modules and dist (dist is copied separately after build). // The package.json "files" field controls what npm pack actually includes. await cpRecursive(inputDir, mainPackageDir, p => !p.endsWith("/node_modules") && !p.includes("/dist")); + await cpRecursive("tsc/internal/tsoptions/schemas", path.join(mainPackageDir, "schemas")); if (publishAsTypescript) { await fs.promises.writeFile(path.join(mainPackageDir, "bin", "tsc"), '#!/usr/bin/env node\nimport "../lib/tsc.js";\n'); await fs.promises.chmod(path.join(mainPackageDir, "bin", "tsc"), 0o755); @@ -2354,6 +2368,20 @@ async function testNativePreviewPackage(platforms) { await cpRecursive(hostPlatform.npmDir, platformPackageDir); await fs.promises.writeFile(sourceFile, 'export const value: string = "value";\n'); + const require = createRequire(sourceFile); + const { stdout } = await runOutput("npm", ["pack", "--dry-run", "--json", mainPackageDir]); + /** @type {{ files: { path: string }[] }[]} */ + const packed = JSON.parse(stdout); + for (const name of ["tsconfig", "jsconfig"]) { + const schemaPath = `schemas/${name}.schema.json`; + assert(packed[0].files.some(file => file.path === schemaPath), `Package is missing ${schemaPath}`); + assert.deepEqual( + await fs.promises.readFile(path.join(mainPackageDir, schemaPath)), + await fs.promises.readFile(path.join("tsc/internal/tsoptions/schemas", `${name}.schema.json`)), + ); + assert.equal(require.resolve(`${mainNativePreviewPackage.npmPackageName}/${schemaPath}`), path.join(mainPackageDir, schemaPath)); + } + const binName = publishAsTypescript ? "tsc" : "tsgo"; const binPath = path.join(mainPackageDir, "bin", binName); const { stdout: versionOutput } = await runOutput(process.execPath, [binPath, "--version"]); diff --git a/packages/typescript/package.json b/packages/typescript/package.json index 5e26fd27a4524..dac74ea78b24d 100644 --- a/packages/typescript/package.json +++ b/packages/typescript/package.json @@ -29,6 +29,7 @@ "files": [ "bin", "lib", + "schemas", "dist", "vendor" ], @@ -37,6 +38,8 @@ }, "exports": { "./package.json": "./package.json", + "./schemas/tsconfig.schema.json": "./schemas/tsconfig.schema.json", + "./schemas/jsconfig.schema.json": "./schemas/jsconfig.schema.json", ".": "./lib/version.cjs", "./unstable/sync": { "@typescript/source": "./src/api/sync/api.ts", diff --git a/packages/typescript/src/enums/jsxEmit.enum.ts b/packages/typescript/src/enums/jsxEmit.enum.ts index 45ce98bf97af9..0a728dceeef31 100644 --- a/packages/typescript/src/enums/jsxEmit.enum.ts +++ b/packages/typescript/src/enums/jsxEmit.enum.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/core/compileroptions.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/options.ts. DO NOT EDIT. export enum JsxEmit { None = 0, diff --git a/packages/typescript/src/enums/jsxEmit.ts b/packages/typescript/src/enums/jsxEmit.ts index d60d2e075b09e..4c5aa9d989f47 100644 --- a/packages/typescript/src/enums/jsxEmit.ts +++ b/packages/typescript/src/enums/jsxEmit.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/core/compileroptions.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/options.ts. DO NOT EDIT. export var JsxEmit: any; (function (JsxEmit) { JsxEmit[JsxEmit["None"] = 0] = "None"; diff --git a/packages/typescript/src/enums/moduleDetectionKind.enum.ts b/packages/typescript/src/enums/moduleDetectionKind.enum.ts index 04054993dfecb..3c857ba6bff33 100644 --- a/packages/typescript/src/enums/moduleDetectionKind.enum.ts +++ b/packages/typescript/src/enums/moduleDetectionKind.enum.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/core/compileroptions.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/options.ts. DO NOT EDIT. export enum ModuleDetectionKind { None = 0, diff --git a/packages/typescript/src/enums/moduleDetectionKind.ts b/packages/typescript/src/enums/moduleDetectionKind.ts index dcce48831accc..aef2c39903baf 100644 --- a/packages/typescript/src/enums/moduleDetectionKind.ts +++ b/packages/typescript/src/enums/moduleDetectionKind.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/core/compileroptions.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/options.ts. DO NOT EDIT. export var ModuleDetectionKind: any; (function (ModuleDetectionKind) { ModuleDetectionKind[ModuleDetectionKind["None"] = 0] = "None"; diff --git a/packages/typescript/src/enums/moduleKind.enum.ts b/packages/typescript/src/enums/moduleKind.enum.ts index 0c80df5e49c5a..4ecadf2728b42 100644 --- a/packages/typescript/src/enums/moduleKind.enum.ts +++ b/packages/typescript/src/enums/moduleKind.enum.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/core/compileroptions.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/options.ts. DO NOT EDIT. export enum ModuleKind { None = 0, diff --git a/packages/typescript/src/enums/moduleKind.ts b/packages/typescript/src/enums/moduleKind.ts index 314bff60b2ae5..242fe2a27253c 100644 --- a/packages/typescript/src/enums/moduleKind.ts +++ b/packages/typescript/src/enums/moduleKind.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/core/compileroptions.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/options.ts. DO NOT EDIT. export var ModuleKind: any; (function (ModuleKind) { ModuleKind[ModuleKind["None"] = 0] = "None"; diff --git a/packages/typescript/src/enums/moduleResolutionKind.enum.ts b/packages/typescript/src/enums/moduleResolutionKind.enum.ts index be32672b9750e..51ef127a5864f 100644 --- a/packages/typescript/src/enums/moduleResolutionKind.enum.ts +++ b/packages/typescript/src/enums/moduleResolutionKind.enum.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/core/compileroptions.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/options.ts. DO NOT EDIT. export enum ModuleResolutionKind { Unknown = 0, diff --git a/packages/typescript/src/enums/moduleResolutionKind.ts b/packages/typescript/src/enums/moduleResolutionKind.ts index f4e8040517e5a..83a8decbd0cc5 100644 --- a/packages/typescript/src/enums/moduleResolutionKind.ts +++ b/packages/typescript/src/enums/moduleResolutionKind.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/core/compileroptions.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/options.ts. DO NOT EDIT. export var ModuleResolutionKind: any; (function (ModuleResolutionKind) { ModuleResolutionKind[ModuleResolutionKind["Unknown"] = 0] = "Unknown"; diff --git a/packages/typescript/src/enums/newLineKind.enum.ts b/packages/typescript/src/enums/newLineKind.enum.ts index 56d8ac4a4fdd1..2195a93ee3b0a 100644 --- a/packages/typescript/src/enums/newLineKind.enum.ts +++ b/packages/typescript/src/enums/newLineKind.enum.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/core/compileroptions.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/options.ts. DO NOT EDIT. export enum NewLineKind { None = 0, diff --git a/packages/typescript/src/enums/newLineKind.ts b/packages/typescript/src/enums/newLineKind.ts index 07489d55ac38d..f36d2e22b163c 100644 --- a/packages/typescript/src/enums/newLineKind.ts +++ b/packages/typescript/src/enums/newLineKind.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/core/compileroptions.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/options.ts. DO NOT EDIT. export var NewLineKind: any; (function (NewLineKind) { NewLineKind[NewLineKind["None"] = 0] = "None"; diff --git a/packages/typescript/src/enums/scriptTarget.enum.ts b/packages/typescript/src/enums/scriptTarget.enum.ts index beef0f0eeab76..d801bd2b12ca6 100644 --- a/packages/typescript/src/enums/scriptTarget.enum.ts +++ b/packages/typescript/src/enums/scriptTarget.enum.ts @@ -1,3 +1,5 @@ +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/options.ts. DO NOT EDIT. + export enum ScriptTarget { ES2015 = 2, ES2016 = 3, diff --git a/packages/typescript/src/enums/scriptTarget.ts b/packages/typescript/src/enums/scriptTarget.ts index d750cba77a4bb..7fc873d272c70 100644 --- a/packages/typescript/src/enums/scriptTarget.ts +++ b/packages/typescript/src/enums/scriptTarget.ts @@ -1,3 +1,4 @@ +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/options.ts. DO NOT EDIT. export var ScriptTarget: any; (function (ScriptTarget) { ScriptTarget[ScriptTarget["ES2015"] = 2] = "ES2015"; diff --git a/packages/typescript/src/enums/syntaxKind.enum.ts b/packages/typescript/src/enums/syntaxKind.enum.ts index 5406e8d451380..eaf870fa6ea58 100644 --- a/packages/typescript/src/enums/syntaxKind.enum.ts +++ b/packages/typescript/src/enums/syntaxKind.enum.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/ast/kind_generated.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/ast.json. DO NOT EDIT. export enum SyntaxKind { Unknown = 0, diff --git a/packages/typescript/src/enums/syntaxKind.ts b/packages/typescript/src/enums/syntaxKind.ts index f1076f6dcbdf5..534d19efff25c 100644 --- a/packages/typescript/src/enums/syntaxKind.ts +++ b/packages/typescript/src/enums/syntaxKind.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/ast/kind_generated.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/ast.json. DO NOT EDIT. export var SyntaxKind: any; (function (SyntaxKind) { SyntaxKind[SyntaxKind["Unknown"] = 0] = "Unknown"; diff --git a/tools/scripts/gen/generatedFile.test.mts b/tools/scripts/gen/generatedFile.test.mts index e8c256a58b451..d8b31a5f57926 100644 --- a/tools/scripts/gen/generatedFile.test.mts +++ b/tools/scripts/gen/generatedFile.test.mts @@ -60,6 +60,11 @@ test("validate generates before building and selects the generation scope", asyn runTestAPI: action("test:api"), runTestBenchmarks: action("test:benchmarks"), runTestTools: action("test:tools"), + run: async (command: string, args: string[]) => { + assert.equal(command, "node"); + assert.deepEqual(Array.from(args), ["--test", "./tools/scripts/tsc/options.test.ts"]); + calls.push("test:options"); + }, runSmokeTest: action("test:smoke"), runLint: action("lint"), runFormat: action("format"), @@ -71,6 +76,7 @@ test("validate generates before building and selects the generation scope", asyn assert.ok(calls.indexOf("build") < calls.indexOf("test:tsc")); assert.equal(calls.includes("test:api"), "api" in options || "all" in options); assert.equal(calls.includes("test:tools"), "all" in options); + assert.equal(calls.includes("test:options"), "all" in options); if ("all" in options) { assert.deepEqual(calls.filter(name => name.startsWith("generate")), ["generate"]); } @@ -349,7 +355,7 @@ test("generate:go runs Go generators directly and shares caches with Go fallback const generate = () => x("npx", ["hereby", "generate:go"], { throwOnError: true, nodeOptions: { cwd: root } }); const first = await generate(); assert.doesNotMatch(first.stdout, /\$ go generate|npm run --silent cache|\$ node .*generate-unicode-data/); - const files = fs.globSync(["tsc/internal/**/*generated.go", "packages/typescript/src/api/proto.generated.ts"], { cwd: root }); + const files = fs.globSync(["tsc/internal/**/*generated.go", "packages/typescript/src/api/proto.generated.ts", "packages/typescript/src/enums/*.ts", "tsc/internal/tsoptions/schemas/*.schema.json"], { cwd: root }); const timestamps = files.map(file => fs.statSync(path.join(root, file)).mtimeMs); const current = await generate(); assert.doesNotMatch(current.stdout, /Generated codegen outputs|Generated Unicode tables/); @@ -358,7 +364,8 @@ test("generate:go runs Go generators directly and shares caches with Go fallback const fallback = await x("go", ["-C", "./tsc", "generate", "./internal/diagnostics"], { throwOnError: true, nodeOptions: { cwd: root } }); assert.equal(fallback.stdout.match(/codegen outputs are already up to date/g)?.length, 2); const nested = await x("npx", ["hereby", "generate:compileroptions"], { throwOnError: true, nodeOptions: { cwd: path.join(root, "tsc/internal/core") } }); - assert.equal(nested.stdout.match(/codegen outputs are already up to date/g)?.length, 2); + assert.equal(nested.stdout.match(/codegen outputs are already up to date/g)?.length, 3); + assert.match(nested.stdout, /Enums are up to date/); }); test("generate includes standalone generators without Go traversal", async () => { @@ -778,6 +785,21 @@ test("enum generation skips unchanged outputs and Go verification", async () => const regenerated = await generate(); assert.match(regenerated.stdout, /All generated values match Go\./); assert.match((await generate()).stdout, /Enums are up to date\./); + + const astSchema = path.join(root, "tools/scripts/tsc/ast.json"); + const originalSchema = fs.readFileSync(astSchema, "utf8"); + const goKinds = path.join(root, "tsc/internal/ast/kind_generated.go"); + const goKindsTimestamp = fs.statSync(goKinds).mtimeMs; + try { + fs.writeFileSync(astSchema, originalSchema + "\n"); + assert.match((await generate()).stdout, /All generated values match Go\./); + assert.equal(fs.statSync(goKinds).mtimeMs, goKindsTimestamp); + assert.match((await generate()).stdout, /Enums are up to date\./); + } + finally { + fs.writeFileSync(astSchema, originalSchema); + await generate(); + } }); test("AST generation forwards force to schema generators and the kind stringer", async () => { diff --git a/tools/scripts/tsc/generate-enums.ts b/tools/scripts/tsc/generate-enums.ts index e79cfc8c571a8..485a0a31e1895 100644 --- a/tools/scripts/tsc/generate-enums.ts +++ b/tools/scripts/tsc/generate-enums.ts @@ -10,6 +10,9 @@ import { repoRoot as ROOT, run, } from "../gen/utils.mts"; +import generateOptions from "./generate-options.ts"; +import { options } from "./options.ts"; +import { api } from "./schema.ts"; function runOutput(command: string, args: readonly string[]) { return run(command, args, { captureOutput: true, cwd: ROOT }); @@ -21,12 +24,13 @@ interface EnumDef { goFile: string; outDir: string; fileName?: string | undefined; + metadata?: { file: string; members: EnumMember[]; } | undefined; stringEnum?: boolean | undefined; excludeMembers?: readonly string[] | undefined; valueReplacements?: Record | undefined; } -const enumDefs = [ +export const enumDefs = [ { name: "SymbolFlags", goPrefix: "SymbolFlags", goFile: "tsc/internal/ast/symbolflags.go", outDir: "packages/typescript/src/enums" }, { name: "CheckFlags", goPrefix: "CheckFlags", goFile: "tsc/internal/ast/checkflags.go", outDir: "packages/typescript/src/enums" }, { name: "TypeFlags", goPrefix: "TypeFlags", goFile: "tsc/internal/checker/types.go", outDir: "packages/typescript/src/enums" }, @@ -38,16 +42,27 @@ const enumDefs = [ { name: "TypePredicateKind", goPrefix: "TypePredicateKind", goFile: "tsc/internal/checker/types.go", outDir: "packages/typescript/src/enums" }, { name: "TypeFormatFlags", goPrefix: "TypeFormatFlags", goFile: "tsc/internal/checker/types.go", outDir: "packages/typescript/src/enums" }, { name: "DiagnosticCategory", goPrefix: "Category", goFile: "tsc/internal/diagnostics/diagnostics.go", outDir: "packages/typescript/src/enums" }, - { name: "SyntaxKind", goPrefix: "Kind", goFile: "tsc/internal/ast/kind_generated.go", outDir: "packages/typescript/src/enums" }, + { + name: "SyntaxKind", + goPrefix: "Kind", + goFile: "tsc/internal/ast/kind_generated.go", + outDir: "packages/typescript/src/enums", + metadata: { file: "tools/scripts/tsc/ast.json", members: syntaxKindMembers() }, + }, { name: "NodeFlags", goPrefix: "NodeFlags", goFile: "tsc/internal/ast/nodeflags.go", outDir: "packages/typescript/src/enums" }, { name: "OuterExpressionKinds", goPrefix: "OEK", goFile: "tsc/internal/ast/utilities.go", outDir: "packages/typescript/src/enums" }, { name: "JSDeclarationKind", goPrefix: "JSDeclarationKind", goFile: "tsc/internal/ast/utilities.go", outDir: "packages/typescript/src/enums", fileName: "jsDeclarationKind" }, { name: "ModifierFlags", goPrefix: "ModifierFlags", goFile: "tsc/internal/ast/modifierflags.go", outDir: "packages/typescript/src/enums" }, - { name: "ModuleKind", goPrefix: "ModuleKind", goFile: "tsc/internal/core/compileroptions.go", outDir: "packages/typescript/src/enums" }, - { name: "ModuleResolutionKind", goPrefix: "ModuleResolutionKind", goFile: "tsc/internal/core/compileroptions.go", outDir: "packages/typescript/src/enums" }, - { name: "ModuleDetectionKind", goPrefix: "ModuleDetectionKind", goFile: "tsc/internal/core/compileroptions.go", outDir: "packages/typescript/src/enums" }, - { name: "NewLineKind", goPrefix: "NewLineKind", goFile: "tsc/internal/core/compileroptions.go", outDir: "packages/typescript/src/enums" }, - { name: "JsxEmit", goPrefix: "JsxEmit", goFile: "tsc/internal/core/compileroptions.go", outDir: "packages/typescript/src/enums" }, + ...options.enums.filter(enumDef => enumDef.api).map(enumDef => ({ + name: enumDef.name, + goPrefix: enumDef.name, + goFile: "tsc/internal/core/options_generated.go", + outDir: "packages/typescript/src/enums", + metadata: { + file: "tools/scripts/tsc/options.ts", + members: enumDef.members.filter(member => !member.excludeFromAPI).map(member => ({ name: member.name, value: String(member.value) })), + }, + })), { name: "ScriptKind", goPrefix: "ScriptKind", goFile: "tsc/internal/core/scriptkind.go", outDir: "packages/typescript/src/enums" }, { name: "TokenFlags", goPrefix: "TokenFlags", goFile: "tsc/internal/ast/tokenflags.go", outDir: "packages/typescript/src/enums" }, { name: "DiagnosticDirectivePolicy", goPrefix: "MappedDiagnosticDirectivePolicy", goFile: "tsc/internal/ast/ast.go", outDir: "packages/typescript/src/enums" }, @@ -62,6 +77,11 @@ const enumDefs = [ { name: "InternalSymbolName", goPrefix: "InternalSymbolName", goFile: "tsc/internal/ast/symbol.go", outDir: "packages/typescript/src/enums", stringEnum: true, valueReplacements: { InternalSymbolNamePrefix: "__" } }, ] satisfies EnumDef[]; +function syntaxKindMembers(): EnumMember[] { + const members = api.kindElements().flatMap(element => element.name ? [element.name] : []).map((name, value) => ({ name, value: String(value) })); + return [...members, { name: "Count", value: String(members.length) }, ...api.kindMarkers()]; +} + function parseGoConstBlock(block: string, def: EnumDef): EnumMember[] { const prefix = def.goPrefix; const members: EnumMember[] = []; @@ -335,12 +355,20 @@ function topoSortMembers(members: EnumMember[]): EnumMember[] { } function renderEnumTS(def: EnumDef, members: EnumMember[]): string { - const header = `// Code generated by tools/scripts/tsc/generate-enums.ts from ${def.goFile}. DO NOT EDIT.\n\n`; + const source = def.metadata?.file ?? def.goFile; + const header = `// Code generated by tools/scripts/tsc/generate-enums.ts from ${source}. DO NOT EDIT.\n\n`; const lines = members.map(m => ` ${m.name} = ${m.value},`); return `${header}export enum ${def.name} {\n${lines.join("\n")}\n}\n`; } +export function generateEnum(def: EnumDef): { members: EnumMember[]; code: string; } { + const members = def.metadata + ? topoSortMembers(def.metadata.members) + : parseGoEnum(def); + return { members, code: renderEnumTS(def, members) }; +} + const enumValuesGeneratedGoPath = path.join(ROOT, "tsc/internal/api/enum_values_generated.go"); interface GeneratedEnum { @@ -448,17 +476,23 @@ async function evaluateEnumMembers(enumSource: string, enumName: string): Promis } export default async function generateEnums(force = false) { + await generateOptions(force); const inputs = [ import.meta.filename, + path.join(import.meta.dirname, "options.ts"), + path.join(import.meta.dirname, "options-model.ts"), + path.join(import.meta.dirname, "schema.ts"), ...goInputs(), ]; const enumFiles = enumDefs.map(def => { const camelName = def.fileName ?? def.name.charAt(0).toLowerCase() + def.name.slice(1); + const enumInputs = [...inputs, path.join(ROOT, def.goFile)]; + if (def.metadata) enumInputs.push(path.join(ROOT, def.metadata.file)); return { def, camelName, - typeFile: new GeneratedFile(path.join(ROOT, def.outDir, `${camelName}.enum.ts`), [...inputs, path.join(ROOT, def.goFile)]), - runtimeFile: new GeneratedFile(path.join(ROOT, def.outDir, `${camelName}.ts`), [...inputs, path.join(ROOT, def.goFile)]), + typeFile: new GeneratedFile(path.join(ROOT, def.outDir, `${camelName}.enum.ts`), enumInputs), + runtimeFile: new GeneratedFile(path.join(ROOT, def.outDir, `${camelName}.ts`), enumInputs), }; }); const generatedGoFile = new GeneratedFile(enumValuesGeneratedGoPath, [...inputs, ...enumDefs.map(def => path.join(ROOT, def.goFile))]); @@ -484,13 +518,12 @@ export default async function generateEnums(force = false) { ); } - console.log("Generating enums from Go source..."); + console.log("Generating enums from metadata and Go source..."); const generatedEnums: GeneratedEnum[] = []; for (const { def, camelName, typeFile, runtimeFile } of enumFiles) { - const members = parseGoEnum(def); + const { members, code: enumTS } = generateEnum(def); // Generate .enum.ts (TypeScript enum — used for types) - const enumTS = renderEnumTS(def, members); typeFile.write(enumTS); // Generate .ts (IIFE — used at runtime) diff --git a/tools/scripts/tsc/generate-options.ts b/tools/scripts/tsc/generate-options.ts new file mode 100644 index 0000000000000..61228accd603d --- /dev/null +++ b/tools/scripts/tsc/generate-options.ts @@ -0,0 +1,663 @@ +import assert from "node:assert/strict"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { GeneratedFile } from "../gen/generatedFile.mts"; +import { + formatFiles, + parseGeneratorArgs, + repoRoot, +} from "../gen/utils.mts"; +import { + type CompilerOption, + type Declaration, + fieldName, + type GoValue, + optionKind, + type OptionsModel, + type StoredDeclaration, +} from "./options-model.ts"; +import { generateConfigSchema } from "./options-schema.ts"; +import { options } from "./options.ts"; + +export { generateConfigSchema } from "./options-schema.ts"; + +const header = "// Code generated by tools/scripts/tsc/generate-options.ts. DO NOT EDIT.\n"; +const sourceFiles = ["generate-options.ts", "options.ts", "options-model.ts", "options-schema.ts"]; +const diagnosticsFile = path.join(repoRoot, "tsc/internal/diagnostics/diagnosticMessages.json"); + +export function goValue(value: GoValue | { go: string; }): string { + return typeof value === "object" ? value.go : JSON.stringify(value); +} + +export function compilerDeclarations(model = options) { + return model.compilerOptions.flatMap(option => + (option.declarations ?? []).map(declaration => ({ + name: option.name, + kind: optionKind(option), + ...declaration, + })) + ); +} + +function orderByName(items: T[], order: string[], group: string): T[] { + const names = new Set(items.map(item => item.name)); + const orderedNames = new Set(order); + assert.equal(orderedNames.size, order.length, `Duplicate option in ${group} order`); + for (const name of order) { + assert(names.has(name), `Unknown option in ${group} order: ${name}`); + } + const missing = [...names].filter(name => !orderedNames.has(name)); + assert.equal(missing.length, 0, `Missing options in ${group} order: ${missing.join(", ")}`); + return order.flatMap(name => items.filter(item => item.name === name)); +} + +export function validateOptions(model: OptionsModel): void { + const constants = new Set(); + const enumNames = new Set(); + for (const enumDef of model.enums) { + assert(!enumNames.has(enumDef.name), `Duplicate enum: ${enumDef.name}`); + enumNames.add(enumDef.name); + for (const member of enumDef.members) { + const constant = `core.${enumDef.name}${member.name}`; + assert(!constants.has(constant), `Duplicate enum member: ${constant}`); + if (typeof member.value === "string") { + assert(constants.has(`core.${enumDef.name}${member.value}`), `Unknown enum alias: ${constant}`); + } + else assert(Number.isInteger(member.value), `Invalid enum value: ${constant}`); + constants.add(constant); + } + } + const names = new Set(); + const fields = new Set(); + for (const option of model.compilerOptions) { + for (const name of [option.name, ...(option.parseAliases ?? [])]) { + assert(!names.has(name.toLowerCase()), `Duplicate compiler option: ${name}`); + names.add(name.toLowerCase()); + } + assert(!fields.has(fieldName(option)), `Duplicate compiler field: ${fieldName(option)}`); + fields.add(fieldName(option)); + if (optionKind(option) === "Enum") assert(enumNames.has(option.type), `Unknown enum type: ${option.type}`); + if (option.jsconfigDefault !== undefined) { + const expected = option.type === "Tristate" ? "boolean" : option.type === "*int" ? "number" : "string"; + assert.equal(typeof option.jsconfigDefault, expected, `Invalid jsconfig default: ${option.name}`); + } + } + for (const group of [model.watchOptions, model.typeAcquisition, model.buildOptions]) { + const fields = group.flatMap(option => option.field ? [option.field.name] : []); + assert.equal(new Set(fields).size, fields.length, "Duplicate stored option field"); + for (const option of group) { + if (option.field) assert.equal(optionKind({ name: option.name, type: option.field.type }), option.kind, `Mismatched field type: ${option.name}`); + } + } + const compiler = compilerDeclarations(model); + for (const group of ["commonOptionsWithBuild", "optionsForCompiler"] as const) { + orderByName(compiler.filter(declaration => declaration.group === group), model.declarationOrder[group], group); + } + orderByName(model.buildOptions.filter(option => option.field), model.buildOptionFieldOrder, "BuildOptions fields"); + const declarations = [...compiler, ...model.watchOptions, ...model.typeAcquisition, ...model.buildOptions, ...model.rootOptions, ...Object.values(model.elements)]; + for (const declaration of declarations) { + if (declaration.kind === "Enum") { + assert(model.enumMaps[declaration.name], `Missing enum map: ${declaration.name}`); + } + if (declaration.kind === "List" || declaration.kind === "ListOrElement") { + assert(model.elements[declaration.name], `Missing list element: ${declaration.name}`); + } + for (const value of Object.values(declaration)) { + if (typeof value === "object" && value !== null && "go" in value) { + assert(/^(?:core|diagnostics)\.[A-Za-z_]\w*$|^extraValidation(?:Spec|Locale|None)$/.test(value.go), `Invalid Go reference: ${value.go}`); + } + } + } + for (const [name, map] of Object.entries(model.enumMaps)) { + assert(map.values.length, `Empty enum map: ${name}`); + const keys = map.values.map(entry => entry.name); + assert.equal(new Set(keys).size, keys.length, `Duplicate enum keys: ${name}`); + assert(keys.every(key => key === key.toLowerCase()), `Enum keys must be lowercase: ${name}`); + for (const entry of map.values) { + if (typeof entry.value === "object") assert(constants.has(entry.value.go), `Unknown enum constant: ${entry.value.go}`); + } + } +} + +function coreOptions(): string { + const fields = options.compilerOptions.map(option => { + const comments = [ + ...(option.comment ? [option.comment] : []), + ...(option.deprecated ? ["Deprecated: Do not use outside of options parsing and validation."] : []), + ].map(comment => `// ${comment}\n`).join(""); + const tags = [`json:"${option.name},omitzero"`, ...(option.deprecated ? ['deprecated:"true"'] : []), ...(option.internal ? ['internal:"true"'] : [])]; + return `${comments}${fieldName(option)} ${option.type} \`${tags.join(" ")}\``; + }); + return `// CompilerOptions contains the compiler options exposed by the API. +type CompilerOptions struct { + _ noCopy + ${fields.join("\n")} +} + +// Clone creates a shallow copy of the CompilerOptions. +func (options *CompilerOptions) Clone() *CompilerOptions { + return &CompilerOptions{ + ${options.compilerOptions.map(option => `${fieldName(option)}: options.${fieldName(option)},`).join("\n")} + } +} + +// Equals reports whether all stored option values are equal, including nil versus empty collections. +// Paths are compared by ordered entries, ignoring backing-storage allocation. +${optionsEquality("CompilerOptions", options.compilerOptions.map(option => ({ name: fieldName(option), type: option.type })))} +`; +} + +function optionsEquality(name: string, fields: StoredDeclaration["field"][]): string { + return `func (options *${name}) Equals(other *${name}) bool { + if options == other { return true } + if options == nil || other == nil { return false } + ${ + fields.map(field => { + const a = `options.${field.name}`; + const b = `other.${field.name}`; + let differs: string; + switch (field.type) { + case "*int": + differs = `${a} != ${b} && (${a} == nil || ${b} == nil || *${a} != *${b})`; + break; + case "[]string": + case "[]PluginImport": + differs = `(${a} == nil) != (${b} == nil) || !slices.Equal(${a}, ${b})`; + break; + case "*collections.OrderedMap[string, []string]": + differs = `!${a}.EqualFunc(${b}, func(a, b []string) bool { + return (a == nil) == (b == nil) && slices.Equal(a, b) +})`; + break; + default: + differs = `${a} != ${b}`; + } + return `if ${differs} { return false }`; + }).join("\n") + } + return true +} +`; +} + +function storedOptions(name: string, declarations: StoredDeclaration[], omitZero: boolean): string { + return `type ${name} struct { +${name === "BuildOptions" ? "_ noCopy\n" : ""} +${declarations.map(option => `${option.field.comment ? "\n" + option.field.comment.split("\n").map(line => line ? "// " + line : "").join("\n") + "\n" : ""}${option.field.name} ${option.field.type} \`json:"${option.name}${omitZero ? ",omitzero" : ""}"\``).join("\n")} +} +${name === "WatchOptions" ? "\n// Equals compares stored watch options, preserving nil versus empty collections.\n" + optionsEquality(name, declarations.map(option => option.field)) : ""} +`; +} + +function zeroValue(option: CompilerOption): string { + const kind = optionKind(option); + return kind === "Boolean" ? "core.TSUnknown" : kind === "String" ? '""' : kind === "Enum" ? "0" : "nil"; +} + +function showConfig(): string { + const serializedOptions = options.compilerOptions.filter(option => { + const declaration = option.declarations?.[0]; + return declaration && declaration.category?.go !== "diagnostics.Command_line_Options" && declaration.category?.go !== "diagnostics.Output_Formatting"; + }); + const enumOptions = serializedOptions.filter(option => optionKind(option) === "Enum"); + assert.equal(new Set(enumOptions.map(option => option.type)).size, enumOptions.length, "ShowConfig enum types must have a single option map"); + return `func serializeCompilerOptions(options *core.CompilerOptions, configFilePath string, comparePathsOptions tspath.ComparePathsOptions) *collections.OrderedMap[string, any] { + result := collections.NewOrderedMapWithSizeHint[string, any](32) +${ + serializedOptions.map(option => { + const field = `options.${fieldName(option)}`; + const name = JSON.stringify(option.name); + const declaration = option.declarations![0]; + let value = field; + let condition = `${field} != ${zeroValue(option)}`; + switch (optionKind(option)) { + case "Enum": + return `if ${condition} { + if value := serializeCompilerOptionEnum(${field}); value != "" { + result.Set(${name}, value) + } +}`; + case "Boolean": + condition = `${field} == core.TSTrue || ${field} == core.TSFalse`; + value = `${field} == core.TSTrue`; + break; + case "String": + if (declaration.isFilePath) value = `serializeCompilerOptionPath(${field}, configFilePath, comparePathsOptions)`; + break; + case "List": { + const element = options.elements[option.name]; + if (element?.isFilePath) { + assert.equal(option.type, "[]string", `Unsupported file path list: ${option.name}`); + value = `serializeCompilerOptionPaths(${field}, configFilePath, comparePathsOptions)`; + } + else if (element?.kind === "Enum") { + assert.equal(option.type, "[]string", `Unsupported enum list: ${option.name}`); + value = `serializeCompilerOptionEnumList(${field}, ${options.enumMaps[option.name].goName})`; + } + break; + } + } + return `if ${condition} { + result.Set(${name}, ${value}) +}`; + }).join("\n") + } + return result +} + +func serializeCompilerOptionEnum(value any) string { + switch value := value.(type) { +${ + enumOptions.map(option => { + const seen = new Set(); + const entries = options.enumMaps[option.name].values.filter(entry => { + const value = goValue(entry.value); + if (seen.has(value)) return false; + seen.add(value); + return true; + }); + return `case core.${option.type}: +${entries.map(entry => `if value == ${goValue(entry.value)} { return ${JSON.stringify(entry.name)} }`).join("\n")}`; + }).join("\n") + } + } + return "" +} +`; +} + +function configDirSubstitution(): string { + const substitutedOptions = options.compilerOptions.filter(option => option.declarations?.some(declaration => declaration.allowConfigDirTemplateSubstitution ?? declaration.isFilePath)); + return `func handleOptionConfigDirTemplateSubstitution(compilerOptions *core.CompilerOptions, basePath string) { + if compilerOptions == nil { return } +${ + substitutedOptions.map(option => { + const field = `compilerOptions.${fieldName(option)}`; + switch (option.type) { + case "string": + return `if startsWithConfigDirTemplate(${field}) { + ${field} = getSubstitutedPathWithConfigDirTemplate(${field}, basePath) +}`; + case "[]string": + return `if substitution := getSubstitutedStringArrayWithConfigDirTemplate(${field}, basePath); substitution != nil { + ${field} = substitution +}`; + case "*collections.OrderedMap[string, []string]": + return `{ + var paths *collections.OrderedMap[string, []string] + for k, v := range ${field}.Entries() { + if substitution := getSubstitutedStringArrayWithConfigDirTemplate(v, basePath); substitution != nil { + if paths == nil { + paths = ${field}.Clone() + ${field} = paths + } + paths.Set(k, substitution) + } + } +}`; + default: + throw new Error(`Unsupported configDir substitution type for ${option.name}: ${option.type}`); + } + }).join("\n") + } +} +`; +} + +function mergeCompilerOptions(): string { + return `func mergeCompilerOptionFields(targetOptions, sourceOptions *core.CompilerOptions, explicitNullFields collections.Set[string]) { +${ + options.compilerOptions.map(option => { + const field = fieldName(option); + const zero = zeroValue(option); + return `if explicitNullFields.Has(${JSON.stringify(option.name)}) { + targetOptions.${field} = ${zero} +} else if sourceOptions.${field} != ${zero} { + targetOptions.${field} = sourceOptions.${field} +}`; + }).join("\n") + } +} +`; +} + +function transpileOptions(): string { + const clearedOptions = options.compilerOptions.filter(option => option.declarations?.some(declaration => typeof declaration.transpileOptionValue === "object" && declaration.transpileOptionValue.go === "core.TSUnknown")); + return `${header} +package transpile + +import "github.com/microsoft/TypeScript/tsc/internal/core" + +func clearOptionsForTranspile(options *core.CompilerOptions) { +${clearedOptions.map(option => `options.${fieldName(option)} = ${zeroValue(option)}`).join("\n")} +} +`; +} + +export function generateBuildInfoOptions(model = options): string { + const storedOptions = model.compilerOptions.filter(option => option.declarations?.some(declaration => declaration.affectsBuildInfo)); + return `// ForEachCompilerOptionAffectingBuildInfo visits nonzero options in CompilerOptions field order. +func ForEachCompilerOptionAffectingBuildInfo(options *core.CompilerOptions, fn func(option *CommandLineOption, value any)) { +${ + storedOptions.map(option => + `if options.${fieldName(option)} != ${zeroValue(option)} { + fn(CommandLineCompilerOptionsMap.Get(${JSON.stringify(option.name)}), options.${fieldName(option)}) +}` + ).join("\n") + } +} +`; +} + +export function generateOptionComparisons(model = options): string { + const comparisons = [ + ["SemanticDiagnostics", "affectsSemanticDiagnostics"], + ["DeclarationPath", "affectsDeclarationPath"], + ["Emit", "affectsEmit"], + ] as const; + return `${ + comparisons.map(([name, flag]) => { + const expressions = model.compilerOptions.flatMap(option => { + const declaration = option.declarations?.find(declaration => declaration[flag]); + if (!declaration) return []; + const kind = optionKind(option); + assert(kind === "Boolean" || kind === "String" || kind === "Enum", `Unsupported comparison type for ${option.name}: ${option.type}`); + const value = (receiver: string) => { + const field = `${receiver}.${fieldName(option)}`; + if (declaration.strictFlag) return `${receiver}.GetStrictOptionValue(${field})`; + if (declaration.allowJsFlag) return `${receiver}.GetAllowJS()`; + return field; + }; + return [`${value("oldOptions")} != ${value("newOptions")}`]; + }); + return `func CompilerOptionsAffect${name}(oldOptions *core.CompilerOptions, newOptions *core.CompilerOptions) bool { + if oldOptions == newOptions { return false } + if oldOptions == nil || newOptions == nil { return true } + return ${expressions.join(" ||\n") || "false"} +} +`; + }).join("\n") + } +`; +} + +function numericEnums(): string { + return `${ + options.enums.map(enumDef => + `type ${enumDef.name} int32 + +const ( +${enumDef.members.map(member => `${member.comment ? "// " + member.comment.replaceAll("\n", "\n// ") + "\n" : ""}${enumDef.name}${member.name} ${enumDef.name} = ${typeof member.value === "number" ? member.value : enumDef.name + member.value}${member.trailingComment ? " // " + member.trailingComment : ""}`).join("\n")} +) +` + ).join("\n") + } + +var ModuleKindToModuleResolutionKind = map[ModuleKind]ModuleResolutionKind{ +${options.enums.find(enumDef => enumDef.name === "ModuleKind")!.members.filter(member => member.moduleResolution).map(member => `ModuleKind${member.name}: ModuleResolutionKind${member.moduleResolution},`).join("\n")} +} +`; +} + +const privateMetadata = new Set([ + "extraValidation", + "minValue", + "allowJsFlag", + "strictFlag", + "transpileOptionValue", + "listPreserveFalsyValues", +]); + +function declarationLiteral(declaration: Declaration): string { + const { name, kind, comment, ...metadata } = declaration; + const properties = [`Name: ${JSON.stringify(name)},`, `Kind: CommandLineOptionType${kind},`]; + for (const [key, value] of Object.entries(metadata)) { + if (key === "group" || key === "jsconfigDefault" || key === "field" || key === "variable" || key === "elementOptions" || key === "documentationAnchor" || key === "schemaDescription" || key === "allowConfigDirTemplateSubstitution") continue; + const goName = privateMetadata.has(key) ? key : key[0].toUpperCase() + key.slice(1); + properties.push(`${goName}: ${goValue(value)},`); + } + return `${comment ? "// " + comment.replaceAll("\n", "\n// ") + "\n" : ""}{\n${properties.join("\n")}\n}`; +} + +function declarations(): string { + const all = compilerDeclarations(); + const groups = ["commonOptionsWithBuild", "optionsForCompiler"] as const; + const arrays: [string, Declaration[]][] = [ + ...groups.map(group => [group, orderByName(all.filter(declaration => declaration.group === group), options.declarationOrder[group], group)] as [string, Declaration[]]), + ["OptionsForWatch", options.watchOptions], + ["typeAcquisitionDecls", options.typeAcquisition], + ]; + return `var OptionsDeclarations = slices.Concat(commonOptionsWithBuild, optionsForCompiler) + +var BuildOpts = slices.Concat(commonOptionsWithBuild, OptionsForBuild) + +${arrays.map(([name, values]) => `var ${name} = []*CommandLineOption{\n${values.map(declaration => declarationLiteral(declaration) + ",").join("\n")}\n}`).join("\n\n")} + +var commandLineOptionElements = map[string]*CommandLineOption{ +${Object.entries(options.elements).map(([name, declaration]) => `${JSON.stringify(name)}: ${declarationLiteral(declaration)},`).join("\n")} +} + +var TscBuildOption = CommandLineOption${declarationLiteral(options.buildOptions[0])} + +var OptionsForBuild = []*CommandLineOption{ + &TscBuildOption, + ${options.buildOptions.slice(1).map(option => declarationLiteral(option) + ",").join("\n")} +} +`; +} + +function rootDeclarations(): string { + const elementOptions = { + compilerOptions: "CommandLineCompilerOptionsMap", + typeAcquisition: "commandLineOptionsToMap(typeAcquisitionDecls)", + extends: `commandLineOptionsToMap([]*CommandLineOption{${declarationLiteral(options.elements.extends)}})`, + }; + return `${ + options.rootOptions.filter(option => option.variable).map(option => { + let literal = declarationLiteral(option); + if (option.elementOptions) literal = literal.slice(0, -1) + `ElementOptions: ${elementOptions[option.elementOptions]},\n}`; + return `var ${option.variable} = &CommandLineOption${literal}`; + }).join("\n\n") + } + +var tsconfigRootOptionsMap = &CommandLineOption{ + Name: "undefined", + Kind: CommandLineOptionTypeObject, + ElementOptions: commandLineOptionsToMap([]*CommandLineOption{ + ${options.rootOptions.map(option => (option.variable ?? declarationLiteral(option)) + ",").join("\n")} + }), +} +`; +} + +function enumMaps(): string { + return `${Object.values(options.enumMaps).map(map => `var ${map.goName} = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{\n${map.values.map(entry => `{Key: ${JSON.stringify(entry.name)}, Value: ${goValue(entry.value)}},`).join("\n")}\n})`).join("\n\n")} + +var commandLineOptionEnumMap = map[string]*collections.OrderedMap[string, any]{ +${Object.entries(options.enumMaps).map(([name, map]) => `${JSON.stringify(name)}: ${map.goName},`).join("\n")} +} + +var commandLineOptionDeprecated = map[string]*collections.Set[string]{ +${Object.entries(options.enumMaps).filter(([, map]) => map.deprecatedKeys).map(([name, map]) => `${JSON.stringify(name)}: collections.NewSetFromItems(${map.deprecatedKeys!.map(key => JSON.stringify(key)).join(", ")}),`).join("\n")} +} + +var targetToLibMap = map[core.ScriptTarget]string{ +${options.enums.find(enumDef => enumDef.name === "ScriptTarget")!.members.filter(member => member.lib).toReversed().map(member => `core.ScriptTarget${member.name}: ${JSON.stringify(member.lib)},${member.libComment ? " // " + member.libComment : ""}`).join("\n")} +} +`; +} + +function parserAssignment(option: CompilerOption): string { + const target = `allOptions.${fieldName(option)}`; + if (option.parser === "lib") { + return `if libs, ok := value.([]string); ok { ${target} = libs } else { ${target} = ParseStringArray(value) }`; + } + if (option.parser === "plugins") { + return `if plugins, ok := value.([]any); ok { + ${target} = core.Map(plugins, func(plugin any) core.PluginImport { + if pluginMap, isMap := plugin.(*collections.OrderedMap[string, any]); isMap { + return core.PluginImport{Name: ParseString(pluginMap.GetOrZero("name"))} + } + return core.PluginImport{} + }) + }`; + } + const functions: Partial> = { + "Tristate": "ParseTristate", + "string": "ParseString", + "*int": "parseNumber", + "[]string": "ParseStringArray", + "*collections.OrderedMap[string, []string]": "parseStringMap", + }; + const parser = functions[option.type]; + assert(option.type !== "[]PluginImport", "Plugin options require the plugin parser"); + return `${target} = ${parser ?? `floatOrInt32ToFlag[core.${option.type}]`}(value)`; +} + +function parser(): string { + return `func parseCompilerOptions(key string, value any, allOptions *core.CompilerOptions) (foundKey bool) { + if option := CommandLineCompilerOptionsMap.Get(key); option != nil { key = option.Name } + switch key { + ${options.compilerOptions.map(option => `case ${[option.name, ...(option.parseAliases ?? [])].map(name => JSON.stringify(name)).join(", ")}:\n${parserAssignment(option)}`).join("\n")} + default: + return false + } + return true +} + +func getDefaultCompilerOptions(configFileName string) *core.CompilerOptions { + if configFileName != "" && tspath.GetBaseFileName(configFileName) == "jsconfig.json" { + return &core.CompilerOptions{ + ${ + options.compilerOptions.filter(option => option.jsconfigDefault !== undefined).map(option => { + const value = option.jsconfigDefault!; + const expression = typeof value === "boolean" ? `core.TS${value ? "True" : "False"}` : typeof value === "number" ? `new(${value})` : JSON.stringify(value); + return `${fieldName(option)}: ${expression},`; + }).join("\n") + } + } + } + return &core.CompilerOptions{} +} + +func getDefaultTypeAcquisition(configFileName string) *core.TypeAcquisition { + if configFileName != "" && tspath.GetBaseFileName(configFileName) == "jsconfig.json" { + return &core.TypeAcquisition{ + ${options.typeAcquisition.filter(option => option.jsconfigDefault !== undefined).map(option => `${option.field.name}: core.TS${option.jsconfigDefault ? "True" : "False"},`).join("\n")} + } + } + return &core.TypeAcquisition{} +} +`; +} + +function storedParser(name: string, declarations: StoredDeclaration[], guardNull: boolean): string { + return `func Parse${name}(key string, value any, allOptions *core.${name}) []*ast.Diagnostic { + ${guardNull ? "if value == nil { return nil }" : ""} + if allOptions == nil { return nil } + ${name === "BuildOptions" ? "if option := BuildNameMap.Get(key); option != nil { key = option.Name }" : ""} + switch key { + ${ + declarations.map(option => { + const stored: CompilerOption = { name: option.name, goName: option.field.name, type: option.field.type }; + const assignment = option.kind === "Enum" + ? `if value != nil { allOptions.${option.field.name} = value.(core.${option.field.type}) }` + : parserAssignment(stored); + return `case ${JSON.stringify(option.name)}:\n${assignment}`; + }).join("\n") + } + } + return nil +} +`; +} + +export function generateOptions(): Map { + validateOptions(options); + const buildOptions = options.buildOptions.filter((option): option is StoredDeclaration => option.field !== undefined); + return new Map([ + [ + "tsc/internal/core/options_generated.go", + `${header} +package core + +import ( + "slices" + + "github.com/microsoft/TypeScript/tsc/internal/collections" +) + +//go:generate npx hereby generate:compileroptions + +${coreOptions()} +${numericEnums()} +${storedOptions("WatchOptions", options.watchOptions, false)} +${storedOptions("TypeAcquisition", options.typeAcquisition, true)} +${storedOptions("BuildOptions", orderByName(buildOptions, options.buildOptionFieldOrder, "BuildOptions fields"), true)} +`, + ], + ["tsc/internal/transpile/options_generated.go", transpileOptions()], + [ + "tsc/internal/tsoptions/declarations_generated.go", + `${header} +package tsoptions + +import ( + "slices" + + "github.com/microsoft/TypeScript/tsc/internal/collections" + "github.com/microsoft/TypeScript/tsc/internal/core" + "github.com/microsoft/TypeScript/tsc/internal/diagnostics" +) + +${declarations()} +${rootDeclarations()} +${enumMaps()} +`, + ], + [ + "tsc/internal/tsoptions/options_generated.go", + `${header} +package tsoptions + +import ( + "github.com/microsoft/TypeScript/tsc/internal/ast" + "github.com/microsoft/TypeScript/tsc/internal/collections" + "github.com/microsoft/TypeScript/tsc/internal/core" + "github.com/microsoft/TypeScript/tsc/internal/tspath" +) + +${parser()} +${storedParser("WatchOptions", options.watchOptions, false)} +${storedParser("TypeAcquisition", options.typeAcquisition, true)} +${storedParser("BuildOptions", buildOptions, true)} +${generateOptionComparisons()} +${generateBuildInfoOptions()} +${mergeCompilerOptions()} +${configDirSubstitution()} +${showConfig()} +`, + ], + ...(["tsconfig", "jsconfig"] as const).map(name => [`tsc/internal/tsoptions/schemas/${name}.schema.json`, JSON.stringify(generateConfigSchema(name), null, 4) + "\n"] as [string, string]), + ]); +} + +export default async function generate(force = false): Promise { + const inputs = [...sourceFiles.map(file => path.join(import.meta.dirname, file)), diagnosticsFile]; + const outputs = generateOptions(); + const changed: GeneratedFile[] = []; + for (const [fileName, content] of outputs) { + const file = new GeneratedFile(path.join(repoRoot, fileName), inputs); + if (file.isCurrent(force)) continue; + file.write(content); + changed.push(file); + } + if (changed.length) { + await formatFiles(changed.map(file => file.fileName)); + for (const file of changed) file.markCurrent(); + } +} + +if (process.argv[1] === fileURLToPath(import.meta.url)) { + await generate(parseGeneratorArgs({}).force); +} diff --git a/tools/scripts/tsc/options-model.ts b/tools/scripts/tsc/options-model.ts new file mode 100644 index 0000000000000..1a41577496914 --- /dev/null +++ b/tools/scripts/tsc/options-model.ts @@ -0,0 +1,163 @@ +/** Metadata shared by the compiler options, declaration, and config schema generators. */ + +import type messages from "../../../tsc/internal/diagnostics/diagnosticMessages.json"; + +export interface DiagnosticMessage { + go: `diagnostics.${string}`; + text: keyof typeof messages; +} + +export function diagnostic(text: keyof typeof messages): DiagnosticMessage { + const special: Record = { "*": "_Asterisk", "/": "_Slash", ":": "_Colon" }; + let name = [...text].map(char => special[char] ?? (/[\p{L}\p{Nd}]/u.test(char) ? char : "_")).join("") + .replace(/_+/g, "_").replace(/^_([^0-9])/, "$1").replace(/_+$/, ""); + if (!/^\p{Lu}/u.test(name)) name = (name.startsWith("_") ? "X" : "X_") + name; + return { go: `diagnostics.${name}`, text }; +} + +export type GoValue = string | number | boolean | DiagnosticMessage | { go: `core.${string}`; }; +export type OptionKind = "Boolean" | "String" | "Number" | "Object" | "List" | "ListOrElement" | "Enum"; +export type CompilerOptionType = + | "Tristate" + | "string" + | "*int" + | "[]string" + | "[]PluginImport" + | "*collections.OrderedMap[string, []string]" + | "JsxEmit" + | "ModuleKind" + | "ModuleResolutionKind" + | "ModuleDetectionKind" + | "NewLineKind" + | "ScriptTarget" + | "WatchFileKind" + | "WatchDirectoryKind" + | "PollingKind"; + +export interface DeclarationMetadata { + comment?: string; + shortName?: string; + isFilePath?: boolean; + isTSConfigOnly?: boolean; + isCommandLineOnly?: boolean; + description?: DiagnosticMessage; + schemaDescription?: string; + /** TSConfig reference anchor for schema hovers; defaults to the option name. False omits the link. */ + documentationAnchor?: string | false; + defaultValueDescription?: GoValue; + showInSimplifiedHelpView?: boolean; + category?: DiagnosticMessage; + extraValidation?: { go: string; }; + minValue?: number; + /** Defaults to isFilePath for compiler options; false explicitly disables substitution. */ + allowConfigDirTemplateSubstitution?: boolean; + affectsDeclarationPath?: boolean; + affectsProgramStructure?: boolean; + affectsSemanticDiagnostics?: boolean; + affectsBuildInfo?: boolean; + affectsBindDiagnostics?: boolean; + affectsSourceFile?: boolean; + affectsModuleResolution?: boolean; + affectsEmit?: boolean; + allowJsFlag?: boolean; + strictFlag?: boolean; + transpileOptionValue?: { go: string; }; + listPreserveFalsyValues?: boolean; +} + +export interface Declaration extends DeclarationMetadata { + name: string; + kind: OptionKind; + jsconfigDefault?: boolean; +} + +export interface StoredDeclaration extends Declaration { + field: { name: string; type: CompilerOptionType; comment?: string; }; +} + +export interface RootDeclaration extends Declaration { + variable?: string; + elementOptions?: "compilerOptions" | "typeAcquisition" | "extends"; +} + +type DeclarationGroup = "commonOptionsWithBuild" | "optionsForCompiler"; + +export interface CompilerOption { + name: string; + type: CompilerOptionType; + goName?: string; + internal?: boolean; + deprecated?: boolean; + comment?: string; + parseAliases?: string[]; + parser?: "lib" | "plugins"; + declarations?: (DeclarationMetadata & { + group: DeclarationGroup; + })[]; + jsconfigDefault?: string | number | boolean; +} + +export interface EnumMap { + goName: string; + values: { name: string; value: GoValue; }[]; + deprecatedKeys?: string[]; + /** Removed values retained only in configuration schemas, always deprecated. */ + schemaOnlyValues?: string[]; +} + +export type SchemaOnlyOption = { + name: string; + description: string; +} & ({ type: "boolean" | "string"; } | { type: "enum"; values: string[]; }); + +export interface OptionEnum { + name: string; + api?: boolean; + members: { + name: string; + value: number | string; + comment?: string; + trailingComment?: string; + excludeFromAPI?: boolean; + lib?: string; + libComment?: string; + moduleResolution?: string; + }[]; +} + +export interface OptionsModel { + compilerOptions: CompilerOption[]; + /** Removed options retained only in configuration schemas, always deprecated. */ + schemaOnlyOptions: SchemaOnlyOption[]; + declarationOrder: Record; + watchOptions: StoredDeclaration[]; + typeAcquisition: StoredDeclaration[]; + buildOptions: (Declaration & { field?: StoredDeclaration["field"]; })[]; + buildOptionFieldOrder: string[]; + rootOptions: RootDeclaration[]; + elements: Record; + enumMaps: Record; + enums: OptionEnum[]; +} + +export function optionKind(option: CompilerOption): OptionKind { + switch (option.type) { + case "Tristate": + return "Boolean"; + case "string": + return "String"; + case "*int": + return "Number"; + case "[]string": + case "[]PluginImport": + return "List"; + case "*collections.OrderedMap[string, []string]": + return "Object"; + default: + return "Enum"; + } +} + +export function fieldName(option: CompilerOption): string { + return option.goName ?? option.name[0].toUpperCase() + option.name.slice(1); +} diff --git a/tools/scripts/tsc/options-schema.ts b/tools/scripts/tsc/options-schema.ts new file mode 100644 index 0000000000000..67dc954aad8bf --- /dev/null +++ b/tools/scripts/tsc/options-schema.ts @@ -0,0 +1,222 @@ +import assert from "node:assert/strict"; +import { + type Declaration, + type GoValue, + optionKind, +} from "./options-model.ts"; +import { options } from "./options.ts"; + +export interface JSONSchema { + $schema?: string; + $comment?: string; + $ref?: string; + title?: string; + description?: string; + markdownDescription?: string; + type?: string | string[]; + properties?: Record; + definitions?: Record; + additionalProperties?: boolean | JSONSchema; + required?: string[]; + items?: JSONSchema; + anyOf?: JSONSchema[]; + allOf?: JSONSchema[]; + enum?: string[]; + enumDescriptions?: string[]; + pattern?: string; + default?: string | boolean | number; + minimum?: number; + minLength?: number; + deprecated?: boolean; + deprecationMessage?: string; + allowComments?: boolean; + allowTrailingCommas?: boolean; +} + +function nullable(schema: JSONSchema): JSONSchema { + return { anyOf: [schema, { type: "null" }] }; +} + +function enumSchema(name: string): JSONSchema { + const map = options.enumMaps[name]; + assert(map, `Missing enum map: ${name}`); + const keys = [...map.values.map(entry => entry.name), ...(map.schemaOnlyValues ?? [])]; + return stringEnumSchema(keys, [...(map.deprecatedKeys ?? []), ...(map.schemaOnlyValues ?? [])]); +} + +function stringEnumSchema(keys: string[], deprecatedKeys: string[] = []): JSONSchema { + assert(keys.length > 0, "Empty schema enum"); + assert.equal(new Set(keys).size, keys.length, "Duplicate schema enum values"); + assert(keys.every(key => key === key.toLowerCase()), "Schema enum values must be lowercase"); + const pattern = keys.map(key => [...key].map(char => /[a-z]/.test(char) ? `[${char.toUpperCase()}${char}]` : char.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("")).join("|"); + const suggestions: JSONSchema = { enum: keys }; + if (deprecatedKeys.length) { + suggestions.enumDescriptions = keys.map(key => deprecatedKeys.includes(key) ? "Deprecated." : ""); + } + // Keep enum completions while accepting every casing supported by the parser. + return { type: "string", anyOf: [suggestions, { pattern: `^(${pattern})$` }] }; +} + +function defaultValue(value: GoValue | undefined, name: string): string | number | boolean | undefined { + // Help text may wrap a literal string default in a Markdown code span. + if (typeof value === "string") return value.replace(/^`([^`]*)`$/, "$1"); + if (value === undefined || typeof value !== "object") return value; + if ("text" in value || value.go === "core.TSUnknown") return undefined; + let constant = value.go; + if (constant === "core.ScriptTargetLatestStandard") { + const target = options.enums.find(enumDef => enumDef.name === "ScriptTarget")?.members.find(member => member.name === "LatestStandard"); + assert(target, "Missing ScriptTargetLatestStandard"); + constant = `core.ScriptTarget${target.value}`; + } + const entry = options.enumMaps[name]?.values.find(entry => typeof entry.value === "object" && entry.value.go === constant); + assert(entry, `No schema default for ${name}: ${constant}`); + return entry.name; +} + +function valueSchema(declaration: Declaration): JSONSchema { + switch (declaration.kind) { + case "Boolean": + return { type: "boolean" }; + case "String": + return { type: "string" }; + case "Number": + return { type: "number", ...(declaration.minValue !== undefined ? { minimum: declaration.minValue } : {}) }; + case "Enum": + return enumSchema(declaration.name); + case "List": + case "ListOrElement": { + const element = options.elements[declaration.name]; + assert(element, `Missing list element: ${declaration.name}`); + const items = valueSchema(element); + const array: JSONSchema = { type: "array", items }; + return declaration.kind === "List" ? array : { anyOf: [items, array] }; + } + case "Object": + if (declaration.name === "paths") { + return { type: "object", additionalProperties: { type: "array", items: { type: "string" } } }; + } + if (declaration.name === "plugin") { + return { type: "object", properties: { name: { type: "string" } } }; + } + if (declaration.name === "references") { + return { + type: "object", + properties: { path: { type: "string", minLength: 1 }, circular: { type: "boolean" } }, + required: ["path"], + }; + } + if (declaration.name === "contentMappers") { + return { + type: "object", + properties: { + package: { type: "string", minLength: 1 }, + extensions: { type: "array", items: { type: "string" } }, + options: { type: "object" }, + }, + required: ["package", "extensions"], + additionalProperties: false, + }; + } + throw new Error(`Missing object schema: ${declaration.name}`); + } +} + +function withDescription(schema: JSONSchema, description: string | undefined, anchor: string | false): JSONSchema { + if (description !== undefined) { + schema.description = description; + schema.markdownDescription = anchor === false + ? description + : `${description}\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/${anchor ? `#${anchor}` : ""}).`; + } + return schema; +} + +function optionSchema(declaration: Declaration): JSONSchema { + const schema = nullable(valueSchema(declaration)); + if (declaration.schemaDescription !== undefined) schema.description = declaration.schemaDescription; + else if (declaration.description) schema.description = declaration.description.text; + const value = defaultValue(declaration.defaultValueDescription, declaration.name); + if (value !== undefined) schema.default = value; + const defaultDescription = declaration.defaultValueDescription; + if (typeof defaultDescription === "object" && "text" in defaultDescription) { + schema.description = [schema.description, `Default: ${defaultDescription.text}`].filter(Boolean).join("\n\n"); + } + return withDescription(schema, schema.description, declaration.documentationAnchor ?? declaration.name); +} + +function optionObject(properties: Record) { + return { type: ["object", "null"], properties, additionalProperties: true }; +} + +export function generateConfigSchema(kind: "tsconfig" | "jsconfig") { + const compilerProperties: Record = {}; + for (const option of options.compilerOptions) { + const declaration = option.declarations?.[0]; + if (!declaration || declaration.isCommandLineOnly || declaration.category?.go === "diagnostics.Command_line_Options") continue; + const schema = optionSchema({ + name: option.name, + kind: optionKind(option), + ...declaration, + ...(kind === "jsconfig" && option.jsconfigDefault !== undefined ? { defaultValueDescription: option.jsconfigDefault } : {}), + }); + if (option.deprecated) { + schema.deprecated = true; + schema.deprecationMessage = "This compiler option is deprecated."; + } + compilerProperties[option.name] = schema; + } + for (const option of options.schemaOnlyOptions) { + assert(!options.compilerOptions.some(current => current.name === option.name), `Schema-only option also exists in compiler options: ${option.name}`); + assert(!Object.hasOwn(compilerProperties, option.name), `Duplicate schema-only option: ${option.name}`); + const schema = nullable(option.type === "enum" ? stringEnumSchema(option.values) : { type: option.type }); + schema.deprecated = true; + schema.deprecationMessage = "This option has been removed from TypeScript. It is retained in the schema for historical configurations."; + compilerProperties[option.name] = withDescription(schema, option.description, option.name); + } + const watchProperties = Object.fromEntries(options.watchOptions.map(option => [option.name, optionSchema(option)])); + const acquisitionProperties = Object.fromEntries(options.typeAcquisition.map(option => [ + option.name, + optionSchema({ + documentationAnchor: "typeAcquisition", + ...option, + ...(kind === "jsconfig" && option.jsconfigDefault !== undefined ? { defaultValueDescription: option.jsconfigDefault } : {}), + }), + ])); + const descriptions: Record = { + compilerOptions: "Options for the TypeScript compiler.", + typeAcquisition: "Options for automatic type acquisition in JavaScript projects.", + extends: "Configuration file or files to inherit from. Later entries take precedence. Relative paths are resolved relative to the configuration file in which they occur.", + files: "Files to include in the project, in addition to files matched by include.", + include: "File names or glob patterns to include. Defaults to all supported files when neither files nor include is specified.", + exclude: "File names or glob patterns excluded from include. Does not exclude files brought in by imports, references, types, or files.", + references: "Referenced projects. Each path identifies a configuration file or a directory containing one.", + compileOnSave: "Compile this project when a file is saved in a supporting editor.", + contentMappers: "External content mapper packages and the file extensions they handle. Execution must be enabled separately with --runExternalCode.", + }; + const properties: Record = { + $schema: { type: "string", description: "The JSON schema used to validate this configuration." }, + watchOptions: withDescription({ allOf: [{ $ref: "#/definitions/watchOptions" }] }, "Options for watching files and directories.", "watchOptions"), + }; + for (const option of options.rootOptions) { + const schema = option.elementOptions && option.elementOptions !== "extends" + ? { allOf: [{ $ref: `#/definitions/${option.elementOptions}` }] } + : option.name === "extends" ? valueSchema(option) : optionSchema(option); + properties[option.name] = withDescription(schema, option.schemaDescription ?? descriptions[option.name], option.documentationAnchor ?? option.name); + } + return { + $schema: "http://json-schema.org/draft-07/schema#", + $comment: "Generated by tools/scripts/tsc/generate-options.ts. DO NOT EDIT.", + title: kind === "tsconfig" ? "TypeScript configuration" : "JavaScript configuration", + type: "object", + allowComments: true, + allowTrailingCommas: true, + properties, + // Root properties are extensible so tools can use their own config sections. + additionalProperties: true, + definitions: { + compilerOptions: optionObject(compilerProperties), + watchOptions: optionObject(watchProperties), + typeAcquisition: optionObject(acquisitionProperties), + }, + }; +} diff --git a/tools/scripts/tsc/options.test.ts b/tools/scripts/tsc/options.test.ts new file mode 100644 index 0000000000000..475c095512a7c --- /dev/null +++ b/tools/scripts/tsc/options.test.ts @@ -0,0 +1,590 @@ +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import { test } from "node:test"; +import { repoRoot } from "../gen/utils.mts"; +import { + enumDefs, + generateEnum, +} from "./generate-enums.ts"; +import { + generateBuildInfoOptions, + generateConfigSchema, + generateOptionComparisons, + generateOptions, + validateOptions, +} from "./generate-options.ts"; +import { + diagnostic, + optionKind, +} from "./options-model.ts"; +import type { JSONSchema } from "./options-schema.ts"; +import { options } from "./options.ts"; + +test("option metadata is valid", () => { + validateOptions(options); +}); + +test("diagnostic references use checked message text and preserve Go names", () => { + assert.deepEqual(diagnostic("JavaScript Support"), { go: "diagnostics.JavaScript_Support", text: "JavaScript Support" }); + assert.deepEqual(diagnostic("'{0}' expected."), { go: "diagnostics.X_0_expected", text: "'{0}' expected." }); + // @ts-expect-error Diagnostic text must exist in diagnosticMessages.json. + diagnostic("Not a real diagnostic."); +}); + +test("explicit option orders reject duplicates, unknown names, and omissions", () => { + for ( + const select of [ + (model: typeof options) => model.declarationOrder.commonOptionsWithBuild, + (model: typeof options) => model.declarationOrder.optionsForCompiler, + (model: typeof options) => model.buildOptionFieldOrder, + ] + ) { + const duplicate = structuredClone(options); + const duplicateOrder = select(duplicate); + duplicateOrder.push(duplicateOrder[0]); + assert.throws(() => validateOptions(duplicate), /Duplicate option in .* order/); + + const unknown = structuredClone(options); + select(unknown)[0] = "missingOption"; + assert.throws(() => validateOptions(unknown), /Unknown option in .* order: missingOption/); + + const missing = structuredClone(options); + select(missing).pop(); + assert.throws(() => validateOptions(missing), /Missing options in .* order/); + } + const wrongGroup = structuredClone(options); + wrongGroup.declarationOrder.optionsForCompiler[0] = "watch"; + assert.throws(() => validateOptions(wrongGroup), /Unknown option in optionsForCompiler order: watch/); +}); + +test("generated declarations and build fields follow the explicit name lists", () => { + const files = generateOptions(); + const declarations = files.get("tsc/internal/tsoptions/declarations_generated.go")!; + for (const [group, names] of Object.entries(options.declarationOrder)) { + const body = declarations.split(`var ${group} = []*CommandLineOption{\n`)[1].split("\n}\n")[0]; + const expected = names.flatMap(name => + options.compilerOptions.find(option => option.name === name)!.declarations! + .filter(declaration => declaration.group === group).map(() => name) + ); + assert.deepEqual([...body.matchAll(/\bName: "([^"]+)"/g)].map(match => match[1]), expected); + } + const build = files.get("tsc/internal/core/options_generated.go")!.split("type BuildOptions struct {\n")[1].split("\n}\n")[0]; + assert.deepEqual([...build.matchAll(/`json:"([^",]+),omitzero"`/g)].map(match => match[1]), options.buildOptionFieldOrder); +}); + +test("option TypeScript enums are generated without reading their Go definitions", () => { + for (const optionEnum of options.enums.filter(enumDef => enumDef.api)) { + const def = enumDefs.find(def => def.name === optionEnum.name); + assert(def, optionEnum.name); + const { members, code } = generateEnum({ ...def, goFile: "does-not-exist.go" }); + assert.deepEqual( + members, + optionEnum.members.filter(member => !member.excludeFromAPI).map(member => ({ + name: member.name, + value: String(member.value), + })), + ); + assert.match(code, /^\/\/ Code generated by tools\/scripts\/tsc\/generate-enums.ts from tools\/scripts\/tsc\/options.ts\./); + assert.doesNotMatch(code, /does-not-exist|optionenums_generated/); + if (def.name === "ScriptTarget") { + assert(members.some(member => member.name === "Latest" && member.value === "ESNext")); + for (const name of ["None", "ES5", "LatestStandard"]) assert(!members.some(member => member.name === name), name); + } + } +}); + +test("other TypeScript enums retain their Go sources", () => { + const def = enumDefs.find(def => def.name === "SymbolFlags")!; + const { members, code } = generateEnum(def); + assert(members.length > 0); + assert.match(code, /from tsc\/internal\/ast\/symbolflags.go/); + assert.throws(() => generateEnum({ ...def, goFile: "does-not-exist.go" }), /ENOENT/); +}); + +test("SyntaxKind is generated without reading its Go definition", () => { + const def = enumDefs.find(def => def.name === "SyntaxKind")!; + const { members, code } = generateEnum({ ...def, goFile: "does-not-exist.go" }); + assert.match(code, /^\/\/ Code generated by tools\/scripts\/tsc\/generate-enums.ts from tools\/scripts\/tsc\/ast.json\./); + assert.deepEqual(members[0], { name: "Unknown", value: "0" }); + assert.deepEqual(members[1], { name: "EndOfFile", value: "1" }); + const countIndex = members.findIndex(member => member.name === "Count"); + assert(countIndex > 0); + assert.equal(members[countIndex].value, String(countIndex)); + assert(members.some(member => member.name === "FirstAssignment" && member.value === "EqualsToken")); + assert(members.some(member => member.name === "FirstJSDocTagNode" && member.value === "JSDocUnknownTag")); +}); + +test("metadata enum artifacts are current and use the shared alias ordering", () => { + for (const def of enumDefs.filter(def => def.metadata)) { + const { code } = generateEnum(def); + const name = def.name[0].toLowerCase() + def.name.slice(1); + const actual = fs.readFileSync(path.join(repoRoot, def.outDir, `${name}.enum.ts`), "utf8"); + assert.equal(actual.replaceAll("\r\n", "\n"), code, def.name); + } + const def = enumDefs.find(def => def.name === "SyntaxKind")!; + const { members } = generateEnum({ + ...def, + goFile: "does-not-exist.go", + metadata: { + file: "metadata.json", + members: [{ name: "Alias", value: "Value" }, { name: "Value", value: "7" }], + }, + }); + assert.deepEqual(members, [{ name: "Value", value: "7" }, { name: "Alias", value: "Value" }]); +}); + +test("option generation is deterministic", () => { + assert.deepEqual(generateOptions(), generateOptions()); +}); + +test("generated Go options are grouped by package and responsibility", () => { + assert.deepEqual([...generateOptions().keys()].filter(file => file.endsWith(".go")), [ + "tsc/internal/core/options_generated.go", + "tsc/internal/transpile/options_generated.go", + "tsc/internal/tsoptions/declarations_generated.go", + "tsc/internal/tsoptions/options_generated.go", + ]); +}); + +test("configDir substitution preserves eligible fields and explicit opt-outs", () => { + const files = generateOptions(); + const source = files.get("tsc/internal/tsoptions/options_generated.go")!.split("func handleOptionConfigDirTemplateSubstitution(")[1].split("\nfunc ")[0]; + for (const [name, content] of files) { + if (name.endsWith(".go")) assert.doesNotMatch(content, /allowConfigDirTemplateSubstitution/, name); + } + assert.deepEqual([...new Set([...source.matchAll(/compilerOptions\.(\w+)/g)].map(match => match[1]))], [ + "DeclarationDir", + "OutDir", + "Paths", + "RootDir", + "RootDirs", + "TsBuildInfoFile", + "TypeRoots", + "BaseUrl", + "OutFile", + "GenerateCpuProfile", + "GenerateTrace", + ]); + for (const name of ["project", "pprofDir"]) { + const declaration = options.compilerOptions.find(option => option.name === name)!.declarations![0]; + assert.equal(declaration.isFilePath, true); + assert.equal(declaration.allowConfigDirTemplateSubstitution, false); + } +}); + +test("compiler options preserve the internal fields comment", () => { + const source = generateOptions().get("tsc/internal/core/options_generated.go")!; + assert.match(source, /\/\/ Internal fields\nConfigFilePath /); +}); + +test("build options preserve the compiler options parsing comment", () => { + const source = generateOptions().get("tsc/internal/core/options_generated.go")!; + assert.match(source, /\/\/ CompilerOptions are not parsed here and will be available on ParsedBuildCommandLine\n\n\/\/ Internal fields\nClean /); +}); + +test("transpilation clears only options marked with an unknown transpile value", () => { + const source = generateOptions().get("tsc/internal/transpile/options_generated.go")!; + assert.deepEqual([...source.matchAll(/options\.(\w+) = ([^\n]+)/g)].map(match => [match[1], match[2]]), [ + ["AllowImportingTsExtensions", "core.TSUnknown"], + ["Composite", "core.TSUnknown"], + ["EmitDeclarationOnly", "core.TSUnknown"], + ["Declaration", "core.TSUnknown"], + ["DeclarationDir", '""'], + ["Incremental", "core.TSUnknown"], + ["Lib", "nil"], + ["NoEmit", "core.TSUnknown"], + ["NoEmitOnError", "core.TSUnknown"], + ["Paths", "nil"], + ["RootDirs", "nil"], + ["TsBuildInfoFile", '""'], + ["Types", "nil"], + ["OutFile", '""'], + ]); +}); + +test("option comparisons use effective values and Go field names", () => { + const source = generateOptionComparisons(); + assert.match(source, /oldOptions\.GetStrictOptionValue\(oldOptions\.NoImplicitAny\) != newOptions\.GetStrictOptionValue\(newOptions\.NoImplicitAny\)/); + assert.match(source, /oldOptions\.ESModuleInterop != newOptions\.ESModuleInterop/); + assert.doesNotMatch(source, /reflect\.|oldOptions\.Strict !=|oldOptions\.NoImplicitAny !=/); + + const model = structuredClone(options); + model.compilerOptions.find(option => option.name === "allowJs")!.declarations![0].affectsEmit = true; + const withAllowJs = generateOptionComparisons(model); + assert.match(withAllowJs, /oldOptions\.GetAllowJS\(\) != newOptions\.GetAllowJS\(\)/); + assert.doesNotMatch(withAllowJs, /oldOptions\.AllowJs !=/); +}); + +test("option comparisons reject types that require deep equality", () => { + for (const name of ["maxNodeModuleJsDepth", "types", "paths", "plugins"]) { + const model = structuredClone(options); + model.compilerOptions.find(option => option.name === name)!.declarations![0].affectsEmit = true; + assert.throws(() => generateOptionComparisons(model), new RegExp(`Unsupported comparison type for ${name}:`)); + } +}); + +test("build info omits zero values without treating empty collections as zero", () => { + const model = structuredClone(options); + for (const name of ["maxNodeModuleJsDepth", "types", "paths", "plugins"]) { + model.compilerOptions.find(option => option.name === name)!.declarations![0].affectsBuildInfo = true; + } + const source = generateBuildInfoOptions(model); + for (const field of ["MaxNodeModuleJsDepth", "Types", "Paths", "Plugins"]) { + assert(source.includes(`if options.${field} != nil {`), field); + } + assert.match(source, /if options\.Strict != core\.TSUnknown \{/); + assert.match(source, /if options\.OutDir != "" \{/); + assert.match(source, /if options\.Target != 0 \{/); + assert.doesNotMatch(source, /reflect\.|len\(|GetStrictOptionValue|GetAllowJS/); +}); + +test("all generated options artifacts are checked in and current", () => { + for (const [file, content] of generateOptions()) { + const actual = fs.readFileSync(path.join(repoRoot, file), "utf8"); + if (file.endsWith(".json")) { + assert.deepEqual(JSON.parse(actual), JSON.parse(content), file); + } + else { + // Ignore Go formatting, but preserve the contents of string literals and comments. + const tokens = (source: string) => source.match(/"(?:\\.|[^"\\])*"|`[^`]*`|\/\/[^\r\n]*|[^\s]/g); + assert.deepEqual(tokens(actual), tokens(content), file); + } + } +}); + +test("schema compiler properties are config-visible declarations plus schema-only history", () => { + const schema = generateConfigSchema("tsconfig"); + const expected = options.compilerOptions.filter(option => { + const declaration = option.declarations?.[0]; + return declaration && !declaration.isCommandLineOnly && declaration.category?.go !== "diagnostics.Command_line_Options"; + }).map(option => option.name); + assert.deepEqual(Object.keys(schema.definitions.compilerOptions.properties), [...expected, ...options.schemaOnlyOptions.map(option => option.name)]); + assert.deepEqual(Object.keys(schema.definitions.watchOptions.properties), options.watchOptions.map(option => option.name)); + assert.deepEqual(Object.keys(schema.definitions.typeAcquisition.properties), options.typeAcquisition.map(option => option.name)); + assert.deepEqual(Object.keys(schema.properties).filter(name => name !== "$schema" && name !== "watchOptions"), options.rootOptions.map(option => option.name)); +}); + +test("schemas retain historical options as deprecated without restoring native support", () => { + const files = generateOptions(); + const historical = { + charset: ["utf8", false], + out: ["bundle.js", false], + noImplicitUseStrict: [true, "true"], + noStrictGenericChecks: [true, "true"], + keyofStringsOnly: [true, "true"], + suppressExcessPropertyErrors: [true, "true"], + suppressImplicitAnyIndexErrors: [true, "true"], + preserveValueImports: [true, "true"], + importsNotUsedAsValues: ["preserve", "invalid"], + }; + for (const kind of ["tsconfig", "jsconfig"] as const) { + const schema = generateConfigSchema(kind); + for (const [name, [valid, invalid]] of Object.entries(historical)) { + const property = schema.definitions.compilerOptions.properties[name]; + assert(property, name); + assert.equal(property.deprecated, true, name); + assert(property.deprecationMessage, name); + assert(property.markdownDescription, name); + assert(accepts(property, valid, schema), name); + assert(accepts(property, null, schema), name); + assert(!accepts(property, invalid, schema), name); + assert(!options.compilerOptions.some(option => option.name === name), name); + for (const [file, content] of files) { + if (file.endsWith(".go")) assert(!content.includes(`"${name}"`), `${file}: ${name}`); + } + } + for (const [name, value] of [["target", "es3"], ["target", "es5"], ["module", "none"]]) { + const property = schema.definitions.compilerOptions.properties[name]; + assert(accepts(property, value, schema), `${name}: ${value}`); + assert(accepts(property, value.toUpperCase(), schema), `${name}: ${value.toUpperCase()}`); + const suggestions = property.anyOf![0].anyOf![0]; + assert.equal(suggestions.enumDescriptions![suggestions.enum!.indexOf(value)], "Deprecated."); + } + for (const value of ["remove", "preserve", "error", "REMOVE", "PrEsErVe", "ERROR"]) { + assert(accepts(schema.definitions.compilerOptions.properties.importsNotUsedAsValues, value, schema)); + } + const lib = schema.definitions.compilerOptions.properties.lib; + assert(accepts(lib, ["es2022.sharedmemory", "ES2022.SharedMemory"], schema)); + assert(!accepts(lib, ["es2022.sharedmemory.invalid"], schema)); + const suggestions = lib.anyOf![0].items!.anyOf![0]; + assert.equal(suggestions.enumDescriptions![suggestions.enum!.indexOf("es2022.sharedmemory")], "Deprecated."); + } + assert(!options.enumMaps.target.values.some(entry => entry.name === "es3")); + assert(!options.enumMaps.module.values.some(entry => entry.name === "none")); + assert(!options.enumMaps.lib.values.some(entry => entry.name === "es2022.sharedmemory")); +}); + +// Evaluate only the validation keywords emitted by this generator. Unknown keywords +// fail the test so new schema features must also get acceptance/rejection coverage. +function accepts(schema: JSONSchema, value: unknown, root: JSONSchema): boolean { + for (const key of Object.keys(schema)) { + assert( + [ + "$schema", + "$comment", + "$ref", + "title", + "description", + "markdownDescription", + "type", + "properties", + "definitions", + "additionalProperties", + "required", + "items", + "anyOf", + "allOf", + "enum", + "enumDescriptions", + "pattern", + "default", + "minimum", + "minLength", + "deprecated", + "deprecationMessage", + "allowComments", + "allowTrailingCommas", + ].includes(key), + `Unsupported schema keyword: ${key}`, + ); + } + if (schema.$ref) { + assert.match(schema.$ref, /^#\/definitions\/\w+$/); + const referenced = root.definitions?.[schema.$ref.slice("#/definitions/".length)]; + assert(referenced, `Missing reference: ${schema.$ref}`); + return accepts(referenced, value, root); + } + if (schema.anyOf && !schema.anyOf.some(branch => accepts(branch, value, root))) return false; + if (schema.allOf && !schema.allOf.every(branch => accepts(branch, value, root))) return false; + if (schema.type) { + const types = Array.isArray(schema.type) ? schema.type : [schema.type]; + const type = value === null ? "null" : Array.isArray(value) ? "array" : typeof value; + if (!types.includes(type)) return false; + } + if (schema.enum && !schema.enum.some(item => item === value)) return false; + if (typeof value === "string") { + if (schema.pattern && !new RegExp(schema.pattern).test(value)) return false; + if (schema.minLength !== undefined && value.length < schema.minLength) return false; + } + if (typeof value === "number" && schema.minimum !== undefined && value < schema.minimum) return false; + if (Array.isArray(value) && schema.items && !value.every(item => accepts(schema.items!, item, root))) return false; + if (typeof value === "object" && value !== null && !Array.isArray(value)) { + if (schema.required?.some(name => !Object.hasOwn(value, name))) return false; + for (const [name, property] of Object.entries(value)) { + const child = schema.properties?.[name]; + if (child) { + if (!accepts(child, property, root)) return false; + } + else if (schema.additionalProperties === false) return false; + else if (typeof schema.additionalProperties === "object" && !accepts(schema.additionalProperties, property, root)) return false; + } + } + return true; +} + +test("root option documentation is outside draft-07 references", () => { + for (const kind of ["tsconfig", "jsconfig"] as const) { + const schema = generateConfigSchema(kind); + for (const name of ["compilerOptions", "watchOptions", "typeAcquisition"]) { + const property = schema.properties[name]; + assert.equal(property.$ref, undefined, name); + assert.deepEqual(property.allOf, [{ $ref: `#/definitions/${name}` }]); + assert(property.description, name); + assert(property.markdownDescription, name); + } + } +}); + +test("schemas accept representative valid configs and reject malformed configs", () => { + const valid = [ + {}, + { compilerOptions: null, files: null, include: null, exclude: null, references: null, typeAcquisition: null, watchOptions: null }, + { compilerOptions: { strict: null, target: null, paths: null, types: null, maxNodeModuleJsDepth: null } }, + { extends: "./base.json", files: [] }, + { extends: ["./base.json", "some-package/tsconfig.json"], references: [{ path: "../project", circular: true }] }, + { compilerOptions: { target: "ESNext", module: "NodeNext", moduleResolution: "BUNDLER", jsx: "React-JSX", newLine: "LF" } }, + { compilerOptions: { paths: { "@/*": ["src/*"] }, plugins: [{ name: "some-plugin", customSetting: true }], moduleSuffixes: ["", ".native"] } }, + { watchOptions: { watchFile: "useFsEvents", excludeFiles: ["**/generated/*"], watchInterval: 2000 } }, + { typeAcquisition: { enable: true, include: ["node"], exclude: [] } }, + { contentMappers: [{ package: "mapper", extensions: [".vue"], options: { customSetting: true } }] }, + { "$schema": "./tsconfig.schema.json", "tool-specific": { anything: true } }, + ]; + const invalid = [ + null, + [], + true, + { extends: null }, + { extends: 1 }, + { extends: ["./base", false] }, + { files: ["file.ts", 1] }, + { compilerOptions: { strict: "true" } }, + { compilerOptions: { target: "es9999" } }, + { compilerOptions: { target: "es2025\n" } }, + { compilerOptions: { module: 99 } }, + { compilerOptions: { paths: { "@/*": "src/*" } } }, + { compilerOptions: { paths: { "@/*": [false] } } }, + { compilerOptions: { plugins: ["plugin"] } }, + { compilerOptions: { plugins: [{ name: false }] } }, + { compilerOptions: { maxNodeModuleJsDepth: "2" } }, + { watchOptions: { watchFile: "invented" } }, + { typeAcquisition: { enable: "true" } }, + { typeAcquisition: { exclude: [false] } }, + { references: [{ path: false }] }, + { references: [{}] }, + { references: [{ path: "" }] }, + { references: [{ path: null }] }, + { contentMappers: [{ package: "", extensions: [] }] }, + { contentMappers: [{ package: "mapper" }] }, + { contentMappers: [{ package: "mapper", extensions: [1] }] }, + { contentMappers: [{ package: "mapper", extensions: [], options: null }] }, + ]; + for (const kind of ["tsconfig", "jsconfig"] as const) { + const schema = generateConfigSchema(kind); + for (const config of valid) assert(accepts(schema, config, schema), `${kind}: ${JSON.stringify(config)}`); + for (const config of invalid) assert(!accepts(schema, config, schema), `${kind}: ${JSON.stringify(config)}`); + } +}); + +test("schemas preserve SchemaStore's extensible and partial option objects", () => { + const configs = [ + { compilerOptions: { strictTypo: true, showConfig: true } }, + { watchOptions: { customSetting: true } }, + { typeAcquisition: { customSetting: true } }, + { compilerOptions: { plugins: [{}] } }, + { references: [{ path: "../project", customSetting: true }] }, + { "ts-node": { transpileOnly: true }, "buildOptions": { force: true } }, + ]; + for (const kind of ["tsconfig", "jsconfig"] as const) { + const schema = generateConfigSchema(kind); + for (const config of configs) assert(accepts(schema, config, schema), `${kind}: ${JSON.stringify(config)}`); + } +}); + +test("every enum value accepts mixed casing without broadening the accepted names", () => { + const schema = generateConfigSchema("tsconfig"); + for (const [name, map] of Object.entries(options.enumMaps)) { + const option = schema.definitions.compilerOptions.properties[name] ?? schema.definitions.watchOptions.properties[name]; + assert(option, name); + const list = options.compilerOptions.some(option => option.name === name && optionKind(option) === "List"); + for (const entry of map.values) { + for (const text of [entry.name, entry.name.toUpperCase(), entry.name.replace(/[a-z]/g, (char, index: number) => index % 2 ? char.toUpperCase() : char)]) { + assert(accepts(option, list ? [text] : text, schema), `${name}: ${text}`); + } + for (const text of [`${entry.name}x`, `x${entry.name}`, `${entry.name}\n`, entry.name.replaceAll(".", "!")]) { + if (map.values.some(entry => entry.name === text)) continue; + assert(!accepts(option, list ? [text] : text, schema), `${name}: ${JSON.stringify(text)}`); + } + } + } +}); + +test("schema defaults are valid and conditional defaults stay descriptive", () => { + for (const kind of ["tsconfig", "jsconfig"] as const) { + const schema = generateConfigSchema(kind); + for (const definition of Object.values(schema.definitions)) { + for (const [name, property] of Object.entries(definition.properties)) { + if (property.default !== undefined) assert(accepts(property, property.default, schema), `${kind}: ${name}`); + } + } + assert.equal(schema.definitions.compilerOptions.properties.moduleResolution.default, undefined); + assert.match(schema.definitions.compilerOptions.properties.moduleResolution.description!, /Default:/); + const latestStandard = options.enums.find(enumDef => enumDef.name === "ScriptTarget")!.members.find(member => member.name === "LatestStandard")!.value; + assert.equal(schema.definitions.compilerOptions.properties.target.default, String(latestStandard).toLowerCase()); + for ( + const [name, value] of Object.entries({ + jsxFactory: "React.createElement", + jsxFragmentFactory: "React.Fragment", + jsxImportSource: "react", + reactNamespace: "React", + newLine: "lf", + tsBuildInfoFile: ".tsbuildinfo", + generateCpuProfile: "profile.cpuprofile", + }) + ) { + assert.equal(schema.definitions.compilerOptions.properties[name].default, value, `${kind}: ${name}`); + } + } + assert.doesNotMatch(generateConfigSchema("jsconfig").definitions.compilerOptions.properties.allowJs.description!, /Default:.*false/); + for (const name of ["jsxFactory", "reactNamespace"]) { + const description = options.compilerOptions.find(option => option.name === name)!.declarations![0].defaultValueDescription; + assert(typeof description === "string"); + assert.match(description, /^`.*`$/); + } +}); + +test("schema hover documentation includes reference links and conditional defaults", () => { + for (const kind of ["tsconfig", "jsconfig"] as const) { + const schema = generateConfigSchema(kind); + const compiler = schema.definitions.compilerOptions.properties; + for (const [name, property] of Object.entries(compiler)) { + const declaration = options.compilerOptions.find(option => option.name === name)?.declarations?.[0] + ?? options.schemaOnlyOptions.find(option => option.name === name); + assert(declaration, `${kind}: ${name}`); + if (!declaration.description) { + assert.equal(property.markdownDescription, undefined, `${kind}: ${name}`); + continue; + } + assert(property.description, `${kind}: ${name}`); + const markdown = property.markdownDescription; + assert(markdown, `${kind}: ${name}`); + assert(markdown.startsWith(property.description), `${kind}: ${name}`); + if (name === "deduplicatePackages" || name === "stableTypeOrdering") { + assert.equal(property.markdownDescription, property.description); + } + else { + assert(markdown.includes(`https://www.typescriptlang.org/tsconfig/#${name}`), `${kind}: ${name}`); + } + } + assert.match(compiler.moduleResolution.markdownDescription!, /Default:/); + assert.match(schema.definitions.watchOptions.properties.watchFile.markdownDescription!, /tsconfig\/#watchFile/); + for (const property of Object.values(schema.definitions.typeAcquisition.properties)) { + assert.match(property.markdownDescription!, /tsconfig\/#typeAcquisition/); + } + assert.match(schema.properties.include.markdownDescription!, /tsconfig\/#include/); + assert.equal(schema.properties.contentMappers.markdownDescription, schema.properties.contentMappers.description); + } + for (const [file, content] of generateOptions()) { + if (file.endsWith(".go")) assert.doesNotMatch(content, /DocumentationAnchor|SchemaDescription/); + } +}); + +test("invalid metadata is rejected before generating files", () => { + const duplicate = structuredClone(options); + duplicate.compilerOptions.push(duplicate.compilerOptions[0]); + assert.throws(() => validateOptions(duplicate), /Duplicate compiler option/); + const missingEnum = structuredClone(options); + delete missingEnum.enumMaps.target; + assert.throws(() => validateOptions(missingEnum), /Missing enum map: target/); + const missingElement = structuredClone(options); + delete missingElement.elements.lib; + assert.throws(() => validateOptions(missingElement), /Missing list element: lib/); + const missingConstant = structuredClone(options); + missingConstant.enumMaps.target.values[0].value = { go: "core.ScriptTargetMissing" }; + assert.throws(() => validateOptions(missingConstant), /Unknown enum constant/); + const invalidAlias = structuredClone(options); + invalidAlias.enums[0].members[0].value = "Missing"; + assert.throws(() => validateOptions(invalidAlias), /Unknown enum alias/); +}); + +test("schemas include config options, not API-only or command-line-only fields", () => { + const schema = generateConfigSchema("tsconfig"); + const properties = schema.definitions.compilerOptions.properties; + for (const name of ["strict", "paths", "plugins", "lib", "target", "diagnostics", "pretty"]) { + assert.ok(properties[name], name); + } + for (const name of ["configFilePath", "pathsBasePath", "noDtsResolution", "help", "watch", "showConfig", "runExternalCode"]) { + assert.equal(properties[name], undefined, name); + } +}); + +test("jsconfig defaults are distinct from tsconfig defaults", () => { + const ts = generateConfigSchema("tsconfig"); + const js = generateConfigSchema("jsconfig"); + for (const [name, value] of Object.entries({ allowJs: true, noEmit: true, skipLibCheck: true, maxNodeModuleJsDepth: 2 })) { + assert.equal(js.definitions.compilerOptions.properties[name].default, value); + assert.notEqual(ts.definitions.compilerOptions.properties[name].default, value); + } + assert.equal(js.definitions.typeAcquisition.properties.enable.default, true); + assert.equal(ts.definitions.typeAcquisition.properties.enable.default, false); +}); diff --git a/tools/scripts/tsc/options.ts b/tools/scripts/tsc/options.ts new file mode 100644 index 0000000000000..f9d908e621c7a --- /dev/null +++ b/tools/scripts/tsc/options.ts @@ -0,0 +1,2880 @@ +import { + diagnostic, + type OptionsModel, +} from "./options-model.ts"; + +export const options: OptionsModel = { + schemaOnlyOptions: [ + { + name: "charset", + type: "string", + description: "The text encoding used to read source files in early TypeScript versions.", + }, + { + name: "out", + type: "string", + description: "The legacy predecessor of outFile, which combined emitted JavaScript into a single file.", + }, + { + name: "noImplicitUseStrict", + type: "boolean", + description: "Disable adding 'use strict' directives to emitted JavaScript.", + }, + { + name: "noStrictGenericChecks", + type: "boolean", + description: "Disable strict checking of generic signatures in function types.", + }, + { + name: "keyofStringsOnly", + type: "boolean", + description: "Make keyof return only strings instead of strings, numbers, or symbols.", + }, + { + name: "suppressExcessPropertyErrors", + type: "boolean", + description: "Disable excess property errors when creating object literals.", + }, + { + name: "suppressImplicitAnyIndexErrors", + type: "boolean", + description: "Suppress noImplicitAny errors when indexing objects that lack index signatures.", + }, + { + name: "preserveValueImports", + type: "boolean", + description: "Preserve unused imported values in JavaScript output. Superseded by verbatimModuleSyntax.", + }, + { + name: "importsNotUsedAsValues", + type: "enum", + values: ["remove", "preserve", "error"], + description: "Control emit and checking for imports used only as types. Superseded by verbatimModuleSyntax.", + }, + ], + compilerOptions: [ + { + name: "allowJs", + type: "Tristate", + jsconfigDefault: true, + declarations: [ + { + group: "optionsForCompiler", + allowJsFlag: true, + affectsBuildInfo: true, + showInSimplifiedHelpView: true, + category: diagnostic("JavaScript Support"), + description: diagnostic("Allow JavaScript files to be a part of your program. Use the 'checkJs' option to get errors from these files."), + defaultValueDescription: diagnostic("`false`, unless `checkJs` is set"), + }, + ], + }, + { + name: "allowArbitraryExtensions", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsProgramStructure: true, + category: diagnostic("Modules"), + description: diagnostic("Enable importing files with any extension, provided a declaration file is present."), + defaultValueDescription: false, + }, + ], + }, + { + name: "allowImportingTsExtensions", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Modules"), + description: diagnostic("Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set."), + defaultValueDescription: false, + transpileOptionValue: { go: "core.TSUnknown" }, + }, + ], + }, + { + name: "allowNonTsExtensions", + type: "Tristate", + }, + { + name: "allowUmdGlobalAccess", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Modules"), + description: diagnostic("Allow accessing UMD globals from modules."), + defaultValueDescription: false, + }, + ], + }, + { + name: "allowUnreachableCode", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsBindDiagnostics: true, + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Type Checking"), + description: diagnostic("Disable error reporting for unreachable code."), + defaultValueDescription: { go: "core.TSUnknown" }, + }, + ], + }, + { + name: "allowUnusedLabels", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsBindDiagnostics: true, + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Type Checking"), + description: diagnostic("Disable error reporting for unused labels."), + defaultValueDescription: { go: "core.TSUnknown" }, + }, + ], + }, + { + name: "assumeChangesOnlyAffectDirectDependencies", + type: "Tristate", + declarations: [ + { + group: "commonOptionsWithBuild", + affectsSemanticDiagnostics: true, + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Watch and Build Modes"), + description: diagnostic("Have recompiles in projects that use 'incremental' and 'watch' mode assume that changes within a file will only affect files directly depending on it."), + defaultValueDescription: false, + }, + ], + }, + { + name: "checkJs", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsModuleResolution: true, + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + showInSimplifiedHelpView: true, + category: diagnostic("JavaScript Support"), + description: diagnostic("Enable error reporting in type-checked JavaScript files."), + defaultValueDescription: false, + }, + ], + }, + { + name: "customConditions", + type: "[]string", + declarations: [ + { + group: "optionsForCompiler", + affectsModuleResolution: true, + category: diagnostic("Modules"), + description: diagnostic("Conditions to set in addition to the resolver-specific defaults when resolving imports."), + }, + ], + }, + { + name: "composite", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsBuildInfo: true, + isTSConfigOnly: true, + category: diagnostic("Projects"), + transpileOptionValue: { go: "core.TSUnknown" }, + defaultValueDescription: false, + description: diagnostic("Enable constraints that allow a TypeScript project to be used with project references."), + }, + ], + }, + { + name: "emitDeclarationOnly", + type: "Tristate", + declarations: [ + { + group: "commonOptionsWithBuild", + comment: "Full emit is calculated separately, so this does not set affectsEmit.", + affectsBuildInfo: true, + showInSimplifiedHelpView: true, + category: diagnostic("Emit"), + description: diagnostic("Only output d.ts files and not JavaScript files."), + transpileOptionValue: { go: "core.TSUnknown" }, + defaultValueDescription: false, + }, + ], + }, + { + name: "emitBOM", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Emit"), + description: diagnostic("Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files."), + defaultValueDescription: false, + }, + ], + }, + { + name: "emitDecoratorMetadata", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Language and Environment"), + description: diagnostic("Emit design-type metadata for decorated declarations in source files."), + defaultValueDescription: false, + }, + ], + }, + { + name: "declaration", + type: "Tristate", + declarations: [ + { + group: "commonOptionsWithBuild", + comment: "Full emit is calculated separately, so this does not set affectsEmit.", + shortName: "d", + affectsBuildInfo: true, + showInSimplifiedHelpView: true, + category: diagnostic("Emit"), + transpileOptionValue: { go: "core.TSUnknown" }, + description: diagnostic("Generate .d.ts files from TypeScript and JavaScript files in your project."), + defaultValueDescription: diagnostic("`false`, unless `composite` is set"), + }, + ], + }, + { + name: "declarationDir", + type: "string", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + affectsDeclarationPath: true, + isFilePath: true, + category: diagnostic("Emit"), + transpileOptionValue: { go: "core.TSUnknown" }, + description: diagnostic("Specify the output directory for generated declaration files."), + }, + ], + }, + { + name: "declarationMap", + type: "Tristate", + declarations: [ + { + group: "commonOptionsWithBuild", + comment: "Full emit is calculated separately, so this does not set affectsEmit.", + affectsBuildInfo: true, + showInSimplifiedHelpView: true, + category: diagnostic("Emit"), + defaultValueDescription: false, + description: diagnostic("Create sourcemaps for d.ts files."), + }, + ], + }, + { + name: "deduplicatePackages", + type: "Tristate", + declarations: [ + { + group: "commonOptionsWithBuild", + category: diagnostic("Type Checking"), + description: diagnostic("Deduplicate packages with the same name and version."), + documentationAnchor: false, + defaultValueDescription: true, + affectsProgramStructure: true, + }, + ], + }, + { + name: "disableSizeLimit", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsProgramStructure: true, + category: diagnostic("Editor Support"), + description: diagnostic("Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server."), + defaultValueDescription: false, + }, + ], + }, + { + name: "disableSourceOfProjectReferenceRedirect", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + isTSConfigOnly: true, + category: diagnostic("Projects"), + description: diagnostic("Disable preferring source files instead of declaration files when referencing composite projects."), + defaultValueDescription: false, + }, + ], + }, + { + name: "disableSolutionSearching", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + isTSConfigOnly: true, + category: diagnostic("Projects"), + description: diagnostic("Opt a project out of multi-project reference checking when editing."), + defaultValueDescription: false, + }, + ], + }, + { + name: "disableReferencedProjectLoad", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + isTSConfigOnly: true, + category: diagnostic("Projects"), + description: diagnostic("Reduce the number of projects loaded automatically by TypeScript."), + defaultValueDescription: false, + }, + ], + }, + { + name: "erasableSyntaxOnly", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + category: diagnostic("Interop Constraints"), + description: diagnostic("Do not allow runtime constructs that are not part of ECMAScript."), + defaultValueDescription: false, + affectsBuildInfo: true, + affectsSemanticDiagnostics: true, + }, + ], + }, + { + name: "exactOptionalPropertyTypes", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Type Checking"), + description: diagnostic("Interpret optional property types as written, rather than adding 'undefined'."), + defaultValueDescription: false, + }, + ], + }, + { + name: "experimentalDecorators", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Language and Environment"), + description: diagnostic("Enable experimental support for legacy experimental decorators."), + defaultValueDescription: false, + }, + ], + }, + { + name: "forceConsistentCasingInFileNames", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsModuleResolution: true, + category: diagnostic("Interop Constraints"), + description: diagnostic("Ensure that casing is correct in imports."), + defaultValueDescription: true, + }, + ], + }, + { + name: "isolatedModules", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + category: diagnostic("Interop Constraints"), + description: diagnostic("Ensure that each file can be safely transpiled without relying on other imports."), + transpileOptionValue: { go: "core.TSTrue" }, + defaultValueDescription: false, + }, + ], + }, + { + name: "isolatedDeclarations", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + category: diagnostic("Interop Constraints"), + description: diagnostic("Require sufficient annotation on exports so other tools can trivially generate declaration files."), + defaultValueDescription: false, + affectsBuildInfo: true, + affectsSemanticDiagnostics: true, + }, + ], + }, + { + name: "ignoreConfig", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + showInSimplifiedHelpView: true, + category: diagnostic("Command-line Options"), + isCommandLineOnly: true, + description: diagnostic("Ignore the tsconfig found and build with commandline options and files."), + defaultValueDescription: false, + }, + ], + }, + { + name: "ignoreDeprecations", + type: "string", + declarations: [ + { + group: "optionsForCompiler", + defaultValueDescription: { go: "core.TSUnknown" }, + }, + ], + }, + { + name: "importHelpers", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + affectsSourceFile: true, + category: diagnostic("Emit"), + description: diagnostic("Allow importing helper functions from tslib once per project, instead of including them per-file."), + defaultValueDescription: false, + }, + ], + }, + { + name: "inlineSourceMap", + type: "Tristate", + declarations: [ + { + group: "commonOptionsWithBuild", + comment: "Full emit is calculated separately, so this does not set affectsEmit.", + affectsBuildInfo: true, + category: diagnostic("Emit"), + description: diagnostic("Include sourcemap files inside the emitted JavaScript."), + defaultValueDescription: false, + }, + ], + }, + { + name: "inlineSources", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Emit"), + description: diagnostic("Include source code in the sourcemaps inside the emitted JavaScript."), + defaultValueDescription: false, + }, + ], + }, + { + name: "init", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + showInSimplifiedHelpView: true, + category: diagnostic("Command-line Options"), + description: diagnostic("Initializes a TypeScript project and creates a tsconfig.json file."), + defaultValueDescription: false, + }, + ], + }, + { + name: "incremental", + type: "Tristate", + declarations: [ + { + group: "commonOptionsWithBuild", + shortName: "i", + category: diagnostic("Projects"), + description: diagnostic("Save .tsbuildinfo files to allow for incremental compilation of projects."), + transpileOptionValue: { go: "core.TSUnknown" }, + defaultValueDescription: diagnostic("`false`, unless `composite` is set"), + }, + ], + }, + { + name: "jsx", + type: "JsxEmit", + declarations: [ + { + group: "optionsForCompiler", + comment: "JSX without this option is a semantic error; changing it must refresh semantic diagnostics.", + affectsSourceFile: true, + affectsEmit: true, + affectsBuildInfo: true, + affectsModuleResolution: true, + affectsSemanticDiagnostics: true, + showInSimplifiedHelpView: true, + category: diagnostic("Language and Environment"), + description: diagnostic("Specify what JSX code is generated."), + defaultValueDescription: { go: "core.TSUnknown" }, + }, + ], + }, + { + name: "jsxFactory", + type: "string", + declarations: [ + { + group: "optionsForCompiler", + category: diagnostic("Language and Environment"), + description: diagnostic("Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'."), + defaultValueDescription: "`React.createElement`", + }, + ], + }, + { + name: "jsxFragmentFactory", + type: "string", + declarations: [ + { + group: "optionsForCompiler", + category: diagnostic("Language and Environment"), + description: diagnostic("Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'."), + defaultValueDescription: "React.Fragment", + }, + ], + }, + { + name: "jsxImportSource", + type: "string", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsEmit: true, + affectsBuildInfo: true, + affectsModuleResolution: true, + affectsSourceFile: true, + category: diagnostic("Language and Environment"), + description: diagnostic("Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'."), + defaultValueDescription: "react", + }, + ], + }, + { + name: "lib", + type: "[]string", + parser: "lib", + declarations: [ + { + group: "optionsForCompiler", + affectsProgramStructure: true, + showInSimplifiedHelpView: true, + category: diagnostic("Language and Environment"), + description: diagnostic("Specify a set of bundled library declaration files that describe the target runtime environment."), + transpileOptionValue: { go: "core.TSUnknown" }, + }, + ], + }, + { + name: "libReplacement", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsProgramStructure: true, + category: diagnostic("Language and Environment"), + description: diagnostic("Enable lib replacement."), + defaultValueDescription: false, + }, + ], + }, + { + name: "locale", + type: "string", + declarations: [ + { + group: "commonOptionsWithBuild", + category: diagnostic("Command-line Options"), + isCommandLineOnly: true, + description: diagnostic("Set the language of the messaging from TypeScript. This does not affect emit."), + defaultValueDescription: diagnostic("Platform specific"), + extraValidation: { go: "extraValidationLocale" }, + }, + ], + }, + { + name: "mapRoot", + type: "string", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Emit"), + description: diagnostic("Specify the location where debugger should locate map files instead of generated locations."), + }, + ], + }, + { + name: "module", + type: "ModuleKind", + declarations: [ + { + group: "optionsForCompiler", + shortName: "m", + affectsModuleResolution: true, + affectsEmit: true, + affectsBuildInfo: true, + showInSimplifiedHelpView: true, + category: diagnostic("Modules"), + description: diagnostic("Specify what module code is generated."), + defaultValueDescription: { go: "core.TSUnknown" }, + }, + ], + }, + { + name: "moduleResolution", + type: "ModuleResolutionKind", + declarations: [ + { + group: "optionsForCompiler", + affectsModuleResolution: true, + category: diagnostic("Modules"), + description: diagnostic("Specify how TypeScript looks up a file from a given module specifier."), + defaultValueDescription: diagnostic("`nodenext` if `module` is `nodenext`; `node16` if `module` is `node16` or `node18`; otherwise, `bundler`."), + }, + ], + }, + { + name: "moduleSuffixes", + type: "[]string", + declarations: [ + { + group: "optionsForCompiler", + listPreserveFalsyValues: true, + affectsModuleResolution: true, + category: diagnostic("Modules"), + description: diagnostic("List of file name suffixes to search when resolving a module."), + }, + ], + }, + { + name: "moduleDetection", + type: "ModuleDetectionKind", + parseAliases: [ + "moduleDetectionKind", + ], + declarations: [ + { + group: "optionsForCompiler", + affectsSourceFile: true, + affectsModuleResolution: true, + description: diagnostic("Control what method is used to detect module-format JS files."), + category: diagnostic("Language and Environment"), + defaultValueDescription: diagnostic('"auto": Treat files with imports, exports, import.meta, jsx (with jsx: react-jsx), or esm format (with module: node16+) as modules.'), + }, + ], + }, + { + name: "newLine", + type: "NewLineKind", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Emit"), + description: diagnostic("Set the newline character for emitting files."), + defaultValueDescription: "lf", + }, + ], + }, + { + name: "noEmit", + type: "Tristate", + jsconfigDefault: true, + declarations: [ + { + group: "commonOptionsWithBuild", + showInSimplifiedHelpView: true, + category: diagnostic("Emit"), + description: diagnostic("Disable emitting files from a compilation."), + transpileOptionValue: { go: "core.TSUnknown" }, + defaultValueDescription: false, + }, + ], + }, + { + name: "noCheck", + type: "Tristate", + declarations: [ + { + group: "commonOptionsWithBuild", + comment: "The builder handles this specially so changing noCheck does not discard all diagnostics.", + showInSimplifiedHelpView: false, + category: diagnostic("Compiler Diagnostics"), + description: diagnostic("Disable full type checking (only critical parse and emit errors will be reported)."), + transpileOptionValue: { go: "core.TSTrue" }, + defaultValueDescription: false, + }, + ], + }, + { + name: "noErrorTruncation", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Output Formatting"), + description: diagnostic("Disable truncating types in error messages."), + defaultValueDescription: false, + }, + ], + }, + { + name: "noFallthroughCasesInSwitch", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsBindDiagnostics: true, + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Type Checking"), + description: diagnostic("Enable error reporting for fallthrough cases in switch statements."), + defaultValueDescription: false, + }, + ], + }, + { + name: "noImplicitAny", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + strictFlag: true, + category: diagnostic("Type Checking"), + description: diagnostic("Enable error reporting for expressions and declarations with an implied 'any' type."), + defaultValueDescription: diagnostic("`true`, unless `strict` is `false`"), + }, + ], + }, + { + name: "noImplicitThis", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + strictFlag: true, + category: diagnostic("Type Checking"), + description: diagnostic("Enable error reporting when 'this' is given the type 'any'."), + defaultValueDescription: diagnostic("`true`, unless `strict` is `false`"), + }, + ], + }, + { + name: "noImplicitReturns", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Type Checking"), + description: diagnostic("Enable error reporting for codepaths that do not explicitly return in a function."), + defaultValueDescription: false, + }, + ], + }, + { + name: "noEmitHelpers", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Emit"), + description: diagnostic("Disable generating custom helper functions like '__extends' in compiled output."), + defaultValueDescription: false, + }, + ], + }, + { + name: "noLib", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + comment: "Transpilation does not supply library source files, so noLib avoids reporting missing files.", + category: diagnostic("Language and Environment"), + affectsProgramStructure: true, + description: diagnostic("Disable including any library files, including the default lib.d.ts."), + transpileOptionValue: { go: "core.TSTrue" }, + defaultValueDescription: false, + }, + ], + }, + { + name: "noPropertyAccessFromIndexSignature", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + showInSimplifiedHelpView: false, + category: diagnostic("Type Checking"), + description: diagnostic("Enforces using indexed accessors for keys declared using an indexed type."), + defaultValueDescription: false, + }, + ], + }, + { + name: "noUncheckedIndexedAccess", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Type Checking"), + description: diagnostic("Add 'undefined' to a type when accessed using an index."), + defaultValueDescription: false, + }, + ], + }, + { + name: "noEmitOnError", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Emit"), + transpileOptionValue: { go: "core.TSUnknown" }, + description: diagnostic("Disable emitting files if any type checking errors are reported."), + defaultValueDescription: false, + }, + ], + }, + { + name: "noUnusedLocals", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Type Checking"), + description: diagnostic("Enable error reporting when local variables aren't read."), + defaultValueDescription: false, + }, + ], + }, + { + name: "noUnusedParameters", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Type Checking"), + description: diagnostic("Raise an error when a function parameter isn't read."), + defaultValueDescription: false, + }, + ], + }, + { + name: "noResolve", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + comment: "Transpilation does not resolve the full program, so noResolve avoids reporting missing files.", + affectsModuleResolution: true, + category: diagnostic("Modules"), + description: diagnostic("Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project."), + transpileOptionValue: { go: "core.TSTrue" }, + defaultValueDescription: false, + }, + ], + }, + { + name: "noImplicitOverride", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Type Checking"), + description: diagnostic("Ensure overriding members in derived classes are marked with an override modifier."), + defaultValueDescription: false, + }, + ], + }, + { + name: "noUncheckedSideEffectImports", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Modules"), + description: diagnostic("Check side effect imports."), + defaultValueDescription: true, + }, + ], + }, + { + name: "outDir", + type: "string", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + affectsDeclarationPath: true, + isFilePath: true, + showInSimplifiedHelpView: true, + category: diagnostic("Emit"), + description: diagnostic("Specify an output folder for all emitted files."), + }, + ], + }, + { + name: "paths", + type: "*collections.OrderedMap[string, []string]", + declarations: [ + { + group: "optionsForCompiler", + affectsModuleResolution: true, + allowConfigDirTemplateSubstitution: true, + isTSConfigOnly: true, + category: diagnostic("Modules"), + description: diagnostic("Specify a set of entries that re-map imports to additional lookup locations."), + transpileOptionValue: { go: "core.TSUnknown" }, + }, + ], + }, + { + name: "plugins", + type: "[]PluginImport", + parser: "plugins", + comment: "Plugins are parsed only so tools can report that native TypeScript does not support them.", + declarations: [ + { + group: "optionsForCompiler", + isTSConfigOnly: true, + description: diagnostic("Specify a list of language service plugins to include."), + category: diagnostic("Editor Support"), + }, + ], + }, + { + name: "preserveConstEnums", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Emit"), + description: diagnostic("Disable erasing 'const enum' declarations in generated code."), + defaultValueDescription: false, + }, + ], + }, + { + name: "preserveSymlinks", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + category: diagnostic("Interop Constraints"), + description: diagnostic("Disable resolving symlinks to their realpath. This correlates to the same flag in node."), + defaultValueDescription: false, + }, + ], + }, + { + name: "project", + type: "string", + declarations: [ + { + group: "optionsForCompiler", + shortName: "p", + isFilePath: true, + allowConfigDirTemplateSubstitution: false, + showInSimplifiedHelpView: true, + category: diagnostic("Command-line Options"), + description: diagnostic("Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'."), + }, + ], + }, + { + name: "resolveJsonModule", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsModuleResolution: true, + category: diagnostic("Modules"), + description: diagnostic("Enable importing .json files."), + defaultValueDescription: false, + }, + ], + }, + { + name: "resolvePackageJsonExports", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsModuleResolution: true, + category: diagnostic("Modules"), + description: diagnostic("Use the package.json 'exports' field when resolving package imports."), + defaultValueDescription: diagnostic("`true` when 'moduleResolution' is 'node16', 'nodenext', or 'bundler'; otherwise `false`."), + }, + ], + }, + { + name: "resolvePackageJsonImports", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsModuleResolution: true, + category: diagnostic("Modules"), + description: diagnostic("Use the package.json 'imports' field when resolving imports."), + defaultValueDescription: diagnostic("`true` when 'moduleResolution' is 'node16', 'nodenext', or 'bundler'; otherwise `false`."), + }, + ], + }, + { + name: "removeComments", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + showInSimplifiedHelpView: true, + category: diagnostic("Emit"), + defaultValueDescription: false, + description: diagnostic("Disable emitting comments."), + }, + ], + }, + { + name: "rewriteRelativeImportExtensions", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Modules"), + description: diagnostic("Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files."), + defaultValueDescription: false, + }, + ], + }, + { + name: "reactNamespace", + type: "string", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Language and Environment"), + description: diagnostic("Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit."), + defaultValueDescription: "`React`", + }, + ], + }, + { + name: "rootDir", + type: "string", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + affectsDeclarationPath: true, + isFilePath: true, + category: diagnostic("Modules"), + description: diagnostic("Specify the root folder within your source files."), + defaultValueDescription: diagnostic("Computed from the list of input files"), + }, + ], + }, + { + name: "rootDirs", + type: "[]string", + declarations: [ + { + group: "optionsForCompiler", + isTSConfigOnly: true, + affectsModuleResolution: true, + allowConfigDirTemplateSubstitution: true, + category: diagnostic("Modules"), + description: diagnostic("Allow multiple folders to be treated as one when resolving modules."), + transpileOptionValue: { go: "core.TSUnknown" }, + defaultValueDescription: diagnostic("Computed from the list of input files"), + }, + ], + }, + { + name: "skipLibCheck", + type: "Tristate", + jsconfigDefault: true, + declarations: [ + { + group: "optionsForCompiler", + comment: "Store this in build info to determine whether library files need to be rechecked.", + affectsBuildInfo: true, + category: diagnostic("Completeness"), + description: diagnostic("Skip type checking all .d.ts files."), + defaultValueDescription: false, + }, + ], + }, + { + name: "stableTypeOrdering", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Type Checking"), + description: diagnostic("Ensure types are ordered stably and deterministically across compilations."), + documentationAnchor: false, + defaultValueDescription: true, + }, + ], + }, + { + name: "strict", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + comment: "Individual strict flags determine semantic diagnostics. Store strict in build info so their effective values can be recovered.", + affectsBuildInfo: true, + showInSimplifiedHelpView: true, + category: diagnostic("Type Checking"), + description: diagnostic("Enable all strict type-checking options."), + defaultValueDescription: true, + }, + ], + }, + { + name: "strictBindCallApply", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + strictFlag: true, + category: diagnostic("Type Checking"), + description: diagnostic("Check that the arguments for 'bind', 'call', and 'apply' methods match the original function."), + defaultValueDescription: diagnostic("`true`, unless `strict` is `false`"), + }, + ], + }, + { + name: "strictBuiltinIteratorReturn", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + strictFlag: true, + category: diagnostic("Type Checking"), + description: diagnostic("Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'."), + defaultValueDescription: diagnostic("`true`, unless `strict` is `false`"), + }, + ], + }, + { + name: "strictFunctionTypes", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + strictFlag: true, + category: diagnostic("Type Checking"), + description: diagnostic("When assigning functions, check to ensure parameters and the return values are subtype-compatible."), + defaultValueDescription: diagnostic("`true`, unless `strict` is `false`"), + }, + ], + }, + { + name: "strictNullChecks", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + strictFlag: true, + category: diagnostic("Type Checking"), + description: diagnostic("When type checking, take into account 'null' and 'undefined'."), + defaultValueDescription: diagnostic("`true`, unless `strict` is `false`"), + }, + ], + }, + { + name: "strictPropertyInitialization", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + strictFlag: true, + category: diagnostic("Type Checking"), + description: diagnostic("Check for class properties that are declared but not set in the constructor."), + defaultValueDescription: diagnostic("`true`, unless `strict` is `false`"), + }, + ], + }, + { + name: "stripInternal", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Emit"), + description: diagnostic("Disable emitting declarations that have '@internal' in their JSDoc comments."), + defaultValueDescription: false, + }, + ], + }, + { + name: "skipDefaultLibCheck", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + comment: "Store this in build info to determine whether library files need to be rechecked.", + affectsBuildInfo: true, + category: diagnostic("Completeness"), + description: diagnostic("Skip type checking .d.ts files that are included with TypeScript."), + defaultValueDescription: false, + }, + ], + }, + { + name: "sourceMap", + type: "Tristate", + declarations: [ + { + group: "commonOptionsWithBuild", + comment: "Full emit is calculated separately, so this does not set affectsEmit.", + affectsBuildInfo: true, + showInSimplifiedHelpView: true, + category: diagnostic("Emit"), + defaultValueDescription: false, + description: diagnostic("Create source map files for emitted JavaScript files."), + }, + ], + }, + { + name: "sourceRoot", + type: "string", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Emit"), + description: diagnostic("Specify the root path for debuggers to find the reference source code."), + }, + ], + }, + { + name: "suppressOutputPathCheck", + type: "Tristate", + }, + { + name: "target", + type: "ScriptTarget", + declarations: [ + { + group: "optionsForCompiler", + shortName: "t", + affectsSourceFile: true, + affectsModuleResolution: true, + affectsEmit: true, + affectsBuildInfo: true, + showInSimplifiedHelpView: true, + category: diagnostic("Language and Environment"), + description: diagnostic("Set the JavaScript language version for emitted JavaScript and include compatible library declarations."), + defaultValueDescription: { go: "core.ScriptTargetLatestStandard" }, + }, + ], + }, + { + name: "traceResolution", + type: "Tristate", + declarations: [ + { + group: "commonOptionsWithBuild", + category: diagnostic("Compiler Diagnostics"), + description: diagnostic("Log paths used during the 'moduleResolution' process."), + defaultValueDescription: false, + }, + ], + }, + { + name: "tsBuildInfoFile", + type: "string", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + isFilePath: true, + category: diagnostic("Projects"), + transpileOptionValue: { go: "core.TSUnknown" }, + defaultValueDescription: ".tsbuildinfo", + description: diagnostic("Specify the path to .tsbuildinfo incremental compilation file."), + }, + ], + }, + { + name: "typeRoots", + type: "[]string", + declarations: [ + { + group: "optionsForCompiler", + affectsModuleResolution: true, + allowConfigDirTemplateSubstitution: true, + category: diagnostic("Modules"), + description: diagnostic("Specify multiple folders that act like './node_modules/@types'."), + }, + ], + }, + { + name: "types", + type: "[]string", + declarations: [ + { + group: "optionsForCompiler", + affectsProgramStructure: true, + showInSimplifiedHelpView: true, + category: diagnostic("Modules"), + description: diagnostic("Specify type package names to be included without being referenced in a source file."), + transpileOptionValue: { go: "core.TSUnknown" }, + }, + ], + }, + { + name: "useDefineForClassFields", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Language and Environment"), + description: diagnostic("Emit ECMAScript-standard-compliant class fields."), + defaultValueDescription: diagnostic("`true` for ES2022 and above, including ESNext."), + }, + ], + }, + { + name: "useUnknownInCatchVariables", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + strictFlag: true, + category: diagnostic("Type Checking"), + description: diagnostic("Default catch clause variables as 'unknown' instead of 'any'."), + defaultValueDescription: diagnostic("`true`, unless `strict` is `false`"), + }, + ], + }, + { + name: "verbatimModuleSyntax", + type: "Tristate", + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Interop Constraints"), + description: diagnostic("Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting."), + defaultValueDescription: false, + }, + ], + }, + { + name: "maxNodeModuleJsDepth", + type: "*int", + jsconfigDefault: 2, + declarations: [ + { + group: "optionsForCompiler", + affectsModuleResolution: true, + category: diagnostic("JavaScript Support"), + description: diagnostic("Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'."), + defaultValueDescription: 0, + }, + ], + }, + { + name: "allowSyntheticDefaultImports", + type: "Tristate", + deprecated: true, + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: diagnostic("Interop Constraints"), + description: diagnostic("Allow 'import x from y' when a module doesn't have a default export."), + defaultValueDescription: true, + }, + ], + }, + { + name: "alwaysStrict", + type: "Tristate", + deprecated: true, + declarations: [ + { + group: "optionsForCompiler", + affectsSourceFile: true, + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Type Checking"), + description: diagnostic("Ensure 'use strict' is always emitted."), + defaultValueDescription: true, + }, + ], + }, + { + name: "baseUrl", + type: "string", + deprecated: true, + declarations: [ + { + group: "optionsForCompiler", + affectsModuleResolution: true, + isFilePath: true, + category: diagnostic("Modules"), + description: diagnostic("Specify the base directory to resolve non-relative module names."), + }, + ], + }, + { + name: "downlevelIteration", + type: "Tristate", + deprecated: true, + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + category: diagnostic("Emit"), + description: diagnostic("Emit more compliant, but verbose and less performant JavaScript for iteration."), + defaultValueDescription: false, + }, + ], + }, + { + name: "esModuleInterop", + type: "Tristate", + goName: "ESModuleInterop", + deprecated: true, + declarations: [ + { + group: "optionsForCompiler", + affectsSemanticDiagnostics: true, + affectsEmit: true, + affectsBuildInfo: true, + showInSimplifiedHelpView: true, + category: diagnostic("Interop Constraints"), + description: diagnostic("Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility."), + defaultValueDescription: true, + }, + ], + }, + { + name: "outFile", + type: "string", + deprecated: true, + declarations: [ + { + group: "optionsForCompiler", + affectsEmit: true, + affectsBuildInfo: true, + affectsDeclarationPath: true, + isFilePath: true, + showInSimplifiedHelpView: true, + category: diagnostic("Emit"), + description: diagnostic("Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output."), + transpileOptionValue: { go: "core.TSUnknown" }, + }, + ], + }, + { + name: "configFilePath", + type: "string", + comment: "Internal fields", + }, + { + name: "noDtsResolution", + type: "Tristate", + internal: true, + }, + { + name: "pathsBasePath", + type: "string", + internal: true, + }, + { + name: "diagnostics", + type: "Tristate", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + category: diagnostic("Compiler Diagnostics"), + description: diagnostic("Output compiler performance information after building."), + defaultValueDescription: false, + }, + ], + }, + { + name: "extendedDiagnostics", + type: "Tristate", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + category: diagnostic("Compiler Diagnostics"), + description: diagnostic("Output more detailed compiler performance information after building."), + defaultValueDescription: false, + }, + ], + }, + { + name: "generateCpuProfile", + type: "string", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + isFilePath: true, + category: diagnostic("Compiler Diagnostics"), + description: diagnostic("Emit a v8 CPU profile of the compiler run for debugging."), + defaultValueDescription: "profile.cpuprofile", + }, + ], + }, + { + name: "generateTrace", + type: "string", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + isFilePath: true, + category: diagnostic("Compiler Diagnostics"), + description: diagnostic("Generates an event trace and a list of types."), + }, + ], + }, + { + name: "listEmittedFiles", + type: "Tristate", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + category: diagnostic("Compiler Diagnostics"), + description: diagnostic("Print the names of emitted files after a compilation."), + defaultValueDescription: false, + }, + ], + }, + { + name: "listFiles", + type: "Tristate", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + category: diagnostic("Compiler Diagnostics"), + description: diagnostic("Print all of the files read during the compilation."), + defaultValueDescription: false, + }, + ], + }, + { + name: "explainFiles", + type: "Tristate", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + category: diagnostic("Compiler Diagnostics"), + description: diagnostic("Print files read during the compilation including why it was included."), + defaultValueDescription: false, + }, + ], + }, + { + name: "listFilesOnly", + type: "Tristate", + internal: true, + declarations: [ + { + group: "optionsForCompiler", + category: diagnostic("Command-line Options"), + isCommandLineOnly: true, + description: diagnostic("Print names of files that are part of the compilation and then stop processing."), + defaultValueDescription: false, + }, + ], + }, + { + name: "noEmitForJsFiles", + type: "Tristate", + internal: true, + }, + { + name: "preserveWatchOutput", + type: "Tristate", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + showInSimplifiedHelpView: false, + category: diagnostic("Output Formatting"), + description: diagnostic("Disable wiping the console in watch mode."), + defaultValueDescription: false, + }, + ], + }, + { + name: "pretty", + type: "Tristate", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + showInSimplifiedHelpView: true, + category: diagnostic("Output Formatting"), + description: diagnostic("Enable color and formatting in TypeScript's output to make compiler errors easier to read."), + defaultValueDescription: true, + }, + ], + }, + { + name: "version", + type: "Tristate", + internal: true, + declarations: [ + { + group: "optionsForCompiler", + shortName: "v", + showInSimplifiedHelpView: true, + category: diagnostic("Command-line Options"), + description: diagnostic("Print the compiler's version."), + defaultValueDescription: false, + }, + ], + }, + { + name: "watch", + type: "Tristate", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + shortName: "w", + showInSimplifiedHelpView: true, + isCommandLineOnly: true, + category: diagnostic("Command-line Options"), + description: diagnostic("Watch input files."), + defaultValueDescription: false, + }, + ], + }, + { + name: "showConfig", + type: "Tristate", + internal: true, + declarations: [ + { + group: "optionsForCompiler", + showInSimplifiedHelpView: true, + category: diagnostic("Command-line Options"), + isCommandLineOnly: true, + description: diagnostic("Print the final configuration instead of building."), + defaultValueDescription: false, + }, + ], + }, + { + name: "build", + type: "Tristate", + internal: true, + }, + { + name: "help", + type: "Tristate", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + shortName: "h", + showInSimplifiedHelpView: true, + isCommandLineOnly: true, + category: diagnostic("Command-line Options"), + description: diagnostic("Print this message."), + defaultValueDescription: false, + }, + { + group: "commonOptionsWithBuild", + shortName: "?", + isCommandLineOnly: true, + category: diagnostic("Command-line Options"), + defaultValueDescription: false, + }, + ], + }, + { + name: "all", + type: "Tristate", + internal: true, + declarations: [ + { + group: "optionsForCompiler", + showInSimplifiedHelpView: true, + category: diagnostic("Command-line Options"), + description: diagnostic("Show all compiler options."), + defaultValueDescription: false, + }, + ], + }, + { + name: "runExternalCode", + type: "Tristate", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + category: diagnostic("Command-line Options"), + isCommandLineOnly: true, + description: diagnostic("Allow loading external content mapper plugins that execute code during compilation."), + defaultValueDescription: false, + }, + ], + }, + { + name: "pprofDir", + type: "string", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + isFilePath: true, + allowConfigDirTemplateSubstitution: false, + category: diagnostic("Command-line Options"), + description: diagnostic("Generate pprof CPU/memory profiles to the given directory."), + }, + ], + }, + { + name: "singleThreaded", + type: "Tristate", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + category: diagnostic("Command-line Options"), + description: diagnostic("Run in single threaded mode."), + }, + ], + }, + { + name: "quiet", + type: "Tristate", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + shortName: "q", + category: diagnostic("Command-line Options"), + description: diagnostic("Do not print diagnostics."), + }, + ], + }, + { + name: "checkers", + type: "*int", + internal: true, + declarations: [ + { + group: "commonOptionsWithBuild", + category: diagnostic("Command-line Options"), + description: diagnostic("Set the number of checkers per project."), + defaultValueDescription: diagnostic("4, unless --singleThreaded is passed."), + minValue: 1, + }, + ], + }, + ], + // Preserve help and config output order independently of compiler fields. + // Multiple declarations of an option retain their metadata order. + declarationOrder: { + commonOptionsWithBuild: [ + "help", + "watch", + "preserveWatchOutput", + "listFiles", + "explainFiles", + "listEmittedFiles", + "pretty", + "traceResolution", + "diagnostics", + "extendedDiagnostics", + "generateCpuProfile", + "generateTrace", + "incremental", + "declaration", + "declarationMap", + "emitDeclarationOnly", + "sourceMap", + "inlineSourceMap", + "noCheck", + "deduplicatePackages", + "noEmit", + "assumeChangesOnlyAffectDirectDependencies", + "locale", + "quiet", + "singleThreaded", + "pprofDir", + "checkers", + "runExternalCode", + ], + optionsForCompiler: [ + "all", + "version", + "init", + "project", + "showConfig", + "listFilesOnly", + "ignoreConfig", + "target", + "module", + "lib", + "allowJs", + "checkJs", + "jsx", + "outFile", + "outDir", + "rootDir", + "composite", + "tsBuildInfoFile", + "removeComments", + "importHelpers", + "downlevelIteration", + "isolatedModules", + "verbatimModuleSyntax", + "isolatedDeclarations", + "erasableSyntaxOnly", + "libReplacement", + "strict", + "noImplicitAny", + "strictNullChecks", + "strictFunctionTypes", + "strictBindCallApply", + "strictPropertyInitialization", + "strictBuiltinIteratorReturn", + "noImplicitThis", + "useUnknownInCatchVariables", + "alwaysStrict", + "stableTypeOrdering", + "noUnusedLocals", + "noUnusedParameters", + "exactOptionalPropertyTypes", + "noImplicitReturns", + "noFallthroughCasesInSwitch", + "noUncheckedIndexedAccess", + "noImplicitOverride", + "noPropertyAccessFromIndexSignature", + "moduleResolution", + "baseUrl", + "paths", + "rootDirs", + "typeRoots", + "types", + "allowSyntheticDefaultImports", + "esModuleInterop", + "preserveSymlinks", + "allowUmdGlobalAccess", + "moduleSuffixes", + "allowImportingTsExtensions", + "rewriteRelativeImportExtensions", + "resolvePackageJsonExports", + "resolvePackageJsonImports", + "customConditions", + "noUncheckedSideEffectImports", + "sourceRoot", + "mapRoot", + "inlineSources", + "experimentalDecorators", + "emitDecoratorMetadata", + "jsxFactory", + "jsxFragmentFactory", + "jsxImportSource", + "resolveJsonModule", + "allowArbitraryExtensions", + "reactNamespace", + "skipDefaultLibCheck", + "emitBOM", + "newLine", + "noErrorTruncation", + "noLib", + "noResolve", + "stripInternal", + "disableSizeLimit", + "disableSourceOfProjectReferenceRedirect", + "disableSolutionSearching", + "disableReferencedProjectLoad", + "noEmitHelpers", + "noEmitOnError", + "preserveConstEnums", + "declarationDir", + "skipLibCheck", + "allowUnusedLabels", + "allowUnreachableCode", + "forceConsistentCasingInFileNames", + "maxNodeModuleJsDepth", + "useDefineForClassFields", + "plugins", + "moduleDetection", + "ignoreDeprecations", + ], + }, + watchOptions: [ + { + name: "watchInterval", + kind: "Number", + category: diagnostic("Watch and Build Modes"), + field: { + name: "Interval", + type: "*int", + }, + }, + { + name: "watchFile", + kind: "Enum", + category: diagnostic("Watch and Build Modes"), + description: diagnostic("Specify how the TypeScript watch mode works."), + defaultValueDescription: { go: "core.WatchFileKindUseFsEvents" }, + field: { + name: "FileKind", + type: "WatchFileKind", + }, + }, + { + name: "watchDirectory", + kind: "Enum", + category: diagnostic("Watch and Build Modes"), + description: diagnostic("Specify how directories are watched on systems that lack recursive file-watching functionality."), + defaultValueDescription: { go: "core.WatchDirectoryKindUseFsEvents" }, + field: { + name: "DirectoryKind", + type: "WatchDirectoryKind", + }, + }, + { + name: "fallbackPolling", + kind: "Enum", + category: diagnostic("Watch and Build Modes"), + description: diagnostic("Specify what approach the watcher should use if the system runs out of native file watchers."), + defaultValueDescription: { go: "core.PollingKindPriorityInterval" }, + field: { + name: "FallbackPolling", + type: "PollingKind", + }, + }, + { + name: "synchronousWatchDirectory", + kind: "Boolean", + category: diagnostic("Watch and Build Modes"), + description: diagnostic("Synchronously call callbacks and update the state of directory watchers on platforms that don`t support recursive watching natively."), + defaultValueDescription: false, + field: { + name: "SyncWatchDir", + type: "Tristate", + }, + }, + { + name: "excludeDirectories", + kind: "List", + allowConfigDirTemplateSubstitution: true, + category: diagnostic("Watch and Build Modes"), + description: diagnostic("Remove a list of directories from the watch process."), + field: { + name: "ExcludeDir", + type: "[]string", + }, + }, + { + name: "excludeFiles", + kind: "List", + allowConfigDirTemplateSubstitution: true, + category: diagnostic("Watch and Build Modes"), + description: diagnostic("Remove a list of files from the watch mode's processing."), + field: { + name: "ExcludeFiles", + type: "[]string", + }, + }, + ], + typeAcquisition: [ + { + name: "enable", + kind: "Boolean", + schemaDescription: "Enable automatic type acquisition for JavaScript projects.", + jsconfigDefault: true, + defaultValueDescription: false, + field: { + name: "Enable", + type: "Tristate", + }, + }, + { + name: "include", + kind: "List", + schemaDescription: "Packages to include in automatic type acquisition.", + field: { + name: "Include", + type: "[]string", + }, + }, + { + name: "exclude", + kind: "List", + schemaDescription: "Packages to exclude from automatic type acquisition.", + field: { + name: "Exclude", + type: "[]string", + }, + }, + { + name: "disableFilenameBasedTypeAcquisition", + kind: "Boolean", + schemaDescription: "Disable inferring type acquisition packages from file names.", + defaultValueDescription: false, + field: { + name: "DisableFilenameBasedTypeAcquisition", + type: "Tristate", + }, + }, + ], + buildOptions: [ + { + name: "build", + kind: "Boolean", + shortName: "b", + showInSimplifiedHelpView: true, + category: diagnostic("Command-line Options"), + description: diagnostic("Build one or more projects and their dependencies, if out of date"), + defaultValueDescription: false, + }, + { + name: "verbose", + kind: "Boolean", + shortName: "v", + category: diagnostic("Command-line Options"), + description: diagnostic("Enable verbose logging."), + defaultValueDescription: false, + field: { name: "Verbose", type: "Tristate" }, + }, + { + name: "dry", + kind: "Boolean", + shortName: "d", + category: diagnostic("Command-line Options"), + description: diagnostic("Show what would be built (or deleted, if specified with '--clean')"), + defaultValueDescription: false, + field: { name: "Dry", type: "Tristate" }, + }, + { + name: "force", + kind: "Boolean", + shortName: "f", + category: diagnostic("Command-line Options"), + description: diagnostic("Build all projects, including those that appear to be up to date."), + defaultValueDescription: false, + field: { name: "Force", type: "Tristate" }, + }, + { + name: "clean", + kind: "Boolean", + category: diagnostic("Command-line Options"), + description: diagnostic("Delete the outputs of all projects."), + defaultValueDescription: false, + field: { + name: "Clean", + type: "Tristate", + comment: "CompilerOptions are not parsed here and will be available on ParsedBuildCommandLine\n\nInternal fields", + }, + }, + { + name: "builders", + kind: "Number", + category: diagnostic("Command-line Options"), + description: diagnostic("Set the number of projects to build concurrently."), + defaultValueDescription: diagnostic("4, unless --singleThreaded is passed."), + minValue: 1, + field: { name: "Builders", type: "*int" }, + }, + { + name: "stopBuildOnErrors", + kind: "Boolean", + category: diagnostic("Command-line Options"), + description: diagnostic("Skip building downstream projects on error in upstream project."), + defaultValueDescription: false, + field: { name: "StopBuildOnErrors", type: "Tristate" }, + }, + ], + buildOptionFieldOrder: ["dry", "force", "verbose", "builders", "stopBuildOnErrors", "clean"], + rootOptions: [ + { name: "compilerOptions", kind: "Object", variable: "compilerOptionsDeclaration", elementOptions: "compilerOptions", documentationAnchor: "" }, + { name: "typeAcquisition", kind: "Object", variable: "typeAcquisitionDeclaration", elementOptions: "typeAcquisition" }, + { name: "extends", kind: "ListOrElement", variable: "extendsOptionDeclaration", category: diagnostic("File Management"), elementOptions: "extends" }, + { name: "references", kind: "List" }, + { name: "contentMappers", kind: "List", documentationAnchor: false }, + { name: "files", kind: "List" }, + { name: "include", kind: "List" }, + { name: "exclude", kind: "List" }, + { name: "compileOnSave", kind: "Boolean", variable: "compileOnSaveCommandLineOption", defaultValueDescription: false, documentationAnchor: false }, + ], + elements: { + lib: { + name: "lib", + kind: "Enum", + defaultValueDescription: { go: "core.TSUnknown" }, + }, + rootDirs: { + name: "rootDirs", + kind: "String", + isFilePath: true, + }, + typeRoots: { + name: "typeRoots", + kind: "String", + isFilePath: true, + }, + types: { + name: "types", + kind: "String", + }, + moduleSuffixes: { + name: "moduleSuffixes", + kind: "String", + }, + customConditions: { + name: "condition", + kind: "String", + }, + plugins: { + name: "plugin", + kind: "Object", + }, + references: { + name: "references", + kind: "Object", + }, + contentMappers: { + name: "contentMappers", + kind: "Object", + }, + files: { + name: "files", + kind: "String", + }, + include: { + name: "include", + kind: "String", + }, + exclude: { + name: "exclude", + kind: "String", + }, + extends: { + name: "extends", + kind: "String", + }, + excludeDirectories: { + name: "excludeDirectory", + kind: "String", + isFilePath: true, + extraValidation: { go: "extraValidationSpec" }, + }, + excludeFiles: { + name: "excludeFile", + kind: "String", + isFilePath: true, + extraValidation: { go: "extraValidationSpec" }, + }, + libFiles: { + name: "libFiles", + kind: "String", + }, + }, + enumMaps: { + lib: { + goName: "LibMap", + schemaOnlyValues: ["es2022.sharedmemory"], + values: [ + { name: "es5", value: "lib.es5.d.ts" }, + { name: "es6", value: "lib.es2015.d.ts" }, + { name: "es2015", value: "lib.es2015.d.ts" }, + { name: "es7", value: "lib.es2016.d.ts" }, + { name: "es2016", value: "lib.es2016.d.ts" }, + { name: "es2017", value: "lib.es2017.d.ts" }, + { name: "es2018", value: "lib.es2018.d.ts" }, + { name: "es2019", value: "lib.es2019.d.ts" }, + { name: "es2020", value: "lib.es2020.d.ts" }, + { name: "es2021", value: "lib.es2021.d.ts" }, + { name: "es2022", value: "lib.es2022.d.ts" }, + { name: "es2023", value: "lib.es2023.d.ts" }, + { name: "es2024", value: "lib.es2024.d.ts" }, + { name: "es2025", value: "lib.es2025.d.ts" }, + { name: "esnext", value: "lib.esnext.d.ts" }, + { name: "dom", value: "lib.dom.d.ts" }, + { name: "dom.iterable", value: "lib.dom.iterable.d.ts" }, + { name: "dom.asynciterable", value: "lib.dom.asynciterable.d.ts" }, + { name: "webworker", value: "lib.webworker.d.ts" }, + { name: "webworker.importscripts", value: "lib.webworker.importscripts.d.ts" }, + { name: "webworker.iterable", value: "lib.webworker.iterable.d.ts" }, + { name: "webworker.asynciterable", value: "lib.webworker.asynciterable.d.ts" }, + { name: "scripthost", value: "lib.scripthost.d.ts" }, + { name: "es2015.core", value: "lib.es2015.core.d.ts" }, + { name: "es2015.collection", value: "lib.es2015.collection.d.ts" }, + { name: "es2015.generator", value: "lib.es2015.generator.d.ts" }, + { name: "es2015.iterable", value: "lib.es2015.iterable.d.ts" }, + { name: "es2015.promise", value: "lib.es2015.promise.d.ts" }, + { name: "es2015.proxy", value: "lib.es2015.proxy.d.ts" }, + { name: "es2015.reflect", value: "lib.es2015.reflect.d.ts" }, + { name: "es2015.symbol", value: "lib.es2015.symbol.d.ts" }, + { name: "es2015.symbol.wellknown", value: "lib.es2015.symbol.wellknown.d.ts" }, + { name: "es2016.array.include", value: "lib.es2016.array.include.d.ts" }, + { name: "es2016.intl", value: "lib.es2016.intl.d.ts" }, + { name: "es2017.arraybuffer", value: "lib.es2017.arraybuffer.d.ts" }, + { name: "es2017.date", value: "lib.es2017.date.d.ts" }, + { name: "es2017.object", value: "lib.es2017.object.d.ts" }, + { name: "es2017.sharedmemory", value: "lib.es2017.sharedmemory.d.ts" }, + { name: "es2017.string", value: "lib.es2017.string.d.ts" }, + { name: "es2017.intl", value: "lib.es2017.intl.d.ts" }, + { name: "es2017.typedarrays", value: "lib.es2017.typedarrays.d.ts" }, + { name: "es2018.asyncgenerator", value: "lib.es2018.asyncgenerator.d.ts" }, + { name: "es2018.asynciterable", value: "lib.es2018.asynciterable.d.ts" }, + { name: "es2018.intl", value: "lib.es2018.intl.d.ts" }, + { name: "es2018.promise", value: "lib.es2018.promise.d.ts" }, + { name: "es2018.regexp", value: "lib.es2018.regexp.d.ts" }, + { name: "es2019.array", value: "lib.es2019.array.d.ts" }, + { name: "es2019.object", value: "lib.es2019.object.d.ts" }, + { name: "es2019.string", value: "lib.es2019.string.d.ts" }, + { name: "es2019.symbol", value: "lib.es2019.symbol.d.ts" }, + { name: "es2019.intl", value: "lib.es2019.intl.d.ts" }, + { name: "es2020.bigint", value: "lib.es2020.bigint.d.ts" }, + { name: "es2020.date", value: "lib.es2020.date.d.ts" }, + { name: "es2020.promise", value: "lib.es2020.promise.d.ts" }, + { name: "es2020.sharedmemory", value: "lib.es2020.sharedmemory.d.ts" }, + { name: "es2020.string", value: "lib.es2020.string.d.ts" }, + { name: "es2020.symbol.wellknown", value: "lib.es2020.symbol.wellknown.d.ts" }, + { name: "es2020.intl", value: "lib.es2020.intl.d.ts" }, + { name: "es2020.number", value: "lib.es2020.number.d.ts" }, + { name: "es2021.promise", value: "lib.es2021.promise.d.ts" }, + { name: "es2021.string", value: "lib.es2021.string.d.ts" }, + { name: "es2021.weakref", value: "lib.es2021.weakref.d.ts" }, + { name: "es2021.intl", value: "lib.es2021.intl.d.ts" }, + { name: "es2022.array", value: "lib.es2022.array.d.ts" }, + { name: "es2022.error", value: "lib.es2022.error.d.ts" }, + { name: "es2022.intl", value: "lib.es2022.intl.d.ts" }, + { name: "es2022.object", value: "lib.es2022.object.d.ts" }, + { name: "es2022.string", value: "lib.es2022.string.d.ts" }, + { name: "es2022.regexp", value: "lib.es2022.regexp.d.ts" }, + { name: "es2023.array", value: "lib.es2023.array.d.ts" }, + { name: "es2023.collection", value: "lib.es2023.collection.d.ts" }, + { name: "es2023.intl", value: "lib.es2023.intl.d.ts" }, + { name: "es2024.arraybuffer", value: "lib.es2024.arraybuffer.d.ts" }, + { name: "es2024.collection", value: "lib.es2024.collection.d.ts" }, + { name: "es2024.object", value: "lib.es2024.object.d.ts" }, + { name: "es2024.promise", value: "lib.es2024.promise.d.ts" }, + { name: "es2024.regexp", value: "lib.es2024.regexp.d.ts" }, + { name: "es2024.sharedmemory", value: "lib.es2024.sharedmemory.d.ts" }, + { name: "es2024.string", value: "lib.es2024.string.d.ts" }, + { name: "es2025.collection", value: "lib.es2025.collection.d.ts" }, + { name: "es2025.float16", value: "lib.es2025.float16.d.ts" }, + { name: "es2025.intl", value: "lib.es2025.intl.d.ts" }, + { name: "es2025.iterator", value: "lib.es2025.iterator.d.ts" }, + { name: "es2025.promise", value: "lib.es2025.promise.d.ts" }, + { name: "es2025.regexp", value: "lib.es2025.regexp.d.ts" }, + { name: "esnext.asynciterable", value: "lib.es2018.asynciterable.d.ts" }, + { name: "esnext.symbol", value: "lib.es2019.symbol.d.ts" }, + { name: "esnext.bigint", value: "lib.es2020.bigint.d.ts" }, + { name: "esnext.weakref", value: "lib.es2021.weakref.d.ts" }, + { name: "esnext.object", value: "lib.es2024.object.d.ts" }, + { name: "esnext.regexp", value: "lib.es2024.regexp.d.ts" }, + { name: "esnext.string", value: "lib.es2024.string.d.ts" }, + { name: "esnext.float16", value: "lib.es2025.float16.d.ts" }, + { name: "esnext.iterator", value: "lib.es2025.iterator.d.ts" }, + { name: "esnext.promise", value: "lib.es2025.promise.d.ts" }, + { name: "esnext.array", value: "lib.esnext.array.d.ts" }, + { name: "esnext.collection", value: "lib.esnext.collection.d.ts" }, + { name: "esnext.date", value: "lib.esnext.date.d.ts" }, + { name: "esnext.decorators", value: "lib.esnext.decorators.d.ts" }, + { name: "esnext.disposable", value: "lib.esnext.disposable.d.ts" }, + { name: "esnext.error", value: "lib.esnext.error.d.ts" }, + { name: "esnext.intl", value: "lib.esnext.intl.d.ts" }, + { name: "esnext.sharedmemory", value: "lib.esnext.sharedmemory.d.ts" }, + { name: "esnext.temporal", value: "lib.esnext.temporal.d.ts" }, + { name: "esnext.typedarrays", value: "lib.esnext.typedarrays.d.ts" }, + { name: "decorators", value: "lib.decorators.d.ts" }, + { name: "decorators.legacy", value: "lib.decorators.legacy.d.ts" }, + ], + }, + moduleResolution: { + goName: "moduleResolutionOptionMap", + values: [ + { name: "node16", value: { go: "core.ModuleResolutionKindNode16" } }, + { name: "nodenext", value: { go: "core.ModuleResolutionKindNodeNext" } }, + { name: "bundler", value: { go: "core.ModuleResolutionKindBundler" } }, + { name: "classic", value: { go: "core.ModuleResolutionKindClassic" } }, + { name: "node", value: { go: "core.ModuleResolutionKindNode10" } }, + { name: "node10", value: { go: "core.ModuleResolutionKindNode10" } }, + ], + deprecatedKeys: [ + "node", + "classic", + "node10", + ], + }, + module: { + goName: "moduleOptionMap", + schemaOnlyValues: ["none"], + values: [ + { name: "commonjs", value: { go: "core.ModuleKindCommonJS" } }, + { name: "amd", value: { go: "core.ModuleKindAMD" } }, + { name: "system", value: { go: "core.ModuleKindSystem" } }, + { name: "umd", value: { go: "core.ModuleKindUMD" } }, + { name: "es6", value: { go: "core.ModuleKindES2015" } }, + { name: "es2015", value: { go: "core.ModuleKindES2015" } }, + { name: "es2020", value: { go: "core.ModuleKindES2020" } }, + { name: "es2022", value: { go: "core.ModuleKindES2022" } }, + { name: "esnext", value: { go: "core.ModuleKindESNext" } }, + { name: "node16", value: { go: "core.ModuleKindNode16" } }, + { name: "node18", value: { go: "core.ModuleKindNode18" } }, + { name: "node20", value: { go: "core.ModuleKindNode20" } }, + { name: "nodenext", value: { go: "core.ModuleKindNodeNext" } }, + { name: "preserve", value: { go: "core.ModuleKindPreserve" } }, + ], + deprecatedKeys: [ + "none", + "amd", + "system", + "umd", + ], + }, + target: { + goName: "targetOptionMap", + schemaOnlyValues: ["es3"], + values: [ + { name: "es5", value: { go: "core.ScriptTargetES5" } }, + { name: "es6", value: { go: "core.ScriptTargetES2015" } }, + { name: "es2015", value: { go: "core.ScriptTargetES2015" } }, + { name: "es2016", value: { go: "core.ScriptTargetES2016" } }, + { name: "es2017", value: { go: "core.ScriptTargetES2017" } }, + { name: "es2018", value: { go: "core.ScriptTargetES2018" } }, + { name: "es2019", value: { go: "core.ScriptTargetES2019" } }, + { name: "es2020", value: { go: "core.ScriptTargetES2020" } }, + { name: "es2021", value: { go: "core.ScriptTargetES2021" } }, + { name: "es2022", value: { go: "core.ScriptTargetES2022" } }, + { name: "es2023", value: { go: "core.ScriptTargetES2023" } }, + { name: "es2024", value: { go: "core.ScriptTargetES2024" } }, + { name: "es2025", value: { go: "core.ScriptTargetES2025" } }, + { name: "esnext", value: { go: "core.ScriptTargetESNext" } }, + ], + deprecatedKeys: [ + "es5", + ], + }, + moduleDetection: { + goName: "moduleDetectionOptionMap", + values: [ + { name: "auto", value: { go: "core.ModuleDetectionKindAuto" } }, + { name: "legacy", value: { go: "core.ModuleDetectionKindLegacy" } }, + { name: "force", value: { go: "core.ModuleDetectionKindForce" } }, + ], + }, + jsx: { + goName: "jsxOptionMap", + values: [ + { name: "preserve", value: { go: "core.JsxEmitPreserve" } }, + { name: "react-native", value: { go: "core.JsxEmitReactNative" } }, + { name: "react-jsx", value: { go: "core.JsxEmitReactJSX" } }, + { name: "react-jsxdev", value: { go: "core.JsxEmitReactJSXDev" } }, + { name: "react", value: { go: "core.JsxEmitReact" } }, + ], + }, + newLine: { + goName: "newLineOptionMap", + values: [ + { name: "crlf", value: { go: "core.NewLineKindCRLF" } }, + { name: "lf", value: { go: "core.NewLineKindLF" } }, + ], + }, + watchFile: { + goName: "watchFileEnumMap", + values: [ + { name: "fixedpollinginterval", value: { go: "core.WatchFileKindFixedPollingInterval" } }, + { name: "prioritypollinginterval", value: { go: "core.WatchFileKindPriorityPollingInterval" } }, + { name: "dynamicprioritypolling", value: { go: "core.WatchFileKindDynamicPriorityPolling" } }, + { name: "fixedchunksizepolling", value: { go: "core.WatchFileKindFixedChunkSizePolling" } }, + { name: "usefsevents", value: { go: "core.WatchFileKindUseFsEvents" } }, + { name: "usefseventsonparentdirectory", value: { go: "core.WatchFileKindUseFsEventsOnParentDirectory" } }, + ], + }, + watchDirectory: { + goName: "watchDirectoryEnumMap", + values: [ + { name: "usefsevents", value: { go: "core.WatchDirectoryKindUseFsEvents" } }, + { name: "fixedpollinginterval", value: { go: "core.WatchDirectoryKindFixedPollingInterval" } }, + { name: "dynamicprioritypolling", value: { go: "core.WatchDirectoryKindDynamicPriorityPolling" } }, + { name: "fixedchunksizepolling", value: { go: "core.WatchDirectoryKindFixedChunkSizePolling" } }, + ], + }, + fallbackPolling: { + goName: "fallbackEnumMap", + values: [ + { name: "fixedinterval", value: { go: "core.PollingKindFixedInterval" } }, + { name: "priorityinterval", value: { go: "core.PollingKindPriorityInterval" } }, + { name: "dynamicpriority", value: { go: "core.PollingKindDynamicPriority" } }, + { name: "fixedchunksize", value: { go: "core.PollingKindFixedChunkSize" } }, + ], + }, + }, + enums: [ + { + name: "ModuleDetectionKind", + api: true, + members: [ + { + name: "None", + value: 0, + }, + { + name: "Auto", + value: 1, + }, + { + name: "Legacy", + value: 2, + }, + { + name: "Force", + value: 3, + }, + ], + }, + { + name: "ModuleKind", + api: true, + members: [ + { + name: "None", + value: 0, + }, + { + name: "CommonJS", + value: 1, + }, + { + name: "AMD", + value: 2, + comment: "Deprecated: Do not use outside of options parsing and validation.", + }, + { + name: "UMD", + value: 3, + comment: "Deprecated: Do not use outside of options parsing and validation.", + }, + { + name: "System", + value: 4, + comment: "Deprecated: Do not use outside of options parsing and validation.", + }, + { + name: "ES2015", + value: 5, + comment: "NOTE: ES module kinds should be contiguous to more easily check whether a module kind is *any* ES module kind.\nNon-ES module kinds should not come between ES2015 (the earliest ES module kind) and ESNext (the last ES\nmodule kind).", + }, + { + name: "ES2020", + value: 6, + }, + { + name: "ES2022", + value: 7, + }, + { + name: "ESNext", + value: 99, + }, + { + name: "Node16", + value: 100, + comment: "Node16+ is an amalgam of commonjs (albeit updated) and es2022+, and represents a distinct module system from es2020/esnext", + moduleResolution: "Node16", + }, + { + name: "Node18", + value: 101, + }, + { + name: "Node20", + value: 102, + }, + { + name: "NodeNext", + value: 199, + moduleResolution: "NodeNext", + }, + { + name: "Preserve", + value: 200, + comment: "Emit as written", + }, + ], + }, + { + name: "ModuleResolutionKind", + api: true, + members: [ + { + name: "Unknown", + value: 0, + }, + { + name: "Classic", + value: 1, + comment: "Deprecated: Do not use outside of options parsing and validation.", + }, + { + name: "Node10", + value: 2, + comment: "Deprecated: Do not use outside of options parsing and validation.", + }, + { + name: "Node16", + value: 3, + comment: "Starting with node16, node's module resolver has significant departures from traditional cjs resolution\nto better support ECMAScript modules and their use within node - however more features are still being added.\nTypeScript's Node ESM support was introduced after Node 12 went end-of-life, and Node 14 is the earliest stable\nversion that supports both pattern trailers - *but*, Node 16 is the first version that also supports ECMAScript 2022.\nIn turn, we offer both a `NodeNext` moving resolution target, and a `Node16` version-anchored resolution target", + }, + { + name: "NodeNext", + value: 99, + trailingComment: "Not simply `Node16` so that compiled code linked against TS can use the `Next` value reliably (same as with `ModuleKind`)", + }, + { + name: "Bundler", + value: 100, + }, + ], + }, + { + name: "NewLineKind", + api: true, + members: [ + { + name: "None", + value: 0, + }, + { + name: "CRLF", + value: 1, + }, + { + name: "LF", + value: 2, + }, + ], + }, + { + name: "ScriptTarget", + api: true, + members: [ + { + name: "None", + value: 0, + excludeFromAPI: true, + }, + { + name: "ES5", + value: 1, + comment: "Deprecated: Do not use outside of options parsing and validation.", + excludeFromAPI: true, + }, + { + name: "ES2015", + value: 2, + lib: "lib.es6.d.ts", + libComment: "Use lib.es6.d.ts for compatibility rather than lib.es2015.full.d.ts.", + }, + { + name: "ES2016", + value: 3, + lib: "lib.es2016.full.d.ts", + }, + { + name: "ES2017", + value: 4, + lib: "lib.es2017.full.d.ts", + }, + { + name: "ES2018", + value: 5, + lib: "lib.es2018.full.d.ts", + }, + { + name: "ES2019", + value: 6, + lib: "lib.es2019.full.d.ts", + }, + { + name: "ES2020", + value: 7, + lib: "lib.es2020.full.d.ts", + }, + { + name: "ES2021", + value: 8, + lib: "lib.es2021.full.d.ts", + }, + { + name: "ES2022", + value: 9, + lib: "lib.es2022.full.d.ts", + }, + { + name: "ES2023", + value: 10, + lib: "lib.es2023.full.d.ts", + }, + { + name: "ES2024", + value: 11, + lib: "lib.es2024.full.d.ts", + }, + { + name: "ES2025", + value: 12, + lib: "lib.es2025.full.d.ts", + }, + { + name: "ESNext", + value: 99, + lib: "lib.esnext.full.d.ts", + }, + { + name: "JSON", + value: 100, + }, + { name: "Latest", value: "ESNext" }, + { + name: "LatestStandard", + value: "ES2025", + excludeFromAPI: true, + }, + ], + }, + { + name: "JsxEmit", + api: true, + members: [ + { + name: "None", + value: 0, + }, + { + name: "Preserve", + value: 1, + }, + { + name: "React", + value: 2, + }, + { + name: "ReactNative", + value: 3, + }, + { + name: "ReactJSX", + value: 4, + }, + { + name: "ReactJSXDev", + value: 5, + }, + ], + }, + { + name: "WatchFileKind", + members: [ + { + name: "None", + value: 0, + }, + { + name: "FixedPollingInterval", + value: 1, + }, + { + name: "PriorityPollingInterval", + value: 2, + }, + { + name: "DynamicPriorityPolling", + value: 3, + }, + { + name: "FixedChunkSizePolling", + value: 4, + }, + { + name: "UseFsEvents", + value: 5, + }, + { + name: "UseFsEventsOnParentDirectory", + value: 6, + }, + ], + }, + { + name: "WatchDirectoryKind", + members: [ + { + name: "None", + value: 0, + }, + { + name: "UseFsEvents", + value: 1, + }, + { + name: "FixedPollingInterval", + value: 2, + }, + { + name: "DynamicPriorityPolling", + value: 3, + }, + { + name: "FixedChunkSizePolling", + value: 4, + }, + ], + }, + { + name: "PollingKind", + members: [ + { + name: "None", + value: 0, + }, + { + name: "FixedInterval", + value: 1, + }, + { + name: "PriorityInterval", + value: 2, + }, + { + name: "DynamicPriority", + value: 3, + }, + { + name: "FixedChunkSize", + value: 4, + }, + ], + }, + ], +}; diff --git a/tools/scripts/tsc/tsconfig.json b/tools/scripts/tsc/tsconfig.json index 48c845e97d604..6f6ba801693cb 100644 --- a/tools/scripts/tsc/tsconfig.json +++ b/tools/scripts/tsc/tsconfig.json @@ -1,4 +1,7 @@ { "extends": "../gen/tsconfig.json", + "compilerOptions": { + "resolveJsonModule": true + }, "include": ["**/*.ts"] } diff --git a/tsc/internal/api/enum_values_generated.go b/tsc/internal/api/enum_values_generated.go index cd38442117003..666431c977130 100644 --- a/tsc/internal/api/enum_values_generated.go +++ b/tsc/internal/api/enum_values_generated.go @@ -821,6 +821,12 @@ func main() { "Modifier": toInt32(ast.ModifierFlagsModifier), "JavaScript": toInt32(ast.ModifierFlagsJavaScript), }, + "ModuleDetectionKind": { + "None": toInt32(core.ModuleDetectionKindNone), + "Auto": toInt32(core.ModuleDetectionKindAuto), + "Legacy": toInt32(core.ModuleDetectionKindLegacy), + "Force": toInt32(core.ModuleDetectionKindForce), + }, "ModuleKind": { "None": toInt32(core.ModuleKindNone), "CommonJS": toInt32(core.ModuleKindCommonJS), @@ -845,17 +851,27 @@ func main() { "NodeNext": toInt32(core.ModuleResolutionKindNodeNext), "Bundler": toInt32(core.ModuleResolutionKindBundler), }, - "ModuleDetectionKind": { - "None": toInt32(core.ModuleDetectionKindNone), - "Auto": toInt32(core.ModuleDetectionKindAuto), - "Legacy": toInt32(core.ModuleDetectionKindLegacy), - "Force": toInt32(core.ModuleDetectionKindForce), - }, "NewLineKind": { "None": toInt32(core.NewLineKindNone), "CRLF": toInt32(core.NewLineKindCRLF), "LF": toInt32(core.NewLineKindLF), }, + "ScriptTarget": { + "ES2015": toInt32(core.ScriptTargetES2015), + "ES2016": toInt32(core.ScriptTargetES2016), + "ES2017": toInt32(core.ScriptTargetES2017), + "ES2018": toInt32(core.ScriptTargetES2018), + "ES2019": toInt32(core.ScriptTargetES2019), + "ES2020": toInt32(core.ScriptTargetES2020), + "ES2021": toInt32(core.ScriptTargetES2021), + "ES2022": toInt32(core.ScriptTargetES2022), + "ES2023": toInt32(core.ScriptTargetES2023), + "ES2024": toInt32(core.ScriptTargetES2024), + "ES2025": toInt32(core.ScriptTargetES2025), + "ESNext": toInt32(core.ScriptTargetESNext), + "JSON": toInt32(core.ScriptTargetJSON), + "Latest": toInt32(core.ScriptTargetLatest), + }, "JsxEmit": { "None": toInt32(core.JsxEmitNone), "Preserve": toInt32(core.JsxEmitPreserve), diff --git a/tsc/internal/collections/ordered_map.go b/tsc/internal/collections/ordered_map.go index d4d84f3f8e955..d933ffa0e7557 100644 --- a/tsc/internal/collections/ordered_map.go +++ b/tsc/internal/collections/ordered_map.go @@ -212,6 +212,19 @@ func (m *OrderedMap[K, V]) clone() OrderedMap[K, V] { } } +// EqualFunc compares keys in insertion order and values using equal. +// A nil map differs from a non-nil empty map; backing-storage allocation is ignored. +func (m *OrderedMap[K, V]) EqualFunc(other *OrderedMap[K, V], equal func(V, V) bool) bool { + if m == other { + return true + } + if m == nil || other == nil { + return false + } + return slices.Equal(m.keys, other.keys) && + maps.EqualFunc(m.mp, other.mp, equal) +} + var _ json.MarshalerTo = (*OrderedMap[string, string])(nil) func (m *OrderedMap[K, V]) MarshalJSONTo(enc *json.Encoder) error { diff --git a/tsc/internal/collections/ordered_map_test.go b/tsc/internal/collections/ordered_map_test.go index 86e548ec218d3..25a911e7a5f7d 100644 --- a/tsc/internal/collections/ordered_map_test.go +++ b/tsc/internal/collections/ordered_map_test.go @@ -3,6 +3,7 @@ package collections_test import ( "fmt" "slices" + "strings" "testing" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -10,6 +11,43 @@ import ( "gotest.tools/v3/assert" ) +func TestOrderedMapEqualFunc(t *testing.T) { + t.Parallel() + + zero := &collections.OrderedMap[int, string]{} + allocated := collections.NewOrderedMapWithSizeHint[int, string](0) + ordered := collections.NewOrderedMapFromList([]collections.MapEntry[int, string]{{Key: 1, Value: "a"}, {Key: 2, Value: "b"}}) + reversed := collections.NewOrderedMapFromList([]collections.MapEntry[int, string]{{Key: 2, Value: "b"}, {Key: 1, Value: "a"}}) + uppercase := collections.NewOrderedMapFromList([]collections.MapEntry[int, string]{{Key: 1, Value: "A"}, {Key: 2, Value: "B"}}) + different := ordered.Clone() + different.Set(2, "c") + cleared := ordered.Clone() + cleared.Clear() + + for _, test := range []struct { + name string + a, b *collections.OrderedMap[int, string] + equal bool + }{ + {"nil", nil, nil, true}, + {"nil versus empty", nil, zero, false}, + {"empty allocation", zero, allocated, true}, + {"cleared allocation", zero, cleared, true}, + {"same", ordered, ordered, true}, + {"clone", ordered, ordered.Clone(), true}, + {"different order", ordered, reversed, false}, + {"different values", ordered, different, false}, + {"different length", zero, ordered, false}, + {"custom equality", ordered, uppercase, true}, + } { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + assert.Equal(t, test.a.EqualFunc(test.b, strings.EqualFold), test.equal) + assert.Equal(t, test.b.EqualFunc(test.a, strings.EqualFold), test.equal) + }) + } +} + func TestOrderedMap(t *testing.T) { t.Parallel() diff --git a/tsc/internal/contentmapper/contentmapper.go b/tsc/internal/contentmapper/contentmapper.go index b44dedb42cb23..b69c952aaef2f 100644 --- a/tsc/internal/contentmapper/contentmapper.go +++ b/tsc/internal/contentmapper/contentmapper.go @@ -14,6 +14,7 @@ package contentmapper import ( "errors" "reflect" + "slices" "strings" "sync" @@ -95,6 +96,30 @@ func (m *Mapper) manifestIdentity() string { } } +// Equals compares the complete mapper configuration, not just its advertised identity. +func (m *Mapper) Equals(other *Mapper) bool { + if m == other { + return true + } + if m == nil || other == nil { + return false + } + return m.Package == other.Package && + (m.Extensions == nil) == (other.Extensions == nil) && + slices.Equal(m.Extensions, other.Extensions) && + (m.Options == nil) == (other.Options == nil) && + slices.Equal(m.Options, other.Options) && + m.Name == other.Name && + m.Version == other.Version && + (m.Exec == nil) == (other.Exec == nil) && + slices.Equal(m.Exec, other.Exec) && + (m.CompilerOptions == nil) == (other.CompilerOptions == nil) && + slices.Equal(m.CompilerOptions, other.CompilerOptions) && + m.DynamicConfig == other.DynamicConfig && + m.PackageDirectory == other.PackageDirectory && + m.ContributionID == other.ContributionID +} + // TransformIdentity returns a fingerprint of everything besides a file's content that determines the // output of transforming it with this mapper under the given options: the mapper's identity and the // values of the compiler options it declared it depends on. Folding it into a cache key means a change to diff --git a/tsc/internal/core/buildoptions.go b/tsc/internal/core/buildoptions.go deleted file mode 100644 index 5e7fb707c05f2..0000000000000 --- a/tsc/internal/core/buildoptions.go +++ /dev/null @@ -1,16 +0,0 @@ -package core - -type BuildOptions struct { - _ noCopy - - Dry Tristate `json:"dry,omitzero"` - Force Tristate `json:"force,omitzero"` - Verbose Tristate `json:"verbose,omitzero"` - Builders *int `json:"builders,omitzero"` - StopBuildOnErrors Tristate `json:"stopBuildOnErrors,omitzero"` - - // CompilerOptions are not parsed here and will be available on ParsedBuildCommandLine - - // Internal fields - Clean Tristate `json:"clean,omitzero"` -} diff --git a/tsc/internal/core/compileroptions.go b/tsc/internal/core/compileroptions.go index 191b9feefa17d..54c915d1912fa 100644 --- a/tsc/internal/core/compileroptions.go +++ b/tsc/internal/core/compileroptions.go @@ -1,169 +1,16 @@ package core import ( - "reflect" "slices" "strings" - "github.com/microsoft/TypeScript/tsc/internal/collections" "github.com/microsoft/TypeScript/tsc/internal/tspath" ) -//go:generate npx hereby generate:compileroptions - type PluginImport struct { Name string `json:"name"` } -// CompilerOptions contains the compiler options exposed by the API. -type CompilerOptions struct { - _ noCopy - - AllowJs Tristate `json:"allowJs,omitzero"` - AllowArbitraryExtensions Tristate `json:"allowArbitraryExtensions,omitzero"` - AllowImportingTsExtensions Tristate `json:"allowImportingTsExtensions,omitzero"` - AllowNonTsExtensions Tristate `json:"allowNonTsExtensions,omitzero"` - AllowUmdGlobalAccess Tristate `json:"allowUmdGlobalAccess,omitzero"` - AllowUnreachableCode Tristate `json:"allowUnreachableCode,omitzero"` - AllowUnusedLabels Tristate `json:"allowUnusedLabels,omitzero"` - AssumeChangesOnlyAffectDirectDependencies Tristate `json:"assumeChangesOnlyAffectDirectDependencies,omitzero"` - CheckJs Tristate `json:"checkJs,omitzero"` - CustomConditions []string `json:"customConditions,omitzero"` - Composite Tristate `json:"composite,omitzero"` - EmitDeclarationOnly Tristate `json:"emitDeclarationOnly,omitzero"` - EmitBOM Tristate `json:"emitBOM,omitzero"` - EmitDecoratorMetadata Tristate `json:"emitDecoratorMetadata,omitzero"` - Declaration Tristate `json:"declaration,omitzero"` - DeclarationDir string `json:"declarationDir,omitzero"` - DeclarationMap Tristate `json:"declarationMap,omitzero"` - DeduplicatePackages Tristate `json:"deduplicatePackages,omitzero"` - DisableSizeLimit Tristate `json:"disableSizeLimit,omitzero"` - DisableSourceOfProjectReferenceRedirect Tristate `json:"disableSourceOfProjectReferenceRedirect,omitzero"` - DisableSolutionSearching Tristate `json:"disableSolutionSearching,omitzero"` - DisableReferencedProjectLoad Tristate `json:"disableReferencedProjectLoad,omitzero"` - ErasableSyntaxOnly Tristate `json:"erasableSyntaxOnly,omitzero"` - ExactOptionalPropertyTypes Tristate `json:"exactOptionalPropertyTypes,omitzero"` - ExperimentalDecorators Tristate `json:"experimentalDecorators,omitzero"` - ForceConsistentCasingInFileNames Tristate `json:"forceConsistentCasingInFileNames,omitzero"` - IsolatedModules Tristate `json:"isolatedModules,omitzero"` - IsolatedDeclarations Tristate `json:"isolatedDeclarations,omitzero"` - IgnoreConfig Tristate `json:"ignoreConfig,omitzero"` - IgnoreDeprecations string `json:"ignoreDeprecations,omitzero"` - ImportHelpers Tristate `json:"importHelpers,omitzero"` - InlineSourceMap Tristate `json:"inlineSourceMap,omitzero"` - InlineSources Tristate `json:"inlineSources,omitzero"` - Init Tristate `json:"init,omitzero"` - Incremental Tristate `json:"incremental,omitzero"` - Jsx JsxEmit `json:"jsx,omitzero"` - JsxFactory string `json:"jsxFactory,omitzero"` - JsxFragmentFactory string `json:"jsxFragmentFactory,omitzero"` - JsxImportSource string `json:"jsxImportSource,omitzero"` - Lib []string `json:"lib,omitzero"` - LibReplacement Tristate `json:"libReplacement,omitzero"` - Locale string `json:"locale,omitzero"` - MapRoot string `json:"mapRoot,omitzero"` - Module ModuleKind `json:"module,omitzero"` - ModuleResolution ModuleResolutionKind `json:"moduleResolution,omitzero"` - ModuleSuffixes []string `json:"moduleSuffixes,omitzero"` - ModuleDetection ModuleDetectionKind `json:"moduleDetection,omitzero"` - NewLine NewLineKind `json:"newLine,omitzero"` - NoEmit Tristate `json:"noEmit,omitzero"` - NoCheck Tristate `json:"noCheck,omitzero"` - NoErrorTruncation Tristate `json:"noErrorTruncation,omitzero"` - NoFallthroughCasesInSwitch Tristate `json:"noFallthroughCasesInSwitch,omitzero"` - NoImplicitAny Tristate `json:"noImplicitAny,omitzero"` - NoImplicitThis Tristate `json:"noImplicitThis,omitzero"` - NoImplicitReturns Tristate `json:"noImplicitReturns,omitzero"` - NoEmitHelpers Tristate `json:"noEmitHelpers,omitzero"` - NoLib Tristate `json:"noLib,omitzero"` - NoPropertyAccessFromIndexSignature Tristate `json:"noPropertyAccessFromIndexSignature,omitzero"` - NoUncheckedIndexedAccess Tristate `json:"noUncheckedIndexedAccess,omitzero"` - NoEmitOnError Tristate `json:"noEmitOnError,omitzero"` - NoUnusedLocals Tristate `json:"noUnusedLocals,omitzero"` - NoUnusedParameters Tristate `json:"noUnusedParameters,omitzero"` - NoResolve Tristate `json:"noResolve,omitzero"` - NoImplicitOverride Tristate `json:"noImplicitOverride,omitzero"` - NoUncheckedSideEffectImports Tristate `json:"noUncheckedSideEffectImports,omitzero"` - OutDir string `json:"outDir,omitzero"` - Paths *collections.OrderedMap[string, []string] `json:"paths,omitzero"` - // Plugins are parsed only so tools can report that native TypeScript does not support them. - Plugins []PluginImport `json:"plugins,omitzero"` - PreserveConstEnums Tristate `json:"preserveConstEnums,omitzero"` - PreserveSymlinks Tristate `json:"preserveSymlinks,omitzero"` - Project string `json:"project,omitzero"` - ResolveJsonModule Tristate `json:"resolveJsonModule,omitzero"` - ResolvePackageJsonExports Tristate `json:"resolvePackageJsonExports,omitzero"` - ResolvePackageJsonImports Tristate `json:"resolvePackageJsonImports,omitzero"` - RemoveComments Tristate `json:"removeComments,omitzero"` - RewriteRelativeImportExtensions Tristate `json:"rewriteRelativeImportExtensions,omitzero"` - ReactNamespace string `json:"reactNamespace,omitzero"` - RootDir string `json:"rootDir,omitzero"` - RootDirs []string `json:"rootDirs,omitzero"` - SkipLibCheck Tristate `json:"skipLibCheck,omitzero"` - StableTypeOrdering Tristate `json:"stableTypeOrdering,omitzero"` - Strict Tristate `json:"strict,omitzero"` - StrictBindCallApply Tristate `json:"strictBindCallApply,omitzero"` - StrictBuiltinIteratorReturn Tristate `json:"strictBuiltinIteratorReturn,omitzero"` - StrictFunctionTypes Tristate `json:"strictFunctionTypes,omitzero"` - StrictNullChecks Tristate `json:"strictNullChecks,omitzero"` - StrictPropertyInitialization Tristate `json:"strictPropertyInitialization,omitzero"` - StripInternal Tristate `json:"stripInternal,omitzero"` - SkipDefaultLibCheck Tristate `json:"skipDefaultLibCheck,omitzero"` - SourceMap Tristate `json:"sourceMap,omitzero"` - SourceRoot string `json:"sourceRoot,omitzero"` - SuppressOutputPathCheck Tristate `json:"suppressOutputPathCheck,omitzero"` - Target ScriptTarget `json:"target,omitzero"` - TraceResolution Tristate `json:"traceResolution,omitzero"` - TsBuildInfoFile string `json:"tsBuildInfoFile,omitzero"` - TypeRoots []string `json:"typeRoots,omitzero"` - Types []string `json:"types,omitzero"` - UseDefineForClassFields Tristate `json:"useDefineForClassFields,omitzero"` - UseUnknownInCatchVariables Tristate `json:"useUnknownInCatchVariables,omitzero"` - VerbatimModuleSyntax Tristate `json:"verbatimModuleSyntax,omitzero"` - MaxNodeModuleJsDepth *int `json:"maxNodeModuleJsDepth,omitzero"` - - // Deprecated: Do not use outside of options parsing and validation. - AllowSyntheticDefaultImports Tristate `json:"allowSyntheticDefaultImports,omitzero" deprecated:"true"` - // Deprecated: Do not use outside of options parsing and validation. - AlwaysStrict Tristate `json:"alwaysStrict,omitzero" deprecated:"true"` - // Deprecated: Do not use outside of options parsing and validation. - BaseUrl string `json:"baseUrl,omitzero" deprecated:"true"` - // Deprecated: Do not use outside of options parsing and validation. - DownlevelIteration Tristate `json:"downlevelIteration,omitzero" deprecated:"true"` - // Deprecated: Do not use outside of options parsing and validation. - ESModuleInterop Tristate `json:"esModuleInterop,omitzero" deprecated:"true"` - // Deprecated: Do not use outside of options parsing and validation. - OutFile string `json:"outFile,omitzero" deprecated:"true"` - - // Internal fields - ConfigFilePath string `json:"configFilePath,omitzero"` // internal, but intentionally exposed via API - NoDtsResolution Tristate `json:"noDtsResolution,omitzero" internal:"true"` - PathsBasePath string `json:"pathsBasePath,omitzero" internal:"true"` - Diagnostics Tristate `json:"diagnostics,omitzero" internal:"true"` - ExtendedDiagnostics Tristate `json:"extendedDiagnostics,omitzero" internal:"true"` - GenerateCpuProfile string `json:"generateCpuProfile,omitzero" internal:"true"` - GenerateTrace string `json:"generateTrace,omitzero" internal:"true"` - ListEmittedFiles Tristate `json:"listEmittedFiles,omitzero" internal:"true"` - ListFiles Tristate `json:"listFiles,omitzero" internal:"true"` - ExplainFiles Tristate `json:"explainFiles,omitzero" internal:"true"` - ListFilesOnly Tristate `json:"listFilesOnly,omitzero" internal:"true"` - NoEmitForJsFiles Tristate `json:"noEmitForJsFiles,omitzero" internal:"true"` - PreserveWatchOutput Tristate `json:"preserveWatchOutput,omitzero" internal:"true"` - Pretty Tristate `json:"pretty,omitzero" internal:"true"` - Version Tristate `json:"version,omitzero" internal:"true"` - Watch Tristate `json:"watch,omitzero" internal:"true"` - ShowConfig Tristate `json:"showConfig,omitzero" internal:"true"` - Build Tristate `json:"build,omitzero" internal:"true"` - Help Tristate `json:"help,omitzero" internal:"true"` - All Tristate `json:"all,omitzero" internal:"true"` - RunExternalCode Tristate `json:"runExternalCode,omitzero" internal:"true"` - - PprofDir string `json:"pprofDir,omitzero" internal:"true"` - SingleThreaded Tristate `json:"singleThreaded,omitzero" internal:"true"` - Quiet Tristate `json:"quiet,omitzero" internal:"true"` - Checkers *int `json:"checkers,omitzero" internal:"true"` -} - // noCopy may be embedded into structs which must not be copied // after the first use. // @@ -177,25 +24,6 @@ func (*noCopy) Unlock() {} var EmptyCompilerOptions = &CompilerOptions{} -var optionsType = reflect.TypeFor[CompilerOptions]() - -// Clone creates a shallow copy of the CompilerOptions. -func (options *CompilerOptions) Clone() *CompilerOptions { - // TODO: this could be generated code instead of reflection. - target := &CompilerOptions{} - - sourceValue := reflect.ValueOf(options).Elem() - targetValue := reflect.ValueOf(target).Elem() - - for i := range sourceValue.NumField() { - if optionsType.Field(i).IsExported() { - targetValue.Field(i).Set(sourceValue.Field(i)) - } - } - - return target -} - func (options *CompilerOptions) GetEmitScriptTarget() ScriptTarget { if options.Target != ScriptTargetNone { return options.Target @@ -376,42 +204,6 @@ func (options *CompilerOptions) GetPathsBasePath(currentDirectory string) string return currentDirectory } -type ModuleDetectionKind int32 - -const ( - ModuleDetectionKindNone ModuleDetectionKind = 0 - ModuleDetectionKindAuto ModuleDetectionKind = 1 - ModuleDetectionKindLegacy ModuleDetectionKind = 2 - ModuleDetectionKindForce ModuleDetectionKind = 3 -) - -type ModuleKind int32 - -const ( - ModuleKindNone ModuleKind = 0 - ModuleKindCommonJS ModuleKind = 1 - // Deprecated: Do not use outside of options parsing and validation. - ModuleKindAMD ModuleKind = 2 - // Deprecated: Do not use outside of options parsing and validation. - ModuleKindUMD ModuleKind = 3 - // Deprecated: Do not use outside of options parsing and validation. - ModuleKindSystem ModuleKind = 4 - // NOTE: ES module kinds should be contiguous to more easily check whether a module kind is *any* ES module kind. - // Non-ES module kinds should not come between ES2015 (the earliest ES module kind) and ESNext (the last ES - // module kind). - ModuleKindES2015 ModuleKind = 5 - ModuleKindES2020 ModuleKind = 6 - ModuleKindES2022 ModuleKind = 7 - ModuleKindESNext ModuleKind = 99 - // Node16+ is an amalgam of commonjs (albeit updated) and es2022+, and represents a distinct module system from es2020/esnext - ModuleKindNode16 ModuleKind = 100 - ModuleKindNode18 ModuleKind = 101 - ModuleKindNode20 ModuleKind = 102 - ModuleKindNodeNext ModuleKind = 199 - // Emit as written - ModuleKindPreserve ModuleKind = 200 -) - func (moduleKind ModuleKind) IsNonNodeESM() bool { return moduleKind >= ModuleKindES2015 && moduleKind <= ModuleKindESNext } @@ -430,29 +222,6 @@ const ( ResolutionModeESM = ModuleKindESNext ) -type ModuleResolutionKind int32 - -const ( - ModuleResolutionKindUnknown ModuleResolutionKind = 0 - // Deprecated: Do not use outside of options parsing and validation. - ModuleResolutionKindClassic ModuleResolutionKind = 1 - // Deprecated: Do not use outside of options parsing and validation. - ModuleResolutionKindNode10 ModuleResolutionKind = 2 - // Starting with node16, node's module resolver has significant departures from traditional cjs resolution - // to better support ECMAScript modules and their use within node - however more features are still being added. - // TypeScript's Node ESM support was introduced after Node 12 went end-of-life, and Node 14 is the earliest stable - // version that supports both pattern trailers - *but*, Node 16 is the first version that also supports ECMAScript 2022. - // In turn, we offer both a `NodeNext` moving resolution target, and a `Node16` version-anchored resolution target - ModuleResolutionKindNode16 ModuleResolutionKind = 3 - ModuleResolutionKindNodeNext ModuleResolutionKind = 99 // Not simply `Node16` so that compiled code linked against TS can use the `Next` value reliably (same as with `ModuleKind`) - ModuleResolutionKindBundler ModuleResolutionKind = 100 -) - -var ModuleKindToModuleResolutionKind = map[ModuleKind]ModuleResolutionKind{ - ModuleKindNode16: ModuleResolutionKindNode16, - ModuleKindNodeNext: ModuleResolutionKindNodeNext, -} - // We don't use stringer on this for now, because these values // are user-facing in --traceResolution, and stringer currently // lacks the ability to remove the "ModuleResolutionKind" prefix @@ -479,14 +248,6 @@ func (m ModuleResolutionKind) String() string { } } -type NewLineKind int32 - -const ( - NewLineKindNone NewLineKind = 0 - NewLineKindCRLF NewLineKind = 1 - NewLineKindLF NewLineKind = 2 -) - func GetNewLineKind(s string) NewLineKind { switch s { case "\r\n": @@ -507,40 +268,6 @@ func (newLine NewLineKind) GetNewLineCharacter() string { } } -type ScriptTarget int32 - -const ( - ScriptTargetNone ScriptTarget = 0 - // Deprecated: Do not use outside of options parsing and validation. - ScriptTargetES5 ScriptTarget = 1 - ScriptTargetES2015 ScriptTarget = 2 - ScriptTargetES2016 ScriptTarget = 3 - ScriptTargetES2017 ScriptTarget = 4 - ScriptTargetES2018 ScriptTarget = 5 - ScriptTargetES2019 ScriptTarget = 6 - ScriptTargetES2020 ScriptTarget = 7 - ScriptTargetES2021 ScriptTarget = 8 - ScriptTargetES2022 ScriptTarget = 9 - ScriptTargetES2023 ScriptTarget = 10 - ScriptTargetES2024 ScriptTarget = 11 - ScriptTargetES2025 ScriptTarget = 12 - ScriptTargetESNext ScriptTarget = 99 - ScriptTargetJSON ScriptTarget = 100 - ScriptTargetLatest ScriptTarget = ScriptTargetESNext - ScriptTargetLatestStandard ScriptTarget = ScriptTargetES2025 -) - -type JsxEmit int32 - -const ( - JsxEmitNone JsxEmit = 0 - JsxEmitPreserve JsxEmit = 1 - JsxEmitReact JsxEmit = 2 - JsxEmitReactNative JsxEmit = 3 - JsxEmitReactJSX JsxEmit = 4 - JsxEmitReactJSXDev JsxEmit = 5 -) - func (j JsxEmit) String() string { switch j { case JsxEmitNone: diff --git a/tsc/internal/core/options_generated.go b/tsc/internal/core/options_generated.go new file mode 100644 index 0000000000000..ad5fcd7af4cfe --- /dev/null +++ b/tsc/internal/core/options_generated.go @@ -0,0 +1,901 @@ +// Code generated by tools/scripts/tsc/generate-options.ts. DO NOT EDIT. + +package core + +import ( + "slices" + + "github.com/microsoft/TypeScript/tsc/internal/collections" +) + +//go:generate npx hereby generate:compileroptions + +// CompilerOptions contains the compiler options exposed by the API. +type CompilerOptions struct { + _ noCopy + AllowJs Tristate `json:"allowJs,omitzero"` + AllowArbitraryExtensions Tristate `json:"allowArbitraryExtensions,omitzero"` + AllowImportingTsExtensions Tristate `json:"allowImportingTsExtensions,omitzero"` + AllowNonTsExtensions Tristate `json:"allowNonTsExtensions,omitzero"` + AllowUmdGlobalAccess Tristate `json:"allowUmdGlobalAccess,omitzero"` + AllowUnreachableCode Tristate `json:"allowUnreachableCode,omitzero"` + AllowUnusedLabels Tristate `json:"allowUnusedLabels,omitzero"` + AssumeChangesOnlyAffectDirectDependencies Tristate `json:"assumeChangesOnlyAffectDirectDependencies,omitzero"` + CheckJs Tristate `json:"checkJs,omitzero"` + CustomConditions []string `json:"customConditions,omitzero"` + Composite Tristate `json:"composite,omitzero"` + EmitDeclarationOnly Tristate `json:"emitDeclarationOnly,omitzero"` + EmitBOM Tristate `json:"emitBOM,omitzero"` + EmitDecoratorMetadata Tristate `json:"emitDecoratorMetadata,omitzero"` + Declaration Tristate `json:"declaration,omitzero"` + DeclarationDir string `json:"declarationDir,omitzero"` + DeclarationMap Tristate `json:"declarationMap,omitzero"` + DeduplicatePackages Tristate `json:"deduplicatePackages,omitzero"` + DisableSizeLimit Tristate `json:"disableSizeLimit,omitzero"` + DisableSourceOfProjectReferenceRedirect Tristate `json:"disableSourceOfProjectReferenceRedirect,omitzero"` + DisableSolutionSearching Tristate `json:"disableSolutionSearching,omitzero"` + DisableReferencedProjectLoad Tristate `json:"disableReferencedProjectLoad,omitzero"` + ErasableSyntaxOnly Tristate `json:"erasableSyntaxOnly,omitzero"` + ExactOptionalPropertyTypes Tristate `json:"exactOptionalPropertyTypes,omitzero"` + ExperimentalDecorators Tristate `json:"experimentalDecorators,omitzero"` + ForceConsistentCasingInFileNames Tristate `json:"forceConsistentCasingInFileNames,omitzero"` + IsolatedModules Tristate `json:"isolatedModules,omitzero"` + IsolatedDeclarations Tristate `json:"isolatedDeclarations,omitzero"` + IgnoreConfig Tristate `json:"ignoreConfig,omitzero"` + IgnoreDeprecations string `json:"ignoreDeprecations,omitzero"` + ImportHelpers Tristate `json:"importHelpers,omitzero"` + InlineSourceMap Tristate `json:"inlineSourceMap,omitzero"` + InlineSources Tristate `json:"inlineSources,omitzero"` + Init Tristate `json:"init,omitzero"` + Incremental Tristate `json:"incremental,omitzero"` + Jsx JsxEmit `json:"jsx,omitzero"` + JsxFactory string `json:"jsxFactory,omitzero"` + JsxFragmentFactory string `json:"jsxFragmentFactory,omitzero"` + JsxImportSource string `json:"jsxImportSource,omitzero"` + Lib []string `json:"lib,omitzero"` + LibReplacement Tristate `json:"libReplacement,omitzero"` + Locale string `json:"locale,omitzero"` + MapRoot string `json:"mapRoot,omitzero"` + Module ModuleKind `json:"module,omitzero"` + ModuleResolution ModuleResolutionKind `json:"moduleResolution,omitzero"` + ModuleSuffixes []string `json:"moduleSuffixes,omitzero"` + ModuleDetection ModuleDetectionKind `json:"moduleDetection,omitzero"` + NewLine NewLineKind `json:"newLine,omitzero"` + NoEmit Tristate `json:"noEmit,omitzero"` + NoCheck Tristate `json:"noCheck,omitzero"` + NoErrorTruncation Tristate `json:"noErrorTruncation,omitzero"` + NoFallthroughCasesInSwitch Tristate `json:"noFallthroughCasesInSwitch,omitzero"` + NoImplicitAny Tristate `json:"noImplicitAny,omitzero"` + NoImplicitThis Tristate `json:"noImplicitThis,omitzero"` + NoImplicitReturns Tristate `json:"noImplicitReturns,omitzero"` + NoEmitHelpers Tristate `json:"noEmitHelpers,omitzero"` + NoLib Tristate `json:"noLib,omitzero"` + NoPropertyAccessFromIndexSignature Tristate `json:"noPropertyAccessFromIndexSignature,omitzero"` + NoUncheckedIndexedAccess Tristate `json:"noUncheckedIndexedAccess,omitzero"` + NoEmitOnError Tristate `json:"noEmitOnError,omitzero"` + NoUnusedLocals Tristate `json:"noUnusedLocals,omitzero"` + NoUnusedParameters Tristate `json:"noUnusedParameters,omitzero"` + NoResolve Tristate `json:"noResolve,omitzero"` + NoImplicitOverride Tristate `json:"noImplicitOverride,omitzero"` + NoUncheckedSideEffectImports Tristate `json:"noUncheckedSideEffectImports,omitzero"` + OutDir string `json:"outDir,omitzero"` + Paths *collections.OrderedMap[string, []string] `json:"paths,omitzero"` + // Plugins are parsed only so tools can report that native TypeScript does not support them. + Plugins []PluginImport `json:"plugins,omitzero"` + PreserveConstEnums Tristate `json:"preserveConstEnums,omitzero"` + PreserveSymlinks Tristate `json:"preserveSymlinks,omitzero"` + Project string `json:"project,omitzero"` + ResolveJsonModule Tristate `json:"resolveJsonModule,omitzero"` + ResolvePackageJsonExports Tristate `json:"resolvePackageJsonExports,omitzero"` + ResolvePackageJsonImports Tristate `json:"resolvePackageJsonImports,omitzero"` + RemoveComments Tristate `json:"removeComments,omitzero"` + RewriteRelativeImportExtensions Tristate `json:"rewriteRelativeImportExtensions,omitzero"` + ReactNamespace string `json:"reactNamespace,omitzero"` + RootDir string `json:"rootDir,omitzero"` + RootDirs []string `json:"rootDirs,omitzero"` + SkipLibCheck Tristate `json:"skipLibCheck,omitzero"` + StableTypeOrdering Tristate `json:"stableTypeOrdering,omitzero"` + Strict Tristate `json:"strict,omitzero"` + StrictBindCallApply Tristate `json:"strictBindCallApply,omitzero"` + StrictBuiltinIteratorReturn Tristate `json:"strictBuiltinIteratorReturn,omitzero"` + StrictFunctionTypes Tristate `json:"strictFunctionTypes,omitzero"` + StrictNullChecks Tristate `json:"strictNullChecks,omitzero"` + StrictPropertyInitialization Tristate `json:"strictPropertyInitialization,omitzero"` + StripInternal Tristate `json:"stripInternal,omitzero"` + SkipDefaultLibCheck Tristate `json:"skipDefaultLibCheck,omitzero"` + SourceMap Tristate `json:"sourceMap,omitzero"` + SourceRoot string `json:"sourceRoot,omitzero"` + SuppressOutputPathCheck Tristate `json:"suppressOutputPathCheck,omitzero"` + Target ScriptTarget `json:"target,omitzero"` + TraceResolution Tristate `json:"traceResolution,omitzero"` + TsBuildInfoFile string `json:"tsBuildInfoFile,omitzero"` + TypeRoots []string `json:"typeRoots,omitzero"` + Types []string `json:"types,omitzero"` + UseDefineForClassFields Tristate `json:"useDefineForClassFields,omitzero"` + UseUnknownInCatchVariables Tristate `json:"useUnknownInCatchVariables,omitzero"` + VerbatimModuleSyntax Tristate `json:"verbatimModuleSyntax,omitzero"` + MaxNodeModuleJsDepth *int `json:"maxNodeModuleJsDepth,omitzero"` + // Deprecated: Do not use outside of options parsing and validation. + AllowSyntheticDefaultImports Tristate `json:"allowSyntheticDefaultImports,omitzero" deprecated:"true"` + // Deprecated: Do not use outside of options parsing and validation. + AlwaysStrict Tristate `json:"alwaysStrict,omitzero" deprecated:"true"` + // Deprecated: Do not use outside of options parsing and validation. + BaseUrl string `json:"baseUrl,omitzero" deprecated:"true"` + // Deprecated: Do not use outside of options parsing and validation. + DownlevelIteration Tristate `json:"downlevelIteration,omitzero" deprecated:"true"` + // Deprecated: Do not use outside of options parsing and validation. + ESModuleInterop Tristate `json:"esModuleInterop,omitzero" deprecated:"true"` + // Deprecated: Do not use outside of options parsing and validation. + OutFile string `json:"outFile,omitzero" deprecated:"true"` + // Internal fields + ConfigFilePath string `json:"configFilePath,omitzero"` + NoDtsResolution Tristate `json:"noDtsResolution,omitzero" internal:"true"` + PathsBasePath string `json:"pathsBasePath,omitzero" internal:"true"` + Diagnostics Tristate `json:"diagnostics,omitzero" internal:"true"` + ExtendedDiagnostics Tristate `json:"extendedDiagnostics,omitzero" internal:"true"` + GenerateCpuProfile string `json:"generateCpuProfile,omitzero" internal:"true"` + GenerateTrace string `json:"generateTrace,omitzero" internal:"true"` + ListEmittedFiles Tristate `json:"listEmittedFiles,omitzero" internal:"true"` + ListFiles Tristate `json:"listFiles,omitzero" internal:"true"` + ExplainFiles Tristate `json:"explainFiles,omitzero" internal:"true"` + ListFilesOnly Tristate `json:"listFilesOnly,omitzero" internal:"true"` + NoEmitForJsFiles Tristate `json:"noEmitForJsFiles,omitzero" internal:"true"` + PreserveWatchOutput Tristate `json:"preserveWatchOutput,omitzero" internal:"true"` + Pretty Tristate `json:"pretty,omitzero" internal:"true"` + Version Tristate `json:"version,omitzero" internal:"true"` + Watch Tristate `json:"watch,omitzero" internal:"true"` + ShowConfig Tristate `json:"showConfig,omitzero" internal:"true"` + Build Tristate `json:"build,omitzero" internal:"true"` + Help Tristate `json:"help,omitzero" internal:"true"` + All Tristate `json:"all,omitzero" internal:"true"` + RunExternalCode Tristate `json:"runExternalCode,omitzero" internal:"true"` + PprofDir string `json:"pprofDir,omitzero" internal:"true"` + SingleThreaded Tristate `json:"singleThreaded,omitzero" internal:"true"` + Quiet Tristate `json:"quiet,omitzero" internal:"true"` + Checkers *int `json:"checkers,omitzero" internal:"true"` +} + +// Clone creates a shallow copy of the CompilerOptions. +func (options *CompilerOptions) Clone() *CompilerOptions { + return &CompilerOptions{ + AllowJs: options.AllowJs, + AllowArbitraryExtensions: options.AllowArbitraryExtensions, + AllowImportingTsExtensions: options.AllowImportingTsExtensions, + AllowNonTsExtensions: options.AllowNonTsExtensions, + AllowUmdGlobalAccess: options.AllowUmdGlobalAccess, + AllowUnreachableCode: options.AllowUnreachableCode, + AllowUnusedLabels: options.AllowUnusedLabels, + AssumeChangesOnlyAffectDirectDependencies: options.AssumeChangesOnlyAffectDirectDependencies, + CheckJs: options.CheckJs, + CustomConditions: options.CustomConditions, + Composite: options.Composite, + EmitDeclarationOnly: options.EmitDeclarationOnly, + EmitBOM: options.EmitBOM, + EmitDecoratorMetadata: options.EmitDecoratorMetadata, + Declaration: options.Declaration, + DeclarationDir: options.DeclarationDir, + DeclarationMap: options.DeclarationMap, + DeduplicatePackages: options.DeduplicatePackages, + DisableSizeLimit: options.DisableSizeLimit, + DisableSourceOfProjectReferenceRedirect: options.DisableSourceOfProjectReferenceRedirect, + DisableSolutionSearching: options.DisableSolutionSearching, + DisableReferencedProjectLoad: options.DisableReferencedProjectLoad, + ErasableSyntaxOnly: options.ErasableSyntaxOnly, + ExactOptionalPropertyTypes: options.ExactOptionalPropertyTypes, + ExperimentalDecorators: options.ExperimentalDecorators, + ForceConsistentCasingInFileNames: options.ForceConsistentCasingInFileNames, + IsolatedModules: options.IsolatedModules, + IsolatedDeclarations: options.IsolatedDeclarations, + IgnoreConfig: options.IgnoreConfig, + IgnoreDeprecations: options.IgnoreDeprecations, + ImportHelpers: options.ImportHelpers, + InlineSourceMap: options.InlineSourceMap, + InlineSources: options.InlineSources, + Init: options.Init, + Incremental: options.Incremental, + Jsx: options.Jsx, + JsxFactory: options.JsxFactory, + JsxFragmentFactory: options.JsxFragmentFactory, + JsxImportSource: options.JsxImportSource, + Lib: options.Lib, + LibReplacement: options.LibReplacement, + Locale: options.Locale, + MapRoot: options.MapRoot, + Module: options.Module, + ModuleResolution: options.ModuleResolution, + ModuleSuffixes: options.ModuleSuffixes, + ModuleDetection: options.ModuleDetection, + NewLine: options.NewLine, + NoEmit: options.NoEmit, + NoCheck: options.NoCheck, + NoErrorTruncation: options.NoErrorTruncation, + NoFallthroughCasesInSwitch: options.NoFallthroughCasesInSwitch, + NoImplicitAny: options.NoImplicitAny, + NoImplicitThis: options.NoImplicitThis, + NoImplicitReturns: options.NoImplicitReturns, + NoEmitHelpers: options.NoEmitHelpers, + NoLib: options.NoLib, + NoPropertyAccessFromIndexSignature: options.NoPropertyAccessFromIndexSignature, + NoUncheckedIndexedAccess: options.NoUncheckedIndexedAccess, + NoEmitOnError: options.NoEmitOnError, + NoUnusedLocals: options.NoUnusedLocals, + NoUnusedParameters: options.NoUnusedParameters, + NoResolve: options.NoResolve, + NoImplicitOverride: options.NoImplicitOverride, + NoUncheckedSideEffectImports: options.NoUncheckedSideEffectImports, + OutDir: options.OutDir, + Paths: options.Paths, + Plugins: options.Plugins, + PreserveConstEnums: options.PreserveConstEnums, + PreserveSymlinks: options.PreserveSymlinks, + Project: options.Project, + ResolveJsonModule: options.ResolveJsonModule, + ResolvePackageJsonExports: options.ResolvePackageJsonExports, + ResolvePackageJsonImports: options.ResolvePackageJsonImports, + RemoveComments: options.RemoveComments, + RewriteRelativeImportExtensions: options.RewriteRelativeImportExtensions, + ReactNamespace: options.ReactNamespace, + RootDir: options.RootDir, + RootDirs: options.RootDirs, + SkipLibCheck: options.SkipLibCheck, + StableTypeOrdering: options.StableTypeOrdering, + Strict: options.Strict, + StrictBindCallApply: options.StrictBindCallApply, + StrictBuiltinIteratorReturn: options.StrictBuiltinIteratorReturn, + StrictFunctionTypes: options.StrictFunctionTypes, + StrictNullChecks: options.StrictNullChecks, + StrictPropertyInitialization: options.StrictPropertyInitialization, + StripInternal: options.StripInternal, + SkipDefaultLibCheck: options.SkipDefaultLibCheck, + SourceMap: options.SourceMap, + SourceRoot: options.SourceRoot, + SuppressOutputPathCheck: options.SuppressOutputPathCheck, + Target: options.Target, + TraceResolution: options.TraceResolution, + TsBuildInfoFile: options.TsBuildInfoFile, + TypeRoots: options.TypeRoots, + Types: options.Types, + UseDefineForClassFields: options.UseDefineForClassFields, + UseUnknownInCatchVariables: options.UseUnknownInCatchVariables, + VerbatimModuleSyntax: options.VerbatimModuleSyntax, + MaxNodeModuleJsDepth: options.MaxNodeModuleJsDepth, + AllowSyntheticDefaultImports: options.AllowSyntheticDefaultImports, + AlwaysStrict: options.AlwaysStrict, + BaseUrl: options.BaseUrl, + DownlevelIteration: options.DownlevelIteration, + ESModuleInterop: options.ESModuleInterop, + OutFile: options.OutFile, + ConfigFilePath: options.ConfigFilePath, + NoDtsResolution: options.NoDtsResolution, + PathsBasePath: options.PathsBasePath, + Diagnostics: options.Diagnostics, + ExtendedDiagnostics: options.ExtendedDiagnostics, + GenerateCpuProfile: options.GenerateCpuProfile, + GenerateTrace: options.GenerateTrace, + ListEmittedFiles: options.ListEmittedFiles, + ListFiles: options.ListFiles, + ExplainFiles: options.ExplainFiles, + ListFilesOnly: options.ListFilesOnly, + NoEmitForJsFiles: options.NoEmitForJsFiles, + PreserveWatchOutput: options.PreserveWatchOutput, + Pretty: options.Pretty, + Version: options.Version, + Watch: options.Watch, + ShowConfig: options.ShowConfig, + Build: options.Build, + Help: options.Help, + All: options.All, + RunExternalCode: options.RunExternalCode, + PprofDir: options.PprofDir, + SingleThreaded: options.SingleThreaded, + Quiet: options.Quiet, + Checkers: options.Checkers, + } +} + +// Equals reports whether all stored option values are equal, including nil versus empty collections. +// Paths are compared by ordered entries, ignoring backing-storage allocation. +func (options *CompilerOptions) Equals(other *CompilerOptions) bool { + if options == other { + return true + } + if options == nil || other == nil { + return false + } + if options.AllowJs != other.AllowJs { + return false + } + if options.AllowArbitraryExtensions != other.AllowArbitraryExtensions { + return false + } + if options.AllowImportingTsExtensions != other.AllowImportingTsExtensions { + return false + } + if options.AllowNonTsExtensions != other.AllowNonTsExtensions { + return false + } + if options.AllowUmdGlobalAccess != other.AllowUmdGlobalAccess { + return false + } + if options.AllowUnreachableCode != other.AllowUnreachableCode { + return false + } + if options.AllowUnusedLabels != other.AllowUnusedLabels { + return false + } + if options.AssumeChangesOnlyAffectDirectDependencies != other.AssumeChangesOnlyAffectDirectDependencies { + return false + } + if options.CheckJs != other.CheckJs { + return false + } + if (options.CustomConditions == nil) != (other.CustomConditions == nil) || !slices.Equal(options.CustomConditions, other.CustomConditions) { + return false + } + if options.Composite != other.Composite { + return false + } + if options.EmitDeclarationOnly != other.EmitDeclarationOnly { + return false + } + if options.EmitBOM != other.EmitBOM { + return false + } + if options.EmitDecoratorMetadata != other.EmitDecoratorMetadata { + return false + } + if options.Declaration != other.Declaration { + return false + } + if options.DeclarationDir != other.DeclarationDir { + return false + } + if options.DeclarationMap != other.DeclarationMap { + return false + } + if options.DeduplicatePackages != other.DeduplicatePackages { + return false + } + if options.DisableSizeLimit != other.DisableSizeLimit { + return false + } + if options.DisableSourceOfProjectReferenceRedirect != other.DisableSourceOfProjectReferenceRedirect { + return false + } + if options.DisableSolutionSearching != other.DisableSolutionSearching { + return false + } + if options.DisableReferencedProjectLoad != other.DisableReferencedProjectLoad { + return false + } + if options.ErasableSyntaxOnly != other.ErasableSyntaxOnly { + return false + } + if options.ExactOptionalPropertyTypes != other.ExactOptionalPropertyTypes { + return false + } + if options.ExperimentalDecorators != other.ExperimentalDecorators { + return false + } + if options.ForceConsistentCasingInFileNames != other.ForceConsistentCasingInFileNames { + return false + } + if options.IsolatedModules != other.IsolatedModules { + return false + } + if options.IsolatedDeclarations != other.IsolatedDeclarations { + return false + } + if options.IgnoreConfig != other.IgnoreConfig { + return false + } + if options.IgnoreDeprecations != other.IgnoreDeprecations { + return false + } + if options.ImportHelpers != other.ImportHelpers { + return false + } + if options.InlineSourceMap != other.InlineSourceMap { + return false + } + if options.InlineSources != other.InlineSources { + return false + } + if options.Init != other.Init { + return false + } + if options.Incremental != other.Incremental { + return false + } + if options.Jsx != other.Jsx { + return false + } + if options.JsxFactory != other.JsxFactory { + return false + } + if options.JsxFragmentFactory != other.JsxFragmentFactory { + return false + } + if options.JsxImportSource != other.JsxImportSource { + return false + } + if (options.Lib == nil) != (other.Lib == nil) || !slices.Equal(options.Lib, other.Lib) { + return false + } + if options.LibReplacement != other.LibReplacement { + return false + } + if options.Locale != other.Locale { + return false + } + if options.MapRoot != other.MapRoot { + return false + } + if options.Module != other.Module { + return false + } + if options.ModuleResolution != other.ModuleResolution { + return false + } + if (options.ModuleSuffixes == nil) != (other.ModuleSuffixes == nil) || !slices.Equal(options.ModuleSuffixes, other.ModuleSuffixes) { + return false + } + if options.ModuleDetection != other.ModuleDetection { + return false + } + if options.NewLine != other.NewLine { + return false + } + if options.NoEmit != other.NoEmit { + return false + } + if options.NoCheck != other.NoCheck { + return false + } + if options.NoErrorTruncation != other.NoErrorTruncation { + return false + } + if options.NoFallthroughCasesInSwitch != other.NoFallthroughCasesInSwitch { + return false + } + if options.NoImplicitAny != other.NoImplicitAny { + return false + } + if options.NoImplicitThis != other.NoImplicitThis { + return false + } + if options.NoImplicitReturns != other.NoImplicitReturns { + return false + } + if options.NoEmitHelpers != other.NoEmitHelpers { + return false + } + if options.NoLib != other.NoLib { + return false + } + if options.NoPropertyAccessFromIndexSignature != other.NoPropertyAccessFromIndexSignature { + return false + } + if options.NoUncheckedIndexedAccess != other.NoUncheckedIndexedAccess { + return false + } + if options.NoEmitOnError != other.NoEmitOnError { + return false + } + if options.NoUnusedLocals != other.NoUnusedLocals { + return false + } + if options.NoUnusedParameters != other.NoUnusedParameters { + return false + } + if options.NoResolve != other.NoResolve { + return false + } + if options.NoImplicitOverride != other.NoImplicitOverride { + return false + } + if options.NoUncheckedSideEffectImports != other.NoUncheckedSideEffectImports { + return false + } + if options.OutDir != other.OutDir { + return false + } + if !options.Paths.EqualFunc(other.Paths, func(a, b []string) bool { + return (a == nil) == (b == nil) && slices.Equal(a, b) + }) { + return false + } + if (options.Plugins == nil) != (other.Plugins == nil) || !slices.Equal(options.Plugins, other.Plugins) { + return false + } + if options.PreserveConstEnums != other.PreserveConstEnums { + return false + } + if options.PreserveSymlinks != other.PreserveSymlinks { + return false + } + if options.Project != other.Project { + return false + } + if options.ResolveJsonModule != other.ResolveJsonModule { + return false + } + if options.ResolvePackageJsonExports != other.ResolvePackageJsonExports { + return false + } + if options.ResolvePackageJsonImports != other.ResolvePackageJsonImports { + return false + } + if options.RemoveComments != other.RemoveComments { + return false + } + if options.RewriteRelativeImportExtensions != other.RewriteRelativeImportExtensions { + return false + } + if options.ReactNamespace != other.ReactNamespace { + return false + } + if options.RootDir != other.RootDir { + return false + } + if (options.RootDirs == nil) != (other.RootDirs == nil) || !slices.Equal(options.RootDirs, other.RootDirs) { + return false + } + if options.SkipLibCheck != other.SkipLibCheck { + return false + } + if options.StableTypeOrdering != other.StableTypeOrdering { + return false + } + if options.Strict != other.Strict { + return false + } + if options.StrictBindCallApply != other.StrictBindCallApply { + return false + } + if options.StrictBuiltinIteratorReturn != other.StrictBuiltinIteratorReturn { + return false + } + if options.StrictFunctionTypes != other.StrictFunctionTypes { + return false + } + if options.StrictNullChecks != other.StrictNullChecks { + return false + } + if options.StrictPropertyInitialization != other.StrictPropertyInitialization { + return false + } + if options.StripInternal != other.StripInternal { + return false + } + if options.SkipDefaultLibCheck != other.SkipDefaultLibCheck { + return false + } + if options.SourceMap != other.SourceMap { + return false + } + if options.SourceRoot != other.SourceRoot { + return false + } + if options.SuppressOutputPathCheck != other.SuppressOutputPathCheck { + return false + } + if options.Target != other.Target { + return false + } + if options.TraceResolution != other.TraceResolution { + return false + } + if options.TsBuildInfoFile != other.TsBuildInfoFile { + return false + } + if (options.TypeRoots == nil) != (other.TypeRoots == nil) || !slices.Equal(options.TypeRoots, other.TypeRoots) { + return false + } + if (options.Types == nil) != (other.Types == nil) || !slices.Equal(options.Types, other.Types) { + return false + } + if options.UseDefineForClassFields != other.UseDefineForClassFields { + return false + } + if options.UseUnknownInCatchVariables != other.UseUnknownInCatchVariables { + return false + } + if options.VerbatimModuleSyntax != other.VerbatimModuleSyntax { + return false + } + if options.MaxNodeModuleJsDepth != other.MaxNodeModuleJsDepth && (options.MaxNodeModuleJsDepth == nil || other.MaxNodeModuleJsDepth == nil || *options.MaxNodeModuleJsDepth != *other.MaxNodeModuleJsDepth) { + return false + } + if options.AllowSyntheticDefaultImports != other.AllowSyntheticDefaultImports { + return false + } + if options.AlwaysStrict != other.AlwaysStrict { + return false + } + if options.BaseUrl != other.BaseUrl { + return false + } + if options.DownlevelIteration != other.DownlevelIteration { + return false + } + if options.ESModuleInterop != other.ESModuleInterop { + return false + } + if options.OutFile != other.OutFile { + return false + } + if options.ConfigFilePath != other.ConfigFilePath { + return false + } + if options.NoDtsResolution != other.NoDtsResolution { + return false + } + if options.PathsBasePath != other.PathsBasePath { + return false + } + if options.Diagnostics != other.Diagnostics { + return false + } + if options.ExtendedDiagnostics != other.ExtendedDiagnostics { + return false + } + if options.GenerateCpuProfile != other.GenerateCpuProfile { + return false + } + if options.GenerateTrace != other.GenerateTrace { + return false + } + if options.ListEmittedFiles != other.ListEmittedFiles { + return false + } + if options.ListFiles != other.ListFiles { + return false + } + if options.ExplainFiles != other.ExplainFiles { + return false + } + if options.ListFilesOnly != other.ListFilesOnly { + return false + } + if options.NoEmitForJsFiles != other.NoEmitForJsFiles { + return false + } + if options.PreserveWatchOutput != other.PreserveWatchOutput { + return false + } + if options.Pretty != other.Pretty { + return false + } + if options.Version != other.Version { + return false + } + if options.Watch != other.Watch { + return false + } + if options.ShowConfig != other.ShowConfig { + return false + } + if options.Build != other.Build { + return false + } + if options.Help != other.Help { + return false + } + if options.All != other.All { + return false + } + if options.RunExternalCode != other.RunExternalCode { + return false + } + if options.PprofDir != other.PprofDir { + return false + } + if options.SingleThreaded != other.SingleThreaded { + return false + } + if options.Quiet != other.Quiet { + return false + } + if options.Checkers != other.Checkers && (options.Checkers == nil || other.Checkers == nil || *options.Checkers != *other.Checkers) { + return false + } + return true +} + +type ModuleDetectionKind int32 + +const ( + ModuleDetectionKindNone ModuleDetectionKind = 0 + ModuleDetectionKindAuto ModuleDetectionKind = 1 + ModuleDetectionKindLegacy ModuleDetectionKind = 2 + ModuleDetectionKindForce ModuleDetectionKind = 3 +) + +type ModuleKind int32 + +const ( + ModuleKindNone ModuleKind = 0 + ModuleKindCommonJS ModuleKind = 1 + // Deprecated: Do not use outside of options parsing and validation. + ModuleKindAMD ModuleKind = 2 + // Deprecated: Do not use outside of options parsing and validation. + ModuleKindUMD ModuleKind = 3 + // Deprecated: Do not use outside of options parsing and validation. + ModuleKindSystem ModuleKind = 4 + // NOTE: ES module kinds should be contiguous to more easily check whether a module kind is *any* ES module kind. + // Non-ES module kinds should not come between ES2015 (the earliest ES module kind) and ESNext (the last ES + // module kind). + ModuleKindES2015 ModuleKind = 5 + ModuleKindES2020 ModuleKind = 6 + ModuleKindES2022 ModuleKind = 7 + ModuleKindESNext ModuleKind = 99 + // Node16+ is an amalgam of commonjs (albeit updated) and es2022+, and represents a distinct module system from es2020/esnext + ModuleKindNode16 ModuleKind = 100 + ModuleKindNode18 ModuleKind = 101 + ModuleKindNode20 ModuleKind = 102 + ModuleKindNodeNext ModuleKind = 199 + // Emit as written + ModuleKindPreserve ModuleKind = 200 +) + +type ModuleResolutionKind int32 + +const ( + ModuleResolutionKindUnknown ModuleResolutionKind = 0 + // Deprecated: Do not use outside of options parsing and validation. + ModuleResolutionKindClassic ModuleResolutionKind = 1 + // Deprecated: Do not use outside of options parsing and validation. + ModuleResolutionKindNode10 ModuleResolutionKind = 2 + // Starting with node16, node's module resolver has significant departures from traditional cjs resolution + // to better support ECMAScript modules and their use within node - however more features are still being added. + // TypeScript's Node ESM support was introduced after Node 12 went end-of-life, and Node 14 is the earliest stable + // version that supports both pattern trailers - *but*, Node 16 is the first version that also supports ECMAScript 2022. + // In turn, we offer both a `NodeNext` moving resolution target, and a `Node16` version-anchored resolution target + ModuleResolutionKindNode16 ModuleResolutionKind = 3 + ModuleResolutionKindNodeNext ModuleResolutionKind = 99 // Not simply `Node16` so that compiled code linked against TS can use the `Next` value reliably (same as with `ModuleKind`) + ModuleResolutionKindBundler ModuleResolutionKind = 100 +) + +type NewLineKind int32 + +const ( + NewLineKindNone NewLineKind = 0 + NewLineKindCRLF NewLineKind = 1 + NewLineKindLF NewLineKind = 2 +) + +type ScriptTarget int32 + +const ( + ScriptTargetNone ScriptTarget = 0 + // Deprecated: Do not use outside of options parsing and validation. + ScriptTargetES5 ScriptTarget = 1 + ScriptTargetES2015 ScriptTarget = 2 + ScriptTargetES2016 ScriptTarget = 3 + ScriptTargetES2017 ScriptTarget = 4 + ScriptTargetES2018 ScriptTarget = 5 + ScriptTargetES2019 ScriptTarget = 6 + ScriptTargetES2020 ScriptTarget = 7 + ScriptTargetES2021 ScriptTarget = 8 + ScriptTargetES2022 ScriptTarget = 9 + ScriptTargetES2023 ScriptTarget = 10 + ScriptTargetES2024 ScriptTarget = 11 + ScriptTargetES2025 ScriptTarget = 12 + ScriptTargetESNext ScriptTarget = 99 + ScriptTargetJSON ScriptTarget = 100 + ScriptTargetLatest ScriptTarget = ScriptTargetESNext + ScriptTargetLatestStandard ScriptTarget = ScriptTargetES2025 +) + +type JsxEmit int32 + +const ( + JsxEmitNone JsxEmit = 0 + JsxEmitPreserve JsxEmit = 1 + JsxEmitReact JsxEmit = 2 + JsxEmitReactNative JsxEmit = 3 + JsxEmitReactJSX JsxEmit = 4 + JsxEmitReactJSXDev JsxEmit = 5 +) + +type WatchFileKind int32 + +const ( + WatchFileKindNone WatchFileKind = 0 + WatchFileKindFixedPollingInterval WatchFileKind = 1 + WatchFileKindPriorityPollingInterval WatchFileKind = 2 + WatchFileKindDynamicPriorityPolling WatchFileKind = 3 + WatchFileKindFixedChunkSizePolling WatchFileKind = 4 + WatchFileKindUseFsEvents WatchFileKind = 5 + WatchFileKindUseFsEventsOnParentDirectory WatchFileKind = 6 +) + +type WatchDirectoryKind int32 + +const ( + WatchDirectoryKindNone WatchDirectoryKind = 0 + WatchDirectoryKindUseFsEvents WatchDirectoryKind = 1 + WatchDirectoryKindFixedPollingInterval WatchDirectoryKind = 2 + WatchDirectoryKindDynamicPriorityPolling WatchDirectoryKind = 3 + WatchDirectoryKindFixedChunkSizePolling WatchDirectoryKind = 4 +) + +type PollingKind int32 + +const ( + PollingKindNone PollingKind = 0 + PollingKindFixedInterval PollingKind = 1 + PollingKindPriorityInterval PollingKind = 2 + PollingKindDynamicPriority PollingKind = 3 + PollingKindFixedChunkSize PollingKind = 4 +) + +var ModuleKindToModuleResolutionKind = map[ModuleKind]ModuleResolutionKind{ + ModuleKindNode16: ModuleResolutionKindNode16, + ModuleKindNodeNext: ModuleResolutionKindNodeNext, +} + +type WatchOptions struct { + Interval *int `json:"watchInterval"` + FileKind WatchFileKind `json:"watchFile"` + DirectoryKind WatchDirectoryKind `json:"watchDirectory"` + FallbackPolling PollingKind `json:"fallbackPolling"` + SyncWatchDir Tristate `json:"synchronousWatchDirectory"` + ExcludeDir []string `json:"excludeDirectories"` + ExcludeFiles []string `json:"excludeFiles"` +} + +// Equals compares stored watch options, preserving nil versus empty collections. +func (options *WatchOptions) Equals(other *WatchOptions) bool { + if options == other { + return true + } + if options == nil || other == nil { + return false + } + if options.Interval != other.Interval && (options.Interval == nil || other.Interval == nil || *options.Interval != *other.Interval) { + return false + } + if options.FileKind != other.FileKind { + return false + } + if options.DirectoryKind != other.DirectoryKind { + return false + } + if options.FallbackPolling != other.FallbackPolling { + return false + } + if options.SyncWatchDir != other.SyncWatchDir { + return false + } + if (options.ExcludeDir == nil) != (other.ExcludeDir == nil) || !slices.Equal(options.ExcludeDir, other.ExcludeDir) { + return false + } + if (options.ExcludeFiles == nil) != (other.ExcludeFiles == nil) || !slices.Equal(options.ExcludeFiles, other.ExcludeFiles) { + return false + } + return true +} + +type TypeAcquisition struct { + Enable Tristate `json:"enable,omitzero"` + Include []string `json:"include,omitzero"` + Exclude []string `json:"exclude,omitzero"` + DisableFilenameBasedTypeAcquisition Tristate `json:"disableFilenameBasedTypeAcquisition,omitzero"` +} + +type BuildOptions struct { + _ noCopy + + Dry Tristate `json:"dry,omitzero"` + Force Tristate `json:"force,omitzero"` + Verbose Tristate `json:"verbose,omitzero"` + Builders *int `json:"builders,omitzero"` + StopBuildOnErrors Tristate `json:"stopBuildOnErrors,omitzero"` + + // CompilerOptions are not parsed here and will be available on ParsedBuildCommandLine + + // Internal fields + Clean Tristate `json:"clean,omitzero"` +} diff --git a/tsc/internal/core/typeacquisition.go b/tsc/internal/core/typeacquisition.go index 6edc0ea22f2fe..b8326dd4edfb2 100644 --- a/tsc/internal/core/typeacquisition.go +++ b/tsc/internal/core/typeacquisition.go @@ -2,13 +2,6 @@ package core import "slices" -type TypeAcquisition struct { - Enable Tristate `json:"enable,omitzero"` - Include []string `json:"include,omitzero"` - Exclude []string `json:"exclude,omitzero"` - DisableFilenameBasedTypeAcquisition Tristate `json:"disableFilenameBasedTypeAcquisition,omitzero"` -} - func (ta *TypeAcquisition) Equals(other *TypeAcquisition) bool { if ta == other { return true diff --git a/tsc/internal/core/watchoptions.go b/tsc/internal/core/watchoptions.go index fefed73d30deb..eb324697fb1ac 100644 --- a/tsc/internal/core/watchoptions.go +++ b/tsc/internal/core/watchoptions.go @@ -2,48 +2,6 @@ package core import "time" -type WatchOptions struct { - Interval *int `json:"watchInterval"` - FileKind WatchFileKind `json:"watchFile"` - DirectoryKind WatchDirectoryKind `json:"watchDirectory"` - FallbackPolling PollingKind `json:"fallbackPolling"` - SyncWatchDir Tristate `json:"synchronousWatchDirectory"` - ExcludeDir []string `json:"excludeDirectories"` - ExcludeFiles []string `json:"excludeFiles"` -} - -type WatchFileKind int32 - -const ( - WatchFileKindNone WatchFileKind = 0 - WatchFileKindFixedPollingInterval WatchFileKind = 1 - WatchFileKindPriorityPollingInterval WatchFileKind = 2 - WatchFileKindDynamicPriorityPolling WatchFileKind = 3 - WatchFileKindFixedChunkSizePolling WatchFileKind = 4 - WatchFileKindUseFsEvents WatchFileKind = 5 - WatchFileKindUseFsEventsOnParentDirectory WatchFileKind = 6 -) - -type WatchDirectoryKind int32 - -const ( - WatchDirectoryKindNone WatchDirectoryKind = 0 - WatchDirectoryKindUseFsEvents WatchDirectoryKind = 1 - WatchDirectoryKindFixedPollingInterval WatchDirectoryKind = 2 - WatchDirectoryKindDynamicPriorityPolling WatchDirectoryKind = 3 - WatchDirectoryKindFixedChunkSizePolling WatchDirectoryKind = 4 -) - -type PollingKind int32 - -const ( - PollingKindNone PollingKind = 0 - PollingKindFixedInterval PollingKind = 1 - PollingKindPriorityInterval PollingKind = 2 - PollingKindDynamicPriority PollingKind = 3 - PollingKindFixedChunkSize PollingKind = 4 -) - func (w *WatchOptions) WatchInterval() time.Duration { watchInterval := 2000 * time.Millisecond if w != nil && w.Interval != nil { diff --git a/tsc/internal/execute/incremental/snapshottobuildinfo.go b/tsc/internal/execute/incremental/snapshottobuildinfo.go index 78eea1369565a..541fe7fada8e9 100644 --- a/tsc/internal/execute/incremental/snapshottobuildinfo.go +++ b/tsc/internal/execute/incremental/snapshottobuildinfo.go @@ -3,7 +3,6 @@ package incremental import ( "fmt" "maps" - "reflect" "slices" "strings" @@ -289,21 +288,14 @@ func (t *toBuildInfo) setRootOfIncrementalProgram() { } func (t *toBuildInfo) setCompilerOptions() { - tsoptions.ForEachCompilerOptionValue( + tsoptions.ForEachCompilerOptionAffectingBuildInfo( t.snapshot.options, - func(option *tsoptions.CommandLineOption) bool { - return option.AffectsBuildInfo - }, - func(option *tsoptions.CommandLineOption, value reflect.Value, i int) bool { - if value.IsZero() { - return false - } + func(option *tsoptions.CommandLineOption, value any) { // Make it relative to buildInfo directory if file path if t.buildInfo.Options == nil { t.buildInfo.Options = &collections.OrderedMap[string, any]{} } - t.buildInfo.Options.Set(option.Name, t.toRelativeToBuildInfoCompilerOptionValue(option, value.Interface())) - return false + t.buildInfo.Options.Set(option.Name, t.toRelativeToBuildInfoCompilerOptionValue(option, value)) }, ) } diff --git a/tsc/internal/execute/watcher.go b/tsc/internal/execute/watcher.go index 55907e5d8e7ce..3e33d32fa7a35 100644 --- a/tsc/internal/execute/watcher.go +++ b/tsc/internal/execute/watcher.go @@ -3,7 +3,6 @@ package execute import ( "context" "fmt" - "reflect" "slices" "time" @@ -664,7 +663,7 @@ func (w *Watcher) recheckTsConfig(force bool) bool { } w.configHasErrors = false w.configFilePaths = append([]string{w.configFileName}, configParseResult.ExtendedSourceFiles()...) - if !reflect.DeepEqual(w.config.ParsedConfig, configParseResult.ParsedConfig) { + if !w.config.ParsedConfig.Equals(configParseResult.ParsedConfig) { w.configModified = true } w.replaceContentMapperProject(configParseResult) diff --git a/tsc/internal/project/projectcollectionbuilder.go b/tsc/internal/project/projectcollectionbuilder.go index eb3752678485c..a009d678cb29b 100644 --- a/tsc/internal/project/projectcollectionbuilder.go +++ b/tsc/internal/project/projectcollectionbuilder.go @@ -1316,7 +1316,7 @@ func (b *ProjectCollectionBuilder) updateOrCreateSyntheticProject( project.ChangeIf( func(p *Project) bool { return !slices.Equal(p.CommandLine.FileNames(), newCommandLine.FileNames()) || - !reflect.DeepEqual(p.CommandLine.CompilerOptions(), compilerOptions) || + !p.CommandLine.CompilerOptions().Equals(compilerOptions) || !projectReferencesEqual(p.CommandLine.ProjectReferences(), projectReferences) || !reflect.DeepEqual(p.CommandLine.Errors, configFileParsingDiagnostics) || !slices.Equal(p.CommandLine.ContentMappers(), newCommandLine.ContentMappers()) || @@ -1398,7 +1398,7 @@ func (b *ProjectCollectionBuilder) updateOrCreateInferredProject( changed := b.inferredProject.ChangeIf( func(p *Project) bool { return !slices.Equal(p.CommandLine.FileNames(), newCommandLine.FileNames()) || - !reflect.DeepEqual(p.CommandLine.CompilerOptions(), compilerOptions) || + !p.CommandLine.CompilerOptions().Equals(compilerOptions) || !projectReferencesEqual(p.CommandLine.ProjectReferences(), projectReferences) || !reflect.DeepEqual(p.CommandLine.Errors, configFileParsingDiagnostics) || !slices.Equal(p.CommandLine.ContentMappers(), newCommandLine.ContentMappers()) diff --git a/tsc/internal/transpile/options_generated.go b/tsc/internal/transpile/options_generated.go new file mode 100644 index 0000000000000..2362628b58a51 --- /dev/null +++ b/tsc/internal/transpile/options_generated.go @@ -0,0 +1,22 @@ +// Code generated by tools/scripts/tsc/generate-options.ts. DO NOT EDIT. + +package transpile + +import "github.com/microsoft/TypeScript/tsc/internal/core" + +func clearOptionsForTranspile(options *core.CompilerOptions) { + options.AllowImportingTsExtensions = core.TSUnknown + options.Composite = core.TSUnknown + options.EmitDeclarationOnly = core.TSUnknown + options.Declaration = core.TSUnknown + options.DeclarationDir = "" + options.Incremental = core.TSUnknown + options.Lib = nil + options.NoEmit = core.TSUnknown + options.NoEmitOnError = core.TSUnknown + options.Paths = nil + options.RootDirs = nil + options.TsBuildInfoFile = "" + options.Types = nil + options.OutFile = "" +} diff --git a/tsc/internal/transpile/options_test.go b/tsc/internal/transpile/options_test.go new file mode 100644 index 0000000000000..fd82bcd4d2d42 --- /dev/null +++ b/tsc/internal/transpile/options_test.go @@ -0,0 +1,58 @@ +package transpile + +import ( + "reflect" + "testing" + + "github.com/microsoft/TypeScript/tsc/internal/collections" + "github.com/microsoft/TypeScript/tsc/internal/core" +) + +func TestTranspileClearsInapplicableOptions(t *testing.T) { + t.Parallel() + + for _, declaration := range []bool{false, true} { + name := "module" + transpile := TranspileModule + if declaration { + name = "declaration" + transpile = TranspileDeclaration + } + t.Run(name, func(t *testing.T) { + t.Parallel() + + options := &core.CompilerOptions{ + Incremental: core.TSTrue, + Declaration: core.TSTrue, + EmitDeclarationOnly: core.TSTrue, + NoEmit: core.TSTrue, + Lib: []string{"missing.d.ts"}, + OutFile: "/other/output.js", + Composite: core.TSTrue, + TsBuildInfoFile: "/other/buildinfo", + Paths: collections.NewOrderedMapFromList([]collections.MapEntry[string, []string]{{Key: "*", Value: []string{"/missing/*"}}}), + RootDirs: []string{"/missing"}, + Types: []string{"missing"}, + AllowImportingTsExtensions: core.TSTrue, + NoEmitOnError: core.TSTrue, + DeclarationDir: "/other/declarations", + } + before := options.Clone() + const source = "export const value: number = 1;" + expected := transpile(t.Context(), source, Options{ReportDiagnostics: true}) + actual := transpile(t.Context(), source, Options{CompilerOptions: options, ReportDiagnostics: true}) + if expected == nil || actual == nil { + t.Fatal("Transpilation was unexpectedly canceled") + } + if expected.OutputText == "" || actual.OutputText != expected.OutputText || actual.SourceMapText != expected.SourceMapText { + t.Fatalf("Inapplicable options changed the output: got %#v, want %#v", actual, expected) + } + if len(expected.Diagnostics) != 0 || len(actual.Diagnostics) != 0 { + t.Fatalf("Unexpected diagnostics: got %v, want %v", actual.Diagnostics, expected.Diagnostics) + } + if !reflect.DeepEqual(options, before) { + t.Fatal("Transpilation modified the caller's options") + } + }) + } +} diff --git a/tsc/internal/transpile/transpile.go b/tsc/internal/transpile/transpile.go index 98d999c801b1e..f06af3c113c28 100644 --- a/tsc/internal/transpile/transpile.go +++ b/tsc/internal/transpile/transpile.go @@ -124,20 +124,7 @@ func transpileWorker(ctx context.Context, input string, options Options, declara } // Clear options that do not apply to single-file transpilation. - opts.Incremental = core.TSUnknown - opts.Declaration = core.TSUnknown - opts.EmitDeclarationOnly = core.TSUnknown - opts.NoEmit = core.TSUnknown - opts.Lib = nil - opts.OutFile = "" - opts.Composite = core.TSUnknown - opts.TsBuildInfoFile = "" - opts.Paths = nil - opts.RootDirs = nil - opts.Types = nil - opts.AllowImportingTsExtensions = core.TSUnknown - opts.NoEmitOnError = core.TSUnknown - opts.DeclarationDir = "" + clearOptionsForTranspile(opts) // Do not set `isolatedModules` if `verbatimModuleSyntax` was supplied, since // it would be redundant. diff --git a/tsc/internal/tsoptions/commandlineoption.go b/tsc/internal/tsoptions/commandlineoption.go index 1346e5c0bbd5e..37cd240bc5926 100644 --- a/tsc/internal/tsoptions/commandlineoption.go +++ b/tsc/internal/tsoptions/commandlineoption.go @@ -41,10 +41,6 @@ type CommandLineOption struct { // checks that option with number type has value >= minValue minValue int - // true or undefined - // used for configDirTemplateSubstitutionOptions - allowConfigDirTemplateSubstitution bool - // used for filter in compilerrunner AffectsDeclarationPath bool AffectsProgramStructure bool @@ -101,104 +97,5 @@ func (o *CommandLineOption) DisallowNullOrUndefined() bool { return o.Name == "extends" } -// CommandLineOption.Elements() -var commandLineOptionElements = map[string]*CommandLineOption{ - "lib": { - Name: "lib", - Kind: CommandLineOptionTypeEnum, // libMap, - DefaultValueDescription: core.TSUnknown, - }, - "rootDirs": { - Name: "rootDirs", - Kind: CommandLineOptionTypeString, - IsFilePath: true, - }, - "typeRoots": { - Name: "typeRoots", - Kind: CommandLineOptionTypeString, - IsFilePath: true, - }, - "types": { - Name: "types", - Kind: CommandLineOptionTypeString, - }, - "moduleSuffixes": { - Name: "moduleSuffixes", - Kind: CommandLineOptionTypeString, - }, - "customConditions": { - Name: "condition", - Kind: CommandLineOptionTypeString, - }, - "plugins": { - Name: "plugin", - Kind: CommandLineOptionTypeObject, - }, - // For tsconfig root options - "references": { - Name: "references", - Kind: CommandLineOptionTypeObject, - }, - "contentMappers": { - Name: "contentMappers", - Kind: CommandLineOptionTypeObject, - }, - "files": { - Name: "files", - Kind: CommandLineOptionTypeString, - }, - "include": { - Name: "include", - Kind: CommandLineOptionTypeString, - }, - "exclude": { - Name: "exclude", - Kind: CommandLineOptionTypeString, - }, - "extends": { - Name: "extends", - Kind: CommandLineOptionTypeString, - }, - // For Watch options - "excludeDirectories": { - Name: "excludeDirectory", - Kind: CommandLineOptionTypeString, - IsFilePath: true, - extraValidation: extraValidationSpec, - }, - "excludeFiles": { - Name: "excludeFile", - Kind: CommandLineOptionTypeString, - IsFilePath: true, - extraValidation: extraValidationSpec, - }, - // Test infra options - "libFiles": { - Name: "libFiles", - Kind: CommandLineOptionTypeString, - }, -} - -// CommandLineOption.EnumMap() -var commandLineOptionEnumMap = map[string]*collections.OrderedMap[string, any]{ - "lib": LibMap, - "moduleResolution": moduleResolutionOptionMap, - "module": moduleOptionMap, - "target": targetOptionMap, - "moduleDetection": moduleDetectionOptionMap, - "jsx": jsxOptionMap, - "newLine": newLineOptionMap, - "watchFile": watchFileEnumMap, - "watchDirectory": watchDirectoryEnumMap, - "fallbackPolling": fallbackEnumMap, -} - -// CommandLineOption.DeprecatedKeys() -var commandLineOptionDeprecated = map[string]*collections.Set[string]{ - "module": collections.NewSetFromItems("none", "amd", "system", "umd"), - "moduleResolution": collections.NewSetFromItems("node", "classic", "node10"), - "target": collections.NewSetFromItems("es5"), -} - // todo: revisit to see if this can be improved type CompilerOptionsValue any diff --git a/tsc/internal/tsoptions/compileroptions_test.go b/tsc/internal/tsoptions/compileroptions_test.go new file mode 100644 index 0000000000000..6e04737e15333 --- /dev/null +++ b/tsc/internal/tsoptions/compileroptions_test.go @@ -0,0 +1,446 @@ +package tsoptions + +import ( + "reflect" + "slices" + "strings" + "testing" + + "github.com/microsoft/TypeScript/tsc/internal/collections" + "github.com/microsoft/TypeScript/tsc/internal/core" +) + +func TestGeneratedCompilerOptionParsingAndClone(t *testing.T) { + t.Parallel() + + for field := range reflect.TypeFor[core.CompilerOptions]().Fields() { + if !field.IsExported() { + continue + } + name, _, _ := strings.Cut(field.Tag.Get("json"), ",") + t.Run(name, func(t *testing.T) { + t.Parallel() + options := &core.CompilerOptions{} + optionsValue := reflect.ValueOf(options).Elem() + var input any + var expected any + switch field.Type { + case reflect.TypeFor[core.Tristate](): + input, expected = true, core.TSTrue + case reflect.TypeFor[string](): + input, expected = "value", "value" + case reflect.TypeFor[*int](): + input, expected = float64(2), new(2) + case reflect.TypeFor[[]string](): + input, expected = []any{"first", "second"}, []string{"first", "second"} + case reflect.TypeFor[[]core.PluginImport](): + plugin := &collections.OrderedMap[string, any]{} + plugin.Set("name", "plugin") + input, expected = []any{plugin}, []core.PluginImport{{Name: "plugin"}} + case reflect.TypeFor[*collections.OrderedMap[string, []string]](): + paths := &collections.OrderedMap[string, any]{} + paths.Set("@/*", []any{"src/*"}) + expectedPaths := &collections.OrderedMap[string, []string]{} + expectedPaths.Set("@/*", []string{"src/*"}) + input, expected = paths, expectedPaths + default: + if field.Type.Kind() != reflect.Int32 { + t.Fatalf("Unhandled compiler option type: %v", field.Type) + } + value := reflect.New(field.Type).Elem() + value.SetInt(1) + input, expected = value.Interface(), value.Interface() + } + if errors := ParseCompilerOptions(name, input, options); len(errors) != 0 { + t.Fatalf("Parsing %s: %v", name, errors) + } + actual := optionsValue.FieldByIndex(field.Index).Interface() + if !reflect.DeepEqual(actual, expected) { + t.Errorf("%s: got %#v, want %#v", name, actual, expected) + } + if field.Type.Kind() == reflect.Int32 { + numeric := &core.CompilerOptions{} + ParseCompilerOptions(name, float64(1), numeric) + actual := reflect.ValueOf(numeric).Elem().FieldByIndex(field.Index).Interface() + if !reflect.DeepEqual(actual, expected) { + t.Errorf("%s as a JSON number: got %#v, want %#v", name, actual, expected) + } + } + clone := options.Clone() + if clone == options || !reflect.DeepEqual(clone, options) { + t.Fatal("Clone must return a distinct object with every field copied") + } + clonedValue := reflect.ValueOf(clone).Elem().FieldByIndex(field.Index) + sourceValue := optionsValue.FieldByIndex(field.Index) + if (field.Type.Kind() == reflect.Pointer || field.Type.Kind() == reflect.Slice) && clonedValue.Pointer() != sourceValue.Pointer() { + t.Fatal("Clone must remain shallow") + } + }) + } + + if !reflect.DeepEqual((&core.CompilerOptions{}).Clone(), &core.CompilerOptions{}) { + t.Fatal("Clone must preserve zero values") + } +} + +func TestGeneratedCompilerOptionParserCompatibility(t *testing.T) { + t.Parallel() + + options := &core.CompilerOptions{} + ParseCompilerOptions("STRICT", true, options) + ParseCompilerOptions("moduleDetectionKind", core.ModuleDetectionKindForce, options) + ParseCompilerOptions("lib", []string{"lib.es2025.d.ts"}, options) + ParseCompilerOptions("strict", nil, options) + if options.Strict != core.TSTrue || options.ModuleDetection != core.ModuleDetectionKindForce || !reflect.DeepEqual(options.Lib, []string{"lib.es2025.d.ts"}) { + t.Fatal("Parser did not preserve aliases, typed lib values, or null handling") + } + before := options.Clone() + ParseCompilerOptions("unknownOption", true, options) + if !reflect.DeepEqual(options, before) { + t.Fatal("Unknown options must not change parsed options") + } +} + +func TestCompilerOptionsEquality(t *testing.T) { + t.Parallel() + + check := func(t *testing.T, a, b *core.CompilerOptions) { + t.Helper() + want := reflect.DeepEqual(a, b) + if a != nil && b != nil { + type pathEntry struct { + key string + value []string + } + entries := func(paths *collections.OrderedMap[string, []string]) []pathEntry { + var result []pathEntry + for key, value := range paths.Entries() { + result = append(result, pathEntry{key, value}) + } + return result + } + // Compare observable paths contents, not allocation details of the ordered map. + pathsEqual := (a.Paths == nil) == (b.Paths == nil) && reflect.DeepEqual(entries(a.Paths), entries(b.Paths)) + aFields, bFields := a.Clone(), b.Clone() + aFields.Paths, bFields.Paths = nil, nil + want = pathsEqual && reflect.DeepEqual(aFields, bFields) + } + if got := a.Equals(b); got != want { + t.Fatalf("Got %v, want %v for\n%+v\n%+v", got, want, a, b) + } + } + check(t, nil, nil) + check(t, nil, &core.CompilerOptions{}) + check(t, &core.CompilerOptions{}, nil) + check(t, &core.CompilerOptions{}, &core.CompilerOptions{}) + check(t, &core.CompilerOptions{}, &core.CompilerOptions{Strict: core.TSTrue}) + + allOptions := &core.CompilerOptions{} + for field := range reflect.TypeFor[core.CompilerOptions]().Fields() { + if !field.IsExported() { + continue + } + values := compilerOptionTestValues(t, field) + switch field.Type { + case reflect.TypeFor[*int](): + values = append(values, reflect.ValueOf(new(1)), reflect.ValueOf(new(1)), reflect.ValueOf(new(2))) + case reflect.TypeFor[[]string](): + values = append(values, reflect.ValueOf([]string{"a", "b"}), reflect.ValueOf([]string{"a", "b"}), reflect.ValueOf([]string{"b", "a"})) + case reflect.TypeFor[[]core.PluginImport](): + values = append(values, reflect.ValueOf([]core.PluginImport{{Name: "a"}}), reflect.ValueOf([]core.PluginImport{{Name: "a"}}), reflect.ValueOf([]core.PluginImport{{Name: "b"}})) + } + reflect.ValueOf(allOptions).Elem().FieldByIndex(field.Index).Set(values[len(values)-1]) + t.Run(field.Name, func(t *testing.T) { + t.Parallel() + for _, aValue := range values { + for _, bValue := range values { + a, b := &core.CompilerOptions{}, &core.CompilerOptions{} + reflect.ValueOf(a).Elem().FieldByIndex(field.Index).Set(aValue) + reflect.ValueOf(b).Elem().FieldByIndex(field.Index).Set(bValue) + check(t, a, b) + check(t, a, a) + check(t, a, a.Clone()) + } + } + }) + } + check(t, allOptions, allOptions.Clone()) + check(t, allOptions, &core.CompilerOptions{}) + + paths := []*collections.OrderedMap[string, []string]{ + nil, + {}, + collections.NewOrderedMapWithSizeHint[string, []string](0), + } + for _, values := range [][]string{nil, {}, {"a"}, {"b"}, {"a", "b"}, {"b", "a"}} { + for _, keys := range [][]string{{"x", "y"}, {"y", "x"}} { + m := &collections.OrderedMap[string, []string]{} + for _, key := range keys { + m.Set(key, values) + } + paths = append(paths, m, m.Clone()) + } + } + cleared := paths[len(paths)-1].Clone() + cleared.Clear() + paths = append(paths, cleared) + for _, a := range paths { + for _, b := range paths { + check(t, &core.CompilerOptions{Paths: a}, &core.CompilerOptions{Paths: b}) + } + } +} + +// Keep the reflection-based implementation as an independent check of the generated code. +func forEachReflectedCompilerOptionValue(options *core.CompilerOptions, declFilter func(*CommandLineOption) bool, fn func(option *CommandLineOption, value reflect.Value, i int) bool) bool { + optionsValue := reflect.ValueOf(options).Elem() + optionsType := reflect.TypeFor[core.CompilerOptions]() + for i := range optionsValue.NumField() { + field := optionsType.Field(i) + if !field.IsExported() { + continue + } + if optionDeclaration := CommandLineCompilerOptionsMap.Get(field.Name); optionDeclaration != nil && declFilter(optionDeclaration) { + if fn(optionDeclaration, optionsValue.Field(i), i) { + return true + } + } + } + return false +} + +func reflectedOptionsHaveChanges(oldOptions *core.CompilerOptions, newOptions *core.CompilerOptions, declFilter func(*CommandLineOption) bool) bool { + if oldOptions == newOptions { + return false + } + if oldOptions == nil || newOptions == nil { + return true + } + oldOptionsValue := reflect.ValueOf(oldOptions).Elem() + return forEachReflectedCompilerOptionValue(newOptions, declFilter, func(option *CommandLineOption, value reflect.Value, i int) bool { + newValue := value.Interface() + oldValue := oldOptionsValue.Field(i).Interface() + if option.strictFlag { + return oldOptions.GetStrictOptionValue(oldValue.(core.Tristate)) != newOptions.GetStrictOptionValue(newValue.(core.Tristate)) + } + if option.allowJsFlag { + return oldOptions.GetAllowJS() != newOptions.GetAllowJS() + } + return !reflect.DeepEqual(newValue, oldValue) + }) +} + +func compilerOptionTestValues(t *testing.T, field reflect.StructField) []reflect.Value { + t.Helper() + values := []reflect.Value{reflect.Zero(field.Type)} + for _, n := range []int64{1, 2} { + value := reflect.New(field.Type).Elem() + switch field.Type.Kind() { + case reflect.Int32: + value.SetInt(n) + case reflect.Uint8: + value.SetUint(uint64(n)) + case reflect.String: + value.SetString(string(rune('a' + n))) + case reflect.Pointer: + value.Set(reflect.New(field.Type.Elem())) + case reflect.Slice: + value.Set(reflect.MakeSlice(field.Type, int(n)-1, int(n)-1)) + default: + t.Fatalf("Unhandled compiler option type: %v", field.Type) + } + values = append(values, value) + } + return values +} + +func TestCompilerOptionComparisons(t *testing.T) { + t.Parallel() + + comparisons := []struct { + name string + compare func(*core.CompilerOptions, *core.CompilerOptions) bool + filter func(*CommandLineOption) bool + }{ + {"semanticDiagnostics", CompilerOptionsAffectSemanticDiagnostics, func(option *CommandLineOption) bool { return option.AffectsSemanticDiagnostics }}, + {"declarationPath", CompilerOptionsAffectDeclarationPath, func(option *CommandLineOption) bool { return option.AffectsDeclarationPath }}, + {"emit", CompilerOptionsAffectEmit, func(option *CommandLineOption) bool { return option.AffectsEmit }}, + } + check := func(t *testing.T, oldOptions *core.CompilerOptions, newOptions *core.CompilerOptions) { + t.Helper() + for _, comparison := range comparisons { + want := reflectedOptionsHaveChanges(oldOptions, newOptions, comparison.filter) + if got := comparison.compare(oldOptions, newOptions); got != want { + t.Fatalf("%s: got %v, want %v\nold: %+v\nnew: %+v", comparison.name, got, want, oldOptions, newOptions) + } + } + } + check(t, nil, nil) + check(t, nil, &core.CompilerOptions{}) + check(t, &core.CompilerOptions{}, nil) + check(t, &core.CompilerOptions{}, &core.CompilerOptions{}) + + states := []core.Tristate{core.TSUnknown, core.TSFalse, core.TSTrue} + for field := range reflect.TypeFor[core.CompilerOptions]().Fields() { + if !field.IsExported() { + continue + } + t.Run(field.Name, func(t *testing.T) { + t.Parallel() + values := compilerOptionTestValues(t, field) + for _, strict := range states { + for _, checkJs := range states { + for _, oldValue := range values { + for _, newValue := range values { + oldOptions := &core.CompilerOptions{Strict: strict, CheckJs: checkJs} + newOptions := oldOptions.Clone() + reflect.ValueOf(oldOptions).Elem().FieldByIndex(field.Index).Set(oldValue) + reflect.ValueOf(newOptions).Elem().FieldByIndex(field.Index).Set(newValue) + check(t, oldOptions, newOptions) + check(t, oldOptions, oldOptions) + } + } + } + } + }) + } + + t.Run("explicitStrictFlags", func(t *testing.T) { + t.Parallel() + for _, value := range states { + for _, oldStrict := range states { + for _, newStrict := range states { + oldOptions := &core.CompilerOptions{Strict: oldStrict} + forEachReflectedCompilerOptionValue(oldOptions, func(option *CommandLineOption) bool { return option.strictFlag }, func(_ *CommandLineOption, field reflect.Value, _ int) bool { + field.Set(reflect.ValueOf(value)) + return false + }) + newOptions := oldOptions.Clone() + newOptions.Strict = newStrict + check(t, oldOptions, newOptions) + } + } + } + }) +} + +func TestCompilerOptionsForBuildInfo(t *testing.T) { + t.Parallel() + + type entry struct { + option *CommandLineOption + value any + } + check := func(t *testing.T, options *core.CompilerOptions) { + t.Helper() + var want []entry + forEachReflectedCompilerOptionValue(options, func(option *CommandLineOption) bool { return option.AffectsBuildInfo }, func(option *CommandLineOption, value reflect.Value, _ int) bool { + if !value.IsZero() { + want = append(want, entry{option, value.Interface()}) + } + return false + }) + var got []entry + ForEachCompilerOptionAffectingBuildInfo(options, func(option *CommandLineOption, value any) { + got = append(got, entry{option, value}) + }) + if !reflect.DeepEqual(got, want) { + t.Fatalf("got %+v, want %+v", got, want) + } + } + check(t, &core.CompilerOptions{}) + allOptions := &core.CompilerOptions{} + for field := range reflect.TypeFor[core.CompilerOptions]().Fields() { + if !field.IsExported() { + continue + } + values := compilerOptionTestValues(t, field) + reflect.ValueOf(allOptions).Elem().FieldByIndex(field.Index).Set(values[1]) + t.Run(field.Name, func(t *testing.T) { + t.Parallel() + for _, value := range values { + options := &core.CompilerOptions{} + reflect.ValueOf(options).Elem().FieldByIndex(field.Index).Set(value) + check(t, options) + } + }) + } + check(t, allOptions) +} + +func TestCompilerOptionConfigDirSubstitution(t *testing.T) { + t.Parallel() + + handleOptionConfigDirTemplateSubstitution(nil, "/config") + fields := []string{ + "GenerateCpuProfile", "GenerateTrace", "OutFile", "OutDir", + "RootDir", "TsBuildInfoFile", "BaseUrl", "DeclarationDir", + } + for field := range reflect.TypeFor[core.CompilerOptions]().Fields() { + if field.Type.Kind() != reflect.String { + continue + } + t.Run(field.Name, func(t *testing.T) { + t.Parallel() + for _, value := range []string{"", "unchanged", "${configDir}/output", "prefix/${configDir}/output"} { + options := &core.CompilerOptions{} + actual := reflect.ValueOf(options).Elem().FieldByIndex(field.Index) + actual.SetString(value) + handleOptionConfigDirTemplateSubstitution(options, "/config") + expected := value + if slices.Contains(fields, field.Name) && value == "${configDir}/output" { + expected = "/config/output" + } + if actual.String() != expected { + t.Fatalf("Got %q, want %q", actual.String(), expected) + } + } + }) + } +} + +func TestCompilerOptionConfigDirSubstitutionCopyOnWrite(t *testing.T) { + t.Parallel() + + for _, fieldName := range []string{"RootDirs", "TypeRoots"} { + t.Run(fieldName, func(t *testing.T) { + t.Parallel() + for _, original := range [][]string{nil, {}, {"unchanged"}, {"${configDir}/types", "unchanged"}} { + options := &core.CompilerOptions{} + field := reflect.ValueOf(options).Elem().FieldByName(fieldName) + field.Set(reflect.ValueOf(original)) + handleOptionConfigDirTemplateSubstitution(options, "/config") + actual := field.Interface().([]string) + if len(original) > 0 && original[0] == "${configDir}/types" { + if !slices.Equal(actual, []string{"/config/types", "unchanged"}) || &actual[0] == &original[0] { + t.Fatal("Substitution must copy the changed slice") + } + } else if !reflect.DeepEqual(actual, original) || field.Pointer() != reflect.ValueOf(original).Pointer() { + t.Fatal("Unchanged slices must retain their identity") + } + } + }) + } + + original := &collections.OrderedMap[string, []string]{} + unchanged := []string{"unchanged"} + changed := []string{"${configDir}/src", "other"} + original.Set("unchanged", unchanged) + original.Set("changed", changed) + options := &core.CompilerOptions{Paths: original} + handleOptionConfigDirTemplateSubstitution(options, "/config") + if options.Paths == original || !slices.Equal(options.Paths.GetOrZero("changed"), []string{"/config/src", "other"}) { + t.Fatal("Substitution must clone paths before changing them") + } + if changed[0] != "${configDir}/src" || &options.Paths.GetOrZero("unchanged")[0] != &unchanged[0] { + t.Fatal("Substitution must preserve the original map and unchanged slices") + } + if !slices.Equal(slices.Collect(options.Paths.Keys()), []string{"unchanged", "changed"}) { + t.Fatal("Substitution must preserve paths ordering") + } + substituted := options.Paths + handleOptionConfigDirTemplateSubstitution(options, "/config") + if options.Paths != substituted { + t.Fatal("Unchanged paths must retain their identity") + } +} diff --git a/tsc/internal/tsoptions/declscompiler.go b/tsc/internal/tsoptions/declarations_generated.go similarity index 66% rename from tsc/internal/tsoptions/declscompiler.go rename to tsc/internal/tsoptions/declarations_generated.go index 46fb42faee7c5..44d808108cd58 100644 --- a/tsc/internal/tsoptions/declscompiler.go +++ b/tsc/internal/tsoptions/declarations_generated.go @@ -1,21 +1,24 @@ +// Code generated by tools/scripts/tsc/generate-options.ts. DO NOT EDIT. + package tsoptions import ( - "reflect" "slices" + "github.com/microsoft/TypeScript/tsc/internal/collections" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/diagnostics" ) var OptionsDeclarations = slices.Concat(commonOptionsWithBuild, optionsForCompiler) +var BuildOpts = slices.Concat(commonOptionsWithBuild, OptionsForBuild) + var commonOptionsWithBuild = []*CommandLineOption{ - //******* commonOptionsWithBuild ******* { Name: "help", - ShortName: "h", Kind: CommandLineOptionTypeBoolean, + ShortName: "h", ShowInSimplifiedHelpView: true, IsCommandLineOnly: true, Category: diagnostics.Command_line_Options, @@ -24,16 +27,16 @@ var commonOptionsWithBuild = []*CommandLineOption{ }, { Name: "help", - ShortName: "?", Kind: CommandLineOptionTypeBoolean, + ShortName: "?", IsCommandLineOnly: true, Category: diagnostics.Command_line_Options, DefaultValueDescription: false, }, { Name: "watch", - ShortName: "w", Kind: CommandLineOptionTypeBoolean, + ShortName: "w", ShowInSimplifiedHelpView: true, IsCommandLineOnly: true, Category: diagnostics.Command_line_Options, @@ -106,7 +109,6 @@ var commonOptionsWithBuild = []*CommandLineOption{ Description: diagnostics.Emit_a_v8_CPU_profile_of_the_compiler_run_for_debugging, DefaultValueDescription: "profile.cpuprofile", }, - { Name: "generateTrace", Kind: CommandLineOptionTypeString, @@ -116,18 +118,18 @@ var commonOptionsWithBuild = []*CommandLineOption{ }, { Name: "incremental", - ShortName: "i", Kind: CommandLineOptionTypeBoolean, + ShortName: "i", Category: diagnostics.Projects, Description: diagnostics.Save_tsbuildinfo_files_to_allow_for_incremental_compilation_of_projects, transpileOptionValue: core.TSUnknown, DefaultValueDescription: diagnostics.X_false_unless_composite_is_set, }, + // Full emit is calculated separately, so this does not set affectsEmit. { - Name: "declaration", - ShortName: "d", - Kind: CommandLineOptionTypeBoolean, - // Not setting affectsEmit because we calculate this flag might not affect full emit + Name: "declaration", + Kind: CommandLineOptionTypeBoolean, + ShortName: "d", AffectsBuildInfo: true, ShowInSimplifiedHelpView: true, Category: diagnostics.Emit, @@ -135,20 +137,20 @@ var commonOptionsWithBuild = []*CommandLineOption{ Description: diagnostics.Generate_d_ts_files_from_TypeScript_and_JavaScript_files_in_your_project, DefaultValueDescription: diagnostics.X_false_unless_composite_is_set, }, + // Full emit is calculated separately, so this does not set affectsEmit. { - Name: "declarationMap", - Kind: CommandLineOptionTypeBoolean, - // Not setting affectsEmit because we calculate this flag might not affect full emit + Name: "declarationMap", + Kind: CommandLineOptionTypeBoolean, AffectsBuildInfo: true, ShowInSimplifiedHelpView: true, Category: diagnostics.Emit, DefaultValueDescription: false, Description: diagnostics.Create_sourcemaps_for_d_ts_files, }, + // Full emit is calculated separately, so this does not set affectsEmit. { - Name: "emitDeclarationOnly", - Kind: CommandLineOptionTypeBoolean, - // Not setting affectsEmit because we calculate this flag might not affect full emit + Name: "emitDeclarationOnly", + Kind: CommandLineOptionTypeBoolean, AffectsBuildInfo: true, ShowInSimplifiedHelpView: true, Category: diagnostics.Emit, @@ -156,25 +158,26 @@ var commonOptionsWithBuild = []*CommandLineOption{ transpileOptionValue: core.TSUnknown, DefaultValueDescription: false, }, + // Full emit is calculated separately, so this does not set affectsEmit. { - Name: "sourceMap", - Kind: CommandLineOptionTypeBoolean, - // Not setting affectsEmit because we calculate this flag might not affect full emit + Name: "sourceMap", + Kind: CommandLineOptionTypeBoolean, AffectsBuildInfo: true, ShowInSimplifiedHelpView: true, Category: diagnostics.Emit, DefaultValueDescription: false, Description: diagnostics.Create_source_map_files_for_emitted_JavaScript_files, }, + // Full emit is calculated separately, so this does not set affectsEmit. { - Name: "inlineSourceMap", - Kind: CommandLineOptionTypeBoolean, - // Not setting affectsEmit because we calculate this flag might not affect full emit + Name: "inlineSourceMap", + Kind: CommandLineOptionTypeBoolean, AffectsBuildInfo: true, Category: diagnostics.Emit, Description: diagnostics.Include_sourcemap_files_inside_the_emitted_JavaScript, DefaultValueDescription: false, }, + // The builder handles this specially so changing noCheck does not discard all diagnostics. { Name: "noCheck", Kind: CommandLineOptionTypeBoolean, @@ -183,7 +186,6 @@ var commonOptionsWithBuild = []*CommandLineOption{ Description: diagnostics.Disable_full_type_checking_only_critical_parse_and_emit_errors_will_be_reported, transpileOptionValue: core.TSTrue, DefaultValueDescription: false, - // Not setting affectsSemanticDiagnostics or affectsBuildInfo because we dont want all diagnostics to go away, its handled in builder }, { Name: "deduplicatePackages", @@ -221,11 +223,10 @@ var commonOptionsWithBuild = []*CommandLineOption{ DefaultValueDescription: diagnostics.Platform_specific, extraValidation: extraValidationLocale, }, - { Name: "quiet", - ShortName: "q", Kind: CommandLineOptionTypeBoolean, + ShortName: "q", Category: diagnostics.Command_line_Options, Description: diagnostics.Do_not_print_diagnostics, }, @@ -261,9 +262,6 @@ var commonOptionsWithBuild = []*CommandLineOption{ } var optionsForCompiler = []*CommandLineOption{ - //******* compilerOptions not common with --build ******* - - // CommandLine only options { Name: "all", Kind: CommandLineOptionTypeBoolean, @@ -274,8 +272,8 @@ var optionsForCompiler = []*CommandLineOption{ }, { Name: "version", - ShortName: "v", Kind: CommandLineOptionTypeBoolean, + ShortName: "v", ShowInSimplifiedHelpView: true, Category: diagnostics.Command_line_Options, Description: diagnostics.Print_the_compiler_s_version, @@ -291,8 +289,8 @@ var optionsForCompiler = []*CommandLineOption{ }, { Name: "project", - ShortName: "p", Kind: CommandLineOptionTypeString, + ShortName: "p", IsFilePath: true, ShowInSimplifiedHelpView: true, Category: diagnostics.Command_line_Options, @@ -324,13 +322,10 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Ignore_the_tsconfig_found_and_build_with_commandline_options_and_files, DefaultValueDescription: false, }, - - // Basic - // targetOptionDeclaration, { Name: "target", + Kind: CommandLineOptionTypeEnum, ShortName: "t", - Kind: CommandLineOptionTypeEnum, // targetOptionMap AffectsSourceFile: true, AffectsModuleResolution: true, AffectsEmit: true, @@ -340,12 +335,10 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Set_the_JavaScript_language_version_for_emitted_JavaScript_and_include_compatible_library_declarations, DefaultValueDescription: core.ScriptTargetLatestStandard, }, - - // moduleOptionDeclaration, { Name: "module", + Kind: CommandLineOptionTypeEnum, ShortName: "m", - Kind: CommandLineOptionTypeEnum, // moduleOptionMap AffectsModuleResolution: true, AffectsEmit: true, AffectsBuildInfo: true, @@ -355,13 +348,8 @@ var optionsForCompiler = []*CommandLineOption{ DefaultValueDescription: core.TSUnknown, }, { - Name: "lib", - Kind: CommandLineOptionTypeList, - // elements: &CommandLineOption{ - // name: "lib", - // kind: CommandLineOptionTypeEnum, // libMap, - // defaultValueDescription: core.TSUnknown, - // }, + Name: "lib", + Kind: CommandLineOptionTypeList, AffectsProgramStructure: true, ShowInSimplifiedHelpView: true, Category: diagnostics.Language_and_Environment, @@ -389,16 +377,14 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Enable_error_reporting_in_type_checked_JavaScript_files, DefaultValueDescription: false, }, + // JSX without this option is a semantic error; changing it must refresh semantic diagnostics. { - Name: "jsx", - Kind: CommandLineOptionTypeEnum, // jsxOptionMap, - AffectsSourceFile: true, - AffectsEmit: true, - AffectsBuildInfo: true, - AffectsModuleResolution: true, - // The checker emits an error when it sees JSX but this option is not set in compilerOptions. - // This is effectively a semantic error, so mark this option as affecting semantic diagnostics - // so we know to refresh errors when this option is changed. + Name: "jsx", + Kind: CommandLineOptionTypeEnum, + AffectsSourceFile: true, + AffectsEmit: true, + AffectsBuildInfo: true, + AffectsModuleResolution: true, AffectsSemanticDiagnostics: true, ShowInSimplifiedHelpView: true, Category: diagnostics.Language_and_Environment, @@ -440,9 +426,8 @@ var optionsForCompiler = []*CommandLineOption{ DefaultValueDescription: diagnostics.Computed_from_the_list_of_input_files, }, { - Name: "composite", - Kind: CommandLineOptionTypeBoolean, - // Not setting affectsEmit because we calculate this flag might not affect full emit + Name: "composite", + Kind: CommandLineOptionTypeBoolean, AffectsBuildInfo: true, IsTSConfigOnly: true, Category: diagnostics.Projects, @@ -534,15 +519,10 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Enable_lib_replacement, DefaultValueDescription: false, }, - - // Strict Type Checks - { - Name: "strict", - Kind: CommandLineOptionTypeBoolean, - // Though this affects semantic diagnostics, affectsSemanticDiagnostics is not set here - // The value of each strictFlag depends on own strictFlag value or this and never accessed directly. - // But we need to store `strict` in builf info, even though it won't be examined directly, so that the - // flags it controls (e.g. `strictNullChecks`) will be retrieved correctly + // Individual strict flags determine semantic diagnostics. Store strict in build info so their effective values can be recovered. + { + Name: "strict", + Kind: CommandLineOptionTypeBoolean, AffectsBuildInfo: true, ShowInSimplifiedHelpView: true, Category: diagnostics.Type_Checking, @@ -648,8 +628,6 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Ensure_types_are_ordered_stably_and_deterministically_across_compilations, DefaultValueDescription: true, }, - - // Additional Checks { Name: "noUnusedLocals", Kind: CommandLineOptionTypeBoolean, @@ -724,20 +702,9 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Enforces_using_indexed_accessors_for_keys_declared_using_an_indexed_type, DefaultValueDescription: false, }, - - // Module Resolution - { - Name: "moduleResolution", - Kind: CommandLineOptionTypeEnum, - // new Map(Object.entries({ - // // N.B. The first entry specifies the value shown in `tsc --init` - // node10: ModuleResolutionKind.Node10, - // node: ModuleResolutionKind.Node10, - // classic: ModuleResolutionKind.Classic, - // node16: ModuleResolutionKind.Node16, - // nodenext: ModuleResolutionKind.NodeNext, - // bundler: ModuleResolutionKind.Bundler, - // })), + { + Name: "moduleResolution", + Kind: CommandLineOptionTypeEnum, AffectsModuleResolution: true, Category: diagnostics.Modules, Description: diagnostics.Specify_how_TypeScript_looks_up_a_file_from_a_given_module_specifier, @@ -752,37 +719,30 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Specify_the_base_directory_to_resolve_non_relative_module_names, }, { - // this option can only be specified in tsconfig.json - // use type = object to copy the value as-is - Name: "paths", - Kind: CommandLineOptionTypeObject, - AffectsModuleResolution: true, - allowConfigDirTemplateSubstitution: true, - IsTSConfigOnly: true, - Category: diagnostics.Modules, - Description: diagnostics.Specify_a_set_of_entries_that_re_map_imports_to_additional_lookup_locations, - transpileOptionValue: core.TSUnknown, + Name: "paths", + Kind: CommandLineOptionTypeObject, + AffectsModuleResolution: true, + IsTSConfigOnly: true, + Category: diagnostics.Modules, + Description: diagnostics.Specify_a_set_of_entries_that_re_map_imports_to_additional_lookup_locations, + transpileOptionValue: core.TSUnknown, }, { - // this option can only be specified in tsconfig.json - // use type = object to copy the value as-is - Name: "rootDirs", - Kind: CommandLineOptionTypeList, - IsTSConfigOnly: true, - AffectsModuleResolution: true, - allowConfigDirTemplateSubstitution: true, - Category: diagnostics.Modules, - Description: diagnostics.Allow_multiple_folders_to_be_treated_as_one_when_resolving_modules, - transpileOptionValue: core.TSUnknown, - DefaultValueDescription: diagnostics.Computed_from_the_list_of_input_files, + Name: "rootDirs", + Kind: CommandLineOptionTypeList, + IsTSConfigOnly: true, + AffectsModuleResolution: true, + Category: diagnostics.Modules, + Description: diagnostics.Allow_multiple_folders_to_be_treated_as_one_when_resolving_modules, + transpileOptionValue: core.TSUnknown, + DefaultValueDescription: diagnostics.Computed_from_the_list_of_input_files, }, { - Name: "typeRoots", - Kind: CommandLineOptionTypeList, - AffectsModuleResolution: true, - allowConfigDirTemplateSubstitution: true, - Category: diagnostics.Modules, - Description: diagnostics.Specify_multiple_folders_that_act_like_Slashnode_modules_Slash_types, + Name: "typeRoots", + Kind: CommandLineOptionTypeList, + AffectsModuleResolution: true, + Category: diagnostics.Modules, + Description: diagnostics.Specify_multiple_folders_that_act_like_Slashnode_modules_Slash_types, }, { Name: "types", @@ -888,8 +848,6 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Check_side_effect_imports, DefaultValueDescription: true, }, - - // Source Maps { Name: "sourceRoot", Kind: CommandLineOptionTypeString, @@ -915,8 +873,6 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Include_source_code_in_the_sourcemaps_inside_the_emitted_JavaScript, DefaultValueDescription: false, }, - - // Experimental { Name: "experimentalDecorators", Kind: CommandLineOptionTypeBoolean, @@ -937,8 +893,6 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Emit_design_type_metadata_for_decorated_declarations_in_source_files, DefaultValueDescription: false, }, - - // Advanced { Name: "jsxFactory", Kind: CommandLineOptionTypeString, @@ -981,7 +935,6 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Enable_importing_files_with_any_extension_provided_a_declaration_file_is_present, DefaultValueDescription: false, }, - { Name: "reactNamespace", Kind: CommandLineOptionTypeString, @@ -991,10 +944,10 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Specify_the_object_invoked_for_createElement_This_only_applies_when_targeting_react_JSX_emit, DefaultValueDescription: "`React`", }, + // Store this in build info to determine whether library files need to be rechecked. { - Name: "skipDefaultLibCheck", - Kind: CommandLineOptionTypeBoolean, - // We need to store these to determine whether `lib` files need to be rechecked + Name: "skipDefaultLibCheck", + Kind: CommandLineOptionTypeBoolean, AffectsBuildInfo: true, Category: diagnostics.Completeness, Description: diagnostics.Skip_type_checking_d_ts_files_that_are_included_with_TypeScript, @@ -1011,7 +964,7 @@ var optionsForCompiler = []*CommandLineOption{ }, { Name: "newLine", - Kind: CommandLineOptionTypeEnum, // newLineOptionMap, + Kind: CommandLineOptionTypeEnum, AffectsEmit: true, AffectsBuildInfo: true, Category: diagnostics.Emit, @@ -1027,25 +980,23 @@ var optionsForCompiler = []*CommandLineOption{ Description: diagnostics.Disable_truncating_types_in_error_messages, DefaultValueDescription: false, }, + // Transpilation does not supply library source files, so noLib avoids reporting missing files. { Name: "noLib", Kind: CommandLineOptionTypeBoolean, Category: diagnostics.Language_and_Environment, AffectsProgramStructure: true, Description: diagnostics.Disable_including_any_library_files_including_the_default_lib_d_ts, - // We are not returning a sourceFile for lib file when asked by the program, - // so pass --noLib to avoid reporting a file not found error. transpileOptionValue: core.TSTrue, DefaultValueDescription: false, }, + // Transpilation does not resolve the full program, so noResolve avoids reporting missing files. { Name: "noResolve", Kind: CommandLineOptionTypeBoolean, AffectsModuleResolution: true, Category: diagnostics.Modules, Description: diagnostics.Disallow_import_s_require_s_or_reference_s_from_expanding_the_number_of_files_TypeScript_should_add_to_a_project, - // We are not doing a full typecheck, we are not resolving the whole context, - // so pass --noResolve to avoid reporting missing file errors. transpileOptionValue: core.TSTrue, DefaultValueDescription: false, }, @@ -1129,10 +1080,10 @@ var optionsForCompiler = []*CommandLineOption{ transpileOptionValue: core.TSUnknown, Description: diagnostics.Specify_the_output_directory_for_generated_declaration_files, }, + // Store this in build info to determine whether library files need to be rechecked. { - Name: "skipLibCheck", - Kind: CommandLineOptionTypeBoolean, - // We need to store these to determine whether `lib` files need to be rechecked + Name: "skipLibCheck", + Kind: CommandLineOptionTypeBoolean, AffectsBuildInfo: true, Category: diagnostics.Completeness, Description: diagnostics.Skip_type_checking_all_d_ts_files, @@ -1185,7 +1136,6 @@ var optionsForCompiler = []*CommandLineOption{ DefaultValueDescription: diagnostics.X_true_for_ES2022_and_above_including_ESNext, }, { - // A list of plugins to load in the language service Name: "plugins", Kind: CommandLineOptionTypeList, IsTSConfigOnly: true, @@ -1208,65 +1158,493 @@ var optionsForCompiler = []*CommandLineOption{ }, } -var optionsType = reflect.TypeFor[core.CompilerOptions]() +var OptionsForWatch = []*CommandLineOption{ + { + Name: "watchInterval", + Kind: CommandLineOptionTypeNumber, + Category: diagnostics.Watch_and_Build_Modes, + }, + { + Name: "watchFile", + Kind: CommandLineOptionTypeEnum, + Category: diagnostics.Watch_and_Build_Modes, + Description: diagnostics.Specify_how_the_TypeScript_watch_mode_works, + DefaultValueDescription: core.WatchFileKindUseFsEvents, + }, + { + Name: "watchDirectory", + Kind: CommandLineOptionTypeEnum, + Category: diagnostics.Watch_and_Build_Modes, + Description: diagnostics.Specify_how_directories_are_watched_on_systems_that_lack_recursive_file_watching_functionality, + DefaultValueDescription: core.WatchDirectoryKindUseFsEvents, + }, + { + Name: "fallbackPolling", + Kind: CommandLineOptionTypeEnum, + Category: diagnostics.Watch_and_Build_Modes, + Description: diagnostics.Specify_what_approach_the_watcher_should_use_if_the_system_runs_out_of_native_file_watchers, + DefaultValueDescription: core.PollingKindPriorityInterval, + }, + { + Name: "synchronousWatchDirectory", + Kind: CommandLineOptionTypeBoolean, + Category: diagnostics.Watch_and_Build_Modes, + Description: diagnostics.Synchronously_call_callbacks_and_update_the_state_of_directory_watchers_on_platforms_that_don_t_support_recursive_watching_natively, + DefaultValueDescription: false, + }, + { + Name: "excludeDirectories", + Kind: CommandLineOptionTypeList, + Category: diagnostics.Watch_and_Build_Modes, + Description: diagnostics.Remove_a_list_of_directories_from_the_watch_process, + }, + { + Name: "excludeFiles", + Kind: CommandLineOptionTypeList, + Category: diagnostics.Watch_and_Build_Modes, + Description: diagnostics.Remove_a_list_of_files_from_the_watch_mode_s_processing, + }, +} -func optionsHaveChanges(oldOptions *core.CompilerOptions, newOptions *core.CompilerOptions, declFilter func(*CommandLineOption) bool) bool { - if oldOptions == newOptions { - return false - } - if oldOptions == nil || newOptions == nil { - return true - } - oldOptionsValue := reflect.ValueOf(oldOptions).Elem() - return ForEachCompilerOptionValue(newOptions, declFilter, func(option *CommandLineOption, value reflect.Value, i int) bool { - newValue := value.Interface() - oldValue := oldOptionsValue.Field(i).Interface() - if option.strictFlag { - return oldOptions.GetStrictOptionValue(oldValue.(core.Tristate)) != newOptions.GetStrictOptionValue(newValue.(core.Tristate)) - } - if option.allowJsFlag { - return oldOptions.GetAllowJS() != newOptions.GetAllowJS() - } - return !reflect.DeepEqual(newValue, oldValue) - }) +var typeAcquisitionDecls = []*CommandLineOption{ + { + Name: "enable", + Kind: CommandLineOptionTypeBoolean, + DefaultValueDescription: false, + }, + { + Name: "include", + Kind: CommandLineOptionTypeList, + }, + { + Name: "exclude", + Kind: CommandLineOptionTypeList, + }, + { + Name: "disableFilenameBasedTypeAcquisition", + Kind: CommandLineOptionTypeBoolean, + DefaultValueDescription: false, + }, } -func ForEachCompilerOptionValue(options *core.CompilerOptions, declFilter func(*CommandLineOption) bool, fn func(option *CommandLineOption, value reflect.Value, i int) bool) bool { - optionsValue := reflect.ValueOf(options).Elem() - for i := range optionsValue.NumField() { - field := optionsType.Field(i) - if !field.IsExported() { - continue - } - if optionDeclaration := CommandLineCompilerOptionsMap.Get(field.Name); optionDeclaration != nil && declFilter(optionDeclaration) { - if fn(optionDeclaration, optionsValue.Field(i), i) { - return true - } - } - } - return false +var commandLineOptionElements = map[string]*CommandLineOption{ + "lib": { + Name: "lib", + Kind: CommandLineOptionTypeEnum, + DefaultValueDescription: core.TSUnknown, + }, + "rootDirs": { + Name: "rootDirs", + Kind: CommandLineOptionTypeString, + IsFilePath: true, + }, + "typeRoots": { + Name: "typeRoots", + Kind: CommandLineOptionTypeString, + IsFilePath: true, + }, + "types": { + Name: "types", + Kind: CommandLineOptionTypeString, + }, + "moduleSuffixes": { + Name: "moduleSuffixes", + Kind: CommandLineOptionTypeString, + }, + "customConditions": { + Name: "condition", + Kind: CommandLineOptionTypeString, + }, + "plugins": { + Name: "plugin", + Kind: CommandLineOptionTypeObject, + }, + "references": { + Name: "references", + Kind: CommandLineOptionTypeObject, + }, + "contentMappers": { + Name: "contentMappers", + Kind: CommandLineOptionTypeObject, + }, + "files": { + Name: "files", + Kind: CommandLineOptionTypeString, + }, + "include": { + Name: "include", + Kind: CommandLineOptionTypeString, + }, + "exclude": { + Name: "exclude", + Kind: CommandLineOptionTypeString, + }, + "extends": { + Name: "extends", + Kind: CommandLineOptionTypeString, + }, + "excludeDirectories": { + Name: "excludeDirectory", + Kind: CommandLineOptionTypeString, + IsFilePath: true, + extraValidation: extraValidationSpec, + }, + "excludeFiles": { + Name: "excludeFile", + Kind: CommandLineOptionTypeString, + IsFilePath: true, + extraValidation: extraValidationSpec, + }, + "libFiles": { + Name: "libFiles", + Kind: CommandLineOptionTypeString, + }, } -func CompilerOptionsAffectSemanticDiagnostics( - oldOptions *core.CompilerOptions, - newOptions *core.CompilerOptions, -) bool { - return optionsHaveChanges(oldOptions, newOptions, func(option *CommandLineOption) bool { - return option.AffectsSemanticDiagnostics - }) +var TscBuildOption = CommandLineOption{ + Name: "build", + Kind: CommandLineOptionTypeBoolean, + ShortName: "b", + ShowInSimplifiedHelpView: true, + Category: diagnostics.Command_line_Options, + Description: diagnostics.Build_one_or_more_projects_and_their_dependencies_if_out_of_date, + DefaultValueDescription: false, +} + +var OptionsForBuild = []*CommandLineOption{ + &TscBuildOption, + { + Name: "verbose", + Kind: CommandLineOptionTypeBoolean, + ShortName: "v", + Category: diagnostics.Command_line_Options, + Description: diagnostics.Enable_verbose_logging, + DefaultValueDescription: false, + }, + { + Name: "dry", + Kind: CommandLineOptionTypeBoolean, + ShortName: "d", + Category: diagnostics.Command_line_Options, + Description: diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean, + DefaultValueDescription: false, + }, + { + Name: "force", + Kind: CommandLineOptionTypeBoolean, + ShortName: "f", + Category: diagnostics.Command_line_Options, + Description: diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date, + DefaultValueDescription: false, + }, + { + Name: "clean", + Kind: CommandLineOptionTypeBoolean, + Category: diagnostics.Command_line_Options, + Description: diagnostics.Delete_the_outputs_of_all_projects, + DefaultValueDescription: false, + }, + { + Name: "builders", + Kind: CommandLineOptionTypeNumber, + Category: diagnostics.Command_line_Options, + Description: diagnostics.Set_the_number_of_projects_to_build_concurrently, + DefaultValueDescription: diagnostics.X_4_unless_singleThreaded_is_passed, + minValue: 1, + }, + { + Name: "stopBuildOnErrors", + Kind: CommandLineOptionTypeBoolean, + Category: diagnostics.Command_line_Options, + Description: diagnostics.Skip_building_downstream_projects_on_error_in_upstream_project, + DefaultValueDescription: false, + }, +} + +var compilerOptionsDeclaration = &CommandLineOption{ + Name: "compilerOptions", + Kind: CommandLineOptionTypeObject, + ElementOptions: CommandLineCompilerOptionsMap, +} + +var typeAcquisitionDeclaration = &CommandLineOption{ + Name: "typeAcquisition", + Kind: CommandLineOptionTypeObject, + ElementOptions: commandLineOptionsToMap(typeAcquisitionDecls), +} + +var extendsOptionDeclaration = &CommandLineOption{ + Name: "extends", + Kind: CommandLineOptionTypeListOrElement, + Category: diagnostics.File_Management, + ElementOptions: commandLineOptionsToMap([]*CommandLineOption{{ + Name: "extends", + Kind: CommandLineOptionTypeString, + }}), +} + +var compileOnSaveCommandLineOption = &CommandLineOption{ + Name: "compileOnSave", + Kind: CommandLineOptionTypeBoolean, + DefaultValueDescription: false, +} + +var tsconfigRootOptionsMap = &CommandLineOption{ + Name: "undefined", + Kind: CommandLineOptionTypeObject, + ElementOptions: commandLineOptionsToMap([]*CommandLineOption{ + compilerOptionsDeclaration, + typeAcquisitionDeclaration, + extendsOptionDeclaration, + { + Name: "references", + Kind: CommandLineOptionTypeList, + }, + { + Name: "contentMappers", + Kind: CommandLineOptionTypeList, + }, + { + Name: "files", + Kind: CommandLineOptionTypeList, + }, + { + Name: "include", + Kind: CommandLineOptionTypeList, + }, + { + Name: "exclude", + Kind: CommandLineOptionTypeList, + }, + compileOnSaveCommandLineOption, + }), +} + +var LibMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ + {Key: "es5", Value: "lib.es5.d.ts"}, + {Key: "es6", Value: "lib.es2015.d.ts"}, + {Key: "es2015", Value: "lib.es2015.d.ts"}, + {Key: "es7", Value: "lib.es2016.d.ts"}, + {Key: "es2016", Value: "lib.es2016.d.ts"}, + {Key: "es2017", Value: "lib.es2017.d.ts"}, + {Key: "es2018", Value: "lib.es2018.d.ts"}, + {Key: "es2019", Value: "lib.es2019.d.ts"}, + {Key: "es2020", Value: "lib.es2020.d.ts"}, + {Key: "es2021", Value: "lib.es2021.d.ts"}, + {Key: "es2022", Value: "lib.es2022.d.ts"}, + {Key: "es2023", Value: "lib.es2023.d.ts"}, + {Key: "es2024", Value: "lib.es2024.d.ts"}, + {Key: "es2025", Value: "lib.es2025.d.ts"}, + {Key: "esnext", Value: "lib.esnext.d.ts"}, + {Key: "dom", Value: "lib.dom.d.ts"}, + {Key: "dom.iterable", Value: "lib.dom.iterable.d.ts"}, + {Key: "dom.asynciterable", Value: "lib.dom.asynciterable.d.ts"}, + {Key: "webworker", Value: "lib.webworker.d.ts"}, + {Key: "webworker.importscripts", Value: "lib.webworker.importscripts.d.ts"}, + {Key: "webworker.iterable", Value: "lib.webworker.iterable.d.ts"}, + {Key: "webworker.asynciterable", Value: "lib.webworker.asynciterable.d.ts"}, + {Key: "scripthost", Value: "lib.scripthost.d.ts"}, + {Key: "es2015.core", Value: "lib.es2015.core.d.ts"}, + {Key: "es2015.collection", Value: "lib.es2015.collection.d.ts"}, + {Key: "es2015.generator", Value: "lib.es2015.generator.d.ts"}, + {Key: "es2015.iterable", Value: "lib.es2015.iterable.d.ts"}, + {Key: "es2015.promise", Value: "lib.es2015.promise.d.ts"}, + {Key: "es2015.proxy", Value: "lib.es2015.proxy.d.ts"}, + {Key: "es2015.reflect", Value: "lib.es2015.reflect.d.ts"}, + {Key: "es2015.symbol", Value: "lib.es2015.symbol.d.ts"}, + {Key: "es2015.symbol.wellknown", Value: "lib.es2015.symbol.wellknown.d.ts"}, + {Key: "es2016.array.include", Value: "lib.es2016.array.include.d.ts"}, + {Key: "es2016.intl", Value: "lib.es2016.intl.d.ts"}, + {Key: "es2017.arraybuffer", Value: "lib.es2017.arraybuffer.d.ts"}, + {Key: "es2017.date", Value: "lib.es2017.date.d.ts"}, + {Key: "es2017.object", Value: "lib.es2017.object.d.ts"}, + {Key: "es2017.sharedmemory", Value: "lib.es2017.sharedmemory.d.ts"}, + {Key: "es2017.string", Value: "lib.es2017.string.d.ts"}, + {Key: "es2017.intl", Value: "lib.es2017.intl.d.ts"}, + {Key: "es2017.typedarrays", Value: "lib.es2017.typedarrays.d.ts"}, + {Key: "es2018.asyncgenerator", Value: "lib.es2018.asyncgenerator.d.ts"}, + {Key: "es2018.asynciterable", Value: "lib.es2018.asynciterable.d.ts"}, + {Key: "es2018.intl", Value: "lib.es2018.intl.d.ts"}, + {Key: "es2018.promise", Value: "lib.es2018.promise.d.ts"}, + {Key: "es2018.regexp", Value: "lib.es2018.regexp.d.ts"}, + {Key: "es2019.array", Value: "lib.es2019.array.d.ts"}, + {Key: "es2019.object", Value: "lib.es2019.object.d.ts"}, + {Key: "es2019.string", Value: "lib.es2019.string.d.ts"}, + {Key: "es2019.symbol", Value: "lib.es2019.symbol.d.ts"}, + {Key: "es2019.intl", Value: "lib.es2019.intl.d.ts"}, + {Key: "es2020.bigint", Value: "lib.es2020.bigint.d.ts"}, + {Key: "es2020.date", Value: "lib.es2020.date.d.ts"}, + {Key: "es2020.promise", Value: "lib.es2020.promise.d.ts"}, + {Key: "es2020.sharedmemory", Value: "lib.es2020.sharedmemory.d.ts"}, + {Key: "es2020.string", Value: "lib.es2020.string.d.ts"}, + {Key: "es2020.symbol.wellknown", Value: "lib.es2020.symbol.wellknown.d.ts"}, + {Key: "es2020.intl", Value: "lib.es2020.intl.d.ts"}, + {Key: "es2020.number", Value: "lib.es2020.number.d.ts"}, + {Key: "es2021.promise", Value: "lib.es2021.promise.d.ts"}, + {Key: "es2021.string", Value: "lib.es2021.string.d.ts"}, + {Key: "es2021.weakref", Value: "lib.es2021.weakref.d.ts"}, + {Key: "es2021.intl", Value: "lib.es2021.intl.d.ts"}, + {Key: "es2022.array", Value: "lib.es2022.array.d.ts"}, + {Key: "es2022.error", Value: "lib.es2022.error.d.ts"}, + {Key: "es2022.intl", Value: "lib.es2022.intl.d.ts"}, + {Key: "es2022.object", Value: "lib.es2022.object.d.ts"}, + {Key: "es2022.string", Value: "lib.es2022.string.d.ts"}, + {Key: "es2022.regexp", Value: "lib.es2022.regexp.d.ts"}, + {Key: "es2023.array", Value: "lib.es2023.array.d.ts"}, + {Key: "es2023.collection", Value: "lib.es2023.collection.d.ts"}, + {Key: "es2023.intl", Value: "lib.es2023.intl.d.ts"}, + {Key: "es2024.arraybuffer", Value: "lib.es2024.arraybuffer.d.ts"}, + {Key: "es2024.collection", Value: "lib.es2024.collection.d.ts"}, + {Key: "es2024.object", Value: "lib.es2024.object.d.ts"}, + {Key: "es2024.promise", Value: "lib.es2024.promise.d.ts"}, + {Key: "es2024.regexp", Value: "lib.es2024.regexp.d.ts"}, + {Key: "es2024.sharedmemory", Value: "lib.es2024.sharedmemory.d.ts"}, + {Key: "es2024.string", Value: "lib.es2024.string.d.ts"}, + {Key: "es2025.collection", Value: "lib.es2025.collection.d.ts"}, + {Key: "es2025.float16", Value: "lib.es2025.float16.d.ts"}, + {Key: "es2025.intl", Value: "lib.es2025.intl.d.ts"}, + {Key: "es2025.iterator", Value: "lib.es2025.iterator.d.ts"}, + {Key: "es2025.promise", Value: "lib.es2025.promise.d.ts"}, + {Key: "es2025.regexp", Value: "lib.es2025.regexp.d.ts"}, + {Key: "esnext.asynciterable", Value: "lib.es2018.asynciterable.d.ts"}, + {Key: "esnext.symbol", Value: "lib.es2019.symbol.d.ts"}, + {Key: "esnext.bigint", Value: "lib.es2020.bigint.d.ts"}, + {Key: "esnext.weakref", Value: "lib.es2021.weakref.d.ts"}, + {Key: "esnext.object", Value: "lib.es2024.object.d.ts"}, + {Key: "esnext.regexp", Value: "lib.es2024.regexp.d.ts"}, + {Key: "esnext.string", Value: "lib.es2024.string.d.ts"}, + {Key: "esnext.float16", Value: "lib.es2025.float16.d.ts"}, + {Key: "esnext.iterator", Value: "lib.es2025.iterator.d.ts"}, + {Key: "esnext.promise", Value: "lib.es2025.promise.d.ts"}, + {Key: "esnext.array", Value: "lib.esnext.array.d.ts"}, + {Key: "esnext.collection", Value: "lib.esnext.collection.d.ts"}, + {Key: "esnext.date", Value: "lib.esnext.date.d.ts"}, + {Key: "esnext.decorators", Value: "lib.esnext.decorators.d.ts"}, + {Key: "esnext.disposable", Value: "lib.esnext.disposable.d.ts"}, + {Key: "esnext.error", Value: "lib.esnext.error.d.ts"}, + {Key: "esnext.intl", Value: "lib.esnext.intl.d.ts"}, + {Key: "esnext.sharedmemory", Value: "lib.esnext.sharedmemory.d.ts"}, + {Key: "esnext.temporal", Value: "lib.esnext.temporal.d.ts"}, + {Key: "esnext.typedarrays", Value: "lib.esnext.typedarrays.d.ts"}, + {Key: "decorators", Value: "lib.decorators.d.ts"}, + {Key: "decorators.legacy", Value: "lib.decorators.legacy.d.ts"}, +}) + +var moduleResolutionOptionMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ + {Key: "node16", Value: core.ModuleResolutionKindNode16}, + {Key: "nodenext", Value: core.ModuleResolutionKindNodeNext}, + {Key: "bundler", Value: core.ModuleResolutionKindBundler}, + {Key: "classic", Value: core.ModuleResolutionKindClassic}, + {Key: "node", Value: core.ModuleResolutionKindNode10}, + {Key: "node10", Value: core.ModuleResolutionKindNode10}, +}) + +var moduleOptionMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ + {Key: "commonjs", Value: core.ModuleKindCommonJS}, + {Key: "amd", Value: core.ModuleKindAMD}, + {Key: "system", Value: core.ModuleKindSystem}, + {Key: "umd", Value: core.ModuleKindUMD}, + {Key: "es6", Value: core.ModuleKindES2015}, + {Key: "es2015", Value: core.ModuleKindES2015}, + {Key: "es2020", Value: core.ModuleKindES2020}, + {Key: "es2022", Value: core.ModuleKindES2022}, + {Key: "esnext", Value: core.ModuleKindESNext}, + {Key: "node16", Value: core.ModuleKindNode16}, + {Key: "node18", Value: core.ModuleKindNode18}, + {Key: "node20", Value: core.ModuleKindNode20}, + {Key: "nodenext", Value: core.ModuleKindNodeNext}, + {Key: "preserve", Value: core.ModuleKindPreserve}, +}) + +var targetOptionMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ + {Key: "es5", Value: core.ScriptTargetES5}, + {Key: "es6", Value: core.ScriptTargetES2015}, + {Key: "es2015", Value: core.ScriptTargetES2015}, + {Key: "es2016", Value: core.ScriptTargetES2016}, + {Key: "es2017", Value: core.ScriptTargetES2017}, + {Key: "es2018", Value: core.ScriptTargetES2018}, + {Key: "es2019", Value: core.ScriptTargetES2019}, + {Key: "es2020", Value: core.ScriptTargetES2020}, + {Key: "es2021", Value: core.ScriptTargetES2021}, + {Key: "es2022", Value: core.ScriptTargetES2022}, + {Key: "es2023", Value: core.ScriptTargetES2023}, + {Key: "es2024", Value: core.ScriptTargetES2024}, + {Key: "es2025", Value: core.ScriptTargetES2025}, + {Key: "esnext", Value: core.ScriptTargetESNext}, +}) + +var moduleDetectionOptionMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ + {Key: "auto", Value: core.ModuleDetectionKindAuto}, + {Key: "legacy", Value: core.ModuleDetectionKindLegacy}, + {Key: "force", Value: core.ModuleDetectionKindForce}, +}) + +var jsxOptionMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ + {Key: "preserve", Value: core.JsxEmitPreserve}, + {Key: "react-native", Value: core.JsxEmitReactNative}, + {Key: "react-jsx", Value: core.JsxEmitReactJSX}, + {Key: "react-jsxdev", Value: core.JsxEmitReactJSXDev}, + {Key: "react", Value: core.JsxEmitReact}, +}) + +var newLineOptionMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ + {Key: "crlf", Value: core.NewLineKindCRLF}, + {Key: "lf", Value: core.NewLineKindLF}, +}) + +var watchFileEnumMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ + {Key: "fixedpollinginterval", Value: core.WatchFileKindFixedPollingInterval}, + {Key: "prioritypollinginterval", Value: core.WatchFileKindPriorityPollingInterval}, + {Key: "dynamicprioritypolling", Value: core.WatchFileKindDynamicPriorityPolling}, + {Key: "fixedchunksizepolling", Value: core.WatchFileKindFixedChunkSizePolling}, + {Key: "usefsevents", Value: core.WatchFileKindUseFsEvents}, + {Key: "usefseventsonparentdirectory", Value: core.WatchFileKindUseFsEventsOnParentDirectory}, +}) + +var watchDirectoryEnumMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ + {Key: "usefsevents", Value: core.WatchDirectoryKindUseFsEvents}, + {Key: "fixedpollinginterval", Value: core.WatchDirectoryKindFixedPollingInterval}, + {Key: "dynamicprioritypolling", Value: core.WatchDirectoryKindDynamicPriorityPolling}, + {Key: "fixedchunksizepolling", Value: core.WatchDirectoryKindFixedChunkSizePolling}, +}) + +var fallbackEnumMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ + {Key: "fixedinterval", Value: core.PollingKindFixedInterval}, + {Key: "priorityinterval", Value: core.PollingKindPriorityInterval}, + {Key: "dynamicpriority", Value: core.PollingKindDynamicPriority}, + {Key: "fixedchunksize", Value: core.PollingKindFixedChunkSize}, +}) + +var commandLineOptionEnumMap = map[string]*collections.OrderedMap[string, any]{ + "lib": LibMap, + "moduleResolution": moduleResolutionOptionMap, + "module": moduleOptionMap, + "target": targetOptionMap, + "moduleDetection": moduleDetectionOptionMap, + "jsx": jsxOptionMap, + "newLine": newLineOptionMap, + "watchFile": watchFileEnumMap, + "watchDirectory": watchDirectoryEnumMap, + "fallbackPolling": fallbackEnumMap, } -func CompilerOptionsAffectDeclarationPath( - oldOptions *core.CompilerOptions, - newOptions *core.CompilerOptions, -) bool { - return optionsHaveChanges(oldOptions, newOptions, func(option *CommandLineOption) bool { - return option.AffectsDeclarationPath - }) +var commandLineOptionDeprecated = map[string]*collections.Set[string]{ + "moduleResolution": collections.NewSetFromItems("node", "classic", "node10"), + "module": collections.NewSetFromItems("none", "amd", "system", "umd"), + "target": collections.NewSetFromItems("es5"), } -func CompilerOptionsAffectEmit(oldOptions *core.CompilerOptions, newOptions *core.CompilerOptions) bool { - return optionsHaveChanges(oldOptions, newOptions, func(option *CommandLineOption) bool { - return option.AffectsEmit - }) +var targetToLibMap = map[core.ScriptTarget]string{ + core.ScriptTargetESNext: "lib.esnext.full.d.ts", + core.ScriptTargetES2025: "lib.es2025.full.d.ts", + core.ScriptTargetES2024: "lib.es2024.full.d.ts", + core.ScriptTargetES2023: "lib.es2023.full.d.ts", + core.ScriptTargetES2022: "lib.es2022.full.d.ts", + core.ScriptTargetES2021: "lib.es2021.full.d.ts", + core.ScriptTargetES2020: "lib.es2020.full.d.ts", + core.ScriptTargetES2019: "lib.es2019.full.d.ts", + core.ScriptTargetES2018: "lib.es2018.full.d.ts", + core.ScriptTargetES2017: "lib.es2017.full.d.ts", + core.ScriptTargetES2016: "lib.es2016.full.d.ts", + core.ScriptTargetES2015: "lib.es6.d.ts", // Use lib.es6.d.ts for compatibility rather than lib.es2015.full.d.ts. } diff --git a/tsc/internal/tsoptions/declsbuild.go b/tsc/internal/tsoptions/declsbuild.go deleted file mode 100644 index fa48cd16a592f..0000000000000 --- a/tsc/internal/tsoptions/declsbuild.go +++ /dev/null @@ -1,69 +0,0 @@ -package tsoptions - -import ( - "slices" - - "github.com/microsoft/TypeScript/tsc/internal/diagnostics" -) - -var TscBuildOption = CommandLineOption{ - Name: "build", - Kind: "boolean", - ShortName: "b", - ShowInSimplifiedHelpView: true, - Category: diagnostics.Command_line_Options, - Description: diagnostics.Build_one_or_more_projects_and_their_dependencies_if_out_of_date, - DefaultValueDescription: false, -} - -var OptionsForBuild = []*CommandLineOption{ - &TscBuildOption, - { - Name: "verbose", - ShortName: "v", - Category: diagnostics.Command_line_Options, - Description: diagnostics.Enable_verbose_logging, - Kind: "boolean", - DefaultValueDescription: false, - }, - { - Name: "dry", - ShortName: "d", - Category: diagnostics.Command_line_Options, - Description: diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean, - Kind: "boolean", - DefaultValueDescription: false, - }, - { - Name: "force", - ShortName: "f", - Category: diagnostics.Command_line_Options, - Description: diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date, - Kind: "boolean", - DefaultValueDescription: false, - }, - { - Name: "clean", - Category: diagnostics.Command_line_Options, - Description: diagnostics.Delete_the_outputs_of_all_projects, - Kind: "boolean", - DefaultValueDescription: false, - }, - { - Name: "builders", - Kind: CommandLineOptionTypeNumber, - Category: diagnostics.Command_line_Options, - Description: diagnostics.Set_the_number_of_projects_to_build_concurrently, - DefaultValueDescription: diagnostics.X_4_unless_singleThreaded_is_passed, - minValue: 1, - }, - { - Name: "stopBuildOnErrors", - Category: diagnostics.Command_line_Options, - Description: diagnostics.Skip_building_downstream_projects_on_error_in_upstream_project, - Kind: "boolean", - DefaultValueDescription: false, - }, -} - -var BuildOpts = slices.Concat(commonOptionsWithBuild, OptionsForBuild) diff --git a/tsc/internal/tsoptions/declstypeacquisition.go b/tsc/internal/tsoptions/declstypeacquisition.go deleted file mode 100644 index fe7ceb66c7ec5..0000000000000 --- a/tsc/internal/tsoptions/declstypeacquisition.go +++ /dev/null @@ -1,29 +0,0 @@ -package tsoptions - -var typeAcquisitionDeclaration = &CommandLineOption{ - Name: "typeAcquisition", - Kind: CommandLineOptionTypeObject, - ElementOptions: commandLineOptionsToMap(typeAcquisitionDecls), -} - -// Do not delete this without updating the website's tsconfig generation. -var typeAcquisitionDecls = []*CommandLineOption{ - { - Name: "enable", - Kind: CommandLineOptionTypeBoolean, - DefaultValueDescription: false, - }, - { - Name: "include", - Kind: CommandLineOptionTypeList, - }, - { - Name: "exclude", - Kind: CommandLineOptionTypeList, - }, - { - Name: "disableFilenameBasedTypeAcquisition", - Kind: CommandLineOptionTypeBoolean, - DefaultValueDescription: false, - }, -} diff --git a/tsc/internal/tsoptions/declswatch.go b/tsc/internal/tsoptions/declswatch.go deleted file mode 100644 index aef18639faf7a..0000000000000 --- a/tsc/internal/tsoptions/declswatch.go +++ /dev/null @@ -1,88 +0,0 @@ -package tsoptions - -import ( - "github.com/microsoft/TypeScript/tsc/internal/core" - "github.com/microsoft/TypeScript/tsc/internal/diagnostics" -) - -var OptionsForWatch = []*CommandLineOption{ - { - Name: "watchInterval", - Kind: CommandLineOptionTypeNumber, - Category: diagnostics.Watch_and_Build_Modes, - }, - { - Name: "watchFile", - Kind: CommandLineOptionTypeEnum, - // new Map(Object.entries({ - // fixedpollinginterval: WatchFileKind.FixedPollingInterval, - // prioritypollinginterval: WatchFileKind.PriorityPollingInterval, - // dynamicprioritypolling: WatchFileKind.DynamicPriorityPolling, - // fixedchunksizepolling: WatchFileKind.FixedChunkSizePolling, - // usefsevents: WatchFileKind.UseFsEvents, - // usefseventsonparentdirectory: WatchFileKind.UseFsEventsOnParentDirectory, - // })), - Category: diagnostics.Watch_and_Build_Modes, - Description: diagnostics.Specify_how_the_TypeScript_watch_mode_works, - DefaultValueDescription: core.WatchFileKindUseFsEvents, - }, - { - Name: "watchDirectory", - Kind: CommandLineOptionTypeEnum, - // new Map(Object.entries({ - // usefsevents: WatchDirectoryKind.UseFsEvents, - // fixedpollinginterval: WatchDirectoryKind.FixedPollingInterval, - // dynamicprioritypolling: WatchDirectoryKind.DynamicPriorityPolling, - // fixedchunksizepolling: WatchDirectoryKind.FixedChunkSizePolling, - // })), - Category: diagnostics.Watch_and_Build_Modes, - Description: diagnostics.Specify_how_directories_are_watched_on_systems_that_lack_recursive_file_watching_functionality, - DefaultValueDescription: core.WatchDirectoryKindUseFsEvents, - }, - { - Name: "fallbackPolling", - Kind: CommandLineOptionTypeEnum, - // new Map(Object.entries({ - // fixedinterval: PollingWatchKind.FixedInterval, - // priorityinterval: PollingWatchKind.PriorityInterval, - // dynamicpriority: PollingWatchKind.DynamicPriority, - // fixedchunksize: PollingWatchKind.FixedChunkSize, - // })), - Category: diagnostics.Watch_and_Build_Modes, - Description: diagnostics.Specify_what_approach_the_watcher_should_use_if_the_system_runs_out_of_native_file_watchers, - DefaultValueDescription: core.PollingKindPriorityInterval, - }, - { - Name: "synchronousWatchDirectory", - Kind: CommandLineOptionTypeBoolean, - Category: diagnostics.Watch_and_Build_Modes, - Description: diagnostics.Synchronously_call_callbacks_and_update_the_state_of_directory_watchers_on_platforms_that_don_t_support_recursive_watching_natively, - DefaultValueDescription: false, - }, - { - Name: "excludeDirectories", - Kind: CommandLineOptionTypeList, - // element: { - // Name: "excludeDirectory", - // Kind: "string", - // isFilePath: true, - // extraValidation: specToDiagnostic, - // }, - allowConfigDirTemplateSubstitution: true, - Category: diagnostics.Watch_and_Build_Modes, - Description: diagnostics.Remove_a_list_of_directories_from_the_watch_process, - }, - { - Name: "excludeFiles", - Kind: CommandLineOptionTypeList, - // element: { - // Name: "excludeFile", - // Kind: "string", - // isFilePath: true, - // extraValidation: specToDiagnostic, - // }, - allowConfigDirTemplateSubstitution: true, - Category: diagnostics.Watch_and_Build_Modes, - Description: diagnostics.Remove_a_list_of_files_from_the_watch_mode_s_processing, - }, -} diff --git a/tsc/internal/tsoptions/enummaps.go b/tsc/internal/tsoptions/enummaps.go index 3bf67a8640675..47548032da0a4 100644 --- a/tsc/internal/tsoptions/enummaps.go +++ b/tsc/internal/tsoptions/enummaps.go @@ -8,122 +8,6 @@ import ( "github.com/microsoft/TypeScript/tsc/internal/tspath" ) -var LibMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ - // JavaScript only - {Key: "es5", Value: "lib.es5.d.ts"}, - {Key: "es6", Value: "lib.es2015.d.ts"}, - {Key: "es2015", Value: "lib.es2015.d.ts"}, - {Key: "es7", Value: "lib.es2016.d.ts"}, - {Key: "es2016", Value: "lib.es2016.d.ts"}, - {Key: "es2017", Value: "lib.es2017.d.ts"}, - {Key: "es2018", Value: "lib.es2018.d.ts"}, - {Key: "es2019", Value: "lib.es2019.d.ts"}, - {Key: "es2020", Value: "lib.es2020.d.ts"}, - {Key: "es2021", Value: "lib.es2021.d.ts"}, - {Key: "es2022", Value: "lib.es2022.d.ts"}, - {Key: "es2023", Value: "lib.es2023.d.ts"}, - {Key: "es2024", Value: "lib.es2024.d.ts"}, - {Key: "es2025", Value: "lib.es2025.d.ts"}, - {Key: "esnext", Value: "lib.esnext.d.ts"}, - // Host only - {Key: "dom", Value: "lib.dom.d.ts"}, - {Key: "dom.iterable", Value: "lib.dom.iterable.d.ts"}, - {Key: "dom.asynciterable", Value: "lib.dom.asynciterable.d.ts"}, - {Key: "webworker", Value: "lib.webworker.d.ts"}, - {Key: "webworker.importscripts", Value: "lib.webworker.importscripts.d.ts"}, - {Key: "webworker.iterable", Value: "lib.webworker.iterable.d.ts"}, - {Key: "webworker.asynciterable", Value: "lib.webworker.asynciterable.d.ts"}, - {Key: "scripthost", Value: "lib.scripthost.d.ts"}, - // ES2015 and later By-feature options - {Key: "es2015.core", Value: "lib.es2015.core.d.ts"}, - {Key: "es2015.collection", Value: "lib.es2015.collection.d.ts"}, - {Key: "es2015.generator", Value: "lib.es2015.generator.d.ts"}, - {Key: "es2015.iterable", Value: "lib.es2015.iterable.d.ts"}, - {Key: "es2015.promise", Value: "lib.es2015.promise.d.ts"}, - {Key: "es2015.proxy", Value: "lib.es2015.proxy.d.ts"}, - {Key: "es2015.reflect", Value: "lib.es2015.reflect.d.ts"}, - {Key: "es2015.symbol", Value: "lib.es2015.symbol.d.ts"}, - {Key: "es2015.symbol.wellknown", Value: "lib.es2015.symbol.wellknown.d.ts"}, - {Key: "es2016.array.include", Value: "lib.es2016.array.include.d.ts"}, - {Key: "es2016.intl", Value: "lib.es2016.intl.d.ts"}, - {Key: "es2017.arraybuffer", Value: "lib.es2017.arraybuffer.d.ts"}, - {Key: "es2017.date", Value: "lib.es2017.date.d.ts"}, - {Key: "es2017.object", Value: "lib.es2017.object.d.ts"}, - {Key: "es2017.sharedmemory", Value: "lib.es2017.sharedmemory.d.ts"}, - {Key: "es2017.string", Value: "lib.es2017.string.d.ts"}, - {Key: "es2017.intl", Value: "lib.es2017.intl.d.ts"}, - {Key: "es2017.typedarrays", Value: "lib.es2017.typedarrays.d.ts"}, - {Key: "es2018.asyncgenerator", Value: "lib.es2018.asyncgenerator.d.ts"}, - {Key: "es2018.asynciterable", Value: "lib.es2018.asynciterable.d.ts"}, - {Key: "es2018.intl", Value: "lib.es2018.intl.d.ts"}, - {Key: "es2018.promise", Value: "lib.es2018.promise.d.ts"}, - {Key: "es2018.regexp", Value: "lib.es2018.regexp.d.ts"}, - {Key: "es2019.array", Value: "lib.es2019.array.d.ts"}, - {Key: "es2019.object", Value: "lib.es2019.object.d.ts"}, - {Key: "es2019.string", Value: "lib.es2019.string.d.ts"}, - {Key: "es2019.symbol", Value: "lib.es2019.symbol.d.ts"}, - {Key: "es2019.intl", Value: "lib.es2019.intl.d.ts"}, - {Key: "es2020.bigint", Value: "lib.es2020.bigint.d.ts"}, - {Key: "es2020.date", Value: "lib.es2020.date.d.ts"}, - {Key: "es2020.promise", Value: "lib.es2020.promise.d.ts"}, - {Key: "es2020.sharedmemory", Value: "lib.es2020.sharedmemory.d.ts"}, - {Key: "es2020.string", Value: "lib.es2020.string.d.ts"}, - {Key: "es2020.symbol.wellknown", Value: "lib.es2020.symbol.wellknown.d.ts"}, - {Key: "es2020.intl", Value: "lib.es2020.intl.d.ts"}, - {Key: "es2020.number", Value: "lib.es2020.number.d.ts"}, - {Key: "es2021.promise", Value: "lib.es2021.promise.d.ts"}, - {Key: "es2021.string", Value: "lib.es2021.string.d.ts"}, - {Key: "es2021.weakref", Value: "lib.es2021.weakref.d.ts"}, - {Key: "es2021.intl", Value: "lib.es2021.intl.d.ts"}, - {Key: "es2022.array", Value: "lib.es2022.array.d.ts"}, - {Key: "es2022.error", Value: "lib.es2022.error.d.ts"}, - {Key: "es2022.intl", Value: "lib.es2022.intl.d.ts"}, - {Key: "es2022.object", Value: "lib.es2022.object.d.ts"}, - {Key: "es2022.string", Value: "lib.es2022.string.d.ts"}, - {Key: "es2022.regexp", Value: "lib.es2022.regexp.d.ts"}, - {Key: "es2023.array", Value: "lib.es2023.array.d.ts"}, - {Key: "es2023.collection", Value: "lib.es2023.collection.d.ts"}, - {Key: "es2023.intl", Value: "lib.es2023.intl.d.ts"}, - {Key: "es2024.arraybuffer", Value: "lib.es2024.arraybuffer.d.ts"}, - {Key: "es2024.collection", Value: "lib.es2024.collection.d.ts"}, - {Key: "es2024.object", Value: "lib.es2024.object.d.ts"}, - {Key: "es2024.promise", Value: "lib.es2024.promise.d.ts"}, - {Key: "es2024.regexp", Value: "lib.es2024.regexp.d.ts"}, - {Key: "es2024.sharedmemory", Value: "lib.es2024.sharedmemory.d.ts"}, - {Key: "es2024.string", Value: "lib.es2024.string.d.ts"}, - {Key: "es2025.collection", Value: "lib.es2025.collection.d.ts"}, - {Key: "es2025.float16", Value: "lib.es2025.float16.d.ts"}, - {Key: "es2025.intl", Value: "lib.es2025.intl.d.ts"}, - {Key: "es2025.iterator", Value: "lib.es2025.iterator.d.ts"}, - {Key: "es2025.promise", Value: "lib.es2025.promise.d.ts"}, - {Key: "es2025.regexp", Value: "lib.es2025.regexp.d.ts"}, - // Fallback for backward compatibility - {Key: "esnext.asynciterable", Value: "lib.es2018.asynciterable.d.ts"}, - {Key: "esnext.symbol", Value: "lib.es2019.symbol.d.ts"}, - {Key: "esnext.bigint", Value: "lib.es2020.bigint.d.ts"}, - {Key: "esnext.weakref", Value: "lib.es2021.weakref.d.ts"}, - {Key: "esnext.object", Value: "lib.es2024.object.d.ts"}, - {Key: "esnext.regexp", Value: "lib.es2024.regexp.d.ts"}, - {Key: "esnext.string", Value: "lib.es2024.string.d.ts"}, - {Key: "esnext.float16", Value: "lib.es2025.float16.d.ts"}, - {Key: "esnext.iterator", Value: "lib.es2025.iterator.d.ts"}, - {Key: "esnext.promise", Value: "lib.es2025.promise.d.ts"}, - // ESNext By-feature options - {Key: "esnext.array", Value: "lib.esnext.array.d.ts"}, - {Key: "esnext.collection", Value: "lib.esnext.collection.d.ts"}, - {Key: "esnext.date", Value: "lib.esnext.date.d.ts"}, - {Key: "esnext.decorators", Value: "lib.esnext.decorators.d.ts"}, - {Key: "esnext.disposable", Value: "lib.esnext.disposable.d.ts"}, - {Key: "esnext.error", Value: "lib.esnext.error.d.ts"}, - {Key: "esnext.intl", Value: "lib.esnext.intl.d.ts"}, - {Key: "esnext.sharedmemory", Value: "lib.esnext.sharedmemory.d.ts"}, - {Key: "esnext.temporal", Value: "lib.esnext.temporal.d.ts"}, - {Key: "esnext.typedarrays", Value: "lib.esnext.typedarrays.d.ts"}, - // Decorators - {Key: "decorators", Value: "lib.decorators.d.ts"}, - {Key: "decorators.legacy", Value: "lib.decorators.legacy.d.ts"}, -}) - var ( Libs = slices.Collect(LibMap.Keys()) LibFilesSet = collections.NewSetFromItems(core.Map(slices.Collect(LibMap.Values()), func(s any) string { return s.(string) })...) @@ -142,83 +26,6 @@ func GetLibFileName(libName string) (string, bool) { return lib.(string), true } -var moduleResolutionOptionMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ - {Key: "node16", Value: core.ModuleResolutionKindNode16}, - {Key: "nodenext", Value: core.ModuleResolutionKindNodeNext}, - {Key: "bundler", Value: core.ModuleResolutionKindBundler}, - {Key: "classic", Value: core.ModuleResolutionKindClassic}, - {Key: "node", Value: core.ModuleResolutionKindNode10}, - {Key: "node10", Value: core.ModuleResolutionKindNode10}, -}) - -var targetOptionMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ - {Key: "es5", Value: core.ScriptTargetES5}, - {Key: "es6", Value: core.ScriptTargetES2015}, - {Key: "es2015", Value: core.ScriptTargetES2015}, - {Key: "es2016", Value: core.ScriptTargetES2016}, - {Key: "es2017", Value: core.ScriptTargetES2017}, - {Key: "es2018", Value: core.ScriptTargetES2018}, - {Key: "es2019", Value: core.ScriptTargetES2019}, - {Key: "es2020", Value: core.ScriptTargetES2020}, - {Key: "es2021", Value: core.ScriptTargetES2021}, - {Key: "es2022", Value: core.ScriptTargetES2022}, - {Key: "es2023", Value: core.ScriptTargetES2023}, - {Key: "es2024", Value: core.ScriptTargetES2024}, - {Key: "es2025", Value: core.ScriptTargetES2025}, - {Key: "esnext", Value: core.ScriptTargetESNext}, -}) - -var moduleOptionMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ - {Key: "commonjs", Value: core.ModuleKindCommonJS}, - {Key: "amd", Value: core.ModuleKindAMD}, - {Key: "system", Value: core.ModuleKindSystem}, - {Key: "umd", Value: core.ModuleKindUMD}, - {Key: "es6", Value: core.ModuleKindES2015}, - {Key: "es2015", Value: core.ModuleKindES2015}, - {Key: "es2020", Value: core.ModuleKindES2020}, - {Key: "es2022", Value: core.ModuleKindES2022}, - {Key: "esnext", Value: core.ModuleKindESNext}, - {Key: "node16", Value: core.ModuleKindNode16}, - {Key: "node18", Value: core.ModuleKindNode18}, - {Key: "node20", Value: core.ModuleKindNode20}, - {Key: "nodenext", Value: core.ModuleKindNodeNext}, - {Key: "preserve", Value: core.ModuleKindPreserve}, -}) - -var moduleDetectionOptionMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ - {Key: "auto", Value: core.ModuleDetectionKindAuto}, - {Key: "legacy", Value: core.ModuleDetectionKindLegacy}, - {Key: "force", Value: core.ModuleDetectionKindForce}, -}) - -var jsxOptionMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ - {Key: "preserve", Value: core.JsxEmitPreserve}, - {Key: "react-native", Value: core.JsxEmitReactNative}, - {Key: "react-jsx", Value: core.JsxEmitReactJSX}, - {Key: "react-jsxdev", Value: core.JsxEmitReactJSXDev}, - {Key: "react", Value: core.JsxEmitReact}, -}) - -var newLineOptionMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ - {Key: "crlf", Value: core.NewLineKindCRLF}, - {Key: "lf", Value: core.NewLineKindLF}, -}) - -var targetToLibMap = map[core.ScriptTarget]string{ - core.ScriptTargetESNext: "lib.esnext.full.d.ts", - core.ScriptTargetES2025: "lib.es2025.full.d.ts", - core.ScriptTargetES2024: "lib.es2024.full.d.ts", - core.ScriptTargetES2023: "lib.es2023.full.d.ts", - core.ScriptTargetES2022: "lib.es2022.full.d.ts", - core.ScriptTargetES2021: "lib.es2021.full.d.ts", - core.ScriptTargetES2020: "lib.es2020.full.d.ts", - core.ScriptTargetES2019: "lib.es2019.full.d.ts", - core.ScriptTargetES2018: "lib.es2018.full.d.ts", - core.ScriptTargetES2017: "lib.es2017.full.d.ts", - core.ScriptTargetES2016: "lib.es2016.full.d.ts", - core.ScriptTargetES2015: "lib.es6.d.ts", // We don't use lib.es2015.full.d.ts due to breaking change. -} - func TargetToLibMap() map[core.ScriptTarget]string { return targetToLibMap } @@ -230,26 +37,3 @@ func GetDefaultLibFileName(options *core.CompilerOptions) string { } return name } - -var watchFileEnumMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ - {Key: "fixedpollinginterval", Value: core.WatchFileKindFixedPollingInterval}, - {Key: "prioritypollinginterval", Value: core.WatchFileKindPriorityPollingInterval}, - {Key: "dynamicprioritypolling", Value: core.WatchFileKindDynamicPriorityPolling}, - {Key: "fixedchunksizepolling", Value: core.WatchFileKindFixedChunkSizePolling}, - {Key: "usefsevents", Value: core.WatchFileKindUseFsEvents}, - {Key: "usefseventsonparentdirectory", Value: core.WatchFileKindUseFsEventsOnParentDirectory}, -}) - -var watchDirectoryEnumMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ - {Key: "usefsevents", Value: core.WatchDirectoryKindUseFsEvents}, - {Key: "fixedpollinginterval", Value: core.WatchDirectoryKindFixedPollingInterval}, - {Key: "dynamicprioritypolling", Value: core.WatchDirectoryKindDynamicPriorityPolling}, - {Key: "fixedchunksizepolling", Value: core.WatchDirectoryKindFixedChunkSizePolling}, -}) - -var fallbackEnumMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{ - {Key: "fixedinterval", Value: core.PollingKindFixedInterval}, - {Key: "priorityinterval", Value: core.PollingKindPriorityInterval}, - {Key: "dynamicpriority", Value: core.PollingKindDynamicPriority}, - {Key: "fixedchunksize", Value: core.PollingKindFixedChunkSize}, -}) diff --git a/tsc/internal/tsoptions/options_generated.go b/tsc/internal/tsoptions/options_generated.go new file mode 100644 index 0000000000000..daf46de4907fc --- /dev/null +++ b/tsc/internal/tsoptions/options_generated.go @@ -0,0 +1,1880 @@ +// Code generated by tools/scripts/tsc/generate-options.ts. DO NOT EDIT. + +package tsoptions + +import ( + "github.com/microsoft/TypeScript/tsc/internal/ast" + "github.com/microsoft/TypeScript/tsc/internal/collections" + "github.com/microsoft/TypeScript/tsc/internal/core" + "github.com/microsoft/TypeScript/tsc/internal/tspath" +) + +func parseCompilerOptions(key string, value any, allOptions *core.CompilerOptions) (foundKey bool) { + if option := CommandLineCompilerOptionsMap.Get(key); option != nil { + key = option.Name + } + switch key { + case "allowJs": + allOptions.AllowJs = ParseTristate(value) + case "allowArbitraryExtensions": + allOptions.AllowArbitraryExtensions = ParseTristate(value) + case "allowImportingTsExtensions": + allOptions.AllowImportingTsExtensions = ParseTristate(value) + case "allowNonTsExtensions": + allOptions.AllowNonTsExtensions = ParseTristate(value) + case "allowUmdGlobalAccess": + allOptions.AllowUmdGlobalAccess = ParseTristate(value) + case "allowUnreachableCode": + allOptions.AllowUnreachableCode = ParseTristate(value) + case "allowUnusedLabels": + allOptions.AllowUnusedLabels = ParseTristate(value) + case "assumeChangesOnlyAffectDirectDependencies": + allOptions.AssumeChangesOnlyAffectDirectDependencies = ParseTristate(value) + case "checkJs": + allOptions.CheckJs = ParseTristate(value) + case "customConditions": + allOptions.CustomConditions = ParseStringArray(value) + case "composite": + allOptions.Composite = ParseTristate(value) + case "emitDeclarationOnly": + allOptions.EmitDeclarationOnly = ParseTristate(value) + case "emitBOM": + allOptions.EmitBOM = ParseTristate(value) + case "emitDecoratorMetadata": + allOptions.EmitDecoratorMetadata = ParseTristate(value) + case "declaration": + allOptions.Declaration = ParseTristate(value) + case "declarationDir": + allOptions.DeclarationDir = ParseString(value) + case "declarationMap": + allOptions.DeclarationMap = ParseTristate(value) + case "deduplicatePackages": + allOptions.DeduplicatePackages = ParseTristate(value) + case "disableSizeLimit": + allOptions.DisableSizeLimit = ParseTristate(value) + case "disableSourceOfProjectReferenceRedirect": + allOptions.DisableSourceOfProjectReferenceRedirect = ParseTristate(value) + case "disableSolutionSearching": + allOptions.DisableSolutionSearching = ParseTristate(value) + case "disableReferencedProjectLoad": + allOptions.DisableReferencedProjectLoad = ParseTristate(value) + case "erasableSyntaxOnly": + allOptions.ErasableSyntaxOnly = ParseTristate(value) + case "exactOptionalPropertyTypes": + allOptions.ExactOptionalPropertyTypes = ParseTristate(value) + case "experimentalDecorators": + allOptions.ExperimentalDecorators = ParseTristate(value) + case "forceConsistentCasingInFileNames": + allOptions.ForceConsistentCasingInFileNames = ParseTristate(value) + case "isolatedModules": + allOptions.IsolatedModules = ParseTristate(value) + case "isolatedDeclarations": + allOptions.IsolatedDeclarations = ParseTristate(value) + case "ignoreConfig": + allOptions.IgnoreConfig = ParseTristate(value) + case "ignoreDeprecations": + allOptions.IgnoreDeprecations = ParseString(value) + case "importHelpers": + allOptions.ImportHelpers = ParseTristate(value) + case "inlineSourceMap": + allOptions.InlineSourceMap = ParseTristate(value) + case "inlineSources": + allOptions.InlineSources = ParseTristate(value) + case "init": + allOptions.Init = ParseTristate(value) + case "incremental": + allOptions.Incremental = ParseTristate(value) + case "jsx": + allOptions.Jsx = floatOrInt32ToFlag[core.JsxEmit](value) + case "jsxFactory": + allOptions.JsxFactory = ParseString(value) + case "jsxFragmentFactory": + allOptions.JsxFragmentFactory = ParseString(value) + case "jsxImportSource": + allOptions.JsxImportSource = ParseString(value) + case "lib": + if libs, ok := value.([]string); ok { + allOptions.Lib = libs + } else { + allOptions.Lib = ParseStringArray(value) + } + case "libReplacement": + allOptions.LibReplacement = ParseTristate(value) + case "locale": + allOptions.Locale = ParseString(value) + case "mapRoot": + allOptions.MapRoot = ParseString(value) + case "module": + allOptions.Module = floatOrInt32ToFlag[core.ModuleKind](value) + case "moduleResolution": + allOptions.ModuleResolution = floatOrInt32ToFlag[core.ModuleResolutionKind](value) + case "moduleSuffixes": + allOptions.ModuleSuffixes = ParseStringArray(value) + case "moduleDetection", "moduleDetectionKind": + allOptions.ModuleDetection = floatOrInt32ToFlag[core.ModuleDetectionKind](value) + case "newLine": + allOptions.NewLine = floatOrInt32ToFlag[core.NewLineKind](value) + case "noEmit": + allOptions.NoEmit = ParseTristate(value) + case "noCheck": + allOptions.NoCheck = ParseTristate(value) + case "noErrorTruncation": + allOptions.NoErrorTruncation = ParseTristate(value) + case "noFallthroughCasesInSwitch": + allOptions.NoFallthroughCasesInSwitch = ParseTristate(value) + case "noImplicitAny": + allOptions.NoImplicitAny = ParseTristate(value) + case "noImplicitThis": + allOptions.NoImplicitThis = ParseTristate(value) + case "noImplicitReturns": + allOptions.NoImplicitReturns = ParseTristate(value) + case "noEmitHelpers": + allOptions.NoEmitHelpers = ParseTristate(value) + case "noLib": + allOptions.NoLib = ParseTristate(value) + case "noPropertyAccessFromIndexSignature": + allOptions.NoPropertyAccessFromIndexSignature = ParseTristate(value) + case "noUncheckedIndexedAccess": + allOptions.NoUncheckedIndexedAccess = ParseTristate(value) + case "noEmitOnError": + allOptions.NoEmitOnError = ParseTristate(value) + case "noUnusedLocals": + allOptions.NoUnusedLocals = ParseTristate(value) + case "noUnusedParameters": + allOptions.NoUnusedParameters = ParseTristate(value) + case "noResolve": + allOptions.NoResolve = ParseTristate(value) + case "noImplicitOverride": + allOptions.NoImplicitOverride = ParseTristate(value) + case "noUncheckedSideEffectImports": + allOptions.NoUncheckedSideEffectImports = ParseTristate(value) + case "outDir": + allOptions.OutDir = ParseString(value) + case "paths": + allOptions.Paths = parseStringMap(value) + case "plugins": + if plugins, ok := value.([]any); ok { + allOptions.Plugins = core.Map(plugins, func(plugin any) core.PluginImport { + if pluginMap, isMap := plugin.(*collections.OrderedMap[string, any]); isMap { + return core.PluginImport{Name: ParseString(pluginMap.GetOrZero("name"))} + } + return core.PluginImport{} + }) + } + case "preserveConstEnums": + allOptions.PreserveConstEnums = ParseTristate(value) + case "preserveSymlinks": + allOptions.PreserveSymlinks = ParseTristate(value) + case "project": + allOptions.Project = ParseString(value) + case "resolveJsonModule": + allOptions.ResolveJsonModule = ParseTristate(value) + case "resolvePackageJsonExports": + allOptions.ResolvePackageJsonExports = ParseTristate(value) + case "resolvePackageJsonImports": + allOptions.ResolvePackageJsonImports = ParseTristate(value) + case "removeComments": + allOptions.RemoveComments = ParseTristate(value) + case "rewriteRelativeImportExtensions": + allOptions.RewriteRelativeImportExtensions = ParseTristate(value) + case "reactNamespace": + allOptions.ReactNamespace = ParseString(value) + case "rootDir": + allOptions.RootDir = ParseString(value) + case "rootDirs": + allOptions.RootDirs = ParseStringArray(value) + case "skipLibCheck": + allOptions.SkipLibCheck = ParseTristate(value) + case "stableTypeOrdering": + allOptions.StableTypeOrdering = ParseTristate(value) + case "strict": + allOptions.Strict = ParseTristate(value) + case "strictBindCallApply": + allOptions.StrictBindCallApply = ParseTristate(value) + case "strictBuiltinIteratorReturn": + allOptions.StrictBuiltinIteratorReturn = ParseTristate(value) + case "strictFunctionTypes": + allOptions.StrictFunctionTypes = ParseTristate(value) + case "strictNullChecks": + allOptions.StrictNullChecks = ParseTristate(value) + case "strictPropertyInitialization": + allOptions.StrictPropertyInitialization = ParseTristate(value) + case "stripInternal": + allOptions.StripInternal = ParseTristate(value) + case "skipDefaultLibCheck": + allOptions.SkipDefaultLibCheck = ParseTristate(value) + case "sourceMap": + allOptions.SourceMap = ParseTristate(value) + case "sourceRoot": + allOptions.SourceRoot = ParseString(value) + case "suppressOutputPathCheck": + allOptions.SuppressOutputPathCheck = ParseTristate(value) + case "target": + allOptions.Target = floatOrInt32ToFlag[core.ScriptTarget](value) + case "traceResolution": + allOptions.TraceResolution = ParseTristate(value) + case "tsBuildInfoFile": + allOptions.TsBuildInfoFile = ParseString(value) + case "typeRoots": + allOptions.TypeRoots = ParseStringArray(value) + case "types": + allOptions.Types = ParseStringArray(value) + case "useDefineForClassFields": + allOptions.UseDefineForClassFields = ParseTristate(value) + case "useUnknownInCatchVariables": + allOptions.UseUnknownInCatchVariables = ParseTristate(value) + case "verbatimModuleSyntax": + allOptions.VerbatimModuleSyntax = ParseTristate(value) + case "maxNodeModuleJsDepth": + allOptions.MaxNodeModuleJsDepth = parseNumber(value) + case "allowSyntheticDefaultImports": + allOptions.AllowSyntheticDefaultImports = ParseTristate(value) + case "alwaysStrict": + allOptions.AlwaysStrict = ParseTristate(value) + case "baseUrl": + allOptions.BaseUrl = ParseString(value) + case "downlevelIteration": + allOptions.DownlevelIteration = ParseTristate(value) + case "esModuleInterop": + allOptions.ESModuleInterop = ParseTristate(value) + case "outFile": + allOptions.OutFile = ParseString(value) + case "configFilePath": + allOptions.ConfigFilePath = ParseString(value) + case "noDtsResolution": + allOptions.NoDtsResolution = ParseTristate(value) + case "pathsBasePath": + allOptions.PathsBasePath = ParseString(value) + case "diagnostics": + allOptions.Diagnostics = ParseTristate(value) + case "extendedDiagnostics": + allOptions.ExtendedDiagnostics = ParseTristate(value) + case "generateCpuProfile": + allOptions.GenerateCpuProfile = ParseString(value) + case "generateTrace": + allOptions.GenerateTrace = ParseString(value) + case "listEmittedFiles": + allOptions.ListEmittedFiles = ParseTristate(value) + case "listFiles": + allOptions.ListFiles = ParseTristate(value) + case "explainFiles": + allOptions.ExplainFiles = ParseTristate(value) + case "listFilesOnly": + allOptions.ListFilesOnly = ParseTristate(value) + case "noEmitForJsFiles": + allOptions.NoEmitForJsFiles = ParseTristate(value) + case "preserveWatchOutput": + allOptions.PreserveWatchOutput = ParseTristate(value) + case "pretty": + allOptions.Pretty = ParseTristate(value) + case "version": + allOptions.Version = ParseTristate(value) + case "watch": + allOptions.Watch = ParseTristate(value) + case "showConfig": + allOptions.ShowConfig = ParseTristate(value) + case "build": + allOptions.Build = ParseTristate(value) + case "help": + allOptions.Help = ParseTristate(value) + case "all": + allOptions.All = ParseTristate(value) + case "runExternalCode": + allOptions.RunExternalCode = ParseTristate(value) + case "pprofDir": + allOptions.PprofDir = ParseString(value) + case "singleThreaded": + allOptions.SingleThreaded = ParseTristate(value) + case "quiet": + allOptions.Quiet = ParseTristate(value) + case "checkers": + allOptions.Checkers = parseNumber(value) + default: + return false + } + return true +} + +func getDefaultCompilerOptions(configFileName string) *core.CompilerOptions { + if configFileName != "" && tspath.GetBaseFileName(configFileName) == "jsconfig.json" { + return &core.CompilerOptions{ + AllowJs: core.TSTrue, + NoEmit: core.TSTrue, + SkipLibCheck: core.TSTrue, + MaxNodeModuleJsDepth: new(2), + } + } + return &core.CompilerOptions{} +} + +func getDefaultTypeAcquisition(configFileName string) *core.TypeAcquisition { + if configFileName != "" && tspath.GetBaseFileName(configFileName) == "jsconfig.json" { + return &core.TypeAcquisition{ + Enable: core.TSTrue, + } + } + return &core.TypeAcquisition{} +} + +func ParseWatchOptions(key string, value any, allOptions *core.WatchOptions) []*ast.Diagnostic { + if allOptions == nil { + return nil + } + + switch key { + case "watchInterval": + allOptions.Interval = parseNumber(value) + case "watchFile": + if value != nil { + allOptions.FileKind = value.(core.WatchFileKind) + } + case "watchDirectory": + if value != nil { + allOptions.DirectoryKind = value.(core.WatchDirectoryKind) + } + case "fallbackPolling": + if value != nil { + allOptions.FallbackPolling = value.(core.PollingKind) + } + case "synchronousWatchDirectory": + allOptions.SyncWatchDir = ParseTristate(value) + case "excludeDirectories": + allOptions.ExcludeDir = ParseStringArray(value) + case "excludeFiles": + allOptions.ExcludeFiles = ParseStringArray(value) + } + return nil +} + +func ParseTypeAcquisition(key string, value any, allOptions *core.TypeAcquisition) []*ast.Diagnostic { + if value == nil { + return nil + } + if allOptions == nil { + return nil + } + + switch key { + case "enable": + allOptions.Enable = ParseTristate(value) + case "include": + allOptions.Include = ParseStringArray(value) + case "exclude": + allOptions.Exclude = ParseStringArray(value) + case "disableFilenameBasedTypeAcquisition": + allOptions.DisableFilenameBasedTypeAcquisition = ParseTristate(value) + } + return nil +} + +func ParseBuildOptions(key string, value any, allOptions *core.BuildOptions) []*ast.Diagnostic { + if value == nil { + return nil + } + if allOptions == nil { + return nil + } + if option := BuildNameMap.Get(key); option != nil { + key = option.Name + } + switch key { + case "verbose": + allOptions.Verbose = ParseTristate(value) + case "dry": + allOptions.Dry = ParseTristate(value) + case "force": + allOptions.Force = ParseTristate(value) + case "clean": + allOptions.Clean = ParseTristate(value) + case "builders": + allOptions.Builders = parseNumber(value) + case "stopBuildOnErrors": + allOptions.StopBuildOnErrors = ParseTristate(value) + } + return nil +} + +func CompilerOptionsAffectSemanticDiagnostics(oldOptions *core.CompilerOptions, newOptions *core.CompilerOptions) bool { + if oldOptions == newOptions { + return false + } + if oldOptions == nil || newOptions == nil { + return true + } + return oldOptions.AllowImportingTsExtensions != newOptions.AllowImportingTsExtensions || + oldOptions.AllowUmdGlobalAccess != newOptions.AllowUmdGlobalAccess || + oldOptions.AllowUnreachableCode != newOptions.AllowUnreachableCode || + oldOptions.AllowUnusedLabels != newOptions.AllowUnusedLabels || + oldOptions.AssumeChangesOnlyAffectDirectDependencies != newOptions.AssumeChangesOnlyAffectDirectDependencies || + oldOptions.CheckJs != newOptions.CheckJs || + oldOptions.EmitDecoratorMetadata != newOptions.EmitDecoratorMetadata || + oldOptions.ErasableSyntaxOnly != newOptions.ErasableSyntaxOnly || + oldOptions.ExactOptionalPropertyTypes != newOptions.ExactOptionalPropertyTypes || + oldOptions.ExperimentalDecorators != newOptions.ExperimentalDecorators || + oldOptions.IsolatedDeclarations != newOptions.IsolatedDeclarations || + oldOptions.Jsx != newOptions.Jsx || + oldOptions.JsxImportSource != newOptions.JsxImportSource || + oldOptions.NoErrorTruncation != newOptions.NoErrorTruncation || + oldOptions.NoFallthroughCasesInSwitch != newOptions.NoFallthroughCasesInSwitch || + oldOptions.GetStrictOptionValue(oldOptions.NoImplicitAny) != newOptions.GetStrictOptionValue(newOptions.NoImplicitAny) || + oldOptions.GetStrictOptionValue(oldOptions.NoImplicitThis) != newOptions.GetStrictOptionValue(newOptions.NoImplicitThis) || + oldOptions.NoImplicitReturns != newOptions.NoImplicitReturns || + oldOptions.NoPropertyAccessFromIndexSignature != newOptions.NoPropertyAccessFromIndexSignature || + oldOptions.NoUncheckedIndexedAccess != newOptions.NoUncheckedIndexedAccess || + oldOptions.NoUnusedLocals != newOptions.NoUnusedLocals || + oldOptions.NoUnusedParameters != newOptions.NoUnusedParameters || + oldOptions.NoImplicitOverride != newOptions.NoImplicitOverride || + oldOptions.NoUncheckedSideEffectImports != newOptions.NoUncheckedSideEffectImports || + oldOptions.RewriteRelativeImportExtensions != newOptions.RewriteRelativeImportExtensions || + oldOptions.StableTypeOrdering != newOptions.StableTypeOrdering || + oldOptions.GetStrictOptionValue(oldOptions.StrictBindCallApply) != newOptions.GetStrictOptionValue(newOptions.StrictBindCallApply) || + oldOptions.GetStrictOptionValue(oldOptions.StrictBuiltinIteratorReturn) != newOptions.GetStrictOptionValue(newOptions.StrictBuiltinIteratorReturn) || + oldOptions.GetStrictOptionValue(oldOptions.StrictFunctionTypes) != newOptions.GetStrictOptionValue(newOptions.StrictFunctionTypes) || + oldOptions.GetStrictOptionValue(oldOptions.StrictNullChecks) != newOptions.GetStrictOptionValue(newOptions.StrictNullChecks) || + oldOptions.GetStrictOptionValue(oldOptions.StrictPropertyInitialization) != newOptions.GetStrictOptionValue(newOptions.StrictPropertyInitialization) || + oldOptions.UseDefineForClassFields != newOptions.UseDefineForClassFields || + oldOptions.GetStrictOptionValue(oldOptions.UseUnknownInCatchVariables) != newOptions.GetStrictOptionValue(newOptions.UseUnknownInCatchVariables) || + oldOptions.VerbatimModuleSyntax != newOptions.VerbatimModuleSyntax || + oldOptions.AllowSyntheticDefaultImports != newOptions.AllowSyntheticDefaultImports || + oldOptions.ESModuleInterop != newOptions.ESModuleInterop +} + +func CompilerOptionsAffectDeclarationPath(oldOptions *core.CompilerOptions, newOptions *core.CompilerOptions) bool { + if oldOptions == newOptions { + return false + } + if oldOptions == nil || newOptions == nil { + return true + } + return oldOptions.DeclarationDir != newOptions.DeclarationDir || + oldOptions.OutDir != newOptions.OutDir || + oldOptions.RootDir != newOptions.RootDir || + oldOptions.OutFile != newOptions.OutFile +} + +func CompilerOptionsAffectEmit(oldOptions *core.CompilerOptions, newOptions *core.CompilerOptions) bool { + if oldOptions == newOptions { + return false + } + if oldOptions == nil || newOptions == nil { + return true + } + return oldOptions.AssumeChangesOnlyAffectDirectDependencies != newOptions.AssumeChangesOnlyAffectDirectDependencies || + oldOptions.EmitBOM != newOptions.EmitBOM || + oldOptions.EmitDecoratorMetadata != newOptions.EmitDecoratorMetadata || + oldOptions.DeclarationDir != newOptions.DeclarationDir || + oldOptions.ExperimentalDecorators != newOptions.ExperimentalDecorators || + oldOptions.ImportHelpers != newOptions.ImportHelpers || + oldOptions.InlineSources != newOptions.InlineSources || + oldOptions.Jsx != newOptions.Jsx || + oldOptions.JsxImportSource != newOptions.JsxImportSource || + oldOptions.MapRoot != newOptions.MapRoot || + oldOptions.Module != newOptions.Module || + oldOptions.NewLine != newOptions.NewLine || + oldOptions.NoEmitHelpers != newOptions.NoEmitHelpers || + oldOptions.NoEmitOnError != newOptions.NoEmitOnError || + oldOptions.OutDir != newOptions.OutDir || + oldOptions.PreserveConstEnums != newOptions.PreserveConstEnums || + oldOptions.RemoveComments != newOptions.RemoveComments || + oldOptions.ReactNamespace != newOptions.ReactNamespace || + oldOptions.RootDir != newOptions.RootDir || + oldOptions.StripInternal != newOptions.StripInternal || + oldOptions.SourceRoot != newOptions.SourceRoot || + oldOptions.Target != newOptions.Target || + oldOptions.TsBuildInfoFile != newOptions.TsBuildInfoFile || + oldOptions.UseDefineForClassFields != newOptions.UseDefineForClassFields || + oldOptions.VerbatimModuleSyntax != newOptions.VerbatimModuleSyntax || + oldOptions.AlwaysStrict != newOptions.AlwaysStrict || + oldOptions.DownlevelIteration != newOptions.DownlevelIteration || + oldOptions.ESModuleInterop != newOptions.ESModuleInterop || + oldOptions.OutFile != newOptions.OutFile +} + +// ForEachCompilerOptionAffectingBuildInfo visits nonzero options in CompilerOptions field order. +func ForEachCompilerOptionAffectingBuildInfo(options *core.CompilerOptions, fn func(option *CommandLineOption, value any)) { + if options.AllowJs != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("allowJs"), options.AllowJs) + } + if options.AllowImportingTsExtensions != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("allowImportingTsExtensions"), options.AllowImportingTsExtensions) + } + if options.AllowUmdGlobalAccess != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("allowUmdGlobalAccess"), options.AllowUmdGlobalAccess) + } + if options.AllowUnreachableCode != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("allowUnreachableCode"), options.AllowUnreachableCode) + } + if options.AllowUnusedLabels != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("allowUnusedLabels"), options.AllowUnusedLabels) + } + if options.AssumeChangesOnlyAffectDirectDependencies != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("assumeChangesOnlyAffectDirectDependencies"), options.AssumeChangesOnlyAffectDirectDependencies) + } + if options.CheckJs != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("checkJs"), options.CheckJs) + } + if options.Composite != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("composite"), options.Composite) + } + if options.EmitDeclarationOnly != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("emitDeclarationOnly"), options.EmitDeclarationOnly) + } + if options.EmitBOM != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("emitBOM"), options.EmitBOM) + } + if options.EmitDecoratorMetadata != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("emitDecoratorMetadata"), options.EmitDecoratorMetadata) + } + if options.Declaration != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("declaration"), options.Declaration) + } + if options.DeclarationDir != "" { + fn(CommandLineCompilerOptionsMap.Get("declarationDir"), options.DeclarationDir) + } + if options.DeclarationMap != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("declarationMap"), options.DeclarationMap) + } + if options.ErasableSyntaxOnly != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("erasableSyntaxOnly"), options.ErasableSyntaxOnly) + } + if options.ExactOptionalPropertyTypes != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("exactOptionalPropertyTypes"), options.ExactOptionalPropertyTypes) + } + if options.ExperimentalDecorators != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("experimentalDecorators"), options.ExperimentalDecorators) + } + if options.IsolatedDeclarations != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("isolatedDeclarations"), options.IsolatedDeclarations) + } + if options.ImportHelpers != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("importHelpers"), options.ImportHelpers) + } + if options.InlineSourceMap != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("inlineSourceMap"), options.InlineSourceMap) + } + if options.InlineSources != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("inlineSources"), options.InlineSources) + } + if options.Jsx != 0 { + fn(CommandLineCompilerOptionsMap.Get("jsx"), options.Jsx) + } + if options.JsxImportSource != "" { + fn(CommandLineCompilerOptionsMap.Get("jsxImportSource"), options.JsxImportSource) + } + if options.MapRoot != "" { + fn(CommandLineCompilerOptionsMap.Get("mapRoot"), options.MapRoot) + } + if options.Module != 0 { + fn(CommandLineCompilerOptionsMap.Get("module"), options.Module) + } + if options.NewLine != 0 { + fn(CommandLineCompilerOptionsMap.Get("newLine"), options.NewLine) + } + if options.NoErrorTruncation != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noErrorTruncation"), options.NoErrorTruncation) + } + if options.NoFallthroughCasesInSwitch != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noFallthroughCasesInSwitch"), options.NoFallthroughCasesInSwitch) + } + if options.NoImplicitAny != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noImplicitAny"), options.NoImplicitAny) + } + if options.NoImplicitThis != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noImplicitThis"), options.NoImplicitThis) + } + if options.NoImplicitReturns != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noImplicitReturns"), options.NoImplicitReturns) + } + if options.NoEmitHelpers != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noEmitHelpers"), options.NoEmitHelpers) + } + if options.NoPropertyAccessFromIndexSignature != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noPropertyAccessFromIndexSignature"), options.NoPropertyAccessFromIndexSignature) + } + if options.NoUncheckedIndexedAccess != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noUncheckedIndexedAccess"), options.NoUncheckedIndexedAccess) + } + if options.NoEmitOnError != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noEmitOnError"), options.NoEmitOnError) + } + if options.NoUnusedLocals != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noUnusedLocals"), options.NoUnusedLocals) + } + if options.NoUnusedParameters != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noUnusedParameters"), options.NoUnusedParameters) + } + if options.NoImplicitOverride != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noImplicitOverride"), options.NoImplicitOverride) + } + if options.NoUncheckedSideEffectImports != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("noUncheckedSideEffectImports"), options.NoUncheckedSideEffectImports) + } + if options.OutDir != "" { + fn(CommandLineCompilerOptionsMap.Get("outDir"), options.OutDir) + } + if options.PreserveConstEnums != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("preserveConstEnums"), options.PreserveConstEnums) + } + if options.RemoveComments != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("removeComments"), options.RemoveComments) + } + if options.RewriteRelativeImportExtensions != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("rewriteRelativeImportExtensions"), options.RewriteRelativeImportExtensions) + } + if options.ReactNamespace != "" { + fn(CommandLineCompilerOptionsMap.Get("reactNamespace"), options.ReactNamespace) + } + if options.RootDir != "" { + fn(CommandLineCompilerOptionsMap.Get("rootDir"), options.RootDir) + } + if options.SkipLibCheck != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("skipLibCheck"), options.SkipLibCheck) + } + if options.StableTypeOrdering != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("stableTypeOrdering"), options.StableTypeOrdering) + } + if options.Strict != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("strict"), options.Strict) + } + if options.StrictBindCallApply != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("strictBindCallApply"), options.StrictBindCallApply) + } + if options.StrictBuiltinIteratorReturn != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("strictBuiltinIteratorReturn"), options.StrictBuiltinIteratorReturn) + } + if options.StrictFunctionTypes != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("strictFunctionTypes"), options.StrictFunctionTypes) + } + if options.StrictNullChecks != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("strictNullChecks"), options.StrictNullChecks) + } + if options.StrictPropertyInitialization != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("strictPropertyInitialization"), options.StrictPropertyInitialization) + } + if options.StripInternal != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("stripInternal"), options.StripInternal) + } + if options.SkipDefaultLibCheck != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("skipDefaultLibCheck"), options.SkipDefaultLibCheck) + } + if options.SourceMap != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("sourceMap"), options.SourceMap) + } + if options.SourceRoot != "" { + fn(CommandLineCompilerOptionsMap.Get("sourceRoot"), options.SourceRoot) + } + if options.Target != 0 { + fn(CommandLineCompilerOptionsMap.Get("target"), options.Target) + } + if options.TsBuildInfoFile != "" { + fn(CommandLineCompilerOptionsMap.Get("tsBuildInfoFile"), options.TsBuildInfoFile) + } + if options.UseDefineForClassFields != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("useDefineForClassFields"), options.UseDefineForClassFields) + } + if options.UseUnknownInCatchVariables != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("useUnknownInCatchVariables"), options.UseUnknownInCatchVariables) + } + if options.VerbatimModuleSyntax != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("verbatimModuleSyntax"), options.VerbatimModuleSyntax) + } + if options.AllowSyntheticDefaultImports != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("allowSyntheticDefaultImports"), options.AllowSyntheticDefaultImports) + } + if options.AlwaysStrict != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("alwaysStrict"), options.AlwaysStrict) + } + if options.DownlevelIteration != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("downlevelIteration"), options.DownlevelIteration) + } + if options.ESModuleInterop != core.TSUnknown { + fn(CommandLineCompilerOptionsMap.Get("esModuleInterop"), options.ESModuleInterop) + } + if options.OutFile != "" { + fn(CommandLineCompilerOptionsMap.Get("outFile"), options.OutFile) + } +} + +func mergeCompilerOptionFields(targetOptions, sourceOptions *core.CompilerOptions, explicitNullFields collections.Set[string]) { + if explicitNullFields.Has("allowJs") { + targetOptions.AllowJs = core.TSUnknown + } else if sourceOptions.AllowJs != core.TSUnknown { + targetOptions.AllowJs = sourceOptions.AllowJs + } + if explicitNullFields.Has("allowArbitraryExtensions") { + targetOptions.AllowArbitraryExtensions = core.TSUnknown + } else if sourceOptions.AllowArbitraryExtensions != core.TSUnknown { + targetOptions.AllowArbitraryExtensions = sourceOptions.AllowArbitraryExtensions + } + if explicitNullFields.Has("allowImportingTsExtensions") { + targetOptions.AllowImportingTsExtensions = core.TSUnknown + } else if sourceOptions.AllowImportingTsExtensions != core.TSUnknown { + targetOptions.AllowImportingTsExtensions = sourceOptions.AllowImportingTsExtensions + } + if explicitNullFields.Has("allowNonTsExtensions") { + targetOptions.AllowNonTsExtensions = core.TSUnknown + } else if sourceOptions.AllowNonTsExtensions != core.TSUnknown { + targetOptions.AllowNonTsExtensions = sourceOptions.AllowNonTsExtensions + } + if explicitNullFields.Has("allowUmdGlobalAccess") { + targetOptions.AllowUmdGlobalAccess = core.TSUnknown + } else if sourceOptions.AllowUmdGlobalAccess != core.TSUnknown { + targetOptions.AllowUmdGlobalAccess = sourceOptions.AllowUmdGlobalAccess + } + if explicitNullFields.Has("allowUnreachableCode") { + targetOptions.AllowUnreachableCode = core.TSUnknown + } else if sourceOptions.AllowUnreachableCode != core.TSUnknown { + targetOptions.AllowUnreachableCode = sourceOptions.AllowUnreachableCode + } + if explicitNullFields.Has("allowUnusedLabels") { + targetOptions.AllowUnusedLabels = core.TSUnknown + } else if sourceOptions.AllowUnusedLabels != core.TSUnknown { + targetOptions.AllowUnusedLabels = sourceOptions.AllowUnusedLabels + } + if explicitNullFields.Has("assumeChangesOnlyAffectDirectDependencies") { + targetOptions.AssumeChangesOnlyAffectDirectDependencies = core.TSUnknown + } else if sourceOptions.AssumeChangesOnlyAffectDirectDependencies != core.TSUnknown { + targetOptions.AssumeChangesOnlyAffectDirectDependencies = sourceOptions.AssumeChangesOnlyAffectDirectDependencies + } + if explicitNullFields.Has("checkJs") { + targetOptions.CheckJs = core.TSUnknown + } else if sourceOptions.CheckJs != core.TSUnknown { + targetOptions.CheckJs = sourceOptions.CheckJs + } + if explicitNullFields.Has("customConditions") { + targetOptions.CustomConditions = nil + } else if sourceOptions.CustomConditions != nil { + targetOptions.CustomConditions = sourceOptions.CustomConditions + } + if explicitNullFields.Has("composite") { + targetOptions.Composite = core.TSUnknown + } else if sourceOptions.Composite != core.TSUnknown { + targetOptions.Composite = sourceOptions.Composite + } + if explicitNullFields.Has("emitDeclarationOnly") { + targetOptions.EmitDeclarationOnly = core.TSUnknown + } else if sourceOptions.EmitDeclarationOnly != core.TSUnknown { + targetOptions.EmitDeclarationOnly = sourceOptions.EmitDeclarationOnly + } + if explicitNullFields.Has("emitBOM") { + targetOptions.EmitBOM = core.TSUnknown + } else if sourceOptions.EmitBOM != core.TSUnknown { + targetOptions.EmitBOM = sourceOptions.EmitBOM + } + if explicitNullFields.Has("emitDecoratorMetadata") { + targetOptions.EmitDecoratorMetadata = core.TSUnknown + } else if sourceOptions.EmitDecoratorMetadata != core.TSUnknown { + targetOptions.EmitDecoratorMetadata = sourceOptions.EmitDecoratorMetadata + } + if explicitNullFields.Has("declaration") { + targetOptions.Declaration = core.TSUnknown + } else if sourceOptions.Declaration != core.TSUnknown { + targetOptions.Declaration = sourceOptions.Declaration + } + if explicitNullFields.Has("declarationDir") { + targetOptions.DeclarationDir = "" + } else if sourceOptions.DeclarationDir != "" { + targetOptions.DeclarationDir = sourceOptions.DeclarationDir + } + if explicitNullFields.Has("declarationMap") { + targetOptions.DeclarationMap = core.TSUnknown + } else if sourceOptions.DeclarationMap != core.TSUnknown { + targetOptions.DeclarationMap = sourceOptions.DeclarationMap + } + if explicitNullFields.Has("deduplicatePackages") { + targetOptions.DeduplicatePackages = core.TSUnknown + } else if sourceOptions.DeduplicatePackages != core.TSUnknown { + targetOptions.DeduplicatePackages = sourceOptions.DeduplicatePackages + } + if explicitNullFields.Has("disableSizeLimit") { + targetOptions.DisableSizeLimit = core.TSUnknown + } else if sourceOptions.DisableSizeLimit != core.TSUnknown { + targetOptions.DisableSizeLimit = sourceOptions.DisableSizeLimit + } + if explicitNullFields.Has("disableSourceOfProjectReferenceRedirect") { + targetOptions.DisableSourceOfProjectReferenceRedirect = core.TSUnknown + } else if sourceOptions.DisableSourceOfProjectReferenceRedirect != core.TSUnknown { + targetOptions.DisableSourceOfProjectReferenceRedirect = sourceOptions.DisableSourceOfProjectReferenceRedirect + } + if explicitNullFields.Has("disableSolutionSearching") { + targetOptions.DisableSolutionSearching = core.TSUnknown + } else if sourceOptions.DisableSolutionSearching != core.TSUnknown { + targetOptions.DisableSolutionSearching = sourceOptions.DisableSolutionSearching + } + if explicitNullFields.Has("disableReferencedProjectLoad") { + targetOptions.DisableReferencedProjectLoad = core.TSUnknown + } else if sourceOptions.DisableReferencedProjectLoad != core.TSUnknown { + targetOptions.DisableReferencedProjectLoad = sourceOptions.DisableReferencedProjectLoad + } + if explicitNullFields.Has("erasableSyntaxOnly") { + targetOptions.ErasableSyntaxOnly = core.TSUnknown + } else if sourceOptions.ErasableSyntaxOnly != core.TSUnknown { + targetOptions.ErasableSyntaxOnly = sourceOptions.ErasableSyntaxOnly + } + if explicitNullFields.Has("exactOptionalPropertyTypes") { + targetOptions.ExactOptionalPropertyTypes = core.TSUnknown + } else if sourceOptions.ExactOptionalPropertyTypes != core.TSUnknown { + targetOptions.ExactOptionalPropertyTypes = sourceOptions.ExactOptionalPropertyTypes + } + if explicitNullFields.Has("experimentalDecorators") { + targetOptions.ExperimentalDecorators = core.TSUnknown + } else if sourceOptions.ExperimentalDecorators != core.TSUnknown { + targetOptions.ExperimentalDecorators = sourceOptions.ExperimentalDecorators + } + if explicitNullFields.Has("forceConsistentCasingInFileNames") { + targetOptions.ForceConsistentCasingInFileNames = core.TSUnknown + } else if sourceOptions.ForceConsistentCasingInFileNames != core.TSUnknown { + targetOptions.ForceConsistentCasingInFileNames = sourceOptions.ForceConsistentCasingInFileNames + } + if explicitNullFields.Has("isolatedModules") { + targetOptions.IsolatedModules = core.TSUnknown + } else if sourceOptions.IsolatedModules != core.TSUnknown { + targetOptions.IsolatedModules = sourceOptions.IsolatedModules + } + if explicitNullFields.Has("isolatedDeclarations") { + targetOptions.IsolatedDeclarations = core.TSUnknown + } else if sourceOptions.IsolatedDeclarations != core.TSUnknown { + targetOptions.IsolatedDeclarations = sourceOptions.IsolatedDeclarations + } + if explicitNullFields.Has("ignoreConfig") { + targetOptions.IgnoreConfig = core.TSUnknown + } else if sourceOptions.IgnoreConfig != core.TSUnknown { + targetOptions.IgnoreConfig = sourceOptions.IgnoreConfig + } + if explicitNullFields.Has("ignoreDeprecations") { + targetOptions.IgnoreDeprecations = "" + } else if sourceOptions.IgnoreDeprecations != "" { + targetOptions.IgnoreDeprecations = sourceOptions.IgnoreDeprecations + } + if explicitNullFields.Has("importHelpers") { + targetOptions.ImportHelpers = core.TSUnknown + } else if sourceOptions.ImportHelpers != core.TSUnknown { + targetOptions.ImportHelpers = sourceOptions.ImportHelpers + } + if explicitNullFields.Has("inlineSourceMap") { + targetOptions.InlineSourceMap = core.TSUnknown + } else if sourceOptions.InlineSourceMap != core.TSUnknown { + targetOptions.InlineSourceMap = sourceOptions.InlineSourceMap + } + if explicitNullFields.Has("inlineSources") { + targetOptions.InlineSources = core.TSUnknown + } else if sourceOptions.InlineSources != core.TSUnknown { + targetOptions.InlineSources = sourceOptions.InlineSources + } + if explicitNullFields.Has("init") { + targetOptions.Init = core.TSUnknown + } else if sourceOptions.Init != core.TSUnknown { + targetOptions.Init = sourceOptions.Init + } + if explicitNullFields.Has("incremental") { + targetOptions.Incremental = core.TSUnknown + } else if sourceOptions.Incremental != core.TSUnknown { + targetOptions.Incremental = sourceOptions.Incremental + } + if explicitNullFields.Has("jsx") { + targetOptions.Jsx = 0 + } else if sourceOptions.Jsx != 0 { + targetOptions.Jsx = sourceOptions.Jsx + } + if explicitNullFields.Has("jsxFactory") { + targetOptions.JsxFactory = "" + } else if sourceOptions.JsxFactory != "" { + targetOptions.JsxFactory = sourceOptions.JsxFactory + } + if explicitNullFields.Has("jsxFragmentFactory") { + targetOptions.JsxFragmentFactory = "" + } else if sourceOptions.JsxFragmentFactory != "" { + targetOptions.JsxFragmentFactory = sourceOptions.JsxFragmentFactory + } + if explicitNullFields.Has("jsxImportSource") { + targetOptions.JsxImportSource = "" + } else if sourceOptions.JsxImportSource != "" { + targetOptions.JsxImportSource = sourceOptions.JsxImportSource + } + if explicitNullFields.Has("lib") { + targetOptions.Lib = nil + } else if sourceOptions.Lib != nil { + targetOptions.Lib = sourceOptions.Lib + } + if explicitNullFields.Has("libReplacement") { + targetOptions.LibReplacement = core.TSUnknown + } else if sourceOptions.LibReplacement != core.TSUnknown { + targetOptions.LibReplacement = sourceOptions.LibReplacement + } + if explicitNullFields.Has("locale") { + targetOptions.Locale = "" + } else if sourceOptions.Locale != "" { + targetOptions.Locale = sourceOptions.Locale + } + if explicitNullFields.Has("mapRoot") { + targetOptions.MapRoot = "" + } else if sourceOptions.MapRoot != "" { + targetOptions.MapRoot = sourceOptions.MapRoot + } + if explicitNullFields.Has("module") { + targetOptions.Module = 0 + } else if sourceOptions.Module != 0 { + targetOptions.Module = sourceOptions.Module + } + if explicitNullFields.Has("moduleResolution") { + targetOptions.ModuleResolution = 0 + } else if sourceOptions.ModuleResolution != 0 { + targetOptions.ModuleResolution = sourceOptions.ModuleResolution + } + if explicitNullFields.Has("moduleSuffixes") { + targetOptions.ModuleSuffixes = nil + } else if sourceOptions.ModuleSuffixes != nil { + targetOptions.ModuleSuffixes = sourceOptions.ModuleSuffixes + } + if explicitNullFields.Has("moduleDetection") { + targetOptions.ModuleDetection = 0 + } else if sourceOptions.ModuleDetection != 0 { + targetOptions.ModuleDetection = sourceOptions.ModuleDetection + } + if explicitNullFields.Has("newLine") { + targetOptions.NewLine = 0 + } else if sourceOptions.NewLine != 0 { + targetOptions.NewLine = sourceOptions.NewLine + } + if explicitNullFields.Has("noEmit") { + targetOptions.NoEmit = core.TSUnknown + } else if sourceOptions.NoEmit != core.TSUnknown { + targetOptions.NoEmit = sourceOptions.NoEmit + } + if explicitNullFields.Has("noCheck") { + targetOptions.NoCheck = core.TSUnknown + } else if sourceOptions.NoCheck != core.TSUnknown { + targetOptions.NoCheck = sourceOptions.NoCheck + } + if explicitNullFields.Has("noErrorTruncation") { + targetOptions.NoErrorTruncation = core.TSUnknown + } else if sourceOptions.NoErrorTruncation != core.TSUnknown { + targetOptions.NoErrorTruncation = sourceOptions.NoErrorTruncation + } + if explicitNullFields.Has("noFallthroughCasesInSwitch") { + targetOptions.NoFallthroughCasesInSwitch = core.TSUnknown + } else if sourceOptions.NoFallthroughCasesInSwitch != core.TSUnknown { + targetOptions.NoFallthroughCasesInSwitch = sourceOptions.NoFallthroughCasesInSwitch + } + if explicitNullFields.Has("noImplicitAny") { + targetOptions.NoImplicitAny = core.TSUnknown + } else if sourceOptions.NoImplicitAny != core.TSUnknown { + targetOptions.NoImplicitAny = sourceOptions.NoImplicitAny + } + if explicitNullFields.Has("noImplicitThis") { + targetOptions.NoImplicitThis = core.TSUnknown + } else if sourceOptions.NoImplicitThis != core.TSUnknown { + targetOptions.NoImplicitThis = sourceOptions.NoImplicitThis + } + if explicitNullFields.Has("noImplicitReturns") { + targetOptions.NoImplicitReturns = core.TSUnknown + } else if sourceOptions.NoImplicitReturns != core.TSUnknown { + targetOptions.NoImplicitReturns = sourceOptions.NoImplicitReturns + } + if explicitNullFields.Has("noEmitHelpers") { + targetOptions.NoEmitHelpers = core.TSUnknown + } else if sourceOptions.NoEmitHelpers != core.TSUnknown { + targetOptions.NoEmitHelpers = sourceOptions.NoEmitHelpers + } + if explicitNullFields.Has("noLib") { + targetOptions.NoLib = core.TSUnknown + } else if sourceOptions.NoLib != core.TSUnknown { + targetOptions.NoLib = sourceOptions.NoLib + } + if explicitNullFields.Has("noPropertyAccessFromIndexSignature") { + targetOptions.NoPropertyAccessFromIndexSignature = core.TSUnknown + } else if sourceOptions.NoPropertyAccessFromIndexSignature != core.TSUnknown { + targetOptions.NoPropertyAccessFromIndexSignature = sourceOptions.NoPropertyAccessFromIndexSignature + } + if explicitNullFields.Has("noUncheckedIndexedAccess") { + targetOptions.NoUncheckedIndexedAccess = core.TSUnknown + } else if sourceOptions.NoUncheckedIndexedAccess != core.TSUnknown { + targetOptions.NoUncheckedIndexedAccess = sourceOptions.NoUncheckedIndexedAccess + } + if explicitNullFields.Has("noEmitOnError") { + targetOptions.NoEmitOnError = core.TSUnknown + } else if sourceOptions.NoEmitOnError != core.TSUnknown { + targetOptions.NoEmitOnError = sourceOptions.NoEmitOnError + } + if explicitNullFields.Has("noUnusedLocals") { + targetOptions.NoUnusedLocals = core.TSUnknown + } else if sourceOptions.NoUnusedLocals != core.TSUnknown { + targetOptions.NoUnusedLocals = sourceOptions.NoUnusedLocals + } + if explicitNullFields.Has("noUnusedParameters") { + targetOptions.NoUnusedParameters = core.TSUnknown + } else if sourceOptions.NoUnusedParameters != core.TSUnknown { + targetOptions.NoUnusedParameters = sourceOptions.NoUnusedParameters + } + if explicitNullFields.Has("noResolve") { + targetOptions.NoResolve = core.TSUnknown + } else if sourceOptions.NoResolve != core.TSUnknown { + targetOptions.NoResolve = sourceOptions.NoResolve + } + if explicitNullFields.Has("noImplicitOverride") { + targetOptions.NoImplicitOverride = core.TSUnknown + } else if sourceOptions.NoImplicitOverride != core.TSUnknown { + targetOptions.NoImplicitOverride = sourceOptions.NoImplicitOverride + } + if explicitNullFields.Has("noUncheckedSideEffectImports") { + targetOptions.NoUncheckedSideEffectImports = core.TSUnknown + } else if sourceOptions.NoUncheckedSideEffectImports != core.TSUnknown { + targetOptions.NoUncheckedSideEffectImports = sourceOptions.NoUncheckedSideEffectImports + } + if explicitNullFields.Has("outDir") { + targetOptions.OutDir = "" + } else if sourceOptions.OutDir != "" { + targetOptions.OutDir = sourceOptions.OutDir + } + if explicitNullFields.Has("paths") { + targetOptions.Paths = nil + } else if sourceOptions.Paths != nil { + targetOptions.Paths = sourceOptions.Paths + } + if explicitNullFields.Has("plugins") { + targetOptions.Plugins = nil + } else if sourceOptions.Plugins != nil { + targetOptions.Plugins = sourceOptions.Plugins + } + if explicitNullFields.Has("preserveConstEnums") { + targetOptions.PreserveConstEnums = core.TSUnknown + } else if sourceOptions.PreserveConstEnums != core.TSUnknown { + targetOptions.PreserveConstEnums = sourceOptions.PreserveConstEnums + } + if explicitNullFields.Has("preserveSymlinks") { + targetOptions.PreserveSymlinks = core.TSUnknown + } else if sourceOptions.PreserveSymlinks != core.TSUnknown { + targetOptions.PreserveSymlinks = sourceOptions.PreserveSymlinks + } + if explicitNullFields.Has("project") { + targetOptions.Project = "" + } else if sourceOptions.Project != "" { + targetOptions.Project = sourceOptions.Project + } + if explicitNullFields.Has("resolveJsonModule") { + targetOptions.ResolveJsonModule = core.TSUnknown + } else if sourceOptions.ResolveJsonModule != core.TSUnknown { + targetOptions.ResolveJsonModule = sourceOptions.ResolveJsonModule + } + if explicitNullFields.Has("resolvePackageJsonExports") { + targetOptions.ResolvePackageJsonExports = core.TSUnknown + } else if sourceOptions.ResolvePackageJsonExports != core.TSUnknown { + targetOptions.ResolvePackageJsonExports = sourceOptions.ResolvePackageJsonExports + } + if explicitNullFields.Has("resolvePackageJsonImports") { + targetOptions.ResolvePackageJsonImports = core.TSUnknown + } else if sourceOptions.ResolvePackageJsonImports != core.TSUnknown { + targetOptions.ResolvePackageJsonImports = sourceOptions.ResolvePackageJsonImports + } + if explicitNullFields.Has("removeComments") { + targetOptions.RemoveComments = core.TSUnknown + } else if sourceOptions.RemoveComments != core.TSUnknown { + targetOptions.RemoveComments = sourceOptions.RemoveComments + } + if explicitNullFields.Has("rewriteRelativeImportExtensions") { + targetOptions.RewriteRelativeImportExtensions = core.TSUnknown + } else if sourceOptions.RewriteRelativeImportExtensions != core.TSUnknown { + targetOptions.RewriteRelativeImportExtensions = sourceOptions.RewriteRelativeImportExtensions + } + if explicitNullFields.Has("reactNamespace") { + targetOptions.ReactNamespace = "" + } else if sourceOptions.ReactNamespace != "" { + targetOptions.ReactNamespace = sourceOptions.ReactNamespace + } + if explicitNullFields.Has("rootDir") { + targetOptions.RootDir = "" + } else if sourceOptions.RootDir != "" { + targetOptions.RootDir = sourceOptions.RootDir + } + if explicitNullFields.Has("rootDirs") { + targetOptions.RootDirs = nil + } else if sourceOptions.RootDirs != nil { + targetOptions.RootDirs = sourceOptions.RootDirs + } + if explicitNullFields.Has("skipLibCheck") { + targetOptions.SkipLibCheck = core.TSUnknown + } else if sourceOptions.SkipLibCheck != core.TSUnknown { + targetOptions.SkipLibCheck = sourceOptions.SkipLibCheck + } + if explicitNullFields.Has("stableTypeOrdering") { + targetOptions.StableTypeOrdering = core.TSUnknown + } else if sourceOptions.StableTypeOrdering != core.TSUnknown { + targetOptions.StableTypeOrdering = sourceOptions.StableTypeOrdering + } + if explicitNullFields.Has("strict") { + targetOptions.Strict = core.TSUnknown + } else if sourceOptions.Strict != core.TSUnknown { + targetOptions.Strict = sourceOptions.Strict + } + if explicitNullFields.Has("strictBindCallApply") { + targetOptions.StrictBindCallApply = core.TSUnknown + } else if sourceOptions.StrictBindCallApply != core.TSUnknown { + targetOptions.StrictBindCallApply = sourceOptions.StrictBindCallApply + } + if explicitNullFields.Has("strictBuiltinIteratorReturn") { + targetOptions.StrictBuiltinIteratorReturn = core.TSUnknown + } else if sourceOptions.StrictBuiltinIteratorReturn != core.TSUnknown { + targetOptions.StrictBuiltinIteratorReturn = sourceOptions.StrictBuiltinIteratorReturn + } + if explicitNullFields.Has("strictFunctionTypes") { + targetOptions.StrictFunctionTypes = core.TSUnknown + } else if sourceOptions.StrictFunctionTypes != core.TSUnknown { + targetOptions.StrictFunctionTypes = sourceOptions.StrictFunctionTypes + } + if explicitNullFields.Has("strictNullChecks") { + targetOptions.StrictNullChecks = core.TSUnknown + } else if sourceOptions.StrictNullChecks != core.TSUnknown { + targetOptions.StrictNullChecks = sourceOptions.StrictNullChecks + } + if explicitNullFields.Has("strictPropertyInitialization") { + targetOptions.StrictPropertyInitialization = core.TSUnknown + } else if sourceOptions.StrictPropertyInitialization != core.TSUnknown { + targetOptions.StrictPropertyInitialization = sourceOptions.StrictPropertyInitialization + } + if explicitNullFields.Has("stripInternal") { + targetOptions.StripInternal = core.TSUnknown + } else if sourceOptions.StripInternal != core.TSUnknown { + targetOptions.StripInternal = sourceOptions.StripInternal + } + if explicitNullFields.Has("skipDefaultLibCheck") { + targetOptions.SkipDefaultLibCheck = core.TSUnknown + } else if sourceOptions.SkipDefaultLibCheck != core.TSUnknown { + targetOptions.SkipDefaultLibCheck = sourceOptions.SkipDefaultLibCheck + } + if explicitNullFields.Has("sourceMap") { + targetOptions.SourceMap = core.TSUnknown + } else if sourceOptions.SourceMap != core.TSUnknown { + targetOptions.SourceMap = sourceOptions.SourceMap + } + if explicitNullFields.Has("sourceRoot") { + targetOptions.SourceRoot = "" + } else if sourceOptions.SourceRoot != "" { + targetOptions.SourceRoot = sourceOptions.SourceRoot + } + if explicitNullFields.Has("suppressOutputPathCheck") { + targetOptions.SuppressOutputPathCheck = core.TSUnknown + } else if sourceOptions.SuppressOutputPathCheck != core.TSUnknown { + targetOptions.SuppressOutputPathCheck = sourceOptions.SuppressOutputPathCheck + } + if explicitNullFields.Has("target") { + targetOptions.Target = 0 + } else if sourceOptions.Target != 0 { + targetOptions.Target = sourceOptions.Target + } + if explicitNullFields.Has("traceResolution") { + targetOptions.TraceResolution = core.TSUnknown + } else if sourceOptions.TraceResolution != core.TSUnknown { + targetOptions.TraceResolution = sourceOptions.TraceResolution + } + if explicitNullFields.Has("tsBuildInfoFile") { + targetOptions.TsBuildInfoFile = "" + } else if sourceOptions.TsBuildInfoFile != "" { + targetOptions.TsBuildInfoFile = sourceOptions.TsBuildInfoFile + } + if explicitNullFields.Has("typeRoots") { + targetOptions.TypeRoots = nil + } else if sourceOptions.TypeRoots != nil { + targetOptions.TypeRoots = sourceOptions.TypeRoots + } + if explicitNullFields.Has("types") { + targetOptions.Types = nil + } else if sourceOptions.Types != nil { + targetOptions.Types = sourceOptions.Types + } + if explicitNullFields.Has("useDefineForClassFields") { + targetOptions.UseDefineForClassFields = core.TSUnknown + } else if sourceOptions.UseDefineForClassFields != core.TSUnknown { + targetOptions.UseDefineForClassFields = sourceOptions.UseDefineForClassFields + } + if explicitNullFields.Has("useUnknownInCatchVariables") { + targetOptions.UseUnknownInCatchVariables = core.TSUnknown + } else if sourceOptions.UseUnknownInCatchVariables != core.TSUnknown { + targetOptions.UseUnknownInCatchVariables = sourceOptions.UseUnknownInCatchVariables + } + if explicitNullFields.Has("verbatimModuleSyntax") { + targetOptions.VerbatimModuleSyntax = core.TSUnknown + } else if sourceOptions.VerbatimModuleSyntax != core.TSUnknown { + targetOptions.VerbatimModuleSyntax = sourceOptions.VerbatimModuleSyntax + } + if explicitNullFields.Has("maxNodeModuleJsDepth") { + targetOptions.MaxNodeModuleJsDepth = nil + } else if sourceOptions.MaxNodeModuleJsDepth != nil { + targetOptions.MaxNodeModuleJsDepth = sourceOptions.MaxNodeModuleJsDepth + } + if explicitNullFields.Has("allowSyntheticDefaultImports") { + targetOptions.AllowSyntheticDefaultImports = core.TSUnknown + } else if sourceOptions.AllowSyntheticDefaultImports != core.TSUnknown { + targetOptions.AllowSyntheticDefaultImports = sourceOptions.AllowSyntheticDefaultImports + } + if explicitNullFields.Has("alwaysStrict") { + targetOptions.AlwaysStrict = core.TSUnknown + } else if sourceOptions.AlwaysStrict != core.TSUnknown { + targetOptions.AlwaysStrict = sourceOptions.AlwaysStrict + } + if explicitNullFields.Has("baseUrl") { + targetOptions.BaseUrl = "" + } else if sourceOptions.BaseUrl != "" { + targetOptions.BaseUrl = sourceOptions.BaseUrl + } + if explicitNullFields.Has("downlevelIteration") { + targetOptions.DownlevelIteration = core.TSUnknown + } else if sourceOptions.DownlevelIteration != core.TSUnknown { + targetOptions.DownlevelIteration = sourceOptions.DownlevelIteration + } + if explicitNullFields.Has("esModuleInterop") { + targetOptions.ESModuleInterop = core.TSUnknown + } else if sourceOptions.ESModuleInterop != core.TSUnknown { + targetOptions.ESModuleInterop = sourceOptions.ESModuleInterop + } + if explicitNullFields.Has("outFile") { + targetOptions.OutFile = "" + } else if sourceOptions.OutFile != "" { + targetOptions.OutFile = sourceOptions.OutFile + } + if explicitNullFields.Has("configFilePath") { + targetOptions.ConfigFilePath = "" + } else if sourceOptions.ConfigFilePath != "" { + targetOptions.ConfigFilePath = sourceOptions.ConfigFilePath + } + if explicitNullFields.Has("noDtsResolution") { + targetOptions.NoDtsResolution = core.TSUnknown + } else if sourceOptions.NoDtsResolution != core.TSUnknown { + targetOptions.NoDtsResolution = sourceOptions.NoDtsResolution + } + if explicitNullFields.Has("pathsBasePath") { + targetOptions.PathsBasePath = "" + } else if sourceOptions.PathsBasePath != "" { + targetOptions.PathsBasePath = sourceOptions.PathsBasePath + } + if explicitNullFields.Has("diagnostics") { + targetOptions.Diagnostics = core.TSUnknown + } else if sourceOptions.Diagnostics != core.TSUnknown { + targetOptions.Diagnostics = sourceOptions.Diagnostics + } + if explicitNullFields.Has("extendedDiagnostics") { + targetOptions.ExtendedDiagnostics = core.TSUnknown + } else if sourceOptions.ExtendedDiagnostics != core.TSUnknown { + targetOptions.ExtendedDiagnostics = sourceOptions.ExtendedDiagnostics + } + if explicitNullFields.Has("generateCpuProfile") { + targetOptions.GenerateCpuProfile = "" + } else if sourceOptions.GenerateCpuProfile != "" { + targetOptions.GenerateCpuProfile = sourceOptions.GenerateCpuProfile + } + if explicitNullFields.Has("generateTrace") { + targetOptions.GenerateTrace = "" + } else if sourceOptions.GenerateTrace != "" { + targetOptions.GenerateTrace = sourceOptions.GenerateTrace + } + if explicitNullFields.Has("listEmittedFiles") { + targetOptions.ListEmittedFiles = core.TSUnknown + } else if sourceOptions.ListEmittedFiles != core.TSUnknown { + targetOptions.ListEmittedFiles = sourceOptions.ListEmittedFiles + } + if explicitNullFields.Has("listFiles") { + targetOptions.ListFiles = core.TSUnknown + } else if sourceOptions.ListFiles != core.TSUnknown { + targetOptions.ListFiles = sourceOptions.ListFiles + } + if explicitNullFields.Has("explainFiles") { + targetOptions.ExplainFiles = core.TSUnknown + } else if sourceOptions.ExplainFiles != core.TSUnknown { + targetOptions.ExplainFiles = sourceOptions.ExplainFiles + } + if explicitNullFields.Has("listFilesOnly") { + targetOptions.ListFilesOnly = core.TSUnknown + } else if sourceOptions.ListFilesOnly != core.TSUnknown { + targetOptions.ListFilesOnly = sourceOptions.ListFilesOnly + } + if explicitNullFields.Has("noEmitForJsFiles") { + targetOptions.NoEmitForJsFiles = core.TSUnknown + } else if sourceOptions.NoEmitForJsFiles != core.TSUnknown { + targetOptions.NoEmitForJsFiles = sourceOptions.NoEmitForJsFiles + } + if explicitNullFields.Has("preserveWatchOutput") { + targetOptions.PreserveWatchOutput = core.TSUnknown + } else if sourceOptions.PreserveWatchOutput != core.TSUnknown { + targetOptions.PreserveWatchOutput = sourceOptions.PreserveWatchOutput + } + if explicitNullFields.Has("pretty") { + targetOptions.Pretty = core.TSUnknown + } else if sourceOptions.Pretty != core.TSUnknown { + targetOptions.Pretty = sourceOptions.Pretty + } + if explicitNullFields.Has("version") { + targetOptions.Version = core.TSUnknown + } else if sourceOptions.Version != core.TSUnknown { + targetOptions.Version = sourceOptions.Version + } + if explicitNullFields.Has("watch") { + targetOptions.Watch = core.TSUnknown + } else if sourceOptions.Watch != core.TSUnknown { + targetOptions.Watch = sourceOptions.Watch + } + if explicitNullFields.Has("showConfig") { + targetOptions.ShowConfig = core.TSUnknown + } else if sourceOptions.ShowConfig != core.TSUnknown { + targetOptions.ShowConfig = sourceOptions.ShowConfig + } + if explicitNullFields.Has("build") { + targetOptions.Build = core.TSUnknown + } else if sourceOptions.Build != core.TSUnknown { + targetOptions.Build = sourceOptions.Build + } + if explicitNullFields.Has("help") { + targetOptions.Help = core.TSUnknown + } else if sourceOptions.Help != core.TSUnknown { + targetOptions.Help = sourceOptions.Help + } + if explicitNullFields.Has("all") { + targetOptions.All = core.TSUnknown + } else if sourceOptions.All != core.TSUnknown { + targetOptions.All = sourceOptions.All + } + if explicitNullFields.Has("runExternalCode") { + targetOptions.RunExternalCode = core.TSUnknown + } else if sourceOptions.RunExternalCode != core.TSUnknown { + targetOptions.RunExternalCode = sourceOptions.RunExternalCode + } + if explicitNullFields.Has("pprofDir") { + targetOptions.PprofDir = "" + } else if sourceOptions.PprofDir != "" { + targetOptions.PprofDir = sourceOptions.PprofDir + } + if explicitNullFields.Has("singleThreaded") { + targetOptions.SingleThreaded = core.TSUnknown + } else if sourceOptions.SingleThreaded != core.TSUnknown { + targetOptions.SingleThreaded = sourceOptions.SingleThreaded + } + if explicitNullFields.Has("quiet") { + targetOptions.Quiet = core.TSUnknown + } else if sourceOptions.Quiet != core.TSUnknown { + targetOptions.Quiet = sourceOptions.Quiet + } + if explicitNullFields.Has("checkers") { + targetOptions.Checkers = nil + } else if sourceOptions.Checkers != nil { + targetOptions.Checkers = sourceOptions.Checkers + } +} + +func handleOptionConfigDirTemplateSubstitution(compilerOptions *core.CompilerOptions, basePath string) { + if compilerOptions == nil { + return + } + if startsWithConfigDirTemplate(compilerOptions.DeclarationDir) { + compilerOptions.DeclarationDir = getSubstitutedPathWithConfigDirTemplate(compilerOptions.DeclarationDir, basePath) + } + if startsWithConfigDirTemplate(compilerOptions.OutDir) { + compilerOptions.OutDir = getSubstitutedPathWithConfigDirTemplate(compilerOptions.OutDir, basePath) + } + { + var paths *collections.OrderedMap[string, []string] + for k, v := range compilerOptions.Paths.Entries() { + if substitution := getSubstitutedStringArrayWithConfigDirTemplate(v, basePath); substitution != nil { + if paths == nil { + paths = compilerOptions.Paths.Clone() + compilerOptions.Paths = paths + } + paths.Set(k, substitution) + } + } + } + if startsWithConfigDirTemplate(compilerOptions.RootDir) { + compilerOptions.RootDir = getSubstitutedPathWithConfigDirTemplate(compilerOptions.RootDir, basePath) + } + if substitution := getSubstitutedStringArrayWithConfigDirTemplate(compilerOptions.RootDirs, basePath); substitution != nil { + compilerOptions.RootDirs = substitution + } + if startsWithConfigDirTemplate(compilerOptions.TsBuildInfoFile) { + compilerOptions.TsBuildInfoFile = getSubstitutedPathWithConfigDirTemplate(compilerOptions.TsBuildInfoFile, basePath) + } + if substitution := getSubstitutedStringArrayWithConfigDirTemplate(compilerOptions.TypeRoots, basePath); substitution != nil { + compilerOptions.TypeRoots = substitution + } + if startsWithConfigDirTemplate(compilerOptions.BaseUrl) { + compilerOptions.BaseUrl = getSubstitutedPathWithConfigDirTemplate(compilerOptions.BaseUrl, basePath) + } + if startsWithConfigDirTemplate(compilerOptions.OutFile) { + compilerOptions.OutFile = getSubstitutedPathWithConfigDirTemplate(compilerOptions.OutFile, basePath) + } + if startsWithConfigDirTemplate(compilerOptions.GenerateCpuProfile) { + compilerOptions.GenerateCpuProfile = getSubstitutedPathWithConfigDirTemplate(compilerOptions.GenerateCpuProfile, basePath) + } + if startsWithConfigDirTemplate(compilerOptions.GenerateTrace) { + compilerOptions.GenerateTrace = getSubstitutedPathWithConfigDirTemplate(compilerOptions.GenerateTrace, basePath) + } +} + +func serializeCompilerOptions(options *core.CompilerOptions, configFilePath string, comparePathsOptions tspath.ComparePathsOptions) *collections.OrderedMap[string, any] { + result := collections.NewOrderedMapWithSizeHint[string, any](32) + if options.AllowJs == core.TSTrue || options.AllowJs == core.TSFalse { + result.Set("allowJs", options.AllowJs == core.TSTrue) + } + if options.AllowArbitraryExtensions == core.TSTrue || options.AllowArbitraryExtensions == core.TSFalse { + result.Set("allowArbitraryExtensions", options.AllowArbitraryExtensions == core.TSTrue) + } + if options.AllowImportingTsExtensions == core.TSTrue || options.AllowImportingTsExtensions == core.TSFalse { + result.Set("allowImportingTsExtensions", options.AllowImportingTsExtensions == core.TSTrue) + } + if options.AllowUmdGlobalAccess == core.TSTrue || options.AllowUmdGlobalAccess == core.TSFalse { + result.Set("allowUmdGlobalAccess", options.AllowUmdGlobalAccess == core.TSTrue) + } + if options.AllowUnreachableCode == core.TSTrue || options.AllowUnreachableCode == core.TSFalse { + result.Set("allowUnreachableCode", options.AllowUnreachableCode == core.TSTrue) + } + if options.AllowUnusedLabels == core.TSTrue || options.AllowUnusedLabels == core.TSFalse { + result.Set("allowUnusedLabels", options.AllowUnusedLabels == core.TSTrue) + } + if options.AssumeChangesOnlyAffectDirectDependencies == core.TSTrue || options.AssumeChangesOnlyAffectDirectDependencies == core.TSFalse { + result.Set("assumeChangesOnlyAffectDirectDependencies", options.AssumeChangesOnlyAffectDirectDependencies == core.TSTrue) + } + if options.CheckJs == core.TSTrue || options.CheckJs == core.TSFalse { + result.Set("checkJs", options.CheckJs == core.TSTrue) + } + if options.CustomConditions != nil { + result.Set("customConditions", options.CustomConditions) + } + if options.Composite == core.TSTrue || options.Composite == core.TSFalse { + result.Set("composite", options.Composite == core.TSTrue) + } + if options.EmitDeclarationOnly == core.TSTrue || options.EmitDeclarationOnly == core.TSFalse { + result.Set("emitDeclarationOnly", options.EmitDeclarationOnly == core.TSTrue) + } + if options.EmitBOM == core.TSTrue || options.EmitBOM == core.TSFalse { + result.Set("emitBOM", options.EmitBOM == core.TSTrue) + } + if options.EmitDecoratorMetadata == core.TSTrue || options.EmitDecoratorMetadata == core.TSFalse { + result.Set("emitDecoratorMetadata", options.EmitDecoratorMetadata == core.TSTrue) + } + if options.Declaration == core.TSTrue || options.Declaration == core.TSFalse { + result.Set("declaration", options.Declaration == core.TSTrue) + } + if options.DeclarationDir != "" { + result.Set("declarationDir", serializeCompilerOptionPath(options.DeclarationDir, configFilePath, comparePathsOptions)) + } + if options.DeclarationMap == core.TSTrue || options.DeclarationMap == core.TSFalse { + result.Set("declarationMap", options.DeclarationMap == core.TSTrue) + } + if options.DeduplicatePackages == core.TSTrue || options.DeduplicatePackages == core.TSFalse { + result.Set("deduplicatePackages", options.DeduplicatePackages == core.TSTrue) + } + if options.DisableSizeLimit == core.TSTrue || options.DisableSizeLimit == core.TSFalse { + result.Set("disableSizeLimit", options.DisableSizeLimit == core.TSTrue) + } + if options.DisableSourceOfProjectReferenceRedirect == core.TSTrue || options.DisableSourceOfProjectReferenceRedirect == core.TSFalse { + result.Set("disableSourceOfProjectReferenceRedirect", options.DisableSourceOfProjectReferenceRedirect == core.TSTrue) + } + if options.DisableSolutionSearching == core.TSTrue || options.DisableSolutionSearching == core.TSFalse { + result.Set("disableSolutionSearching", options.DisableSolutionSearching == core.TSTrue) + } + if options.DisableReferencedProjectLoad == core.TSTrue || options.DisableReferencedProjectLoad == core.TSFalse { + result.Set("disableReferencedProjectLoad", options.DisableReferencedProjectLoad == core.TSTrue) + } + if options.ErasableSyntaxOnly == core.TSTrue || options.ErasableSyntaxOnly == core.TSFalse { + result.Set("erasableSyntaxOnly", options.ErasableSyntaxOnly == core.TSTrue) + } + if options.ExactOptionalPropertyTypes == core.TSTrue || options.ExactOptionalPropertyTypes == core.TSFalse { + result.Set("exactOptionalPropertyTypes", options.ExactOptionalPropertyTypes == core.TSTrue) + } + if options.ExperimentalDecorators == core.TSTrue || options.ExperimentalDecorators == core.TSFalse { + result.Set("experimentalDecorators", options.ExperimentalDecorators == core.TSTrue) + } + if options.ForceConsistentCasingInFileNames == core.TSTrue || options.ForceConsistentCasingInFileNames == core.TSFalse { + result.Set("forceConsistentCasingInFileNames", options.ForceConsistentCasingInFileNames == core.TSTrue) + } + if options.IsolatedModules == core.TSTrue || options.IsolatedModules == core.TSFalse { + result.Set("isolatedModules", options.IsolatedModules == core.TSTrue) + } + if options.IsolatedDeclarations == core.TSTrue || options.IsolatedDeclarations == core.TSFalse { + result.Set("isolatedDeclarations", options.IsolatedDeclarations == core.TSTrue) + } + if options.IgnoreDeprecations != "" { + result.Set("ignoreDeprecations", options.IgnoreDeprecations) + } + if options.ImportHelpers == core.TSTrue || options.ImportHelpers == core.TSFalse { + result.Set("importHelpers", options.ImportHelpers == core.TSTrue) + } + if options.InlineSourceMap == core.TSTrue || options.InlineSourceMap == core.TSFalse { + result.Set("inlineSourceMap", options.InlineSourceMap == core.TSTrue) + } + if options.InlineSources == core.TSTrue || options.InlineSources == core.TSFalse { + result.Set("inlineSources", options.InlineSources == core.TSTrue) + } + if options.Incremental == core.TSTrue || options.Incremental == core.TSFalse { + result.Set("incremental", options.Incremental == core.TSTrue) + } + if options.Jsx != 0 { + if value := serializeCompilerOptionEnum(options.Jsx); value != "" { + result.Set("jsx", value) + } + } + if options.JsxFactory != "" { + result.Set("jsxFactory", options.JsxFactory) + } + if options.JsxFragmentFactory != "" { + result.Set("jsxFragmentFactory", options.JsxFragmentFactory) + } + if options.JsxImportSource != "" { + result.Set("jsxImportSource", options.JsxImportSource) + } + if options.Lib != nil { + result.Set("lib", serializeCompilerOptionEnumList(options.Lib, LibMap)) + } + if options.LibReplacement == core.TSTrue || options.LibReplacement == core.TSFalse { + result.Set("libReplacement", options.LibReplacement == core.TSTrue) + } + if options.MapRoot != "" { + result.Set("mapRoot", options.MapRoot) + } + if options.Module != 0 { + if value := serializeCompilerOptionEnum(options.Module); value != "" { + result.Set("module", value) + } + } + if options.ModuleResolution != 0 { + if value := serializeCompilerOptionEnum(options.ModuleResolution); value != "" { + result.Set("moduleResolution", value) + } + } + if options.ModuleSuffixes != nil { + result.Set("moduleSuffixes", options.ModuleSuffixes) + } + if options.ModuleDetection != 0 { + if value := serializeCompilerOptionEnum(options.ModuleDetection); value != "" { + result.Set("moduleDetection", value) + } + } + if options.NewLine != 0 { + if value := serializeCompilerOptionEnum(options.NewLine); value != "" { + result.Set("newLine", value) + } + } + if options.NoEmit == core.TSTrue || options.NoEmit == core.TSFalse { + result.Set("noEmit", options.NoEmit == core.TSTrue) + } + if options.NoCheck == core.TSTrue || options.NoCheck == core.TSFalse { + result.Set("noCheck", options.NoCheck == core.TSTrue) + } + if options.NoFallthroughCasesInSwitch == core.TSTrue || options.NoFallthroughCasesInSwitch == core.TSFalse { + result.Set("noFallthroughCasesInSwitch", options.NoFallthroughCasesInSwitch == core.TSTrue) + } + if options.NoImplicitAny == core.TSTrue || options.NoImplicitAny == core.TSFalse { + result.Set("noImplicitAny", options.NoImplicitAny == core.TSTrue) + } + if options.NoImplicitThis == core.TSTrue || options.NoImplicitThis == core.TSFalse { + result.Set("noImplicitThis", options.NoImplicitThis == core.TSTrue) + } + if options.NoImplicitReturns == core.TSTrue || options.NoImplicitReturns == core.TSFalse { + result.Set("noImplicitReturns", options.NoImplicitReturns == core.TSTrue) + } + if options.NoEmitHelpers == core.TSTrue || options.NoEmitHelpers == core.TSFalse { + result.Set("noEmitHelpers", options.NoEmitHelpers == core.TSTrue) + } + if options.NoLib == core.TSTrue || options.NoLib == core.TSFalse { + result.Set("noLib", options.NoLib == core.TSTrue) + } + if options.NoPropertyAccessFromIndexSignature == core.TSTrue || options.NoPropertyAccessFromIndexSignature == core.TSFalse { + result.Set("noPropertyAccessFromIndexSignature", options.NoPropertyAccessFromIndexSignature == core.TSTrue) + } + if options.NoUncheckedIndexedAccess == core.TSTrue || options.NoUncheckedIndexedAccess == core.TSFalse { + result.Set("noUncheckedIndexedAccess", options.NoUncheckedIndexedAccess == core.TSTrue) + } + if options.NoEmitOnError == core.TSTrue || options.NoEmitOnError == core.TSFalse { + result.Set("noEmitOnError", options.NoEmitOnError == core.TSTrue) + } + if options.NoUnusedLocals == core.TSTrue || options.NoUnusedLocals == core.TSFalse { + result.Set("noUnusedLocals", options.NoUnusedLocals == core.TSTrue) + } + if options.NoUnusedParameters == core.TSTrue || options.NoUnusedParameters == core.TSFalse { + result.Set("noUnusedParameters", options.NoUnusedParameters == core.TSTrue) + } + if options.NoResolve == core.TSTrue || options.NoResolve == core.TSFalse { + result.Set("noResolve", options.NoResolve == core.TSTrue) + } + if options.NoImplicitOverride == core.TSTrue || options.NoImplicitOverride == core.TSFalse { + result.Set("noImplicitOverride", options.NoImplicitOverride == core.TSTrue) + } + if options.NoUncheckedSideEffectImports == core.TSTrue || options.NoUncheckedSideEffectImports == core.TSFalse { + result.Set("noUncheckedSideEffectImports", options.NoUncheckedSideEffectImports == core.TSTrue) + } + if options.OutDir != "" { + result.Set("outDir", serializeCompilerOptionPath(options.OutDir, configFilePath, comparePathsOptions)) + } + if options.Paths != nil { + result.Set("paths", options.Paths) + } + if options.Plugins != nil { + result.Set("plugins", options.Plugins) + } + if options.PreserveConstEnums == core.TSTrue || options.PreserveConstEnums == core.TSFalse { + result.Set("preserveConstEnums", options.PreserveConstEnums == core.TSTrue) + } + if options.PreserveSymlinks == core.TSTrue || options.PreserveSymlinks == core.TSFalse { + result.Set("preserveSymlinks", options.PreserveSymlinks == core.TSTrue) + } + if options.ResolveJsonModule == core.TSTrue || options.ResolveJsonModule == core.TSFalse { + result.Set("resolveJsonModule", options.ResolveJsonModule == core.TSTrue) + } + if options.ResolvePackageJsonExports == core.TSTrue || options.ResolvePackageJsonExports == core.TSFalse { + result.Set("resolvePackageJsonExports", options.ResolvePackageJsonExports == core.TSTrue) + } + if options.ResolvePackageJsonImports == core.TSTrue || options.ResolvePackageJsonImports == core.TSFalse { + result.Set("resolvePackageJsonImports", options.ResolvePackageJsonImports == core.TSTrue) + } + if options.RemoveComments == core.TSTrue || options.RemoveComments == core.TSFalse { + result.Set("removeComments", options.RemoveComments == core.TSTrue) + } + if options.RewriteRelativeImportExtensions == core.TSTrue || options.RewriteRelativeImportExtensions == core.TSFalse { + result.Set("rewriteRelativeImportExtensions", options.RewriteRelativeImportExtensions == core.TSTrue) + } + if options.ReactNamespace != "" { + result.Set("reactNamespace", options.ReactNamespace) + } + if options.RootDir != "" { + result.Set("rootDir", serializeCompilerOptionPath(options.RootDir, configFilePath, comparePathsOptions)) + } + if options.RootDirs != nil { + result.Set("rootDirs", serializeCompilerOptionPaths(options.RootDirs, configFilePath, comparePathsOptions)) + } + if options.SkipLibCheck == core.TSTrue || options.SkipLibCheck == core.TSFalse { + result.Set("skipLibCheck", options.SkipLibCheck == core.TSTrue) + } + if options.StableTypeOrdering == core.TSTrue || options.StableTypeOrdering == core.TSFalse { + result.Set("stableTypeOrdering", options.StableTypeOrdering == core.TSTrue) + } + if options.Strict == core.TSTrue || options.Strict == core.TSFalse { + result.Set("strict", options.Strict == core.TSTrue) + } + if options.StrictBindCallApply == core.TSTrue || options.StrictBindCallApply == core.TSFalse { + result.Set("strictBindCallApply", options.StrictBindCallApply == core.TSTrue) + } + if options.StrictBuiltinIteratorReturn == core.TSTrue || options.StrictBuiltinIteratorReturn == core.TSFalse { + result.Set("strictBuiltinIteratorReturn", options.StrictBuiltinIteratorReturn == core.TSTrue) + } + if options.StrictFunctionTypes == core.TSTrue || options.StrictFunctionTypes == core.TSFalse { + result.Set("strictFunctionTypes", options.StrictFunctionTypes == core.TSTrue) + } + if options.StrictNullChecks == core.TSTrue || options.StrictNullChecks == core.TSFalse { + result.Set("strictNullChecks", options.StrictNullChecks == core.TSTrue) + } + if options.StrictPropertyInitialization == core.TSTrue || options.StrictPropertyInitialization == core.TSFalse { + result.Set("strictPropertyInitialization", options.StrictPropertyInitialization == core.TSTrue) + } + if options.StripInternal == core.TSTrue || options.StripInternal == core.TSFalse { + result.Set("stripInternal", options.StripInternal == core.TSTrue) + } + if options.SkipDefaultLibCheck == core.TSTrue || options.SkipDefaultLibCheck == core.TSFalse { + result.Set("skipDefaultLibCheck", options.SkipDefaultLibCheck == core.TSTrue) + } + if options.SourceMap == core.TSTrue || options.SourceMap == core.TSFalse { + result.Set("sourceMap", options.SourceMap == core.TSTrue) + } + if options.SourceRoot != "" { + result.Set("sourceRoot", options.SourceRoot) + } + if options.Target != 0 { + if value := serializeCompilerOptionEnum(options.Target); value != "" { + result.Set("target", value) + } + } + if options.TraceResolution == core.TSTrue || options.TraceResolution == core.TSFalse { + result.Set("traceResolution", options.TraceResolution == core.TSTrue) + } + if options.TsBuildInfoFile != "" { + result.Set("tsBuildInfoFile", serializeCompilerOptionPath(options.TsBuildInfoFile, configFilePath, comparePathsOptions)) + } + if options.TypeRoots != nil { + result.Set("typeRoots", serializeCompilerOptionPaths(options.TypeRoots, configFilePath, comparePathsOptions)) + } + if options.Types != nil { + result.Set("types", options.Types) + } + if options.UseDefineForClassFields == core.TSTrue || options.UseDefineForClassFields == core.TSFalse { + result.Set("useDefineForClassFields", options.UseDefineForClassFields == core.TSTrue) + } + if options.UseUnknownInCatchVariables == core.TSTrue || options.UseUnknownInCatchVariables == core.TSFalse { + result.Set("useUnknownInCatchVariables", options.UseUnknownInCatchVariables == core.TSTrue) + } + if options.VerbatimModuleSyntax == core.TSTrue || options.VerbatimModuleSyntax == core.TSFalse { + result.Set("verbatimModuleSyntax", options.VerbatimModuleSyntax == core.TSTrue) + } + if options.MaxNodeModuleJsDepth != nil { + result.Set("maxNodeModuleJsDepth", options.MaxNodeModuleJsDepth) + } + if options.AllowSyntheticDefaultImports == core.TSTrue || options.AllowSyntheticDefaultImports == core.TSFalse { + result.Set("allowSyntheticDefaultImports", options.AllowSyntheticDefaultImports == core.TSTrue) + } + if options.AlwaysStrict == core.TSTrue || options.AlwaysStrict == core.TSFalse { + result.Set("alwaysStrict", options.AlwaysStrict == core.TSTrue) + } + if options.BaseUrl != "" { + result.Set("baseUrl", serializeCompilerOptionPath(options.BaseUrl, configFilePath, comparePathsOptions)) + } + if options.DownlevelIteration == core.TSTrue || options.DownlevelIteration == core.TSFalse { + result.Set("downlevelIteration", options.DownlevelIteration == core.TSTrue) + } + if options.ESModuleInterop == core.TSTrue || options.ESModuleInterop == core.TSFalse { + result.Set("esModuleInterop", options.ESModuleInterop == core.TSTrue) + } + if options.OutFile != "" { + result.Set("outFile", serializeCompilerOptionPath(options.OutFile, configFilePath, comparePathsOptions)) + } + if options.Diagnostics == core.TSTrue || options.Diagnostics == core.TSFalse { + result.Set("diagnostics", options.Diagnostics == core.TSTrue) + } + if options.ExtendedDiagnostics == core.TSTrue || options.ExtendedDiagnostics == core.TSFalse { + result.Set("extendedDiagnostics", options.ExtendedDiagnostics == core.TSTrue) + } + if options.GenerateCpuProfile != "" { + result.Set("generateCpuProfile", serializeCompilerOptionPath(options.GenerateCpuProfile, configFilePath, comparePathsOptions)) + } + if options.GenerateTrace != "" { + result.Set("generateTrace", serializeCompilerOptionPath(options.GenerateTrace, configFilePath, comparePathsOptions)) + } + if options.ListEmittedFiles == core.TSTrue || options.ListEmittedFiles == core.TSFalse { + result.Set("listEmittedFiles", options.ListEmittedFiles == core.TSTrue) + } + if options.ListFiles == core.TSTrue || options.ListFiles == core.TSFalse { + result.Set("listFiles", options.ListFiles == core.TSTrue) + } + if options.ExplainFiles == core.TSTrue || options.ExplainFiles == core.TSFalse { + result.Set("explainFiles", options.ExplainFiles == core.TSTrue) + } + return result +} + +func serializeCompilerOptionEnum(value any) string { + switch value := value.(type) { + case core.JsxEmit: + if value == core.JsxEmitPreserve { + return "preserve" + } + if value == core.JsxEmitReactNative { + return "react-native" + } + if value == core.JsxEmitReactJSX { + return "react-jsx" + } + if value == core.JsxEmitReactJSXDev { + return "react-jsxdev" + } + if value == core.JsxEmitReact { + return "react" + } + case core.ModuleKind: + if value == core.ModuleKindCommonJS { + return "commonjs" + } + if value == core.ModuleKindAMD { + return "amd" + } + if value == core.ModuleKindSystem { + return "system" + } + if value == core.ModuleKindUMD { + return "umd" + } + if value == core.ModuleKindES2015 { + return "es6" + } + if value == core.ModuleKindES2020 { + return "es2020" + } + if value == core.ModuleKindES2022 { + return "es2022" + } + if value == core.ModuleKindESNext { + return "esnext" + } + if value == core.ModuleKindNode16 { + return "node16" + } + if value == core.ModuleKindNode18 { + return "node18" + } + if value == core.ModuleKindNode20 { + return "node20" + } + if value == core.ModuleKindNodeNext { + return "nodenext" + } + if value == core.ModuleKindPreserve { + return "preserve" + } + case core.ModuleResolutionKind: + if value == core.ModuleResolutionKindNode16 { + return "node16" + } + if value == core.ModuleResolutionKindNodeNext { + return "nodenext" + } + if value == core.ModuleResolutionKindBundler { + return "bundler" + } + if value == core.ModuleResolutionKindClassic { + return "classic" + } + if value == core.ModuleResolutionKindNode10 { + return "node" + } + case core.ModuleDetectionKind: + if value == core.ModuleDetectionKindAuto { + return "auto" + } + if value == core.ModuleDetectionKindLegacy { + return "legacy" + } + if value == core.ModuleDetectionKindForce { + return "force" + } + case core.NewLineKind: + if value == core.NewLineKindCRLF { + return "crlf" + } + if value == core.NewLineKindLF { + return "lf" + } + case core.ScriptTarget: + if value == core.ScriptTargetES5 { + return "es5" + } + if value == core.ScriptTargetES2015 { + return "es6" + } + if value == core.ScriptTargetES2016 { + return "es2016" + } + if value == core.ScriptTargetES2017 { + return "es2017" + } + if value == core.ScriptTargetES2018 { + return "es2018" + } + if value == core.ScriptTargetES2019 { + return "es2019" + } + if value == core.ScriptTargetES2020 { + return "es2020" + } + if value == core.ScriptTargetES2021 { + return "es2021" + } + if value == core.ScriptTargetES2022 { + return "es2022" + } + if value == core.ScriptTargetES2023 { + return "es2023" + } + if value == core.ScriptTargetES2024 { + return "es2024" + } + if value == core.ScriptTargetES2025 { + return "es2025" + } + if value == core.ScriptTargetESNext { + return "esnext" + } + } + return "" +} diff --git a/tsc/internal/tsoptions/parsedoptions.go b/tsc/internal/tsoptions/parsedoptions.go index 9922ccda24628..c257af76bc616 100644 --- a/tsc/internal/tsoptions/parsedoptions.go +++ b/tsc/internal/tsoptions/parsedoptions.go @@ -1,6 +1,8 @@ package tsoptions import ( + "slices" + "github.com/microsoft/TypeScript/tsc/internal/contentmapper" "github.com/microsoft/TypeScript/tsc/internal/core" ) @@ -14,3 +16,26 @@ type ParsedOptions struct { ProjectReferences []*core.ProjectReference `json:"projectReferences"` ContentMappers []*contentmapper.Mapper `json:"contentMappers"` } + +// Equals compares parsed configuration values using each option type's equality semantics. +func (p *ParsedOptions) Equals(other *ParsedOptions) bool { + if p == other { + return true + } + if p == nil || other == nil { + return false + } + if !p.CompilerOptions.Equals(other.CompilerOptions) || + !p.WatchOptions.Equals(other.WatchOptions) || + !p.TypeAcquisition.Equals(other.TypeAcquisition) { + return false + } + return (p.FileNames == nil) == (other.FileNames == nil) && + slices.Equal(p.FileNames, other.FileNames) && + (p.ProjectReferences == nil) == (other.ProjectReferences == nil) && + slices.EqualFunc(p.ProjectReferences, other.ProjectReferences, func(a, b *core.ProjectReference) bool { + return a == b || a != nil && b != nil && *a == *b + }) && + (p.ContentMappers == nil) == (other.ContentMappers == nil) && + slices.EqualFunc(p.ContentMappers, other.ContentMappers, (*contentmapper.Mapper).Equals) +} diff --git a/tsc/internal/tsoptions/parsedoptions_test.go b/tsc/internal/tsoptions/parsedoptions_test.go new file mode 100644 index 0000000000000..191be1a0a5f9a --- /dev/null +++ b/tsc/internal/tsoptions/parsedoptions_test.go @@ -0,0 +1,194 @@ +package tsoptions + +import ( + "reflect" + "testing" + + "github.com/microsoft/TypeScript/tsc/internal/collections" + "github.com/microsoft/TypeScript/tsc/internal/contentmapper" + "github.com/microsoft/TypeScript/tsc/internal/core" +) + +func TestParsedOptionsEquality(t *testing.T) { + t.Parallel() + + check := func(t *testing.T, a, b *ParsedOptions) { + t.Helper() + if got, want := a.Equals(b), reflect.DeepEqual(a, b); got != want { + t.Fatalf("Got %v, want %v for\n%+v\n%+v", got, want, a, b) + } + } + check(t, nil, nil) + check(t, nil, &ParsedOptions{}) + check(t, &ParsedOptions{}, nil) + check(t, &ParsedOptions{}, &ParsedOptions{}) + makeOptions := func() *ParsedOptions { + return &ParsedOptions{ + CompilerOptions: &core.CompilerOptions{Strict: core.TSTrue}, + WatchOptions: &core.WatchOptions{ + Interval: new(10), FileKind: core.WatchFileKindUseFsEvents, + ExcludeDir: []string{"dir"}, ExcludeFiles: []string{"file"}, + }, + TypeAcquisition: &core.TypeAcquisition{Enable: core.TSTrue, Include: []string{"a"}, Exclude: []string{"b"}}, + FileNames: []string{"a.ts", "b.ts"}, + ProjectReferences: []*core.ProjectReference{ + {Path: "/project", OriginalPath: "../project", Circular: true}, nil, + }, + ContentMappers: []*contentmapper.Mapper{{ + Package: "mapper", Extensions: []string{".vue"}, Options: []byte(`{"setting":true}`), + Name: "mapper", Version: "1", Exec: []string{"node", "mapper.js"}, CompilerOptions: []string{"target"}, DynamicConfig: true, + PackageDirectory: "/node_modules/mapper", ContributionID: "extension", + }, nil}, + } + } + check(t, makeOptions(), makeOptions()) + for _, object := range []func(*ParsedOptions) any{ + func(p *ParsedOptions) any { return p }, + func(p *ParsedOptions) any { return p.ContentMappers[0] }, + } { + typ := reflect.TypeOf(object(makeOptions())).Elem() + for _, field := range reflect.VisibleFields(typ) { + if field.Anonymous && field.Type.Kind() == reflect.Struct { + continue + } + t.Run("field coverage/"+typ.Name()+"/"+field.Name, func(t *testing.T) { + t.Parallel() + a, b := makeOptions(), makeOptions() + value := reflect.ValueOf(object(b)).Elem().FieldByIndex(field.Index) + if !value.CanSet() { + t.Fatalf("Add explicit equality coverage for %s.%s", typ.Name(), field.Name) + } + if value.IsZero() { + t.Fatalf("Populate %s.%s in makeOptions so its equality is exercised", typ.Name(), field.Name) + } + value.SetZero() + check(t, a, b) + check(t, b, a) + }) + } + } + for _, test := range []struct { + name string + change func(*ParsedOptions) + }{ + {"compiler options", func(p *ParsedOptions) { p.CompilerOptions.Strict = core.TSFalse }}, + {"nil compiler options", func(p *ParsedOptions) { p.CompilerOptions = nil }}, + {"nil watch options", func(p *ParsedOptions) { p.WatchOptions = nil }}, + {"watch interval", func(p *ParsedOptions) { p.WatchOptions.Interval = new(20) }}, + {"nil type acquisition", func(p *ParsedOptions) { p.TypeAcquisition = nil }}, + {"type acquisition enable", func(p *ParsedOptions) { p.TypeAcquisition.Enable = core.TSFalse }}, + {"type acquisition include", func(p *ParsedOptions) { p.TypeAcquisition.Include[0] = "other" }}, + {"type acquisition exclude", func(p *ParsedOptions) { p.TypeAcquisition.Exclude[0] = "other" }}, + {"type acquisition filename", func(p *ParsedOptions) { p.TypeAcquisition.DisableFilenameBasedTypeAcquisition = core.TSTrue }}, + {"filenames order", func(p *ParsedOptions) { p.FileNames = []string{"b.ts", "a.ts"} }}, + {"reference path", func(p *ParsedOptions) { p.ProjectReferences[0].Path = "/other" }}, + {"reference original path", func(p *ParsedOptions) { p.ProjectReferences[0].OriginalPath = "./other" }}, + {"reference circular", func(p *ParsedOptions) { p.ProjectReferences[0].Circular = false }}, + {"nil reference", func(p *ParsedOptions) { p.ProjectReferences[0] = nil }}, + {"reference order", func(p *ParsedOptions) { + p.ProjectReferences[0], p.ProjectReferences[1] = p.ProjectReferences[1], p.ProjectReferences[0] + }}, + {"mapper package", func(p *ParsedOptions) { p.ContentMappers[0].Package = "other" }}, + {"mapper extension", func(p *ParsedOptions) { p.ContentMappers[0].Extensions[0] = ".other" }}, + {"mapper options", func(p *ParsedOptions) { p.ContentMappers[0].Options = []byte(`{}`) }}, + {"mapper name", func(p *ParsedOptions) { p.ContentMappers[0].Name = "other" }}, + {"mapper version", func(p *ParsedOptions) { p.ContentMappers[0].Version = "2" }}, + {"mapper exec", func(p *ParsedOptions) { p.ContentMappers[0].Exec[1] = "other.js" }}, + {"mapper compiler options", func(p *ParsedOptions) { p.ContentMappers[0].CompilerOptions[0] = "jsx" }}, + {"mapper dynamic config", func(p *ParsedOptions) { p.ContentMappers[0].DynamicConfig = false }}, + {"mapper directory", func(p *ParsedOptions) { p.ContentMappers[0].PackageDirectory = "/other" }}, + {"mapper contribution", func(p *ParsedOptions) { p.ContentMappers[0].ContributionID = "other" }}, + {"nil mapper", func(p *ParsedOptions) { p.ContentMappers[0] = nil }}, + {"mapper order", func(p *ParsedOptions) { + p.ContentMappers[0], p.ContentMappers[1] = p.ContentMappers[1], p.ContentMappers[0] + }}, + } { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + a, b := makeOptions(), makeOptions() + test.change(b) + check(t, a, b) + check(t, b, a) + check(t, b, b) + }) + } + + // Each slice's nil and empty forms remain distinct. + for _, typ := range []reflect.Type{ + reflect.TypeFor[ParsedOptions](), + reflect.TypeFor[contentmapper.Definition](), reflect.TypeFor[contentmapper.Manifest](), + } { + for field := range typ.Fields() { + if field.Type.Kind() != reflect.Slice { + continue + } + t.Run(typ.Name()+"/"+field.Name, func(t *testing.T) { + t.Parallel() + a, b := makeOptions(), makeOptions() + for i, p := range []*ParsedOptions{a, b} { + var object any = p + switch typ { + case reflect.TypeFor[contentmapper.Definition](): + object = &p.ContentMappers[0].Definition + case reflect.TypeFor[contentmapper.Manifest](): + object = &p.ContentMappers[0].Manifest + } + value := reflect.ValueOf(object).Elem().FieldByIndex(field.Index) + if i == 0 { + value.SetZero() + } else { + value.Set(reflect.MakeSlice(field.Type, 0, 0)) + } + } + check(t, a, b) + check(t, b, a) + }) + } + } + + for field := range reflect.TypeFor[core.WatchOptions]().Fields() { + t.Run("watch/"+field.Name, func(t *testing.T) { + t.Parallel() + for _, aValue := range compilerOptionTestValues(t, field) { + for _, bValue := range compilerOptionTestValues(t, field) { + a, b := makeOptions(), makeOptions() + reflect.ValueOf(a.WatchOptions).Elem().FieldByIndex(field.Index).Set(aValue) + reflect.ValueOf(b.WatchOptions).Elem().FieldByIndex(field.Index).Set(bValue) + check(t, a, b) + } + } + }) + } +} + +func TestParsedOptionsEqualityIgnoresEmptyTypeAcquisitionLists(t *testing.T) { + t.Parallel() + + options := []*core.TypeAcquisition{ + {}, + {Include: []string{}}, + {Exclude: []string{}}, + {Include: []string{}, Exclude: []string{}}, + } + for _, a := range options { + for _, b := range options { + left := &ParsedOptions{TypeAcquisition: a} + right := &ParsedOptions{TypeAcquisition: b} + if !left.Equals(right) { + t.Fatalf("Nil and empty type acquisition lists must compare equal: %+v, %+v", a, b) + } + } + } +} + +func TestParsedOptionsEqualityIgnoresPathsAllocation(t *testing.T) { + t.Parallel() + + zero := &collections.OrderedMap[string, []string]{} + allocated := collections.NewOrderedMapWithSizeHint[string, []string](0) + a := &ParsedOptions{CompilerOptions: &core.CompilerOptions{Paths: zero}} + b := &ParsedOptions{CompilerOptions: &core.CompilerOptions{Paths: allocated}} + if !a.Equals(b) || !b.Equals(a) { + t.Fatal("Empty paths maps must compare equal regardless of allocation") + } +} diff --git a/tsc/internal/tsoptions/parsinghelpers.go b/tsc/internal/tsoptions/parsinghelpers.go index 11180c49cb0e7..2ff2c15253ba3 100644 --- a/tsc/internal/tsoptions/parsinghelpers.go +++ b/tsc/internal/tsoptions/parsinghelpers.go @@ -1,9 +1,6 @@ package tsoptions import ( - "reflect" - "strings" - "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" "github.com/microsoft/TypeScript/tsc/internal/contentmapper" @@ -276,297 +273,6 @@ func ParseCompilerOptions(key string, value any, allOptions *core.CompilerOption return nil } -func parseCompilerOptions(key string, value any, allOptions *core.CompilerOptions) (foundKey bool) { - option := CommandLineCompilerOptionsMap.Get(key) - if option != nil { - key = option.Name - } - switch key { - case "allowJs": - allOptions.AllowJs = ParseTristate(value) - case "allowImportingTsExtensions": - allOptions.AllowImportingTsExtensions = ParseTristate(value) - case "allowSyntheticDefaultImports": - allOptions.AllowSyntheticDefaultImports = ParseTristate(value) - case "allowNonTsExtensions": - allOptions.AllowNonTsExtensions = ParseTristate(value) - case "allowUmdGlobalAccess": - allOptions.AllowUmdGlobalAccess = ParseTristate(value) - case "allowUnreachableCode": - allOptions.AllowUnreachableCode = ParseTristate(value) - case "allowUnusedLabels": - allOptions.AllowUnusedLabels = ParseTristate(value) - case "allowArbitraryExtensions": - allOptions.AllowArbitraryExtensions = ParseTristate(value) - case "alwaysStrict": - allOptions.AlwaysStrict = ParseTristate(value) - case "assumeChangesOnlyAffectDirectDependencies": - allOptions.AssumeChangesOnlyAffectDirectDependencies = ParseTristate(value) - case "baseUrl": - allOptions.BaseUrl = ParseString(value) - case "build": - allOptions.Build = ParseTristate(value) - case "checkJs": - allOptions.CheckJs = ParseTristate(value) - case "customConditions": - allOptions.CustomConditions = ParseStringArray(value) - case "composite": - allOptions.Composite = ParseTristate(value) - case "declarationDir": - allOptions.DeclarationDir = ParseString(value) - case "deduplicatePackages": - allOptions.DeduplicatePackages = ParseTristate(value) - case "diagnostics": - allOptions.Diagnostics = ParseTristate(value) - case "disableSizeLimit": - allOptions.DisableSizeLimit = ParseTristate(value) - case "disableSourceOfProjectReferenceRedirect": - allOptions.DisableSourceOfProjectReferenceRedirect = ParseTristate(value) - case "disableSolutionSearching": - allOptions.DisableSolutionSearching = ParseTristate(value) - case "disableReferencedProjectLoad": - allOptions.DisableReferencedProjectLoad = ParseTristate(value) - case "declarationMap": - allOptions.DeclarationMap = ParseTristate(value) - case "declaration": - allOptions.Declaration = ParseTristate(value) - case "downlevelIteration": - allOptions.DownlevelIteration = ParseTristate(value) - case "erasableSyntaxOnly": - allOptions.ErasableSyntaxOnly = ParseTristate(value) - case "emitDeclarationOnly": - allOptions.EmitDeclarationOnly = ParseTristate(value) - case "extendedDiagnostics": - allOptions.ExtendedDiagnostics = ParseTristate(value) - case "emitDecoratorMetadata": - allOptions.EmitDecoratorMetadata = ParseTristate(value) - case "emitBOM": - allOptions.EmitBOM = ParseTristate(value) - case "esModuleInterop": - allOptions.ESModuleInterop = ParseTristate(value) - case "exactOptionalPropertyTypes": - allOptions.ExactOptionalPropertyTypes = ParseTristate(value) - case "explainFiles": - allOptions.ExplainFiles = ParseTristate(value) - case "experimentalDecorators": - allOptions.ExperimentalDecorators = ParseTristate(value) - case "forceConsistentCasingInFileNames": - allOptions.ForceConsistentCasingInFileNames = ParseTristate(value) - case "generateCpuProfile": - allOptions.GenerateCpuProfile = ParseString(value) - case "generateTrace": - allOptions.GenerateTrace = ParseString(value) - case "isolatedModules": - allOptions.IsolatedModules = ParseTristate(value) - case "ignoreConfig": - allOptions.IgnoreConfig = ParseTristate(value) - case "ignoreDeprecations": - allOptions.IgnoreDeprecations = ParseString(value) - case "importHelpers": - allOptions.ImportHelpers = ParseTristate(value) - case "incremental": - allOptions.Incremental = ParseTristate(value) - case "init": - allOptions.Init = ParseTristate(value) - case "inlineSourceMap": - allOptions.InlineSourceMap = ParseTristate(value) - case "inlineSources": - allOptions.InlineSources = ParseTristate(value) - case "isolatedDeclarations": - allOptions.IsolatedDeclarations = ParseTristate(value) - case "jsx": - allOptions.Jsx = floatOrInt32ToFlag[core.JsxEmit](value) - case "jsxFactory": - allOptions.JsxFactory = ParseString(value) - case "jsxFragmentFactory": - allOptions.JsxFragmentFactory = ParseString(value) - case "jsxImportSource": - allOptions.JsxImportSource = ParseString(value) - case "lib": - if _, ok := value.([]string); ok { - allOptions.Lib = value.([]string) - } else { - allOptions.Lib = ParseStringArray(value) - } - case "libReplacement": - allOptions.LibReplacement = ParseTristate(value) - case "listEmittedFiles": - allOptions.ListEmittedFiles = ParseTristate(value) - case "listFiles": - allOptions.ListFiles = ParseTristate(value) - case "listFilesOnly": - allOptions.ListFilesOnly = ParseTristate(value) - case "locale": - allOptions.Locale = ParseString(value) - case "mapRoot": - allOptions.MapRoot = ParseString(value) - case "module": - allOptions.Module = floatOrInt32ToFlag[core.ModuleKind](value) - case "moduleDetectionKind": - allOptions.ModuleDetection = floatOrInt32ToFlag[core.ModuleDetectionKind](value) - case "moduleResolution": - allOptions.ModuleResolution = floatOrInt32ToFlag[core.ModuleResolutionKind](value) - case "moduleSuffixes": - allOptions.ModuleSuffixes = ParseStringArray(value) - case "moduleDetection": - allOptions.ModuleDetection = floatOrInt32ToFlag[core.ModuleDetectionKind](value) - case "noCheck": - allOptions.NoCheck = ParseTristate(value) - case "noFallthroughCasesInSwitch": - allOptions.NoFallthroughCasesInSwitch = ParseTristate(value) - case "noEmitForJsFiles": - allOptions.NoEmitForJsFiles = ParseTristate(value) - case "noErrorTruncation": - allOptions.NoErrorTruncation = ParseTristate(value) - case "noImplicitAny": - allOptions.NoImplicitAny = ParseTristate(value) - case "noImplicitThis": - allOptions.NoImplicitThis = ParseTristate(value) - case "noLib": - allOptions.NoLib = ParseTristate(value) - case "noPropertyAccessFromIndexSignature": - allOptions.NoPropertyAccessFromIndexSignature = ParseTristate(value) - case "noUncheckedIndexedAccess": - allOptions.NoUncheckedIndexedAccess = ParseTristate(value) - case "noEmitHelpers": - allOptions.NoEmitHelpers = ParseTristate(value) - case "noEmitOnError": - allOptions.NoEmitOnError = ParseTristate(value) - case "noImplicitReturns": - allOptions.NoImplicitReturns = ParseTristate(value) - case "noUnusedLocals": - allOptions.NoUnusedLocals = ParseTristate(value) - case "noUnusedParameters": - allOptions.NoUnusedParameters = ParseTristate(value) - case "noImplicitOverride": - allOptions.NoImplicitOverride = ParseTristate(value) - case "noUncheckedSideEffectImports": - allOptions.NoUncheckedSideEffectImports = ParseTristate(value) - case "outFile": - allOptions.OutFile = ParseString(value) - case "noResolve": - allOptions.NoResolve = ParseTristate(value) - case "paths": - allOptions.Paths = parseStringMap(value) - case "plugins": - // Native TypeScript does not load plugins; retain them only so tools can report the incompatibility. - if plugins, ok := value.([]any); ok { - allOptions.Plugins = core.Map(plugins, func(plugin any) core.PluginImport { - if pluginMap, isMap := plugin.(*collections.OrderedMap[string, any]); isMap { - return core.PluginImport{Name: ParseString(pluginMap.GetOrZero("name"))} - } - return core.PluginImport{} - }) - } - case "preserveWatchOutput": - allOptions.PreserveWatchOutput = ParseTristate(value) - case "preserveConstEnums": - allOptions.PreserveConstEnums = ParseTristate(value) - case "preserveSymlinks": - allOptions.PreserveSymlinks = ParseTristate(value) - case "project": - allOptions.Project = ParseString(value) - case "pretty": - allOptions.Pretty = ParseTristate(value) - case "resolveJsonModule": - allOptions.ResolveJsonModule = ParseTristate(value) - case "resolvePackageJsonExports": - allOptions.ResolvePackageJsonExports = ParseTristate(value) - case "resolvePackageJsonImports": - allOptions.ResolvePackageJsonImports = ParseTristate(value) - case "reactNamespace": - allOptions.ReactNamespace = ParseString(value) - case "rewriteRelativeImportExtensions": - allOptions.RewriteRelativeImportExtensions = ParseTristate(value) - case "rootDir": - allOptions.RootDir = ParseString(value) - case "rootDirs": - allOptions.RootDirs = ParseStringArray(value) - case "removeComments": - allOptions.RemoveComments = ParseTristate(value) - case "stableTypeOrdering": - allOptions.StableTypeOrdering = ParseTristate(value) - case "strict": - allOptions.Strict = ParseTristate(value) - case "strictBindCallApply": - allOptions.StrictBindCallApply = ParseTristate(value) - case "strictBuiltinIteratorReturn": - allOptions.StrictBuiltinIteratorReturn = ParseTristate(value) - case "strictFunctionTypes": - allOptions.StrictFunctionTypes = ParseTristate(value) - case "strictNullChecks": - allOptions.StrictNullChecks = ParseTristate(value) - case "strictPropertyInitialization": - allOptions.StrictPropertyInitialization = ParseTristate(value) - case "skipDefaultLibCheck": - allOptions.SkipDefaultLibCheck = ParseTristate(value) - case "sourceMap": - allOptions.SourceMap = ParseTristate(value) - case "sourceRoot": - allOptions.SourceRoot = ParseString(value) - case "stripInternal": - allOptions.StripInternal = ParseTristate(value) - case "suppressOutputPathCheck": - allOptions.SuppressOutputPathCheck = ParseTristate(value) - case "target": - allOptions.Target = floatOrInt32ToFlag[core.ScriptTarget](value) - case "traceResolution": - allOptions.TraceResolution = ParseTristate(value) - case "tsBuildInfoFile": - allOptions.TsBuildInfoFile = ParseString(value) - case "typeRoots": - allOptions.TypeRoots = ParseStringArray(value) - case "types": - allOptions.Types = ParseStringArray(value) - case "useDefineForClassFields": - allOptions.UseDefineForClassFields = ParseTristate(value) - case "useUnknownInCatchVariables": - allOptions.UseUnknownInCatchVariables = ParseTristate(value) - case "verbatimModuleSyntax": - allOptions.VerbatimModuleSyntax = ParseTristate(value) - case "version": - allOptions.Version = ParseTristate(value) - case "help": - allOptions.Help = ParseTristate(value) - case "all": - allOptions.All = ParseTristate(value) - case "maxNodeModuleJsDepth": - allOptions.MaxNodeModuleJsDepth = parseNumber(value) - case "skipLibCheck": - allOptions.SkipLibCheck = ParseTristate(value) - case "noEmit": - allOptions.NoEmit = ParseTristate(value) - case "showConfig": - allOptions.ShowConfig = ParseTristate(value) - case "configFilePath": - allOptions.ConfigFilePath = ParseString(value) - case "noDtsResolution": - allOptions.NoDtsResolution = ParseTristate(value) - case "pathsBasePath": - allOptions.PathsBasePath = ParseString(value) - case "outDir": - allOptions.OutDir = ParseString(value) - case "newLine": - allOptions.NewLine = floatOrInt32ToFlag[core.NewLineKind](value) - case "watch": - allOptions.Watch = ParseTristate(value) - case "pprofDir": - allOptions.PprofDir = ParseString(value) - case "singleThreaded": - allOptions.SingleThreaded = ParseTristate(value) - case "quiet": - allOptions.Quiet = ParseTristate(value) - case "checkers": - allOptions.Checkers = parseNumber(value) - case "runExternalCode": - allOptions.RunExternalCode = ParseTristate(value) - default: - // different than any key above - return false - } - return true -} - func floatOrInt32ToFlag[T ~int32](value any) T { if v, ok := value.(T); ok { return v @@ -574,83 +280,6 @@ func floatOrInt32ToFlag[T ~int32](value any) T { return T(value.(float64)) } -func ParseWatchOptions(key string, value any, allOptions *core.WatchOptions) []*ast.Diagnostic { - if allOptions == nil { - return nil - } - switch key { - case "watchInterval": - allOptions.Interval = parseNumber(value) - case "watchFile": - if value != nil { - allOptions.FileKind = value.(core.WatchFileKind) - } - case "watchDirectory": - if value != nil { - allOptions.DirectoryKind = value.(core.WatchDirectoryKind) - } - case "fallbackPolling": - if value != nil { - allOptions.FallbackPolling = value.(core.PollingKind) - } - case "synchronousWatchDirectory": - allOptions.SyncWatchDir = ParseTristate(value) - case "excludeDirectories": - allOptions.ExcludeDir = ParseStringArray(value) - case "excludeFiles": - allOptions.ExcludeFiles = ParseStringArray(value) - } - return nil -} - -func ParseTypeAcquisition(key string, value any, allOptions *core.TypeAcquisition) []*ast.Diagnostic { - if value == nil { - return nil - } - if allOptions == nil { - return nil - } - switch key { - case "enable": - allOptions.Enable = ParseTristate(value) - case "include": - allOptions.Include = ParseStringArray(value) - case "exclude": - allOptions.Exclude = ParseStringArray(value) - case "disableFilenameBasedTypeAcquisition": - allOptions.DisableFilenameBasedTypeAcquisition = ParseTristate(value) - } - return nil -} - -func ParseBuildOptions(key string, value any, allOptions *core.BuildOptions) []*ast.Diagnostic { - if value == nil { - return nil - } - if allOptions == nil { - return nil - } - option := BuildNameMap.Get(key) - if option != nil { - key = option.Name - } - switch key { - case "clean": - allOptions.Clean = ParseTristate(value) - case "dry": - allOptions.Dry = ParseTristate(value) - case "force": - allOptions.Force = ParseTristate(value) - case "builders": - allOptions.Builders = parseNumber(value) - case "stopBuildOnErrors": - allOptions.StopBuildOnErrors = ParseTristate(value) - case "verbose": - allOptions.Verbose = ParseTristate(value) - } - return nil -} - // mergeCompilerOptions merges the source compiler options into the target compiler options // with optional awareness of explicitly set null values in the raw JSON. // Fields in the source options will overwrite the corresponding fields in the target options, @@ -677,29 +306,7 @@ func mergeCompilerOptions(targetOptions, sourceOptions *core.CompilerOptions, ra } } - // Do the merge, handling explicit nulls during the normal merge - targetValue := reflect.ValueOf(targetOptions).Elem() - sourceValue := reflect.ValueOf(sourceOptions).Elem() - targetType := targetValue.Type() - - for i := range targetValue.NumField() { - targetField := targetValue.Field(i) - sourceField := sourceValue.Field(i) - - // Get the JSON field name for this struct field and check if it's explicitly null - if jsonTag := targetType.Field(i).Tag.Get("json"); jsonTag != "" { - if jsonFieldName, _, _ := strings.Cut(jsonTag, ","); jsonFieldName != "" && explicitNullFields.Has(jsonFieldName) { - targetField.SetZero() - continue - } - } - - // Normal merge behavior: copy non-zero fields - if !sourceField.IsZero() { - targetField.Set(sourceField) - } - } - + mergeCompilerOptionFields(targetOptions, sourceOptions, explicitNullFields) return targetOptions } diff --git a/tsc/internal/tsoptions/parsinghelpers_test.go b/tsc/internal/tsoptions/parsinghelpers_test.go index 151db96ad96f3..87a2483ea988c 100644 --- a/tsc/internal/tsoptions/parsinghelpers_test.go +++ b/tsc/internal/tsoptions/parsinghelpers_test.go @@ -5,9 +5,94 @@ import ( "strings" "testing" + "github.com/microsoft/TypeScript/tsc/internal/collections" "github.com/microsoft/TypeScript/tsc/internal/core" ) +func TestMergeCompilerOptions(t *testing.T) { + t.Parallel() + + if mergeCompilerOptions(nil, nil, nil) != nil { + t.Fatal("Merging nil options must return nil") + } + unchanged := &core.CompilerOptions{Strict: core.TSTrue} + if mergeCompilerOptions(unchanged, nil, nil) != unchanged || unchanged.Strict != core.TSTrue { + t.Fatal("A nil source must leave the target unchanged") + } + + for field := range reflect.TypeFor[core.CompilerOptions]().Fields() { + if !field.IsExported() { + continue + } + t.Run(field.Name, func(t *testing.T) { + t.Parallel() + name, _, _ := strings.Cut(field.Tag.Get("json"), ",") + nullOptions := &collections.OrderedMap[string, any]{} + nullOptions.Set(name, nil) + raw := &collections.OrderedMap[string, any]{} + raw.Set("compilerOptions", nullOptions) + values := compilerOptionTestValues(t, field) + for _, targetValue := range values { + for _, sourceValue := range values { + for _, explicitNull := range []bool{false, true} { + target := &core.CompilerOptions{} + source := &core.CompilerOptions{} + reflect.ValueOf(target).Elem().FieldByIndex(field.Index).Set(targetValue) + reflect.ValueOf(source).Elem().FieldByIndex(field.Index).Set(sourceValue) + expected := target.Clone() + expectedField := reflect.ValueOf(expected).Elem().FieldByIndex(field.Index) + var rawSource any + if explicitNull { + rawSource = raw + expectedField.SetZero() + } else if !sourceValue.IsZero() { + expectedField.Set(sourceValue) + } + if got := mergeCompilerOptions(target, source, rawSource); got != target || !reflect.DeepEqual(got, expected) { + t.Fatalf("Merge differs for target=%v, source=%v, explicitNull=%v", targetValue, sourceValue, explicitNull) + } + actualField := reflect.ValueOf(target).Elem().FieldByIndex(field.Index) + if (field.Type.Kind() == reflect.Pointer || field.Type.Kind() == reflect.Slice) && actualField.Pointer() != expectedField.Pointer() { + t.Fatal("Merge must preserve shallow sharing") + } + if !reflect.DeepEqual(reflect.ValueOf(source).Elem().FieldByIndex(field.Index).Interface(), sourceValue.Interface()) { + t.Fatal("Merge must not modify the source") + } + } + } + } + }) + } +} + +func TestMergeCompilerOptionsRawNulls(t *testing.T) { + t.Parallel() + + for _, name := range []string{"moduleDetection", "ModuleDetection", "moduleDetectionKind", "unknownOption"} { + t.Run(name, func(t *testing.T) { + t.Parallel() + rawOptions := &collections.OrderedMap[string, any]{} + rawOptions.Set(name, nil) + raw := &collections.OrderedMap[string, any]{} + raw.Set("compilerOptions", rawOptions) + target := &core.CompilerOptions{ModuleDetection: core.ModuleDetectionKindForce} + source := &core.CompilerOptions{ModuleDetection: core.ModuleDetectionKindAuto} + mergeCompilerOptions(target, source, raw) + expected := core.ModuleDetectionKindAuto + if name == "moduleDetection" { + expected = core.ModuleDetectionKindNone + } + if target.ModuleDetection != expected { + t.Fatalf("Got %v, want %v", target.ModuleDetection, expected) + } + mergeCompilerOptions(source, source, raw) + if source.ModuleDetection != expected { + t.Fatal("Merging an object with itself must still apply explicit nulls") + } + }) + } +} + func TestParseCompilerOptionNoMissingFields(t *testing.T) { t.Parallel() var missingKeys []string diff --git a/tsc/internal/tsoptions/schemas/jsconfig.schema.json b/tsc/internal/tsoptions/schemas/jsconfig.schema.json new file mode 100644 index 0000000000000..f60eab11d50e8 --- /dev/null +++ b/tsc/internal/tsoptions/schemas/jsconfig.schema.json @@ -0,0 +1,2338 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "Generated by tools/scripts/tsc/generate-options.ts. DO NOT EDIT.", + "title": "JavaScript configuration", + "type": "object", + "allowComments": true, + "allowTrailingCommas": true, + "properties": { + "$schema": { + "type": "string", + "description": "The JSON schema used to validate this configuration." + }, + "watchOptions": { + "allOf": [ + { + "$ref": "#/definitions/watchOptions" + } + ], + "description": "Options for watching files and directories.", + "markdownDescription": "Options for watching files and directories.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#watchOptions)." + }, + "compilerOptions": { + "allOf": [ + { + "$ref": "#/definitions/compilerOptions" + } + ], + "description": "Options for the TypeScript compiler.", + "markdownDescription": "Options for the TypeScript compiler.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/)." + }, + "typeAcquisition": { + "allOf": [ + { + "$ref": "#/definitions/typeAcquisition" + } + ], + "description": "Options for automatic type acquisition in JavaScript projects.", + "markdownDescription": "Options for automatic type acquisition in JavaScript projects.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#typeAcquisition)." + }, + "extends": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Configuration file or files to inherit from. Later entries take precedence. Relative paths are resolved relative to the configuration file in which they occur.", + "markdownDescription": "Configuration file or files to inherit from. Later entries take precedence. Relative paths are resolved relative to the configuration file in which they occur.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#extends)." + }, + "references": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string", + "minLength": 1 + }, + "circular": { + "type": "boolean" + } + }, + "required": [ + "path" + ] + } + }, + { + "type": "null" + } + ], + "description": "Referenced projects. Each path identifies a configuration file or a directory containing one.", + "markdownDescription": "Referenced projects. Each path identifies a configuration file or a directory containing one.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#references)." + }, + "contentMappers": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "properties": { + "package": { + "type": "string", + "minLength": 1 + }, + "extensions": { + "type": "array", + "items": { + "type": "string" + } + }, + "options": { + "type": "object" + } + }, + "required": [ + "package", + "extensions" + ], + "additionalProperties": false + } + }, + { + "type": "null" + } + ], + "description": "External content mapper packages and the file extensions they handle. Execution must be enabled separately with --runExternalCode.", + "markdownDescription": "External content mapper packages and the file extensions they handle. Execution must be enabled separately with --runExternalCode." + }, + "files": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Files to include in the project, in addition to files matched by include.", + "markdownDescription": "Files to include in the project, in addition to files matched by include.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#files)." + }, + "include": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "File names or glob patterns to include. Defaults to all supported files when neither files nor include is specified.", + "markdownDescription": "File names or glob patterns to include. Defaults to all supported files when neither files nor include is specified.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#include)." + }, + "exclude": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "File names or glob patterns excluded from include. Does not exclude files brought in by imports, references, types, or files.", + "markdownDescription": "File names or glob patterns excluded from include. Does not exclude files brought in by imports, references, types, or files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#exclude)." + }, + "compileOnSave": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "description": "Compile this project when a file is saved in a supporting editor.", + "markdownDescription": "Compile this project when a file is saved in a supporting editor." + } + }, + "additionalProperties": true, + "definitions": { + "compilerOptions": { + "type": [ + "object", + "null" + ], + "properties": { + "allowJs": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Allow JavaScript files to be a part of your program. Use the 'checkJs' option to get errors from these files.", + "default": true, + "markdownDescription": "Allow JavaScript files to be a part of your program. Use the 'checkJs' option to get errors from these files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowJs)." + }, + "allowArbitraryExtensions": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable importing files with any extension, provided a declaration file is present.", + "default": false, + "markdownDescription": "Enable importing files with any extension, provided a declaration file is present.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowArbitraryExtensions)." + }, + "allowImportingTsExtensions": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set.", + "default": false, + "markdownDescription": "Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowImportingTsExtensions)." + }, + "allowUmdGlobalAccess": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Allow accessing UMD globals from modules.", + "default": false, + "markdownDescription": "Allow accessing UMD globals from modules.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowUmdGlobalAccess)." + }, + "allowUnreachableCode": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable error reporting for unreachable code.", + "markdownDescription": "Disable error reporting for unreachable code.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowUnreachableCode)." + }, + "allowUnusedLabels": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable error reporting for unused labels.", + "markdownDescription": "Disable error reporting for unused labels.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowUnusedLabels)." + }, + "assumeChangesOnlyAffectDirectDependencies": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Have recompiles in projects that use 'incremental' and 'watch' mode assume that changes within a file will only affect files directly depending on it.", + "default": false, + "markdownDescription": "Have recompiles in projects that use 'incremental' and 'watch' mode assume that changes within a file will only affect files directly depending on it.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#assumeChangesOnlyAffectDirectDependencies)." + }, + "checkJs": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable error reporting in type-checked JavaScript files.", + "default": false, + "markdownDescription": "Enable error reporting in type-checked JavaScript files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#checkJs)." + }, + "customConditions": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Conditions to set in addition to the resolver-specific defaults when resolving imports.", + "markdownDescription": "Conditions to set in addition to the resolver-specific defaults when resolving imports.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#customConditions)." + }, + "composite": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable constraints that allow a TypeScript project to be used with project references.", + "default": false, + "markdownDescription": "Enable constraints that allow a TypeScript project to be used with project references.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#composite)." + }, + "emitDeclarationOnly": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Only output d.ts files and not JavaScript files.", + "default": false, + "markdownDescription": "Only output d.ts files and not JavaScript files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#emitDeclarationOnly)." + }, + "emitBOM": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files.", + "default": false, + "markdownDescription": "Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#emitBOM)." + }, + "emitDecoratorMetadata": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Emit design-type metadata for decorated declarations in source files.", + "default": false, + "markdownDescription": "Emit design-type metadata for decorated declarations in source files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#emitDecoratorMetadata)." + }, + "declaration": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Generate .d.ts files from TypeScript and JavaScript files in your project.\n\nDefault: `false`, unless `composite` is set", + "markdownDescription": "Generate .d.ts files from TypeScript and JavaScript files in your project.\n\nDefault: `false`, unless `composite` is set\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#declaration)." + }, + "declarationDir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the output directory for generated declaration files.", + "markdownDescription": "Specify the output directory for generated declaration files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#declarationDir)." + }, + "declarationMap": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Create sourcemaps for d.ts files.", + "default": false, + "markdownDescription": "Create sourcemaps for d.ts files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#declarationMap)." + }, + "deduplicatePackages": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Deduplicate packages with the same name and version.", + "default": true, + "markdownDescription": "Deduplicate packages with the same name and version." + }, + "disableSizeLimit": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server.", + "default": false, + "markdownDescription": "Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#disableSizeLimit)." + }, + "disableSourceOfProjectReferenceRedirect": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable preferring source files instead of declaration files when referencing composite projects.", + "default": false, + "markdownDescription": "Disable preferring source files instead of declaration files when referencing composite projects.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#disableSourceOfProjectReferenceRedirect)." + }, + "disableSolutionSearching": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Opt a project out of multi-project reference checking when editing.", + "default": false, + "markdownDescription": "Opt a project out of multi-project reference checking when editing.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#disableSolutionSearching)." + }, + "disableReferencedProjectLoad": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Reduce the number of projects loaded automatically by TypeScript.", + "default": false, + "markdownDescription": "Reduce the number of projects loaded automatically by TypeScript.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#disableReferencedProjectLoad)." + }, + "erasableSyntaxOnly": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Do not allow runtime constructs that are not part of ECMAScript.", + "default": false, + "markdownDescription": "Do not allow runtime constructs that are not part of ECMAScript.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#erasableSyntaxOnly)." + }, + "exactOptionalPropertyTypes": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Interpret optional property types as written, rather than adding 'undefined'.", + "default": false, + "markdownDescription": "Interpret optional property types as written, rather than adding 'undefined'.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#exactOptionalPropertyTypes)." + }, + "experimentalDecorators": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable experimental support for legacy experimental decorators.", + "default": false, + "markdownDescription": "Enable experimental support for legacy experimental decorators.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#experimentalDecorators)." + }, + "forceConsistentCasingInFileNames": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Ensure that casing is correct in imports.", + "default": true, + "markdownDescription": "Ensure that casing is correct in imports.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#forceConsistentCasingInFileNames)." + }, + "isolatedModules": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Ensure that each file can be safely transpiled without relying on other imports.", + "default": false, + "markdownDescription": "Ensure that each file can be safely transpiled without relying on other imports.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#isolatedModules)." + }, + "isolatedDeclarations": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Require sufficient annotation on exports so other tools can trivially generate declaration files.", + "default": false, + "markdownDescription": "Require sufficient annotation on exports so other tools can trivially generate declaration files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#isolatedDeclarations)." + }, + "ignoreDeprecations": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "importHelpers": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Allow importing helper functions from tslib once per project, instead of including them per-file.", + "default": false, + "markdownDescription": "Allow importing helper functions from tslib once per project, instead of including them per-file.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#importHelpers)." + }, + "inlineSourceMap": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Include sourcemap files inside the emitted JavaScript.", + "default": false, + "markdownDescription": "Include sourcemap files inside the emitted JavaScript.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#inlineSourceMap)." + }, + "inlineSources": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Include source code in the sourcemaps inside the emitted JavaScript.", + "default": false, + "markdownDescription": "Include source code in the sourcemaps inside the emitted JavaScript.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#inlineSources)." + }, + "incremental": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Save .tsbuildinfo files to allow for incremental compilation of projects.\n\nDefault: `false`, unless `composite` is set", + "markdownDescription": "Save .tsbuildinfo files to allow for incremental compilation of projects.\n\nDefault: `false`, unless `composite` is set\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#incremental)." + }, + "jsx": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "preserve", + "react-native", + "react-jsx", + "react-jsxdev", + "react" + ] + }, + { + "pattern": "^([Pp][Rr][Ee][Ss][Ee][Rr][Vv][Ee]|[Rr][Ee][Aa][Cc][Tt]-[Nn][Aa][Tt][Ii][Vv][Ee]|[Rr][Ee][Aa][Cc][Tt]-[Jj][Ss][Xx]|[Rr][Ee][Aa][Cc][Tt]-[Jj][Ss][Xx][Dd][Ee][Vv]|[Rr][Ee][Aa][Cc][Tt])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Specify what JSX code is generated.", + "markdownDescription": "Specify what JSX code is generated.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#jsx)." + }, + "jsxFactory": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.", + "default": "React.createElement", + "markdownDescription": "Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#jsxFactory)." + }, + "jsxFragmentFactory": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'.", + "default": "React.Fragment", + "markdownDescription": "Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#jsxFragmentFactory)." + }, + "jsxImportSource": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'.", + "default": "react", + "markdownDescription": "Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#jsxImportSource)." + }, + "lib": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string", + "anyOf": [ + { + "enum": [ + "es5", + "es6", + "es2015", + "es7", + "es2016", + "es2017", + "es2018", + "es2019", + "es2020", + "es2021", + "es2022", + "es2023", + "es2024", + "es2025", + "esnext", + "dom", + "dom.iterable", + "dom.asynciterable", + "webworker", + "webworker.importscripts", + "webworker.iterable", + "webworker.asynciterable", + "scripthost", + "es2015.core", + "es2015.collection", + "es2015.generator", + "es2015.iterable", + "es2015.promise", + "es2015.proxy", + "es2015.reflect", + "es2015.symbol", + "es2015.symbol.wellknown", + "es2016.array.include", + "es2016.intl", + "es2017.arraybuffer", + "es2017.date", + "es2017.object", + "es2017.sharedmemory", + "es2017.string", + "es2017.intl", + "es2017.typedarrays", + "es2018.asyncgenerator", + "es2018.asynciterable", + "es2018.intl", + "es2018.promise", + "es2018.regexp", + "es2019.array", + "es2019.object", + "es2019.string", + "es2019.symbol", + "es2019.intl", + "es2020.bigint", + "es2020.date", + "es2020.promise", + "es2020.sharedmemory", + "es2020.string", + "es2020.symbol.wellknown", + "es2020.intl", + "es2020.number", + "es2021.promise", + "es2021.string", + "es2021.weakref", + "es2021.intl", + "es2022.array", + "es2022.error", + "es2022.intl", + "es2022.object", + "es2022.string", + "es2022.regexp", + "es2023.array", + "es2023.collection", + "es2023.intl", + "es2024.arraybuffer", + "es2024.collection", + "es2024.object", + "es2024.promise", + "es2024.regexp", + "es2024.sharedmemory", + "es2024.string", + "es2025.collection", + "es2025.float16", + "es2025.intl", + "es2025.iterator", + "es2025.promise", + "es2025.regexp", + "esnext.asynciterable", + "esnext.symbol", + "esnext.bigint", + "esnext.weakref", + "esnext.object", + "esnext.regexp", + "esnext.string", + "esnext.float16", + "esnext.iterator", + "esnext.promise", + "esnext.array", + "esnext.collection", + "esnext.date", + "esnext.decorators", + "esnext.disposable", + "esnext.error", + "esnext.intl", + "esnext.sharedmemory", + "esnext.temporal", + "esnext.typedarrays", + "decorators", + "decorators.legacy", + "es2022.sharedmemory" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Deprecated." + ] + }, + { + "pattern": "^([Ee][Ss]5|[Ee][Ss]6|[Ee][Ss]2015|[Ee][Ss]7|[Ee][Ss]2016|[Ee][Ss]2017|[Ee][Ss]2018|[Ee][Ss]2019|[Ee][Ss]2020|[Ee][Ss]2021|[Ee][Ss]2022|[Ee][Ss]2023|[Ee][Ss]2024|[Ee][Ss]2025|[Ee][Ss][Nn][Ee][Xx][Tt]|[Dd][Oo][Mm]|[Dd][Oo][Mm]\\.[Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Dd][Oo][Mm]\\.[Aa][Ss][Yy][Nn][Cc][Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Ww][Ee][Bb][Ww][Oo][Rr][Kk][Ee][Rr]|[Ww][Ee][Bb][Ww][Oo][Rr][Kk][Ee][Rr]\\.[Ii][Mm][Pp][Oo][Rr][Tt][Ss][Cc][Rr][Ii][Pp][Tt][Ss]|[Ww][Ee][Bb][Ww][Oo][Rr][Kk][Ee][Rr]\\.[Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Ww][Ee][Bb][Ww][Oo][Rr][Kk][Ee][Rr]\\.[Aa][Ss][Yy][Nn][Cc][Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Ss][Cc][Rr][Ii][Pp][Tt][Hh][Oo][Ss][Tt]|[Ee][Ss]2015\\.[Cc][Oo][Rr][Ee]|[Ee][Ss]2015\\.[Cc][Oo][Ll][Ll][Ee][Cc][Tt][Ii][Oo][Nn]|[Ee][Ss]2015\\.[Gg][Ee][Nn][Ee][Rr][Aa][Tt][Oo][Rr]|[Ee][Ss]2015\\.[Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Ee][Ss]2015\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss]2015\\.[Pp][Rr][Oo][Xx][Yy]|[Ee][Ss]2015\\.[Rr][Ee][Ff][Ll][Ee][Cc][Tt]|[Ee][Ss]2015\\.[Ss][Yy][Mm][Bb][Oo][Ll]|[Ee][Ss]2015\\.[Ss][Yy][Mm][Bb][Oo][Ll]\\.[Ww][Ee][Ll][Ll][Kk][Nn][Oo][Ww][Nn]|[Ee][Ss]2016\\.[Aa][Rr][Rr][Aa][Yy]\\.[Ii][Nn][Cc][Ll][Uu][Dd][Ee]|[Ee][Ss]2016\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2017\\.[Aa][Rr][Rr][Aa][Yy][Bb][Uu][Ff][Ff][Ee][Rr]|[Ee][Ss]2017\\.[Dd][Aa][Tt][Ee]|[Ee][Ss]2017\\.[Oo][Bb][Jj][Ee][Cc][Tt]|[Ee][Ss]2017\\.[Ss][Hh][Aa][Rr][Ee][Dd][Mm][Ee][Mm][Oo][Rr][Yy]|[Ee][Ss]2017\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss]2017\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2017\\.[Tt][Yy][Pp][Ee][Dd][Aa][Rr][Rr][Aa][Yy][Ss]|[Ee][Ss]2018\\.[Aa][Ss][Yy][Nn][Cc][Gg][Ee][Nn][Ee][Rr][Aa][Tt][Oo][Rr]|[Ee][Ss]2018\\.[Aa][Ss][Yy][Nn][Cc][Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Ee][Ss]2018\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2018\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss]2018\\.[Rr][Ee][Gg][Ee][Xx][Pp]|[Ee][Ss]2019\\.[Aa][Rr][Rr][Aa][Yy]|[Ee][Ss]2019\\.[Oo][Bb][Jj][Ee][Cc][Tt]|[Ee][Ss]2019\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss]2019\\.[Ss][Yy][Mm][Bb][Oo][Ll]|[Ee][Ss]2019\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2020\\.[Bb][Ii][Gg][Ii][Nn][Tt]|[Ee][Ss]2020\\.[Dd][Aa][Tt][Ee]|[Ee][Ss]2020\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss]2020\\.[Ss][Hh][Aa][Rr][Ee][Dd][Mm][Ee][Mm][Oo][Rr][Yy]|[Ee][Ss]2020\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss]2020\\.[Ss][Yy][Mm][Bb][Oo][Ll]\\.[Ww][Ee][Ll][Ll][Kk][Nn][Oo][Ww][Nn]|[Ee][Ss]2020\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2020\\.[Nn][Uu][Mm][Bb][Ee][Rr]|[Ee][Ss]2021\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss]2021\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss]2021\\.[Ww][Ee][Aa][Kk][Rr][Ee][Ff]|[Ee][Ss]2021\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2022\\.[Aa][Rr][Rr][Aa][Yy]|[Ee][Ss]2022\\.[Ee][Rr][Rr][Oo][Rr]|[Ee][Ss]2022\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2022\\.[Oo][Bb][Jj][Ee][Cc][Tt]|[Ee][Ss]2022\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss]2022\\.[Rr][Ee][Gg][Ee][Xx][Pp]|[Ee][Ss]2023\\.[Aa][Rr][Rr][Aa][Yy]|[Ee][Ss]2023\\.[Cc][Oo][Ll][Ll][Ee][Cc][Tt][Ii][Oo][Nn]|[Ee][Ss]2023\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2024\\.[Aa][Rr][Rr][Aa][Yy][Bb][Uu][Ff][Ff][Ee][Rr]|[Ee][Ss]2024\\.[Cc][Oo][Ll][Ll][Ee][Cc][Tt][Ii][Oo][Nn]|[Ee][Ss]2024\\.[Oo][Bb][Jj][Ee][Cc][Tt]|[Ee][Ss]2024\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss]2024\\.[Rr][Ee][Gg][Ee][Xx][Pp]|[Ee][Ss]2024\\.[Ss][Hh][Aa][Rr][Ee][Dd][Mm][Ee][Mm][Oo][Rr][Yy]|[Ee][Ss]2024\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss]2025\\.[Cc][Oo][Ll][Ll][Ee][Cc][Tt][Ii][Oo][Nn]|[Ee][Ss]2025\\.[Ff][Ll][Oo][Aa][Tt]16|[Ee][Ss]2025\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2025\\.[Ii][Tt][Ee][Rr][Aa][Tt][Oo][Rr]|[Ee][Ss]2025\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss]2025\\.[Rr][Ee][Gg][Ee][Xx][Pp]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Aa][Ss][Yy][Nn][Cc][Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ss][Yy][Mm][Bb][Oo][Ll]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Bb][Ii][Gg][Ii][Nn][Tt]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ww][Ee][Aa][Kk][Rr][Ee][Ff]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Oo][Bb][Jj][Ee][Cc][Tt]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Rr][Ee][Gg][Ee][Xx][Pp]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ff][Ll][Oo][Aa][Tt]16|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ii][Tt][Ee][Rr][Aa][Tt][Oo][Rr]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Aa][Rr][Rr][Aa][Yy]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Cc][Oo][Ll][Ll][Ee][Cc][Tt][Ii][Oo][Nn]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Dd][Aa][Tt][Ee]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Dd][Ee][Cc][Oo][Rr][Aa][Tt][Oo][Rr][Ss]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Dd][Ii][Ss][Pp][Oo][Ss][Aa][Bb][Ll][Ee]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ee][Rr][Rr][Oo][Rr]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ii][Nn][Tt][Ll]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ss][Hh][Aa][Rr][Ee][Dd][Mm][Ee][Mm][Oo][Rr][Yy]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Tt][Ee][Mm][Pp][Oo][Rr][Aa][Ll]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Tt][Yy][Pp][Ee][Dd][Aa][Rr][Rr][Aa][Yy][Ss]|[Dd][Ee][Cc][Oo][Rr][Aa][Tt][Oo][Rr][Ss]|[Dd][Ee][Cc][Oo][Rr][Aa][Tt][Oo][Rr][Ss]\\.[Ll][Ee][Gg][Aa][Cc][Yy]|[Ee][Ss]2022\\.[Ss][Hh][Aa][Rr][Ee][Dd][Mm][Ee][Mm][Oo][Rr][Yy])$" + } + ] + } + }, + { + "type": "null" + } + ], + "description": "Specify a set of bundled library declaration files that describe the target runtime environment.", + "markdownDescription": "Specify a set of bundled library declaration files that describe the target runtime environment.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#lib)." + }, + "libReplacement": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable lib replacement.", + "default": false, + "markdownDescription": "Enable lib replacement.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#libReplacement)." + }, + "mapRoot": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the location where debugger should locate map files instead of generated locations.", + "markdownDescription": "Specify the location where debugger should locate map files instead of generated locations.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#mapRoot)." + }, + "module": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "commonjs", + "amd", + "system", + "umd", + "es6", + "es2015", + "es2020", + "es2022", + "esnext", + "node16", + "node18", + "node20", + "nodenext", + "preserve", + "none" + ], + "enumDescriptions": [ + "", + "Deprecated.", + "Deprecated.", + "Deprecated.", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Deprecated." + ] + }, + { + "pattern": "^([Cc][Oo][Mm][Mm][Oo][Nn][Jj][Ss]|[Aa][Mm][Dd]|[Ss][Yy][Ss][Tt][Ee][Mm]|[Uu][Mm][Dd]|[Ee][Ss]6|[Ee][Ss]2015|[Ee][Ss]2020|[Ee][Ss]2022|[Ee][Ss][Nn][Ee][Xx][Tt]|[Nn][Oo][Dd][Ee]16|[Nn][Oo][Dd][Ee]18|[Nn][Oo][Dd][Ee]20|[Nn][Oo][Dd][Ee][Nn][Ee][Xx][Tt]|[Pp][Rr][Ee][Ss][Ee][Rr][Vv][Ee]|[Nn][Oo][Nn][Ee])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Specify what module code is generated.", + "markdownDescription": "Specify what module code is generated.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#module)." + }, + "moduleResolution": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "node16", + "nodenext", + "bundler", + "classic", + "node", + "node10" + ], + "enumDescriptions": [ + "", + "", + "", + "Deprecated.", + "Deprecated.", + "Deprecated." + ] + }, + { + "pattern": "^([Nn][Oo][Dd][Ee]16|[Nn][Oo][Dd][Ee][Nn][Ee][Xx][Tt]|[Bb][Uu][Nn][Dd][Ll][Ee][Rr]|[Cc][Ll][Aa][Ss][Ss][Ii][Cc]|[Nn][Oo][Dd][Ee]|[Nn][Oo][Dd][Ee]10)$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Specify how TypeScript looks up a file from a given module specifier.\n\nDefault: `nodenext` if `module` is `nodenext`; `node16` if `module` is `node16` or `node18`; otherwise, `bundler`.", + "markdownDescription": "Specify how TypeScript looks up a file from a given module specifier.\n\nDefault: `nodenext` if `module` is `nodenext`; `node16` if `module` is `node16` or `node18`; otherwise, `bundler`.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#moduleResolution)." + }, + "moduleSuffixes": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "List of file name suffixes to search when resolving a module.", + "markdownDescription": "List of file name suffixes to search when resolving a module.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#moduleSuffixes)." + }, + "moduleDetection": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "auto", + "legacy", + "force" + ] + }, + { + "pattern": "^([Aa][Uu][Tt][Oo]|[Ll][Ee][Gg][Aa][Cc][Yy]|[Ff][Oo][Rr][Cc][Ee])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Control what method is used to detect module-format JS files.\n\nDefault: \"auto\": Treat files with imports, exports, import.meta, jsx (with jsx: react-jsx), or esm format (with module: node16+) as modules.", + "markdownDescription": "Control what method is used to detect module-format JS files.\n\nDefault: \"auto\": Treat files with imports, exports, import.meta, jsx (with jsx: react-jsx), or esm format (with module: node16+) as modules.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#moduleDetection)." + }, + "newLine": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "crlf", + "lf" + ] + }, + { + "pattern": "^([Cc][Rr][Ll][Ff]|[Ll][Ff])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Set the newline character for emitting files.", + "default": "lf", + "markdownDescription": "Set the newline character for emitting files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#newLine)." + }, + "noEmit": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable emitting files from a compilation.", + "default": true, + "markdownDescription": "Disable emitting files from a compilation.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noEmit)." + }, + "noCheck": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable full type checking (only critical parse and emit errors will be reported).", + "default": false, + "markdownDescription": "Disable full type checking (only critical parse and emit errors will be reported).\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noCheck)." + }, + "noErrorTruncation": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable truncating types in error messages.", + "default": false, + "markdownDescription": "Disable truncating types in error messages.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noErrorTruncation)." + }, + "noFallthroughCasesInSwitch": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable error reporting for fallthrough cases in switch statements.", + "default": false, + "markdownDescription": "Enable error reporting for fallthrough cases in switch statements.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noFallthroughCasesInSwitch)." + }, + "noImplicitAny": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable error reporting for expressions and declarations with an implied 'any' type.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "Enable error reporting for expressions and declarations with an implied 'any' type.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noImplicitAny)." + }, + "noImplicitThis": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable error reporting when 'this' is given the type 'any'.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "Enable error reporting when 'this' is given the type 'any'.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noImplicitThis)." + }, + "noImplicitReturns": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable error reporting for codepaths that do not explicitly return in a function.", + "default": false, + "markdownDescription": "Enable error reporting for codepaths that do not explicitly return in a function.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noImplicitReturns)." + }, + "noEmitHelpers": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable generating custom helper functions like '__extends' in compiled output.", + "default": false, + "markdownDescription": "Disable generating custom helper functions like '__extends' in compiled output.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noEmitHelpers)." + }, + "noLib": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable including any library files, including the default lib.d.ts.", + "default": false, + "markdownDescription": "Disable including any library files, including the default lib.d.ts.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noLib)." + }, + "noPropertyAccessFromIndexSignature": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enforces using indexed accessors for keys declared using an indexed type.", + "default": false, + "markdownDescription": "Enforces using indexed accessors for keys declared using an indexed type.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noPropertyAccessFromIndexSignature)." + }, + "noUncheckedIndexedAccess": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Add 'undefined' to a type when accessed using an index.", + "default": false, + "markdownDescription": "Add 'undefined' to a type when accessed using an index.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noUncheckedIndexedAccess)." + }, + "noEmitOnError": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable emitting files if any type checking errors are reported.", + "default": false, + "markdownDescription": "Disable emitting files if any type checking errors are reported.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noEmitOnError)." + }, + "noUnusedLocals": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable error reporting when local variables aren't read.", + "default": false, + "markdownDescription": "Enable error reporting when local variables aren't read.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noUnusedLocals)." + }, + "noUnusedParameters": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Raise an error when a function parameter isn't read.", + "default": false, + "markdownDescription": "Raise an error when a function parameter isn't read.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noUnusedParameters)." + }, + "noResolve": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project.", + "default": false, + "markdownDescription": "Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noResolve)." + }, + "noImplicitOverride": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Ensure overriding members in derived classes are marked with an override modifier.", + "default": false, + "markdownDescription": "Ensure overriding members in derived classes are marked with an override modifier.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noImplicitOverride)." + }, + "noUncheckedSideEffectImports": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Check side effect imports.", + "default": true, + "markdownDescription": "Check side effect imports.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noUncheckedSideEffectImports)." + }, + "outDir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify an output folder for all emitted files.", + "markdownDescription": "Specify an output folder for all emitted files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#outDir)." + }, + "paths": { + "anyOf": [ + { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "type": "null" + } + ], + "description": "Specify a set of entries that re-map imports to additional lookup locations.", + "markdownDescription": "Specify a set of entries that re-map imports to additional lookup locations.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#paths)." + }, + "plugins": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + }, + { + "type": "null" + } + ], + "description": "Specify a list of language service plugins to include.", + "markdownDescription": "Specify a list of language service plugins to include.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#plugins)." + }, + "preserveConstEnums": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable erasing 'const enum' declarations in generated code.", + "default": false, + "markdownDescription": "Disable erasing 'const enum' declarations in generated code.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#preserveConstEnums)." + }, + "preserveSymlinks": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable resolving symlinks to their realpath. This correlates to the same flag in node.", + "default": false, + "markdownDescription": "Disable resolving symlinks to their realpath. This correlates to the same flag in node.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#preserveSymlinks)." + }, + "resolveJsonModule": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable importing .json files.", + "default": false, + "markdownDescription": "Enable importing .json files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#resolveJsonModule)." + }, + "resolvePackageJsonExports": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Use the package.json 'exports' field when resolving package imports.\n\nDefault: `true` when 'moduleResolution' is 'node16', 'nodenext', or 'bundler'; otherwise `false`.", + "markdownDescription": "Use the package.json 'exports' field when resolving package imports.\n\nDefault: `true` when 'moduleResolution' is 'node16', 'nodenext', or 'bundler'; otherwise `false`.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#resolvePackageJsonExports)." + }, + "resolvePackageJsonImports": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Use the package.json 'imports' field when resolving imports.\n\nDefault: `true` when 'moduleResolution' is 'node16', 'nodenext', or 'bundler'; otherwise `false`.", + "markdownDescription": "Use the package.json 'imports' field when resolving imports.\n\nDefault: `true` when 'moduleResolution' is 'node16', 'nodenext', or 'bundler'; otherwise `false`.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#resolvePackageJsonImports)." + }, + "removeComments": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable emitting comments.", + "default": false, + "markdownDescription": "Disable emitting comments.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#removeComments)." + }, + "rewriteRelativeImportExtensions": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files.", + "default": false, + "markdownDescription": "Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#rewriteRelativeImportExtensions)." + }, + "reactNamespace": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit.", + "default": "React", + "markdownDescription": "Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#reactNamespace)." + }, + "rootDir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the root folder within your source files.\n\nDefault: Computed from the list of input files", + "markdownDescription": "Specify the root folder within your source files.\n\nDefault: Computed from the list of input files\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#rootDir)." + }, + "rootDirs": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Allow multiple folders to be treated as one when resolving modules.\n\nDefault: Computed from the list of input files", + "markdownDescription": "Allow multiple folders to be treated as one when resolving modules.\n\nDefault: Computed from the list of input files\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#rootDirs)." + }, + "skipLibCheck": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Skip type checking all .d.ts files.", + "default": true, + "markdownDescription": "Skip type checking all .d.ts files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#skipLibCheck)." + }, + "stableTypeOrdering": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Ensure types are ordered stably and deterministically across compilations.", + "default": true, + "markdownDescription": "Ensure types are ordered stably and deterministically across compilations." + }, + "strict": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable all strict type-checking options.", + "default": true, + "markdownDescription": "Enable all strict type-checking options.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#strict)." + }, + "strictBindCallApply": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Check that the arguments for 'bind', 'call', and 'apply' methods match the original function.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "Check that the arguments for 'bind', 'call', and 'apply' methods match the original function.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#strictBindCallApply)." + }, + "strictBuiltinIteratorReturn": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#strictBuiltinIteratorReturn)." + }, + "strictFunctionTypes": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "When assigning functions, check to ensure parameters and the return values are subtype-compatible.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "When assigning functions, check to ensure parameters and the return values are subtype-compatible.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#strictFunctionTypes)." + }, + "strictNullChecks": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "When type checking, take into account 'null' and 'undefined'.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "When type checking, take into account 'null' and 'undefined'.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#strictNullChecks)." + }, + "strictPropertyInitialization": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Check for class properties that are declared but not set in the constructor.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "Check for class properties that are declared but not set in the constructor.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#strictPropertyInitialization)." + }, + "stripInternal": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable emitting declarations that have '@internal' in their JSDoc comments.", + "default": false, + "markdownDescription": "Disable emitting declarations that have '@internal' in their JSDoc comments.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#stripInternal)." + }, + "skipDefaultLibCheck": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Skip type checking .d.ts files that are included with TypeScript.", + "default": false, + "markdownDescription": "Skip type checking .d.ts files that are included with TypeScript.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#skipDefaultLibCheck)." + }, + "sourceMap": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Create source map files for emitted JavaScript files.", + "default": false, + "markdownDescription": "Create source map files for emitted JavaScript files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#sourceMap)." + }, + "sourceRoot": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the root path for debuggers to find the reference source code.", + "markdownDescription": "Specify the root path for debuggers to find the reference source code.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#sourceRoot)." + }, + "target": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "es5", + "es6", + "es2015", + "es2016", + "es2017", + "es2018", + "es2019", + "es2020", + "es2021", + "es2022", + "es2023", + "es2024", + "es2025", + "esnext", + "es3" + ], + "enumDescriptions": [ + "Deprecated.", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Deprecated." + ] + }, + { + "pattern": "^([Ee][Ss]5|[Ee][Ss]6|[Ee][Ss]2015|[Ee][Ss]2016|[Ee][Ss]2017|[Ee][Ss]2018|[Ee][Ss]2019|[Ee][Ss]2020|[Ee][Ss]2021|[Ee][Ss]2022|[Ee][Ss]2023|[Ee][Ss]2024|[Ee][Ss]2025|[Ee][Ss][Nn][Ee][Xx][Tt]|[Ee][Ss]3)$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Set the JavaScript language version for emitted JavaScript and include compatible library declarations.", + "default": "es2025", + "markdownDescription": "Set the JavaScript language version for emitted JavaScript and include compatible library declarations.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#target)." + }, + "traceResolution": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Log paths used during the 'moduleResolution' process.", + "default": false, + "markdownDescription": "Log paths used during the 'moduleResolution' process.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#traceResolution)." + }, + "tsBuildInfoFile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the path to .tsbuildinfo incremental compilation file.", + "default": ".tsbuildinfo", + "markdownDescription": "Specify the path to .tsbuildinfo incremental compilation file.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#tsBuildInfoFile)." + }, + "typeRoots": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Specify multiple folders that act like './node_modules/@types'.", + "markdownDescription": "Specify multiple folders that act like './node_modules/@types'.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#typeRoots)." + }, + "types": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Specify type package names to be included without being referenced in a source file.", + "markdownDescription": "Specify type package names to be included without being referenced in a source file.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#types)." + }, + "useDefineForClassFields": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Emit ECMAScript-standard-compliant class fields.\n\nDefault: `true` for ES2022 and above, including ESNext.", + "markdownDescription": "Emit ECMAScript-standard-compliant class fields.\n\nDefault: `true` for ES2022 and above, including ESNext.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#useDefineForClassFields)." + }, + "useUnknownInCatchVariables": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Default catch clause variables as 'unknown' instead of 'any'.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "Default catch clause variables as 'unknown' instead of 'any'.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#useUnknownInCatchVariables)." + }, + "verbatimModuleSyntax": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting.", + "default": false, + "markdownDescription": "Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax)." + }, + "maxNodeModuleJsDepth": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'.", + "default": 2, + "markdownDescription": "Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#maxNodeModuleJsDepth)." + }, + "allowSyntheticDefaultImports": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Allow 'import x from y' when a module doesn't have a default export.", + "default": true, + "markdownDescription": "Allow 'import x from y' when a module doesn't have a default export.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowSyntheticDefaultImports).", + "deprecated": true, + "deprecationMessage": "This compiler option is deprecated." + }, + "alwaysStrict": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Ensure 'use strict' is always emitted.", + "default": true, + "markdownDescription": "Ensure 'use strict' is always emitted.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#alwaysStrict).", + "deprecated": true, + "deprecationMessage": "This compiler option is deprecated." + }, + "baseUrl": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the base directory to resolve non-relative module names.", + "markdownDescription": "Specify the base directory to resolve non-relative module names.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#baseUrl).", + "deprecated": true, + "deprecationMessage": "This compiler option is deprecated." + }, + "downlevelIteration": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Emit more compliant, but verbose and less performant JavaScript for iteration.", + "default": false, + "markdownDescription": "Emit more compliant, but verbose and less performant JavaScript for iteration.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#downlevelIteration).", + "deprecated": true, + "deprecationMessage": "This compiler option is deprecated." + }, + "esModuleInterop": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility.", + "default": true, + "markdownDescription": "Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#esModuleInterop).", + "deprecated": true, + "deprecationMessage": "This compiler option is deprecated." + }, + "outFile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output.", + "markdownDescription": "Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#outFile).", + "deprecated": true, + "deprecationMessage": "This compiler option is deprecated." + }, + "diagnostics": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Output compiler performance information after building.", + "default": false, + "markdownDescription": "Output compiler performance information after building.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#diagnostics)." + }, + "extendedDiagnostics": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Output more detailed compiler performance information after building.", + "default": false, + "markdownDescription": "Output more detailed compiler performance information after building.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#extendedDiagnostics)." + }, + "generateCpuProfile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Emit a v8 CPU profile of the compiler run for debugging.", + "default": "profile.cpuprofile", + "markdownDescription": "Emit a v8 CPU profile of the compiler run for debugging.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#generateCpuProfile)." + }, + "generateTrace": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Generates an event trace and a list of types.", + "markdownDescription": "Generates an event trace and a list of types.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#generateTrace)." + }, + "listEmittedFiles": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Print the names of emitted files after a compilation.", + "default": false, + "markdownDescription": "Print the names of emitted files after a compilation.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#listEmittedFiles)." + }, + "listFiles": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Print all of the files read during the compilation.", + "default": false, + "markdownDescription": "Print all of the files read during the compilation.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#listFiles)." + }, + "explainFiles": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Print files read during the compilation including why it was included.", + "default": false, + "markdownDescription": "Print files read during the compilation including why it was included.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#explainFiles)." + }, + "preserveWatchOutput": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable wiping the console in watch mode.", + "default": false, + "markdownDescription": "Disable wiping the console in watch mode.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#preserveWatchOutput)." + }, + "pretty": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable color and formatting in TypeScript's output to make compiler errors easier to read.", + "default": true, + "markdownDescription": "Enable color and formatting in TypeScript's output to make compiler errors easier to read.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#pretty)." + }, + "charset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "The text encoding used to read source files in early TypeScript versions.", + "markdownDescription": "The text encoding used to read source files in early TypeScript versions.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#charset)." + }, + "out": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "The legacy predecessor of outFile, which combined emitted JavaScript into a single file.", + "markdownDescription": "The legacy predecessor of outFile, which combined emitted JavaScript into a single file.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#out)." + }, + "noImplicitUseStrict": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Disable adding 'use strict' directives to emitted JavaScript.", + "markdownDescription": "Disable adding 'use strict' directives to emitted JavaScript.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noImplicitUseStrict)." + }, + "noStrictGenericChecks": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Disable strict checking of generic signatures in function types.", + "markdownDescription": "Disable strict checking of generic signatures in function types.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noStrictGenericChecks)." + }, + "keyofStringsOnly": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Make keyof return only strings instead of strings, numbers, or symbols.", + "markdownDescription": "Make keyof return only strings instead of strings, numbers, or symbols.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#keyofStringsOnly)." + }, + "suppressExcessPropertyErrors": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Disable excess property errors when creating object literals.", + "markdownDescription": "Disable excess property errors when creating object literals.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#suppressExcessPropertyErrors)." + }, + "suppressImplicitAnyIndexErrors": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Suppress noImplicitAny errors when indexing objects that lack index signatures.", + "markdownDescription": "Suppress noImplicitAny errors when indexing objects that lack index signatures.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#suppressImplicitAnyIndexErrors)." + }, + "preserveValueImports": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Preserve unused imported values in JavaScript output. Superseded by verbatimModuleSyntax.", + "markdownDescription": "Preserve unused imported values in JavaScript output. Superseded by verbatimModuleSyntax.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#preserveValueImports)." + }, + "importsNotUsedAsValues": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "remove", + "preserve", + "error" + ] + }, + { + "pattern": "^([Rr][Ee][Mm][Oo][Vv][Ee]|[Pp][Rr][Ee][Ss][Ee][Rr][Vv][Ee]|[Ee][Rr][Rr][Oo][Rr])$" + } + ] + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Control emit and checking for imports used only as types. Superseded by verbatimModuleSyntax.", + "markdownDescription": "Control emit and checking for imports used only as types. Superseded by verbatimModuleSyntax.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#importsNotUsedAsValues)." + } + }, + "additionalProperties": true + }, + "watchOptions": { + "type": [ + "object", + "null" + ], + "properties": { + "watchInterval": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "watchFile": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "fixedpollinginterval", + "prioritypollinginterval", + "dynamicprioritypolling", + "fixedchunksizepolling", + "usefsevents", + "usefseventsonparentdirectory" + ] + }, + { + "pattern": "^([Ff][Ii][Xx][Ee][Dd][Pp][Oo][Ll][Ll][Ii][Nn][Gg][Ii][Nn][Tt][Ee][Rr][Vv][Aa][Ll]|[Pp][Rr][Ii][Oo][Rr][Ii][Tt][Yy][Pp][Oo][Ll][Ll][Ii][Nn][Gg][Ii][Nn][Tt][Ee][Rr][Vv][Aa][Ll]|[Dd][Yy][Nn][Aa][Mm][Ii][Cc][Pp][Rr][Ii][Oo][Rr][Ii][Tt][Yy][Pp][Oo][Ll][Ll][Ii][Nn][Gg]|[Ff][Ii][Xx][Ee][Dd][Cc][Hh][Uu][Nn][Kk][Ss][Ii][Zz][Ee][Pp][Oo][Ll][Ll][Ii][Nn][Gg]|[Uu][Ss][Ee][Ff][Ss][Ee][Vv][Ee][Nn][Tt][Ss]|[Uu][Ss][Ee][Ff][Ss][Ee][Vv][Ee][Nn][Tt][Ss][Oo][Nn][Pp][Aa][Rr][Ee][Nn][Tt][Dd][Ii][Rr][Ee][Cc][Tt][Oo][Rr][Yy])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Specify how the TypeScript watch mode works.", + "default": "usefsevents", + "markdownDescription": "Specify how the TypeScript watch mode works.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#watchFile)." + }, + "watchDirectory": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "usefsevents", + "fixedpollinginterval", + "dynamicprioritypolling", + "fixedchunksizepolling" + ] + }, + { + "pattern": "^([Uu][Ss][Ee][Ff][Ss][Ee][Vv][Ee][Nn][Tt][Ss]|[Ff][Ii][Xx][Ee][Dd][Pp][Oo][Ll][Ll][Ii][Nn][Gg][Ii][Nn][Tt][Ee][Rr][Vv][Aa][Ll]|[Dd][Yy][Nn][Aa][Mm][Ii][Cc][Pp][Rr][Ii][Oo][Rr][Ii][Tt][Yy][Pp][Oo][Ll][Ll][Ii][Nn][Gg]|[Ff][Ii][Xx][Ee][Dd][Cc][Hh][Uu][Nn][Kk][Ss][Ii][Zz][Ee][Pp][Oo][Ll][Ll][Ii][Nn][Gg])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Specify how directories are watched on systems that lack recursive file-watching functionality.", + "default": "usefsevents", + "markdownDescription": "Specify how directories are watched on systems that lack recursive file-watching functionality.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#watchDirectory)." + }, + "fallbackPolling": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "fixedinterval", + "priorityinterval", + "dynamicpriority", + "fixedchunksize" + ] + }, + { + "pattern": "^([Ff][Ii][Xx][Ee][Dd][Ii][Nn][Tt][Ee][Rr][Vv][Aa][Ll]|[Pp][Rr][Ii][Oo][Rr][Ii][Tt][Yy][Ii][Nn][Tt][Ee][Rr][Vv][Aa][Ll]|[Dd][Yy][Nn][Aa][Mm][Ii][Cc][Pp][Rr][Ii][Oo][Rr][Ii][Tt][Yy]|[Ff][Ii][Xx][Ee][Dd][Cc][Hh][Uu][Nn][Kk][Ss][Ii][Zz][Ee])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Specify what approach the watcher should use if the system runs out of native file watchers.", + "default": "priorityinterval", + "markdownDescription": "Specify what approach the watcher should use if the system runs out of native file watchers.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#fallbackPolling)." + }, + "synchronousWatchDirectory": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Synchronously call callbacks and update the state of directory watchers on platforms that don`t support recursive watching natively.", + "default": false, + "markdownDescription": "Synchronously call callbacks and update the state of directory watchers on platforms that don`t support recursive watching natively.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#synchronousWatchDirectory)." + }, + "excludeDirectories": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Remove a list of directories from the watch process.", + "markdownDescription": "Remove a list of directories from the watch process.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#excludeDirectories)." + }, + "excludeFiles": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Remove a list of files from the watch mode's processing.", + "markdownDescription": "Remove a list of files from the watch mode's processing.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#excludeFiles)." + } + }, + "additionalProperties": true + }, + "typeAcquisition": { + "type": [ + "object", + "null" + ], + "properties": { + "enable": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable automatic type acquisition for JavaScript projects.", + "default": true, + "markdownDescription": "Enable automatic type acquisition for JavaScript projects.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#typeAcquisition)." + }, + "include": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Packages to include in automatic type acquisition.", + "markdownDescription": "Packages to include in automatic type acquisition.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#typeAcquisition)." + }, + "exclude": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Packages to exclude from automatic type acquisition.", + "markdownDescription": "Packages to exclude from automatic type acquisition.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#typeAcquisition)." + }, + "disableFilenameBasedTypeAcquisition": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable inferring type acquisition packages from file names.", + "default": false, + "markdownDescription": "Disable inferring type acquisition packages from file names.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#typeAcquisition)." + } + }, + "additionalProperties": true + } + } +} diff --git a/tsc/internal/tsoptions/schemas/tsconfig.schema.json b/tsc/internal/tsoptions/schemas/tsconfig.schema.json new file mode 100644 index 0000000000000..64f45f568e94e --- /dev/null +++ b/tsc/internal/tsoptions/schemas/tsconfig.schema.json @@ -0,0 +1,2337 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "Generated by tools/scripts/tsc/generate-options.ts. DO NOT EDIT.", + "title": "TypeScript configuration", + "type": "object", + "allowComments": true, + "allowTrailingCommas": true, + "properties": { + "$schema": { + "type": "string", + "description": "The JSON schema used to validate this configuration." + }, + "watchOptions": { + "allOf": [ + { + "$ref": "#/definitions/watchOptions" + } + ], + "description": "Options for watching files and directories.", + "markdownDescription": "Options for watching files and directories.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#watchOptions)." + }, + "compilerOptions": { + "allOf": [ + { + "$ref": "#/definitions/compilerOptions" + } + ], + "description": "Options for the TypeScript compiler.", + "markdownDescription": "Options for the TypeScript compiler.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/)." + }, + "typeAcquisition": { + "allOf": [ + { + "$ref": "#/definitions/typeAcquisition" + } + ], + "description": "Options for automatic type acquisition in JavaScript projects.", + "markdownDescription": "Options for automatic type acquisition in JavaScript projects.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#typeAcquisition)." + }, + "extends": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Configuration file or files to inherit from. Later entries take precedence. Relative paths are resolved relative to the configuration file in which they occur.", + "markdownDescription": "Configuration file or files to inherit from. Later entries take precedence. Relative paths are resolved relative to the configuration file in which they occur.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#extends)." + }, + "references": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string", + "minLength": 1 + }, + "circular": { + "type": "boolean" + } + }, + "required": [ + "path" + ] + } + }, + { + "type": "null" + } + ], + "description": "Referenced projects. Each path identifies a configuration file or a directory containing one.", + "markdownDescription": "Referenced projects. Each path identifies a configuration file or a directory containing one.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#references)." + }, + "contentMappers": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "properties": { + "package": { + "type": "string", + "minLength": 1 + }, + "extensions": { + "type": "array", + "items": { + "type": "string" + } + }, + "options": { + "type": "object" + } + }, + "required": [ + "package", + "extensions" + ], + "additionalProperties": false + } + }, + { + "type": "null" + } + ], + "description": "External content mapper packages and the file extensions they handle. Execution must be enabled separately with --runExternalCode.", + "markdownDescription": "External content mapper packages and the file extensions they handle. Execution must be enabled separately with --runExternalCode." + }, + "files": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Files to include in the project, in addition to files matched by include.", + "markdownDescription": "Files to include in the project, in addition to files matched by include.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#files)." + }, + "include": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "File names or glob patterns to include. Defaults to all supported files when neither files nor include is specified.", + "markdownDescription": "File names or glob patterns to include. Defaults to all supported files when neither files nor include is specified.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#include)." + }, + "exclude": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "File names or glob patterns excluded from include. Does not exclude files brought in by imports, references, types, or files.", + "markdownDescription": "File names or glob patterns excluded from include. Does not exclude files brought in by imports, references, types, or files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#exclude)." + }, + "compileOnSave": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "description": "Compile this project when a file is saved in a supporting editor.", + "markdownDescription": "Compile this project when a file is saved in a supporting editor." + } + }, + "additionalProperties": true, + "definitions": { + "compilerOptions": { + "type": [ + "object", + "null" + ], + "properties": { + "allowJs": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Allow JavaScript files to be a part of your program. Use the 'checkJs' option to get errors from these files.\n\nDefault: `false`, unless `checkJs` is set", + "markdownDescription": "Allow JavaScript files to be a part of your program. Use the 'checkJs' option to get errors from these files.\n\nDefault: `false`, unless `checkJs` is set\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowJs)." + }, + "allowArbitraryExtensions": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable importing files with any extension, provided a declaration file is present.", + "default": false, + "markdownDescription": "Enable importing files with any extension, provided a declaration file is present.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowArbitraryExtensions)." + }, + "allowImportingTsExtensions": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set.", + "default": false, + "markdownDescription": "Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowImportingTsExtensions)." + }, + "allowUmdGlobalAccess": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Allow accessing UMD globals from modules.", + "default": false, + "markdownDescription": "Allow accessing UMD globals from modules.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowUmdGlobalAccess)." + }, + "allowUnreachableCode": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable error reporting for unreachable code.", + "markdownDescription": "Disable error reporting for unreachable code.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowUnreachableCode)." + }, + "allowUnusedLabels": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable error reporting for unused labels.", + "markdownDescription": "Disable error reporting for unused labels.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowUnusedLabels)." + }, + "assumeChangesOnlyAffectDirectDependencies": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Have recompiles in projects that use 'incremental' and 'watch' mode assume that changes within a file will only affect files directly depending on it.", + "default": false, + "markdownDescription": "Have recompiles in projects that use 'incremental' and 'watch' mode assume that changes within a file will only affect files directly depending on it.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#assumeChangesOnlyAffectDirectDependencies)." + }, + "checkJs": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable error reporting in type-checked JavaScript files.", + "default": false, + "markdownDescription": "Enable error reporting in type-checked JavaScript files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#checkJs)." + }, + "customConditions": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Conditions to set in addition to the resolver-specific defaults when resolving imports.", + "markdownDescription": "Conditions to set in addition to the resolver-specific defaults when resolving imports.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#customConditions)." + }, + "composite": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable constraints that allow a TypeScript project to be used with project references.", + "default": false, + "markdownDescription": "Enable constraints that allow a TypeScript project to be used with project references.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#composite)." + }, + "emitDeclarationOnly": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Only output d.ts files and not JavaScript files.", + "default": false, + "markdownDescription": "Only output d.ts files and not JavaScript files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#emitDeclarationOnly)." + }, + "emitBOM": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files.", + "default": false, + "markdownDescription": "Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#emitBOM)." + }, + "emitDecoratorMetadata": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Emit design-type metadata for decorated declarations in source files.", + "default": false, + "markdownDescription": "Emit design-type metadata for decorated declarations in source files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#emitDecoratorMetadata)." + }, + "declaration": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Generate .d.ts files from TypeScript and JavaScript files in your project.\n\nDefault: `false`, unless `composite` is set", + "markdownDescription": "Generate .d.ts files from TypeScript and JavaScript files in your project.\n\nDefault: `false`, unless `composite` is set\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#declaration)." + }, + "declarationDir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the output directory for generated declaration files.", + "markdownDescription": "Specify the output directory for generated declaration files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#declarationDir)." + }, + "declarationMap": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Create sourcemaps for d.ts files.", + "default": false, + "markdownDescription": "Create sourcemaps for d.ts files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#declarationMap)." + }, + "deduplicatePackages": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Deduplicate packages with the same name and version.", + "default": true, + "markdownDescription": "Deduplicate packages with the same name and version." + }, + "disableSizeLimit": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server.", + "default": false, + "markdownDescription": "Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#disableSizeLimit)." + }, + "disableSourceOfProjectReferenceRedirect": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable preferring source files instead of declaration files when referencing composite projects.", + "default": false, + "markdownDescription": "Disable preferring source files instead of declaration files when referencing composite projects.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#disableSourceOfProjectReferenceRedirect)." + }, + "disableSolutionSearching": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Opt a project out of multi-project reference checking when editing.", + "default": false, + "markdownDescription": "Opt a project out of multi-project reference checking when editing.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#disableSolutionSearching)." + }, + "disableReferencedProjectLoad": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Reduce the number of projects loaded automatically by TypeScript.", + "default": false, + "markdownDescription": "Reduce the number of projects loaded automatically by TypeScript.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#disableReferencedProjectLoad)." + }, + "erasableSyntaxOnly": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Do not allow runtime constructs that are not part of ECMAScript.", + "default": false, + "markdownDescription": "Do not allow runtime constructs that are not part of ECMAScript.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#erasableSyntaxOnly)." + }, + "exactOptionalPropertyTypes": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Interpret optional property types as written, rather than adding 'undefined'.", + "default": false, + "markdownDescription": "Interpret optional property types as written, rather than adding 'undefined'.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#exactOptionalPropertyTypes)." + }, + "experimentalDecorators": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable experimental support for legacy experimental decorators.", + "default": false, + "markdownDescription": "Enable experimental support for legacy experimental decorators.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#experimentalDecorators)." + }, + "forceConsistentCasingInFileNames": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Ensure that casing is correct in imports.", + "default": true, + "markdownDescription": "Ensure that casing is correct in imports.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#forceConsistentCasingInFileNames)." + }, + "isolatedModules": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Ensure that each file can be safely transpiled without relying on other imports.", + "default": false, + "markdownDescription": "Ensure that each file can be safely transpiled without relying on other imports.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#isolatedModules)." + }, + "isolatedDeclarations": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Require sufficient annotation on exports so other tools can trivially generate declaration files.", + "default": false, + "markdownDescription": "Require sufficient annotation on exports so other tools can trivially generate declaration files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#isolatedDeclarations)." + }, + "ignoreDeprecations": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "importHelpers": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Allow importing helper functions from tslib once per project, instead of including them per-file.", + "default": false, + "markdownDescription": "Allow importing helper functions from tslib once per project, instead of including them per-file.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#importHelpers)." + }, + "inlineSourceMap": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Include sourcemap files inside the emitted JavaScript.", + "default": false, + "markdownDescription": "Include sourcemap files inside the emitted JavaScript.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#inlineSourceMap)." + }, + "inlineSources": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Include source code in the sourcemaps inside the emitted JavaScript.", + "default": false, + "markdownDescription": "Include source code in the sourcemaps inside the emitted JavaScript.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#inlineSources)." + }, + "incremental": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Save .tsbuildinfo files to allow for incremental compilation of projects.\n\nDefault: `false`, unless `composite` is set", + "markdownDescription": "Save .tsbuildinfo files to allow for incremental compilation of projects.\n\nDefault: `false`, unless `composite` is set\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#incremental)." + }, + "jsx": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "preserve", + "react-native", + "react-jsx", + "react-jsxdev", + "react" + ] + }, + { + "pattern": "^([Pp][Rr][Ee][Ss][Ee][Rr][Vv][Ee]|[Rr][Ee][Aa][Cc][Tt]-[Nn][Aa][Tt][Ii][Vv][Ee]|[Rr][Ee][Aa][Cc][Tt]-[Jj][Ss][Xx]|[Rr][Ee][Aa][Cc][Tt]-[Jj][Ss][Xx][Dd][Ee][Vv]|[Rr][Ee][Aa][Cc][Tt])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Specify what JSX code is generated.", + "markdownDescription": "Specify what JSX code is generated.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#jsx)." + }, + "jsxFactory": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.", + "default": "React.createElement", + "markdownDescription": "Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#jsxFactory)." + }, + "jsxFragmentFactory": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'.", + "default": "React.Fragment", + "markdownDescription": "Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#jsxFragmentFactory)." + }, + "jsxImportSource": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'.", + "default": "react", + "markdownDescription": "Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#jsxImportSource)." + }, + "lib": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string", + "anyOf": [ + { + "enum": [ + "es5", + "es6", + "es2015", + "es7", + "es2016", + "es2017", + "es2018", + "es2019", + "es2020", + "es2021", + "es2022", + "es2023", + "es2024", + "es2025", + "esnext", + "dom", + "dom.iterable", + "dom.asynciterable", + "webworker", + "webworker.importscripts", + "webworker.iterable", + "webworker.asynciterable", + "scripthost", + "es2015.core", + "es2015.collection", + "es2015.generator", + "es2015.iterable", + "es2015.promise", + "es2015.proxy", + "es2015.reflect", + "es2015.symbol", + "es2015.symbol.wellknown", + "es2016.array.include", + "es2016.intl", + "es2017.arraybuffer", + "es2017.date", + "es2017.object", + "es2017.sharedmemory", + "es2017.string", + "es2017.intl", + "es2017.typedarrays", + "es2018.asyncgenerator", + "es2018.asynciterable", + "es2018.intl", + "es2018.promise", + "es2018.regexp", + "es2019.array", + "es2019.object", + "es2019.string", + "es2019.symbol", + "es2019.intl", + "es2020.bigint", + "es2020.date", + "es2020.promise", + "es2020.sharedmemory", + "es2020.string", + "es2020.symbol.wellknown", + "es2020.intl", + "es2020.number", + "es2021.promise", + "es2021.string", + "es2021.weakref", + "es2021.intl", + "es2022.array", + "es2022.error", + "es2022.intl", + "es2022.object", + "es2022.string", + "es2022.regexp", + "es2023.array", + "es2023.collection", + "es2023.intl", + "es2024.arraybuffer", + "es2024.collection", + "es2024.object", + "es2024.promise", + "es2024.regexp", + "es2024.sharedmemory", + "es2024.string", + "es2025.collection", + "es2025.float16", + "es2025.intl", + "es2025.iterator", + "es2025.promise", + "es2025.regexp", + "esnext.asynciterable", + "esnext.symbol", + "esnext.bigint", + "esnext.weakref", + "esnext.object", + "esnext.regexp", + "esnext.string", + "esnext.float16", + "esnext.iterator", + "esnext.promise", + "esnext.array", + "esnext.collection", + "esnext.date", + "esnext.decorators", + "esnext.disposable", + "esnext.error", + "esnext.intl", + "esnext.sharedmemory", + "esnext.temporal", + "esnext.typedarrays", + "decorators", + "decorators.legacy", + "es2022.sharedmemory" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Deprecated." + ] + }, + { + "pattern": "^([Ee][Ss]5|[Ee][Ss]6|[Ee][Ss]2015|[Ee][Ss]7|[Ee][Ss]2016|[Ee][Ss]2017|[Ee][Ss]2018|[Ee][Ss]2019|[Ee][Ss]2020|[Ee][Ss]2021|[Ee][Ss]2022|[Ee][Ss]2023|[Ee][Ss]2024|[Ee][Ss]2025|[Ee][Ss][Nn][Ee][Xx][Tt]|[Dd][Oo][Mm]|[Dd][Oo][Mm]\\.[Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Dd][Oo][Mm]\\.[Aa][Ss][Yy][Nn][Cc][Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Ww][Ee][Bb][Ww][Oo][Rr][Kk][Ee][Rr]|[Ww][Ee][Bb][Ww][Oo][Rr][Kk][Ee][Rr]\\.[Ii][Mm][Pp][Oo][Rr][Tt][Ss][Cc][Rr][Ii][Pp][Tt][Ss]|[Ww][Ee][Bb][Ww][Oo][Rr][Kk][Ee][Rr]\\.[Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Ww][Ee][Bb][Ww][Oo][Rr][Kk][Ee][Rr]\\.[Aa][Ss][Yy][Nn][Cc][Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Ss][Cc][Rr][Ii][Pp][Tt][Hh][Oo][Ss][Tt]|[Ee][Ss]2015\\.[Cc][Oo][Rr][Ee]|[Ee][Ss]2015\\.[Cc][Oo][Ll][Ll][Ee][Cc][Tt][Ii][Oo][Nn]|[Ee][Ss]2015\\.[Gg][Ee][Nn][Ee][Rr][Aa][Tt][Oo][Rr]|[Ee][Ss]2015\\.[Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Ee][Ss]2015\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss]2015\\.[Pp][Rr][Oo][Xx][Yy]|[Ee][Ss]2015\\.[Rr][Ee][Ff][Ll][Ee][Cc][Tt]|[Ee][Ss]2015\\.[Ss][Yy][Mm][Bb][Oo][Ll]|[Ee][Ss]2015\\.[Ss][Yy][Mm][Bb][Oo][Ll]\\.[Ww][Ee][Ll][Ll][Kk][Nn][Oo][Ww][Nn]|[Ee][Ss]2016\\.[Aa][Rr][Rr][Aa][Yy]\\.[Ii][Nn][Cc][Ll][Uu][Dd][Ee]|[Ee][Ss]2016\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2017\\.[Aa][Rr][Rr][Aa][Yy][Bb][Uu][Ff][Ff][Ee][Rr]|[Ee][Ss]2017\\.[Dd][Aa][Tt][Ee]|[Ee][Ss]2017\\.[Oo][Bb][Jj][Ee][Cc][Tt]|[Ee][Ss]2017\\.[Ss][Hh][Aa][Rr][Ee][Dd][Mm][Ee][Mm][Oo][Rr][Yy]|[Ee][Ss]2017\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss]2017\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2017\\.[Tt][Yy][Pp][Ee][Dd][Aa][Rr][Rr][Aa][Yy][Ss]|[Ee][Ss]2018\\.[Aa][Ss][Yy][Nn][Cc][Gg][Ee][Nn][Ee][Rr][Aa][Tt][Oo][Rr]|[Ee][Ss]2018\\.[Aa][Ss][Yy][Nn][Cc][Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Ee][Ss]2018\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2018\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss]2018\\.[Rr][Ee][Gg][Ee][Xx][Pp]|[Ee][Ss]2019\\.[Aa][Rr][Rr][Aa][Yy]|[Ee][Ss]2019\\.[Oo][Bb][Jj][Ee][Cc][Tt]|[Ee][Ss]2019\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss]2019\\.[Ss][Yy][Mm][Bb][Oo][Ll]|[Ee][Ss]2019\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2020\\.[Bb][Ii][Gg][Ii][Nn][Tt]|[Ee][Ss]2020\\.[Dd][Aa][Tt][Ee]|[Ee][Ss]2020\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss]2020\\.[Ss][Hh][Aa][Rr][Ee][Dd][Mm][Ee][Mm][Oo][Rr][Yy]|[Ee][Ss]2020\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss]2020\\.[Ss][Yy][Mm][Bb][Oo][Ll]\\.[Ww][Ee][Ll][Ll][Kk][Nn][Oo][Ww][Nn]|[Ee][Ss]2020\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2020\\.[Nn][Uu][Mm][Bb][Ee][Rr]|[Ee][Ss]2021\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss]2021\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss]2021\\.[Ww][Ee][Aa][Kk][Rr][Ee][Ff]|[Ee][Ss]2021\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2022\\.[Aa][Rr][Rr][Aa][Yy]|[Ee][Ss]2022\\.[Ee][Rr][Rr][Oo][Rr]|[Ee][Ss]2022\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2022\\.[Oo][Bb][Jj][Ee][Cc][Tt]|[Ee][Ss]2022\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss]2022\\.[Rr][Ee][Gg][Ee][Xx][Pp]|[Ee][Ss]2023\\.[Aa][Rr][Rr][Aa][Yy]|[Ee][Ss]2023\\.[Cc][Oo][Ll][Ll][Ee][Cc][Tt][Ii][Oo][Nn]|[Ee][Ss]2023\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2024\\.[Aa][Rr][Rr][Aa][Yy][Bb][Uu][Ff][Ff][Ee][Rr]|[Ee][Ss]2024\\.[Cc][Oo][Ll][Ll][Ee][Cc][Tt][Ii][Oo][Nn]|[Ee][Ss]2024\\.[Oo][Bb][Jj][Ee][Cc][Tt]|[Ee][Ss]2024\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss]2024\\.[Rr][Ee][Gg][Ee][Xx][Pp]|[Ee][Ss]2024\\.[Ss][Hh][Aa][Rr][Ee][Dd][Mm][Ee][Mm][Oo][Rr][Yy]|[Ee][Ss]2024\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss]2025\\.[Cc][Oo][Ll][Ll][Ee][Cc][Tt][Ii][Oo][Nn]|[Ee][Ss]2025\\.[Ff][Ll][Oo][Aa][Tt]16|[Ee][Ss]2025\\.[Ii][Nn][Tt][Ll]|[Ee][Ss]2025\\.[Ii][Tt][Ee][Rr][Aa][Tt][Oo][Rr]|[Ee][Ss]2025\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss]2025\\.[Rr][Ee][Gg][Ee][Xx][Pp]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Aa][Ss][Yy][Nn][Cc][Ii][Tt][Ee][Rr][Aa][Bb][Ll][Ee]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ss][Yy][Mm][Bb][Oo][Ll]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Bb][Ii][Gg][Ii][Nn][Tt]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ww][Ee][Aa][Kk][Rr][Ee][Ff]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Oo][Bb][Jj][Ee][Cc][Tt]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Rr][Ee][Gg][Ee][Xx][Pp]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ss][Tt][Rr][Ii][Nn][Gg]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ff][Ll][Oo][Aa][Tt]16|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ii][Tt][Ee][Rr][Aa][Tt][Oo][Rr]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Pp][Rr][Oo][Mm][Ii][Ss][Ee]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Aa][Rr][Rr][Aa][Yy]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Cc][Oo][Ll][Ll][Ee][Cc][Tt][Ii][Oo][Nn]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Dd][Aa][Tt][Ee]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Dd][Ee][Cc][Oo][Rr][Aa][Tt][Oo][Rr][Ss]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Dd][Ii][Ss][Pp][Oo][Ss][Aa][Bb][Ll][Ee]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ee][Rr][Rr][Oo][Rr]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ii][Nn][Tt][Ll]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Ss][Hh][Aa][Rr][Ee][Dd][Mm][Ee][Mm][Oo][Rr][Yy]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Tt][Ee][Mm][Pp][Oo][Rr][Aa][Ll]|[Ee][Ss][Nn][Ee][Xx][Tt]\\.[Tt][Yy][Pp][Ee][Dd][Aa][Rr][Rr][Aa][Yy][Ss]|[Dd][Ee][Cc][Oo][Rr][Aa][Tt][Oo][Rr][Ss]|[Dd][Ee][Cc][Oo][Rr][Aa][Tt][Oo][Rr][Ss]\\.[Ll][Ee][Gg][Aa][Cc][Yy]|[Ee][Ss]2022\\.[Ss][Hh][Aa][Rr][Ee][Dd][Mm][Ee][Mm][Oo][Rr][Yy])$" + } + ] + } + }, + { + "type": "null" + } + ], + "description": "Specify a set of bundled library declaration files that describe the target runtime environment.", + "markdownDescription": "Specify a set of bundled library declaration files that describe the target runtime environment.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#lib)." + }, + "libReplacement": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable lib replacement.", + "default": false, + "markdownDescription": "Enable lib replacement.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#libReplacement)." + }, + "mapRoot": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the location where debugger should locate map files instead of generated locations.", + "markdownDescription": "Specify the location where debugger should locate map files instead of generated locations.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#mapRoot)." + }, + "module": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "commonjs", + "amd", + "system", + "umd", + "es6", + "es2015", + "es2020", + "es2022", + "esnext", + "node16", + "node18", + "node20", + "nodenext", + "preserve", + "none" + ], + "enumDescriptions": [ + "", + "Deprecated.", + "Deprecated.", + "Deprecated.", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Deprecated." + ] + }, + { + "pattern": "^([Cc][Oo][Mm][Mm][Oo][Nn][Jj][Ss]|[Aa][Mm][Dd]|[Ss][Yy][Ss][Tt][Ee][Mm]|[Uu][Mm][Dd]|[Ee][Ss]6|[Ee][Ss]2015|[Ee][Ss]2020|[Ee][Ss]2022|[Ee][Ss][Nn][Ee][Xx][Tt]|[Nn][Oo][Dd][Ee]16|[Nn][Oo][Dd][Ee]18|[Nn][Oo][Dd][Ee]20|[Nn][Oo][Dd][Ee][Nn][Ee][Xx][Tt]|[Pp][Rr][Ee][Ss][Ee][Rr][Vv][Ee]|[Nn][Oo][Nn][Ee])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Specify what module code is generated.", + "markdownDescription": "Specify what module code is generated.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#module)." + }, + "moduleResolution": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "node16", + "nodenext", + "bundler", + "classic", + "node", + "node10" + ], + "enumDescriptions": [ + "", + "", + "", + "Deprecated.", + "Deprecated.", + "Deprecated." + ] + }, + { + "pattern": "^([Nn][Oo][Dd][Ee]16|[Nn][Oo][Dd][Ee][Nn][Ee][Xx][Tt]|[Bb][Uu][Nn][Dd][Ll][Ee][Rr]|[Cc][Ll][Aa][Ss][Ss][Ii][Cc]|[Nn][Oo][Dd][Ee]|[Nn][Oo][Dd][Ee]10)$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Specify how TypeScript looks up a file from a given module specifier.\n\nDefault: `nodenext` if `module` is `nodenext`; `node16` if `module` is `node16` or `node18`; otherwise, `bundler`.", + "markdownDescription": "Specify how TypeScript looks up a file from a given module specifier.\n\nDefault: `nodenext` if `module` is `nodenext`; `node16` if `module` is `node16` or `node18`; otherwise, `bundler`.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#moduleResolution)." + }, + "moduleSuffixes": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "List of file name suffixes to search when resolving a module.", + "markdownDescription": "List of file name suffixes to search when resolving a module.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#moduleSuffixes)." + }, + "moduleDetection": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "auto", + "legacy", + "force" + ] + }, + { + "pattern": "^([Aa][Uu][Tt][Oo]|[Ll][Ee][Gg][Aa][Cc][Yy]|[Ff][Oo][Rr][Cc][Ee])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Control what method is used to detect module-format JS files.\n\nDefault: \"auto\": Treat files with imports, exports, import.meta, jsx (with jsx: react-jsx), or esm format (with module: node16+) as modules.", + "markdownDescription": "Control what method is used to detect module-format JS files.\n\nDefault: \"auto\": Treat files with imports, exports, import.meta, jsx (with jsx: react-jsx), or esm format (with module: node16+) as modules.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#moduleDetection)." + }, + "newLine": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "crlf", + "lf" + ] + }, + { + "pattern": "^([Cc][Rr][Ll][Ff]|[Ll][Ff])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Set the newline character for emitting files.", + "default": "lf", + "markdownDescription": "Set the newline character for emitting files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#newLine)." + }, + "noEmit": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable emitting files from a compilation.", + "default": false, + "markdownDescription": "Disable emitting files from a compilation.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noEmit)." + }, + "noCheck": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable full type checking (only critical parse and emit errors will be reported).", + "default": false, + "markdownDescription": "Disable full type checking (only critical parse and emit errors will be reported).\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noCheck)." + }, + "noErrorTruncation": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable truncating types in error messages.", + "default": false, + "markdownDescription": "Disable truncating types in error messages.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noErrorTruncation)." + }, + "noFallthroughCasesInSwitch": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable error reporting for fallthrough cases in switch statements.", + "default": false, + "markdownDescription": "Enable error reporting for fallthrough cases in switch statements.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noFallthroughCasesInSwitch)." + }, + "noImplicitAny": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable error reporting for expressions and declarations with an implied 'any' type.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "Enable error reporting for expressions and declarations with an implied 'any' type.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noImplicitAny)." + }, + "noImplicitThis": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable error reporting when 'this' is given the type 'any'.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "Enable error reporting when 'this' is given the type 'any'.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noImplicitThis)." + }, + "noImplicitReturns": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable error reporting for codepaths that do not explicitly return in a function.", + "default": false, + "markdownDescription": "Enable error reporting for codepaths that do not explicitly return in a function.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noImplicitReturns)." + }, + "noEmitHelpers": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable generating custom helper functions like '__extends' in compiled output.", + "default": false, + "markdownDescription": "Disable generating custom helper functions like '__extends' in compiled output.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noEmitHelpers)." + }, + "noLib": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable including any library files, including the default lib.d.ts.", + "default": false, + "markdownDescription": "Disable including any library files, including the default lib.d.ts.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noLib)." + }, + "noPropertyAccessFromIndexSignature": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enforces using indexed accessors for keys declared using an indexed type.", + "default": false, + "markdownDescription": "Enforces using indexed accessors for keys declared using an indexed type.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noPropertyAccessFromIndexSignature)." + }, + "noUncheckedIndexedAccess": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Add 'undefined' to a type when accessed using an index.", + "default": false, + "markdownDescription": "Add 'undefined' to a type when accessed using an index.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noUncheckedIndexedAccess)." + }, + "noEmitOnError": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable emitting files if any type checking errors are reported.", + "default": false, + "markdownDescription": "Disable emitting files if any type checking errors are reported.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noEmitOnError)." + }, + "noUnusedLocals": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable error reporting when local variables aren't read.", + "default": false, + "markdownDescription": "Enable error reporting when local variables aren't read.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noUnusedLocals)." + }, + "noUnusedParameters": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Raise an error when a function parameter isn't read.", + "default": false, + "markdownDescription": "Raise an error when a function parameter isn't read.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noUnusedParameters)." + }, + "noResolve": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project.", + "default": false, + "markdownDescription": "Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noResolve)." + }, + "noImplicitOverride": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Ensure overriding members in derived classes are marked with an override modifier.", + "default": false, + "markdownDescription": "Ensure overriding members in derived classes are marked with an override modifier.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noImplicitOverride)." + }, + "noUncheckedSideEffectImports": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Check side effect imports.", + "default": true, + "markdownDescription": "Check side effect imports.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noUncheckedSideEffectImports)." + }, + "outDir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify an output folder for all emitted files.", + "markdownDescription": "Specify an output folder for all emitted files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#outDir)." + }, + "paths": { + "anyOf": [ + { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "type": "null" + } + ], + "description": "Specify a set of entries that re-map imports to additional lookup locations.", + "markdownDescription": "Specify a set of entries that re-map imports to additional lookup locations.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#paths)." + }, + "plugins": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + }, + { + "type": "null" + } + ], + "description": "Specify a list of language service plugins to include.", + "markdownDescription": "Specify a list of language service plugins to include.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#plugins)." + }, + "preserveConstEnums": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable erasing 'const enum' declarations in generated code.", + "default": false, + "markdownDescription": "Disable erasing 'const enum' declarations in generated code.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#preserveConstEnums)." + }, + "preserveSymlinks": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable resolving symlinks to their realpath. This correlates to the same flag in node.", + "default": false, + "markdownDescription": "Disable resolving symlinks to their realpath. This correlates to the same flag in node.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#preserveSymlinks)." + }, + "resolveJsonModule": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable importing .json files.", + "default": false, + "markdownDescription": "Enable importing .json files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#resolveJsonModule)." + }, + "resolvePackageJsonExports": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Use the package.json 'exports' field when resolving package imports.\n\nDefault: `true` when 'moduleResolution' is 'node16', 'nodenext', or 'bundler'; otherwise `false`.", + "markdownDescription": "Use the package.json 'exports' field when resolving package imports.\n\nDefault: `true` when 'moduleResolution' is 'node16', 'nodenext', or 'bundler'; otherwise `false`.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#resolvePackageJsonExports)." + }, + "resolvePackageJsonImports": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Use the package.json 'imports' field when resolving imports.\n\nDefault: `true` when 'moduleResolution' is 'node16', 'nodenext', or 'bundler'; otherwise `false`.", + "markdownDescription": "Use the package.json 'imports' field when resolving imports.\n\nDefault: `true` when 'moduleResolution' is 'node16', 'nodenext', or 'bundler'; otherwise `false`.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#resolvePackageJsonImports)." + }, + "removeComments": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable emitting comments.", + "default": false, + "markdownDescription": "Disable emitting comments.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#removeComments)." + }, + "rewriteRelativeImportExtensions": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files.", + "default": false, + "markdownDescription": "Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#rewriteRelativeImportExtensions)." + }, + "reactNamespace": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit.", + "default": "React", + "markdownDescription": "Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#reactNamespace)." + }, + "rootDir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the root folder within your source files.\n\nDefault: Computed from the list of input files", + "markdownDescription": "Specify the root folder within your source files.\n\nDefault: Computed from the list of input files\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#rootDir)." + }, + "rootDirs": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Allow multiple folders to be treated as one when resolving modules.\n\nDefault: Computed from the list of input files", + "markdownDescription": "Allow multiple folders to be treated as one when resolving modules.\n\nDefault: Computed from the list of input files\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#rootDirs)." + }, + "skipLibCheck": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Skip type checking all .d.ts files.", + "default": false, + "markdownDescription": "Skip type checking all .d.ts files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#skipLibCheck)." + }, + "stableTypeOrdering": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Ensure types are ordered stably and deterministically across compilations.", + "default": true, + "markdownDescription": "Ensure types are ordered stably and deterministically across compilations." + }, + "strict": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable all strict type-checking options.", + "default": true, + "markdownDescription": "Enable all strict type-checking options.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#strict)." + }, + "strictBindCallApply": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Check that the arguments for 'bind', 'call', and 'apply' methods match the original function.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "Check that the arguments for 'bind', 'call', and 'apply' methods match the original function.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#strictBindCallApply)." + }, + "strictBuiltinIteratorReturn": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#strictBuiltinIteratorReturn)." + }, + "strictFunctionTypes": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "When assigning functions, check to ensure parameters and the return values are subtype-compatible.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "When assigning functions, check to ensure parameters and the return values are subtype-compatible.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#strictFunctionTypes)." + }, + "strictNullChecks": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "When type checking, take into account 'null' and 'undefined'.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "When type checking, take into account 'null' and 'undefined'.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#strictNullChecks)." + }, + "strictPropertyInitialization": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Check for class properties that are declared but not set in the constructor.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "Check for class properties that are declared but not set in the constructor.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#strictPropertyInitialization)." + }, + "stripInternal": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable emitting declarations that have '@internal' in their JSDoc comments.", + "default": false, + "markdownDescription": "Disable emitting declarations that have '@internal' in their JSDoc comments.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#stripInternal)." + }, + "skipDefaultLibCheck": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Skip type checking .d.ts files that are included with TypeScript.", + "default": false, + "markdownDescription": "Skip type checking .d.ts files that are included with TypeScript.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#skipDefaultLibCheck)." + }, + "sourceMap": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Create source map files for emitted JavaScript files.", + "default": false, + "markdownDescription": "Create source map files for emitted JavaScript files.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#sourceMap)." + }, + "sourceRoot": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the root path for debuggers to find the reference source code.", + "markdownDescription": "Specify the root path for debuggers to find the reference source code.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#sourceRoot)." + }, + "target": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "es5", + "es6", + "es2015", + "es2016", + "es2017", + "es2018", + "es2019", + "es2020", + "es2021", + "es2022", + "es2023", + "es2024", + "es2025", + "esnext", + "es3" + ], + "enumDescriptions": [ + "Deprecated.", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Deprecated." + ] + }, + { + "pattern": "^([Ee][Ss]5|[Ee][Ss]6|[Ee][Ss]2015|[Ee][Ss]2016|[Ee][Ss]2017|[Ee][Ss]2018|[Ee][Ss]2019|[Ee][Ss]2020|[Ee][Ss]2021|[Ee][Ss]2022|[Ee][Ss]2023|[Ee][Ss]2024|[Ee][Ss]2025|[Ee][Ss][Nn][Ee][Xx][Tt]|[Ee][Ss]3)$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Set the JavaScript language version for emitted JavaScript and include compatible library declarations.", + "default": "es2025", + "markdownDescription": "Set the JavaScript language version for emitted JavaScript and include compatible library declarations.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#target)." + }, + "traceResolution": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Log paths used during the 'moduleResolution' process.", + "default": false, + "markdownDescription": "Log paths used during the 'moduleResolution' process.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#traceResolution)." + }, + "tsBuildInfoFile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the path to .tsbuildinfo incremental compilation file.", + "default": ".tsbuildinfo", + "markdownDescription": "Specify the path to .tsbuildinfo incremental compilation file.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#tsBuildInfoFile)." + }, + "typeRoots": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Specify multiple folders that act like './node_modules/@types'.", + "markdownDescription": "Specify multiple folders that act like './node_modules/@types'.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#typeRoots)." + }, + "types": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Specify type package names to be included without being referenced in a source file.", + "markdownDescription": "Specify type package names to be included without being referenced in a source file.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#types)." + }, + "useDefineForClassFields": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Emit ECMAScript-standard-compliant class fields.\n\nDefault: `true` for ES2022 and above, including ESNext.", + "markdownDescription": "Emit ECMAScript-standard-compliant class fields.\n\nDefault: `true` for ES2022 and above, including ESNext.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#useDefineForClassFields)." + }, + "useUnknownInCatchVariables": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Default catch clause variables as 'unknown' instead of 'any'.\n\nDefault: `true`, unless `strict` is `false`", + "markdownDescription": "Default catch clause variables as 'unknown' instead of 'any'.\n\nDefault: `true`, unless `strict` is `false`\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#useUnknownInCatchVariables)." + }, + "verbatimModuleSyntax": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting.", + "default": false, + "markdownDescription": "Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax)." + }, + "maxNodeModuleJsDepth": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'.", + "default": 0, + "markdownDescription": "Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#maxNodeModuleJsDepth)." + }, + "allowSyntheticDefaultImports": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Allow 'import x from y' when a module doesn't have a default export.", + "default": true, + "markdownDescription": "Allow 'import x from y' when a module doesn't have a default export.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#allowSyntheticDefaultImports).", + "deprecated": true, + "deprecationMessage": "This compiler option is deprecated." + }, + "alwaysStrict": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Ensure 'use strict' is always emitted.", + "default": true, + "markdownDescription": "Ensure 'use strict' is always emitted.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#alwaysStrict).", + "deprecated": true, + "deprecationMessage": "This compiler option is deprecated." + }, + "baseUrl": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify the base directory to resolve non-relative module names.", + "markdownDescription": "Specify the base directory to resolve non-relative module names.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#baseUrl).", + "deprecated": true, + "deprecationMessage": "This compiler option is deprecated." + }, + "downlevelIteration": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Emit more compliant, but verbose and less performant JavaScript for iteration.", + "default": false, + "markdownDescription": "Emit more compliant, but verbose and less performant JavaScript for iteration.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#downlevelIteration).", + "deprecated": true, + "deprecationMessage": "This compiler option is deprecated." + }, + "esModuleInterop": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility.", + "default": true, + "markdownDescription": "Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#esModuleInterop).", + "deprecated": true, + "deprecationMessage": "This compiler option is deprecated." + }, + "outFile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output.", + "markdownDescription": "Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#outFile).", + "deprecated": true, + "deprecationMessage": "This compiler option is deprecated." + }, + "diagnostics": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Output compiler performance information after building.", + "default": false, + "markdownDescription": "Output compiler performance information after building.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#diagnostics)." + }, + "extendedDiagnostics": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Output more detailed compiler performance information after building.", + "default": false, + "markdownDescription": "Output more detailed compiler performance information after building.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#extendedDiagnostics)." + }, + "generateCpuProfile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Emit a v8 CPU profile of the compiler run for debugging.", + "default": "profile.cpuprofile", + "markdownDescription": "Emit a v8 CPU profile of the compiler run for debugging.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#generateCpuProfile)." + }, + "generateTrace": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Generates an event trace and a list of types.", + "markdownDescription": "Generates an event trace and a list of types.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#generateTrace)." + }, + "listEmittedFiles": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Print the names of emitted files after a compilation.", + "default": false, + "markdownDescription": "Print the names of emitted files after a compilation.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#listEmittedFiles)." + }, + "listFiles": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Print all of the files read during the compilation.", + "default": false, + "markdownDescription": "Print all of the files read during the compilation.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#listFiles)." + }, + "explainFiles": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Print files read during the compilation including why it was included.", + "default": false, + "markdownDescription": "Print files read during the compilation including why it was included.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#explainFiles)." + }, + "preserveWatchOutput": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable wiping the console in watch mode.", + "default": false, + "markdownDescription": "Disable wiping the console in watch mode.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#preserveWatchOutput)." + }, + "pretty": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable color and formatting in TypeScript's output to make compiler errors easier to read.", + "default": true, + "markdownDescription": "Enable color and formatting in TypeScript's output to make compiler errors easier to read.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#pretty)." + }, + "charset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "The text encoding used to read source files in early TypeScript versions.", + "markdownDescription": "The text encoding used to read source files in early TypeScript versions.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#charset)." + }, + "out": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "The legacy predecessor of outFile, which combined emitted JavaScript into a single file.", + "markdownDescription": "The legacy predecessor of outFile, which combined emitted JavaScript into a single file.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#out)." + }, + "noImplicitUseStrict": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Disable adding 'use strict' directives to emitted JavaScript.", + "markdownDescription": "Disable adding 'use strict' directives to emitted JavaScript.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noImplicitUseStrict)." + }, + "noStrictGenericChecks": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Disable strict checking of generic signatures in function types.", + "markdownDescription": "Disable strict checking of generic signatures in function types.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#noStrictGenericChecks)." + }, + "keyofStringsOnly": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Make keyof return only strings instead of strings, numbers, or symbols.", + "markdownDescription": "Make keyof return only strings instead of strings, numbers, or symbols.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#keyofStringsOnly)." + }, + "suppressExcessPropertyErrors": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Disable excess property errors when creating object literals.", + "markdownDescription": "Disable excess property errors when creating object literals.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#suppressExcessPropertyErrors)." + }, + "suppressImplicitAnyIndexErrors": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Suppress noImplicitAny errors when indexing objects that lack index signatures.", + "markdownDescription": "Suppress noImplicitAny errors when indexing objects that lack index signatures.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#suppressImplicitAnyIndexErrors)." + }, + "preserveValueImports": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Preserve unused imported values in JavaScript output. Superseded by verbatimModuleSyntax.", + "markdownDescription": "Preserve unused imported values in JavaScript output. Superseded by verbatimModuleSyntax.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#preserveValueImports)." + }, + "importsNotUsedAsValues": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "remove", + "preserve", + "error" + ] + }, + { + "pattern": "^([Rr][Ee][Mm][Oo][Vv][Ee]|[Pp][Rr][Ee][Ss][Ee][Rr][Vv][Ee]|[Ee][Rr][Rr][Oo][Rr])$" + } + ] + }, + { + "type": "null" + } + ], + "deprecated": true, + "deprecationMessage": "This option has been removed from TypeScript. It is retained in the schema for historical configurations.", + "description": "Control emit and checking for imports used only as types. Superseded by verbatimModuleSyntax.", + "markdownDescription": "Control emit and checking for imports used only as types. Superseded by verbatimModuleSyntax.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#importsNotUsedAsValues)." + } + }, + "additionalProperties": true + }, + "watchOptions": { + "type": [ + "object", + "null" + ], + "properties": { + "watchInterval": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "watchFile": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "fixedpollinginterval", + "prioritypollinginterval", + "dynamicprioritypolling", + "fixedchunksizepolling", + "usefsevents", + "usefseventsonparentdirectory" + ] + }, + { + "pattern": "^([Ff][Ii][Xx][Ee][Dd][Pp][Oo][Ll][Ll][Ii][Nn][Gg][Ii][Nn][Tt][Ee][Rr][Vv][Aa][Ll]|[Pp][Rr][Ii][Oo][Rr][Ii][Tt][Yy][Pp][Oo][Ll][Ll][Ii][Nn][Gg][Ii][Nn][Tt][Ee][Rr][Vv][Aa][Ll]|[Dd][Yy][Nn][Aa][Mm][Ii][Cc][Pp][Rr][Ii][Oo][Rr][Ii][Tt][Yy][Pp][Oo][Ll][Ll][Ii][Nn][Gg]|[Ff][Ii][Xx][Ee][Dd][Cc][Hh][Uu][Nn][Kk][Ss][Ii][Zz][Ee][Pp][Oo][Ll][Ll][Ii][Nn][Gg]|[Uu][Ss][Ee][Ff][Ss][Ee][Vv][Ee][Nn][Tt][Ss]|[Uu][Ss][Ee][Ff][Ss][Ee][Vv][Ee][Nn][Tt][Ss][Oo][Nn][Pp][Aa][Rr][Ee][Nn][Tt][Dd][Ii][Rr][Ee][Cc][Tt][Oo][Rr][Yy])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Specify how the TypeScript watch mode works.", + "default": "usefsevents", + "markdownDescription": "Specify how the TypeScript watch mode works.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#watchFile)." + }, + "watchDirectory": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "usefsevents", + "fixedpollinginterval", + "dynamicprioritypolling", + "fixedchunksizepolling" + ] + }, + { + "pattern": "^([Uu][Ss][Ee][Ff][Ss][Ee][Vv][Ee][Nn][Tt][Ss]|[Ff][Ii][Xx][Ee][Dd][Pp][Oo][Ll][Ll][Ii][Nn][Gg][Ii][Nn][Tt][Ee][Rr][Vv][Aa][Ll]|[Dd][Yy][Nn][Aa][Mm][Ii][Cc][Pp][Rr][Ii][Oo][Rr][Ii][Tt][Yy][Pp][Oo][Ll][Ll][Ii][Nn][Gg]|[Ff][Ii][Xx][Ee][Dd][Cc][Hh][Uu][Nn][Kk][Ss][Ii][Zz][Ee][Pp][Oo][Ll][Ll][Ii][Nn][Gg])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Specify how directories are watched on systems that lack recursive file-watching functionality.", + "default": "usefsevents", + "markdownDescription": "Specify how directories are watched on systems that lack recursive file-watching functionality.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#watchDirectory)." + }, + "fallbackPolling": { + "anyOf": [ + { + "type": "string", + "anyOf": [ + { + "enum": [ + "fixedinterval", + "priorityinterval", + "dynamicpriority", + "fixedchunksize" + ] + }, + { + "pattern": "^([Ff][Ii][Xx][Ee][Dd][Ii][Nn][Tt][Ee][Rr][Vv][Aa][Ll]|[Pp][Rr][Ii][Oo][Rr][Ii][Tt][Yy][Ii][Nn][Tt][Ee][Rr][Vv][Aa][Ll]|[Dd][Yy][Nn][Aa][Mm][Ii][Cc][Pp][Rr][Ii][Oo][Rr][Ii][Tt][Yy]|[Ff][Ii][Xx][Ee][Dd][Cc][Hh][Uu][Nn][Kk][Ss][Ii][Zz][Ee])$" + } + ] + }, + { + "type": "null" + } + ], + "description": "Specify what approach the watcher should use if the system runs out of native file watchers.", + "default": "priorityinterval", + "markdownDescription": "Specify what approach the watcher should use if the system runs out of native file watchers.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#fallbackPolling)." + }, + "synchronousWatchDirectory": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Synchronously call callbacks and update the state of directory watchers on platforms that don`t support recursive watching natively.", + "default": false, + "markdownDescription": "Synchronously call callbacks and update the state of directory watchers on platforms that don`t support recursive watching natively.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#synchronousWatchDirectory)." + }, + "excludeDirectories": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Remove a list of directories from the watch process.", + "markdownDescription": "Remove a list of directories from the watch process.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#excludeDirectories)." + }, + "excludeFiles": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Remove a list of files from the watch mode's processing.", + "markdownDescription": "Remove a list of files from the watch mode's processing.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#excludeFiles)." + } + }, + "additionalProperties": true + }, + "typeAcquisition": { + "type": [ + "object", + "null" + ], + "properties": { + "enable": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Enable automatic type acquisition for JavaScript projects.", + "default": false, + "markdownDescription": "Enable automatic type acquisition for JavaScript projects.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#typeAcquisition)." + }, + "include": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Packages to include in automatic type acquisition.", + "markdownDescription": "Packages to include in automatic type acquisition.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#typeAcquisition)." + }, + "exclude": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Packages to exclude from automatic type acquisition.", + "markdownDescription": "Packages to exclude from automatic type acquisition.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#typeAcquisition)." + }, + "disableFilenameBasedTypeAcquisition": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Disable inferring type acquisition packages from file names.", + "default": false, + "markdownDescription": "Disable inferring type acquisition packages from file names.\n\nSee the [TSConfig reference](https://www.typescriptlang.org/tsconfig/#typeAcquisition)." + } + }, + "additionalProperties": true + } + } +} diff --git a/tsc/internal/tsoptions/showconfig.go b/tsc/internal/tsoptions/showconfig.go index 17b7c03612a68..5e5d016cd8933 100644 --- a/tsc/internal/tsoptions/showconfig.go +++ b/tsc/internal/tsoptions/showconfig.go @@ -1,18 +1,14 @@ package tsoptions import ( - "reflect" - "github.com/microsoft/TypeScript/tsc/internal/collections" "github.com/microsoft/TypeScript/tsc/internal/core" - "github.com/microsoft/TypeScript/tsc/internal/debug" - "github.com/microsoft/TypeScript/tsc/internal/diagnostics" "github.com/microsoft/TypeScript/tsc/internal/tspath" ) // computeFn wraps a typed getter method so it can be stored in an impliedOption's // compute field (which has type func(*core.CompilerOptions) any). -func computeFn[T any](fn func(*core.CompilerOptions) T) func(*core.CompilerOptions) any { +func computeFn[T comparable](fn func(*core.CompilerOptions) T) func(*core.CompilerOptions) any { return func(opts *core.CompilerOptions) any { return fn(opts) } @@ -159,139 +155,30 @@ func getNameOfCompilerOptionValue(value any, enumMap *collections.OrderedMap[str return "" } -// serializeCompilerOptions converts CompilerOptions to an ordered map with -// string names as keys and serialized values (enums as strings, paths as -// relative paths, etc.) matching the output of tsc --showConfig. -func serializeCompilerOptions(options *core.CompilerOptions, configFilePath string, comparePathsOptions tspath.ComparePathsOptions) *collections.OrderedMap[string, any] { - result := collections.NewOrderedMapWithSizeHint[string, any](32) +func serializeCompilerOptionPath(value string, configFilePath string, comparePathsOptions tspath.ComparePathsOptions) string { configDir := tspath.GetDirectoryPath(configFilePath) + absolute := tspath.GetNormalizedAbsolutePath(value, configDir) + return tspath.GetRelativePathFromFile(configFilePath, absolute, comparePathsOptions) +} - optionsValue := reflect.ValueOf(options).Elem() - optionsTypeInfo := reflect.TypeFor[core.CompilerOptions]() - - for i := range optionsValue.NumField() { - field := optionsTypeInfo.Field(i) - if !field.IsExported() { - continue - } - - optionDecl := CommandLineCompilerOptionsMap.Get(field.Name) - if optionDecl == nil { - continue - } - - // Skip command-line-only and output formatting options - if optionDecl.Category == diagnostics.Command_line_Options || optionDecl.Category == diagnostics.Output_Formatting { - continue - } - - fieldValue := optionsValue.Field(i) - - // Skip zero values (unset options) - if fieldValue.IsZero() { - continue - } - - name := optionDecl.Name - value := fieldValue.Interface() - - enumMap := optionDecl.EnumMap() - if enumMap != nil { - // Enum option - convert numeric value to string name - serialized := serializeEnumValue(value, enumMap) - if serialized != "" { - result.Set(name, serialized) - } - continue - } - - switch optionDecl.Kind { - case CommandLineOptionTypeListOrElement: - debug.Assert(false, "listOrElement option should not reach serialization") - case CommandLineOptionTypeList: - elem := optionDecl.Elements() - if elem != nil && elem.IsFilePath { - // List of file paths - make relative - if strs, ok := value.([]string); ok { - relPaths := make([]string, len(strs)) - for j, s := range strs { - absPath := tspath.GetNormalizedAbsolutePath(s, configDir) - relPaths[j] = tspath.GetRelativePathFromFile(configFilePath, absPath, comparePathsOptions) - } - result.Set(name, relPaths) - continue - } - } - if elem != nil && elem.EnumMap() != nil { - // List of enum values (e.g., lib) - elemMap := elem.EnumMap() - if strs, ok := value.([]string); ok { - serialized := make([]string, 0, len(strs)) - for _, s := range strs { - // lib values are already stored as the d.ts filename, need to find original key - found := getNameOfCompilerOptionValue(s, elemMap) - if found != "" { - serialized = append(serialized, found) - } else { - serialized = append(serialized, s) - } - } - result.Set(name, serialized) - continue - } - } - result.Set(name, value) - - case CommandLineOptionTypeString: - if optionDecl.IsFilePath { - // File path option - make relative to config - if s, ok := value.(string); ok && s != "" { - absPath := tspath.GetNormalizedAbsolutePath(s, configDir) - result.Set(name, tspath.GetRelativePathFromFile(configFilePath, absPath, comparePathsOptions)) - continue - } - } - result.Set(name, value) - - case CommandLineOptionTypeBoolean: - if t, ok := value.(core.Tristate); ok { - if t.IsTrue() { - result.Set(name, true) - } else if t.IsFalse() { - result.Set(name, false) - } - } else { - result.Set(name, value) - } - - case CommandLineOptionTypeNumber: - result.Set(name, value) - - default: - result.Set(name, value) - } +func serializeCompilerOptionPaths(values []string, configFilePath string, comparePathsOptions tspath.ComparePathsOptions) []string { + result := make([]string, len(values)) + for i, value := range values { + result[i] = serializeCompilerOptionPath(value, configFilePath, comparePathsOptions) } - return result } -// serializeEnumValue converts an enum field value to its corresponding string key -// using the option's enum map. It handles int32-based enum types. -func serializeEnumValue(value any, enumMap *collections.OrderedMap[string, any]) string { - // The enum maps store values as core.ModuleKind, core.ScriptTarget, etc. - // But those are all int32 underneath. We need to compare by the underlying int32 value. - rv := reflect.ValueOf(value) - if rv.CanInt() { - intVal := rv.Int() - for k, v := range enumMap.Entries() { - ev := reflect.ValueOf(v) - if ev.CanInt() && ev.Int() == intVal { - return k - } +func serializeCompilerOptionEnumList(values []string, enumMap *collections.OrderedMap[string, any]) []string { + result := make([]string, len(values)) + for i, value := range values { + if name := getNameOfCompilerOptionValue(value, enumMap); name != "" { + result[i] = name + } else { + result[i] = value } } - // Fallback: direct comparison - return getNameOfCompilerOptionValue(value, enumMap) + return result } // addImpliedOptions adds compiler options that are implied by other explicitly-set options, @@ -334,7 +221,7 @@ func addImpliedOptions( defaultVal := entry.compute(defaultOpts) // If the implied value equals the default, this option doesn't add useful information. - if reflect.DeepEqual(implied, defaultVal) { + if implied == defaultVal { continue } @@ -368,7 +255,7 @@ func serializeImpliedOptionValue(optionDecl *CommandLineOption, value any) any { } enumMap := optionDecl.EnumMap() if enumMap != nil { - s := serializeEnumValue(value, enumMap) + s := serializeCompilerOptionEnum(value) if s != "" { return s } diff --git a/tsc/internal/tsoptions/showconfig_test.go b/tsc/internal/tsoptions/showconfig_test.go new file mode 100644 index 0000000000000..4ef008fabd20d --- /dev/null +++ b/tsc/internal/tsoptions/showconfig_test.go @@ -0,0 +1,177 @@ +package tsoptions + +import ( + "reflect" + "slices" + "testing" + + "github.com/microsoft/TypeScript/tsc/internal/collections" + "github.com/microsoft/TypeScript/tsc/internal/core" + "github.com/microsoft/TypeScript/tsc/internal/debug" + "github.com/microsoft/TypeScript/tsc/internal/diagnostics" + "github.com/microsoft/TypeScript/tsc/internal/tspath" +) + +// Preserve the reflection-based serializer as an independent check of generated serialization. +func reflectedSerializeCompilerOptions(options *core.CompilerOptions, configFilePath string, comparePathsOptions tspath.ComparePathsOptions) *collections.OrderedMap[string, any] { + result := collections.NewOrderedMapWithSizeHint[string, any](32) + configDir := tspath.GetDirectoryPath(configFilePath) + optionsValue := reflect.ValueOf(options).Elem() + for i := range optionsValue.NumField() { + field := optionsValue.Type().Field(i) + if !field.IsExported() { + continue + } + option := CommandLineCompilerOptionsMap.Get(field.Name) + if option == nil || option.Category == diagnostics.Command_line_Options || option.Category == diagnostics.Output_Formatting { + continue + } + fieldValue := optionsValue.Field(i) + if fieldValue.IsZero() { + continue + } + value := fieldValue.Interface() + if enumMap := option.EnumMap(); enumMap != nil { + for key, enumValue := range enumMap.Entries() { + if reflect.ValueOf(enumValue).Int() == fieldValue.Int() { + result.Set(option.Name, key) + break + } + } + continue + } + switch option.Kind { + case CommandLineOptionTypeListOrElement: + debug.Assert(false, "listOrElement option should not reach serialization") + case CommandLineOptionTypeList: + element := option.Elements() + if values, ok := value.([]string); ok && element != nil { + if element.IsFilePath { + relative := make([]string, len(values)) + for j, path := range values { + absolute := tspath.GetNormalizedAbsolutePath(path, configDir) + relative[j] = tspath.GetRelativePathFromFile(configFilePath, absolute, comparePathsOptions) + } + result.Set(option.Name, relative) + continue + } + if enumMap := element.EnumMap(); enumMap != nil { + serialized := make([]string, 0, len(values)) + for _, item := range values { + for key, enumValue := range enumMap.Entries() { + if enumValue == item { + item = key + break + } + } + serialized = append(serialized, item) + } + result.Set(option.Name, serialized) + continue + } + } + result.Set(option.Name, value) + case CommandLineOptionTypeString: + if option.IsFilePath { + value = tspath.GetRelativePathFromFile(configFilePath, tspath.GetNormalizedAbsolutePath(value.(string), configDir), comparePathsOptions) + } + result.Set(option.Name, value) + case CommandLineOptionTypeBoolean: + tristate := value.(core.Tristate) + if tristate.IsTrue() { + result.Set(option.Name, true) + } else if tristate.IsFalse() { + result.Set(option.Name, false) + } + default: + result.Set(option.Name, value) + } + } + return result +} + +func TestShowConfigSerialization(t *testing.T) { + t.Parallel() + + comparePaths := tspath.ComparePathsOptions{CurrentDirectory: "/project", UseCaseSensitiveFileNames: true} + check := func(t *testing.T, options *core.CompilerOptions) { + t.Helper() + got := serializeCompilerOptions(options, "/project/tsconfig.json", comparePaths) + want := reflectedSerializeCompilerOptions(options, "/project/tsconfig.json", comparePaths) + if !reflect.DeepEqual(got, want) { + t.Errorf("Serialization differs:\ngot keys: %+v\nwant keys: %+v", slices.Collect(got.Keys()), slices.Collect(want.Keys())) + for name, expected := range want.Entries() { + if actual := got.GetOrZero(name); !reflect.DeepEqual(actual, expected) { + t.Errorf("%s: got %#v, want %#v", name, actual, expected) + } + } + } + } + check(t, &core.CompilerOptions{}) + allOptions := &core.CompilerOptions{} + for field := range reflect.TypeFor[core.CompilerOptions]().Fields() { + if !field.IsExported() { + continue + } + values := compilerOptionTestValues(t, field) + if option := CommandLineCompilerOptionsMap.Get(field.Name); option != nil && option.EnumMap() != nil { + for value := range option.EnumMap().Values() { + values = append(values, reflect.ValueOf(value)) + } + } + switch field.Type.Kind() { + case reflect.Int32: + invalid := reflect.New(field.Type).Elem() + invalid.SetInt(-1) + values = append(values, invalid) + case reflect.Uint8: + values = append(values, reflect.ValueOf(core.Tristate(255))) + case reflect.String: + values = append(values, reflect.ValueOf("/project/src"), reflect.ValueOf("../other"), reflect.ValueOf("./local")) + } + if field.Type == reflect.TypeFor[[]string]() { + values = append(values, reflect.ValueOf([]string{"lib.es2015.d.ts", "lib.es2016.d.ts", "unknown", "../types"})) + } + reflect.ValueOf(allOptions).Elem().FieldByIndex(field.Index).Set(values[len(values)-1]) + t.Run(field.Name, func(t *testing.T) { + t.Parallel() + for _, value := range values { + options := &core.CompilerOptions{} + reflect.ValueOf(options).Elem().FieldByIndex(field.Index).Set(value) + check(t, options) + } + }) + } + check(t, allOptions) + paths := &collections.OrderedMap[string, []string]{} + paths.Set("@/*", []string{"./src/*", "../shared/*"}) + paths.Set("empty", []string{}) + check(t, &core.CompilerOptions{ + Paths: paths, + Plugins: []core.PluginImport{{Name: "plugin"}}, + MaxNodeModuleJsDepth: new(0), + }) +} + +func TestShowConfigEnumSerialization(t *testing.T) { + t.Parallel() + + for _, option := range OptionsDeclarations { + enumMap := option.EnumMap() + if enumMap == nil { + continue + } + t.Run(option.Name, func(t *testing.T) { + t.Parallel() + seen := make(map[any]string) + for name, value := range enumMap.Entries() { + if _, ok := seen[value]; !ok { + seen[value] = name + } + if got := serializeCompilerOptionEnum(value); got != seen[value] { + t.Errorf("%v: got %q, want first alias %q", value, got, seen[value]) + } + } + }) + } +} diff --git a/tsc/internal/tsoptions/tsconfigparsing.go b/tsc/internal/tsoptions/tsconfigparsing.go index 8f50493b2747c..363530c4ac7c0 100644 --- a/tsc/internal/tsoptions/tsconfigparsing.go +++ b/tsc/internal/tsoptions/tsconfigparsing.go @@ -33,64 +33,6 @@ type extendsResult struct { extendedSourceFiles collections.Set[string] } -var compilerOptionsDeclaration = &CommandLineOption{ - Name: "compilerOptions", - Kind: CommandLineOptionTypeObject, - ElementOptions: CommandLineCompilerOptionsMap, -} - -var compileOnSaveCommandLineOption = &CommandLineOption{ - Name: "compileOnSave", - Kind: CommandLineOptionTypeBoolean, - DefaultValueDescription: false, -} - -var extendsOptionDeclaration = &CommandLineOption{ - Name: "extends", - Kind: CommandLineOptionTypeListOrElement, - Category: diagnostics.File_Management, - ElementOptions: commandLineOptionsToMap([]*CommandLineOption{ - {Name: "extends", Kind: CommandLineOptionTypeString}, - }), -} - -var tsconfigRootOptionsMap = &CommandLineOption{ - Name: "undefined", // should never be needed since this is root - Kind: CommandLineOptionTypeObject, - ElementOptions: commandLineOptionsToMap([]*CommandLineOption{ - compilerOptionsDeclaration, - typeAcquisitionDeclaration, - extendsOptionDeclaration, - { - Name: "references", - Kind: CommandLineOptionTypeList, // should be a list of projectReference - // Category: diagnostics.Projects, - }, - { - Name: "contentMappers", - Kind: CommandLineOptionTypeList, // list of content mapper objects - }, - { - Name: "files", - Kind: CommandLineOptionTypeList, - // Category: diagnostics.File_Management, - }, - { - Name: "include", - Kind: CommandLineOptionTypeList, - // Category: diagnostics.File_Management, - // DefaultValueDescription: diagnostics.if_files_is_specified_otherwise_Asterisk_Asterisk_Slash_Asterisk, - }, - { - Name: "exclude", - Kind: CommandLineOptionTypeList, - // Category: diagnostics.File_Management, - // DefaultValueDescription: diagnostics.Node_modules_bower_components_jspm_packages_plus_the_value_of_outDir_if_one_is_specified, - }, - compileOnSaveCommandLineOption, - }), -} - type configFileSpecs struct { filesSpecs any // Present to report errors (user specified specs), validatedIncludeSpecs are used for file name matching @@ -433,23 +375,20 @@ func convertJsonOptionOfListType( const configDirTemplate = "${configDir}" -func startsWithConfigDirTemplate(value any) bool { - str, ok := value.(string) - if !ok { - return false - } - return strings.HasPrefix(strings.ToLower(str), strings.ToLower(configDirTemplate)) +func startsWithConfigDirTemplate(value string) bool { + return strings.HasPrefix(strings.ToLower(value), strings.ToLower(configDirTemplate)) } func normalizeNonListOptionValue(option *CommandLineOption, basePath string, value any) any { if option.IsFilePath { - value = tspath.NormalizeSlashes(value.(string)) - if !startsWithConfigDirTemplate(value) { - value = tspath.GetNormalizedAbsolutePath(value.(string), basePath) + path := tspath.NormalizeSlashes(value.(string)) + if !startsWithConfigDirTemplate(path) { + path = tspath.GetNormalizedAbsolutePath(path, basePath) } - if value == "" { - value = "." + if path == "" { + path = "." } + return path } return value } @@ -924,28 +863,6 @@ func convertToObject(sourceFile *ast.SourceFile) (any, []*ast.Diagnostic) { return convertToJson(sourceFile, rootExpression, true /*returnValue*/, nil /*jsonConversionNotifier*/) } -func getDefaultCompilerOptions(configFileName string) *core.CompilerOptions { - options := &core.CompilerOptions{} - if configFileName != "" && tspath.GetBaseFileName(configFileName) == "jsconfig.json" { - depth := 2 - options = &core.CompilerOptions{ - AllowJs: core.TSTrue, - MaxNodeModuleJsDepth: &depth, - SkipLibCheck: core.TSTrue, - NoEmit: core.TSTrue, - } - } - return options -} - -func getDefaultTypeAcquisition(configFileName string) *core.TypeAcquisition { - options := &core.TypeAcquisition{} - if configFileName != "" && tspath.GetBaseFileName(configFileName) == "jsconfig.json" { - options.Enable = core.TSTrue - } - return options -} - func convertCompilerOptionsFromJsonWorker(jsonOptions any, basePath string, configFileName string) (*core.CompilerOptions, []*ast.Diagnostic) { options := getDefaultCompilerOptions(configFileName) _, errors := convertOptionsFromJson(CommandLineCompilerOptionsMap, jsonOptions, basePath, &compilerOptionsParser{options}) @@ -1138,7 +1055,7 @@ func parseConfig( if !isString { return path } - if startsWithConfigDirTemplate(path) || tspath.IsRootedDiskPath(pathStr) { + if startsWithConfigDirTemplate(pathStr) || tspath.IsRootedDiskPath(pathStr) { return pathStr } else { if relativeDifference == "" { @@ -1801,6 +1718,7 @@ func getTsConfigObjectLiteralExpression(tsConfigSourceFile *ast.SourceFile) *ast } func getSubstitutedPathWithConfigDirTemplate(value string, basePath string) string { + // TODO: Match the case-insensitive prefix check; Replace currently only substitutes "${configDir}" with this exact casing. return tspath.GetNormalizedAbsolutePath(strings.Replace(value, configDirTemplate, "./", 1), basePath) } @@ -1820,56 +1738,6 @@ func getSubstitutedStringArrayWithConfigDirTemplate(list []string, basePath stri return nil } -func handleOptionConfigDirTemplateSubstitution(compilerOptions *core.CompilerOptions, basePath string) { - if compilerOptions == nil { - return - } - - // !!! don't hardcode this; use options declarations? - - var paths *collections.OrderedMap[string, []string] - for k, v := range compilerOptions.Paths.Entries() { - if substitution := getSubstitutedStringArrayWithConfigDirTemplate(v, basePath); substitution != nil { - if paths == nil { - paths = compilerOptions.Paths.Clone() - compilerOptions.Paths = paths - } - paths.Set(k, substitution) - } - } - - if rootDirs := getSubstitutedStringArrayWithConfigDirTemplate(compilerOptions.RootDirs, basePath); rootDirs != nil { - compilerOptions.RootDirs = rootDirs - } - if typeRoots := getSubstitutedStringArrayWithConfigDirTemplate(compilerOptions.TypeRoots, basePath); typeRoots != nil { - compilerOptions.TypeRoots = typeRoots - } - if startsWithConfigDirTemplate(compilerOptions.GenerateCpuProfile) { - compilerOptions.GenerateCpuProfile = getSubstitutedPathWithConfigDirTemplate(compilerOptions.GenerateCpuProfile, basePath) - } - if startsWithConfigDirTemplate(compilerOptions.GenerateTrace) { - compilerOptions.GenerateTrace = getSubstitutedPathWithConfigDirTemplate(compilerOptions.GenerateTrace, basePath) - } - if startsWithConfigDirTemplate(compilerOptions.OutFile) { - compilerOptions.OutFile = getSubstitutedPathWithConfigDirTemplate(compilerOptions.OutFile, basePath) - } - if startsWithConfigDirTemplate(compilerOptions.OutDir) { - compilerOptions.OutDir = getSubstitutedPathWithConfigDirTemplate(compilerOptions.OutDir, basePath) - } - if startsWithConfigDirTemplate(compilerOptions.RootDir) { - compilerOptions.RootDir = getSubstitutedPathWithConfigDirTemplate(compilerOptions.RootDir, basePath) - } - if startsWithConfigDirTemplate(compilerOptions.TsBuildInfoFile) { - compilerOptions.TsBuildInfoFile = getSubstitutedPathWithConfigDirTemplate(compilerOptions.TsBuildInfoFile, basePath) - } - if startsWithConfigDirTemplate(compilerOptions.BaseUrl) { - compilerOptions.BaseUrl = getSubstitutedPathWithConfigDirTemplate(compilerOptions.BaseUrl, basePath) - } - if startsWithConfigDirTemplate(compilerOptions.DeclarationDir) { - compilerOptions.DeclarationDir = getSubstitutedPathWithConfigDirTemplate(compilerOptions.DeclarationDir, basePath) - } -} - // hasFileWithHigherPriorityExtension determines whether a literal or wildcard file has already been included that has a higher extension priority. // file is the path to the file. func hasFileWithHigherPriorityExtension(file string, extensions [][]string, hasFile func(fileName string) bool) bool {