standard 0.0.34
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of standard might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.circleci/config.yml +35 -0
- data/.gitignore +8 -0
- data/.standard.yml +4 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +58 -0
- data/LICENSE.txt +24 -0
- data/README.md +354 -0
- data/Rakefile +12 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/config/base.yml +1045 -0
- data/config/ruby-1.8.yml +8 -0
- data/config/ruby-1.9.yml +4 -0
- data/config/ruby-2.2.yml +8 -0
- data/exe/standardrb +7 -0
- data/lib/standard/builds_config.rb +26 -0
- data/lib/standard/cli.rb +23 -0
- data/lib/standard/cop/semantic_blocks.rb +162 -0
- data/lib/standard/creates_config_store/assigns_rubocop_yaml.rb +26 -0
- data/lib/standard/creates_config_store/configures_ignored_paths.rb +45 -0
- data/lib/standard/creates_config_store/sets_target_ruby_version.rb +25 -0
- data/lib/standard/creates_config_store.rb +23 -0
- data/lib/standard/detects_fixability.rb +20 -0
- data/lib/standard/file_finder.rb +13 -0
- data/lib/standard/formatter.rb +79 -0
- data/lib/standard/loads_runner.rb +9 -0
- data/lib/standard/loads_yaml_config.rb +60 -0
- data/lib/standard/merges_settings.rb +64 -0
- data/lib/standard/parses_cli_option.rb +21 -0
- data/lib/standard/railtie.rb +11 -0
- data/lib/standard/rake.rb +26 -0
- data/lib/standard/rubocop/ext.rb +7 -0
- data/lib/standard/runners/help.rb +44 -0
- data/lib/standard/runners/rubocop.rb +36 -0
- data/lib/standard/runners/version.rb +9 -0
- data/lib/standard/version.rb +3 -0
- data/lib/standard.rb +13 -0
- data/standard.gemspec +29 -0
- metadata +179 -0
data/config/ruby-1.8.yml
ADDED
data/config/ruby-1.9.yml
ADDED
data/config/ruby-2.2.yml
ADDED
data/exe/standardrb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative "loads_yaml_config"
|
2
|
+
require_relative "merges_settings"
|
3
|
+
require_relative "creates_config_store"
|
4
|
+
|
5
|
+
module Standard
|
6
|
+
Config = Struct.new(:runner, :paths, :rubocop_options, :rubocop_config_store)
|
7
|
+
|
8
|
+
class BuildsConfig
|
9
|
+
def initialize
|
10
|
+
@loads_yaml_config = LoadsYamlConfig.new
|
11
|
+
@merges_settings = MergesSettings.new
|
12
|
+
@creates_config_store = CreatesConfigStore.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(argv, search_path = Dir.pwd)
|
16
|
+
standard_config = @loads_yaml_config.call(argv, search_path)
|
17
|
+
settings = @merges_settings.call(argv, standard_config)
|
18
|
+
Config.new(
|
19
|
+
settings.runner,
|
20
|
+
settings.paths,
|
21
|
+
settings.options,
|
22
|
+
@creates_config_store.call(standard_config)
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/standard/cli.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative "builds_config"
|
2
|
+
require_relative "loads_runner"
|
3
|
+
|
4
|
+
module Standard
|
5
|
+
class Cli
|
6
|
+
SUCCESS_STATUS_CODE = 0
|
7
|
+
FAILURE_STATUS_CODE = 1
|
8
|
+
|
9
|
+
def initialize(argv)
|
10
|
+
@argv = argv
|
11
|
+
@builds_config = BuildsConfig.new
|
12
|
+
@loads_runner = LoadsRunner.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
config = @builds_config.call(@argv)
|
17
|
+
|
18
|
+
success = @loads_runner.call(config.runner).call(config)
|
19
|
+
|
20
|
+
success ? SUCCESS_STATUS_CODE : FAILURE_STATUS_CODE
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module RuboCop::Cop
|
2
|
+
module Standard
|
3
|
+
class SemanticBlocks < RuboCop::Cop::Cop
|
4
|
+
include RuboCop::Cop::IgnoredMethods
|
5
|
+
|
6
|
+
def on_send(node)
|
7
|
+
return unless node.arguments?
|
8
|
+
return if node.parenthesized? || node.operator_method?
|
9
|
+
|
10
|
+
node.arguments.each do |arg|
|
11
|
+
get_blocks(arg) do |block|
|
12
|
+
# If there are no parentheses around the arguments, then braces
|
13
|
+
# and do-end have different meaning due to how they bind, so we
|
14
|
+
# allow either.
|
15
|
+
ignore_node(block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_block(node)
|
21
|
+
return if ignored_node?(node) || proper_block_style?(node)
|
22
|
+
|
23
|
+
add_offense(node, location: :begin)
|
24
|
+
end
|
25
|
+
|
26
|
+
def autocorrect(node)
|
27
|
+
return if correction_would_break_code?(node)
|
28
|
+
|
29
|
+
if node.single_line?
|
30
|
+
replace_do_end_with_braces(node.loc)
|
31
|
+
elsif node.braces?
|
32
|
+
replace_braces_with_do_end(node.loc)
|
33
|
+
else
|
34
|
+
replace_do_end_with_braces(node.loc)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def message(node)
|
41
|
+
if node.single_line?
|
42
|
+
"Prefer `{...}` over `do...end` for single-line blocks."
|
43
|
+
elsif node.loc.begin.source == "{"
|
44
|
+
"Prefer `do...end` over `{...}` for procedural blocks."
|
45
|
+
else
|
46
|
+
"Prefer `{...}` over `do...end` for functional blocks."
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def replace_braces_with_do_end(loc)
|
51
|
+
b = loc.begin
|
52
|
+
e = loc.end
|
53
|
+
|
54
|
+
lambda do |corrector|
|
55
|
+
corrector.insert_before(b, " ") unless whitespace_before?(b)
|
56
|
+
corrector.insert_before(e, " ") unless whitespace_before?(e)
|
57
|
+
corrector.insert_after(b, " ") unless whitespace_after?(b)
|
58
|
+
corrector.replace(b, "do")
|
59
|
+
corrector.replace(e, "end")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def replace_do_end_with_braces(loc)
|
64
|
+
b = loc.begin
|
65
|
+
e = loc.end
|
66
|
+
|
67
|
+
lambda do |corrector|
|
68
|
+
corrector.insert_after(b, " ") unless whitespace_after?(b, 2)
|
69
|
+
|
70
|
+
corrector.replace(b, "{")
|
71
|
+
corrector.replace(e, "}")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def whitespace_before?(range)
|
76
|
+
range.source_buffer.source[range.begin_pos - 1, 1] =~ /\s/
|
77
|
+
end
|
78
|
+
|
79
|
+
def whitespace_after?(range, length = 1)
|
80
|
+
range.source_buffer.source[range.begin_pos + length, 1] =~ /\s/
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_blocks(node, &block)
|
84
|
+
case node.type
|
85
|
+
when :block
|
86
|
+
yield node
|
87
|
+
when :send
|
88
|
+
get_blocks(node.receiver, &block) if node.receiver
|
89
|
+
when :hash
|
90
|
+
# A hash which is passed as method argument may have no braces
|
91
|
+
# In that case, one of the K/V pairs could contain a block node
|
92
|
+
# which could change in meaning if do...end replaced {...}
|
93
|
+
return if node.braces?
|
94
|
+
|
95
|
+
node.each_child_node { |child| get_blocks(child, &block) }
|
96
|
+
when :pair
|
97
|
+
node.each_child_node { |child| get_blocks(child, &block) }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def proper_block_style?(node)
|
102
|
+
method_name = node.method_name
|
103
|
+
|
104
|
+
if ignored_method?(method_name)
|
105
|
+
true
|
106
|
+
elsif node.single_line?
|
107
|
+
node.braces?
|
108
|
+
elsif node.braces?
|
109
|
+
!procedural_method?(method_name) &&
|
110
|
+
(functional_method?(method_name) || functional_block?(node))
|
111
|
+
else
|
112
|
+
procedural_method?(method_name) || !return_value_used?(node)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def correction_would_break_code?(node)
|
117
|
+
return unless node.keywords?
|
118
|
+
|
119
|
+
node.send_node.arguments? && !node.send_node.parenthesized?
|
120
|
+
end
|
121
|
+
|
122
|
+
def functional_method?(method_name)
|
123
|
+
cop_config["FunctionalMethods"].map(&:to_sym).include?(method_name)
|
124
|
+
end
|
125
|
+
|
126
|
+
def functional_block?(node)
|
127
|
+
return_value_used?(node) || return_value_of_scope?(node)
|
128
|
+
end
|
129
|
+
|
130
|
+
def procedural_method?(method_name)
|
131
|
+
cop_config["ProceduralMethods"].map(&:to_sym).include?(method_name)
|
132
|
+
end
|
133
|
+
|
134
|
+
def return_value_used?(node)
|
135
|
+
return unless node.parent
|
136
|
+
|
137
|
+
# If there are parentheses around the block, check if that
|
138
|
+
# is being used.
|
139
|
+
if node.parent.begin_type?
|
140
|
+
return_value_used?(node.parent)
|
141
|
+
else
|
142
|
+
node.parent.assignment? || node.parent.send_type?
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def return_value_of_scope?(node)
|
147
|
+
return unless node.parent
|
148
|
+
|
149
|
+
conditional?(node.parent) || array_or_range?(node.parent) ||
|
150
|
+
node.parent.children.last == node
|
151
|
+
end
|
152
|
+
|
153
|
+
def conditional?(node)
|
154
|
+
node.if_type? || node.or_type? || node.and_type?
|
155
|
+
end
|
156
|
+
|
157
|
+
def array_or_range?(node)
|
158
|
+
node.array_type? || node.irange_type? || node.erange_type?
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
class Standard::CreatesConfigStore
|
4
|
+
class AssignsRubocopYaml
|
5
|
+
def call(config_store, standard_config)
|
6
|
+
config_store.options_config = rubocop_yaml_path(standard_config[:ruby_version])
|
7
|
+
config_store.instance_variable_get("@options_config")
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def rubocop_yaml_path(desired_version)
|
13
|
+
file_name = if desired_version < Gem::Version.new("1.9")
|
14
|
+
"ruby-1.8.yml"
|
15
|
+
elsif desired_version < Gem::Version.new("2.0")
|
16
|
+
"ruby-1.9.yml"
|
17
|
+
elsif desired_version < Gem::Version.new("2.3")
|
18
|
+
"ruby-2.2.yml"
|
19
|
+
else
|
20
|
+
"base.yml"
|
21
|
+
end
|
22
|
+
|
23
|
+
Pathname.new(__dir__).join("../../../config/#{file_name}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class Standard::CreatesConfigStore
|
2
|
+
class ConfiguresIgnoredPaths
|
3
|
+
DEFAULT_IGNORES = [
|
4
|
+
# Match RuboCop's defaults: https://github.com/rubocop-hq/rubocop/blob/v0.61.1/config/default.yml#L60-L63
|
5
|
+
".git/**/*",
|
6
|
+
"node_modules/**/*",
|
7
|
+
"vendor/**/*",
|
8
|
+
# Standard's own default ignores:
|
9
|
+
"bin/*",
|
10
|
+
"db/schema.rb",
|
11
|
+
"tmp/**/*",
|
12
|
+
].map { |path| [path, ["AllCops"]] }.freeze
|
13
|
+
|
14
|
+
def call(options_config, standard_config)
|
15
|
+
ignored_patterns(standard_config).each do |(path, cops)|
|
16
|
+
cops.each do |cop|
|
17
|
+
options_config[cop] ||= {}
|
18
|
+
options_config[cop]["Exclude"] ||= []
|
19
|
+
options_config[cop]["Exclude"] |= [
|
20
|
+
absolutify(standard_config[:config_root], path),
|
21
|
+
]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def ignored_patterns(standard_config)
|
29
|
+
(standard_config[:default_ignores] ? DEFAULT_IGNORES : []) +
|
30
|
+
standard_config[:ignore]
|
31
|
+
end
|
32
|
+
|
33
|
+
def absolutify(config_root, path)
|
34
|
+
if !absolute?(path)
|
35
|
+
File.expand_path(File.join(config_root || Dir.pwd, path))
|
36
|
+
else
|
37
|
+
path
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def absolute?(path)
|
42
|
+
path =~ %r{\A([A-Z]:)?/}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Standard::CreatesConfigStore
|
2
|
+
class SetsTargetRubyVersion
|
3
|
+
def call(options_config, standard_config)
|
4
|
+
options_config["AllCops"]["TargetRubyVersion"] = floatify_version(
|
5
|
+
max_rubocop_supported_version(standard_config[:ruby_version])
|
6
|
+
)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def max_rubocop_supported_version(desired_version)
|
12
|
+
rubocop_supported_version = Gem::Version.new("2.2")
|
13
|
+
if desired_version < rubocop_supported_version
|
14
|
+
rubocop_supported_version
|
15
|
+
else
|
16
|
+
desired_version
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def floatify_version(version)
|
21
|
+
major, minor = version.segments
|
22
|
+
"#{major}.#{minor}".to_f # lol
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "rubocop"
|
2
|
+
|
3
|
+
require_relative "creates_config_store/assigns_rubocop_yaml"
|
4
|
+
require_relative "creates_config_store/sets_target_ruby_version"
|
5
|
+
require_relative "creates_config_store/configures_ignored_paths"
|
6
|
+
|
7
|
+
module Standard
|
8
|
+
class CreatesConfigStore
|
9
|
+
def initialize
|
10
|
+
@assigns_rubocop_yaml = AssignsRubocopYaml.new
|
11
|
+
@sets_target_ruby_version = SetsTargetRubyVersion.new
|
12
|
+
@configures_ignored_paths = ConfiguresIgnoredPaths.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(standard_config)
|
16
|
+
RuboCop::ConfigStore.new.tap do |config_store|
|
17
|
+
options_config = @assigns_rubocop_yaml.call(config_store, standard_config)
|
18
|
+
@sets_target_ruby_version.call(options_config, standard_config)
|
19
|
+
@configures_ignored_paths.call(options_config, standard_config)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Standard
|
2
|
+
class DetectsFixability
|
3
|
+
def call(offenses)
|
4
|
+
offenses.any? { |offense|
|
5
|
+
cop = cop_instance(offense.cop_name)
|
6
|
+
cop.support_autocorrect? && safe?(cop)
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def cop_instance(cop_name)
|
13
|
+
RuboCop::Cop.const_get(cop_name.gsub("/", "::")).new
|
14
|
+
end
|
15
|
+
|
16
|
+
def safe?(cop)
|
17
|
+
cop.cop_config.fetch("SafeAutoCorrect", true)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "rubocop"
|
2
|
+
require_relative "detects_fixability"
|
3
|
+
|
4
|
+
module Standard
|
5
|
+
class Formatter < RuboCop::Formatter::BaseFormatter
|
6
|
+
CALL_TO_ACTION_MESSAGE = <<-CALL_TO_ACTION.gsub(/^ {6}/, "")
|
7
|
+
Notice: Disagree with these rules? While StandardRB is pre-1.0.0, feel free to submit suggestions to:
|
8
|
+
https://github.com/testdouble/standard/issues/new
|
9
|
+
CALL_TO_ACTION
|
10
|
+
|
11
|
+
def initialize(*args)
|
12
|
+
super
|
13
|
+
@detects_fixability = DetectsFixability.new
|
14
|
+
@header_printed_already = false
|
15
|
+
@fix_suggestion_printed_already = false
|
16
|
+
@any_uncorrected_offenses = false
|
17
|
+
end
|
18
|
+
|
19
|
+
def file_finished(file, offenses)
|
20
|
+
return unless (uncorrected_offenses = offenses.reject(&:corrected?)).any?
|
21
|
+
@any_uncorrected_offenses = true
|
22
|
+
|
23
|
+
print_header_once
|
24
|
+
print_fix_suggestion_once(uncorrected_offenses)
|
25
|
+
|
26
|
+
uncorrected_offenses.each do |o|
|
27
|
+
output.printf(" %s:%d:%d: %s\n", path_to(file), o.line, o.real_column, o.message.tr("\n", " "))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def finished(_)
|
32
|
+
print_call_for_feedback if @any_uncorrected_offenses
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def print_header_once
|
38
|
+
return if @header_printed_already
|
39
|
+
|
40
|
+
output.print <<-HEADER.gsub(/^ {8}/, "")
|
41
|
+
standard: Use Ruby Standard Style (https://github.com/testdouble/standard)
|
42
|
+
HEADER
|
43
|
+
|
44
|
+
@header_printed_already = true
|
45
|
+
end
|
46
|
+
|
47
|
+
def print_fix_suggestion_once(offenses)
|
48
|
+
if !@fix_suggestion_printed_already && should_suggest_fix?(offenses)
|
49
|
+
command = if File.split($PROGRAM_NAME).last == "rake"
|
50
|
+
"rake standard:fix"
|
51
|
+
else
|
52
|
+
"standardrb --fix"
|
53
|
+
end
|
54
|
+
|
55
|
+
output.print <<-HEADER.gsub(/^ {10}/, "")
|
56
|
+
standard: Run `#{command}` to automatically fix some problems.
|
57
|
+
HEADER
|
58
|
+
@fix_suggestion_printed_already = true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def path_to(file)
|
63
|
+
Pathname.new(file).relative_path_from(Pathname.new(Dir.pwd))
|
64
|
+
end
|
65
|
+
|
66
|
+
def print_call_for_feedback
|
67
|
+
output.print "\n"
|
68
|
+
output.print CALL_TO_ACTION_MESSAGE
|
69
|
+
end
|
70
|
+
|
71
|
+
def auto_correct_option_provided?
|
72
|
+
options[:auto_correct] || options[:safe_auto_correct]
|
73
|
+
end
|
74
|
+
|
75
|
+
def should_suggest_fix?(offenses)
|
76
|
+
!auto_correct_option_provided? && @detects_fixability.call(offenses)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "pathname"
|
3
|
+
require_relative "file_finder"
|
4
|
+
require_relative "parses_cli_option"
|
5
|
+
|
6
|
+
module Standard
|
7
|
+
class LoadsYamlConfig
|
8
|
+
def initialize
|
9
|
+
@parses_cli_option = ParsesCliOption.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(argv, search_path)
|
13
|
+
yaml_path = @parses_cli_option.call(argv, "--config") ||
|
14
|
+
FileFinder.new.call(".standard.yml", search_path)
|
15
|
+
construct_config(yaml_path, load_standard_yaml(yaml_path))
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def load_standard_yaml(yaml_path)
|
21
|
+
if yaml_path
|
22
|
+
YAML.load_file(yaml_path) || {}
|
23
|
+
else
|
24
|
+
{}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def construct_config(yaml_path, standard_yaml)
|
29
|
+
{
|
30
|
+
ruby_version: Gem::Version.new((standard_yaml["ruby_version"] || RUBY_VERSION)),
|
31
|
+
fix: !!standard_yaml["fix"],
|
32
|
+
format: standard_yaml["format"],
|
33
|
+
parallel: !!standard_yaml["parallel"],
|
34
|
+
ignore: expand_ignore_config(standard_yaml["ignore"]),
|
35
|
+
default_ignores: standard_yaml.key?("default_ignores") ? !!standard_yaml["default_ignores"] : true,
|
36
|
+
config_root: yaml_path ? Pathname.new(yaml_path).dirname.to_s : nil,
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def expand_ignore_config(ignore_config)
|
41
|
+
arrayify(ignore_config).map { |rule|
|
42
|
+
if rule.is_a?(String)
|
43
|
+
[rule, ["AllCops"]]
|
44
|
+
elsif rule.is_a?(Hash)
|
45
|
+
rule.entries.first
|
46
|
+
end
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def arrayify(object)
|
51
|
+
if object.nil?
|
52
|
+
[]
|
53
|
+
elsif object.respond_to?(:to_ary)
|
54
|
+
object.to_ary || [object]
|
55
|
+
else
|
56
|
+
[object]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "rubocop"
|
2
|
+
|
3
|
+
module Standard
|
4
|
+
class MergesSettings
|
5
|
+
Settings = Struct.new(:runner, :options, :paths)
|
6
|
+
|
7
|
+
def call(argv, standard_yaml)
|
8
|
+
standard_argv, rubocop_argv = separate_argv(argv)
|
9
|
+
standard_cli_flags = parse_standard_argv(standard_argv)
|
10
|
+
rubocop_cli_flags, lint_paths = RuboCop::Options.new.parse(rubocop_argv)
|
11
|
+
|
12
|
+
Settings.new(
|
13
|
+
determine_command(standard_argv),
|
14
|
+
merge(standard_yaml, standard_cli_flags, without_banned(rubocop_cli_flags)),
|
15
|
+
lint_paths
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def separate_argv(argv)
|
22
|
+
argv.partition { |flag|
|
23
|
+
["--fix", "--no-fix", "--version", "-v", "--help", "-h"].include?(flag)
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse_standard_argv(argv)
|
28
|
+
argv.each_with_object({}) { |arg, cli_flags|
|
29
|
+
if arg == "--fix"
|
30
|
+
cli_flags[:auto_correct] = true
|
31
|
+
cli_flags[:safe_auto_correct] = true
|
32
|
+
elsif arg == "--no-fix"
|
33
|
+
cli_flags[:auto_correct] = false
|
34
|
+
cli_flags[:safe_auto_correct] = false
|
35
|
+
end
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def determine_command(argv)
|
40
|
+
if (argv & ["--help", "-h"]).any?
|
41
|
+
:help
|
42
|
+
elsif (argv & ["--version", "-v"]).any?
|
43
|
+
:version
|
44
|
+
else
|
45
|
+
:rubocop
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def merge(standard_yaml, standard_cli_flags, rubocop_cli_flags)
|
50
|
+
{
|
51
|
+
auto_correct: standard_yaml[:fix],
|
52
|
+
safe_auto_correct: standard_yaml[:fix],
|
53
|
+
formatters: [[standard_yaml[:format] || "Standard::Formatter", nil]],
|
54
|
+
parallel: standard_yaml[:parallel],
|
55
|
+
}.merge(standard_cli_flags).merge(rubocop_cli_flags)
|
56
|
+
end
|
57
|
+
|
58
|
+
def without_banned(rubocop_cli_flags)
|
59
|
+
rubocop_cli_flags.tap do |flags|
|
60
|
+
flags.delete(:config)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
module Standard
|
4
|
+
class ParsesCliOption
|
5
|
+
def call(argv, option_name)
|
6
|
+
return unless (config_file = argv_value_for(argv, option_name))
|
7
|
+
|
8
|
+
resolved_config = Pathname.new(config_file)
|
9
|
+
if resolved_config.exist?
|
10
|
+
resolved_config.expand_path
|
11
|
+
else
|
12
|
+
raise "Configuration file \"#{resolved_config.expand_path}\" not found."
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def argv_value_for(argv, option_name)
|
17
|
+
return unless (index = argv.index(option_name))
|
18
|
+
argv[index + 1]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Standard
|
2
|
+
module RakeSupport
|
3
|
+
# Allow command line flags set in STANDARDOPTS (like MiniTest's TESTOPTS)
|
4
|
+
def self.argvify
|
5
|
+
if ENV["STANDARDOPTS"]
|
6
|
+
ENV["STANDARDOPTS"].split(/\s+/)
|
7
|
+
else
|
8
|
+
[]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Lint with the Standard Ruby style guide"
|
15
|
+
task :standard do
|
16
|
+
require "standard"
|
17
|
+
exit_code = Standard::Cli.new(Standard::RakeSupport.argvify).run
|
18
|
+
fail unless exit_code == 0
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Lint and automatically fix with the Standard Ruby style guide"
|
22
|
+
task :"standard:fix" do
|
23
|
+
require "standard"
|
24
|
+
exit_code = Standard::Cli.new(Standard::RakeSupport.argvify + ["--fix"]).run
|
25
|
+
fail unless exit_code == 0
|
26
|
+
end
|