Class: Reek::Examiner

Inherits:
Object
  • Object
show all
Defined in:
lib/reek/examiner.rb

Overview

Applies all available smell detectors to a source.

Defined Under Namespace

Classes: NullHandler

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source, filter_by_smells: [], configuration: Configuration::AppConfiguration.default, detector_repository_class: DetectorRepository, error_handler: NullHandler.new) ⇒ Examiner

Creates an Examiner which scans the given source for code smells.

Parameters:

  • source (File, IO, String)

    If source is a String it is assumed to be Ruby source code; if it is a File or IO, it is opened and Ruby source code is read from it;

  • filter_by_smells (Array<String>) (defaults to: [])

    List of smell types to filter by, e.g. “DuplicateMethodCall”.

  • configuration (Configuration::AppConfiguration) (defaults to: Configuration::AppConfiguration.default)

    The configuration for this Examiner.



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/reek/examiner.rb', line 38

def initialize(source,
               filter_by_smells: [],
               configuration: Configuration::AppConfiguration.default,
               detector_repository_class: DetectorRepository,
               error_handler: NullHandler.new)
  @source              = Source::SourceCode.from(source)
  @origin              = @source.origin
  @smell_types         = detector_repository_class.eligible_smell_types(filter_by_smells)
  @detector_repository = detector_repository_class.new(smell_types: @smell_types,
                                                       configuration: configuration.directive_for(@origin))
  @error_handler       = error_handler
end

Instance Attribute Details

#detector_repositoryObject (readonly, private)

Returns the value of attribute detector_repository.



82
83
84
# File 'lib/reek/examiner.rb', line 82

def detector_repository
  @detector_repository
end

#originString (readonly)

Returns origin of the source being analysed.

Returns:

  • (String)

    origin of the source being analysed



54
55
56
# File 'lib/reek/examiner.rb', line 54

def origin
  @origin
end

#sourceObject (readonly, private)

Returns the value of attribute source.



82
83
84
# File 'lib/reek/examiner.rb', line 82

def source
  @source
end

Instance Method Details

#examine_treeObject (private)



119
120
121
122
123
# File 'lib/reek/examiner.rb', line 119

def examine_tree
  ContextBuilder.new(syntax_tree).context_tree.flat_map do |element|
    detector_repository.examine(element)
  end
end

#runArray<SmellWarning> (private)

Runs the Examiner on the given source to scan for code smells.

In case one of the smell detectors raises an exception we probably hit a Reek bug. So we catch the exception here, let the user know something went wrong and continue with the analysis.

Returns:



92
93
94
95
96
97
98
99
100
# File 'lib/reek/examiner.rb', line 92

def run
  wrap_exceptions do
    examine_tree
  end
rescue StandardError => error
  raise unless @error_handler.handle error

  []
end

#smellsArray<SmellWarning>

Returns the smells found in the source.

Returns:



60
61
62
# File 'lib/reek/examiner.rb', line 60

def smells
  @smells ||= run.sort.uniq
end

#smells_countInteger

Returns the number of smells found in the source.

Returns:

  • (Integer)

    the number of smells found in the source



68
69
70
# File 'lib/reek/examiner.rb', line 68

def smells_count
  smells.length
end

#smelly?Boolean

Returns true if and only if there are code smells in the source.

Returns:

  • (Boolean)

    true if and only if there are code smells in the source.



76
77
78
# File 'lib/reek/examiner.rb', line 76

def smelly?
  !smells.empty?
end

#syntax_treeObject (private)



115
116
117
# File 'lib/reek/examiner.rb', line 115

def syntax_tree
  @syntax_tree ||= source.syntax_tree
end

#wrap_exceptionsObject (private)



103
104
105
106
107
108
109
110
111
112
113
# File 'lib/reek/examiner.rb', line 103

def wrap_exceptions
  yield
rescue Errors::BaseError
  raise
rescue EncodingError
  raise Errors::EncodingError.new(origin: origin)
rescue Parser::SyntaxError
  raise Errors::SyntaxError.new(origin: origin)
rescue StandardError
  raise Errors::IncomprehensibleSourceError.new(origin: origin)
end