Skip to content

Commit

Permalink
Rewrite relative import extensions with flag
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewbranch committed Aug 26, 2024
1 parent a86b5e2 commit 7159132
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 7 deletions.
9 changes: 9 additions & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,15 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
defaultValueDescription: false,
transpileOptionValue: undefined,
},
{
name: "rewriteRelativeImportExtensions",
type: "boolean",
affectsSemanticDiagnostics: true,
affectsBuildInfo: true,
category: Diagnostics.Modules,
description: Diagnostics.Rewrite_ts_tsx_mts_and_cts_file_extensions_in_relative_import_paths_to_their_JavaScript_equivalent_in_output_files,
defaultValueDescription: false,
},
{
name: "resolvePackageJsonExports",
type: "boolean",
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -5934,6 +5934,10 @@
"category": "Message",
"code": 6420
},
"Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files.": {
"category": "Message",
"code": 6421
},

"The expected type comes from property '{0}' which is declared here on type '{1}'": {
"category": "Message",
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/moduleNameResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
forEach,
forEachAncestorDirectory,
formatMessage,
getAllowImportingTsExtensions,
getAllowJSCompilerOption,
getAnyExtensionFromPath,
getBaseFileName,
Expand Down Expand Up @@ -3303,7 +3304,7 @@ function resolveFromTypeRoot(moduleName: string, state: ModuleResolutionState) {
// so this function doesn't check them to avoid propagating errors.
/** @internal */
export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string) {
return !!compilerOptions.allowImportingTsExtensions || fromFileName && isDeclarationFileName(fromFileName);
return getAllowImportingTsExtensions(compilerOptions) || 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 @@ -4523,7 +4523,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
}
}

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

Expand Down
48 changes: 43 additions & 5 deletions src/compiler/transformers/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
Bundle,
CallExpression,
CaseBlock,
changeExtension,
childIsDecorated,
ClassDeclaration,
ClassElement,
Expand Down Expand Up @@ -55,6 +56,7 @@ import {
getInitializedVariables,
getIsolatedModules,
getOriginalNode,
getOutputExtension,
getParseTreeNode,
getProperties,
getStrictOptionValue,
Expand All @@ -81,6 +83,7 @@ import {
isClassElement,
isClassLike,
isComputedPropertyName,
isDeclarationFileName,
isDecorator,
isElementAccessExpression,
isEntityName,
Expand Down Expand Up @@ -122,6 +125,7 @@ import {
isSimpleInlineableExpression,
isSourceFile,
isStatement,
isStringLiteral,
isTemplateLiteral,
isTryStatement,
JsxOpeningElement,
Expand Down Expand Up @@ -155,6 +159,7 @@ import {
parameterIsThisKeyword,
ParameterPropertyDeclaration,
ParenthesizedExpression,
pathIsRelative,
PropertyAccessExpression,
PropertyDeclaration,
PropertyName,
Expand Down Expand Up @@ -2269,12 +2274,22 @@ export function transformTypeScript(context: TransformationContext) {
node,
/*modifiers*/ undefined,
importClause,
node.moduleSpecifier,
rewriteModuleSpecifier(node.moduleSpecifier),
node.attributes,
)
: undefined;
}

function rewriteModuleSpecifier(node: Expression): Expression;
function rewriteModuleSpecifier(node: Expression | undefined): Expression | undefined;
function rewriteModuleSpecifier(node: Expression | undefined): Expression | undefined {
if (!node || !compilerOptions.rewriteRelativeImportExtensions || !isStringLiteral(node) || !pathIsRelative(node.text) || isDeclarationFileName(node.text)) {
return node;
}
const updatedText = changeExtension(node.text, getOutputExtension(node.text, compilerOptions));
return updatedText !== node.text ? setOriginalNode(setTextRange(factory.createStringLiteral(updatedText, node.singleQuote), node), node) : node;
}

/**
* Visits an import clause, eliding it if its `name` and `namedBindings` may both be elided.
*
Expand Down Expand Up @@ -2342,7 +2357,14 @@ export function transformTypeScript(context: TransformationContext) {
// never elide `export <whatever> from <whereever>` declarations -
// they should be kept for sideffects/untyped exports, even when the
// type checker doesn't know about any exports
return node;
return factory.updateExportDeclaration(
node,
node.modifiers,
node.isTypeOnly,
node.exportClause,
rewriteModuleSpecifier(node.moduleSpecifier),
node.attributes,
);
}

// Elide the export declaration if all of its named exports are elided.
Expand All @@ -2359,7 +2381,7 @@ export function transformTypeScript(context: TransformationContext) {
/*modifiers*/ undefined,
node.isTypeOnly,
exportClause,
node.moduleSpecifier,
rewriteModuleSpecifier(node.moduleSpecifier),
node.attributes,
)
: undefined;
Expand Down Expand Up @@ -2421,8 +2443,24 @@ export function transformTypeScript(context: TransformationContext) {
}

if (isExternalModuleImportEqualsDeclaration(node)) {
const isReferenced = shouldEmitAliasDeclaration(node);
return isReferenced ? visitEachChild(node, visitor, context) : undefined;
if (!shouldEmitAliasDeclaration(node)) {
return undefined;
}
const updatedModuleSpecifier = rewriteModuleSpecifier(node.moduleReference.expression);
if (updatedModuleSpecifier !== node.moduleReference.expression) {
return visitEachChild(
factory.updateImportEqualsDeclaration(
node,
node.modifiers,
node.isTypeOnly,
node.name,
factory.updateExternalModuleReference(node.moduleReference, updatedModuleSpecifier),
),
visitor,
context,
);
}
return visitEachChild(node, visitor, context);
}

if (!shouldEmitImportEqualsDeclaration(node)) {
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7443,6 +7443,7 @@ export interface CompilerOptions {
removeComments?: boolean;
resolvePackageJsonExports?: boolean;
resolvePackageJsonImports?: boolean;
rewriteRelativeImportExtensions?: boolean;
rootDir?: string;
rootDirs?: string[];
skipLibCheck?: boolean;
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8821,6 +8821,12 @@ function createComputedCompilerOptions<T extends Record<string, CompilerOptionKe

/** @internal */
export const computedOptions = createComputedCompilerOptions({
allowImportingTsExtensions: {
dependencies: ["rewriteRelativeImportExtensions"],
computeValue: compilerOptions => {
return !!(compilerOptions.allowImportingTsExtensions || compilerOptions.rewriteRelativeImportExtensions);
},
},
target: {
dependencies: ["module"],
computeValue: compilerOptions => {
Expand Down Expand Up @@ -9046,6 +9052,8 @@ export const computedOptions = createComputedCompilerOptions({
},
});

/** @internal */
export const getAllowImportingTsExtensions = computedOptions.allowImportingTsExtensions.computeValue;
/** @internal */
export const getEmitScriptTarget = computedOptions.target.computeValue;
/** @internal */
Expand Down

0 comments on commit 7159132

Please sign in to comment.