From 30e3816ed1a1fb11e1c381ce9b1b4e3254912fd2 Mon Sep 17 00:00:00 2001 From: Sijawusz Pur Rahnama Date: Fri, 17 Nov 2023 18:36:19 +0100 Subject: [PATCH] Do not report expanded arguments in `ShadowingOuterLocalVar` rule --- .../lint/shadowing_outer_local_var_spec.cr | 24 +++++++++++++++++++ .../rule/lint/shadowing_outer_local_var.cr | 11 +++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/spec/ameba/rule/lint/shadowing_outer_local_var_spec.cr b/spec/ameba/rule/lint/shadowing_outer_local_var_spec.cr index f7315608..be734f7a 100644 --- a/spec/ameba/rule/lint/shadowing_outer_local_var_spec.cr +++ b/spec/ameba/rule/lint/shadowing_outer_local_var_spec.cr @@ -31,6 +31,30 @@ module Ameba::Rule::Lint CRYSTAL end + pending "reports if there is a shadowing in an unpacked variable in a block" do + expect_issue subject, <<-CRYSTAL + def some_method + foo = 1 + + [{3}].each do |(foo)| + # ^ error: Shadowing outer local variable `foo` + end + end + CRYSTAL + end + + pending "reports if there is a shadowing in an unpacked variable in a block (2)" do + expect_issue subject, <<-CRYSTAL + def some_method + foo = 1 + + [{[3]}].each do |((foo))| + # ^ error: Shadowing outer local variable `foo` + end + end + CRYSTAL + end + it "does not report outer vars declared below shadowed block" do expect_no_issues subject, <<-CRYSTAL methods = klass.methods.select { |m| m.annotation(MyAnn) } diff --git a/src/ameba/rule/lint/shadowing_outer_local_var.cr b/src/ameba/rule/lint/shadowing_outer_local_var.cr index 9a1f8c84..1ac1c239 100644 --- a/src/ameba/rule/lint/shadowing_outer_local_var.cr +++ b/src/ameba/rule/lint/shadowing_outer_local_var.cr @@ -53,13 +53,16 @@ module Ameba::Rule::Lint return unless outer_scope = scope.outer_scope scope.arguments.reject(&.ignored?).each do |arg| - variable = outer_scope.find_variable(arg.name) + # TODO: handle unpacked variables from `Block#unpacks` + next unless name = arg.name.presence + + variable = outer_scope.find_variable(name) next if variable.nil? || !variable.declared_before?(arg) - next if outer_scope.assigns_ivar?(arg.name) - next if outer_scope.assigns_type_dec?(arg.name) + next if outer_scope.assigns_ivar?(name) + next if outer_scope.assigns_type_dec?(name) - issue_for arg.node, MSG % arg.name + issue_for arg.node, MSG % name end end end