kevinrutherford-reek 1.1.3.10 → 1.1.3.11
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -1
- data/bin/reek +2 -17
- data/features/masking_smells.feature +22 -8
- data/features/options.feature +12 -5
- data/features/reports.feature +22 -12
- data/features/samples.feature +66 -66
- data/lib/reek/adapters/application.rb +47 -0
- data/lib/reek/{config_file.rb → adapters/config_file.rb} +0 -0
- data/lib/reek/adapters/core_extras.rb +72 -0
- data/lib/reek/{object_source.rb → adapters/object_source.rb} +7 -6
- data/lib/reek/{rake_task.rb → adapters/rake_task.rb} +2 -2
- data/lib/reek/adapters/report.rb +91 -0
- data/lib/reek/adapters/source.rb +49 -0
- data/lib/reek/{spec.rb → adapters/spec.rb} +20 -9
- data/lib/reek/block_context.rb +1 -1
- data/lib/reek/class_context.rb +3 -2
- data/lib/reek/code_parser.rb +4 -0
- data/lib/reek/command_line.rb +85 -0
- data/lib/reek/detector_stack.rb +23 -6
- data/lib/reek/exceptions.reek +5 -1
- data/lib/reek/smell_warning.rb +5 -1
- data/lib/reek/smells/duplication.rb +5 -3
- data/lib/reek/smells/smell_detector.rb +15 -1
- data/lib/reek/smells/uncommunicative_name.rb +1 -1
- data/lib/reek/sniffer.rb +34 -66
- data/lib/reek.rb +1 -1
- data/reek.gemspec +3 -3
- data/spec/quality/reek_source_spec.rb +15 -0
- data/spec/reek/adapters/report_spec.rb +48 -0
- data/spec/reek/{should_reek_of_spec.rb → adapters/should_reek_of_spec.rb} +14 -11
- data/spec/reek/{should_reek_only_of_spec.rb → adapters/should_reek_only_of_spec.rb} +6 -4
- data/spec/reek/{should_reek_spec.rb → adapters/should_reek_spec.rb} +13 -10
- data/spec/reek/block_context_spec.rb +6 -0
- data/spec/reek/code_parser_spec.rb +6 -1
- data/spec/reek/config_spec.rb +3 -3
- data/spec/reek/smell_warning_spec.rb +2 -1
- data/spec/reek/smells/duplication_spec.rb +1 -1
- data/spec/reek/smells/large_class_spec.rb +3 -2
- data/spec/reek/smells/long_method_spec.rb +4 -3
- data/spec/reek/smells/long_parameter_list_spec.rb +0 -2
- data/spec/reek/smells/smell_detector_spec.rb +2 -16
- data/spec/reek/smells/uncommunicative_name_spec.rb +1 -2
- data/spec/reek/smells/utility_function_spec.rb +4 -0
- data/spec/samples/not_quite_masked/dirty.rb +8 -0
- data/spec/samples/not_quite_masked/masked.reek +5 -0
- data/spec/spec_helper.rb +1 -1
- data/tasks/reek.rake +2 -2
- data/tasks/test.rake +8 -8
- metadata +18 -20
- data/features/rake_task.feature +0 -9
- data/lib/reek/core_extras.rb +0 -50
- data/lib/reek/options.rb +0 -103
- data/lib/reek/report.rb +0 -115
- data/lib/reek/source.rb +0 -36
- data/spec/reek/options_spec.rb +0 -13
- data/spec/reek/report_spec.rb +0 -49
- data/spec/slow/inline_spec.rb +0 -44
- data/spec/slow/optparse_spec.rb +0 -112
- data/spec/slow/redcloth_spec.rb +0 -105
- data/spec/slow/reek_source_spec.rb +0 -13
data/History.txt
CHANGED
@@ -6,18 +6,22 @@
|
|
6
6
|
** Output now reports on all files examined, even if they have no smells
|
7
7
|
** Smell warnings are indented in the report; file summary headers are not
|
8
8
|
** Reports for multiple sources are run together; no more blank lines
|
9
|
-
** Reports in spec matcher failures are quiet
|
9
|
+
** Reports in spec matcher failures are quiet (fixed #38)
|
10
10
|
* The smells masked by *.reek config files can now be seen:
|
11
11
|
** The header for each source file now counts masked smells
|
12
12
|
** The --show-all (-a) option shows masked warnings in the report
|
13
|
+
* The spec matchers are now accessed by requiring 'reek/adapters/spec'
|
13
14
|
|
14
15
|
=== Minor Changes
|
15
16
|
* Reek's RDoc is now hosted at http://rdoc.info/projects/kevinrutherford/reek
|
17
|
+
* If a dir is passed on the command-line all **/*.rb files below it are examined (fixed #41)
|
16
18
|
* Several changes to the LongMethod counting algorithm:
|
17
19
|
** LongMethod now counts statements deeper into each method (fixed #25)
|
18
20
|
** LongMethod no longer counts control structures, only their contained stmts
|
19
21
|
** See http://wiki.github.com/kevinrutherford/reek/long-method for details
|
20
22
|
* LargeClass is disabled when checking in-memory classes (fixed #28)
|
23
|
+
* UtilityFunction no longer reports methods that call 'super' (fixed #39)
|
24
|
+
* Duplication warnings now report the number of identical calls
|
21
25
|
* Now reports an error for corrupt config files
|
22
26
|
* Empty config files are ignored
|
23
27
|
|
data/bin/reek
CHANGED
@@ -6,21 +6,6 @@
|
|
6
6
|
# Author: Kevin Rutherford
|
7
7
|
#
|
8
8
|
|
9
|
-
require 'reek/
|
9
|
+
require 'reek/adapters/application'
|
10
10
|
|
11
|
-
|
12
|
-
begin
|
13
|
-
sniffer = Reek::Options.parse(args)
|
14
|
-
# SMELL:
|
15
|
-
# This should use the actual type of report selected by the user's options
|
16
|
-
puts sniffer.full_report
|
17
|
-
return sniffer.smelly? ? 2 : 0
|
18
|
-
rescue SystemExit => ex
|
19
|
-
return ex.status
|
20
|
-
rescue Exception => error
|
21
|
-
$stderr.puts "Error: #{error}"
|
22
|
-
return 1
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
exit reek(ARGV)
|
11
|
+
exit Reek::Application.new(ARGV).execute
|
@@ -11,8 +11,8 @@ Feature: Masking smells using config files
|
|
11
11
|
"""
|
12
12
|
spec/samples/empty_config_file/dirty.rb -- 6 warnings:
|
13
13
|
Dirty has the variable name '@s' (Uncommunicative Name)
|
14
|
-
Dirty#a calls @s.title
|
15
|
-
Dirty#a calls puts(@s.title)
|
14
|
+
Dirty#a calls @s.title twice (Duplication)
|
15
|
+
Dirty#a calls puts(@s.title) twice (Duplication)
|
16
16
|
Dirty#a has the name 'a' (Uncommunicative Name)
|
17
17
|
Dirty#a/block has the variable name 'x' (Uncommunicative Name)
|
18
18
|
Dirty#a/block/block is nested (Nested Iterators)
|
@@ -35,8 +35,8 @@ Feature: Masking smells using config files
|
|
35
35
|
And it reports:
|
36
36
|
"""
|
37
37
|
spec/samples/masked/dirty.rb -- 3 warnings (+3 masked):
|
38
|
-
Dirty#a calls @s.title
|
39
|
-
Dirty#a calls puts(@s.title)
|
38
|
+
Dirty#a calls @s.title twice (Duplication)
|
39
|
+
Dirty#a calls puts(@s.title) twice (Duplication)
|
40
40
|
Dirty#a/block/block is nested (Nested Iterators)
|
41
41
|
|
42
42
|
"""
|
@@ -48,8 +48,8 @@ Feature: Masking smells using config files
|
|
48
48
|
"""
|
49
49
|
spec/samples/masked/dirty.rb -- 3 warnings (+3 masked):
|
50
50
|
(masked) Dirty has the variable name '@s' (Uncommunicative Name)
|
51
|
-
Dirty#a calls @s.title
|
52
|
-
Dirty#a calls puts(@s.title)
|
51
|
+
Dirty#a calls @s.title twice (Duplication)
|
52
|
+
Dirty#a calls puts(@s.title) twice (Duplication)
|
53
53
|
(masked) Dirty#a has the name 'a' (Uncommunicative Name)
|
54
54
|
(masked) Dirty#a/block has the variable name 'x' (Uncommunicative Name)
|
55
55
|
Dirty#a/block/block is nested (Nested Iterators)
|
@@ -62,8 +62,22 @@ Feature: Masking smells using config files
|
|
62
62
|
And it reports:
|
63
63
|
"""
|
64
64
|
spec/samples/masked/dirty.rb -- 3 warnings (+3 masked):
|
65
|
-
Dirty#a calls @s.title
|
66
|
-
Dirty#a calls puts(@s.title)
|
65
|
+
Dirty#a calls @s.title twice (Duplication)
|
66
|
+
Dirty#a calls puts(@s.title) twice (Duplication)
|
67
|
+
Dirty#a/block/block is nested (Nested Iterators)
|
68
|
+
|
69
|
+
"""
|
70
|
+
|
71
|
+
Scenario: non-masked smells are only counted once
|
72
|
+
When I run reek spec/samples/not_quite_masked/dirty.rb
|
73
|
+
Then it fails with exit status 2
|
74
|
+
And it reports:
|
75
|
+
"""
|
76
|
+
spec/samples/not_quite_masked/dirty.rb -- 5 warnings (+1 masked):
|
77
|
+
Dirty has the variable name '@s' (Uncommunicative Name)
|
78
|
+
Dirty#a calls @s.title twice (Duplication)
|
79
|
+
Dirty#a calls puts(@s.title) twice (Duplication)
|
80
|
+
Dirty#a has the name 'a' (Uncommunicative Name)
|
67
81
|
Dirty#a/block/block is nested (Nested Iterators)
|
68
82
|
|
69
83
|
"""
|
data/features/options.feature
CHANGED
@@ -24,19 +24,26 @@ Feature: Reek can be controlled using command-line options
|
|
24
24
|
Then it succeeds
|
25
25
|
And it reports:
|
26
26
|
"""
|
27
|
-
Usage: reek [options] files
|
27
|
+
Usage: reek [options] [files]
|
28
|
+
|
29
|
+
Examples:
|
30
|
+
|
31
|
+
reek lib/*.rb
|
32
|
+
reek -q -a lib
|
33
|
+
cat my_class.rb | reek
|
28
34
|
|
29
|
-
If no files are given, Reek reads source code from standard input.
|
30
35
|
See http://wiki.github.com/kevinrutherford/reek for detailed help.
|
31
36
|
|
37
|
+
Common options:
|
38
|
+
-h, --help Show this message
|
39
|
+
-v, --version Show version
|
32
40
|
|
33
|
-
|
41
|
+
|
42
|
+
Report formatting:
|
34
43
|
-a, --[no-]show-all Show all smells, including those masked by config settings
|
35
44
|
-q, --quiet Suppress headings for smell-free source files
|
36
|
-
-h, --help Show this message
|
37
45
|
-f, --format FORMAT Specify the format of smell warnings
|
38
46
|
-c, --context-first Sort by context; sets the format string to "%m%c %w (%s)"
|
39
47
|
-s, --smell-first Sort by smell; sets the format string to "%m[%s] %c %w"
|
40
|
-
-v, --version Show version
|
41
48
|
|
42
49
|
"""
|
data/features/reports.feature
CHANGED
@@ -4,30 +4,35 @@ Feature: Correctly formatted reports
|
|
4
4
|
As a developer
|
5
5
|
I want to be able to parse reek's output simply and consistently
|
6
6
|
|
7
|
-
Scenario: two reports run together with indented smells
|
8
|
-
When I run reek
|
7
|
+
Scenario Outline: two reports run together with indented smells
|
8
|
+
When I run reek <args>
|
9
9
|
Then it fails with exit status 2
|
10
10
|
And it reports:
|
11
11
|
"""
|
12
12
|
spec/samples/two_smelly_files/dirty_one.rb -- 6 warnings:
|
13
13
|
Dirty has the variable name '@s' (Uncommunicative Name)
|
14
|
-
Dirty#a calls @s.title
|
15
|
-
Dirty#a calls puts(@s.title)
|
14
|
+
Dirty#a calls @s.title twice (Duplication)
|
15
|
+
Dirty#a calls puts(@s.title) twice (Duplication)
|
16
16
|
Dirty#a has the name 'a' (Uncommunicative Name)
|
17
17
|
Dirty#a/block has the variable name 'x' (Uncommunicative Name)
|
18
18
|
Dirty#a/block/block is nested (Nested Iterators)
|
19
19
|
spec/samples/two_smelly_files/dirty_two.rb -- 6 warnings:
|
20
20
|
Dirty has the variable name '@s' (Uncommunicative Name)
|
21
|
-
Dirty#a calls @s.title
|
22
|
-
Dirty#a calls puts(@s.title)
|
21
|
+
Dirty#a calls @s.title twice (Duplication)
|
22
|
+
Dirty#a calls puts(@s.title) twice (Duplication)
|
23
23
|
Dirty#a has the name 'a' (Uncommunicative Name)
|
24
24
|
Dirty#a/block has the variable name 'x' (Uncommunicative Name)
|
25
25
|
Dirty#a/block/block is nested (Nested Iterators)
|
26
26
|
|
27
27
|
"""
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
Examples:
|
30
|
+
| args |
|
31
|
+
| spec/samples/two_smelly_files/*.rb |
|
32
|
+
| spec/samples/two_smelly_files |
|
33
|
+
|
34
|
+
Scenario Outline: good files show headers consecutively
|
35
|
+
When I run reek <args>
|
31
36
|
Then it succeeds
|
32
37
|
And it reports:
|
33
38
|
"""
|
@@ -37,6 +42,11 @@ Feature: Correctly formatted reports
|
|
37
42
|
|
38
43
|
"""
|
39
44
|
|
45
|
+
Examples:
|
46
|
+
| args |
|
47
|
+
| spec/samples/three_clean_files/*.rb |
|
48
|
+
| spec/samples/three_clean_files |
|
49
|
+
|
40
50
|
Scenario Outline: --quiet turns off headers for fragrant files
|
41
51
|
When I run reek <option> spec/samples/three_clean_files/*.rb
|
42
52
|
Then it succeeds
|
@@ -59,15 +69,15 @@ Feature: Correctly formatted reports
|
|
59
69
|
"""
|
60
70
|
spec/samples/clean_due_to_masking/dirty_one.rb -- 0 warnings (+6 masked):
|
61
71
|
(masked) Dirty has the variable name '@s' (Uncommunicative Name)
|
62
|
-
(masked) Dirty#a calls @s.title
|
63
|
-
(masked) Dirty#a calls puts(@s.title)
|
72
|
+
(masked) Dirty#a calls @s.title twice (Duplication)
|
73
|
+
(masked) Dirty#a calls puts(@s.title) twice (Duplication)
|
64
74
|
(masked) Dirty#a has the name 'a' (Uncommunicative Name)
|
65
75
|
(masked) Dirty#a/block has the variable name 'x' (Uncommunicative Name)
|
66
76
|
(masked) Dirty#a/block/block is nested (Nested Iterators)
|
67
77
|
spec/samples/clean_due_to_masking/dirty_two.rb -- 0 warnings (+6 masked):
|
68
78
|
(masked) Dirty has the variable name '@s' (Uncommunicative Name)
|
69
|
-
(masked) Dirty#a calls @s.title
|
70
|
-
(masked) Dirty#a calls puts(@s.title)
|
79
|
+
(masked) Dirty#a calls @s.title twice (Duplication)
|
80
|
+
(masked) Dirty#a calls puts(@s.title) twice (Duplication)
|
71
81
|
(masked) Dirty#a has the name 'a' (Uncommunicative Name)
|
72
82
|
(masked) Dirty#a/block has the variable name 'x' (Uncommunicative Name)
|
73
83
|
(masked) Dirty#a/block/block is nested (Nested Iterators)
|
data/features/samples.feature
CHANGED
@@ -11,25 +11,25 @@ Feature: Basic smell detection
|
|
11
11
|
"""
|
12
12
|
spec/samples/inline.rb -- 32 warnings:
|
13
13
|
Inline::C has at least 13 instance variables (Large Class)
|
14
|
-
Inline::C#build calls ($? == 0)
|
15
|
-
Inline::C#build calls Inline.directory
|
16
|
-
Inline::C#build calls io.puts
|
17
|
-
Inline::C#build calls io.puts("#endif")
|
18
|
-
Inline::C#build calls io.puts("#ifdef __cplusplus")
|
19
|
-
Inline::C#build calls module_name
|
20
|
-
Inline::C#build calls warn("Output:\n#{result}")
|
14
|
+
Inline::C#build calls ($? == 0) twice (Duplication)
|
15
|
+
Inline::C#build calls Inline.directory 5 times (Duplication)
|
16
|
+
Inline::C#build calls io.puts 6 times (Duplication)
|
17
|
+
Inline::C#build calls io.puts("#endif") twice (Duplication)
|
18
|
+
Inline::C#build calls io.puts("#ifdef __cplusplus") twice (Duplication)
|
19
|
+
Inline::C#build calls module_name twice (Duplication)
|
20
|
+
Inline::C#build calls warn("Output:\n#{result}") twice (Duplication)
|
21
21
|
Inline::C#build has approx 60 statements (Long Method)
|
22
22
|
Inline::C#build has the variable name 't' (Uncommunicative Name)
|
23
23
|
Inline::C#build/block/block has the variable name 'n' (Uncommunicative Name)
|
24
24
|
Inline::C#build/block/block is nested (Nested Iterators)
|
25
25
|
Inline::C#c has the name 'c' (Uncommunicative Name)
|
26
|
-
Inline::C#crap_for_windoze calls Config::CONFIG["libdir"]
|
27
|
-
Inline::C#generate calls result.sub!(/\A\n/, "")
|
28
|
-
Inline::C#generate calls signature["args"]
|
29
|
-
Inline::C#generate calls signature["args"].map
|
26
|
+
Inline::C#crap_for_windoze calls Config::CONFIG["libdir"] twice (Duplication)
|
27
|
+
Inline::C#generate calls result.sub!(/\A\n/, "") twice (Duplication)
|
28
|
+
Inline::C#generate calls signature["args"] twice (Duplication)
|
29
|
+
Inline::C#generate calls signature["args"].map twice (Duplication)
|
30
30
|
Inline::C#generate has approx 32 statements (Long Method)
|
31
|
-
Inline::C#initialize calls stack.empty?
|
32
|
-
Inline::C#load calls so_name
|
31
|
+
Inline::C#initialize calls stack.empty? twice (Duplication)
|
32
|
+
Inline::C#load calls so_name twice (Duplication)
|
33
33
|
Inline::C#module_name/block has the variable name 'm' (Uncommunicative Name)
|
34
34
|
Inline::C#module_name/block has the variable name 'x' (Uncommunicative Name)
|
35
35
|
Inline::C#parse_signature has approx 15 statements (Long Method)
|
@@ -37,9 +37,9 @@ Feature: Basic smell detection
|
|
37
37
|
Inline::C#parse_signature/block has the variable name 'x' (Uncommunicative Name)
|
38
38
|
Inline::C#strip_comments doesn't depend on instance state (Utility Function)
|
39
39
|
Inline::C#strip_comments refers to src more than self (Feature Envy)
|
40
|
-
Inline::self.rootdir calls env.nil?
|
40
|
+
Inline::self.rootdir calls env.nil? twice (Duplication)
|
41
41
|
Inline::self.rootdir has approx 8 statements (Long Method)
|
42
|
-
Module#inline calls Inline.const_get(lang)
|
42
|
+
Module#inline calls Inline.const_get(lang) twice (Duplication)
|
43
43
|
Module#inline has approx 11 statements (Long Method)
|
44
44
|
Module#inline is controlled by argument options (Control Couple)
|
45
45
|
|
@@ -53,8 +53,8 @@ Feature: Basic smell detection
|
|
53
53
|
spec/samples/optparse.rb -- 117 warnings:
|
54
54
|
OptionParser has at least 59 methods (Large Class)
|
55
55
|
OptionParser#CompletingHash#match/block/block is nested (Nested Iterators)
|
56
|
-
OptionParser#Completion::complete calls candidates.size
|
57
|
-
OptionParser#Completion::complete calls k.id2name
|
56
|
+
OptionParser#Completion::complete calls candidates.size twice (Duplication)
|
57
|
+
OptionParser#Completion::complete calls k.id2name twice (Duplication)
|
58
58
|
OptionParser#Completion::complete has approx 22 statements (Long Method)
|
59
59
|
OptionParser#Completion::complete has the variable name 'k' (Uncommunicative Name)
|
60
60
|
OptionParser#Completion::complete has the variable name 'v' (Uncommunicative Name)
|
@@ -80,23 +80,23 @@ Feature: Basic smell detection
|
|
80
80
|
OptionParser#Switch#PlacedArgument#parse has approx 6 statements (Long Method)
|
81
81
|
OptionParser#Switch#RequiredArgument#parse is controlled by argument arg (Control Couple)
|
82
82
|
OptionParser#Switch#add_banner has the variable name 's' (Uncommunicative Name)
|
83
|
-
OptionParser#Switch#conv_arg calls conv
|
83
|
+
OptionParser#Switch#conv_arg calls conv twice (Duplication)
|
84
84
|
OptionParser#Switch#initialize has 7 parameters (Long Parameter List)
|
85
|
-
OptionParser#Switch#parse_arg calls pattern
|
86
|
-
OptionParser#Switch#parse_arg calls s.length
|
85
|
+
OptionParser#Switch#parse_arg calls pattern twice (Duplication)
|
86
|
+
OptionParser#Switch#parse_arg calls s.length twice (Duplication)
|
87
87
|
OptionParser#Switch#parse_arg has approx 11 statements (Long Method)
|
88
88
|
OptionParser#Switch#parse_arg has the variable name 'm' (Uncommunicative Name)
|
89
89
|
OptionParser#Switch#parse_arg has the variable name 's' (Uncommunicative Name)
|
90
90
|
OptionParser#Switch#self.guess has the variable name 't' (Uncommunicative Name)
|
91
91
|
OptionParser#Switch#self.incompatible_argument_styles has the variable name 't' (Uncommunicative Name)
|
92
|
-
OptionParser#Switch#summarize calls (indent + l)
|
93
|
-
OptionParser#Switch#summarize calls arg
|
94
|
-
OptionParser#Switch#summarize calls left.collect
|
95
|
-
OptionParser#Switch#summarize calls left.collect { |s| s.length }.max
|
96
|
-
OptionParser#Switch#summarize calls left.collect { |s| s.length }.max.to_i
|
97
|
-
OptionParser#Switch#summarize calls left.shift
|
98
|
-
OptionParser#Switch#summarize calls left[-1]
|
99
|
-
OptionParser#Switch#summarize calls s.length
|
92
|
+
OptionParser#Switch#summarize calls (indent + l) twice (Duplication)
|
93
|
+
OptionParser#Switch#summarize calls arg 4 times (Duplication)
|
94
|
+
OptionParser#Switch#summarize calls left.collect twice (Duplication)
|
95
|
+
OptionParser#Switch#summarize calls left.collect { |s| s.length }.max twice (Duplication)
|
96
|
+
OptionParser#Switch#summarize calls left.collect { |s| s.length }.max.to_i twice (Duplication)
|
97
|
+
OptionParser#Switch#summarize calls left.shift twice (Duplication)
|
98
|
+
OptionParser#Switch#summarize calls left[-1] 3 times (Duplication)
|
99
|
+
OptionParser#Switch#summarize calls s.length 3 times (Duplication)
|
100
100
|
OptionParser#Switch#summarize has 5 parameters (Long Parameter List)
|
101
101
|
OptionParser#Switch#summarize has approx 25 statements (Long Method)
|
102
102
|
OptionParser#Switch#summarize has the variable name 'l' (Uncommunicative Name)
|
@@ -117,21 +117,21 @@ Feature: Basic smell detection
|
|
117
117
|
OptionParser#block/block is nested (Nested Iterators)
|
118
118
|
OptionParser#complete has 4 parameters (Long Parameter List)
|
119
119
|
OptionParser#complete/block/block is nested (Nested Iterators)
|
120
|
-
OptionParser#getopts calls result[opt] = false
|
120
|
+
OptionParser#getopts calls result[opt] = false twice (Duplication)
|
121
121
|
OptionParser#getopts has approx 17 statements (Long Method)
|
122
122
|
OptionParser#getopts/block is controlled by argument val (Control Couple)
|
123
123
|
OptionParser#load/block has the variable name 's' (Uncommunicative Name)
|
124
|
-
OptionParser#make_switch calls (long << o = q.downcase)
|
125
|
-
OptionParser#make_switch calls (sdesc << "-#{q}")
|
126
|
-
OptionParser#make_switch calls default_style.guess(arg = a)
|
127
|
-
OptionParser#make_switch calls notwice(NilClass, klass, "type")
|
128
|
-
OptionParser#make_switch calls notwice(a ? (Object) : (TrueClass), klass, "type")
|
129
|
-
OptionParser#make_switch calls pattern.method(:convert)
|
130
|
-
OptionParser#make_switch calls pattern.method(:convert).to_proc
|
131
|
-
OptionParser#make_switch calls pattern.respond_to?(:convert)
|
132
|
-
OptionParser#make_switch calls q.downcase
|
133
|
-
OptionParser#make_switch calls search(:atype, FalseClass)
|
134
|
-
OptionParser#make_switch calls search(:atype, o)
|
124
|
+
OptionParser#make_switch calls (long << o = q.downcase) twice (Duplication)
|
125
|
+
OptionParser#make_switch calls (sdesc << "-#{q}") twice (Duplication)
|
126
|
+
OptionParser#make_switch calls default_style.guess(arg = a) 4 times (Duplication)
|
127
|
+
OptionParser#make_switch calls notwice(NilClass, klass, "type") twice (Duplication)
|
128
|
+
OptionParser#make_switch calls notwice(a ? (Object) : (TrueClass), klass, "type") twice (Duplication)
|
129
|
+
OptionParser#make_switch calls pattern.method(:convert) twice (Duplication)
|
130
|
+
OptionParser#make_switch calls pattern.method(:convert).to_proc twice (Duplication)
|
131
|
+
OptionParser#make_switch calls pattern.respond_to?(:convert) twice (Duplication)
|
132
|
+
OptionParser#make_switch calls q.downcase 3 times (Duplication)
|
133
|
+
OptionParser#make_switch calls search(:atype, FalseClass) twice (Duplication)
|
134
|
+
OptionParser#make_switch calls search(:atype, o) 6 times (Duplication)
|
135
135
|
OptionParser#make_switch has approx 68 statements (Long Method)
|
136
136
|
OptionParser#make_switch has the variable name 'a' (Uncommunicative Name)
|
137
137
|
OptionParser#make_switch has the variable name 'n' (Uncommunicative Name)
|
@@ -146,22 +146,22 @@ Feature: Basic smell detection
|
|
146
146
|
OptionParser#make_switch/block/block has the variable name 'v' (Uncommunicative Name)
|
147
147
|
OptionParser#make_switch/block/block is nested (Nested Iterators)
|
148
148
|
OptionParser#make_switch/block/block/block is nested (Nested Iterators)
|
149
|
-
OptionParser#order calls argv[0]
|
149
|
+
OptionParser#order calls argv[0] twice (Duplication)
|
150
150
|
OptionParser#order refers to argv more than self (Feature Envy)
|
151
|
-
OptionParser#parse calls argv[0]
|
151
|
+
OptionParser#parse calls argv[0] twice (Duplication)
|
152
152
|
OptionParser#parse refers to argv more than self (Feature Envy)
|
153
|
-
OptionParser#parse_in_order calls $!.set_option(arg, true)
|
154
|
-
OptionParser#parse_in_order calls cb.call(val)
|
155
|
-
OptionParser#parse_in_order calls raise($!.set_option(arg, true))
|
156
|
-
OptionParser#parse_in_order calls raise(*exc)
|
157
|
-
OptionParser#parse_in_order calls setter.call(sw.switch_name, val)
|
158
|
-
OptionParser#parse_in_order calls sw.block
|
159
|
-
OptionParser#parse_in_order calls sw.switch_name
|
153
|
+
OptionParser#parse_in_order calls $!.set_option(arg, true) twice (Duplication)
|
154
|
+
OptionParser#parse_in_order calls cb.call(val) twice (Duplication)
|
155
|
+
OptionParser#parse_in_order calls raise($!.set_option(arg, true)) twice (Duplication)
|
156
|
+
OptionParser#parse_in_order calls raise(*exc) twice (Duplication)
|
157
|
+
OptionParser#parse_in_order calls setter.call(sw.switch_name, val) twice (Duplication)
|
158
|
+
OptionParser#parse_in_order calls sw.block twice (Duplication)
|
159
|
+
OptionParser#parse_in_order calls sw.switch_name twice (Duplication)
|
160
160
|
OptionParser#parse_in_order has approx 28 statements (Long Method)
|
161
161
|
OptionParser#parse_in_order/block is controlled by argument setter (Control Couple)
|
162
162
|
OptionParser#parse_in_order/block/block is nested (Nested Iterators)
|
163
163
|
OptionParser#parse_in_order/block/block/block is nested (Nested Iterators)
|
164
|
-
OptionParser#permute calls argv[0]
|
164
|
+
OptionParser#permute calls argv[0] twice (Duplication)
|
165
165
|
OptionParser#permute refers to argv more than self (Feature Envy)
|
166
166
|
OptionParser#search/block has the variable name 'k' (Uncommunicative Name)
|
167
167
|
OptionParser#summarize has 4 parameters (Long Parameter List)
|
@@ -185,12 +185,12 @@ Feature: Basic smell detection
|
|
185
185
|
RedCloth#block_markdown_rule doesn't depend on instance state (Utility Function)
|
186
186
|
RedCloth#block_markdown_rule refers to text more than self (Feature Envy)
|
187
187
|
RedCloth#block_markdown_setext refers to text more than self (Feature Envy)
|
188
|
-
RedCloth#block_textile_lists calls (line_id - 1)
|
189
|
-
RedCloth#block_textile_lists calls depth.last
|
190
|
-
RedCloth#block_textile_lists calls depth.last.length
|
191
|
-
RedCloth#block_textile_lists calls depth[i]
|
192
|
-
RedCloth#block_textile_lists calls lines[(line_id - 1)]
|
193
|
-
RedCloth#block_textile_lists calls tl.length
|
188
|
+
RedCloth#block_textile_lists calls (line_id - 1) twice (Duplication)
|
189
|
+
RedCloth#block_textile_lists calls depth.last 5 times (Duplication)
|
190
|
+
RedCloth#block_textile_lists calls depth.last.length twice (Duplication)
|
191
|
+
RedCloth#block_textile_lists calls depth[i] twice (Duplication)
|
192
|
+
RedCloth#block_textile_lists calls lines[(line_id - 1)] twice (Duplication)
|
193
|
+
RedCloth#block_textile_lists calls tl.length 3 times (Duplication)
|
194
194
|
RedCloth#block_textile_lists has approx 20 statements (Long Method)
|
195
195
|
RedCloth#block_textile_lists refers to depth more than self (Feature Envy)
|
196
196
|
RedCloth#block_textile_lists/block/block is nested (Nested Iterators)
|
@@ -205,7 +205,7 @@ Feature: Basic smell detection
|
|
205
205
|
RedCloth#blocks/block is controlled by argument deep_code (Control Couple)
|
206
206
|
RedCloth#blocks/block/block is nested (Nested Iterators)
|
207
207
|
RedCloth#check_refs is controlled by argument text (Control Couple)
|
208
|
-
RedCloth#clean_html calls tags[tag]
|
208
|
+
RedCloth#clean_html calls tags[tag] twice (Duplication)
|
209
209
|
RedCloth#clean_html doesn't depend on instance state (Utility Function)
|
210
210
|
RedCloth#clean_html has approx 14 statements (Long Method)
|
211
211
|
RedCloth#clean_html refers to raw more than self (Feature Envy)
|
@@ -243,7 +243,7 @@ Feature: Basic smell detection
|
|
243
243
|
RedCloth#inline_textile_span/block/block is nested (Nested Iterators)
|
244
244
|
RedCloth#no_textile doesn't depend on instance state (Utility Function)
|
245
245
|
RedCloth#no_textile refers to text more than self (Feature Envy)
|
246
|
-
RedCloth#pba calls $1.length
|
246
|
+
RedCloth#pba calls $1.length twice (Duplication)
|
247
247
|
RedCloth#pba has approx 21 statements (Long Method)
|
248
248
|
RedCloth#pba is controlled by argument text_in (Control Couple)
|
249
249
|
RedCloth#pba refers to style more than self (Feature Envy)
|
@@ -252,14 +252,14 @@ Feature: Basic smell detection
|
|
252
252
|
RedCloth#refs_textile/block has the variable name 'm' (Uncommunicative Name)
|
253
253
|
RedCloth#retrieve/block has the variable name 'i' (Uncommunicative Name)
|
254
254
|
RedCloth#retrieve/block has the variable name 'r' (Uncommunicative Name)
|
255
|
-
RedCloth#rip_offtags calls ((codepre - used_offtags.length) > 0)
|
256
|
-
RedCloth#rip_offtags calls (@pre_list.last << line)
|
257
|
-
RedCloth#rip_offtags calls (codepre - used_offtags.length)
|
258
|
-
RedCloth#rip_offtags calls @pre_list.last
|
259
|
-
RedCloth#rip_offtags calls codepre.zero?
|
260
|
-
RedCloth#rip_offtags calls htmlesc(line, :NoQuotes)
|
261
|
-
RedCloth#rip_offtags calls used_offtags.length
|
262
|
-
RedCloth#rip_offtags calls used_offtags["notextile"]
|
255
|
+
RedCloth#rip_offtags calls ((codepre - used_offtags.length) > 0) twice (Duplication)
|
256
|
+
RedCloth#rip_offtags calls (@pre_list.last << line) twice (Duplication)
|
257
|
+
RedCloth#rip_offtags calls (codepre - used_offtags.length) twice (Duplication)
|
258
|
+
RedCloth#rip_offtags calls @pre_list.last twice (Duplication)
|
259
|
+
RedCloth#rip_offtags calls codepre.zero? twice (Duplication)
|
260
|
+
RedCloth#rip_offtags calls htmlesc(line, :NoQuotes) twice (Duplication)
|
261
|
+
RedCloth#rip_offtags calls used_offtags.length twice (Duplication)
|
262
|
+
RedCloth#rip_offtags calls used_offtags["notextile"] 3 times (Duplication)
|
263
263
|
RedCloth#rip_offtags has approx 18 statements (Long Method)
|
264
264
|
RedCloth#textile_bq has 4 parameters (Long Parameter List)
|
265
265
|
RedCloth#textile_bq is controlled by argument atts (Control Couple)
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'reek/command_line'
|
2
|
+
require 'reek/adapters/source'
|
3
|
+
require 'reek/adapters/core_extras'
|
4
|
+
require 'reek/adapters/report'
|
5
|
+
|
6
|
+
module Reek
|
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
|
+
def initialize(argv)
|
14
|
+
@argv = argv
|
15
|
+
end
|
16
|
+
|
17
|
+
def examine_sources
|
18
|
+
# SMELL: Greedy Method
|
19
|
+
# Options.parse executes the -v and -h commands and throws a SystemExit
|
20
|
+
args = Options.new(@argv).parse
|
21
|
+
if args.length > 0
|
22
|
+
@sniffer = args.sniff
|
23
|
+
else
|
24
|
+
@sniffer = Reek::Sniffer.new($stdin.to_reek_source('$stdin'))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def reek
|
29
|
+
examine_sources
|
30
|
+
# SMELL:
|
31
|
+
# This should use the actual type of report selected by the user's options
|
32
|
+
puts Report.new(@sniffer.sniffers).full_report
|
33
|
+
return @sniffer.smelly? ? 2 : 0
|
34
|
+
end
|
35
|
+
|
36
|
+
def execute
|
37
|
+
begin
|
38
|
+
return reek
|
39
|
+
rescue SystemExit => ex
|
40
|
+
return ex.status
|
41
|
+
rescue Exception => error
|
42
|
+
$stderr.puts "Error: #{error}"
|
43
|
+
return 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
File without changes
|
@@ -0,0 +1,72 @@
|
|
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
|
+
|
14
|
+
#
|
15
|
+
# Constructs a Sniffer which examines this object for code smells.
|
16
|
+
# (This feature is only enabled if you have the ParseTree gem installed.)
|
17
|
+
#
|
18
|
+
def to_reek_source
|
19
|
+
ObjectSource.new(self, self.to_s)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class File
|
24
|
+
#
|
25
|
+
# Creates a new +Source+ that assumes this File contains Ruby source
|
26
|
+
# code and prepares it to be examined for code smells.
|
27
|
+
#
|
28
|
+
def to_reek_source
|
29
|
+
Reek::SourceFile.new(self)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class IO
|
34
|
+
#
|
35
|
+
# Creates a new +Source+ that assumes this IO stream contains Ruby source
|
36
|
+
# code and prepares it to be examined for code smells.
|
37
|
+
#
|
38
|
+
def to_reek_source(description = 'io')
|
39
|
+
Reek::Source.new(self.readlines.join, description)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class String
|
44
|
+
#
|
45
|
+
# Creates a new +Source+ that assumes this string contains Ruby source
|
46
|
+
# code and prepares it to be examined for code smells.
|
47
|
+
#
|
48
|
+
def to_reek_source
|
49
|
+
Reek::Source.new(self, 'string')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Array
|
54
|
+
def paths
|
55
|
+
self.map do |path|
|
56
|
+
if test 'd', path
|
57
|
+
Dir["#{path}/**/*.rb"].paths
|
58
|
+
else
|
59
|
+
path
|
60
|
+
end
|
61
|
+
end.flatten.sort
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Creates a new +Sniffer+ that assumes this Array contains the names
|
66
|
+
# of Ruby source files and examines those files for smells.
|
67
|
+
#
|
68
|
+
def sniff
|
69
|
+
sniffers = paths.map {|path| File.new(path).sniff}
|
70
|
+
Reek::SnifferSet.new(sniffers, 'dir')
|
71
|
+
end
|
72
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'reek/adapters/source'
|
2
|
+
|
1
3
|
module Reek
|
2
4
|
class ObjectSource < Source # :nodoc:
|
3
5
|
|
@@ -9,9 +11,10 @@ module Reek
|
|
9
11
|
return unifier.process(sexp[0])
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
14
|
+
def configure(sniffer)
|
13
15
|
super
|
14
|
-
|
16
|
+
disabled_config = {Reek::Smells::SmellDetector::ENABLED_KEY => false}
|
17
|
+
sniffer.configure(LargeClass, disabled_config)
|
15
18
|
end
|
16
19
|
|
17
20
|
def can_parse_objects?
|
@@ -39,9 +42,7 @@ class Object
|
|
39
42
|
# Constructs a Sniffer which examines this object for code smells.
|
40
43
|
# (This feature is only enabled if you have the ParseTree gem installed.)
|
41
44
|
#
|
42
|
-
def
|
43
|
-
|
44
|
-
ObjectSource.new(self, self.to_s, result)
|
45
|
-
result
|
45
|
+
def to_reek_source
|
46
|
+
ObjectSource.new(self, self.to_s)
|
46
47
|
end
|
47
48
|
end
|
@@ -59,7 +59,7 @@ module Reek
|
|
59
59
|
# Defines a new task, using the name +name+.
|
60
60
|
def initialize(name = :reek)
|
61
61
|
@name = name
|
62
|
-
@libs = [File.expand_path(File.dirname(__FILE__) + '
|
62
|
+
@libs = [File.expand_path(File.dirname(__FILE__) + '/../../../lib')]
|
63
63
|
@source_files = nil
|
64
64
|
@ruby_opts = []
|
65
65
|
@reek_opts = ''
|
@@ -87,7 +87,7 @@ private
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def self.reek_script
|
90
|
-
File.expand_path(File.dirname(__FILE__) + '
|
90
|
+
File.expand_path(File.dirname(__FILE__) + '/../../../bin/reek')
|
91
91
|
end
|
92
92
|
|
93
93
|
def self.ruby_exe
|