Skip to content
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

Allow allowImportingTsExtensions to be set in any module resolution mode #52230

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
{
name: "allowImportingTsExtensions",
type: "boolean",
affectsModuleResolution: true,
affectsSemanticDiagnostics: true,
Copy link
Member Author

Choose a reason for hiding this comment

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

This was a mistake—the option has very intentionally never affected how module resolution works, only whether an error is raised. I’m not sure whether it caused the issue we observed during the bug bash, but I added a unit test that shows the error disappearing when updating this option.

category: Diagnostics.Modules,
description: Diagnostics.Allow_imports_to_include_TypeScript_file_extensions_Requires_moduleResolution_bundler_and_either_noEmit_or_emitDeclarationOnly_to_be_set,
defaultValueDescription: false,
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -4233,7 +4233,7 @@
"category": "Error",
"code": 5095
},
"Option 'allowImportingTsExtensions' can only be used when 'moduleResolution' is set to 'bundler' and either 'noEmit' or 'emitDeclarationOnly' is set.": {
"Option 'allowImportingTsExtensions' can only be used when either 'noEmit' or 'emitDeclarationOnly' is set.": {
"category": "Error",
"code": 5096
},
Expand Down
4 changes: 1 addition & 3 deletions src/compiler/moduleNameResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3033,9 +3033,7 @@ export function classicNameResolver(moduleName: string, containingFile: string,
// Program errors validate that `noEmit` or `emitDeclarationOnly` is also set,
// so this function doesn't check them to avoid propagating errors.
export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string) {
return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Bundler && (
!!compilerOptions.allowImportingTsExtensions ||
fromFileName && isDeclarationFileName(fromFileName));
return !!compilerOptions.allowImportingTsExtensions || fromFileName && isDeclarationFileName(fromFileName);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4213,7 +4213,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
}

if (options.allowImportingTsExtensions && !(options.noEmit || options.emitDeclarationOnly)) {
createOptionValueDiagnostic("allowImportingTsExtensions", Diagnostics.Option_allowImportingTsExtensions_can_only_be_used_when_moduleResolution_is_set_to_bundler_and_either_noEmit_or_emitDeclarationOnly_is_set);
createOptionValueDiagnostic("allowImportingTsExtensions", Diagnostics.Option_allowImportingTsExtensions_can_only_be_used_when_either_noEmit_or_emitDeclarationOnly_is_set);
}

const moduleResolution = getEmitModuleResolutionKind(options);
Expand Down
38 changes: 38 additions & 0 deletions src/testRunner/unittests/tscWatch/programUpdates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1957,4 +1957,42 @@ import { x } from "../b";`),
},
]
});

verifyTscWatch({
scenario,
subScenario: "when changing `allowImportingTsExtensions` of config file",
commandLineArgs: ["-w", "-p", ".", "--extendedDiagnostics"],
sys: () => {
const module1: File = {
path: `/user/username/projects/myproject/a.ts`,
content: ``
};
const module2: File = {
path: `/user/username/projects/myproject/b.ts`,
content: `import "./a.ts";`
};
const config: File = {
path: `/user/username/projects/myproject/tsconfig.json`,
content: JSON.stringify({
compilerOptions: {
noEmit: true,
allowImportingTsExtensions: false
}
}),
};
return createWatchedSystem([module1, module2, config, libFile], { currentDirectory: "/user/username/projects/myproject" });
},
edits: [
{
caption: "Change allowImportingTsExtensions to true",
edit: sys => sys.writeFile(`/user/username/projects/myproject/tsconfig.json`, JSON.stringify({
compilerOptions: {
noEmit: true,
allowImportingTsExtensions: true
}
})),
timeouts: sys => sys.checkTimeoutQueueLengthAndRun(1),
},
]
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
error TS5056: Cannot write file 'out/b.js' because it would be overwritten by multiple input files.
error TS5056: Cannot write file 'out/c.js' because it would be overwritten by multiple input files.
error TS5096: Option 'allowImportingTsExtensions' can only be used when 'moduleResolution' is set to 'bundler' and either 'noEmit' or 'emitDeclarationOnly' is set.
error TS5096: Option 'allowImportingTsExtensions' can only be used when either 'noEmit' or 'emitDeclarationOnly' is set.
error TS6054: File '/project/e.txt' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx', '.cts', '.d.cts', '.cjs', '.mts', '.d.mts', '.mjs'.
The file is in the program because:
Root file specified for compilation
Expand All @@ -11,7 +11,7 @@ error TS6054: File '/project/e.txt' has an unsupported extension. The only suppo

!!! error TS5056: Cannot write file 'out/b.js' because it would be overwritten by multiple input files.
!!! error TS5056: Cannot write file 'out/c.js' because it would be overwritten by multiple input files.
!!! error TS5096: Option 'allowImportingTsExtensions' can only be used when 'moduleResolution' is set to 'bundler' and either 'noEmit' or 'emitDeclarationOnly' is set.
!!! error TS5096: Option 'allowImportingTsExtensions' can only be used when either 'noEmit' or 'emitDeclarationOnly' is set.
!!! error TS6054: File '/project/e.txt' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx', '.cts', '.d.cts', '.cjs', '.mts', '.d.mts', '.mjs'.
!!! error TS6054: The file is in the program because:
!!! error TS6054: Root file specified for compilation
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
Input::
//// [/user/username/projects/myproject/a.ts]


//// [/user/username/projects/myproject/b.ts]
import "./a.ts";

//// [/user/username/projects/myproject/tsconfig.json]
{"compilerOptions":{"noEmit":true,"allowImportingTsExtensions":false}}

//// [/a/lib/lib.d.ts]
/// <reference no-default-lib="true"/>
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
interface RegExp {}
interface String { charAt: any; }
interface Array<T> { length: number; [n: number]: T; }


/a/lib/tsc.js -w -p . --extendedDiagnostics
Output::
[12:00:23 AM] Starting compilation in watch mode...

Current directory: /user/username/projects/myproject CaseSensitiveFileNames: false
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 undefined Config file
Synchronizing program
CreatingProgramWith::
roots: ["/user/username/projects/myproject/a.ts","/user/username/projects/myproject/b.ts"]
options: {"noEmit":true,"allowImportingTsExtensions":false,"watch":true,"project":"/user/username/projects/myproject","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/a.ts 250 undefined Source file
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b.ts 250 undefined Source file
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 undefined Source file
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots
b.ts:1:8 - error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.

1 import "./a.ts";
   ~~~~~~~~

[12:00:24 AM] Found 1 error. Watching for file changes.

DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 1 undefined Wild card directory
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 1 undefined Wild card directory


Program root files: ["/user/username/projects/myproject/a.ts","/user/username/projects/myproject/b.ts"]
Program options: {"noEmit":true,"allowImportingTsExtensions":false,"watch":true,"project":"/user/username/projects/myproject","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
Program structureReused: Not
Program files::
/a/lib/lib.d.ts
/user/username/projects/myproject/a.ts
/user/username/projects/myproject/b.ts

Semantic diagnostics in builder refreshed for::
/a/lib/lib.d.ts
/user/username/projects/myproject/a.ts
/user/username/projects/myproject/b.ts

Shape signatures in builder refreshed for::
/a/lib/lib.d.ts (used version)
/user/username/projects/myproject/a.ts (used version)
/user/username/projects/myproject/b.ts (used version)

PolledWatches::
/user/username/projects/myproject/node_modules/@types:
{"pollingInterval":500}

FsWatches::
/user/username/projects/myproject/tsconfig.json:
{}
/user/username/projects/myproject/a.ts:
{}
/user/username/projects/myproject/b.ts:
{}
/a/lib/lib.d.ts:
{}

FsWatchesRecursive::
/user/username/projects/myproject:
{}

exitCode:: ExitStatus.undefined


Change:: Change allowImportingTsExtensions to true

Input::
//// [/user/username/projects/myproject/tsconfig.json]
{"compilerOptions":{"noEmit":true,"allowImportingTsExtensions":true}}


Output::
FileWatcher:: Triggered with /user/username/projects/myproject/tsconfig.json 1:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 undefined Config file
Scheduling update
Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/tsconfig.json 1:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 undefined Config file
Reloading config file: /user/username/projects/myproject/tsconfig.json
Synchronizing program
[12:00:28 AM] File change detected. Starting incremental compilation...

CreatingProgramWith::
roots: ["/user/username/projects/myproject/a.ts","/user/username/projects/myproject/b.ts"]
options: {"noEmit":true,"allowImportingTsExtensions":true,"watch":true,"project":"/user/username/projects/myproject","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
[12:00:29 AM] Found 0 errors. Watching for file changes.



Program root files: ["/user/username/projects/myproject/a.ts","/user/username/projects/myproject/b.ts"]
Program options: {"noEmit":true,"allowImportingTsExtensions":true,"watch":true,"project":"/user/username/projects/myproject","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
Program structureReused: Completely
Program files::
/a/lib/lib.d.ts
/user/username/projects/myproject/a.ts
/user/username/projects/myproject/b.ts

Semantic diagnostics in builder refreshed for::
/a/lib/lib.d.ts
/user/username/projects/myproject/a.ts
/user/username/projects/myproject/b.ts

No shapes updated in the builder::

PolledWatches::
/user/username/projects/myproject/node_modules/@types:
{"pollingInterval":500}

FsWatches::
/user/username/projects/myproject/tsconfig.json:
{}
/user/username/projects/myproject/a.ts:
{}
/user/username/projects/myproject/b.ts:
{}
/a/lib/lib.d.ts:
{}

FsWatchesRecursive::
/user/username/projects/myproject:
{}

exitCode:: ExitStatus.undefined

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// @allowImportingTsExtensions: true
// @noEmit: true
// @moduleResolution: classic,node10,node16,nodenext,bundler
// @jsx: preserve
// @noTypesAndSymbols: true

// @Filename: /ts.ts
export {};

// @Filename: /tsx.tsx
export {};

// @Filename: /dts.d.ts
export {};

// @Filename: /b.ts
import {} from "./ts.js";
import {} from "./ts.ts";
import type {} from "./ts.d.ts";

import {} from "./tsx.js";
import {} from "./tsx.jsx";
import {} from "./tsx.ts";
import {} from "./tsx.tsx";
import type {} from "./tsx.d.ts";

import {} from "./dts.js";
import {} from "./dts.ts";
import type {} from "./dts.d.ts";