mirror of
https://gitea.invidious.io/iv-org/shard-ameba.git
synced 2024-08-15 00:53:29 +00:00
Merge pull request #439 from crystal-ameba/fix-issue-353
Make `Lint/SharedVarInFiber` rule account for `loop { ... }`
This commit is contained in:
commit
c9bc01f88c
4 changed files with 89 additions and 2 deletions
|
@ -298,6 +298,34 @@ module Ameba::AST
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "Crystal::Call" do
|
||||||
|
context "loop" do
|
||||||
|
it "constructs a branch in block" do
|
||||||
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
|
def method(a)
|
||||||
|
loop do
|
||||||
|
b = (a = 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
CRYSTAL
|
||||||
|
branch.to_s.should eq "b = (a = 1)"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "other" do
|
||||||
|
it "skips constructing a branch in block" do
|
||||||
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
|
def method(a)
|
||||||
|
1.upto(10) do
|
||||||
|
b = (a = 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
CRYSTAL
|
||||||
|
branch.should be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "#initialize" do
|
describe "#initialize" do
|
||||||
it "creates new branch" do
|
it "creates new branch" do
|
||||||
nodes = as_nodes <<-CRYSTAL
|
nodes = as_nodes <<-CRYSTAL
|
||||||
|
@ -358,6 +386,30 @@ module Ameba::AST
|
||||||
branch = Branch.new nodes.assign_nodes.first, branchable
|
branch = Branch.new nodes.assign_nodes.first, branchable
|
||||||
branch.in_loop?.should be_false
|
branch.in_loop?.should be_false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "Crystal::Call" do
|
||||||
|
it "returns true if branch is in a loop" do
|
||||||
|
nodes = as_nodes <<-CRYSTAL
|
||||||
|
loop do
|
||||||
|
a = 1
|
||||||
|
end
|
||||||
|
CRYSTAL
|
||||||
|
branchable = Branchable.new nodes.call_nodes.first
|
||||||
|
branch = Branch.new nodes.assign_nodes.first, branchable
|
||||||
|
branch.in_loop?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if branch is not in a loop" do
|
||||||
|
nodes = as_nodes <<-CRYSTAL
|
||||||
|
1.upto(10) do
|
||||||
|
a = 1
|
||||||
|
end
|
||||||
|
CRYSTAL
|
||||||
|
branchable = Branchable.new nodes.call_nodes.first
|
||||||
|
branch = Branch.new nodes.assign_nodes.first, branchable
|
||||||
|
branch.in_loop?.should be_false
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -39,7 +39,7 @@ module Ameba::Rule::Lint
|
||||||
CRYSTAL
|
CRYSTAL
|
||||||
end
|
end
|
||||||
|
|
||||||
it "reports if there is a shared var in spawn" do
|
it "reports if there is a shared var in spawn (while)" do
|
||||||
source = expect_issue subject, <<-CRYSTAL
|
source = expect_issue subject, <<-CRYSTAL
|
||||||
i = 0
|
i = 0
|
||||||
while i < 10
|
while i < 10
|
||||||
|
@ -56,6 +56,24 @@ module Ameba::Rule::Lint
|
||||||
expect_no_corrections source
|
expect_no_corrections source
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "reports if there is a shared var in spawn (loop)" do
|
||||||
|
source = expect_issue subject, <<-CRYSTAL
|
||||||
|
i = 0
|
||||||
|
loop do
|
||||||
|
break if i >= 10
|
||||||
|
spawn do
|
||||||
|
puts(i)
|
||||||
|
# ^ error: Shared variable `i` is used in fiber
|
||||||
|
end
|
||||||
|
i += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
Fiber.yield
|
||||||
|
CRYSTAL
|
||||||
|
|
||||||
|
expect_no_corrections source
|
||||||
|
end
|
||||||
|
|
||||||
it "reports reassigned reference to shared var in spawn" do
|
it "reports reassigned reference to shared var in spawn" do
|
||||||
source = expect_issue subject, <<-CRYSTAL
|
source = expect_issue subject, <<-CRYSTAL
|
||||||
channel = Channel(String).new
|
channel = Channel(String).new
|
||||||
|
|
|
@ -259,6 +259,7 @@ module Ameba
|
||||||
Crystal::MacroLiteral,
|
Crystal::MacroLiteral,
|
||||||
Crystal::Expressions,
|
Crystal::Expressions,
|
||||||
Crystal::ControlExpression,
|
Crystal::ControlExpression,
|
||||||
|
Crystal::Call,
|
||||||
}
|
}
|
||||||
|
|
||||||
def initialize(node)
|
def initialize(node)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
require "./util"
|
||||||
|
|
||||||
module Ameba::AST
|
module Ameba::AST
|
||||||
# Represents the branch in Crystal code.
|
# Represents the branch in Crystal code.
|
||||||
# Branch is a part of a branchable statement.
|
# Branch is a part of a branchable statement.
|
||||||
|
@ -67,6 +69,8 @@ module Ameba::AST
|
||||||
|
|
||||||
# :nodoc:
|
# :nodoc:
|
||||||
private class BranchVisitor < Crystal::Visitor
|
private class BranchVisitor < Crystal::Visitor
|
||||||
|
include Util
|
||||||
|
|
||||||
@current_branch : Crystal::ASTNode?
|
@current_branch : Crystal::ASTNode?
|
||||||
|
|
||||||
property branchable : Branchable?
|
property branchable : Branchable?
|
||||||
|
@ -79,7 +83,7 @@ module Ameba::AST
|
||||||
on_branchable_start(node, branches)
|
on_branchable_start(node, branches)
|
||||||
end
|
end
|
||||||
|
|
||||||
private def on_branchable_start(node, branches : Array | Tuple)
|
private def on_branchable_start(node, branches : Enumerable)
|
||||||
@branchable = Branchable.new(node, @branchable)
|
@branchable = Branchable.new(node, @branchable)
|
||||||
|
|
||||||
branches.each do |branch_node|
|
branches.each do |branch_node|
|
||||||
|
@ -172,6 +176,18 @@ module Ameba::AST
|
||||||
def end_visit(node : Crystal::MacroFor)
|
def end_visit(node : Crystal::MacroFor)
|
||||||
on_branchable_end node
|
on_branchable_end node
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def visit(node : Crystal::Call)
|
||||||
|
if loop?(node) && (block = node.block)
|
||||||
|
on_branchable_start node, block.body
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def end_visit(node : Crystal::Call)
|
||||||
|
if loop?(node) && node.block
|
||||||
|
on_branchable_end node
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue