bscan / PerlNavigator

Perl Language Server that includes syntax checking, perl critic, and code navigation
MIT License
198 stars 39 forks source link

inquistor failed with error: Can't Regexp::Common::FIRSTKEY #106

Closed jamesheesbeen closed 10 months ago

jamesheesbeen commented 10 months ago

I'm having some issues with the extension which after a quick search pointed me to #54 - the symptoms are the same for me, but unfortunately I think the cause is slightly different.

I tried running the relevant perl -c etc. command to see if there were any errors encountered and it seems the Regexp::Common module is causing an issue with inquisitor.

PN:inquistor failed with error: Can't Regexp::Common::FIRSTKEY at /home/username-redacted/.vscode-server/extensions/bscan.perlnavigator-0.7.9/server/src/perl/Inquisitor.pm line 216.

Please let me know if there is any other info I can provide to help solve this issue.

bscan commented 10 months ago

Hi @jamesheesbeen, thanks for filing the issue. Yes, I agree this is a very similar issue. The Inquisitor is the core piece of introspection, so many features will fail if it throws an error. Although errors in that code have been fairly rare lately.

I'm trying to replicate the issue, but have not yet been able to. Looks like something is happening with the way Regexp::Common uses tied hashes. I see that %Regexp::Common::RE is itself a tied hash that is tied to Regexp::Common, so Regexp::Common::FIRSTKEY would be used in looping over the keys of the hash. However, I don't yet see why this is failing. Perhaps something is modifying this variable or hooking into the symbol table in an unusual way.

Do you have a short example of code that throws this error?

jamesheesbeen commented 10 months ago

Hi @bscan, thanks for looking into this (and creating this extension in the first place! I'm excited to try it out)

I actually just copied the first snippet in the Regexp::Common module docs to see if that would be enough and it does still produce an error:

use Regexp::Common;

while (<>) {
    /$RE{num}{real}/               and print q{a number};
    /$RE{quoted}/                  and print q{a ['"`] quoted string};
   m[$RE{delimited}{-delim=>'/'}]  and print q{a /.../ sequence};
    /$RE{balanced}{-parens=>'()'}/ and print q{balanced parentheses};
    /$RE{profanity}/               and print q{a #*@%-ing word};
}

1;

Running perl -c with inquisitor on that file is enough for it to provide the same error message for me on my machine.

PN:inquistor failed with error: Can't Regexp::Common::FIRSTKEY at /home/username/.vscode-server/extensions/bscan.perlnavigator-0.7.9/server/src/perl/Inquisitor.pm line 216.

If you need any other output from that, let me know and I'll add it.

bscan commented 10 months ago

Thanks! I see the issue. The %RE hash that is imported by Regexp::Common is a tied hash, but most of the normal methods are not defined on it. For example, any of the following checks will fail the the error of Can't Regexp::Common::FIRSTKEY error:

use Regexp::Common;

my %foo = %RE;    # Fails
print "True" if(%RE);   # Would also fail
print "Hash length" if(scalar keys %RE); # Would also fail

However, we don't need to know if the hash has any elements in it. For autocompletion, we simply want to know it exists. I made a change to simply check for type glob existence, similar to:

print "Hash exists\n" if(*RE{HASH});

The fix is now in the vscode marketplace and on NPM in version 0.7.11. Thanks for the bug report.