sabat-rubocop 0.9.0

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 (239) hide show
  1. data/.gitignore +50 -0
  2. data/.rspec +1 -0
  3. data/.rubocop.yml +7 -0
  4. data/.travis.yml +7 -0
  5. data/.yardopts +2 -0
  6. data/CHANGELOG.md +268 -0
  7. data/CONTRIBUTING.md +16 -0
  8. data/Gemfile +7 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +324 -0
  11. data/Rakefile +29 -0
  12. data/bin/rubocop +22 -0
  13. data/config/default.yml +58 -0
  14. data/config/disabled.yml +5 -0
  15. data/config/enabled.yml +403 -0
  16. data/lib/rubocop.rb +116 -0
  17. data/lib/rubocop/cli.rb +407 -0
  18. data/lib/rubocop/config.rb +250 -0
  19. data/lib/rubocop/config_store.rb +39 -0
  20. data/lib/rubocop/cop/cop.rb +138 -0
  21. data/lib/rubocop/cop/lint/assignment_in_condition.rb +54 -0
  22. data/lib/rubocop/cop/lint/end_alignment.rb +189 -0
  23. data/lib/rubocop/cop/lint/end_in_method.rb +30 -0
  24. data/lib/rubocop/cop/lint/ensure_return.rb +22 -0
  25. data/lib/rubocop/cop/lint/eval.rb +22 -0
  26. data/lib/rubocop/cop/lint/handle_exceptions.rb +20 -0
  27. data/lib/rubocop/cop/lint/literal_in_condition.rb +81 -0
  28. data/lib/rubocop/cop/lint/loop.rb +29 -0
  29. data/lib/rubocop/cop/lint/rescue_exception.rb +29 -0
  30. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +34 -0
  31. data/lib/rubocop/cop/lint/unreachable_code.rb +35 -0
  32. data/lib/rubocop/cop/lint/unused_local_variable.rb +32 -0
  33. data/lib/rubocop/cop/lint/void.rb +58 -0
  34. data/lib/rubocop/cop/offence.rb +136 -0
  35. data/lib/rubocop/cop/rails/validation.rb +30 -0
  36. data/lib/rubocop/cop/style/access_control.rb +58 -0
  37. data/lib/rubocop/cop/style/alias.rb +28 -0
  38. data/lib/rubocop/cop/style/align_parameters.rb +39 -0
  39. data/lib/rubocop/cop/style/and_or.rb +45 -0
  40. data/lib/rubocop/cop/style/ascii_comments.rb +21 -0
  41. data/lib/rubocop/cop/style/ascii_identifiers.rb +22 -0
  42. data/lib/rubocop/cop/style/attr.rb +20 -0
  43. data/lib/rubocop/cop/style/avoid_class_vars.rb +20 -0
  44. data/lib/rubocop/cop/style/avoid_for.rb +18 -0
  45. data/lib/rubocop/cop/style/avoid_global_vars.rb +65 -0
  46. data/lib/rubocop/cop/style/avoid_perl_backrefs.rb +21 -0
  47. data/lib/rubocop/cop/style/avoid_perlisms.rb +50 -0
  48. data/lib/rubocop/cop/style/begin_block.rb +18 -0
  49. data/lib/rubocop/cop/style/block_comments.rb +20 -0
  50. data/lib/rubocop/cop/style/block_nesting.rb +47 -0
  51. data/lib/rubocop/cop/style/blocks.rb +27 -0
  52. data/lib/rubocop/cop/style/case_equality.rb +22 -0
  53. data/lib/rubocop/cop/style/case_indentation.rb +28 -0
  54. data/lib/rubocop/cop/style/character_literal.rb +37 -0
  55. data/lib/rubocop/cop/style/class_and_module_camel_case.rb +33 -0
  56. data/lib/rubocop/cop/style/class_methods.rb +22 -0
  57. data/lib/rubocop/cop/style/collection_methods.rb +56 -0
  58. data/lib/rubocop/cop/style/colon_method_call.rb +29 -0
  59. data/lib/rubocop/cop/style/constant_name.rb +31 -0
  60. data/lib/rubocop/cop/style/def_parentheses.rb +70 -0
  61. data/lib/rubocop/cop/style/documentation.rb +58 -0
  62. data/lib/rubocop/cop/style/dot_position.rb +25 -0
  63. data/lib/rubocop/cop/style/empty_line_between_defs.rb +26 -0
  64. data/lib/rubocop/cop/style/empty_lines.rb +40 -0
  65. data/lib/rubocop/cop/style/empty_literal.rb +53 -0
  66. data/lib/rubocop/cop/style/encoding.rb +29 -0
  67. data/lib/rubocop/cop/style/end_block.rb +18 -0
  68. data/lib/rubocop/cop/style/end_of_line.rb +23 -0
  69. data/lib/rubocop/cop/style/favor_join.rb +29 -0
  70. data/lib/rubocop/cop/style/favor_modifier.rb +118 -0
  71. data/lib/rubocop/cop/style/favor_sprintf.rb +28 -0
  72. data/lib/rubocop/cop/style/favor_unless_over_negated_if.rb +54 -0
  73. data/lib/rubocop/cop/style/hash_syntax.rb +47 -0
  74. data/lib/rubocop/cop/style/if_then_else.rb +29 -0
  75. data/lib/rubocop/cop/style/if_with_semicolon.rb +20 -0
  76. data/lib/rubocop/cop/style/lambda.rb +47 -0
  77. data/lib/rubocop/cop/style/leading_comment_space.rb +25 -0
  78. data/lib/rubocop/cop/style/line_continuation.rb +26 -0
  79. data/lib/rubocop/cop/style/line_length.rb +30 -0
  80. data/lib/rubocop/cop/style/method_and_variable_snake_case.rb +61 -0
  81. data/lib/rubocop/cop/style/method_call_parentheses.rb +22 -0
  82. data/lib/rubocop/cop/style/method_length.rb +57 -0
  83. data/lib/rubocop/cop/style/multiline_if_then.rb +47 -0
  84. data/lib/rubocop/cop/style/not.rb +24 -0
  85. data/lib/rubocop/cop/style/numeric_literals.rb +25 -0
  86. data/lib/rubocop/cop/style/one_line_conditional.rb +20 -0
  87. data/lib/rubocop/cop/style/op_method.rb +29 -0
  88. data/lib/rubocop/cop/style/parameter_lists.rb +42 -0
  89. data/lib/rubocop/cop/style/parentheses_around_condition.rb +42 -0
  90. data/lib/rubocop/cop/style/proc.rb +30 -0
  91. data/lib/rubocop/cop/style/reduce_arguments.rb +34 -0
  92. data/lib/rubocop/cop/style/regexp_literal.rb +39 -0
  93. data/lib/rubocop/cop/style/rescue_modifier.rb +55 -0
  94. data/lib/rubocop/cop/style/semicolon.rb +51 -0
  95. data/lib/rubocop/cop/style/single_line_methods.rb +48 -0
  96. data/lib/rubocop/cop/style/space_after_comma_etc.rb +69 -0
  97. data/lib/rubocop/cop/style/space_after_control_keyword.rb +32 -0
  98. data/lib/rubocop/cop/style/string_literals.rb +36 -0
  99. data/lib/rubocop/cop/style/surrounding_space.rb +314 -0
  100. data/lib/rubocop/cop/style/symbol_array.rb +31 -0
  101. data/lib/rubocop/cop/style/symbol_name.rb +27 -0
  102. data/lib/rubocop/cop/style/tab.rb +25 -0
  103. data/lib/rubocop/cop/style/ternary_operator.rb +49 -0
  104. data/lib/rubocop/cop/style/trailing_whitespace.rb +24 -0
  105. data/lib/rubocop/cop/style/trivial_accessors.rb +32 -0
  106. data/lib/rubocop/cop/style/unless_else.rb +26 -0
  107. data/lib/rubocop/cop/style/variable_interpolation.rb +32 -0
  108. data/lib/rubocop/cop/style/when_then.rb +25 -0
  109. data/lib/rubocop/cop/style/while_until_do.rb +45 -0
  110. data/lib/rubocop/cop/style/word_array.rb +44 -0
  111. data/lib/rubocop/cop/util.rb +27 -0
  112. data/lib/rubocop/cop/variable_inspector.rb +280 -0
  113. data/lib/rubocop/formatter/base_formatter.rb +119 -0
  114. data/lib/rubocop/formatter/clang_style_formatter.rb +21 -0
  115. data/lib/rubocop/formatter/emacs_style_formatter.rb +17 -0
  116. data/lib/rubocop/formatter/formatter_set.rb +77 -0
  117. data/lib/rubocop/formatter/json_formatter.rb +76 -0
  118. data/lib/rubocop/formatter/progress_formatter.rb +63 -0
  119. data/lib/rubocop/formatter/simple_text_formatter.rb +62 -0
  120. data/lib/rubocop/version.rb +21 -0
  121. data/rubocop.gemspec +36 -0
  122. data/spec/.rubocop.yml +5 -0
  123. data/spec/project_spec.rb +24 -0
  124. data/spec/rubocop/cli_spec.rb +906 -0
  125. data/spec/rubocop/config_spec.rb +470 -0
  126. data/spec/rubocop/config_store_spec.rb +66 -0
  127. data/spec/rubocop/cops/cop_spec.rb +38 -0
  128. data/spec/rubocop/cops/lint/assignment_in_condition_spec.rb +111 -0
  129. data/spec/rubocop/cops/lint/end_alignment_spec.rb +333 -0
  130. data/spec/rubocop/cops/lint/end_in_method_spec.rb +35 -0
  131. data/spec/rubocop/cops/lint/ensure_return_spec.rb +37 -0
  132. data/spec/rubocop/cops/lint/eval_spec.rb +41 -0
  133. data/spec/rubocop/cops/lint/handle_exceptions_spec.rb +36 -0
  134. data/spec/rubocop/cops/lint/literal_in_condition_spec.rb +42 -0
  135. data/spec/rubocop/cops/lint/loop_spec.rb +33 -0
  136. data/spec/rubocop/cops/lint/rescue_exception_spec.rb +127 -0
  137. data/spec/rubocop/cops/lint/shadowing_outer_local_variable_spec.rb +243 -0
  138. data/spec/rubocop/cops/lint/unreachable_code_spec.rb +69 -0
  139. data/spec/rubocop/cops/lint/unused_local_variable_spec.rb +497 -0
  140. data/spec/rubocop/cops/lint/void_spec.rb +63 -0
  141. data/spec/rubocop/cops/offence_spec.rb +133 -0
  142. data/spec/rubocop/cops/rails/validation_spec.rb +27 -0
  143. data/spec/rubocop/cops/style/access_control_spec.rb +142 -0
  144. data/spec/rubocop/cops/style/alias_spec.rb +47 -0
  145. data/spec/rubocop/cops/style/align_parameters_spec.rb +199 -0
  146. data/spec/rubocop/cops/style/and_or_spec.rb +39 -0
  147. data/spec/rubocop/cops/style/ascii_comments_spec.rb +28 -0
  148. data/spec/rubocop/cops/style/ascii_identifiers_spec.rb +28 -0
  149. data/spec/rubocop/cops/style/attr_spec.rb +20 -0
  150. data/spec/rubocop/cops/style/avoid_class_vars_spec.rb +27 -0
  151. data/spec/rubocop/cops/style/avoid_for_spec.rb +37 -0
  152. data/spec/rubocop/cops/style/avoid_global_vars_spec.rb +34 -0
  153. data/spec/rubocop/cops/style/avoid_perl_backrefs_spec.rb +20 -0
  154. data/spec/rubocop/cops/style/avoid_perlisms_spec.rb +47 -0
  155. data/spec/rubocop/cops/style/begin_block_spec.rb +19 -0
  156. data/spec/rubocop/cops/style/block_comments_spec.rb +27 -0
  157. data/spec/rubocop/cops/style/block_nesting_spec.rb +159 -0
  158. data/spec/rubocop/cops/style/blocks_spec.rb +35 -0
  159. data/spec/rubocop/cops/style/case_equality_spec.rb +18 -0
  160. data/spec/rubocop/cops/style/case_indentation_spec.rb +88 -0
  161. data/spec/rubocop/cops/style/character_literal_spec.rb +28 -0
  162. data/spec/rubocop/cops/style/class_and_module_camel_case_spec.rb +46 -0
  163. data/spec/rubocop/cops/style/class_methods_spec.rb +51 -0
  164. data/spec/rubocop/cops/style/collection_methods_spec.rb +41 -0
  165. data/spec/rubocop/cops/style/colon_method_call_spec.rb +55 -0
  166. data/spec/rubocop/cops/style/constant_name_spec.rb +56 -0
  167. data/spec/rubocop/cops/style/def_with_parentheses_spec.rb +40 -0
  168. data/spec/rubocop/cops/style/def_without_parentheses_spec.rb +34 -0
  169. data/spec/rubocop/cops/style/documentation_spec.rb +79 -0
  170. data/spec/rubocop/cops/style/dot_position_spec.rb +30 -0
  171. data/spec/rubocop/cops/style/empty_line_between_defs_spec.rb +85 -0
  172. data/spec/rubocop/cops/style/empty_lines_spec.rb +40 -0
  173. data/spec/rubocop/cops/style/empty_literal_spec.rb +91 -0
  174. data/spec/rubocop/cops/style/encoding_spec.rb +49 -0
  175. data/spec/rubocop/cops/style/end_block_spec.rb +19 -0
  176. data/spec/rubocop/cops/style/end_of_line_spec.rb +25 -0
  177. data/spec/rubocop/cops/style/favor_join_spec.rb +37 -0
  178. data/spec/rubocop/cops/style/favor_modifier_spec.rb +160 -0
  179. data/spec/rubocop/cops/style/favor_sprintf_spec.rb +53 -0
  180. data/spec/rubocop/cops/style/favor_unless_over_negated_if_spec.rb +64 -0
  181. data/spec/rubocop/cops/style/favor_until_over_negated_while_spec.rb +47 -0
  182. data/spec/rubocop/cops/style/hash_syntax_spec.rb +51 -0
  183. data/spec/rubocop/cops/style/if_with_semicolon_spec.rb +25 -0
  184. data/spec/rubocop/cops/style/lambda_spec.rb +45 -0
  185. data/spec/rubocop/cops/style/leading_comment_space_spec.rb +65 -0
  186. data/spec/rubocop/cops/style/line_continuation_spec.rb +26 -0
  187. data/spec/rubocop/cops/style/line_length_spec.rb +25 -0
  188. data/spec/rubocop/cops/style/method_and_variable_snake_case_spec.rb +95 -0
  189. data/spec/rubocop/cops/style/method_call_parentheses_spec.rb +25 -0
  190. data/spec/rubocop/cops/style/method_length_spec.rb +151 -0
  191. data/spec/rubocop/cops/style/multiline_if_then_spec.rb +97 -0
  192. data/spec/rubocop/cops/style/not_spec.rb +28 -0
  193. data/spec/rubocop/cops/style/numeric_literals_spec.rb +51 -0
  194. data/spec/rubocop/cops/style/one_line_conditional_spec.rb +18 -0
  195. data/spec/rubocop/cops/style/op_method_spec.rb +80 -0
  196. data/spec/rubocop/cops/style/parameter_lists_spec.rb +49 -0
  197. data/spec/rubocop/cops/style/parentheses_around_condition_spec.rb +59 -0
  198. data/spec/rubocop/cops/style/proc_spec.rb +28 -0
  199. data/spec/rubocop/cops/style/reduce_arguments_spec.rb +59 -0
  200. data/spec/rubocop/cops/style/regexp_literal_spec.rb +83 -0
  201. data/spec/rubocop/cops/style/rescue_modifier_spec.rb +122 -0
  202. data/spec/rubocop/cops/style/semicolon_spec.rb +95 -0
  203. data/spec/rubocop/cops/style/single_line_methods_spec.rb +54 -0
  204. data/spec/rubocop/cops/style/space_after_colon_spec.rb +29 -0
  205. data/spec/rubocop/cops/style/space_after_comma_spec.rb +31 -0
  206. data/spec/rubocop/cops/style/space_after_control_keyword_spec.rb +69 -0
  207. data/spec/rubocop/cops/style/space_after_semicolon_spec.rb +24 -0
  208. data/spec/rubocop/cops/style/space_around_braces_spec.rb +49 -0
  209. data/spec/rubocop/cops/style/space_around_equals_in_default_parameter_spec.rb +34 -0
  210. data/spec/rubocop/cops/style/space_around_operators_spec.rb +216 -0
  211. data/spec/rubocop/cops/style/space_inside_brackets_spec.rb +51 -0
  212. data/spec/rubocop/cops/style/space_inside_hash_literal_braces_spec.rb +99 -0
  213. data/spec/rubocop/cops/style/space_inside_parens_spec.rb +33 -0
  214. data/spec/rubocop/cops/style/string_literals_spec.rb +62 -0
  215. data/spec/rubocop/cops/style/symbol_array_spec.rb +45 -0
  216. data/spec/rubocop/cops/style/symbol_name_spec.rb +122 -0
  217. data/spec/rubocop/cops/style/tab_spec.rb +23 -0
  218. data/spec/rubocop/cops/style/ternary_operator_spec.rb +42 -0
  219. data/spec/rubocop/cops/style/trailing_whitespace_spec.rb +29 -0
  220. data/spec/rubocop/cops/style/trivial_accessors_spec.rb +338 -0
  221. data/spec/rubocop/cops/style/unless_else_spec.rb +31 -0
  222. data/spec/rubocop/cops/style/variable_interpolation_spec.rb +53 -0
  223. data/spec/rubocop/cops/style/when_then_spec.rb +40 -0
  224. data/spec/rubocop/cops/style/while_until_do_spec.rb +47 -0
  225. data/spec/rubocop/cops/style/word_array_spec.rb +61 -0
  226. data/spec/rubocop/cops/variable_inspector_spec.rb +374 -0
  227. data/spec/rubocop/formatter/base_formatter_spec.rb +190 -0
  228. data/spec/rubocop/formatter/clang_style_formatter_spec.rb +70 -0
  229. data/spec/rubocop/formatter/emacs_style_formatter_spec.rb +32 -0
  230. data/spec/rubocop/formatter/formatter_set_spec.rb +132 -0
  231. data/spec/rubocop/formatter/json_formatter_spec.rb +142 -0
  232. data/spec/rubocop/formatter/progress_formatter_spec.rb +196 -0
  233. data/spec/rubocop/formatter/simple_text_formatter_spec.rb +74 -0
  234. data/spec/spec_helper.rb +92 -0
  235. data/spec/support/file_helper.rb +21 -0
  236. data/spec/support/isolated_environment.rb +27 -0
  237. data/spec/support/mri_syntax_checker.rb +69 -0
  238. data/spec/support/shared_examples.rb +33 -0
  239. metadata +517 -0
@@ -0,0 +1,250 @@
1
+ # encoding: utf-8
2
+
3
+ require 'delegate'
4
+ require 'yaml'
5
+ require 'pathname'
6
+
7
+ module Rubocop
8
+ # This class represents the configuration of the RuboCop application
9
+ # and all its cops. A Config is associated with a YAML configuration
10
+ # file from which it was read. Several different Configs can be used
11
+ # during a run of the rubocop program, if files in several
12
+ # directories are inspected.
13
+ class Config < DelegateClass(Hash)
14
+ class ValidationError < StandardError; end
15
+
16
+ DOTFILE = '.rubocop.yml'
17
+ RUBOCOP_HOME = File.realpath(File.join(File.dirname(__FILE__), '..', '..'))
18
+ DEFAULT_FILE = File.join(RUBOCOP_HOME, 'config', 'default.yml')
19
+
20
+ attr_reader :loaded_path
21
+
22
+ class << self
23
+ def load_file(path)
24
+ path = File.absolute_path(path)
25
+ hash = YAML.load_file(path)
26
+
27
+ base_configs(path, hash['inherit_from']).reverse.each do |base_config|
28
+ base_config.each do |key, value|
29
+ if value.is_a?(Hash)
30
+ if key == 'AllCops' && value['Excludes']
31
+ correct_relative_excludes(value, base_config, path)
32
+ end
33
+ hash[key] = hash.has_key?(key) ? merge(value, hash[key]) : value
34
+ end
35
+ end
36
+ end
37
+
38
+ hash.delete('inherit_from')
39
+ config = new(hash, path)
40
+ config.warn_unless_valid
41
+ config
42
+ end
43
+
44
+ def correct_relative_excludes(all_cops, base_config, path)
45
+ all_cops['Excludes'].map! do |exclude_elem|
46
+ if exclude_elem.is_a?(String) && exclude_elem =~ %r([^/].*/)
47
+ rel_path = relative_path(base_config.loaded_path,
48
+ File.dirname(path))
49
+ rel_path.to_s.sub(/#{DOTFILE}$/, '') + exclude_elem
50
+ else
51
+ exclude_elem
52
+ end
53
+ end
54
+ end
55
+
56
+ def relative_path(path, base)
57
+ path_name = Pathname.new(File.expand_path(path))
58
+ path_name.relative_path_from(Pathname.new(base)).to_s
59
+ end
60
+
61
+ # Return a recursive merge of two hashes. That is, a normal hash
62
+ # merge, with the addition that any value that is a hash, and
63
+ # occurs in both arguments, will also be merged. And so on.
64
+ def merge(base_hash, derived_hash)
65
+ result = {}
66
+ base_hash.each do |key, value|
67
+ result[key] = if derived_hash.has_key?(key)
68
+ if value.is_a?(Hash)
69
+ merge(value, derived_hash[key])
70
+ else
71
+ derived_hash[key]
72
+ end
73
+ else
74
+ base_hash[key]
75
+ end
76
+ end
77
+ derived_hash.each do |key, value|
78
+ result[key] = value unless base_hash.has_key?(key)
79
+ end
80
+ result
81
+ end
82
+
83
+ def base_configs(path, inherit_from)
84
+ base_files = case inherit_from
85
+ when nil then []
86
+ when String then [inherit_from]
87
+ when Array then inherit_from
88
+ end
89
+ base_files.map do |f|
90
+ f = File.join(File.dirname(path), f) unless f.start_with?('/')
91
+ load_file(f)
92
+ end
93
+ end
94
+
95
+ # Returns the path of .rubocop.yml searching upwards in the
96
+ # directory structure starting at the given directory where the
97
+ # inspected file is. If no .rubocop.yml is found there, the
98
+ # user's home directory is checked. If there's no .rubocop.yml
99
+ # there either, the path to the default file is returned.
100
+ def configuration_file_for(target_dir)
101
+ config_files_in_path(target_dir).first || DEFAULT_FILE
102
+ end
103
+
104
+ def configuration_from_file(config_file)
105
+ config = load_file(config_file)
106
+ found_files = config_files_in_path(config_file)
107
+ if found_files.any? && found_files.last != config_file
108
+ add_excludes_from_higher_level(config, load_file(found_files.last))
109
+ end
110
+ merge_with_default(config, config_file)
111
+ end
112
+
113
+ def add_excludes_from_higher_level(config, highest_config)
114
+ if highest_config['AllCops'] && highest_config['AllCops']['Excludes']
115
+ config['AllCops'] ||= {}
116
+ config['AllCops']['Excludes'] ||= []
117
+ highest_config['AllCops']['Excludes'].each do |path|
118
+ unless path.is_a?(Regexp) || path.start_with?('/')
119
+ diff_in_level = config.loaded_path.count('/') -
120
+ highest_config.loaded_path.count('/')
121
+ path = '../' * diff_in_level + path
122
+ end
123
+ config['AllCops']['Excludes'] << path
124
+ end
125
+ config['AllCops']['Excludes'].uniq!
126
+ end
127
+ end
128
+
129
+ def default_configuration
130
+ @default_configuration ||= load_file(DEFAULT_FILE)
131
+ end
132
+
133
+ def merge_with_default(config, config_file)
134
+ new(merge(default_configuration, config), config_file)
135
+ end
136
+
137
+ private
138
+
139
+ def config_files_in_path(target)
140
+ possible_config_files = dirs_to_search(target).map do |dir|
141
+ File.join(dir, DOTFILE)
142
+ end
143
+ possible_config_files.select { |config_file| File.exist?(config_file) }
144
+ end
145
+
146
+ def dirs_to_search(target_dir)
147
+ dirs_to_search = []
148
+ target_dir_pathname = Pathname.new(File.expand_path(target_dir))
149
+ target_dir_pathname.ascend do |dir_pathname|
150
+ dirs_to_search << dir_pathname.to_s
151
+ end
152
+ dirs_to_search << Dir.home
153
+ dirs_to_search
154
+ end
155
+ end
156
+
157
+ def initialize(hash = {}, loaded_path = nil)
158
+ @hash = hash
159
+ @loaded_path = loaded_path
160
+ super(@hash)
161
+ end
162
+
163
+ def for_cop(cop)
164
+ self[cop]
165
+ end
166
+
167
+ def cop_enabled?(cop)
168
+ self[cop].nil? || self[cop]['Enabled']
169
+ end
170
+
171
+ def warn_unless_valid
172
+ validate
173
+ rescue Config::ValidationError => e
174
+ puts "Warning: #{e.message}".color(:red)
175
+ end
176
+
177
+ # TODO: This should be a private method
178
+ def validate
179
+ # Don't validate RuboCop's own files. Avoids inifinite recursion.
180
+ return if @loaded_path.start_with?(RUBOCOP_HOME)
181
+
182
+ default_config = self.class.default_configuration
183
+
184
+ valid_cop_names, invalid_cop_names = @hash.keys.partition do |key|
185
+ default_config.has_key?(key)
186
+ end
187
+
188
+ invalid_cop_names.each do |name|
189
+ fail ValidationError,
190
+ "unrecognized cop #{name} found in #{loaded_path || self}"
191
+ end
192
+
193
+ valid_cop_names.each do |name|
194
+ @hash[name].each_key do |param|
195
+ unless default_config[name].has_key?(param)
196
+ fail ValidationError,
197
+ "unrecognized parameter #{name}:#{param} found " +
198
+ "in #{loaded_path || self}"
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ def file_to_include?(file)
205
+ relative_file_path = relative_path_to_loaded_dir(file)
206
+ patterns_to_include.any? do |pattern|
207
+ match_path?(pattern, relative_file_path)
208
+ end
209
+ end
210
+
211
+ def file_to_exclude?(file)
212
+ relative_file_path = relative_path_to_loaded_dir(file)
213
+ patterns_to_exclude.any? do |pattern|
214
+ match_path?(pattern, relative_file_path)
215
+ end
216
+ end
217
+
218
+ def patterns_to_include
219
+ @hash['AllCops']['Includes']
220
+ end
221
+
222
+ def patterns_to_exclude
223
+ @hash['AllCops']['Excludes']
224
+ end
225
+
226
+ private
227
+
228
+ def relative_path_to_loaded_dir(file)
229
+ return file unless loaded_path
230
+ Config.relative_path(file, loaded_dir_pathname)
231
+ end
232
+
233
+ def loaded_dir_pathname
234
+ return nil unless loaded_path
235
+ @loaded_dir ||= begin
236
+ loaded_dir = File.expand_path(File.dirname(loaded_path))
237
+ Pathname.new(loaded_dir)
238
+ end
239
+ end
240
+
241
+ def match_path?(pattern, path)
242
+ case pattern
243
+ when String
244
+ File.basename(path) == pattern || File.fnmatch(pattern, path)
245
+ when Regexp
246
+ path =~ pattern
247
+ end
248
+ end
249
+ end
250
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ # Handles chaching of configurations and association of inspected
5
+ # ruby files to configurations.
6
+ module ConfigStore
7
+ module_function
8
+
9
+ def prepare
10
+ # @options_config stores a config that is specified in the command line.
11
+ # This takes precedence over configs located in any directories
12
+ @options_config = nil
13
+
14
+ # @path_cache maps directories to configuration paths. We search
15
+ # for .rubocop.yml only if we haven't already found it for the
16
+ # given directory.
17
+ @path_cache = {}
18
+
19
+ # @object_cache maps configuration file paths to
20
+ # configuration objects so we only need to load them once.
21
+ @object_cache = {}
22
+ end
23
+
24
+ def set_options_config(options_config)
25
+ loaded_config = Config.load_file(options_config)
26
+ @options_config = Config.merge_with_default(loaded_config,
27
+ options_config)
28
+ end
29
+
30
+ def for(file)
31
+ return @options_config if @options_config
32
+
33
+ dir = File.dirname(file)
34
+ @path_cache[dir] ||= Config.configuration_file_for(dir)
35
+ path = @path_cache[dir]
36
+ @object_cache[path] ||= Config.configuration_from_file(path)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,138 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # A basic wrapper around Parser's tokens.
6
+ class Token
7
+ attr_reader :pos, :type, :text
8
+
9
+ def initialize(pos, type, text)
10
+ @pos, @type, @text = pos, type, text
11
+ end
12
+
13
+ def to_s
14
+ "[[#{@pos.line}, #{@pos.column}], #{@type}, #{@text.inspect}]"
15
+ end
16
+ end
17
+
18
+ # A scaffold for concrete cops.
19
+ #
20
+ # The Cop class is meant to be extended.
21
+ #
22
+ # Cops track offences and can autocorrect them of the fly.
23
+ class Cop < Parser::Rewriter
24
+ extend AST::Sexp
25
+
26
+ attr_accessor :offences
27
+ attr_accessor :debug
28
+ attr_accessor :autocorrect
29
+ attr_writer :disabled_lines
30
+
31
+ @all = []
32
+ @config = {}
33
+
34
+ class << self
35
+ attr_accessor :all
36
+ attr_accessor :config
37
+ end
38
+
39
+ def self.inherited(subclass)
40
+ all << subclass
41
+ end
42
+
43
+ def self.cop_name
44
+ name.to_s.split('::').last
45
+ end
46
+
47
+ def self.cop_type
48
+ name.to_s.split('::')[-2].downcase.to_sym
49
+ end
50
+
51
+ def self.style?
52
+ cop_type == :style
53
+ end
54
+
55
+ def self.lint?
56
+ cop_type == :lint
57
+ end
58
+
59
+ def self.rails?
60
+ cop_type == :rails
61
+ end
62
+
63
+ def initialize
64
+ @offences = []
65
+ @debug = false
66
+ @autocorrect = false
67
+ end
68
+
69
+ def inspect(source_buffer, source, tokens, ast, comments)
70
+ if autocorrect
71
+ filename = source_buffer.instance_variable_get(:@name)
72
+ new_source = rewrite(source_buffer, ast)
73
+ unless new_source == source_buffer.source
74
+ File.open(filename, 'w') { |f| f.write(new_source) }
75
+ source_buffer.instance_variable_set(:@source, nil)
76
+ source_buffer.read
77
+ end
78
+ else
79
+ process(ast)
80
+ end
81
+ end
82
+
83
+ def do_autocorrect(node)
84
+ autocorrect_action(node) if autocorrect
85
+ end
86
+
87
+ def autocorrect_action(node)
88
+ end
89
+
90
+ def ignore_node(node)
91
+ end
92
+
93
+ def add_offence(severity, location, message)
94
+ unless @disabled_lines && @disabled_lines.include?(location.line)
95
+ message = debug ? "#{name}: #{message}" : message
96
+ @offences << Offence.new(severity, location, message, name)
97
+ end
98
+ end
99
+
100
+ def name
101
+ self.class.cop_name
102
+ end
103
+
104
+ private
105
+
106
+ def on_node(syms, sexp, excludes = [])
107
+ yield sexp if Array(syms).include?(sexp.type)
108
+
109
+ return if Array(excludes).include?(sexp.type)
110
+
111
+ sexp.children.each do |elem|
112
+ if elem.is_a?(Parser::AST::Node)
113
+ on_node(syms, elem, excludes) { |s| yield s }
114
+ end
115
+ end
116
+ end
117
+
118
+ def command?(name, node)
119
+ return unless node.type == :send
120
+
121
+ receiver, method_name, _args = *node
122
+
123
+ # commands have no explicit receiver
124
+ !receiver && method_name == name
125
+ end
126
+
127
+ def source_range(source_buffer, preceding_lines, begin_column,
128
+ column_count)
129
+ newline_length = 1
130
+ begin_pos = preceding_lines.reduce(0) do |a, e|
131
+ a + e.length + newline_length
132
+ end + begin_column
133
+ Parser::Source::Range.new(source_buffer, begin_pos,
134
+ begin_pos + column_count)
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for assignments in the conditions of
7
+ # if/while/until.
8
+ class AssignmentInCondition < Cop
9
+ ASGN_NODES = [:lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn]
10
+ MSG = 'Assignment in condition - you probably meant to use ==.'
11
+
12
+ def on_if(node)
13
+ check(node)
14
+ super
15
+ end
16
+
17
+ def on_while(node)
18
+ check(node)
19
+ super
20
+ end
21
+
22
+ def on_until(node)
23
+ check(node)
24
+ super
25
+ end
26
+
27
+ private
28
+
29
+ def check(node)
30
+ condition, = *node
31
+
32
+ on_node([:begin, *ASGN_NODES], condition) do |asgn_node|
33
+ # skip safe assignment nodes if safe assignment is allowed
34
+ return if safe_assignment_allowed? && safe_assignment?(asgn_node)
35
+
36
+ # assignment nodes from shorthand ops like ||= don't have operator
37
+ if asgn_node.type != :begin && asgn_node.loc.operator
38
+ add_offence(:warning, asgn_node.loc.operator, MSG)
39
+ end
40
+ end
41
+ end
42
+
43
+ def safe_assignment?(node)
44
+ node.type == :begin && node.children.size == 1 &&
45
+ ASGN_NODES.include?(node.children[0].type)
46
+ end
47
+
48
+ def safe_assignment_allowed?
49
+ AssignmentInCondition.config['AllowSafeAssignment']
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end