Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --editor-mode CLI option #12682

Merged
merged 1 commit into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/new_add_editor_mode_option.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#12682](https://github.com/rubocop/rubocop/issues/12682): Add `--editor-mode` CLI option. ([@koic][])
2 changes: 1 addition & 1 deletion docs/modules/ROOT/pages/configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ Style/PerlBackrefs:
==== `contextual`

This setting enables autocorrection when launched from the `rubocop` command, but it is not available through LSP.
e.g., `rubocop --lsp` or a program where `RuboCop::LSP.enable` has been applied.
e.g., `rubocop --lsp`, `rubocop --editor-mode`, or a program where `RuboCop::LSP.enable` has been applied.

Inspections via the command line are treated as code that has been finalized.

Expand Down
3 changes: 3 additions & 0 deletions docs/modules/ROOT/pages/usage/basic_usage.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,9 @@ $ rubocop --only Rails/Blank,Layout/HeredocIndentation,Naming/FileName
| `-s/--stdin`
| Pipe source from STDIN. This is useful for editor integration. Takes one argument, a 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.

| `--editor-mode`
| Optimize real-time feedback in editors, adjusting behaviors for editing experience. Editors that run RuboCop directly (e.g., by shelling out) encounter the same issues as with `--lsp`. This option is designed for such editors.

| `-S/--display-style-guide`
| Display style guide URLs in offense messages.

Expand Down
7 changes: 6 additions & 1 deletion lib/rubocop/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class CLI
STATUS_INTERRUPTED = Signal.list['INT'] + 128
DEFAULT_PARALLEL_OPTIONS = %i[
color config debug display_style_guide display_time display_only_fail_level_offenses
display_only_failed except extra_details fail_level fix_layout format
display_only_failed editor_mode except extra_details fail_level fix_layout format
ignore_disable_comments lint only only_guide_cops require safe
autocorrect safe_autocorrect autocorrect_all
].freeze
Expand Down Expand Up @@ -151,6 +151,7 @@ def parallel_by_default!

def act_on_options
set_options_to_config_loader
handle_editor_mode

@config_store.options_config = @options[:config] if @options[:config]
@config_store.force_default_config! if @options[:force_default_config]
Expand All @@ -174,6 +175,10 @@ def set_options_to_config_loader
ConfigLoader.ignore_unrecognized_cops = @options[:ignore_unrecognized_cops]
end

def handle_editor_mode
RuboCop::LSP.enable if @options[:editor_mode]
end

# rubocop:disable Metrics/CyclomaticComplexity
def handle_exiting_options
return unless Options::EXITING_OPTIONS.any? { |o| @options.key? o }
Expand Down
11 changes: 11 additions & 0 deletions lib/rubocop/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def add_check_options(opts) # rubocop:disable Metrics/AbcSize, Metrics/MethodLen
option(opts, '--ignore-unrecognized-cops')
option(opts, '--force-default-config')
option(opts, '-s', '--stdin FILE')
option(opts, '--editor-mode')
option(opts, '-P', '--[no-]parallel')
option(opts, '--raise-cop-error')
add_severity_option(opts)
Expand Down Expand Up @@ -369,6 +370,7 @@ def validate_compatibility # rubocop:disable Metrics/MethodLength
validate_display_only_failed
validate_display_only_failed_and_display_only_correctable
validate_display_only_correctable_and_autocorrect
validate_lsp_and_editor_mode
disable_parallel_when_invalid_option_combo

return if incompatible_options.size <= 1
Expand Down Expand Up @@ -416,6 +418,13 @@ def validate_display_only_failed_and_display_only_correctable
format('--display-only-failed cannot be used together with other display options.')
end

def validate_lsp_and_editor_mode
return if !@options.key?(:lsp) || !@options.key?(:editor_mode)
koic marked this conversation as resolved.
Show resolved Hide resolved

raise OptionArgumentError,
format('Do not specify `--editor-mode` as it is redundant in `--lsp`.')
end

def validate_autocorrect
if @options.key?(:safe_autocorrect) && @options.key?(:autocorrect_all)
message = Rainbow(<<~MESSAGE).red
Expand Down Expand Up @@ -609,6 +618,8 @@ module OptionsHelp
'parallel. Default is true.'],
stdin: ['Pipe source from STDIN, using FILE in offense',
'reports. This is useful for editor integration.'],
editor_mode: ['Optimize real-time feedback in editors,',
'adjusting behaviors for editing experience.'],
init: 'Generate a .rubocop.yml file in the current directory.',
server: ['If a server process has not been started yet, start',
'the server process and execute inspection with server.',
Expand Down
70 changes: 70 additions & 0 deletions spec/rubocop/cli/options_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2230,6 +2230,76 @@ def f
end
end

describe '--editor-mode' do
let(:target_file) { 'example.rb' }

before do
create_file(target_file, <<~RUBY)
def empty_method
end
RUBY

create_file('.rubocop.yml', <<~YAML)
AllCops:
SuggestExtensions: false
Layout/EmptyLineAfterMagicComment:
AutoCorrect: contextual
YAML
end

after { RuboCop::LSP.disable }

context 'when using `--editor-mode`' do
it 'registers an offense, but does not correct for `Layout/EmptyLineAfterMagicComment` with `AutoCorrect: contextual`' do
status_code = cli.run(['--editor-mode', '-a', '--only', 'Style/EmptyMethod', target_file])

expect(status_code).to eq(1)
expect($stderr.string).to eq('')
expect(File.read('example.rb')).to eq(<<~RUBY)
def empty_method
end
RUBY
expect($stdout.string).to eq(<<~RESULT)
Inspecting 1 file
C
Offenses:
example.rb:1:1: C: Style/EmptyMethod: Put empty method definitions on a single line.
def empty_method ...
^^^^^^^^^^^^^^^^
1 file inspected, 1 offense detected
RESULT
end
end

context 'when not using `--editor-mode`' do
it 'registers an offense and corrects for `Layout/EmptyLineAfterMagicComment` with `AutoCorrect: contextual`' do
status_code = cli.run(['-a', '--only', 'Style/EmptyMethod', target_file])

expect(status_code).to eq(0)
expect($stderr.string).to eq('')
expect(File.read('example.rb')).to eq(<<~RUBY)
def empty_method; end
RUBY
expect($stdout.string).to eq(<<~RESULT)
Inspecting 1 file
C
Offenses:
example.rb:1:1: C: [Corrected] Style/EmptyMethod: Put empty method definitions on a single line.
def empty_method ...
^^^^^^^^^^^^^^^^
1 file inspected, 1 offense detected, 1 offense corrected
RESULT
end
end
end

describe '--require', :restore_registry do
context 'when adding an extension' do
before do
Expand Down
9 changes: 9 additions & 0 deletions spec/rubocop/options_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ def abs(path)
files are present in the directory tree.
-s, --stdin FILE Pipe source from STDIN, using FILE in offense
reports. This is useful for editor integration.
--editor-mode Optimize real-time feedback in editors,
adjusting behaviors for editing experience.
-P, --[no-]parallel Use available CPUs to execute inspection in
parallel. Default is true.
--raise-cop-error Raise cop-related errors with cause and location.
Expand Down Expand Up @@ -262,6 +264,13 @@ def abs(path)
.to raise_error(RuboCop::OptionArgumentError, msg)
end

it 'rejects using `--lsp` with `--editor-mode`' do
msg = 'Do not specify `--editor-mode` as it is redundant in `--lsp`.'
expect do
options.parse %w[--lsp --editor-mode]
end.to raise_error(RuboCop::OptionArgumentError, msg)
end

it 'mentions all incompatible options when more than two are used' do
msg = 'Incompatible cli options: [:version, :verbose_version, :show_cops]'
expect { options.parse %w[-vV --show-cops] }
Expand Down