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
data/README.rdoc
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
= Reek -- code smell detection for Ruby
|
|
2
|
-
|
|
3
|
-
Reek is a tool that examines Ruby classes, modules and methods and
|
|
4
|
-
reports any code smells it finds. Install it like this:
|
|
5
|
-
|
|
6
|
-
$ gem install reek
|
|
7
|
-
|
|
8
|
-
and run it like this:
|
|
9
|
-
|
|
10
|
-
$ reek [options] [dir_or_source_file]*
|
|
11
|
-
|
|
12
|
-
For a full list of command-line options see the Reek
|
|
13
|
-
wiki[http://wiki.github.com/kevinrutherford/reek/command-line-options]
|
|
14
|
-
or run
|
|
15
|
-
|
|
16
|
-
$ reek --help
|
|
17
|
-
|
|
18
|
-
== Example
|
|
19
|
-
|
|
20
|
-
Imagine a source file <tt>csv_writer.rb</tt> containing:
|
|
21
|
-
|
|
22
|
-
class CsvWriter
|
|
23
|
-
def write_line(fields)
|
|
24
|
-
if (fields.length == 0)
|
|
25
|
-
puts
|
|
26
|
-
else
|
|
27
|
-
write_field(fields[0])
|
|
28
|
-
1.upto(fields.length-1) do |i|
|
|
29
|
-
print ","
|
|
30
|
-
write_field(fields[i])
|
|
31
|
-
end
|
|
32
|
-
puts
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
#...
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
Reek will report the following code smells in this file:
|
|
40
|
-
|
|
41
|
-
$ reek csv_writer.rb
|
|
42
|
-
CsvWriter#write_line calls fields.length multiple times (Duplication)
|
|
43
|
-
CsvWriter#write_line has approx 6 statements (Long Method)
|
|
44
|
-
CsvWriter#write_line/block has the variable name 'i' (Uncommunicative Name)
|
|
45
|
-
|
|
46
|
-
== Features
|
|
47
|
-
|
|
48
|
-
Reek currently includes checks for some aspects of the following smells:
|
|
49
|
-
|
|
50
|
-
* {Control Couple}[http://wiki.github.com/kevinrutherford/reek/control-couple]
|
|
51
|
-
* {Data Clump}[http://wiki.github.com/kevinrutherford/reek/data-clump]
|
|
52
|
-
* {Feature Envy}[http://wiki.github.com/kevinrutherford/reek/feature-envy]
|
|
53
|
-
* {Large Class}[http://wiki.github.com/kevinrutherford/reek/large-class]
|
|
54
|
-
* {Long Method}[http://wiki.github.com/kevinrutherford/reek/long-method]
|
|
55
|
-
* {Long Parameter List}[http://wiki.github.com/kevinrutherford/reek/long-parameter-list]
|
|
56
|
-
* {Simulated Polymorphism}[http://wiki.github.com/kevinrutherford/reek/simulated-polymorphism]
|
|
57
|
-
* {Uncommunicative Name}[http://wiki.github.com/kevinrutherford/reek/uncommunicative-name]
|
|
58
|
-
|
|
59
|
-
...and more. See the Reek wiki[http://wiki.github.com/kevinrutherford/reek/code-smells]
|
|
60
|
-
for up to date details of exactly what Reek will check in your code.
|
|
61
|
-
|
|
62
|
-
=== Tool Integration
|
|
63
|
-
|
|
64
|
-
Reek integrates with many of your favourite tools:
|
|
65
|
-
|
|
66
|
-
* Use <tt>Reek::RakeTask</tt> to easily add Reek to your Rakefile
|
|
67
|
-
* Use <tt>Reek::Spec</tt> to add the <tt>should_not reek</tt> custom matcher to your Rspec examples
|
|
68
|
-
* Reek is fully compliant with Ruby 1.8.6, 1.8.7 and 1.9.1
|
|
69
|
-
|
|
70
|
-
=== Dependencies
|
|
71
|
-
|
|
72
|
-
Reek makes use of the following other gems:
|
|
73
|
-
|
|
74
|
-
* ruby_parser
|
|
75
|
-
* sexp_processor
|
|
76
|
-
* ruby2ruby
|
|
77
|
-
|
|
78
|
-
== Learn More
|
|
79
|
-
|
|
80
|
-
Find out more about Reek from any of the following sources:
|
|
81
|
-
|
|
82
|
-
* Browse the Reek documentation at http://wiki.github.com/kevinrutherford/reek
|
|
83
|
-
* Browse the code or install the latest cutting-edge beta version from http://github.com/kevinrutherford/reek/tree
|
|
84
|
-
* Read the code API at http://rdoc.info/projects/kevinrutherford/reek
|
data/features/profile.feature
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
@profile
|
|
2
|
-
Feature: Reek's configuration can be based on any number of canned profiles
|
|
3
|
-
The starting point for configuring the smell detectors can be
|
|
4
|
-
selected from a list of supplied config files.
|
|
5
|
-
|
|
6
|
-
# Scenario: XP profile reveals Attribute smells
|
|
7
|
-
# When I run reek --profile xp spec/samples/not_quite_masked/dirty.rb
|
|
8
|
-
# Then the exit status indicates smells
|
|
9
|
-
# And it reports:
|
|
10
|
-
# """
|
|
11
|
-
# spec/samples/not_quite_masked/dirty.rb -- 5 warnings (+2 masked):
|
|
12
|
-
# Dirty declares the attribute property (Attribute)
|
|
13
|
-
# Dirty has the variable name '@s' (Uncommunicative Name)
|
|
14
|
-
# Dirty#a calls @s.title twice (Duplication)
|
|
15
|
-
# Dirty#a calls puts(@s.title) twice (Duplication)
|
|
16
|
-
# Dirty#a has the name 'a' (Uncommunicative Name)
|
|
17
|
-
#
|
|
18
|
-
# """
|
|
19
|
-
#
|
|
20
|
-
# Scenario: XP profile works with unmasked smells
|
|
21
|
-
# When I run reek --show-all --profile xp spec/samples/not_quite_masked/dirty.rb
|
|
22
|
-
# Then the exit status indicates smells
|
|
23
|
-
# And it reports:
|
|
24
|
-
# """
|
|
25
|
-
# spec/samples/not_quite_masked/dirty.rb -- 5 warnings (+2 masked):
|
|
26
|
-
# Dirty declares the attribute property (Attribute)
|
|
27
|
-
# Dirty has the variable name '@s' (Uncommunicative Name)
|
|
28
|
-
# Dirty#a calls @s.title twice (Duplication)
|
|
29
|
-
# Dirty#a calls puts(@s.title) twice (Duplication)
|
|
30
|
-
# Dirty#a has the name 'a' (Uncommunicative Name)
|
|
31
|
-
# (masked) Dirty#a/block has the variable name 'x' (Uncommunicative Name)
|
|
32
|
-
# (masked) Dirty#a/block/block is nested (Nested Iterators)
|
|
33
|
-
#
|
|
34
|
-
# """
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
require 'reek/adapters/command_line'
|
|
2
|
-
require 'reek/adapters/source'
|
|
3
|
-
require 'reek/adapters/core_extras'
|
|
4
|
-
|
|
5
|
-
module Reek
|
|
6
|
-
|
|
7
|
-
#
|
|
8
|
-
# Represents an instance of a Reek application.
|
|
9
|
-
# This is the entry point for all invocations of Reek from the
|
|
10
|
-
# command line.
|
|
11
|
-
#
|
|
12
|
-
class Application
|
|
13
|
-
|
|
14
|
-
STATUS_SUCCESS = 0
|
|
15
|
-
STATUS_ERROR = 1
|
|
16
|
-
STATUS_SMELLS = 2
|
|
17
|
-
|
|
18
|
-
def initialize(argv)
|
|
19
|
-
@options = Options.new(argv)
|
|
20
|
-
@status = STATUS_SUCCESS
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def execute
|
|
24
|
-
begin
|
|
25
|
-
cmd = @options.parse
|
|
26
|
-
cmd.execute(self)
|
|
27
|
-
rescue Exception => error
|
|
28
|
-
$stderr.puts "Error: #{error}"
|
|
29
|
-
@status = STATUS_ERROR
|
|
30
|
-
end
|
|
31
|
-
return @status
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def output(text)
|
|
35
|
-
puts text
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def report_success
|
|
39
|
-
@status = STATUS_SUCCESS
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def report_smells
|
|
43
|
-
@status = STATUS_SMELLS
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
require 'optparse'
|
|
2
|
-
require 'reek'
|
|
3
|
-
require 'reek/adapters/report'
|
|
4
|
-
require 'reek/help_command'
|
|
5
|
-
require 'reek/reek_command'
|
|
6
|
-
require 'reek/version_command'
|
|
7
|
-
|
|
8
|
-
module Reek
|
|
9
|
-
|
|
10
|
-
class Options
|
|
11
|
-
|
|
12
|
-
def initialize(argv)
|
|
13
|
-
@argv = argv
|
|
14
|
-
@parser = OptionParser.new
|
|
15
|
-
@report_class = VerboseReport
|
|
16
|
-
@show_all = false
|
|
17
|
-
@command = nil
|
|
18
|
-
set_options
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def banner
|
|
22
|
-
progname = @parser.program_name
|
|
23
|
-
# SMELL:
|
|
24
|
-
# The following banner isn't really correct. Help, Version and Reek
|
|
25
|
-
# are really sub-commands (in the git/svn sense) and so the usage
|
|
26
|
-
# banner should show three different command-lines. The other
|
|
27
|
-
# options are all flags for the Reek sub-command.
|
|
28
|
-
#
|
|
29
|
-
# reek -h|--help Display a help message
|
|
30
|
-
#
|
|
31
|
-
# reek -v|--version Output the tool's version number
|
|
32
|
-
#
|
|
33
|
-
# reek [options] files List the smells in the given files
|
|
34
|
-
# -a|--[no-]show-all Report masked smells
|
|
35
|
-
# -q|-[no-]quiet Only list files that have smells
|
|
36
|
-
# files Names of files or dirs to be checked
|
|
37
|
-
#
|
|
38
|
-
return <<EOB
|
|
39
|
-
Usage: #{progname} [options] [files]
|
|
40
|
-
|
|
41
|
-
Examples:
|
|
42
|
-
|
|
43
|
-
#{progname} lib/*.rb
|
|
44
|
-
#{progname} -q -a lib
|
|
45
|
-
cat my_class.rb | #{progname}
|
|
46
|
-
|
|
47
|
-
See http://wiki.github.com/kevinrutherford/reek for detailed help.
|
|
48
|
-
|
|
49
|
-
EOB
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def parse
|
|
53
|
-
@parser.parse!(@argv)
|
|
54
|
-
@command ||= ReekCommand.new(@argv, @report_class, @show_all)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def set_options
|
|
58
|
-
@parser.banner = banner
|
|
59
|
-
@parser.separator "Common options:"
|
|
60
|
-
@parser.on("-h", "--help", "Show this message") do
|
|
61
|
-
@command = HelpCommand.new(@parser)
|
|
62
|
-
end
|
|
63
|
-
@parser.on("-v", "--version", "Show version") do
|
|
64
|
-
@command = VersionCommand.new(@parser.program_name)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
@parser.separator "\nReport formatting:"
|
|
68
|
-
@parser.on("-a", "--[no-]show-all", "Show all smells, including those masked by config settings") do |opt|
|
|
69
|
-
@show_all = opt
|
|
70
|
-
end
|
|
71
|
-
@parser.on("-q", "--[no-]quiet", "Suppress headings for smell-free source files") do |opt|
|
|
72
|
-
@report_class = opt ? QuietReport : VerboseReport
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
require 'yaml'
|
|
2
|
-
|
|
3
|
-
module Reek
|
|
4
|
-
class ConfigFile
|
|
5
|
-
|
|
6
|
-
def initialize(file_path)
|
|
7
|
-
@file_path = file_path
|
|
8
|
-
@hash = YAML.load_file(@file_path) || {}
|
|
9
|
-
problem('not a Hash') unless Hash === @hash
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
#
|
|
13
|
-
# Configure the given sniffer using the contents of the config file.
|
|
14
|
-
#
|
|
15
|
-
def configure(sniffer)
|
|
16
|
-
@hash.each { |klass_name, config|
|
|
17
|
-
sniffer.configure(find_class(klass_name), config)
|
|
18
|
-
}
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def find_class(name)
|
|
22
|
-
klass = Reek::Smells.const_get(name)
|
|
23
|
-
problem("#{name} is not a code smell") unless klass
|
|
24
|
-
klass
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def problem(reason)
|
|
28
|
-
raise "Invalid configuration file \"#{File.basename(@file_path)}\" -- #{reason}"
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
require 'reek/adapters/source'
|
|
2
|
-
require 'reek/sniffer'
|
|
3
|
-
|
|
4
|
-
class Object
|
|
5
|
-
#
|
|
6
|
-
# Creates a new +Sniffer+ that assumes this object contains Ruby source
|
|
7
|
-
# code and examines that code for smells. Calls +to_reek_source+ on self
|
|
8
|
-
# to obtain the +Source+ object wrapper.
|
|
9
|
-
#
|
|
10
|
-
def sniff
|
|
11
|
-
Reek::Sniffer.new(self.to_reek_source)
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
class File
|
|
16
|
-
#
|
|
17
|
-
# Creates a new +Source+ that assumes this File contains Ruby source
|
|
18
|
-
# code and prepares it to be examined for code smells.
|
|
19
|
-
#
|
|
20
|
-
def to_reek_source
|
|
21
|
-
Reek::SourceFile.new(self)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
class IO
|
|
26
|
-
#
|
|
27
|
-
# Creates a new +Source+ that assumes this IO stream contains Ruby source
|
|
28
|
-
# code and prepares it to be examined for code smells.
|
|
29
|
-
#
|
|
30
|
-
def to_reek_source(description = 'io')
|
|
31
|
-
Reek::Source.new(self.readlines.join, description)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
class String
|
|
36
|
-
#
|
|
37
|
-
# Creates a new +Source+ that assumes this string contains Ruby source
|
|
38
|
-
# code and prepares it to be examined for code smells.
|
|
39
|
-
#
|
|
40
|
-
def to_reek_source
|
|
41
|
-
Reek::Source.new(self, 'string')
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
class Array
|
|
46
|
-
def paths
|
|
47
|
-
self.map do |path|
|
|
48
|
-
if test 'd', path
|
|
49
|
-
Dir["#{path}/**/*.rb"].paths
|
|
50
|
-
else
|
|
51
|
-
path
|
|
52
|
-
end
|
|
53
|
-
end.flatten.sort
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
#
|
|
57
|
-
# Creates a new +Sniffer+ that assumes this Array contains the names
|
|
58
|
-
# of Ruby source files and examines those files for smells.
|
|
59
|
-
#
|
|
60
|
-
def sniff
|
|
61
|
-
sniffers = paths.map {|path| File.new(path).sniff}
|
|
62
|
-
Reek::SnifferSet.new(sniffers, 'dir')
|
|
63
|
-
end
|
|
64
|
-
end
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
# Define a task library for running reek.
|
|
4
|
-
|
|
5
|
-
require 'rake'
|
|
6
|
-
require 'rake/tasklib'
|
|
7
|
-
|
|
8
|
-
module Reek
|
|
9
|
-
|
|
10
|
-
# A Rake task that runs reek on a set of source files.
|
|
11
|
-
#
|
|
12
|
-
# Example:
|
|
13
|
-
#
|
|
14
|
-
# Reek::RakeTask.new do |t|
|
|
15
|
-
# t.fail_on_error = false
|
|
16
|
-
# end
|
|
17
|
-
#
|
|
18
|
-
# This will create a task that can be run with:
|
|
19
|
-
#
|
|
20
|
-
# rake reek
|
|
21
|
-
#
|
|
22
|
-
# Examples:
|
|
23
|
-
#
|
|
24
|
-
# rake reek # checks lib/**/*.rb
|
|
25
|
-
# rake reek REEK_SRC=just_one_file.rb # checks a single source file
|
|
26
|
-
# rake reek REEK_OPTS=-s # sorts the report by smell
|
|
27
|
-
#
|
|
28
|
-
class RakeTask < ::Rake::TaskLib
|
|
29
|
-
|
|
30
|
-
# Name of reek task.
|
|
31
|
-
# Defaults to :reek.
|
|
32
|
-
attr_accessor :name
|
|
33
|
-
|
|
34
|
-
# Array of directories to be added to $LOAD_PATH before running reek.
|
|
35
|
-
# Defaults to ['<the absolute path to reek's lib directory>']
|
|
36
|
-
attr_accessor :libs
|
|
37
|
-
|
|
38
|
-
# Glob pattern to match source files.
|
|
39
|
-
# Setting the REEK_SRC environment variable overrides this.
|
|
40
|
-
# Defaults to 'lib/**/*.rb'.
|
|
41
|
-
attr_accessor :source_files
|
|
42
|
-
|
|
43
|
-
# String containing commandline options to be passed to Reek.
|
|
44
|
-
# Setting the REEK_OPTS environment variable overrides this value.
|
|
45
|
-
# Defaults to ''.
|
|
46
|
-
attr_accessor :reek_opts
|
|
47
|
-
|
|
48
|
-
# Array of commandline options to pass to ruby. Defaults to [].
|
|
49
|
-
attr_accessor :ruby_opts
|
|
50
|
-
|
|
51
|
-
# Whether or not to fail Rake when an error occurs (typically when smells are found).
|
|
52
|
-
# Defaults to true.
|
|
53
|
-
attr_accessor :fail_on_error
|
|
54
|
-
|
|
55
|
-
# Use verbose output. If this is set to true, the task will print
|
|
56
|
-
# the reek command to stdout. Defaults to false.
|
|
57
|
-
attr_accessor :verbose
|
|
58
|
-
|
|
59
|
-
# Defines a new task, using the name +name+.
|
|
60
|
-
def initialize(name = :reek)
|
|
61
|
-
@name = name
|
|
62
|
-
@libs = [File.expand_path(File.dirname(__FILE__) + '/../../../lib')]
|
|
63
|
-
@source_files = nil
|
|
64
|
-
@ruby_opts = []
|
|
65
|
-
@reek_opts = ''
|
|
66
|
-
@fail_on_error = true
|
|
67
|
-
@sort = nil
|
|
68
|
-
|
|
69
|
-
yield self if block_given?
|
|
70
|
-
@source_files ||= 'lib/**/*.rb'
|
|
71
|
-
define
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
private
|
|
75
|
-
|
|
76
|
-
def define # :nodoc:
|
|
77
|
-
desc 'Check for code smells' unless ::Rake.application.last_comment
|
|
78
|
-
task(name) { run_task }
|
|
79
|
-
self
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def run_task
|
|
83
|
-
return if source_file_list.empty?
|
|
84
|
-
cmd = cmd_words.join(' ')
|
|
85
|
-
puts cmd if @verbose
|
|
86
|
-
raise('Smells found!') if !system(cmd) and fail_on_error
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def self.reek_script
|
|
90
|
-
File.expand_path(File.dirname(__FILE__) + '/../../../bin/reek')
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def self.ruby_exe
|
|
94
|
-
File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def cmd_words
|
|
98
|
-
[RakeTask.ruby_exe] +
|
|
99
|
-
ruby_options +
|
|
100
|
-
[ %Q|"#{RakeTask.reek_script}"| ] +
|
|
101
|
-
[sort_option] +
|
|
102
|
-
source_file_list.collect { |fn| %["#{fn}"] }
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def ruby_options
|
|
106
|
-
lib_path = @libs.join(File::PATH_SEPARATOR)
|
|
107
|
-
@ruby_opts.clone << "-I\"#{lib_path}\""
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def sort_option
|
|
111
|
-
ENV['REEK_OPTS'] || @reek_opts
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def source_file_list # :nodoc:
|
|
115
|
-
files = ENV['REEK_SRC'] || @source_files
|
|
116
|
-
return [] unless files
|
|
117
|
-
return FileList[files]
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
end
|
|
121
|
-
end
|
data/lib/reek/adapters/report.rb
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
require 'set'
|
|
2
|
-
require 'reek/adapters/command_line' # SMELL: Global Variable
|
|
3
|
-
require 'reek/masking_collection'
|
|
4
|
-
|
|
5
|
-
module Reek
|
|
6
|
-
class ReportSection
|
|
7
|
-
|
|
8
|
-
SMELL_FORMAT = '%m%c %w (%s)'
|
|
9
|
-
|
|
10
|
-
def initialize(sniffer, display_masked_warnings)
|
|
11
|
-
@cwarnings = MaskingCollection.new
|
|
12
|
-
@desc = sniffer.desc
|
|
13
|
-
@display_masked_warnings = display_masked_warnings # SMELL: Control Couple
|
|
14
|
-
sniffer.report_on(@cwarnings)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Creates a formatted report of all the +Smells::SmellWarning+ objects recorded in
|
|
18
|
-
# this report, with a heading.
|
|
19
|
-
def verbose_report
|
|
20
|
-
result = header
|
|
21
|
-
result += ":\n#{smell_list}" if should_report
|
|
22
|
-
result += "\n"
|
|
23
|
-
result
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def quiet_report
|
|
27
|
-
return '' unless should_report
|
|
28
|
-
# SMELL: duplicate knowledge of the header layout
|
|
29
|
-
"#{header}:\n#{smell_list}\n"
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def header
|
|
33
|
-
"#{@desc} -- #{visible_header}#{masked_header}"
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Creates a formatted report of all the +Smells::SmellWarning+ objects recorded in
|
|
37
|
-
# this report.
|
|
38
|
-
def smell_list
|
|
39
|
-
result = []
|
|
40
|
-
if @display_masked_warnings
|
|
41
|
-
@cwarnings.each_item {|smell| result << " #{smell.report(SMELL_FORMAT)}"}
|
|
42
|
-
else
|
|
43
|
-
@cwarnings.each_visible_item {|smell| result << " #{smell.report(SMELL_FORMAT)}"}
|
|
44
|
-
end
|
|
45
|
-
result.join("\n")
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
private
|
|
49
|
-
|
|
50
|
-
def should_report
|
|
51
|
-
@cwarnings.num_visible_items > 0 or (@display_masked_warnings and @cwarnings.num_masked_items > 0)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def visible_header
|
|
55
|
-
num_smells = @cwarnings.num_visible_items
|
|
56
|
-
result = "#{num_smells} warning"
|
|
57
|
-
result += 's' unless num_smells == 1
|
|
58
|
-
result
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def masked_header
|
|
62
|
-
num_masked_warnings = @cwarnings.num_masked_items
|
|
63
|
-
num_masked_warnings == 0 ? '' : " (+#{num_masked_warnings} masked)"
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
class Report
|
|
68
|
-
def initialize(sniffers, display_masked_warnings = false)
|
|
69
|
-
@partials = Array(sniffers).map {|sn| ReportSection.new(sn, display_masked_warnings)}
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
class VerboseReport < Report
|
|
74
|
-
# SMELL: Implementation Inheritance
|
|
75
|
-
def report
|
|
76
|
-
@partials.map { |section| section.verbose_report }.join
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
class QuietReport < Report
|
|
81
|
-
# SMELL: Implementation Inheritance
|
|
82
|
-
def report
|
|
83
|
-
@partials.map { |section| section.quiet_report }.join
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
data/lib/reek/adapters/source.rb
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
require 'ruby_parser'
|
|
2
|
-
require 'reek/adapters/config_file'
|
|
3
|
-
require 'reek/tree_dresser'
|
|
4
|
-
|
|
5
|
-
module Reek
|
|
6
|
-
|
|
7
|
-
#
|
|
8
|
-
# A +Source+ object represents a chunk of Ruby source code.
|
|
9
|
-
#
|
|
10
|
-
class Source
|
|
11
|
-
|
|
12
|
-
@@err_io = $stderr
|
|
13
|
-
|
|
14
|
-
class << self
|
|
15
|
-
def err_io=(io)
|
|
16
|
-
original = @@err_io
|
|
17
|
-
@@err_io = io
|
|
18
|
-
original
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
attr_reader :desc
|
|
23
|
-
|
|
24
|
-
def initialize(code, desc, parser = RubyParser.new)
|
|
25
|
-
@source = code
|
|
26
|
-
@desc = desc
|
|
27
|
-
@parser = parser
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def configure(sniffer) end
|
|
31
|
-
|
|
32
|
-
def syntax_tree
|
|
33
|
-
begin
|
|
34
|
-
ast = @parser.parse(@source, @desc)
|
|
35
|
-
rescue Exception => error
|
|
36
|
-
@@err_io.puts "#{desc}: #{error.class.name}: #{error}"
|
|
37
|
-
end
|
|
38
|
-
ast ||= s()
|
|
39
|
-
TreeDresser.new.dress(ast)
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
#
|
|
44
|
-
# Represents a file of Ruby source, whose contents will be examined
|
|
45
|
-
# for code smells.
|
|
46
|
-
#
|
|
47
|
-
class SourceFile < Source
|
|
48
|
-
|
|
49
|
-
def self.lines(file)
|
|
50
|
-
IO.readlines(file.path)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def initialize(file)
|
|
54
|
-
@file = file
|
|
55
|
-
super(SourceFile.lines(@file).join, @file.path)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def configure(sniffer)
|
|
59
|
-
path = File.expand_path(File.dirname(@file.path))
|
|
60
|
-
all_config_files(path).each { |cf| ConfigFile.new(cf).configure(sniffer) }
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
private
|
|
64
|
-
|
|
65
|
-
def all_config_files(path)
|
|
66
|
-
return [] unless File.exist?(path)
|
|
67
|
-
parent = File.dirname(path)
|
|
68
|
-
return [] if path == parent
|
|
69
|
-
all_config_files(parent) + Dir["#{path}/*.reek"]
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|