Project

General

Profile

Feature #14938

Provide API to get same result as ruby -wc

Added by mtsmfm (Fumiaki Matsushima) over 1 year ago. Updated over 1 year ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:88107]

Description

I'm the author of an implementation of Ruby Language Server.
Currently, it uses RubyVM::InstructionSequence.compile to get the result of ruby -wc and parses message and location by regexp.

https://github.com/mtsmfm/language_server-ruby/blob/v0.11.0/lib/language_server/linter/ruby_wc.rb#L30

Do you have any plan to provide API?

History

Updated by shevegen (Robert A. Heiler) over 1 year ago

This may also be useful for irb/pry add-ons, I think.

Perhaps Koichi-san can comment on the issue if he has time.

Updated by ko1 (Koichi Sasada) over 1 year ago

Good idea. Do you have an idea about API and implementation?
Maybe parse.y should be modified (== difficult).

Updated by mtsmfm (Fumiaki Matsushima) over 1 year ago

I want to get 3 things.

  1. Type (warning or error)
  2. Message
  3. Location

I think location interface should be the same as RubyVM::AST::Node

https://ruby-doc.org/core-2.6.0.preview2/RubyVM/AST/Node.html

My proposal is the following:

source = <<-RUBY
a = 1
RUBY

results = RubyVM::AST.lint(source) # I'm not sure about suitable class/module for this method
result = results.first
result.type
#=> warning
result.message
#=> assigned but unused variable - a
result.first_lineno
#=> 1 
result.last_lineno
#=> 1 
result.first_column
#=> 0
result.last_column
#=> 1 (or 5?)

Updated by nobu (Nobuyoshi Nakada) over 1 year ago

Why don't you use ripper?

#!/usr/bin/ruby
require 'ripper'
class Lint < Ripper
  def warn(*s)
    @results << [:warning, lineno, column, *s]
  end
  alias warning warn

  def results
    unless defined?(@results) and @results
      @results = []
      parse
    end
    @results
  end
end

$VERBOSE = true
results = Lint.new("def f;a = 0;end").results
p results
$ ruby lint.rb 
[[:warning, 1, 15, "assigned but unused variable - %s", "a"]]

Updated by mtsmfm (Fumiaki Matsushima) over 1 year ago

Hmm, I tried warn but it doesn't work in some case:

#!/usr/bin/ruby
require 'ripper'
require 'tempfile'

class Lint < Ripper
  def warn(*s)
    @results << [:warning, lineno, column, *s]
  end
  alias warning warn

  def results
    unless defined?(@results) and @results
      @results = []
      parse
    end
    @results
  end
end

data = DATA.read
result1 = nil

Tempfile.create do |file|
  file.write(data)
  file.flush
  result1 = `ruby -wc #{file.path}`
end

$VERBOSE = true
result2 = Lint.new(data).results.first

p result1
#=> /tmp/20180729-457-smihk6:1: warning: ambiguous first argument; put parentheses or a space even after `/' operator
#=> "Syntax OK\n"
p result2
#=> nil
__END__
a /#{

}/

In addition,

  • How can I get the range of code instead of lineno and column only?
  • Is there any way to detect syntax error?
    • It seems Ripper#compile_error doesn't work
#!/usr/bin/ruby
require 'ripper'
require 'tempfile'

class Lint < Ripper
  def compile_error(*s)
    @results << [:error, lineno, column, *s]
  end

  def results
    unless defined?(@results) and @results
      @results = []
      parse
    end
    @results
  end
end

data = DATA.read
result1 = nil

Tempfile.create do |file|
  file.write(data)
  file.flush
  result1 = `ruby -wc #{file.path}`
end

$VERBOSE = true
result2 = Lint.new(data).results.first

p result1
#=> /tmp/20180729-461-1wcbfr4:1: syntax error, unexpected end-of-input
#=> ""
p result2
#=> nil
__END__
def

Updated by nobu (Nobuyoshi Nakada) over 1 year ago

mtsmfm (Fumiaki Matsushima) wrote:

#=> /tmp/20180729-457-smihk6:1: warning: ambiguous first argument; put parentheses or a space even after `/' operator

This warning dispatches on_arg_ambiguous method.

  • How can I get the range of code instead of lineno and column only?

No way right now.
I think you can propose new methods for them.

#=> /tmp/20180729-461-1wcbfr4:1: syntax error, unexpected end-of-input

It dispatches on_parse_error method.

Updated by mtsmfm (Fumiaki Matsushima) over 1 year ago

This warning dispatches on_arg_ambiguous method.

It dispatches on_parse_error method.

How can I find the list of all events for warning and compile error?
When should I use compile_error?
https://docs.ruby-lang.org/en/2.5.0/Ripper.html#method-i-compile_error

I think you can propose new methods for them.

You meant adding new methods to Ripper, right?
If Ripper can have first_lineno, last_lineno, first_ column and last_ column, it's enough for me for now.

Also available in: Atom PDF