Skip to content

Commit 73b081e

Browse files
fix(macro): map injected imports to original statements (#2252)
1 parent fcc2983 commit 73b081e

File tree

2 files changed

+67
-34
lines changed

2 files changed

+67
-34
lines changed

packages/babel-plugin-lingui-macro/src/index.ts

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { JsMacroName } from "./constants"
88
import {
99
type LinguiConfigNormalized,
1010
getConfig as loadConfig,
11+
LinguiConfig,
1112
} from "@lingui/conf"
1213

1314
let config: LinguiConfigNormalized
@@ -86,34 +87,50 @@ const getIdentifierPath = ((path: NodePath, node: Identifier) => {
8687
return foundPath
8788
}) as any
8889

90+
type MacroImports = {
91+
corePackage: Set<NodePath<babelTypes.ImportDeclaration>>
92+
jsxPackage: Set<NodePath<babelTypes.ImportDeclaration>>
93+
all: Set<NodePath<babelTypes.ImportDeclaration>>
94+
}
95+
96+
const LinguiSymbolToImportMap = {
97+
Trans: "jsxPackage",
98+
useLingui: "jsxPackage",
99+
i18n: "corePackage",
100+
} satisfies Record<LinguiSymbol, keyof LinguiConfig["macro"]>
101+
89102
export default function ({
90103
types: t,
91104
}: {
92105
types: typeof babelTypes
93106
}): PluginObj {
94-
function addImport(state: PluginPass, name: LinguiSymbol) {
95-
const path = state.get(
96-
"macroImport"
97-
) as NodePath<babelTypes.ImportDeclaration>
107+
function addImport(
108+
macroImports: MacroImports,
109+
state: PluginPass,
110+
name: LinguiSymbol
111+
) {
112+
const [path] = macroImports[LinguiSymbolToImportMap[name]]
98113

99114
const config = state.get("linguiConfig") as LinguiConfigNormalized
100115

101116
if (!state.get("has_import_" + name)) {
102117
state.set("has_import_" + name, true)
103118
const [moduleSource, importName] = config.runtimeConfigModule[name]
104119

105-
const [newPath] = path.insertAfter(
106-
t.importDeclaration(
107-
[
108-
t.importSpecifier(
109-
getSymbolIdentifier(state, name),
110-
t.identifier(importName)
111-
),
112-
],
113-
t.stringLiteral(moduleSource)
114-
)
120+
const importDecl = t.importDeclaration(
121+
[
122+
t.importSpecifier(
123+
getSymbolIdentifier(state, name),
124+
t.identifier(importName)
125+
),
126+
],
127+
t.stringLiteral(moduleSource)
115128
)
116129

130+
importDecl.loc = path.node.loc
131+
132+
const [newPath] = path.insertAfter(importDecl)
133+
117134
path.parentPath.scope.registerDeclaration(newPath)
118135
}
119136

@@ -122,18 +139,34 @@ export default function ({
122139
)
123140
}
124141

125-
function getMacroImports(path: NodePath<Program>) {
126-
const linguiPackages = new Set([
127-
...config.macro.corePackage,
128-
...config.macro.jsxPackage,
129-
])
142+
function getMacroImports(path: NodePath<Program>): MacroImports {
143+
const corePackage = new Set(
144+
path
145+
.get("body")
146+
.filter(
147+
(statement) =>
148+
statement.isImportDeclaration() &&
149+
config.macro.corePackage.includes(
150+
statement.get("source").node.value
151+
)
152+
) as NodePath<babelTypes.ImportDeclaration>[]
153+
)
130154

131-
return path.get("body").filter((statement) => {
132-
return (
133-
statement.isImportDeclaration() &&
134-
linguiPackages.has(statement.get("source").node.value)
135-
)
136-
})
155+
const jsxPackage = new Set(
156+
path
157+
.get("body")
158+
.filter(
159+
(statement) =>
160+
statement.isImportDeclaration() &&
161+
config.macro.jsxPackage.includes(statement.get("source").node.value)
162+
) as NodePath<babelTypes.ImportDeclaration>[]
163+
)
164+
165+
return {
166+
corePackage,
167+
jsxPackage,
168+
all: new Set([...corePackage, ...jsxPackage]),
169+
}
137170
}
138171

139172
function getSymbolIdentifier(
@@ -184,17 +217,15 @@ export default function ({
184217

185218
const macroImports = getMacroImports(path)
186219

187-
if (!macroImports.length) {
220+
if (!macroImports.all.size) {
188221
return
189222
}
190223

191-
state.set("macroImport", macroImports[0])
192-
193224
state.set("linguiIdentifiers", {
194225
i18n: path.scope.generateUidIdentifier("i18n"),
195226
Trans: path.scope.generateUidIdentifier("Trans"),
196227
useLingui: path.scope.generateUidIdentifier("useLingui"),
197-
})
228+
} satisfies Record<LinguiSymbol, babelTypes.Identifier>)
198229

199230
path.traverse(
200231
{
@@ -224,7 +255,7 @@ export default function ({
224255

225256
if (newNode) {
226257
const [newPath] = path.replaceWith(newNode)
227-
addImport(state, "Trans").reference(newPath)
258+
addImport(macroImports, state, "Trans").reference(newPath)
228259
}
229260
},
230261

@@ -261,11 +292,13 @@ export default function ({
261292
const [newPath] = path.replaceWith(newNode)
262293

263294
if (macro.needsUseLinguiImport) {
264-
addImport(state, "useLingui").reference(newPath)
295+
addImport(macroImports, state, "useLingui").reference(
296+
newPath
297+
)
265298
}
266299

267300
if (macro.needsI18nImport) {
268-
addImport(state, "i18n").reference(newPath)
301+
addImport(macroImports, state, "i18n").reference(newPath)
269302
}
270303
}
271304
},
@@ -275,7 +308,7 @@ export default function ({
275308
},
276309
exit(path, state) {
277310
const macroImports = getMacroImports(path)
278-
macroImports.forEach((path) => path.remove())
311+
macroImports.all.forEach((path) => path.remove())
279312
},
280313
},
281314
} as Visitor<PluginPass>,

packages/babel-plugin-lingui-macro/test/__snapshots__/jsx-trans.test.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -759,8 +759,8 @@ import { t } from "@lingui/core/macro";
759759
760760
↓ ↓ ↓ ↓ ↓ ↓
761761
762-
import { i18n as _i18n } from "@lingui/core";
763762
import { Trans as _Trans } from "@lingui/react";
763+
import { i18n as _i18n } from "@lingui/core";
764764
<_Trans
765765
{
766766
/*i18n*/

0 commit comments

Comments
 (0)