prism icon indicating copy to clipboard operation
prism copied to clipboard

method_source not working with Prism due to different SyntaxError messages

Open eregon opened this issue 1 year ago • 1 comments

Running https://github.com/banister/method_source 's test suite passes on ruby master but fails with RUBYOPT=--parser=prism bundle exec rake:

Failures:

  1) MethodSource::CodeHelpers should not raise an error on broken lines: def\na\n(); end
     Failure/Error: eval("BEGIN{throw :valid}\n#{str}")
     
     SyntaxError:
       (eval at /home/eregon/code/method_source/lib/method_source/code_helpers.rb:71):3: syntax errors found (SyntaxError)
         1 | BEGIN{throw :valid}
       > 2 | def
           |    ^ expected an `end` to close the `def` statement
           |    ^ expected a delimiter to close the parameters
       > 3 | 
           | ^ unexpected end of file, assuming it is closing the parent top level context
     
           | ^ unexpected end of file; expected a method name
     # ./lib/method_source/code_helpers.rb:71:in 'Kernel#eval'
     # ./lib/method_source/code_helpers.rb:71:in 'block in MethodSource::CodeHelpers#complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in 'Kernel#catch'
     # ./lib/method_source/code_helpers.rb:70:in 'MethodSource::CodeHelpers#complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in 'block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in 'Integer#upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in 'block (3 levels) in <top (required)>'

  2) MethodSource::CodeHelpers should not raise an error on broken lines: p = <<FOO\nlots\nand\nlots of\nfoo\nFOO
     Failure/Error: eval("BEGIN{throw :valid}\n#{str}")
     
     SyntaxError:
       (eval at /home/eregon/code/method_source/lib/method_source/code_helpers.rb:71):3: syntax error found (SyntaxError)
         1 | BEGIN{throw :valid}
         2 | p = <<FOO
       > 3 | 
           | ^ could not find a terminator for the heredoc
     # ./lib/method_source/code_helpers.rb:71:in 'Kernel#eval'
     # ./lib/method_source/code_helpers.rb:71:in 'block in MethodSource::CodeHelpers#complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in 'Kernel#catch'
     # ./lib/method_source/code_helpers.rb:70:in 'MethodSource::CodeHelpers#complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in 'block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in 'Integer#upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in 'block (3 levels) in <top (required)>'

  3) MethodSource::CodeHelpers should not raise an error on broken lines: [\n:lets,\n'list',\n[/nested/\n], things ]
     Failure/Error: eval("BEGIN{throw :valid}\n#{str}")
     
     SyntaxError:
       (eval at /home/eregon/code/method_source/lib/method_source/code_helpers.rb:71):2: syntax error found (SyntaxError)
         1 | BEGIN{throw :valid}
       > 2 | [
           |  ^ expected a `]` to close the array
         3 | 
     # ./lib/method_source/code_helpers.rb:71:in 'Kernel#eval'
     # ./lib/method_source/code_helpers.rb:71:in 'block in MethodSource::CodeHelpers#complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in 'Kernel#catch'
     # ./lib/method_source/code_helpers.rb:70:in 'MethodSource::CodeHelpers#complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in 'block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in 'Integer#upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in 'block (3 levels) in <top (required)>'

  4) MethodSource::CodeHelpers should not raise an error on broken lines: abc =~ /hello\n/
     Failure/Error: eval("BEGIN{throw :valid}\n#{str}")
     
     SyntaxError:
       (eval at /home/eregon/code/method_source/lib/method_source/code_helpers.rb:71):2: syntax error found (SyntaxError)
         1 | BEGIN{throw :valid}
       > 2 | abc =~ /hello
           |        ^ expected a closing delimiter for the regular expression
         3 | 
     # ./lib/method_source/code_helpers.rb:71:in 'Kernel#eval'
     # ./lib/method_source/code_helpers.rb:71:in 'block in MethodSource::CodeHelpers#complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in 'Kernel#catch'
     # ./lib/method_source/code_helpers.rb:70:in 'MethodSource::CodeHelpers#complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in 'block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in 'Integer#upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in 'block (3 levels) in <top (required)>'

  5) MethodSource::CodeHelpers should not raise an error on broken lines: issue = %W/\n343/
     Failure/Error: eval("BEGIN{throw :valid}\n#{str}")
     
     SyntaxError:
       (eval at /home/eregon/code/method_source/lib/method_source/code_helpers.rb:71):2: syntax error found (SyntaxError)
         1 | BEGIN{throw :valid}
       > 2 | issue = %W/
           |         ^~~ expected a closing delimiter for the `%W` list
         3 | 
     # ./lib/method_source/code_helpers.rb:71:in 'Kernel#eval'
     # ./lib/method_source/code_helpers.rb:71:in 'block in MethodSource::CodeHelpers#complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in 'Kernel#catch'
     # ./lib/method_source/code_helpers.rb:70:in 'MethodSource::CodeHelpers#complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in 'block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in 'Integer#upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in 'block (3 levels) in <top (required)>'

  6) MethodSource::CodeHelpers should not raise an error on broken lines: puts 1, 2,\n3
     Failure/Error: eval("BEGIN{throw :valid}\n#{str}")
     
     SyntaxError:
       (eval at /home/eregon/code/method_source/lib/method_source/code_helpers.rb:71):2: syntax error found (SyntaxError)
         1 | BEGIN{throw :valid}
       > 2 | puts 1, 2,
           |          ^ expected an argument
         3 | 
     # ./lib/method_source/code_helpers.rb:71:in 'Kernel#eval'
     # ./lib/method_source/code_helpers.rb:71:in 'block in MethodSource::CodeHelpers#complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in 'Kernel#catch'
     # ./lib/method_source/code_helpers.rb:70:in 'MethodSource::CodeHelpers#complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in 'block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in 'Integer#upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in 'block (3 levels) in <top (required)>'

  7) MethodSource Methods should return source for an *_evaled method
     Failure/Error: raise SourceNotFoundError, "Could not parse source for #{name}: #{e.message}"
     
     MethodSource::SourceNotFoundError:
       Could not parse source for hello_name: (eval at /home/eregon/code/method_source/lib/method_source/code_helpers.rb:71):3: syntax errors found
         1 | BEGIN{throw :valid}
         2 |   def hello_#{name}(*args)
       > 3 | 
           | ^ expected an `end` to close the `def` statement
     
           | ^ unexpected end of file, assuming it is closing the parent top level context
     # ./lib/method_source.rb:29:in 'MethodSource.source_helper'
     # ./lib/method_source.rb:115:in 'MethodSource::MethodExtensions#source'
     # ./spec/method_source_spec.rb:75:in 'block (3 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # SyntaxError:
     #   (eval at /home/eregon/code/method_source/lib/method_source/code_helpers.rb:71):3: syntax errors found (SyntaxError)
     #     1 | BEGIN{throw :valid}
     #     2 |   def hello_#{name}(*args)
     #   > 3 | 
     #       | ^ expected an `end` to close the `def` statement
     #   
     #       | ^ unexpected end of file, assuming it is closing the parent top level context
     #   ./lib/method_source/code_helpers.rb:71:in 'Kernel#eval'

Finished in 0.00674 seconds (files took 0.04986 seconds to load)
36 examples, 7 failures

Failed examples:

rspec './spec/method_source/code_helpers_spec.rb[1:2]' # MethodSource::CodeHelpers should not raise an error on broken lines: def\na\n(); end
rspec './spec/method_source/code_helpers_spec.rb[1:3]' # MethodSource::CodeHelpers should not raise an error on broken lines: p = <<FOO\nlots\nand\nlots of\nfoo\nFOO
rspec './spec/method_source/code_helpers_spec.rb[1:4]' # MethodSource::CodeHelpers should not raise an error on broken lines: [\n:lets,\n'list',\n[/nested/\n], things ]
rspec './spec/method_source/code_helpers_spec.rb[1:5]' # MethodSource::CodeHelpers should not raise an error on broken lines: abc =~ /hello\n/
rspec './spec/method_source/code_helpers_spec.rb[1:6]' # MethodSource::CodeHelpers should not raise an error on broken lines: issue = %W/\n343/
rspec './spec/method_source/code_helpers_spec.rb[1:9]' # MethodSource::CodeHelpers should not raise an error on broken lines: puts 1, 2,\n3
rspec ./spec/method_source_spec.rb:74 # MethodSource Methods should return source for an *_evaled method

Because of https://github.com/banister/method_source/blob/06f21c66380c64ff05c8031c0208eef240da0e83/lib/method_source/code_helpers.rb#L125-L131

Is there a better way with Prism to find "subsets of SyntaxErrors that can be fixed by adding more input to the buffer" than matching messages (which seems very brittle)?

eregon avatar Apr 25 '24 10:04 eregon

@kddnewton Any thoughts regarding that last sentence? IIRC IRB also wanted this predicate for syntax errors.

eregon avatar May 24 '24 10:05 eregon

To answer your question — there is not currently a way. I think that discussion is still taking place here: https://bugs.ruby-lang.org/issues/20024.

kddnewton avatar Sep 25 '24 19:09 kddnewton