reek 4.7.1 → 5.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/.codeclimate.yml +17 -12
- data/.rubocop.yml +36 -7
- data/.simplecov +1 -0
- data/.travis.yml +3 -9
- data/.yardopts +1 -1
- data/CHANGELOG.md +59 -0
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +5 -5
- data/README.md +134 -104
- 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 +7 -7
- data/docs/Instance-Variable-Assumption.md +1 -1
- 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 +45 -6
- data/docs/Uncommunicative-Module-Name.md +49 -7
- data/docs/Uncommunicative-Parameter-Name.md +43 -5
- data/docs/Uncommunicative-Variable-Name.md +73 -2
- data/docs/Unused-Private-Method.md +3 -3
- data/docs/defaults.reek.yml +129 -0
- data/docs/yard_plugin.rb +1 -0
- data/features/command_line_interface/basic_usage.feature +2 -2
- data/features/command_line_interface/options.feature +46 -4
- data/features/command_line_interface/show_progress.feature +4 -4
- data/features/command_line_interface/smell_selection.feature +1 -1
- data/features/command_line_interface/smells_count.feature +6 -6
- data/features/command_line_interface/stdin.feature +30 -8
- data/features/configuration_files/accept_setting.feature +45 -28
- data/features/configuration_files/directory_specific_directives.feature +80 -75
- data/features/configuration_files/exclude_directives.feature +11 -10
- data/features/configuration_files/exclude_paths_directives.feature +4 -4
- data/features/configuration_files/masking_smells.feature +38 -9
- data/features/configuration_files/mix_accept_reject_setting.feature +31 -28
- data/features/configuration_files/reject_setting.feature +52 -41
- data/features/configuration_files/schema_validation.feature +59 -0
- data/features/configuration_files/unused_private_method.feature +18 -16
- data/features/configuration_loading.feature +53 -10
- data/features/configuration_via_source_comments/erroneous_source_comments.feature +3 -3
- data/features/configuration_via_source_comments/well_formed_source_comments.feature +2 -2
- data/features/locales.feature +32 -0
- data/features/rake_task/rake_task.feature +58 -18
- data/features/reports/json.feature +3 -3
- data/features/reports/reports.feature +34 -34
- data/features/reports/yaml.feature +3 -3
- data/features/rspec_matcher.feature +40 -0
- data/features/samples.feature +287 -287
- data/features/step_definitions/reek_steps.rb +2 -2
- data/features/step_definitions/sample_file_steps.rb +9 -4
- data/features/support/env.rb +2 -11
- data/features/todo_list.feature +26 -23
- data/lib/reek/ast/builder.rb +1 -1
- data/lib/reek/ast/node.rb +40 -58
- data/lib/reek/ast/object_refs.rb +1 -1
- data/lib/reek/ast/reference_collector.rb +2 -4
- data/lib/reek/ast/sexp_extensions/case.rb +1 -1
- data/lib/reek/ast/sexp_extensions/if.rb +8 -1
- data/lib/reek/ast/sexp_extensions/logical_operators.rb +1 -1
- data/lib/reek/ast/sexp_extensions/methods.rb +4 -6
- data/lib/reek/ast/sexp_extensions/send.rb +0 -4
- 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 +8 -8
- data/lib/reek/cli/options.rb +31 -16
- data/lib/reek/cli/silencer.rb +14 -3
- data/lib/reek/code_comment.rb +14 -16
- data/lib/reek/configuration/app_configuration.rb +32 -27
- data/lib/reek/configuration/configuration_converter.rb +110 -0
- data/lib/reek/configuration/configuration_file_finder.rb +16 -41
- 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 +3 -3
- data/lib/reek/context/code_context.rb +47 -43
- data/lib/reek/context/ghost_context.rb +0 -2
- data/lib/reek/context/method_context.rb +22 -15
- data/lib/reek/context/module_context.rb +5 -9
- data/lib/reek/context/root_context.rb +0 -4
- data/lib/reek/context/send_context.rb +2 -2
- data/lib/reek/context_builder.rb +43 -44
- data/lib/reek/detector_repository.rb +11 -11
- data/lib/reek/documentation_link.rb +28 -0
- data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +14 -13
- data/lib/reek/errors/bad_detector_in_comment_error.rb +12 -11
- data/lib/reek/errors/base_error.rb +3 -0
- data/lib/reek/errors/config_file_error.rb +11 -0
- data/lib/reek/errors/encoding_error.rb +43 -0
- data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +13 -12
- data/lib/reek/errors/incomprehensible_source_error.rb +22 -24
- data/lib/reek/errors/syntax_error.rb +41 -0
- data/lib/reek/examiner.rb +24 -26
- data/lib/reek/logging_error_handler.rb +7 -5
- data/lib/reek/rake/task.rb +8 -4
- data/lib/reek/report/base_report.rb +8 -12
- data/lib/reek/report/code_climate/code_climate_configuration.rb +1 -1
- data/lib/reek/report/code_climate/code_climate_configuration.yml +6 -10
- 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/report.rb +15 -10
- data/lib/reek/smell_configuration.rb +2 -2
- data/lib/reek/smell_detectors/attribute.rb +5 -11
- data/lib/reek/smell_detectors/base_detector.rb +30 -26
- data/lib/reek/smell_detectors/boolean_parameter.rb +3 -5
- data/lib/reek/smell_detectors/class_variable.rb +5 -14
- data/lib/reek/smell_detectors/control_parameter.rb +18 -33
- data/lib/reek/smell_detectors/data_clump.rb +15 -9
- data/lib/reek/smell_detectors/duplicate_method_call.rb +23 -17
- data/lib/reek/smell_detectors/feature_envy.rb +9 -7
- data/lib/reek/smell_detectors/instance_variable_assumption.rb +14 -23
- data/lib/reek/smell_detectors/irresponsible_module.rb +5 -12
- data/lib/reek/smell_detectors/long_parameter_list.rb +10 -7
- data/lib/reek/smell_detectors/long_yield_list.rb +10 -7
- data/lib/reek/smell_detectors/manual_dispatch.rb +4 -5
- data/lib/reek/smell_detectors/{prima_donna_method.rb → missing_safe_method.rb} +20 -20
- data/lib/reek/smell_detectors/module_initialize.rb +3 -5
- data/lib/reek/smell_detectors/nested_iterators.rb +16 -24
- data/lib/reek/smell_detectors/nil_check.rb +8 -15
- data/lib/reek/smell_detectors/repeated_conditional.rb +13 -11
- data/lib/reek/smell_detectors/subclassed_from_core_class.rb +7 -8
- data/lib/reek/smell_detectors/too_many_constants.rb +10 -9
- data/lib/reek/smell_detectors/too_many_instance_variables.rb +10 -6
- data/lib/reek/smell_detectors/too_many_methods.rb +11 -7
- data/lib/reek/smell_detectors/too_many_statements.rb +10 -6
- data/lib/reek/smell_detectors/uncommunicative_method_name.rb +10 -11
- data/lib/reek/smell_detectors/uncommunicative_module_name.rb +14 -18
- data/lib/reek/smell_detectors/uncommunicative_parameter_name.rb +17 -22
- data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +26 -27
- data/lib/reek/smell_detectors/unused_parameters.rb +4 -6
- data/lib/reek/smell_detectors/unused_private_method.rb +11 -18
- data/lib/reek/smell_detectors/utility_function.rb +12 -16
- data/lib/reek/smell_detectors.rb +1 -2
- data/lib/reek/smell_warning.rb +15 -8
- data/lib/reek/source/source_code.rb +57 -58
- data/lib/reek/source/source_locator.rb +8 -8
- 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/spec.rb +6 -6
- data/lib/reek/tree_dresser.rb +8 -8
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +5 -7
- data/samples/checkstyle.xml +1 -1
- 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/configuration/partial_mask.reek +3 -2
- data/samples/configuration/regular_configuration/.reek.yml +4 -0
- data/samples/paths.rb +5 -4
- data/samples/source_with_hidden_directories/.hidden/hidden.rb +1 -0
- data/samples/source_with_hidden_directories/not_hidden.rb +1 -0
- data/spec/factories/factories.rb +2 -13
- data/spec/reek/ast/node_spec.rb +103 -10
- data/spec/reek/ast/reference_collector_spec.rb +1 -1
- data/spec/reek/ast/sexp_extensions_spec.rb +14 -34
- data/spec/reek/cli/application_spec.rb +52 -42
- data/spec/reek/cli/command/todo_list_command_spec.rb +6 -4
- data/spec/reek/cli/silencer_spec.rb +28 -0
- data/spec/reek/code_comment_spec.rb +31 -38
- data/spec/reek/configuration/app_configuration_spec.rb +46 -33
- data/spec/reek/configuration/configuration_file_finder_spec.rb +133 -51
- data/spec/reek/configuration/default_directive_spec.rb +1 -1
- data/spec/reek/configuration/directory_directives_spec.rb +6 -7
- data/spec/reek/configuration/excluded_paths_spec.rb +6 -6
- 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 +70 -106
- data/spec/reek/context/ghost_context_spec.rb +9 -9
- data/spec/reek/context/method_context_spec.rb +2 -2
- data/spec/reek/context/module_context_spec.rb +3 -3
- data/spec/reek/context/root_context_spec.rb +1 -1
- data/spec/reek/context_builder_spec.rb +20 -0
- data/spec/reek/documentation_link_spec.rb +20 -0
- data/spec/reek/errors/base_error_spec.rb +13 -0
- data/spec/reek/examiner_spec.rb +136 -29
- data/spec/reek/rake/task_spec.rb +25 -2
- data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +82 -80
- data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +6 -6
- 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 +3 -3
- data/spec/reek/report/yaml_report_spec.rb +9 -38
- data/spec/reek/report_spec.rb +3 -3
- data/spec/reek/smell_detectors/base_detector_spec.rb +4 -5
- data/spec/reek/smell_detectors/boolean_parameter_spec.rb +2 -2
- data/spec/reek/smell_detectors/class_variable_spec.rb +26 -32
- data/spec/reek/smell_detectors/control_parameter_spec.rb +34 -4
- data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +3 -3
- data/spec/reek/smell_detectors/feature_envy_spec.rb +47 -2
- data/spec/reek/smell_detectors/irresponsible_module_spec.rb +0 -11
- data/spec/reek/smell_detectors/{prima_donna_method_spec.rb → missing_safe_method_spec.rb} +10 -10
- data/spec/reek/smell_detectors/module_initialize_spec.rb +14 -0
- data/spec/reek/smell_detectors/nested_iterators_spec.rb +1 -1
- 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 +36 -15
- data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +9 -9
- data/spec/reek/smell_detectors/unused_parameters_spec.rb +3 -3
- data/spec/reek/smell_detectors/unused_private_method_spec.rb +21 -10
- data/spec/reek/smell_detectors/utility_function_spec.rb +57 -5
- data/spec/reek/smell_warning_spec.rb +12 -8
- data/spec/reek/source/source_code_spec.rb +22 -21
- data/spec/reek/source/source_locator_spec.rb +17 -17
- data/spec/reek/spec/should_reek_of_spec.rb +25 -29
- data/spec/reek/spec/should_reek_only_of_spec.rb +2 -2
- data/spec/reek/spec/should_reek_spec.rb +8 -8
- data/spec/reek/spec/smell_matcher_spec.rb +23 -23
- data/spec/reek/tree_dresser_spec.rb +12 -17
- data/spec/spec_helper.rb +6 -17
- data/tasks/configuration.rake +8 -5
- metadata +74 -41
- data/defaults.reek +0 -131
- data/features/configuration_files/warn_about_multiple_configuration_files.feature +0 -44
- 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 -36
- data/lib/reek/report/formatter.rb +0 -33
- 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
- /data/{samples/configuration/more_than_one_configuration_file/regular.reek → .reek.yml} +0 -0
- /data/samples/{clean.rb → clean_source/clean.rb} +0 -0
- /data/samples/{exceptions.reek → configuration/home/home.reek.yml} +0 -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/{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/uncommunicative_parameter_name.rb → source_with_non_ruby_files/ruby.rb} +0 -0
data/lib/reek/context_builder.rb
CHANGED
|
@@ -20,8 +20,9 @@ module Reek
|
|
|
20
20
|
# counting. Ideally `ContextBuilder` would only build up the context tree and leave the
|
|
21
21
|
# statement and reference counting to the contexts.
|
|
22
22
|
#
|
|
23
|
-
# :reek:TooManyMethods
|
|
24
|
-
# :reek:UnusedPrivateMethod
|
|
23
|
+
# @quality :reek:TooManyMethods { max_methods: 31 }
|
|
24
|
+
# @quality :reek:UnusedPrivateMethod { exclude: [ !ruby/regexp /process_/ ] }
|
|
25
|
+
# @quality :reek:DataClump
|
|
25
26
|
class ContextBuilder
|
|
26
27
|
attr_reader :context_tree
|
|
27
28
|
|
|
@@ -58,10 +59,10 @@ module Reek
|
|
|
58
59
|
# RootContext -> children: 1 ModuleContext -> children: 1 MethodContext
|
|
59
60
|
#
|
|
60
61
|
# @return [Reek::Context::RootContext] tree of nested contexts
|
|
61
|
-
def build(exp)
|
|
62
|
+
def build(exp, parent_exp = nil)
|
|
62
63
|
context_processor = "process_#{exp.type}"
|
|
63
64
|
if context_processor_exists?(context_processor)
|
|
64
|
-
send(context_processor, exp)
|
|
65
|
+
send(context_processor, exp, parent_exp)
|
|
65
66
|
else
|
|
66
67
|
process exp
|
|
67
68
|
end
|
|
@@ -71,12 +72,12 @@ module Reek
|
|
|
71
72
|
# Handles every node for which we have no context_processor.
|
|
72
73
|
#
|
|
73
74
|
def process(exp)
|
|
74
|
-
exp.children.grep(AST::Node).each(
|
|
75
|
+
exp.children.grep(AST::Node).each { |child| build(child, exp) }
|
|
75
76
|
end
|
|
76
77
|
|
|
77
78
|
# Handles `module` and `class` nodes.
|
|
78
79
|
#
|
|
79
|
-
def process_module(exp)
|
|
80
|
+
def process_module(exp, _parent)
|
|
80
81
|
inside_new_context(Context::ModuleContext, exp) do
|
|
81
82
|
process(exp)
|
|
82
83
|
end
|
|
@@ -91,7 +92,7 @@ module Reek
|
|
|
91
92
|
# class << self
|
|
92
93
|
# end
|
|
93
94
|
#
|
|
94
|
-
def process_sclass(exp)
|
|
95
|
+
def process_sclass(exp, _parent)
|
|
95
96
|
inside_new_context(Context::GhostContext, exp) do
|
|
96
97
|
process(exp)
|
|
97
98
|
end
|
|
@@ -103,9 +104,9 @@ module Reek
|
|
|
103
104
|
#
|
|
104
105
|
# Foo = Class.new Bar
|
|
105
106
|
#
|
|
106
|
-
def process_casgn(exp)
|
|
107
|
+
def process_casgn(exp, parent)
|
|
107
108
|
if exp.defines_module?
|
|
108
|
-
process_module(exp)
|
|
109
|
+
process_module(exp, parent)
|
|
109
110
|
else
|
|
110
111
|
process(exp)
|
|
111
112
|
end
|
|
@@ -119,8 +120,8 @@ module Reek
|
|
|
119
120
|
#
|
|
120
121
|
# Given the above example we would count 2 statements overall.
|
|
121
122
|
#
|
|
122
|
-
def process_def(exp)
|
|
123
|
-
inside_new_context(current_context.method_context_class, exp) do
|
|
123
|
+
def process_def(exp, parent)
|
|
124
|
+
inside_new_context(current_context.method_context_class, exp, parent) do
|
|
124
125
|
increase_statement_count_by(exp.body)
|
|
125
126
|
process(exp)
|
|
126
127
|
end
|
|
@@ -134,8 +135,8 @@ module Reek
|
|
|
134
135
|
#
|
|
135
136
|
# Given the above example we would count 2 statements overall.
|
|
136
137
|
#
|
|
137
|
-
def process_defs(exp)
|
|
138
|
-
inside_new_context(Context::SingletonMethodContext, exp) do
|
|
138
|
+
def process_defs(exp, parent)
|
|
139
|
+
inside_new_context(Context::SingletonMethodContext, exp, parent) do
|
|
139
140
|
increase_statement_count_by(exp.body)
|
|
140
141
|
process(exp)
|
|
141
142
|
end
|
|
@@ -151,14 +152,14 @@ module Reek
|
|
|
151
152
|
# we also record to what the method call is referring to
|
|
152
153
|
# which we later use for smell detectors like FeatureEnvy.
|
|
153
154
|
#
|
|
154
|
-
def process_send(exp)
|
|
155
|
+
def process_send(exp, _parent)
|
|
156
|
+
process(exp)
|
|
155
157
|
case current_context
|
|
156
158
|
when Context::ModuleContext
|
|
157
159
|
handle_send_for_modules exp
|
|
158
160
|
when Context::MethodContext
|
|
159
161
|
handle_send_for_methods exp
|
|
160
162
|
end
|
|
161
|
-
process(exp)
|
|
162
163
|
end
|
|
163
164
|
|
|
164
165
|
# Handles `op_asgn` nodes a.k.a. Ruby's assignment operators.
|
|
@@ -173,7 +174,7 @@ module Reek
|
|
|
173
174
|
#
|
|
174
175
|
# We record one reference to `x` given the example above.
|
|
175
176
|
#
|
|
176
|
-
def process_op_asgn(exp)
|
|
177
|
+
def process_op_asgn(exp, _parent)
|
|
177
178
|
current_context.record_call_to(exp)
|
|
178
179
|
process(exp)
|
|
179
180
|
end
|
|
@@ -192,7 +193,7 @@ module Reek
|
|
|
192
193
|
#
|
|
193
194
|
# We record one reference to `self`.
|
|
194
195
|
#
|
|
195
|
-
def process_ivar(exp)
|
|
196
|
+
def process_ivar(exp, _parent)
|
|
196
197
|
current_context.record_use_of_self
|
|
197
198
|
process(exp)
|
|
198
199
|
end
|
|
@@ -205,7 +206,7 @@ module Reek
|
|
|
205
206
|
#
|
|
206
207
|
# def self.foo; end
|
|
207
208
|
#
|
|
208
|
-
def process_self(
|
|
209
|
+
def process_self(_exp, _parent)
|
|
209
210
|
current_context.record_use_of_self
|
|
210
211
|
end
|
|
211
212
|
|
|
@@ -225,7 +226,7 @@ module Reek
|
|
|
225
226
|
#
|
|
226
227
|
# We record one reference to `self`.
|
|
227
228
|
#
|
|
228
|
-
def process_zsuper(
|
|
229
|
+
def process_zsuper(_exp, _parent)
|
|
229
230
|
current_context.record_use_of_self
|
|
230
231
|
end
|
|
231
232
|
|
|
@@ -249,7 +250,7 @@ module Reek
|
|
|
249
250
|
#
|
|
250
251
|
# We record one reference to `self`.
|
|
251
252
|
#
|
|
252
|
-
def process_super(exp)
|
|
253
|
+
def process_super(exp, _parent)
|
|
253
254
|
current_context.record_use_of_self
|
|
254
255
|
process(exp)
|
|
255
256
|
end
|
|
@@ -262,7 +263,7 @@ module Reek
|
|
|
262
263
|
#
|
|
263
264
|
# Counts non-empty blocks as one statement.
|
|
264
265
|
#
|
|
265
|
-
def process_block(exp)
|
|
266
|
+
def process_block(exp, _parent)
|
|
266
267
|
increase_statement_count_by(exp.block)
|
|
267
268
|
process(exp)
|
|
268
269
|
end
|
|
@@ -282,7 +283,7 @@ module Reek
|
|
|
282
283
|
# At the end we subtract one statement because the surrounding context was already counted
|
|
283
284
|
# as one (e.g. via `process_def`).
|
|
284
285
|
#
|
|
285
|
-
def process_begin(exp)
|
|
286
|
+
def process_begin(exp, _parent)
|
|
286
287
|
increase_statement_count_by(exp.children)
|
|
287
288
|
decrease_statement_count
|
|
288
289
|
process(exp)
|
|
@@ -308,7 +309,7 @@ module Reek
|
|
|
308
309
|
# `children[1]` refers to the `if` body (so `puts 'bingo'` from above) and
|
|
309
310
|
# `children[2]` to the `else` body (so `3` from above), which might be nil.
|
|
310
311
|
#
|
|
311
|
-
def process_if(exp)
|
|
312
|
+
def process_if(exp, _parent)
|
|
312
313
|
children = exp.children
|
|
313
314
|
increase_statement_count_by(children[1])
|
|
314
315
|
increase_statement_count_by(children[2])
|
|
@@ -331,7 +332,7 @@ module Reek
|
|
|
331
332
|
#
|
|
332
333
|
# `children[1]` below refers to the `while` body (so `puts 'bingo'` from above)
|
|
333
334
|
#
|
|
334
|
-
def process_while(exp)
|
|
335
|
+
def process_while(exp, _parent)
|
|
335
336
|
increase_statement_count_by(exp.children[1])
|
|
336
337
|
decrease_statement_count
|
|
337
338
|
process(exp)
|
|
@@ -354,7 +355,7 @@ module Reek
|
|
|
354
355
|
#
|
|
355
356
|
# `children[2]` below refers to the `while` body (so `puts i` from above)
|
|
356
357
|
#
|
|
357
|
-
def process_for(exp)
|
|
358
|
+
def process_for(exp, _parent)
|
|
358
359
|
increase_statement_count_by(exp.children[2])
|
|
359
360
|
decrease_statement_count
|
|
360
361
|
process(exp)
|
|
@@ -384,7 +385,7 @@ module Reek
|
|
|
384
385
|
# `exp` would be the whole method body wrapped under a `rescue` node.
|
|
385
386
|
# See `process_resbody` for additional reference.
|
|
386
387
|
#
|
|
387
|
-
def process_rescue(exp)
|
|
388
|
+
def process_rescue(exp, _parent)
|
|
388
389
|
increase_statement_count_by(exp.children.first)
|
|
389
390
|
decrease_statement_count
|
|
390
391
|
process(exp)
|
|
@@ -412,7 +413,7 @@ module Reek
|
|
|
412
413
|
# `exp` would be the whole `rescue` body.
|
|
413
414
|
# See `process_rescue` for additional reference.
|
|
414
415
|
#
|
|
415
|
-
def process_resbody(exp)
|
|
416
|
+
def process_resbody(exp, _parent)
|
|
416
417
|
increase_statement_count_by(exp.children[1..-1].compact)
|
|
417
418
|
process(exp)
|
|
418
419
|
end
|
|
@@ -434,7 +435,7 @@ module Reek
|
|
|
434
435
|
# At the end we subtract one statement because the surrounding context was already counted
|
|
435
436
|
# as one (e.g. via `process_def`).
|
|
436
437
|
#
|
|
437
|
-
def process_case(exp)
|
|
438
|
+
def process_case(exp, _parent)
|
|
438
439
|
increase_statement_count_by(exp.else_body)
|
|
439
440
|
decrease_statement_count
|
|
440
441
|
process(exp)
|
|
@@ -460,7 +461,7 @@ module Reek
|
|
|
460
461
|
#
|
|
461
462
|
# Counts the `when` body.
|
|
462
463
|
#
|
|
463
|
-
def process_when(exp)
|
|
464
|
+
def process_when(exp, _parent)
|
|
464
465
|
increase_statement_count_by(exp.body)
|
|
465
466
|
process(exp)
|
|
466
467
|
end
|
|
@@ -469,7 +470,7 @@ module Reek
|
|
|
469
470
|
self.class.private_method_defined?(name)
|
|
470
471
|
end
|
|
471
472
|
|
|
472
|
-
# :reek:ControlParameter
|
|
473
|
+
# @quality :reek:ControlParameter
|
|
473
474
|
def increase_statement_count_by(sexp)
|
|
474
475
|
current_context.statement_counter.increase_by sexp
|
|
475
476
|
end
|
|
@@ -481,37 +482,35 @@ module Reek
|
|
|
481
482
|
# Stores a reference to the current context, creates a nested new one,
|
|
482
483
|
# yields to the given block and then restores the previous context.
|
|
483
484
|
#
|
|
484
|
-
# @param klass [Context::*Context]
|
|
485
|
-
# @param
|
|
485
|
+
# @param klass [Context::*Context] context class
|
|
486
|
+
# @param args arguments for the class initializer
|
|
486
487
|
# @yield block
|
|
487
488
|
#
|
|
488
|
-
def inside_new_context(klass,
|
|
489
|
-
new_context = append_new_context(klass,
|
|
489
|
+
def inside_new_context(klass, *args)
|
|
490
|
+
new_context = append_new_context(klass, *args)
|
|
490
491
|
|
|
491
492
|
orig, self.current_context = current_context, new_context
|
|
492
493
|
yield
|
|
493
494
|
self.current_context = orig
|
|
494
495
|
end
|
|
495
496
|
|
|
496
|
-
#
|
|
497
|
-
# current context.
|
|
497
|
+
# Appends a new child context to the current context but does not change
|
|
498
|
+
# the current context.
|
|
498
499
|
#
|
|
499
|
-
# @param klass [Context::*Context]
|
|
500
|
-
# @param args
|
|
500
|
+
# @param klass [Context::*Context] context class
|
|
501
|
+
# @param args arguments for the class initializer
|
|
501
502
|
#
|
|
502
|
-
# @return [Context::*Context]
|
|
503
|
+
# @return [Context::*Context] the context that was appended
|
|
503
504
|
#
|
|
504
505
|
def append_new_context(klass, *args)
|
|
505
|
-
klass.new(
|
|
506
|
+
klass.new(*args).tap do |new_context|
|
|
506
507
|
new_context.register_with_parent(current_context)
|
|
507
508
|
end
|
|
508
509
|
end
|
|
509
510
|
|
|
510
511
|
def handle_send_for_modules(exp)
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
current_context.track_visibility(method_name, arg_names)
|
|
514
|
-
current_context.track_singleton_visibility(method_name, arg_names)
|
|
512
|
+
arg_names = exp.args.map { |arg| arg.children.first }
|
|
513
|
+
current_context.track_visibility(exp.name, arg_names)
|
|
515
514
|
register_attributes(exp)
|
|
516
515
|
end
|
|
517
516
|
|
|
@@ -35,31 +35,31 @@ module Reek
|
|
|
35
35
|
configuration: {})
|
|
36
36
|
@configuration = configuration
|
|
37
37
|
@smell_types = smell_types
|
|
38
|
-
@detectors = smell_types.map { |klass| klass.new configuration_for(klass) }
|
|
39
38
|
end
|
|
40
39
|
|
|
41
40
|
def examine(context)
|
|
42
|
-
smell_detectors_for(context.type).flat_map do |
|
|
43
|
-
detector.
|
|
41
|
+
smell_detectors_for(context.type).flat_map do |klass|
|
|
42
|
+
detector = klass.new configuration: configuration_for(klass), context: context
|
|
43
|
+
detector.run
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
# @return [Array<String>] The names of all known SmellDetectors
|
|
48
|
+
# e.g. ["BooleanParameter", "ClassVariable"].
|
|
49
|
+
def self.available_detector_names
|
|
50
|
+
smell_types.map(&:smell_type)
|
|
51
|
+
end
|
|
52
|
+
|
|
47
53
|
private
|
|
48
54
|
|
|
49
|
-
attr_reader :configuration, :smell_types
|
|
55
|
+
attr_reader :configuration, :smell_types
|
|
50
56
|
|
|
51
57
|
def configuration_for(klass)
|
|
52
58
|
configuration.fetch klass, {}
|
|
53
59
|
end
|
|
54
60
|
|
|
55
61
|
def smell_detectors_for(type)
|
|
56
|
-
|
|
57
|
-
detector.contexts.include? type
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def enabled_detectors
|
|
62
|
-
detectors.select { |detector| detector.config.enabled? }
|
|
62
|
+
smell_types.select { |detector| detector.contexts.include? type }
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
65
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Reek
|
|
4
|
+
# Generate versioned links to our documentation
|
|
5
|
+
module DocumentationLink
|
|
6
|
+
HELP_LINK_TEMPLATE = 'https://github.com/troessner/reek/blob/v%<version>s/docs/%<item>s.md'
|
|
7
|
+
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
# Build link to the documentation about the given subject for the current
|
|
11
|
+
# version of Reek. The subject can be either a smell type like
|
|
12
|
+
# 'FeatureEnvy' or a general subject like 'Rake Task'.
|
|
13
|
+
#
|
|
14
|
+
# @param subject [String]
|
|
15
|
+
# @return [String] the full URL for the relevant documentation
|
|
16
|
+
def build(subject)
|
|
17
|
+
Kernel.format(HELP_LINK_TEMPLATE, version: Version::STRING, item: name_to_param(subject))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Convert the given subject name to a form that is acceptable in a URL.
|
|
21
|
+
def name_to_param(name)
|
|
22
|
+
# Splits the subject on the start of capitalized words, optionally
|
|
23
|
+
# preceded by a space. The space is discarded, the start of the word is
|
|
24
|
+
# not.
|
|
25
|
+
name.split(/ *(?=[A-Z][a-z])/).join('-')
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'base_error'
|
|
4
|
+
require_relative '../documentation_link'
|
|
4
5
|
|
|
5
6
|
module Reek
|
|
6
7
|
module Errors
|
|
7
8
|
# Gets raised when trying to configure a detector with an option
|
|
8
9
|
# which is unknown to it.
|
|
9
10
|
class BadDetectorConfigurationKeyInCommentError < BaseError
|
|
10
|
-
UNKNOWN_SMELL_DETECTOR_MESSAGE = <<-
|
|
11
|
+
UNKNOWN_SMELL_DETECTOR_MESSAGE = <<-MESSAGE
|
|
11
12
|
|
|
12
|
-
Error: You are trying to configure the smell detector '
|
|
13
|
-
in one of your source code comments with the unknown option
|
|
14
|
-
The source is '
|
|
13
|
+
Error: You are trying to configure the smell detector '%<detector>s'
|
|
14
|
+
in one of your source code comments with the unknown option %<option>s.
|
|
15
|
+
The source is '%<source>s' and the comment belongs to the expression starting in line %<line>d.
|
|
15
16
|
Here's the original comment:
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
%<comment>s
|
|
18
19
|
|
|
19
20
|
Please see the Reek docs for:
|
|
20
|
-
* how to configure Reek via source code comments:
|
|
21
|
-
* what basic options are available:
|
|
21
|
+
* how to configure Reek via source code comments: #{DocumentationLink.build('Smell Suppression')}
|
|
22
|
+
* what basic options are available: #{DocumentationLink.build('Basic Smell Options')}
|
|
22
23
|
* what custom options are available by checking the detector specific documentation in /docs
|
|
23
24
|
Update the offensive comment (or remove it if no longer applicable) and re-run Reek.
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
MESSAGE
|
|
26
27
|
|
|
27
28
|
def initialize(detector_name:, offensive_keys:, source:, line:, original_comment:)
|
|
28
29
|
message = format(UNKNOWN_SMELL_DETECTOR_MESSAGE,
|
|
29
|
-
detector_name,
|
|
30
|
-
offensive_keys,
|
|
31
|
-
source,
|
|
32
|
-
line,
|
|
33
|
-
original_comment)
|
|
30
|
+
detector: detector_name,
|
|
31
|
+
option: offensive_keys,
|
|
32
|
+
source: source,
|
|
33
|
+
line: line,
|
|
34
|
+
comment: original_comment)
|
|
34
35
|
super message
|
|
35
36
|
end
|
|
36
37
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'base_error'
|
|
4
|
+
require_relative '../documentation_link'
|
|
4
5
|
|
|
5
6
|
module Reek
|
|
6
7
|
module Errors
|
|
@@ -8,28 +9,28 @@ module Reek
|
|
|
8
9
|
# This might happen for multiple reasons. The users might have a typo in
|
|
9
10
|
# his comment or he might use a detector that does not exist anymore.
|
|
10
11
|
class BadDetectorInCommentError < BaseError
|
|
11
|
-
UNKNOWN_SMELL_DETECTOR_MESSAGE = <<-
|
|
12
|
+
UNKNOWN_SMELL_DETECTOR_MESSAGE = <<-MESSAGE
|
|
12
13
|
|
|
13
|
-
Error: You are trying to configure an unknown smell detector '
|
|
14
|
+
Error: You are trying to configure an unknown smell detector '%<detector>s' in one
|
|
14
15
|
of your source code comments.
|
|
15
|
-
The source is '
|
|
16
|
+
The source is '%<source>s' and the comment belongs to the expression starting in line %<line>d.
|
|
16
17
|
Here's the original comment:
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
%<comment>s
|
|
19
20
|
|
|
20
21
|
Please see the Reek docs for:
|
|
21
|
-
* how to configure Reek via source code comments:
|
|
22
|
-
* what smell detectors are available:
|
|
22
|
+
* how to configure Reek via source code comments: #{DocumentationLink.build('Smell Suppression')}
|
|
23
|
+
* what smell detectors are available: #{DocumentationLink.build('Code Smells')}
|
|
23
24
|
Update the offensive comment (or remove it if no longer applicable) and re-run Reek.
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
MESSAGE
|
|
26
27
|
|
|
27
28
|
def initialize(detector_name:, source:, line:, original_comment:)
|
|
28
29
|
message = format(UNKNOWN_SMELL_DETECTOR_MESSAGE,
|
|
29
|
-
detector_name,
|
|
30
|
-
source,
|
|
31
|
-
line,
|
|
32
|
-
original_comment)
|
|
30
|
+
detector: detector_name,
|
|
31
|
+
source: source,
|
|
32
|
+
line: line,
|
|
33
|
+
comment: original_comment)
|
|
33
34
|
super message
|
|
34
35
|
end
|
|
35
36
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_error'
|
|
4
|
+
|
|
5
|
+
module Reek
|
|
6
|
+
module Errors
|
|
7
|
+
# Gets raised when Reek is unable to process the source due to an EncodingError
|
|
8
|
+
class EncodingError < BaseError
|
|
9
|
+
TEMPLATE = "Source '%<source>s' cannot be processed by Reek due to an encoding error in the source file."
|
|
10
|
+
|
|
11
|
+
LONG_TEMPLATE = <<-MESSAGE
|
|
12
|
+
!!!
|
|
13
|
+
%<message>s
|
|
14
|
+
|
|
15
|
+
This is a problem that is outside of Reek's scope and should be fixed by you, the
|
|
16
|
+
user, in order for Reek being able to continue.
|
|
17
|
+
Check out this article for an idea on how to get started:
|
|
18
|
+
https://www.justinweiss.com/articles/3-steps-to-fix-encoding-problems-in-ruby/
|
|
19
|
+
|
|
20
|
+
Exception message:
|
|
21
|
+
|
|
22
|
+
%<exception>s
|
|
23
|
+
|
|
24
|
+
Original backtrace:
|
|
25
|
+
|
|
26
|
+
%<original>s
|
|
27
|
+
|
|
28
|
+
!!!
|
|
29
|
+
MESSAGE
|
|
30
|
+
|
|
31
|
+
def initialize(origin:)
|
|
32
|
+
super format(TEMPLATE, source: origin)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def long_message
|
|
36
|
+
format(LONG_TEMPLATE,
|
|
37
|
+
message: message,
|
|
38
|
+
exception: cause.inspect,
|
|
39
|
+
original: cause.backtrace.join("\n\t"))
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -1,34 +1,35 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'base_error'
|
|
4
|
+
require_relative '../documentation_link'
|
|
4
5
|
|
|
5
6
|
module Reek
|
|
6
7
|
module Errors
|
|
7
8
|
# Gets raised when trying to use a configuration for a detector
|
|
8
9
|
# that can't be parsed into a hash.
|
|
9
10
|
class GarbageDetectorConfigurationInCommentError < BaseError
|
|
10
|
-
BAD_DETECTOR_CONFIGURATION_MESSAGE = <<-
|
|
11
|
+
BAD_DETECTOR_CONFIGURATION_MESSAGE = <<-MESSAGE
|
|
11
12
|
|
|
12
|
-
Error: You are trying to configure the smell detector '
|
|
13
|
-
Unfortunately we
|
|
14
|
-
The source is '
|
|
13
|
+
Error: You are trying to configure the smell detector '%<detector>s'.
|
|
14
|
+
Unfortunately we cannot parse the configuration you have given.
|
|
15
|
+
The source is '%<source>s' and the comment belongs to the expression starting in line %<line>d.
|
|
15
16
|
Here's the original comment:
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
%<comment>s
|
|
18
19
|
|
|
19
20
|
Please see the Reek docs for:
|
|
20
|
-
* how to configure Reek via source code comments:
|
|
21
|
-
* what smell detectors are available:
|
|
21
|
+
* how to configure Reek via source code comments: #{DocumentationLink.build('Smell Suppression')}
|
|
22
|
+
* what smell detectors are available: #{DocumentationLink.build('Code Smells')}
|
|
22
23
|
Update the offensive comment (or remove it if no longer applicable) and re-run Reek.
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
MESSAGE
|
|
25
26
|
|
|
26
27
|
def initialize(detector_name:, source:, line:, original_comment:)
|
|
27
28
|
message = format(BAD_DETECTOR_CONFIGURATION_MESSAGE,
|
|
28
|
-
detector_name,
|
|
29
|
-
source,
|
|
30
|
-
line,
|
|
31
|
-
original_comment)
|
|
29
|
+
detector: detector_name,
|
|
30
|
+
source: source,
|
|
31
|
+
line: line,
|
|
32
|
+
comment: original_comment)
|
|
32
33
|
super message
|
|
33
34
|
end
|
|
34
35
|
end
|
|
@@ -6,42 +6,40 @@ module Reek
|
|
|
6
6
|
module Errors
|
|
7
7
|
# Gets raised when Reek is unable to process the source
|
|
8
8
|
class IncomprehensibleSourceError < BaseError
|
|
9
|
-
|
|
10
|
-
!!!
|
|
11
|
-
Source %s can not be processed by Reek.
|
|
9
|
+
TEMPLATE = 'Source %<source>s cannot be processed by Reek.'
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
LONG_TEMPLATE = <<-MESSAGE
|
|
12
|
+
!!!
|
|
13
|
+
%<message>s
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
below into account - you might have misspelled a smell detector for instance.
|
|
18
|
-
(In the future Reek will handle configuration errors more gracefully, something
|
|
19
|
-
we are working on already).
|
|
15
|
+
This is most likely a Reek bug.
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
team by opening up a corresponding issue at https://github.com/troessner/reek/issues.
|
|
17
|
+
It would be great if you could report this back to the Reek team by opening a
|
|
18
|
+
corresponding issue at https://github.com/troessner/reek/issues.
|
|
24
19
|
|
|
25
|
-
Please make sure to include the source in question, the Reek version
|
|
26
|
-
|
|
20
|
+
Please make sure to include the source in question, the Reek version and the
|
|
21
|
+
original exception below.
|
|
27
22
|
|
|
28
23
|
Exception message:
|
|
29
24
|
|
|
30
|
-
|
|
25
|
+
%<exception>s
|
|
31
26
|
|
|
32
27
|
Original exception:
|
|
33
28
|
|
|
34
|
-
|
|
29
|
+
%<original>s
|
|
35
30
|
|
|
36
31
|
!!!
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def initialize(origin
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
MESSAGE
|
|
33
|
+
|
|
34
|
+
def initialize(origin:)
|
|
35
|
+
super format(TEMPLATE, source: origin)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def long_message
|
|
39
|
+
format(LONG_TEMPLATE,
|
|
40
|
+
message: message,
|
|
41
|
+
exception: cause.inspect,
|
|
42
|
+
original: cause.backtrace.join("\n\t"))
|
|
45
43
|
end
|
|
46
44
|
end
|
|
47
45
|
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_error'
|
|
4
|
+
|
|
5
|
+
module Reek
|
|
6
|
+
module Errors
|
|
7
|
+
# Gets raised when Reek is unable to process the source due to a SyntaxError
|
|
8
|
+
class SyntaxError < BaseError
|
|
9
|
+
TEMPLATE = "Source '%<source>s' cannot be processed by Reek due to a syntax error in the source file."
|
|
10
|
+
|
|
11
|
+
LONG_TEMPLATE = <<-MESSAGE
|
|
12
|
+
!!!
|
|
13
|
+
%<message>s
|
|
14
|
+
|
|
15
|
+
This is a problem that is outside of Reek's scope and should be fixed by you, the
|
|
16
|
+
user, in order for Reek being able to continue.
|
|
17
|
+
|
|
18
|
+
Exception message:
|
|
19
|
+
|
|
20
|
+
%<exception>s
|
|
21
|
+
|
|
22
|
+
Original backtrace:
|
|
23
|
+
|
|
24
|
+
%<original>s
|
|
25
|
+
|
|
26
|
+
!!!
|
|
27
|
+
MESSAGE
|
|
28
|
+
|
|
29
|
+
def initialize(origin:)
|
|
30
|
+
super format(TEMPLATE, source: origin)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def long_message
|
|
34
|
+
format(LONG_TEMPLATE,
|
|
35
|
+
message: message,
|
|
36
|
+
exception: cause.inspect,
|
|
37
|
+
original: cause.backtrace.join("\n\t"))
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|