rubocop 0.17.0 → 0.18.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +65 -42
- data/CONTRIBUTING.md +20 -3
- data/config/enabled.yml +10 -0
- data/lib/rubocop.rb +7 -0
- data/lib/rubocop/cop/cop.rb +4 -13
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +1 -1
- data/lib/rubocop/cop/lint/loop.rb +1 -1
- data/lib/rubocop/cop/lint/require_parentheses.rb +72 -0
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -1
- data/lib/rubocop/cop/style/access_modifier_indentation.rb +3 -1
- data/lib/rubocop/cop/style/align_array.rb +1 -1
- data/lib/rubocop/cop/style/align_hash.rb +1 -1
- data/lib/rubocop/cop/style/align_parameters.rb +1 -1
- data/lib/rubocop/cop/style/def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +53 -0
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +1 -1
- data/lib/rubocop/cop/style/proc.rb +6 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
- data/lib/rubocop/cop/style/space_after_method_name.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma.rb +7 -0
- data/lib/rubocop/cop/style/word_array.rb +27 -0
- data/lib/rubocop/cop/util.rb +1 -0
- data/lib/rubocop/formatter/simple_text_formatter.rb +6 -2
- data/lib/rubocop/options.rb +1 -1
- data/lib/rubocop/path_util.rb +22 -0
- data/lib/rubocop/rake_task.rb +17 -3
- data/lib/rubocop/version.rb +1 -1
- data/rubocop.gemspec +2 -2
- data/spec/project_spec.rb +93 -0
- data/spec/rubocop/cli_spec.rb +27 -22
- data/spec/rubocop/cop/cop_spec.rb +1 -1
- data/spec/rubocop/cop/lint/ambiguous_operator_spec.rb +2 -2
- data/spec/rubocop/cop/lint/ambiguous_regexp_literal_spec.rb +1 -1
- data/spec/rubocop/cop/lint/block_alignment_spec.rb +5 -5
- data/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb +2 -2
- data/spec/rubocop/cop/lint/require_parentheses_spec.rb +82 -0
- data/spec/rubocop/cop/lint/rescue_exception_spec.rb +1 -1
- data/spec/rubocop/cop/lint/shadowing_outer_local_variable_spec.rb +9 -9
- data/spec/rubocop/cop/lint/useless_assignment_spec.rb +54 -54
- data/spec/rubocop/cop/lint/useless_setter_call_spec.rb +6 -6
- data/spec/rubocop/cop/style/access_modifier_indentation_spec.rb +49 -8
- data/spec/rubocop/cop/style/align_array_spec.rb +1 -1
- data/spec/rubocop/cop/style/align_hash_spec.rb +1 -1
- data/spec/rubocop/cop/style/align_parameters_spec.rb +2 -2
- data/spec/rubocop/cop/style/blocks_spec.rb +1 -1
- data/spec/rubocop/cop/style/case_indentation_spec.rb +1 -1
- data/spec/rubocop/cop/style/dot_position_spec.rb +1 -1
- data/spec/rubocop/cop/style/favor_unless_over_negated_if_spec.rb +2 -2
- data/spec/rubocop/cop/style/if_unless_modifier_spec.rb +3 -3
- data/spec/rubocop/cop/style/indentation_consistency_spec.rb +4 -4
- data/spec/rubocop/cop/style/indentation_width_spec.rb +3 -3
- data/spec/rubocop/cop/style/line_end_concatenation_spec.rb +27 -0
- data/spec/rubocop/cop/style/multiline_block_chain_spec.rb +1 -1
- data/spec/rubocop/cop/style/proc_spec.rb +5 -0
- data/spec/rubocop/cop/style/regexp_literal_spec.rb +4 -4
- data/spec/rubocop/cop/style/string_literals_spec.rb +7 -7
- data/spec/rubocop/cop/style/trailing_comma_spec.rb +27 -6
- data/spec/rubocop/cop/style/unless_else_spec.rb +1 -1
- data/spec/rubocop/cop/style/variable_interpolation_spec.rb +2 -2
- data/spec/rubocop/cop/style/word_array_spec.rb +10 -0
- data/spec/rubocop/cop/variable_inspector/variable_table_spec.rb +4 -4
- data/spec/rubocop/formatter/disabled_config_formatter_spec.rb +1 -1
- data/spec/rubocop/formatter/formatter_set_spec.rb +1 -1
- data/spec/rubocop/path_util_spec.rb +42 -0
- data/spec/spec_helper.rb +3 -1
- metadata +29 -8
@@ -39,7 +39,7 @@ module Rubocop
|
|
39
39
|
def alternative_style
|
40
40
|
a = cop_config['SupportedStyles'].map(&:to_sym)
|
41
41
|
if a.size != 2
|
42
|
-
fail 'alternative_style can only be used when there are exactly '
|
42
|
+
fail 'alternative_style can only be used when there are exactly ' \
|
43
43
|
'2 SupportedStyles'
|
44
44
|
end
|
45
45
|
style == a.first ? a.last : a.first
|
@@ -7,6 +7,7 @@ module Rubocop
|
|
7
7
|
# Modifiers should be indented as deeps are method definitions and
|
8
8
|
# surrounded by blank lines.
|
9
9
|
class AccessModifierIndentation < Cop
|
10
|
+
include AutocorrectAlignment
|
10
11
|
include ConfigurableEnforcedStyle
|
11
12
|
|
12
13
|
MSG = '%s access modifiers like %s.'
|
@@ -47,7 +48,8 @@ module Rubocop
|
|
47
48
|
access_modifier_start_col = send_node.loc.expression.column
|
48
49
|
offset = access_modifier_start_col - class_start_col
|
49
50
|
|
50
|
-
|
51
|
+
@column_delta = expected_indent_offset - offset
|
52
|
+
if @column_delta == 0
|
51
53
|
correct_style_detected
|
52
54
|
else
|
53
55
|
add_offence(send_node, :expression) do
|
@@ -9,7 +9,7 @@ module Rubocop
|
|
9
9
|
class DefWithParentheses < Cop
|
10
10
|
include CheckMethods
|
11
11
|
|
12
|
-
MSG = "Omit the parentheses in defs when the method doesn't accept "
|
12
|
+
MSG = "Omit the parentheses in defs when the method doesn't accept " \
|
13
13
|
'any arguments.'
|
14
14
|
|
15
15
|
def check(node, _method_name, args, _body)
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks for string literal concatenation at
|
7
|
+
# the end of a line.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# some_str = 'ala' +
|
13
|
+
# 'bala'
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# some_str = 'ala' \
|
17
|
+
# 'bala'
|
18
|
+
#
|
19
|
+
class LineEndConcatenation < Cop
|
20
|
+
MSG = 'Use \\ instead of + to concatenate those strings.'
|
21
|
+
|
22
|
+
def on_send(node)
|
23
|
+
add_offence(node, :selector) if offending_node?(node)
|
24
|
+
end
|
25
|
+
|
26
|
+
def autocorrect(node)
|
27
|
+
@corrections << lambda do |corrector|
|
28
|
+
# replace + with \
|
29
|
+
corrector.replace(node.loc.selector, '\\')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def offending_node?(node)
|
36
|
+
receiver, method, arg = *node
|
37
|
+
|
38
|
+
# TODO: Report Emacs bug.
|
39
|
+
return false unless :+ == method
|
40
|
+
|
41
|
+
return false unless receiver.type == :str
|
42
|
+
|
43
|
+
return false unless arg.type == :str
|
44
|
+
|
45
|
+
receiver_line = receiver.loc.expression.line
|
46
|
+
arg_line = arg.loc.expression.line
|
47
|
+
|
48
|
+
receiver_line != arg_line
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -5,7 +5,7 @@ module Rubocop
|
|
5
5
|
module Style
|
6
6
|
# This cop checks for nested ternary op expressions.
|
7
7
|
class NestedTernaryOperator < Cop
|
8
|
-
MSG = 'Ternary operators must not be nested. Prefer if/else '
|
8
|
+
MSG = 'Ternary operators must not be nested. Prefer if/else ' \
|
9
9
|
'constructs instead.'
|
10
10
|
|
11
11
|
def on_if(node)
|
@@ -7,7 +7,7 @@ module Rubocop
|
|
7
7
|
class SpaceAfterMethodName < Cop
|
8
8
|
include CheckMethods
|
9
9
|
|
10
|
-
MSG = 'Never put a space between a method name and the opening '
|
10
|
+
MSG = 'Never put a space between a method name and the opening ' \
|
11
11
|
'parenthesis.'
|
12
12
|
|
13
13
|
def check(_node, _method_name, args, body)
|
@@ -48,6 +48,9 @@ module Rubocop
|
|
48
48
|
def check(node, items, kind, begin_pos, end_pos)
|
49
49
|
sb = items.first.loc.expression.source_buffer
|
50
50
|
after_last_item = Parser::Source::Range.new(sb, begin_pos, end_pos)
|
51
|
+
|
52
|
+
return if heredoc?(after_last_item.source)
|
53
|
+
|
51
54
|
comma_offset = after_last_item.source =~ /,/
|
52
55
|
should_have_comma = style == :comma && multiline?(node)
|
53
56
|
if comma_offset
|
@@ -60,6 +63,10 @@ module Rubocop
|
|
60
63
|
end
|
61
64
|
end
|
62
65
|
|
66
|
+
def heredoc?(source_after_last_item)
|
67
|
+
source_after_last_item =~ /\w/
|
68
|
+
end
|
69
|
+
|
63
70
|
# Returns true if the node has round/square/curly brackets.
|
64
71
|
def brackets?(node)
|
65
72
|
!node.loc.end.nil?
|
@@ -53,6 +53,33 @@ module Rubocop
|
|
53
53
|
def min_size
|
54
54
|
cop_config['MinSize']
|
55
55
|
end
|
56
|
+
|
57
|
+
def autocorrect(node)
|
58
|
+
sb = node.loc.expression.source_buffer
|
59
|
+
interpolated = false
|
60
|
+
|
61
|
+
contents = node.children.map do |n|
|
62
|
+
if character_literal?(n)
|
63
|
+
interpolated = true
|
64
|
+
begin_pos = n.loc.expression.begin_pos + '?'.length
|
65
|
+
end_pos = n.loc.expression.end_pos
|
66
|
+
else
|
67
|
+
begin_pos = n.loc.begin.end_pos
|
68
|
+
end_pos = n.loc.end.begin_pos
|
69
|
+
end
|
70
|
+
Parser::Source::Range.new(sb, begin_pos, end_pos).source
|
71
|
+
end.join(' ')
|
72
|
+
|
73
|
+
char = interpolated ? 'W' : 'w'
|
74
|
+
|
75
|
+
@corrections << lambda do |corrector|
|
76
|
+
corrector.replace(node.loc.expression, "%#{char}(#{contents})")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def character_literal?(node)
|
81
|
+
node.loc.end.nil?
|
82
|
+
end
|
56
83
|
end
|
57
84
|
end
|
58
85
|
end
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -9,6 +9,7 @@ module Rubocop
|
|
9
9
|
# location of the problem and the associated message.
|
10
10
|
class SimpleTextFormatter < BaseFormatter
|
11
11
|
include Colorizable
|
12
|
+
include PathUtil
|
12
13
|
|
13
14
|
COLOR_FOR_SEVERITY = {
|
14
15
|
refactor: :yellow,
|
@@ -73,8 +74,11 @@ module Rubocop
|
|
73
74
|
end
|
74
75
|
|
75
76
|
def smart_path(path)
|
76
|
-
|
77
|
-
|
77
|
+
# Ideally, we calculate this relative to the project root.
|
78
|
+
base_dir = Dir.pwd
|
79
|
+
|
80
|
+
if path.start_with? base_dir
|
81
|
+
relative_path(path, base_dir)
|
78
82
|
else
|
79
83
|
path
|
80
84
|
end
|
data/lib/rubocop/options.rb
CHANGED
@@ -123,7 +123,7 @@ module Rubocop
|
|
123
123
|
# since those are mostly used by external tools.
|
124
124
|
rejected = args.reject! { |a| %w(-s --silent).include?(a) }
|
125
125
|
if rejected
|
126
|
-
warn '-s/--silent options is dropped. '
|
126
|
+
warn '-s/--silent options is dropped. ' \
|
127
127
|
'`emacs` and `files` formatters no longer display summary.'
|
128
128
|
end
|
129
129
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
# Common methods and behaviors for dealing with paths.
|
5
|
+
module PathUtil
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def relative_path(path, base_dir = Dir.pwd)
|
9
|
+
Pathname.new(path).relative_path_from(Pathname.new(base_dir)).to_s
|
10
|
+
end
|
11
|
+
|
12
|
+
def match_path?(pattern, path)
|
13
|
+
case pattern
|
14
|
+
when String
|
15
|
+
basename = File.basename(path)
|
16
|
+
path == pattern || basename == pattern || File.fnmatch(pattern, path)
|
17
|
+
when Regexp
|
18
|
+
path =~ pattern
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/rubocop/rake_task.rb
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
require 'rake'
|
4
4
|
require 'rake/tasklib'
|
5
5
|
|
6
|
-
require 'rubocop/options'
|
7
|
-
|
8
6
|
module Rubocop
|
9
7
|
# Provides a custom rake task.
|
10
8
|
#
|
@@ -16,6 +14,8 @@ module Rubocop
|
|
16
14
|
attr_accessor :fail_on_error
|
17
15
|
attr_accessor :patterns
|
18
16
|
attr_accessor :formatters
|
17
|
+
attr_accessor :requires
|
18
|
+
attr_accessor :options
|
19
19
|
|
20
20
|
def initialize(*args, &task_block)
|
21
21
|
setup_ivars(args)
|
@@ -39,17 +39,31 @@ module Rubocop
|
|
39
39
|
|
40
40
|
cli = CLI.new
|
41
41
|
puts 'Running RuboCop...' if verbose
|
42
|
-
result = cli.run(
|
42
|
+
result = cli.run(full_options)
|
43
43
|
abort('RuboCop failed!') if fail_on_error unless result == 0
|
44
44
|
end
|
45
45
|
|
46
46
|
private
|
47
47
|
|
48
|
+
def full_options
|
49
|
+
[].tap do |result|
|
50
|
+
result.concat(formatters.map { |f| ['--format', f] }.flatten)
|
51
|
+
result.concat(requires.map { |r| ['--require', r] }.flatten)
|
52
|
+
result.concat(options)
|
53
|
+
result.concat(patterns)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
48
57
|
def setup_ivars(args)
|
58
|
+
# More lazy-loading to keep load time down.
|
59
|
+
require 'rubocop/options'
|
60
|
+
|
49
61
|
@name = args.shift || :rubocop
|
50
62
|
@verbose = true
|
51
63
|
@fail_on_error = true
|
52
64
|
@patterns = []
|
65
|
+
@requires = []
|
66
|
+
@options = []
|
53
67
|
@formatters = [Rubocop::Options::DEFAULT_FORMATTER]
|
54
68
|
end
|
55
69
|
end
|
data/lib/rubocop/version.rb
CHANGED
data/rubocop.gemspec
CHANGED
@@ -26,10 +26,10 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.rubygems_version = '1.8.23'
|
27
27
|
s.summary = 'Automatic Ruby code style checking tool.'
|
28
28
|
|
29
|
-
s.add_runtime_dependency('rainbow', '
|
29
|
+
s.add_runtime_dependency('rainbow', '>= 1.99.1', '< 3.0')
|
30
30
|
s.add_runtime_dependency('parser', '~> 2.1.3')
|
31
31
|
s.add_runtime_dependency('powerpack', '~> 0.0.6')
|
32
|
-
s.add_runtime_dependency('json', '
|
32
|
+
s.add_runtime_dependency('json', '>= 1.7.7', '< 2')
|
33
33
|
s.add_development_dependency('rake', '~> 10.1')
|
34
34
|
s.add_development_dependency('rspec', '~> 2.14')
|
35
35
|
s.add_development_dependency('yard', '~> 0.8')
|
data/spec/project_spec.rb
CHANGED
@@ -22,4 +22,97 @@ describe 'RuboCop Project' do
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
25
|
+
|
26
|
+
describe 'changelog' do
|
27
|
+
subject(:changelog) do
|
28
|
+
path = File.join(File.dirname(__FILE__), '..', 'CHANGELOG.md')
|
29
|
+
File.read(path)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'has link definitions for all implicit links' do
|
33
|
+
implicit_link_names = changelog.scan(/\[([^\]]+)\]\[\]/).flatten.uniq
|
34
|
+
implicit_link_names.each do |name|
|
35
|
+
expect(changelog).to include("[#{name}]: http")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'entry' do
|
40
|
+
subject(:entries) { lines.grep(/^\*/).map(&:chomp) }
|
41
|
+
let(:lines) { changelog.each_line }
|
42
|
+
|
43
|
+
it 'has a whitespace between the * and the body' do
|
44
|
+
entries.each do |entry|
|
45
|
+
expect(entry).to match(/^\* \S/)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'after version 0.14.0' do
|
50
|
+
let(:lines) do
|
51
|
+
changelog.each_line.take_while do |line|
|
52
|
+
!line.start_with?('## 0.14.0')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'has a link to the contributors at the end' do
|
57
|
+
entries.each do |entry|
|
58
|
+
expect(entry).to match(/\(\[@\S+\]\[\](?:, \[@\S+\]\[\])*\)$/)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'link to related issue' do
|
64
|
+
let(:issues) do
|
65
|
+
entries.map do |entry|
|
66
|
+
entry.match(/\[(?<number>[#\d]+)\]\((?<url>[^\)]+)\)/)
|
67
|
+
end.compact
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'has an issue number prefixed with #' do
|
71
|
+
issues.each do |issue|
|
72
|
+
expect(issue[:number]).to match(/^#\d+$/)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'has a valid URL' do
|
77
|
+
issues.each do |issue|
|
78
|
+
number = issue[:number].gsub(/\D/, '')
|
79
|
+
pattern = %r{^https://github\.com/bbatsov/rubocop/(?:issues|pull)/#{number}$} # rubocop:disable LineLength
|
80
|
+
expect(issue[:url]).to match(pattern)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'has a colon and a whitespace at the end' do
|
85
|
+
entries_including_issue_link = entries.select do |entry|
|
86
|
+
entry.match(/^\*\s*\[/)
|
87
|
+
end
|
88
|
+
|
89
|
+
entries_including_issue_link.each do |entry|
|
90
|
+
expect(entry).to include('): ')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe 'body' do
|
96
|
+
let(:bodies) do
|
97
|
+
entries.map do |entry|
|
98
|
+
entry
|
99
|
+
.sub(/^\*\s*(?:\[.+?\):\s*)?/, '')
|
100
|
+
.sub(/\s*\([^\)]+\)$/, '')
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'does not start with a lower case' do
|
105
|
+
bodies.each do |body|
|
106
|
+
expect(body).not_to match(/^[a-z]/)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'ends with a punctuation' do
|
111
|
+
bodies.each do |body|
|
112
|
+
expect(body).to match(/[\.\!]$/)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
25
118
|
end
|