reek 2.2.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.travis.yml +9 -4
- data/CHANGELOG +8 -0
- data/Gemfile +6 -4
- data/README.md +6 -0
- data/docs/API.md +51 -22
- data/docs/Configuration-Files.md +12 -1
- data/docs/Feature-Envy.md +30 -10
- data/docs/How-reek-works-internally.md +109 -39
- data/docs/RSpec-matchers.md +26 -22
- data/docs/Reek-Driven-Development.md +0 -8
- data/docs/Utility-Function.md +8 -10
- data/features/{ruby_api/api.feature → command_line_interface/basic_usage.feature} +2 -2
- data/features/programmatic_access.feature +21 -2
- data/features/samples.feature +3 -1
- data/lib/reek.rb +2 -2
- data/lib/reek/{core → ast}/ast_node_class_map.rb +8 -8
- data/lib/reek/{sexp/sexp_node.rb → ast/node.rb} +47 -6
- data/lib/reek/{core → ast}/object_refs.rb +2 -1
- data/lib/reek/{core → ast}/reference_collector.rb +2 -1
- data/lib/reek/{sexp → ast}/sexp_extensions.rb +10 -5
- data/lib/reek/{sexp → ast}/sexp_formatter.rb +7 -5
- data/lib/reek/cli/application.rb +1 -0
- data/lib/reek/cli/command.rb +1 -0
- data/lib/reek/cli/input.rb +4 -1
- data/lib/reek/cli/option_interpreter.rb +6 -4
- data/lib/reek/cli/options.rb +2 -1
- data/lib/reek/cli/reek_command.rb +3 -2
- data/lib/reek/cli/silencer.rb +1 -0
- data/lib/reek/{core → cli}/warning_collector.rb +2 -1
- data/lib/reek/code_comment.rb +36 -0
- data/lib/reek/configuration/app_configuration.rb +17 -2
- data/lib/reek/configuration/configuration_file_finder.rb +1 -0
- data/lib/reek/{core → context}/code_context.rb +7 -5
- data/lib/reek/{core → context}/method_context.rb +5 -3
- data/lib/reek/{core → context}/module_context.rb +8 -3
- data/lib/reek/{core/stop_context.rb → context/root_context.rb} +4 -2
- data/lib/reek/{core → context}/singleton_method_context.rb +2 -1
- data/lib/reek/examiner.rb +82 -0
- data/lib/reek/report/formatter.rb +70 -0
- data/lib/reek/report/heading_formatter.rb +45 -0
- data/lib/reek/report/location_formatter.rb +35 -0
- data/lib/reek/report/report.rb +198 -0
- data/lib/reek/smells.rb +24 -13
- data/lib/reek/smells/attribute.rb +6 -4
- data/lib/reek/smells/boolean_parameter.rb +3 -1
- data/lib/reek/smells/class_variable.rb +3 -1
- data/lib/reek/smells/control_parameter.rb +3 -1
- data/lib/reek/smells/data_clump.rb +3 -1
- data/lib/reek/smells/duplicate_method_call.rb +3 -1
- data/lib/reek/smells/feature_envy.rb +3 -1
- data/lib/reek/smells/irresponsible_module.rb +12 -7
- data/lib/reek/smells/long_parameter_list.rb +5 -3
- data/lib/reek/smells/long_yield_list.rb +3 -1
- data/lib/reek/smells/module_initialize.rb +3 -1
- data/lib/reek/smells/nested_iterators.rb +3 -1
- data/lib/reek/smells/nil_check.rb +3 -1
- data/lib/reek/smells/prima_donna_method.rb +3 -1
- data/lib/reek/smells/repeated_conditional.rb +5 -3
- data/lib/reek/{core → smells}/smell_configuration.rb +3 -1
- data/lib/reek/smells/smell_detector.rb +9 -7
- data/lib/reek/{core → smells}/smell_repository.rb +3 -2
- data/lib/reek/smells/smell_warning.rb +6 -4
- data/lib/reek/smells/too_many_instance_variables.rb +3 -1
- data/lib/reek/smells/too_many_methods.rb +3 -1
- data/lib/reek/smells/too_many_statements.rb +3 -1
- data/lib/reek/smells/uncommunicative_method_name.rb +3 -1
- data/lib/reek/smells/uncommunicative_module_name.rb +3 -1
- data/lib/reek/smells/uncommunicative_parameter_name.rb +3 -1
- data/lib/reek/smells/uncommunicative_variable_name.rb +3 -1
- data/lib/reek/smells/unused_parameters.rb +3 -1
- data/lib/reek/smells/utility_function.rb +5 -2
- data/lib/reek/source/source_code.rb +40 -9
- data/lib/reek/source/source_locator.rb +30 -12
- data/lib/reek/spec/should_reek.rb +5 -4
- data/lib/reek/spec/should_reek_of.rb +3 -2
- data/lib/reek/spec/should_reek_only_of.rb +5 -4
- data/lib/reek/tree_dresser.rb +32 -0
- data/lib/reek/tree_walker.rb +182 -0
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +3 -3
- data/spec/factories/factories.rb +2 -0
- data/spec/reek/{sexp/sexp_node_spec.rb → ast/node_spec.rb} +2 -2
- data/spec/reek/{core → ast}/object_refs_spec.rb +3 -3
- data/spec/reek/{core → ast}/reference_collector_spec.rb +2 -2
- data/spec/reek/{sexp → ast}/sexp_extensions_spec.rb +6 -16
- data/spec/reek/{sexp → ast}/sexp_formatter_spec.rb +2 -2
- data/spec/reek/cli/option_interpreter_spec.rb +2 -1
- data/spec/reek/{core → cli}/warning_collector_spec.rb +3 -3
- data/spec/reek/{core/code_comment_spec.rb → code_comment_spec.rb} +3 -3
- data/spec/reek/configuration/app_configuration_spec.rb +31 -18
- data/spec/reek/{core → context}/code_context_spec.rb +14 -15
- data/spec/reek/{core → context}/method_context_spec.rb +8 -8
- data/spec/reek/{core → context}/module_context_spec.rb +4 -4
- data/spec/reek/context/root_context_spec.rb +14 -0
- data/spec/reek/{core → context}/singleton_method_context_spec.rb +4 -4
- data/spec/reek/{core/examiner_spec.rb → examiner_spec.rb} +3 -42
- data/spec/reek/{cli → report}/html_report_spec.rb +5 -5
- data/spec/reek/report/json_report_spec.rb +20 -0
- data/spec/reek/{cli → report}/text_report_spec.rb +14 -14
- data/spec/reek/{cli → report}/xml_report_spec.rb +7 -7
- data/spec/reek/report/yaml_report_spec.rb +20 -0
- data/spec/reek/smells/attribute_spec.rb +2 -1
- data/spec/reek/smells/boolean_parameter_spec.rb +1 -1
- data/spec/reek/smells/class_variable_spec.rb +5 -5
- data/spec/reek/smells/control_parameter_spec.rb +1 -1
- data/spec/reek/smells/data_clump_spec.rb +1 -1
- data/spec/reek/smells/duplicate_method_call_spec.rb +3 -3
- data/spec/reek/smells/feature_envy_spec.rb +1 -1
- data/spec/reek/smells/irresponsible_module_spec.rb +24 -28
- data/spec/reek/smells/long_parameter_list_spec.rb +2 -2
- data/spec/reek/smells/long_yield_list_spec.rb +2 -2
- data/spec/reek/smells/nested_iterators_spec.rb +1 -1
- data/spec/reek/smells/nil_check_spec.rb +2 -2
- data/spec/reek/smells/prima_donna_method_spec.rb +3 -3
- data/spec/reek/smells/repeated_conditional_spec.rb +6 -6
- data/spec/reek/{core → smells}/smell_configuration_spec.rb +4 -4
- data/spec/reek/smells/smell_detector_shared.rb +2 -2
- data/spec/reek/{core → smells}/smell_repository_spec.rb +5 -4
- data/spec/reek/smells/too_many_instance_variables_spec.rb +1 -1
- data/spec/reek/smells/too_many_methods_spec.rb +4 -4
- data/spec/reek/smells/too_many_statements_spec.rb +2 -2
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +1 -1
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +4 -4
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +2 -2
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +3 -3
- data/spec/reek/smells/utility_function_spec.rb +23 -1
- data/spec/reek/source/source_code_spec.rb +1 -1
- data/spec/reek/source/source_locator_spec.rb +30 -0
- data/spec/reek/spec/should_reek_of_spec.rb +0 -17
- data/spec/reek/spec/should_reek_spec.rb +0 -25
- data/spec/reek/tree_dresser_spec.rb +16 -0
- data/spec/reek/{core/tree_walker_spec.rb → tree_walker_spec.rb} +5 -5
- data/spec/samples/{simple_configuration.reek → configuration/simple_configuration.reek} +0 -0
- data/spec/samples/configuration/with_excluded_paths.reek +4 -0
- data/spec/samples/source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb +5 -0
- data/spec/samples/source_with_exclude_paths/nested/ignore_me_as_well/irresponsible_module.rb +2 -0
- data/spec/samples/source_with_exclude_paths/nested/uncommunicative_parameter_name.rb +6 -0
- data/spec/spec_helper.rb +6 -7
- data/tasks/develop.rake +2 -2
- metadata +71 -69
- data/lib/reek/cli/report/formatter.rb +0 -69
- data/lib/reek/cli/report/heading_formatter.rb +0 -45
- data/lib/reek/cli/report/location_formatter.rb +0 -34
- data/lib/reek/cli/report/report.rb +0 -191
- data/lib/reek/core/ast_node.rb +0 -38
- data/lib/reek/core/code_comment.rb +0 -37
- data/lib/reek/core/examiner.rb +0 -85
- data/lib/reek/core/tree_dresser.rb +0 -24
- data/lib/reek/core/tree_walker.rb +0 -180
- data/lib/reek/source/source_repository.rb +0 -43
- data/spec/reek/cli/json_report_spec.rb +0 -20
- data/spec/reek/cli/yaml_report_spec.rb +0 -20
- data/spec/reek/core/object_source_spec.rb +0 -18
- data/spec/reek/core/stop_context_spec.rb +0 -14
- data/spec/reek/core/tree_dresser_spec.rb +0 -16
@@ -1,69 +0,0 @@
|
|
1
|
-
require_relative 'location_formatter'
|
2
|
-
|
3
|
-
module Reek
|
4
|
-
module CLI
|
5
|
-
module Report
|
6
|
-
#
|
7
|
-
# Formatter handling the formatting of the report at large.
|
8
|
-
# Formatting of the individual warnings is handled by the
|
9
|
-
# passed-in warning formatter.
|
10
|
-
#
|
11
|
-
module Formatter
|
12
|
-
def self.format_list(warnings, formatter = SimpleWarningFormatter.new)
|
13
|
-
warnings.map do |warning|
|
14
|
-
" #{formatter.format warning}"
|
15
|
-
end.join("\n")
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.header(examiner)
|
19
|
-
count = examiner.smells_count
|
20
|
-
result = Rainbow("#{examiner.description} -- ").cyan +
|
21
|
-
Rainbow("#{count} warning").yellow
|
22
|
-
result += Rainbow('s').yellow unless count == 1
|
23
|
-
result
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
#
|
28
|
-
# Basic formatter that just shows a simple message for each warning,
|
29
|
-
# prepended with the result of the passed-in location formatter.
|
30
|
-
#
|
31
|
-
class SimpleWarningFormatter
|
32
|
-
def initialize(location_formatter = BlankLocationFormatter)
|
33
|
-
@location_formatter = location_formatter
|
34
|
-
end
|
35
|
-
|
36
|
-
def format(warning)
|
37
|
-
"#{@location_formatter.format(warning)}#{base_format(warning)}"
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def base_format(warning)
|
43
|
-
"#{warning.context} #{warning.message} (#{warning.smell_type})"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
#
|
48
|
-
# Formatter that adds a link to the wiki to the basic message from
|
49
|
-
# SimpleWarningFormatter.
|
50
|
-
#
|
51
|
-
class WikiLinkWarningFormatter < SimpleWarningFormatter
|
52
|
-
BASE_URL_FOR_HELP_LINK = 'https://github.com/troessner/reek/wiki/'
|
53
|
-
|
54
|
-
def format(warning)
|
55
|
-
"#{super} " \
|
56
|
-
"[#{explanatory_link(warning)}]"
|
57
|
-
end
|
58
|
-
|
59
|
-
def explanatory_link(warning)
|
60
|
-
"#{BASE_URL_FOR_HELP_LINK}#{class_name_to_param(warning.smell_type)}"
|
61
|
-
end
|
62
|
-
|
63
|
-
def class_name_to_param(name)
|
64
|
-
name.split(/(?=[A-Z])/).join('-')
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module Reek
|
2
|
-
module CLI
|
3
|
-
module Report
|
4
|
-
module HeadingFormatter
|
5
|
-
#
|
6
|
-
# Base class for heading formatters.
|
7
|
-
# Is responsible for formatting the heading emitted for each examiner
|
8
|
-
#
|
9
|
-
class Base
|
10
|
-
attr_reader :report_formatter
|
11
|
-
|
12
|
-
def initialize(report_formatter)
|
13
|
-
@report_formatter = report_formatter
|
14
|
-
end
|
15
|
-
|
16
|
-
def header(examiner)
|
17
|
-
if show_header?(examiner)
|
18
|
-
report_formatter.header examiner
|
19
|
-
else
|
20
|
-
''
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
#
|
26
|
-
# Lists out each examiner, even if it has no smell
|
27
|
-
#
|
28
|
-
class Verbose < Base
|
29
|
-
def show_header?(_examiner)
|
30
|
-
true
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
#
|
35
|
-
# Lists only smelly examiners
|
36
|
-
#
|
37
|
-
class Quiet < Base
|
38
|
-
def show_header?(examiner)
|
39
|
-
examiner.smelly?
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module Reek
|
2
|
-
module CLI
|
3
|
-
module Report
|
4
|
-
#
|
5
|
-
# Formats the location of a warning as an empty string.
|
6
|
-
#
|
7
|
-
module BlankLocationFormatter
|
8
|
-
def self.format(_warning)
|
9
|
-
''
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
#
|
14
|
-
# Formats the location of a warning as an array of line numbers.
|
15
|
-
#
|
16
|
-
module DefaultLocationFormatter
|
17
|
-
def self.format(warning)
|
18
|
-
"#{warning.lines.inspect}:"
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
#
|
23
|
-
# Formats the location of a warning as a combination of source file name
|
24
|
-
# and line number. In this format, it is not possible to show more than
|
25
|
-
# one line number, so the first number is displayed.
|
26
|
-
#
|
27
|
-
module SingleLineLocationFormatter
|
28
|
-
def self.format(warning)
|
29
|
-
"#{warning.source}:#{warning.lines.first}: "
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,191 +0,0 @@
|
|
1
|
-
require 'rainbow'
|
2
|
-
require 'json'
|
3
|
-
|
4
|
-
module Reek
|
5
|
-
module CLI
|
6
|
-
module Report
|
7
|
-
#
|
8
|
-
# A report that contains the smells and smell counts following source code analysis.
|
9
|
-
#
|
10
|
-
class Base
|
11
|
-
DEFAULT_FORMAT = :text
|
12
|
-
NO_WARNINGS_COLOR = :green
|
13
|
-
WARNINGS_COLOR = :red
|
14
|
-
|
15
|
-
def initialize(options = {})
|
16
|
-
@examiners = []
|
17
|
-
@total_smell_count = 0
|
18
|
-
@options = options
|
19
|
-
@warning_formatter = options.fetch :warning_formatter, SimpleWarningFormatter.new
|
20
|
-
@report_formatter = options.fetch :report_formatter, Formatter
|
21
|
-
@sort_by_issue_count = options.fetch :sort_by_issue_count, false
|
22
|
-
end
|
23
|
-
|
24
|
-
def add_examiner(examiner)
|
25
|
-
@total_smell_count += examiner.smells_count
|
26
|
-
@examiners << examiner
|
27
|
-
self
|
28
|
-
end
|
29
|
-
|
30
|
-
def smells?
|
31
|
-
@total_smell_count > 0
|
32
|
-
end
|
33
|
-
|
34
|
-
def smells
|
35
|
-
@examiners.map(&:smells).flatten
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
#
|
40
|
-
# Generates a sorted, text summary of smells in examiners
|
41
|
-
#
|
42
|
-
class TextReport < Base
|
43
|
-
def show
|
44
|
-
sort_examiners if smells?
|
45
|
-
display_summary
|
46
|
-
display_total_smell_count
|
47
|
-
end
|
48
|
-
|
49
|
-
def smells
|
50
|
-
@examiners.each_with_object([]) do |examiner, result|
|
51
|
-
result << summarize_single_examiner(examiner)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
def display_summary
|
58
|
-
smells.reject(&:empty?).each { |smell| puts smell }
|
59
|
-
end
|
60
|
-
|
61
|
-
def display_total_smell_count
|
62
|
-
return unless @examiners.size > 1
|
63
|
-
print total_smell_count_message
|
64
|
-
end
|
65
|
-
|
66
|
-
def summarize_single_examiner(examiner)
|
67
|
-
result = heading_formatter.header(examiner)
|
68
|
-
if examiner.smelly?
|
69
|
-
formatted_list = @report_formatter.format_list(examiner.smells,
|
70
|
-
@warning_formatter)
|
71
|
-
result += ":\n#{formatted_list}"
|
72
|
-
end
|
73
|
-
result
|
74
|
-
end
|
75
|
-
|
76
|
-
def sort_examiners
|
77
|
-
@examiners.sort_by!(&:smells_count).reverse! if @sort_by_issue_count
|
78
|
-
end
|
79
|
-
|
80
|
-
def total_smell_count_message
|
81
|
-
colour = smells? ? WARNINGS_COLOR : NO_WARNINGS_COLOR
|
82
|
-
s = @total_smell_count == 1 ? '' : 's'
|
83
|
-
Rainbow("#{@total_smell_count} total warning#{s}\n").color(colour)
|
84
|
-
end
|
85
|
-
|
86
|
-
def heading_formatter
|
87
|
-
@heading_formatter ||=
|
88
|
-
@options.fetch(:heading_formatter, HeadingFormatter::Quiet).new(@report_formatter)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
#
|
93
|
-
# Displays a list of smells in YAML format
|
94
|
-
# YAML with empty array for 0 smells
|
95
|
-
class YAMLReport < Base
|
96
|
-
def show
|
97
|
-
print smells.map(&:yaml_hash).to_yaml
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
#
|
102
|
-
# Displays a list of smells in JSON format
|
103
|
-
# JSON with empty array for 0 smells
|
104
|
-
class JSONReport < Base
|
105
|
-
def show
|
106
|
-
print ::JSON.generate(
|
107
|
-
smells.map do |smell|
|
108
|
-
smell.yaml_hash(@warning_formatter)
|
109
|
-
end
|
110
|
-
)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
#
|
115
|
-
# Saves the report as a HTML file
|
116
|
-
#
|
117
|
-
class HTMLReport < Base
|
118
|
-
require 'erb'
|
119
|
-
|
120
|
-
def show
|
121
|
-
path = File.expand_path('../../../../../assets/html_output.html.erb',
|
122
|
-
__FILE__)
|
123
|
-
File.open('reek.html', 'w+') do |file|
|
124
|
-
file.puts ERB.new(File.read(path)).result(binding)
|
125
|
-
end
|
126
|
-
print("Html file saved\n")
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
#
|
131
|
-
# Generates a list of smells in XML format
|
132
|
-
#
|
133
|
-
class XMLReport < Base
|
134
|
-
require 'rexml/document'
|
135
|
-
|
136
|
-
def initialize(options = {})
|
137
|
-
super options
|
138
|
-
end
|
139
|
-
|
140
|
-
def show
|
141
|
-
checkstyle = REXML::Element.new('checkstyle', document)
|
142
|
-
|
143
|
-
smells.group_by(&:source).each do |file, file_smells|
|
144
|
-
file_to_xml(file, file_smells, checkstyle)
|
145
|
-
end
|
146
|
-
|
147
|
-
print_xml(checkstyle.parent)
|
148
|
-
end
|
149
|
-
|
150
|
-
private
|
151
|
-
|
152
|
-
def document
|
153
|
-
REXML::Document.new.tap do |doc|
|
154
|
-
doc << REXML::XMLDecl.new
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
def file_to_xml(file, file_smells, parent)
|
159
|
-
REXML::Element.new('file', parent).tap do |element|
|
160
|
-
element.attributes['name'] = File.realpath(file)
|
161
|
-
smells_to_xml(file_smells, element)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def smells_to_xml(smells, parent)
|
166
|
-
smells.each do |smell|
|
167
|
-
smell_to_xml(smell, parent)
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
def smell_to_xml(smell, parent)
|
172
|
-
REXML::Element.new('error', parent).tap do |element|
|
173
|
-
attributes = [
|
174
|
-
['line', smell.lines.first],
|
175
|
-
['column', 0],
|
176
|
-
['severity', 'warning'],
|
177
|
-
['message', smell.message],
|
178
|
-
['source', smell.smell_type]
|
179
|
-
]
|
180
|
-
element.add_attributes(attributes)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
def print_xml(document)
|
185
|
-
formatter = REXML::Formatters::Default.new
|
186
|
-
puts formatter.write(document, '')
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
data/lib/reek/core/ast_node.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'parser'
|
2
|
-
|
3
|
-
module Reek
|
4
|
-
module Core
|
5
|
-
# Base class for AST nodes extended with utility methods. Contains some
|
6
|
-
# methods to ease the transition from Sexp to AST::Node.
|
7
|
-
class ASTNode < Parser::AST::Node
|
8
|
-
def initialize(type, children = [], options = {})
|
9
|
-
@comments = options.fetch(:comments, [])
|
10
|
-
super
|
11
|
-
end
|
12
|
-
|
13
|
-
def comments
|
14
|
-
@comments.map(&:text).join("\n")
|
15
|
-
end
|
16
|
-
|
17
|
-
# @deprecated
|
18
|
-
def [](index)
|
19
|
-
elements[index]
|
20
|
-
end
|
21
|
-
|
22
|
-
def line
|
23
|
-
loc.line
|
24
|
-
end
|
25
|
-
|
26
|
-
# @deprecated
|
27
|
-
def first
|
28
|
-
type
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def elements
|
34
|
-
[type, *children]
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
|
3
|
-
module Reek
|
4
|
-
module Core
|
5
|
-
#
|
6
|
-
# A comment header from an abstract syntax tree; found directly above
|
7
|
-
# module, class and method definitions.
|
8
|
-
#
|
9
|
-
class CodeComment
|
10
|
-
CONFIG_REGEX = /:reek:(\w+)(:\s*\{.*?\})?/
|
11
|
-
|
12
|
-
def initialize(text)
|
13
|
-
@text = text.gsub(CONFIG_REGEX) do
|
14
|
-
add_to_config($1, $2)
|
15
|
-
''
|
16
|
-
end.gsub(/#/, '').gsub(/\n/, '').strip
|
17
|
-
end
|
18
|
-
|
19
|
-
def config
|
20
|
-
@config ||= Hash.new { |hash, key| hash[key] = {} }
|
21
|
-
end
|
22
|
-
|
23
|
-
def descriptive?
|
24
|
-
@text.split(/\s+/).length >= 2
|
25
|
-
end
|
26
|
-
|
27
|
-
protected
|
28
|
-
|
29
|
-
def add_to_config(smell, options)
|
30
|
-
options ||= ': { enabled: false }'
|
31
|
-
config.merge! YAML.load(smell.gsub(/(?:^|_)(.)/) { $1.upcase } + options)
|
32
|
-
# TODO: extend this to all configs -------------------^
|
33
|
-
# TODO: extend to allow configuration of whole smell class, not just subclass
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/lib/reek/core/examiner.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
# NOTE: tree_walker is required first to ensure unparser is required before
|
2
|
-
# parser. This prevents a potentially incompatible version of parser from being
|
3
|
-
# loaded first. This is only relevant when running bin/reek straight from a
|
4
|
-
# checkout directory without using Bundler.
|
5
|
-
#
|
6
|
-
# See also https://github.com/troessner/reek/pull/468
|
7
|
-
require_relative 'tree_walker'
|
8
|
-
require_relative 'smell_repository'
|
9
|
-
require_relative 'warning_collector'
|
10
|
-
require_relative '../source/source_repository'
|
11
|
-
|
12
|
-
module Reek
|
13
|
-
module Core
|
14
|
-
#
|
15
|
-
# Applies all available smell detectors to a source.
|
16
|
-
#
|
17
|
-
class Examiner
|
18
|
-
#
|
19
|
-
# A simple description of the source being analysed for smells.
|
20
|
-
# If the source is a single File, this will be the file's path.
|
21
|
-
#
|
22
|
-
attr_accessor :description
|
23
|
-
|
24
|
-
#
|
25
|
-
# Creates an Examiner which scans the given +source+ for code smells.
|
26
|
-
#
|
27
|
-
# @param source [Source::SourceCode, Array<String>, #to_reek_source]
|
28
|
-
# If +source+ is a String it is assumed to be Ruby source code;
|
29
|
-
# if it is a File, the file is opened and parsed for Ruby source code;
|
30
|
-
# and if it is an Array, it is assumed to be a list of file paths,
|
31
|
-
# each of which is opened and parsed for source code.
|
32
|
-
#
|
33
|
-
def initialize(source, smell_types_to_filter_by = [])
|
34
|
-
@sources = Source::SourceRepository.parse(source)
|
35
|
-
@description = @sources.description
|
36
|
-
@collector = Core::WarningCollector.new
|
37
|
-
@smell_types = eligible_smell_types(smell_types_to_filter_by)
|
38
|
-
|
39
|
-
run
|
40
|
-
end
|
41
|
-
|
42
|
-
#
|
43
|
-
# @return [Array<SmellWarning>] the smells found in the source
|
44
|
-
#
|
45
|
-
def smells
|
46
|
-
@smells ||= @collector.warnings
|
47
|
-
end
|
48
|
-
|
49
|
-
#
|
50
|
-
# @return [Integer] the number of smells found in the source
|
51
|
-
#
|
52
|
-
def smells_count
|
53
|
-
smells.length
|
54
|
-
end
|
55
|
-
|
56
|
-
#
|
57
|
-
# @return [Boolean] true if and only if there are code smells in the source.
|
58
|
-
#
|
59
|
-
def smelly?
|
60
|
-
!smells.empty?
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def run
|
66
|
-
@sources.each do |source|
|
67
|
-
smell_repository = Core::SmellRepository.new(source.description, @smell_types)
|
68
|
-
syntax_tree = source.syntax_tree
|
69
|
-
Core::TreeWalker.new(smell_repository).process(syntax_tree) if syntax_tree
|
70
|
-
smell_repository.report_on(@collector)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def eligible_smell_types(smell_types_to_filter_by = [])
|
75
|
-
if smell_types_to_filter_by.any?
|
76
|
-
Core::SmellRepository.smell_types.select do |klass|
|
77
|
-
smell_types_to_filter_by.include? klass.smell_type
|
78
|
-
end
|
79
|
-
else
|
80
|
-
Core::SmellRepository.smell_types
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|