sandi_meter 1.0.3 → 1.0.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.
- checksums.yaml +9 -9
- data/bin/sandi_meter +2 -0
- data/html/script.js +10 -9
- data/lib/sandi_meter/analyzer.rb +42 -62
- data/lib/sandi_meter/calculator.rb +26 -41
- data/lib/sandi_meter/cli.rb +21 -10
- data/lib/sandi_meter/file_scanner.rb +1 -1
- data/lib/sandi_meter/logger.rb +20 -22
- data/lib/sandi_meter/rules_checker.rb +20 -0
- data/lib/sandi_meter/sandi_meter/class.rb +29 -0
- data/lib/sandi_meter/sandi_meter/method.rb +26 -0
- data/lib/sandi_meter/sandi_meter/method_call.rb +11 -0
- data/lib/sandi_meter/version.rb +1 -1
- data/spec/analyzer_spec.rb +199 -46
- data/spec/calculator_spec.rb +3 -3
- data/spec/rules_checker_spec.rb +32 -0
- data/spec/support/args_loader.rb +28 -0
- data/spec/support/attr_matcher.rb +28 -0
- data/spec/support/helper_methods.rb +17 -0
- data/spec/test_helper.rb +1 -46
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NjM5NTVlNTgyZGU3ZDQ2ZjgyMzU0MmY1YjkwZmFkNjViMjYzNzE1YQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
7
|
-
|
6
|
+
NjJjODA5ZDlkZDQwZmU0OThmYjAzOGM0ZjJhMjEzNjI0ZWI0M2E1OQ==
|
7
|
+
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YzE5OTlmMjQ2NzkzMzY4MzU5NDYwMDEwYjNlOGNiMTI5ZDc0MDlkODdlZjFm
|
10
|
+
ODdiM2Q3ZTkwMzc5YjE2M2QzMDc3MjhjZmUxMjNhNzU3ODQ4MzYyYzM0YjRj
|
11
|
+
MjQwYzBkOGIzNjM2ZjlhODg0NjAyZmJiNWYxY2NmODk1YjRiYmU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NDU3NmQ4MGIwYmU5YmQ1MjdiNjJjMTk1ODRiZWM0MmYzYThjZTk0NmRjODZj
|
14
|
+
OGQxOGZkOTVhMTI2YzU5YWZlODg5MmM1ZDYxOTA1ZjBhYWYxMDQzODNmMzRk
|
15
|
+
YTRiM2VhODZjYjNmYWM5NjIyZjljNmJlZDA2YjMwMDBjZTJhNTQ=
|
data/bin/sandi_meter
CHANGED
data/html/script.js
CHANGED
@@ -35,7 +35,7 @@ function plotLine(id, data, ykeys, labels) {
|
|
35
35
|
});
|
36
36
|
}
|
37
37
|
|
38
|
-
function
|
38
|
+
function lastReport(data) {
|
39
39
|
return data.sort(function(a, b){
|
40
40
|
var keyA = new Date(a.timestamp),
|
41
41
|
keyB = new Date(b.timestamp);
|
@@ -47,23 +47,24 @@ function latestReport(data) {
|
|
47
47
|
}
|
48
48
|
|
49
49
|
function dateHeader(last_report) {
|
50
|
-
var
|
50
|
+
var date = new Date(last_report.timestamp);
|
51
|
+
var d = date.toString().split(' ');
|
51
52
|
return date_string = [d[3], d[1], d[2], d[4]].join(' ');
|
52
53
|
}
|
53
54
|
|
54
55
|
function setHeader(last_report) {
|
55
|
-
$('.js-report-date').text("Latest report from " + dateHeader(
|
56
|
+
$('.js-report-date').text("Latest report from " + dateHeader(last_report));
|
56
57
|
}
|
57
58
|
|
58
59
|
$(document).ready(function(){
|
59
|
-
|
60
|
+
last_report = lastReport(data);
|
60
61
|
|
61
|
-
setHeader();
|
62
|
+
setHeader(last_report);
|
62
63
|
|
63
|
-
plotDonut(
|
64
|
-
plotDonut(
|
65
|
-
plotDonut(
|
66
|
-
plotDonut(
|
64
|
+
plotDonut(last_report.r10, last_report.r11, '1. Classes under 100 lines', '1. Classes more than 100 lines', 'pie1');
|
65
|
+
plotDonut(last_report.r20, last_report.r21, '2. Methods under 5 lines', '2. Methods more than 5 lines', 'pie2');
|
66
|
+
plotDonut(last_report.r30, last_report.r31, '3. Method calls with less than 4 params', '3. Method calls with more than 4 params', 'pie3');
|
67
|
+
plotDonut(last_report.r40, last_report.r41, '4. Controllers with one instance variable', '4. Controllers with many instance variables', 'pie4');
|
67
68
|
|
68
69
|
plotLine('plot1', data, ['r10', 'r11'], ['under 100 lines', 'more than 100 lines.']);
|
69
70
|
plotLine('plot2', data, ['r20', 'r21'], ['under 5 lines', 'more than 5 lines']);
|
data/lib/sandi_meter/analyzer.rb
CHANGED
@@ -2,21 +2,19 @@ require 'ripper'
|
|
2
2
|
require_relative 'warning_scanner'
|
3
3
|
require_relative 'loc_checker'
|
4
4
|
require_relative 'method_arguments_counter'
|
5
|
+
require_relative 'sandi_meter/class'
|
6
|
+
require_relative 'sandi_meter/method_call'
|
7
|
+
require_relative 'sandi_meter/method'
|
5
8
|
|
6
9
|
module SandiMeter
|
7
10
|
class Analyzer
|
8
|
-
|
11
|
+
attr_accessor :parent_token, :private_or_protected
|
12
|
+
attr_reader :classes, :methods, :method_calls
|
9
13
|
|
10
14
|
def initialize
|
11
15
|
@classes = []
|
12
|
-
@misindented_classes = []
|
13
|
-
@misindented_methods = {}
|
14
16
|
@methods = {}
|
15
17
|
@method_calls = []
|
16
|
-
@instance_variables = {}
|
17
|
-
|
18
|
-
@parent_token = nil
|
19
|
-
@private_or_protected = false
|
20
18
|
end
|
21
19
|
|
22
20
|
def analyze(file_path)
|
@@ -26,7 +24,7 @@ module SandiMeter
|
|
26
24
|
@indentation_warnings = indentation_warnings
|
27
25
|
# TODO
|
28
26
|
# add better determination wheter file is controller
|
29
|
-
@
|
27
|
+
@controller = !!(file_path =~ /\w+_controller.rb$/)
|
30
28
|
|
31
29
|
sexp = Ripper.sexp(@file_body)
|
32
30
|
scan_sexp(sexp)
|
@@ -38,28 +36,6 @@ module SandiMeter
|
|
38
36
|
def output
|
39
37
|
loc_checker = SandiMeter::LOCChecker.new(@file_lines)
|
40
38
|
|
41
|
-
@classes.map! do |klass_params|
|
42
|
-
klass_params << loc_checker.check(klass_params, 'class')
|
43
|
-
klass_params << "#{@file_path}:#{klass_params[1]}"
|
44
|
-
end
|
45
|
-
|
46
|
-
@misindented_classes.map! do |klass_params|
|
47
|
-
klass_params << "#{@file_path}:#{klass_params[1]}"
|
48
|
-
end
|
49
|
-
|
50
|
-
@methods.each_pair do |klass, methods|
|
51
|
-
methods.each do |method_params|
|
52
|
-
method_params << loc_checker.check(method_params, 'def')
|
53
|
-
method_params << "#{@file_path}:#{method_params[1]}"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
@misindented_methods.each_pair do |klass, methods|
|
58
|
-
methods.each do |method_params|
|
59
|
-
method_params << "#{@file_path}:#{method_params[1]}"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
39
|
{
|
64
40
|
classes: @classes,
|
65
41
|
misindented_classes: @misindented_classes,
|
@@ -79,7 +55,11 @@ module SandiMeter
|
|
79
55
|
class_tokens.insert(0, current_namespace) unless current_namespace.empty?
|
80
56
|
class_name = class_tokens.join('::')
|
81
57
|
|
82
|
-
|
58
|
+
{
|
59
|
+
name: class_name,
|
60
|
+
first_line: line_number,
|
61
|
+
path: @file_path
|
62
|
+
}
|
83
63
|
end
|
84
64
|
|
85
65
|
# MOVE
|
@@ -92,12 +72,15 @@ module SandiMeter
|
|
92
72
|
end
|
93
73
|
|
94
74
|
def find_method_params(sexp)
|
95
|
-
sexp[1].flatten[1,2]
|
75
|
+
name, first_line = sexp[1].flatten[1, 2]
|
76
|
+
{
|
77
|
+
name: name,
|
78
|
+
first_line: first_line,
|
79
|
+
path: @file_path
|
80
|
+
}
|
96
81
|
end
|
97
82
|
|
98
|
-
def find_last_line(
|
99
|
-
token_name, line = params
|
100
|
-
|
83
|
+
def find_last_line(line, token = 'class')
|
101
84
|
token_indentation = @file_lines[line - 1].index(token)
|
102
85
|
# TODO
|
103
86
|
# add check for trailing spaces
|
@@ -110,24 +93,21 @@ module SandiMeter
|
|
110
93
|
case element.first
|
111
94
|
when :module
|
112
95
|
module_params = find_class_params(element, current_namespace)
|
113
|
-
|
114
|
-
|
96
|
+
|
97
|
+
module_params[:last_line] = find_last_line(module_params[:first_line], 'module')
|
98
|
+
current_namespace = module_params[:name]
|
115
99
|
|
116
100
|
scan_sexp(element, current_namespace)
|
117
101
|
when :class
|
118
102
|
class_params = find_class_params(element, current_namespace)
|
119
103
|
|
120
|
-
|
121
|
-
class_params
|
122
|
-
@misindented_classes << class_params
|
123
|
-
else
|
124
|
-
class_params += [find_last_line(class_params)]
|
125
|
-
|
126
|
-
# in case of one liner class last line will be nil
|
127
|
-
(class_params.last == nil ? @misindented_classes : @classes) << class_params
|
104
|
+
unless @indentation_warnings['class'] && @indentation_warnings['class'].any? { |first_line, last_line| first_line == class_params[:first_line] }
|
105
|
+
class_params[:last_line] = find_last_line(class_params[:first_line])
|
128
106
|
end
|
129
107
|
|
130
|
-
|
108
|
+
@classes << SandiMeter::Class.new(class_params)
|
109
|
+
|
110
|
+
current_namespace = class_params[:name]
|
131
111
|
scan_sexp(element, current_namespace)
|
132
112
|
end
|
133
113
|
end
|
@@ -142,7 +122,11 @@ module SandiMeter
|
|
142
122
|
counter = SandiMeter::MethodArgumentsCounter.new
|
143
123
|
arguments_count, line = counter.count(sexp)
|
144
124
|
|
145
|
-
@method_calls <<
|
125
|
+
@method_calls << SandiMeter::MethodCall.new(
|
126
|
+
path: @file_path,
|
127
|
+
first_line: line,
|
128
|
+
number_of_arguments: arguments_count
|
129
|
+
)
|
146
130
|
|
147
131
|
find_args_add_block(sexp)
|
148
132
|
else
|
@@ -158,9 +142,8 @@ module SandiMeter
|
|
158
142
|
next unless sexp.kind_of?(Array)
|
159
143
|
|
160
144
|
if sexp.first == :assign
|
161
|
-
@
|
162
|
-
|
163
|
-
@instance_variables[current_namespace][method_name] << sexp[1][1][1] if sexp[1][1][0] == :@ivar
|
145
|
+
method = @methods[current_namespace].find { |m| m.name == method_name }
|
146
|
+
method.ivars << sexp[1][1][1] if sexp[1][1][0] == :@ivar
|
164
147
|
else
|
165
148
|
scan_def_for_ivars(current_namespace, method_name, sexp)
|
166
149
|
end
|
@@ -175,19 +158,16 @@ module SandiMeter
|
|
175
158
|
case element.first
|
176
159
|
when :def
|
177
160
|
method_params = find_method_params(element)
|
178
|
-
|
179
|
-
|
180
|
-
method_params
|
181
|
-
@misindented_methods[current_namespace] ||= []
|
182
|
-
@misindented_methods[current_namespace] << method_params
|
183
|
-
else
|
184
|
-
method_params += [find_last_line(method_params, 'def')]
|
185
|
-
method_params << number_of_arguments(element)
|
186
|
-
@methods[current_namespace] ||= []
|
187
|
-
@methods[current_namespace] << method_params
|
161
|
+
method_params[:number_of_arguments] = number_of_arguments(element)
|
162
|
+
unless @indentation_warnings['def'] && @indentation_warnings['def'].any? { |first_line, last_line| first_line == method_params[:first_line] }
|
163
|
+
method_params[:last_line] = find_last_line(method_params[:first_line], 'def')
|
188
164
|
end
|
189
|
-
|
190
|
-
|
165
|
+
|
166
|
+
@methods[current_namespace] ||= []
|
167
|
+
@methods[current_namespace] << SandiMeter::Method.new(method_params) unless @private_or_protected
|
168
|
+
|
169
|
+
if @controller && !@private_or_protected
|
170
|
+
scan_def_for_ivars(current_namespace, method_params[:name], element)
|
191
171
|
end
|
192
172
|
|
193
173
|
find_args_add_block(element)
|
@@ -31,16 +31,13 @@ module SandiMeter
|
|
31
31
|
private
|
32
32
|
def log_first_rule
|
33
33
|
@output[:first_rule][:log] ||= {}
|
34
|
-
@output[:first_rule][:log][:classes] = @data[:classes].inject([]) do |log,
|
35
|
-
|
36
|
-
# wrap each class params into class and get params with
|
37
|
-
# verbose name instead of array keys (class_params[2] should be klass.line_count)
|
38
|
-
log << [class_params.first, class_params[2] - class_params[1] - 1, class_params.last] if class_params[-2] == false
|
34
|
+
@output[:first_rule][:log][:classes] = @data[:classes].inject([]) do |log, klass|
|
35
|
+
log << [klass.name, klass.size, klass.path] if klass.last_line && !klass.small?
|
39
36
|
log
|
40
37
|
end
|
41
38
|
|
42
|
-
@output[:first_rule][:log][:misindented_classes] = @data[:
|
43
|
-
log << [
|
39
|
+
@output[:first_rule][:log][:misindented_classes] = @data[:classes].select { |c| c.last_line.nil? }.inject([]) do |log, klass|
|
40
|
+
log << [klass.name, nil, klass.path]
|
44
41
|
log
|
45
42
|
end
|
46
43
|
end
|
@@ -51,25 +48,16 @@ module SandiMeter
|
|
51
48
|
@output[:second_rule][:log][:misindented_methods] ||= []
|
52
49
|
|
53
50
|
@data[:methods].each_pair do |klass, methods|
|
54
|
-
methods.select { |m| m
|
55
|
-
|
56
|
-
# TODO
|
57
|
-
# wrap method param to method class so method_params[1] becomes method.first_line
|
58
|
-
# and method_params[2] method.last_line
|
59
|
-
params << method_params[2] - method_params[1] - 1
|
60
|
-
params << method_params.last
|
61
|
-
|
62
|
-
@output[:second_rule][:log][:methods] << params
|
51
|
+
methods.select { |m| !m.misindented? && !m.small? }.each do |method|
|
52
|
+
@output[:second_rule][:log][:methods] << [klass, method.name, method.size, method.path]
|
63
53
|
end
|
64
54
|
end
|
65
55
|
|
66
|
-
@data[:
|
67
|
-
methods.each do |
|
68
|
-
|
69
|
-
params << nil
|
70
|
-
params << method_params.last
|
56
|
+
@data[:methods].each_pair do |klass, methods|
|
57
|
+
methods.each do |method|
|
58
|
+
next unless method.misindented?
|
71
59
|
|
72
|
-
@output[:second_rule][:log][:misindented_methods] <<
|
60
|
+
@output[:second_rule][:log][:misindented_methods] << [klass, method.name, method.size, method.path]
|
73
61
|
end
|
74
62
|
end
|
75
63
|
end
|
@@ -80,8 +68,8 @@ module SandiMeter
|
|
80
68
|
|
81
69
|
# TODO
|
82
70
|
# add name of method being called
|
83
|
-
proper_method_calls = @data[:method_calls].inject(0) do |sum,
|
84
|
-
@output[:third_rule][:log][:method_calls] <<
|
71
|
+
proper_method_calls = @data[:method_calls].inject(0) do |sum, method_call|
|
72
|
+
@output[:third_rule][:log][:method_calls] << [method_call.number_of_arguments, method_call.path] if method_call.number_of_arguments > 4
|
85
73
|
end
|
86
74
|
end
|
87
75
|
|
@@ -89,23 +77,20 @@ module SandiMeter
|
|
89
77
|
@output[:fourth_rule][:log] ||={}
|
90
78
|
@output[:fourth_rule][:log][:controllers] ||= []
|
91
79
|
|
92
|
-
@data[:
|
93
|
-
methods.
|
94
|
-
if
|
95
|
-
|
96
|
-
|
80
|
+
@data[:classes].select { |c| c.controller }.each do |klass|
|
81
|
+
@data[:methods][klass].each do |method|
|
82
|
+
next if method.ivars.empty?
|
83
|
+
|
84
|
+
@output[:fourth_rule][:log][:controllers] << [klass.name, method.name, method.ivars]
|
97
85
|
end
|
98
86
|
end
|
99
87
|
end
|
100
88
|
|
101
89
|
def check_first_rule
|
102
90
|
total_classes_amount = @data[:classes].size
|
103
|
-
small_classes_amount = @data[:classes].
|
104
|
-
sum += 1 if class_params[-2] == true
|
105
|
-
sum
|
106
|
-
end
|
91
|
+
small_classes_amount = @data[:classes].select(&:small?).size
|
107
92
|
|
108
|
-
misindented_classes_amount = @data[:
|
93
|
+
misindented_classes_amount = @data[:classes].select { |c| c.last_line.nil? }
|
109
94
|
|
110
95
|
@output[:first_rule] ||= {}
|
111
96
|
@output[:first_rule][:small_classes_amount] = small_classes_amount
|
@@ -120,13 +105,13 @@ module SandiMeter
|
|
120
105
|
small_methods_amount = 0
|
121
106
|
|
122
107
|
@data[:methods].each_pair do |klass, methods|
|
123
|
-
small_methods_amount += methods.select { |m| m
|
108
|
+
small_methods_amount += methods.select { |m| m.small? }.size
|
124
109
|
total_methods_amount += methods.size
|
125
110
|
end
|
126
111
|
|
127
112
|
misindented_methods_amount = 0
|
128
|
-
@data[:
|
129
|
-
misindented_methods_amount += methods.size
|
113
|
+
@data[:methods].each_pair do |klass, methods|
|
114
|
+
misindented_methods_amount += methods.select { |m| m.last_line.nil? }.size
|
130
115
|
end
|
131
116
|
|
132
117
|
@output[:second_rule] ||= {}
|
@@ -142,8 +127,8 @@ module SandiMeter
|
|
142
127
|
def check_third_rule
|
143
128
|
total_method_calls = @data[:method_calls].size
|
144
129
|
|
145
|
-
proper_method_calls = @data[:method_calls].inject(0) do |sum,
|
146
|
-
sum += 1 unless
|
130
|
+
proper_method_calls = @data[:method_calls].inject(0) do |sum, method_call|
|
131
|
+
sum += 1 unless method_call.number_of_arguments > 4
|
147
132
|
sum
|
148
133
|
end
|
149
134
|
|
@@ -158,9 +143,9 @@ module SandiMeter
|
|
158
143
|
proper_controllers_amount = 0
|
159
144
|
total_controllers_amount = 0
|
160
145
|
|
161
|
-
@data[:
|
146
|
+
@data[:classes].select { |c| c.controller? }.each do |klass|
|
162
147
|
total_controllers_amount += 1
|
163
|
-
proper_controllers_amount += 1 unless methods.
|
148
|
+
proper_controllers_amount += 1 unless @data[:methods][klass.name].select { |m| m.ivars.uniq.size > 1 }.empty?
|
164
149
|
end
|
165
150
|
|
166
151
|
@output[:fourth_rule] ||= {}
|
data/lib/sandi_meter/cli.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require 'mixlib/cli'
|
3
3
|
require 'sandi_meter/file_scanner'
|
4
4
|
require 'sandi_meter/formatter'
|
5
|
+
require 'sandi_meter/rules_checker'
|
5
6
|
require 'sandi_meter/logger'
|
6
7
|
require 'sandi_meter/version'
|
7
8
|
require 'sandi_meter/html_generator'
|
@@ -61,6 +62,18 @@ module SandiMeter
|
|
61
62
|
cli = CommandParser.new
|
62
63
|
cli.parse_options
|
63
64
|
|
65
|
+
if cli.config[:graph]
|
66
|
+
log_dir_path = File.join(cli.config[:path], 'sandi_meter')
|
67
|
+
FileUtils.mkdir(log_dir_path) unless Dir.exists?(log_dir_path)
|
68
|
+
# put ignore file
|
69
|
+
ignore_file_path = File.join(cli.config[:path], 'sandi_meter', '.sandi_meter')
|
70
|
+
if File.directory?(cli.config[:path]) && !File.exists?(ignore_file_path)
|
71
|
+
File.open(ignore_file_path, "w") do |file|
|
72
|
+
file.write %w(db vendor).join("\n")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
64
77
|
if cli.config[:version]
|
65
78
|
# stolen from gem 'bubs' :)
|
66
79
|
puts "SandiMeter ".tr('A-Za-z1-90', 'Ⓐ-Ⓩⓐ-ⓩ①-⑨⓪').split('').join(' ') + SandiMeter::VERSION
|
@@ -81,28 +94,26 @@ module SandiMeter
|
|
81
94
|
|
82
95
|
if cli.config[:graph]
|
83
96
|
if File.directory?(cli.config[:path])
|
84
|
-
logger = SandiMeter::Logger.new
|
85
|
-
logger.log!(cli.config[:path]
|
97
|
+
logger = SandiMeter::Logger.new(data)
|
98
|
+
logger.log!(cli.config[:path])
|
86
99
|
|
87
100
|
html_generator = SandiMeter::HtmlGenerator.new
|
88
101
|
html_generator.copy_assets!(cli.config[:path])
|
89
102
|
html_generator.generate_data!(cli.config[:path])
|
90
103
|
html_generator.generate_details!(cli.config[:path], data)
|
91
104
|
|
92
|
-
# put ignore file
|
93
|
-
ignore_file_path = File.join(cli.config[:path], 'sandi_meter', '.sandi_meter')
|
94
|
-
if File.directory?(cli.config[:path]) && !File.exists?(ignore_file_path)
|
95
|
-
File.open(ignore_file_path, "w") do |file|
|
96
|
-
file.write %w(db vendor).join("\n")
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
105
|
index_html_path = File.join(cli.config[:path], 'sandi_meter/index.html')
|
101
106
|
system "open #{index_html_path}"
|
102
107
|
else
|
103
108
|
puts "WARNING!!! HTML mode works only if you scan folder."
|
104
109
|
end
|
105
110
|
end
|
111
|
+
|
112
|
+
if RulesChecker.new(data).ok?
|
113
|
+
exit 0
|
114
|
+
else
|
115
|
+
exit 1
|
116
|
+
end
|
106
117
|
end
|
107
118
|
|
108
119
|
def self.show_sandi_rules
|
@@ -22,7 +22,7 @@ module SandiMeter
|
|
22
22
|
|
23
23
|
private
|
24
24
|
def scan_dir(path)
|
25
|
-
Dir["#{path}/**/*.rb"].reject { |f|
|
25
|
+
Dir["#{path}/**/*.rb"].reject { |f| !@exclude_patterns.to_s.empty? && f =~ /#{@exclude_patterns}/ }.each do |file|
|
26
26
|
scan_file(file)
|
27
27
|
end
|
28
28
|
end
|
data/lib/sandi_meter/logger.rb
CHANGED
@@ -1,34 +1,32 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
|
3
3
|
module SandiMeter
|
4
|
-
class Logger
|
5
|
-
def log!(path
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
File.open(File.join(log_dir_path, 'sandi_meter.log'), 'a') do |file|
|
10
|
-
file.puts(log_line(data))
|
4
|
+
class Logger < Struct.new(:data)
|
5
|
+
def log!(path)
|
6
|
+
File.open(File.join(path, 'sandi_meter', 'sandi_meter.log'), 'a') do |file|
|
7
|
+
file.puts(log_line)
|
11
8
|
end
|
12
9
|
end
|
13
10
|
|
14
11
|
private
|
15
|
-
def log_line
|
16
|
-
|
17
|
-
|
18
|
-
log_line_data << data[:first_rule][:total_classes_amount] - data[:first_rule][:small_classes_amount]
|
19
|
-
|
20
|
-
log_line_data << data[:second_rule][:small_methods_amount]
|
21
|
-
log_line_data << data[:second_rule][:total_methods_amount] - data[:second_rule][:small_methods_amount]
|
22
|
-
|
23
|
-
log_line_data << data[:third_rule][:proper_method_calls]
|
24
|
-
log_line_data << data[:third_rule][:total_method_calls] - data[:third_rule][:proper_method_calls]
|
25
|
-
|
26
|
-
log_line_data << data[:fourth_rule][:proper_controllers_amount]
|
27
|
-
log_line_data << data[:fourth_rule][:total_controllers_amount] - data[:fourth_rule][:proper_controllers_amount]
|
12
|
+
def log_line
|
13
|
+
rules_log.join(';')
|
14
|
+
end
|
28
15
|
|
29
|
-
|
16
|
+
def log_rule(rule_key, proper_key, total_key)
|
17
|
+
[
|
18
|
+
data[rule_key][proper_key],
|
19
|
+
data[rule_key][total_key] - data[rule_key][proper_key]
|
20
|
+
]
|
21
|
+
end
|
30
22
|
|
31
|
-
|
23
|
+
def rules_log
|
24
|
+
log_line_data = [log_rule(:first_rule, :small_classes_amount, :total_classes_amount)]
|
25
|
+
log_line_data += log_rule(:second_rule, :small_methods_amount, :total_methods_amount)
|
26
|
+
log_line_data += log_rule(:third_rule, :proper_method_calls, :total_method_calls)
|
27
|
+
log_line_data += log_rule(:fourth_rule, :proper_controllers_amount, :total_controllers_amount)
|
28
|
+
log_line_data += [Time.now.to_i]
|
32
29
|
end
|
33
30
|
end
|
34
31
|
end
|
32
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SandiMeter
|
2
|
+
class RulesChecker
|
3
|
+
def initialize(data)
|
4
|
+
@rules = []
|
5
|
+
@rules << percentage(data[:first_rule][:small_classes_amount], data[:first_rule][:total_classes_amount])
|
6
|
+
@rules << percentage(data[:second_rule][:small_methods_amount], data[:second_rule][:total_methods_amount])
|
7
|
+
@rules << percentage(data[:third_rule][:proper_method_calls], data[:third_rule][:total_method_calls])
|
8
|
+
@rules << percentage(data[:fourth_rule][:proper_controllers_amount], data[:fourth_rule][:total_controllers_amount])
|
9
|
+
end
|
10
|
+
|
11
|
+
def ok?
|
12
|
+
@rules.all? { |rule| rule == 1 }
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def percentage(amount, total)
|
17
|
+
total > 0 ? amount / total : 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module SandiMeter
|
2
|
+
class Class
|
3
|
+
MAX_LOC = 100
|
4
|
+
|
5
|
+
attr_accessor :name, :path, :first_line, :last_line, :controller
|
6
|
+
|
7
|
+
def initialize(params = {})
|
8
|
+
params.each do |key, value|
|
9
|
+
instance_variable_set("@#{key}", value)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def size
|
14
|
+
last_line and (last_line - first_line - 1)
|
15
|
+
end
|
16
|
+
|
17
|
+
def small?
|
18
|
+
last_line && size <= MAX_LOC
|
19
|
+
end
|
20
|
+
|
21
|
+
def misindented?
|
22
|
+
!!(last_line)
|
23
|
+
end
|
24
|
+
|
25
|
+
def controller?
|
26
|
+
!!(path =~ /\w+_controller.rb$/)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SandiMeter
|
2
|
+
class Method
|
3
|
+
MAX_LOC = 5
|
4
|
+
|
5
|
+
attr_accessor :name, :misindented, :first_line, :last_line, :path, :number_of_arguments, :ivars
|
6
|
+
|
7
|
+
def initialize(params = {})
|
8
|
+
params.each do |key, value|
|
9
|
+
instance_variable_set("@#{key}", value)
|
10
|
+
end
|
11
|
+
@ivars = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def size
|
15
|
+
@last_line - @first_line - 1 if @last_line
|
16
|
+
end
|
17
|
+
|
18
|
+
def misindented?
|
19
|
+
!(@last_line)
|
20
|
+
end
|
21
|
+
|
22
|
+
def small?
|
23
|
+
size <= MAX_LOC if @last_line
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/sandi_meter/version.rb
CHANGED
data/spec/analyzer_spec.rb
CHANGED
@@ -12,17 +12,34 @@ describe SandiMeter::Analyzer do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'finds indentation warnings for method' do
|
15
|
-
analyzer.classes.
|
16
|
-
|
15
|
+
klass = analyzer.classes.find { |c| c.name == "TestClass" }
|
16
|
+
|
17
|
+
klass.should have_attributes(
|
18
|
+
first_line: 1,
|
19
|
+
last_line: 5,
|
20
|
+
path: test_file_path(3)
|
21
|
+
)
|
17
22
|
end
|
18
23
|
|
19
24
|
it 'finds methods' do
|
20
|
-
analyzer.methods
|
21
|
-
|
25
|
+
method = analyzer.methods["TestClass"].find { |m| m.name == "blah" }
|
26
|
+
|
27
|
+
method.should have_attributes(
|
28
|
+
first_line: 2,
|
29
|
+
last_line: 4,
|
30
|
+
number_of_arguments: 0,
|
31
|
+
path: test_file_path(3)
|
32
|
+
)
|
22
33
|
end
|
23
34
|
|
24
35
|
it 'finds method calls that brakes third rule' do
|
25
|
-
analyzer.method_calls.
|
36
|
+
method_call = analyzer.method_calls.first
|
37
|
+
|
38
|
+
method_call.should have_attributes(
|
39
|
+
first_line: 3,
|
40
|
+
number_of_arguments: 5,
|
41
|
+
path: test_file_path(3)
|
42
|
+
)
|
26
43
|
end
|
27
44
|
end
|
28
45
|
|
@@ -34,13 +51,24 @@ describe SandiMeter::Analyzer do
|
|
34
51
|
end
|
35
52
|
|
36
53
|
it 'finds indentation warnings for method' do
|
37
|
-
analyzer.classes.
|
38
|
-
|
54
|
+
klass = analyzer.classes.find { |c| c.name == "MyApp::TestClass" }
|
55
|
+
|
56
|
+
klass.should have_attributes(
|
57
|
+
first_line: 2,
|
58
|
+
last_line: nil,
|
59
|
+
path: test_file_path(1)
|
60
|
+
)
|
39
61
|
end
|
40
62
|
|
41
63
|
it 'finds methods' do
|
42
|
-
analyzer.methods.
|
43
|
-
|
64
|
+
method = analyzer.methods["MyApp::TestClass"].find { |m| m.name == "blah" }
|
65
|
+
|
66
|
+
method.should have_attributes(
|
67
|
+
first_line: 3,
|
68
|
+
last_line: nil,
|
69
|
+
number_of_arguments: 0,
|
70
|
+
path: test_file_path(1)
|
71
|
+
)
|
44
72
|
end
|
45
73
|
end
|
46
74
|
|
@@ -52,15 +80,41 @@ describe SandiMeter::Analyzer do
|
|
52
80
|
end
|
53
81
|
|
54
82
|
it 'finds classes' do
|
55
|
-
analyzer.classes.
|
56
|
-
|
57
|
-
|
83
|
+
klass = analyzer.classes.find { |c| c.name == "FirstTestClass" }
|
84
|
+
|
85
|
+
klass.should have_attributes(
|
86
|
+
first_line: 1,
|
87
|
+
last_line: 4,
|
88
|
+
path: test_file_path(4)
|
89
|
+
)
|
90
|
+
|
91
|
+
klass = analyzer.classes.find { |c| c.name == "SecondTestClass" }
|
92
|
+
|
93
|
+
klass.should have_attributes(
|
94
|
+
first_line: 6,
|
95
|
+
last_line: 9,
|
96
|
+
path: test_file_path(4)
|
97
|
+
)
|
58
98
|
end
|
59
99
|
|
60
100
|
it 'finds methods' do
|
61
|
-
analyzer.methods["FirstTestClass"].
|
62
|
-
|
63
|
-
|
101
|
+
method = analyzer.methods["FirstTestClass"].find { |m| m.name == "first_meth" }
|
102
|
+
|
103
|
+
method.should have_attributes(
|
104
|
+
first_line: 2,
|
105
|
+
last_line: 3,
|
106
|
+
number_of_arguments: 1,
|
107
|
+
path: test_file_path(4)
|
108
|
+
)
|
109
|
+
|
110
|
+
method = analyzer.methods["SecondTestClass"].find { |m| m.name == "second_meth" }
|
111
|
+
|
112
|
+
method.should have_attributes(
|
113
|
+
first_line: 7,
|
114
|
+
last_line: 8,
|
115
|
+
number_of_arguments: 1,
|
116
|
+
path: test_file_path(4)
|
117
|
+
)
|
64
118
|
end
|
65
119
|
end
|
66
120
|
|
@@ -72,13 +126,17 @@ describe SandiMeter::Analyzer do
|
|
72
126
|
end
|
73
127
|
|
74
128
|
it 'finds classes' do
|
75
|
-
analyzer.
|
76
|
-
|
129
|
+
klass = analyzer.classes.find { |c| c.name == "OneLinerClass" }
|
130
|
+
|
131
|
+
klass.should have_attributes(
|
132
|
+
first_line: 1,
|
133
|
+
last_line: nil,
|
134
|
+
path: test_file_path(5)
|
135
|
+
)
|
77
136
|
end
|
78
137
|
|
79
138
|
it 'finds methods' do
|
80
139
|
analyzer.methods.should be_empty
|
81
|
-
analyzer.misindented_methods.should be_empty
|
82
140
|
end
|
83
141
|
end
|
84
142
|
|
@@ -90,16 +148,45 @@ describe SandiMeter::Analyzer do
|
|
90
148
|
end
|
91
149
|
|
92
150
|
it 'finds class and subclass' do
|
93
|
-
analyzer.classes.
|
94
|
-
|
95
|
-
|
151
|
+
klass = analyzer.classes.find { |c| c.name == "MyApp::Blah::User" }
|
152
|
+
klass.should have_attributes(
|
153
|
+
first_line: 5,
|
154
|
+
last_line: 13,
|
155
|
+
path: test_file_path(7)
|
156
|
+
)
|
157
|
+
|
158
|
+
klass = analyzer.classes.find { |c| c.name == "MyApp::Blah::User::SubUser" }
|
159
|
+
klass.should have_attributes(
|
160
|
+
first_line: 9,
|
161
|
+
last_line: 12,
|
162
|
+
path: test_file_path(7)
|
163
|
+
)
|
96
164
|
end
|
97
165
|
|
98
166
|
it 'finds methods' do
|
99
|
-
analyzer.methods["MyApp::Blah"].
|
100
|
-
|
101
|
-
|
102
|
-
|
167
|
+
method = analyzer.methods["MyApp::Blah"].find { |m| m.name == "module_meth" }
|
168
|
+
method.should have_attributes(
|
169
|
+
first_line: 2,
|
170
|
+
last_line: 3,
|
171
|
+
number_of_arguments: 0,
|
172
|
+
path: test_file_path(7)
|
173
|
+
)
|
174
|
+
|
175
|
+
method = analyzer.methods["MyApp::Blah::User"].find { |m| m.name == "class_meth" }
|
176
|
+
method.should have_attributes(
|
177
|
+
first_line: 6,
|
178
|
+
last_line: 7,
|
179
|
+
number_of_arguments: 0,
|
180
|
+
path: test_file_path(7)
|
181
|
+
)
|
182
|
+
|
183
|
+
method = analyzer.methods["MyApp::Blah::User::SubUser"].find { |m| m.name == "sub_meth" }
|
184
|
+
method.should have_attributes(
|
185
|
+
first_line: 10,
|
186
|
+
last_line: 11,
|
187
|
+
number_of_arguments: 0,
|
188
|
+
path: test_file_path(7)
|
189
|
+
)
|
103
190
|
end
|
104
191
|
end
|
105
192
|
|
@@ -111,15 +198,33 @@ describe SandiMeter::Analyzer do
|
|
111
198
|
end
|
112
199
|
|
113
200
|
it 'finds class and subclass' do
|
114
|
-
analyzer.classes.
|
115
|
-
|
201
|
+
klass = analyzer.classes.find { |c| c.name == "RailsController" }
|
202
|
+
klass.should have_attributes(
|
203
|
+
first_line: 1,
|
204
|
+
last_line: 12,
|
205
|
+
path: test_file_path(8)
|
206
|
+
)
|
116
207
|
end
|
117
208
|
|
118
209
|
it 'finds methods' do
|
119
|
-
analyzer.methods["RailsController"].
|
120
|
-
|
121
|
-
|
122
|
-
|
210
|
+
method = analyzer.methods["RailsController"].find { |m| m.name == "index" }
|
211
|
+
method.should have_attributes(
|
212
|
+
first_line: 2,
|
213
|
+
last_line: 3,
|
214
|
+
number_of_arguments: 0,
|
215
|
+
path: test_file_path(8)
|
216
|
+
)
|
217
|
+
|
218
|
+
method = analyzer.methods["RailsController"].find { |m| m.name == "destroy" }
|
219
|
+
method.should have_attributes(
|
220
|
+
first_line: 5,
|
221
|
+
last_line: 6,
|
222
|
+
number_of_arguments: 0,
|
223
|
+
path: test_file_path(8)
|
224
|
+
)
|
225
|
+
|
226
|
+
method = analyzer.methods["RailsController"].find { |m| m.name == "private_meth" }
|
227
|
+
method.should be_nil
|
123
228
|
end
|
124
229
|
end
|
125
230
|
|
@@ -132,7 +237,8 @@ describe SandiMeter::Analyzer do
|
|
132
237
|
end
|
133
238
|
|
134
239
|
it 'finds instance variable' do
|
135
|
-
analyzer.
|
240
|
+
method = analyzer.methods["UsersController"].find { |m| m.name == "index" }
|
241
|
+
method.ivars.should eq(["@users"])
|
136
242
|
end
|
137
243
|
end
|
138
244
|
|
@@ -144,7 +250,8 @@ describe SandiMeter::Analyzer do
|
|
144
250
|
end
|
145
251
|
|
146
252
|
it 'does not find instance variables' do
|
147
|
-
analyzer.
|
253
|
+
method = analyzer.methods["GuestController"].find { |m| m.name == "create_guest_user" }
|
254
|
+
method.ivars.should be_empty
|
148
255
|
end
|
149
256
|
end
|
150
257
|
|
@@ -156,7 +263,11 @@ describe SandiMeter::Analyzer do
|
|
156
263
|
end
|
157
264
|
|
158
265
|
it 'does not find instance variable' do
|
159
|
-
analyzer.
|
266
|
+
method = analyzer.methods["User"].find { |m| m.name == "initialize" }
|
267
|
+
method.ivars.should be_empty
|
268
|
+
|
269
|
+
method = analyzer.methods["User"].find { |m| m.name == "hi" }
|
270
|
+
method.ivars.should be_empty
|
160
271
|
end
|
161
272
|
end
|
162
273
|
|
@@ -168,22 +279,24 @@ describe SandiMeter::Analyzer do
|
|
168
279
|
end
|
169
280
|
|
170
281
|
it 'finds method defined after public keyword' do
|
171
|
-
analyzer.
|
282
|
+
method = analyzer.methods["UsersController"].find { |m| m.name == "create" }
|
283
|
+
method.ivars.should eq(["@user"])
|
172
284
|
end
|
173
285
|
|
174
286
|
it 'omits actions without instance variables' do
|
175
|
-
analyzer.
|
287
|
+
method = analyzer.methods["UsersController"].find { |m| m.name == "show" }
|
288
|
+
method.ivars.should be_empty
|
176
289
|
end
|
177
290
|
|
178
291
|
it 'omits private methods' do
|
179
|
-
analyzer.
|
292
|
+
method = analyzer.methods["UsersController"].find { |m| m.name == "find_user" }
|
293
|
+
method.should be_nil
|
180
294
|
end
|
181
295
|
|
182
296
|
it 'omits protected methods' do
|
183
|
-
analyzer.
|
297
|
+
method = analyzer.methods["UsersController"].find { |m| m.name == "protected_find_user" }
|
298
|
+
method.should be_nil
|
184
299
|
end
|
185
|
-
|
186
|
-
|
187
300
|
end
|
188
301
|
end
|
189
302
|
|
@@ -195,7 +308,13 @@ describe SandiMeter::Analyzer do
|
|
195
308
|
end
|
196
309
|
|
197
310
|
it 'counts arguments' do
|
198
|
-
analyzer.method_calls.
|
311
|
+
method_call = analyzer.method_calls.first
|
312
|
+
|
313
|
+
method_call.should have_attributes(
|
314
|
+
first_line: 3,
|
315
|
+
number_of_arguments: 5,
|
316
|
+
path: test_file_path(11)
|
317
|
+
)
|
199
318
|
end
|
200
319
|
end
|
201
320
|
|
@@ -207,11 +326,24 @@ describe SandiMeter::Analyzer do
|
|
207
326
|
end
|
208
327
|
|
209
328
|
it 'are count for class definition' do
|
210
|
-
analyzer.classes.
|
329
|
+
klass = analyzer.classes.find { |c| c.name == "Valera" }
|
330
|
+
|
331
|
+
klass.should have_attributes(
|
332
|
+
first_line: 1,
|
333
|
+
last_line: 109,
|
334
|
+
path: test_file_path(12)
|
335
|
+
)
|
211
336
|
end
|
212
337
|
|
213
338
|
it 'are count for method definition' do
|
214
|
-
analyzer.methods
|
339
|
+
method = analyzer.methods["Valera"].find { |m| m.name == "doodle" }
|
340
|
+
|
341
|
+
method.should have_attributes(
|
342
|
+
first_line: 2,
|
343
|
+
last_line: 9,
|
344
|
+
number_of_arguments: 0,
|
345
|
+
path: test_file_path(12)
|
346
|
+
)
|
215
347
|
end
|
216
348
|
end
|
217
349
|
|
@@ -236,15 +368,36 @@ describe SandiMeter::Analyzer do
|
|
236
368
|
end
|
237
369
|
|
238
370
|
it 'mark 4line methods good' do
|
239
|
-
methods
|
371
|
+
method = analyzer.methods["TestClass"].find { |m| m.name == "render4" }
|
372
|
+
|
373
|
+
method.should have_attributes(
|
374
|
+
first_line: 2,
|
375
|
+
last_line: 7,
|
376
|
+
number_of_arguments: 0,
|
377
|
+
path: test_file_path(14)
|
378
|
+
)
|
240
379
|
end
|
241
380
|
|
242
381
|
it 'mark 5line methods good' do
|
243
|
-
methods
|
382
|
+
method = analyzer.methods["TestClass"].find { |m| m.name == "render5" }
|
383
|
+
|
384
|
+
method.should have_attributes(
|
385
|
+
first_line: 9,
|
386
|
+
last_line: 15,
|
387
|
+
number_of_arguments: 0,
|
388
|
+
path: test_file_path(14)
|
389
|
+
)
|
244
390
|
end
|
245
391
|
|
246
392
|
it 'mark 6line methods bad' do
|
247
|
-
methods
|
393
|
+
method = analyzer.methods["TestClass"].find { |m| m.name == "render6" }
|
394
|
+
|
395
|
+
method.should have_attributes(
|
396
|
+
first_line: 17,
|
397
|
+
last_line: 24,
|
398
|
+
number_of_arguments: 0,
|
399
|
+
path: test_file_path(14)
|
400
|
+
)
|
248
401
|
end
|
249
402
|
end
|
250
403
|
end
|
data/spec/calculator_spec.rb
CHANGED
@@ -16,13 +16,13 @@ describe SandiMeter::Calculator do
|
|
16
16
|
|
17
17
|
it 'counts class lines' do
|
18
18
|
output = calculator.calculate!(true)
|
19
|
-
|
20
|
-
|
19
|
+
klass = output[:first_rule][:log][:classes].find { |params| params.first == "User" }
|
20
|
+
klass[1].should eq(109)
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'counts method lines' do
|
24
24
|
output = calculator.calculate!(true)
|
25
|
-
method_params = output[:second_rule][:log][:methods].find { |
|
25
|
+
method_params = output[:second_rule][:log][:methods].find { |method| method[1] == "create" }
|
26
26
|
method_params[2].should eq(6)
|
27
27
|
end
|
28
28
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require_relative '../lib/sandi_meter/rules_checker'
|
3
|
+
|
4
|
+
describe SandiMeter::RulesChecker do
|
5
|
+
let(:fail_conditions) do
|
6
|
+
{
|
7
|
+
first_rule: { small_classes_amount: 1, total_classes_amount: 2 },
|
8
|
+
second_rule: { small_methods_amount: 2, total_methods_amount: 2 },
|
9
|
+
third_rule: { proper_method_calls: 2, total_method_calls: 2 },
|
10
|
+
fourth_rule: { proper_controllers_amount: 2, total_controllers_amount: 2 }
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:succeed_conditions) do
|
15
|
+
{
|
16
|
+
first_rule: { small_classes_amount: 2, total_classes_amount: 2 },
|
17
|
+
second_rule: { small_methods_amount: 2, total_methods_amount: 2 },
|
18
|
+
third_rule: { proper_method_calls: 2, total_method_calls: 2 },
|
19
|
+
fourth_rule: { proper_controllers_amount: 0, total_controllers_amount: 0 }
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#ok?" do
|
24
|
+
it "returns false in any of conditions fail" do
|
25
|
+
expect(SandiMeter::RulesChecker.new(fail_conditions)).to_not be_ok
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns true if all of conditions succeed" do
|
29
|
+
expect(SandiMeter::RulesChecker.new(succeed_conditions)).to be_ok
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class ArgsLoader
|
2
|
+
def reset!
|
3
|
+
@sexp = nil
|
4
|
+
end
|
5
|
+
|
6
|
+
def load(method_call)
|
7
|
+
reset!
|
8
|
+
load_method_add_arg(Ripper.sexp(method_call))
|
9
|
+
return @sexp
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def load_method_add_arg(method_sexp)
|
14
|
+
method_sexp.each do |s|
|
15
|
+
next unless s.kind_of?(Array)
|
16
|
+
|
17
|
+
s.each do |a|
|
18
|
+
next unless a.kind_of?(Array)
|
19
|
+
|
20
|
+
if a.first == :args_add_block
|
21
|
+
@sexp ||= a
|
22
|
+
else
|
23
|
+
load_method_add_arg(s)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rspec/expectations'
|
2
|
+
|
3
|
+
RSpec::Matchers.define :have_attributes do |expected|
|
4
|
+
match do |actual|
|
5
|
+
result = true
|
6
|
+
expected.each do |key, value|
|
7
|
+
result = false unless actual.send(key) == value
|
8
|
+
end
|
9
|
+
|
10
|
+
result
|
11
|
+
end
|
12
|
+
|
13
|
+
failure_message_for_should do |actual|
|
14
|
+
wrong_fields = {}
|
15
|
+
expected.each do |key, value|
|
16
|
+
wrong_fields[key] = {
|
17
|
+
actual: actual.send(key),
|
18
|
+
expected: value
|
19
|
+
} unless actual.send(key) == value
|
20
|
+
end
|
21
|
+
|
22
|
+
wrong_fields.inject("In #{actual.class.name} ") do |message, wrong_field|
|
23
|
+
key, value = wrong_field
|
24
|
+
message << "expected that #{key} would be #{value[:expected]}, but was #{value[:actual]}\n"
|
25
|
+
message
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
def test_file_path(file_name)
|
2
|
+
File.join(
|
3
|
+
File.dirname(__FILE__),
|
4
|
+
"../test_classes/#{file_name}.rb"
|
5
|
+
)
|
6
|
+
end
|
7
|
+
|
8
|
+
def read_test_file(file_name)
|
9
|
+
File.read(
|
10
|
+
test_file_path(file_name)
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def load_args_block(method_call)
|
15
|
+
loader = ArgsLoader.new
|
16
|
+
loader.load(method_call)
|
17
|
+
end
|
data/spec/test_helper.rb
CHANGED
@@ -1,49 +1,4 @@
|
|
1
1
|
require 'rspec/autorun'
|
2
2
|
require 'ripper'
|
3
3
|
|
4
|
-
|
5
|
-
File.join(
|
6
|
-
File.dirname(__FILE__),
|
7
|
-
"test_classes/#{file_name}.rb"
|
8
|
-
)
|
9
|
-
end
|
10
|
-
|
11
|
-
def read_test_file(file_name)
|
12
|
-
File.read(
|
13
|
-
test_file_path(file_name)
|
14
|
-
)
|
15
|
-
end
|
16
|
-
|
17
|
-
def load_args_block(method_call)
|
18
|
-
loader = ArgsLoader.new
|
19
|
-
loader.load(method_call)
|
20
|
-
end
|
21
|
-
|
22
|
-
class ArgsLoader
|
23
|
-
def reset!
|
24
|
-
@sexp = nil
|
25
|
-
end
|
26
|
-
|
27
|
-
def load(method_call)
|
28
|
-
reset!
|
29
|
-
load_method_add_arg(Ripper.sexp(method_call))
|
30
|
-
return @sexp
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
def load_method_add_arg(method_sexp)
|
35
|
-
method_sexp.each do |s|
|
36
|
-
next unless s.kind_of?(Array)
|
37
|
-
|
38
|
-
s.each do |a|
|
39
|
-
next unless a.kind_of?(Array)
|
40
|
-
|
41
|
-
if a.first == :args_add_block
|
42
|
-
@sexp ||= a
|
43
|
-
else
|
44
|
-
load_method_add_arg(s)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
4
|
+
Dir["#{Dir.pwd}/spec/support/**/*.rb"].each { |f| require f }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sandi_meter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anatoli Makarevich
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -82,6 +82,10 @@ files:
|
|
82
82
|
- lib/sandi_meter/loc_checker.rb
|
83
83
|
- lib/sandi_meter/logger.rb
|
84
84
|
- lib/sandi_meter/method_arguments_counter.rb
|
85
|
+
- lib/sandi_meter/rules_checker.rb
|
86
|
+
- lib/sandi_meter/sandi_meter/class.rb
|
87
|
+
- lib/sandi_meter/sandi_meter/method.rb
|
88
|
+
- lib/sandi_meter/sandi_meter/method_call.rb
|
85
89
|
- lib/sandi_meter/version.rb
|
86
90
|
- lib/sandi_meter/warning_scanner.rb
|
87
91
|
- bin/sandi_meter
|
@@ -89,6 +93,10 @@ files:
|
|
89
93
|
- spec/calculator_spec.rb
|
90
94
|
- spec/loc_checker_spec.rb
|
91
95
|
- spec/method_arguments_counter_spec.rb
|
96
|
+
- spec/rules_checker_spec.rb
|
97
|
+
- spec/support/args_loader.rb
|
98
|
+
- spec/support/attr_matcher.rb
|
99
|
+
- spec/support/helper_methods.rb
|
92
100
|
- spec/test_classes/1.rb
|
93
101
|
- spec/test_classes/10.rb
|
94
102
|
- spec/test_classes/10_controller.rb
|
@@ -129,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
137
|
version: '0'
|
130
138
|
requirements: []
|
131
139
|
rubyforge_project:
|
132
|
-
rubygems_version: 2.
|
140
|
+
rubygems_version: 2.1.10
|
133
141
|
signing_key:
|
134
142
|
specification_version: 4
|
135
143
|
summary: Sandi Metz rules checker
|