reek 3.3.1 → 3.4.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 +4 -0
- data/CHANGELOG.md +6 -0
- data/CONTRIBUTING.md +3 -0
- data/README.md +12 -4
- data/Rakefile +1 -0
- data/config/defaults.reek +1 -2
- data/docs/Nested-Iterators.md +6 -1
- data/docs/Smell-Suppression.md +69 -5
- data/docs/Uncommunicative-Module-Name.md +1 -1
- data/docs/Utility-Function.md +13 -1
- data/docs/style-guide.md +18 -0
- data/docs/templates/default/docstring/html/public_api_marker.erb +3 -0
- data/docs/templates/default/docstring/setup.rb +41 -0
- data/docs/templates/default/fulldoc/html/css/common.css +1 -0
- data/docs/yard_plugin.rb +2 -0
- data/features/command_line_interface/smell_selection.feature +1 -0
- data/features/configuration_files/masking_smells.feature +12 -0
- data/features/samples.feature +27 -26
- data/features/step_definitions/sample_file_steps.rb +25 -30
- data/lib/reek/ast/ast_node_class_map.rb +1 -1
- data/lib/reek/ast/node.rb +3 -4
- data/lib/reek/ast/object_refs.rb +2 -2
- data/lib/reek/ast/reference_collector.rb +0 -1
- data/lib/reek/ast/sexp_extensions.rb +1 -2
- data/lib/reek/ast/sexp_formatter.rb +1 -2
- data/lib/reek/cli/application.rb +0 -1
- data/lib/reek/cli/command.rb +0 -1
- data/lib/reek/cli/input.rb +2 -1
- data/lib/reek/cli/option_interpreter.rb +0 -1
- data/lib/reek/cli/options.rb +3 -1
- data/lib/reek/cli/reek_command.rb +0 -1
- data/lib/reek/cli/silencer.rb +4 -4
- data/lib/reek/cli/warning_collector.rb +0 -1
- data/lib/reek/code_comment.rb +6 -11
- data/lib/reek/configuration/app_configuration.rb +0 -3
- data/lib/reek/configuration/configuration_file_finder.rb +4 -1
- data/lib/reek/configuration/configuration_validator.rb +1 -0
- data/lib/reek/configuration/directory_directives.rb +4 -0
- data/lib/reek/configuration/excluded_paths.rb +2 -1
- data/lib/reek/context/code_context.rb +11 -4
- data/lib/reek/context/method_context.rb +1 -6
- data/lib/reek/context/module_context.rb +0 -1
- data/lib/reek/context/root_context.rb +0 -1
- data/lib/reek/context/singleton_method_context.rb +0 -1
- data/lib/reek/examiner.rb +15 -15
- data/lib/reek/rake/task.rb +14 -0
- data/lib/reek/report.rb +0 -8
- data/lib/reek/report/formatter.rb +13 -12
- data/lib/reek/report/heading_formatter.rb +2 -1
- data/lib/reek/report/location_formatter.rb +0 -3
- data/lib/reek/report/report.rb +34 -14
- data/lib/reek/smells/attribute.rb +6 -6
- data/lib/reek/smells/boolean_parameter.rb +8 -8
- data/lib/reek/smells/class_variable.rb +7 -6
- data/lib/reek/smells/control_parameter.rb +8 -7
- data/lib/reek/smells/data_clump.rb +18 -20
- data/lib/reek/smells/duplicate_method_call.rb +10 -6
- data/lib/reek/smells/feature_envy.rb +17 -9
- data/lib/reek/smells/irresponsible_module.rb +6 -6
- data/lib/reek/smells/long_parameter_list.rb +7 -7
- data/lib/reek/smells/long_yield_list.rb +10 -9
- data/lib/reek/smells/module_initialize.rb +7 -6
- data/lib/reek/smells/nested_iterators.rb +5 -6
- data/lib/reek/smells/nil_check.rb +4 -5
- data/lib/reek/smells/prima_donna_method.rb +5 -5
- data/lib/reek/smells/repeated_conditional.rb +9 -6
- data/lib/reek/smells/smell_configuration.rb +1 -7
- data/lib/reek/smells/smell_detector.rb +28 -25
- data/lib/reek/smells/smell_repository.rb +18 -19
- data/lib/reek/smells/smell_warning.rb +34 -21
- data/lib/reek/smells/too_many_instance_variables.rb +5 -6
- data/lib/reek/smells/too_many_methods.rb +6 -6
- data/lib/reek/smells/too_many_statements.rb +5 -6
- data/lib/reek/smells/uncommunicative_method_name.rb +6 -6
- data/lib/reek/smells/uncommunicative_module_name.rb +36 -22
- data/lib/reek/smells/uncommunicative_parameter_name.rb +27 -19
- data/lib/reek/smells/uncommunicative_variable_name.rb +13 -7
- data/lib/reek/smells/unused_parameters.rb +10 -9
- data/lib/reek/smells/utility_function.rb +22 -11
- data/lib/reek/source/source_code.rb +11 -12
- data/lib/reek/source/source_locator.rb +6 -1
- data/lib/reek/spec.rb +11 -0
- data/lib/reek/spec/should_reek.rb +0 -3
- data/lib/reek/spec/should_reek_of.rb +1 -1
- data/lib/reek/spec/should_reek_only_of.rb +0 -1
- data/lib/reek/tree_dresser.rb +3 -1
- data/lib/reek/tree_walker.rb +4 -5
- data/lib/reek/version.rb +4 -1
- data/reek.gemspec +1 -1
- data/spec/factories/factories.rb +17 -6
- data/spec/quality/reek_source_spec.rb +3 -1
- data/spec/reek/cli/warning_collector_spec.rb +3 -2
- data/spec/reek/code_comment_spec.rb +8 -10
- data/spec/reek/configuration/directory_directives_spec.rb +2 -2
- data/spec/reek/configuration/excluded_paths_spec.rb +2 -2
- data/spec/reek/context/method_context_spec.rb +0 -26
- data/spec/reek/report/json_report_spec.rb +83 -6
- data/spec/reek/report/yaml_report_spec.rb +76 -6
- data/spec/reek/smells/attribute_spec.rb +1 -1
- data/spec/reek/smells/boolean_parameter_spec.rb +2 -3
- data/spec/reek/smells/class_variable_spec.rb +1 -1
- 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 +1 -1
- data/spec/reek/smells/feature_envy_spec.rb +1 -0
- data/spec/reek/smells/irresponsible_module_spec.rb +1 -1
- data/spec/reek/smells/long_parameter_list_spec.rb +1 -1
- data/spec/reek/smells/long_yield_list_spec.rb +1 -1
- data/spec/reek/smells/nested_iterators_spec.rb +1 -1
- data/spec/reek/smells/repeated_conditional_spec.rb +1 -1
- data/spec/reek/smells/smell_configuration_spec.rb +9 -9
- data/spec/reek/smells/smell_detector_shared.rb +0 -9
- data/spec/reek/smells/smell_repository_spec.rb +1 -8
- data/spec/reek/smells/smell_warning_spec.rb +3 -2
- data/spec/reek/smells/too_many_instance_variables_spec.rb +1 -1
- data/spec/reek/smells/too_many_methods_spec.rb +2 -4
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +1 -1
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +22 -5
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +1 -1
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +1 -1
- data/spec/reek/smells/utility_function_spec.rb +49 -0
- metadata +9 -5
@@ -5,15 +5,9 @@ module Reek
|
|
5
5
|
#
|
6
6
|
# A context wrapper for any method definition found in a syntax tree.
|
7
7
|
#
|
8
|
-
# @api private
|
9
8
|
class MethodContext < CodeContext
|
10
9
|
attr_reader :refs
|
11
10
|
|
12
|
-
def envious_receivers
|
13
|
-
return {} if refs.self_is_max?
|
14
|
-
refs.most_popular
|
15
|
-
end
|
16
|
-
|
17
11
|
def references_self?
|
18
12
|
exp.depends_on_instance?
|
19
13
|
end
|
@@ -22,6 +16,7 @@ module Reek
|
|
22
16
|
local_nodes(:lvar).find { |node| node.var_name == param.to_sym }
|
23
17
|
end
|
24
18
|
|
19
|
+
# :reek:FeatureEnvy
|
25
20
|
def unused_params
|
26
21
|
exp.arguments.select do |param|
|
27
22
|
next if param.anonymous_splat?
|
data/lib/reek/examiner.rb
CHANGED
@@ -13,6 +13,9 @@ module Reek
|
|
13
13
|
#
|
14
14
|
# Applies all available smell detectors to a source.
|
15
15
|
#
|
16
|
+
# @public
|
17
|
+
#
|
18
|
+
# :reek:TooManyInstanceVariables: { max_instance_variables: 6 }
|
16
19
|
class Examiner
|
17
20
|
#
|
18
21
|
# Creates an Examiner which scans the given +source+ for code smells.
|
@@ -26,27 +29,32 @@ module Reek
|
|
26
29
|
#
|
27
30
|
# @param configuration [Configuration::AppConfiguration]
|
28
31
|
# The configuration for this Examiner.
|
32
|
+
#
|
33
|
+
# @public
|
29
34
|
def initialize(source,
|
30
35
|
filter_by_smells = [],
|
31
36
|
configuration: Configuration::AppConfiguration.default)
|
32
37
|
@source = Source::SourceCode.from(source)
|
33
38
|
@configuration = configuration
|
34
39
|
@collector = CLI::WarningCollector.new
|
35
|
-
@smell_types = eligible_smell_types(filter_by_smells)
|
40
|
+
@smell_types = Smells::SmellRepository.eligible_smell_types(filter_by_smells)
|
36
41
|
|
37
42
|
run
|
38
43
|
end
|
39
44
|
|
45
|
+
# FIXME: Should be named "origin"
|
40
46
|
#
|
41
47
|
# @return [String] description of the source being analysed
|
42
48
|
#
|
49
|
+
# @public
|
43
50
|
def description
|
44
|
-
@description ||= source.
|
51
|
+
@description ||= source.origin
|
45
52
|
end
|
46
53
|
|
47
54
|
#
|
48
55
|
# @return [Array<SmellWarning>] the smells found in the source
|
49
56
|
#
|
57
|
+
# @public
|
50
58
|
def smells
|
51
59
|
@smells ||= collector.warnings
|
52
60
|
end
|
@@ -54,6 +62,7 @@ module Reek
|
|
54
62
|
#
|
55
63
|
# @return [Integer] the number of smells found in the source
|
56
64
|
#
|
65
|
+
# @public
|
57
66
|
def smells_count
|
58
67
|
smells.length
|
59
68
|
end
|
@@ -61,6 +70,7 @@ module Reek
|
|
61
70
|
#
|
62
71
|
# @return [Boolean] true if and only if there are code smells in the source.
|
63
72
|
#
|
73
|
+
# @public
|
64
74
|
def smelly?
|
65
75
|
!smells.empty?
|
66
76
|
end
|
@@ -70,22 +80,12 @@ module Reek
|
|
70
80
|
private_attr_reader :configuration, :collector, :smell_types, :source
|
71
81
|
|
72
82
|
def run
|
73
|
-
smell_repository = Smells::SmellRepository.new(
|
74
|
-
|
75
|
-
|
83
|
+
smell_repository = Smells::SmellRepository.new(
|
84
|
+
smell_types: smell_types,
|
85
|
+
configuration: configuration.directive_for(description))
|
76
86
|
syntax_tree = source.syntax_tree
|
77
87
|
TreeWalker.new(smell_repository, syntax_tree).walk if syntax_tree
|
78
88
|
smell_repository.report_on(collector)
|
79
89
|
end
|
80
|
-
|
81
|
-
def eligible_smell_types(filter_by_smells = [])
|
82
|
-
if filter_by_smells.any?
|
83
|
-
Smells::SmellRepository.smell_types.select do |klass|
|
84
|
-
filter_by_smells.include? klass.smell_type
|
85
|
-
end
|
86
|
-
else
|
87
|
-
Smells::SmellRepository.smell_types
|
88
|
-
end
|
89
|
-
end
|
90
90
|
end
|
91
91
|
end
|
data/lib/reek/rake/task.rb
CHANGED
@@ -12,6 +12,7 @@ module Reek
|
|
12
12
|
# (Classes here will be configured via the Rakefile, and therefore will
|
13
13
|
# possess a :reek:attribute or two.)
|
14
14
|
#
|
15
|
+
# @public
|
15
16
|
module Rake
|
16
17
|
# A Rake task that runs reek on a set of source files.
|
17
18
|
#
|
@@ -33,32 +34,43 @@ module Reek
|
|
33
34
|
# rake reek REEK_SRC=just_one_file.rb # checks a single source file
|
34
35
|
# rake reek REEK_OPTS=-s # sorts the report by smell
|
35
36
|
#
|
37
|
+
# @public
|
38
|
+
#
|
39
|
+
# :reek:TooManyInstanceVariables: { max_instance_variables: 6 }
|
40
|
+
# :reek:Attribute
|
36
41
|
class Task < ::Rake::TaskLib
|
37
42
|
# Name of reek task. Defaults to :reek.
|
43
|
+
# @public
|
38
44
|
attr_writer :name
|
39
45
|
|
40
46
|
# Path to reek's config file.
|
41
47
|
# Setting the REEK_CFG environment variable overrides this.
|
48
|
+
# @public
|
42
49
|
attr_accessor :config_file
|
43
50
|
|
44
51
|
# Glob pattern to match source files.
|
45
52
|
# Setting the REEK_SRC environment variable overrides this.
|
46
53
|
# Defaults to 'lib/**/*.rb'.
|
54
|
+
# @public
|
47
55
|
attr_reader :source_files
|
48
56
|
|
49
57
|
# String containing commandline options to be passed to Reek.
|
50
58
|
# Setting the REEK_OPTS environment variable overrides this value.
|
51
59
|
# Defaults to ''.
|
60
|
+
# @public
|
52
61
|
attr_accessor :reek_opts
|
53
62
|
|
54
63
|
# Whether or not to fail Rake when an error occurs (typically when smells are found).
|
55
64
|
# Defaults to true.
|
65
|
+
# @public
|
56
66
|
attr_writer :fail_on_error
|
57
67
|
|
58
68
|
# Use verbose output. If this is set to true, the task will print
|
59
69
|
# the reek command to stdout. Defaults to false.
|
70
|
+
# @public
|
60
71
|
attr_writer :verbose
|
61
72
|
|
73
|
+
# @public
|
62
74
|
def initialize(name = :reek)
|
63
75
|
@config_file = ENV['REEK_CFG']
|
64
76
|
@name = name
|
@@ -71,6 +83,7 @@ module Reek
|
|
71
83
|
define_task
|
72
84
|
end
|
73
85
|
|
86
|
+
# @public
|
74
87
|
def source_files=(files)
|
75
88
|
raise ArgumentError, no_string_given_for_file_list_warning unless files.is_a?(String)
|
76
89
|
@source_files = FileList[files]
|
@@ -101,6 +114,7 @@ module Reek
|
|
101
114
|
reject(&:empty?)
|
102
115
|
end
|
103
116
|
|
117
|
+
# :reek:UtilityFunction
|
104
118
|
def sys_call_failed?
|
105
119
|
!$CHILD_STATUS.success?
|
106
120
|
end
|
data/lib/reek/report.rb
CHANGED
@@ -7,7 +7,6 @@ module Reek
|
|
7
7
|
module Report
|
8
8
|
module_function
|
9
9
|
|
10
|
-
# @api private
|
11
10
|
REPORT_CLASSES = {
|
12
11
|
yaml: YAMLReport,
|
13
12
|
json: JSONReport,
|
@@ -16,19 +15,16 @@ module Reek
|
|
16
15
|
text: TextReport
|
17
16
|
}
|
18
17
|
|
19
|
-
# @api private
|
20
18
|
LOCATION_FORMATTERS = {
|
21
19
|
single_line: SingleLineLocationFormatter,
|
22
20
|
plain: BlankLocationFormatter,
|
23
21
|
numbers: DefaultLocationFormatter
|
24
22
|
}
|
25
23
|
|
26
|
-
# @api private
|
27
24
|
HEADING_FORMATTERS = {
|
28
25
|
verbose: HeadingFormatter::Verbose,
|
29
26
|
quiet: HeadingFormatter::Quiet }
|
30
27
|
|
31
|
-
# @api private
|
32
28
|
WARNING_FORMATTER_CLASSES = {
|
33
29
|
wiki_links: WikiLinkWarningFormatter,
|
34
30
|
simple: SimpleWarningFormatter
|
@@ -40,28 +36,24 @@ module Reek
|
|
40
36
|
#
|
41
37
|
# @return The mapped report class
|
42
38
|
#
|
43
|
-
# @api private
|
44
39
|
def report_class(report_format)
|
45
40
|
REPORT_CLASSES.fetch(report_format) do
|
46
41
|
raise "Unknown report format: #{report_format}"
|
47
42
|
end
|
48
43
|
end
|
49
44
|
|
50
|
-
# @api private
|
51
45
|
def location_formatter(location_format)
|
52
46
|
LOCATION_FORMATTERS.fetch(location_format) do
|
53
47
|
raise "Unknown location format: #{location_format}"
|
54
48
|
end
|
55
49
|
end
|
56
50
|
|
57
|
-
# @api private
|
58
51
|
def heading_formatter(heading_format)
|
59
52
|
HEADING_FORMATTERS.fetch(heading_format) do
|
60
53
|
raise "Unknown heading format: #{heading_format}"
|
61
54
|
end
|
62
55
|
end
|
63
56
|
|
64
|
-
# @api private
|
65
57
|
def warning_formatter_class(warning_format)
|
66
58
|
WARNING_FORMATTER_CLASSES.fetch(warning_format) do
|
67
59
|
raise "Unknown warning format: #{warning_format}"
|
@@ -8,7 +8,6 @@ module Reek
|
|
8
8
|
# Formatting of the individual warnings is handled by the
|
9
9
|
# passed-in warning formatter.
|
10
10
|
#
|
11
|
-
# @api private
|
12
11
|
module Formatter
|
13
12
|
def self.format_list(warnings, formatter: SimpleWarningFormatter.new)
|
14
13
|
warnings.map do |warning|
|
@@ -29,24 +28,20 @@ module Reek
|
|
29
28
|
# Basic formatter that just shows a simple message for each warning,
|
30
29
|
# prepended with the result of the passed-in location formatter.
|
31
30
|
#
|
32
|
-
# @api private
|
33
31
|
class SimpleWarningFormatter
|
34
32
|
def initialize(location_formatter: BlankLocationFormatter)
|
35
33
|
@location_formatter = location_formatter
|
36
34
|
end
|
37
35
|
|
38
36
|
def format(warning)
|
39
|
-
"#{location_formatter.format(warning)}#{
|
37
|
+
"#{location_formatter.format(warning)}#{warning.base_message}"
|
40
38
|
end
|
41
39
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
"#{warning.context} #{warning.message} (#{warning.smell_type})"
|
40
|
+
# :reek:UtilityFunction
|
41
|
+
def format_hash(warning)
|
42
|
+
warning.yaml_hash
|
46
43
|
end
|
47
44
|
|
48
|
-
private
|
49
|
-
|
50
45
|
private_attr_reader :location_formatter
|
51
46
|
end
|
52
47
|
|
@@ -54,19 +49,25 @@ module Reek
|
|
54
49
|
# Formatter that adds a link to the wiki to the basic message from
|
55
50
|
# SimpleWarningFormatter.
|
56
51
|
#
|
57
|
-
# @api private
|
58
52
|
class WikiLinkWarningFormatter < SimpleWarningFormatter
|
59
53
|
BASE_URL_FOR_HELP_LINK = 'https://github.com/troessner/reek/blob/master/docs/'
|
60
54
|
|
61
55
|
def format(warning)
|
62
56
|
"#{super} " \
|
63
|
-
"[#{explanatory_link(warning)}
|
57
|
+
"[#{explanatory_link(warning)}]"
|
64
58
|
end
|
65
59
|
|
60
|
+
def format_hash(warning)
|
61
|
+
super(warning).merge('wiki_link' => explanatory_link(warning))
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
66
|
def explanatory_link(warning)
|
67
|
-
"#{BASE_URL_FOR_HELP_LINK}#{class_name_to_param(warning.smell_type)}"
|
67
|
+
"#{BASE_URL_FOR_HELP_LINK}#{class_name_to_param(warning.smell_type)}.md"
|
68
68
|
end
|
69
69
|
|
70
|
+
# :reek:UtilityFunction
|
70
71
|
def class_name_to_param(name)
|
71
72
|
name.split(/(?=[A-Z])/).join('-')
|
72
73
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Reek
|
2
2
|
module Report
|
3
|
-
# @api private
|
4
3
|
module HeadingFormatter
|
5
4
|
#
|
6
5
|
# Base class for heading formatters.
|
@@ -14,6 +13,7 @@ module Reek
|
|
14
13
|
@report_formatter = report_formatter
|
15
14
|
end
|
16
15
|
|
16
|
+
# :reek:UtilityFunction
|
17
17
|
def show_header?(_examiner)
|
18
18
|
raise NotImplementedError
|
19
19
|
end
|
@@ -40,6 +40,7 @@ module Reek
|
|
40
40
|
# Lists only smelly examiners
|
41
41
|
#
|
42
42
|
class Quiet < Base
|
43
|
+
# :reek:UtilityFunction
|
43
44
|
def show_header?(examiner)
|
44
45
|
examiner.smelly?
|
45
46
|
end
|
@@ -3,7 +3,6 @@ module Reek
|
|
3
3
|
#
|
4
4
|
# Formats the location of a warning as an empty string.
|
5
5
|
#
|
6
|
-
# @api private
|
7
6
|
module BlankLocationFormatter
|
8
7
|
def self.format(_warning)
|
9
8
|
''
|
@@ -13,7 +12,6 @@ module Reek
|
|
13
12
|
#
|
14
13
|
# Formats the location of a warning as an array of line numbers.
|
15
14
|
#
|
16
|
-
# @api private
|
17
15
|
module DefaultLocationFormatter
|
18
16
|
def self.format(warning)
|
19
17
|
"#{warning.lines.inspect}:"
|
@@ -25,7 +23,6 @@ module Reek
|
|
25
23
|
# and line number. In this format, it is not possible to show more than
|
26
24
|
# one line number, so the first number is displayed.
|
27
25
|
#
|
28
|
-
# @api private
|
29
26
|
module SingleLineLocationFormatter
|
30
27
|
def self.format(warning)
|
31
28
|
"#{warning.source}:#{warning.lines.first}: "
|
data/lib/reek/report/report.rb
CHANGED
@@ -5,17 +5,23 @@ require_relative 'formatter'
|
|
5
5
|
require_relative 'heading_formatter'
|
6
6
|
|
7
7
|
module Reek
|
8
|
+
# @public
|
8
9
|
module Report
|
9
10
|
#
|
10
11
|
# A report that contains the smells and smell counts following source code analysis.
|
11
12
|
#
|
12
13
|
# @abstract Subclass and override {#show} to create a concrete report class.
|
14
|
+
#
|
15
|
+
# @public
|
16
|
+
#
|
17
|
+
# :reek:TooManyInstanceVariables: { max_instance_variables: 6 }
|
13
18
|
class Base
|
14
|
-
# @api private
|
15
19
|
NO_WARNINGS_COLOR = :green
|
16
|
-
# @api private
|
17
20
|
WARNINGS_COLOR = :red
|
18
21
|
|
22
|
+
# @public
|
23
|
+
#
|
24
|
+
# :reek:BooleanParameter
|
19
25
|
def initialize(heading_formatter: HeadingFormatter::Quiet,
|
20
26
|
report_formatter: Formatter, sort_by_issue_count: false,
|
21
27
|
warning_formatter: SimpleWarningFormatter.new)
|
@@ -25,12 +31,16 @@ module Reek
|
|
25
31
|
@sort_by_issue_count = sort_by_issue_count
|
26
32
|
@total_smell_count = 0
|
27
33
|
@warning_formatter = warning_formatter
|
34
|
+
|
35
|
+
# TODO: Only used in TextReport and YAMLReport
|
28
36
|
end
|
29
37
|
|
30
38
|
# Add Examiner to report on. The report will output results for all
|
31
39
|
# added examiners.
|
32
40
|
#
|
33
41
|
# @param [Reek::Examiner] examiner object to report on
|
42
|
+
#
|
43
|
+
# @public
|
34
44
|
def add_examiner(examiner)
|
35
45
|
self.total_smell_count += examiner.smells_count
|
36
46
|
examiners << examiner
|
@@ -38,16 +48,16 @@ module Reek
|
|
38
48
|
end
|
39
49
|
|
40
50
|
# Render the report results on STDOUT
|
51
|
+
#
|
52
|
+
# @public
|
41
53
|
def show
|
42
54
|
raise NotImplementedError
|
43
55
|
end
|
44
56
|
|
45
|
-
# @api private
|
46
57
|
def smells?
|
47
58
|
total_smell_count > 0
|
48
59
|
end
|
49
60
|
|
50
|
-
# @api private
|
51
61
|
def smells
|
52
62
|
examiners.map(&:smells).flatten
|
53
63
|
end
|
@@ -65,7 +75,9 @@ module Reek
|
|
65
75
|
#
|
66
76
|
# Generates a sorted, text summary of smells in examiners
|
67
77
|
#
|
78
|
+
# @public
|
68
79
|
class TextReport < Base
|
80
|
+
# @public
|
69
81
|
def show
|
70
82
|
sort_examiners if smells?
|
71
83
|
display_summary
|
@@ -103,39 +115,42 @@ module Reek
|
|
103
115
|
|
104
116
|
def total_smell_count_message
|
105
117
|
colour = smells? ? WARNINGS_COLOR : NO_WARNINGS_COLOR
|
106
|
-
|
107
|
-
Rainbow("#{total_smell_count} total warning#{s}\n").color(colour)
|
118
|
+
Rainbow("#{total_smell_count} total warning#{total_smell_count == 1 ? '' : 's'}\n").color(colour)
|
108
119
|
end
|
109
120
|
end
|
110
121
|
|
111
122
|
#
|
112
123
|
# Displays a list of smells in YAML format
|
113
124
|
# YAML with empty array for 0 smells
|
125
|
+
#
|
126
|
+
# @public
|
114
127
|
class YAMLReport < Base
|
115
|
-
|
116
|
-
|
128
|
+
# @public
|
129
|
+
def show(out = $stdout)
|
130
|
+
out.print smells.map { |smell| warning_formatter.format_hash(smell) }.to_yaml
|
117
131
|
end
|
118
132
|
end
|
119
133
|
|
120
134
|
#
|
121
135
|
# Displays a list of smells in JSON format
|
122
136
|
# JSON with empty array for 0 smells
|
137
|
+
#
|
138
|
+
# @public
|
123
139
|
class JSONReport < Base
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
smell.yaml_hash(warning_formatter)
|
128
|
-
end
|
129
|
-
)
|
140
|
+
# @public
|
141
|
+
def show(out = $stdout)
|
142
|
+
out.print ::JSON.generate smells.map { |smell| warning_formatter.format_hash(smell) }
|
130
143
|
end
|
131
144
|
end
|
132
145
|
|
133
146
|
#
|
134
147
|
# Saves the report as a HTML file
|
135
148
|
#
|
149
|
+
# @public
|
136
150
|
class HTMLReport < Base
|
137
151
|
require 'erb'
|
138
152
|
|
153
|
+
# @public
|
139
154
|
def show(target_path: Pathname.new('reek.html'))
|
140
155
|
template_path = Pathname.new("#{__dir__}/html_report.html.erb")
|
141
156
|
File.write target_path, ERB.new(template_path.read).result(binding)
|
@@ -146,9 +161,11 @@ module Reek
|
|
146
161
|
#
|
147
162
|
# Generates a list of smells in XML format
|
148
163
|
#
|
164
|
+
# @public
|
149
165
|
class XMLReport < Base
|
150
166
|
require 'rexml/document'
|
151
167
|
|
168
|
+
# @public
|
152
169
|
def show
|
153
170
|
document.write output: $stdout, indent: 2
|
154
171
|
$stdout.puts
|
@@ -170,6 +187,8 @@ module Reek
|
|
170
187
|
end
|
171
188
|
end
|
172
189
|
|
190
|
+
# :reek:FeatureEnvy
|
191
|
+
# :reek:NestedIterators: { max_allowed_nesting: 2 }
|
173
192
|
def file(name, smells)
|
174
193
|
REXML::Element.new('file').tap do |file|
|
175
194
|
file.add_attribute 'name', File.realpath(name)
|
@@ -181,6 +200,7 @@ module Reek
|
|
181
200
|
end
|
182
201
|
end
|
183
202
|
|
203
|
+
# :reek:UtilityFunction
|
184
204
|
def error(smell, line)
|
185
205
|
REXML::Element.new('error').tap do |error|
|
186
206
|
error.add_attributes 'column' => 0,
|