mirror of
https://gitea.invidious.io/iv-org/shard-ameba.git
synced 2024-08-15 00:53:29 +00:00
parent
fde321f7e6
commit
6b56c87e78
5 changed files with 55 additions and 1 deletions
|
@ -151,6 +151,16 @@ module Ameba::Rule::Lint
|
||||||
subject.catch(source).should be_valid
|
subject.catch(source).should be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "does not report if argument shadows an ivar assignment" do
|
||||||
|
s = Source.new %(
|
||||||
|
def bar(@foo)
|
||||||
|
@foo.try do |foo|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
subject.catch(s).should be_valid
|
||||||
|
end
|
||||||
|
|
||||||
it "reports rule, location and message" do
|
it "reports rule, location and message" do
|
||||||
source = Source.new %(
|
source = Source.new %(
|
||||||
foo = 1
|
foo = 1
|
||||||
|
|
|
@ -10,6 +10,9 @@ module Ameba::AST
|
||||||
# Link to the arguments in current scope
|
# Link to the arguments in current scope
|
||||||
getter arguments = [] of Argument
|
getter arguments = [] of Argument
|
||||||
|
|
||||||
|
# Link to the instance variables used in current scope
|
||||||
|
getter ivariables = [] of InstanceVariable
|
||||||
|
|
||||||
# Link to the outer scope
|
# Link to the outer scope
|
||||||
getter outer_scope : Scope?
|
getter outer_scope : Scope?
|
||||||
|
|
||||||
|
@ -44,11 +47,27 @@ module Ameba::AST
|
||||||
variables << Variable.new(node, self)
|
variables << Variable.new(node, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Creates a new argument in the current scope.
|
||||||
|
#
|
||||||
|
# ```
|
||||||
|
# scope = Scope.new(class_node, nil)
|
||||||
|
# scope.add_argument(arg_node)
|
||||||
|
# ```
|
||||||
def add_argument(node)
|
def add_argument(node)
|
||||||
add_variable Crystal::Var.new(node.name).at(node)
|
add_variable Crystal::Var.new(node.name).at(node)
|
||||||
arguments << Argument.new(node, variables.last)
|
arguments << Argument.new(node, variables.last)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Adds a new instance variable to the current scope.
|
||||||
|
#
|
||||||
|
# ```
|
||||||
|
# scope = Scope.new(class_node, nil)
|
||||||
|
# scope.add_ivariable(ivar_node)
|
||||||
|
# ```
|
||||||
|
def add_ivariable(node)
|
||||||
|
ivariables << InstanceVariable.new(node)
|
||||||
|
end
|
||||||
|
|
||||||
# Returns variable by its name or nil if it does not exist.
|
# Returns variable by its name or nil if it does not exist.
|
||||||
#
|
#
|
||||||
# ```
|
# ```
|
||||||
|
@ -75,6 +94,12 @@ module Ameba::AST
|
||||||
node.is_a?(Crystal::Block) || node.is_a?(Crystal::ProcLiteral)
|
node.is_a?(Crystal::Block) || node.is_a?(Crystal::ProcLiteral)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns true instance variable assinged in this scope.
|
||||||
|
def assigns_ivar?(name)
|
||||||
|
arguments.find { |arg| arg.name == name } &&
|
||||||
|
ivariables.find { |var| var.name == "@#{name}" }
|
||||||
|
end
|
||||||
|
|
||||||
# Returns true if and only if current scope represents some
|
# Returns true if and only if current scope represents some
|
||||||
# type definition, for example a class.
|
# type definition, for example a class.
|
||||||
def type_definition?
|
def type_definition?
|
||||||
|
|
13
src/ameba/ast/variabling/ivariable.cr
Normal file
13
src/ameba/ast/variabling/ivariable.cr
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
module Ameba::AST
|
||||||
|
class InstanceVariable
|
||||||
|
getter node : Crystal::InstanceVar
|
||||||
|
|
||||||
|
delegate location, to: @node
|
||||||
|
delegate end_location, to: @node
|
||||||
|
delegate name, to: @node
|
||||||
|
delegate to_s, to: @node
|
||||||
|
|
||||||
|
def initialize(@node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -135,6 +135,11 @@ module Ameba::AST
|
||||||
@current_scope.add_argument node
|
@current_scope.add_argument node
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :nodoc:
|
||||||
|
def visit(node : Crystal::InstanceVar)
|
||||||
|
@current_scope.add_ivariable(node)
|
||||||
|
end
|
||||||
|
|
||||||
# :nodoc:
|
# :nodoc:
|
||||||
def visit(node : Crystal::Var)
|
def visit(node : Crystal::Var)
|
||||||
variable = @current_scope.find_variable node.name
|
variable = @current_scope.find_variable node.name
|
||||||
|
|
|
@ -54,7 +54,8 @@ module Ameba::Rule::Lint
|
||||||
private def find_shadowing(source, scope)
|
private def find_shadowing(source, scope)
|
||||||
scope.arguments.each do |arg|
|
scope.arguments.each do |arg|
|
||||||
next if arg.ignored?
|
next if arg.ignored?
|
||||||
if scope.outer_scope.try &.find_variable(arg.name)
|
outer_scope = scope.outer_scope
|
||||||
|
if outer_scope && outer_scope.find_variable(arg.name) && !outer_scope.assigns_ivar?(arg.name)
|
||||||
issue_for arg.node, MSG % arg.name
|
issue_for arg.node, MSG % arg.name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue