excellent 1.5.4 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
-