Skip to content
This repository was archived by the owner on Jul 31, 2023. It is now read-only.
This repository was archived by the owner on Jul 31, 2023. It is now read-only.

Wrong file path passed to RuboCop and Reek #719

Closed
@FooBarWidget

Description

@FooBarWidget

Your environment

  • vscode-ruby version: 0.28.1, and also commit 7b5b602
  • Ruby version: 2.7.2
  • Ruby version manager (if any): RVM
  • VS Code version: 1.54.3
  • Operating System: macOS Catalina
  • Using language server? (eg useLanguageServer is true in your configuration?) yes

Expected behavior

RuboCop is run with these arguments:

[
  "bundle",
  "exec",
  "rubocop",
  "-s",
  "/path-to-file.rb",
  "-f",
  "json"
]

Reek is run with these arguments:

[
  "bundle",
  "exec",
  "reek",
  "-f",
  "json",
  "--stdin-filename",
  "/path-to-file.rb"
]

Actual behavior

RuboCop is run with these arguments:

[
  "bundle",
  "exec",
  "rubocop",
  "-s",
  "'/path-to-file.rb'",  // <--- note the extraneous single quotes!
  "-f",
  "json"
]

Reek is run with these arguments:

[
  "bundle",
  "exec",
  "reek",
  "-f",
  "json",
  "--stdin-filename",
  "'/path-to-file.rb'"    // <--- note the extraneous single quotes!
]

To reproduce:

  1. Create a shell script ~/fake-rubocop that prints the exact arguments passed:

    #!/bin/sh
    set -x
    exec bundle exec rubocop "$@"

    Make sure to chmod +x it.

  2. Create a shell script ~/fake-reek that prints the exact arguments passed:

    #!/bin/sh
    set -x
    exec bundle exec reek "$@"

    Make sure to chmod +x it.

  3. Use this configuration:

    "ruby.useLanguageServer": true,
    "ruby.lint": {
        "rubocop": {
            "command": "/path-to-home-directory/fake-rubocop"
        },
        "reek": {
            "command": "/path-to-home-directory/fake-reek"
        }
    },
  4. Open a Ruby project directory. Inside that project directory, open a random Ruby file.

  5. In the Ruby Language Server output, observe that fake-rubocop logs this:

    + exec bundle exec rubocop -s ''\''/path-to-file.rb'\''' -f json
    

    We expect no extraneous quotes:

    + exec bundle exec rubocop -s /path-to-file -f json
    
  6. In the Ruby Language Server output, observe that fake-reek logs this:

    + exec bundle exec reek -f json --stdin-filename ''\''/path-to-file.rb'\'''
    

    We expect no extraneous quotes:

    + exec bundle exec reek -f json --stdin-filename /path-to-file.rb
    

Comments

Because of the extraneous quotes, we pass invalid filenames to RuboCop and Reek.

I don't know whether this causes problems for Reek, but it does cause problems for RuboCop: see #227. Normally, RuboCop checks each level of parent directory in the input file's path, in search for a .rubocop.yml. But because we pass an invalid filename, RuboCop can't find a .rubocop.yml, and ends up ignoring the .rubocop.yml that the project has.

The extraneous quotes are deliberately inserted by the code:

  • In packages/language-server-ruby/src/linters/RuboCop.ts:

    let args = ['-s', `'${documentPath.fsPath}'`, '-f', 'json'];
  • In packages/language-server-ruby/src/linters/Reek.ts:

    return ['-f', 'json', '--stdin-filename', `'${documentPath.fsPath}'`];

I suspect that the author meant to prevent any issues with spaces in filenames. However, Linters are executed through cross-spawn, which doesn't execute commands through a shell. There should be no problems with spaces in filenames: each element in the argument array represents exactly one argument, with no shell trying to split up filenames by space.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions