reek 4.6.0 → 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 +79 -26
- data/.simplecov +1 -0
- data/.travis.yml +3 -9
- data/.yardopts +1 -1
- data/CHANGELOG.md +76 -0
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +5 -5
- data/README.md +138 -107
- data/Rakefile +16 -3
- data/bin/code_climate_reek +1 -0
- data/bin/reek +2 -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 +31 -5
- 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/codeclimate.feature +59 -0
- 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 +14 -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/ast_node_class_map.rb +1 -0
- data/lib/reek/ast/builder.rb +16 -0
- data/lib/reek/ast/node.rb +50 -58
- data/lib/reek/ast/object_refs.rb +2 -1
- data/lib/reek/ast/reference_collector.rb +3 -4
- data/lib/reek/ast/sexp_extensions/arguments.rb +1 -0
- data/lib/reek/ast/sexp_extensions/attribute_assignments.rb +1 -0
- data/lib/reek/ast/sexp_extensions/begin.rb +17 -0
- data/lib/reek/ast/sexp_extensions/block.rb +1 -0
- data/lib/reek/ast/sexp_extensions/case.rb +2 -1
- data/lib/reek/ast/sexp_extensions/constant.rb +1 -0
- data/lib/reek/ast/sexp_extensions/if.rb +9 -1
- data/lib/reek/ast/sexp_extensions/lambda.rb +1 -0
- data/lib/reek/ast/sexp_extensions/literal.rb +1 -0
- data/lib/reek/ast/sexp_extensions/logical_operators.rb +2 -1
- data/lib/reek/ast/sexp_extensions/methods.rb +5 -6
- data/lib/reek/ast/sexp_extensions/module.rb +55 -8
- data/lib/reek/ast/sexp_extensions/nested_assignables.rb +1 -0
- data/lib/reek/ast/sexp_extensions/self.rb +1 -0
- data/lib/reek/ast/sexp_extensions/send.rb +1 -4
- data/lib/reek/ast/sexp_extensions/super.rb +1 -0
- data/lib/reek/ast/sexp_extensions/symbols.rb +1 -0
- data/lib/reek/ast/sexp_extensions/variables.rb +1 -0
- data/lib/reek/ast/sexp_extensions/when.rb +1 -0
- data/lib/reek/ast/sexp_extensions/yield.rb +1 -0
- data/lib/reek/ast/sexp_extensions.rb +2 -0
- data/lib/reek/cli/application.rb +5 -3
- data/lib/reek/cli/command/base_command.rb +1 -0
- data/lib/reek/cli/command/report_command.rb +2 -2
- data/lib/reek/cli/command/todo_list_command.rb +9 -8
- data/lib/reek/cli/options.rb +32 -16
- data/lib/reek/cli/silencer.rb +15 -3
- data/lib/reek/cli/status.rb +1 -0
- data/lib/reek/code_comment.rb +14 -16
- data/lib/reek/configuration/app_configuration.rb +34 -28
- data/lib/reek/configuration/configuration_converter.rb +110 -0
- data/lib/reek/configuration/configuration_file_finder.rb +17 -41
- data/lib/reek/configuration/configuration_validator.rb +13 -23
- data/lib/reek/configuration/default_directive.rb +18 -3
- data/lib/reek/configuration/directory_directives.rb +18 -11
- data/lib/reek/configuration/excluded_paths.rb +2 -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 +4 -3
- data/lib/reek/context/class_context.rb +1 -0
- data/lib/reek/context/code_context.rb +49 -44
- data/lib/reek/context/ghost_context.rb +1 -2
- data/lib/reek/context/method_context.rb +26 -18
- data/lib/reek/context/module_context.rb +11 -11
- data/lib/reek/context/root_context.rb +1 -4
- data/lib/reek/context/send_context.rb +3 -2
- data/lib/reek/context/singleton_attribute_context.rb +1 -0
- data/lib/reek/context/singleton_method_context.rb +1 -0
- data/lib/reek/context/statement_counter.rb +1 -0
- data/lib/reek/context/visibility_tracker.rb +1 -0
- data/lib/reek/context_builder.rb +44 -44
- data/lib/reek/detector_repository.rb +12 -11
- data/lib/reek/documentation_link.rb +28 -0
- data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +15 -13
- data/lib/reek/errors/bad_detector_in_comment_error.rb +13 -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 +14 -12
- data/lib/reek/errors/incomprehensible_source_error.rb +23 -24
- data/lib/reek/errors/syntax_error.rb +41 -0
- data/lib/reek/examiner.rb +24 -22
- data/lib/reek/logging_error_handler.rb +8 -5
- data/lib/reek/rake/task.rb +8 -5
- data/lib/reek/report/base_report.rb +9 -12
- data/lib/reek/report/code_climate/code_climate_configuration.rb +2 -1
- data/lib/reek/report/code_climate/code_climate_configuration.yml +6 -6
- data/lib/reek/report/code_climate/code_climate_fingerprint.rb +1 -0
- data/lib/reek/report/code_climate/code_climate_formatter.rb +1 -0
- data/lib/reek/report/code_climate/code_climate_report.rb +1 -0
- data/lib/reek/report/code_climate.rb +1 -0
- data/lib/reek/report/documentation_link_warning_formatter.rb +17 -0
- data/lib/reek/report/heading_formatter.rb +54 -0
- data/lib/reek/report/html_report.rb +1 -0
- data/lib/reek/report/json_report.rb +2 -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 +2 -2
- data/lib/reek/report/xml_report.rb +4 -3
- data/lib/reek/report/yaml_report.rb +2 -1
- data/lib/reek/report.rb +16 -10
- data/lib/reek/smell_configuration.rb +3 -2
- data/lib/reek/smell_detectors/attribute.rb +6 -11
- data/lib/reek/smell_detectors/base_detector.rb +31 -26
- data/lib/reek/smell_detectors/boolean_parameter.rb +4 -5
- data/lib/reek/smell_detectors/class_variable.rb +6 -14
- data/lib/reek/smell_detectors/control_parameter.rb +19 -33
- data/lib/reek/smell_detectors/data_clump.rb +16 -9
- data/lib/reek/smell_detectors/duplicate_method_call.rb +24 -17
- data/lib/reek/smell_detectors/feature_envy.rb +10 -7
- data/lib/reek/smell_detectors/instance_variable_assumption.rb +15 -23
- data/lib/reek/smell_detectors/irresponsible_module.rb +6 -12
- data/lib/reek/smell_detectors/long_parameter_list.rb +11 -7
- data/lib/reek/smell_detectors/long_yield_list.rb +11 -7
- data/lib/reek/smell_detectors/manual_dispatch.rb +5 -5
- data/lib/reek/smell_detectors/{prima_donna_method.rb → missing_safe_method.rb} +21 -20
- data/lib/reek/smell_detectors/module_initialize.rb +4 -5
- data/lib/reek/smell_detectors/nested_iterators.rb +17 -24
- data/lib/reek/smell_detectors/nil_check.rb +9 -15
- data/lib/reek/smell_detectors/repeated_conditional.rb +14 -11
- data/lib/reek/smell_detectors/subclassed_from_core_class.rb +8 -8
- data/lib/reek/smell_detectors/too_many_constants.rb +11 -9
- data/lib/reek/smell_detectors/too_many_instance_variables.rb +11 -6
- data/lib/reek/smell_detectors/too_many_methods.rb +12 -7
- data/lib/reek/smell_detectors/too_many_statements.rb +11 -6
- data/lib/reek/smell_detectors/uncommunicative_method_name.rb +11 -11
- data/lib/reek/smell_detectors/uncommunicative_module_name.rb +15 -18
- data/lib/reek/smell_detectors/uncommunicative_parameter_name.rb +18 -22
- data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +27 -27
- data/lib/reek/smell_detectors/unused_parameters.rb +5 -6
- data/lib/reek/smell_detectors/unused_private_method.rb +14 -20
- data/lib/reek/smell_detectors/utility_function.rb +13 -16
- data/lib/reek/smell_detectors.rb +2 -1
- data/lib/reek/smell_warning.rb +16 -8
- data/lib/reek/source/source_code.rb +65 -46
- data/lib/reek/source/source_locator.rb +9 -8
- data/lib/reek/spec/should_reek.rb +3 -2
- data/lib/reek/spec/should_reek_of.rb +13 -26
- data/lib/reek/spec/should_reek_only_of.rb +5 -4
- data/lib/reek/spec/smell_matcher.rb +2 -1
- data/lib/reek/spec.rb +7 -6
- data/lib/reek/tree_dresser.rb +9 -8
- data/lib/reek/version.rb +2 -1
- data/lib/reek.rb +1 -0
- data/reek.gemspec +5 -6
- 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 +15 -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/statement_counter_spec.rb +1 -0
- 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 +137 -29
- data/spec/reek/rake/task_spec.rb +25 -2
- data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +82 -78
- data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +6 -6
- data/spec/reek/report/code_climate/code_climate_report_spec.rb +22 -22
- 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 +17 -46
- 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 +59 -21
- 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 +27 -38
- data/spec/reek/source/source_locator_spec.rb +42 -12
- data/spec/reek/spec/should_reek_of_spec.rb +25 -30
- 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 +7 -17
- data/tasks/configuration.rake +8 -5
- metadata +77 -40
- data/defaults.reek +0 -128
- data/features/configuration_files/warn_about_multiple_configuration_files.feature +0 -44
- data/lib/reek/errors/parse_error.rb +0 -19
- data/lib/reek/report/formatter/heading_formatter.rb +0 -51
- data/lib/reek/report/formatter/location_formatter.rb +0 -41
- data/lib/reek/report/formatter/progress_formatter.rb +0 -80
- data/lib/reek/report/formatter/simple_warning_formatter.rb +0 -35
- data/lib/reek/report/formatter/wiki_link_warning_formatter.rb +0 -35
- data/lib/reek/report/formatter.rb +0 -32
- 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/{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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative '../code_comment'
|
|
3
4
|
require_relative '../ast/object_refs'
|
|
4
5
|
require_relative 'statement_counter'
|
|
@@ -13,51 +14,19 @@ module Reek
|
|
|
13
14
|
# code element. CodeContexts form a tree in the same way the code does,
|
|
14
15
|
# with each context holding a reference to a unique outer context.
|
|
15
16
|
#
|
|
16
|
-
# :reek:TooManyMethods
|
|
17
|
-
# :reek:TooManyInstanceVariables
|
|
17
|
+
# @quality :reek:TooManyMethods { max_methods: 19 }
|
|
18
|
+
# @quality :reek:TooManyInstanceVariables { max_instance_variables: 8 }
|
|
18
19
|
class CodeContext
|
|
19
20
|
include Enumerable
|
|
20
21
|
extend Forwardable
|
|
21
|
-
delegate
|
|
22
|
-
delegate %i(name type) => :exp
|
|
22
|
+
delegate [:name, :type] => :exp
|
|
23
23
|
|
|
24
24
|
attr_reader :children, :parent, :exp, :statement_counter
|
|
25
25
|
|
|
26
26
|
# Initializes a new CodeContext.
|
|
27
27
|
#
|
|
28
|
-
# @param _parent [CodeContext, nil] The parent context
|
|
29
28
|
# @param exp [Reek::AST::Node] The code described by this context
|
|
30
|
-
|
|
31
|
-
# For example, given the following code:
|
|
32
|
-
#
|
|
33
|
-
# class Omg
|
|
34
|
-
# def foo(x)
|
|
35
|
-
# puts x
|
|
36
|
-
# end
|
|
37
|
-
# end
|
|
38
|
-
#
|
|
39
|
-
# The {ContextBuilder} object first instantiates a {RootContext}, which has no parent.
|
|
40
|
-
#
|
|
41
|
-
# Next, it instantiates a {ModuleContext}, with +parent+ being the
|
|
42
|
-
# {RootContext} just created, and +exp+ looking like this:
|
|
43
|
-
#
|
|
44
|
-
# (class
|
|
45
|
-
# (const nil :Omg) nil
|
|
46
|
-
# (def :foo
|
|
47
|
-
# (args
|
|
48
|
-
# (arg :x))
|
|
49
|
-
# (send nil :puts
|
|
50
|
-
# (lvar :x))))
|
|
51
|
-
#
|
|
52
|
-
# Finally, {ContextBuilder} will instantiate a {MethodContext}. This time,
|
|
53
|
-
# +parent+ is the {ModuleContext} created above, and +exp+ is:
|
|
54
|
-
#
|
|
55
|
-
# (def :foo
|
|
56
|
-
# (args
|
|
57
|
-
# (arg :x))
|
|
58
|
-
# (send nil :puts
|
|
59
|
-
# (lvar :x)))
|
|
60
|
-
def initialize(_parent, exp)
|
|
29
|
+
def initialize(exp)
|
|
61
30
|
@exp = exp
|
|
62
31
|
@children = []
|
|
63
32
|
@statement_counter = StatementCounter.new
|
|
@@ -70,12 +39,12 @@ module Reek
|
|
|
70
39
|
# @yield block that is executed for every node.
|
|
71
40
|
#
|
|
72
41
|
def local_nodes(type, ignored = [], &blk)
|
|
73
|
-
ignored
|
|
74
|
-
each_node(type, ignored, &blk)
|
|
42
|
+
ignored |= [:class, :module]
|
|
43
|
+
exp.each_node(type, ignored, &blk)
|
|
75
44
|
end
|
|
76
45
|
|
|
77
46
|
# Iterate over `self` and child contexts.
|
|
78
|
-
# The main difference (among others) to `
|
|
47
|
+
# The main difference (among others) to `local_nodes` is that we are traversing
|
|
79
48
|
# `CodeContexts` here, not AST nodes (see `Reek::AST::Node`).
|
|
80
49
|
#
|
|
81
50
|
# @yield block that is executed for every node.
|
|
@@ -90,6 +59,44 @@ module Reek
|
|
|
90
59
|
end
|
|
91
60
|
end
|
|
92
61
|
|
|
62
|
+
# Link the present context to its parent.
|
|
63
|
+
#
|
|
64
|
+
# @param parent [Reek::AST::Node] The parent context of the code described by this context
|
|
65
|
+
#
|
|
66
|
+
# For example, given the following code:
|
|
67
|
+
#
|
|
68
|
+
# class Omg
|
|
69
|
+
# def foo(x)
|
|
70
|
+
# puts x
|
|
71
|
+
# end
|
|
72
|
+
# end
|
|
73
|
+
#
|
|
74
|
+
# The {ContextBuilder} object first instantiates a {RootContext}, which has no parent.
|
|
75
|
+
#
|
|
76
|
+
# Next, it instantiates a {ModuleContext}, with +exp+ looking like this:
|
|
77
|
+
#
|
|
78
|
+
# (class
|
|
79
|
+
# (const nil :Omg) nil
|
|
80
|
+
# (def :foo
|
|
81
|
+
# (args
|
|
82
|
+
# (arg :x))
|
|
83
|
+
# (send nil :puts
|
|
84
|
+
# (lvar :x))))
|
|
85
|
+
#
|
|
86
|
+
# It will then call #register_with_parent on the {ModuleContext}, passing
|
|
87
|
+
# in the parent {RootContext}.
|
|
88
|
+
#
|
|
89
|
+
# Finally, {ContextBuilder} will instantiate a {MethodContext}. This time,
|
|
90
|
+
# +exp+ is:
|
|
91
|
+
#
|
|
92
|
+
# (def :foo
|
|
93
|
+
# (args
|
|
94
|
+
# (arg :x))
|
|
95
|
+
# (send nil :puts
|
|
96
|
+
# (lvar :x)))
|
|
97
|
+
#
|
|
98
|
+
# Then it will call #register_with_parent on the {MethodContext}, passing
|
|
99
|
+
# in the parent {ModuleContext}.
|
|
93
100
|
def register_with_parent(parent)
|
|
94
101
|
@parent = parent.append_child_context(self) if parent
|
|
95
102
|
end
|
|
@@ -103,17 +110,15 @@ module Reek
|
|
|
103
110
|
self
|
|
104
111
|
end
|
|
105
112
|
|
|
106
|
-
# :reek:TooManyStatements
|
|
107
|
-
# :reek:FeatureEnvy
|
|
113
|
+
# @quality :reek:TooManyStatements { max_statements: 6 }
|
|
114
|
+
# @quality :reek:FeatureEnvy
|
|
108
115
|
def record_call_to(exp)
|
|
109
116
|
receiver = exp.receiver
|
|
110
117
|
type = receiver ? receiver.type : :self
|
|
111
118
|
line = exp.line
|
|
112
119
|
case type
|
|
113
120
|
when :lvar, :lvasgn
|
|
114
|
-
unless exp.object_creation_call?
|
|
115
|
-
refs.record_reference(name: receiver.name, line: line)
|
|
116
|
-
end
|
|
121
|
+
refs.record_reference(name: receiver.name, line: line) unless exp.object_creation_call?
|
|
117
122
|
when :self
|
|
118
123
|
refs.record_reference(name: :self, line: line)
|
|
119
124
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'code_context'
|
|
3
4
|
require_relative 'singleton_method_context'
|
|
4
5
|
|
|
@@ -40,8 +41,6 @@ module Reek
|
|
|
40
41
|
names: names
|
|
41
42
|
end
|
|
42
43
|
|
|
43
|
-
def track_singleton_visibility(_visibility, _names); end
|
|
44
|
-
|
|
45
44
|
def record_use_of_self
|
|
46
45
|
parent.record_use_of_self
|
|
47
46
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'code_context'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -6,14 +7,15 @@ module Reek
|
|
|
6
7
|
#
|
|
7
8
|
# A context wrapper for any method definition found in a syntax tree.
|
|
8
9
|
#
|
|
9
|
-
# :reek:Attribute
|
|
10
|
+
# @quality :reek:Attribute
|
|
10
11
|
class MethodContext < CodeContext
|
|
11
12
|
attr_accessor :visibility
|
|
12
13
|
attr_reader :refs
|
|
13
14
|
|
|
14
|
-
def initialize(
|
|
15
|
+
def initialize(exp, parent_exp)
|
|
16
|
+
@parent_exp = parent_exp
|
|
15
17
|
@visibility = :public
|
|
16
|
-
super
|
|
18
|
+
super exp
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def references_self?
|
|
@@ -21,29 +23,24 @@ module Reek
|
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def uses_param?(param)
|
|
24
|
-
#
|
|
26
|
+
# :lvasgn catches:
|
|
27
|
+
#
|
|
25
28
|
# def foo(bar); bar += 1; end
|
|
26
|
-
# In this example there is no `lvar` node present.
|
|
27
29
|
#
|
|
28
|
-
#
|
|
30
|
+
# :lvar catches:
|
|
31
|
+
#
|
|
29
32
|
# def foo(bar); other(bar); end
|
|
30
33
|
# def foo(bar); tmp = other(bar); tmp[0]; end
|
|
31
34
|
#
|
|
32
|
-
|
|
33
|
-
# This means that if we would just search for [:lvar, :lvasgn]
|
|
34
|
-
# (e.g. via Reek::AST::Node#find_nodes) this would fail for this example since we would
|
|
35
|
-
# stop at the `lvasgn` and not detect the contained `lvar`.
|
|
36
|
-
# Hence we first get all `lvar` nodes followed by all `lvasgn` nodes.
|
|
37
|
-
#
|
|
38
|
-
(local_nodes(:lvar) + local_nodes(:lvasgn)).find { |node| node.var_name == param.to_sym }
|
|
35
|
+
local_nodes([:lvar, :lvasgn]).find { |node| node.var_name == param.name }
|
|
39
36
|
end
|
|
40
37
|
|
|
41
|
-
# :reek:FeatureEnvy
|
|
38
|
+
# @quality :reek:FeatureEnvy
|
|
42
39
|
def unused_params
|
|
43
|
-
exp.arguments.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
exp.arguments.reject do |param|
|
|
41
|
+
param.anonymous_splat? ||
|
|
42
|
+
param.marked_unused? ||
|
|
43
|
+
uses_param?(param)
|
|
47
44
|
end
|
|
48
45
|
end
|
|
49
46
|
|
|
@@ -79,6 +76,17 @@ module Reek
|
|
|
79
76
|
def non_public_visibility?
|
|
80
77
|
visibility != :public
|
|
81
78
|
end
|
|
79
|
+
|
|
80
|
+
def full_comment
|
|
81
|
+
own = super
|
|
82
|
+
return own unless own.empty?
|
|
83
|
+
return parent_exp.full_comment if parent_exp
|
|
84
|
+
''
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
attr_reader :parent_exp
|
|
82
90
|
end
|
|
83
91
|
end
|
|
84
92
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'code_context'
|
|
3
4
|
require_relative 'attribute_context'
|
|
4
5
|
require_relative 'method_context'
|
|
@@ -9,13 +10,11 @@ module Reek
|
|
|
9
10
|
#
|
|
10
11
|
# A context wrapper for any module found in a syntax tree.
|
|
11
12
|
#
|
|
12
|
-
# :reek:FeatureEnvy
|
|
13
13
|
class ModuleContext < CodeContext
|
|
14
14
|
attr_reader :visibility_tracker
|
|
15
15
|
|
|
16
|
-
def initialize(
|
|
16
|
+
def initialize(exp)
|
|
17
17
|
super
|
|
18
|
-
|
|
19
18
|
@visibility_tracker = VisibilityTracker.new
|
|
20
19
|
end
|
|
21
20
|
|
|
@@ -44,9 +43,9 @@ module Reek
|
|
|
44
43
|
AttributeContext
|
|
45
44
|
end
|
|
46
45
|
|
|
47
|
-
def defined_instance_methods(visibility: :
|
|
46
|
+
def defined_instance_methods(visibility: :any)
|
|
48
47
|
instance_method_children.select do |context|
|
|
49
|
-
context.visibility == visibility
|
|
48
|
+
visibility == :any || context.visibility == visibility
|
|
50
49
|
end
|
|
51
50
|
end
|
|
52
51
|
|
|
@@ -60,7 +59,7 @@ module Reek
|
|
|
60
59
|
# @deprecated use `defined_instance_methods` instead
|
|
61
60
|
#
|
|
62
61
|
def node_instance_methods
|
|
63
|
-
local_nodes(:def)
|
|
62
|
+
local_nodes(:def).to_a
|
|
64
63
|
end
|
|
65
64
|
|
|
66
65
|
def descriptively_commented?
|
|
@@ -73,24 +72,25 @@ module Reek
|
|
|
73
72
|
# However, if the module is empty, it is not considered a namespace module.
|
|
74
73
|
#
|
|
75
74
|
# @return true if the module is a namespace module
|
|
75
|
+
#
|
|
76
|
+
# @quality :reek:FeatureEnvy
|
|
76
77
|
def namespace_module?
|
|
77
78
|
return false if exp.type == :casgn
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
children = exp.direct_children
|
|
80
|
+
children.any? && children.all? { |child| [:casgn, :class, :module].include? child.type }
|
|
80
81
|
end
|
|
81
82
|
|
|
82
83
|
def track_visibility(visibility, names)
|
|
83
84
|
visibility_tracker.track_visibility children: instance_method_children,
|
|
84
85
|
visibility: visibility,
|
|
85
86
|
names: names
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def track_singleton_visibility(visibility, names)
|
|
89
87
|
visibility_tracker.track_singleton_visibility children: singleton_method_children,
|
|
90
88
|
visibility: visibility,
|
|
91
89
|
names: names
|
|
92
90
|
end
|
|
93
91
|
|
|
92
|
+
private
|
|
93
|
+
|
|
94
94
|
def instance_method_children
|
|
95
95
|
children.select(&:instance_method?)
|
|
96
96
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'code_context'
|
|
3
4
|
require_relative 'method_context'
|
|
4
5
|
|
|
@@ -8,10 +9,6 @@ module Reek
|
|
|
8
9
|
# A context wrapper representing the root of an abstract syntax tree.
|
|
9
10
|
#
|
|
10
11
|
class RootContext < CodeContext
|
|
11
|
-
def initialize(exp)
|
|
12
|
-
super(nil, exp)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
12
|
def type
|
|
16
13
|
:root
|
|
17
14
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'code_context'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -9,9 +10,9 @@ module Reek
|
|
|
9
10
|
class SendContext < CodeContext
|
|
10
11
|
attr_reader :name
|
|
11
12
|
|
|
12
|
-
def initialize(
|
|
13
|
+
def initialize(exp, name)
|
|
13
14
|
@name = name
|
|
14
|
-
super
|
|
15
|
+
super exp
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
18
|
end
|
data/lib/reek/context_builder.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'context/attribute_context'
|
|
3
4
|
require_relative 'context/class_context'
|
|
4
5
|
require_relative 'context/ghost_context'
|
|
@@ -19,8 +20,9 @@ module Reek
|
|
|
19
20
|
# counting. Ideally `ContextBuilder` would only build up the context tree and leave the
|
|
20
21
|
# statement and reference counting to the contexts.
|
|
21
22
|
#
|
|
22
|
-
# :reek:TooManyMethods
|
|
23
|
-
# :reek:UnusedPrivateMethod
|
|
23
|
+
# @quality :reek:TooManyMethods { max_methods: 31 }
|
|
24
|
+
# @quality :reek:UnusedPrivateMethod { exclude: [ !ruby/regexp /process_/ ] }
|
|
25
|
+
# @quality :reek:DataClump
|
|
24
26
|
class ContextBuilder
|
|
25
27
|
attr_reader :context_tree
|
|
26
28
|
|
|
@@ -57,10 +59,10 @@ module Reek
|
|
|
57
59
|
# RootContext -> children: 1 ModuleContext -> children: 1 MethodContext
|
|
58
60
|
#
|
|
59
61
|
# @return [Reek::Context::RootContext] tree of nested contexts
|
|
60
|
-
def build(exp)
|
|
62
|
+
def build(exp, parent_exp = nil)
|
|
61
63
|
context_processor = "process_#{exp.type}"
|
|
62
64
|
if context_processor_exists?(context_processor)
|
|
63
|
-
send(context_processor, exp)
|
|
65
|
+
send(context_processor, exp, parent_exp)
|
|
64
66
|
else
|
|
65
67
|
process exp
|
|
66
68
|
end
|
|
@@ -70,12 +72,12 @@ module Reek
|
|
|
70
72
|
# Handles every node for which we have no context_processor.
|
|
71
73
|
#
|
|
72
74
|
def process(exp)
|
|
73
|
-
exp.children.grep(AST::Node).each(
|
|
75
|
+
exp.children.grep(AST::Node).each { |child| build(child, exp) }
|
|
74
76
|
end
|
|
75
77
|
|
|
76
78
|
# Handles `module` and `class` nodes.
|
|
77
79
|
#
|
|
78
|
-
def process_module(exp)
|
|
80
|
+
def process_module(exp, _parent)
|
|
79
81
|
inside_new_context(Context::ModuleContext, exp) do
|
|
80
82
|
process(exp)
|
|
81
83
|
end
|
|
@@ -90,7 +92,7 @@ module Reek
|
|
|
90
92
|
# class << self
|
|
91
93
|
# end
|
|
92
94
|
#
|
|
93
|
-
def process_sclass(exp)
|
|
95
|
+
def process_sclass(exp, _parent)
|
|
94
96
|
inside_new_context(Context::GhostContext, exp) do
|
|
95
97
|
process(exp)
|
|
96
98
|
end
|
|
@@ -102,9 +104,9 @@ module Reek
|
|
|
102
104
|
#
|
|
103
105
|
# Foo = Class.new Bar
|
|
104
106
|
#
|
|
105
|
-
def process_casgn(exp)
|
|
107
|
+
def process_casgn(exp, parent)
|
|
106
108
|
if exp.defines_module?
|
|
107
|
-
process_module(exp)
|
|
109
|
+
process_module(exp, parent)
|
|
108
110
|
else
|
|
109
111
|
process(exp)
|
|
110
112
|
end
|
|
@@ -118,8 +120,8 @@ module Reek
|
|
|
118
120
|
#
|
|
119
121
|
# Given the above example we would count 2 statements overall.
|
|
120
122
|
#
|
|
121
|
-
def process_def(exp)
|
|
122
|
-
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
|
|
123
125
|
increase_statement_count_by(exp.body)
|
|
124
126
|
process(exp)
|
|
125
127
|
end
|
|
@@ -133,8 +135,8 @@ module Reek
|
|
|
133
135
|
#
|
|
134
136
|
# Given the above example we would count 2 statements overall.
|
|
135
137
|
#
|
|
136
|
-
def process_defs(exp)
|
|
137
|
-
inside_new_context(Context::SingletonMethodContext, exp) do
|
|
138
|
+
def process_defs(exp, parent)
|
|
139
|
+
inside_new_context(Context::SingletonMethodContext, exp, parent) do
|
|
138
140
|
increase_statement_count_by(exp.body)
|
|
139
141
|
process(exp)
|
|
140
142
|
end
|
|
@@ -150,14 +152,14 @@ module Reek
|
|
|
150
152
|
# we also record to what the method call is referring to
|
|
151
153
|
# which we later use for smell detectors like FeatureEnvy.
|
|
152
154
|
#
|
|
153
|
-
def process_send(exp)
|
|
155
|
+
def process_send(exp, _parent)
|
|
156
|
+
process(exp)
|
|
154
157
|
case current_context
|
|
155
158
|
when Context::ModuleContext
|
|
156
159
|
handle_send_for_modules exp
|
|
157
160
|
when Context::MethodContext
|
|
158
161
|
handle_send_for_methods exp
|
|
159
162
|
end
|
|
160
|
-
process(exp)
|
|
161
163
|
end
|
|
162
164
|
|
|
163
165
|
# Handles `op_asgn` nodes a.k.a. Ruby's assignment operators.
|
|
@@ -172,7 +174,7 @@ module Reek
|
|
|
172
174
|
#
|
|
173
175
|
# We record one reference to `x` given the example above.
|
|
174
176
|
#
|
|
175
|
-
def process_op_asgn(exp)
|
|
177
|
+
def process_op_asgn(exp, _parent)
|
|
176
178
|
current_context.record_call_to(exp)
|
|
177
179
|
process(exp)
|
|
178
180
|
end
|
|
@@ -191,7 +193,7 @@ module Reek
|
|
|
191
193
|
#
|
|
192
194
|
# We record one reference to `self`.
|
|
193
195
|
#
|
|
194
|
-
def process_ivar(exp)
|
|
196
|
+
def process_ivar(exp, _parent)
|
|
195
197
|
current_context.record_use_of_self
|
|
196
198
|
process(exp)
|
|
197
199
|
end
|
|
@@ -204,7 +206,7 @@ module Reek
|
|
|
204
206
|
#
|
|
205
207
|
# def self.foo; end
|
|
206
208
|
#
|
|
207
|
-
def process_self(
|
|
209
|
+
def process_self(_exp, _parent)
|
|
208
210
|
current_context.record_use_of_self
|
|
209
211
|
end
|
|
210
212
|
|
|
@@ -224,7 +226,7 @@ module Reek
|
|
|
224
226
|
#
|
|
225
227
|
# We record one reference to `self`.
|
|
226
228
|
#
|
|
227
|
-
def process_zsuper(
|
|
229
|
+
def process_zsuper(_exp, _parent)
|
|
228
230
|
current_context.record_use_of_self
|
|
229
231
|
end
|
|
230
232
|
|
|
@@ -248,7 +250,7 @@ module Reek
|
|
|
248
250
|
#
|
|
249
251
|
# We record one reference to `self`.
|
|
250
252
|
#
|
|
251
|
-
def process_super(exp)
|
|
253
|
+
def process_super(exp, _parent)
|
|
252
254
|
current_context.record_use_of_self
|
|
253
255
|
process(exp)
|
|
254
256
|
end
|
|
@@ -261,7 +263,7 @@ module Reek
|
|
|
261
263
|
#
|
|
262
264
|
# Counts non-empty blocks as one statement.
|
|
263
265
|
#
|
|
264
|
-
def process_block(exp)
|
|
266
|
+
def process_block(exp, _parent)
|
|
265
267
|
increase_statement_count_by(exp.block)
|
|
266
268
|
process(exp)
|
|
267
269
|
end
|
|
@@ -281,7 +283,7 @@ module Reek
|
|
|
281
283
|
# At the end we subtract one statement because the surrounding context was already counted
|
|
282
284
|
# as one (e.g. via `process_def`).
|
|
283
285
|
#
|
|
284
|
-
def process_begin(exp)
|
|
286
|
+
def process_begin(exp, _parent)
|
|
285
287
|
increase_statement_count_by(exp.children)
|
|
286
288
|
decrease_statement_count
|
|
287
289
|
process(exp)
|
|
@@ -307,7 +309,7 @@ module Reek
|
|
|
307
309
|
# `children[1]` refers to the `if` body (so `puts 'bingo'` from above) and
|
|
308
310
|
# `children[2]` to the `else` body (so `3` from above), which might be nil.
|
|
309
311
|
#
|
|
310
|
-
def process_if(exp)
|
|
312
|
+
def process_if(exp, _parent)
|
|
311
313
|
children = exp.children
|
|
312
314
|
increase_statement_count_by(children[1])
|
|
313
315
|
increase_statement_count_by(children[2])
|
|
@@ -330,7 +332,7 @@ module Reek
|
|
|
330
332
|
#
|
|
331
333
|
# `children[1]` below refers to the `while` body (so `puts 'bingo'` from above)
|
|
332
334
|
#
|
|
333
|
-
def process_while(exp)
|
|
335
|
+
def process_while(exp, _parent)
|
|
334
336
|
increase_statement_count_by(exp.children[1])
|
|
335
337
|
decrease_statement_count
|
|
336
338
|
process(exp)
|
|
@@ -353,7 +355,7 @@ module Reek
|
|
|
353
355
|
#
|
|
354
356
|
# `children[2]` below refers to the `while` body (so `puts i` from above)
|
|
355
357
|
#
|
|
356
|
-
def process_for(exp)
|
|
358
|
+
def process_for(exp, _parent)
|
|
357
359
|
increase_statement_count_by(exp.children[2])
|
|
358
360
|
decrease_statement_count
|
|
359
361
|
process(exp)
|
|
@@ -383,7 +385,7 @@ module Reek
|
|
|
383
385
|
# `exp` would be the whole method body wrapped under a `rescue` node.
|
|
384
386
|
# See `process_resbody` for additional reference.
|
|
385
387
|
#
|
|
386
|
-
def process_rescue(exp)
|
|
388
|
+
def process_rescue(exp, _parent)
|
|
387
389
|
increase_statement_count_by(exp.children.first)
|
|
388
390
|
decrease_statement_count
|
|
389
391
|
process(exp)
|
|
@@ -411,7 +413,7 @@ module Reek
|
|
|
411
413
|
# `exp` would be the whole `rescue` body.
|
|
412
414
|
# See `process_rescue` for additional reference.
|
|
413
415
|
#
|
|
414
|
-
def process_resbody(exp)
|
|
416
|
+
def process_resbody(exp, _parent)
|
|
415
417
|
increase_statement_count_by(exp.children[1..-1].compact)
|
|
416
418
|
process(exp)
|
|
417
419
|
end
|
|
@@ -433,7 +435,7 @@ module Reek
|
|
|
433
435
|
# At the end we subtract one statement because the surrounding context was already counted
|
|
434
436
|
# as one (e.g. via `process_def`).
|
|
435
437
|
#
|
|
436
|
-
def process_case(exp)
|
|
438
|
+
def process_case(exp, _parent)
|
|
437
439
|
increase_statement_count_by(exp.else_body)
|
|
438
440
|
decrease_statement_count
|
|
439
441
|
process(exp)
|
|
@@ -459,7 +461,7 @@ module Reek
|
|
|
459
461
|
#
|
|
460
462
|
# Counts the `when` body.
|
|
461
463
|
#
|
|
462
|
-
def process_when(exp)
|
|
464
|
+
def process_when(exp, _parent)
|
|
463
465
|
increase_statement_count_by(exp.body)
|
|
464
466
|
process(exp)
|
|
465
467
|
end
|
|
@@ -468,7 +470,7 @@ module Reek
|
|
|
468
470
|
self.class.private_method_defined?(name)
|
|
469
471
|
end
|
|
470
472
|
|
|
471
|
-
# :reek:ControlParameter
|
|
473
|
+
# @quality :reek:ControlParameter
|
|
472
474
|
def increase_statement_count_by(sexp)
|
|
473
475
|
current_context.statement_counter.increase_by sexp
|
|
474
476
|
end
|
|
@@ -480,37 +482,35 @@ module Reek
|
|
|
480
482
|
# Stores a reference to the current context, creates a nested new one,
|
|
481
483
|
# yields to the given block and then restores the previous context.
|
|
482
484
|
#
|
|
483
|
-
# @param klass [Context::*Context]
|
|
484
|
-
# @param
|
|
485
|
+
# @param klass [Context::*Context] context class
|
|
486
|
+
# @param args arguments for the class initializer
|
|
485
487
|
# @yield block
|
|
486
488
|
#
|
|
487
|
-
def inside_new_context(klass,
|
|
488
|
-
new_context = append_new_context(klass,
|
|
489
|
+
def inside_new_context(klass, *args)
|
|
490
|
+
new_context = append_new_context(klass, *args)
|
|
489
491
|
|
|
490
492
|
orig, self.current_context = current_context, new_context
|
|
491
493
|
yield
|
|
492
494
|
self.current_context = orig
|
|
493
495
|
end
|
|
494
496
|
|
|
495
|
-
#
|
|
496
|
-
# current context.
|
|
497
|
+
# Appends a new child context to the current context but does not change
|
|
498
|
+
# the current context.
|
|
497
499
|
#
|
|
498
|
-
# @param klass [Context::*Context]
|
|
499
|
-
# @param args
|
|
500
|
+
# @param klass [Context::*Context] context class
|
|
501
|
+
# @param args arguments for the class initializer
|
|
500
502
|
#
|
|
501
|
-
# @return [Context::*Context]
|
|
503
|
+
# @return [Context::*Context] the context that was appended
|
|
502
504
|
#
|
|
503
505
|
def append_new_context(klass, *args)
|
|
504
|
-
klass.new(
|
|
506
|
+
klass.new(*args).tap do |new_context|
|
|
505
507
|
new_context.register_with_parent(current_context)
|
|
506
508
|
end
|
|
507
509
|
end
|
|
508
510
|
|
|
509
511
|
def handle_send_for_modules(exp)
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
current_context.track_visibility(method_name, arg_names)
|
|
513
|
-
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)
|
|
514
514
|
register_attributes(exp)
|
|
515
515
|
end
|
|
516
516
|
|