excellent 1.5.4 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/History.txt +6 -0
  2. data/README.rdoc +2 -2
  3. data/bin/excellent +32 -14
  4. data/lib/simplabs/excellent/checks/abc_metric_method_check.rb +2 -2
  5. data/lib/simplabs/excellent/checks/assignment_in_conditional_check.rb +2 -2
  6. data/lib/simplabs/excellent/checks/base.rb +9 -7
  7. data/lib/simplabs/excellent/checks/case_missing_else_check.rb +2 -2
  8. data/lib/simplabs/excellent/checks/class_line_count_check.rb +1 -1
  9. data/lib/simplabs/excellent/checks/class_name_check.rb +1 -1
  10. data/lib/simplabs/excellent/checks/control_coupling_check.rb +1 -1
  11. data/lib/simplabs/excellent/checks/cyclomatic_complexity_block_check.rb +1 -1
  12. data/lib/simplabs/excellent/checks/cyclomatic_complexity_check.rb +3 -3
  13. data/lib/simplabs/excellent/checks/cyclomatic_complexity_method_check.rb +1 -1
  14. data/lib/simplabs/excellent/checks/empty_rescue_body_check.rb +1 -1
  15. data/lib/simplabs/excellent/checks/flog_block_check.rb +1 -1
  16. data/lib/simplabs/excellent/checks/flog_check.rb +3 -3
  17. data/lib/simplabs/excellent/checks/flog_class_check.rb +1 -1
  18. data/lib/simplabs/excellent/checks/flog_method_check.rb +1 -1
  19. data/lib/simplabs/excellent/checks/for_loop_check.rb +2 -2
  20. data/lib/simplabs/excellent/checks/global_variable_check.rb +2 -2
  21. data/lib/simplabs/excellent/checks/line_count_check.rb +3 -3
  22. data/lib/simplabs/excellent/checks/method_line_count_check.rb +1 -1
  23. data/lib/simplabs/excellent/checks/method_name_check.rb +1 -1
  24. data/lib/simplabs/excellent/checks/module_line_count_check.rb +1 -1
  25. data/lib/simplabs/excellent/checks/module_name_check.rb +1 -1
  26. data/lib/simplabs/excellent/checks/name_check.rb +3 -3
  27. data/lib/simplabs/excellent/checks/nested_iterators_check.rb +2 -2
  28. data/lib/simplabs/excellent/checks/parameter_number_check.rb +2 -2
  29. data/lib/simplabs/excellent/checks/rails/attr_accessible_check.rb +1 -1
  30. data/lib/simplabs/excellent/checks/rails/attr_protected_check.rb +1 -1
  31. data/lib/simplabs/excellent/checks/rails/custom_initialize_method_check.rb +1 -1
  32. data/lib/simplabs/excellent/checks/rails/instance_var_in_partial_check.rb +2 -2
  33. data/lib/simplabs/excellent/checks/rails/params_hash_in_view_check.rb +3 -3
  34. data/lib/simplabs/excellent/checks/rails/session_hash_in_view_check.rb +3 -3
  35. data/lib/simplabs/excellent/checks/rails/validations_check.rb +1 -1
  36. data/lib/simplabs/excellent/checks/singleton_variable_check.rb +1 -1
  37. data/lib/simplabs/excellent/formatters/html.rb +103 -7
  38. data/lib/simplabs/excellent/parsing/call_context.rb +11 -1
  39. data/lib/simplabs/excellent/parsing/code_processor.rb +15 -13
  40. data/lib/simplabs/excellent/parsing/constant_context.rb +20 -0
  41. data/lib/simplabs/excellent/parsing/cvar_context.rb +1 -1
  42. data/lib/simplabs/excellent/parsing/gasgn_context.rb +21 -0
  43. data/lib/simplabs/excellent/parsing/ivar_context.rb +1 -1
  44. data/lib/simplabs/excellent/parsing/method_context.rb +1 -1
  45. data/lib/simplabs/excellent/parsing/parser.rb +0 -1
  46. data/lib/simplabs/excellent/parsing/sexp_context.rb +10 -1
  47. data/lib/simplabs/excellent/parsing/singleton_method_context.rb +1 -1
  48. data/lib/simplabs/excellent/rake/excellent_task.rb +1 -1
  49. data/spec/checks/rails/validations_check_spec.rb +1 -1
  50. metadata +44 -57
@@ -1,3 +1,9 @@
1
+ =======
2
+ = 1.5.5
3
+
4
+ * better option parsing in the executable, (thanks trans, http://github.com/trans)
5
+ * added line count parser (not yet used), (thanks trans, http://github.com/trans)
6
+
1
7
  = 1.5.4
2
8
 
3
9
  * fixed handling of parser errors
@@ -46,7 +46,7 @@ To analyse all the models in your Rails application, just do
46
46
  in your <tt>RAILS_ROOT</tt>. You can also invoke analysation through the Simplabs::Excellent::Runner class. Excellent can also produce HTML output. To
47
47
  get a formatted HTML report, just specify <tt>html:<filename></tt>:
48
48
 
49
- excellent html:out.html app/models
49
+ excellent -o out.html app/models
50
50
 
51
51
  You can also use Excellent in a Rake task:
52
52
 
@@ -67,6 +67,6 @@ If you want to contribute, just fork the repo. Also I would appretiate suggestio
67
67
 
68
68
  == Author
69
69
 
70
- Copyright (c) 2008-2009 Marco Otte-Witte (http://simplabs.com), released under the MIT license.
70
+ Copyright (c) 2008-2010 Marco Otte-Witte (http://simplabs.com), released under the MIT license.
71
71
 
72
72
  Excellent was inspired by roodi (http://github.com/martinjandrews/roodi), reek (http://github.com/kevinrutherford/reek) and flog (http://github.com/seattlerb/flog).
@@ -1,31 +1,49 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
4
-
5
3
  require 'simplabs/excellent'
6
4
  require 'pathname'
5
+ require 'optparse'
7
6
 
8
- excellent = Simplabs::Excellent::Runner.new
7
+ options = {}
9
8
 
10
- if ARGV.first =~ /html:[^\s]+/
11
- begin
12
- output = File.open(ARGV.first.sub(/html:/, ''), 'w+')
13
- formatter = Simplabs::Excellent::Formatters::Html.new(output)
14
- ARGV.shift
15
- rescue
9
+ optparse = OptionParser.new do |opt|
10
+ opt.banner = 'Usage: excellent [OPTIONS] <PATH1> [<PATH2> ...]'
11
+ opt.on('--output', '-o [FILE]', 'Write HTML output to [FILE].') do |target|
12
+ options[:output] = target
13
+ end
14
+ opt.on_tail('--help', '-h', 'Help') do
15
+ puts optparse
16
+ exit
16
17
  end
17
- else
18
- formatter = Simplabs::Excellent::Formatters::Text.new
19
18
  end
20
19
 
21
- if ARGV.empty?
20
+ optparse.parse!
21
+
22
+ target = options[:output]
23
+ paths = ARGV.dup
24
+
25
+ if paths.empty?
22
26
  puts "\n You must specify one or more directories to analyse, e.g.:\n"
23
- puts "\n excellent app/\n\n"
27
+ puts "\n excellent lib/\n\n"
24
28
  exit 1
25
29
  end
26
30
 
31
+ if target
32
+ begin
33
+ fileio = File.open(target, 'w+')
34
+ formatter = Simplabs::Excellent::Formatters::Html.new(fileio)
35
+ rescue Errno::ENOENT
36
+ puts "\n #{target} cannot be opened for writing. Specify a file name like so:\n"
37
+ puts "\n excellent -o excellent.html lib/\n\n"
38
+ end
39
+ else
40
+ formatter = Simplabs::Excellent::Formatters::Text.new
41
+ end
42
+
43
+ excellent = Simplabs::Excellent::Runner.new
44
+
27
45
  begin
28
- excellent.check_paths(ARGV, formatter)
46
+ excellent.check_paths(paths, formatter)
29
47
  rescue ArgumentError
30
48
  puts "\n** Excellent cannot find the paths specified!\n\n"
31
49
  exit 1
@@ -24,8 +24,8 @@ module Simplabs
24
24
 
25
25
  def initialize(options = {}) #:nodoc:
26
26
  super()
27
- @threshold = options[:threshold] || DEFAULT_THRESHOLD
28
- @interesting_nodes = [:defn, :defs]
27
+ @threshold = options[:threshold] || DEFAULT_THRESHOLD
28
+ @interesting_contexts = [Parsing::MethodContext, Parsing::SingletonMethodContext]
29
29
  end
30
30
 
31
31
  def evaluate(context) #:nodoc:
@@ -22,8 +22,8 @@ module Simplabs
22
22
 
23
23
  def initialize(options = {}) #:nodoc:
24
24
  super()
25
- @interesting_nodes = [:if, :while, :until]
26
- @interesting_files = [/\.rb$/, /\.erb$/]
25
+ @interesting_contexts = [Parsing::IfContext, Parsing::WhileContext, Parsing::UntilContext]
26
+ @interesting_files = [/\.rb$/, /\.erb$/]
27
27
  end
28
28
 
29
29
  def evaluate(context) #:nodoc:
@@ -6,15 +6,16 @@ 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
+ # This is the base class for all code checks. All checks must specify +interesting_contexts+. When one of these contexts is processed by Excellent, it
10
+ # will invoke the +evaluate_context+ method of all checks that specify the context as one if their +interesting_contexts+.
11
11
  class Base
12
12
 
13
13
  attr_reader :warnings
14
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
15
+ # An array of contexts that are interesting for the check. These contexts are based on symbols as returned by RubyParser (see
16
+ # http://parsetree.rubyforge.org/ruby_parser/) and add some additional data,
17
+ # e.g. <tt>Ifcontext</tt> or <tt>MethodContext</tt>
18
+ attr_reader :interesting_contexts
18
19
 
19
20
  # An array of regular expressions for file names that are interesting for the check. These will usually be path extensions rather than longer
20
21
  # patterns (e.g. *.rb as well as *.erb files or *.rb files only).
@@ -27,12 +28,13 @@ module Simplabs
27
28
  @interesting_files = [/\.rb$/]
28
29
  end
29
30
 
30
- # 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).
31
+ # This method is called whenever Excellent processes a context that the check specified as one of the contexts it is interested in (see
32
+ # interesting_contexts).
31
33
  #
32
34
  # ==== Parameters
33
35
  #
34
36
  # * <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).
35
- def evaluate_node(context)
37
+ def evaluate_context(context)
36
38
  evaluate(context)
37
39
  end
38
40
 
@@ -17,8 +17,8 @@ module Simplabs
17
17
 
18
18
  def initialize #:nodoc:
19
19
  super
20
- @interesting_nodes = [:case]
21
- @interesting_files = [/\.rb$/, /\.erb$/]
20
+ @interesting_contexts = [Parsing::CaseContext]
21
+ @interesting_files = [/\.rb$/, /\.erb$/]
22
22
  end
23
23
 
24
24
  def evaluate(context) #:nodoc:
@@ -18,7 +18,7 @@ module Simplabs
18
18
 
19
19
  def initialize(options = {}) #:nodoc:
20
20
  threshold = options[:threshold] || DEFAULT_THRESHOLD
21
- super([:class], threshold)
21
+ super([Parsing::ClassContext], threshold)
22
22
  end
23
23
 
24
24
  protected
@@ -20,7 +20,7 @@ module Simplabs
20
20
 
21
21
  def initialize(options = {}) #:nodoc:
22
22
  pattern = options[:pattern] || DEFAULT_PATTERN
23
- super([:class], pattern)
23
+ super([Parsing::ClassContext], pattern)
24
24
  end
25
25
 
26
26
  protected
@@ -17,7 +17,7 @@ module Simplabs
17
17
 
18
18
  def initialize #:nodoc:
19
19
  super
20
- @interesting_nodes = [:if, :case]
20
+ @interesting_contexts = [Parsing::IfContext, Parsing::CaseContext]
21
21
  end
22
22
 
23
23
  def evaluate(context) #:nodoc:
@@ -30,7 +30,7 @@ module Simplabs
30
30
 
31
31
  def initialize(options = {}) #:nodoc:
32
32
  threshold = options[:threshold] || DEFAULT_THRESHOLD
33
- super([:iter], threshold)
33
+ super([Parsing::BlockContext], threshold)
34
34
  end
35
35
 
36
36
  def evaluate(context) #:nodoc:
@@ -8,10 +8,10 @@ module Simplabs
8
8
 
9
9
  class CyclomaticComplexityCheck < Base #:nodoc:
10
10
 
11
- def initialize(interesting_nodes, threshold)
11
+ def initialize(interesting_contexts, threshold)
12
12
  super()
13
- @interesting_nodes = interesting_nodes
14
- @threshold = threshold
13
+ @interesting_contexts = interesting_contexts
14
+ @threshold = threshold
15
15
  end
16
16
 
17
17
  end
@@ -30,7 +30,7 @@ module Simplabs
30
30
 
31
31
  def initialize(options = {}) #:nodoc:
32
32
  threshold = options[:threshold] || DEFAULT_THRESHOLD
33
- super([:defn, :defs], threshold)
33
+ super([Parsing::MethodContext, Parsing::SingletonMethodContext], threshold)
34
34
  end
35
35
 
36
36
  def evaluate(context) #:nodoc:
@@ -15,7 +15,7 @@ module Simplabs
15
15
 
16
16
  def initialize #:nodoc:
17
17
  super
18
- @interesting_nodes = [:resbody]
18
+ @interesting_contexts = [Parsing::ResbodyContext]
19
19
  end
20
20
 
21
21
  def evaluate(context) #:nodoc:
@@ -22,7 +22,7 @@ module Simplabs
22
22
 
23
23
  def initialize(options = {}) #:nodoc:
24
24
  threshold = options[:threshold] || DEFAULT_THRESHOLD
25
- super([:iter], threshold)
25
+ super([Parsing::BlockContext], threshold)
26
26
  end
27
27
 
28
28
  protected
@@ -8,10 +8,10 @@ module Simplabs
8
8
 
9
9
  class FlogCheck < Base #:nodoc:
10
10
 
11
- def initialize(interesting_nodes, threshold)
11
+ def initialize(interesting_contexts, threshold)
12
12
  super()
13
- @interesting_nodes = interesting_nodes
14
- @threshold = threshold
13
+ @interesting_contexts = interesting_contexts
14
+ @threshold = threshold
15
15
  end
16
16
 
17
17
  def evaluate(context)
@@ -22,7 +22,7 @@ module Simplabs
22
22
 
23
23
  def initialize(options = {}) #:nodoc:
24
24
  threshold = options[:threshold] || DEFAULT_THRESHOLD
25
- super([:class], threshold)
25
+ super([Parsing::ClassContext], threshold)
26
26
  end
27
27
 
28
28
  protected
@@ -22,7 +22,7 @@ module Simplabs
22
22
 
23
23
  def initialize(options = {}) #:nodoc:
24
24
  threshold = options[:threshold] || DEFAULT_THRESHOLD
25
- super([:defn, :defs], threshold)
25
+ super([Parsing::MethodContext, Parsing::SingletonMethodContext], threshold)
26
26
  end
27
27
 
28
28
  protected
@@ -25,8 +25,8 @@ module Simplabs
25
25
 
26
26
  def initialize #:nodoc:
27
27
  super
28
- @interesting_nodes = [:for]
29
- @interesting_files = [/\.rb$/, /\.erb$/]
28
+ @interesting_contexts = [Parsing::ForLoopContext]
29
+ @interesting_files = [/\.rb$/, /\.erb$/]
30
30
  end
31
31
 
32
32
  def evaluate(context) #:nodoc:
@@ -16,8 +16,8 @@ module Simplabs
16
16
 
17
17
  def initialize #:nodoc:
18
18
  super
19
- @interesting_nodes = [:gvar, :gasgn]
20
- @interesting_files = [/\.rb$/, /\.erb$/]
19
+ @interesting_contexts = [Parsing::GvarContext, Parsing::GasgnContext]
20
+ @interesting_files = [/\.rb$/, /\.erb$/]
21
21
  end
22
22
 
23
23
  def evaluate(context) #:nodoc:
@@ -8,10 +8,10 @@ module Simplabs
8
8
 
9
9
  class LineCountCheck < Base #:nodoc:
10
10
 
11
- def initialize(interesting_nodes, threshold)
11
+ def initialize(interesting_contexts, threshold)
12
12
  super()
13
- @interesting_nodes = interesting_nodes
14
- @threshold = threshold
13
+ @interesting_contexts = interesting_contexts
14
+ @threshold = threshold
15
15
  end
16
16
 
17
17
  def evaluate(context)
@@ -18,7 +18,7 @@ module Simplabs
18
18
 
19
19
  def initialize(options = {}) #:nodoc:
20
20
  threshold = options[:threshold] || DEFAULT_THRESHOLD
21
- super([:defn], threshold)
21
+ super([Parsing::MethodContext], threshold)
22
22
  end
23
23
 
24
24
  protected
@@ -20,7 +20,7 @@ module Simplabs
20
20
 
21
21
  def initialize(options = {}) #:nodoc:
22
22
  pattern = options['pattern'] || DEFAULT_PATTERN
23
- super([:defn, :defs], pattern)
23
+ super([Parsing::MethodContext, Parsing::SingletonMethodContext], pattern)
24
24
  end
25
25
 
26
26
  protected
@@ -18,7 +18,7 @@ module Simplabs
18
18
 
19
19
  def initialize(options = {}) #:nodoc:
20
20
  threshold = options[:threshold] || DEFAULT_THRESHOLD
21
- super([:module], threshold)
21
+ super([Parsing::ModuleContext], threshold)
22
22
  end
23
23
 
24
24
  protected
@@ -20,7 +20,7 @@ module Simplabs
20
20
 
21
21
  def initialize(options = {}) #:nodoc:
22
22
  pattern = options['pattern'] || DEFAULT_PATTERN
23
- super([:module], pattern)
23
+ super([Parsing::ModuleContext], pattern)
24
24
  end
25
25
 
26
26
  protected
@@ -8,10 +8,10 @@ module Simplabs
8
8
 
9
9
  class NameCheck < Base #:nodoc:
10
10
 
11
- def initialize(interesting_nodes, pattern)
11
+ def initialize(interesting_contexts, pattern)
12
12
  super()
13
- @interesting_nodes = interesting_nodes
14
- @pattern = pattern
13
+ @interesting_contexts = interesting_contexts
14
+ @pattern = pattern
15
15
  end
16
16
 
17
17
  def evaluate(context)
@@ -15,8 +15,8 @@ module Simplabs
15
15
 
16
16
  def initialize #:nodoc:
17
17
  super
18
- @interesting_nodes = [:iter]
19
- @interesting_files = [/\.rb$/, /\.erb$/]
18
+ @interesting_contexts = [Parsing::BlockContext]
19
+ @interesting_files = [/\.rb$/, /\.erb$/]
20
20
  end
21
21
 
22
22
  def evaluate(context) #:nodoc:
@@ -19,8 +19,8 @@ module Simplabs
19
19
 
20
20
  def initialize(options = {}) #:nodoc:
21
21
  super()
22
- @threshold = options[:threshold] || DEFAULT_THRESHOLD
23
- @interesting_nodes = [:defn, :iter, :defs]
22
+ @threshold = options[:threshold] || DEFAULT_THRESHOLD
23
+ @interesting_contexts = [Parsing::MethodContext, Parsing::SingletonMethodContext, Parsing::BlockContext]
24
24
  end
25
25
 
26
26
  def evaluate(context) #:nodoc:
@@ -20,7 +20,7 @@ module Simplabs
20
20
 
21
21
  def initialize #:nodoc:
22
22
  super
23
- @interesting_nodes = [:class]
23
+ @interesting_contexts = [Parsing::ClassContext]
24
24
  end
25
25
 
26
26
  def evaluate(context) #:nodoc:
@@ -21,7 +21,7 @@ module Simplabs
21
21
 
22
22
  def initialize #:nodoc:
23
23
  super
24
- @interesting_nodes = [:class]
24
+ @interesting_contexts = [Parsing::ClassContext]
25
25
  end
26
26
 
27
27
  def evaluate(context) #:nodoc:
@@ -19,7 +19,7 @@ module Simplabs
19
19
 
20
20
  def initialize #:nodoc:
21
21
  super
22
- @interesting_nodes = [:class]
22
+ @interesting_contexts = [Parsing::ClassContext]
23
23
  end
24
24
 
25
25
  def evaluate(context) #:nodoc:
@@ -18,12 +18,12 @@ module Simplabs
18
18
 
19
19
  def initialize #:nodoc:
20
20
  super
21
- @interesting_nodes = [:ivar]
21
+ @interesting_contexts = [Parsing::IvarContext]
22
22
  @interesting_files = [/^_.*\.erb$/]
23
23
  end
24
24
 
25
25
  def evaluate(context) #:nodoc:
26
- add_warning(context, 'Instance variable {{variable}} used in partial.', { :variable => context.full_name })
26
+ add_warning(context, 'Instance variable {{variable}} used in partial.', { :variable => context.full_name }, -1)
27
27
  end
28
28
 
29
29
  end
@@ -19,12 +19,12 @@ module Simplabs
19
19
 
20
20
  def initialize #:nodoc:
21
21
  super
22
- @interesting_nodes = [:call]
23
- @interesting_files = [/^.*\.(erb|rhtml)$/]
22
+ @interesting_contexts = [Parsing::CallContext]
23
+ @interesting_files = [/^.*\.(erb|rhtml)$/]
24
24
  end
25
25
 
26
26
  def evaluate(context) #:nodoc:
27
- add_warning(context, 'Params hash used in view.') if (context.full_name == 'params')
27
+ add_warning(context, 'Params hash used in view.', {}, -1) if (context.full_name == 'params')
28
28
  end
29
29
 
30
30
  end
@@ -19,12 +19,12 @@ module Simplabs
19
19
 
20
20
  def initialize #:nodoc:
21
21
  super
22
- @interesting_nodes = [:call]
23
- @interesting_files = [/^.*\.(erb|rhtml)$/]
22
+ @interesting_contexts = [Parsing::CallContext]
23
+ @interesting_files = [/^.*\.(erb|rhtml|haml)$/]
24
24
  end
25
25
 
26
26
  def evaluate(context) #:nodoc:
27
- add_warning(context, 'Session hash used in view.') if (context.full_name == 'session')
27
+ add_warning(context, 'Session hash used in view.', {}, -1) if (context.full_name == 'session')
28
28
  end
29
29
 
30
30
  end
@@ -18,7 +18,7 @@ module Simplabs
18
18
 
19
19
  def initialize #:nodoc:
20
20
  super
21
- @interesting_nodes = [:class]
21
+ @interesting_contexts = [Parsing::ClassContext]
22
22
  end
23
23
 
24
24
  def evaluate(context) #:nodoc:
@@ -16,7 +16,7 @@ module Simplabs
16
16
 
17
17
  def initialize #:nodoc:
18
18
  super
19
- @interesting_nodes = [:cvar]
19
+ @interesting_contexts = [Parsing::CvarContext]
20
20
  @interesting_files = [/\.rb$/, /\.erb$/]
21
21
  end
22
22
 
@@ -1,4 +1,5 @@
1
1
  require 'simplabs/excellent/formatters/base'
2
+ require 'rubygems'
2
3
 
3
4
  module Simplabs
4
5
 
@@ -71,14 +72,11 @@ module Simplabs
71
72
  }
72
73
 
73
74
  dd {
74
- margin: 5px 0px 5px 20px;
75
- }
76
-
77
- dd.warning {
75
+ margin: 5px 0px 5px 20px;
78
76
  background: #faf834;
79
77
  }
80
78
 
81
- dd.warning span.lineNumber {
79
+ dd span.lineNumber {
82
80
  background: #ccc;
83
81
  font-weight: bold;
84
82
  padding: 3px;
@@ -86,7 +84,7 @@ module Simplabs
86
84
  margin: 0 10px 0 0;
87
85
  }
88
86
 
89
- dd.warning span.number {
87
+ dd span.number {
90
88
  width: 30px;
91
89
  text-align: right;
92
90
  display: inline-block;
@@ -109,6 +107,102 @@ module Simplabs
109
107
  color: #fff;
110
108
  background-color: #222;
111
109
  }
110
+
111
+ .af { color:#00C }
112
+ .an { color:#007 }
113
+ .at { color:#f08 }
114
+ .av { color:#700 }
115
+ .aw { color:#C00 }
116
+ .bi { color:#509; font-weight:bold }
117
+ .c { color:#888; }
118
+
119
+ .ch { color:#04D }
120
+ .ch .k { color:#04D }
121
+ .ch .dl { color:#039 }
122
+
123
+ .cl { color:#B06; font-weight:bold }
124
+ .co { color:#036; font-weight:bold }
125
+ .cr { color:#0A0 }
126
+ .cv { color:#369 }
127
+ .df { color:#099; font-weight:bold }
128
+ .di { color:#088; font-weight:bold }
129
+ .dl { color:black }
130
+ .do { color:#970 }
131
+ .dt { color:#34b }
132
+ .ds { color:#D42; font-weight:bold }
133
+ .e { color:#666; font-weight:bold }
134
+ .en { color:#800; font-weight:bold }
135
+ .er { color:#F00; background-color:#FAA }
136
+ .ex { color:#F00; font-weight:bold }
137
+ .fl { color:#60E; font-weight:bold }
138
+ .fu { color:#06B; font-weight:bold }
139
+ .gv { color:#d70; font-weight:bold }
140
+ .hx { color:#058; font-weight:bold }
141
+ .i { color:#00D; font-weight:bold }
142
+ .ic { color:#B44; font-weight:bold }
143
+
144
+ .il { background: #eee; color: black }
145
+ .il .il { background: #ddd }
146
+ .il .il .il { background: #ccc }
147
+ .il .idl { font-weight: bold; color: #777 }
148
+
149
+ .im { color:#f00; }
150
+ .in { color:#B2B; font-weight:bold }
151
+ .iv { color:#33B }
152
+ .la { color:#970; font-weight:bold }
153
+ .lv { color:#963 }
154
+ .oc { color:#40E; font-weight:bold }
155
+ .of { color:#000; font-weight:bold }
156
+ .op { }
157
+ .pc { color:#038; font-weight:bold }
158
+ .pd { color:#369; font-weight:bold }
159
+ .pp { color:#579; }
160
+ .ps { color:#00C; font-weight: bold; }
161
+ .pt { color:#349; font-weight:bold }
162
+ .r, .kw { color:#080; font-weight:bold }
163
+
164
+ .ke { color: #808; }
165
+ .ke .dl { color: #606; }
166
+ .ke .ch { color: #80f; }
167
+ .vl { color: #088; }
168
+
169
+ .rx { background-color:#fff0ff }
170
+ .rx .k { color:#808 }
171
+ .rx .dl { color:#404 }
172
+ .rx .mod { color:#C2C }
173
+ .rx .fu { color:#404; font-weight: bold }
174
+
175
+ .s { background-color:#fff0f0; color: #D20; }
176
+ .s .s { background-color:#ffe0e0 }
177
+ .s .s .s { background-color:#ffd0d0 }
178
+ .s .k { }
179
+ .s .ch { color: #b0b; }
180
+ .s .dl { color: #710; }
181
+
182
+ .sh { background-color:#f0fff0; color:#2B2 }
183
+ .sh .k { }
184
+ .sh .dl { color:#161 }
185
+
186
+ .sy { color:#A60 }
187
+ .sy .k { color:#A60 }
188
+ .sy .dl { color:#630 }
189
+
190
+ .ta { color:#070 }
191
+ .tf { color:#070; font-weight:bold }
192
+ .ts { color:#D70; font-weight:bold }
193
+ .ty { color:#339; font-weight:bold }
194
+ .v { color:#036 }
195
+ .xt { color:#444 }
196
+
197
+ .ins { background: #afa; }
198
+ .del { background: #faa; }
199
+ .chg { color: #aaf; background: #007; }
200
+ .head { color: #f8f; background: #505 }
201
+
202
+ .ins .ins { color: #080; font-weight:bold }
203
+ .del .del { color: #800; font-weight:bold }
204
+ .chg .chg { color: #66f; }
205
+ .head .head { color: #f4f; }
112
206
  </style>
113
207
  </head>
114
208
  <body>
@@ -132,7 +226,9 @@ module Simplabs
132
226
  END
133
227
 
134
228
  WARNING_TEMPLATE = <<-END
135
- <dd class="warning"><span class="lineNumber">Line <span class="number">{{line_number}}</span></span>{{message}}</dd>
229
+ <dd>
230
+ <span class="lineNumber">Line <span class="number">{{line_number}}</span></span>{{message}}
231
+ </dd>
136
232
  END
137
233
 
138
234
  FOOTER_TEMPLATE = <<-END
@@ -13,7 +13,17 @@ module Simplabs
13
13
 
14
14
  def initialize(exp, parent)
15
15
  super
16
- @receiver = exp[1].is_a?(Sexp) ? (exp[1][1].nil? ? exp[1][2].to_s : exp[1][1].to_s) : nil
16
+ @receiver = if exp[1].is_a?(Sexp) && exp[1].node_type == :colon2
17
+ resolve_colon(exp[1])
18
+ elsif exp[1].is_a?(Sexp)
19
+ if exp[1].node_type != :call
20
+ exp[1][1].nil? ? exp[1][2].to_s : exp[1][1].to_s
21
+ else
22
+ nil
23
+ end
24
+ else
25
+ nil
26
+ end
17
27
  @method = exp[2].to_s
18
28
  @full_name = [@receiver, @method].compact.join('.')
19
29
  record_validation
@@ -12,9 +12,11 @@ require 'simplabs/excellent/parsing/while_context'
12
12
  require 'simplabs/excellent/parsing/until_context'
13
13
  require 'simplabs/excellent/parsing/cvar_context'
14
14
  require 'simplabs/excellent/parsing/gvar_context'
15
+ require 'simplabs/excellent/parsing/gasgn_context'
15
16
  require 'simplabs/excellent/parsing/ivar_context'
16
17
  require 'simplabs/excellent/parsing/resbody_context'
17
18
  require 'simplabs/excellent/parsing/call_context'
19
+ require 'simplabs/excellent/parsing/constant_context'
18
20
 
19
21
  module Simplabs
20
22
 
@@ -35,8 +37,6 @@ module Simplabs
35
37
 
36
38
  def process(exp)
37
39
  super
38
- rescue
39
- #continue on errors
40
40
  end
41
41
 
42
42
  def process_class(exp)
@@ -68,7 +68,7 @@ module Simplabs
68
68
  end
69
69
 
70
70
  def process_gasgn(exp)
71
- process_default(exp, GvarContext.new(exp, @contexts.last))
71
+ process_default(exp, GasgnContext.new(exp, @contexts.last))
72
72
  end
73
73
 
74
74
  def process_if(exp)
@@ -113,6 +113,10 @@ module Simplabs
113
113
  process_default(exp, ResbodyContext.new(exp, @contexts.last))
114
114
  end
115
115
 
116
+ def process_cdecl(exp)
117
+ process_default(exp, ConstantContext.new(exp, @contexts.last))
118
+ end
119
+
116
120
  def process_default(exp, context = nil)
117
121
  @contexts.push(context) if context
118
122
  @contexts.each do |c|
@@ -120,27 +124,25 @@ module Simplabs
120
124
  c.send(method, exp) if c.respond_to?(method)
121
125
  end
122
126
  exp.children.each { |sub| process(sub) }
123
- apply_checks(exp)
127
+ apply_checks(exp.file, context) if context
124
128
  @contexts.pop if context
125
129
  exp
126
130
  end
127
131
 
128
132
  private
129
133
 
130
- def apply_checks(exp)
131
- if exp.is_a?(Sexp)
132
- checks = @checks[exp.node_type] || []
133
- checks.each { |check| check.evaluate_node(@contexts.last) if check.interesting_files.any? { |pattern| File.basename(exp.file) =~ pattern } }
134
- end
134
+ def apply_checks(file, context)
135
+ checks = @checks[context.class] || []
136
+ checks.each { |check| check.evaluate_context(@contexts.last) if check.interesting_files.any? { |pattern| File.basename(file) =~ pattern } }
135
137
  end
136
138
 
137
139
  def setup_checks(checks)
138
140
  @checks = {}
139
141
  checks.each do |check|
140
- check.interesting_nodes.each do |node|
141
- @checks[node] ||= []
142
- @checks[node] << check
143
- @checks[node].uniq!
142
+ check.interesting_contexts.each do |context|
143
+ @checks[context] ||= []
144
+ @checks[context] << check
145
+ @checks[context].uniq!
144
146
  end
145
147
  end
146
148
  end
@@ -0,0 +1,20 @@
1
+ module Simplabs
2
+
3
+ module Excellent
4
+
5
+ module Parsing
6
+
7
+ class ConstantContext < SexpContext #:nodoc:
8
+
9
+ def initialize(exp, parent)
10
+ super
11
+ @name = exp[1]
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -12,7 +12,7 @@ module Simplabs
12
12
  end
13
13
 
14
14
  def full_name
15
- return @name if @parent.blank?
15
+ return @name if !@parent
16
16
  full_name = @name
17
17
  parent = @parent
18
18
  parent = parent.parent until parent.is_a?(ClassContext) || parent.is_a?(ModuleContext)
@@ -0,0 +1,21 @@
1
+ module Simplabs
2
+
3
+ module Excellent
4
+
5
+ module Parsing
6
+
7
+ class GasgnContext < SexpContext #:nodoc:
8
+
9
+ def initialize(exp, parent)
10
+ super
11
+ @name = exp[1].to_s.sub(/^\$/, '')
12
+ @full_name = @name
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -17,7 +17,7 @@ module Simplabs
17
17
  parent = @parent
18
18
  parent = parent.parent until parent.is_a?(ClassContext) || parent.is_a?(ModuleContext) || parent.nil?
19
19
  if parent
20
- full_name = "#{parent.full_name}.#{full_name}"
20
+ full_name = "@#{full_name}"
21
21
  else
22
22
  @name
23
23
  end
@@ -33,7 +33,7 @@ module Simplabs
33
33
 
34
34
  def full_name
35
35
  parent = @parent.is_a?(BlockContext) ? @parent.parent : @parent
36
- return @name if parent.blank?
36
+ return @name if !parent
37
37
  "#{parent.full_name}##{@name}"
38
38
  end
39
39
 
@@ -1,6 +1,5 @@
1
1
  require 'rubygems'
2
2
  require 'ruby_parser'
3
- require 'facets'
4
3
  require 'erb'
5
4
 
6
5
  module Simplabs
@@ -91,7 +91,7 @@ module Simplabs
91
91
  # 'Basket#add_product'.
92
92
  def full_name
93
93
  return @full_name if @full_name
94
- return @name if @parent.blank?
94
+ return @name if !@parent
95
95
  "#{@parent.full_name}::#{@name}"
96
96
  end
97
97
 
@@ -116,6 +116,15 @@ module Simplabs
116
116
  found_assignment
117
117
  end
118
118
 
119
+ def resolve_colon(exp)
120
+ scope = if exp[1].node_type == :colon2
121
+ resolve_colon(exp[1])
122
+ elsif exp[1].node_type == :const
123
+ exp[1][1]
124
+ end
125
+ "#{scope.to_s}::#{exp[2].to_s}"
126
+ end
127
+
119
128
  end
120
129
 
121
130
  end
@@ -25,7 +25,7 @@ module Simplabs
25
25
  def full_name
26
26
  return @full_name if @full_name
27
27
  parent = @parent.is_a?(BlockContext) ? @parent.parent : @parent
28
- return @name if parent.blank?
28
+ return @name if !parent
29
29
  "#{parent.full_name}.#{@name}"
30
30
  end
31
31
 
@@ -46,7 +46,7 @@ module Simplabs
46
46
  end
47
47
  task name do
48
48
  paths = @paths.join(' ')
49
- format = @html ? " html:#{@html}" : ''
49
+ format = @html ? " -o #{@html}" : ''
50
50
  system("excellent#{format} #{paths}")
51
51
  $stdout.puts("\nWrote Excellent result to #{@html}\n\n") if @html
52
52
  end
@@ -45,7 +45,7 @@ describe Simplabs::Excellent::Checks::Rails::ValidationsCheck do
45
45
  warnings.should be_empty
46
46
  end
47
47
 
48
- %(validate validate_on_create validate_on_update).each do |method|
48
+ %w(validate validate_on_create validate_on_update).each do |method|
49
49
 
50
50
  it "should accept an active record model that validates attribute by overriding #{method}" do
51
51
  code = <<-END
metadata CHANGED
@@ -1,56 +1,45 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: excellent
3
- version: !ruby/object:Gem::Version
4
- version: 1.5.4
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.6.0
5
+ prerelease:
5
6
  platform: ruby
6
- authors:
7
+ authors:
7
8
  - Marco Otte-Witte
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
-
12
- date: 2009-08-05 00:00:00 +02:00
13
- default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
12
+ date: 2009-08-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
16
15
  name: ruby_parser
16
+ requirement: &70159583025320 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '2.0'
17
22
  type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: "2.0"
24
- version:
25
- - !ruby/object:Gem::Dependency
23
+ prerelease: false
24
+ version_requirements: *70159583025320
25
+ - !ruby/object:Gem::Dependency
26
26
  name: sexp_processor
27
+ requirement: &70159583024300 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '3.0'
27
33
  type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: "3.0"
34
- version:
35
- - !ruby/object:Gem::Dependency
36
- name: facets
37
- type: :runtime
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: "2.7"
44
- version:
34
+ prerelease: false
35
+ version_requirements: *70159583024300
45
36
  description:
46
37
  email: marco.otte-witte@simplabs.com
47
- executables:
38
+ executables:
48
39
  - excellent
49
40
  extensions: []
50
-
51
41
  extra_rdoc_files: []
52
-
53
- files:
42
+ files:
54
43
  - History.txt
55
44
  - README.rdoc
56
45
  - VERSION.yml
@@ -104,11 +93,13 @@ files:
104
93
  - lib/simplabs/excellent/parsing/class_context.rb
105
94
  - lib/simplabs/excellent/parsing/code_processor.rb
106
95
  - lib/simplabs/excellent/parsing/conditional_context.rb
96
+ - lib/simplabs/excellent/parsing/constant_context.rb
107
97
  - lib/simplabs/excellent/parsing/cvar_context.rb
108
98
  - lib/simplabs/excellent/parsing/cyclomatic_complexity_measure.rb
109
99
  - lib/simplabs/excellent/parsing/flog_measure.rb
110
100
  - lib/simplabs/excellent/parsing/for_loop_context.rb
111
101
  - lib/simplabs/excellent/parsing/gvar_context.rb
102
+ - lib/simplabs/excellent/parsing/gasgn_context.rb
112
103
  - lib/simplabs/excellent/parsing/if_context.rb
113
104
  - lib/simplabs/excellent/parsing/ivar_context.rb
114
105
  - lib/simplabs/excellent/parsing/method_context.rb
@@ -156,34 +147,30 @@ files:
156
147
  - spec/checks/singleton_variable_check_spec.rb
157
148
  - spec/extensions/string_spec.rb
158
149
  - spec/spec_helper.rb
159
- has_rdoc: true
160
150
  homepage: http://github.com/simplabs/excellent
161
151
  licenses: []
162
-
163
152
  post_install_message:
164
- rdoc_options:
153
+ rdoc_options:
165
154
  - --inline-source
166
155
  - --charset=UTF-8
167
- require_paths:
156
+ require_paths:
168
157
  - lib
169
- required_ruby_version: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - ">="
172
- - !ruby/object:Gem::Version
173
- version: "0"
174
- version:
175
- required_rubygems_version: !ruby/object:Gem::Requirement
176
- requirements:
177
- - - ">="
178
- - !ruby/object:Gem::Version
179
- version: "0"
180
- version:
158
+ required_ruby_version: !ruby/object:Gem::Requirement
159
+ none: false
160
+ requirements:
161
+ - - ! '>='
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ none: false
166
+ requirements:
167
+ - - ! '>='
168
+ - !ruby/object:Gem::Version
169
+ version: '0'
181
170
  requirements: []
182
-
183
171
  rubyforge_project:
184
- rubygems_version: 1.3.5
172
+ rubygems_version: 1.8.11
185
173
  signing_key:
186
174
  specification_version: 2
187
175
  summary: Source Code analysis gem for Ruby and Rails
188
176
  test_files: []
189
-