ridecharge-rubocop 0.0.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.
Files changed (219) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +14 -0
  5. data/CHANGELOG.md +0 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +35 -0
  9. data/Rakefile +22 -0
  10. data/bin/ridecharge-rubocop +49 -0
  11. data/config/0default.yml +8 -0
  12. data/config/fleet-magic-todo.yml +380 -0
  13. data/config/rc-todo.yml +190 -0
  14. data/config/ridecharge-rubocop_todo.yml +73 -0
  15. data/config/rubocop/default.yml +308 -0
  16. data/config/rubocop/disabled.yml +9 -0
  17. data/config/rubocop/enabled.yml +648 -0
  18. data/config/standard-todo.yml +24 -0
  19. data/config/tabs.yml +15 -0
  20. data/config/vehicle-todo.yml +195 -0
  21. data/lib/ridecharge/rubocop.rb +2 -0
  22. data/lib/ridecharge/rubocop/version.rb +5 -0
  23. data/lib/rubocop/config_loader_monkeypatch.rb +117 -0
  24. data/lib/rubocop/ridecharge.rb +1 -0
  25. data/ridecharge-rubocop.gemspec +25 -0
  26. data/spec/isolated_environment_spec.rb +24 -0
  27. data/spec/project_spec.rb +118 -0
  28. data/spec/rubocop/cli_spec.rb +1385 -0
  29. data/spec/rubocop/config_loader_spec.rb +328 -0
  30. data/spec/rubocop/config_spec.rb +179 -0
  31. data/spec/rubocop/config_store_spec.rb +53 -0
  32. data/spec/rubocop/cop/commissioner_spec.rb +83 -0
  33. data/spec/rubocop/cop/cop_spec.rb +114 -0
  34. data/spec/rubocop/cop/corrector_spec.rb +59 -0
  35. data/spec/rubocop/cop/lint/ambiguous_operator_spec.rb +113 -0
  36. data/spec/rubocop/cop/lint/ambiguous_regexp_literal_spec.rb +35 -0
  37. data/spec/rubocop/cop/lint/assignment_in_condition_spec.rb +107 -0
  38. data/spec/rubocop/cop/lint/block_alignment_spec.rb +411 -0
  39. data/spec/rubocop/cop/lint/condition_position_spec.rb +49 -0
  40. data/spec/rubocop/cop/lint/debugger_spec.rb +39 -0
  41. data/spec/rubocop/cop/lint/else_layout_spec.rb +65 -0
  42. data/spec/rubocop/cop/lint/empty_ensure_spec.rb +27 -0
  43. data/spec/rubocop/cop/lint/end_alignment_spec.rb +136 -0
  44. data/spec/rubocop/cop/lint/end_in_method_spec.rb +29 -0
  45. data/spec/rubocop/cop/lint/ensure_return_spec.rb +39 -0
  46. data/spec/rubocop/cop/lint/eval_spec.rb +35 -0
  47. data/spec/rubocop/cop/lint/handle_exceptions_spec.rb +30 -0
  48. data/spec/rubocop/cop/lint/invalid_character_literal_spec.rb +33 -0
  49. data/spec/rubocop/cop/lint/literal_in_condition_spec.rb +63 -0
  50. data/spec/rubocop/cop/lint/loop_spec.rb +27 -0
  51. data/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb +57 -0
  52. data/spec/rubocop/cop/lint/require_parentheses_spec.rb +82 -0
  53. data/spec/rubocop/cop/lint/rescue_exception_spec.rb +131 -0
  54. data/spec/rubocop/cop/lint/shadowing_outer_local_variable_spec.rb +237 -0
  55. data/spec/rubocop/cop/lint/syntax_spec.rb +34 -0
  56. data/spec/rubocop/cop/lint/unreachable_code_spec.rb +63 -0
  57. data/spec/rubocop/cop/lint/useless_assignment_spec.rb +1570 -0
  58. data/spec/rubocop/cop/lint/useless_comparison_spec.rb +30 -0
  59. data/spec/rubocop/cop/lint/useless_else_without_rescue_spec.rb +48 -0
  60. data/spec/rubocop/cop/lint/useless_setter_call_spec.rb +149 -0
  61. data/spec/rubocop/cop/lint/void_spec.rb +57 -0
  62. data/spec/rubocop/cop/offence_spec.rb +133 -0
  63. data/spec/rubocop/cop/rails/default_scope_spec.rb +37 -0
  64. data/spec/rubocop/cop/rails/has_and_belongs_to_many_spec.rb +13 -0
  65. data/spec/rubocop/cop/rails/output_spec.rb +41 -0
  66. data/spec/rubocop/cop/rails/read_attribute_spec.rb +13 -0
  67. data/spec/rubocop/cop/rails/validation_spec.rb +21 -0
  68. data/spec/rubocop/cop/style/access_modifier_indentation_spec.rb +361 -0
  69. data/spec/rubocop/cop/style/accessor_method_name_spec.rb +81 -0
  70. data/spec/rubocop/cop/style/alias_spec.rb +59 -0
  71. data/spec/rubocop/cop/style/align_array_spec.rb +75 -0
  72. data/spec/rubocop/cop/style/align_hash_spec.rb +310 -0
  73. data/spec/rubocop/cop/style/align_parameters_spec.rb +222 -0
  74. data/spec/rubocop/cop/style/and_or_spec.rb +57 -0
  75. data/spec/rubocop/cop/style/ascii_comments_spec.rb +22 -0
  76. data/spec/rubocop/cop/style/ascii_identifiers_spec.rb +36 -0
  77. data/spec/rubocop/cop/style/attr_spec.rb +19 -0
  78. data/spec/rubocop/cop/style/begin_block_spec.rb +13 -0
  79. data/spec/rubocop/cop/style/block_comments_spec.rb +21 -0
  80. data/spec/rubocop/cop/style/block_nesting_spec.rb +156 -0
  81. data/spec/rubocop/cop/style/blocks_spec.rb +99 -0
  82. data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +284 -0
  83. data/spec/rubocop/cop/style/case_equality_spec.rb +12 -0
  84. data/spec/rubocop/cop/style/case_indentation_spec.rb +289 -0
  85. data/spec/rubocop/cop/style/character_literal_spec.rb +37 -0
  86. data/spec/rubocop/cop/style/class_and_module_camel_case_spec.rb +40 -0
  87. data/spec/rubocop/cop/style/class_length_spec.rb +131 -0
  88. data/spec/rubocop/cop/style/class_methods_spec.rb +45 -0
  89. data/spec/rubocop/cop/style/class_vars_spec.rb +19 -0
  90. data/spec/rubocop/cop/style/collection_methods_spec.rb +48 -0
  91. data/spec/rubocop/cop/style/colon_method_call_spec.rb +60 -0
  92. data/spec/rubocop/cop/style/comment_annotation_spec.rb +86 -0
  93. data/spec/rubocop/cop/style/constant_name_spec.rb +65 -0
  94. data/spec/rubocop/cop/style/cyclomatic_complexity_spec.rb +204 -0
  95. data/spec/rubocop/cop/style/def_with_parentheses_spec.rb +39 -0
  96. data/spec/rubocop/cop/style/documentation_spec.rb +123 -0
  97. data/spec/rubocop/cop/style/dot_position_spec.rb +94 -0
  98. data/spec/rubocop/cop/style/empty_line_between_defs_spec.rb +127 -0
  99. data/spec/rubocop/cop/style/empty_lines_around_access_modifier_spec.rb +56 -0
  100. data/spec/rubocop/cop/style/empty_lines_around_body_spec.rb +131 -0
  101. data/spec/rubocop/cop/style/empty_lines_spec.rb +40 -0
  102. data/spec/rubocop/cop/style/empty_literal_spec.rb +100 -0
  103. data/spec/rubocop/cop/style/encoding_spec.rb +56 -0
  104. data/spec/rubocop/cop/style/end_block_spec.rb +13 -0
  105. data/spec/rubocop/cop/style/end_of_line_spec.rb +47 -0
  106. data/spec/rubocop/cop/style/even_odd_spec.rb +75 -0
  107. data/spec/rubocop/cop/style/favor_join_spec.rb +31 -0
  108. data/spec/rubocop/cop/style/favor_sprintf_spec.rb +47 -0
  109. data/spec/rubocop/cop/style/favor_unless_over_negated_if_spec.rb +76 -0
  110. data/spec/rubocop/cop/style/favor_until_over_negated_while_spec.rb +41 -0
  111. data/spec/rubocop/cop/style/final_newline_spec.rb +30 -0
  112. data/spec/rubocop/cop/style/flip_flop_spec.rb +23 -0
  113. data/spec/rubocop/cop/style/for_spec.rb +105 -0
  114. data/spec/rubocop/cop/style/global_vars_spec.rb +34 -0
  115. data/spec/rubocop/cop/style/hash_methods_spec.rb +45 -0
  116. data/spec/rubocop/cop/style/hash_syntax_spec.rb +131 -0
  117. data/spec/rubocop/cop/style/if_unless_modifier_spec.rb +128 -0
  118. data/spec/rubocop/cop/style/if_with_semicolon_spec.rb +19 -0
  119. data/spec/rubocop/cop/style/indentation_consistency_spec.rb +490 -0
  120. data/spec/rubocop/cop/style/indentation_width_spec.rb +470 -0
  121. data/spec/rubocop/cop/style/lambda_call_spec.rb +65 -0
  122. data/spec/rubocop/cop/style/lambda_spec.rb +41 -0
  123. data/spec/rubocop/cop/style/leading_comment_space_spec.rb +64 -0
  124. data/spec/rubocop/cop/style/line_end_concatenation_spec.rb +34 -0
  125. data/spec/rubocop/cop/style/line_length_spec.rb +20 -0
  126. data/spec/rubocop/cop/style/method_call_parentheses_spec.rb +59 -0
  127. data/spec/rubocop/cop/style/method_called_on_do_end_block_spec.rb +60 -0
  128. data/spec/rubocop/cop/style/method_def_parentheses_spec.rb +106 -0
  129. data/spec/rubocop/cop/style/method_length_spec.rb +147 -0
  130. data/spec/rubocop/cop/style/method_name_spec.rb +125 -0
  131. data/spec/rubocop/cop/style/module_function_spec.rb +24 -0
  132. data/spec/rubocop/cop/style/multiline_block_chain_spec.rb +78 -0
  133. data/spec/rubocop/cop/style/multiline_if_then_spec.rb +107 -0
  134. data/spec/rubocop/cop/style/multiline_ternary_operator_spec.rb +18 -0
  135. data/spec/rubocop/cop/style/nested_ternary_operator_spec.rb +21 -0
  136. data/spec/rubocop/cop/style/nil_comparison_spec.rb +30 -0
  137. data/spec/rubocop/cop/style/not_spec.rb +22 -0
  138. data/spec/rubocop/cop/style/numeric_literals_spec.rb +64 -0
  139. data/spec/rubocop/cop/style/one_line_conditional_spec.rb +13 -0
  140. data/spec/rubocop/cop/style/op_method_spec.rb +74 -0
  141. data/spec/rubocop/cop/style/parameter_lists_spec.rb +44 -0
  142. data/spec/rubocop/cop/style/parentheses_around_condition_spec.rb +122 -0
  143. data/spec/rubocop/cop/style/perl_backrefs_spec.rb +17 -0
  144. data/spec/rubocop/cop/style/predicate_name_spec.rb +25 -0
  145. data/spec/rubocop/cop/style/proc_spec.rb +27 -0
  146. data/spec/rubocop/cop/style/raise_args_spec.rb +82 -0
  147. data/spec/rubocop/cop/style/redundant_begin_spec.rb +57 -0
  148. data/spec/rubocop/cop/style/redundant_exception_spec.rb +27 -0
  149. data/spec/rubocop/cop/style/redundant_return_spec.rb +171 -0
  150. data/spec/rubocop/cop/style/redundant_self_spec.rb +142 -0
  151. data/spec/rubocop/cop/style/regexp_literal_spec.rb +83 -0
  152. data/spec/rubocop/cop/style/rescue_modifier_spec.rb +116 -0
  153. data/spec/rubocop/cop/style/semicolon_spec.rb +100 -0
  154. data/spec/rubocop/cop/style/signal_exception_spec.rb +266 -0
  155. data/spec/rubocop/cop/style/single_line_block_params_spec.rb +68 -0
  156. data/spec/rubocop/cop/style/single_line_methods_spec.rb +52 -0
  157. data/spec/rubocop/cop/style/space_after_colon_spec.rb +38 -0
  158. data/spec/rubocop/cop/style/space_after_comma_spec.rb +30 -0
  159. data/spec/rubocop/cop/style/space_after_control_keyword_spec.rb +84 -0
  160. data/spec/rubocop/cop/style/space_after_method_name_spec.rb +70 -0
  161. data/spec/rubocop/cop/style/space_after_not_spec.rb +22 -0
  162. data/spec/rubocop/cop/style/space_after_semicolon_spec.rb +23 -0
  163. data/spec/rubocop/cop/style/space_around_block_braces_spec.rb +283 -0
  164. data/spec/rubocop/cop/style/space_around_equals_in_parameter_default_spec.rb +33 -0
  165. data/spec/rubocop/cop/style/space_around_operators_spec.rb +325 -0
  166. data/spec/rubocop/cop/style/space_before_modifier_keyword_spec.rb +70 -0
  167. data/spec/rubocop/cop/style/space_inside_brackets_spec.rb +52 -0
  168. data/spec/rubocop/cop/style/space_inside_hash_literal_braces_spec.rb +138 -0
  169. data/spec/rubocop/cop/style/space_inside_parens_spec.rb +34 -0
  170. data/spec/rubocop/cop/style/special_global_vars_spec.rb +56 -0
  171. data/spec/rubocop/cop/style/string_literals_spec.rb +212 -0
  172. data/spec/rubocop/cop/style/symbol_array_spec.rb +37 -0
  173. data/spec/rubocop/cop/style/tab_spec.rb +17 -0
  174. data/spec/rubocop/cop/style/trailing_blank_lines_spec.rb +43 -0
  175. data/spec/rubocop/cop/style/trailing_comma_spec.rb +230 -0
  176. data/spec/rubocop/cop/style/trailing_whitespace_spec.rb +30 -0
  177. data/spec/rubocop/cop/style/trivial_accessors_spec.rb +415 -0
  178. data/spec/rubocop/cop/style/unless_else_spec.rb +25 -0
  179. data/spec/rubocop/cop/style/variable_interpolation_spec.rb +47 -0
  180. data/spec/rubocop/cop/style/variable_name_spec.rb +107 -0
  181. data/spec/rubocop/cop/style/when_then_spec.rb +41 -0
  182. data/spec/rubocop/cop/style/while_until_do_spec.rb +53 -0
  183. data/spec/rubocop/cop/style/while_until_modifier_spec.rb +75 -0
  184. data/spec/rubocop/cop/style/word_array_spec.rb +97 -0
  185. data/spec/rubocop/cop/team_spec.rb +156 -0
  186. data/spec/rubocop/cop/util_spec.rb +49 -0
  187. data/spec/rubocop/cop/variable_inspector/assignment_spec.rb +213 -0
  188. data/spec/rubocop/cop/variable_inspector/locatable_spec.rb +734 -0
  189. data/spec/rubocop/cop/variable_inspector/scope_spec.rb +184 -0
  190. data/spec/rubocop/cop/variable_inspector/variable_spec.rb +73 -0
  191. data/spec/rubocop/cop/variable_inspector/variable_table_spec.rb +269 -0
  192. data/spec/rubocop/cop/variable_inspector_spec.rb +29 -0
  193. data/spec/rubocop/file_inspector_spec.rb +78 -0
  194. data/spec/rubocop/formatter/base_formatter_spec.rb +191 -0
  195. data/spec/rubocop/formatter/clang_style_formatter_spec.rb +114 -0
  196. data/spec/rubocop/formatter/colorizable_spec.rb +107 -0
  197. data/spec/rubocop/formatter/disabled_config_formatter_spec.rb +50 -0
  198. data/spec/rubocop/formatter/emacs_style_formatter_spec.rb +62 -0
  199. data/spec/rubocop/formatter/file_list_formatter_spec.rb +33 -0
  200. data/spec/rubocop/formatter/formatter_set_spec.rb +132 -0
  201. data/spec/rubocop/formatter/json_formatter_spec.rb +148 -0
  202. data/spec/rubocop/formatter/offence_count_formatter_spec.rb +52 -0
  203. data/spec/rubocop/formatter/progress_formatter_spec.rb +182 -0
  204. data/spec/rubocop/formatter/simple_text_formatter_spec.rb +123 -0
  205. data/spec/rubocop/options_spec.rb +145 -0
  206. data/spec/rubocop/path_util_spec.rb +42 -0
  207. data/spec/rubocop/processed_source_spec.rb +114 -0
  208. data/spec/rubocop/source_parser_spec.rb +139 -0
  209. data/spec/rubocop/target_finder_spec.rb +180 -0
  210. data/spec/rubocop/token_spec.rb +25 -0
  211. data/spec/spec_helper.rb +136 -0
  212. data/spec/support/ast_helper.rb +15 -0
  213. data/spec/support/file_helper.rb +21 -0
  214. data/spec/support/isolated_environment.rb +34 -0
  215. data/spec/support/mri_syntax_checker.rb +73 -0
  216. data/spec/support/shared_context.rb +22 -0
  217. data/spec/support/shared_examples.rb +33 -0
  218. data/spec/support/statement_modifier_helper.rb +41 -0
  219. metadata +511 -0
@@ -0,0 +1,1385 @@
1
+ # encoding: utf-8
2
+
3
+ require 'fileutils'
4
+ require 'tmpdir'
5
+ require 'spec_helper'
6
+
7
+ describe Rubocop::CLI, :isolated_environment do
8
+ include FileHelper
9
+
10
+ subject(:cli) { described_class.new }
11
+
12
+ before(:each) do
13
+ $stdout = StringIO.new
14
+ $stderr = StringIO.new
15
+ Rubocop::ConfigLoader.debug = false
16
+ end
17
+
18
+ after(:each) do
19
+ $stdout = STDOUT
20
+ $stderr = STDERR
21
+ end
22
+
23
+ def abs(path)
24
+ File.expand_path(path)
25
+ end
26
+
27
+ describe 'option' do
28
+ describe '--version' do
29
+ it 'exits cleanly' do
30
+ expect { cli.run ['-v'] }.to exit_with_code(0)
31
+ expect { cli.run ['--version'] }.to exit_with_code(0)
32
+ expect($stdout.string).to eq((Rubocop::Version::STRING + "\n") * 2)
33
+ end
34
+ end
35
+
36
+ describe '--auto-correct' do
37
+ it 'can correct two problems with blocks' do
38
+ # {} should be do..end and space is missing.
39
+ create_file('example.rb', ['# encoding: utf-8',
40
+ '(1..10).each{ |i|',
41
+ ' puts i',
42
+ '}'])
43
+ expect(cli.run(['--auto-correct'])).to eq(1)
44
+ expect(IO.read('example.rb'))
45
+ .to eq(['# encoding: utf-8',
46
+ '(1..10).each do |i|',
47
+ ' puts i',
48
+ 'end'].join("\n") + "\n")
49
+ end
50
+
51
+ # In this example, the auto-correction (changing "raise" to "fail")
52
+ # creates a new problem (alignment of parameters), which is also
53
+ # corrected automatically.
54
+ it 'can correct a problems and the problem it creates' do
55
+ create_file('example.rb',
56
+ ['# encoding: utf-8',
57
+ 'raise NotImplementedError,',
58
+ " 'Method should be overridden in child classes'"])
59
+ expect(cli.run(['--auto-correct'])).to eq(1)
60
+ expect(IO.read('example.rb'))
61
+ .to eq(['# encoding: utf-8',
62
+ 'fail NotImplementedError,',
63
+ " 'Method should be overridden in child classes'"]
64
+ .join("\n") + "\n")
65
+ expect($stdout.string)
66
+ .to eq(['Inspecting 1 file',
67
+ 'C',
68
+ '',
69
+ 'Offences:',
70
+ '',
71
+ 'example.rb:2:1: C: [Corrected] Use `fail` instead of ' \
72
+ '`raise` to signal exceptions.',
73
+ 'raise NotImplementedError,',
74
+ '^^^^^',
75
+ 'example.rb:3:7: C: [Corrected] Align the parameters of a ' \
76
+ 'method call if they span more than one line.',
77
+ " 'Method should be overridden in child classes'",
78
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^',
79
+ '',
80
+ '1 file inspected, 2 offences detected, 2 offences ' \
81
+ 'corrected',
82
+ ''].join("\n"))
83
+ end
84
+
85
+ # Thanks to repeated auto-correction, we can get rid of the trailing
86
+ # spaces, and then the extra empty line.
87
+ it 'can correct two problems in the same place' do
88
+ create_file('example.rb',
89
+ ['# encoding: utf-8',
90
+ '# Example class.',
91
+ 'class Klass',
92
+ ' ',
93
+ ' def f',
94
+ ' end',
95
+ 'end'])
96
+ expect(cli.run(['--auto-correct'])).to eq(1)
97
+ expect(IO.read('example.rb'))
98
+ .to eq(['# encoding: utf-8',
99
+ '# Example class.',
100
+ 'class Klass',
101
+ ' def f',
102
+ ' end',
103
+ 'end'].join("\n") + "\n")
104
+ expect($stderr.string).to eq('')
105
+ expect($stdout.string)
106
+ .to eq(['Inspecting 1 file',
107
+ 'C',
108
+ '',
109
+ 'Offences:',
110
+ '',
111
+ 'example.rb:4:1: C: [Corrected] Trailing whitespace ' \
112
+ 'detected.',
113
+ 'example.rb:4:1: C: [Corrected] Extra empty line detected ' \
114
+ 'at body beginning.',
115
+ '',
116
+ '1 file inspected, 2 offences detected, 2 offences ' \
117
+ 'corrected',
118
+ ''].join("\n"))
119
+ end
120
+ end
121
+
122
+ describe '--auto-gen-config' do
123
+ it 'exits with error if asked to re-generate a todo list that is in ' \
124
+ 'use' do
125
+ create_file('example1.rb', ['# encoding: utf-8',
126
+ 'x= 0 ',
127
+ '#' * 85,
128
+ 'y ',
129
+ 'puts x'])
130
+ todo_contents = ['# This configuration was generated with `rubocop' \
131
+ ' --auto-gen-config`',
132
+ '',
133
+ 'LineLength:',
134
+ ' Enabled: false']
135
+ create_file('rubocop-todo.yml', todo_contents)
136
+ expect(IO.read('rubocop-todo.yml'))
137
+ .to eq(todo_contents.join("\n") + "\n")
138
+ create_file('.rubocop.yml', ['inherit_from: rubocop-todo.yml'])
139
+ expect(cli.run(['--auto-gen-config'])).to eq(1)
140
+ expect($stderr.string).to eq('Remove rubocop-todo.yml from the ' \
141
+ 'current configuration before ' +
142
+ "generating it again.\n")
143
+ end
144
+
145
+ it 'exits with error if file arguments are given' do
146
+ create_file('example1.rb', ['# encoding: utf-8',
147
+ 'x= 0 ',
148
+ '#' * 85,
149
+ 'y ',
150
+ 'puts x'])
151
+ expect(cli.run(['--auto-gen-config', 'example1.rb'])).to eq(1)
152
+ expect($stderr.string)
153
+ .to eq('--auto-gen-config can not be combined with any other ' \
154
+ "arguments.\n")
155
+ expect($stdout.string).to eq('')
156
+ end
157
+
158
+ it 'can generate a todo list' do
159
+ create_file('example1.rb', ['# encoding: utf-8',
160
+ '$x= 0 ',
161
+ '#' * 90,
162
+ '#' * 85,
163
+ 'y ',
164
+ 'puts x'])
165
+ create_file('example2.rb', ['# encoding: utf-8',
166
+ "\tx = 0",
167
+ 'puts x'])
168
+ expect(cli.run(['--auto-gen-config'])).to eq(1)
169
+ expect($stderr.string).to eq('')
170
+ expect($stdout.string)
171
+ .to include([
172
+ 'Created rubocop-todo.yml.',
173
+ 'Run rubocop with --config rubocop-todo.yml, or',
174
+ 'add inherit_from: rubocop-todo.yml in a ' \
175
+ '.rubocop.yml file.',
176
+ ''].join("\n"))
177
+ expected =
178
+ ['# This configuration was generated by `rubocop --auto-gen-config`',
179
+ /# on .* using RuboCop version .*/,
180
+ '# The point is for the user to remove these configuration records',
181
+ '# one by one as the offences are removed from the code base.',
182
+ '# Note that changes in the inspected code, or installation of new',
183
+ '# versions of RuboCop, may require this file to be generated ' \
184
+ 'again.',
185
+ '',
186
+ '# Offence count: 1',
187
+ '# Configuration parameters: AllowedVariables.',
188
+ 'GlobalVars:',
189
+ ' Enabled: false',
190
+ '',
191
+ '# Offence count: 1',
192
+ 'IndentationConsistency:',
193
+ ' Enabled: false',
194
+ '',
195
+ '# Offence count: 2',
196
+ 'LineLength:',
197
+ ' Max: 90',
198
+ '',
199
+ '# Offence count: 1',
200
+ '# Cop supports --auto-correct.',
201
+ 'SpaceAroundOperators:',
202
+ ' Enabled: false',
203
+ '',
204
+ '# Offence count: 1',
205
+ 'Tab:',
206
+ ' Enabled: false',
207
+ '',
208
+ '# Offence count: 2',
209
+ '# Cop supports --auto-correct.',
210
+ 'TrailingWhitespace:',
211
+ ' Enabled: false']
212
+ actual = IO.read('rubocop-todo.yml').split($RS)
213
+ expected.each_with_index do |line, ix|
214
+ if line.is_a?(String)
215
+ expect(actual[ix]).to eq(line)
216
+ else
217
+ expect(actual[ix]).to match(line)
218
+ end
219
+ end
220
+ end
221
+ end
222
+
223
+ describe '--only' do
224
+ it 'runs just one cop' do
225
+ create_file('example.rb', ['if x== 0 ',
226
+ "\ty",
227
+ 'end'])
228
+ # IfUnlessModifier depends on the configuration of LineLength.
229
+
230
+ expect(cli.run(['--format', 'simple',
231
+ '--only', 'IfUnlessModifier',
232
+ 'example.rb'])).to eq(1)
233
+ expect($stdout.string)
234
+ .to eq(['== example.rb ==',
235
+ 'C: 1: 1: Favor modifier if usage when you ' \
236
+ 'have a single-line body. Another good alternative is ' +
237
+ 'the usage of control flow &&/||.',
238
+ '',
239
+ '1 file inspected, 1 offence detected',
240
+ ''].join("\n"))
241
+ end
242
+ end
243
+
244
+ describe '--lint' do
245
+ it 'runs only lint cops' do
246
+ create_file('example.rb', ['if 0 ',
247
+ "\ty",
248
+ 'end'])
249
+ # IfUnlessModifier depends on the configuration of LineLength.
250
+
251
+ expect(cli.run(['--format', 'simple', '--lint',
252
+ 'example.rb'])).to eq(1)
253
+ expect($stdout.string)
254
+ .to eq(['== example.rb ==',
255
+ 'W: 1: 4: Literal 0 appeared in a condition.',
256
+ '',
257
+ '1 file inspected, 1 offence detected',
258
+ ''].join("\n"))
259
+ end
260
+ end
261
+
262
+ describe '-d/--debug' do
263
+ it 'shows config files' do
264
+ create_file('example1.rb', "\tputs 0")
265
+ expect(cli.run(['--debug', 'example1.rb'])).to eq(1)
266
+ home = File.dirname(File.dirname(File.dirname(__FILE__)))
267
+ expect($stdout.string.lines.grep(/configuration/).map(&:chomp))
268
+ .to eq(["For #{abs('')}:" +
269
+ " configuration from #{home}/config/default.yml",
270
+ "Inheriting configuration from #{home}/config/enabled.yml",
271
+ "Inheriting configuration from #{home}/config/disabled.yml"
272
+ ])
273
+ end
274
+
275
+ it 'shows cop names' do
276
+ create_file('example1.rb', "\tputs 0")
277
+ expect(cli.run(['--format',
278
+ 'emacs',
279
+ '--debug',
280
+ 'example1.rb'])).to eq(1)
281
+ expect($stdout.string.lines.to_a[-1])
282
+ .to eq(["#{abs('example1.rb')}:1:1: C: Tab: Tab detected.",
283
+ ''].join("\n"))
284
+ end
285
+ end
286
+
287
+ describe '-D/--display-cop-names' do
288
+ it 'shows cop names' do
289
+ create_file('example1.rb', "\tputs 0")
290
+ expect(cli.run(['--format',
291
+ 'emacs',
292
+ '--debug',
293
+ 'example1.rb'])).to eq(1)
294
+ expect($stdout.string.lines.to_a[-1])
295
+ .to eq(["#{abs('example1.rb')}:1:1: C: Tab: Tab detected.",
296
+ ''].join("\n"))
297
+ end
298
+ end
299
+
300
+ describe '--show-cops' do
301
+ shared_examples(:prints_config) do
302
+ it 'prints the current configuration' do
303
+ out = stdout.lines.to_a
304
+ printed_config = YAML.load(out.join)
305
+ cop_names = (cop_list[0] || '').split(',')
306
+ cop_names.each do |cop_name|
307
+ global_conf[cop_name].each do |key, value|
308
+ printed_value = printed_config[cop_name][key]
309
+ expect(printed_value).to eq(value)
310
+ end
311
+ end
312
+ end
313
+ end
314
+
315
+ let(:cops) { Rubocop::Cop::Cop.all }
316
+
317
+ let(:global_conf) do
318
+ config_path =
319
+ Rubocop::ConfigLoader.configuration_file_for(Dir.pwd.to_s)
320
+ Rubocop::ConfigLoader.configuration_from_file(config_path)
321
+ end
322
+
323
+ let(:stdout) { $stdout.string }
324
+
325
+ before do
326
+ expect { cli.run ['--show-cops'] + cop_list }.to exit_with_code(0)
327
+ end
328
+
329
+ context 'with no args' do
330
+ let(:cop_list) { [] }
331
+
332
+ # Extracts the first line out of the description
333
+ def short_description_of_cop(cop)
334
+ desc = full_description_of_cop(cop)
335
+ desc ? desc.lines.first.strip : ''
336
+ end
337
+
338
+ # Gets the full description of the cop or nil if no description is set.
339
+ def full_description_of_cop(cop)
340
+ cop_config = global_conf.for_cop(cop)
341
+ cop_config['Description']
342
+ end
343
+
344
+ it 'prints all available cops and their description' do
345
+ cops.each do |cop|
346
+ expect(stdout).to include cop.cop_name
347
+ # Because of line breaks, we will only find the beginning.
348
+ expect(stdout).to include short_description_of_cop(cop)[0..60]
349
+ end
350
+ end
351
+
352
+ it 'prints all types' do
353
+ cops
354
+ .types
355
+ .map(&:to_s)
356
+ .map(&:capitalize)
357
+ .each { |type| expect(stdout).to include(type) }
358
+ end
359
+
360
+ it 'prints all cops in their right type listing' do
361
+ lines = stdout.lines
362
+ lines.slice_before(/Type /).each do |slice|
363
+ types = cops.types.map(&:to_s).map(&:capitalize)
364
+ current = types.delete(slice.shift[/Type '(?<c>[^'']+)'/, 'c'])
365
+ # all cops in their type listing
366
+ cops.with_type(current).each do |cop|
367
+ expect(slice.any? { |l| l.include? cop.cop_name }).to be_true
368
+ end
369
+
370
+ # no cop in wrong type listing
371
+ types.each do |type|
372
+ cops.with_type(type).each do |cop|
373
+ expect(slice.any? { |l| l.include? cop.cop_name }).to be_false
374
+ end
375
+ end
376
+ end
377
+ end
378
+
379
+ include_examples :prints_config
380
+ end
381
+
382
+ context 'with one cop given' do
383
+ let(:cop_list) { ['Tab'] }
384
+
385
+ it 'prints that cop and nothing else' do
386
+ expect(stdout).to eq(['Tab:',
387
+ ' Description: No hard tabs.',
388
+ ' Enabled: true',
389
+ '',
390
+ ''].join("\n"))
391
+ end
392
+
393
+ include_examples :prints_config
394
+ end
395
+
396
+ context 'with two cops given' do
397
+ let(:cop_list) { ['Tab,LineLength'] }
398
+ include_examples :prints_config
399
+ end
400
+
401
+ context 'with one of the cops misspelled' do
402
+ let(:cop_list) { ['Tab,X123'] }
403
+
404
+ it 'skips the unknown cop' do
405
+ expect(stdout).to eq(['Tab:',
406
+ ' Description: No hard tabs.',
407
+ ' Enabled: true',
408
+ '',
409
+ ''].join("\n"))
410
+ end
411
+ end
412
+ end
413
+
414
+ describe '-f/--format' do
415
+ let(:target_file) { 'example.rb' }
416
+
417
+ before do
418
+ create_file(target_file, [
419
+ '# encoding: utf-8',
420
+ '#' * 90
421
+ ])
422
+ end
423
+
424
+ describe 'builtin formatters' do
425
+ context 'when simple format is specified' do
426
+ it 'outputs with simple format' do
427
+ cli.run(['--format', 'simple', 'example.rb'])
428
+ expect($stdout.string)
429
+ .to include([
430
+ "== #{target_file} ==",
431
+ 'C: 2: 80: Line is too long. [90/79]'
432
+ ].join("\n"))
433
+ end
434
+ end
435
+
436
+ context 'when clang format is specified' do
437
+ it 'outputs with clang format' do
438
+ create_file('example1.rb', ['# encoding: utf-8',
439
+ 'x= 0 ',
440
+ '#' * 85,
441
+ 'y ',
442
+ 'puts x'])
443
+ create_file('example2.rb', ['# encoding: utf-8',
444
+ "\tx",
445
+ 'def a',
446
+ ' puts',
447
+ 'end'])
448
+ create_file('example3.rb', ['# encoding: utf-8',
449
+ 'def badName',
450
+ ' if something',
451
+ ' test',
452
+ ' end',
453
+ 'end'])
454
+ expect(cli.run(['--format', 'clang', 'example1.rb',
455
+ 'example2.rb', 'example3.rb']))
456
+ .to eq(1)
457
+ expect($stdout.string)
458
+ .to eq(['example1.rb:2:2: C: Surrounding space missing for ' \
459
+ "operator '='.",
460
+ 'x= 0 ',
461
+ ' ^',
462
+ 'example1.rb:2:5: C: Trailing whitespace detected.',
463
+ 'x= 0 ',
464
+ ' ^',
465
+ 'example1.rb:3:80: C: Line is too long. [85/79]',
466
+ '###################################################' \
467
+ '##################################',
468
+ ' ' \
469
+ ' ^^^^^^',
470
+ 'example1.rb:4:2: C: Trailing whitespace detected.',
471
+ 'y ',
472
+ ' ^',
473
+ 'example2.rb:2:1: C: Tab detected.',
474
+ "\tx",
475
+ '^',
476
+ 'example2.rb:3:1: C: Inconsistent indentation ' \
477
+ 'detected.',
478
+ 'def a',
479
+ '',
480
+ 'example2.rb:4:1: C: Use 2 (not 3) spaces for ' \
481
+ 'indentation.',
482
+ ' puts',
483
+ '^^^',
484
+ 'example3.rb:2:5: C: Use snake_case for methods.',
485
+ 'def badName',
486
+ ' ^^^^^^^',
487
+ 'example3.rb:3:3: C: Favor modifier if usage ' \
488
+ 'when you have a single-line body. Another good ' +
489
+ 'alternative is the usage of control flow &&/||.',
490
+ ' if something',
491
+ ' ^^',
492
+ 'example3.rb:5:5: W: end at 5, 4 is not aligned ' \
493
+ 'with if at 3, 2',
494
+ ' end',
495
+ ' ^^^',
496
+ '',
497
+ '3 files inspected, 10 offences detected',
498
+ ''].join("\n"))
499
+ end
500
+ end
501
+
502
+ context 'when emacs format is specified' do
503
+ it 'outputs with emacs format' do
504
+ create_file('example1.rb', ['# encoding: utf-8',
505
+ 'x= 0 ',
506
+ 'y ',
507
+ 'puts x'])
508
+ create_file('example2.rb', ['# encoding: utf-8',
509
+ "\tx = 0",
510
+ 'puts x'])
511
+ expect(cli.run(['--format', 'emacs', 'example1.rb',
512
+ 'example2.rb'])).to eq(1)
513
+ expected_output =
514
+ ["#{abs('example1.rb')}:2:2: C: Surrounding space missing" +
515
+ " for operator '='.",
516
+ "#{abs('example1.rb')}:2:5: C: Trailing whitespace detected.",
517
+ "#{abs('example1.rb')}:3:2: C: Trailing whitespace detected.",
518
+ "#{abs('example2.rb')}:2:1: C: Tab detected.",
519
+ "#{abs('example2.rb')}:3:1: C: Inconsistent indentation " +
520
+ 'detected.',
521
+ ''].join("\n")
522
+ expect($stdout.string).to eq(expected_output)
523
+ end
524
+ end
525
+
526
+ context 'when unknown format name is specified' do
527
+ it 'aborts with error message' do
528
+ expect { cli.run(['--format', 'unknown', 'example.rb']) }
529
+ .to exit_with_code(1)
530
+ expect($stderr.string)
531
+ .to include('No formatter for "unknown"')
532
+ end
533
+ end
534
+ end
535
+
536
+ describe 'custom formatter' do
537
+ let(:target_file) { abs('example.rb') }
538
+
539
+ context 'when a class name is specified' do
540
+ it 'uses the class as a formatter' do
541
+ module ::MyTool
542
+ class RubocopFormatter < Rubocop::Formatter::BaseFormatter
543
+ def started(all_files)
544
+ output.puts "started: #{all_files.join(',')}"
545
+ end
546
+
547
+ def file_started(file, options)
548
+ output.puts "file_started: #{file}"
549
+ end
550
+
551
+ def file_finished(file, offences)
552
+ output.puts "file_finished: #{file}"
553
+ end
554
+
555
+ def finished(processed_files)
556
+ output.puts "finished: #{processed_files.join(',')}"
557
+ end
558
+ end
559
+ end
560
+
561
+ cli.run(['--format', 'MyTool::RubocopFormatter', 'example.rb'])
562
+ expect($stdout.string).to eq([
563
+ "started: #{target_file}",
564
+ "file_started: #{target_file}",
565
+ "file_finished: #{target_file}",
566
+ "finished: #{target_file}",
567
+ ''
568
+ ].join("\n"))
569
+ end
570
+ end
571
+
572
+ context 'when unknown class name is specified' do
573
+ it 'aborts with error message' do
574
+ args = '--format UnknownFormatter example.rb'
575
+ expect { cli.run(args.split) }.to exit_with_code(1)
576
+ expect($stderr.string).to include('UnknownFormatter')
577
+ end
578
+ end
579
+ end
580
+
581
+ it 'can be used multiple times' do
582
+ cli.run(['--format', 'simple', '--format', 'emacs', 'example.rb'])
583
+ expect($stdout.string)
584
+ .to include([
585
+ "== #{target_file} ==",
586
+ 'C: 2: 80: Line is too long. [90/79]',
587
+ "#{abs(target_file)}:2:80: C: Line is too long. " +
588
+ '[90/79]'
589
+ ].join("\n"))
590
+ end
591
+ end
592
+
593
+ describe '-o/--out option' do
594
+ let(:target_file) { 'example.rb' }
595
+
596
+ before do
597
+ create_file(target_file, [
598
+ '# encoding: utf-8',
599
+ '#' * 90
600
+ ])
601
+ end
602
+
603
+ it 'redirects output to the specified file' do
604
+ cli.run(['--out', 'output.txt', target_file])
605
+ expect(File.read('output.txt')).to include('Line is too long.')
606
+ end
607
+
608
+ it 'is applied to the previously specified formatter' do
609
+ cli.run([
610
+ '--format', 'simple',
611
+ '--format', 'emacs', '--out', 'emacs_output.txt',
612
+ target_file
613
+ ])
614
+
615
+ expect($stdout.string).to eq([
616
+ "== #{target_file} ==",
617
+ 'C: 2: 80: Line is too long. [90/79]',
618
+ '',
619
+ '1 file inspected, 1 offence detected',
620
+ ''
621
+ ].join("\n"))
622
+
623
+ expect(File.read('emacs_output.txt'))
624
+ .to eq("#{abs(target_file)}:2:80: C: Line is too long. [90/79]\n")
625
+ end
626
+ end
627
+ end
628
+
629
+ describe '#wants_to_quit?' do
630
+ it 'is initially false' do
631
+ expect(cli.wants_to_quit?).to be_false
632
+ end
633
+
634
+ context 'when true' do
635
+ it 'returns 1' do
636
+ create_file('example.rb', '# encoding: utf-8')
637
+ cli.wants_to_quit = true
638
+ expect(cli.run(['example.rb'])).to eq(1)
639
+ end
640
+ end
641
+ end
642
+
643
+ describe '#trap_interrupt' do
644
+ before do
645
+ @interrupt_handlers = []
646
+ allow(Signal).to receive(:trap).with('INT') do |&block|
647
+ @interrupt_handlers << block
648
+ end
649
+ end
650
+
651
+ def interrupt
652
+ @interrupt_handlers.each(&:call)
653
+ end
654
+
655
+ it 'adds a handler for SIGINT' do
656
+ expect(@interrupt_handlers).to be_empty
657
+ cli.trap_interrupt
658
+ expect(@interrupt_handlers.size).to eq(1)
659
+ end
660
+
661
+ context 'with SIGINT once' do
662
+ it 'sets #wants_to_quit? to true' do
663
+ cli.trap_interrupt
664
+ expect(cli.wants_to_quit?).to be_false
665
+ interrupt
666
+ expect(cli.wants_to_quit?).to be_true
667
+ end
668
+
669
+ it 'does not exit immediately' do
670
+ expect_any_instance_of(Object).not_to receive(:exit)
671
+ expect_any_instance_of(Object).not_to receive(:exit!)
672
+ cli.trap_interrupt
673
+ interrupt
674
+ end
675
+ end
676
+
677
+ context 'with SIGINT twice' do
678
+ it 'exits immediately' do
679
+ expect_any_instance_of(Object).to receive(:exit!).with(1)
680
+ cli.trap_interrupt
681
+ interrupt
682
+ interrupt
683
+ end
684
+ end
685
+ end
686
+
687
+ it 'checks a given correct file and returns 0' do
688
+ create_file('example.rb', [
689
+ '# encoding: utf-8',
690
+ 'x = 0',
691
+ 'puts x'
692
+ ])
693
+ expect(cli.run(['--format', 'simple', 'example.rb'])).to eq(0)
694
+ expect($stdout.string)
695
+ .to eq("\n1 file inspected, no offences detected\n")
696
+ end
697
+
698
+ it 'checks a given file with faults and returns 1' do
699
+ create_file('example.rb', [
700
+ '# encoding: utf-8',
701
+ 'x = 0 ',
702
+ 'puts x'
703
+ ])
704
+ expect(cli.run(['--format', 'simple', 'example.rb'])).to eq(1)
705
+ expect($stdout.string)
706
+ .to eq ['== example.rb ==',
707
+ 'C: 2: 6: Trailing whitespace detected.',
708
+ '',
709
+ '1 file inspected, 1 offence detected',
710
+ ''].join("\n")
711
+ end
712
+
713
+ it 'registers an offence for a syntax error' do
714
+ create_file('example.rb', [
715
+ '# encoding: utf-8',
716
+ 'class Test',
717
+ 'en'
718
+ ])
719
+ expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
720
+ expect($stdout.string)
721
+ .to eq(["#{abs('example.rb')}:4:1: E: unexpected " +
722
+ 'token $end',
723
+ ''].join("\n"))
724
+ end
725
+
726
+ it 'registers an offence for Parser warnings' do
727
+ create_file('example.rb', [
728
+ '# encoding: utf-8',
729
+ 'puts *test',
730
+ 'if a then b else c end'
731
+ ])
732
+ expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
733
+ expect($stdout.string)
734
+ .to eq(["#{abs('example.rb')}:2:6: W: " +
735
+ 'Ambiguous splat operator. Parenthesize the method arguments ' +
736
+ "if it's surely a splat operator, or add a whitespace to the " +
737
+ 'right of the * if it should be a multiplication.',
738
+ "#{abs('example.rb')}:3:1: C: " +
739
+ 'Favor the ternary operator (?:) over if/then/else/end ' +
740
+ 'constructs.',
741
+ ''].join("\n"))
742
+ end
743
+
744
+ it 'can process a file with an invalid UTF-8 byte sequence' do
745
+ create_file('example.rb', [
746
+ '# encoding: utf-8',
747
+ "# #{'f9'.hex.chr}#{'29'.hex.chr}"
748
+ ])
749
+ expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
750
+ expect($stdout.string)
751
+ .to eq(["#{abs('example.rb')}:1:1: F: Invalid byte sequence in utf-8.",
752
+ ''].join("\n"))
753
+ end
754
+
755
+ describe 'rubocop:disable comment' do
756
+ it 'can disable all cops in a code section' do
757
+ create_file('example.rb',
758
+ ['# encoding: utf-8',
759
+ '# rubocop:disable all',
760
+ '#' * 90,
761
+ 'x(123456)',
762
+ 'y("123")',
763
+ 'def func',
764
+ ' # rubocop: enable LineLength, StringLiterals',
765
+ ' ' + '#' * 93,
766
+ ' x(123456)',
767
+ ' y("123")',
768
+ 'end'])
769
+ expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
770
+ # all cops were disabled, then 2 were enabled again, so we
771
+ # should get 2 offences reported.
772
+ expect($stdout.string)
773
+ .to eq(["#{abs('example.rb')}:8:80: C: Line is too long. [95/79]",
774
+ "#{abs('example.rb')}:10:5: C: Prefer single-quoted " +
775
+ "strings when you don't need string interpolation or " +
776
+ 'special symbols.',
777
+ ''].join("\n"))
778
+ end
779
+
780
+ it 'can disable selected cops in a code section' do
781
+ create_file('example.rb',
782
+ ['# encoding: utf-8',
783
+ '# rubocop:disable LineLength,NumericLiterals,' +
784
+ 'StringLiterals',
785
+ '#' * 90,
786
+ 'x(123456)',
787
+ 'y("123")',
788
+ 'def func',
789
+ ' # rubocop: enable LineLength, StringLiterals',
790
+ ' ' + '#' * 93,
791
+ ' x(123456)',
792
+ ' y("123")',
793
+ 'end'])
794
+ expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
795
+ # 3 cops were disabled, then 2 were enabled again, so we
796
+ # should get 2 offences reported.
797
+ expect($stdout.string)
798
+ .to eq(["#{abs('example.rb')}:8:80: C: Line is too long. [95/79]",
799
+ "#{abs('example.rb')}:10:5: C: Prefer single-quoted " +
800
+ "strings when you don't need string interpolation or " +
801
+ 'special symbols.',
802
+ ''].join("\n"))
803
+ end
804
+
805
+ it 'can disable all cops on a single line' do
806
+ create_file('example.rb', [
807
+ '# encoding: utf-8',
808
+ 'y("123", 123456) # rubocop:disable all'
809
+ ])
810
+ expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(0)
811
+ expect($stdout.string).to be_empty
812
+ end
813
+
814
+ it 'can disable selected cops on a single line' do
815
+ create_file('example.rb',
816
+ [
817
+ '# encoding: utf-8',
818
+ '#' * 90 + ' # rubocop:disable LineLength',
819
+ '#' * 95,
820
+ 'y("123") # rubocop:disable LineLength,StringLiterals'
821
+ ])
822
+ expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
823
+ expect($stdout.string)
824
+ .to eq(
825
+ ["#{abs('example.rb')}:3:80: C: Line is too long. [95/79]",
826
+ ''].join("\n"))
827
+ end
828
+ end
829
+
830
+ it 'finds a file with no .rb extension but has a shebang line' do
831
+ create_file('example', [
832
+ '#!/usr/bin/env ruby',
833
+ '# encoding: utf-8',
834
+ 'x = 0',
835
+ 'puts x'
836
+ ])
837
+ expect(cli.run(%w(--format simple))).to eq(0)
838
+ expect($stdout.string)
839
+ .to eq(['', '1 file inspected, no offences detected', ''].join("\n"))
840
+ end
841
+
842
+ describe 'enabling/disabling rails cops' do
843
+ it 'by default does not run rails cops' do
844
+ create_file('app/models/example1.rb', ['# encoding: utf-8',
845
+ 'read_attribute(:test)'])
846
+ expect(cli.run(['--format', 'simple', 'app/models/example1.rb']))
847
+ .to eq(0)
848
+ end
849
+
850
+ it 'with -R given runs rails cops' do
851
+ create_file('app/models/example1.rb', ['# encoding: utf-8',
852
+ 'read_attribute(:test)'])
853
+ expect(cli.run(['--format', 'simple', '-R', 'app/models/example1.rb']))
854
+ .to eq(1)
855
+ expect($stdout.string).to include('Prefer self[:attribute]')
856
+ end
857
+
858
+ it 'with configation option true in one dir runs rails cops there' do
859
+ create_file('dir1/app/models/example1.rb', ['# encoding: utf-8',
860
+ 'read_attribute(:test)'])
861
+ create_file('dir1/.rubocop.yml', [
862
+ 'AllCops:',
863
+ ' RunRailsCops: true',
864
+ ])
865
+ create_file('dir2/app/models/example2.rb', ['# encoding: utf-8',
866
+ 'read_attribute(:test)'])
867
+ create_file('dir2/.rubocop.yml', [
868
+ 'AllCops:',
869
+ ' RunRailsCops: false',
870
+ ])
871
+ expect(cli.run(['--format', 'simple', 'dir1', 'dir2'])).to eq(1)
872
+ expect($stdout.string)
873
+ .to eq(['== dir1/app/models/example1.rb ==',
874
+ 'C: 2: 1: Prefer self[:attribute] over read_attribute' +
875
+ '(:attribute).',
876
+ '',
877
+ '2 files inspected, 1 offence detected',
878
+ ''].join("\n"))
879
+ end
880
+
881
+ it 'with configation option false but -R given runs rails cops' do
882
+ create_file('app/models/example1.rb', ['# encoding: utf-8',
883
+ 'read_attribute(:test)'])
884
+ create_file('.rubocop.yml', [
885
+ 'AllCops:',
886
+ ' RunRailsCops: false',
887
+ ])
888
+ expect(cli.run(['--format', 'simple', '-R', 'app/models/example1.rb']))
889
+ .to eq(1)
890
+ expect($stdout.string).to include('Prefer self[:attribute]')
891
+ end
892
+ end
893
+
894
+ describe 'cops can exclude files based on config' do
895
+ it 'ignores excluded files' do
896
+ create_file('example.rb', [
897
+ '# encoding: utf-8',
898
+ 'x = 0'
899
+ ])
900
+ create_file('regexp.rb', [
901
+ '# encoding: utf-8',
902
+ 'x = 0'
903
+ ])
904
+ create_file('exclude_glob.rb', [
905
+ '#!/usr/bin/env ruby',
906
+ '# encoding: utf-8',
907
+ 'x = 0'
908
+ ])
909
+ create_file('dir/thing.rb', [
910
+ '# encoding: utf-8',
911
+ 'x = 0'
912
+ ])
913
+ create_file('.rubocop.yml', [
914
+ 'UselessAssignment:',
915
+ ' Exclude:',
916
+ ' - example.rb',
917
+ ' - !ruby/regexp /regexp.rb\z/',
918
+ ' - "exclude_*"',
919
+ ' - "dir/*"'
920
+ ])
921
+ expect(cli.run(%w(--format simple))).to eq(0)
922
+ expect($stdout.string)
923
+ .to eq(['', '4 files inspected, no offences detected',
924
+ ''].join("\n"))
925
+ end
926
+
927
+ end
928
+
929
+ describe 'configuration from file' do
930
+ it 'finds included files' do
931
+ create_file('example', [
932
+ '# encoding: utf-8',
933
+ 'x = 0',
934
+ 'puts x'
935
+ ])
936
+ create_file('regexp', [
937
+ '# encoding: utf-8',
938
+ 'x = 0',
939
+ 'puts x'
940
+ ])
941
+ create_file('.rubocop.yml', [
942
+ 'AllCops:',
943
+ ' Includes:',
944
+ ' - example',
945
+ ' - !ruby/regexp /regexp$/'
946
+ ])
947
+ expect(cli.run(%w(--format simple))).to eq(0)
948
+ expect($stdout.string)
949
+ .to eq(['', '2 files inspected, no offences detected',
950
+ ''].join("\n"))
951
+ end
952
+
953
+ it 'ignores excluded files' do
954
+ create_file('example.rb', [
955
+ '# encoding: utf-8',
956
+ 'x = 0',
957
+ 'puts x'
958
+ ])
959
+ create_file('regexp.rb', [
960
+ '# encoding: utf-8',
961
+ 'x = 0',
962
+ 'puts x'
963
+ ])
964
+ create_file('exclude_glob.rb', [
965
+ '#!/usr/bin/env ruby',
966
+ '# encoding: utf-8',
967
+ 'x = 0',
968
+ 'puts x'
969
+ ])
970
+ create_file('.rubocop.yml', [
971
+ 'AllCops:',
972
+ ' Excludes:',
973
+ ' - example.rb',
974
+ ' - !ruby/regexp /regexp.rb$/',
975
+ ' - "exclude_*"'
976
+ ])
977
+ expect(cli.run(%w(--format simple))).to eq(0)
978
+ expect($stdout.string)
979
+ .to eq(['', '0 files inspected, no offences detected',
980
+ ''].join("\n"))
981
+ end
982
+
983
+ # With rubinius 2.0.0.rc1 + rspec 2.13.1,
984
+ # File.stub(:open).and_call_original causes SystemStackError.
985
+ it 'does not read files in excluded list', broken: :rbx do
986
+ %w(rb.rb non-rb.ext without-ext).each do |filename|
987
+ create_file("example/ignored/#{filename}", [
988
+ '# encoding: utf-8',
989
+ '#' * 90
990
+ ])
991
+ end
992
+
993
+ create_file('example/.rubocop.yml', [
994
+ 'AllCops:',
995
+ ' Excludes:',
996
+ ' - ignored/**',
997
+ ])
998
+ expect(File).not_to receive(:open).with(%r(/ignored/))
999
+ allow(File).to receive(:open).and_call_original
1000
+ expect(cli.run(%w(--format simple example))).to eq(0)
1001
+ expect($stdout.string)
1002
+ .to eq(['', '0 files inspected, no offences detected',
1003
+ ''].join("\n"))
1004
+ end
1005
+
1006
+ it 'can be configured with option to disable a certain error' do
1007
+ create_file('example1.rb', 'puts 0 ')
1008
+ create_file('rubocop.yml', [
1009
+ 'Encoding:',
1010
+ ' Enabled: false',
1011
+ '',
1012
+ 'CaseIndentation:',
1013
+ ' Enabled: false'
1014
+ ])
1015
+ expect(cli.run(['--format', 'simple',
1016
+ '-c', 'rubocop.yml', 'example1.rb'])).to eq(1)
1017
+ expect($stdout.string)
1018
+ .to eq(['== example1.rb ==',
1019
+ 'C: 1: 7: Trailing whitespace detected.',
1020
+ '',
1021
+ '1 file inspected, 1 offence detected',
1022
+ ''].join("\n"))
1023
+ end
1024
+
1025
+ it 'can disable parser-derived offences with warning severity' do
1026
+ # `-' interpreted as argument prefix
1027
+ create_file('example.rb', 'puts -1')
1028
+ create_file('.rubocop.yml', [
1029
+ 'Encoding:',
1030
+ ' Enabled: false',
1031
+ '',
1032
+ 'AmbiguousOperator:',
1033
+ ' Enabled: false'
1034
+ ])
1035
+ expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(0)
1036
+ end
1037
+
1038
+ it 'cannot disable Syntax offences with fatal/error severity' do
1039
+ create_file('example.rb', 'class Test')
1040
+ create_file('.rubocop.yml', [
1041
+ 'Encoding:',
1042
+ ' Enabled: false',
1043
+ '',
1044
+ 'Syntax:',
1045
+ ' Enabled: false'
1046
+ ])
1047
+ expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
1048
+ expect($stdout.string).to include('unexpected token $end')
1049
+ end
1050
+
1051
+ it 'can be configured to override a parameter that is a hash' do
1052
+ create_file('example1.rb',
1053
+ ['# encoding: utf-8',
1054
+ 'arr.find_all { |e| e > 0 }.collect { |e| -e }'])
1055
+ # We only care about select over find_all. All other preferred methods
1056
+ # appearing in the default config are gone when we override
1057
+ # PreferredMethods. We get no report about collect.
1058
+ create_file('rubocop.yml',
1059
+ ['CollectionMethods:',
1060
+ ' PreferredMethods:',
1061
+ ' find_all: select'])
1062
+ cli.run(['--format', 'simple', '-c', 'rubocop.yml', 'example1.rb'])
1063
+ expect($stdout.string)
1064
+ .to eq(['== example1.rb ==',
1065
+ 'C: 2: 5: Prefer select over find_all.',
1066
+ '',
1067
+ '1 file inspected, 1 offence detected',
1068
+ ''].join("\n"))
1069
+ end
1070
+
1071
+ it 'works when a cop that others depend on is disabled' do
1072
+ create_file('example1.rb', ['if a',
1073
+ ' b',
1074
+ 'end'])
1075
+ create_file('rubocop.yml', [
1076
+ 'Encoding:',
1077
+ ' Enabled: false',
1078
+ '',
1079
+ 'LineLength:',
1080
+ ' Enabled: false'
1081
+ ])
1082
+ result = cli.run(['--format', 'simple',
1083
+ '-c', 'rubocop.yml', 'example1.rb'])
1084
+ expect($stdout.string)
1085
+ .to eq(['== example1.rb ==',
1086
+ 'C: 1: 1: Favor modifier if usage when you have ' +
1087
+ 'a single-line body. Another good alternative is the ' +
1088
+ 'usage of control flow &&/||.',
1089
+ '',
1090
+ '1 file inspected, 1 offence detected',
1091
+ ''].join("\n"))
1092
+ expect(result).to eq(1)
1093
+ end
1094
+
1095
+ it 'can be configured with project config to disable a certain error' do
1096
+ create_file('example_src/example1.rb', 'puts 0 ')
1097
+ create_file('example_src/.rubocop.yml', [
1098
+ 'Encoding:',
1099
+ ' Enabled: false',
1100
+ '',
1101
+ 'CaseIndentation:',
1102
+ ' Enabled: false'
1103
+ ])
1104
+ expect(cli.run(['--format', 'simple',
1105
+ 'example_src/example1.rb'])).to eq(1)
1106
+ expect($stdout.string)
1107
+ .to eq(['== example_src/example1.rb ==',
1108
+ 'C: 1: 7: Trailing whitespace detected.',
1109
+ '',
1110
+ '1 file inspected, 1 offence detected',
1111
+ ''].join("\n"))
1112
+ end
1113
+
1114
+ it 'can use an alternative max line length from a config file' do
1115
+ create_file('example_src/example1.rb', [
1116
+ '# encoding: utf-8',
1117
+ '#' * 90
1118
+ ])
1119
+ create_file('example_src/.rubocop.yml', [
1120
+ 'LineLength:',
1121
+ ' Enabled: true',
1122
+ ' Max: 100'
1123
+ ])
1124
+ expect(cli.run(['--format', 'simple',
1125
+ 'example_src/example1.rb'])).to eq(0)
1126
+ expect($stdout.string)
1127
+ .to eq(['', '1 file inspected, no offences detected', ''].join("\n"))
1128
+ end
1129
+
1130
+ it 'can have different config files in different directories' do
1131
+ %w(src lib).each do |dir|
1132
+ create_file("example/#{dir}/example1.rb", [
1133
+ '# encoding: utf-8',
1134
+ '#' * 90
1135
+ ])
1136
+ end
1137
+ create_file('example/src/.rubocop.yml', [
1138
+ 'LineLength:',
1139
+ ' Enabled: true',
1140
+ ' Max: 100'
1141
+ ])
1142
+ expect(cli.run(%w(--format simple example))).to eq(1)
1143
+ expect($stdout.string).to eq(
1144
+ ['== example/lib/example1.rb ==',
1145
+ 'C: 2: 80: Line is too long. [90/79]',
1146
+ '',
1147
+ '2 files inspected, 1 offence detected',
1148
+ ''].join("\n"))
1149
+ end
1150
+
1151
+ it 'prefers a config file in ancestor directory to another in home' do
1152
+ create_file('example_src/example1.rb', [
1153
+ '# encoding: utf-8',
1154
+ '#' * 90
1155
+ ])
1156
+ create_file('example_src/.rubocop.yml', [
1157
+ 'LineLength:',
1158
+ ' Enabled: true',
1159
+ ' Max: 100'
1160
+ ])
1161
+ create_file("#{Dir.home}/.rubocop.yml", [
1162
+ 'LineLength:',
1163
+ ' Enabled: true',
1164
+ ' Max: 80'
1165
+ ])
1166
+ expect(cli.run(['--format', 'simple',
1167
+ 'example_src/example1.rb'])).to eq(0)
1168
+ expect($stdout.string)
1169
+ .to eq(['', '1 file inspected, no offences detected', ''].join("\n"))
1170
+ end
1171
+
1172
+ it 'can exclude directories relative to .rubocop.yml' do
1173
+ %w(src etc/test etc/spec tmp/test tmp/spec).each do |dir|
1174
+ create_file("example/#{dir}/example1.rb", [
1175
+ '# encoding: utf-8',
1176
+ '#' * 90
1177
+ ])
1178
+ end
1179
+
1180
+ create_file('example/.rubocop.yml', [
1181
+ 'AllCops:',
1182
+ ' Excludes:',
1183
+ ' - src/**',
1184
+ ' - etc/**',
1185
+ ' - tmp/spec/**'
1186
+ ])
1187
+
1188
+ expect(cli.run(%w(--format simple example))).to eq(1)
1189
+ expect($stdout.string).to eq(
1190
+ ['== example/tmp/test/example1.rb ==',
1191
+ 'C: 2: 80: Line is too long. [90/79]',
1192
+ '',
1193
+ '1 file inspected, 1 offence detected',
1194
+ ''].join("\n"))
1195
+ end
1196
+
1197
+ it 'can exclude a typical vendor directory' do
1198
+ create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/.rubocop.yml',
1199
+ ['AllCops:',
1200
+ ' Excludes:',
1201
+ ' - lib/parser/lexer.rb'])
1202
+
1203
+ create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/lib/ex.rb',
1204
+ ['# encoding: utf-8',
1205
+ '#' * 90])
1206
+
1207
+ create_file('.rubocop.yml',
1208
+ ['AllCops:',
1209
+ ' Excludes:',
1210
+ ' - vendor/**'])
1211
+
1212
+ cli.run(%w(--format simple))
1213
+ expect($stdout.string)
1214
+ .to eq(['', '0 files inspected, no offences detected',
1215
+ ''].join("\n"))
1216
+ end
1217
+
1218
+ # Being immune to bad configuration files in excluded directories has
1219
+ # become important due to a bug in rubygems
1220
+ # (https://github.com/rubygems/rubygems/issues/680) that makes
1221
+ # installations of, for example, rubocop lack their .rubocop.yml in the
1222
+ # root directory.
1223
+ it 'can exclude a vendor directory with an erroneous config file' do
1224
+ create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/.rubocop.yml',
1225
+ ['inherit_from: non_existent.yml'])
1226
+
1227
+ create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/lib/ex.rb',
1228
+ ['# encoding: utf-8',
1229
+ '#' * 90])
1230
+
1231
+ create_file('.rubocop.yml',
1232
+ ['AllCops:',
1233
+ ' Excludes:',
1234
+ ' - vendor/**'])
1235
+
1236
+ cli.run(%w(--format simple))
1237
+ expect($stderr.string).to eq('')
1238
+ expect($stdout.string)
1239
+ .to eq(['', '0 files inspected, no offences detected',
1240
+ ''].join("\n"))
1241
+ end
1242
+
1243
+ # Relative exclude paths in .rubocop.yml files are relative to that file,
1244
+ # but in configuration files with other names they will be relative to
1245
+ # whatever file inherits from them.
1246
+ it 'can exclude a vendor directory indirectly' do
1247
+ create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/.rubocop.yml',
1248
+ ['AllCops:',
1249
+ ' Excludes:',
1250
+ ' - lib/parser/lexer.rb'])
1251
+
1252
+ create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/lib/ex.rb',
1253
+ ['# encoding: utf-8',
1254
+ '#' * 90])
1255
+
1256
+ create_file('.rubocop.yml',
1257
+ ['inherit_from: config/default.yml'])
1258
+
1259
+ create_file('config/default.yml',
1260
+ ['AllCops:',
1261
+ ' Excludes:',
1262
+ ' - vendor/**'])
1263
+
1264
+ cli.run(%w(--format simple))
1265
+ expect($stdout.string)
1266
+ .to eq(['', '0 files inspected, no offences detected',
1267
+ ''].join("\n"))
1268
+ end
1269
+
1270
+ it 'prints a warning for an unrecognized cop name in .rubocop.yml' do
1271
+ create_file('example/example1.rb', [
1272
+ '# encoding: utf-8',
1273
+ '#' * 90
1274
+ ])
1275
+
1276
+ create_file('example/.rubocop.yml', [
1277
+ 'LyneLenth:',
1278
+ ' Enabled: true',
1279
+ ' Max: 100'
1280
+ ])
1281
+
1282
+ expect(cli.run(%w(--format simple example))).to eq(1)
1283
+ expect($stderr.string)
1284
+ .to eq(
1285
+ ['Warning: unrecognized cop LyneLenth found in ' +
1286
+ abs('example/.rubocop.yml'),
1287
+ ''].join("\n"))
1288
+ end
1289
+
1290
+ it 'prints a warning for an unrecognized configuration parameter' do
1291
+ create_file('example/example1.rb', [
1292
+ '# encoding: utf-8',
1293
+ '#' * 90
1294
+ ])
1295
+
1296
+ create_file('example/.rubocop.yml', [
1297
+ 'LineLength:',
1298
+ ' Enabled: true',
1299
+ ' Min: 10'
1300
+ ])
1301
+
1302
+ expect(cli.run(%w(--format simple example))).to eq(1)
1303
+ expect($stderr.string)
1304
+ .to eq(
1305
+ ['Warning: unrecognized parameter LineLength:Min found in ' +
1306
+ abs('example/.rubocop.yml'),
1307
+ ''].join("\n"))
1308
+ end
1309
+
1310
+ it 'works when a configuration file passed by -c specifies Excludes with regexp' do
1311
+ create_file('example/example1.rb', [
1312
+ '# encoding: utf-8',
1313
+ '#' * 90
1314
+ ])
1315
+
1316
+ create_file('rubocop.yml', [
1317
+ 'AllCops:',
1318
+ ' Excludes:',
1319
+ ' - !ruby/regexp /example1\.rb$/'
1320
+ ])
1321
+
1322
+ cli.run(%w(--format simple -c rubocop.yml))
1323
+ expect($stdout.string)
1324
+ .to eq(['', '0 files inspected, no offences detected',
1325
+ ''].join("\n"))
1326
+ end
1327
+
1328
+ it 'works when a configuration file passed by -c specifies Excludes with strings' do
1329
+ create_file('example/example1.rb', [
1330
+ '# encoding: utf-8',
1331
+ '#' * 90
1332
+ ])
1333
+
1334
+ create_file('rubocop.yml', [
1335
+ 'AllCops:',
1336
+ ' Excludes:',
1337
+ ' - example/**'
1338
+ ])
1339
+
1340
+ cli.run(%w(--format simple -c rubocop.yml))
1341
+ expect($stdout.string)
1342
+ .to eq(['', '0 files inspected, no offences detected',
1343
+ ''].join("\n"))
1344
+ end
1345
+
1346
+ it 'works when a configuration file specifies a Severity' do
1347
+ create_file('example/example1.rb', [
1348
+ '# encoding: utf-8',
1349
+ '#' * 90
1350
+ ])
1351
+
1352
+ create_file('rubocop.yml', [
1353
+ 'LineLength:',
1354
+ ' Severity: error',
1355
+ ])
1356
+
1357
+ cli.run(%w(--format simple -c rubocop.yml))
1358
+ expect($stdout.string)
1359
+ .to eq(['== example/example1.rb ==',
1360
+ 'E: 2: 80: Line is too long. [90/79]',
1361
+ '',
1362
+ '1 file inspected, 1 offence detected',
1363
+ ''].join("\n"))
1364
+ expect($stderr.string).to eq('')
1365
+ end
1366
+
1367
+ it 'fails when a configuration file specifies an invalid Severity' do
1368
+ create_file('example/example1.rb', [
1369
+ '# encoding: utf-8',
1370
+ '#' * 90
1371
+ ])
1372
+
1373
+ create_file('rubocop.yml', [
1374
+ 'LineLength:',
1375
+ ' Severity: superbad',
1376
+ ])
1377
+
1378
+ cli.run(%w(--format simple -c rubocop.yml))
1379
+ expect($stderr.string)
1380
+ .to eq("Warning: Invalid severity 'superbad'. " +
1381
+ 'Valid severities are refactor, convention, ' +
1382
+ "warning, error, fatal.\n")
1383
+ end
1384
+ end
1385
+ end