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.
- 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
|