diff --git a/turbopack/crates/turbopack-ecmascript/src/analyzer/imports.rs b/turbopack/crates/turbopack-ecmascript/src/analyzer/imports.rs index 0ec518ffa86a..c1c22519eda1 100644 --- a/turbopack/crates/turbopack-ecmascript/src/analyzer/imports.rs +++ b/turbopack/crates/turbopack-ecmascript/src/analyzer/imports.rs @@ -1223,17 +1223,26 @@ impl Visit for Analyzer<'_> { } fn visit_member_expr(&mut self, node: &MemberExpr) { - if let MemberProp::Ident(..) | MemberProp::PrivateName(..) = &node.prop - && node.obj.is_ident() + if matches!( + &node.prop, + MemberProp::Ident(..) | MemberProp::PrivateName(..) + ) && let Expr::Ident(ident) = &*node.obj { - // Skip traversing if obj is a Expr::Ident, so that it doesn't get added to + // Intentionally skipping over visit_expr(node.obj) here so that it doesn't get added to // full_star_imports below in visit_expr. + ident.visit_with(self); + } else { + node.visit_children_with(self); + } + } - // TODO this currently doesn't properly mark the import in self.program_decl_usage, see - // todo in - // turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/ - // import-star/input/index.js - return; + fn visit_expr(&mut self, node: &Expr) { + // Careful about adding anything here, visit_member_expr might skip over this method for + // some Expr::Ident-s. + if let Expr::Ident(i) = node + && let Some(module_path) = self.namespace_imports_to_specifier.get(&i.to_id()) + { + self.data.full_star_imports.insert(module_path.clone()); } node.visit_children_with(self); } @@ -1258,15 +1267,6 @@ impl Visit for Analyzer<'_> { node.visit_children_with(self); } - fn visit_expr(&mut self, node: &Expr) { - if let Expr::Ident(i) = node - && let Some(module_path) = self.namespace_imports_to_specifier.get(&i.to_id()) - { - self.data.full_star_imports.insert(module_path.clone()); - } - node.visit_children_with(self); - } - fn visit_ident(&mut self, node: &Ident) { let id = node.to_id(); if let Some((esm_reference_index, _)) = self.data.get_binding(&id) { diff --git a/turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/member-call/input/a.js b/turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/member-call/input/a.js new file mode 100644 index 000000000000..816958923b48 --- /dev/null +++ b/turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/member-call/input/a.js @@ -0,0 +1,9 @@ +import { b } from './b.js' + +export function a() { + return sub.call() +} + +function sub() { + return b +} diff --git a/turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/member-call/input/b.js b/turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/member-call/input/b.js new file mode 100644 index 000000000000..57e2a26314d4 --- /dev/null +++ b/turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/member-call/input/b.js @@ -0,0 +1 @@ +export const b = 123 diff --git a/turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/member-call/input/index.js b/turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/member-call/input/index.js new file mode 100644 index 000000000000..d8a24b3a359e --- /dev/null +++ b/turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/member-call/input/index.js @@ -0,0 +1,5 @@ +import { a } from './a.js' + +it('should work', () => { + expect(a()).toBe(123) +}) diff --git a/turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/member-call/options.json b/turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/member-call/options.json new file mode 100644 index 000000000000..bf30b867b721 --- /dev/null +++ b/turbopack/crates/turbopack-tests/tests/execution/turbopack/remove-unused-imports/member-call/options.json @@ -0,0 +1,3 @@ +{ + "scopeHoisting": false +}