Skip to content

fix(no-unused-vars): guard namespace re-export handling#620

Merged
fansenze merged 3 commits intoweb-infra-dev:mainfrom
wChenonly:main
Apr 9, 2026
Merged

fix(no-unused-vars): guard namespace re-export handling#620
fansenze merged 3 commits intoweb-infra-dev:mainfrom
wChenonly:main

Conversation

@wChenonly
Copy link
Copy Markdown
Contributor

@wChenonly wChenonly commented Apr 9, 2026

Avoid a panic in no_unused_vars when scanning export declarations.

export * as ns from "..." produces a NamespaceExport export clause, not NamedExports, so skip non-named export clauses before calling AsNamedExports().

Add a regression test covering an unused import alongside a namespace re-export in the same file.

Summary

I am migrating rsdoctor to rslint and encountered an error.

nr
✔ script to run › lint

> rsdoctor-monorepo@ lint /Users/wchenonly/work/gitHub/f/rsdoctor
> rslint

panic: interface conversion: ast.nodeData is *ast.NamespaceExport, not *ast.NamedExports [recovered, repanicked]

goroutine 49590 [running]:
sync.(*WaitGroup).Go.func1.1()
        /opt/hostedtoolcache/go/1.26.0/x64/src/sync/waitgroup.go:251 +0x48
panic({0x105fa8a40?, 0x2f61dd663380?})
        /opt/hostedtoolcache/go/1.26.0/x64/src/runtime/panic.go:860 +0x12c
github.com/microsoft/typescript-go/internal/ast.(*Node).AsNamedExports(...)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:1665
github.com/web-infra-dev/rslint/internal/plugins/typescript/rules/no_unused_vars.isReExportedSymbol.func1(0x106075fe0?)
        /home/runner/_work/rslint/rslint/internal/plugins/typescript/rules/no_unused_vars/no_unused_vars.go:1089 +0x220
github.com/microsoft/typescript-go/internal/ast.visitNodes(...)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:38
github.com/microsoft/typescript-go/internal/ast.visitNodeList(...)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:47
github.com/microsoft/typescript-go/internal/ast.(*SourceFile).ForEachChild(0x2f61b48e9188, 0x2f61dd22ac40)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:11191 +0xa4
github.com/microsoft/typescript-go/internal/ast.(*Node).ForEachChild(0x2f61a69f7558?, 0x1051c4cec?)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:252 +0x24
github.com/web-infra-dev/rslint/internal/plugins/typescript/rules/no_unused_vars.isReExportedSymbol({0x2f61b48e9188, 0x2f619d66ed88, 0x2f61d2ee6608, 0x2f61dd662bd0, 0x2f61dd67aa40, 0x2f61dd67aa80, 0x2f61dd67aac0, 0x2f61dd67ab00, 0x2f61dd67ab40, 0x2f61dd67ab80}, ...)
        /home/runner/_work/rslint/rslint/internal/plugins/typescript/rules/no_unused_vars/no_unused_vars.go:1081 +0xd8
github.com/web-infra-dev/rslint/internal/plugins/typescript/rules/no_unused_vars.isExported({0x2f61b48e9188, 0x2f619d66ed88, 0x2f61d2ee6608, 0x2f61dd662bd0, 0x2f61dd67aa40, 0x2f61dd67aa80, 0x2f61dd67aac0, 0x2f61dd67ab00, 0x2f61dd67ab40, 0x2f61dd67ab80}, ...)
        /home/runner/_work/rslint/rslint/internal/plugins/typescript/rules/no_unused_vars/no_unused_vars.go:1067 +0x1b8
github.com/web-infra-dev/rslint/internal/plugins/typescript/rules/no_unused_vars.processVariable({0x2f61b48e9188, 0x2f619d66ed88, 0x2f61d2ee6608, 0x2f61dd662bd0, 0x2f61dd67aa40, 0x2f61dd67aa80, 0x2f61dd67aac0, 0x2f61dd67ab00, 0x2f61dd67ab40, 0x2f61dd67ab80}, ...)
        /home/runner/_work/rslint/rslint/internal/plugins/typescript/rules/no_unused_vars/no_unused_vars.go:1682 +0x420
github.com/web-infra-dev/rslint/internal/plugins/typescript/rules/no_unused_vars.init.func1.11(0x2f61b4926000)
        /home/runner/_work/rslint/rslint/internal/plugins/typescript/rules/no_unused_vars/no_unused_vars.go:2043 +0x130
github.com/web-infra-dev/rslint/internal/linter.RunLinterInProgram.func8(0x115, 0x2f61b4926000)
        /home/runner/_work/rslint/rslint/internal/linter/linter.go:259 +0x6c
github.com/web-infra-dev/rslint/internal/linter.RunLinterInProgram.func10(0x2f61b4926000)
        /home/runner/_work/rslint/rslint/internal/linter/linter.go:306 +0x48
github.com/microsoft/typescript-go/internal/ast.visitNodes(...)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:38
github.com/microsoft/typescript-go/internal/ast.visitNodeList(...)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:47
github.com/microsoft/typescript-go/internal/ast.(*NamedImports).ForEachChild(0x2f61a69f7ac8?, 0x2f61dd22cae0)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:5180 +0x74
github.com/microsoft/typescript-go/internal/ast.(*Node).ForEachChild(0x114?, 0x2f61b47dcec0?)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:252 +0x24
github.com/web-infra-dev/rslint/internal/linter.RunLinterInProgram.func10(0x2f61b47dcec0)
        /home/runner/_work/rslint/rslint/internal/linter/linter.go:321 +0x134
github.com/microsoft/typescript-go/internal/ast.visit(...)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:31
github.com/microsoft/typescript-go/internal/ast.(*ImportClause).ForEachChild(0x0?, 0x2f61dd67c8f0?)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:5084 +0x74
github.com/microsoft/typescript-go/internal/ast.(*Node).ForEachChild(0x2f61a69f0112?, 0x2f61972bcfc0?)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:252 +0x24
github.com/web-infra-dev/rslint/internal/linter.RunLinterInProgram.func10(0x2f61972bcfc0)
        /home/runner/_work/rslint/rslint/internal/linter/linter.go:321 +0x134
github.com/microsoft/typescript-go/internal/ast.visit(...)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:31
github.com/microsoft/typescript-go/internal/ast.(*ImportDeclaration).ForEachChild(0x2f61972bd020, 0x2f61dd22cae0)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:4930 +0x6c
github.com/microsoft/typescript-go/internal/ast.(*Node).ForEachChild(0x200004009f0111?, 0x2f61972bd020?)
        /home/runner/_work/rslint/rslint/typescript-go/internal/ast/ast.go:252 +0x24
github.com/web-infra-dev/rslint/internal/linter.RunLinterInProgram.func10(0x2f61972bd020)
        /home/runner/_work/rslint/rslint/internal/linter/linter.go:321 +0x134

Related Links

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).

Avoid a panic in no_unused_vars when scanning export declarations.

`export * as ns from "..."` produces a `NamespaceExport` export clause,
not `NamedExports`, so skip non-named export clauses before calling
`AsNamedExports()`.

Add a regression test covering an unused import alongside a namespace
re-export in the same file.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses a potential runtime panic in the no_unused_vars rule by adding a type check before asserting an export clause as NamedExports. This prevents issues when encountering NamespaceExport declarations. A corresponding test case has been added to ensure correct handling of namespace re-exports and accurate identification of unused imports. There is no feedback to provide on the code changes.

Comment thread internal/plugins/typescript/rules/no_unused_vars/no_unused_vars_imports_test.go Outdated
@fansenze fansenze merged commit 968308e into web-infra-dev:main Apr 9, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants