excellent 1.5.4

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 (106) hide show
  1. data/History.txt +69 -0
  2. data/README.rdoc +72 -0
  3. data/VERSION.yml +4 -0
  4. data/bin/excellent +34 -0
  5. data/lib/simplabs/excellent.rb +16 -0
  6. data/lib/simplabs/excellent/checks.rb +33 -0
  7. data/lib/simplabs/excellent/checks/abc_metric_method_check.rb +43 -0
  8. data/lib/simplabs/excellent/checks/assignment_in_conditional_check.rb +39 -0
  9. data/lib/simplabs/excellent/checks/base.rb +62 -0
  10. data/lib/simplabs/excellent/checks/case_missing_else_check.rb +34 -0
  11. data/lib/simplabs/excellent/checks/class_line_count_check.rb +36 -0
  12. data/lib/simplabs/excellent/checks/class_name_check.rb +38 -0
  13. data/lib/simplabs/excellent/checks/control_coupling_check.rb +35 -0
  14. data/lib/simplabs/excellent/checks/cyclomatic_complexity_block_check.rb +48 -0
  15. data/lib/simplabs/excellent/checks/cyclomatic_complexity_check.rb +23 -0
  16. data/lib/simplabs/excellent/checks/cyclomatic_complexity_method_check.rb +48 -0
  17. data/lib/simplabs/excellent/checks/empty_rescue_body_check.rb +31 -0
  18. data/lib/simplabs/excellent/checks/flog_block_check.rb +40 -0
  19. data/lib/simplabs/excellent/checks/flog_check.rb +27 -0
  20. data/lib/simplabs/excellent/checks/flog_class_check.rb +40 -0
  21. data/lib/simplabs/excellent/checks/flog_method_check.rb +40 -0
  22. data/lib/simplabs/excellent/checks/for_loop_check.rb +42 -0
  23. data/lib/simplabs/excellent/checks/global_variable_check.rb +33 -0
  24. data/lib/simplabs/excellent/checks/line_count_check.rb +27 -0
  25. data/lib/simplabs/excellent/checks/method_line_count_check.rb +36 -0
  26. data/lib/simplabs/excellent/checks/method_name_check.rb +38 -0
  27. data/lib/simplabs/excellent/checks/module_line_count_check.rb +36 -0
  28. data/lib/simplabs/excellent/checks/module_name_check.rb +38 -0
  29. data/lib/simplabs/excellent/checks/name_check.rb +27 -0
  30. data/lib/simplabs/excellent/checks/nested_iterators_check.rb +34 -0
  31. data/lib/simplabs/excellent/checks/parameter_number_check.rb +38 -0
  32. data/lib/simplabs/excellent/checks/rails.rb +22 -0
  33. data/lib/simplabs/excellent/checks/rails/attr_accessible_check.rb +38 -0
  34. data/lib/simplabs/excellent/checks/rails/attr_protected_check.rb +39 -0
  35. data/lib/simplabs/excellent/checks/rails/custom_initialize_method_check.rb +37 -0
  36. data/lib/simplabs/excellent/checks/rails/instance_var_in_partial_check.rb +37 -0
  37. data/lib/simplabs/excellent/checks/rails/params_hash_in_view_check.rb +38 -0
  38. data/lib/simplabs/excellent/checks/rails/session_hash_in_view_check.rb +38 -0
  39. data/lib/simplabs/excellent/checks/rails/validations_check.rb +36 -0
  40. data/lib/simplabs/excellent/checks/singleton_variable_check.rb +33 -0
  41. data/lib/simplabs/excellent/command_line_runner.rb +37 -0
  42. data/lib/simplabs/excellent/extensions/sexp.rb +21 -0
  43. data/lib/simplabs/excellent/extensions/string.rb +28 -0
  44. data/lib/simplabs/excellent/formatters.rb +13 -0
  45. data/lib/simplabs/excellent/formatters/base.rb +49 -0
  46. data/lib/simplabs/excellent/formatters/html.rb +153 -0
  47. data/lib/simplabs/excellent/formatters/text.rb +40 -0
  48. data/lib/simplabs/excellent/parsing.rb +10 -0
  49. data/lib/simplabs/excellent/parsing/abc_measure.rb +52 -0
  50. data/lib/simplabs/excellent/parsing/block_context.rb +43 -0
  51. data/lib/simplabs/excellent/parsing/call_context.rb +52 -0
  52. data/lib/simplabs/excellent/parsing/case_context.rb +31 -0
  53. data/lib/simplabs/excellent/parsing/class_context.rb +99 -0
  54. data/lib/simplabs/excellent/parsing/code_processor.rb +165 -0
  55. data/lib/simplabs/excellent/parsing/conditional_context.rb +25 -0
  56. data/lib/simplabs/excellent/parsing/cvar_context.rb +28 -0
  57. data/lib/simplabs/excellent/parsing/cyclomatic_complexity_measure.rb +73 -0
  58. data/lib/simplabs/excellent/parsing/flog_measure.rb +192 -0
  59. data/lib/simplabs/excellent/parsing/for_loop_context.rb +15 -0
  60. data/lib/simplabs/excellent/parsing/gvar_context.rb +21 -0
  61. data/lib/simplabs/excellent/parsing/if_context.rb +38 -0
  62. data/lib/simplabs/excellent/parsing/ivar_context.rb +32 -0
  63. data/lib/simplabs/excellent/parsing/method_context.rb +50 -0
  64. data/lib/simplabs/excellent/parsing/module_context.rb +29 -0
  65. data/lib/simplabs/excellent/parsing/parser.rb +35 -0
  66. data/lib/simplabs/excellent/parsing/resbody_context.rb +39 -0
  67. data/lib/simplabs/excellent/parsing/scopeable.rb +34 -0
  68. data/lib/simplabs/excellent/parsing/sexp_context.rb +125 -0
  69. data/lib/simplabs/excellent/parsing/singleton_method_context.rb +55 -0
  70. data/lib/simplabs/excellent/parsing/until_context.rb +24 -0
  71. data/lib/simplabs/excellent/parsing/while_context.rb +24 -0
  72. data/lib/simplabs/excellent/rake.rb +1 -0
  73. data/lib/simplabs/excellent/rake/excellent_task.rb +61 -0
  74. data/lib/simplabs/excellent/runner.rb +143 -0
  75. data/lib/simplabs/excellent/warning.rb +53 -0
  76. data/spec/checks/abc_metric_method_check_spec.rb +122 -0
  77. data/spec/checks/assignment_in_conditional_check_spec.rb +90 -0
  78. data/spec/checks/case_missing_else_check_spec.rb +42 -0
  79. data/spec/checks/class_line_count_check_spec.rb +62 -0
  80. data/spec/checks/class_name_check_spec.rb +48 -0
  81. data/spec/checks/control_coupling_check_spec.rb +103 -0
  82. data/spec/checks/cyclomatic_complexity_block_check_spec.rb +47 -0
  83. data/spec/checks/cyclomatic_complexity_method_check_spec.rb +210 -0
  84. data/spec/checks/empty_rescue_body_check_spec.rb +170 -0
  85. data/spec/checks/flog_block_check_spec.rb +28 -0
  86. data/spec/checks/flog_class_check_spec.rb +28 -0
  87. data/spec/checks/flog_method_check_spec.rb +46 -0
  88. data/spec/checks/for_loop_check_spec.rb +52 -0
  89. data/spec/checks/global_variable_check_spec.rb +66 -0
  90. data/spec/checks/method_line_count_check_spec.rb +49 -0
  91. data/spec/checks/method_name_check_spec.rb +112 -0
  92. data/spec/checks/module_line_count_check_spec.rb +48 -0
  93. data/spec/checks/module_name_check_spec.rb +61 -0
  94. data/spec/checks/nested_iterators_check_spec.rb +44 -0
  95. data/spec/checks/parameter_number_check_spec.rb +97 -0
  96. data/spec/checks/rails/attr_accessible_check_spec.rb +79 -0
  97. data/spec/checks/rails/attr_protected_check_spec.rb +77 -0
  98. data/spec/checks/rails/custom_initialize_method_check_spec.rb +58 -0
  99. data/spec/checks/rails/instance_var_in_partial_check_spec.rb +40 -0
  100. data/spec/checks/rails/params_hash_in_view_check_spec.rb +40 -0
  101. data/spec/checks/rails/session_hash_in_view_check_spec.rb +40 -0
  102. data/spec/checks/rails/validations_check_spec.rb +81 -0
  103. data/spec/checks/singleton_variable_check_spec.rb +66 -0
  104. data/spec/extensions/string_spec.rb +13 -0
  105. data/spec/spec_helper.rb +13 -0
  106. metadata +189 -0
@@ -0,0 +1,27 @@
1
+ require 'simplabs/excellent/checks/base'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ class LineCountCheck < Base #:nodoc:
10
+
11
+ def initialize(interesting_nodes, threshold)
12
+ super()
13
+ @interesting_nodes = interesting_nodes
14
+ @threshold = threshold
15
+ end
16
+
17
+ def evaluate(context)
18
+ add_warning(*warning_args(context)) unless context.line_count <= @threshold
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,36 @@
1
+ require 'simplabs/excellent/checks/line_count_check'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ # This check reports methods which have more lines than the threshold. Methods with a large number of lines are hard to read and understand
10
+ # and often an indicator for badly designed code as well.
11
+ #
12
+ # ==== Applies to
13
+ #
14
+ # * methods
15
+ class MethodLineCountCheck < LineCountCheck
16
+
17
+ DEFAULT_THRESHOLD = 20
18
+
19
+ def initialize(options = {}) #:nodoc:
20
+ threshold = options[:threshold] || DEFAULT_THRESHOLD
21
+ super([:defn], threshold)
22
+ end
23
+
24
+ protected
25
+
26
+ def warning_args(context) #:nodoc:
27
+ [context, '{{method}} has {{count}} lines.', { :method => context.full_name, :count => context.line_count }]
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,38 @@
1
+ require 'simplabs/excellent/checks/base'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ # This check reports methods with bad names. Badly named methods make reading and understanding the code much harder. Method names regarded as bad
10
+ # are for example:
11
+ #
12
+ # * names that are camel cased
13
+ #
14
+ # ==== Applies to
15
+ #
16
+ # * methods
17
+ class MethodNameCheck < NameCheck
18
+
19
+ DEFAULT_PATTERN = /^[_a-z<>=\[|+-\/\*\~\%\&`\|\^]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
20
+
21
+ def initialize(options = {}) #:nodoc:
22
+ pattern = options['pattern'] || DEFAULT_PATTERN
23
+ super([:defn, :defs], pattern)
24
+ end
25
+
26
+ protected
27
+
28
+ def warning_args(context) #:nodoc:
29
+ [context, 'Bad method name {{method}}.', { :method => context.full_name }]
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,36 @@
1
+ require 'simplabs/excellent/checks/line_count_check'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ # This check reports modules which have more lines than the threshold. Modules with a large number of lines are hard to read and understand
10
+ # and often an indicator for badly designed code as well.
11
+ #
12
+ # ==== Applies to
13
+ #
14
+ # * modules
15
+ class ModuleLineCountCheck < LineCountCheck
16
+
17
+ DEFAULT_THRESHOLD = 300
18
+
19
+ def initialize(options = {}) #:nodoc:
20
+ threshold = options[:threshold] || DEFAULT_THRESHOLD
21
+ super([:module], threshold)
22
+ end
23
+
24
+ protected
25
+
26
+ def warning_args(context) #:nodoc:
27
+ [context, '{{module}} has {{count}} lines.', { :module => context.full_name, :count => context.line_count }]
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,38 @@
1
+ require 'simplabs/excellent/checks/base'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ # This check reports modules with bad names. Badly named modules make reading and understanding the code much harder. Module names regarded as bad
10
+ # are for example:
11
+ #
12
+ # * names that are not Pascal cased (camel cased, starting with an upper case letter)
13
+ #
14
+ # ==== Applies to
15
+ #
16
+ # * modules
17
+ class ModuleNameCheck < NameCheck
18
+
19
+ DEFAULT_PATTERN = /^[A-Z][a-zA-Z0-9]*$/
20
+
21
+ def initialize(options = {}) #:nodoc:
22
+ pattern = options['pattern'] || DEFAULT_PATTERN
23
+ super([:module], pattern)
24
+ end
25
+
26
+ protected
27
+
28
+ def warning_args(context) #:nodoc:
29
+ [context, 'Bad module name {{module}}.', { :module => context.full_name }]
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,27 @@
1
+ require 'simplabs/excellent/checks/base'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ class NameCheck < Base #:nodoc:
10
+
11
+ def initialize(interesting_nodes, pattern)
12
+ super()
13
+ @interesting_nodes = interesting_nodes
14
+ @pattern = pattern
15
+ end
16
+
17
+ def evaluate(context)
18
+ add_warning(*warning_args(context)) unless context.name.to_s =~ @pattern
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,34 @@
1
+ require 'simplabs/excellent/checks/base'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ # This check reports nested iterators. Nested iterators lead to introduce performance issues.
10
+ #
11
+ # ==== Applies to
12
+ #
13
+ # * blocks
14
+ class NestedIteratorsCheck < Base
15
+
16
+ def initialize #:nodoc:
17
+ super
18
+ @interesting_nodes = [:iter]
19
+ @interesting_files = [/\.rb$/, /\.erb$/]
20
+ end
21
+
22
+ def evaluate(context) #:nodoc:
23
+ if context.inside_block?
24
+ add_warning(context, '{{block}} inside of {{parent}}.', { :block => context.full_name, :parent => context.parent.full_name })
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,38 @@
1
+ require 'simplabs/excellent/checks/base'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ # This check reports method and blocks that have more parameters than the threshold. Methods with long parameter lists are harder to understand
10
+ # and often an indicator for bad design as well.
11
+ #
12
+ # ==== Applies to
13
+ #
14
+ # * methods
15
+ # * blocks
16
+ class ParameterNumberCheck < Base
17
+
18
+ DEFAULT_THRESHOLD = 3
19
+
20
+ def initialize(options = {}) #:nodoc:
21
+ super()
22
+ @threshold = options[:threshold] || DEFAULT_THRESHOLD
23
+ @interesting_nodes = [:defn, :iter, :defs]
24
+ end
25
+
26
+ def evaluate(context) #:nodoc:
27
+ unless context.parameters.length <= @threshold
28
+ add_warning(context, '{{method}} has {{parameters}} parameters.', { :method => context.full_name, :parameters => context.parameters.length })
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,22 @@
1
+ module Simplabs
2
+
3
+ module Excellent
4
+
5
+ module Checks
6
+
7
+ module Rails #:nodoc:
8
+ end
9
+
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+
16
+ require 'simplabs/excellent/checks/rails/attr_accessible_check'
17
+ require 'simplabs/excellent/checks/rails/attr_protected_check'
18
+ require 'simplabs/excellent/checks/rails/instance_var_in_partial_check'
19
+ require 'simplabs/excellent/checks/rails/validations_check'
20
+ require 'simplabs/excellent/checks/rails/params_hash_in_view_check'
21
+ require 'simplabs/excellent/checks/rails/session_hash_in_view_check'
22
+ require 'simplabs/excellent/checks/rails/custom_initialize_method_check'
@@ -0,0 +1,38 @@
1
+ require 'simplabs/excellent/checks/base'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ module Rails
10
+
11
+ # This check reports +ActiveRecord+ models that do not specify +attr_accessible+. Specifying +attr_accessible+ is viable to protect models from
12
+ # mass assignment attacks (see http://guides.rubyonrails.org/security.html#mass-assignment). +attr_accessible+ specifies a list of properties
13
+ # that are writeable by mass assignments. For a +User+ model for example, that list would possibly include properties like +first_name+ and
14
+ # +last_name+ while it should not include properties like +is_admin+.
15
+ #
16
+ # ==== Applies to
17
+ #
18
+ # * +ActiveRecord+ models
19
+ class AttrAccessibleCheck < Base
20
+
21
+ def initialize #:nodoc:
22
+ super
23
+ @interesting_nodes = [:class]
24
+ end
25
+
26
+ def evaluate(context) #:nodoc:
27
+ add_warning(context, '{{class}} does not specify attr_accessible.', { :class => context.full_name }) if context.active_record_model? && !context.specifies_attr_accessible?
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,39 @@
1
+ require 'simplabs/excellent/checks/base'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ module Rails
10
+
11
+ # This check reports +ActiveRecord+ models that specify +attr_protected+. Like +attr_accessible+, +attr_protected+ is a helper to secure
12
+ # +ActiveRecord+ models against mass assignment attacks (see http://guides.rubyonrails.org/security.html#mass-assignment), but instead of
13
+ # specifying a white list of properties that are writeable by mass assignments as +attr_accessible+ does, +attr_protected+ specifies a black
14
+ # list. Such a black list approach is usually less secure since the list has to be updated for every new property that is introduced, which
15
+ # is easy to forget.
16
+ #
17
+ # ==== Applies to
18
+ #
19
+ # * +ActiveRecord+ models
20
+ class AttrProtectedCheck < Base
21
+
22
+ def initialize #:nodoc:
23
+ super
24
+ @interesting_nodes = [:class]
25
+ end
26
+
27
+ def evaluate(context) #:nodoc:
28
+ add_warning(context, '{{class}} specifies attr_protected.', { :class => context.full_name }) if context.active_record_model? && context.specifies_attr_protected?
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,37 @@
1
+ require 'simplabs/excellent/checks/base'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ module Rails
10
+
11
+ # This check reports +ActiveRecord+ models that define a custom +initialize+ method. Since +ActiveRecord+ does not always call +new+ to
12
+ # create instances, these custom +initialize+ methods might not always be called, which makes the behavior of the application very hard to
13
+ # understand.
14
+ #
15
+ # ==== Applies to
16
+ #
17
+ # * +ActiveRecord+ models
18
+ class CustomInitializeMethodCheck < Base
19
+
20
+ def initialize #:nodoc:
21
+ super
22
+ @interesting_nodes = [:class]
23
+ end
24
+
25
+ def evaluate(context) #:nodoc:
26
+ add_warning(context, '{{class}} defines initialize method.', { :class => context.full_name }) if context.active_record_model? && !context.defines_initializer?
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,37 @@
1
+ require 'simplabs/excellent/checks/base'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ module Rails
10
+
11
+ # This check reports partials that use instance variables. Using instance variables in partials couples the partial to the controller action or
12
+ # template that includes the partial and that has to define the instance variable.
13
+ #
14
+ # ==== Applies to
15
+ #
16
+ # * partials
17
+ class InstanceVarInPartialCheck < Base
18
+
19
+ def initialize #:nodoc:
20
+ super
21
+ @interesting_nodes = [:ivar]
22
+ @interesting_files = [/^_.*\.erb$/]
23
+ end
24
+
25
+ def evaluate(context) #:nodoc:
26
+ add_warning(context, 'Instance variable {{variable}} used in partial.', { :variable => context.full_name })
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end