roodi 2.2.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 07d949870658795c4a909c32faf4e50b37f29813
4
+ data.tar.gz: 54f229d5e6901aa1246d5e314ab63fa462acb923
5
+ SHA512:
6
+ metadata.gz: 94c41207f62016bd29d2eb1ada674d89772e9594cebd80bf96d750137048b0a9e16451dd54280f145e4a88019da2d9ecf6b56235d57ca4dec87ae1c54ac6ef8f
7
+ data.tar.gz: 6f31b01a3c5376860ad999fa8d0ff1de82847315f0d8257d19cd26b7c56ef024e725999737aebf9b541830b3fe5b5302a8b87412aaa150c5f22562fe6ddd742b
@@ -0,0 +1,3 @@
1
+ doc
2
+ pkg
3
+ Gemfile.lock
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - 2.0.0
7
+ - jruby-18mode # JRuby in 1.8 mode
8
+ - jruby-19mode # JRuby in 1.9 mode
9
+ - rbx-18mode
10
+ - rbx-19mode
11
+ - ree
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
- source :rubygems
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
5
  gem "rake"
6
- gem "rspec", "~> 1.3.2"
6
+ gem "rspec", "~> 2.14.1"
@@ -1,3 +1,13 @@
1
+ = 3.0.0
2
+
3
+ * Removed MissingForeignKeyIndexCheck, since it is specific to Rails/ActiveRecord and thus doesn't belong in Roodi
4
+ * A build is now running on Travis for the following Ruby versions: 1.8, 1.9, 2.0, JRuby 1.8 mode, JRuby 1.9 mode, Rubinius 1.8 mode, Rubinius 1.9 mode, Ruby Enterprise Edition
5
+ * Using ruby_parser 3.2.2
6
+ * Better check if OS is windows (#2 Martin Gotink)
7
+ * Accept 'next' in a rescue block (#1 Virgil Mihailovici)
8
+ * Rescue line count when there are no lines
9
+ * Pull down updates from https://github.com/zdennis/roodi that includes updates from https://github.com/hooroo/roodi and https://github.com/aselder/roodi re: pull request https://github.com/martinjandrews/roodi/pull/12 https://github.com/martinjandrews/roodi/pull/11
10
+
1
11
  = 2.0.1
2
12
 
3
13
  * Fixed a bug where roodi.yml was not being loaded. Patch supplied by Rob Mitchell.
@@ -1,56 +1,72 @@
1
- = roodi
1
+ # roodi
2
2
 
3
- * http://roodi.rubyforge.org
3
+ [![Build Status](https://travis-ci.org/roodi/roodi.png?branch=master)](https://travis-ci.org/roodi/roodi)
4
4
 
5
- == DESCRIPTION:
5
+ ## Description
6
6
 
7
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.
8
8
 
9
- == INSTALL:
9
+ ## Install
10
10
 
11
- * sudo gem install roodi
11
+ `$ sudo gem install roodi`
12
12
 
13
- == SYNOPSIS:
13
+ ## Synopsis
14
14
 
15
15
  To check one or more files using the default configuration that comes with Roodi, use:
16
- roodi [-config=file] [pattern ...]
17
16
 
18
- === EXAMPLE USAGE
17
+ `$ roodi [-config=file] [pattern ...]`
18
+
19
+ ## Example Usage
19
20
 
20
21
  Check all ruby files in a rails app:
21
- roodi "rails_app/**/*.rb"
22
+
23
+ `$ roodi "rails_app/**/*.rb"`
22
24
 
23
25
  Check one controller and one model file in a rails app:
24
- roodi app/controller/sample_controller.rb app/models/sample.rb
26
+
27
+ `$ roodi app/controller/sample_controller.rb app/models/sample.rb`
25
28
 
26
29
  Check one controller and all model files in a rails app:
27
- roodi app/controller/sample_controller.rb "app/models/*.rb"
30
+
31
+ `$ roodi app/controller/sample_controller.rb "app/models/*.rb"`
28
32
 
29
33
  Check all ruby files in a rails app with a custom configuration file:
30
- roodi -config=my_roodi_config.yml "rails_app/**/*.rb"
34
+
35
+ `$ roodi -config=my_roodi_config.yml "rails_app/**/*.rb"`
31
36
 
32
37
  If you're writing a check, it is useful to see the structure of a file the way that Roodi tokenizes it (via ruby_parser). Use:
33
- roodi-describe [filename]
34
38
 
35
- == CUSTOM CONFIGURATION
39
+ `$ roodi-describe [filename]`
40
+
41
+ ## Custom Configuration
36
42
 
37
43
  To change the set of checks included, or to change the default values of the checks, you can provide your own config file. The config file is a YAML file that lists the checks to be included. Each check can optionally include a hash of options that are passed to the check to configure it. For example, the default config file looks like this:
38
44
 
39
- AssignmentInConditionalCheck: { }
40
- CaseMissingElseCheck: { }
41
- ClassLineCountCheck: { line_count: 300 }
42
- ClassNameCheck: { pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/ }
43
- CyclomaticComplexityBlockCheck: { complexity: 4 }
44
- CyclomaticComplexityMethodCheck: { complexity: 8 }
45
- EmptyRescueBodyCheck: { }
46
- ForLoopCheck: { }
47
- MethodLineCountCheck: { line_count: 20 }
48
- MethodNameCheck: { pattern: !ruby/regexp /^[_a-z<>=\[\]|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ }
49
- ModuleLineCountCheck: { line_count: 300 }
50
- ModuleNameCheck: { pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/ }
51
- ParameterNumberCheck: { parameter_count: 5 }
52
-
53
- == SUPPORTED CHECKS:
45
+ AssignmentInConditionalCheck:
46
+ CaseMissingElseCheck:
47
+ ClassLineCountCheck:
48
+ line_count: 300
49
+ ClassNameCheck:
50
+ pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
51
+ ClassVariableCheck:
52
+ CyclomaticComplexityBlockCheck:
53
+ complexity: 4
54
+ CyclomaticComplexityMethodCheck:
55
+ complexity: 8
56
+ EmptyRescueBodyCheck:
57
+ ForLoopCheck:
58
+ MethodLineCountCheck:
59
+ line_count: 20
60
+ MethodNameCheck:
61
+ pattern: !ruby/regexp /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
62
+ ModuleLineCountCheck:
63
+ line_count: 300
64
+ ModuleNameCheck:
65
+ pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
66
+ ParameterNumberCheck:
67
+ parameter_count: 5
68
+
69
+ ## Supported Checks
54
70
 
55
71
  * AssignmentInConditionalCheck - Check for an assignment inside a conditional. It's probably a mistaken equality comparison.
56
72
  * CaseMissingElseCheck - Check that case statements have an else statement so that all cases are covered.
@@ -66,11 +82,11 @@ To change the set of checks included, or to change the default values of the che
66
82
  * ModuleNameCheck - Check that module names match convention.
67
83
  * ParameterNumberCheck - Check that the number of parameters on a method is below the threshold.
68
84
 
69
- == SUGGESTED CHECKS:
85
+ ## Suggested Checks
70
86
 
71
87
  * 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.
72
88
 
73
- == LICENSE:
89
+ ## License
74
90
 
75
91
  (The MIT License)
76
92
 
data/Rakefile CHANGED
@@ -1,10 +1,8 @@
1
1
  require 'rake'
2
- require 'spec/rake/spectask'
2
+ require 'rspec/core/rake_task'
3
3
  require 'bundler'
4
4
  require 'roodi'
5
5
 
6
- Bundler::GemHelper.install_tasks
7
-
8
6
  def roodi(ruby_files)
9
7
  roodi = Roodi::Core::Runner.new
10
8
  ruby_files.each { |file| roodi.check_file(file) }
@@ -13,9 +11,7 @@ def roodi(ruby_files)
13
11
  end
14
12
 
15
13
  desc "Run all specs"
16
- Spec::Rake::SpecTask.new('spec') do |t|
17
- t.spec_files = FileList['spec/**/*spec.rb']
18
- end
14
+ RSpec::Core::RakeTask.new(:spec)
19
15
 
20
16
  desc "Run Roodi against all source files"
21
17
  task :roodi do
@@ -23,4 +19,4 @@ task :roodi do
23
19
  roodi(Dir.glob(pattern))
24
20
  end
25
21
 
26
- task :default => :spec
22
+ task :default => [:spec, :roodi]
@@ -5,13 +5,13 @@ require 'roodi/checks/class_line_count_check'
5
5
  require 'roodi/checks/class_name_check'
6
6
  require 'roodi/checks/class_variable_check'
7
7
  require 'roodi/checks/control_coupling_check'
8
+ require 'roodi/checks/core_method_override_check'
8
9
  require 'roodi/checks/cyclomatic_complexity_block_check'
9
10
  require 'roodi/checks/cyclomatic_complexity_method_check'
10
11
  require 'roodi/checks/empty_rescue_body_check'
11
12
  require 'roodi/checks/for_loop_check'
12
13
  require 'roodi/checks/method_line_count_check'
13
14
  require 'roodi/checks/method_name_check'
14
- require 'roodi/checks/missing_foreign_key_index_check'
15
15
  require 'roodi/checks/module_line_count_check'
16
16
  require 'roodi/checks/module_name_check'
17
17
  require 'roodi/checks/npath_complexity_method_check'
@@ -3,7 +3,7 @@ require 'roodi/checks/check'
3
3
  module Roodi
4
4
  module Checks
5
5
  # TODO: Add summary
6
- #
6
+ #
7
7
  # TODO: Add detail
8
8
  class AbcMetricMethodCheck < Check
9
9
  # ASSIGNMENTS = [:attrasgn, :attrset, :dasgn_curr, :iasgn, :lasgn, :masgn]
@@ -11,18 +11,18 @@ module Roodi
11
11
  # BRANCHES = [:if, :else, :while, :until, :for, :rescue, :case, :when, :and, :or]
12
12
  BRANCHES = [:vcall, :call]
13
13
  # CONDITIONS = [:and, :or]
14
- CONDITIONS = [:==, :<=, :>=, :<, :>]
14
+ CONDITIONS = [:==, :"!=", :<=, :>=, :<, :>]
15
15
  # = *= /= %= += <<= >>= &= |= ^=
16
16
  OPERATORS = [:*, :/, :%, :+, :<<, :>>, :&, :|, :^]
17
17
  DEFAULT_SCORE = 10
18
-
18
+
19
19
  attr_accessor :score
20
20
 
21
21
  def initialize
22
22
  super()
23
23
  self.score = DEFAULT_SCORE
24
24
  end
25
-
25
+
26
26
  def interesting_nodes
27
27
  [:defn]
28
28
  end
@@ -35,7 +35,7 @@ module Roodi
35
35
  score = Math.sqrt(a*a + b*b + c*c)
36
36
  add_error "Method name \"#{method_name}\" has an ABC metric score of <#{a},#{b},#{c}> = #{score}. It should be #{@score} or less." unless score <= @score
37
37
  end
38
-
38
+
39
39
  private
40
40
 
41
41
  def count_assignments(node)
@@ -44,7 +44,7 @@ module Roodi
44
44
  node.children.each {|node| count += count_assignments(node)}
45
45
  count
46
46
  end
47
-
47
+
48
48
  def count_branches(node)
49
49
  count = 0
50
50
  count = count + 1 if branch?(node)
@@ -58,22 +58,22 @@ module Roodi
58
58
  node.children.each {|node| count += count_conditionals(node)}
59
59
  count
60
60
  end
61
-
61
+
62
62
  def assignment?(node)
63
63
  ASSIGNMENTS.include?(node.node_type)
64
64
  end
65
-
65
+
66
66
  def branch?(node)
67
67
  BRANCHES.include?(node.node_type) && !conditional?(node) && !operator?(node)
68
68
  end
69
-
69
+
70
70
  def conditional?(node)
71
- (:call == node.node_type) && CONDITIONS.include?(node[2])
71
+ (:call == node.node_type) && CONDITIONS.include?(node[2])
72
72
  end
73
-
73
+
74
74
  def operator?(node)
75
- (:call == node.node_type) && OPERATORS.include?(node[2])
76
- end
75
+ (:call == node.node_type) && OPERATORS.include?(node[2])
76
+ end
77
77
  end
78
78
  end
79
79
  end
@@ -0,0 +1,23 @@
1
+ require 'roodi/checks/check'
2
+
3
+ module Roodi
4
+ module Checks
5
+ # Checks a class to make sure it doesn't override core methods on Object.
6
+ #
7
+ # An example is when the 'class' method of a class is overriden. This causes code
8
+ # that tests the class of an object to fail.
9
+ class CoreMethodOverrideCheck < Check
10
+
11
+ def interesting_nodes
12
+ [:defn]
13
+ end
14
+
15
+ def evaluate_start(node)
16
+ [ :class ].each do |core_name|
17
+ add_error("Class overrides method '#{core_name}'.") if node[1] == core_name
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -7,7 +7,7 @@ module Roodi
7
7
  # When the body of a rescue block is empty, exceptions can get caught and swallowed without
8
8
  # any feedback to the user.
9
9
  class EmptyRescueBodyCheck < Check
10
- STATEMENT_NODES = [:fcall, :return, :attrasgn, :vcall, :nil, :call, :lasgn, :true, :false]
10
+ STATEMENT_NODES = [:fcall, :return, :attrasgn, :vcall, :nil, :call, :lasgn, :true, :false, :next]
11
11
 
12
12
  def interesting_nodes
13
13
  [:resbody]
@@ -3,7 +3,7 @@ require 'roodi/checks/check'
3
3
  module Roodi
4
4
  module Checks
5
5
  class LineCountCheck < Check
6
-
6
+
7
7
  attr_accessor :line_count
8
8
 
9
9
  def evaluate_start(node)
@@ -12,9 +12,17 @@ module Roodi
12
12
  end
13
13
 
14
14
  protected
15
-
15
+
16
16
  def count_lines(node)
17
- node.last.line - node.line - 1
17
+ node.last.respond_to?(:line) ? node.last.line - node.line : 0
18
+
19
+ rescue NoMethodError => e
20
+ #TODO: Add spec for this, nothing breaks when removing it.
21
+ if ENV['DEBUG'] =~ /true/i
22
+ STDERR.puts "!! line counting error #{e.message}\t #{node.inspect}"
23
+ STDERR.puts "!! Does the node have any lines?"
24
+ end
25
+ 0
18
26
  end
19
27
 
20
28
  end
@@ -25,7 +25,7 @@ module Roodi
25
25
  def evaluate_start(node)
26
26
  method_name = node[1]
27
27
  arguments = node[2]
28
- actual_parameter_count = arguments.inject(-1) { |count, each| count = count + (each.class == Symbol ? 1 : 0) }
28
+ actual_parameter_count = arguments.select {|arg| [Sexp, Symbol].include? arg.class}.count - 1
29
29
  add_error "Method name \"#{method_name}\" has #{actual_parameter_count} parameters. It should have #{@parameter_count} or less." unless actual_parameter_count <= @parameter_count
30
30
  end
31
31
 
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'ruby_parser'
3
+ require 'rbconfig'
3
4
 
4
5
  module Roodi
5
6
  module Core
@@ -14,7 +15,7 @@ module Roodi
14
15
 
15
16
  def silence_stream(stream)
16
17
  old_stream = stream.dup
17
- stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
18
+ stream.reopen(null_stream_output)
18
19
  stream.sync = true
19
20
  yield
20
21
  ensure
@@ -25,6 +26,23 @@ module Roodi
25
26
  @parser ||= RubyParser.new
26
27
  @parser.parse(content, filename)
27
28
  end
29
+
30
+ def null_stream_output
31
+ null_output_for_platform(RbConfig::CONFIG['host_os'])
32
+ end
33
+
34
+ def null_output_for_platform(host_os)
35
+ case host_os
36
+ when windows_host_os_matcher
37
+ 'NUL:'
38
+ else
39
+ '/dev/null'
40
+ end
41
+ end
42
+
43
+ def windows_host_os_matcher
44
+ /mingw|mswin32|cygwin/o
45
+ end
28
46
  end
29
47
  end
30
48
  end
@@ -31,11 +31,12 @@ module Roodi
31
31
  end
32
32
 
33
33
  def check_file(filename)
34
+ return unless File.exists?(filename)
34
35
  check(filename, File.read(filename))
35
36
  end
36
37
 
37
38
  def print(filename, content)
38
- node = parse(content, filename)
39
+ node = parse(filename, content)
39
40
  puts "Line: #{node.line}"
40
41
  pp node
41
42
  end
@@ -1,3 +1,3 @@
1
1
  module Roodi
2
- VERSION = '2.2.0'
2
+ VERSION = '3.0.0'
3
3
  end
@@ -6,13 +6,18 @@ Gem::Specification.new do |gem|
6
6
  gem.name = "roodi"
7
7
  gem.summary = "Roodi stands for Ruby Object Oriented Design Inferometer"
8
8
  gem.description = "Roodi stands for Ruby Object Oriented Design Inferometer"
9
- gem.homepage = "http://roodi.rubyforge.org"
10
- gem.authors = ["Marty Andrews"]
11
- gem.email = "marty@cogent.co"
9
+ gem.homepage = "http://github.com/roodi/roodi"
10
+ gem.authors = ["Marty Andrews", "Peter Evjan"]
11
+ gem.email = "peter.evjan@gmail.com"
12
12
  gem.files = Dir['lib/**/*.rb'] + Dir['bin/*'] + Dir['[A-Za-z]*'] + Dir['spec/**/*']
13
13
  gem.version = Roodi::VERSION.dup
14
14
  gem.platform = Gem::Platform::RUBY
15
- gem.add_runtime_dependency("ruby_parser", "~> 2.3.0")
15
+ gem.add_runtime_dependency("ruby_parser", "~> 3.2.2")
16
16
  gem.executables = ["roodi", "roodi-describe"]
17
+ gem.files = `git ls-files`.split($\)
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
20
+ gem.require_paths = ["lib"]
21
+ gem.license = 'MIT'
17
22
 
18
23
  end
data/roodi.yml CHANGED
@@ -1,25 +1,23 @@
1
1
  AssignmentInConditionalCheck:
2
2
  CaseMissingElseCheck:
3
- ClassLineCountCheck:
4
- line_count: 300
5
- ClassNameCheck:
3
+ ClassLineCountCheck:
4
+ line_count: 300
5
+ ClassNameCheck:
6
6
  pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
7
7
  ClassVariableCheck:
8
- CyclomaticComplexityBlockCheck:
8
+ CyclomaticComplexityBlockCheck:
9
9
  complexity: 4
10
- CyclomaticComplexityMethodCheck:
10
+ CyclomaticComplexityMethodCheck:
11
11
  complexity: 8
12
12
  EmptyRescueBodyCheck:
13
13
  ForLoopCheck:
14
- MethodLineCountCheck:
15
- line_count: 20
16
- MethodNameCheck:
17
- pattern: !ruby/regexp /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
18
- # MissingForeignKeyIndexCheck:
19
- ModuleLineCountCheck:
14
+ MethodLineCountCheck:
15
+ line_count: 20
16
+ MethodNameCheck:
17
+ pattern: !ruby/regexp /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
18
+ ModuleLineCountCheck:
20
19
  line_count: 300
21
- ModuleNameCheck:
20
+ ModuleNameCheck:
22
21
  pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
23
- ParameterNumberCheck:
22
+ ParameterNumberCheck:
24
23
  parameter_count: 5
25
-
@@ -0,0 +1,31 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Roodi::Checks::CoreMethodOverrideCheck do
4
+ before(:each) do
5
+ @roodi = Roodi::Core::Runner.new(Roodi::Checks::CoreMethodOverrideCheck.new)
6
+ end
7
+
8
+ it "should accept a class with a method" do
9
+ content = <<-END
10
+ class WellBehavedClass
11
+ def well_behaved_method
12
+ end
13
+ end
14
+ END
15
+ @roodi.check_content(content)
16
+ @roodi.errors.should be_empty
17
+ end
18
+
19
+ it "should reject a class which overrides the class method" do
20
+ content = <<-END
21
+ class BadClass
22
+ def class
23
+ end
24
+ end
25
+ END
26
+ @roodi.check_content(content)
27
+ errors = @roodi.errors
28
+ errors.should_not be_empty
29
+ errors[0].to_s.should eql("dummy-file.rb:2 - Class overrides method 'class'.")
30
+ end
31
+ end
@@ -137,4 +137,18 @@ describe Roodi::Checks::EmptyRescueBodyCheck do
137
137
  errors = @roodi.errors
138
138
  errors.should be_empty
139
139
  end
140
+
141
+ it "should accept a rescue block that has only a next statement" do
142
+ content = <<-END
143
+ begin
144
+ call_method
145
+ rescue Exception => e
146
+ next
147
+ end
148
+ END
149
+ @roodi.check_content(content)
150
+ errors = @roodi.errors
151
+ errors.should be_empty
152
+ end
153
+
140
154
  end
@@ -28,26 +28,4 @@ describe Roodi::Checks::NpathComplexityMethodCheck do
28
28
  END
29
29
  verify_content_complexity(content, 2)
30
30
  end
31
-
32
- it "should find nested if block" do
33
- pending "NPath Complexity implementation that can support 'else' blocks"
34
- content = <<-END
35
- def method_name
36
- if (value1)
37
- foo
38
- else
39
- bar
40
- end
41
- if (value2)
42
- bam
43
- else
44
- baz
45
- end
46
- if (value3)
47
- one
48
- end
49
- end
50
- END
51
- verify_content_complexity(content, 8)
52
- end
53
31
  end
@@ -1,3 +1,3 @@
1
1
  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
2
2
  require 'roodi'
3
- require 'spec'
3
+ require 'rspec'
metadata CHANGED
@@ -1,40 +1,49 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roodi
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
5
- prerelease:
4
+ version: 3.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Marty Andrews
8
+ - Peter Evjan
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-25 00:00:00.000000000 Z
12
+ date: 2013-08-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ruby_parser
16
16
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
17
  requirements:
19
18
  - - ~>
20
19
  - !ruby/object:Gem::Version
21
- version: 2.3.0
20
+ version: 3.2.2
22
21
  type: :runtime
23
22
  prerelease: false
24
23
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
24
  requirements:
27
25
  - - ~>
28
26
  - !ruby/object:Gem::Version
29
- version: 2.3.0
27
+ version: 3.2.2
30
28
  description: Roodi stands for Ruby Object Oriented Design Inferometer
31
- email: marty@cogent.co
29
+ email: peter.evjan@gmail.com
32
30
  executables:
33
31
  - roodi
34
32
  - roodi-describe
35
33
  extensions: []
36
34
  extra_rdoc_files: []
37
35
  files:
36
+ - .gitignore
37
+ - .travis.yml
38
+ - Gemfile
39
+ - History.txt
40
+ - Manifest.txt
41
+ - README.md
42
+ - Rakefile
43
+ - bin/roodi
44
+ - bin/roodi-describe
45
+ - lib/roodi.rb
46
+ - lib/roodi/checks.rb
38
47
  - lib/roodi/checks/abc_metric_method_check.rb
39
48
  - lib/roodi/checks/assignment_in_conditional_check.rb
40
49
  - lib/roodi/checks/case_missing_else_check.rb
@@ -43,6 +52,7 @@ files:
43
52
  - lib/roodi/checks/class_name_check.rb
44
53
  - lib/roodi/checks/class_variable_check.rb
45
54
  - lib/roodi/checks/control_coupling_check.rb
55
+ - lib/roodi/checks/core_method_override_check.rb
46
56
  - lib/roodi/checks/cyclomatic_complexity_block_check.rb
47
57
  - lib/roodi/checks/cyclomatic_complexity_check.rb
48
58
  - lib/roodi/checks/cyclomatic_complexity_method_check.rb
@@ -51,31 +61,20 @@ files:
51
61
  - lib/roodi/checks/line_count_check.rb
52
62
  - lib/roodi/checks/method_line_count_check.rb
53
63
  - lib/roodi/checks/method_name_check.rb
54
- - lib/roodi/checks/missing_foreign_key_index_check.rb
55
64
  - lib/roodi/checks/module_line_count_check.rb
56
65
  - lib/roodi/checks/module_name_check.rb
57
66
  - lib/roodi/checks/name_check.rb
58
67
  - lib/roodi/checks/npath_complexity_check.rb
59
68
  - lib/roodi/checks/npath_complexity_method_check.rb
60
69
  - lib/roodi/checks/parameter_number_check.rb
61
- - lib/roodi/checks.rb
70
+ - lib/roodi/core.rb
62
71
  - lib/roodi/core/checking_visitor.rb
63
72
  - lib/roodi/core/error.rb
64
73
  - lib/roodi/core/parser.rb
65
74
  - lib/roodi/core/runner.rb
66
75
  - lib/roodi/core/visitable_sexp.rb
67
- - lib/roodi/core.rb
68
76
  - lib/roodi/version.rb
69
- - lib/roodi.rb
70
77
  - lib/roodi_task.rb
71
- - bin/roodi
72
- - bin/roodi-describe
73
- - Gemfile
74
- - Gemfile.lock
75
- - History.txt
76
- - Manifest.txt
77
- - Rakefile
78
- - README.txt
79
78
  - roodi.gemspec
80
79
  - roodi.yml
81
80
  - spec/roodi/checks/abc_metric_method_check_spec.rb
@@ -85,13 +84,13 @@ files:
85
84
  - spec/roodi/checks/class_name_check_spec.rb
86
85
  - spec/roodi/checks/class_variable_check_spec.rb
87
86
  - spec/roodi/checks/control_coupling_check_spec.rb
87
+ - spec/roodi/checks/core_method_override_check_spec.rb
88
88
  - spec/roodi/checks/cyclomatic_complexity_block_check_spec.rb
89
89
  - spec/roodi/checks/cyclomatic_complexity_method_check_spec.rb
90
90
  - spec/roodi/checks/empty_rescue_body_check_spec.rb
91
91
  - spec/roodi/checks/for_loop_check_spec.rb
92
92
  - spec/roodi/checks/method_line_count_check_spec.rb
93
93
  - spec/roodi/checks/method_name_check_spec.rb
94
- - spec/roodi/checks/missing_foreign_key_index_check_spec.rb
95
94
  - spec/roodi/checks/module_line_count_check_spec.rb
96
95
  - spec/roodi/checks/module_name_check_spec.rb
97
96
  - spec/roodi/checks/npath_complexity_method_check_spec.rb
@@ -99,34 +98,49 @@ files:
99
98
  - spec/roodi/core/runner_spec.rb
100
99
  - spec/roodi/roodi.yml
101
100
  - spec/spec_helper.rb
102
- homepage: http://roodi.rubyforge.org
103
- licenses: []
101
+ homepage: http://github.com/roodi/roodi
102
+ licenses:
103
+ - MIT
104
+ metadata: {}
104
105
  post_install_message:
105
106
  rdoc_options: []
106
107
  require_paths:
107
108
  - lib
108
109
  required_ruby_version: !ruby/object:Gem::Requirement
109
- none: false
110
110
  requirements:
111
- - - ! '>='
111
+ - - '>='
112
112
  - !ruby/object:Gem::Version
113
113
  version: '0'
114
- segments:
115
- - 0
116
- hash: -2141010416866692951
117
114
  required_rubygems_version: !ruby/object:Gem::Requirement
118
- none: false
119
115
  requirements:
120
- - - ! '>='
116
+ - - '>='
121
117
  - !ruby/object:Gem::Version
122
118
  version: '0'
123
- segments:
124
- - 0
125
- hash: -2141010416866692951
126
119
  requirements: []
127
120
  rubyforge_project:
128
- rubygems_version: 1.8.24
121
+ rubygems_version: 2.0.3
129
122
  signing_key:
130
- specification_version: 3
123
+ specification_version: 4
131
124
  summary: Roodi stands for Ruby Object Oriented Design Inferometer
132
- test_files: []
125
+ test_files:
126
+ - spec/roodi/checks/abc_metric_method_check_spec.rb
127
+ - spec/roodi/checks/assignment_in_conditional_check_spec.rb
128
+ - spec/roodi/checks/case_missing_else_check_spec.rb
129
+ - spec/roodi/checks/class_line_count_check_spec.rb
130
+ - spec/roodi/checks/class_name_check_spec.rb
131
+ - spec/roodi/checks/class_variable_check_spec.rb
132
+ - spec/roodi/checks/control_coupling_check_spec.rb
133
+ - spec/roodi/checks/core_method_override_check_spec.rb
134
+ - spec/roodi/checks/cyclomatic_complexity_block_check_spec.rb
135
+ - spec/roodi/checks/cyclomatic_complexity_method_check_spec.rb
136
+ - spec/roodi/checks/empty_rescue_body_check_spec.rb
137
+ - spec/roodi/checks/for_loop_check_spec.rb
138
+ - spec/roodi/checks/method_line_count_check_spec.rb
139
+ - spec/roodi/checks/method_name_check_spec.rb
140
+ - spec/roodi/checks/module_line_count_check_spec.rb
141
+ - spec/roodi/checks/module_name_check_spec.rb
142
+ - spec/roodi/checks/npath_complexity_method_check_spec.rb
143
+ - spec/roodi/checks/parameter_number_check_spec.rb
144
+ - spec/roodi/core/runner_spec.rb
145
+ - spec/roodi/roodi.yml
146
+ - spec/spec_helper.rb
@@ -1,22 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- roodi (2.2.0)
5
- ruby_parser (~> 2.3.0)
6
-
7
- GEM
8
- remote: http://rubygems.org/
9
- specs:
10
- rake (10.0.3)
11
- rspec (1.3.2)
12
- ruby_parser (2.3.0)
13
- sexp_processor (~> 3.0)
14
- sexp_processor (3.2.0)
15
-
16
- PLATFORMS
17
- ruby
18
-
19
- DEPENDENCIES
20
- rake
21
- roodi!
22
- rspec (~> 1.3.2)
@@ -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,33 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
-
3
- describe Roodi::Checks::MissingForeignKeyIndexCheck do
4
- before(:each) do
5
- @roodi = Roodi::Core::Runner.new(Roodi::Checks::MissingForeignKeyIndexCheck.make)
6
- end
7
-
8
- it "should warn about a missing foreign key" do
9
- content = <<-END
10
- ActiveRecord::Schema.define(:version => 20091215233604) do
11
- create_table "projects", :force => true do |t|
12
- t.string "name"
13
- end
14
-
15
- create_table "revisions", :force => true do |t|
16
- t.integer "project_id"
17
- t.string "key"
18
- end
19
-
20
- add_index "revisions", ["project_id"], :name => "index_revisions_on_project_id"
21
-
22
- create_table "source_files", :force => true do |t|
23
- t.integer "revision_id"
24
- t.string "filename"
25
- end
26
- end
27
- END
28
- @roodi.check_content(content, "schema.rb")
29
- errors = @roodi.errors
30
- errors.should_not be_empty
31
- errors[0].to_s.should eql("schema.rb:1 - Table 'source_files' is missing an index on the foreign key 'revision_id'")
32
- end
33
- end