Skip to content

Commit 7159132

Browse files
committed
Rewrite relative import extensions with flag
1 parent a86b5e2 commit 7159132

File tree

7 files changed

+68
-7
lines changed

7 files changed

+68
-7
lines changed

src/compiler/commandLineParser.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,15 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
11761176
defaultValueDescription: false,
11771177
transpileOptionValue: undefined,
11781178
},
1179+
{
1180+
name: "rewriteRelativeImportExtensions",
1181+
type: "boolean",
1182+
affectsSemanticDiagnostics: true,
1183+
affectsBuildInfo: true,
1184+
category: Diagnostics.Modules,
1185+
description: Diagnostics.Rewrite_ts_tsx_mts_and_cts_file_extensions_in_relative_import_paths_to_their_JavaScript_equivalent_in_output_files,
1186+
defaultValueDescription: false,
1187+
},
11791188
{
11801189
name: "resolvePackageJsonExports",
11811190
type: "boolean",

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5934,6 +5934,10 @@
59345934
"category": "Message",
59355935
"code": 6420
59365936
},
5937+
"Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files.": {
5938+
"category": "Message",
5939+
"code": 6421
5940+
},
59375941

59385942
"The expected type comes from property '{0}' which is declared here on type '{1}'": {
59395943
"category": "Message",

src/compiler/moduleNameResolver.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
forEach,
3737
forEachAncestorDirectory,
3838
formatMessage,
39+
getAllowImportingTsExtensions,
3940
getAllowJSCompilerOption,
4041
getAnyExtensionFromPath,
4142
getBaseFileName,
@@ -3303,7 +3304,7 @@ function resolveFromTypeRoot(moduleName: string, state: ModuleResolutionState) {
33033304
// so this function doesn't check them to avoid propagating errors.
33043305
/** @internal */
33053306
export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string) {
3306-
return !!compilerOptions.allowImportingTsExtensions || fromFileName && isDeclarationFileName(fromFileName);
3307+
return getAllowImportingTsExtensions(compilerOptions) || fromFileName && isDeclarationFileName(fromFileName);
33073308
}
33083309

33093310
/**

src/compiler/program.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4523,7 +4523,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
45234523
}
45244524
}
45254525

4526-
if (options.allowImportingTsExtensions && !(options.noEmit || options.emitDeclarationOnly)) {
4526+
if (options.allowImportingTsExtensions && !(options.noEmit || options.emitDeclarationOnly || options.rewriteRelativeImportExtensions)) {
45274527
createOptionValueDiagnostic("allowImportingTsExtensions", Diagnostics.Option_allowImportingTsExtensions_can_only_be_used_when_either_noEmit_or_emitDeclarationOnly_is_set);
45284528
}
45294529

src/compiler/transformers/ts.ts

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
Bundle,
1313
CallExpression,
1414
CaseBlock,
15+
changeExtension,
1516
childIsDecorated,
1617
ClassDeclaration,
1718
ClassElement,
@@ -55,6 +56,7 @@ import {
5556
getInitializedVariables,
5657
getIsolatedModules,
5758
getOriginalNode,
59+
getOutputExtension,
5860
getParseTreeNode,
5961
getProperties,
6062
getStrictOptionValue,
@@ -81,6 +83,7 @@ import {
8183
isClassElement,
8284
isClassLike,
8385
isComputedPropertyName,
86+
isDeclarationFileName,
8487
isDecorator,
8588
isElementAccessExpression,
8689
isEntityName,
@@ -122,6 +125,7 @@ import {
122125
isSimpleInlineableExpression,
123126
isSourceFile,
124127
isStatement,
128+
isStringLiteral,
125129
isTemplateLiteral,
126130
isTryStatement,
127131
JsxOpeningElement,
@@ -155,6 +159,7 @@ import {
155159
parameterIsThisKeyword,
156160
ParameterPropertyDeclaration,
157161
ParenthesizedExpression,
162+
pathIsRelative,
158163
PropertyAccessExpression,
159164
PropertyDeclaration,
160165
PropertyName,
@@ -2269,12 +2274,22 @@ export function transformTypeScript(context: TransformationContext) {
22692274
node,
22702275
/*modifiers*/ undefined,
22712276
importClause,
2272-
node.moduleSpecifier,
2277+
rewriteModuleSpecifier(node.moduleSpecifier),
22732278
node.attributes,
22742279
)
22752280
: undefined;
22762281
}
22772282

2283+
function rewriteModuleSpecifier(node: Expression): Expression;
2284+
function rewriteModuleSpecifier(node: Expression | undefined): Expression | undefined;
2285+
function rewriteModuleSpecifier(node: Expression | undefined): Expression | undefined {
2286+
if (!node || !compilerOptions.rewriteRelativeImportExtensions || !isStringLiteral(node) || !pathIsRelative(node.text) || isDeclarationFileName(node.text)) {
2287+
return node;
2288+
}
2289+
const updatedText = changeExtension(node.text, getOutputExtension(node.text, compilerOptions));
2290+
return updatedText !== node.text ? setOriginalNode(setTextRange(factory.createStringLiteral(updatedText, node.singleQuote), node), node) : node;
2291+
}
2292+
22782293
/**
22792294
* Visits an import clause, eliding it if its `name` and `namedBindings` may both be elided.
22802295
*
@@ -2342,7 +2357,14 @@ export function transformTypeScript(context: TransformationContext) {
23422357
// never elide `export <whatever> from <whereever>` declarations -
23432358
// they should be kept for sideffects/untyped exports, even when the
23442359
// type checker doesn't know about any exports
2345-
return node;
2360+
return factory.updateExportDeclaration(
2361+
node,
2362+
node.modifiers,
2363+
node.isTypeOnly,
2364+
node.exportClause,
2365+
rewriteModuleSpecifier(node.moduleSpecifier),
2366+
node.attributes,
2367+
);
23462368
}
23472369

23482370
// Elide the export declaration if all of its named exports are elided.
@@ -2359,7 +2381,7 @@ export function transformTypeScript(context: TransformationContext) {
23592381
/*modifiers*/ undefined,
23602382
node.isTypeOnly,
23612383
exportClause,
2362-
node.moduleSpecifier,
2384+
rewriteModuleSpecifier(node.moduleSpecifier),
23632385
node.attributes,
23642386
)
23652387
: undefined;
@@ -2421,8 +2443,24 @@ export function transformTypeScript(context: TransformationContext) {
24212443
}
24222444

24232445
if (isExternalModuleImportEqualsDeclaration(node)) {
2424-
const isReferenced = shouldEmitAliasDeclaration(node);
2425-
return isReferenced ? visitEachChild(node, visitor, context) : undefined;
2446+
if (!shouldEmitAliasDeclaration(node)) {
2447+
return undefined;
2448+
}
2449+
const updatedModuleSpecifier = rewriteModuleSpecifier(node.moduleReference.expression);
2450+
if (updatedModuleSpecifier !== node.moduleReference.expression) {
2451+
return visitEachChild(
2452+
factory.updateImportEqualsDeclaration(
2453+
node,
2454+
node.modifiers,
2455+
node.isTypeOnly,
2456+
node.name,
2457+
factory.updateExternalModuleReference(node.moduleReference, updatedModuleSpecifier),
2458+
),
2459+
visitor,
2460+
context,
2461+
);
2462+
}
2463+
return visitEachChild(node, visitor, context);
24262464
}
24272465

24282466
if (!shouldEmitImportEqualsDeclaration(node)) {

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7443,6 +7443,7 @@ export interface CompilerOptions {
74437443
removeComments?: boolean;
74447444
resolvePackageJsonExports?: boolean;
74457445
resolvePackageJsonImports?: boolean;
7446+
rewriteRelativeImportExtensions?: boolean;
74467447
rootDir?: string;
74477448
rootDirs?: string[];
74487449
skipLibCheck?: boolean;

src/compiler/utilities.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8821,6 +8821,12 @@ function createComputedCompilerOptions<T extends Record<string, CompilerOptionKe
88218821

88228822
/** @internal */
88238823
export const computedOptions = createComputedCompilerOptions({
8824+
allowImportingTsExtensions: {
8825+
dependencies: ["rewriteRelativeImportExtensions"],
8826+
computeValue: compilerOptions => {
8827+
return !!(compilerOptions.allowImportingTsExtensions || compilerOptions.rewriteRelativeImportExtensions);
8828+
},
8829+
},
88248830
target: {
88258831
dependencies: ["module"],
88268832
computeValue: compilerOptions => {
@@ -9046,6 +9052,8 @@ export const computedOptions = createComputedCompilerOptions({
90469052
},
90479053
});
90489054

9055+
/** @internal */
9056+
export const getAllowImportingTsExtensions = computedOptions.allowImportingTsExtensions.computeValue;
90499057
/** @internal */
90509058
export const getEmitScriptTarget = computedOptions.target.computeValue;
90519059
/** @internal */

0 commit comments

Comments
 (0)