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.
Files changed (209) hide show
  1. data/.yardopts +10 -0
  2. data/History.txt +62 -0
  3. data/README.md +74 -0
  4. data/bin/reek +2 -2
  5. data/config/defaults.reek +44 -5
  6. data/features/api.feature +20 -0
  7. data/features/masking_smells.feature +60 -42
  8. data/features/options.feature +7 -2
  9. data/features/rake_task.feature +29 -22
  10. data/features/reports.feature +9 -41
  11. data/features/samples.feature +184 -196
  12. data/features/stdin.feature +5 -8
  13. data/features/step_definitions/reek_steps.rb +8 -4
  14. data/features/support/env.rb +2 -3
  15. data/features/yaml.feature +85 -0
  16. data/lib/reek/cli/application.rb +46 -0
  17. data/lib/reek/cli/command_line.rb +108 -0
  18. data/lib/reek/cli/help_command.rb +18 -0
  19. data/lib/reek/cli/reek_command.rb +37 -0
  20. data/lib/reek/cli/report.rb +58 -0
  21. data/lib/reek/cli/version_command.rb +19 -0
  22. data/lib/reek/cli/yaml_command.rb +32 -0
  23. data/lib/reek/core/code_context.rb +64 -0
  24. data/lib/reek/core/code_parser.rb +166 -0
  25. data/lib/reek/core/method_context.rb +84 -0
  26. data/lib/reek/core/module_context.rb +20 -0
  27. data/lib/reek/core/object_refs.rb +51 -0
  28. data/lib/reek/core/singleton_method_context.rb +20 -0
  29. data/lib/reek/core/smell_configuration.rb +62 -0
  30. data/lib/reek/core/sniffer.rb +105 -0
  31. data/lib/reek/core/stop_context.rb +30 -0
  32. data/lib/reek/core/warning_collector.rb +27 -0
  33. data/lib/reek/examiner.rb +104 -0
  34. data/lib/reek/rake/task.rb +142 -0
  35. data/lib/reek/smell_warning.rb +73 -23
  36. data/lib/reek/smells/attribute.rb +26 -21
  37. data/lib/reek/smells/boolean_parameter.rb +38 -0
  38. data/lib/reek/smells/class_variable.rb +22 -9
  39. data/lib/reek/smells/control_couple.rb +40 -16
  40. data/lib/reek/smells/data_clump.rb +114 -23
  41. data/lib/reek/smells/duplication.rb +55 -15
  42. data/lib/reek/smells/feature_envy.rb +16 -7
  43. data/lib/reek/smells/irresponsible_module.rb +37 -0
  44. data/lib/reek/smells/large_class.rb +37 -19
  45. data/lib/reek/smells/long_method.rb +20 -9
  46. data/lib/reek/smells/long_parameter_list.rb +22 -10
  47. data/lib/reek/smells/long_yield_list.rb +43 -7
  48. data/lib/reek/smells/nested_iterators.rb +68 -8
  49. data/lib/reek/smells/simulated_polymorphism.rb +26 -15
  50. data/lib/reek/smells/smell_detector.rb +29 -51
  51. data/lib/reek/smells/uncommunicative_method_name.rb +74 -0
  52. data/lib/reek/smells/uncommunicative_module_name.rb +74 -0
  53. data/lib/reek/smells/uncommunicative_parameter_name.rb +79 -0
  54. data/lib/reek/smells/uncommunicative_variable_name.rb +89 -0
  55. data/lib/reek/smells/utility_function.rb +51 -12
  56. data/lib/reek/smells.rb +29 -0
  57. data/lib/reek/source/code_comment.rb +37 -0
  58. data/lib/reek/source/config_file.rb +72 -0
  59. data/lib/reek/source/core_extras.rb +46 -0
  60. data/lib/reek/source/reference_collector.rb +28 -0
  61. data/lib/reek/source/sexp_formatter.rb +17 -0
  62. data/lib/reek/source/source_code.rb +44 -0
  63. data/lib/reek/source/source_file.rb +32 -0
  64. data/lib/reek/source/source_locator.rb +42 -0
  65. data/lib/reek/source/tree_dresser.rb +204 -0
  66. data/lib/reek/source.rb +18 -0
  67. data/lib/reek/spec/should_reek.rb +31 -0
  68. data/lib/reek/spec/should_reek_of.rb +37 -0
  69. data/lib/reek/spec/should_reek_only_of.rb +37 -0
  70. data/lib/reek/spec.rb +51 -0
  71. data/lib/reek.rb +8 -4
  72. data/reek.gemspec +9 -7
  73. data/spec/matchers/smell_of_matcher.rb +58 -0
  74. data/spec/reek/{help_command_spec.rb → cli/help_command_spec.rb} +3 -4
  75. data/spec/reek/cli/reek_command_spec.rb +46 -0
  76. data/spec/reek/cli/report_spec.rb +30 -0
  77. data/spec/reek/{version_command_spec.rb → cli/version_command_spec.rb} +3 -3
  78. data/spec/reek/cli/yaml_command_spec.rb +47 -0
  79. data/spec/reek/core/code_context_spec.rb +145 -0
  80. data/spec/reek/{code_parser_spec.rb → core/code_parser_spec.rb} +7 -6
  81. data/spec/reek/{config_spec.rb → core/config_spec.rb} +2 -6
  82. data/spec/reek/{method_context_spec.rb → core/method_context_spec.rb} +16 -36
  83. data/spec/reek/core/module_context_spec.rb +27 -0
  84. data/spec/reek/{object_refs_spec.rb → core/object_refs_spec.rb} +5 -6
  85. data/spec/reek/core/singleton_method_context_spec.rb +9 -0
  86. data/spec/reek/core/smell_configuration_spec.rb +11 -0
  87. data/spec/reek/core/stop_context_spec.rb +17 -0
  88. data/spec/reek/core/warning_collector_spec.rb +27 -0
  89. data/spec/reek/examiner_spec.rb +103 -0
  90. data/spec/reek/smell_warning_spec.rb +74 -82
  91. data/spec/reek/smells/attribute_spec.rb +42 -23
  92. data/spec/reek/smells/behaves_like_variable_detector.rb +2 -2
  93. data/spec/reek/smells/boolean_parameter_spec.rb +66 -0
  94. data/spec/reek/smells/class_variable_spec.rb +60 -75
  95. data/spec/reek/smells/control_couple_spec.rb +37 -32
  96. data/spec/reek/smells/data_clump_spec.rb +63 -24
  97. data/spec/reek/smells/duplication_spec.rb +106 -57
  98. data/spec/reek/smells/feature_envy_spec.rb +113 -92
  99. data/spec/reek/smells/irresponsible_module_spec.rb +58 -0
  100. data/spec/reek/smells/large_class_spec.rb +67 -57
  101. data/spec/reek/smells/long_method_spec.rb +40 -10
  102. data/spec/reek/smells/long_parameter_list_spec.rb +50 -28
  103. data/spec/reek/smells/long_yield_list_spec.rb +57 -0
  104. data/spec/reek/smells/nested_iterators_spec.rb +115 -7
  105. data/spec/reek/smells/simulated_polymorphism_spec.rb +56 -20
  106. data/spec/reek/smells/smell_detector_shared.rb +42 -0
  107. data/spec/reek/smells/uncommunicative_method_name_spec.rb +42 -0
  108. data/spec/reek/smells/uncommunicative_module_name_spec.rb +66 -0
  109. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +71 -0
  110. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +120 -0
  111. data/spec/reek/smells/utility_function_spec.rb +50 -4
  112. data/spec/reek/source/code_comment_spec.rb +82 -0
  113. data/spec/reek/source/object_source_spec.rb +20 -0
  114. data/spec/reek/source/reference_collector_spec.rb +53 -0
  115. data/spec/reek/{adapters/source_spec.rb → source/source_code_spec.rb} +7 -8
  116. data/spec/reek/source/tree_dresser_spec.rb +270 -0
  117. data/spec/reek/spec/should_reek_of_spec.rb +76 -0
  118. data/spec/reek/spec/should_reek_only_of_spec.rb +89 -0
  119. data/spec/reek/{adapters → spec}/should_reek_spec.rb +8 -32
  120. data/spec/samples/all_but_one_masked/clean_one.rb +1 -0
  121. data/spec/samples/all_but_one_masked/dirty.rb +1 -0
  122. data/spec/samples/all_but_one_masked/masked.reek +5 -1
  123. data/spec/samples/clean_due_to_masking/clean_one.rb +1 -0
  124. data/spec/samples/clean_due_to_masking/clean_three.rb +1 -0
  125. data/spec/samples/clean_due_to_masking/clean_two.rb +1 -0
  126. data/spec/samples/clean_due_to_masking/dirty_one.rb +1 -1
  127. data/spec/samples/clean_due_to_masking/dirty_two.rb +1 -1
  128. data/spec/samples/clean_due_to_masking/masked.reek +5 -1
  129. data/spec/samples/config/allow_duplication.reek +3 -0
  130. data/spec/samples/config/deeper_nested_iterators.reek +3 -0
  131. data/spec/samples/corrupt_config_file/dirty.rb +1 -1
  132. data/spec/samples/demo/demo.rb +8 -0
  133. data/spec/samples/empty_config_file/dirty.rb +2 -1
  134. data/spec/samples/exceptions.reek +1 -1
  135. data/spec/samples/inline_config/dirty.rb +16 -0
  136. data/spec/samples/inline_config/masked.reek +7 -0
  137. data/spec/samples/mask_some/dirty.rb +8 -0
  138. data/spec/samples/mask_some/some.reek +8 -0
  139. data/spec/samples/masked/dirty.rb +2 -1
  140. data/spec/samples/masked/masked.reek +3 -1
  141. data/spec/samples/mixed_results/clean_one.rb +1 -0
  142. data/spec/samples/mixed_results/clean_three.rb +1 -0
  143. data/spec/samples/mixed_results/clean_two.rb +1 -0
  144. data/spec/samples/mixed_results/dirty_one.rb +1 -0
  145. data/spec/samples/mixed_results/dirty_two.rb +1 -0
  146. data/spec/samples/not_quite_masked/dirty.rb +2 -1
  147. data/spec/samples/not_quite_masked/masked.reek +1 -1
  148. data/spec/samples/overrides/masked/dirty.rb +2 -1
  149. data/spec/samples/overrides/masked/lower.reek +3 -1
  150. data/spec/samples/three_clean_files/clean_one.rb +1 -0
  151. data/spec/samples/three_clean_files/clean_three.rb +1 -0
  152. data/spec/samples/three_clean_files/clean_two.rb +1 -0
  153. data/spec/samples/two_smelly_files/dirty_one.rb +2 -1
  154. data/spec/samples/two_smelly_files/dirty_two.rb +2 -1
  155. data/spec/spec_helper.rb +10 -2
  156. data/tasks/reek.rake +2 -2
  157. data/tasks/test.rake +12 -3
  158. metadata +121 -79
  159. data/README.rdoc +0 -84
  160. data/features/profile.feature +0 -34
  161. data/lib/reek/adapters/application.rb +0 -46
  162. data/lib/reek/adapters/command_line.rb +0 -77
  163. data/lib/reek/adapters/config_file.rb +0 -31
  164. data/lib/reek/adapters/core_extras.rb +0 -64
  165. data/lib/reek/adapters/rake_task.rb +0 -121
  166. data/lib/reek/adapters/report.rb +0 -86
  167. data/lib/reek/adapters/source.rb +0 -72
  168. data/lib/reek/adapters/spec.rb +0 -133
  169. data/lib/reek/block_context.rb +0 -62
  170. data/lib/reek/class_context.rb +0 -41
  171. data/lib/reek/code_context.rb +0 -68
  172. data/lib/reek/code_parser.rb +0 -203
  173. data/lib/reek/configuration.rb +0 -57
  174. data/lib/reek/detector_stack.rb +0 -37
  175. data/lib/reek/help_command.rb +0 -14
  176. data/lib/reek/if_context.rb +0 -18
  177. data/lib/reek/masking_collection.rb +0 -33
  178. data/lib/reek/method_context.rb +0 -138
  179. data/lib/reek/module_context.rb +0 -49
  180. data/lib/reek/name.rb +0 -57
  181. data/lib/reek/object_refs.rb +0 -49
  182. data/lib/reek/reek_command.rb +0 -28
  183. data/lib/reek/sexp_formatter.rb +0 -10
  184. data/lib/reek/singleton_method_context.rb +0 -26
  185. data/lib/reek/smells/uncommunicative_name.rb +0 -84
  186. data/lib/reek/sniffer.rb +0 -177
  187. data/lib/reek/stop_context.rb +0 -35
  188. data/lib/reek/tree_dresser.rb +0 -82
  189. data/lib/reek/version_command.rb +0 -14
  190. data/lib/reek/yield_call_context.rb +0 -12
  191. data/spec/reek/adapters/report_spec.rb +0 -31
  192. data/spec/reek/adapters/should_reek_of_spec.rb +0 -138
  193. data/spec/reek/adapters/should_reek_only_of_spec.rb +0 -87
  194. data/spec/reek/block_context_spec.rb +0 -65
  195. data/spec/reek/class_context_spec.rb +0 -161
  196. data/spec/reek/code_context_spec.rb +0 -182
  197. data/spec/reek/configuration_spec.rb +0 -12
  198. data/spec/reek/if_context_spec.rb +0 -17
  199. data/spec/reek/masking_collection_spec.rb +0 -236
  200. data/spec/reek/module_context_spec.rb +0 -46
  201. data/spec/reek/name_spec.rb +0 -37
  202. data/spec/reek/object_source_spec.rb +0 -23
  203. data/spec/reek/reek_command_spec.rb +0 -45
  204. data/spec/reek/singleton_method_context_spec.rb +0 -16
  205. data/spec/reek/smells/smell_detector_spec.rb +0 -36
  206. data/spec/reek/smells/uncommunicative_name_spec.rb +0 -146
  207. data/spec/reek/sniffer_spec.rb +0 -11
  208. data/spec/reek/stop_context_spec.rb +0 -33
  209. 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
@@ -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
@@ -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
@@ -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