Skip to content

Fix namespace::clean stub missing get_functions and clean_subroutines#183

Open
dwright wants to merge 1 commit intobscan:mainfrom
dwright:fix-namespace-clean-get-functions-stub
Open

Fix namespace::clean stub missing get_functions and clean_subroutines#183
dwright wants to merge 1 commit intobscan:mainfrom
dwright:fix-namespace-clean-get-functions-stub

Conversation

@dwright
Copy link

@dwright dwright commented Feb 26, 2026

Inquisitor.pm stubs out namespace::clean to prevent it from wiping the symbol table before inspection:

$INC{'namespace/clean.pm'} = '';
*{'namespace::clean::import'} = sub { };

However, the stub only provides import and VERSION. Any module that calls namespace::clean->get_functions($package) or namespace::clean->clean_subroutines(...) as a class method at file scope — not inside a BEGIN block — will fail with:

Can't locate object method "get_functions" via package "namespace::clean"

This causes a cascade of BEGIN failed errors through the dependency chain, which perlnavigator surfaces as dozens of false Syntax error diagnostics in the editor — one per line of the stack trace — all pointing to line 1 of the file being checked.

Root Cause
The call to namespace::clean->get_functions(...) at file scope is valid Perl and works at runtime, because namespace::clean loads normally. But under -MInquisitor, the real namespace::clean is blocked from loading, and the stub doesn't provide a get_functions method.

Fix
Add a working get_functions stub that reads CODE symbols from the package stash directly — matching the real implementation's return value — and a no-op clean_subroutines stub:

*{'namespace::clean::get_functions'} = sub {
    my ($pragma, $class) = @_;
    no strict 'refs';
    return { map { $_ => \&{"${class}::${_}"} }
             grep { defined &{"${class}::${_}"} }
             keys %{"${class}::"} };
};
*{'namespace::clean::clean_subroutines'} = sub { };

The clean_subroutines stub is a safe no-op since symbol table cleanup is intentionally skipped during inspection anyway.

Tests
Added t/02_NamespaceClean.t with a regression test and testWorkspace/MyLib/NamespaceCleanCaller.pm as a fixture that calls namespace::clean->get_functions(__PACKAGE__) at file scope. All 6 tests pass.

The namespace::clean stub only provided import() and VERSION, but not
get_functions() or clean_subroutines(). Any module that calls
namespace::clean->get_functions($package) at file scope (not inside a
BEGIN block) would fail with:

  Can't locate object method "get_functions" via package "namespace::clean"

This causes a cascade of BEGIN failed errors through the dependency
chain, surfacing as dozens of false Syntax diagnostics in the editor.

Fix: add a get_functions stub that reads CODE symbols from the package
stash directly, matching the real implementation's return value, and a
no-op clean_subroutines stub.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant