rubocop 1.30.0 → 1.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -2
- data/config/default.yml +41 -8
- data/config/obsoletion.yml +2 -0
- data/exe/rubocop +15 -7
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +3 -3
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_loader.rb +1 -0
- data/lib/rubocop/config_validator.rb +9 -5
- data/lib/rubocop/cop/base.rb +4 -0
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_filename.rb +4 -4
- data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -2
- data/lib/rubocop/cop/corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +3 -3
- data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +1 -1
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +31 -16
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -1
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/require_mfa.rb +20 -20
- data/lib/rubocop/cop/generator.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -5
- data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +25 -4
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +4 -4
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +9 -9
- data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +9 -9
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +27 -27
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +17 -11
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +49 -10
- data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +68 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +130 -0
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +10 -10
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -3
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +7 -7
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +51 -0
- data/lib/rubocop/cop/lint/interpolation_check.rb +1 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -0
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +122 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +3 -3
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +5 -5
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +2 -2
- data/lib/rubocop/cop/lint/struct_new_override.rb +2 -2
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +44 -0
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +41 -12
- data/lib/rubocop/cop/mixin/range_help.rb +7 -3
- data/lib/rubocop/cop/naming/accessor_method_name.rb +3 -1
- data/lib/rubocop/cop/naming/variable_number.rb +17 -17
- data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
- data/lib/rubocop/cop/style/and_or.rb +8 -8
- data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +4 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -0
- data/lib/rubocop/cop/style/empty_else.rb +10 -10
- data/lib/rubocop/cop/style/empty_method.rb +16 -1
- data/lib/rubocop/cop/style/encoding.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/fetch_env_var.rb +9 -2
- data/lib/rubocop/cop/style/format_string_token.rb +48 -17
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +8 -6
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -1
- data/lib/rubocop/cop/style/hash_except.rb +88 -8
- data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
- data/lib/rubocop/cop/style/implicit_runtime_error.rb +2 -2
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +1 -1
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/missing_else.rb +24 -24
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -2
- data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -3
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +1 -3
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +19 -7
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/not.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +1 -1
- data/lib/rubocop/cop/style/redundant_return.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/rescue_standard_error.rb +10 -10
- data/lib/rubocop/cop/style/safe_navigation.rb +3 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
- data/lib/rubocop/cop/style/string_concatenation.rb +5 -6
- data/lib/rubocop/cop/style/struct_inheritance.rb +2 -2
- data/lib/rubocop/cop/style/swap_values.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/cop/style/unpack_first.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cops_documentation_generator.rb +18 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -5
- data/lib/rubocop/formatter/formatter_set.rb +20 -19
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +15 -2
- data/lib/rubocop/formatter/html_formatter.rb +0 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +2 -0
- data/lib/rubocop/formatter/simple_text_formatter.rb +6 -7
- data/lib/rubocop/formatter.rb +31 -0
- data/lib/rubocop/options.rb +25 -2
- data/lib/rubocop/rake_task.rb +30 -9
- data/lib/rubocop/runner.rb +2 -2
- data/lib/rubocop/server/cache.rb +109 -0
- data/lib/rubocop/server/cli.rb +104 -0
- data/lib/rubocop/server/client_command/base.rb +44 -0
- data/lib/rubocop/server/client_command/exec.rb +59 -0
- data/lib/rubocop/server/client_command/restart.rb +25 -0
- data/lib/rubocop/server/client_command/start.rb +43 -0
- data/lib/rubocop/server/client_command/status.rb +28 -0
- data/lib/rubocop/server/client_command/stop.rb +31 -0
- data/lib/rubocop/server/client_command.rb +26 -0
- data/lib/rubocop/server/core.rb +79 -0
- data/lib/rubocop/server/errors.rb +23 -0
- data/lib/rubocop/server/helper.rb +34 -0
- data/lib/rubocop/server/server_command/base.rb +50 -0
- data/lib/rubocop/server/server_command/exec.rb +34 -0
- data/lib/rubocop/server/server_command/stop.rb +24 -0
- data/lib/rubocop/server/server_command.rb +21 -0
- data/lib/rubocop/server/socket_reader.rb +65 -0
- data/lib/rubocop/server.rb +53 -0
- data/lib/rubocop/version.rb +15 -8
- data/lib/rubocop.rb +7 -26
- metadata +42 -5
- data/lib/rubocop/cop/gemspec/date_assignment.rb +0 -49
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'colorizable'
|
4
|
-
require_relative 'text_util'
|
5
4
|
|
6
5
|
module RuboCop
|
7
6
|
module Formatter
|
@@ -63,7 +62,7 @@ module RuboCop
|
|
63
62
|
rainbow,
|
64
63
|
# :safe_autocorrect is a derived option based on several command-line
|
65
64
|
# arguments - see Rubocop::Options#add_autocorrection_options
|
66
|
-
|
65
|
+
safe_autocorrect: @options[:safe_autocorrect])
|
67
66
|
|
68
67
|
output.puts
|
69
68
|
output.puts report.summary
|
@@ -110,22 +109,22 @@ module RuboCop
|
|
110
109
|
# rubocop:disable Metrics/ParameterLists
|
111
110
|
def initialize(
|
112
111
|
file_count, offense_count, correction_count, correctable_count, rainbow,
|
113
|
-
|
112
|
+
safe_autocorrect: false
|
114
113
|
)
|
115
114
|
@file_count = file_count
|
116
115
|
@offense_count = offense_count
|
117
116
|
@correction_count = correction_count
|
118
117
|
@correctable_count = correctable_count
|
119
118
|
@rainbow = rainbow
|
120
|
-
@
|
119
|
+
@safe_autocorrect = safe_autocorrect
|
121
120
|
end
|
122
121
|
# rubocop:enable Metrics/ParameterLists
|
123
122
|
|
124
123
|
def summary
|
125
124
|
if @correction_count.positive?
|
126
125
|
if @correctable_count.positive?
|
127
|
-
"#{files} inspected, #{offenses} detected, #{corrections} corrected,"\
|
128
|
-
"
|
126
|
+
"#{files} inspected, #{offenses} detected, #{corrections} corrected, " \
|
127
|
+
"#{correctable}"
|
129
128
|
else
|
130
129
|
"#{files} inspected, #{offenses} detected, #{corrections} corrected"
|
131
130
|
end
|
@@ -159,7 +158,7 @@ module RuboCop
|
|
159
158
|
end
|
160
159
|
|
161
160
|
def correctable
|
162
|
-
if @
|
161
|
+
if @safe_autocorrect
|
163
162
|
text = pluralize(@correctable_count, 'more offense')
|
164
163
|
"#{colorize(text, :yellow)} can be corrected with `rubocop -A`"
|
165
164
|
else
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Formatter
|
5
|
+
require_relative 'formatter/text_util'
|
6
|
+
|
7
|
+
require_relative 'formatter/base_formatter'
|
8
|
+
require_relative 'formatter/simple_text_formatter'
|
9
|
+
# relies on simple text
|
10
|
+
require_relative 'formatter/clang_style_formatter'
|
11
|
+
require_relative 'formatter/disabled_config_formatter'
|
12
|
+
require_relative 'formatter/emacs_style_formatter'
|
13
|
+
require_relative 'formatter/file_list_formatter'
|
14
|
+
require_relative 'formatter/fuubar_style_formatter'
|
15
|
+
require_relative 'formatter/git_hub_actions_formatter'
|
16
|
+
require_relative 'formatter/html_formatter'
|
17
|
+
require_relative 'formatter/json_formatter'
|
18
|
+
require_relative 'formatter/junit_formatter'
|
19
|
+
require_relative 'formatter/markdown_formatter'
|
20
|
+
require_relative 'formatter/offense_count_formatter'
|
21
|
+
require_relative 'formatter/progress_formatter'
|
22
|
+
require_relative 'formatter/quiet_formatter'
|
23
|
+
require_relative 'formatter/tap_formatter'
|
24
|
+
require_relative 'formatter/worst_offenders_formatter'
|
25
|
+
require_relative 'formatter/pacman_formatter'
|
26
|
+
# relies on progress formatter
|
27
|
+
require_relative 'formatter/auto_gen_config_formatter'
|
28
|
+
|
29
|
+
require_relative 'formatter/formatter_set'
|
30
|
+
end
|
31
|
+
end
|
data/lib/rubocop/options.rb
CHANGED
@@ -63,6 +63,7 @@ module RuboCop
|
|
63
63
|
|
64
64
|
add_check_options(opts)
|
65
65
|
add_cache_options(opts)
|
66
|
+
add_server_options(opts)
|
66
67
|
add_output_options(opts)
|
67
68
|
add_autocorrection_options(opts)
|
68
69
|
add_config_generation_options(opts)
|
@@ -129,6 +130,7 @@ module RuboCop
|
|
129
130
|
end
|
130
131
|
end
|
131
132
|
|
133
|
+
# rubocop:todo Naming/InclusiveLanguage
|
132
134
|
# the autocorrect command-line arguments map to the autocorrect @options values like so:
|
133
135
|
# :fix_layout :autocorrect :safe_autocorrect :autocorrect_all
|
134
136
|
# -x, --fix-layout true true - -
|
@@ -156,6 +158,7 @@ module RuboCop
|
|
156
158
|
option(opts, '--disable-uncorrectable')
|
157
159
|
end
|
158
160
|
end
|
161
|
+
# rubocop:enable Naming/InclusiveLanguage
|
159
162
|
|
160
163
|
def add_config_generation_options(opts)
|
161
164
|
section(opts, 'Config Generation') do
|
@@ -201,6 +204,16 @@ module RuboCop
|
|
201
204
|
end
|
202
205
|
end
|
203
206
|
|
207
|
+
def add_server_options(opts)
|
208
|
+
section(opts, 'Server Options') do
|
209
|
+
option(opts, '--[no-]server')
|
210
|
+
option(opts, '--restart-server')
|
211
|
+
option(opts, '--start-server')
|
212
|
+
option(opts, '--stop-server')
|
213
|
+
option(opts, '--server-status')
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
204
217
|
def add_additional_modes(opts)
|
205
218
|
section(opts, 'Additional Modes') do
|
206
219
|
option(opts, '-L', '--list-target-files')
|
@@ -226,7 +239,7 @@ module RuboCop
|
|
226
239
|
end
|
227
240
|
|
228
241
|
def handle_deprecated_option(old_option, new_option)
|
229
|
-
warn "#{old_option} is deprecated; use #{new_option}"
|
242
|
+
warn rainbow.wrap("#{old_option} is deprecated; use #{new_option} instead.").yellow
|
230
243
|
@options[long_opt_symbol([new_option])] = @options.delete(long_opt_symbol([old_option]))
|
231
244
|
end
|
232
245
|
|
@@ -569,7 +582,17 @@ module RuboCop
|
|
569
582
|
'parallel. Default is true.'],
|
570
583
|
stdin: ['Pipe source from STDIN, using FILE in offense',
|
571
584
|
'reports. This is useful for editor integration.'],
|
572
|
-
init: 'Generate a .rubocop.yml file in the current directory.'
|
585
|
+
init: 'Generate a .rubocop.yml file in the current directory.',
|
586
|
+
server: ['If a server process has not been started yet, start',
|
587
|
+
'the server process and execute inspection with server.',
|
588
|
+
'Default is false.',
|
589
|
+
'You can specify the server host and port with the',
|
590
|
+
'$RUBOCOP_SERVER_HOST and the $RUBOCOP_SERVER_PORT',
|
591
|
+
'environment variables.'],
|
592
|
+
restart_server: 'Restart server process.',
|
593
|
+
start_server: 'Start server process.',
|
594
|
+
stop_server: 'Stop server process.',
|
595
|
+
server_status: 'Show server status.'
|
573
596
|
}.freeze
|
574
597
|
end
|
575
598
|
end
|
data/lib/rubocop/rake_task.rb
CHANGED
@@ -32,6 +32,15 @@ module RuboCop
|
|
32
32
|
|
33
33
|
private
|
34
34
|
|
35
|
+
def perform(option)
|
36
|
+
options = full_options.unshift(option)
|
37
|
+
# `parallel` will automatically be removed from the options internally.
|
38
|
+
# This is a nice to have to suppress the warning message
|
39
|
+
# about --parallel and --autocorrect not being compatible.
|
40
|
+
options.delete('--parallel')
|
41
|
+
run_cli(verbose, options)
|
42
|
+
end
|
43
|
+
|
35
44
|
def run_cli(verbose, options)
|
36
45
|
# We lazy-load RuboCop so that the task doesn't dramatically impact the
|
37
46
|
# load time of your Rakefile.
|
@@ -60,19 +69,31 @@ module RuboCop
|
|
60
69
|
@formatters = []
|
61
70
|
end
|
62
71
|
|
63
|
-
def setup_subtasks(name, *args, &task_block)
|
72
|
+
def setup_subtasks(name, *args, &task_block) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
64
73
|
namespace(name) do
|
65
|
-
|
74
|
+
# rubocop:todo Naming/InclusiveLanguage
|
75
|
+
task(:auto_correct, *args) do
|
76
|
+
warn Rainbow(
|
77
|
+
'rubocop:auto_correct task is deprecated; ' \
|
78
|
+
'use rubocop:autocorrect task or rubocop:autocorrect_all task instead.'
|
79
|
+
).yellow
|
80
|
+
::Rake::Task['rubocop:autocorrect'].invoke
|
81
|
+
end
|
82
|
+
# rubocop:enable Naming/InclusiveLanguage
|
83
|
+
|
84
|
+
desc "Autocorrect RuboCop offenses (only when it's safe)."
|
85
|
+
task(:autocorrect, *args) do |_, task_args|
|
86
|
+
RakeFileUtils.verbose(verbose) do
|
87
|
+
yield(*[self, task_args].slice(0, task_block.arity)) if task_block
|
88
|
+
perform('--autocorrect')
|
89
|
+
end
|
90
|
+
end
|
66
91
|
|
67
|
-
|
92
|
+
desc 'Autocorrect RuboCop offenses (safe and unsafe).'
|
93
|
+
task(:autocorrect_all, *args) do |_, task_args|
|
68
94
|
RakeFileUtils.verbose(verbose) do
|
69
95
|
yield(*[self, task_args].slice(0, task_block.arity)) if task_block
|
70
|
-
|
71
|
-
# `parallel` will automatically be removed from the options internally.
|
72
|
-
# This is a nice to have to suppress the warning message
|
73
|
-
# about --parallel and --autocorrect not being compatible.
|
74
|
-
options.delete('--parallel')
|
75
|
-
run_cli(verbose, options)
|
96
|
+
perform('--autocorrect-all')
|
76
97
|
end
|
77
98
|
end
|
78
99
|
end
|
data/lib/rubocop/runner.rb
CHANGED
@@ -382,7 +382,7 @@ module RuboCop
|
|
382
382
|
if @options[:display_only_fail_level_offenses]
|
383
383
|
offenses.select { |o| considered_failure?(o) }
|
384
384
|
elsif @options[:display_only_safe_correctable]
|
385
|
-
offenses.select { |o|
|
385
|
+
offenses.select { |o| supports_safe_autocorrect?(o) }
|
386
386
|
elsif @options[:display_only_correctable]
|
387
387
|
offenses.select(&:correctable?)
|
388
388
|
else
|
@@ -390,7 +390,7 @@ module RuboCop
|
|
390
390
|
end
|
391
391
|
end
|
392
392
|
|
393
|
-
def
|
393
|
+
def supports_safe_autocorrect?(offense)
|
394
394
|
cop_class = Cop::Registry.global.find_by_cop_name(offense.cop_name)
|
395
395
|
default_cfg = default_config(offense.cop_name)
|
396
396
|
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
#
|
6
|
+
# This code is based on https://github.com/fohte/rubocop-daemon.
|
7
|
+
#
|
8
|
+
# Copyright (c) 2018 Hayato Kawai
|
9
|
+
#
|
10
|
+
# The MIT License (MIT)
|
11
|
+
#
|
12
|
+
# https://github.com/fohte/rubocop-daemon/blob/master/LICENSE.txt
|
13
|
+
#
|
14
|
+
module RuboCop
|
15
|
+
module Server
|
16
|
+
# Caches the states of server process.
|
17
|
+
# @api private
|
18
|
+
class Cache
|
19
|
+
GEMFILE_NAMES = %w[Gemfile gems.rb].freeze
|
20
|
+
|
21
|
+
class << self
|
22
|
+
# Searches for Gemfile or gems.rb in the current dir or any parent dirs
|
23
|
+
def project_dir
|
24
|
+
current_dir = Dir.pwd
|
25
|
+
while current_dir != '/'
|
26
|
+
return current_dir if GEMFILE_NAMES.any? do |gemfile|
|
27
|
+
File.exist?(File.join(current_dir, gemfile))
|
28
|
+
end
|
29
|
+
|
30
|
+
current_dir = File.expand_path('..', current_dir)
|
31
|
+
end
|
32
|
+
# If we can't find a Gemfile, just use the current directory
|
33
|
+
Dir.pwd
|
34
|
+
end
|
35
|
+
|
36
|
+
def project_dir_cache_key
|
37
|
+
@project_dir_cache_key ||= project_dir[1..].tr('/', '+')
|
38
|
+
end
|
39
|
+
|
40
|
+
def dir
|
41
|
+
cache_path = File.expand_path('~/.cache/rubocop_cache/server')
|
42
|
+
Pathname.new(File.join(cache_path, project_dir_cache_key)).tap do |d|
|
43
|
+
d.mkpath unless d.exist?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def port_path
|
48
|
+
dir.join('port')
|
49
|
+
end
|
50
|
+
|
51
|
+
def token_path
|
52
|
+
dir.join('token')
|
53
|
+
end
|
54
|
+
|
55
|
+
def pid_path
|
56
|
+
dir.join('pid')
|
57
|
+
end
|
58
|
+
|
59
|
+
def lock_path
|
60
|
+
dir.join('lock')
|
61
|
+
end
|
62
|
+
|
63
|
+
def status_path
|
64
|
+
dir.join('status')
|
65
|
+
end
|
66
|
+
|
67
|
+
def version_path
|
68
|
+
dir.join('version')
|
69
|
+
end
|
70
|
+
|
71
|
+
def pid_running?
|
72
|
+
Process.kill(0, pid_path.read.to_i) == 1
|
73
|
+
rescue Errno::ESRCH
|
74
|
+
false
|
75
|
+
end
|
76
|
+
|
77
|
+
def acquire_lock
|
78
|
+
lock_file = File.open(lock_path, File::CREAT)
|
79
|
+
# flock returns 0 if successful, and false if not.
|
80
|
+
flock_result = lock_file.flock(File::LOCK_EX | File::LOCK_NB)
|
81
|
+
yield flock_result != false
|
82
|
+
ensure
|
83
|
+
lock_file.flock(File::LOCK_UN)
|
84
|
+
lock_file.close
|
85
|
+
end
|
86
|
+
|
87
|
+
def write_port_and_token_files(port:, token:)
|
88
|
+
port_path.write(port)
|
89
|
+
token_path.write(token)
|
90
|
+
end
|
91
|
+
|
92
|
+
def write_pid_file
|
93
|
+
pid_path.write(Process.pid)
|
94
|
+
yield
|
95
|
+
ensure
|
96
|
+
dir.rmtree
|
97
|
+
end
|
98
|
+
|
99
|
+
def write_status_file(status)
|
100
|
+
status_path.write(status)
|
101
|
+
end
|
102
|
+
|
103
|
+
def write_version_file(version)
|
104
|
+
version_path.write(version)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'rainbow'
|
5
|
+
|
6
|
+
#
|
7
|
+
# This code is based on https://github.com/fohte/rubocop-daemon.
|
8
|
+
#
|
9
|
+
# Copyright (c) 2018 Hayato Kawai
|
10
|
+
#
|
11
|
+
# The MIT License (MIT)
|
12
|
+
#
|
13
|
+
# https://github.com/fohte/rubocop-daemon/blob/master/LICENSE.txt
|
14
|
+
#
|
15
|
+
module RuboCop
|
16
|
+
module Server
|
17
|
+
# The CLI is a class responsible of handling server command line interface logic.
|
18
|
+
# @api private
|
19
|
+
class CLI
|
20
|
+
# Same exit status value as `RuboCop::CLI`.
|
21
|
+
STATUS_SUCCESS = 0
|
22
|
+
STATUS_ERROR = 2
|
23
|
+
|
24
|
+
SERVER_OPTIONS = %w[
|
25
|
+
--server --no-server --server-status --restart-server --start-server --stop-server
|
26
|
+
].freeze
|
27
|
+
EXCLUSIVE_OPTIONS = (SERVER_OPTIONS - %w[--server --no-server]).freeze
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@exit = false
|
31
|
+
end
|
32
|
+
|
33
|
+
def run(argv = ARGV)
|
34
|
+
unless Server.support_server?
|
35
|
+
return error('RuboCop server is not supported by this Ruby.') if use_server_option?(argv)
|
36
|
+
|
37
|
+
return STATUS_SUCCESS
|
38
|
+
end
|
39
|
+
|
40
|
+
deleted_server_arguments = delete_server_argument_from(argv)
|
41
|
+
|
42
|
+
if deleted_server_arguments.size >= 2
|
43
|
+
return error("#{deleted_server_arguments.join(', ')} cannot be specified together.")
|
44
|
+
end
|
45
|
+
|
46
|
+
server_command = deleted_server_arguments.first
|
47
|
+
|
48
|
+
if EXCLUSIVE_OPTIONS.include?(server_command) && argv.count >= 2
|
49
|
+
return error("#{server_command} cannot be combined with other options.")
|
50
|
+
end
|
51
|
+
|
52
|
+
run_command(server_command)
|
53
|
+
|
54
|
+
STATUS_SUCCESS
|
55
|
+
end
|
56
|
+
|
57
|
+
def exit?
|
58
|
+
@exit
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength:
|
64
|
+
def run_command(server_command)
|
65
|
+
case server_command
|
66
|
+
when '--server'
|
67
|
+
Server::ClientCommand::Start.new.run unless Server.running?
|
68
|
+
when '--no-server'
|
69
|
+
Server::ClientCommand::Stop.new.run if Server.running?
|
70
|
+
when '--restart-server'
|
71
|
+
@exit = true
|
72
|
+
Server::ClientCommand::Restart.new.run
|
73
|
+
when '--start-server'
|
74
|
+
@exit = true
|
75
|
+
Server::ClientCommand::Start.new.run
|
76
|
+
when '--stop-server'
|
77
|
+
@exit = true
|
78
|
+
Server::ClientCommand::Stop.new.run
|
79
|
+
when '--server-status'
|
80
|
+
@exit = true
|
81
|
+
Server::ClientCommand::Status.new.run
|
82
|
+
end
|
83
|
+
end
|
84
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength:
|
85
|
+
|
86
|
+
def delete_server_argument_from(all_arguments)
|
87
|
+
SERVER_OPTIONS.each_with_object([]) do |server_option, server_arguments|
|
88
|
+
server_arguments << all_arguments.delete(server_option)
|
89
|
+
end.compact
|
90
|
+
end
|
91
|
+
|
92
|
+
def use_server_option?(argv)
|
93
|
+
(argv & SERVER_OPTIONS).any?
|
94
|
+
end
|
95
|
+
|
96
|
+
def error(message)
|
97
|
+
@exit = true
|
98
|
+
warn Rainbow(message).red
|
99
|
+
|
100
|
+
STATUS_ERROR
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'shellwords'
|
4
|
+
require 'socket'
|
5
|
+
|
6
|
+
#
|
7
|
+
# This code is based on https://github.com/fohte/rubocop-daemon.
|
8
|
+
#
|
9
|
+
# Copyright (c) 2018 Hayato Kawai
|
10
|
+
#
|
11
|
+
# The MIT License (MIT)
|
12
|
+
#
|
13
|
+
# https://github.com/fohte/rubocop-daemon/blob/master/LICENSE.txt
|
14
|
+
#
|
15
|
+
module RuboCop
|
16
|
+
module Server
|
17
|
+
module ClientCommand
|
18
|
+
# Abstract base class for server client command.
|
19
|
+
# @api private
|
20
|
+
class Base
|
21
|
+
def run
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def send_request(command:, args: [], body: '')
|
28
|
+
TCPSocket.open('127.0.0.1', Cache.port_path.read) do |socket|
|
29
|
+
socket.puts [Cache.token_path.read, Dir.pwd, command, *args].shelljoin
|
30
|
+
socket.write body
|
31
|
+
socket.close_write
|
32
|
+
$stdout.write socket.read(4096) until socket.eof?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def check_running_server
|
37
|
+
Server.running?.tap do |running|
|
38
|
+
warn 'RuboCop server is not running.' unless running
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This code is based on https://github.com/fohte/rubocop-daemon.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2018 Hayato Kawai
|
7
|
+
#
|
8
|
+
# The MIT License (MIT)
|
9
|
+
#
|
10
|
+
# https://github.com/fohte/rubocop-daemon/blob/master/LICENSE.txt
|
11
|
+
#
|
12
|
+
module RuboCop
|
13
|
+
module Server
|
14
|
+
module ClientCommand
|
15
|
+
# This class is a client command to execute server process.
|
16
|
+
# @api private
|
17
|
+
class Exec < Base
|
18
|
+
def run
|
19
|
+
ensure_server!
|
20
|
+
Cache.status_path.delete if Cache.status_path.file?
|
21
|
+
send_request(
|
22
|
+
command: 'exec',
|
23
|
+
args: ARGV.dup,
|
24
|
+
body: $stdin.tty? ? '' : $stdin.read
|
25
|
+
)
|
26
|
+
status
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def ensure_server!
|
32
|
+
if incompatible_version?
|
33
|
+
puts 'RuboCop version incompatibility found, RuboCop server restarting...'
|
34
|
+
ClientCommand::Stop.new.run
|
35
|
+
elsif check_running_server
|
36
|
+
return
|
37
|
+
end
|
38
|
+
|
39
|
+
ClientCommand::Start.new.run
|
40
|
+
end
|
41
|
+
|
42
|
+
def incompatible_version?
|
43
|
+
RuboCop::Version::STRING != Cache.version_path.read
|
44
|
+
end
|
45
|
+
|
46
|
+
def status
|
47
|
+
unless Cache.status_path.file?
|
48
|
+
raise "RuboCop server: Could not find status file at: #{Cache.status_path}"
|
49
|
+
end
|
50
|
+
|
51
|
+
status = Cache.status_path.read
|
52
|
+
raise "RuboCop server: '#{status}' is not a valid status!" if (status =~ /^\d+$/).nil?
|
53
|
+
|
54
|
+
status.to_i
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This code is based on https://github.com/fohte/rubocop-daemon.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2018 Hayato Kawai
|
7
|
+
#
|
8
|
+
# The MIT License (MIT)
|
9
|
+
#
|
10
|
+
# https://github.com/fohte/rubocop-daemon/blob/master/LICENSE.txt
|
11
|
+
#
|
12
|
+
module RuboCop
|
13
|
+
module Server
|
14
|
+
module ClientCommand
|
15
|
+
# This class is a client command to restart server process.
|
16
|
+
# @api private
|
17
|
+
class Restart < Base
|
18
|
+
def run
|
19
|
+
ClientCommand::Stop.new.run
|
20
|
+
ClientCommand::Start.new.run
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This code is based on https://github.com/fohte/rubocop-daemon.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2018 Hayato Kawai
|
7
|
+
#
|
8
|
+
# The MIT License (MIT)
|
9
|
+
#
|
10
|
+
# https://github.com/fohte/rubocop-daemon/blob/master/LICENSE.txt
|
11
|
+
#
|
12
|
+
module RuboCop
|
13
|
+
module Server
|
14
|
+
module ClientCommand
|
15
|
+
# This class is a client command to start server process.
|
16
|
+
# @api private
|
17
|
+
class Start < Base
|
18
|
+
def run
|
19
|
+
if Server.running?
|
20
|
+
warn "RuboCop server (#{Cache.pid_path.read}) is already running."
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
Cache.acquire_lock do |locked|
|
25
|
+
unless locked
|
26
|
+
# Another process is already starting server,
|
27
|
+
# so wait for it to be ready.
|
28
|
+
Server.wait_for_running_status!(true)
|
29
|
+
exit 0
|
30
|
+
end
|
31
|
+
|
32
|
+
Cache.write_version_file(RuboCop::Version::STRING)
|
33
|
+
|
34
|
+
host = ENV.fetch('RUBOCOP_SERVER_HOST', '127.0.0.1')
|
35
|
+
port = ENV.fetch('RUBOCOP_SERVER_PORT', 0)
|
36
|
+
|
37
|
+
Server::Core.new.start(host, port)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This code is based on https://github.com/fohte/rubocop-daemon.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2018 Hayato Kawai
|
7
|
+
#
|
8
|
+
# The MIT License (MIT)
|
9
|
+
#
|
10
|
+
# https://github.com/fohte/rubocop-daemon/blob/master/LICENSE.txt
|
11
|
+
#
|
12
|
+
module RuboCop
|
13
|
+
module Server
|
14
|
+
module ClientCommand
|
15
|
+
# This class is a client command to show server process status.
|
16
|
+
# @api private
|
17
|
+
class Status < Base
|
18
|
+
def run
|
19
|
+
if Server.running?
|
20
|
+
puts "RuboCop server (#{Cache.pid_path.read}) is running."
|
21
|
+
else
|
22
|
+
puts 'RuboCop server is not running.'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This code is based on https://github.com/fohte/rubocop-daemon.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2018 Hayato Kawai
|
7
|
+
#
|
8
|
+
# The MIT License (MIT)
|
9
|
+
#
|
10
|
+
# https://github.com/fohte/rubocop-daemon/blob/master/LICENSE.txt
|
11
|
+
#
|
12
|
+
module RuboCop
|
13
|
+
module Server
|
14
|
+
module ClientCommand
|
15
|
+
# This class is a client command to stop server process.
|
16
|
+
# @api private
|
17
|
+
class Stop < Base
|
18
|
+
def run
|
19
|
+
return unless check_running_server
|
20
|
+
|
21
|
+
pid = fork do
|
22
|
+
send_request(command: 'stop')
|
23
|
+
Server.wait_for_running_status!(false)
|
24
|
+
end
|
25
|
+
|
26
|
+
Process.waitpid(pid)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|