Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NoMethodError: undefined method '[]' for nil with ruby3.4.0dev #225

Open
mtasaka opened this issue Dec 4, 2024 · 2 comments
Open

NoMethodError: undefined method '[]' for nil with ruby3.4.0dev #225

mtasaka opened this issue Dec 4, 2024 · 2 comments

Comments

@mtasaka
Copy link

mtasaka commented Dec 4, 2024

Using ruby 3.4.0dev (2024-12-04 master e539342f65) +PRISM [x86_64-linux]
ruby/ruby@e539342

pupplet-lint git head 167ab94
rspec testsuite does not do anything but exits abnormally:

$ rspec spec/unit ; echo $?
rspec/json_expectations is not available
WARNING: `around(:context)` hooks are not supported and behave like `around(:example)`. Called from /builddir/build/GIT/puppet-lint/spec/unit/puppet-lint/bin_spec.rb:608:in 'block (3 levels) in <top (required)>'.

PuppetLint::Bin
  when running normally
    exitstatus

Finished in 0.00475 seconds (files took 0.32275 seconds to load)
1 example, 0 failures

1

Then explicitly executing testsuite shows backtrace error:

$ env RUBYLIB=$(pwd)/lib ./bin/puppet-lint ./spec/fixtures/test/manifests/init.pp
Whoops! It looks like puppet-lint has encountered an error that it doesn't
know how to handle. Please open an issue at https://github.com/puppetlabs/puppet-lint
and paste the following output into the issue description.
---
puppet-lint version: 4.2.4
ruby version: 3.4.0-p-1
platform: x86_64-linux
file path: ./spec/fixtures/test/manifests/init.pp
file contents:
---
# foo
class test {
}

---
error:
---
NoMethodError: undefined method '[]' for nil
/builddir/build/GIT/puppet-lint/lib/puppet-lint/data.rb:63:in 'PuppetLint::Data.tokens'
/builddir/build/GIT/puppet-lint/lib/puppet-lint/data.rb:608:in 'PuppetLint::Data.parse_control_comments'
/builddir/build/GIT/puppet-lint/lib/puppet-lint/checks.rb:26:in 'PuppetLint::Checks#load_data'
/builddir/build/GIT/puppet-lint/lib/puppet-lint/checks.rb:55:in 'PuppetLint::Checks#run'
/builddir/build/GIT/puppet-lint/lib/puppet-lint.rb:226:in 'PuppetLint#run'
/builddir/build/GIT/puppet-lint/lib/puppet-lint/bin.rb:85:in 'block in PuppetLint::Bin#run'
/builddir/build/GIT/puppet-lint/lib/puppet-lint/bin.rb:80:in 'Array#each'
/builddir/build/GIT/puppet-lint/lib/puppet-lint/bin.rb:80:in 'PuppetLint::Bin#run'
./bin/puppet-lint:7:in '<main>'
---

Works normally with ruby 3.3.6 (2024-11-05 revision 75015d4c1f) [x86_64-linux]

@mtasaka
Copy link
Author

mtasaka commented Dec 4, 2024

So this is due to ruby3.4 backtrace change:

https://github.com/ruby/ruby/blob/e539342f65e468fc7f926277eff61cb8b8a60622/NEWS.md?plain=1#L224-L242

Especially, now single quote is used instead of backtick .
So now this regex does not match:

begin
caller(0..0).first[%r{`.*'}][1..-2]
rescue NoMethodError
caller(1..1).first[%r{`.*'}][1..-2]

Extra change is that backtrace now shows class name.

A fix for this is something like:

$ git diff
diff --git a/lib/puppet-lint/data.rb b/lib/puppet-lint/data.rb
index f219cf5..0518d58 100644
--- a/lib/puppet-lint/data.rb
+++ b/lib/puppet-lint/data.rb
@@ -58,12 +58,13 @@ class PuppetLint::Data
                          end
                        else
                          begin
-                           caller(0..0).first[%r{`.*'}][1..-2]
+                           caller(0..0).first[%r{[`'].*'}][1..-2]
                          rescue NoMethodError
-                           caller(1..1).first[%r{`.*'}][1..-2]
+                           caller(1..1).first[%r{[`'].*'}][1..-2]
                          end
                        end
 
+      calling_method.gsub!(/^.*[#\.]/, "")
       if calling_method == 'check'
         @tokens.dup
       else

@ekohl
Copy link

ekohl commented Dec 4, 2024

https://stackoverflow.com/questions/5100299/how-to-get-the-name-of-the-calling-method suggests a better method is to use caller_locations which returns Location objects which have a label method, avoiding the need to do any regular expression parsing.

The same thread mentions it's a Ruby 2 thing, but this Ruby 1 compatibility should have been dropped long ago. Also mentions that caller_locations is faster, so we can drop the RuboCop disable statements as well.

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

No branches or pull requests

2 participants