simplabs-excellent 1.0.1 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +19 -0
- data/README.rdoc +34 -0
- data/VERSION.yml +1 -1
- data/bin/excellent +21 -6
- data/lib/simplabs/excellent.rb +7 -5
- data/lib/simplabs/excellent/checks.rb +18 -1
- data/lib/simplabs/excellent/checks/abc_metric_method_check.rb +19 -56
- data/lib/simplabs/excellent/checks/assignment_in_conditional_check.rb +16 -16
- data/lib/simplabs/excellent/checks/base.rb +30 -21
- data/lib/simplabs/excellent/checks/case_missing_else_check.rb +13 -5
- data/lib/simplabs/excellent/checks/class_line_count_check.rb +10 -8
- data/lib/simplabs/excellent/checks/class_name_check.rb +11 -10
- data/lib/simplabs/excellent/checks/control_coupling_check.rb +13 -10
- data/lib/simplabs/excellent/checks/cyclomatic_complexity_block_check.rb +25 -9
- data/lib/simplabs/excellent/checks/cyclomatic_complexity_check.rb +4 -20
- data/lib/simplabs/excellent/checks/cyclomatic_complexity_method_check.rb +25 -10
- data/lib/simplabs/excellent/checks/duplication_check.rb +50 -0
- data/lib/simplabs/excellent/checks/empty_rescue_body_check.rb +10 -18
- 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 +20 -4
- data/lib/simplabs/excellent/checks/line_count_check.rb +3 -21
- data/lib/simplabs/excellent/checks/method_line_count_check.rb +9 -7
- data/lib/simplabs/excellent/checks/method_name_check.rb +13 -9
- data/lib/simplabs/excellent/checks/module_line_count_check.rb +9 -7
- data/lib/simplabs/excellent/checks/module_name_check.rb +11 -7
- data/lib/simplabs/excellent/checks/name_check.rb +3 -8
- data/lib/simplabs/excellent/checks/nested_iterators_check.rb +33 -0
- data/lib/simplabs/excellent/checks/parameter_number_check.rb +13 -12
- data/lib/simplabs/excellent/checks/rails.rb +17 -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/singleton_variable_check.rb +32 -0
- data/lib/simplabs/excellent/extensions/sexp.rb +21 -0
- data/lib/simplabs/excellent/extensions/string.rb +23 -0
- data/lib/simplabs/excellent/parsing.rb +12 -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 +36 -0
- data/lib/simplabs/excellent/parsing/case_context.rb +31 -0
- data/lib/simplabs/excellent/parsing/class_context.rb +68 -0
- data/lib/simplabs/excellent/parsing/code_processor.rb +154 -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/if_context.rb +38 -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/{core → parsing}/parser.rb +4 -2
- 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/runner.rb +105 -0
- data/lib/simplabs/excellent/warning.rb +53 -0
- data/spec/checks/abc_metric_method_check_spec.rb +36 -8
- data/spec/checks/assignment_in_conditional_check_spec.rb +31 -14
- data/spec/checks/case_missing_else_check_spec.rb +8 -8
- data/spec/checks/class_line_count_check_spec.rb +24 -11
- data/spec/checks/class_name_check_spec.rb +9 -9
- data/spec/checks/control_coupling_check_spec.rb +84 -13
- data/spec/checks/cyclomatic_complexity_block_check_spec.rb +13 -17
- data/spec/checks/cyclomatic_complexity_method_check_spec.rb +32 -6
- data/spec/checks/duplication_check_spec.rb +139 -0
- data/spec/checks/empty_rescue_body_check_spec.rb +54 -16
- 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 +11 -11
- data/spec/checks/method_line_count_check_spec.rb +11 -12
- data/spec/checks/method_name_check_spec.rb +34 -13
- data/spec/checks/module_line_count_check_spec.rb +11 -12
- data/spec/checks/module_name_check_spec.rb +31 -7
- data/spec/checks/nested_iterators_check_spec.rb +44 -0
- data/spec/checks/parameter_number_check_spec.rb +48 -12
- 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/singleton_variable_check_spec.rb +66 -0
- data/spec/{core/extensions/underscore_spec.rb → extensions/string_spec.rb} +1 -1
- metadata +58 -15
- data/README.markdown +0 -30
- data/lib/simplabs/excellent/checks/class_variable_check.rb +0 -25
- data/lib/simplabs/excellent/core.rb +0 -2
- data/lib/simplabs/excellent/core/checking_visitor.rb +0 -34
- data/lib/simplabs/excellent/core/error.rb +0 -31
- data/lib/simplabs/excellent/core/extensions/underscore.rb +0 -27
- data/lib/simplabs/excellent/core/iterator_visitor.rb +0 -29
- data/lib/simplabs/excellent/core/parse_tree_runner.rb +0 -88
- data/lib/simplabs/excellent/core/visitable_sexp.rb +0 -31
- data/spec/checks/class_variable_check_spec.rb +0 -26
data/History.txt
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
= 1.2.1
|
2
|
+
|
3
|
+
* renamed Error to Warning
|
4
|
+
* added documentation
|
5
|
+
|
6
|
+
= 1.2.0
|
7
|
+
|
8
|
+
* cleanup
|
9
|
+
* added 2 Rails specific checks, AttrAccessibleCheck and AttrProtectedCheck
|
10
|
+
|
11
|
+
= 1.1.0
|
12
|
+
|
13
|
+
* completely restructured, made everything running in the flow of the SexpProcessor
|
14
|
+
* added most tests from reek (except for UtilityFunction and FeatureEnvy)
|
15
|
+
|
16
|
+
= 1.0.1
|
17
|
+
|
18
|
+
* fixed some errors
|
19
|
+
|
1
20
|
= 1.0.0
|
2
21
|
|
3
22
|
* this is basically just a custom version of roodi, converted to ruby_parser to be 1.9 safe
|
data/README.rdoc
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
= Excellent
|
2
|
+
|
3
|
+
Excellent detects commonly regarded bad code snippets like empty +rescue+ blocks etc. It combines roodi (http://github.com/martinjandrews/roodi), most checks of reek (http://github.com/kevinrutherford/reek), flog (http://github.com/seattlerb/flog) and also adds some Rails specific checks.
|
4
|
+
|
5
|
+
See the API documentation at http://docs.github.com/simplabs/excellent and the WIKI at http://wiki.github.com/simplabs/excellent.
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
|
9
|
+
Simply install with Ruby Gems:
|
10
|
+
|
11
|
+
gem sources -a http://gems.github.com
|
12
|
+
sudo gem install simplabs-excellent
|
13
|
+
|
14
|
+
== Example
|
15
|
+
|
16
|
+
To analyse all the models in your Rails application, just do
|
17
|
+
|
18
|
+
excellent app/models
|
19
|
+
|
20
|
+
in your <tt>RAILS_ROOT</tt>. You can also invoke analysation through the Simplabs::Excellent::Runner class.
|
21
|
+
|
22
|
+
== Static analysis
|
23
|
+
|
24
|
+
A few words regarding static code analysis: Static code analysis tools like Excellent can never really understand the code. They just search for patterns that *might* inidicate problematic code. The word *might* really has to be stressed here since static analysis will usually return a reasonable number of false positives. For example, there might be pretty good reasons for empty +rescue+ blocks that suppress all errors (Excellent itself does it). So, don't try and code with the aim of passing Excellent with zero warnings. That will most likely make your code a mess. Instead use Excellent as a helper to find *possibly* problematic code early.
|
25
|
+
|
26
|
+
== Contribute
|
27
|
+
|
28
|
+
If you want to contribute, just fork the repo. Also I would appretiate suggestions for more checks (especially Rails specific checks) - simply open a new issue: http://github.com/simplabs/excellent/issues.
|
29
|
+
|
30
|
+
== Author
|
31
|
+
|
32
|
+
Copyright (c) 2008-2009 Marco Otte-Witte (http://simplabs.com), released under the MIT license.
|
33
|
+
|
34
|
+
Excellent was inspired by and is in parts based on roodi (http://github.com/martinjandrews/roodi), reek (http://github.com/kevinrutherford/reek) and flog (http://github.com/seattlerb/flog).
|
data/VERSION.yml
CHANGED
data/bin/excellent
CHANGED
@@ -5,16 +5,31 @@ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
|
|
5
5
|
require 'simplabs/excellent'
|
6
6
|
require 'pathname'
|
7
7
|
|
8
|
-
excellent = Simplabs::Excellent::
|
8
|
+
excellent = Simplabs::Excellent::Runner.new
|
9
|
+
|
10
|
+
if ARGV.empty?
|
11
|
+
puts "\n You must specify one or more directories to analyse, e.g.:\n"
|
12
|
+
puts "\n excellent app/\n\n"
|
13
|
+
exit 1
|
14
|
+
end
|
9
15
|
|
10
16
|
ARGV.each do |arg|
|
11
|
-
|
17
|
+
if File.file?(arg)
|
18
|
+
excellent.check_file(arg)
|
19
|
+
elsif File.directory?(arg)
|
20
|
+
Dir.glob("#{arg}/**/*.rb").each { |file| excellent.check_file(file) }
|
21
|
+
else
|
22
|
+
puts "\n** Excellent cannot find '#{arg}'\n\n"
|
23
|
+
exit 1
|
24
|
+
end
|
12
25
|
end
|
13
26
|
|
14
|
-
|
15
|
-
|
16
|
-
|
27
|
+
unless excellent.warnings.empty?
|
28
|
+
puts "\n Warnings:\n\n"
|
29
|
+
excellent.warnings.each do |warning|
|
30
|
+
puts " * File #{warning.filename}, line #{warning.line_number}: #{warning.message}"
|
31
|
+
end
|
17
32
|
end
|
18
|
-
puts
|
33
|
+
puts "\n Found #{excellent.warnings.size} warnings.\n\n"
|
19
34
|
|
20
35
|
exit 0
|
data/lib/simplabs/excellent.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'simplabs/excellent/checks'
|
2
|
-
require 'simplabs/excellent/
|
2
|
+
require 'simplabs/excellent/parsing'
|
3
3
|
require 'rubygems'
|
4
4
|
require 'sexp'
|
5
5
|
|
6
|
-
module
|
6
|
+
module Simplabs #:nodoc:
|
7
7
|
|
8
|
-
|
8
|
+
module Excellent #:nodoc:
|
9
9
|
|
10
|
-
|
10
|
+
VERSION = '1.2.0'
|
11
|
+
|
12
|
+
end
|
11
13
|
|
12
|
-
|
14
|
+
end
|
@@ -1,9 +1,20 @@
|
|
1
|
+
module Simplabs
|
2
|
+
|
3
|
+
module Excellent
|
4
|
+
|
5
|
+
module Checks #:nodoc:
|
6
|
+
end
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
1
12
|
require 'simplabs/excellent/checks/abc_metric_method_check'
|
2
13
|
require 'simplabs/excellent/checks/assignment_in_conditional_check'
|
3
14
|
require 'simplabs/excellent/checks/case_missing_else_check'
|
4
15
|
require 'simplabs/excellent/checks/class_line_count_check'
|
5
16
|
require 'simplabs/excellent/checks/class_name_check'
|
6
|
-
require 'simplabs/excellent/checks/
|
17
|
+
require 'simplabs/excellent/checks/singleton_variable_check'
|
7
18
|
require 'simplabs/excellent/checks/control_coupling_check'
|
8
19
|
require 'simplabs/excellent/checks/cyclomatic_complexity_block_check'
|
9
20
|
require 'simplabs/excellent/checks/cyclomatic_complexity_method_check'
|
@@ -14,3 +25,9 @@ require 'simplabs/excellent/checks/method_name_check'
|
|
14
25
|
require 'simplabs/excellent/checks/module_line_count_check'
|
15
26
|
require 'simplabs/excellent/checks/module_name_check'
|
16
27
|
require 'simplabs/excellent/checks/parameter_number_check'
|
28
|
+
require 'simplabs/excellent/checks/duplication_check'
|
29
|
+
require 'simplabs/excellent/checks/nested_iterators_check'
|
30
|
+
require 'simplabs/excellent/checks/flog_method_check'
|
31
|
+
require 'simplabs/excellent/checks/flog_block_check'
|
32
|
+
require 'simplabs/excellent/checks/flog_class_check'
|
33
|
+
require 'simplabs/excellent/checks/rails'
|
@@ -6,70 +6,33 @@ module Simplabs
|
|
6
6
|
|
7
7
|
module Checks
|
8
8
|
|
9
|
+
# This check reports methods with an ABC metric score that is higher than the threshold. The ABC metric is basically a measure for complexity
|
10
|
+
# and is calculated as:
|
11
|
+
#
|
12
|
+
# a = number of assignments
|
13
|
+
# b = number of branches
|
14
|
+
# c = number of conditions
|
15
|
+
#
|
16
|
+
# score = Math.sqrt(a*a + b*b + c*c)
|
17
|
+
#
|
18
|
+
# ==== Applies to
|
19
|
+
#
|
20
|
+
# * methods
|
9
21
|
class AbcMetricMethodCheck < Base
|
10
22
|
|
11
|
-
ASSIGNMENTS = [:lasgn]
|
12
|
-
BRANCHES = [:vcall, :call]
|
13
|
-
CONDITIONS = [:==, :<=, :>=, :<, :>]
|
14
|
-
OPERATORS = [:*, :/, :%, :+, :<<, :>>, :&, :|, :^, :-, :**]
|
15
23
|
DEFAULT_THRESHOLD = 10
|
16
24
|
|
17
|
-
def initialize(options = {})
|
25
|
+
def initialize(options = {}) #:nodoc:
|
18
26
|
super()
|
19
|
-
@threshold
|
27
|
+
@threshold = options[:threshold] || DEFAULT_THRESHOLD
|
28
|
+
@interesting_nodes = [:defn, :defs]
|
20
29
|
end
|
21
30
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def evaluate(node)
|
27
|
-
method_name = node[1]
|
28
|
-
a = count_assignments(node)
|
29
|
-
b = count_branches(node)
|
30
|
-
c = count_conditionals(node)
|
31
|
-
score = Math.sqrt(a*a + b*b + c*c)
|
32
|
-
add_error('Method {{method}} has abc score of {{score}}.', { :method => method_name, :score => score }) unless score <= @threshold
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def count_assignments(node)
|
38
|
-
count = 0
|
39
|
-
count = count + 1 if assignment?(node)
|
40
|
-
node.children.each { |node| count += count_assignments(node) }
|
41
|
-
count
|
42
|
-
end
|
43
|
-
|
44
|
-
def count_branches(node)
|
45
|
-
count = 0
|
46
|
-
count = count + 1 if branch?(node)
|
47
|
-
node.children.each { |node| count += count_branches(node) }
|
48
|
-
count
|
49
|
-
end
|
50
|
-
|
51
|
-
def count_conditionals(node)
|
52
|
-
count = 0
|
53
|
-
count = count + 1 if conditional?(node)
|
54
|
-
node.children.each { |node| count += count_conditionals(node) }
|
55
|
-
count
|
31
|
+
def evaluate(context) #:nodoc:
|
32
|
+
unless context.abc_score <= @threshold
|
33
|
+
add_warning(context, '{{method}} has abc score of {{score}}.', { :method => context.full_name, :score => context.abc_score })
|
56
34
|
end
|
57
|
-
|
58
|
-
def assignment?(node)
|
59
|
-
ASSIGNMENTS.include?(node.node_type)
|
60
|
-
end
|
61
|
-
|
62
|
-
def branch?(node)
|
63
|
-
BRANCHES.include?(node.node_type) && !conditional?(node) && !operator?(node)
|
64
|
-
end
|
65
|
-
|
66
|
-
def conditional?(node)
|
67
|
-
(:call == node.node_type) && CONDITIONS.include?(node[2])
|
68
|
-
end
|
69
|
-
|
70
|
-
def operator?(node)
|
71
|
-
(:call == node.node_type) && OPERATORS.include?(node[2])
|
72
|
-
end
|
35
|
+
end
|
73
36
|
|
74
37
|
end
|
75
38
|
|
@@ -6,29 +6,29 @@ module Simplabs
|
|
6
6
|
|
7
7
|
module Checks
|
8
8
|
|
9
|
+
# This check reports conditionals that test an assignment as in
|
10
|
+
#
|
11
|
+
# something(var) if var = method()
|
12
|
+
#
|
13
|
+
# Assignments in conditions are often typos.
|
14
|
+
#
|
15
|
+
# ==== Applies to
|
16
|
+
#
|
17
|
+
# * +if+
|
18
|
+
# * +else+
|
19
|
+
# * +while+
|
20
|
+
# * +until+
|
9
21
|
class AssignmentInConditionalCheck < Base
|
10
22
|
|
11
|
-
def initialize(options = {})
|
23
|
+
def initialize(options = {}) #:nodoc:
|
12
24
|
super()
|
25
|
+
@interesting_nodes = [:if, :while, :until]
|
13
26
|
end
|
14
27
|
|
15
|
-
def
|
16
|
-
|
28
|
+
def evaluate(context) #:nodoc:
|
29
|
+
add_warning(context, 'Assignment in condition.') if context.tests_assignment?
|
17
30
|
end
|
18
31
|
|
19
|
-
def evaluate(node)
|
20
|
-
add_error('Assignment in condition.') if has_assignment?(node[1])
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def has_assignment?(node)
|
26
|
-
found_assignment = false
|
27
|
-
found_assignment = found_assignment || node.node_type == :lasgn
|
28
|
-
node.children.each { |child| found_assignment = found_assignment || has_assignment?(child) }
|
29
|
-
found_assignment
|
30
|
-
end
|
31
|
-
|
32
32
|
end
|
33
33
|
|
34
34
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'simplabs/excellent/
|
1
|
+
require 'simplabs/excellent/warning'
|
2
2
|
|
3
3
|
module Simplabs
|
4
4
|
|
@@ -6,33 +6,42 @@ module Simplabs
|
|
6
6
|
|
7
7
|
module Checks
|
8
8
|
|
9
|
+
# This is the base class for all code checks. All checks must specify +interesting_nodes+. When one of these nodes is processed by Excellent, it
|
10
|
+
# will invoke the +evaluate_node+ method of all checks that specify the node as one if their +interesting_nodes+.
|
9
11
|
class Base
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
attr_reader :warnings
|
14
|
+
|
15
|
+
# An array of node types that are interesting for the check. These are symbols as returned by RubyParser (see http://parsetree.rubyforge.org/ruby_parser/),
|
16
|
+
# e.g. <tt>:if</tt> or <tt>:defn</tt>
|
17
|
+
attr_reader :interesting_nodes
|
18
|
+
|
19
|
+
def initialize #:nodoc:
|
20
|
+
@warnings = []
|
17
21
|
end
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
|
23
|
+
# This method is called whenever Excellent processes a node that the check specified as one of the nodes it is interested in (see interesting_nodes).
|
24
|
+
#
|
25
|
+
# ==== Parameters
|
26
|
+
#
|
27
|
+
# * <tt>context</tt> - This is the last context the code processor has constructed. It contains all information required to execute the check (see Simplabs::Excellent::Parsing::SexpContext).
|
28
|
+
def evaluate_node(context)
|
29
|
+
evaluate(context)
|
25
30
|
end
|
26
|
-
|
27
|
-
|
31
|
+
|
32
|
+
# Adds a warning
|
33
|
+
#
|
34
|
+
# ==== Parameters
|
35
|
+
#
|
36
|
+
# * <tt>context</tt> - The context the check has been executed on.
|
37
|
+
# * <tt>message</tt> - The warning message.
|
38
|
+
# * <tt>info</tt> - The information hash that contains more info on the finding.
|
39
|
+
# * <tt>offset</tt> - The line offset that is added to the context's line property.
|
40
|
+
def add_warning(context, message, info = {}, offset = 0)
|
28
41
|
klass = self.class
|
29
|
-
@
|
42
|
+
@warnings << Simplabs::Excellent::Warning.new(klass, message, context.file, context.line + offset, info)
|
30
43
|
end
|
31
44
|
|
32
|
-
def errors
|
33
|
-
@errors
|
34
|
-
end
|
35
|
-
|
36
45
|
end
|
37
46
|
|
38
47
|
end
|
@@ -6,14 +6,22 @@ module Simplabs
|
|
6
6
|
|
7
7
|
module Checks
|
8
8
|
|
9
|
+
# This check reports +case+ statements that don't have an +else+ clause that would be executed when no case matches. If the tested value will never
|
10
|
+
# adopt any other values than the ones tested for in the cases, this should be expressed in the code by e.g. throwing an exception in the +else+
|
11
|
+
# clause.
|
12
|
+
#
|
13
|
+
# ==== Applies to
|
14
|
+
#
|
15
|
+
# * +case+ statements
|
9
16
|
class CaseMissingElseCheck < Base
|
10
17
|
|
11
|
-
def
|
12
|
-
|
18
|
+
def initialize #:nodoc:
|
19
|
+
super
|
20
|
+
@interesting_nodes = [:case]
|
13
21
|
end
|
14
|
-
|
15
|
-
def evaluate(
|
16
|
-
|
22
|
+
|
23
|
+
def evaluate(context) #:nodoc:
|
24
|
+
add_warning(context, 'Case statement is missing else clause.') unless context.has_else_clause?
|
17
25
|
end
|
18
26
|
|
19
27
|
end
|
@@ -6,23 +6,25 @@ module Simplabs
|
|
6
6
|
|
7
7
|
module Checks
|
8
8
|
|
9
|
+
# This check reports classes which have more lines than the threshold. Classes with a large number of lines are hard to read and understand and
|
10
|
+
# often an indicator for badly designed code as well.
|
11
|
+
#
|
12
|
+
# ==== Applies to
|
13
|
+
#
|
14
|
+
# * classes
|
9
15
|
class ClassLineCountCheck < LineCountCheck
|
10
16
|
|
11
|
-
DEFAULT_THRESHOLD =
|
17
|
+
DEFAULT_THRESHOLD = 400
|
12
18
|
|
13
|
-
def initialize(options = {})
|
19
|
+
def initialize(options = {}) #:nodoc:
|
14
20
|
threshold = options[:threshold] || DEFAULT_THRESHOLD
|
15
21
|
super([:class], threshold)
|
16
22
|
end
|
17
23
|
|
18
24
|
protected
|
19
25
|
|
20
|
-
def
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
def error_args(node, line_count)
|
25
|
-
['Class {{class}} has {{count}} lines.', { :class => node[1], :count => line_count }]
|
26
|
+
def warning_args(context) #:nodoc:
|
27
|
+
[context, '{{class}} has {{count}} lines.', { :class => context.full_name, :count => context.line_count }]
|
26
28
|
end
|
27
29
|
|
28
30
|
end
|
@@ -6,26 +6,27 @@ module Simplabs
|
|
6
6
|
|
7
7
|
module Checks
|
8
8
|
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
9
|
+
# This check reports classes with bad names. Badly named classes make reading and understanding the code much harder. Class names regarded as bad
|
10
|
+
# are for example:
|
11
|
+
#
|
12
|
+
# * names that are not Pascal cased (camel cased, starting with an upper case letter)
|
13
|
+
#
|
14
|
+
# ==== Applies to
|
15
|
+
#
|
16
|
+
# * classes
|
12
17
|
class ClassNameCheck < NameCheck
|
13
18
|
|
14
19
|
DEFAULT_PATTERN = /^[A-Z]{1}[a-zA-Z0-9]*$/
|
15
20
|
|
16
|
-
def initialize(options = {})
|
21
|
+
def initialize(options = {}) #:nodoc:
|
17
22
|
pattern = options[:pattern] || DEFAULT_PATTERN
|
18
23
|
super([:class], pattern)
|
19
24
|
end
|
20
25
|
|
21
|
-
def find_name(node)
|
22
|
-
node[1].class == Symbol ? node[1] : node[1].last
|
23
|
-
end
|
24
|
-
|
25
26
|
protected
|
26
27
|
|
27
|
-
def
|
28
|
-
['Bad class name {{class}}.', { :class =>
|
28
|
+
def warning_args(context) #:nodoc:
|
29
|
+
[context, 'Bad class name {{class}}.', { :class => context.full_name }]
|
29
30
|
end
|
30
31
|
|
31
32
|
end
|