Repository: nuxt/nuxt
File: packages/nuxt/src/core/plugins/tree-shake.ts (TypeScript)

Code before:
            if (importDecl.source.type !== 'Literal' || !importDecl.specifiers) {
              return
            }

            const importPath = importDecl.source.value

            for (const specifier of importDecl.specifiers) {
              if (specifier.type !== 'ImportSpecifier' || specifier.imported.type !== 'Identifier') {
                continue
              }

              const importedName = specifier.imported.name
              const localName = specifier.local.name

              // Track all imports of composable names, regardless of path
              if (allComposableNames.has(importedName)) {
                allImportedComposableNames.add(localName)

                // Only track the path if it's from an allowed source
                if (importPath === '#imports' || options.composables[importPath]?.includes(importedName)) {
                  importedComposables.set(localName, importPath)
                }
              }
            }
            return
          }

          // Look for function call expressions
          if (node.type !== 'CallExpression' || node.callee.type !== 'Identifier') {
            return
          }

          const functionName = node.callee.name

          // Check if this is a composable we should tree-shake
          if (!allComposableNames.has(functionName) && !importedComposables.has(functionName)) {
            return
          }

          // If it's explicitly imported from an allowed path, tree-shake it
          if (importedComposables.has(functionName)) {
            s.overwrite(node.start, node.end, ` false && /*@__PURE__*/ ${functionName}${code.slice(node.callee.end, node.end)}`)
            return
          }

          // If it's not explicitly imported at all, assume it's auto-imported and tree-shake it
          if (!allImportedComposableNames.has(functionName)) {
            s.overwrite(node.start, node.end, ` false && /*@__PURE__*/ ${functionName}${code.slice(node.callee.end, node.end)}`)
          }
        })


Review comment (bug):
if you use the ScopeTracker, you can then get the declaration of the identifier and check if it's an import
```ts
const scopeTrackerNode = scopeTracker.getDeclaration(functionName)

if (
  scopeTrackerNode?.type === 'Import'
  && scopeTrackerNode.importNode.source.value === /* ... */
)
```

this way, it will support shadowing outer-scope composables

```ts
// edge case example
import { onMounted } from '#imports'

onMounted(() => console.log('treeshake this'))

function foo() { 
  onMounted()
  // we will need a pre-pass to collect all identifiers for each scope, though...
  function onMounted() {
    console.log('do not treeshake this')
  }
}
```

Code after:
        })
        scopeTracker.freeze()

        // Process nodes and check for tree-shaking opportunities
        walk(parseResult.program, {
          scopeTracker,
          enter (node) {
            if (node.type !== 'CallExpression' || node.callee.type !== 'Identifier') {
              return
            }

            const functionName = node.callee.name
            const scopeTrackerNode = scopeTracker.getDeclaration(functionName)

            if (scopeTrackerNode) {
            // don't tree-shake if there's a local declaration
              if (scopeTrackerNode.type !== 'Import') {
                return
              }

              if (scopeTrackerNode.importNode.type !== 'ImportDeclaration') {
                return
              }

              // check if import is from an allowed source and composable
              const importPath = scopeTrackerNode.importNode.source.value

              const importSpecifier = scopeTrackerNode.node
              const importedName = importSpecifier.type === 'ImportSpecifier' && importSpecifier.imported.type === 'Identifier'
                ? importSpecifier.imported.name
                : importSpecifier.local.name

              const isFromAllowedPath = importPath === '#imports'
                ? allComposableNames.has(importedName)
                : options.composables[importPath]?.includes(importedName)

              if (!isFromAllowedPath) {
                return
              }
            }

            if (!scopeTrackerNode && !allComposableNames.has(functionName)) {
              return
            }

            // TODO: validate function name against actual auto-imports registry
            s.overwrite(node.start, node.end, ` false && /*@__PURE__*/ ${functionName}${code.slice(node.callee.end, node.end)}`)
          },
        })

        if (s.hasChanged()) {