reek 2.2.1 → 3.0.0

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 (157) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +9 -4
  4. data/CHANGELOG +8 -0
  5. data/Gemfile +6 -4
  6. data/README.md +6 -0
  7. data/docs/API.md +51 -22
  8. data/docs/Configuration-Files.md +12 -1
  9. data/docs/Feature-Envy.md +30 -10
  10. data/docs/How-reek-works-internally.md +109 -39
  11. data/docs/RSpec-matchers.md +26 -22
  12. data/docs/Reek-Driven-Development.md +0 -8
  13. data/docs/Utility-Function.md +8 -10
  14. data/features/{ruby_api/api.feature → command_line_interface/basic_usage.feature} +2 -2
  15. data/features/programmatic_access.feature +21 -2
  16. data/features/samples.feature +3 -1
  17. data/lib/reek.rb +2 -2
  18. data/lib/reek/{core → ast}/ast_node_class_map.rb +8 -8
  19. data/lib/reek/{sexp/sexp_node.rb → ast/node.rb} +47 -6
  20. data/lib/reek/{core → ast}/object_refs.rb +2 -1
  21. data/lib/reek/{core → ast}/reference_collector.rb +2 -1
  22. data/lib/reek/{sexp → ast}/sexp_extensions.rb +10 -5
  23. data/lib/reek/{sexp → ast}/sexp_formatter.rb +7 -5
  24. data/lib/reek/cli/application.rb +1 -0
  25. data/lib/reek/cli/command.rb +1 -0
  26. data/lib/reek/cli/input.rb +4 -1
  27. data/lib/reek/cli/option_interpreter.rb +6 -4
  28. data/lib/reek/cli/options.rb +2 -1
  29. data/lib/reek/cli/reek_command.rb +3 -2
  30. data/lib/reek/cli/silencer.rb +1 -0
  31. data/lib/reek/{core → cli}/warning_collector.rb +2 -1
  32. data/lib/reek/code_comment.rb +36 -0
  33. data/lib/reek/configuration/app_configuration.rb +17 -2
  34. data/lib/reek/configuration/configuration_file_finder.rb +1 -0
  35. data/lib/reek/{core → context}/code_context.rb +7 -5
  36. data/lib/reek/{core → context}/method_context.rb +5 -3
  37. data/lib/reek/{core → context}/module_context.rb +8 -3
  38. data/lib/reek/{core/stop_context.rb → context/root_context.rb} +4 -2
  39. data/lib/reek/{core → context}/singleton_method_context.rb +2 -1
  40. data/lib/reek/examiner.rb +82 -0
  41. data/lib/reek/report/formatter.rb +70 -0
  42. data/lib/reek/report/heading_formatter.rb +45 -0
  43. data/lib/reek/report/location_formatter.rb +35 -0
  44. data/lib/reek/report/report.rb +198 -0
  45. data/lib/reek/smells.rb +24 -13
  46. data/lib/reek/smells/attribute.rb +6 -4
  47. data/lib/reek/smells/boolean_parameter.rb +3 -1
  48. data/lib/reek/smells/class_variable.rb +3 -1
  49. data/lib/reek/smells/control_parameter.rb +3 -1
  50. data/lib/reek/smells/data_clump.rb +3 -1
  51. data/lib/reek/smells/duplicate_method_call.rb +3 -1
  52. data/lib/reek/smells/feature_envy.rb +3 -1
  53. data/lib/reek/smells/irresponsible_module.rb +12 -7
  54. data/lib/reek/smells/long_parameter_list.rb +5 -3
  55. data/lib/reek/smells/long_yield_list.rb +3 -1
  56. data/lib/reek/smells/module_initialize.rb +3 -1
  57. data/lib/reek/smells/nested_iterators.rb +3 -1
  58. data/lib/reek/smells/nil_check.rb +3 -1
  59. data/lib/reek/smells/prima_donna_method.rb +3 -1
  60. data/lib/reek/smells/repeated_conditional.rb +5 -3
  61. data/lib/reek/{core → smells}/smell_configuration.rb +3 -1
  62. data/lib/reek/smells/smell_detector.rb +9 -7
  63. data/lib/reek/{core → smells}/smell_repository.rb +3 -2
  64. data/lib/reek/smells/smell_warning.rb +6 -4
  65. data/lib/reek/smells/too_many_instance_variables.rb +3 -1
  66. data/lib/reek/smells/too_many_methods.rb +3 -1
  67. data/lib/reek/smells/too_many_statements.rb +3 -1
  68. data/lib/reek/smells/uncommunicative_method_name.rb +3 -1
  69. data/lib/reek/smells/uncommunicative_module_name.rb +3 -1
  70. data/lib/reek/smells/uncommunicative_parameter_name.rb +3 -1
  71. data/lib/reek/smells/uncommunicative_variable_name.rb +3 -1
  72. data/lib/reek/smells/unused_parameters.rb +3 -1
  73. data/lib/reek/smells/utility_function.rb +5 -2
  74. data/lib/reek/source/source_code.rb +40 -9
  75. data/lib/reek/source/source_locator.rb +30 -12
  76. data/lib/reek/spec/should_reek.rb +5 -4
  77. data/lib/reek/spec/should_reek_of.rb +3 -2
  78. data/lib/reek/spec/should_reek_only_of.rb +5 -4
  79. data/lib/reek/tree_dresser.rb +32 -0
  80. data/lib/reek/tree_walker.rb +182 -0
  81. data/lib/reek/version.rb +1 -1
  82. data/reek.gemspec +3 -3
  83. data/spec/factories/factories.rb +2 -0
  84. data/spec/reek/{sexp/sexp_node_spec.rb → ast/node_spec.rb} +2 -2
  85. data/spec/reek/{core → ast}/object_refs_spec.rb +3 -3
  86. data/spec/reek/{core → ast}/reference_collector_spec.rb +2 -2
  87. data/spec/reek/{sexp → ast}/sexp_extensions_spec.rb +6 -16
  88. data/spec/reek/{sexp → ast}/sexp_formatter_spec.rb +2 -2
  89. data/spec/reek/cli/option_interpreter_spec.rb +2 -1
  90. data/spec/reek/{core → cli}/warning_collector_spec.rb +3 -3
  91. data/spec/reek/{core/code_comment_spec.rb → code_comment_spec.rb} +3 -3
  92. data/spec/reek/configuration/app_configuration_spec.rb +31 -18
  93. data/spec/reek/{core → context}/code_context_spec.rb +14 -15
  94. data/spec/reek/{core → context}/method_context_spec.rb +8 -8
  95. data/spec/reek/{core → context}/module_context_spec.rb +4 -4
  96. data/spec/reek/context/root_context_spec.rb +14 -0
  97. data/spec/reek/{core → context}/singleton_method_context_spec.rb +4 -4
  98. data/spec/reek/{core/examiner_spec.rb → examiner_spec.rb} +3 -42
  99. data/spec/reek/{cli → report}/html_report_spec.rb +5 -5
  100. data/spec/reek/report/json_report_spec.rb +20 -0
  101. data/spec/reek/{cli → report}/text_report_spec.rb +14 -14
  102. data/spec/reek/{cli → report}/xml_report_spec.rb +7 -7
  103. data/spec/reek/report/yaml_report_spec.rb +20 -0
  104. data/spec/reek/smells/attribute_spec.rb +2 -1
  105. data/spec/reek/smells/boolean_parameter_spec.rb +1 -1
  106. data/spec/reek/smells/class_variable_spec.rb +5 -5
  107. data/spec/reek/smells/control_parameter_spec.rb +1 -1
  108. data/spec/reek/smells/data_clump_spec.rb +1 -1
  109. data/spec/reek/smells/duplicate_method_call_spec.rb +3 -3
  110. data/spec/reek/smells/feature_envy_spec.rb +1 -1
  111. data/spec/reek/smells/irresponsible_module_spec.rb +24 -28
  112. data/spec/reek/smells/long_parameter_list_spec.rb +2 -2
  113. data/spec/reek/smells/long_yield_list_spec.rb +2 -2
  114. data/spec/reek/smells/nested_iterators_spec.rb +1 -1
  115. data/spec/reek/smells/nil_check_spec.rb +2 -2
  116. data/spec/reek/smells/prima_donna_method_spec.rb +3 -3
  117. data/spec/reek/smells/repeated_conditional_spec.rb +6 -6
  118. data/spec/reek/{core → smells}/smell_configuration_spec.rb +4 -4
  119. data/spec/reek/smells/smell_detector_shared.rb +2 -2
  120. data/spec/reek/{core → smells}/smell_repository_spec.rb +5 -4
  121. data/spec/reek/smells/too_many_instance_variables_spec.rb +1 -1
  122. data/spec/reek/smells/too_many_methods_spec.rb +4 -4
  123. data/spec/reek/smells/too_many_statements_spec.rb +2 -2
  124. data/spec/reek/smells/uncommunicative_method_name_spec.rb +1 -1
  125. data/spec/reek/smells/uncommunicative_module_name_spec.rb +4 -4
  126. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +2 -2
  127. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +3 -3
  128. data/spec/reek/smells/utility_function_spec.rb +23 -1
  129. data/spec/reek/source/source_code_spec.rb +1 -1
  130. data/spec/reek/source/source_locator_spec.rb +30 -0
  131. data/spec/reek/spec/should_reek_of_spec.rb +0 -17
  132. data/spec/reek/spec/should_reek_spec.rb +0 -25
  133. data/spec/reek/tree_dresser_spec.rb +16 -0
  134. data/spec/reek/{core/tree_walker_spec.rb → tree_walker_spec.rb} +5 -5
  135. data/spec/samples/{simple_configuration.reek → configuration/simple_configuration.reek} +0 -0
  136. data/spec/samples/configuration/with_excluded_paths.reek +4 -0
  137. data/spec/samples/source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb +5 -0
  138. data/spec/samples/source_with_exclude_paths/nested/ignore_me_as_well/irresponsible_module.rb +2 -0
  139. data/spec/samples/source_with_exclude_paths/nested/uncommunicative_parameter_name.rb +6 -0
  140. data/spec/spec_helper.rb +6 -7
  141. data/tasks/develop.rake +2 -2
  142. metadata +71 -69
  143. data/lib/reek/cli/report/formatter.rb +0 -69
  144. data/lib/reek/cli/report/heading_formatter.rb +0 -45
  145. data/lib/reek/cli/report/location_formatter.rb +0 -34
  146. data/lib/reek/cli/report/report.rb +0 -191
  147. data/lib/reek/core/ast_node.rb +0 -38
  148. data/lib/reek/core/code_comment.rb +0 -37
  149. data/lib/reek/core/examiner.rb +0 -85
  150. data/lib/reek/core/tree_dresser.rb +0 -24
  151. data/lib/reek/core/tree_walker.rb +0 -180
  152. data/lib/reek/source/source_repository.rb +0 -43
  153. data/spec/reek/cli/json_report_spec.rb +0 -20
  154. data/spec/reek/cli/yaml_report_spec.rb +0 -20
  155. data/spec/reek/core/object_source_spec.rb +0 -18
  156. data/spec/reek/core/stop_context_spec.rb +0 -14
  157. data/spec/reek/core/tree_dresser_spec.rb +0 -16
@@ -1,4 +1,5 @@
1
1
  require_relative 'smell_detector'
2
+ require_relative 'smell_warning'
2
3
 
3
4
  module Reek
4
5
  module Smells
@@ -7,7 +8,8 @@ module Reek
7
8
  # hard to tell initialization order and parameters so having 'initialize'
8
9
  # in a module is usually a bad idea
9
10
  #
10
- # See docs/Module-Initialize for details.
11
+ # See {file:docs/Module-Initialize.md} for details.
12
+ # @api private
11
13
  class ModuleInitialize < SmellDetector
12
14
  def self.contexts # :nodoc:
13
15
  [:module]
@@ -1,4 +1,5 @@
1
1
  require_relative 'smell_detector'
2
+ require_relative 'smell_warning'
2
3
 
3
4
  module Reek
4
5
  module Smells
@@ -7,7 +8,8 @@ module Reek
7
8
  #
8
9
  # +NestedIterators+ reports failing methods only once.
9
10
  #
10
- # See docs/Nested-Iterators for details.
11
+ # See {file:docs/Nested-Iterators.md} for details.
12
+ # @api private
11
13
  class NestedIterators < SmellDetector
12
14
  # The name of the config field that sets the maximum depth
13
15
  # of nested iterators to be permitted within any single method.
@@ -1,11 +1,13 @@
1
1
  require_relative 'smell_detector'
2
+ require_relative 'smell_warning'
2
3
 
3
4
  module Reek
4
5
  module Smells
5
6
  # Checking for nil is a special kind of type check, and therefore a case of
6
7
  # SimulatedPolymorphism.
7
8
  #
8
- # See docs/Nil-Check for details.
9
+ # See {file:docs/Nil-Check.md} for details.
10
+ # @api private
9
11
  class NilCheck < SmellDetector
10
12
  def self.smell_category
11
13
  'SimulatedPolymorphism'
@@ -1,4 +1,5 @@
1
1
  require_relative 'smell_detector'
2
+ require_relative 'smell_warning'
2
3
 
3
4
  module Reek
4
5
  module Smells
@@ -21,7 +22,8 @@ module Reek
21
22
  #
22
23
  # Such a method is called PrimaDonnaMethod and is reported as a smell.
23
24
  #
24
- # See docs/Prima-Donna-Method for details.
25
+ # See {file:docs/Prima-Donna-Method.md} for details.
26
+ # @api private
25
27
  class PrimaDonnaMethod < SmellDetector
26
28
  def self.contexts # :nodoc:
27
29
  [:class]
@@ -1,5 +1,6 @@
1
+ require_relative '../ast/node'
1
2
  require_relative 'smell_detector'
2
- require_relative '../core/ast_node'
3
+ require_relative 'smell_warning'
3
4
 
4
5
  module Reek
5
6
  module Smells
@@ -22,7 +23,8 @@ module Reek
22
23
  # +RepeatedConditional+ checks for multiple conditionals
23
24
  # testing the same value throughout a single class.
24
25
  #
25
- # See docs/Repeated-Conditional for details.
26
+ # See {file:docs/Repeated-Conditional.md} for details.
27
+ # @api private
26
28
  class RepeatedConditional < SmellDetector
27
29
  # The name of the config field that sets the maximum number of
28
30
  # identical conditionals permitted within any single class.
@@ -33,7 +35,7 @@ module Reek
33
35
  'SimulatedPolymorphism'
34
36
  end
35
37
 
36
- BLOCK_GIVEN_CONDITION = AST::Node.new(:send, [nil, :block_given?])
38
+ BLOCK_GIVEN_CONDITION = ::Parser::AST::Node.new(:send, [nil, :block_given?])
37
39
 
38
40
  def self.contexts # :nodoc:
39
41
  [:class]
@@ -1,8 +1,9 @@
1
1
  module Reek
2
- module Core
2
+ module Smells
3
3
  #
4
4
  # Represents a single set of configuration options for a smell detector
5
5
  #
6
+ # @api private
6
7
  class SmellConfiguration
7
8
  # The name of the config field that specifies whether a smell is
8
9
  # enabled. Set to +true+ or +false+.
@@ -45,6 +46,7 @@ module Reek
45
46
  #
46
47
  # A set of context-specific overrides for smell detectors.
47
48
  #
49
+ # @api private
48
50
  class Overrides
49
51
  def initialize(hash)
50
52
  @hash = hash
@@ -1,5 +1,5 @@
1
1
  require 'set'
2
- require_relative '../core/smell_configuration'
2
+ require_relative 'smell_configuration'
3
3
 
4
4
  module Reek
5
5
  module Smells
@@ -7,10 +7,12 @@ module Reek
7
7
  # Shared responsibilities of all smell detectors.
8
8
  #
9
9
  # See
10
- # - docs/Basic-Smell-Options
11
- # - docs/Code-Smells
12
- # - docs/Configuration-Files
10
+ # - {file:docs/Basic-Smell-Options.md}
11
+ # - {file:docs/Code-Smells.md}
12
+ # - {file:docs/Configuration-Files.md}
13
13
  # for details.
14
+ #
15
+ # @api private
14
16
  class SmellDetector
15
17
  attr_reader :source
16
18
 
@@ -30,7 +32,7 @@ module Reek
30
32
 
31
33
  def default_config
32
34
  {
33
- Core::SmellConfiguration::ENABLED_KEY => true,
35
+ SmellConfiguration::ENABLED_KEY => true,
34
36
  EXCLUDE_KEY => DEFAULT_EXCLUDE_SET.dup
35
37
  }
36
38
  end
@@ -71,7 +73,7 @@ module Reek
71
73
 
72
74
  def initialize(source, config = self.class.default_config)
73
75
  @source = source
74
- @config = Core::SmellConfiguration.new(config)
76
+ @config = SmellConfiguration.new(config)
75
77
  @smells_found = []
76
78
  end
77
79
 
@@ -98,7 +100,7 @@ module Reek
98
100
  end
99
101
 
100
102
  def enabled_for?(context)
101
- enabled? && config_for(context)[Core::SmellConfiguration::ENABLED_KEY] != false
103
+ enabled? && config_for(context)[SmellConfiguration::ENABLED_KEY] != false
102
104
  end
103
105
 
104
106
  def exception?(context)
@@ -1,12 +1,13 @@
1
1
  require_relative '../smells'
2
- require_relative '../smells/smell_detector'
2
+ require_relative 'smell_detector'
3
3
  require_relative '../configuration/app_configuration'
4
4
 
5
5
  module Reek
6
- module Core
6
+ module Smells
7
7
  #
8
8
  # Contains all the existing smells and exposes operations on them.
9
9
  #
10
+ # @api private
10
11
  class SmellRepository
11
12
  attr_reader :detectors
12
13
 
@@ -19,10 +19,6 @@ module Reek
19
19
  self.parameters = options.fetch(:parameters, {})
20
20
  end
21
21
 
22
- def smell_classes
23
- [smell_detector.smell_category, smell_detector.smell_type]
24
- end
25
-
26
22
  def hash
27
23
  sort_key.hash
28
24
  end
@@ -35,10 +31,12 @@ module Reek
35
31
  (self <=> other) == 0
36
32
  end
37
33
 
34
+ # @api private
38
35
  def matches?(klass, other_parameters = {})
39
36
  smell_classes.include?(klass.to_s) && common_parameters_equal?(other_parameters)
40
37
  end
41
38
 
39
+ # @api private
42
40
  def report_on(listener)
43
41
  listener.found_smell(self)
44
42
  end
@@ -58,6 +56,10 @@ module Reek
58
56
 
59
57
  private
60
58
 
59
+ def smell_classes
60
+ [smell_detector.smell_category, smell_detector.smell_type]
61
+ end
62
+
61
63
  def common_parameters_equal?(other_parameters)
62
64
  other_parameters.keys.each do |key|
63
65
  unless parameters.key?(key)
@@ -1,4 +1,5 @@
1
1
  require_relative 'smell_detector'
2
+ require_relative 'smell_warning'
2
3
 
3
4
  module Reek
4
5
  module Smells
@@ -9,7 +10,8 @@ module Reek
9
10
  # +TooManyInstanceVariables' reports classes having more than a
10
11
  # configurable number of instance variables.
11
12
  #
12
- # See docs/Too-Many-Instance-Variables for details.
13
+ # See {file:docs/Too-Many-Instance-Variables.md} for details.
14
+ # @api private
13
15
  class TooManyInstanceVariables < SmellDetector
14
16
  # The name of the config field that sets the maximum number of instance
15
17
  # variables permitted in a class.
@@ -1,4 +1,5 @@
1
1
  require_relative 'smell_detector'
2
+ require_relative 'smell_warning'
2
3
 
3
4
  module Reek
4
5
  module Smells
@@ -11,7 +12,8 @@ module Reek
11
12
  # methods, and excludes methods inherited from superclasses or included
12
13
  # modules.
13
14
  #
14
- # See docs/Too-Many-Methods for details.
15
+ # See {file:docs/Too-Many-Methods.md} for details.
16
+ # @api private
15
17
  class TooManyMethods < SmellDetector
16
18
  # The name of the config field that sets the maximum number of methods
17
19
  # permitted in a class.
@@ -1,4 +1,5 @@
1
1
  require_relative 'smell_detector'
2
+ require_relative 'smell_warning'
2
3
 
3
4
  module Reek
4
5
  module Smells
@@ -7,7 +8,8 @@ module Reek
7
8
  #
8
9
  # +TooManyStatements+ reports any method with more than 5 statements.
9
10
  #
10
- # See docs/Too-Many-Statements for details.
11
+ # See {file:docs/Too-Many-Statements.md} for details.
12
+ # @api private
11
13
  class TooManyStatements < SmellDetector
12
14
  # The name of the config field that sets the maximum number of
13
15
  # statements permitted in any method.
@@ -1,4 +1,5 @@
1
1
  require_relative 'smell_detector'
2
+ require_relative 'smell_warning'
2
3
 
3
4
  module Reek
4
5
  module Smells
@@ -15,7 +16,8 @@ module Reek
15
16
  # * 1-character names
16
17
  # * names ending with a number
17
18
  #
18
- # See docs/Uncommunicative-Method-Name for details.
19
+ # See {file:docs/Uncommunicative-Method-Name.md} for details.
20
+ # @api private
19
21
  class UncommunicativeMethodName < SmellDetector
20
22
  # The name of the config field that lists the regexps of
21
23
  # smelly names to be reported.
@@ -1,4 +1,5 @@
1
1
  require_relative 'smell_detector'
2
+ require_relative 'smell_warning'
2
3
 
3
4
  module Reek
4
5
  module Smells
@@ -15,7 +16,8 @@ module Reek
15
16
  # * 1-character names
16
17
  # * names ending with a number
17
18
  #
18
- # See docs/Uncommunicative-Module-Name for details.
19
+ # See {file:docs/Uncommunicative-Module-Name.md} for details.
20
+ # @api private
19
21
  class UncommunicativeModuleName < SmellDetector
20
22
  # The name of the config field that lists the regexps of
21
23
  # smelly names to be reported.
@@ -1,4 +1,5 @@
1
1
  require_relative 'smell_detector'
2
+ require_relative 'smell_warning'
2
3
 
3
4
  module Reek
4
5
  module Smells
@@ -15,7 +16,8 @@ module Reek
15
16
  # * 1-character names
16
17
  # * names ending with a number
17
18
  #
18
- # See docs/Uncommunicative-Parameter-Name for details.
19
+ # See {file:docs/Uncommunicative-Parameter-Name.md} for details.
20
+ # @api private
19
21
  class UncommunicativeParameterName < SmellDetector
20
22
  # The name of the config field that lists the regexps of
21
23
  # smelly names to be reported.
@@ -1,4 +1,5 @@
1
1
  require_relative 'smell_detector'
2
+ require_relative 'smell_warning'
2
3
 
3
4
  module Reek
4
5
  module Smells
@@ -15,7 +16,8 @@ module Reek
15
16
  # * 1-character names
16
17
  # * names ending with a number
17
18
  #
18
- # See docs/Uncommunicative-Variable-Name for details.
19
+ # See {file:docs/Uncommunicative-Variable-Name.md} for details.
20
+ # @api private
19
21
  class UncommunicativeVariableName < SmellDetector
20
22
  # The name of the config field that lists the regexps of
21
23
  # smelly names to be reported.
@@ -1,11 +1,13 @@
1
1
  require_relative 'smell_detector'
2
+ require_relative 'smell_warning'
2
3
 
3
4
  module Reek
4
5
  module Smells
5
6
  #
6
7
  # Methods should use their parameters.
7
8
  #
8
- # See docs/Unused-Parameters for details.
9
+ # See {file:docs/Unused-Parameters.md} for details.
10
+ # @api private
9
11
  class UnusedParameters < SmellDetector
10
12
  def self.smell_category
11
13
  'UnusedCode'
@@ -1,5 +1,6 @@
1
+ require_relative '../ast/reference_collector'
1
2
  require_relative 'smell_detector'
2
- require_relative '../core/reference_collector'
3
+ require_relative 'smell_warning'
3
4
 
4
5
  module Reek
5
6
  module Smells
@@ -34,7 +35,8 @@ module Reek
34
35
  # If the method does refer to self, but refers to some other object more,
35
36
  # +FeatureEnvy+ is reported instead.
36
37
  #
37
- # See docs/Utility-Function for details.
38
+ # See {file:docs/Utility-Function.md} for details.
39
+ # @api private
38
40
  class UtilityFunction < SmellDetector
39
41
  def self.smell_category
40
42
  'LowCohesion'
@@ -52,6 +54,7 @@ module Reek
52
54
  # @return [Array<SmellWarning>]
53
55
  #
54
56
  def examine_context(method_ctx)
57
+ return [] if method_ctx.exp.singleton_method?
55
58
  return [] if method_ctx.num_statements == 0
56
59
  return [] if method_ctx.references_self?
57
60
  return [] if num_helper_methods(method_ctx).zero?
@@ -1,15 +1,17 @@
1
1
  require_relative '../cli/silencer'
2
2
  Reek::CLI::Silencer.silently do
3
- require 'parser/current'
3
+ require 'parser/ruby22'
4
4
  end
5
- require_relative '../core/tree_dresser'
6
- require_relative '../core/ast_node'
5
+ require_relative '../tree_dresser'
6
+ require_relative '../ast/node'
7
7
 
8
8
  module Reek
9
+ # @api private
9
10
  module Source
10
11
  #
11
12
  # A +Source+ object represents a chunk of Ruby source code.
12
13
  #
14
+ # @api private
13
15
  class SourceCode
14
16
  attr_reader :description
15
17
 
@@ -18,7 +20,7 @@ module Reek
18
20
  # code - ruby code as String
19
21
  # description - in case of STDIN this is "STDIN" otherwise it's a filepath as String
20
22
  # parser - the parser to use for generating AST's out of the given source
21
- def initialize(code, description, parser = Parser::Ruby21)
23
+ def initialize(code, description, parser = Parser::Ruby22)
22
24
  @source = code
23
25
  @description = description
24
26
  @parser = parser
@@ -30,9 +32,9 @@ module Reek
30
32
  # - from IO (STDIN) a la `echo "class Foo; end" | reek`
31
33
  # - from String via our rspec matchers a la `expect("class Foo; end").to reek`
32
34
  #
33
- # source - One of File|IO|String
35
+ # @param source [File|IO|String] - the given source
34
36
  #
35
- # Returns an instance of SourceCode
37
+ # @return an instance of SourceCode
36
38
  def self.from(source)
37
39
  case source
38
40
  when File then new(source.read, source.path)
@@ -41,9 +43,37 @@ module Reek
41
43
  end
42
44
  end
43
45
 
44
- # Parses the given source into an AST.
46
+ # Parses the given source into an AST and associates the source code comments with it.
47
+ # This AST is then traversed by a TreeDresser which adorns the nodes in the AST
48
+ # with our SexpExtensions.
49
+ # Finally this AST is returned where each node is an anonymous subclass of Reek::AST::Node
45
50
  #
46
- # @return [Reek::Core::ASTNode] the AST presentation of the given source
51
+ # Important to note is that reek will not fail on unparseable files but rather print out
52
+ # a warning and then just continue.
53
+ #
54
+ # Given this @source:
55
+ #
56
+ # # comment about C
57
+ # class C
58
+ # def m
59
+ # puts 'nada'
60
+ # end
61
+ # end
62
+ #
63
+ # this method would return something that looks like
64
+ #
65
+ # (class
66
+ # (const nil :C) nil
67
+ # (def :m
68
+ # (args)
69
+ # (send nil :puts
70
+ # (str "nada"))))
71
+ #
72
+ # where each node is possibly adorned with our SexpExtensions (see ast/ast_node_class_map
73
+ # and ast/sexp_extensions for details).
74
+ #
75
+ # @return [Anonymous subclass of Reek::AST::Node] the AST presentation
76
+ # for the given source
47
77
  def syntax_tree
48
78
  @syntax_tree ||=
49
79
  begin
@@ -53,8 +83,9 @@ module Reek
53
83
  $stderr.puts "#{description}: #{error.class.name}: #{error}"
54
84
  end
55
85
 
86
+ # See https://whitequark.github.io/parser/Parser/Source/Comment/Associator.html
56
87
  comment_map = Parser::Source::Comment.associate(ast, comments) if ast
57
- Core::TreeDresser.new.dress(ast, comment_map)
88
+ TreeDresser.new.dress(ast, comment_map)
58
89
  end
59
90
  end
60
91
  end