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.
- data/.gitignore +50 -0
- data/.rspec +1 -0
- data/.rubocop.yml +7 -0
- data/.travis.yml +7 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +268 -0
- data/CONTRIBUTING.md +16 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +20 -0
- data/README.md +324 -0
- data/Rakefile +29 -0
- data/bin/rubocop +22 -0
- data/config/default.yml +58 -0
- data/config/disabled.yml +5 -0
- data/config/enabled.yml +403 -0
- data/lib/rubocop.rb +116 -0
- data/lib/rubocop/cli.rb +407 -0
- data/lib/rubocop/config.rb +250 -0
- data/lib/rubocop/config_store.rb +39 -0
- data/lib/rubocop/cop/cop.rb +138 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +54 -0
- data/lib/rubocop/cop/lint/end_alignment.rb +189 -0
- data/lib/rubocop/cop/lint/end_in_method.rb +30 -0
- data/lib/rubocop/cop/lint/ensure_return.rb +22 -0
- data/lib/rubocop/cop/lint/eval.rb +22 -0
- data/lib/rubocop/cop/lint/handle_exceptions.rb +20 -0
- data/lib/rubocop/cop/lint/literal_in_condition.rb +81 -0
- data/lib/rubocop/cop/lint/loop.rb +29 -0
- data/lib/rubocop/cop/lint/rescue_exception.rb +29 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +34 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +35 -0
- data/lib/rubocop/cop/lint/unused_local_variable.rb +32 -0
- data/lib/rubocop/cop/lint/void.rb +58 -0
- data/lib/rubocop/cop/offence.rb +136 -0
- data/lib/rubocop/cop/rails/validation.rb +30 -0
- data/lib/rubocop/cop/style/access_control.rb +58 -0
- data/lib/rubocop/cop/style/alias.rb +28 -0
- data/lib/rubocop/cop/style/align_parameters.rb +39 -0
- data/lib/rubocop/cop/style/and_or.rb +45 -0
- data/lib/rubocop/cop/style/ascii_comments.rb +21 -0
- data/lib/rubocop/cop/style/ascii_identifiers.rb +22 -0
- data/lib/rubocop/cop/style/attr.rb +20 -0
- data/lib/rubocop/cop/style/avoid_class_vars.rb +20 -0
- data/lib/rubocop/cop/style/avoid_for.rb +18 -0
- data/lib/rubocop/cop/style/avoid_global_vars.rb +65 -0
- data/lib/rubocop/cop/style/avoid_perl_backrefs.rb +21 -0
- data/lib/rubocop/cop/style/avoid_perlisms.rb +50 -0
- data/lib/rubocop/cop/style/begin_block.rb +18 -0
- data/lib/rubocop/cop/style/block_comments.rb +20 -0
- data/lib/rubocop/cop/style/block_nesting.rb +47 -0
- data/lib/rubocop/cop/style/blocks.rb +27 -0
- data/lib/rubocop/cop/style/case_equality.rb +22 -0
- data/lib/rubocop/cop/style/case_indentation.rb +28 -0
- data/lib/rubocop/cop/style/character_literal.rb +37 -0
- data/lib/rubocop/cop/style/class_and_module_camel_case.rb +33 -0
- data/lib/rubocop/cop/style/class_methods.rb +22 -0
- data/lib/rubocop/cop/style/collection_methods.rb +56 -0
- data/lib/rubocop/cop/style/colon_method_call.rb +29 -0
- data/lib/rubocop/cop/style/constant_name.rb +31 -0
- data/lib/rubocop/cop/style/def_parentheses.rb +70 -0
- data/lib/rubocop/cop/style/documentation.rb +58 -0
- data/lib/rubocop/cop/style/dot_position.rb +25 -0
- data/lib/rubocop/cop/style/empty_line_between_defs.rb +26 -0
- data/lib/rubocop/cop/style/empty_lines.rb +40 -0
- data/lib/rubocop/cop/style/empty_literal.rb +53 -0
- data/lib/rubocop/cop/style/encoding.rb +29 -0
- data/lib/rubocop/cop/style/end_block.rb +18 -0
- data/lib/rubocop/cop/style/end_of_line.rb +23 -0
- data/lib/rubocop/cop/style/favor_join.rb +29 -0
- data/lib/rubocop/cop/style/favor_modifier.rb +118 -0
- data/lib/rubocop/cop/style/favor_sprintf.rb +28 -0
- data/lib/rubocop/cop/style/favor_unless_over_negated_if.rb +54 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +47 -0
- data/lib/rubocop/cop/style/if_then_else.rb +29 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +20 -0
- data/lib/rubocop/cop/style/lambda.rb +47 -0
- data/lib/rubocop/cop/style/leading_comment_space.rb +25 -0
- data/lib/rubocop/cop/style/line_continuation.rb +26 -0
- data/lib/rubocop/cop/style/line_length.rb +30 -0
- data/lib/rubocop/cop/style/method_and_variable_snake_case.rb +61 -0
- data/lib/rubocop/cop/style/method_call_parentheses.rb +22 -0
- data/lib/rubocop/cop/style/method_length.rb +57 -0
- data/lib/rubocop/cop/style/multiline_if_then.rb +47 -0
- data/lib/rubocop/cop/style/not.rb +24 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +25 -0
- data/lib/rubocop/cop/style/one_line_conditional.rb +20 -0
- data/lib/rubocop/cop/style/op_method.rb +29 -0
- data/lib/rubocop/cop/style/parameter_lists.rb +42 -0
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +42 -0
- data/lib/rubocop/cop/style/proc.rb +30 -0
- data/lib/rubocop/cop/style/reduce_arguments.rb +34 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +39 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +55 -0
- data/lib/rubocop/cop/style/semicolon.rb +51 -0
- data/lib/rubocop/cop/style/single_line_methods.rb +48 -0
- data/lib/rubocop/cop/style/space_after_comma_etc.rb +69 -0
- data/lib/rubocop/cop/style/space_after_control_keyword.rb +32 -0
- data/lib/rubocop/cop/style/string_literals.rb +36 -0
- data/lib/rubocop/cop/style/surrounding_space.rb +314 -0
- data/lib/rubocop/cop/style/symbol_array.rb +31 -0
- data/lib/rubocop/cop/style/symbol_name.rb +27 -0
- data/lib/rubocop/cop/style/tab.rb +25 -0
- data/lib/rubocop/cop/style/ternary_operator.rb +49 -0
- data/lib/rubocop/cop/style/trailing_whitespace.rb +24 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +32 -0
- data/lib/rubocop/cop/style/unless_else.rb +26 -0
- data/lib/rubocop/cop/style/variable_interpolation.rb +32 -0
- data/lib/rubocop/cop/style/when_then.rb +25 -0
- data/lib/rubocop/cop/style/while_until_do.rb +45 -0
- data/lib/rubocop/cop/style/word_array.rb +44 -0
- data/lib/rubocop/cop/util.rb +27 -0
- data/lib/rubocop/cop/variable_inspector.rb +280 -0
- data/lib/rubocop/formatter/base_formatter.rb +119 -0
- data/lib/rubocop/formatter/clang_style_formatter.rb +21 -0
- data/lib/rubocop/formatter/emacs_style_formatter.rb +17 -0
- data/lib/rubocop/formatter/formatter_set.rb +77 -0
- data/lib/rubocop/formatter/json_formatter.rb +76 -0
- data/lib/rubocop/formatter/progress_formatter.rb +63 -0
- data/lib/rubocop/formatter/simple_text_formatter.rb +62 -0
- data/lib/rubocop/version.rb +21 -0
- data/rubocop.gemspec +36 -0
- data/spec/.rubocop.yml +5 -0
- data/spec/project_spec.rb +24 -0
- data/spec/rubocop/cli_spec.rb +906 -0
- data/spec/rubocop/config_spec.rb +470 -0
- data/spec/rubocop/config_store_spec.rb +66 -0
- data/spec/rubocop/cops/cop_spec.rb +38 -0
- data/spec/rubocop/cops/lint/assignment_in_condition_spec.rb +111 -0
- data/spec/rubocop/cops/lint/end_alignment_spec.rb +333 -0
- data/spec/rubocop/cops/lint/end_in_method_spec.rb +35 -0
- data/spec/rubocop/cops/lint/ensure_return_spec.rb +37 -0
- data/spec/rubocop/cops/lint/eval_spec.rb +41 -0
- data/spec/rubocop/cops/lint/handle_exceptions_spec.rb +36 -0
- data/spec/rubocop/cops/lint/literal_in_condition_spec.rb +42 -0
- data/spec/rubocop/cops/lint/loop_spec.rb +33 -0
- data/spec/rubocop/cops/lint/rescue_exception_spec.rb +127 -0
- data/spec/rubocop/cops/lint/shadowing_outer_local_variable_spec.rb +243 -0
- data/spec/rubocop/cops/lint/unreachable_code_spec.rb +69 -0
- data/spec/rubocop/cops/lint/unused_local_variable_spec.rb +497 -0
- data/spec/rubocop/cops/lint/void_spec.rb +63 -0
- data/spec/rubocop/cops/offence_spec.rb +133 -0
- data/spec/rubocop/cops/rails/validation_spec.rb +27 -0
- data/spec/rubocop/cops/style/access_control_spec.rb +142 -0
- data/spec/rubocop/cops/style/alias_spec.rb +47 -0
- data/spec/rubocop/cops/style/align_parameters_spec.rb +199 -0
- data/spec/rubocop/cops/style/and_or_spec.rb +39 -0
- data/spec/rubocop/cops/style/ascii_comments_spec.rb +28 -0
- data/spec/rubocop/cops/style/ascii_identifiers_spec.rb +28 -0
- data/spec/rubocop/cops/style/attr_spec.rb +20 -0
- data/spec/rubocop/cops/style/avoid_class_vars_spec.rb +27 -0
- data/spec/rubocop/cops/style/avoid_for_spec.rb +37 -0
- data/spec/rubocop/cops/style/avoid_global_vars_spec.rb +34 -0
- data/spec/rubocop/cops/style/avoid_perl_backrefs_spec.rb +20 -0
- data/spec/rubocop/cops/style/avoid_perlisms_spec.rb +47 -0
- data/spec/rubocop/cops/style/begin_block_spec.rb +19 -0
- data/spec/rubocop/cops/style/block_comments_spec.rb +27 -0
- data/spec/rubocop/cops/style/block_nesting_spec.rb +159 -0
- data/spec/rubocop/cops/style/blocks_spec.rb +35 -0
- data/spec/rubocop/cops/style/case_equality_spec.rb +18 -0
- data/spec/rubocop/cops/style/case_indentation_spec.rb +88 -0
- data/spec/rubocop/cops/style/character_literal_spec.rb +28 -0
- data/spec/rubocop/cops/style/class_and_module_camel_case_spec.rb +46 -0
- data/spec/rubocop/cops/style/class_methods_spec.rb +51 -0
- data/spec/rubocop/cops/style/collection_methods_spec.rb +41 -0
- data/spec/rubocop/cops/style/colon_method_call_spec.rb +55 -0
- data/spec/rubocop/cops/style/constant_name_spec.rb +56 -0
- data/spec/rubocop/cops/style/def_with_parentheses_spec.rb +40 -0
- data/spec/rubocop/cops/style/def_without_parentheses_spec.rb +34 -0
- data/spec/rubocop/cops/style/documentation_spec.rb +79 -0
- data/spec/rubocop/cops/style/dot_position_spec.rb +30 -0
- data/spec/rubocop/cops/style/empty_line_between_defs_spec.rb +85 -0
- data/spec/rubocop/cops/style/empty_lines_spec.rb +40 -0
- data/spec/rubocop/cops/style/empty_literal_spec.rb +91 -0
- data/spec/rubocop/cops/style/encoding_spec.rb +49 -0
- data/spec/rubocop/cops/style/end_block_spec.rb +19 -0
- data/spec/rubocop/cops/style/end_of_line_spec.rb +25 -0
- data/spec/rubocop/cops/style/favor_join_spec.rb +37 -0
- data/spec/rubocop/cops/style/favor_modifier_spec.rb +160 -0
- data/spec/rubocop/cops/style/favor_sprintf_spec.rb +53 -0
- data/spec/rubocop/cops/style/favor_unless_over_negated_if_spec.rb +64 -0
- data/spec/rubocop/cops/style/favor_until_over_negated_while_spec.rb +47 -0
- data/spec/rubocop/cops/style/hash_syntax_spec.rb +51 -0
- data/spec/rubocop/cops/style/if_with_semicolon_spec.rb +25 -0
- data/spec/rubocop/cops/style/lambda_spec.rb +45 -0
- data/spec/rubocop/cops/style/leading_comment_space_spec.rb +65 -0
- data/spec/rubocop/cops/style/line_continuation_spec.rb +26 -0
- data/spec/rubocop/cops/style/line_length_spec.rb +25 -0
- data/spec/rubocop/cops/style/method_and_variable_snake_case_spec.rb +95 -0
- data/spec/rubocop/cops/style/method_call_parentheses_spec.rb +25 -0
- data/spec/rubocop/cops/style/method_length_spec.rb +151 -0
- data/spec/rubocop/cops/style/multiline_if_then_spec.rb +97 -0
- data/spec/rubocop/cops/style/not_spec.rb +28 -0
- data/spec/rubocop/cops/style/numeric_literals_spec.rb +51 -0
- data/spec/rubocop/cops/style/one_line_conditional_spec.rb +18 -0
- data/spec/rubocop/cops/style/op_method_spec.rb +80 -0
- data/spec/rubocop/cops/style/parameter_lists_spec.rb +49 -0
- data/spec/rubocop/cops/style/parentheses_around_condition_spec.rb +59 -0
- data/spec/rubocop/cops/style/proc_spec.rb +28 -0
- data/spec/rubocop/cops/style/reduce_arguments_spec.rb +59 -0
- data/spec/rubocop/cops/style/regexp_literal_spec.rb +83 -0
- data/spec/rubocop/cops/style/rescue_modifier_spec.rb +122 -0
- data/spec/rubocop/cops/style/semicolon_spec.rb +95 -0
- data/spec/rubocop/cops/style/single_line_methods_spec.rb +54 -0
- data/spec/rubocop/cops/style/space_after_colon_spec.rb +29 -0
- data/spec/rubocop/cops/style/space_after_comma_spec.rb +31 -0
- data/spec/rubocop/cops/style/space_after_control_keyword_spec.rb +69 -0
- data/spec/rubocop/cops/style/space_after_semicolon_spec.rb +24 -0
- data/spec/rubocop/cops/style/space_around_braces_spec.rb +49 -0
- data/spec/rubocop/cops/style/space_around_equals_in_default_parameter_spec.rb +34 -0
- data/spec/rubocop/cops/style/space_around_operators_spec.rb +216 -0
- data/spec/rubocop/cops/style/space_inside_brackets_spec.rb +51 -0
- data/spec/rubocop/cops/style/space_inside_hash_literal_braces_spec.rb +99 -0
- data/spec/rubocop/cops/style/space_inside_parens_spec.rb +33 -0
- data/spec/rubocop/cops/style/string_literals_spec.rb +62 -0
- data/spec/rubocop/cops/style/symbol_array_spec.rb +45 -0
- data/spec/rubocop/cops/style/symbol_name_spec.rb +122 -0
- data/spec/rubocop/cops/style/tab_spec.rb +23 -0
- data/spec/rubocop/cops/style/ternary_operator_spec.rb +42 -0
- data/spec/rubocop/cops/style/trailing_whitespace_spec.rb +29 -0
- data/spec/rubocop/cops/style/trivial_accessors_spec.rb +338 -0
- data/spec/rubocop/cops/style/unless_else_spec.rb +31 -0
- data/spec/rubocop/cops/style/variable_interpolation_spec.rb +53 -0
- data/spec/rubocop/cops/style/when_then_spec.rb +40 -0
- data/spec/rubocop/cops/style/while_until_do_spec.rb +47 -0
- data/spec/rubocop/cops/style/word_array_spec.rb +61 -0
- data/spec/rubocop/cops/variable_inspector_spec.rb +374 -0
- data/spec/rubocop/formatter/base_formatter_spec.rb +190 -0
- data/spec/rubocop/formatter/clang_style_formatter_spec.rb +70 -0
- data/spec/rubocop/formatter/emacs_style_formatter_spec.rb +32 -0
- data/spec/rubocop/formatter/formatter_set_spec.rb +132 -0
- data/spec/rubocop/formatter/json_formatter_spec.rb +142 -0
- data/spec/rubocop/formatter/progress_formatter_spec.rb +196 -0
- data/spec/rubocop/formatter/simple_text_formatter_spec.rb +74 -0
- data/spec/spec_helper.rb +92 -0
- data/spec/support/file_helper.rb +21 -0
- data/spec/support/isolated_environment.rb +27 -0
- data/spec/support/mri_syntax_checker.rb +69 -0
- data/spec/support/shared_examples.rb +33 -0
- 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
|