metric_fu-roodi 2.2.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/bin/metric_fu-roodi +2 -19
  3. data/bin/metric_fu-roodi-describe +2 -5
  4. data/lib/roodi.rb +6 -2
  5. data/lib/roodi/version.rb +1 -1
  6. metadata +13 -119
  7. data/.gitignore +0 -3
  8. data/.rspec +0 -2
  9. data/Gemfile +0 -6
  10. data/History.txt +0 -111
  11. data/Manifest.txt +0 -56
  12. data/README.txt +0 -98
  13. data/Rakefile +0 -31
  14. data/TODO.md +0 -3
  15. data/lib/roodi/checks.rb +0 -18
  16. data/lib/roodi/checks/abc_metric_method_check.rb +0 -79
  17. data/lib/roodi/checks/assignment_in_conditional_check.rb +0 -32
  18. data/lib/roodi/checks/case_missing_else_check.rb +0 -20
  19. data/lib/roodi/checks/check.rb +0 -76
  20. data/lib/roodi/checks/class_line_count_check.rb +0 -28
  21. data/lib/roodi/checks/class_name_check.rb +0 -31
  22. data/lib/roodi/checks/class_variable_check.rb +0 -24
  23. data/lib/roodi/checks/control_coupling_check.rb +0 -20
  24. data/lib/roodi/checks/cyclomatic_complexity_block_check.rb +0 -41
  25. data/lib/roodi/checks/cyclomatic_complexity_check.rb +0 -50
  26. data/lib/roodi/checks/cyclomatic_complexity_method_check.rb +0 -42
  27. data/lib/roodi/checks/empty_rescue_body_check.rb +0 -32
  28. data/lib/roodi/checks/for_loop_check.rb +0 -20
  29. data/lib/roodi/checks/line_count_check.rb +0 -28
  30. data/lib/roodi/checks/method_line_count_check.rb +0 -29
  31. data/lib/roodi/checks/method_name_check.rb +0 -31
  32. data/lib/roodi/checks/missing_foreign_key_index_check.rb +0 -99
  33. data/lib/roodi/checks/module_line_count_check.rb +0 -28
  34. data/lib/roodi/checks/module_name_check.rb +0 -31
  35. data/lib/roodi/checks/name_check.rb +0 -16
  36. data/lib/roodi/checks/npath_complexity_check.rb +0 -75
  37. data/lib/roodi/checks/npath_complexity_method_check.rb +0 -29
  38. data/lib/roodi/checks/parameter_number_check.rb +0 -34
  39. data/lib/roodi/core.rb +0 -1
  40. data/lib/roodi/core/checking_visitor.rb +0 -26
  41. data/lib/roodi/core/error.rb +0 -17
  42. data/lib/roodi/core/parser.rb +0 -48
  43. data/lib/roodi/core/runner.rb +0 -81
  44. data/lib/roodi/core/visitable_sexp.rb +0 -25
  45. data/lib/roodi_task.rb +0 -35
  46. data/roodi.gemspec +0 -26
  47. data/roodi.yml +0 -25
  48. data/spec/roodi/checks/abc_metric_method_check_spec.rb +0 -89
  49. data/spec/roodi/checks/assignment_in_conditional_check_spec.rb +0 -105
  50. data/spec/roodi/checks/case_missing_else_check_spec.rb +0 -32
  51. data/spec/roodi/checks/class_line_count_check_spec.rb +0 -39
  52. data/spec/roodi/checks/class_name_check_spec.rb +0 -39
  53. data/spec/roodi/checks/class_variable_check_spec.rb +0 -17
  54. data/spec/roodi/checks/control_coupling_check_spec.rb +0 -23
  55. data/spec/roodi/checks/cyclomatic_complexity_block_check_spec.rb +0 -67
  56. data/spec/roodi/checks/cyclomatic_complexity_method_check_spec.rb +0 -200
  57. data/spec/roodi/checks/empty_rescue_body_check_spec.rb +0 -154
  58. data/spec/roodi/checks/for_loop_check_spec.rb +0 -18
  59. data/spec/roodi/checks/method_line_count_check_spec.rb +0 -56
  60. data/spec/roodi/checks/method_name_check_spec.rb +0 -76
  61. data/spec/roodi/checks/missing_foreign_key_index_check_spec.rb +0 -33
  62. data/spec/roodi/checks/module_line_count_check_spec.rb +0 -39
  63. data/spec/roodi/checks/module_name_check_spec.rb +0 -27
  64. data/spec/roodi/checks/npath_complexity_method_check_spec.rb +0 -53
  65. data/spec/roodi/checks/parameter_number_check_spec.rb +0 -47
  66. data/spec/roodi/core/runner_spec.rb +0 -25
  67. data/spec/roodi/roodi.yml +0 -2
  68. data/spec/spec_helper.rb +0 -3
@@ -1,42 +0,0 @@
1
- require 'roodi/checks/cyclomatic_complexity_check'
2
-
3
- module Roodi
4
- module Checks
5
- # Checks cyclomatic complexity of a method against a specified limit.
6
- #
7
- # The cyclomatic complexity is measured by the number of "if", "unless", "elsif", "?:",
8
- # "while", "until", "for", "rescue", "case", "when", "&&", "and", "||" and "or"
9
- # statements (plus one) in the body of the member. It is a measure of the minimum
10
- # number of possible paths through the source and therefore the number of required tests.
11
- #
12
- # Generally, for a method, 1-4 is considered good, 5-8 ok, 9-10 consider re-factoring, and
13
- # 11+ re-factor now!
14
- class CyclomaticComplexityMethodCheck < CyclomaticComplexityCheck
15
-
16
- DEFAULT_COMPLEXITY = 8
17
-
18
- def initialize
19
- super()
20
- self.complexity = DEFAULT_COMPLEXITY
21
- end
22
-
23
- def interesting_nodes
24
- [:defn] + COMPLEXITY_NODE_TYPES
25
- end
26
-
27
- def evaluate_start_defn(node)
28
- @method_name = @node[1]
29
- increase_depth
30
- end
31
-
32
- def evaluate_end_defn(node)
33
- decrease_depth
34
- end
35
-
36
- def evaluate_matching_end
37
- add_error "Method name \"#{@method_name}\" cyclomatic complexity is #{@count}. It should be #{@complexity} or less." unless @count <= @complexity
38
- end
39
-
40
- end
41
- end
42
- end
@@ -1,32 +0,0 @@
1
- require 'roodi/checks/check'
2
-
3
- module Roodi
4
- module Checks
5
- # Checks the body of a rescue block to make sure it's not empty..
6
- #
7
- # When the body of a rescue block is empty, exceptions can get caught and swallowed without
8
- # any feedback to the user.
9
- class EmptyRescueBodyCheck < Check
10
- STATEMENT_NODES = [:fcall, :return, :attrasgn, :vcall, :nil, :call, :lasgn, :true, :false, :next]
11
-
12
- def interesting_nodes
13
- [:resbody]
14
- end
15
-
16
- def evaluate_start(node)
17
- add_error("Rescue block should not be empty.") unless has_statement?(node.children[1])
18
- end
19
-
20
- private
21
-
22
- def has_statement?(node)
23
- false unless node
24
- has_local_statement?(node) or node.children.any? { |child| has_statement?(child) } if node
25
- end
26
-
27
- def has_local_statement?(node)
28
- STATEMENT_NODES.include?(node.node_type)
29
- end
30
- end
31
- end
32
- end
@@ -1,20 +0,0 @@
1
- require 'roodi/checks/check'
2
-
3
- module Roodi
4
- module Checks
5
- # Checks to make sure for loops are not being used..
6
- #
7
- # Using a for loop is not idiomatic use of Ruby, and is usually a sign that someone with
8
- # more experience in a different programming language is trying out Ruby. Use
9
- # Enumerable.each with a block instead.
10
- class ForLoopCheck < Check
11
- def interesting_nodes
12
- [:for]
13
- end
14
-
15
- def evaluate_start(node)
16
- add_error "Don't use 'for' loops. Use Enumerable.each instead."
17
- end
18
- end
19
- end
20
- end
@@ -1,28 +0,0 @@
1
- require 'roodi/checks/check'
2
-
3
- module Roodi
4
- module Checks
5
- class LineCountCheck < Check
6
-
7
- attr_accessor :line_count
8
-
9
- def evaluate_start(node)
10
- line_count = count_lines(node)
11
- add_error "#{message_prefix} \"#{node[1]}\" has #{line_count} lines. It should have #{@line_count} or less." unless line_count <= @line_count
12
- end
13
-
14
- protected
15
-
16
- def count_lines(node)
17
- node.last.line - node.line - 1
18
- rescue NoMethodError => e
19
- if ENV['DEBUG'] =~ /true/i
20
- STDERR.puts "!! line counting error #{e.message}\t #{node.inspect}"
21
- STDERR.puts "!! Does the node have any lines?"
22
- end
23
- 0
24
- end
25
-
26
- end
27
- end
28
- end
@@ -1,29 +0,0 @@
1
- require 'roodi/checks/line_count_check'
2
-
3
- module Roodi
4
- module Checks
5
- # Checks a method to make sure the number of lines it has is under the specified limit.
6
- #
7
- # A method getting too large is a code smell that indicates it might be doing more than one
8
- # thing and becoming hard to test. It should probably be refactored into multiple methods
9
- # that each do a single thing well.
10
- class MethodLineCountCheck < LineCountCheck
11
-
12
- DEFAULT_LINE_COUNT = 20
13
-
14
- def initialize
15
- super()
16
- self.line_count = DEFAULT_LINE_COUNT
17
- end
18
-
19
- def interesting_nodes
20
- [:defn]
21
- end
22
-
23
- def message_prefix
24
- 'Method'
25
- end
26
-
27
- end
28
- end
29
- end
@@ -1,31 +0,0 @@
1
- require 'roodi/checks/name_check'
2
-
3
- module Roodi
4
- module Checks
5
- # Checks a method name to make sure it matches the specified pattern.
6
- #
7
- # Keeping to a consistent nameing convention makes your code easier to read.
8
- class MethodNameCheck < NameCheck
9
-
10
- DEFAULT_PATTERN = /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
11
-
12
- def initialize
13
- super()
14
- self.pattern = DEFAULT_PATTERN
15
- end
16
-
17
- def interesting_nodes
18
- [:defn]
19
- end
20
-
21
- def message_prefix
22
- 'Method'
23
- end
24
-
25
- def find_name(node)
26
- node[1]
27
- end
28
-
29
- end
30
- end
31
- end
@@ -1,99 +0,0 @@
1
- require 'roodi/checks/check'
2
- require 'pathname'
3
-
4
- module Roodi
5
- module Checks
6
- # Checks to make sure for loops are not being used..
7
- #
8
- # Using a for loop is not idiomatic use of Ruby, and is usually a sign that someone with
9
- # more experience in a different programming language is trying out Ruby. Use
10
- # Enumerable.each with a block instead.
11
- class MissingForeignKeyIndexCheck < Check
12
- def initialize
13
- super()
14
- @foreign_keys = {}
15
- @indexes = {}
16
- end
17
-
18
- def interesting_nodes
19
- [:call]
20
- end
21
-
22
- def evaluate_start_call(node)
23
- if analyzing_schema(node)
24
- if creating_table(node)
25
- @current_table = create_table_name(node)
26
- end
27
-
28
- if creating_foreign_key(node)
29
- @foreign_keys[@current_table] ||= []
30
- @foreign_keys[@current_table] << foreign_key_column_name(node)
31
- end
32
-
33
- if adding_index(node)
34
- @indexes[index_table_name(node)] ||= []
35
- @indexes[index_table_name(node)] << index_column_name(node)
36
- end
37
- end
38
- end
39
-
40
- def evaluate_end_call(node)
41
- #ignored
42
- end
43
-
44
- def analyzing_schema(node)
45
- pathname = Pathname.new(node.file)
46
- @analyzing_schema ||= ("schema.rb" == pathname.basename.to_s)
47
- end
48
-
49
- def creating_table(node)
50
- :create_table == node[2]
51
- end
52
-
53
- def create_table_name(node)
54
- # Get table name out of this:
55
- # s(:call, nil, :create_table, s(:arglist, s(:str, "duplicate_blocks"), s(:hash, s(:lit, :force), s(:true))))
56
- node[3][1][1]
57
- end
58
-
59
- def creating_foreign_key(node)
60
- #s(:call, s(:lvar, :t), :integer, s(:arglist, s(:str, "duplicate_set_id"), s(:hash, s(:lit, :null), s(:false))))
61
- column_type = node[2]
62
- column_name = node[3][1][1]
63
- :integer == column_type && "_id" == column_name[-3,3]
64
- end
65
-
66
- def foreign_key_column_name(node)
67
- #s(:call, s(:lvar, :t), :integer, s(:arglist, s(:str, "duplicate_set_id"), s(:hash, s(:lit, :null), s(:false))))
68
- column_name = node[3][1][1]
69
- end
70
-
71
- def adding_index(node)
72
- :add_index == node[2]
73
- end
74
-
75
- def index_table_name(node)
76
- # Get table name out of this:
77
- # s(:call, nil, :add_index, s(:arglist, s(:str, "duplicate_blocks"), s(:array, s(:str, "duplicate_set_id")), s(:hash, s(:lit, :name), s(:str, "index_duplicate_blocks_on_duplicate_set_id"))))
78
- node[3][1][1]
79
- end
80
-
81
- def index_column_name(node)
82
- # Get index column name out of this:
83
- # s(:call, nil, :add_index, s(:arglist, s(:str, "duplicate_blocks"), s(:array, s(:str, "duplicate_set_id")), s(:hash, s(:lit, :name), s(:str, "index_duplicate_blocks_on_duplicate_set_id"))))
84
- node[3][2][1][1]
85
- end
86
-
87
- def end_file(filename)
88
- @foreign_keys.keys.each do |table|
89
- foreign_keys = @foreign_keys[table] || []
90
- indexes = @indexes[table] || []
91
- missing_indexes = foreign_keys - indexes
92
- missing_indexes.each do |fkey|
93
- add_error("Table '#{table}' is missing an index on the foreign key '#{fkey}'", filename, 1)
94
- end
95
- end
96
- end
97
- end
98
- end
99
- end
@@ -1,28 +0,0 @@
1
- require 'roodi/checks/line_count_check'
2
-
3
- module Roodi
4
- module Checks
5
- # Checks a module to make sure the number of lines it has is under the specified limit.
6
- #
7
- # A module getting too large is a code smell that indicates it might be taking on too many
8
- # responsibilities. It should probably be refactored into multiple smaller modules.
9
- class ModuleLineCountCheck < LineCountCheck
10
-
11
- DEFAULT_LINE_COUNT = 300
12
-
13
- def initialize
14
- super()
15
- self.line_count = DEFAULT_LINE_COUNT
16
- end
17
-
18
- def interesting_nodes
19
- [:module]
20
- end
21
-
22
- def message_prefix
23
- 'Module'
24
- end
25
-
26
- end
27
- end
28
- end
@@ -1,31 +0,0 @@
1
- require 'roodi/checks/name_check'
2
-
3
- module Roodi
4
- module Checks
5
- # Checks a module name to make sure it matches the specified pattern.
6
- #
7
- # Keeping to a consistent nameing convention makes your code easier to read.
8
- class ModuleNameCheck < NameCheck
9
-
10
- DEFAULT_PATTERN = /^[A-Z][a-zA-Z0-9]*$/
11
-
12
- def initialize
13
- super()
14
- self.pattern = DEFAULT_PATTERN
15
- end
16
-
17
- def interesting_nodes
18
- [:module]
19
- end
20
-
21
- def message_prefix
22
- 'Module'
23
- end
24
-
25
- def find_name(node)
26
- node[1].class == Symbol ? node[1] : node[1].last
27
- end
28
-
29
- end
30
- end
31
- end
@@ -1,16 +0,0 @@
1
- require 'roodi/checks/check'
2
-
3
- module Roodi
4
- module Checks
5
- class NameCheck < Check
6
-
7
- attr_accessor :pattern
8
-
9
- def evaluate_start(node)
10
- name = find_name(node)
11
- add_error "#{message_prefix} name \"#{name}\" should match pattern #{@pattern.inspect}" unless name.to_s =~ @pattern
12
- end
13
-
14
- end
15
- end
16
- end
@@ -1,75 +0,0 @@
1
- require 'roodi/checks/check'
2
-
3
- module Roodi
4
- module Checks
5
- class NpathComplexityCheck < Check
6
- # , :when, :and, :or
7
- MULTIPLYING_NODE_TYPES = [:if, :while, :until, :for, :case]
8
- ADDING_NODE_TYPES = [:rescue]
9
- COMPLEXITY_NODE_TYPES = MULTIPLYING_NODE_TYPES + ADDING_NODE_TYPES
10
-
11
- attr_accessor :complexity
12
-
13
- def initialize(complexity)
14
- super()
15
- @complexity = complexity
16
- @value_stack = []
17
- @current_value = 1
18
- end
19
-
20
- def evalute_start_if(node)
21
- push_value
22
- end
23
-
24
- def evalute_start_while(node)
25
- push_value
26
- end
27
-
28
- def evalute_start_until(node)
29
- push_value
30
- end
31
-
32
- def evalute_start_for(node)
33
- push_value
34
- end
35
-
36
- def evalute_start_case(node)
37
- push_value
38
- end
39
-
40
- def evalute_start_rescue(node)
41
- push_value
42
- end
43
-
44
- MULTIPLYING_NODE_TYPES.each do |type|
45
- define_method "evaluate_end_#{type}" do |node|
46
- leave_multiplying_conditional
47
- end
48
- end
49
-
50
- ADDING_NODE_TYPES.each do |type|
51
- define_method "evaluate_end_#{type}" do |node|
52
- leave_multiplying_conditional
53
- end
54
- end
55
-
56
- protected
57
-
58
- def push_value
59
- @value_stack.push @current_value
60
- @current_value = 1
61
- end
62
-
63
- def leave_multiplying_conditional
64
- pop = @value_stack.pop
65
- @current_value = (@current_value + 1) * pop
66
- end
67
-
68
- def leave_adding_conditional
69
- pop = @value_stack.pop
70
- puts "#{type}, so adding #{pop}"
71
- @current_value = @current_value - 1 + pop
72
- end
73
- end
74
- end
75
- end
@@ -1,29 +0,0 @@
1
- require 'roodi/checks/npath_complexity_check'
2
-
3
- module Roodi
4
- module Checks
5
- # Checks Npath complexity of a method against a specified limit.
6
- class NpathComplexityMethodCheck < NpathComplexityCheck
7
-
8
- DEFAULT_COMPLEXITY = 8
9
-
10
- def initialize
11
- super(DEFAULT_COMPLEXITY)
12
- end
13
-
14
- def interesting_nodes
15
- [:defn] + COMPLEXITY_NODE_TYPES
16
- end
17
-
18
- def evaluate_start_defn(node)
19
- @method_name = @node[1]
20
- push_value
21
- end
22
-
23
- def evaluate_end_defn(node)
24
- add_error "Method name \"#{@method_name}\" n-path complexity is #{@current_value}. It should be #{@complexity} or less." unless @current_value <= @complexity
25
- end
26
-
27
- end
28
- end
29
- end