roodi 3.0.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 07d949870658795c4a909c32faf4e50b37f29813
4
- data.tar.gz: 54f229d5e6901aa1246d5e314ab63fa462acb923
3
+ metadata.gz: 2eb90b5c384b0916cd61ec2cf8f5a8f950458f23
4
+ data.tar.gz: 76875cad67471324e5017ea7dd82e28c49307ba6
5
5
  SHA512:
6
- metadata.gz: 94c41207f62016bd29d2eb1ada674d89772e9594cebd80bf96d750137048b0a9e16451dd54280f145e4a88019da2d9ecf6b56235d57ca4dec87ae1c54ac6ef8f
7
- data.tar.gz: 6f31b01a3c5376860ad999fa8d0ff1de82847315f0d8257d19cd26b7c56ef024e725999737aebf9b541830b3fe5b5302a8b87412aaa150c5f22562fe6ddd742b
6
+ metadata.gz: b68ac64dba9440ef8088cce40aaf71e4a3e2af8b7d9315255191cda7d786ca591862c13a319c5b109cc32c93f05eb17b81a4c3ef42b94962cfb9d31bbc6f92ee
7
+ data.tar.gz: 57ca381da9ccd33455286ec37a7a0798010ccc744ebba90f23668187470eae1a6d9d28181fcb1204450a59bfdfbae3bf4d5f402fe5b009c14438a6f16f8870c5
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  doc
2
2
  pkg
3
3
  Gemfile.lock
4
+ coverage
data/Gemfile CHANGED
@@ -4,3 +4,4 @@ gemspec
4
4
 
5
5
  gem "rake"
6
6
  gem "rspec", "~> 2.14.1"
7
+ gem 'coveralls', :require => false
@@ -1,3 +1,15 @@
1
+ = 3.0.1
2
+
3
+ * Added brief class level documentation on all checks
4
+ * No longer printing out "Line: 1" every time you run roodi-describe
5
+ * Added code coverage badge from Coverall.io
6
+ * Added code coverage through Coveralls.io
7
+ * Pulled duplicated find_name method up to super class
8
+ * Added Code Climate badge
9
+ * Added info about how to contribute
10
+ * Updated copyright info to be current
11
+ * Re-added tasks for releasing new versions of the gem
12
+
1
13
  = 3.0.0
2
14
 
3
15
  * Removed MissingForeignKeyIndexCheck, since it is specific to Rails/ActiveRecord and thus doesn't belong in Roodi
data/README.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # roodi
2
2
 
3
3
  [![Build Status](https://travis-ci.org/roodi/roodi.png?branch=master)](https://travis-ci.org/roodi/roodi)
4
+ [![Code Climate](https://codeclimate.com/repos/5204c3fc7e00a47bf7015e4e/badges/44ede0c56a53ff100012/gpa.png)](https://codeclimate.com/repos/5204c3fc7e00a47bf7015e4e/feed)
5
+ [![Coverage Status](https://coveralls.io/repos/roodi/roodi/badge.png?branch=master)](https://coveralls.io/r/roodi/roodi?branch=master)
4
6
 
5
7
  ## Description
6
8
 
7
- Roodi stands for Ruby Object Oriented Design Inferometer. It parses your Ruby code and warns you about design issues you have based on the checks that is has configured.
9
+ Roodi stands for Ruby Object Oriented Design Inferometer. It parses your Ruby code and warns you about design issues you have based on the checks that is has configured.
8
10
 
9
11
  ## Install
10
12
 
@@ -86,11 +88,24 @@ To change the set of checks included, or to change the default values of the che
86
88
 
87
89
  * BlockVariableShadowCheck - Check that a block variable does not have the same name as a method parameter or local variable. It may be mistakenly referenced within the block.
88
90
 
91
+ ## Contributing
92
+
93
+ ### Bug reporting
94
+ Please use the GitHub issue tracker.
95
+
96
+ ### Want to submit some code?
97
+ Fantastic! Please follow this procedure:
98
+ - Fork the repository
99
+ - Create a well-named topic branch
100
+ - Add specs for any changes you make
101
+ - Write meaningful commit messages explaining why this change is needed
102
+ - Create a pull request.
103
+
89
104
  ## License
90
105
 
91
106
  (The MIT License)
92
107
 
93
- Copyright (c) 2008 Marty Andrews
108
+ Copyright (c) 2013 Peter Evjan
94
109
 
95
110
  Permission is hereby granted, free of charge, to any person obtaining
96
111
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -2,6 +2,7 @@ require 'rake'
2
2
  require 'rspec/core/rake_task'
3
3
  require 'bundler'
4
4
  require 'roodi'
5
+ require 'bundler/gem_tasks'
5
6
 
6
7
  def roodi(ruby_files)
7
8
  roodi = Roodi::Core::Runner.new
@@ -2,17 +2,13 @@ require 'roodi/checks/check'
2
2
 
3
3
  module Roodi
4
4
  module Checks
5
- # TODO: Add summary
6
- #
7
- # TODO: Add detail
5
+ # The ABC metric method check calculates the number of Assignments,
6
+ # Branches and Conditionals in your code. It is similar to
7
+ # cyclomatic complexity, so the lower the better.
8
8
  class AbcMetricMethodCheck < Check
9
- # ASSIGNMENTS = [:attrasgn, :attrset, :dasgn_curr, :iasgn, :lasgn, :masgn]
10
9
  ASSIGNMENTS = [:lasgn]
11
- # BRANCHES = [:if, :else, :while, :until, :for, :rescue, :case, :when, :and, :or]
12
10
  BRANCHES = [:vcall, :call]
13
- # CONDITIONS = [:and, :or]
14
11
  CONDITIONS = [:==, :"!=", :<=, :>=, :<, :>]
15
- # = *= /= %= += <<= >>= &= |= ^=
16
12
  OPERATORS = [:*, :/, :%, :+, :<<, :>>, :&, :|, :^]
17
13
  DEFAULT_SCORE = 10
18
14
 
@@ -2,12 +2,13 @@ require 'roodi/core/error'
2
2
 
3
3
  module Roodi
4
4
  module Checks
5
+ # Base class for all the checks
5
6
  class Check
6
7
 
7
8
  NODE_TYPES = [:defn, :module, :resbody, :lvar, :cvar, :class, :if, :while, :until, :for, :rescue, :case, :when, :and, :or]
8
9
 
9
10
  class << self
10
-
11
+
11
12
  def make(options = nil)
12
13
  check = new
13
14
  if options
@@ -23,7 +24,7 @@ module Roodi
23
24
  def initialize
24
25
  @errors = []
25
26
  end
26
-
27
+
27
28
  NODE_TYPES.each do |node|
28
29
  start_node_method = "evaluate_start_#{node}"
29
30
  end_node_method = "evaluate_end_#{node}"
@@ -37,10 +38,10 @@ module Roodi
37
38
 
38
39
  def start_file(filename)
39
40
  end
40
-
41
+
41
42
  def end_file(filename)
42
43
  end
43
-
44
+
44
45
  def evaluate_start(node)
45
46
  end
46
47
 
@@ -57,17 +58,17 @@ module Roodi
57
58
  evaluate_node(:start, node)
58
59
  evaluate_start(node)
59
60
  end
60
-
61
+
61
62
  def evaluate_node_end(node)
62
63
  evaluate_node(:end, node)
63
64
  evaluate_end(node)
64
65
  end
65
-
66
+
66
67
  def add_error(error, filename = @node.file, line = @node.line)
67
68
  @errors ||= []
68
69
  @errors << Roodi::Core::Error.new("#{filename}", "#{line}", error)
69
70
  end
70
-
71
+
71
72
  def errors
72
73
  @errors
73
74
  end
@@ -3,17 +3,17 @@ require 'roodi/checks/name_check'
3
3
  module Roodi
4
4
  module Checks
5
5
  # Checks a class name to make sure it matches the specified pattern.
6
- #
6
+ #
7
7
  # Keeping to a consistent naming convention makes your code easier to read.
8
8
  class ClassNameCheck < NameCheck
9
9
 
10
10
  DEFAULT_PATTERN = /^[A-Z][a-zA-Z0-9]*$/
11
-
11
+
12
12
  def initialize
13
13
  super()
14
14
  self.pattern = DEFAULT_PATTERN
15
15
  end
16
-
16
+
17
17
  def interesting_nodes
18
18
  [:class]
19
19
  end
@@ -22,10 +22,6 @@ module Roodi
22
22
  'Class'
23
23
  end
24
24
 
25
- def find_name(node)
26
- node[1].class == Symbol ? node[1] : node[1].last
27
- end
28
-
29
25
  end
30
26
  end
31
27
  end
@@ -2,6 +2,10 @@ require 'roodi/checks/check'
2
2
 
3
3
  module Roodi
4
4
  module Checks
5
+ # Checks if a method uses an argument to decide on what execution path to take
6
+ #
7
+ # It is a kind of duplication, since the caller knows what path should be taken.
8
+ # Also, it means the method has more than one responsibility.
5
9
  class ControlCouplingCheck < Check
6
10
  def interesting_nodes
7
11
  [:defn, :lvar]
@@ -11,7 +15,7 @@ module Roodi
11
15
  @method_name = node[1]
12
16
  @arguments = node[2][1..-1]
13
17
  end
14
-
18
+
15
19
  def evaluate_start_lvar(node)
16
20
  add_error "Method \"#{@method_name}\" uses the argument \"#{node[1]}\" for internal control." if @arguments.detect {|each| each == node[1]}
17
21
  end
@@ -2,8 +2,13 @@ require 'roodi/checks/check'
2
2
 
3
3
  module Roodi
4
4
  module Checks
5
+ # Cyclomatic complexity counts the number of linearly independent paths in
6
+ # the code. The lower the score, the better.
7
+ #
8
+ # Read more in the inventor Thomas J. McCabe's original research
9
+ # paper: www.literateprogramming.com/mccabe.pdf
5
10
  class CyclomaticComplexityCheck < Check
6
-
11
+
7
12
  COMPLEXITY_NODE_TYPES = [:if, :while, :until, :for, :rescue, :case, :when, :and, :or]
8
13
 
9
14
  attr_accessor :complexity
@@ -13,19 +18,19 @@ module Roodi
13
18
  @count = 0
14
19
  @counting = 0
15
20
  end
16
-
21
+
17
22
  COMPLEXITY_NODE_TYPES.each do |type|
18
23
  define_method "evaluate_start_#{type}" do |node|
19
24
  @count = @count + 1 if counting?
20
25
  end
21
26
  end
22
-
27
+
23
28
  protected
24
-
29
+
25
30
  def count_complexity(node)
26
31
  count_branches(node) + 1
27
32
  end
28
-
33
+
29
34
  def increase_depth
30
35
  @count = 1 unless counting?
31
36
  @counting = @counting + 1
@@ -38,9 +43,9 @@ module Roodi
38
43
  evaluate_matching_end
39
44
  end
40
45
  end
41
-
46
+
42
47
  private
43
-
48
+
44
49
  def counting?
45
50
  @counting > 0
46
51
  end
@@ -2,6 +2,7 @@ require 'roodi/checks/check'
2
2
 
3
3
  module Roodi
4
4
  module Checks
5
+ # Checks how many lines there are in a ruby_parser node
5
6
  class LineCountCheck < Check
6
7
 
7
8
  attr_accessor :line_count
@@ -3,12 +3,12 @@ require 'roodi/checks/name_check'
3
3
  module Roodi
4
4
  module Checks
5
5
  # Checks a module name to make sure it matches the specified pattern.
6
- #
6
+ #
7
7
  # Keeping to a consistent nameing convention makes your code easier to read.
8
8
  class ModuleNameCheck < NameCheck
9
9
 
10
10
  DEFAULT_PATTERN = /^[A-Z][a-zA-Z0-9]*$/
11
-
11
+
12
12
  def initialize
13
13
  super()
14
14
  self.pattern = DEFAULT_PATTERN
@@ -22,10 +22,6 @@ module Roodi
22
22
  'Module'
23
23
  end
24
24
 
25
- def find_name(node)
26
- node[1].class == Symbol ? node[1] : node[1].last
27
- end
28
-
29
25
  end
30
26
  end
31
27
  end
@@ -2,6 +2,7 @@ require 'roodi/checks/check'
2
2
 
3
3
  module Roodi
4
4
  module Checks
5
+ # Checking that a node's name matches a pattern
5
6
  class NameCheck < Check
6
7
 
7
8
  attr_accessor :pattern
@@ -11,6 +12,10 @@ module Roodi
11
12
  add_error "#{message_prefix} name \"#{name}\" should match pattern #{@pattern.inspect}" unless name.to_s =~ @pattern
12
13
  end
13
14
 
15
+ def find_name(node)
16
+ node[1].class == Symbol ? node[1] : node[1].last
17
+ end
18
+
14
19
  end
15
20
  end
16
21
  end
@@ -2,6 +2,11 @@ require 'roodi/checks/check'
2
2
 
3
3
  module Roodi
4
4
  module Checks
5
+ # Checks NPATH complexity of a node
6
+ #
7
+ # NPATH counts acyclic execution paths in a piece of code.
8
+ # Here is an article by Brian A. Nejmeh that explains it in more detail:
9
+ # http://www.accessmylibrary.com/article-1G1-6242192/npath-measure-execution-path.html
5
10
  class NpathComplexityCheck < Check
6
11
  # , :when, :and, :or
7
12
  MULTIPLYING_NODE_TYPES = [:if, :while, :until, :for, :case]
@@ -9,18 +14,18 @@ module Roodi
9
14
  COMPLEXITY_NODE_TYPES = MULTIPLYING_NODE_TYPES + ADDING_NODE_TYPES
10
15
 
11
16
  attr_accessor :complexity
12
-
17
+
13
18
  def initialize(complexity)
14
19
  super()
15
20
  @complexity = complexity
16
21
  @value_stack = []
17
22
  @current_value = 1
18
23
  end
19
-
24
+
20
25
  def evalute_start_if(node)
21
26
  push_value
22
27
  end
23
-
28
+
24
29
  def evalute_start_while(node)
25
30
  push_value
26
31
  end
@@ -40,7 +45,7 @@ module Roodi
40
45
  def evalute_start_rescue(node)
41
46
  push_value
42
47
  end
43
-
48
+
44
49
  MULTIPLYING_NODE_TYPES.each do |type|
45
50
  define_method "evaluate_end_#{type}" do |node|
46
51
  leave_multiplying_conditional
@@ -52,9 +57,9 @@ module Roodi
52
57
  leave_multiplying_conditional
53
58
  end
54
59
  end
55
-
60
+
56
61
  protected
57
-
62
+
58
63
  def push_value
59
64
  @value_stack.push @current_value
60
65
  @current_value = 1
@@ -64,7 +69,7 @@ module Roodi
64
69
  pop = @value_stack.pop
65
70
  @current_value = (@current_value + 1) * pop
66
71
  end
67
-
72
+
68
73
  def leave_adding_conditional
69
74
  pop = @value_stack.pop
70
75
  puts "#{type}, so adding #{pop}"
@@ -2,15 +2,15 @@ require 'roodi/checks/npath_complexity_check'
2
2
 
3
3
  module Roodi
4
4
  module Checks
5
- # Checks Npath complexity of a method against a specified limit.
5
+ # Checks NPATH complexity of a method against a specified limit.
6
6
  class NpathComplexityMethodCheck < NpathComplexityCheck
7
7
 
8
8
  DEFAULT_COMPLEXITY = 8
9
-
9
+
10
10
  def initialize
11
11
  super(DEFAULT_COMPLEXITY)
12
12
  end
13
-
13
+
14
14
  def interesting_nodes
15
15
  [:defn] + COMPLEXITY_NODE_TYPES
16
16
  end
@@ -9,14 +9,14 @@ module Roodi
9
9
  module Core
10
10
  class Runner
11
11
  DEFAULT_CONFIG = File.join(File.dirname(__FILE__), "..", "..", "..", "roodi.yml")
12
-
12
+
13
13
  attr_writer :config
14
-
14
+
15
15
  def initialize(*checks)
16
16
  @config = DEFAULT_CONFIG
17
17
  @checks = checks unless checks.empty?
18
18
  end
19
-
19
+
20
20
  def check(filename, content)
21
21
  @checks ||= load_checks
22
22
  @checker ||= CheckingVisitor.new(@checks)
@@ -29,34 +29,33 @@ module Roodi
29
29
  def check_content(content, filename = "dummy-file.rb")
30
30
  check(filename, content)
31
31
  end
32
-
32
+
33
33
  def check_file(filename)
34
34
  return unless File.exists?(filename)
35
35
  check(filename, File.read(filename))
36
36
  end
37
-
37
+
38
38
  def print(filename, content)
39
39
  node = parse(filename, content)
40
- puts "Line: #{node.line}"
41
40
  pp node
42
41
  end
43
42
 
44
43
  def print_content(content)
45
44
  print("dummy-file.rb", content)
46
45
  end
47
-
46
+
48
47
  def print_file(filename)
49
48
  print(filename, File.read(filename))
50
49
  end
51
-
50
+
52
51
  def errors
53
52
  @checks ||= []
54
53
  all_errors = @checks.collect {|check| check.errors}
55
54
  all_errors.flatten
56
55
  end
57
-
56
+
58
57
  private
59
-
58
+
60
59
  def parse(filename, content)
61
60
  begin
62
61
  Parser.new.parse(content, filename)
@@ -1,3 +1,3 @@
1
1
  module Roodi
2
- VERSION = '3.0.0'
2
+ VERSION = '3.0.1'
3
3
  end
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
5
5
 
6
6
  gem.name = "roodi"
7
7
  gem.summary = "Roodi stands for Ruby Object Oriented Design Inferometer"
8
- gem.description = "Roodi stands for Ruby Object Oriented Design Inferometer"
8
+ gem.description = "Roodi parses your Ruby code and warns you about design issues you have based on the checks that is has configured"
9
9
  gem.homepage = "http://github.com/roodi/roodi"
10
10
  gem.authors = ["Marty Andrews", "Peter Evjan"]
11
11
  gem.email = "peter.evjan@gmail.com"
@@ -1,3 +1,6 @@
1
1
  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
2
2
  require 'roodi'
3
3
  require 'rspec'
4
+ require 'coveralls'
5
+ Coveralls.wear!
6
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roodi
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marty Andrews
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-14 00:00:00.000000000 Z
12
+ date: 2013-08-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ruby_parser
@@ -25,7 +25,8 @@ dependencies:
25
25
  - - ~>
26
26
  - !ruby/object:Gem::Version
27
27
  version: 3.2.2
28
- description: Roodi stands for Ruby Object Oriented Design Inferometer
28
+ description: Roodi parses your Ruby code and warns you about design issues you have
29
+ based on the checks that is has configured
29
30
  email: peter.evjan@gmail.com
30
31
  executables:
31
32
  - roodi