reek 1.2.6 → 1.2.8
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.
- data/.yardopts +10 -0
- data/History.txt +62 -0
- data/README.md +74 -0
- data/bin/reek +2 -2
- data/config/defaults.reek +44 -5
- data/features/api.feature +20 -0
- data/features/masking_smells.feature +60 -42
- data/features/options.feature +7 -2
- data/features/rake_task.feature +29 -22
- data/features/reports.feature +9 -41
- data/features/samples.feature +184 -196
- data/features/stdin.feature +5 -8
- data/features/step_definitions/reek_steps.rb +8 -4
- data/features/support/env.rb +2 -3
- data/features/yaml.feature +85 -0
- data/lib/reek/cli/application.rb +46 -0
- data/lib/reek/cli/command_line.rb +108 -0
- data/lib/reek/cli/help_command.rb +18 -0
- data/lib/reek/cli/reek_command.rb +37 -0
- data/lib/reek/cli/report.rb +58 -0
- data/lib/reek/cli/version_command.rb +19 -0
- data/lib/reek/cli/yaml_command.rb +32 -0
- data/lib/reek/core/code_context.rb +64 -0
- data/lib/reek/core/code_parser.rb +166 -0
- data/lib/reek/core/method_context.rb +84 -0
- data/lib/reek/core/module_context.rb +20 -0
- data/lib/reek/core/object_refs.rb +51 -0
- data/lib/reek/core/singleton_method_context.rb +20 -0
- data/lib/reek/core/smell_configuration.rb +62 -0
- data/lib/reek/core/sniffer.rb +105 -0
- data/lib/reek/core/stop_context.rb +30 -0
- data/lib/reek/core/warning_collector.rb +27 -0
- data/lib/reek/examiner.rb +104 -0
- data/lib/reek/rake/task.rb +142 -0
- data/lib/reek/smell_warning.rb +73 -23
- data/lib/reek/smells/attribute.rb +26 -21
- data/lib/reek/smells/boolean_parameter.rb +38 -0
- data/lib/reek/smells/class_variable.rb +22 -9
- data/lib/reek/smells/control_couple.rb +40 -16
- data/lib/reek/smells/data_clump.rb +114 -23
- data/lib/reek/smells/duplication.rb +55 -15
- data/lib/reek/smells/feature_envy.rb +16 -7
- data/lib/reek/smells/irresponsible_module.rb +37 -0
- data/lib/reek/smells/large_class.rb +37 -19
- data/lib/reek/smells/long_method.rb +20 -9
- data/lib/reek/smells/long_parameter_list.rb +22 -10
- data/lib/reek/smells/long_yield_list.rb +43 -7
- data/lib/reek/smells/nested_iterators.rb +68 -8
- data/lib/reek/smells/simulated_polymorphism.rb +26 -15
- data/lib/reek/smells/smell_detector.rb +29 -51
- data/lib/reek/smells/uncommunicative_method_name.rb +74 -0
- data/lib/reek/smells/uncommunicative_module_name.rb +74 -0
- data/lib/reek/smells/uncommunicative_parameter_name.rb +79 -0
- data/lib/reek/smells/uncommunicative_variable_name.rb +89 -0
- data/lib/reek/smells/utility_function.rb +51 -12
- data/lib/reek/smells.rb +29 -0
- data/lib/reek/source/code_comment.rb +37 -0
- data/lib/reek/source/config_file.rb +72 -0
- data/lib/reek/source/core_extras.rb +46 -0
- data/lib/reek/source/reference_collector.rb +28 -0
- data/lib/reek/source/sexp_formatter.rb +17 -0
- data/lib/reek/source/source_code.rb +44 -0
- data/lib/reek/source/source_file.rb +32 -0
- data/lib/reek/source/source_locator.rb +42 -0
- data/lib/reek/source/tree_dresser.rb +204 -0
- data/lib/reek/source.rb +18 -0
- data/lib/reek/spec/should_reek.rb +31 -0
- data/lib/reek/spec/should_reek_of.rb +37 -0
- data/lib/reek/spec/should_reek_only_of.rb +37 -0
- data/lib/reek/spec.rb +51 -0
- data/lib/reek.rb +8 -4
- data/reek.gemspec +9 -7
- data/spec/matchers/smell_of_matcher.rb +58 -0
- data/spec/reek/{help_command_spec.rb → cli/help_command_spec.rb} +3 -4
- data/spec/reek/cli/reek_command_spec.rb +46 -0
- data/spec/reek/cli/report_spec.rb +30 -0
- data/spec/reek/{version_command_spec.rb → cli/version_command_spec.rb} +3 -3
- data/spec/reek/cli/yaml_command_spec.rb +47 -0
- data/spec/reek/core/code_context_spec.rb +145 -0
- data/spec/reek/{code_parser_spec.rb → core/code_parser_spec.rb} +7 -6
- data/spec/reek/{config_spec.rb → core/config_spec.rb} +2 -6
- data/spec/reek/{method_context_spec.rb → core/method_context_spec.rb} +16 -36
- data/spec/reek/core/module_context_spec.rb +27 -0
- data/spec/reek/{object_refs_spec.rb → core/object_refs_spec.rb} +5 -6
- data/spec/reek/core/singleton_method_context_spec.rb +9 -0
- data/spec/reek/core/smell_configuration_spec.rb +11 -0
- data/spec/reek/core/stop_context_spec.rb +17 -0
- data/spec/reek/core/warning_collector_spec.rb +27 -0
- data/spec/reek/examiner_spec.rb +103 -0
- data/spec/reek/smell_warning_spec.rb +74 -82
- data/spec/reek/smells/attribute_spec.rb +42 -23
- data/spec/reek/smells/behaves_like_variable_detector.rb +2 -2
- data/spec/reek/smells/boolean_parameter_spec.rb +66 -0
- data/spec/reek/smells/class_variable_spec.rb +60 -75
- data/spec/reek/smells/control_couple_spec.rb +37 -32
- data/spec/reek/smells/data_clump_spec.rb +63 -24
- data/spec/reek/smells/duplication_spec.rb +106 -57
- data/spec/reek/smells/feature_envy_spec.rb +113 -92
- data/spec/reek/smells/irresponsible_module_spec.rb +58 -0
- data/spec/reek/smells/large_class_spec.rb +67 -57
- data/spec/reek/smells/long_method_spec.rb +40 -10
- data/spec/reek/smells/long_parameter_list_spec.rb +50 -28
- data/spec/reek/smells/long_yield_list_spec.rb +57 -0
- data/spec/reek/smells/nested_iterators_spec.rb +115 -7
- data/spec/reek/smells/simulated_polymorphism_spec.rb +56 -20
- data/spec/reek/smells/smell_detector_shared.rb +42 -0
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +42 -0
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +66 -0
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +71 -0
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +120 -0
- data/spec/reek/smells/utility_function_spec.rb +50 -4
- data/spec/reek/source/code_comment_spec.rb +82 -0
- data/spec/reek/source/object_source_spec.rb +20 -0
- data/spec/reek/source/reference_collector_spec.rb +53 -0
- data/spec/reek/{adapters/source_spec.rb → source/source_code_spec.rb} +7 -8
- data/spec/reek/source/tree_dresser_spec.rb +270 -0
- data/spec/reek/spec/should_reek_of_spec.rb +76 -0
- data/spec/reek/spec/should_reek_only_of_spec.rb +89 -0
- data/spec/reek/{adapters → spec}/should_reek_spec.rb +8 -32
- data/spec/samples/all_but_one_masked/clean_one.rb +1 -0
- data/spec/samples/all_but_one_masked/dirty.rb +1 -0
- data/spec/samples/all_but_one_masked/masked.reek +5 -1
- data/spec/samples/clean_due_to_masking/clean_one.rb +1 -0
- data/spec/samples/clean_due_to_masking/clean_three.rb +1 -0
- data/spec/samples/clean_due_to_masking/clean_two.rb +1 -0
- data/spec/samples/clean_due_to_masking/dirty_one.rb +1 -1
- data/spec/samples/clean_due_to_masking/dirty_two.rb +1 -1
- data/spec/samples/clean_due_to_masking/masked.reek +5 -1
- data/spec/samples/config/allow_duplication.reek +3 -0
- data/spec/samples/config/deeper_nested_iterators.reek +3 -0
- data/spec/samples/corrupt_config_file/dirty.rb +1 -1
- data/spec/samples/demo/demo.rb +8 -0
- data/spec/samples/empty_config_file/dirty.rb +2 -1
- data/spec/samples/exceptions.reek +1 -1
- data/spec/samples/inline_config/dirty.rb +16 -0
- data/spec/samples/inline_config/masked.reek +7 -0
- data/spec/samples/mask_some/dirty.rb +8 -0
- data/spec/samples/mask_some/some.reek +8 -0
- data/spec/samples/masked/dirty.rb +2 -1
- data/spec/samples/masked/masked.reek +3 -1
- data/spec/samples/mixed_results/clean_one.rb +1 -0
- data/spec/samples/mixed_results/clean_three.rb +1 -0
- data/spec/samples/mixed_results/clean_two.rb +1 -0
- data/spec/samples/mixed_results/dirty_one.rb +1 -0
- data/spec/samples/mixed_results/dirty_two.rb +1 -0
- data/spec/samples/not_quite_masked/dirty.rb +2 -1
- data/spec/samples/not_quite_masked/masked.reek +1 -1
- data/spec/samples/overrides/masked/dirty.rb +2 -1
- data/spec/samples/overrides/masked/lower.reek +3 -1
- data/spec/samples/three_clean_files/clean_one.rb +1 -0
- data/spec/samples/three_clean_files/clean_three.rb +1 -0
- data/spec/samples/three_clean_files/clean_two.rb +1 -0
- data/spec/samples/two_smelly_files/dirty_one.rb +2 -1
- data/spec/samples/two_smelly_files/dirty_two.rb +2 -1
- data/spec/spec_helper.rb +10 -2
- data/tasks/reek.rake +2 -2
- data/tasks/test.rake +12 -3
- metadata +121 -79
- data/README.rdoc +0 -84
- data/features/profile.feature +0 -34
- data/lib/reek/adapters/application.rb +0 -46
- data/lib/reek/adapters/command_line.rb +0 -77
- data/lib/reek/adapters/config_file.rb +0 -31
- data/lib/reek/adapters/core_extras.rb +0 -64
- data/lib/reek/adapters/rake_task.rb +0 -121
- data/lib/reek/adapters/report.rb +0 -86
- data/lib/reek/adapters/source.rb +0 -72
- data/lib/reek/adapters/spec.rb +0 -133
- data/lib/reek/block_context.rb +0 -62
- data/lib/reek/class_context.rb +0 -41
- data/lib/reek/code_context.rb +0 -68
- data/lib/reek/code_parser.rb +0 -203
- data/lib/reek/configuration.rb +0 -57
- data/lib/reek/detector_stack.rb +0 -37
- data/lib/reek/help_command.rb +0 -14
- data/lib/reek/if_context.rb +0 -18
- data/lib/reek/masking_collection.rb +0 -33
- data/lib/reek/method_context.rb +0 -138
- data/lib/reek/module_context.rb +0 -49
- data/lib/reek/name.rb +0 -57
- data/lib/reek/object_refs.rb +0 -49
- data/lib/reek/reek_command.rb +0 -28
- data/lib/reek/sexp_formatter.rb +0 -10
- data/lib/reek/singleton_method_context.rb +0 -26
- data/lib/reek/smells/uncommunicative_name.rb +0 -84
- data/lib/reek/sniffer.rb +0 -177
- data/lib/reek/stop_context.rb +0 -35
- data/lib/reek/tree_dresser.rb +0 -82
- data/lib/reek/version_command.rb +0 -14
- data/lib/reek/yield_call_context.rb +0 -12
- data/spec/reek/adapters/report_spec.rb +0 -31
- data/spec/reek/adapters/should_reek_of_spec.rb +0 -138
- data/spec/reek/adapters/should_reek_only_of_spec.rb +0 -87
- data/spec/reek/block_context_spec.rb +0 -65
- data/spec/reek/class_context_spec.rb +0 -161
- data/spec/reek/code_context_spec.rb +0 -182
- data/spec/reek/configuration_spec.rb +0 -12
- data/spec/reek/if_context_spec.rb +0 -17
- data/spec/reek/masking_collection_spec.rb +0 -236
- data/spec/reek/module_context_spec.rb +0 -46
- data/spec/reek/name_spec.rb +0 -37
- data/spec/reek/object_source_spec.rb +0 -23
- data/spec/reek/reek_command_spec.rb +0 -45
- data/spec/reek/singleton_method_context_spec.rb +0 -16
- data/spec/reek/smells/smell_detector_spec.rb +0 -36
- data/spec/reek/smells/uncommunicative_name_spec.rb +0 -146
- data/spec/reek/sniffer_spec.rb +0 -11
- data/spec/reek/stop_context_spec.rb +0 -33
- data/spec/reek/tree_dresser_spec.rb +0 -20
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'source_code')
|
|
2
|
+
|
|
3
|
+
module Reek
|
|
4
|
+
module Source
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# Represents a file of Ruby source, whose contents will be examined
|
|
8
|
+
# for code smells.
|
|
9
|
+
#
|
|
10
|
+
class SourceFile < SourceCode
|
|
11
|
+
|
|
12
|
+
def initialize(path)
|
|
13
|
+
@path = path
|
|
14
|
+
super(IO.readlines(@path).join, @path)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def configure(sniffer)
|
|
18
|
+
path = File.expand_path(File.dirname(@path))
|
|
19
|
+
all_config_files(path).each { |cf| ConfigFile.new(cf).configure(sniffer) }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def all_config_files(path)
|
|
25
|
+
return [] unless File.exist?(path)
|
|
26
|
+
parent = File.dirname(path)
|
|
27
|
+
return [] if path == parent
|
|
28
|
+
all_config_files(parent) + Dir["#{path}/*.reek"]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'core_extras')
|
|
2
|
+
|
|
3
|
+
module Reek
|
|
4
|
+
module Source
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# Finds Ruby source files in a filesystem.
|
|
8
|
+
#
|
|
9
|
+
class SourceLocator
|
|
10
|
+
def initialize(paths)
|
|
11
|
+
@paths = paths
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def all_sources
|
|
15
|
+
valid_paths.map {|path| File.new(path).to_reek_source }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def all_ruby_source_files(paths)
|
|
21
|
+
paths.map do |path|
|
|
22
|
+
if test 'd', path
|
|
23
|
+
all_ruby_source_files(Dir["#{path}/**/*.rb"])
|
|
24
|
+
else
|
|
25
|
+
path
|
|
26
|
+
end
|
|
27
|
+
end.flatten.sort
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def valid_paths
|
|
31
|
+
all_ruby_source_files(@paths).select do |path|
|
|
32
|
+
if test 'f', path
|
|
33
|
+
true
|
|
34
|
+
else
|
|
35
|
+
$stderr.puts "Error: No such file - #{path}"
|
|
36
|
+
false
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
module Reek
|
|
2
|
+
module Source
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# Extensions to +Sexp+ to allow +CodeParser+ to navigate the abstract
|
|
6
|
+
# syntax tree more easily.
|
|
7
|
+
#
|
|
8
|
+
module SexpNode
|
|
9
|
+
def self.format(expr)
|
|
10
|
+
case expr
|
|
11
|
+
when Sexp then expr.format_ruby
|
|
12
|
+
else expr.to_s
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def hash
|
|
17
|
+
self.inspect.hash
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def is_language_node?
|
|
21
|
+
first.class == Symbol
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def has_type?(type)
|
|
25
|
+
is_language_node? and first == type
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def each_node(type, ignoring, &blk)
|
|
29
|
+
if block_given?
|
|
30
|
+
look_for(type, ignoring, &blk)
|
|
31
|
+
else
|
|
32
|
+
result = []
|
|
33
|
+
look_for(type, ignoring) {|exp| result << exp}
|
|
34
|
+
result
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
#
|
|
39
|
+
# Carries out a depth-first traversal of this syntax tree, yielding
|
|
40
|
+
# every Sexp of type +target_type+. The traversal ignores any node
|
|
41
|
+
# whose type is listed in the Array +ignoring+.
|
|
42
|
+
#
|
|
43
|
+
def look_for(target_type, ignoring, &blk)
|
|
44
|
+
each do |elem|
|
|
45
|
+
if Sexp === elem then
|
|
46
|
+
elem.look_for(target_type, ignoring, &blk) unless ignoring.include?(elem.first)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
blk.call(self) if first == target_type
|
|
50
|
+
end
|
|
51
|
+
def format_ruby
|
|
52
|
+
return self[0].to_s unless Array === self
|
|
53
|
+
Ruby2Ruby.new.process(deep_copy)
|
|
54
|
+
end
|
|
55
|
+
def deep_copy
|
|
56
|
+
YAML::load(YAML::dump(self))
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
module SexpExtensions
|
|
61
|
+
module AttrasgnNode
|
|
62
|
+
def args() self[3] end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
module CaseNode
|
|
66
|
+
def condition() self[1] end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
module CallNode
|
|
70
|
+
def receiver() self[1] end
|
|
71
|
+
def method_name() self[2] end
|
|
72
|
+
def args() self[3] end
|
|
73
|
+
def arg_names
|
|
74
|
+
args[1..-1].map {|arg| arg[1]}
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
module CvarNode
|
|
79
|
+
def name() self[1] end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
CvasgnNode = CvarNode
|
|
83
|
+
CvdeclNode = CvarNode
|
|
84
|
+
|
|
85
|
+
module MethodNode
|
|
86
|
+
def arg_names
|
|
87
|
+
unless @args
|
|
88
|
+
@args = argslist[1..-1].reject {|param| Sexp === param or param.to_s =~ /^&/}
|
|
89
|
+
end
|
|
90
|
+
@args
|
|
91
|
+
end
|
|
92
|
+
def parameters()
|
|
93
|
+
unless @params
|
|
94
|
+
@params = argslist.reject {|param| Sexp === param}
|
|
95
|
+
end
|
|
96
|
+
@params
|
|
97
|
+
end
|
|
98
|
+
def parameter_names
|
|
99
|
+
parameters[1..-1]
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
module DefnNode
|
|
104
|
+
def name() self[1] end
|
|
105
|
+
def argslist() self[2] end
|
|
106
|
+
def body() self[3] end
|
|
107
|
+
include MethodNode
|
|
108
|
+
def full_name(outer)
|
|
109
|
+
prefix = outer == '' ? '' : "#{outer}#"
|
|
110
|
+
"#{prefix}#{name}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
module DefsNode
|
|
115
|
+
def receiver() self[1] end
|
|
116
|
+
def name() self[2] end
|
|
117
|
+
def argslist() self[3] end
|
|
118
|
+
def body() self[4] end
|
|
119
|
+
include MethodNode
|
|
120
|
+
def full_name(outer)
|
|
121
|
+
prefix = outer == '' ? '' : "#{outer}#"
|
|
122
|
+
"#{prefix}#{SexpNode.format(receiver)}.#{name}"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
module IfNode
|
|
127
|
+
def condition() self[1] end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
module IterNode
|
|
131
|
+
def call() self[1] end
|
|
132
|
+
def args() self[2] end
|
|
133
|
+
def block() self[3] end
|
|
134
|
+
def parameters() self[2] || [] end
|
|
135
|
+
def parameter_names
|
|
136
|
+
result = parameters
|
|
137
|
+
return case result[0]
|
|
138
|
+
when :lasgn
|
|
139
|
+
[result[1]]
|
|
140
|
+
when :masgn
|
|
141
|
+
result[1][1..-1].map {|lasgn| lasgn[1]}
|
|
142
|
+
else
|
|
143
|
+
[]
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
module LitNode
|
|
149
|
+
def value() self[1] end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
module ModuleNode
|
|
153
|
+
def name() self[1] end
|
|
154
|
+
def simple_name
|
|
155
|
+
expr = name
|
|
156
|
+
while Sexp === expr and expr[0] == :colon2
|
|
157
|
+
expr = expr[2]
|
|
158
|
+
end
|
|
159
|
+
expr
|
|
160
|
+
end
|
|
161
|
+
def full_name(outer)
|
|
162
|
+
prefix = outer == '' ? '' : "#{outer}::"
|
|
163
|
+
"#{prefix}#{text_name}"
|
|
164
|
+
end
|
|
165
|
+
def text_name
|
|
166
|
+
SexpNode.format(name)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
module ClassNode
|
|
171
|
+
include ModuleNode
|
|
172
|
+
def superclass() self[2] end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
module YieldNode
|
|
176
|
+
def args() self[1..-1] end
|
|
177
|
+
def arg_names
|
|
178
|
+
args.map {|arg| arg[1]}
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
#
|
|
184
|
+
# Adorns an abstract syntax tree with mix-in modules to make accessing
|
|
185
|
+
# the tree more understandable and less implementation-dependent.
|
|
186
|
+
#
|
|
187
|
+
class TreeDresser
|
|
188
|
+
|
|
189
|
+
def dress(sexp)
|
|
190
|
+
sexp.extend(SexpNode)
|
|
191
|
+
module_name = extensions_for(sexp.sexp_type)
|
|
192
|
+
if SexpExtensions.const_defined?(module_name)
|
|
193
|
+
sexp.extend(SexpExtensions.const_get(module_name))
|
|
194
|
+
end
|
|
195
|
+
sexp[0..-1].each { |sub| dress(sub) if Array === sub }
|
|
196
|
+
sexp
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def extensions_for(node_type)
|
|
200
|
+
"#{node_type.to_s.capitalize}Node"
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
data/lib/reek/source.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'source', 'code_comment')
|
|
2
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'source', 'config_file')
|
|
3
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'source', 'core_extras')
|
|
4
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'source', 'sexp_formatter')
|
|
5
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'source', 'source_code')
|
|
6
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'source', 'source_file')
|
|
7
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'source', 'source_locator')
|
|
8
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'source', 'tree_dresser')
|
|
9
|
+
|
|
10
|
+
module Reek
|
|
11
|
+
|
|
12
|
+
#
|
|
13
|
+
# This module contains a set of classes for interacting with Ruby
|
|
14
|
+
# source code and abstract syntax trees.
|
|
15
|
+
#
|
|
16
|
+
module Source # :nodoc: all
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'examiner')
|
|
2
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'cli', 'report')
|
|
3
|
+
|
|
4
|
+
module Reek
|
|
5
|
+
module Spec
|
|
6
|
+
|
|
7
|
+
#
|
|
8
|
+
# An rspec matcher that matches when the +actual+ has code smells.
|
|
9
|
+
#
|
|
10
|
+
class ShouldReek # :nodoc:
|
|
11
|
+
def matches?(actual)
|
|
12
|
+
@examiner = Examiner.new(actual)
|
|
13
|
+
@examiner.smelly?
|
|
14
|
+
end
|
|
15
|
+
def failure_message_for_should
|
|
16
|
+
"Expected #{@examiner.description} to reek, but it didn't"
|
|
17
|
+
end
|
|
18
|
+
def failure_message_for_should_not
|
|
19
|
+
rpt = Cli::ReportFormatter.format_list(@examiner.smells)
|
|
20
|
+
"Expected no smells, but got:\n#{rpt}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
#
|
|
25
|
+
# Returns +true+ if and only if the target source code contains smells.
|
|
26
|
+
#
|
|
27
|
+
def reek
|
|
28
|
+
ShouldReek.new
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'examiner')
|
|
2
|
+
|
|
3
|
+
module Reek
|
|
4
|
+
module Spec
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# An rspec matcher that matches when the +actual+ has the specified
|
|
8
|
+
# code smell.
|
|
9
|
+
#
|
|
10
|
+
class ShouldReekOf # :nodoc:
|
|
11
|
+
def initialize(klass, patterns)
|
|
12
|
+
@klass = klass
|
|
13
|
+
@patterns = patterns
|
|
14
|
+
end
|
|
15
|
+
def matches?(actual)
|
|
16
|
+
@examiner = Examiner.new(actual)
|
|
17
|
+
@all_smells = @examiner.smells
|
|
18
|
+
@all_smells.any? {|warning| warning.matches?(@klass, @patterns)}
|
|
19
|
+
end
|
|
20
|
+
def failure_message_for_should
|
|
21
|
+
"Expected #{@examiner.description} to reek of #{@klass}, but it didn't"
|
|
22
|
+
end
|
|
23
|
+
def failure_message_for_should_not
|
|
24
|
+
"Expected #{@examiner.description} not to reek of #{@klass}, but it did"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
#
|
|
29
|
+
# Checks the target source code for instances of +smell_class+,
|
|
30
|
+
# and returns +true+ only if one of them has a report string matching
|
|
31
|
+
# all of the +patterns+.
|
|
32
|
+
#
|
|
33
|
+
def reek_of(smell_class, *patterns)
|
|
34
|
+
ShouldReekOf.new(smell_class, patterns)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'examiner')
|
|
2
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'cli', 'report')
|
|
3
|
+
|
|
4
|
+
module Reek
|
|
5
|
+
module Spec
|
|
6
|
+
|
|
7
|
+
#
|
|
8
|
+
# An rspec matcher that matches when the +actual+ has the specified
|
|
9
|
+
# code smell and no others.
|
|
10
|
+
#
|
|
11
|
+
class ShouldReekOnlyOf < ShouldReekOf # :nodoc:
|
|
12
|
+
def matches?(actual)
|
|
13
|
+
matches_examiner?(Examiner.new(actual))
|
|
14
|
+
end
|
|
15
|
+
def matches_examiner?(examiner)
|
|
16
|
+
@examiner = examiner
|
|
17
|
+
@warnings = @examiner.smells
|
|
18
|
+
@warnings.length == 1 and @warnings[0].matches?(@klass, @patterns)
|
|
19
|
+
end
|
|
20
|
+
def failure_message_for_should
|
|
21
|
+
rpt = Cli::ReportFormatter.format_list(@warnings)
|
|
22
|
+
"Expected #{@examiner.description} to reek only of #{@klass}, but got:\n#{rpt}"
|
|
23
|
+
end
|
|
24
|
+
def failure_message_for_should_not
|
|
25
|
+
"Expected #{@examiner.description} not to reek only of #{@klass}, but it did"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# As for reek_of, but the matched smell warning must be the only warning of
|
|
31
|
+
# any kind in the target source code's Reek report.
|
|
32
|
+
#
|
|
33
|
+
def reek_only_of(smell_class, *patterns)
|
|
34
|
+
ShouldReekOnlyOf.new(smell_class, patterns)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/reek/spec.rb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec', 'should_reek')
|
|
2
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec', 'should_reek_of')
|
|
3
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec', 'should_reek_only_of')
|
|
4
|
+
|
|
5
|
+
module Reek
|
|
6
|
+
|
|
7
|
+
#
|
|
8
|
+
# Provides matchers for Rspec, making it easy to check code quality.
|
|
9
|
+
#
|
|
10
|
+
# If you require this module somewhere within your spec (or in your spec_helper),
|
|
11
|
+
# Reek will arrange to update Spec::Runner's config so that it knows about the
|
|
12
|
+
# matchers defined here.
|
|
13
|
+
#
|
|
14
|
+
# === Examples
|
|
15
|
+
#
|
|
16
|
+
# Here's a spec that ensures there are no active code smells in the current project:
|
|
17
|
+
#
|
|
18
|
+
# describe 'source code quality' do
|
|
19
|
+
# Dir['lib/**/*.rb'].each do |path|
|
|
20
|
+
# it "reports no smells in #{path}" do
|
|
21
|
+
# File.new(path).should_not reek
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# And here's an even simpler way to do the same:
|
|
27
|
+
#
|
|
28
|
+
# it 'has no code smells' do
|
|
29
|
+
# Dir['lib/**/*.rb'].should_not reek
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# Here's a simple check of a code fragment:
|
|
33
|
+
#
|
|
34
|
+
# 'def equals(other) other.thing == self.thing end'.should_not reek
|
|
35
|
+
#
|
|
36
|
+
# To check for specific smells, use something like this:
|
|
37
|
+
#
|
|
38
|
+
# ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'
|
|
39
|
+
# ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
|
|
40
|
+
# ruby.should reek_of(:Duplication, /@other.thing.foo/)
|
|
41
|
+
# ruby.should_not reek_of(:FeatureEnvy)
|
|
42
|
+
#
|
|
43
|
+
module Spec
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if Object.const_defined?(:Spec)
|
|
48
|
+
Spec::Runner.configure do |config|
|
|
49
|
+
config.include(Reek::Spec)
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/reek.rb
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
#
|
|
2
|
+
# Reek's core functionality
|
|
3
|
+
#
|
|
4
|
+
module Reek
|
|
5
|
+
VERSION = '1.2.8'
|
|
5
6
|
end
|
|
7
|
+
|
|
8
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'reek', 'examiner')
|
|
9
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'reek', 'smell_warning')
|
data/reek.gemspec
CHANGED
|
@@ -2,27 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |s|
|
|
4
4
|
s.name = %q{reek}
|
|
5
|
-
s.version = "1.2.
|
|
5
|
+
s.version = "1.2.8"
|
|
6
6
|
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
8
8
|
s.authors = ["Kevin Rutherford"]
|
|
9
|
-
s.date = %q{
|
|
9
|
+
s.date = %q{2010-04-26}
|
|
10
10
|
s.default_executable = %q{reek}
|
|
11
11
|
s.description = %q{Reek is a tool that examines Ruby classes, modules and methods
|
|
12
12
|
and reports any code smells it finds.
|
|
13
13
|
}
|
|
14
14
|
s.email = ["kevin@rutherford-software.com"]
|
|
15
15
|
s.executables = ["reek"]
|
|
16
|
-
s.extra_rdoc_files = ["History.txt", "License.txt"
|
|
17
|
-
s.files = ["History.txt", "License.txt", "README.
|
|
16
|
+
s.extra_rdoc_files = ["History.txt", "License.txt"]
|
|
17
|
+
s.files = [".yardopts", "History.txt", "License.txt", "README.md", "Rakefile", "bin/reek", "config/defaults.reek", "features/api.feature", "features/masking_smells.feature", "features/options.feature", "features/rake_task.feature", "features/reports.feature", "features/samples.feature", "features/stdin.feature", "features/step_definitions/reek_steps.rb", "features/support/env.rb", "features/yaml.feature", "lib/reek.rb", "lib/reek/cli/application.rb", "lib/reek/cli/command_line.rb", "lib/reek/cli/help_command.rb", "lib/reek/cli/reek_command.rb", "lib/reek/cli/report.rb", "lib/reek/cli/version_command.rb", "lib/reek/cli/yaml_command.rb", "lib/reek/core/code_context.rb", "lib/reek/core/code_parser.rb", "lib/reek/core/method_context.rb", "lib/reek/core/module_context.rb", "lib/reek/core/object_refs.rb", "lib/reek/core/singleton_method_context.rb", "lib/reek/core/smell_configuration.rb", "lib/reek/core/sniffer.rb", "lib/reek/core/stop_context.rb", "lib/reek/core/warning_collector.rb", "lib/reek/examiner.rb", "lib/reek/rake/task.rb", "lib/reek/smell_warning.rb", "lib/reek/smells.rb", "lib/reek/smells/attribute.rb", "lib/reek/smells/boolean_parameter.rb", "lib/reek/smells/class_variable.rb", "lib/reek/smells/control_couple.rb", "lib/reek/smells/data_clump.rb", "lib/reek/smells/duplication.rb", "lib/reek/smells/feature_envy.rb", "lib/reek/smells/irresponsible_module.rb", "lib/reek/smells/large_class.rb", "lib/reek/smells/long_method.rb", "lib/reek/smells/long_parameter_list.rb", "lib/reek/smells/long_yield_list.rb", "lib/reek/smells/nested_iterators.rb", "lib/reek/smells/simulated_polymorphism.rb", "lib/reek/smells/smell_detector.rb", "lib/reek/smells/uncommunicative_method_name.rb", "lib/reek/smells/uncommunicative_module_name.rb", "lib/reek/smells/uncommunicative_parameter_name.rb", "lib/reek/smells/uncommunicative_variable_name.rb", "lib/reek/smells/utility_function.rb", "lib/reek/source.rb", "lib/reek/source/code_comment.rb", "lib/reek/source/config_file.rb", "lib/reek/source/core_extras.rb", "lib/reek/source/reference_collector.rb", "lib/reek/source/sexp_formatter.rb", "lib/reek/source/source_code.rb", "lib/reek/source/source_file.rb", "lib/reek/source/source_locator.rb", "lib/reek/source/tree_dresser.rb", "lib/reek/spec.rb", "lib/reek/spec/should_reek.rb", "lib/reek/spec/should_reek_of.rb", "lib/reek/spec/should_reek_only_of.rb", "reek.gemspec", "spec/matchers/smell_of_matcher.rb", "spec/reek/cli/help_command_spec.rb", "spec/reek/cli/reek_command_spec.rb", "spec/reek/cli/report_spec.rb", "spec/reek/cli/version_command_spec.rb", "spec/reek/cli/yaml_command_spec.rb", "spec/reek/core/code_context_spec.rb", "spec/reek/core/code_parser_spec.rb", "spec/reek/core/config_spec.rb", "spec/reek/core/method_context_spec.rb", "spec/reek/core/module_context_spec.rb", "spec/reek/core/object_refs_spec.rb", "spec/reek/core/singleton_method_context_spec.rb", "spec/reek/core/smell_configuration_spec.rb", "spec/reek/core/stop_context_spec.rb", "spec/reek/core/warning_collector_spec.rb", "spec/reek/examiner_spec.rb", "spec/reek/smell_warning_spec.rb", "spec/reek/smells/attribute_spec.rb", "spec/reek/smells/behaves_like_variable_detector.rb", "spec/reek/smells/boolean_parameter_spec.rb", "spec/reek/smells/class_variable_spec.rb", "spec/reek/smells/control_couple_spec.rb", "spec/reek/smells/data_clump_spec.rb", "spec/reek/smells/duplication_spec.rb", "spec/reek/smells/feature_envy_spec.rb", "spec/reek/smells/irresponsible_module_spec.rb", "spec/reek/smells/large_class_spec.rb", "spec/reek/smells/long_method_spec.rb", "spec/reek/smells/long_parameter_list_spec.rb", "spec/reek/smells/long_yield_list_spec.rb", "spec/reek/smells/nested_iterators_spec.rb", "spec/reek/smells/simulated_polymorphism_spec.rb", "spec/reek/smells/smell_detector_shared.rb", "spec/reek/smells/uncommunicative_method_name_spec.rb", "spec/reek/smells/uncommunicative_module_name_spec.rb", "spec/reek/smells/uncommunicative_parameter_name_spec.rb", "spec/reek/smells/uncommunicative_variable_name_spec.rb", "spec/reek/smells/utility_function_spec.rb", "spec/reek/source/code_comment_spec.rb", "spec/reek/source/object_source_spec.rb", "spec/reek/source/reference_collector_spec.rb", "spec/reek/source/source_code_spec.rb", "spec/reek/source/tree_dresser_spec.rb", "spec/reek/spec/should_reek_of_spec.rb", "spec/reek/spec/should_reek_only_of_spec.rb", "spec/reek/spec/should_reek_spec.rb", "spec/samples/all_but_one_masked/clean_one.rb", "spec/samples/all_but_one_masked/dirty.rb", "spec/samples/all_but_one_masked/masked.reek", "spec/samples/clean_due_to_masking/clean_one.rb", "spec/samples/clean_due_to_masking/clean_three.rb", "spec/samples/clean_due_to_masking/clean_two.rb", "spec/samples/clean_due_to_masking/dirty_one.rb", "spec/samples/clean_due_to_masking/dirty_two.rb", "spec/samples/clean_due_to_masking/masked.reek", "spec/samples/config/allow_duplication.reek", "spec/samples/config/deeper_nested_iterators.reek", "spec/samples/corrupt_config_file/corrupt.reek", "spec/samples/corrupt_config_file/dirty.rb", "spec/samples/demo/demo.rb", "spec/samples/empty_config_file/dirty.rb", "spec/samples/empty_config_file/empty.reek", "spec/samples/exceptions.reek", "spec/samples/inline_config/dirty.rb", "spec/samples/inline_config/masked.reek", "spec/samples/inline.rb", "spec/samples/mask_some/dirty.rb", "spec/samples/mask_some/some.reek", "spec/samples/masked/dirty.rb", "spec/samples/masked/masked.reek", "spec/samples/mixed_results/clean_one.rb", "spec/samples/mixed_results/clean_three.rb", "spec/samples/mixed_results/clean_two.rb", "spec/samples/mixed_results/dirty_one.rb", "spec/samples/mixed_results/dirty_two.rb", "spec/samples/not_quite_masked/dirty.rb", "spec/samples/not_quite_masked/masked.reek", "spec/samples/optparse.rb", "spec/samples/overrides/masked/dirty.rb", "spec/samples/overrides/masked/lower.reek", "spec/samples/overrides/upper.reek", "spec/samples/redcloth.rb", "spec/samples/three_clean_files/clean_one.rb", "spec/samples/three_clean_files/clean_three.rb", "spec/samples/three_clean_files/clean_two.rb", "spec/samples/two_smelly_files/dirty_one.rb", "spec/samples/two_smelly_files/dirty_two.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/reek.rake", "tasks/test.rake"]
|
|
18
18
|
s.homepage = %q{http://wiki.github.com/kevinrutherford/reek}
|
|
19
19
|
s.post_install_message = %q{
|
|
20
|
-
|
|
20
|
+
Thank you for downloading Reek. For info:
|
|
21
|
+
- see the reek wiki http://wiki.github.com/kevinrutherford/reek
|
|
22
|
+
- follow @rubyreek on twitter
|
|
21
23
|
}
|
|
22
|
-
s.rdoc_options = ["--main", "README.
|
|
24
|
+
s.rdoc_options = ["--main", "README.md"]
|
|
23
25
|
s.require_paths = ["lib"]
|
|
24
26
|
s.rubyforge_project = %q{reek}
|
|
25
|
-
s.rubygems_version = %q{1.3.
|
|
27
|
+
s.rubygems_version = %q{1.3.6}
|
|
26
28
|
s.summary = %q{Code smell detector for Ruby}
|
|
27
29
|
|
|
28
30
|
if s.respond_to? :specification_version then
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module SmellOfMatcher
|
|
2
|
+
class SmellOf
|
|
3
|
+
def initialize(klass, *expected_smells)
|
|
4
|
+
@klass = klass
|
|
5
|
+
@expected_smells = expected_smells
|
|
6
|
+
@config = {}
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def failure_message_for_should
|
|
10
|
+
"Expected #{@source.desc} to smell of #{@klass}, but it didn't: #{@reason}"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def failure_message_for_should_not
|
|
14
|
+
"Expected #{@source.desc} not to smell of #{@klass}, but it did"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def matches?(src)
|
|
18
|
+
@source = src.to_reek_source
|
|
19
|
+
ctx = MethodContext.new(nil, @source.syntax_tree)
|
|
20
|
+
detector = @klass.new(@source.desc, @klass.default_config.merge(@config))
|
|
21
|
+
detector.examine(ctx)
|
|
22
|
+
actual_smells = detector.smells_found.to_a
|
|
23
|
+
if actual_smells.empty?
|
|
24
|
+
@reason = 'no smells found by detector'
|
|
25
|
+
return false
|
|
26
|
+
end
|
|
27
|
+
return false if actual_smells.any? do |expected_smell|
|
|
28
|
+
@reason = "Found #{expected_smell.smell_class}/#{expected_smell.subclass}" &&
|
|
29
|
+
expected_smell.smell_class != @klass::SMELL_CLASS &&
|
|
30
|
+
expected_smell.subclass != @klass::SMELL_SUBCLASS
|
|
31
|
+
end
|
|
32
|
+
return actual_smells.length == 1 if @expected_smells.empty?
|
|
33
|
+
return false unless @expected_smells.length == actual_smells.length
|
|
34
|
+
@expected_smells.each_with_index do |expected_smell,index|
|
|
35
|
+
expected_smell.each do |(key,value)|
|
|
36
|
+
if actual_smells[index].smell[key] != value
|
|
37
|
+
@reason = "#{key} != #{value}"
|
|
38
|
+
return false
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
true
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def with_config(options)
|
|
46
|
+
@config = options
|
|
47
|
+
self
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def smell_of(klass, *smells)
|
|
52
|
+
SmellOf.new(klass, *smells)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
Spec::Runner.configure do |config|
|
|
57
|
+
config.include(SmellOfMatcher)
|
|
58
|
+
end
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
require File.dirname(__FILE__)
|
|
1
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'spec_helper')
|
|
2
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'cli', 'help_command')
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
include Reek
|
|
4
|
+
include Reek::Cli
|
|
6
5
|
|
|
7
6
|
describe HelpCommand do
|
|
8
7
|
before :each do
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'spec_helper')
|
|
2
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'cli', 'reek_command')
|
|
3
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'cli', 'report')
|
|
4
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'examiner')
|
|
5
|
+
|
|
6
|
+
include Reek
|
|
7
|
+
include Reek::Cli
|
|
8
|
+
|
|
9
|
+
describe ReekCommand do
|
|
10
|
+
before :each do
|
|
11
|
+
@view = mock('view', :null_object => true)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context 'with smells' do
|
|
15
|
+
before :each do
|
|
16
|
+
examiner = Examiner.new('def x(); end')
|
|
17
|
+
@cmd = ReekCommand.new(QuietReport, ['def x(); end'])
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'displays the correct text on the view' do
|
|
21
|
+
@view.should_receive(:output).with(/UncommunicativeName/)
|
|
22
|
+
@cmd.execute(@view)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'tells the view it succeeded' do
|
|
26
|
+
@view.should_receive(:report_smells)
|
|
27
|
+
@cmd.execute(@view)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context 'with no smells' do
|
|
32
|
+
before :each do
|
|
33
|
+
@cmd = ReekCommand.new(QuietReport, ['def clean(); end'])
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'displays nothing on the view' do
|
|
37
|
+
@view.should_receive(:output).with('')
|
|
38
|
+
@cmd.execute(@view)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'tells the view it succeeded' do
|
|
42
|
+
@view.should_receive(:report_success)
|
|
43
|
+
@cmd.execute(@view)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|