Skip to content

Feature implementation from commits b86ab7d..5a3271b #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 25 commits into
base: feature-base-branch-1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
81c9518
Fix getResolvePackageJsonImports utility (#61707)
andrewbranch May 16, 2025
b504a1e
Handle lock file 3 version when caching the typings ensuring we can r…
sheetalkamat May 21, 2025
44d4671
Update pr_owners.txt (#61798)
jakebailey Jun 3, 2025
3dd0a35
Initialize the map for dts to reference and source to reference when …
sheetalkamat Jun 4, 2025
2b88aeb
LEGO: Pull request from lego/hb_5378966c-b857-470a-8675-daebef4a6da1_…
csigs Jun 4, 2025
a591ca3
fix(61747): for (using of = is incorrectly parsed (#61764)
a-tarasyuk Jun 5, 2025
ac03ba4
fix(checker): report error when using bigint as enum key (#61777)
magic-akari Jun 5, 2025
cd34199
tsc --init update (#61813)
RyanCavanaugh Jun 6, 2025
a69c6d0
Add support for `import defer` proposal (#60757)
nicolo-ribaudo Jun 6, 2025
ffd98c1
feat: add Error.isError() to ESNext lib (#60788)
dirkluijk Jun 6, 2025
51dcd90
Cache mapper instantiations (#61505)
Andarist Jun 6, 2025
652ed7f
Add lib.esnext.sharedmemory (#61646)
Renegade334 Jun 6, 2025
1e24945
explicitly disallow `using` in ambient contexts (#61781)
Renegade334 Jun 6, 2025
fa2a0fc
Issue "'{0}' declarations can only be declared inside a block." for b…
Andarist Jun 6, 2025
7715955
Fix helpers emit for .cjs files in ESM module mode (#61814)
andrewbranch Jun 6, 2025
355b9e0
Avoid resolving source prop type when the target is `unknown`/`any` (…
Andarist Jun 6, 2025
97cfa26
optimization, reduce memory usage (#61822)
VincentBailly Jun 9, 2025
cb38d99
Add `--module node20` (#61805)
andrewbranch Jun 9, 2025
34d1ea6
Fix type variable leaks and cache inconsistencies (#61668)
ahejlsberg Jun 9, 2025
0dfd0c2
Restore `import defer =` parsing (#61837)
nicolo-ribaudo Jun 9, 2025
12e09f4
Port "Improve type discrimination algorithm" from tsgo (#61828)
jakebailey Jun 9, 2025
529ed09
fix link to "Help Wanted" issues (#61843)
AllenSH12 Jun 11, 2025
dd1e258
LEGO: Pull request from lego/hb_5378966c-b857-470a-8675-daebef4a6da1_…
csigs Jun 11, 2025
f1d2494
LEGO: Pull request from lego/hb_5378966c-b857-470a-8675-daebef4a6da1_…
csigs Jun 17, 2025
5a3271b
LEGO: Pull request from lego/hb_5378966c-b857-470a-8675-daebef4a6da1_…
csigs Jun 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 0 additions & 5 deletions .github/pr_owners.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,9 @@ weswigham
andrewbranch
RyanCavanaugh
sheetalkamat
rbuckton
ahejlsberg
amcasey
minestarks
armanio123
gabritto
jakebailey
DanielRosenwasser
navya9singh
iisaduan
dependabot
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ In general, things we find useful when reviewing suggestions are:

## What You'll Need

0. [A bug or feature you want to work on](https://github.com/microsoft/TypeScript/labels/help%20wanted)!
0. [A bug or feature you want to work on](https://github.com/microsoft/TypeScript/issues?q=is%3Aissue%20label%3A%22Help%20Wanted%22)!
1. [A GitHub account](https://github.com/join).
2. A copy of the TypeScript code. See the next steps for instructions.
3. [Node](https://nodejs.org), which runs JavaScript locally. Current or LTS will both work.
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/builderState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ export namespace BuilderState {
* Gets the path to reference file from file name, it could be resolvedPath if present otherwise path
*/
function getReferencedFileFromFileName(program: Program, fileName: string, sourceFileDirectory: Path, getCanonicalFileName: GetCanonicalFileName): Path {
return toPath(program.getProjectReferenceRedirect(fileName) || fileName, sourceFileDirectory, getCanonicalFileName);
return toPath(program.getRedirectFromSourceFile(fileName)?.outputDts || fileName, sourceFileDirectory, getCanonicalFileName);
}

/**
Expand Down
393 changes: 258 additions & 135 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

264 changes: 125 additions & 139 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ import {
filterMutate,
find,
findIndex,
firstOrUndefinedIterator,
flatten,
forEach,
forEachEntry,
Expand Down Expand Up @@ -249,6 +248,8 @@ const libEntries: [string, string][] = [
["esnext.iterator", "lib.esnext.iterator.d.ts"],
["esnext.promise", "lib.esnext.promise.d.ts"],
["esnext.float16", "lib.esnext.float16.d.ts"],
["esnext.error", "lib.esnext.error.d.ts"],
["esnext.sharedmemory", "lib.esnext.sharedmemory.d.ts"],
["decorators", "lib.decorators.d.ts"],
["decorators.legacy", "lib.decorators.legacy.d.ts"],
];
Expand Down Expand Up @@ -602,6 +603,7 @@ export const moduleOptionDeclaration: CommandLineOptionOfCustomType = {
esnext: ModuleKind.ESNext,
node16: ModuleKind.Node16,
node18: ModuleKind.Node18,
node20: ModuleKind.Node20,
nodenext: ModuleKind.NodeNext,
preserve: ModuleKind.Preserve,
})),
Expand Down Expand Up @@ -2789,140 +2791,146 @@ function serializeOptionBaseObject(
return result;
}

/**
* Generate a list of the compiler options whose value is not the default.
* @param options compilerOptions to be evaluated.
/** @internal */
export function getCompilerOptionsDiffValue(options: CompilerOptions, newLine: string): string {
const compilerOptionsMap = getSerializedCompilerOption(options);
return getOverwrittenDefaultOptions();

function makePadding(paddingLength: number): string {
return Array(paddingLength + 1).join(" ");
}

function getOverwrittenDefaultOptions() {
const result: string[] = [];
const tab = makePadding(2);
commandOptionsWithoutBuild.forEach(cmd => {
if (!compilerOptionsMap.has(cmd.name)) {
return;
}

const newValue = compilerOptionsMap.get(cmd.name);
const defaultValue = getDefaultValueForOption(cmd);
if (newValue !== defaultValue) {
result.push(`${tab}${cmd.name}: ${newValue}`);
}
else if (hasProperty(defaultInitCompilerOptions, cmd.name)) {
result.push(`${tab}${cmd.name}: ${defaultValue}`);
}
});
return result.join(newLine) + newLine;
}
}

/**
* Get the compiler options to be written into the tsconfig.json.
* @param options commandlineOptions to be included in the compileOptions.
*/
function getSerializedCompilerOption(options: CompilerOptions): Map<string, CompilerOptionsValue> {
const compilerOptions = extend(options, defaultInitCompilerOptions);
return serializeCompilerOptions(compilerOptions);
}
/**
* Generate tsconfig configuration when running command line "--init"
* @param options commandlineOptions to be generated into tsconfig.json
* @param fileNames array of filenames to be generated into tsconfig.json
*
* @internal
*/
export function generateTSConfig(options: CompilerOptions, fileNames: readonly string[], newLine: string): string {
const compilerOptionsMap = getSerializedCompilerOption(options);
return writeConfigurations();
export function generateTSConfig(options: CompilerOptions, newLine: string): string {
type PresetValue = string | number | boolean | (string | number | boolean)[];

const tab = " ";
const result: string[] = [];
const allSetOptions = Object.keys(options).filter(k => k !== "init" && k !== "help" && k !== "watch");

result.push(`{`);
result.push(`${tab}// ${getLocaleSpecificMessage(Diagnostics.Visit_https_Colon_Slash_Slashaka_ms_Slashtsconfig_to_read_more_about_this_file)}`);
result.push(`${tab}"compilerOptions": {`);

emitHeader(Diagnostics.File_Layout);
emitOption("rootDir", "./src", "optional");
emitOption("outDir", "./dist", "optional");

newline();

emitHeader(Diagnostics.Environment_Settings);
emitHeader(Diagnostics.See_also_https_Colon_Slash_Slashaka_ms_Slashtsconfig_Slashmodule);
emitOption("module", ModuleKind.NodeNext);
emitOption("target", ScriptTarget.ESNext);
emitOption("types", []);
if (options.lib) {
emitOption("lib", options.lib);
}
emitHeader(Diagnostics.For_nodejs_Colon);
result.push(`${tab}${tab}// "lib": ["esnext"],`);
result.push(`${tab}${tab}// "types": ["node"],`);
emitHeader(Diagnostics.and_npm_install_D_types_Slashnode);

newline();

emitHeader(Diagnostics.Other_Outputs);
emitOption("sourceMap", /*defaultValue*/ true);
emitOption("declaration", /*defaultValue*/ true);
emitOption("declarationMap", /*defaultValue*/ true);

newline();

emitHeader(Diagnostics.Stricter_Typechecking_Options);
emitOption("noUncheckedIndexedAccess", /*defaultValue*/ true);
emitOption("exactOptionalPropertyTypes", /*defaultValue*/ true);

newline();

emitHeader(Diagnostics.Style_Options);
emitOption("noImplicitReturns", /*defaultValue*/ true, "optional");
emitOption("noImplicitOverride", /*defaultValue*/ true, "optional");
emitOption("noUnusedLocals", /*defaultValue*/ true, "optional");
emitOption("noUnusedParameters", /*defaultValue*/ true, "optional");
emitOption("noFallthroughCasesInSwitch", /*defaultValue*/ true, "optional");
emitOption("noPropertyAccessFromIndexSignature", /*defaultValue*/ true, "optional");

newline();

emitHeader(Diagnostics.Recommended_Options);
emitOption("strict", /*defaultValue*/ true);
emitOption("jsx", JsxEmit.ReactJSX);
emitOption("verbatimModuleSyntax", /*defaultValue*/ true);
emitOption("isolatedModules", /*defaultValue*/ true);
emitOption("noUncheckedSideEffectImports", /*defaultValue*/ true);
emitOption("moduleDetection", ModuleDetectionKind.Force);
emitOption("skipLibCheck", /*defaultValue*/ true);

// Write any user-provided options we haven't already
if (allSetOptions.length > 0) {
newline();
while (allSetOptions.length > 0) {
emitOption(allSetOptions[0], options[allSetOptions[0]]);
}
}

function makePadding(paddingLength: number): string {
return Array(paddingLength + 1).join(" ");
function newline() {
result.push("");
}

function isAllowedOptionForOutput({ category, name, isCommandLineOnly }: CommandLineOption): boolean {
// Skip options which do not have a category or have categories which are more niche
const categoriesToSkip = [Diagnostics.Command_line_Options, Diagnostics.Editor_Support, Diagnostics.Compiler_Diagnostics, Diagnostics.Backwards_Compatibility, Diagnostics.Watch_and_Build_Modes, Diagnostics.Output_Formatting];
return !isCommandLineOnly && category !== undefined && (!categoriesToSkip.includes(category) || compilerOptionsMap.has(name));
function emitHeader(header: DiagnosticMessage) {
result.push(`${tab}${tab}// ${getLocaleSpecificMessage(header)}`);
}

function writeConfigurations() {
// Filter applicable options to place in the file
const categorizedOptions = new Map<DiagnosticMessage, CommandLineOption[]>();
// Set allowed categories in order
categorizedOptions.set(Diagnostics.Projects, []);
categorizedOptions.set(Diagnostics.Language_and_Environment, []);
categorizedOptions.set(Diagnostics.Modules, []);
categorizedOptions.set(Diagnostics.JavaScript_Support, []);
categorizedOptions.set(Diagnostics.Emit, []);
categorizedOptions.set(Diagnostics.Interop_Constraints, []);
categorizedOptions.set(Diagnostics.Type_Checking, []);
categorizedOptions.set(Diagnostics.Completeness, []);
for (const option of optionDeclarations) {
if (isAllowedOptionForOutput(option)) {
let listForCategory = categorizedOptions.get(option.category!);
if (!listForCategory) categorizedOptions.set(option.category!, listForCategory = []);
listForCategory.push(option);
}
// commented = 'always': Always comment this out, even if it's on commandline
// commented = 'optional': Comment out unless it's on commandline
// commented = 'never': Never comment this out
function emitOption<K extends string & keyof CompilerOptions>(setting: K, defaultValue: CompilerOptions[K], commented: "always" | "optional" | "never" = "never") {
const existingOptionIndex = allSetOptions.indexOf(setting);
if (existingOptionIndex >= 0) {
allSetOptions.splice(existingOptionIndex, 1);
}

// Serialize all options and their descriptions
let marginLength = 0;
let seenKnownKeys = 0;
const entries: { value: string; description?: string; }[] = [];
categorizedOptions.forEach((options, category) => {
if (entries.length !== 0) {
entries.push({ value: "" });
}
entries.push({ value: `/* ${getLocaleSpecificMessage(category)} */` });
for (const option of options) {
let optionName;
if (compilerOptionsMap.has(option.name)) {
optionName = `"${option.name}": ${JSON.stringify(compilerOptionsMap.get(option.name))}${(seenKnownKeys += 1) === compilerOptionsMap.size ? "" : ","}`;
}
else {
optionName = `// "${option.name}": ${JSON.stringify(getDefaultValueForOption(option))},`;
}
entries.push({
value: optionName,
description: `/* ${option.description && getLocaleSpecificMessage(option.description) || option.name} */`,
});
marginLength = Math.max(optionName.length, marginLength);
}
});

// Write the output
const tab = makePadding(2);
const result: string[] = [];
result.push(`{`);
result.push(`${tab}"compilerOptions": {`);
result.push(`${tab}${tab}/* ${getLocaleSpecificMessage(Diagnostics.Visit_https_Colon_Slash_Slashaka_ms_Slashtsconfig_to_read_more_about_this_file)} */`);
result.push("");
// Print out each row, aligning all the descriptions on the same column.
for (const entry of entries) {
const { value, description = "" } = entry;
result.push(value && `${tab}${tab}${value}${description && (makePadding(marginLength - value.length + 2) + description)}`);
let comment: boolean;
if (commented === "always") {
comment = true;
}
if (fileNames.length) {
result.push(`${tab}},`);
result.push(`${tab}"files": [`);
for (let i = 0; i < fileNames.length; i++) {
result.push(`${tab}${tab}${JSON.stringify(fileNames[i])}${i === fileNames.length - 1 ? "" : ","}`);
}
result.push(`${tab}]`);
else if (commented === "never") {
comment = false;
}
else {
result.push(`${tab}}`);
comment = !hasProperty(options, setting);
}
result.push(`}`);

return result.join(newLine) + newLine;
const value = (options[setting] ?? defaultValue) as PresetValue;
if (comment) {
result.push(`${tab}${tab}// "${setting}": ${formatValueOrArray(setting, value)},`);
}
else {
result.push(`${tab}${tab}"${setting}": ${formatValueOrArray(setting, value)},`);
}
}

function formatValueOrArray(settingName: string, value: PresetValue): string {
const option = optionDeclarations.filter(c => c.name === settingName)[0];
if (!option) Debug.fail(`No option named ${settingName}?`);
const map = (option.type instanceof Map) ? option.type : undefined;
if (isArray(value)) {
// eslint-disable-next-line local/no-in-operator
const map = ("element" in option && (option.element.type instanceof Map)) ? option.element.type : undefined;
return `[${value.map(v => formatSingleValue(v, map)).join(", ")}]`;
}
else {
return formatSingleValue(value, map);
}
}

function formatSingleValue(value: PresetValue, map: Map<string, string | number> | undefined) {
if (map) {
value = getNameOfCompilerOptionValue(value as string | number, map) ?? Debug.fail(`No matching value of ${value}`);
}
return JSON.stringify(value);
}

result.push(`${tab}}`);
result.push(`}`);
result.push(``);

return result.join(newLine);
}

/** @internal */
Expand Down Expand Up @@ -4256,25 +4264,3 @@ function getOptionValueWithEmptyStrings(value: any, option: CommandLineOption):
});
}
}

function getDefaultValueForOption(option: CommandLineOption): {} {
switch (option.type) {
case "number":
return 1;
case "boolean":
return true;
case "string":
const defaultValue = option.defaultValueDescription;
return option.isFilePath ? `./${defaultValue && typeof defaultValue === "string" ? defaultValue : ""}` : "";
case "list":
return [];
case "listOrElement":
return getDefaultValueForOption(option.element);
case "object":
return {};
default:
const value = firstOrUndefinedIterator(option.type.keys());
if (value !== undefined) return value;
return Debug.fail("Expected 'option.type' to have entries.");
}
}
Loading