Skip to content

Commit

Permalink
Allow allowImportingTsExtensions to be set in any module resolution…
Browse files Browse the repository at this point in the history
… mode (#52230)
  • Loading branch information
andrewbranch authored Jan 17, 2023
1 parent 8094007 commit 436833a
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,7 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
{
name: "allowImportingTsExtensions",
type: "boolean",
affectsModuleResolution: true,
affectsSemanticDiagnostics: true,
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";

0 comments on commit 436833a

Please sign in to comment.