Project

General

Profile

Feature #14938

Provide API to get same result as ruby -wc

Added by mtsmfm (Fumiaki Matsushima) 12 months ago. Updated 12 months 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) 12 months 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) 12 months ago

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

Updated by mtsmfm (Fumiaki Matsushima) 12 months 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) 12 months 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) 12 months 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) 12 months 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) 12 months 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