diff --git a/src/language-js/print/call-arguments.js b/src/language-js/print/call-arguments.js index cc2c95f38..f958d4698 100644 --- a/src/language-js/print/call-arguments.js +++ b/src/language-js/print/call-arguments.js @@ -78,24 +78,6 @@ function printCallArguments(path, options, print) { printedArguments.push(argDoc); }); - // Don't break simple import with long module name - if ( - (node.type === "TSImportType" || node.type === "ImportExpression") && - args.length === 1 && - !hasComment(args[0]) - ) { - let source = args[0]; - - // TODO: remove this once https://github.com/typescript-eslint/typescript-eslint/issues/11583 get fixed - if (node.type === "TSImportType" && source.type === "TSLiteralType") { - source = source.literal; - } - - if (isStringLiteral(source)) { - return group(["(", printedArguments, ")"]); - } - } - const maybeTrailingComma = // Angular does not allow trailing comma !options.parser.startsWith("__ng_") && diff --git a/src/language-js/print/call-expression.js b/src/language-js/print/call-expression.js index 3b4875dca..7678db258 100644 --- a/src/language-js/print/call-expression.js +++ b/src/language-js/print/call-expression.js @@ -2,6 +2,7 @@ import { group, join } from "../../document/builders.js"; import pathNeedsParens from "../needs-parens.js"; import { getCallArguments, + hasComment, isCallExpression, isMemberish, isStringLiteral, @@ -15,8 +16,7 @@ import { printFunctionTypeParameters, printOptionalToken } from "./misc.js"; function printCallExpression(path, options, print) { const { node } = path; - const isNew = node.type === "NewExpression"; - const isDynamicImport = node.type === "ImportExpression"; + const isNewExpression = node.type === "NewExpression"; const optional = printOptionalToken(path); const args = getCallArguments(node); @@ -26,6 +26,8 @@ function printCallExpression(path, options, print) { if ( isTemplateLiteralSingleArg || + // Don't break simple `import()` with long module name + isSimpleModuleImport(path) || // Dangling comments are not handled, all these special cases should have arguments #9668 // We want to keep CommonJS- and AMD-style require calls, and AMD-style // define calls, as a unit. @@ -41,7 +43,7 @@ function printCallExpression(path, options, print) { }); if (!(isTemplateLiteralSingleArg && printed[0].label?.embed)) { return [ - isNew ? "new " : "", + isNewExpression ? "new " : "", printCallee(path, print), optional, printFunctionTypeParameters(path, options, print), @@ -52,11 +54,14 @@ function printCallExpression(path, options, print) { } } + const isDynamicImport = + node.type === "ImportExpression" || node.type === "TSImportType"; + // We detect calls on member lookups and possibly print them in a // special chain format. See `printMemberChain` for more info. if ( !isDynamicImport && - !isNew && + !isNewExpression && isMemberish(node.callee) && !path.call( (path) => pathNeedsParens(path, options), @@ -68,7 +73,7 @@ function printCallExpression(path, options, print) { } const contents = [ - isNew ? "new " : "", + isNewExpression ? "new " : "", printCallee(path, print), optional, printFunctionTypeParameters(path, options, print), @@ -87,13 +92,50 @@ function printCallExpression(path, options, print) { function printCallee(path, print) { const { node } = path; - if (node.type === "ImportExpression") { + if (node.type === "ImportExpression" || node.type === "TSImportType") { return `import${node.phase ? `.${node.phase}` : ""}`; } return print("callee"); } +function isSimpleModuleImport(path) { + const { node } = path; + + if ( + !( + // `import("foo")` + ( + node.type === "ImportExpression" || + // `type foo = import("foo")` + node.type === "TSImportType" || + // `require("foo")` + (node.type === "CallExpression" && + !node.optional && + node.callee.type === "Identifier" && + node.callee.name === "require") + ) + ) + ) { + return false; + } + + const args = getCallArguments(node); + + if (args.length !== 1 || hasComment(args[0])) { + return false; + } + + let source = args[0]; + + // TODO: remove this once https://github.com/typescript-eslint/typescript-eslint/issues/11583 get fixed + if (node.type === "TSImportType" && source.type === "TSLiteralType") { + source = source.literal; + } + + return isStringLiteral(source); +} + function isCommonsJsOrAmdModuleDefinition(path) { const { node } = path; diff --git a/src/language-js/print/misc.js b/src/language-js/print/misc.js index 69d1cda52..e2a8d284b 100644 --- a/src/language-js/print/misc.js +++ b/src/language-js/print/misc.js @@ -91,13 +91,21 @@ function printAbstractToken({ node }) { } function printFunctionTypeParameters(path, options, print) { - const fun = path.node; - if (fun.typeArguments) { + const { node } = path; + + // `TSImportType.typeArguments` is after `qualifier`, not before the "arguments" + if (node.type === "TSImportType") { + return ""; + } + + if (node.typeArguments) { return print("typeArguments"); } - if (fun.typeParameters) { + + if (node.typeParameters) { return print("typeParameters"); } + return ""; } diff --git a/src/language-js/print/typescript.js b/src/language-js/print/typescript.js index 92b534fd9..619cf97b2 100644 --- a/src/language-js/print/typescript.js +++ b/src/language-js/print/typescript.js @@ -15,7 +15,7 @@ import { import isTsKeywordType from "../utils/is-ts-keyword-type.js"; import { printArray } from "./array.js"; import { printBlock } from "./block.js"; -import printCallArguments from "./call-arguments.js"; +import { printCallExpression } from "./call-expression.js"; import { printBinaryCastExpression } from "./cast-expression.js"; import { printClassMethod, printClassProperty } from "./class.js"; import { @@ -215,8 +215,7 @@ function printTypescript(path, options, print) { return [print("expression"), "!"]; case "TSImportType": return [ - "import", - printCallArguments(path, options, print), + printCallExpression(path, options, print), !node.qualifier ? "" : [".", print("qualifier")], printTypeParameters( path, diff --git a/tests/format/js/require/__snapshots__/format.test.js.snap b/tests/format/js/require/__snapshots__/format.test.js.snap index 740a769cd..5b8451af3 100644 --- a/tests/format/js/require/__snapshots__/format.test.js.snap +++ b/tests/format/js/require/__snapshots__/format.test.js.snap @@ -24,6 +24,8 @@ const plugin2 = require( ) ); +const plugin3 = require('./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module') + =====================================output===================================== const { one, @@ -63,5 +65,7 @@ const plugin2 = require( path.join(__dirname, global.STANDALONE ? "../standalone.js" : ".."), ); +const plugin3 = require("./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module"); + ================================================================================ `; diff --git a/tests/format/js/require/require.js b/tests/format/js/require/require.js index 0ab375268..f41e03c85 100644 --- a/tests/format/js/require/require.js +++ b/tests/format/js/require/require.js @@ -15,3 +15,5 @@ const plugin2 = require( global.STANDALONE ? "../standalone.js" : '..' ) ); + +const plugin3 = require('./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module')