rubocop 0.24.1 → 0.25.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.

Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +12 -8
  3. data/.travis.yml +1 -1
  4. data/CHANGELOG.md +42 -0
  5. data/Gemfile +2 -0
  6. data/README.md +27 -6
  7. data/bin/rubocop +10 -15
  8. data/config/default.yml +72 -25
  9. data/config/enabled.yml +57 -25
  10. data/lib/rubocop.rb +15 -8
  11. data/lib/rubocop/config_loader.rb +11 -7
  12. data/lib/rubocop/cop/cop.rb +16 -16
  13. data/lib/rubocop/cop/ignored_node.rb +11 -4
  14. data/lib/rubocop/cop/lint/block_alignment.rb +29 -4
  15. data/lib/rubocop/cop/lint/debugger.rb +8 -1
  16. data/lib/rubocop/cop/lint/def_end_alignment.rb +5 -1
  17. data/lib/rubocop/cop/lint/end_alignment.rb +5 -5
  18. data/lib/rubocop/cop/lint/end_in_method.rb +2 -2
  19. data/lib/rubocop/cop/lint/useless_setter_call.rb +2 -2
  20. data/lib/rubocop/cop/{style → metrics}/block_nesting.rb +1 -1
  21. data/lib/rubocop/cop/{style → metrics}/class_length.rb +4 -4
  22. data/lib/rubocop/cop/{style → metrics}/cyclomatic_complexity.rb +5 -16
  23. data/lib/rubocop/cop/{style → metrics}/line_length.rb +1 -1
  24. data/lib/rubocop/cop/{style → metrics}/method_length.rb +8 -4
  25. data/lib/rubocop/cop/{style → metrics}/parameter_lists.rb +1 -1
  26. data/lib/rubocop/cop/metrics/perceived_complexity.rb +61 -0
  27. data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +10 -2
  28. data/lib/rubocop/cop/mixin/code_length.rb +2 -3
  29. data/lib/rubocop/cop/mixin/configurable_naming.rb +6 -20
  30. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  31. data/lib/rubocop/cop/mixin/if_node.rb +1 -1
  32. data/lib/rubocop/cop/mixin/method_complexity.rb +32 -0
  33. data/lib/rubocop/cop/mixin/negative_conditional.rb +1 -1
  34. data/lib/rubocop/cop/mixin/{check_methods.rb → on_method.rb} +3 -3
  35. data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +24 -0
  36. data/lib/rubocop/cop/mixin/percent_literal.rb +2 -1
  37. data/lib/rubocop/cop/mixin/space_inside.rb +33 -4
  38. data/lib/rubocop/cop/mixin/statement_modifier.rb +14 -14
  39. data/lib/rubocop/cop/mixin/string_help.rb +4 -0
  40. data/lib/rubocop/cop/mixin/surrounding_space.rb +1 -0
  41. data/lib/rubocop/cop/rails/delegate.rb +2 -2
  42. data/lib/rubocop/cop/rails/output.rb +4 -2
  43. data/lib/rubocop/cop/style/accessor_method_name.rb +2 -2
  44. data/lib/rubocop/cop/style/align_hash.rb +9 -1
  45. data/lib/rubocop/cop/style/and_or.rb +37 -3
  46. data/lib/rubocop/cop/style/bare_percent_literals.rb +46 -0
  47. data/lib/rubocop/cop/style/block_end_newline.rb +56 -0
  48. data/lib/rubocop/cop/style/character_literal.rb +1 -1
  49. data/lib/rubocop/cop/style/def_with_parentheses.rb +2 -2
  50. data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +31 -3
  51. data/lib/rubocop/cop/style/empty_lines_around_body.rb +6 -2
  52. data/lib/rubocop/cop/style/end_of_line.rb +3 -14
  53. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -6
  54. data/lib/rubocop/cop/style/if_with_semicolon.rb +6 -7
  55. data/lib/rubocop/cop/style/indentation_width.rb +3 -8
  56. data/lib/rubocop/cop/style/method_def_parentheses.rb +2 -2
  57. data/lib/rubocop/cop/style/method_name.rb +4 -18
  58. data/lib/rubocop/cop/style/multiline_block_layout.rb +73 -0
  59. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -4
  60. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  61. data/lib/rubocop/cop/style/negated_while.rb +2 -2
  62. data/lib/rubocop/cop/style/next.rb +12 -0
  63. data/lib/rubocop/cop/style/one_line_conditional.rb +6 -6
  64. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +22 -8
  65. data/lib/rubocop/cop/style/percent_q_literals.rb +53 -0
  66. data/lib/rubocop/cop/style/predicate_name.rb +2 -2
  67. data/lib/rubocop/cop/style/redundant_begin.rb +2 -2
  68. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  69. data/lib/rubocop/cop/style/rescue_modifier.rb +7 -3
  70. data/lib/rubocop/cop/style/single_line_methods.rb +2 -2
  71. data/lib/rubocop/cop/style/space_after_method_name.rb +2 -2
  72. data/lib/rubocop/cop/style/space_inside_block_braces.rb +14 -10
  73. data/lib/rubocop/cop/style/space_inside_brackets.rb +5 -1
  74. data/lib/rubocop/cop/style/string_literals.rb +5 -8
  75. data/lib/rubocop/cop/style/trailing_comma.rb +15 -3
  76. data/lib/rubocop/cop/style/trivial_accessors.rb +2 -2
  77. data/lib/rubocop/cop/style/unneeded_capital_w.rb +2 -4
  78. data/lib/rubocop/cop/style/unneeded_percent_q.rb +13 -0
  79. data/lib/rubocop/cop/style/variable_interpolation.rb +14 -2
  80. data/lib/rubocop/cop/style/variable_name.rb +17 -17
  81. data/lib/rubocop/cop/style/while_until_modifier.rb +2 -5
  82. data/lib/rubocop/cop/util.rb +5 -0
  83. data/lib/rubocop/cop/variable_force.rb +7 -6
  84. data/lib/rubocop/formatter/base_formatter.rb +2 -2
  85. data/lib/rubocop/processed_source.rb +5 -22
  86. data/lib/rubocop/version.rb +1 -1
  87. data/relnotes/v0.25.0.md +91 -0
  88. data/rubocop.gemspec +2 -3
  89. data/spec/project_spec.rb +1 -1
  90. data/spec/rubocop/cli_spec.rb +70 -44
  91. data/spec/rubocop/comment_config_spec.rb +6 -6
  92. data/spec/rubocop/config_loader_spec.rb +19 -13
  93. data/spec/rubocop/config_spec.rb +3 -3
  94. data/spec/rubocop/cop/commissioner_spec.rb +1 -1
  95. data/spec/rubocop/cop/cop_spec.rb +3 -3
  96. data/spec/rubocop/cop/lint/block_alignment_spec.rb +113 -6
  97. data/spec/rubocop/cop/lint/debugger_spec.rb +10 -6
  98. data/spec/rubocop/cop/lint/useless_assignment_spec.rb +12 -0
  99. data/spec/rubocop/cop/{style → metrics}/block_nesting_spec.rb +1 -1
  100. data/spec/rubocop/cop/{style → metrics}/class_length_spec.rb +1 -1
  101. data/spec/rubocop/cop/{style → metrics}/cyclomatic_complexity_spec.rb +1 -1
  102. data/spec/rubocop/cop/{style → metrics}/if_unless_modifier_spec.rb +2 -2
  103. data/spec/rubocop/cop/{style → metrics}/line_length_spec.rb +7 -7
  104. data/spec/rubocop/cop/{style → metrics}/method_length_spec.rb +1 -1
  105. data/spec/rubocop/cop/{style → metrics}/parameter_lists_spec.rb +1 -1
  106. data/spec/rubocop/cop/metrics/perceived_complexity_spec.rb +222 -0
  107. data/spec/rubocop/cop/{style → metrics}/while_until_modifier_spec.rb +2 -2
  108. data/spec/rubocop/cop/rails/output_spec.rb +8 -2
  109. data/spec/rubocop/cop/style/align_hash_spec.rb +7 -0
  110. data/spec/rubocop/cop/style/and_or_spec.rb +245 -43
  111. data/spec/rubocop/cop/style/bare_percent_literals_spec.rb +132 -0
  112. data/spec/rubocop/cop/style/block_end_newline_spec.rb +61 -0
  113. data/spec/rubocop/cop/style/empty_lines_around_access_modifier_spec.rb +34 -0
  114. data/spec/rubocop/cop/style/end_of_line_spec.rb +8 -0
  115. data/spec/rubocop/cop/style/guard_clause_spec.rb +1 -1
  116. data/spec/rubocop/cop/style/multiline_block_layout_spec.rb +138 -0
  117. data/spec/rubocop/cop/style/next_spec.rb +32 -3
  118. data/spec/rubocop/cop/style/percent_literal_delimiters_spec.rb +34 -0
  119. data/spec/rubocop/cop/style/percent_q_literals_spec.rb +122 -0
  120. data/spec/rubocop/cop/style/space_inside_block_braces_spec.rb +20 -0
  121. data/spec/rubocop/cop/style/space_inside_brackets_spec.rb +26 -2
  122. data/spec/rubocop/cop/style/trailing_comma_spec.rb +112 -0
  123. data/spec/rubocop/cop/style/unneeded_percent_q_spec.rb +86 -31
  124. data/spec/rubocop/cop/style/variable_interpolation_spec.rb +21 -1
  125. data/spec/rubocop/cop/team_spec.rb +14 -9
  126. data/spec/spec_helper.rb +1 -0
  127. metadata +47 -50
  128. data/lib/rubocop/cop/mixin/if_then_else.rb +0 -23
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe RuboCop::Cop::Style::BlockEndNewline do
6
+ subject(:cop) { described_class.new }
7
+
8
+ it 'does not register an offense for a one-liner' do
9
+ inspect_source(cop, ['test do foo end'])
10
+ expect(cop.messages).to be_empty
11
+ end
12
+
13
+ it 'does not register an offense for multiline blocks with newlines before '\
14
+ 'the end' do
15
+ inspect_source(cop,
16
+ ['test do',
17
+ ' foo',
18
+ 'end'])
19
+ expect(cop.messages).to be_empty
20
+ end
21
+
22
+ it 'registers an offense when multiline block end is not on its own line' do
23
+ inspect_source(cop,
24
+ ['test do',
25
+ ' foo end'
26
+ ])
27
+ expect(cop.messages)
28
+ .to eq(['Expression at 2, 7 should be on its own line.'])
29
+ end
30
+
31
+ it 'registers an offense when multiline block } is not on its own line' do
32
+ inspect_source(cop,
33
+ ['test {',
34
+ ' foo }'
35
+ ])
36
+ expect(cop.messages)
37
+ .to eq(['Expression at 2, 7 should be on its own line.'])
38
+ end
39
+
40
+ it 'autocorrects a do/end block where the end is not on its own line' do
41
+ src = ['test do',
42
+ ' foo end']
43
+
44
+ new_source = autocorrect_source(cop, src)
45
+
46
+ expect(new_source).to eq(['test do',
47
+ ' foo ',
48
+ 'end'].join("\n"))
49
+ end
50
+
51
+ it 'autocorrects a {} block where the } is not on its own line' do
52
+ src = ['test {',
53
+ ' foo }']
54
+
55
+ new_source = autocorrect_source(cop, src)
56
+
57
+ expect(new_source).to eq(['test {',
58
+ ' foo ',
59
+ '}'].join("\n"))
60
+ end
61
+ end
@@ -32,6 +32,40 @@ describe RuboCop::Cop::Style::EmptyLinesAroundAccessModifier do
32
32
  .to eq(["Keep a blank line before and after `#{access_modifier}`."])
33
33
  end
34
34
 
35
+ it "autocorrects blank line before #{access_modifier}" do
36
+ corrected = autocorrect_source(cop,
37
+ ['class Test',
38
+ ' something',
39
+ " #{access_modifier}",
40
+ '',
41
+ ' def test; end',
42
+ 'end'])
43
+ expect(corrected).to eq(['class Test',
44
+ ' something',
45
+ '',
46
+ " #{access_modifier}",
47
+ '',
48
+ ' def test; end',
49
+ 'end'].join("\n"))
50
+ end
51
+
52
+ it 'autocorrects blank line after #{access_modifier}' do
53
+ corrected = autocorrect_source(cop,
54
+ ['class Test',
55
+ ' something',
56
+ '',
57
+ " #{access_modifier}",
58
+ ' def test; end',
59
+ 'end'])
60
+ expect(corrected).to eq(['class Test',
61
+ ' something',
62
+ '',
63
+ " #{access_modifier}",
64
+ '',
65
+ ' def test; end',
66
+ 'end'].join("\n"))
67
+ end
68
+
35
69
  it 'accepts missing blank line when at the beginning of class/module' do
36
70
  inspect_source(cop,
37
71
  ['class Test',
@@ -54,4 +54,12 @@ describe RuboCop::Cop::Style::EndOfLine do
54
54
 
55
55
  include_examples 'iso-8859-15'
56
56
  end
57
+
58
+ context 'when source is a string' do
59
+ it 'registers an offence' do
60
+ inspect_source(cop, ["x=0\r"])
61
+
62
+ expect(cop.messages).to eq(['Carriage return character detected.'])
63
+ end
64
+ end
57
65
  end
@@ -102,7 +102,7 @@ describe RuboCop::Cop::Style::GuardClause, :config do
102
102
 
103
103
  context 'MinBodyLength: 1' do
104
104
  let(:cop_config) do
105
- { 'EnforcedStyle' => 'MinBodyLength: 1' }
105
+ { 'MinBodyLength' => 1 }
106
106
  end
107
107
 
108
108
  it 'reports an offense for if whose body has 1 line' do
@@ -0,0 +1,138 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe RuboCop::Cop::Style::MultilineBlockLayout do
6
+ subject(:cop) { described_class.new }
7
+
8
+ it 'registers an offense for missing newline in do/end block w/o params' do
9
+ inspect_source(cop,
10
+ ['test do foo',
11
+ 'end'
12
+ ])
13
+ expect(cop.messages)
14
+ .to eq(['Block body expression is on the same line as the block start.'])
15
+ end
16
+
17
+ it 'registers an offense for missing newline in {} block w/o params' do
18
+ inspect_source(cop,
19
+ ['test { foo',
20
+ '}'
21
+ ])
22
+ expect(cop.messages)
23
+ .to eq(['Block body expression is on the same line as the block start.'])
24
+ end
25
+
26
+ it 'registers an offense for missing newline in do/end block with params' do
27
+ inspect_source(cop,
28
+ ['test do |x| foo',
29
+ 'end'
30
+ ])
31
+ expect(cop.messages)
32
+ .to eq(['Block body expression is on the same line as the block start.'])
33
+ end
34
+
35
+ it 'registers an offense for missing newline in {} block with params' do
36
+ inspect_source(cop,
37
+ ['test { |x| foo',
38
+ '}'
39
+ ])
40
+ expect(cop.messages)
41
+ .to eq(['Block body expression is on the same line as the block start.'])
42
+ end
43
+
44
+ it 'does not register an offense for one-line do/end blocks' do
45
+ inspect_source(cop, 'test do foo end')
46
+ expect(cop.offenses).to be_empty
47
+ end
48
+
49
+ it 'does not register an offense for one-line {} blocks' do
50
+ inspect_source(cop, 'test { foo }')
51
+ expect(cop.offenses).to be_empty
52
+ end
53
+
54
+ it 'does not register offenses when there is a newline for do/end block' do
55
+ inspect_source(cop,
56
+ ['test do',
57
+ ' foo',
58
+ 'end'
59
+ ])
60
+ expect(cop.offenses).to be_empty
61
+ end
62
+
63
+ it 'does not error out when the block is empty' do
64
+ inspect_source(cop,
65
+ ['test do |x|',
66
+ 'end'
67
+ ])
68
+ expect(cop.offenses).to be_empty
69
+ end
70
+
71
+ it 'does not register offenses when there is a newline for {} block' do
72
+ inspect_source(cop,
73
+ ['test {',
74
+ ' foo',
75
+ '}'
76
+ ])
77
+ expect(cop.offenses).to be_empty
78
+ end
79
+
80
+ it 'registers offenses for lambdas as expected' do
81
+ inspect_source(cop,
82
+ ['-> (x) do foo',
83
+ ' bar',
84
+ 'end'
85
+ ])
86
+ expect(cop.messages)
87
+ .to eq(['Block body expression is on the same line as the block start.'])
88
+ end
89
+
90
+ it 'auto-corrects a do/end block with params that is missing newlines' do
91
+ src = ['test do |foo| bar',
92
+ 'end']
93
+
94
+ new_source = autocorrect_source(cop, src)
95
+
96
+ expect(new_source).to eq(['test do |foo| ',
97
+ ' bar',
98
+ 'end'].join("\n"))
99
+ end
100
+
101
+ it 'auto-corrects a do/end block with a mult-line body' do
102
+ src = ['test do |foo| bar',
103
+ ' test',
104
+ 'end']
105
+
106
+ new_source = autocorrect_source(cop, src)
107
+
108
+ expect(new_source).to eq(['test do |foo| ',
109
+ ' bar',
110
+ ' test',
111
+ 'end'].join("\n"))
112
+ end
113
+
114
+ it 'auto-corrects a {} block with params that is missing newlines' do
115
+ src = ['test { |foo| bar',
116
+ '}']
117
+
118
+ new_source = autocorrect_source(cop, src)
119
+
120
+ expect(new_source).to eq(['test { |foo| ',
121
+ ' bar',
122
+ '}'].join("\n"))
123
+ end
124
+
125
+ it 'autocorrects in more complex case with lambda and assignment, and '\
126
+ 'aligns the next line two spaces out from the start of the block' do
127
+ src = ['x = -> (y) { foo',
128
+ ' bar',
129
+ '}']
130
+
131
+ new_source = autocorrect_source(cop, src)
132
+
133
+ expect(new_source).to eq(['x = -> (y) { ',
134
+ ' foo',
135
+ ' bar',
136
+ '}'].join("\n"))
137
+ end
138
+ end
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
 
5
5
  describe RuboCop::Cop::Style::Next, :config do
6
6
  subject(:cop) { described_class.new(config) }
7
- let(:cop_config) { {} }
7
+ let(:cop_config) { { 'MinBodyLength' => 1 } }
8
8
 
9
9
  it 'finds all kind of loops with condition at the end of the iteration' do
10
10
  # TODO: Split this long example into multiple examples.
@@ -173,7 +173,7 @@ describe RuboCop::Cop::Style::Next, :config do
173
173
  { 'EnforcedStyle' => 'always' }
174
174
  end
175
175
 
176
- it 'ignores modifier ifs' do
176
+ it 'does not ignore modifier ifs' do
177
177
  inspect_source(cop,
178
178
  ['[].each do |o|',
179
179
  ' puts o if o == 1',
@@ -251,6 +251,35 @@ describe RuboCop::Cop::Style::Next, :config do
251
251
  ' if true',
252
252
  ' end',
253
253
  'end'])
254
- expect(cop.offenses.size).to eq(1)
254
+ expect(cop.offenses).to be_empty
255
+ end
256
+
257
+ context 'MinBodyLength: 3' do
258
+ let(:cop_config) do
259
+ { 'MinBodyLength' => 3 }
260
+ end
261
+
262
+ it 'accepts if whose body has 1 line' do
263
+ inspect_source(cop,
264
+ ['arr.each do |e|',
265
+ ' if something',
266
+ ' work',
267
+ ' end',
268
+ 'end'])
269
+ expect(cop.offenses).to be_empty
270
+ end
271
+
272
+ it 'reports an offense for if whose body has 3 lines' do
273
+ inspect_source(cop,
274
+ ['arr.each do |e|',
275
+ ' if something',
276
+ ' work',
277
+ ' work',
278
+ ' work',
279
+ ' end',
280
+ 'end'])
281
+ expect(cop.offenses.size).to eq(1)
282
+ expect(cop.highlights).to eq(['each'])
283
+ end
255
284
  end
256
285
  end
@@ -258,5 +258,39 @@ describe RuboCop::Cop::Style::PercentLiteralDelimiters, :config do
258
258
  new_source = autocorrect_source(cop, ['%w(', 'some', 'words', ')'])
259
259
  expect(new_source).to eq("%w[\nsome\nwords\n]")
260
260
  end
261
+
262
+ it 'preserves indentation when correcting a multiline array' do
263
+ original_source = [
264
+ ' array = %w(',
265
+ ' first',
266
+ ' second',
267
+ ' )'
268
+ ]
269
+ corrected_source = [
270
+ ' array = %w[',
271
+ ' first',
272
+ ' second',
273
+ ' ]'
274
+ ].join("\n")
275
+ new_source = autocorrect_source(cop, original_source)
276
+ expect(new_source).to eq(corrected_source)
277
+ end
278
+
279
+ it 'preserves irregular indentation when correcting a multiline array' do
280
+ original_source = [
281
+ ' array = %w(',
282
+ ' first',
283
+ ' second',
284
+ ')'
285
+ ]
286
+ corrected_source = [
287
+ ' array = %w[',
288
+ ' first',
289
+ ' second',
290
+ ']'
291
+ ].join("\n")
292
+ new_source = autocorrect_source(cop, original_source)
293
+ expect(new_source).to eq(corrected_source)
294
+ end
261
295
  end
262
296
  end
@@ -0,0 +1,122 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe RuboCop::Cop::Style::PercentQLiterals, :config do
6
+ subject(:cop) { described_class.new(config) }
7
+
8
+ shared_examples 'accepts quote characters' do
9
+ it 'accepts single quotes' do
10
+ inspect_source(cop, ["'hi'"])
11
+ expect(cop.offenses).to be_empty
12
+ end
13
+
14
+ it 'accepts double quotes' do
15
+ inspect_source(cop, ['"hi"'])
16
+ expect(cop.offenses).to be_empty
17
+ end
18
+ end
19
+
20
+ shared_examples 'accepts any q string with backslash t' do
21
+ context 'with special characters' do
22
+ it 'accepts %q' do
23
+ inspect_source(cop, ['%q(\t)'])
24
+ expect(cop.offenses).to be_empty
25
+ end
26
+
27
+ it 'accepts %Q' do
28
+ inspect_source(cop, ['%Q(\t)'])
29
+ expect(cop.offenses).to be_empty
30
+ end
31
+ end
32
+ end
33
+
34
+ context 'when EnforcedStyle is lower_case_q' do
35
+ let(:cop_config) { { 'EnforcedStyle' => 'lower_case_q' } }
36
+
37
+ context 'without interpolation' do
38
+ it 'accepts %q' do
39
+ inspect_source(cop, ['%q(hi)'])
40
+ expect(cop.offenses).to be_empty
41
+ end
42
+
43
+ it 'registers offense for %Q' do
44
+ inspect_source(cop, ['%Q(hi)'])
45
+ expect(cop.messages)
46
+ .to eq(['Do not use `%Q` unless interpolation is needed. Use `%q`.'])
47
+ expect(cop.highlights).to eq(['%Q('])
48
+ end
49
+
50
+ it 'auto-corrects' do
51
+ new_source = autocorrect_source(cop, '%Q(hi)')
52
+ expect(new_source).to eq('%q(hi)')
53
+ end
54
+
55
+ include_examples 'accepts quote characters'
56
+ include_examples 'accepts any q string with backslash t'
57
+ end
58
+
59
+ context 'with interpolation' do
60
+ it 'accepts %Q' do
61
+ inspect_source(cop, ['%Q(#{1 + 2})'])
62
+ expect(cop.offenses).to be_empty
63
+ end
64
+
65
+ it 'accepts %q' do
66
+ # This is most probably a mistake, but not this cop's responisibility.
67
+ inspect_source(cop, ['%q(#{1 + 2})'])
68
+ expect(cop.offenses).to be_empty
69
+ end
70
+
71
+ include_examples 'accepts quote characters'
72
+ end
73
+ end
74
+
75
+ context 'when EnforcedStyle is upper_case_q' do
76
+ let(:cop_config) { { 'EnforcedStyle' => 'upper_case_q' } }
77
+
78
+ context 'without interpolation' do
79
+ it 'registers offense for %q' do
80
+ inspect_source(cop, ['%q(hi)'])
81
+ expect(cop.messages).to eq(['Use `%Q` instead of `%q`.'])
82
+ expect(cop.highlights).to eq(['%q('])
83
+ end
84
+
85
+ it 'accepts %Q' do
86
+ inspect_source(cop, ['%Q(hi)'])
87
+ expect(cop.offenses).to be_empty
88
+ end
89
+
90
+ it 'auto-corrects' do
91
+ new_source = autocorrect_source(cop, '%q[hi]')
92
+ expect(new_source).to eq('%Q[hi]')
93
+ end
94
+
95
+ include_examples 'accepts quote characters'
96
+ include_examples 'accepts any q string with backslash t'
97
+ end
98
+
99
+ context 'with interpolation' do
100
+ it 'accepts %Q' do
101
+ inspect_source(cop, ['%Q(#{1 + 2})'])
102
+ expect(cop.offenses).to be_empty
103
+ end
104
+
105
+ it 'accepts %q' do
106
+ # It's strange if interpolation syntax appears inside a static string,
107
+ # but we can't be sure if it's a mistake or not. Changing it to %Q
108
+ # would alter semantics, so we leave it as it is.
109
+ inspect_source(cop, ['%q(#{1 + 2})'])
110
+ expect(cop.offenses).to be_empty
111
+ end
112
+
113
+ it 'does not auto-correct' do
114
+ source = '%q(#{1 + 2})'
115
+ new_source = autocorrect_source(cop, source)
116
+ expect(new_source).to eq(source)
117
+ end
118
+
119
+ include_examples 'accepts quote characters'
120
+ end
121
+ end
122
+ end