reek 2.2.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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