teksymmetry-reek 1.1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/History.txt +131 -0
  2. data/README.txt +36 -0
  3. data/Rakefile +17 -0
  4. data/bin/reek +27 -0
  5. data/config/defaults.reek +51 -0
  6. data/lib/reek/block_context.rb +59 -0
  7. data/lib/reek/class_context.rb +68 -0
  8. data/lib/reek/code_context.rb +54 -0
  9. data/lib/reek/code_parser.rb +221 -0
  10. data/lib/reek/exceptions.reek +13 -0
  11. data/lib/reek/if_context.rb +25 -0
  12. data/lib/reek/method_context.rb +91 -0
  13. data/lib/reek/module_context.rb +33 -0
  14. data/lib/reek/name.rb +49 -0
  15. data/lib/reek/object_refs.rb +52 -0
  16. data/lib/reek/object_source.rb +53 -0
  17. data/lib/reek/options.rb +100 -0
  18. data/lib/reek/rake_task.rb +121 -0
  19. data/lib/reek/report.rb +81 -0
  20. data/lib/reek/sexp_formatter.rb +10 -0
  21. data/lib/reek/singleton_method_context.rb +27 -0
  22. data/lib/reek/smell_warning.rb +49 -0
  23. data/lib/reek/smells/control_couple.rb +61 -0
  24. data/lib/reek/smells/duplication.rb +50 -0
  25. data/lib/reek/smells/feature_envy.rb +58 -0
  26. data/lib/reek/smells/large_class.rb +69 -0
  27. data/lib/reek/smells/long_method.rb +43 -0
  28. data/lib/reek/smells/long_parameter_list.rb +43 -0
  29. data/lib/reek/smells/long_yield_list.rb +18 -0
  30. data/lib/reek/smells/nested_iterators.rb +28 -0
  31. data/lib/reek/smells/smell_detector.rb +66 -0
  32. data/lib/reek/smells/smells.rb +81 -0
  33. data/lib/reek/smells/uncommunicative_name.rb +97 -0
  34. data/lib/reek/smells/utility_function.rb +34 -0
  35. data/lib/reek/source.rb +127 -0
  36. data/lib/reek/spec.rb +146 -0
  37. data/lib/reek/stop_context.rb +50 -0
  38. data/lib/reek/yield_call_context.rb +12 -0
  39. data/lib/reek.rb +7 -0
  40. data/reek.gemspec +44 -0
  41. data/spec/reek/block_context_spec.rb +40 -0
  42. data/spec/reek/class_context_spec.rb +169 -0
  43. data/spec/reek/code_context_spec.rb +93 -0
  44. data/spec/reek/code_parser_spec.rb +34 -0
  45. data/spec/reek/config_spec.rb +42 -0
  46. data/spec/reek/if_context_spec.rb +17 -0
  47. data/spec/reek/method_context_spec.rb +66 -0
  48. data/spec/reek/module_context_spec.rb +38 -0
  49. data/spec/reek/name_spec.rb +13 -0
  50. data/spec/reek/object_refs_spec.rb +131 -0
  51. data/spec/reek/options_spec.rb +13 -0
  52. data/spec/reek/report_spec.rb +48 -0
  53. data/spec/reek/singleton_method_context_spec.rb +17 -0
  54. data/spec/reek/smells/control_couple_spec.rb +23 -0
  55. data/spec/reek/smells/duplication_spec.rb +81 -0
  56. data/spec/reek/smells/feature_envy_spec.rb +221 -0
  57. data/spec/reek/smells/large_class_spec.rb +87 -0
  58. data/spec/reek/smells/long_method_spec.rb +195 -0
  59. data/spec/reek/smells/long_parameter_list_spec.rb +85 -0
  60. data/spec/reek/smells/nested_iterators_spec.rb +33 -0
  61. data/spec/reek/smells/smell_spec.rb +24 -0
  62. data/spec/reek/smells/uncommunicative_name_spec.rb +123 -0
  63. data/spec/reek/smells/utility_function_spec.rb +93 -0
  64. data/spec/slow/inline_spec.rb +40 -0
  65. data/spec/slow/optparse_spec.rb +109 -0
  66. data/spec/slow/redcloth_spec.rb +101 -0
  67. data/spec/slow/reek_source_spec.rb +20 -0
  68. data/spec/slow/samples/inline.rb +704 -0
  69. data/spec/slow/samples/optparse.rb +1788 -0
  70. data/spec/slow/samples/redcloth.rb +1130 -0
  71. data/spec/slow/script_spec.rb +55 -0
  72. data/spec/slow/source_list_spec.rb +40 -0
  73. data/spec/spec.opts +1 -0
  74. data/spec/spec_helper.rb +13 -0
  75. data/tasks/reek.rake +7 -0
  76. data/tasks/rspec.rake +22 -0
  77. metadata +163 -0
data/History.txt ADDED
@@ -0,0 +1,131 @@
1
+ == 1.1.4 (in git)
2
+
3
+ === Minor Changes
4
+ * LongMethod now counts statements deeper into each method (#25)
5
+ * LongMethod no longer counts control structures, only their contained stmts
6
+
7
+ == 1.1.3 2009-05-19
8
+
9
+ === Minor Changes
10
+ * No longer depends directly on the sexp_processor gem
11
+
12
+ === Fixes
13
+ * LargeClass now relies only on the given source code (#26)
14
+
15
+ == 1.1.2 2009-05-18
16
+
17
+ === Major Enhancements
18
+ * Switched from ParseTree to ruby_parser for source code parsing
19
+ * 'MyClass.should_not reek' now only possible if ParseTree gem installed
20
+
21
+ == 1.1.1 2009-05-08
22
+
23
+ === Minor enhancements
24
+ * LargeClass now also warns about any class with > 9 instance variables (#6)
25
+ * Now depends on ruby2ruby, to display code better
26
+ * Duplication notices more repeated method calls
27
+ * Smells within blocks are now reported better
28
+
29
+ == 1.1.0 2009-04-10
30
+
31
+ === Minor enhancements
32
+ * Now possible to write 'MyClass.should_not reek' (#33)
33
+
34
+ === Fixes
35
+ * Now counts attr assignments ([]= etc) in feature envy calculations
36
+ * Doesn't attempt to find *.reek files when reading code from stdin
37
+
38
+ == 1.0.1 2009-04-06
39
+
40
+ === Fixes
41
+ * Dir[...].to_source now creates a Report that can be browsed (#36)
42
+
43
+ == 1.0.0 2009-04-05
44
+
45
+ === Major enhancements
46
+ * Use *.reek files in source tree to configure Reek's behaviour
47
+ * Added -f option to configure report format
48
+ * --sort_order replaced by -f, -c and -s
49
+ * Matchers provided for rspec; eg. foo.should_not reek
50
+
51
+ === Minor enhancements
52
+ * Smells in singleton methods are now analysed
53
+ * Uncommunicative parameter names in blocks now reported
54
+ * Modules and blocks now reflected in scope of smell reports
55
+
56
+ === Fixes
57
+ * Corrected false reports of long arg lists to yield
58
+ * A method can now be a UtilityFunction only when it includes a call
59
+
60
+ == 0.3.1 2008-11-17
61
+
62
+ === Minor enhancements
63
+ * Uncommunicative Name now checks instance variables more thoroughly
64
+ * Uncommunicative Name now warns about names of the form 'x2'
65
+ * Added check for duplicated calls within a method
66
+ * Reduced scope of Feature Envy warnings to cover only overuse of lvars
67
+ * Added rdoc comments explaining what each smell is about
68
+ * Chained iterators are no longer mis-reported as nested
69
+
70
+ == 0.3.0 2008-11-02
71
+
72
+ === Minor enhancements
73
+ * New smell: first naive checks for Control Couple
74
+ * reek now only checks sources passed on the command line
75
+ * Code snippets can be supplied on the commandline
76
+ * Added headings and warnings count when smells in multiple files
77
+ * Added Reek::RakeTask to run reek from rakefiles
78
+
79
+ === Fixes
80
+ * Fixed: Returns exit status 2 when smells are reported
81
+ * Fixed: no longer claims an empty method is a Utility Function
82
+
83
+ == 0.2.3 2008-09-22
84
+
85
+ * Minor enhancements:
86
+ * Only reports Feature Envy when the method isn't a Utility Function
87
+ * General improvements to assessing Feature Envy
88
+ * Tweaks:
89
+ * Fixed: coping with parameterless yield call
90
+ * Fixed: copes with :self as an expression
91
+ * Fixed: displaying the receiver of many more kinds of Feature Envy
92
+ * Fixed: Large Class calculation for Object
93
+
94
+ == 0.2.2 2008-09-15
95
+
96
+ * Tweaks:
97
+ * Fixed --version!
98
+
99
+ == 0.2.1 2008-09-14
100
+
101
+ * Tweaks:
102
+ * Now works from the source code, instead of requiring each named file
103
+ * Added integration tests that run reek on a couple of gems
104
+
105
+ == 0.2.0 2008-09-10
106
+
107
+ * Minor enhancements:
108
+ * Added --help, --version options
109
+ * Added --sort option to sort the report by smell or by code location
110
+
111
+ == 0.1.1 2008-09-09
112
+
113
+ * Some tweaks:
114
+ * Fixed report printing for Feature Envy when the receiver is a block
115
+ * Fixed: successive iterators reported as nested
116
+ * Fixed: Long Method now reports the total length of the method
117
+ * Fixed: each smell reported only once
118
+
119
+ == 0.1.0 2008-09-09
120
+
121
+ * 1 minor enhancement:
122
+ * Added a check for nested iterators within a method
123
+ * Some tweaks:
124
+ * Begun adding some rdoc
125
+ * Split some of the specs into more meaningful chunks
126
+ * Updated the rakefile so that rcov is no longer the default
127
+
128
+ == 0.0.1 2008-09-08
129
+
130
+ * 1 major enhancement:
131
+ * Initial release
data/README.txt ADDED
@@ -0,0 +1,36 @@
1
+ == Reek
2
+
3
+ Code smell detection for Ruby.
4
+
5
+ The documentation is at http://wiki.github.com/kevinrutherford/reek
6
+ The code lives at http://github.com/kevinrutherford/reek/tree
7
+
8
+
9
+ == How to use Uncommunicative name verifier extension ?
10
+
11
+ * Create your configuration reek file under your source base (RAILS_ROOT/app/app.reek)
12
+
13
+ * Add the following configurations -
14
+ UncommunicativeName:
15
+ verifierExtention:
16
+ - <path to your ruby script file>
17
+
18
+ example -
19
+ UncommunicativeName:
20
+ verifierExtention:
21
+ - config/smells/strict_uncommunicative_variable_name_verifier
22
+
23
+ * Remember ruby class name and file name must be similar,
24
+ Use "_" for separating different words. ie SimpleVerifier => simple_verifier.rb
25
+
26
+ * Write following class -
27
+ class StrictUncommunicativeVariableNameVerifier
28
+ def accepted?(p_context, p_variable_name)
29
+ # do stuffs with variable name
30
+ # if it match your requirement
31
+ # return true, nil
32
+ # otherwise
33
+ # return false, "error message"
34
+ end
35
+ end
36
+
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'rake'
2
+ require 'rake/clean'
3
+
4
+ $:.unshift File.dirname(__FILE__) + '/lib'
5
+
6
+ PROJECT_NAME = 'reek'
7
+
8
+ BUILD_DIR = 'build'; directory BUILD_DIR
9
+ PKG_DIR = "#{BUILD_DIR}/pkg"; directory PKG_DIR
10
+ RDOC_DIR = "#{BUILD_DIR}/rdoc"; directory RDOC_DIR
11
+
12
+ GEM_MANIFEST = "Manifest.txt"
13
+ VERSION_FILE = 'lib/reek.rb'
14
+
15
+ CLOBBER.include("#{BUILD_DIR}/*")
16
+
17
+ Dir['tasks/**/*.rake'].each { |t| load t }
data/bin/reek ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Reek examines Ruby source code for smells.
4
+ # Visit http://reek.rubyforge.org/ for docs etc.
5
+ #
6
+ # Author: Kevin Rutherford
7
+ #
8
+
9
+ # Allow local access
10
+ if ARGV.include?("-TX")
11
+ ARGV.delete("-TX")
12
+ require File.join('~/projects/tekSymmetry/reek', 'lib/reek')
13
+ require File.join('~/projects/tekSymmetry/reek', 'lib/reek/source')
14
+ require File.join('~/projects/tekSymmetry/reek', 'lib/reek/options')
15
+ else
16
+ require 'reek'
17
+ require 'reek/source'
18
+ require 'reek/options'
19
+ end
20
+
21
+ exitstatus = 0
22
+ source = Reek::Options.parse(ARGV)
23
+ if source.smelly?
24
+ puts source.report
25
+ exitstatus = 2
26
+ end
27
+ exit(exitstatus)
@@ -0,0 +1,51 @@
1
+ ---
2
+ LargeClass:
3
+ max_methods: 25
4
+ exclude: []
5
+
6
+ enabled: true
7
+ max_instance_variables: 9
8
+ LongParameterList:
9
+ max_params: 3
10
+ exclude: []
11
+
12
+ enabled: true
13
+ FeatureEnvy:
14
+ exclude:
15
+ - initialize
16
+ enabled: true
17
+ UncommunicativeName:
18
+ accept:
19
+ - Inline::C
20
+ exclude: []
21
+
22
+ enabled: true
23
+ reject:
24
+ - !ruby/regexp /^.[0-9]*$/
25
+ NestedIterators:
26
+ exclude: []
27
+
28
+ enabled: true
29
+ LongMethod:
30
+ max_statements: 5
31
+ exclude:
32
+ - initialize
33
+ enabled: true
34
+ Duplication:
35
+ exclude: []
36
+
37
+ enabled: true
38
+ max_calls: 1
39
+ UtilityFunction:
40
+ exclude: []
41
+
42
+ enabled: true
43
+ ControlCouple:
44
+ exclude:
45
+ - initialize
46
+ enabled: true
47
+ LongYieldList:
48
+ max_params: 3
49
+ exclude: []
50
+
51
+ enabled: true
@@ -0,0 +1,59 @@
1
+ require 'set'
2
+ require 'reek/code_context'
3
+
4
+ module Reek
5
+
6
+ module ParameterSet
7
+ def names
8
+ return @names if @names
9
+ return (@names = []) if empty?
10
+ arg = slice(1)
11
+ case slice(0)
12
+ when :masgn
13
+ @names = arg[1..-1].map {|lasgn| Name.new(lasgn[1]) }
14
+ when :lasgn
15
+ @names = [Name.new(arg)]
16
+ end
17
+ end
18
+
19
+ def include?(name)
20
+ names.include?(name)
21
+ end
22
+ end
23
+
24
+ class BlockContext < CodeContext
25
+
26
+ def initialize(outer, exp)
27
+ super
28
+ @name = Name.new('block')
29
+ @parameters = exp[0] if exp
30
+ @parameters ||= []
31
+ @parameters.extend(ParameterSet)
32
+ @local_variables = Set.new
33
+ end
34
+
35
+ def inside_a_block?
36
+ true
37
+ end
38
+
39
+ def has_parameter(name)
40
+ @parameters.include?(name) or @outer.has_parameter(name)
41
+ end
42
+
43
+ def nested_block?
44
+ @outer.inside_a_block?
45
+ end
46
+
47
+ def record_local_variable(sym)
48
+ @local_variables << Name.new(sym)
49
+ end
50
+
51
+ def outer_name
52
+ "#{@outer.outer_name}#{@name}/"
53
+ end
54
+
55
+ def variable_names
56
+ @parameters.names + @local_variables.to_a
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,68 @@
1
+ require 'set'
2
+ require 'reek/code_context'
3
+
4
+ class Class
5
+ def is_overriding_method?(sym)
6
+ instance_methods(false).include?(sym) and superclass.instance_methods(true).include?(sym)
7
+ end
8
+ end
9
+
10
+ module Reek
11
+ class ClassContext < CodeContext
12
+
13
+ def ClassContext.create(outer, exp)
14
+ res = Name.resolve(exp[1], outer)
15
+ ClassContext.new(res[0], res[1], exp[2])
16
+ end
17
+
18
+ def initialize(outer, name, superclass = nil)
19
+ super(outer, nil)
20
+ @name = name
21
+ @superclass = superclass
22
+ @parsed_methods = []
23
+ @instance_variables = Set.new
24
+ end
25
+
26
+ def myself
27
+ @myself ||= @outer.find_module(@name)
28
+ end
29
+
30
+ def find_module(modname)
31
+ return nil unless myself
32
+ @myself.const_or_nil(modname.to_s)
33
+ end
34
+
35
+ def is_overriding_method?(name)
36
+ return false unless myself
37
+ @myself.is_overriding_method?(name.to_s)
38
+ end
39
+
40
+ def is_struct?
41
+ @superclass == [:const, :Struct]
42
+ end
43
+
44
+ def num_methods
45
+ @parsed_methods.length
46
+ end
47
+
48
+ def record_instance_variable(sym)
49
+ @instance_variables << Name.new(sym)
50
+ end
51
+
52
+ def record_method(name)
53
+ @parsed_methods << name.to_s
54
+ end
55
+
56
+ def outer_name
57
+ "#{@outer.outer_name}#{@name}#"
58
+ end
59
+
60
+ def to_s
61
+ "#{@outer.outer_name}#{@name}"
62
+ end
63
+
64
+ def variable_names
65
+ @instance_variables
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,54 @@
1
+ class Module
2
+
3
+ def const_or_nil(sym)
4
+ const_defined?(sym) ? const_get(sym) : nil
5
+ end
6
+ end
7
+
8
+ module Reek
9
+
10
+ #
11
+ # Superclass for all types of source code context. Each instance represents
12
+ # a code element of some kind, and each provides behaviour relevant to that
13
+ # code element. CodeContexts form a tree in the same way the code does,
14
+ # with each context holding a reference to a unique outer context.
15
+ #
16
+ class CodeContext
17
+
18
+ attr_reader :name
19
+
20
+ def initialize(outer, exp)
21
+ @outer = outer
22
+ @exp = exp
23
+ @myself = nil
24
+ end
25
+
26
+ def matches?(strings)
27
+ me = @name.to_s
28
+ strings.any? do |str|
29
+ re = /#{str}/
30
+ re === me or re === self.to_s
31
+ end
32
+ end
33
+
34
+ #
35
+ # Bounces messages up the context tree to the first enclosing context
36
+ # that knows how to deal with the request.
37
+ #
38
+ def method_missing(method, *args)
39
+ @outer.send(method, *args)
40
+ end
41
+
42
+ def num_methods
43
+ 0
44
+ end
45
+
46
+ def outer_name
47
+ "#{@name}/"
48
+ end
49
+
50
+ def to_s
51
+ "#{@outer.outer_name}#{@name}"
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,221 @@
1
+ require 'rubygems'
2
+ require 'sexp'
3
+ require 'reek/block_context'
4
+ require 'reek/class_context'
5
+ require 'reek/module_context'
6
+ require 'reek/stop_context'
7
+ require 'reek/if_context'
8
+ require 'reek/method_context'
9
+ require 'reek/singleton_method_context'
10
+ require 'reek/yield_call_context'
11
+
12
+ class Sexp
13
+ def children
14
+ find_all { |item| Sexp === item }
15
+ end
16
+
17
+ def is_language_node?
18
+ first.class == Symbol
19
+ end
20
+
21
+ def has_type?(type)
22
+ is_language_node? and first == type
23
+ end
24
+ end
25
+
26
+ module Reek
27
+
28
+ class CodeParser
29
+
30
+ # Creates a new Ruby code checker. Any smells discovered
31
+ # will be stored in +report+.
32
+ def initialize(report, smells, ctx = StopContext.new)
33
+ @report = report
34
+ @smells = smells
35
+ @element = ctx
36
+ end
37
+
38
+ def process(exp)
39
+ meth = "process_#{exp[0]}"
40
+ meth = :process_default unless self.respond_to?(meth)
41
+ self.send(meth, exp)
42
+ @element
43
+ end
44
+
45
+ def process_default(exp)
46
+ exp[0..-1].each { |sub| process(sub) if Array === sub }
47
+ end
48
+
49
+ def process_module(exp)
50
+ push(ModuleContext.create(@element, exp)) do
51
+ process_default(exp)
52
+ check_smells(:module)
53
+ end
54
+ end
55
+
56
+ def process_class(exp)
57
+ push(ClassContext.create(@element, exp)) do
58
+ process_default(exp) unless @element.is_struct?
59
+ check_smells(:class)
60
+ end
61
+ end
62
+
63
+ def process_defn(exp)
64
+ handle_context(MethodContext, :defn, exp)
65
+ end
66
+
67
+ def process_defs(exp)
68
+ handle_context(SingletonMethodContext, :defs, exp)
69
+ end
70
+
71
+ def process_args(exp)
72
+ exp[1..-1].each {|sym| @element.record_parameter(sym) }
73
+ end
74
+
75
+ def process_attrset(exp)
76
+ @element.record_depends_on_self if /^@/ === exp[1].to_s
77
+ end
78
+
79
+ def process_lit(exp)
80
+ val = exp[1]
81
+ @element.record_depends_on_self if val == :self
82
+ end
83
+
84
+ def process_iter(exp)
85
+ process(exp[1])
86
+ handle_context(BlockContext, :iter, exp[2..-1])
87
+ end
88
+
89
+ def process_dasgn_curr(exp)
90
+ @element.record_parameter(exp[1])
91
+ process_default(exp)
92
+ end
93
+
94
+ def process_block(exp)
95
+ @element.count_statements(CodeParser.count_statements(exp))
96
+ process_default(exp)
97
+ end
98
+
99
+ def process_yield(exp)
100
+ handle_context(YieldCallContext, :yield, exp)
101
+ end
102
+
103
+ def process_call(exp)
104
+ @element.record_call_to(exp)
105
+ process_default(exp)
106
+ end
107
+
108
+ def process_cfunc(exp)
109
+ @element.record_depends_on_self
110
+ end
111
+
112
+ def process_attrasgn(exp)
113
+ process_call(exp)
114
+ end
115
+
116
+ def process_op_asgn1(exp)
117
+ process_call(exp)
118
+ end
119
+
120
+ def process_if(exp)
121
+ count_clause(exp[2])
122
+ count_clause(exp[3])
123
+ handle_context(IfContext, :if, exp)
124
+ @element.count_statements(-1)
125
+ end
126
+
127
+ def process_while(exp)
128
+ count_clause(exp[2])
129
+ process_default(exp)
130
+ @element.count_statements(-1)
131
+ end
132
+
133
+ def process_until(exp)
134
+ count_clause(exp[2])
135
+ process_default(exp)
136
+ @element.count_statements(-1)
137
+ end
138
+
139
+ def process_for(exp)
140
+ count_clause(exp[3])
141
+ process_default(exp)
142
+ @element.count_statements(-1)
143
+ end
144
+
145
+ def process_rescue(exp)
146
+ count_clause(exp[1])
147
+ process_default(exp)
148
+ @element.count_statements(-1)
149
+ end
150
+
151
+ def process_resbody(exp)
152
+ count_clause(exp[2])
153
+ process_default(exp)
154
+ end
155
+
156
+ def process_case(exp)
157
+ process_default(exp)
158
+ @element.count_statements(-1)
159
+ end
160
+
161
+ def process_when(exp)
162
+ count_clause(exp[2])
163
+ process_default(exp)
164
+ end
165
+
166
+ def process_ivar(exp)
167
+ process_iasgn(exp)
168
+ end
169
+
170
+ def process_lasgn(exp)
171
+ @element.record_local_variable(exp[1])
172
+ process_default(exp)
173
+ end
174
+
175
+ def process_iasgn(exp)
176
+ @element.record_instance_variable(exp[1])
177
+ @element.record_depends_on_self
178
+ process_default(exp)
179
+ end
180
+
181
+ def process_self(exp)
182
+ @element.record_depends_on_self
183
+ end
184
+
185
+ def count_clause(sexp)
186
+ if sexp and !sexp.has_type?(:block)
187
+ @element.count_statements(1)
188
+ end
189
+ end
190
+
191
+ def self.count_statements(exp)
192
+ stmts = exp[1..-1]
193
+ ignore = 0
194
+ ignore += 1 if stmts[1] == s(:nil)
195
+ stmts.length - ignore
196
+ end
197
+
198
+ private
199
+
200
+ def handle_context(klass, type, exp)
201
+ scope = klass.new(@element, exp)
202
+ push(scope) do
203
+ process_default(exp)
204
+ check_smells(type)
205
+ end
206
+ scope
207
+ end
208
+
209
+ def check_smells(type)
210
+ listeners = @smells[type]
211
+ listeners.each {|smell| smell.examine(@element, @report) } if listeners
212
+ end
213
+
214
+ def push(context)
215
+ orig = @element
216
+ @element = context
217
+ yield
218
+ @element = orig
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,13 @@
1
+ ---
2
+ FeatureEnvy:
3
+ exclude:
4
+ - examine_context
5
+ LargeClass:
6
+ exclude:
7
+ - CodeParser
8
+ LongMethod:
9
+ exclude:
10
+ - Reek::SexpFormatter#self.format
11
+ UtilityFunction:
12
+ exclude:
13
+ - Reek::Spec
@@ -0,0 +1,25 @@
1
+ require 'reek/code_context'
2
+
3
+ module Reek
4
+ class IfContext < CodeContext
5
+ attr_reader :if_expr
6
+
7
+ def initialize(outer, exp)
8
+ @outer = outer
9
+ @exp = exp
10
+ @if_expr = exp[1]
11
+ end
12
+
13
+ def tests_a_parameter?
14
+ @if_expr[0] == :lvar and has_parameter(@if_expr[1])
15
+ end
16
+
17
+ def outer_name
18
+ @outer.outer_name
19
+ end
20
+
21
+ def to_s
22
+ @outer.to_s
23
+ end
24
+ end
25
+ end