reek 4.8.2 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/{samples/configuration/more_than_one_configuration_file/regular.reek → .reek.yml} +0 -0
- data/.rubocop.yml +17 -3
- data/.simplecov +1 -0
- data/.travis.yml +0 -5
- data/.yardopts +1 -1
- data/CHANGELOG.md +28 -0
- data/Gemfile +1 -1
- data/README.md +113 -98
- data/Rakefile +16 -3
- data/bin/reek +1 -3
- data/docs/API.md +2 -9
- data/docs/Basic-Smell-Options.md +51 -11
- data/docs/Code-Smells.md +1 -1
- data/docs/Command-Line-Options.md +14 -4
- data/docs/Duplicate-Method-Call.md +49 -1
- data/docs/Feature-Envy.md +44 -0
- data/docs/How-To-Write-New-Detectors.md +2 -3
- data/docs/{Prima-Donna-Method.md → Missing-Safe-Method.md} +11 -9
- data/docs/Rake-Task.md +1 -1
- data/docs/Reek-4-to-Reek-5-migration.md +193 -0
- data/docs/Reek-Driven-Development.md +1 -1
- data/docs/Uncommunicative-Method-Name.md +43 -4
- data/docs/Uncommunicative-Module-Name.md +48 -6
- data/docs/Uncommunicative-Parameter-Name.md +42 -4
- data/docs/Uncommunicative-Variable-Name.md +73 -2
- data/docs/Unused-Private-Method.md +1 -1
- data/docs/defaults.reek.yml +129 -0
- data/docs/yard_plugin.rb +1 -0
- data/features/command_line_interface/options.feature +46 -4
- data/features/command_line_interface/stdin.feature +27 -5
- data/features/configuration_files/accept_setting.feature +39 -22
- data/features/configuration_files/directory_specific_directives.feature +58 -53
- data/features/configuration_files/exclude_directives.feature +8 -7
- data/features/configuration_files/masking_smells.feature +35 -6
- data/features/configuration_files/mix_accept_reject_setting.feature +24 -21
- data/features/configuration_files/reject_setting.feature +45 -34
- data/features/configuration_files/schema_validation.feature +59 -0
- data/features/configuration_files/unused_private_method.feature +14 -12
- data/features/configuration_loading.feature +50 -7
- data/features/rake_task/rake_task.feature +5 -5
- data/features/reports/json.feature +4 -1
- data/features/reports/reports.feature +12 -12
- data/features/reports/yaml.feature +3 -0
- data/features/rspec_matcher.feature +9 -1
- data/features/step_definitions/reek_steps.rb +4 -0
- data/features/step_definitions/sample_file_steps.rb +9 -4
- data/features/support/env.rb +2 -2
- data/features/todo_list.feature +16 -13
- data/lib/reek/ast/node.rb +3 -6
- data/lib/reek/ast/object_refs.rb +1 -1
- data/lib/reek/ast/sexp_extensions/if.rb +1 -1
- data/lib/reek/ast/sexp_extensions/methods.rb +1 -1
- data/lib/reek/cli/application.rb +4 -3
- data/lib/reek/cli/command/report_command.rb +1 -2
- data/lib/reek/cli/command/todo_list_command.rb +4 -2
- data/lib/reek/cli/options.rb +27 -13
- data/lib/reek/cli/silencer.rb +14 -3
- data/lib/reek/code_comment.rb +14 -16
- data/lib/reek/configuration/app_configuration.rb +32 -28
- data/lib/reek/configuration/configuration_converter.rb +110 -0
- data/lib/reek/configuration/configuration_file_finder.rb +15 -40
- data/lib/reek/configuration/configuration_validator.rb +12 -23
- data/lib/reek/configuration/default_directive.rb +17 -3
- data/lib/reek/configuration/directory_directives.rb +17 -11
- data/lib/reek/configuration/excluded_paths.rb +1 -1
- data/lib/reek/configuration/rake_task_converter.rb +29 -0
- data/lib/reek/configuration/schema.yml +210 -0
- data/lib/reek/configuration/schema_validator.rb +38 -0
- data/lib/reek/context/attribute_context.rb +1 -1
- data/lib/reek/context/code_context.rb +4 -4
- data/lib/reek/context/method_context.rb +2 -2
- data/lib/reek/context/module_context.rb +1 -1
- data/lib/reek/context_builder.rb +9 -9
- data/lib/reek/detector_repository.rb +6 -0
- data/lib/reek/documentation_link.rb +2 -2
- data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +1 -1
- data/lib/reek/errors/bad_detector_in_comment_error.rb +1 -1
- data/lib/reek/errors/config_file_error.rb +11 -0
- data/lib/reek/errors/encoding_error.rb +2 -2
- data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +1 -1
- data/lib/reek/errors/incomprehensible_source_error.rb +2 -2
- data/lib/reek/errors/syntax_error.rb +41 -0
- data/lib/reek/examiner.rb +9 -19
- data/lib/reek/rake/task.rb +3 -3
- data/lib/reek/report.rb +15 -10
- data/lib/reek/report/base_report.rb +8 -12
- data/lib/reek/report/code_climate/code_climate_configuration.yml +5 -9
- data/lib/reek/report/documentation_link_warning_formatter.rb +17 -0
- data/lib/reek/report/heading_formatter.rb +54 -0
- data/lib/reek/report/json_report.rb +1 -1
- data/lib/reek/report/location_formatter.rb +40 -0
- data/lib/reek/report/progress_formatter.rb +79 -0
- data/lib/reek/report/simple_warning_formatter.rb +34 -0
- data/lib/reek/report/text_report.rb +1 -2
- data/lib/reek/report/xml_report.rb +3 -3
- data/lib/reek/report/yaml_report.rb +1 -1
- data/lib/reek/smell_configuration.rb +2 -2
- data/lib/reek/smell_detectors.rb +1 -2
- data/lib/reek/smell_detectors/attribute.rb +0 -1
- data/lib/reek/smell_detectors/base_detector.rb +8 -11
- data/lib/reek/smell_detectors/boolean_parameter.rb +0 -1
- data/lib/reek/smell_detectors/class_variable.rb +0 -1
- data/lib/reek/smell_detectors/control_parameter.rb +17 -32
- data/lib/reek/smell_detectors/data_clump.rb +3 -4
- data/lib/reek/smell_detectors/duplicate_method_call.rb +5 -6
- data/lib/reek/smell_detectors/feature_envy.rb +0 -1
- data/lib/reek/smell_detectors/instance_variable_assumption.rb +0 -1
- data/lib/reek/smell_detectors/irresponsible_module.rb +0 -1
- data/lib/reek/smell_detectors/long_parameter_list.rb +1 -2
- data/lib/reek/smell_detectors/long_yield_list.rb +2 -3
- data/lib/reek/smell_detectors/manual_dispatch.rb +2 -2
- data/lib/reek/smell_detectors/{prima_donna_method.rb → missing_safe_method.rb} +6 -7
- data/lib/reek/smell_detectors/module_initialize.rb +0 -1
- data/lib/reek/smell_detectors/nested_iterators.rb +4 -5
- data/lib/reek/smell_detectors/nil_check.rb +0 -1
- data/lib/reek/smell_detectors/repeated_conditional.rb +3 -4
- data/lib/reek/smell_detectors/subclassed_from_core_class.rb +0 -1
- data/lib/reek/smell_detectors/too_many_constants.rb +1 -2
- data/lib/reek/smell_detectors/too_many_instance_variables.rb +1 -2
- data/lib/reek/smell_detectors/too_many_methods.rb +1 -2
- data/lib/reek/smell_detectors/too_many_statements.rb +1 -2
- data/lib/reek/smell_detectors/uncommunicative_method_name.rb +2 -3
- data/lib/reek/smell_detectors/uncommunicative_module_name.rb +2 -3
- data/lib/reek/smell_detectors/uncommunicative_parameter_name.rb +2 -3
- data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +4 -5
- data/lib/reek/smell_detectors/unused_parameters.rb +0 -1
- data/lib/reek/smell_detectors/unused_private_method.rb +0 -1
- data/lib/reek/smell_detectors/utility_function.rb +1 -2
- data/lib/reek/smell_warning.rb +10 -8
- data/lib/reek/source/source_code.rb +40 -55
- data/lib/reek/source/source_locator.rb +7 -7
- data/lib/reek/spec.rb +6 -6
- data/lib/reek/spec/should_reek.rb +2 -2
- data/lib/reek/spec/should_reek_of.rb +9 -16
- data/lib/reek/spec/should_reek_only_of.rb +4 -4
- data/lib/reek/tree_dresser.rb +5 -5
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +3 -3
- data/samples/checkstyle.xml +1 -1
- data/samples/{clean.rb → clean_source/clean.rb} +0 -0
- data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +29 -0
- data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +30 -0
- data/samples/configuration/full_configuration.reek +8 -4
- data/samples/configuration/full_mask.reek +5 -4
- data/samples/{exceptions.reek → configuration/home/home.reek.yml} +0 -0
- data/samples/configuration/partial_mask.reek +3 -2
- data/samples/configuration/regular_configuration/.reek.yml +4 -0
- data/samples/configuration/{more_than_one_configuration_file/todo.reek → regular_configuration/empty_sub_directory/.gitignore} +0 -0
- data/samples/{configuration/single_configuration_file/.reek → no_config_file/.keep} +0 -0
- data/samples/paths.rb +5 -4
- data/samples/{inline.rb → smelly_source/inline.rb} +0 -0
- data/samples/{optparse.rb → smelly_source/optparse.rb} +0 -0
- data/samples/{redcloth.rb → smelly_source/redcloth.rb} +0 -0
- data/samples/{smelly.rb → smelly_source/smelly.rb} +0 -0
- data/samples/source_with_hidden_directories/.hidden/hidden.rb +1 -0
- data/samples/source_with_hidden_directories/not_hidden.rb +1 -0
- data/samples/{source_with_hidden_directories/uncommunicative_parameter_name.rb → source_with_non_ruby_files/ruby.rb} +0 -0
- data/spec/reek/ast/node_spec.rb +5 -5
- data/spec/reek/cli/application_spec.rb +18 -4
- data/spec/reek/cli/command/todo_list_command_spec.rb +4 -2
- data/spec/reek/cli/silencer_spec.rb +28 -0
- data/spec/reek/code_comment_spec.rb +0 -7
- data/spec/reek/configuration/app_configuration_spec.rb +44 -31
- data/spec/reek/configuration/configuration_file_finder_spec.rb +133 -49
- data/spec/reek/configuration/default_directive_spec.rb +1 -1
- data/spec/reek/configuration/directory_directives_spec.rb +3 -4
- data/spec/reek/configuration/excluded_paths_spec.rb +5 -5
- data/spec/reek/configuration/rake_task_converter_spec.rb +33 -0
- data/spec/reek/configuration/schema_validator_spec.rb +165 -0
- data/spec/reek/context/code_context_spec.rb +1 -1
- data/spec/reek/examiner_spec.rb +28 -1
- data/spec/reek/report/json_report_spec.rb +13 -46
- data/spec/reek/report/{formatter/location_formatter_spec.rb → location_formatter_spec.rb} +5 -5
- data/spec/reek/report/{formatter/progress_formatter_spec.rb → progress_formatter_spec.rb} +4 -4
- data/spec/reek/report/text_report_spec.rb +4 -4
- data/spec/reek/report/xml_report_spec.rb +1 -1
- data/spec/reek/report/yaml_report_spec.rb +9 -38
- data/spec/reek/report_spec.rb +3 -3
- data/spec/reek/smell_detectors/feature_envy_spec.rb +2 -2
- data/spec/reek/smell_detectors/{prima_donna_method_spec.rb → missing_safe_method_spec.rb} +9 -9
- data/spec/reek/smell_detectors/too_many_constants_spec.rb +3 -3
- data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +1 -1
- data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +6 -6
- data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +6 -4
- data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +6 -4
- data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +6 -6
- data/spec/reek/smell_detectors/unused_private_method_spec.rb +1 -1
- data/spec/reek/smell_warning_spec.rb +4 -0
- data/spec/reek/source/source_code_spec.rb +16 -22
- data/spec/reek/source/source_locator_spec.rb +11 -11
- data/spec/reek/spec/should_reek_of_spec.rb +0 -4
- data/spec/reek/spec/should_reek_only_of_spec.rb +2 -2
- data/spec/reek/spec/should_reek_spec.rb +1 -1
- data/spec/reek/tree_dresser_spec.rb +2 -6
- data/spec/spec_helper.rb +3 -5
- data/tasks/configuration.rake +8 -5
- metadata +56 -35
- data/defaults.reek +0 -131
- data/features/configuration_files/warn_about_multiple_configuration_files.feature +0 -44
- data/lib/reek/report/formatter.rb +0 -33
- data/lib/reek/report/formatter/heading_formatter.rb +0 -52
- data/lib/reek/report/formatter/location_formatter.rb +0 -42
- data/lib/reek/report/formatter/progress_formatter.rb +0 -81
- data/lib/reek/report/formatter/simple_warning_formatter.rb +0 -35
- data/lib/reek/report/formatter/wiki_link_warning_formatter.rb +0 -23
- data/lib/reek/smell_detectors/syntax.rb +0 -37
- data/samples/configuration/non_public_modifiers_mask.reek +0 -3
- data/samples/smelly_with_inline_mask.rb +0 -8
- data/samples/smelly_with_modifiers.rb +0 -12
- data/samples/source_with_hidden_directories/.hidden/uncommunicative_method_name.rb +0 -5
- data/samples/source_with_non_ruby_files/uncommunicative_parameter_name.rb +0 -6
- data/spec/reek/smell_detectors/syntax_spec.rb +0 -17
@@ -1,9 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../cli/silencer'
|
4
|
-
Reek::CLI::Silencer.
|
5
|
-
require 'parser/ruby25'
|
6
|
-
end
|
4
|
+
Reek::CLI::Silencer.without_warnings { require 'parser/ruby25' }
|
7
5
|
require_relative '../tree_dresser'
|
8
6
|
require_relative '../ast/node'
|
9
7
|
require_relative '../ast/builder'
|
@@ -14,94 +12,82 @@ Reek::AST::Builder.emit_lambda = true
|
|
14
12
|
module Reek
|
15
13
|
module Source
|
16
14
|
#
|
17
|
-
# A +
|
15
|
+
# A +SourceCode+ object represents a chunk of Ruby source code.
|
18
16
|
#
|
19
17
|
class SourceCode
|
20
|
-
|
21
|
-
|
22
|
-
def initialize
|
23
|
-
@diagnostics = []
|
24
|
-
end
|
25
|
-
|
26
|
-
def call(item)
|
27
|
-
@diagnostics << item
|
28
|
-
end
|
29
|
-
|
30
|
-
def result
|
31
|
-
@diagnostics
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
IO_IDENTIFIER = 'STDIN'.freeze
|
36
|
-
STRING_IDENTIFIER = 'string'.freeze
|
37
|
-
|
38
|
-
attr_reader :origin
|
18
|
+
IO_IDENTIFIER = 'STDIN'
|
19
|
+
STRING_IDENTIFIER = 'string'
|
39
20
|
|
40
21
|
# Initializer.
|
41
22
|
#
|
42
|
-
#
|
43
|
-
# origin
|
44
|
-
#
|
45
|
-
|
23
|
+
# @param source [File|Pathname|IO|String] Ruby source code
|
24
|
+
# @param origin [String] Origin of the source code. Will be determined
|
25
|
+
# automatically if left blank.
|
26
|
+
# @param parser the parser to use for generating AST's out of the given code
|
27
|
+
def initialize(source:, origin: nil, parser: self.class.default_parser)
|
46
28
|
@origin = origin
|
47
29
|
@parser = parser
|
48
|
-
|
49
|
-
@code = code
|
30
|
+
@source = source
|
50
31
|
end
|
51
32
|
|
52
33
|
# Initializes an instance of SourceCode given a source.
|
53
|
-
# This source can come via
|
34
|
+
# This source can come via several different ways:
|
54
35
|
# - from Files or Pathnames a la `reek lib/reek/`
|
55
36
|
# - from IO (STDIN) a la `echo "class Foo; end" | reek`
|
56
37
|
# - from String via our rspec matchers a la `expect("class Foo; end").to reek`
|
38
|
+
# - from an existing SourceCode object. This is passed through unchanged
|
57
39
|
#
|
58
|
-
# @param source [File|IO|String]
|
40
|
+
# @param source [SourceCode|File|Pathname|IO|String] the given source
|
41
|
+
# @param origin [String|nil]
|
59
42
|
#
|
60
43
|
# @return an instance of SourceCode
|
61
|
-
|
62
|
-
def self.from(source)
|
44
|
+
def self.from(source, origin: nil)
|
63
45
|
case source
|
64
|
-
when
|
65
|
-
|
66
|
-
when Pathname then new(code: source.read, origin: source.to_s)
|
67
|
-
when String then new(code: source, origin: STRING_IDENTIFIER)
|
46
|
+
when self then source
|
47
|
+
else new(source: source, origin: origin)
|
68
48
|
end
|
69
49
|
end
|
70
50
|
|
71
|
-
def diagnostics
|
72
|
-
parse_result.last
|
73
|
-
end
|
74
|
-
|
75
51
|
def syntax_tree
|
76
|
-
|
52
|
+
@syntax_tree ||= parse
|
77
53
|
end
|
78
54
|
|
79
55
|
def self.default_parser
|
80
56
|
Parser::Ruby25.new(AST::Builder.new).tap do |parser|
|
81
57
|
diagnostics = parser.diagnostics
|
82
|
-
diagnostics.all_errors_are_fatal =
|
83
|
-
diagnostics.ignore_warnings =
|
84
|
-
diagnostics.consumer = DiagnosticsConsumer.new
|
58
|
+
diagnostics.all_errors_are_fatal = true
|
59
|
+
diagnostics.ignore_warnings = true
|
85
60
|
end
|
86
61
|
end
|
87
62
|
|
63
|
+
def origin
|
64
|
+
@origin ||=
|
65
|
+
case source
|
66
|
+
when File then source.path
|
67
|
+
when IO then IO_IDENTIFIER
|
68
|
+
when Pathname then source.to_s
|
69
|
+
when String then STRING_IDENTIFIER
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
88
73
|
private
|
89
74
|
|
90
|
-
def
|
91
|
-
@
|
75
|
+
def code
|
76
|
+
@code ||=
|
77
|
+
case source
|
78
|
+
when File, Pathname then source.read
|
79
|
+
when IO then source.readlines.join
|
80
|
+
when String then source
|
81
|
+
end.force_encoding(Encoding::UTF_8)
|
92
82
|
end
|
93
83
|
|
94
|
-
attr_reader :
|
95
|
-
attr_reader :parser
|
84
|
+
attr_reader :parser, :source
|
96
85
|
|
97
86
|
# Parses the given code into an AST and associates the source code comments with it.
|
98
87
|
# This AST is then traversed by a TreeDresser which adorns the nodes in the AST
|
99
88
|
# with our SexpExtensions.
|
100
89
|
# Finally this AST is returned where each node is an anonymous subclass of Reek::AST::Node
|
101
90
|
#
|
102
|
-
# Important to note is that Reek will not fail on unparseable files but rather register a
|
103
|
-
# parse error to @diagnostics and then just continue.
|
104
|
-
#
|
105
91
|
# Given this @code:
|
106
92
|
#
|
107
93
|
# # comment about C
|
@@ -123,8 +109,7 @@ module Reek
|
|
123
109
|
# where each node is possibly adorned with our SexpExtensions (see ast/ast_node_class_map
|
124
110
|
# and ast/sexp_extensions for details).
|
125
111
|
#
|
126
|
-
# @return
|
127
|
-
# for the given code, List of diagnostics messages
|
112
|
+
# @return Reek::AST::Node the AST presentation for the given code
|
128
113
|
def parse
|
129
114
|
buffer = Parser::Source::Buffer.new(origin, 1)
|
130
115
|
buffer.source = code
|
@@ -132,7 +117,7 @@ module Reek
|
|
132
117
|
|
133
118
|
# See https://whitequark.github.io/parser/Parser/Source/Comment/Associator.html
|
134
119
|
comment_map = Parser::Source::Comment.associate(ast, comments)
|
135
|
-
|
120
|
+
TreeDresser.new.dress(ast, comment_map) || AST::Node.new(:empty)
|
136
121
|
end
|
137
122
|
end
|
138
123
|
end
|
@@ -24,7 +24,7 @@ module Reek
|
|
24
24
|
# Traverses all paths we initialized the SourceLocator with, finds
|
25
25
|
# all relevant Ruby files and returns them as a list.
|
26
26
|
#
|
27
|
-
# @return [Array<Pathname>]
|
27
|
+
# @return [Array<Pathname>] Ruby paths found
|
28
28
|
def sources
|
29
29
|
source_paths
|
30
30
|
end
|
@@ -33,8 +33,8 @@ module Reek
|
|
33
33
|
|
34
34
|
attr_reader :configuration, :paths, :options
|
35
35
|
|
36
|
-
# :reek:TooManyStatements
|
37
|
-
# :reek:NestedIterators
|
36
|
+
# @quality :reek:TooManyStatements { max_statements: 7 }
|
37
|
+
# @quality :reek:NestedIterators { max_allowed_nesting: 2 }
|
38
38
|
def source_paths
|
39
39
|
paths.each_with_object([]) do |given_path, relevant_paths|
|
40
40
|
unless given_path.exist?
|
@@ -67,12 +67,12 @@ module Reek
|
|
67
67
|
configuration.path_excluded?(path)
|
68
68
|
end
|
69
69
|
|
70
|
-
# :reek:UtilityFunction
|
70
|
+
# @quality :reek:UtilityFunction
|
71
71
|
def print_no_such_file_error(path)
|
72
72
|
warn "Error: No such file - #{path}"
|
73
73
|
end
|
74
74
|
|
75
|
-
# :reek:UtilityFunction
|
75
|
+
# @quality :reek:UtilityFunction
|
76
76
|
def hidden_directory?(path)
|
77
77
|
path.basename.to_s.start_with? '.'
|
78
78
|
end
|
@@ -81,12 +81,12 @@ module Reek
|
|
81
81
|
path_excluded?(path) || hidden_directory?(path)
|
82
82
|
end
|
83
83
|
|
84
|
-
# :reek:UtilityFunction
|
84
|
+
# @quality :reek:UtilityFunction
|
85
85
|
def ruby_file?(path)
|
86
86
|
path.extname == '.rb'
|
87
87
|
end
|
88
88
|
|
89
|
-
# :reek:UtilityFunction
|
89
|
+
# @quality :reek:UtilityFunction
|
90
90
|
def current_directory?(path)
|
91
91
|
[Pathname.new('.'), Pathname.new('./')].include?(path)
|
92
92
|
end
|
data/lib/reek/spec.rb
CHANGED
@@ -65,7 +65,7 @@ module Reek
|
|
65
65
|
# raise an ArgumentError to give you a hint that you passed something that doesn't make
|
66
66
|
# much sense.
|
67
67
|
#
|
68
|
-
# @param smell_type [Symbol, String
|
68
|
+
# @param smell_type [Symbol, String] The "smell type" to check for.
|
69
69
|
# @param smell_details [Hash] A hash containing "smell warning" parameters
|
70
70
|
#
|
71
71
|
# @example Without smell_details
|
@@ -84,7 +84,7 @@ module Reek
|
|
84
84
|
#
|
85
85
|
# @public
|
86
86
|
#
|
87
|
-
# :reek:UtilityFunction
|
87
|
+
# @quality :reek:UtilityFunction
|
88
88
|
def reek_of(smell_type,
|
89
89
|
smell_details = {},
|
90
90
|
configuration = Configuration::AppConfiguration.default)
|
@@ -99,11 +99,11 @@ module Reek
|
|
99
99
|
# "reek_only_of" will fail in that case.
|
100
100
|
# 2.) "reek_only_of" doesn't support the additional smell_details hash.
|
101
101
|
#
|
102
|
-
# @param smell_type [Symbol, String
|
102
|
+
# @param smell_type [Symbol, String] The "smell type" to check for.
|
103
103
|
#
|
104
104
|
# @public
|
105
105
|
#
|
106
|
-
# :reek:UtilityFunction
|
106
|
+
# @quality :reek:UtilityFunction
|
107
107
|
def reek_only_of(smell_type, configuration = Configuration::AppConfiguration.default)
|
108
108
|
ShouldReekOnlyOf.new(smell_type, configuration)
|
109
109
|
end
|
@@ -113,8 +113,8 @@ module Reek
|
|
113
113
|
#
|
114
114
|
# @public
|
115
115
|
#
|
116
|
-
# :reek:UtilityFunction
|
117
|
-
def reek(configuration = Configuration::AppConfiguration.
|
116
|
+
# @quality :reek:UtilityFunction
|
117
|
+
def reek(configuration = Configuration::AppConfiguration.from_default_path)
|
118
118
|
ShouldReek.new(configuration: configuration)
|
119
119
|
end
|
120
120
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../examiner'
|
4
|
-
require_relative '../report/
|
4
|
+
require_relative '../report/simple_warning_formatter'
|
5
5
|
|
6
6
|
module Reek
|
7
7
|
module Spec
|
@@ -23,7 +23,7 @@ module Reek
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def failure_message_when_negated
|
26
|
-
rpt = Report::
|
26
|
+
rpt = Report::SimpleWarningFormatter.new.format_list(examiner.smells)
|
27
27
|
"Expected no smells, but got:\n#{rpt}"
|
28
28
|
end
|
29
29
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative '../examiner'
|
4
4
|
require_relative 'smell_matcher'
|
5
|
+
require_relative '../configuration/app_configuration'
|
5
6
|
|
6
7
|
module Reek
|
7
8
|
module Spec
|
@@ -14,12 +15,13 @@ module Reek
|
|
14
15
|
|
15
16
|
attr_reader :failure_message, :failure_message_when_negated
|
16
17
|
|
17
|
-
def initialize(
|
18
|
+
def initialize(smell_type,
|
18
19
|
smell_details = {},
|
19
20
|
configuration = Configuration::AppConfiguration.default)
|
20
|
-
@smell_type =
|
21
|
+
@smell_type = smell_type.to_s
|
21
22
|
@smell_details = smell_details
|
22
|
-
configuration.load_values(
|
23
|
+
configuration.load_values(Configuration::AppConfiguration::DETECTORS_KEY =>
|
24
|
+
{ smell_type => { SmellConfiguration::ENABLED_KEY => true } })
|
23
25
|
@configuration = configuration
|
24
26
|
end
|
25
27
|
|
@@ -34,7 +36,8 @@ module Reek
|
|
34
36
|
|
35
37
|
def with_config(config_hash)
|
36
38
|
new_configuration = Configuration::AppConfiguration.default
|
37
|
-
new_configuration.load_values(
|
39
|
+
new_configuration.load_values(Configuration::AppConfiguration::DETECTORS_KEY =>
|
40
|
+
{ smell_type => config_hash })
|
38
41
|
self.class.new(smell_type, smell_details, new_configuration)
|
39
42
|
end
|
40
43
|
|
@@ -82,7 +85,7 @@ module Reek
|
|
82
85
|
"#{smell_type} with smell details #{smell_details}, but it did"
|
83
86
|
end
|
84
87
|
|
85
|
-
# :reek:FeatureEnvy
|
88
|
+
# @quality :reek:FeatureEnvy
|
86
89
|
def all_relevant_smell_details_formatted
|
87
90
|
matching_smell_types.each_with_object([]).with_index do |(smell, accumulator), index|
|
88
91
|
accumulator << "#{index + 1}.)\n"
|
@@ -93,17 +96,7 @@ module Reek
|
|
93
96
|
end
|
94
97
|
|
95
98
|
def origin
|
96
|
-
examiner.
|
97
|
-
end
|
98
|
-
|
99
|
-
# :reek:UtilityFunction
|
100
|
-
def normalize(smell_type_or_class)
|
101
|
-
case smell_type_or_class
|
102
|
-
when Class
|
103
|
-
smell_type_or_class.smell_type
|
104
|
-
else
|
105
|
-
smell_type_or_class.to_s
|
106
|
-
end
|
99
|
+
examiner.origin
|
107
100
|
end
|
108
101
|
end
|
109
102
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../examiner'
|
4
|
-
require_relative '../report/
|
4
|
+
require_relative '../report/simple_warning_formatter'
|
5
5
|
require_relative 'should_reek_of'
|
6
6
|
require_relative 'smell_matcher'
|
7
7
|
|
@@ -24,12 +24,12 @@ module Reek
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def failure_message
|
27
|
-
rpt = Report::
|
28
|
-
"Expected #{examiner.
|
27
|
+
rpt = Report::SimpleWarningFormatter.new.format_list(warnings)
|
28
|
+
"Expected #{examiner.origin} to reek only of #{smell_type}, but got:\n#{rpt}"
|
29
29
|
end
|
30
30
|
|
31
31
|
def failure_message_when_negated
|
32
|
-
"Expected #{examiner.
|
32
|
+
"Expected #{examiner.origin} not to reek only of #{smell_type}, but it did"
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
data/lib/reek/tree_dresser.rb
CHANGED
@@ -31,14 +31,14 @@ module Reek
|
|
31
31
|
# time the nodes will contain type-dependent mixins, e.g. this:
|
32
32
|
# (const nil :Klazz)
|
33
33
|
# will be of type Reek::AST::Node with Reek::AST::SexpExtensions::ConstNode mixed in.
|
34
|
-
#
|
35
|
-
# @param
|
36
|
-
# @param
|
34
|
+
#
|
35
|
+
# @param sexp [Parser::AST::Node] the given sexp
|
36
|
+
# @param comment_map [Hash] see the documentation for SourceCode#syntax_tree
|
37
37
|
#
|
38
38
|
# @return an instance of Reek::AST::Node with type-dependent sexp extensions mixed in.
|
39
39
|
#
|
40
|
-
# :reek:FeatureEnvy
|
41
|
-
# :reek:TooManyStatements
|
40
|
+
# @quality :reek:FeatureEnvy
|
41
|
+
# @quality :reek:TooManyStatements { max_statements: 6 }
|
42
42
|
def dress(sexp, comment_map)
|
43
43
|
return sexp unless sexp.is_a? ::Parser::AST::Node
|
44
44
|
type = sexp.type
|
data/lib/reek/version.rb
CHANGED
data/reek.gemspec
CHANGED
@@ -5,7 +5,6 @@ Gem::Specification.new do |s|
|
|
5
5
|
s.version = Reek::Version::STRING
|
6
6
|
|
7
7
|
s.authors = ['Kevin Rutherford', 'Timo Roessner', 'Matijs van Zuijlen', 'Piotr Szotkowski']
|
8
|
-
s.default_executable = 'reek'
|
9
8
|
s.description =
|
10
9
|
'Reek is a tool that examines Ruby classes, modules and methods and reports ' \
|
11
10
|
'any code smells it finds.'
|
@@ -15,12 +14,13 @@ Gem::Specification.new do |s|
|
|
15
14
|
s.extra_rdoc_files = ['CHANGELOG.md', 'License.txt']
|
16
15
|
s.files = `git ls-files -z`.split("\0")
|
17
16
|
s.executables = s.files.grep(%r{^bin/}).map { |path| File.basename(path) }
|
18
|
-
s.homepage = 'https://github.com/troessner/reek
|
17
|
+
s.homepage = 'https://github.com/troessner/reek'
|
19
18
|
s.rdoc_options = %w(--main README.md -x assets/|bin/|config/|features/|spec/|tasks/)
|
20
|
-
s.required_ruby_version = '>= 2.
|
19
|
+
s.required_ruby_version = '>= 2.3.0'
|
21
20
|
s.summary = 'Code smell detector for Ruby'
|
22
21
|
|
23
22
|
s.add_runtime_dependency 'codeclimate-engine-rb', '~> 0.4.0'
|
23
|
+
s.add_runtime_dependency 'kwalify', '~> 0.7.0'
|
24
24
|
s.add_runtime_dependency 'parser', '< 2.6', '>= 2.5.0.0'
|
25
25
|
s.add_runtime_dependency 'rainbow', '>= 2.0', '< 4.0'
|
26
26
|
end
|
data/samples/checkstyle.xml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<?xml version='1.0'?>
|
2
2
|
<checkstyle>
|
3
|
-
<file name='samples/smelly.rb'>
|
3
|
+
<file name='samples/smelly_source/smelly.rb'>
|
4
4
|
<error column='0' line='4' message='has the name 'x'' severity='warning' source='UncommunicativeMethodName'/>
|
5
5
|
<error column='0' line='5' message='has the variable name 'y'' severity='warning' source='UncommunicativeVariableName'/>
|
6
6
|
</file>
|
File without changes
|
@@ -0,0 +1,29 @@
|
|
1
|
+
---
|
2
|
+
detectors:
|
3
|
+
UnusedPrivateMethod:
|
4
|
+
exclude:
|
5
|
+
- "/exclude regexp/"
|
6
|
+
UncommunicativeMethodName:
|
7
|
+
reject:
|
8
|
+
- "reject name"
|
9
|
+
accept:
|
10
|
+
- "accept name"
|
11
|
+
UncommunicativeModuleName:
|
12
|
+
reject:
|
13
|
+
- "reject name 1"
|
14
|
+
- "reject name 2"
|
15
|
+
accept:
|
16
|
+
- "accept name 1"
|
17
|
+
- "accept name 2"
|
18
|
+
UncommunicativeParameterName:
|
19
|
+
reject:
|
20
|
+
- "reject name"
|
21
|
+
- "/reject regexp/"
|
22
|
+
accept:
|
23
|
+
- "accept name"
|
24
|
+
- "/accept regexp/"
|
25
|
+
UncommunicativeVariableName:
|
26
|
+
reject:
|
27
|
+
- "/^reject regexp$/"
|
28
|
+
accept:
|
29
|
+
- "/accept(.*)regexp/"
|