SublimeLinter / SublimeLinter-rubocop

SublimeLinter 3 plugin for Ruby, using rubocop.
MIT License
159 stars 40 forks source link

Define a minimal new RubyLinter #55

Closed kaste closed 5 years ago

kaste commented 6 years ago

Experiment: Define a new RubyLinter.

Given a cmd like rubocop --stdin ... it will by default assume rubocop is available on PATH and just execute it. If you set use_bundle_exec it will instead run bundle exec rubocop --stdin ...

A user can set executable. E.g. here/is/my/rubocop or ['here/is/ruby', '-s', 'rubocop'] in the linter settings.

The runtime env can be modified using the linter setting. E.g.

  "linters": {
     "rubocop": {
        "disable": false,
        // "executable": ...
        "env": {
            "PATH": "gems/bin/:$PATH"
        }
revolter commented 6 years ago

But wasn't --stdin part of the problem? As I said, passing that argument hangs the command. Or is the plugin passing the file differently? How can I try this PR directly in Sublime?

kaste commented 6 years ago

As I said, passing that argument hangs the command.

It doesn't hang the command. It waits for input on stdin. Use cat and piping on the shell.

How can I try this PR directly in Sublime?

revolter commented 6 years ago

It still doesn't work, I think it's a Sublime Linter problem. I tried fiddling with linter.py and nothing works. I even changed the command to ['/Users/revolt/.gems/bin/bundle', 'exec', '/Users/revolt/.gems/bin/rubocop'] with no success.

revolter commented 6 years ago

Changing it to only ['/Users/revolt/.gems/bin/rubocop'] still fails :|

/Library/Ruby/Site/2.3.0/rubygems.rb:271:in `find_spec_for_exe': can't find gem rubocop (>= 0.a) (Gem::GemNotFoundException)

How can it not find rubocop if I'm using the absolute path to the executable?!

kaste commented 6 years ago

In the Sublime console you can print the env using import os; os.environ. Maybe the environment within Sublime is different from your shell bc you do (source) stuff when running the shell. (GEM_HOME, GEM_PATH) Maybe you use another virtual environment machinery (rbenv etc.) Maybe you need to sudo install the gems.

I think when executing a command the only relevant variables are the command itself, the working dir and the env at that time. So if this works on your shell, it is important to closely take notes what the state actually is to make it work.

revolter commented 6 years ago

The only required env vars (AFAIK) are:

export GEM_HOME=~/.gems
export PATH=$PATH:$GEM_HOME/bin

and I added them using:

import os

if not 'GEM_HOME' in os.environ:
    os.environ['GEM_HOME'] = '~/.gems'

if not '$GEM_HOME/bin' in os.environ['PATH']:
    os.environ['PATH'] += ':$GEM_HOME/bin'

and it still doesn't work.

I also added:

from subprocess import check_output

print(os.environ)
print('Bundle version: ' + str(check_output(["/Users/revolt/.gems/bin/bundle", "--version"])))

to linter.py and it still crashes:

environ({..., 'PATH': '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:$GEM_HOME/bin', ..., 'GEM_HOME': '~/.gems', ...})
SublimeLinter: #12 __init__.py:1273: ERROR: Linter crashed.

Traceback (most recent call last):
  File "lint.backend in /Users/revolt/Library/Application Support/Sublime Text 3/Installed Packages/SublimeLinter.sublime-package", line 100, in execute_lint_task
  File "lint.linter in /Users/revolt/Library/Application Support/Sublime Text 3/Installed Packages/SublimeLinter.sublime-package", line 758, in lint
  File "lint.linter in /Users/revolt/Library/Application Support/Sublime Text 3/Installed Packages/SublimeLinter.sublime-package", line 485, in get_cmd
  File "lint.linter in /Users/revolt/Library/Application Support/Sublime Text 3/Installed Packages/SublimeLinter.sublime-package", line 498, in build_cmd
  File "/Users/revolt/Library/Application Support/Sublime Text 3/Packages/SublimeLinter-rubocop/linter.py", line 29, in context_sensitive_executable_path
    print('Bundle version: ' + str(check_output(["/Users/revolt/.gems/bin/bundle", "--version"])))
  File "./python3.3/subprocess.py", line 589, in check_output
subprocess.CalledProcessError: Command '['/Users/revolt/.gems/bin/bundle', '--version']' returned non-zero exit status 1

I don't know what can I do more.

kaste commented 6 years ago

😢

kaste commented 6 years ago

The only thing atm

os.environ['PATH'] += ':$GEM_HOME/bin'

I don't know if $GEM_HOME gets expanded here or if an absolute path is needed. (You don't run the program in a shell.) Dito with the '~'. You could try shell=True in your check_output test.

revolter commented 6 years ago

Will try with absolute paths tonight.

revolter commented 6 years ago

Still doesn't work.

joshmfrankel commented 5 years ago

I tried this branch out locally per comment here https://github.com/SublimeLinter/SublimeLinter-rubocop/issues/53#issuecomment-475668794. Here's the configuration I used:

    "rubocop": {
      "env": {
        "PATH": "~/.asdf/shims:$PATH"
      }
    }

Environment information

OS: Ubuntu 16.04 Sublime Text: 3.2 Rubocop: Managed by asdf

This branch fixed two issues for me:

  1. Instead of running /usr/bin/ruby -S rubocop the command is now correctly ran as rubocop
  2. --stdin now properly works by specifying the folder instead of file. Also fixes the previously error:
SublimeLinter: #21 linter.py:639      WARNING: rubocop output:
-s/--stdin requires exactly one path, relative to the root of the project. RuboCop will use this path to determine which cops are enabled (via eg. Include/Exclude), and so that certain cops like Naming/FileName can be checked.

I had a workaround for these issues by first explicitly defining which executable to run with:

"rubocop": {
  "executable": "~/.asdf/shims/rubocop",
}

Then branching off of master and creating a new setting to make --stdin optional with something like:

  if path:
    if settings.get('use_stdin', True):
      command += ['--stdin']

    command += [path, "--force-exclusion"]
    self.tempfile_suffix = None

return command

Given that this PR fixes both there's no need for such a change above. Nice work @kaste figuring this out. Also to note, I did not need the patch described here: https://github.com/SublimeLinter/SublimeLinter/pull/1509

And the final output from Sublime console with linting errors showing up again in panel

cat app/the_relative_dir/the_file_to_lint.rb | rubocop --format emacs --force-exclusion --stdin /home/josh/development/app/the_relative_dir
kaste commented 5 years ago

Closing after a simpler but similar #65 has been provided.