rubyide / vscode-ruby

Provides Ruby language and debugging support for Visual Studio Code
https://marketplace.visualstudio.com/items?itemName=rebornix.Ruby
MIT License
1.26k stars 286 forks source link

rubocop not using .rubocop.yml file #578

Open Zhorian opened 4 years ago

Zhorian commented 4 years ago

Your environment

Expected behavior

I'm expecting test/test_helper.rb to be ignored by rubocop based on my .rubocop.yml file. Confirmed config file is being used when running rubocop from the command line.

Actual behavior

I am still receiving linting errors on the for test/test_helper.rb

This and the next section should include screenshots, code samples, console output, etc. The more information we have to reproduce the better!

settings.json { "editor.formatOnSave": true, "editor.formatOnSaveTimeout": 5000, "powermode.enabled": true, "powermode.enableShake": false, "ruby.useLanguageServer": true, "ruby.lint": { "rubocop": true }, "ruby.format": "rubocop", "sync.gist": "d1b8c7400637948e668f4c6d174c5edb", "workbench.colorTheme": "Blueberry Banana", "workbench.iconTheme": "vscode-icons", }

.rubocop.yml `AllCops: TargetRubyVersion: 2.6.3 Exclude:

image

Zhorian commented 4 years ago

Interestingly this seems to occur when using Solargraph diagnostics too!

andrewmcodes commented 4 years ago

Try turning the bundler option on. I’m not sure if the gem will automatically find the config file in your directory instead of looking globally.

https://github.com/rubyide/vscode-ruby/blob/master/docs/linting.md#configuration-options

Zhorian commented 4 years ago

I've updated my ruby lint settings to below and the issue persists.

"ruby.lint": { "rubocop": { "command": "rubocop", "useBundler": true, } },

artm commented 4 years ago

"useBundler": true is ignored when "command" is given.

artm commented 4 years ago

Context

I had a similar problem but in a somewhat convoluted environment, which I was able to investigate and solve, but my solution is convoluted as well :-) Perhaps @Zhorian's situation is similar in some respect?

My VSCode runs on a windows host connecting via remote ssh extension to a linux developmen VM inside which ruby environments are run in docker containers with docker-compose, so VSCode doesn't have direct access to any ruby commands.

Solving the problem in my context

In order to help linter execute rubocop inside my environment I made a project specific wrapper script inside the project's bin directory and corresponding linter config:

    "ruby.lint": {
        "rubocop": {
            "command": "bin/vscode-rubocop"
        }
    },

My first attempt suffered from this issue (rubocop not respecting .rubocop.yml:

#!/bin/bash
docker-compose exec -T application rubocop "$@"

This happens because of the way linter calls the script (according to the output in the Output view:

Lint: executing bin/vscode-rubocop -s /home/artm/src/project/app/controllers/application_controller.rb -f json

current contents of the file is sent on the stdin (rubocop's -s option) along with the absolute path to the file on the VM's filesystem. But since rubocop is running in a container the same file is available under a different absolute path (/app/app/controllers/application_controller.rb which corresponds to the same relative path because the project directory is mounted to /app. So I adjusted the wrapper script to strip current path prefix from every argument:

#!/bin/bash
docker-compose exec -T application rubocop "${@#$(pwd)/}"

This made rubocop respect .rubocop.yml because now it knows the file path and can find the corresponding configuration file(s).

Suggestions for the extension config

    "ruby.lint": {
        "rubocop": {
            "command": "docker-compose exec -T spring spring rubocop",
            "relativeSourcePaths": true
        }
    },

It would also be nice if it was possible to reuse linter rubocop config in the ruby formatter config, or at least if it supported the same options. As far as I could figure out it is impossible to configure the formatter for my situation now.

P.S.

The final version of my wrapper script:

#!/bin/bash
docker-compose exec -T spring spring rubocop "${@#$(pwd)/}"

Which makes linter a bit faster. This relies on a spring server running inside a service called spring and spring-commands-rubocop being available in the project's bundle.

Zhorian commented 4 years ago

I resolved the issue. I added a .rubocop file (not .rubocop.yml) and added the following.

--force-exclusion

januszm commented 3 years ago

Is creating the .rubocop file with --force-exclusion the official solution? I ran into this problem with vscode ignoring local .rubocop.yml and so far it's the only solution that helps (I've also considered creating a bin/rubocop wrapper but it's simpler)

Zhorian commented 3 years ago

I think adding this to your .vscode/settings.json is the prescribed way of doing this. This is how I've done it in my recent project.

  "ruby.lint": {
    "rubocop": {
      "forceExclusion": true,
    }
  }
AlecRust commented 3 years ago

forceInclusion method no longer works for me or others, see https://github.com/rubyide/vscode-ruby/issues/227.

My schema.rb has Rubocop errors even though it's excluded in .rubocop.yml:

AllCops:
  NewCops: enable
  Exclude:
    - db/schema.rb
Zhorian commented 3 years ago

I had that exact same issue! I ended up doing this which might be a bit overkill

AllCops:
  Exclude:
    - "node_modules/**/*"
    - "tmp/**/*"
    - "vendor/**/*"
    - ".git/**/*"
    - "db/**/*"
    - bin/**/*
januszm commented 3 years ago

I just checked and indeed, none of the solutions (with .vscode/settings.json or .rubocop files) works if I combine AllCops exclusion with specific cop exclusion, like:

AllCops:
  Exclude:
    - vendor/**/*
    - db/schema.rb
    - db/migrate/*.rb
# ...
Metrics/BlockLength:
  Enabled: true
  Exclude:
    - spec/**/*
    - config/routes.rb

with the above configuration, rubocop is happy when I run it from shell, but complains about BlockLength in routes.rb in VsCode editor window

AlexVPopov commented 3 years ago

I can also confirm the issue occurs even with "forceExclusion": true. @Zhorian Could you, please, reopen the issue?

AlexVPopov commented 3 years ago

Hey @Zhorian , sorry, it seems that "useBundler": true was causing the problem on my side, no need to reopen the issue.

lobo-tuerto commented 3 years ago

I have this on my settings.json file for VSCode:

"ruby.lint": {
  "rubocop": true
},

And my .rubocop.yml is being ignored. Is there any way to specify which path the config file can be found? Or any pointers on how to configure it so it'll pick up the yml file at the project's root?


UPDATE:

I used @Zhorian code, and it seems to be working now:

"ruby.lint": {
  "rubocop": {
    "forceExclusion": true,
  }
}
Zhorian commented 2 years ago

It's stopped working for me now.

AlecRust commented 2 years ago

I think #742 may fix this which is pending release.

@Zhorian could you reopen this issue?

AlexWayfer commented 2 years ago

Is something blocking a new release? We can't use RuboCop in VSC almost for 2 years.

gregawoods commented 2 years ago

In order to help linter execute rubocop inside my environment I made a project specific wrapper script inside the project's bin directory and corresponding linter config:

    "ruby.lint": {
        "rubocop": {
            "command": "bin/vscode-rubocop"
        }
    },

@artm How did you get this wrapper script to be found with a relative path? Mine throws an error of unable to execute [snip] as the command could not be found.

It works if I use an absolute path to the script. However, I'm trying to set this up in a relative way so that it can be shared across users and environments.

I also tried using ${workspaceRoot} as described in https://github.com/rubyide/vscode-ruby/issues/187 but that didn't work either.

Would really love to get rubocop working in docker compose!

tgaeta commented 2 years ago

If you find that Rubocop works, but you're still getting warnings and tooltips in VS Code, try this:

"ruby.rubocop.suppressRubocopWarnings": true
scorphus commented 2 years ago

Sorry for the extra noise earlier.

I'm working on what is arguably my ugliest hack in recent times 😄 I'm not quite sure it works, but it seems to work for me.

First, create the following script anywhere on your PATH:

#!/usr/bin/env bash -li

arg_parts=(${@//\'/})
rubocop -s ${arg_parts[1]} -f json --force-exclusion

Then, use it as command:

    "ruby.lint": {
      "rubocop": {
        "command": "myrubocop"
      },

I hope it works for someone else too.

soumyaray commented 2 years ago

I'm having the same issue and I've tried everything in this thread except wrapping rubocop in my own script -- I just don't think that approach is suitable on collaborative projects. Is there an official way to resolve this issue yet?

benzado commented 2 years ago

I've just fixed my local setup using a shim script and I think I've found a clue nobody has mentioned in the earlier comments... vscode-ruby is calling my script with these arguments: -s '/absolute/path/to/file.rb' -f json

I thought that the absolute path was the issue, so I wrote a script similar to this one by @artm. But the workspace path wasn't being stripped off the front of the path... then I realized that the single quotes ' around the path are part of the argument string.

Normally, if you typed rubocop 'file.rb' at the command line, the parser would strip away the quotes and the running script would see file.rb as its first argument. But the vscode-ruby extension is wrapping the path with quotes and then, instead of running it through a shell, passing the quoted string directly via an exec function or something like it.

The net result is that even though RuboCop can find its config files and is smart enough to figure out relative vs absolute paths, an exclusion pattern like test/foo/* won't match a path string like 'test/foo/bar.rb' because test doesn't match 'test.

Here's the shim script I'm using:

#!/bin/sh
# called with args like: -s '/path/to/file.rb' -f json
source_path=${2#\'} # strip leading quote
source_path=${source_path%\'} # strip trailing quote
/path/to/bundle exec rubocop -s "$source_path" -f json

I'm using extension v0.28.1.

Surely enough, on line 61 of RuboCop.ts you can see that it's wrapping the pathname with single quotes. That was introduced by commit d432fee which was trying to support (incorrectly) spaces in paths.

That change was undone by commit 18d5a00, which was added to fix #719, which appears to be a duplicate of this issue.

That commit is on the main branch but hasn't been released yet.

Based on my research, I think this issue should be closed as fixed by PR #720. The problem is that the project is overdue for a release, because it doesn't have an active maintainer.

github-actions[bot] commented 2 years ago

This issue has not had activity for 30 days. It will be automatically closed in 30 days.

AlexWayfer commented 2 years ago

This issue is still an issue. Probably, this bot should be disabled due to #815.

ricardograca commented 1 year ago

According to my testing it seems that any exclusion pattern that points to a specific file name won't work. For example, if we have a file named file.rb with a Metrics/BlockLength linting error and I use this rule in .rubocop.yml, then it won't actually be ignored:

Metrics/BlockLength:
  Exclude: 
    - '**/file.rb'

But, if I move the file to the lib directory and change the exclusion pattern like so, the linting errors will be ignored:

Metrics/BlockLength:
  Exclude: 
    - '**/lib/*'

I can confirm that @benzado's conclusion is correct and #720 does indeed fix the issue, since I manually edited the file ~/.vscode/extensions/rebornix.ruby-0.28.1/dist/server/index.js replacing

`'${i.URI.parse(this.document.uri).fsPath}'`

with:

i.URI.parse(this.document.uri).fsPath

and single file exclusion patterns are now working (after restarting VSCode).

y-amadatsu commented 1 year ago

I made the same modification as @ricardograca and the .rubocop.yml setting is reflected. Thank you @ricardograca !

ricardograca commented 1 year ago

That was supposed to be only a test, but indeed it does the trick until we get a more permanent solution.

gregawoods commented 1 year ago

Worked for me too, I finally see rubocop ignoring Metrics/BlockLength in my rspec files. 🥳

m-o-e commented 1 year ago

The solution by @ricardograca worked for me as well. Thank you!

You can use this oneliner to apply his fix (VSCode must be restarted afterwards):

sed -i .bak "s/\`'\${i.URI.parse(this.document.uri).fsPath}'\`/i.URI.parse(this.document.uri).fsPath/g" ~/.vscode/extensions/rebornix.ruby-0.28.1/dist/server/index.js

It will save a backup of the original file to index.js.bak.

gregawoods commented 1 year ago

I've been using the solution here for a while and it's been good so far. I noticed this morning however that it isn't working with AllCops rules. For example, I'm now seeing BlockLength errors in routes.rb despite it being excluded.

This does not work:

AllCops:
  Exclude:
    - 'config/**/*'

But this works:

Metrics/BlockLength:
  Exclude:
    - 'config/**/*'

I wonder, when could we get at least the partial fix officially released?

mcelicalderon commented 1 year ago

Thank you, @ricardograca and @m-o-e! I can confirm https://github.com/rubyide/vscode-ruby/issues/578#issuecomment-1279970275 worked for me 🙌 at least for some cops. Not sure if I will run into something else as described in https://github.com/rubyide/vscode-ruby/issues/578#issuecomment-1315368920

github-actions[bot] commented 1 year ago

This issue has not had activity for 30 days. It will be automatically closed in 30 days.

AlexWayfer commented 1 year ago

This issue has not had activity for 30 days. It will be automatically closed in 30 days.

We're waiting for 2+ years, bots interfer, forcing to flood useless messages like this one.

severinraez commented 1 year ago

On Ubuntu, I had to adapt the command from @m-o-e to

sed -i.bak "s/\`'\${i.URI.parse(this.document.uri).fsPath}'\`/i.URI.parse(this.document.uri).fsPath/g" ~/.vscode/extensions/rebornix.ruby-0.28.1/dist/server/index.js

(removed the space between -i and .bak, might be a macOS vs linux issue).

januszm commented 1 year ago

On Ubuntu, I had to adapt the command from @m-o-e to (removed the space between -i and .bak, might be a macOS vs linux issue).

And here's the explanation why: https://unix.stackexchange.com/questions/281543/is-my-interpretation-of-sed-i-bak-x-d-some-file-correct