excellent 1.5.4
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/History.txt +69 -0
- data/README.rdoc +72 -0
- data/VERSION.yml +4 -0
- data/bin/excellent +34 -0
- data/lib/simplabs/excellent.rb +16 -0
- data/lib/simplabs/excellent/checks.rb +33 -0
- data/lib/simplabs/excellent/checks/abc_metric_method_check.rb +43 -0
- data/lib/simplabs/excellent/checks/assignment_in_conditional_check.rb +39 -0
- data/lib/simplabs/excellent/checks/base.rb +62 -0
- data/lib/simplabs/excellent/checks/case_missing_else_check.rb +34 -0
- data/lib/simplabs/excellent/checks/class_line_count_check.rb +36 -0
- data/lib/simplabs/excellent/checks/class_name_check.rb +38 -0
- data/lib/simplabs/excellent/checks/control_coupling_check.rb +35 -0
- data/lib/simplabs/excellent/checks/cyclomatic_complexity_block_check.rb +48 -0
- data/lib/simplabs/excellent/checks/cyclomatic_complexity_check.rb +23 -0
- data/lib/simplabs/excellent/checks/cyclomatic_complexity_method_check.rb +48 -0
- data/lib/simplabs/excellent/checks/empty_rescue_body_check.rb +31 -0
- data/lib/simplabs/excellent/checks/flog_block_check.rb +40 -0
- data/lib/simplabs/excellent/checks/flog_check.rb +27 -0
- data/lib/simplabs/excellent/checks/flog_class_check.rb +40 -0
- data/lib/simplabs/excellent/checks/flog_method_check.rb +40 -0
- data/lib/simplabs/excellent/checks/for_loop_check.rb +42 -0
- data/lib/simplabs/excellent/checks/global_variable_check.rb +33 -0
- data/lib/simplabs/excellent/checks/line_count_check.rb +27 -0
- data/lib/simplabs/excellent/checks/method_line_count_check.rb +36 -0
- data/lib/simplabs/excellent/checks/method_name_check.rb +38 -0
- data/lib/simplabs/excellent/checks/module_line_count_check.rb +36 -0
- data/lib/simplabs/excellent/checks/module_name_check.rb +38 -0
- data/lib/simplabs/excellent/checks/name_check.rb +27 -0
- data/lib/simplabs/excellent/checks/nested_iterators_check.rb +34 -0
- data/lib/simplabs/excellent/checks/parameter_number_check.rb +38 -0
- data/lib/simplabs/excellent/checks/rails.rb +22 -0
- data/lib/simplabs/excellent/checks/rails/attr_accessible_check.rb +38 -0
- data/lib/simplabs/excellent/checks/rails/attr_protected_check.rb +39 -0
- data/lib/simplabs/excellent/checks/rails/custom_initialize_method_check.rb +37 -0
- data/lib/simplabs/excellent/checks/rails/instance_var_in_partial_check.rb +37 -0
- data/lib/simplabs/excellent/checks/rails/params_hash_in_view_check.rb +38 -0
- data/lib/simplabs/excellent/checks/rails/session_hash_in_view_check.rb +38 -0
- data/lib/simplabs/excellent/checks/rails/validations_check.rb +36 -0
- data/lib/simplabs/excellent/checks/singleton_variable_check.rb +33 -0
- data/lib/simplabs/excellent/command_line_runner.rb +37 -0
- data/lib/simplabs/excellent/extensions/sexp.rb +21 -0
- data/lib/simplabs/excellent/extensions/string.rb +28 -0
- data/lib/simplabs/excellent/formatters.rb +13 -0
- data/lib/simplabs/excellent/formatters/base.rb +49 -0
- data/lib/simplabs/excellent/formatters/html.rb +153 -0
- data/lib/simplabs/excellent/formatters/text.rb +40 -0
- data/lib/simplabs/excellent/parsing.rb +10 -0
- data/lib/simplabs/excellent/parsing/abc_measure.rb +52 -0
- data/lib/simplabs/excellent/parsing/block_context.rb +43 -0
- data/lib/simplabs/excellent/parsing/call_context.rb +52 -0
- data/lib/simplabs/excellent/parsing/case_context.rb +31 -0
- data/lib/simplabs/excellent/parsing/class_context.rb +99 -0
- data/lib/simplabs/excellent/parsing/code_processor.rb +165 -0
- data/lib/simplabs/excellent/parsing/conditional_context.rb +25 -0
- data/lib/simplabs/excellent/parsing/cvar_context.rb +28 -0
- data/lib/simplabs/excellent/parsing/cyclomatic_complexity_measure.rb +73 -0
- data/lib/simplabs/excellent/parsing/flog_measure.rb +192 -0
- data/lib/simplabs/excellent/parsing/for_loop_context.rb +15 -0
- data/lib/simplabs/excellent/parsing/gvar_context.rb +21 -0
- data/lib/simplabs/excellent/parsing/if_context.rb +38 -0
- data/lib/simplabs/excellent/parsing/ivar_context.rb +32 -0
- data/lib/simplabs/excellent/parsing/method_context.rb +50 -0
- data/lib/simplabs/excellent/parsing/module_context.rb +29 -0
- data/lib/simplabs/excellent/parsing/parser.rb +35 -0
- data/lib/simplabs/excellent/parsing/resbody_context.rb +39 -0
- data/lib/simplabs/excellent/parsing/scopeable.rb +34 -0
- data/lib/simplabs/excellent/parsing/sexp_context.rb +125 -0
- data/lib/simplabs/excellent/parsing/singleton_method_context.rb +55 -0
- data/lib/simplabs/excellent/parsing/until_context.rb +24 -0
- data/lib/simplabs/excellent/parsing/while_context.rb +24 -0
- data/lib/simplabs/excellent/rake.rb +1 -0
- data/lib/simplabs/excellent/rake/excellent_task.rb +61 -0
- data/lib/simplabs/excellent/runner.rb +143 -0
- data/lib/simplabs/excellent/warning.rb +53 -0
- data/spec/checks/abc_metric_method_check_spec.rb +122 -0
- data/spec/checks/assignment_in_conditional_check_spec.rb +90 -0
- data/spec/checks/case_missing_else_check_spec.rb +42 -0
- data/spec/checks/class_line_count_check_spec.rb +62 -0
- data/spec/checks/class_name_check_spec.rb +48 -0
- data/spec/checks/control_coupling_check_spec.rb +103 -0
- data/spec/checks/cyclomatic_complexity_block_check_spec.rb +47 -0
- data/spec/checks/cyclomatic_complexity_method_check_spec.rb +210 -0
- data/spec/checks/empty_rescue_body_check_spec.rb +170 -0
- data/spec/checks/flog_block_check_spec.rb +28 -0
- data/spec/checks/flog_class_check_spec.rb +28 -0
- data/spec/checks/flog_method_check_spec.rb +46 -0
- data/spec/checks/for_loop_check_spec.rb +52 -0
- data/spec/checks/global_variable_check_spec.rb +66 -0
- data/spec/checks/method_line_count_check_spec.rb +49 -0
- data/spec/checks/method_name_check_spec.rb +112 -0
- data/spec/checks/module_line_count_check_spec.rb +48 -0
- data/spec/checks/module_name_check_spec.rb +61 -0
- data/spec/checks/nested_iterators_check_spec.rb +44 -0
- data/spec/checks/parameter_number_check_spec.rb +97 -0
- data/spec/checks/rails/attr_accessible_check_spec.rb +79 -0
- data/spec/checks/rails/attr_protected_check_spec.rb +77 -0
- data/spec/checks/rails/custom_initialize_method_check_spec.rb +58 -0
- data/spec/checks/rails/instance_var_in_partial_check_spec.rb +40 -0
- data/spec/checks/rails/params_hash_in_view_check_spec.rb +40 -0
- data/spec/checks/rails/session_hash_in_view_check_spec.rb +40 -0
- data/spec/checks/rails/validations_check_spec.rb +81 -0
- data/spec/checks/singleton_variable_check_spec.rb +66 -0
- data/spec/extensions/string_spec.rb +13 -0
- data/spec/spec_helper.rb +13 -0
- metadata +189 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'simplabs/excellent/formatters/base'
|
2
|
+
|
3
|
+
module Simplabs
|
4
|
+
|
5
|
+
module Excellent
|
6
|
+
|
7
|
+
module Formatters
|
8
|
+
|
9
|
+
class Text < Base #:nodoc:
|
10
|
+
|
11
|
+
def initialize(stream = $stdout)
|
12
|
+
super
|
13
|
+
@total_warnings = 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def start
|
17
|
+
@stream.puts "\n Excellent result:\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
def file(filename)
|
21
|
+
@stream.puts "\n #{filename}\n"
|
22
|
+
yield self
|
23
|
+
end
|
24
|
+
|
25
|
+
def warning(warning)
|
26
|
+
@stream.puts " * Line #{warning.line_number.to_s.lpad(3)}: \e[33m#{warning.message}\e[0m"
|
27
|
+
@total_warnings += 1
|
28
|
+
end
|
29
|
+
|
30
|
+
def end
|
31
|
+
@stream.puts "\n Found #{@total_warnings} warnings.\n\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Simplabs
|
2
|
+
|
3
|
+
module Excellent
|
4
|
+
|
5
|
+
module Parsing
|
6
|
+
|
7
|
+
module AbcMeasure #:nodoc:
|
8
|
+
|
9
|
+
CONDITIONS = [:==, :<=, :>=, :<, :>]
|
10
|
+
|
11
|
+
def process_lasgn(exp)
|
12
|
+
@assignments ||= 0
|
13
|
+
@assignments += 1
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def process_call(exp)
|
18
|
+
handle_call(exp)
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def process_vcall(exp)
|
23
|
+
handle_call(exp)
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
def abc_score
|
28
|
+
a = @assignments ||= 0
|
29
|
+
b = @branches ||= 0
|
30
|
+
c = @conditionals ||= 0
|
31
|
+
Math.sqrt(a * a + b * b + c * c)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def handle_call(exp)
|
37
|
+
@branches ||= 0
|
38
|
+
@conditionals ||= 0
|
39
|
+
if CONDITIONS.include?(exp[2])
|
40
|
+
@conditionals += 1
|
41
|
+
else
|
42
|
+
@branches += 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'simplabs/excellent/parsing/cyclomatic_complexity_measure'
|
2
|
+
|
3
|
+
module Simplabs
|
4
|
+
|
5
|
+
module Excellent
|
6
|
+
|
7
|
+
module Parsing
|
8
|
+
|
9
|
+
class BlockContext < SexpContext #:nodoc:
|
10
|
+
|
11
|
+
include CyclomaticComplexityMeasure
|
12
|
+
include FlogMeasure
|
13
|
+
|
14
|
+
attr_reader :parameters
|
15
|
+
attr_reader :calls
|
16
|
+
|
17
|
+
def initialize(exp, parent)
|
18
|
+
super
|
19
|
+
@parameters = []
|
20
|
+
@name = 'block'
|
21
|
+
@line = exp.line < exp[1].line ? exp.line : exp[1].line
|
22
|
+
@calls = Hash.new(0)
|
23
|
+
end
|
24
|
+
|
25
|
+
def full_name
|
26
|
+
@name
|
27
|
+
end
|
28
|
+
|
29
|
+
def record_call_to(exp)
|
30
|
+
@calls[exp] += 1
|
31
|
+
end
|
32
|
+
|
33
|
+
def inside_block?
|
34
|
+
@parent.is_a?(BlockContext)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Simplabs
|
2
|
+
|
3
|
+
module Excellent
|
4
|
+
|
5
|
+
module Parsing
|
6
|
+
|
7
|
+
class CallContext < SexpContext #:nodoc:
|
8
|
+
|
9
|
+
include Comparable
|
10
|
+
|
11
|
+
attr_reader :receiver
|
12
|
+
attr_reader :method
|
13
|
+
|
14
|
+
def initialize(exp, parent)
|
15
|
+
super
|
16
|
+
@receiver = exp[1].is_a?(Sexp) ? (exp[1][1].nil? ? exp[1][2].to_s : exp[1][1].to_s) : nil
|
17
|
+
@method = exp[2].to_s
|
18
|
+
@full_name = [@receiver, @method].compact.join('.')
|
19
|
+
record_validation
|
20
|
+
record_call
|
21
|
+
end
|
22
|
+
|
23
|
+
def <=>(other)
|
24
|
+
@full_name <=> other.full_name
|
25
|
+
end
|
26
|
+
alias :eql? :'<=>'
|
27
|
+
|
28
|
+
def hash
|
29
|
+
@full_name.hash
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def record_call
|
35
|
+
parent = @parent
|
36
|
+
parent = parent.parent until parent.nil? || parent.is_a?(MethodContext) || parent.is_a?(BlockContext) || parent.is_a?(SingletonMethodContext)
|
37
|
+
parent.record_call_to(self) if parent
|
38
|
+
end
|
39
|
+
|
40
|
+
def record_validation
|
41
|
+
if ClassContext::VALIDATIONS.include?(@method) && @parent && @parent.is_a?(ClassContext) && @parent.active_record_model?
|
42
|
+
@parent.validations << @method
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'simplabs/excellent/parsing/conditional_context'
|
2
|
+
|
3
|
+
module Simplabs
|
4
|
+
|
5
|
+
module Excellent
|
6
|
+
|
7
|
+
module Parsing
|
8
|
+
|
9
|
+
class CaseContext < ConditionalContext #:nodoc:
|
10
|
+
|
11
|
+
def initialize(exp, parent)
|
12
|
+
super
|
13
|
+
@has_else_clause = exp.last
|
14
|
+
@tests_parameter = contains_parameter?
|
15
|
+
end
|
16
|
+
|
17
|
+
def has_else_clause?
|
18
|
+
@has_else_clause
|
19
|
+
end
|
20
|
+
|
21
|
+
def tests_parameter?
|
22
|
+
@tests_parameter
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'simplabs/excellent/parsing/scopeable'
|
2
|
+
|
3
|
+
module Simplabs
|
4
|
+
|
5
|
+
module Excellent
|
6
|
+
|
7
|
+
module Parsing
|
8
|
+
|
9
|
+
class ClassContext < SexpContext #:nodoc:
|
10
|
+
|
11
|
+
include FlogMeasure
|
12
|
+
include Scopeable
|
13
|
+
|
14
|
+
VALIDATIONS = %w(
|
15
|
+
validates_acceptance_of
|
16
|
+
validates_associated
|
17
|
+
validates_confirmation_of
|
18
|
+
validates_each
|
19
|
+
validates_exclusion_of
|
20
|
+
validates_format_of
|
21
|
+
validates_inclusion_of
|
22
|
+
validates_length_of
|
23
|
+
validates_numericality_of
|
24
|
+
validates_presence_of
|
25
|
+
validates_size_of
|
26
|
+
validates_uniqueness_of
|
27
|
+
)
|
28
|
+
|
29
|
+
attr_reader :methods
|
30
|
+
attr_reader :line_count
|
31
|
+
attr_reader :base_class_name
|
32
|
+
attr_reader :validations
|
33
|
+
|
34
|
+
def initialize(exp, parent)
|
35
|
+
super
|
36
|
+
@name, @full_name = get_names
|
37
|
+
@base_class_name = get_base_class_name
|
38
|
+
@methods = []
|
39
|
+
@line_count = count_lines
|
40
|
+
@attr_accessible = false
|
41
|
+
@attr_protected = false
|
42
|
+
@initializer = false
|
43
|
+
@validations = []
|
44
|
+
end
|
45
|
+
|
46
|
+
def active_record_model?
|
47
|
+
@base_class_name == 'ActiveRecord::Base'
|
48
|
+
end
|
49
|
+
|
50
|
+
def specifies_attr_accessible?
|
51
|
+
@attr_accessible
|
52
|
+
end
|
53
|
+
|
54
|
+
def specifies_attr_protected?
|
55
|
+
@attr_protected
|
56
|
+
end
|
57
|
+
|
58
|
+
def defines_initializer?
|
59
|
+
@initializer
|
60
|
+
end
|
61
|
+
|
62
|
+
def validating?
|
63
|
+
!@validations.empty? || @methods.any?{ |method| %(validate validate_on_create validate_on_update).include?(method.name) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def process_call(exp)
|
67
|
+
@attr_accessible = true if exp[2] == :attr_accessible
|
68
|
+
@attr_protected = true if exp[2] == :attr_protected
|
69
|
+
super
|
70
|
+
end
|
71
|
+
|
72
|
+
def process_defn(exp)
|
73
|
+
@initializer = true if exp[2] == :initialize
|
74
|
+
super
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def get_base_class_name
|
80
|
+
base = @exp[2]
|
81
|
+
base_class_name = ''
|
82
|
+
while base.is_a?(Sexp)
|
83
|
+
base_class_name = "#{base.last}::#{base_class_name}"
|
84
|
+
if base[0] == :colon2
|
85
|
+
base = base[1]
|
86
|
+
else
|
87
|
+
break
|
88
|
+
end
|
89
|
+
end
|
90
|
+
base_class_name = base_class_name.empty? ? nil : base_class_name.sub(/::$/, '')
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'sexp_processor'
|
2
|
+
require 'simplabs/excellent/extensions/sexp'
|
3
|
+
require 'simplabs/excellent/parsing/if_context'
|
4
|
+
require 'simplabs/excellent/parsing/method_context'
|
5
|
+
require 'simplabs/excellent/parsing/singleton_method_context'
|
6
|
+
require 'simplabs/excellent/parsing/case_context'
|
7
|
+
require 'simplabs/excellent/parsing/block_context'
|
8
|
+
require 'simplabs/excellent/parsing/class_context'
|
9
|
+
require 'simplabs/excellent/parsing/module_context'
|
10
|
+
require 'simplabs/excellent/parsing/for_loop_context'
|
11
|
+
require 'simplabs/excellent/parsing/while_context'
|
12
|
+
require 'simplabs/excellent/parsing/until_context'
|
13
|
+
require 'simplabs/excellent/parsing/cvar_context'
|
14
|
+
require 'simplabs/excellent/parsing/gvar_context'
|
15
|
+
require 'simplabs/excellent/parsing/ivar_context'
|
16
|
+
require 'simplabs/excellent/parsing/resbody_context'
|
17
|
+
require 'simplabs/excellent/parsing/call_context'
|
18
|
+
|
19
|
+
module Simplabs
|
20
|
+
|
21
|
+
module Excellent
|
22
|
+
|
23
|
+
module Parsing
|
24
|
+
|
25
|
+
class CodeProcessor < SexpProcessor #:nodoc:
|
26
|
+
|
27
|
+
def initialize(checks)
|
28
|
+
setup_checks(checks)
|
29
|
+
setup_processors
|
30
|
+
super()
|
31
|
+
@require_empty = @warn_on_default = false
|
32
|
+
@contexts = []
|
33
|
+
@default_method = 'process_default'
|
34
|
+
end
|
35
|
+
|
36
|
+
def process(exp)
|
37
|
+
super
|
38
|
+
rescue
|
39
|
+
#continue on errors
|
40
|
+
end
|
41
|
+
|
42
|
+
def process_class(exp)
|
43
|
+
process_default(exp, ClassContext.new(exp, @contexts.last))
|
44
|
+
end
|
45
|
+
|
46
|
+
def process_module(exp)
|
47
|
+
process_default(exp, ModuleContext.new(exp, @contexts.last))
|
48
|
+
end
|
49
|
+
|
50
|
+
def process_defn(exp)
|
51
|
+
process_default(exp, MethodContext.new(exp, @contexts.last))
|
52
|
+
end
|
53
|
+
|
54
|
+
def process_defs(exp)
|
55
|
+
process_default(exp, SingletonMethodContext.new(exp, @contexts.last))
|
56
|
+
end
|
57
|
+
|
58
|
+
def process_ivar(exp)
|
59
|
+
process_default(exp, IvarContext.new(exp, @contexts.last))
|
60
|
+
end
|
61
|
+
|
62
|
+
def process_cvar(exp)
|
63
|
+
process_default(exp, CvarContext.new(exp, @contexts.last))
|
64
|
+
end
|
65
|
+
|
66
|
+
def process_gvar(exp)
|
67
|
+
process_default(exp, GvarContext.new(exp, @contexts.last))
|
68
|
+
end
|
69
|
+
|
70
|
+
def process_gasgn(exp)
|
71
|
+
process_default(exp, GvarContext.new(exp, @contexts.last))
|
72
|
+
end
|
73
|
+
|
74
|
+
def process_if(exp)
|
75
|
+
process_default(exp, IfContext.new(exp, @contexts.last))
|
76
|
+
end
|
77
|
+
|
78
|
+
def process_while(exp)
|
79
|
+
process_default(exp, WhileContext.new(exp, @contexts.last))
|
80
|
+
end
|
81
|
+
|
82
|
+
def process_until(exp)
|
83
|
+
process_default(exp, UntilContext.new(exp, @contexts.last))
|
84
|
+
end
|
85
|
+
|
86
|
+
def process_for(exp)
|
87
|
+
process_default(exp, ForLoopContext.new(exp, @contexts.last))
|
88
|
+
end
|
89
|
+
|
90
|
+
def process_args(exp)
|
91
|
+
exp[1..-1].each { |parameter| @contexts.last.parameters << parameter if parameter.is_a?(Symbol) }
|
92
|
+
process_default(exp)
|
93
|
+
end
|
94
|
+
|
95
|
+
def process_masgn(exp)
|
96
|
+
exp[1][1..-1].each { |parameter| @contexts.last.parameters << parameter[1] if parameter[1].is_a?(Symbol) } if @contexts.last.is_a?(BlockContext)
|
97
|
+
process_default(exp)
|
98
|
+
end
|
99
|
+
|
100
|
+
def process_case(exp)
|
101
|
+
process_default(exp, CaseContext.new(exp, @contexts.last))
|
102
|
+
end
|
103
|
+
|
104
|
+
def process_iter(exp)
|
105
|
+
process_default(exp, BlockContext.new(exp, @contexts.last))
|
106
|
+
end
|
107
|
+
|
108
|
+
def process_call(exp)
|
109
|
+
process_default(exp, CallContext.new(exp, @contexts.last))
|
110
|
+
end
|
111
|
+
|
112
|
+
def process_resbody(exp)
|
113
|
+
process_default(exp, ResbodyContext.new(exp, @contexts.last))
|
114
|
+
end
|
115
|
+
|
116
|
+
def process_default(exp, context = nil)
|
117
|
+
@contexts.push(context) if context
|
118
|
+
@contexts.each do |c|
|
119
|
+
method = "process_#{exp.node_type}".to_sym
|
120
|
+
c.send(method, exp) if c.respond_to?(method)
|
121
|
+
end
|
122
|
+
exp.children.each { |sub| process(sub) }
|
123
|
+
apply_checks(exp)
|
124
|
+
@contexts.pop if context
|
125
|
+
exp
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def apply_checks(exp)
|
131
|
+
if exp.is_a?(Sexp)
|
132
|
+
checks = @checks[exp.node_type] || []
|
133
|
+
checks.each { |check| check.evaluate_node(@contexts.last) if check.interesting_files.any? { |pattern| File.basename(exp.file) =~ pattern } }
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def setup_checks(checks)
|
138
|
+
@checks = {}
|
139
|
+
checks.each do |check|
|
140
|
+
check.interesting_nodes.each do |node|
|
141
|
+
@checks[node] ||= []
|
142
|
+
@checks[node] << check
|
143
|
+
@checks[node].uniq!
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def setup_processors
|
149
|
+
@checks.each_key do |key|
|
150
|
+
method = "process_#{key.to_s}".to_sym
|
151
|
+
unless self.respond_to?(method)
|
152
|
+
self.class.send(:define_method, method) do |exp| # def process_call(exp)
|
153
|
+
process_default(exp) # process_default(exp)
|
154
|
+
end # end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|