mirror of
https://gitea.invidious.io/iv-org/shard-ameba.git
synced 2024-08-15 00:53:29 +00:00
Specs cleanup
This commit is contained in:
parent
e6ebca7a5b
commit
8112dddc8f
24 changed files with 267 additions and 251 deletions
|
@ -10,29 +10,29 @@ module Ameba::AST
|
||||||
describe ".of" do
|
describe ".of" do
|
||||||
context "Crystal::If" do
|
context "Crystal::If" do
|
||||||
it "constructs a branch in If.cond" do
|
it "constructs a branch in If.cond" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
if a = get_something # --> Crystal::Assign
|
if a = get_something # --> Crystal::Assign
|
||||||
puts a
|
puts a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = get_something"
|
branch.to_s.should eq "a = get_something"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in If.then" do
|
it "constructs a branch in If.then" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
if true
|
if true
|
||||||
a = 2 # --> Crystal::Assign
|
a = 2 # --> Crystal::Assign
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 2"
|
branch.to_s.should eq "a = 2"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in If.else" do
|
it "constructs a branch in If.else" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
if true
|
if true
|
||||||
nil
|
nil
|
||||||
|
@ -40,45 +40,45 @@ module Ameba::AST
|
||||||
a = 2 # --> Crystal::Assign
|
a = 2 # --> Crystal::Assign
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 2"
|
branch.to_s.should eq "a = 2"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in inline If" do
|
it "constructs a branch in inline If" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
a = 0 if a == 2 # --> Crystal::Assign
|
a = 0 if a == 2 # --> Crystal::Assign
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 0"
|
branch.to_s.should eq "a = 0"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "Crystal::Unless" do
|
context "Crystal::Unless" do
|
||||||
it "constructs a branch in Unless.cond" do
|
it "constructs a branch in Unless.cond" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
unless a = get_something # --> Crystal::Assign
|
unless a = get_something # --> Crystal::Assign
|
||||||
puts a
|
puts a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = get_something"
|
branch.to_s.should eq "a = get_something"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in Unless.then" do
|
it "constructs a branch in Unless.then" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
unless true
|
unless true
|
||||||
a = 2 # --> Crystal::Assign
|
a = 2 # --> Crystal::Assign
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 2"
|
branch.to_s.should eq "a = 2"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a new branch in Unless.else" do
|
it "constructs a new branch in Unless.else" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
unless true
|
unless true
|
||||||
nil
|
nil
|
||||||
|
@ -86,188 +86,188 @@ module Ameba::AST
|
||||||
a = 2 # --> Crystal::Assign
|
a = 2 # --> Crystal::Assign
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 2"
|
branch.to_s.should eq "a = 2"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in inline Unless" do
|
it "constructs a branch in inline Unless" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
(a = 0; b = 3) unless a == 2 # --> Crystal::Expressions
|
(a = 0; b = 3) unless a == 2 # --> Crystal::Expressions
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "(a = 0\nb = 3)"
|
branch.to_s.should eq "(a = 0\nb = 3)"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "Crystal::BinaryOp" do
|
context "Crystal::BinaryOp" do
|
||||||
it "constructs a branch in left node" do
|
it "constructs a branch in left node" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
(a = 2) && do_something
|
(a = 2) && do_something
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "(a = 2)"
|
branch.to_s.should eq "(a = 2)"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in right node" do
|
it "constructs a branch in right node" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
do_something || (a = 0)
|
do_something || (a = 0)
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "(a = 0)"
|
branch.to_s.should eq "(a = 0)"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "Crystal::Case" do
|
context "Crystal::Case" do
|
||||||
it "constructs a branch in cond" do
|
it "constructs a branch in cond" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
case (a = 2)
|
case (a = 2)
|
||||||
when true then nil
|
when true then nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "(a = 2)"
|
branch.to_s.should eq "(a = 2)"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in when" do
|
it "constructs a branch in when" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
case a
|
case a
|
||||||
when a = 3 then nil
|
when a = 3 then nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "when a = 3\n nil\n"
|
branch.to_s.should eq "when a = 3\n nil\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in else" do
|
it "constructs a branch in else" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
case a
|
case a
|
||||||
when true then nil
|
when true then nil
|
||||||
else a = 4
|
else a = 4
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 4"
|
branch.to_s.should eq "a = 4"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "Crystal::While" do
|
context "Crystal::While" do
|
||||||
it "constructs a branch in cond" do
|
it "constructs a branch in cond" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
while a = 1
|
while a = 1
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 1"
|
branch.to_s.should eq "a = 1"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in body" do
|
it "constructs a branch in body" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
while true
|
while true
|
||||||
b = (a = 1)
|
b = (a = 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "b = (a = 1)"
|
branch.to_s.should eq "b = (a = 1)"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "Crystal::Until" do
|
context "Crystal::Until" do
|
||||||
it "constructs a branch in cond" do
|
it "constructs a branch in cond" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
until a = 1
|
until a = 1
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 1"
|
branch.to_s.should eq "a = 1"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in body" do
|
it "constructs a branch in body" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
until false
|
until false
|
||||||
b = (a = 1)
|
b = (a = 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "b = (a = 1)"
|
branch.to_s.should eq "b = (a = 1)"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "Crystal::ExceptionHandler" do
|
context "Crystal::ExceptionHandler" do
|
||||||
it "constructs a branch in body" do
|
it "constructs a branch in body" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
a = 1
|
a = 1
|
||||||
rescue
|
rescue
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 1"
|
branch.to_s.should eq "a = 1"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in a rescue" do
|
it "constructs a branch in a rescue" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
rescue
|
rescue
|
||||||
a = 1
|
a = 1
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 1"
|
branch.to_s.should eq "a = 1"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in else" do
|
it "constructs a branch in else" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
rescue
|
rescue
|
||||||
else
|
else
|
||||||
a = 1
|
a = 1
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 1"
|
branch.to_s.should eq "a = 1"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in ensure" do
|
it "constructs a branch in ensure" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
rescue
|
rescue
|
||||||
ensure
|
ensure
|
||||||
a = 1
|
a = 1
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 1"
|
branch.to_s.should eq "a = 1"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "Crystal::MacroIf" do
|
context "Crystal::MacroIf" do
|
||||||
it "constructs a branch in cond" do
|
it "constructs a branch in cond" do
|
||||||
branch = branch_of_assign_in_def %(
|
branch = branch_of_assign_in_def <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
{% if a = 2 %}
|
{% if a = 2 %}
|
||||||
{% end %}
|
{% end %}
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch.to_s.should eq "a = 2"
|
branch.to_s.should eq "a = 2"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "constructs a branch in then" do
|
it "constructs a branch in then" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
{% if true %}
|
{% if true %}
|
||||||
a = 2
|
a = 2
|
||||||
{% end %}
|
{% end %}
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch = Branch.of(nodes.macro_literal_nodes.first, nodes.def_nodes.first)
|
branch = Branch.of(nodes.macro_literal_nodes.first, nodes.def_nodes.first)
|
||||||
branch.to_s.strip.should eq "a = 2"
|
branch.to_s.strip.should eq "a = 2"
|
||||||
end
|
end
|
||||||
|
@ -275,24 +275,24 @@ module Ameba::AST
|
||||||
|
|
||||||
context "Crystal::MacroFor" do
|
context "Crystal::MacroFor" do
|
||||||
it "constructs a branch in body" do
|
it "constructs a branch in body" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
{% for x in [1, 2, 3] %}
|
{% for x in [1, 2, 3] %}
|
||||||
a = 2
|
a = 2
|
||||||
{% end %}
|
{% end %}
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch = Branch.of(nodes.macro_literal_nodes.first, nodes.def_nodes.first)
|
branch = Branch.of(nodes.macro_literal_nodes.first, nodes.def_nodes.first)
|
||||||
branch.to_s.strip.should eq "a = 2"
|
branch.to_s.strip.should eq "a = 2"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns nil if branch does not exist" do
|
it "returns nil if branch does not exist" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
a = 2
|
a = 2
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branch = Branch.of(nodes.assign_nodes.first, nodes.def_nodes.first)
|
branch = Branch.of(nodes.assign_nodes.first, nodes.def_nodes.first)
|
||||||
branch.should be_nil
|
branch.should be_nil
|
||||||
end
|
end
|
||||||
|
@ -300,11 +300,11 @@ module Ameba::AST
|
||||||
|
|
||||||
describe "#initialize" do
|
describe "#initialize" do
|
||||||
it "creates new branch" do
|
it "creates new branch" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
if true
|
if true
|
||||||
a = 2
|
a = 2
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branchable = Branchable.new nodes.if_nodes.first
|
branchable = Branchable.new nodes.if_nodes.first
|
||||||
branch = Branch.new nodes.assign_nodes.first, branchable
|
branch = Branch.new nodes.assign_nodes.first, branchable
|
||||||
branch.node.should_not be_nil
|
branch.node.should_not be_nil
|
||||||
|
@ -313,22 +313,22 @@ module Ameba::AST
|
||||||
|
|
||||||
describe "delegation" do
|
describe "delegation" do
|
||||||
it "delegates to_s to node" do
|
it "delegates to_s to node" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
if true
|
if true
|
||||||
a = 2
|
a = 2
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branchable = Branchable.new nodes.if_nodes.first
|
branchable = Branchable.new nodes.if_nodes.first
|
||||||
branch = Branch.new nodes.assign_nodes.first, branchable
|
branch = Branch.new nodes.assign_nodes.first, branchable
|
||||||
branch.to_s.should eq branch.node.to_s
|
branch.to_s.should eq branch.node.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
it "delegates locations to node" do
|
it "delegates locations to node" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
if true
|
if true
|
||||||
a = 2
|
a = 2
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branchable = Branchable.new nodes.if_nodes.first
|
branchable = Branchable.new nodes.if_nodes.first
|
||||||
branch = Branch.new nodes.assign_nodes.first, branchable
|
branch = Branch.new nodes.assign_nodes.first, branchable
|
||||||
branch.location.should eq branch.node.location
|
branch.location.should eq branch.node.location
|
||||||
|
@ -338,22 +338,22 @@ module Ameba::AST
|
||||||
|
|
||||||
describe "#in_loop?" do
|
describe "#in_loop?" do
|
||||||
it "returns true if branch is in a loop" do
|
it "returns true if branch is in a loop" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
while true
|
while true
|
||||||
a = 1
|
a = 1
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branchable = Branchable.new nodes.while_nodes.first
|
branchable = Branchable.new nodes.while_nodes.first
|
||||||
branch = Branch.new nodes.assign_nodes.first, branchable
|
branch = Branch.new nodes.assign_nodes.first, branchable
|
||||||
branch.in_loop?.should be_true
|
branch.in_loop?.should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns false if branch is not in a loop" do
|
it "returns false if branch is not in a loop" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
if a > 2
|
if a > 2
|
||||||
a = 1
|
a = 1
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
branchable = Branchable.new nodes.if_nodes.first
|
branchable = Branchable.new nodes.if_nodes.first
|
||||||
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
|
||||||
|
|
|
@ -4,20 +4,20 @@ module Ameba::AST
|
||||||
describe Branchable do
|
describe Branchable do
|
||||||
describe "#initialize" do
|
describe "#initialize" do
|
||||||
it "creates a new branchable" do
|
it "creates a new branchable" do
|
||||||
branchable = Branchable.new as_node %(a = 2 if true)
|
branchable = Branchable.new as_node "a = 2 if true"
|
||||||
branchable.node.should_not be_nil
|
branchable.node.should_not be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "delegation" do
|
describe "delegation" do
|
||||||
it "delegates to_s to @node" do
|
it "delegates to_s to @node" do
|
||||||
node = as_node %(a = 2 if true)
|
node = as_node "a = 2 if true"
|
||||||
branchable = Branchable.new node
|
branchable = Branchable.new node
|
||||||
branchable.to_s.should eq node.to_s
|
branchable.to_s.should eq node.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
it "delegates locations to @node" do
|
it "delegates locations to @node" do
|
||||||
node = as_node %(a = 2 if true)
|
node = as_node "a = 2 if true"
|
||||||
branchable = Branchable.new node
|
branchable = Branchable.new node
|
||||||
branchable.location.should eq node.location
|
branchable.location.should eq node.location
|
||||||
branchable.end_location.should eq node.end_location
|
branchable.end_location.should eq node.end_location
|
||||||
|
@ -26,22 +26,22 @@ module Ameba::AST
|
||||||
|
|
||||||
describe "#loop?" do
|
describe "#loop?" do
|
||||||
it "returns true if it is a while loop" do
|
it "returns true if it is a while loop" do
|
||||||
branchable = Branchable.new as_node %(while true; a = 2; end)
|
branchable = Branchable.new as_node "while true; a = 2; end"
|
||||||
branchable.loop?.should be_true
|
branchable.loop?.should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns true if it is the until loop" do
|
it "returns true if it is the until loop" do
|
||||||
branchable = Branchable.new as_node %(until false; a = 2; end)
|
branchable = Branchable.new as_node "until false; a = 2; end"
|
||||||
branchable.loop?.should be_true
|
branchable.loop?.should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns true if it is loop" do
|
it "returns true if it is loop" do
|
||||||
branchable = Branchable.new as_node %(loop {})
|
branchable = Branchable.new as_node "loop {}"
|
||||||
branchable.loop?.should be_true
|
branchable.loop?.should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns false otherwise" do
|
it "returns false otherwise" do
|
||||||
branchable = Branchable.new as_node %(a = 2 if true)
|
branchable = Branchable.new as_node "a = 2 if true"
|
||||||
branchable.loop?.should be_false
|
branchable.loop?.should be_false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@ module Ameba::AST
|
||||||
end
|
end
|
||||||
|
|
||||||
it "delegates locations to @node" do
|
it "delegates locations to @node" do
|
||||||
node = as_node %(break if true)
|
node = as_node("break if true")
|
||||||
flow_expression = FlowExpression.new node, false
|
flow_expression = FlowExpression.new node, false
|
||||||
flow_expression.location.should eq node.location
|
flow_expression.location.should eq node.location
|
||||||
flow_expression.end_location.should eq node.end_location
|
flow_expression.end_location.should eq node.end_location
|
||||||
|
@ -27,20 +27,20 @@ module Ameba::AST
|
||||||
|
|
||||||
describe "#unreachable_nodes" do
|
describe "#unreachable_nodes" do
|
||||||
it "returns unreachable nodes" do
|
it "returns unreachable nodes" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def foobar
|
def foobar
|
||||||
return
|
return
|
||||||
a = 1
|
a = 1
|
||||||
a = 2
|
a = 2
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
node = nodes.expressions_nodes.first
|
node = nodes.expressions_nodes.first
|
||||||
flow_expression = FlowExpression.new node, false
|
flow_expression = FlowExpression.new node, false
|
||||||
flow_expression.unreachable_nodes.should eq nodes.assign_nodes
|
flow_expression.unreachable_nodes.should eq nodes.assign_nodes
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns nil if there is no unreachable node after loop" do
|
it "returns nil if there is no unreachable node after loop" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def run
|
def run
|
||||||
idx = items.size - 1
|
idx = items.size - 1
|
||||||
while 0 <= idx
|
while 0 <= idx
|
||||||
|
@ -49,19 +49,19 @@ module Ameba::AST
|
||||||
|
|
||||||
puts "foo"
|
puts "foo"
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
node = nodes.expressions_nodes.first
|
node = nodes.expressions_nodes.first
|
||||||
flow_expression = FlowExpression.new node, false
|
flow_expression = FlowExpression.new node, false
|
||||||
flow_expression.unreachable_nodes.empty?.should eq true
|
flow_expression.unreachable_nodes.empty?.should eq true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns nil if there is no unreachable node" do
|
it "returns nil if there is no unreachable node" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def foobar
|
def foobar
|
||||||
a = 1
|
a = 1
|
||||||
return a
|
return a
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
node = nodes.expressions_nodes.first
|
node = nodes.expressions_nodes.first
|
||||||
flow_expression = FlowExpression.new node, false
|
flow_expression = FlowExpression.new node, false
|
||||||
flow_expression.unreachable_nodes.empty?.should eq true
|
flow_expression.unreachable_nodes.empty?.should eq true
|
||||||
|
|
|
@ -49,14 +49,14 @@ module Ameba::AST
|
||||||
|
|
||||||
describe "#references?" do
|
describe "#references?" do
|
||||||
it "returns true if current scope references variable" do
|
it "returns true if current scope references variable" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
a = 2
|
a = 2
|
||||||
block do
|
block do
|
||||||
3.times { |i| a = a + i }
|
3.times { |i| a = a + i }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
scope = Scope.new nodes.def_nodes.first
|
scope = Scope.new nodes.def_nodes.first
|
||||||
var_node = nodes.var_nodes.first
|
var_node = nodes.var_nodes.first
|
||||||
scope.add_variable var_node
|
scope.add_variable var_node
|
||||||
|
@ -69,14 +69,14 @@ module Ameba::AST
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns false if inner scopes are not checked" do
|
it "returns false if inner scopes are not checked" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
a = 2
|
a = 2
|
||||||
block do
|
block do
|
||||||
3.times { |i| a = a + i }
|
3.times { |i| a = a + i }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
scope = Scope.new nodes.def_nodes.first
|
scope = Scope.new nodes.def_nodes.first
|
||||||
var_node = nodes.var_nodes.first
|
var_node = nodes.var_nodes.first
|
||||||
scope.add_variable var_node
|
scope.add_variable var_node
|
||||||
|
@ -89,7 +89,7 @@ module Ameba::AST
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns false if current scope does not reference variable" do
|
it "returns false if current scope does not reference variable" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
a = 2
|
a = 2
|
||||||
block do
|
block do
|
||||||
|
@ -97,7 +97,7 @@ module Ameba::AST
|
||||||
3.times { |i| b = b + i }
|
3.times { |i| b = b + i }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
scope = Scope.new nodes.def_nodes.first
|
scope = Scope.new nodes.def_nodes.first
|
||||||
var_node = nodes.var_nodes.first
|
var_node = nodes.var_nodes.first
|
||||||
scope.add_variable var_node
|
scope.add_variable var_node
|
||||||
|
@ -150,57 +150,53 @@ module Ameba::AST
|
||||||
|
|
||||||
describe "#block?" do
|
describe "#block?" do
|
||||||
it "returns true if Crystal::Block" do
|
it "returns true if Crystal::Block" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes("3.times {}")
|
||||||
3.times {}
|
|
||||||
)
|
|
||||||
scope = Scope.new nodes.block_nodes.first
|
scope = Scope.new nodes.block_nodes.first
|
||||||
scope.block?.should be_true
|
scope.block?.should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns false otherwise" do
|
it "returns false otherwise" do
|
||||||
scope = Scope.new as_node "a = 1"
|
scope = Scope.new as_node("a = 1")
|
||||||
scope.block?.should be_false
|
scope.block?.should be_false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#spawn_block?" do
|
describe "#spawn_block?" do
|
||||||
it "returns true if a node is a spawn block" do
|
it "returns true if a node is a spawn block" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes("spawn {}")
|
||||||
spawn {}
|
|
||||||
)
|
|
||||||
scope = Scope.new nodes.block_nodes.first
|
scope = Scope.new nodes.block_nodes.first
|
||||||
scope.spawn_block?.should be_true
|
scope.spawn_block?.should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns false otherwise" do
|
it "returns false otherwise" do
|
||||||
scope = Scope.new as_node "a = 1"
|
scope = Scope.new as_node("a = 1")
|
||||||
scope.spawn_block?.should be_false
|
scope.spawn_block?.should be_false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#in_macro?" do
|
describe "#in_macro?" do
|
||||||
it "returns true if Crystal::Macro" do
|
it "returns true if Crystal::Macro" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
macro included
|
macro included
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
scope = Scope.new nodes.macro_nodes.first
|
scope = Scope.new nodes.macro_nodes.first
|
||||||
scope.in_macro?.should be_true
|
scope.in_macro?.should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns true if node is nested to Crystal::Macro" do
|
it "returns true if node is nested to Crystal::Macro" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
macro included
|
macro included
|
||||||
{{ @type.each do |type| a = type end }}
|
{{ @type.each do |type| a = type end }}
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
outer_scope = Scope.new nodes.macro_nodes.first
|
outer_scope = Scope.new nodes.macro_nodes.first
|
||||||
scope = Scope.new nodes.block_nodes.first, outer_scope
|
scope = Scope.new nodes.block_nodes.first, outer_scope
|
||||||
scope.in_macro?.should be_true
|
scope.in_macro?.should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns false otherwise" do
|
it "returns false otherwise" do
|
||||||
scope = Scope.new as_node "a = 1"
|
scope = Scope.new as_node("a = 1")
|
||||||
scope.in_macro?.should be_false
|
scope.in_macro?.should be_false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,15 +41,14 @@ module Ameba::AST
|
||||||
|
|
||||||
describe "#branch" do
|
describe "#branch" do
|
||||||
it "returns the branch of the assignment" do
|
it "returns the branch of the assignment" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
if a
|
if a
|
||||||
a = 3 # --> Crystal::Expressions
|
a = 3 # --> Crystal::Expressions
|
||||||
puts a
|
puts a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
|
|
||||||
scope = Scope.new nodes.def_nodes.first
|
scope = Scope.new nodes.def_nodes.first
|
||||||
variable = Variable.new(nodes.var_nodes.first, scope)
|
variable = Variable.new(nodes.var_nodes.first, scope)
|
||||||
assignment = Assignment.new(nodes.assign_nodes.first, variable, scope)
|
assignment = Assignment.new(nodes.assign_nodes.first, variable, scope)
|
||||||
|
@ -58,7 +57,7 @@ module Ameba::AST
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns inner branch" do
|
it "returns inner branch" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def method(a, b)
|
def method(a, b)
|
||||||
if a
|
if a
|
||||||
if b
|
if b
|
||||||
|
@ -66,7 +65,7 @@ module Ameba::AST
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
scope = Scope.new nodes.def_nodes.first
|
scope = Scope.new nodes.def_nodes.first
|
||||||
variable = Variable.new(nodes.var_nodes.first, scope)
|
variable = Variable.new(nodes.var_nodes.first, scope)
|
||||||
assignment = Assignment.new(nodes.assign_nodes.first, variable, scope)
|
assignment = Assignment.new(nodes.assign_nodes.first, variable, scope)
|
||||||
|
@ -75,12 +74,11 @@ module Ameba::AST
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns nil if assignment does not have a branch" do
|
it "returns nil if assignment does not have a branch" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
a = 2
|
a = 2
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
|
|
||||||
scope = Scope.new nodes.def_nodes.first
|
scope = Scope.new nodes.def_nodes.first
|
||||||
variable = Variable.new(nodes.var_nodes.first, scope)
|
variable = Variable.new(nodes.var_nodes.first, scope)
|
||||||
assignment = Assignment.new(nodes.assign_nodes.first, variable, scope)
|
assignment = Assignment.new(nodes.assign_nodes.first, variable, scope)
|
||||||
|
@ -90,12 +88,11 @@ module Ameba::AST
|
||||||
|
|
||||||
describe "#transformed?" do
|
describe "#transformed?" do
|
||||||
it "returns false if the assignment is not transformed by the compiler" do
|
it "returns false if the assignment is not transformed by the compiler" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def method(a)
|
def method(a)
|
||||||
a = 2
|
a = 2
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
|
|
||||||
scope = Scope.new nodes.def_nodes.first
|
scope = Scope.new nodes.def_nodes.first
|
||||||
variable = Variable.new(nodes.var_nodes.first, scope)
|
variable = Variable.new(nodes.var_nodes.first, scope)
|
||||||
assignment = Assignment.new(nodes.assign_nodes.first, variable, scope)
|
assignment = Assignment.new(nodes.assign_nodes.first, variable, scope)
|
||||||
|
@ -103,11 +100,10 @@ module Ameba::AST
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns true if the assignment is transformed by the compiler" do
|
it "returns true if the assignment is transformed by the compiler" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
array.each do |(a, b)|
|
array.each do |(a, b)|
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
|
|
||||||
scope = Scope.new nodes.block_nodes.first
|
scope = Scope.new nodes.block_nodes.first
|
||||||
variable = Variable.new(nodes.var_nodes.first, scope)
|
variable = Variable.new(nodes.var_nodes.first, scope)
|
||||||
assignment = Assignment.new(nodes.assign_nodes.first, variable, scope)
|
assignment = Assignment.new(nodes.assign_nodes.first, variable, scope)
|
||||||
|
|
|
@ -79,12 +79,12 @@ module Ameba::AST
|
||||||
|
|
||||||
describe "#captured_by_block?" do
|
describe "#captured_by_block?" do
|
||||||
it "returns truthy if the variable is captured by block" do
|
it "returns truthy if the variable is captured by block" do
|
||||||
nodes = as_nodes %(
|
nodes = as_nodes <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
a = 2
|
a = 2
|
||||||
3.times { |i| a = a + i }
|
3.times { |i| a = a + i }
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
scope = Scope.new nodes.def_nodes.first
|
scope = Scope.new nodes.def_nodes.first
|
||||||
var_node = nodes.var_nodes.first
|
var_node = nodes.var_nodes.first
|
||||||
scope.add_variable var_node
|
scope.add_variable var_node
|
||||||
|
@ -95,12 +95,12 @@ module Ameba::AST
|
||||||
variable.captured_by_block?.should be_truthy
|
variable.captured_by_block?.should be_truthy
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns falsey if the variable is not captured by the block" do
|
it "returns falsy if the variable is not captured by the block" do
|
||||||
scope = Scope.new as_node %(
|
scope = Scope.new as_node <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
a = 1
|
a = 1
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
scope.add_variable Crystal::Var.new "a"
|
scope.add_variable Crystal::Var.new "a"
|
||||||
variable = scope.variables.first
|
variable = scope.variables.first
|
||||||
variable.captured_by_block?.should be_falsey
|
variable.captured_by_block?.should be_falsey
|
||||||
|
|
|
@ -19,33 +19,33 @@ module Ameba::AST
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is 1 if there is Macro::For" do
|
it "is 1 if there is Macro::For" do
|
||||||
code = %(
|
code = <<-CRYSTAL
|
||||||
def initialize()
|
def initialize
|
||||||
{% for c in ALL_NODES %}
|
{% for c in ALL_NODES %}
|
||||||
true || false
|
true || false
|
||||||
{% end %}
|
{% end %}
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
node = Crystal::Parser.new(code).parse
|
node = Crystal::Parser.new(code).parse
|
||||||
visitor = CountingVisitor.new node
|
visitor = CountingVisitor.new node
|
||||||
visitor.count.should eq 1
|
visitor.count.should eq 1
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is 1 if there is Macro::If" do
|
it "is 1 if there is Macro::If" do
|
||||||
code = %(
|
code = <<-CRYSTAL
|
||||||
def initialize()
|
def initialize
|
||||||
{% if foo.bar? %}
|
{% if foo.bar? %}
|
||||||
true || false
|
true || false
|
||||||
{% end %}
|
{% end %}
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
node = Crystal::Parser.new(code).parse
|
node = Crystal::Parser.new(code).parse
|
||||||
visitor = CountingVisitor.new node
|
visitor = CountingVisitor.new node
|
||||||
visitor.count.should eq 1
|
visitor.count.should eq 1
|
||||||
end
|
end
|
||||||
|
|
||||||
it "increases count for every exhaustive case" do
|
it "increases count for every exhaustive case" do
|
||||||
code = %(
|
code = <<-CRYSTAL
|
||||||
def hello(a : Int32 | Int64 | Float32 | Float64)
|
def hello(a : Int32 | Int64 | Float32 | Float64)
|
||||||
case a
|
case a
|
||||||
in Int32 then "int32"
|
in Int32 then "int32"
|
||||||
|
@ -54,7 +54,7 @@ module Ameba::AST
|
||||||
in Float64 then "float64"
|
in Float64 then "float64"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
node = Crystal::Parser.new(code).parse
|
node = Crystal::Parser.new(code).parse
|
||||||
visitor = CountingVisitor.new node
|
visitor = CountingVisitor.new node
|
||||||
visitor.count.should eq 2
|
visitor.count.should eq 2
|
||||||
|
|
|
@ -6,17 +6,17 @@ module Ameba::AST
|
||||||
describe FlowExpressionVisitor do
|
describe FlowExpressionVisitor do
|
||||||
it "creates an expression for return" do
|
it "creates an expression for return" do
|
||||||
rule = FlowExpressionRule.new
|
rule = FlowExpressionRule.new
|
||||||
FlowExpressionVisitor.new rule, Source.new %(
|
FlowExpressionVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
def foo
|
def foo
|
||||||
return :bar
|
return :bar
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
rule.expressions.size.should eq 1
|
rule.expressions.size.should eq 1
|
||||||
end
|
end
|
||||||
|
|
||||||
it "can create multiple expressions" do
|
it "can create multiple expressions" do
|
||||||
rule = FlowExpressionRule.new
|
rule = FlowExpressionRule.new
|
||||||
FlowExpressionVisitor.new rule, Source.new %(
|
FlowExpressionVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
def foo
|
def foo
|
||||||
if bar
|
if bar
|
||||||
return :baz
|
return :baz
|
||||||
|
@ -24,13 +24,13 @@ module Ameba::AST
|
||||||
return :foobar
|
return :foobar
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
rule.expressions.size.should eq 3
|
rule.expressions.size.should eq 3
|
||||||
end
|
end
|
||||||
|
|
||||||
it "properly creates nested flow expressions" do
|
it "properly creates nested flow expressions" do
|
||||||
rule = FlowExpressionRule.new
|
rule = FlowExpressionRule.new
|
||||||
FlowExpressionVisitor.new rule, Source.new %(
|
FlowExpressionVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
def foo
|
def foo
|
||||||
return (
|
return (
|
||||||
loop do
|
loop do
|
||||||
|
@ -39,27 +39,27 @@ module Ameba::AST
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
rule.expressions.size.should eq 4
|
rule.expressions.size.should eq 4
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates an expression for break" do
|
it "creates an expression for break" do
|
||||||
rule = FlowExpressionRule.new
|
rule = FlowExpressionRule.new
|
||||||
FlowExpressionVisitor.new rule, Source.new %(
|
FlowExpressionVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
while true
|
while true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
rule.expressions.size.should eq 1
|
rule.expressions.size.should eq 1
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates an expression for next" do
|
it "creates an expression for next" do
|
||||||
rule = FlowExpressionRule.new
|
rule = FlowExpressionRule.new
|
||||||
FlowExpressionVisitor.new rule, Source.new %(
|
FlowExpressionVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
while true
|
while true
|
||||||
next if something
|
next if something
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
rule.expressions.size.should eq 1
|
rule.expressions.size.should eq 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,11 +5,11 @@ module Ameba::AST
|
||||||
rule = RedundantControlExpressionRule.new
|
rule = RedundantControlExpressionRule.new
|
||||||
|
|
||||||
describe RedundantControlExpressionVisitor do
|
describe RedundantControlExpressionVisitor do
|
||||||
node = as_node %(
|
node = as_node <<-CRYSTAL
|
||||||
a = 1
|
a = 1
|
||||||
b = 2
|
b = 2
|
||||||
return a + b
|
return a + b
|
||||||
)
|
CRYSTAL
|
||||||
subject = RedundantControlExpressionVisitor.new(rule, source, node)
|
subject = RedundantControlExpressionVisitor.new(rule, source, node)
|
||||||
|
|
||||||
it "assigns valid attributes" do
|
it "assigns valid attributes" do
|
||||||
|
|
|
@ -4,37 +4,37 @@ module Ameba::AST
|
||||||
describe ScopeVisitor do
|
describe ScopeVisitor do
|
||||||
it "creates a scope for the def" do
|
it "creates a scope for the def" do
|
||||||
rule = ScopeRule.new
|
rule = ScopeRule.new
|
||||||
ScopeVisitor.new rule, Source.new %(
|
ScopeVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
rule.scopes.size.should eq 1
|
rule.scopes.size.should eq 1
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a scope for the proc" do
|
it "creates a scope for the proc" do
|
||||||
rule = ScopeRule.new
|
rule = ScopeRule.new
|
||||||
ScopeVisitor.new rule, Source.new %(
|
ScopeVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
-> {}
|
-> {}
|
||||||
)
|
CRYSTAL
|
||||||
rule.scopes.size.should eq 1
|
rule.scopes.size.should eq 1
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a scope for the block" do
|
it "creates a scope for the block" do
|
||||||
rule = ScopeRule.new
|
rule = ScopeRule.new
|
||||||
ScopeVisitor.new rule, Source.new %(
|
ScopeVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
3.times {}
|
3.times {}
|
||||||
)
|
CRYSTAL
|
||||||
rule.scopes.size.should eq 2
|
rule.scopes.size.should eq 2
|
||||||
end
|
end
|
||||||
|
|
||||||
context "inner scopes" do
|
context "inner scopes" do
|
||||||
it "creates scope for block inside def" do
|
it "creates scope for block inside def" do
|
||||||
rule = ScopeRule.new
|
rule = ScopeRule.new
|
||||||
ScopeVisitor.new rule, Source.new %(
|
ScopeVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
3.times {}
|
3.times {}
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
rule.scopes.size.should eq 2
|
rule.scopes.size.should eq 2
|
||||||
rule.scopes.last.outer_scope.should_not be_nil
|
rule.scopes.last.outer_scope.should_not be_nil
|
||||||
rule.scopes.first.outer_scope.should eq rule.scopes.last
|
rule.scopes.first.outer_scope.should eq rule.scopes.last
|
||||||
|
@ -42,11 +42,11 @@ module Ameba::AST
|
||||||
|
|
||||||
it "creates scope for block inside block" do
|
it "creates scope for block inside block" do
|
||||||
rule = ScopeRule.new
|
rule = ScopeRule.new
|
||||||
ScopeVisitor.new rule, Source.new %(
|
ScopeVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
3.times do
|
3.times do
|
||||||
2.times {}
|
2.times {}
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
rule.scopes.size.should eq 3
|
rule.scopes.size.should eq 3
|
||||||
inner_block = rule.scopes.first
|
inner_block = rule.scopes.first
|
||||||
outer_block = rule.scopes.last
|
outer_block = rule.scopes.last
|
||||||
|
|
|
@ -4,10 +4,12 @@ module Ameba::AST
|
||||||
describe TopLevelNodesVisitor do
|
describe TopLevelNodesVisitor do
|
||||||
describe "#require_nodes" do
|
describe "#require_nodes" do
|
||||||
it "returns require node" do
|
it "returns require node" do
|
||||||
source = Source.new %(
|
source = Source.new <<-CRYSTAL
|
||||||
require "foo"
|
require "foo"
|
||||||
def bar; end
|
|
||||||
)
|
def bar
|
||||||
|
end
|
||||||
|
CRYSTAL
|
||||||
visitor = TopLevelNodesVisitor.new(source.ast)
|
visitor = TopLevelNodesVisitor.new(source.ast)
|
||||||
visitor.require_nodes.size.should eq 1
|
visitor.require_nodes.size.should eq 1
|
||||||
visitor.require_nodes.first.to_s.should eq %q(require "foo")
|
visitor.require_nodes.first.to_s.should eq %q(require "foo")
|
||||||
|
|
|
@ -26,135 +26,135 @@ module Ameba
|
||||||
end
|
end
|
||||||
|
|
||||||
it "disables a rule with a comment directive" do
|
it "disables a rule with a comment directive" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
# ameba:disable #{NamedRule.name}
|
# ameba:disable #{NamedRule.name}
|
||||||
Time.epoch(1483859302)
|
Time.epoch(1483859302)
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(NamedRule.new, location: {1, 12}, message: "Error!")
|
source.add_issue(NamedRule.new, location: {1, 12}, message: "Error!")
|
||||||
s.should be_valid
|
source.should be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "disables a rule with a line that ends with a comment directive" do
|
it "disables a rule with a line that ends with a comment directive" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
Time.epoch(1483859302) # ameba:disable #{NamedRule.name}
|
Time.epoch(1483859302) # ameba:disable #{NamedRule.name}
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(NamedRule.new, location: {1, 12}, message: "Error!")
|
source.add_issue(NamedRule.new, location: {1, 12}, message: "Error!")
|
||||||
s.should be_valid
|
source.should be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not disable a rule of a different name" do
|
it "does not disable a rule of a different name" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
# ameba:disable WrongName
|
# ameba:disable WrongName
|
||||||
Time.epoch(1483859302)
|
Time.epoch(1483859302)
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(NamedRule.new, location: {2, 12}, message: "Error!")
|
source.add_issue(NamedRule.new, location: {2, 12}, message: "Error!")
|
||||||
s.should_not be_valid
|
source.should_not be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "disables a rule if multiple rule names provided" do
|
it "disables a rule if multiple rule names provided" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
# ameba:disable SomeRule LargeNumbers #{NamedRule.name} SomeOtherRule
|
# ameba:disable SomeRule LargeNumbers #{NamedRule.name} SomeOtherRule
|
||||||
Time.epoch(1483859302)
|
Time.epoch(1483859302)
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(NamedRule.new, location: {2, 12}, message: "")
|
source.add_issue(NamedRule.new, location: {2, 12}, message: "")
|
||||||
s.should be_valid
|
source.should be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "disables a rule if multiple rule names are separated by comma" do
|
it "disables a rule if multiple rule names are separated by comma" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
# ameba:disable SomeRule, LargeNumbers, #{NamedRule.name}, SomeOtherRule
|
# ameba:disable SomeRule, LargeNumbers, #{NamedRule.name}, SomeOtherRule
|
||||||
Time.epoch(1483859302)
|
Time.epoch(1483859302)
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(NamedRule.new, location: {2, 12}, message: "")
|
source.add_issue(NamedRule.new, location: {2, 12}, message: "")
|
||||||
s.should be_valid
|
source.should be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not disable if multiple rule names used without required one" do
|
it "does not disable if multiple rule names used without required one" do
|
||||||
s = Source.new %(
|
source = Source.new <<-CRYSTAL
|
||||||
# ameba:disable SomeRule, SomeOtherRule LargeNumbers
|
# ameba:disable SomeRule, SomeOtherRule LargeNumbers
|
||||||
Time.epoch(1483859302)
|
Time.epoch(1483859302)
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(NamedRule.new, location: {2, 12}, message: "")
|
source.add_issue(NamedRule.new, location: {2, 12}, message: "")
|
||||||
s.should_not be_valid
|
source.should_not be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not disable if comment directive has wrong place" do
|
it "does not disable if comment directive has wrong place" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
# ameba:disable #{NamedRule.name}
|
# ameba:disable #{NamedRule.name}
|
||||||
#
|
#
|
||||||
Time.epoch(1483859302)
|
Time.epoch(1483859302)
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(NamedRule.new, location: {3, 12}, message: "")
|
source.add_issue(NamedRule.new, location: {3, 12}, message: "")
|
||||||
s.should_not be_valid
|
source.should_not be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not disable if comment directive added to the wrong line" do
|
it "does not disable if comment directive added to the wrong line" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
if use_epoch? # ameba:disable #{NamedRule.name}
|
if use_epoch? # ameba:disable #{NamedRule.name}
|
||||||
Time.epoch(1483859302)
|
Time.epoch(1483859302)
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(NamedRule.new, location: {3, 12}, message: "")
|
source.add_issue(NamedRule.new, location: {3, 12}, message: "")
|
||||||
s.should_not be_valid
|
source.should_not be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not disable if that is not a comment directive" do
|
it "does not disable if that is not a comment directive" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
"ameba:disable #{NamedRule.name}"
|
"ameba:disable #{NamedRule.name}"
|
||||||
Time.epoch(1483859302)
|
Time.epoch(1483859302)
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(NamedRule.new, location: {3, 12}, message: "")
|
source.add_issue(NamedRule.new, location: {3, 12}, message: "")
|
||||||
s.should_not be_valid
|
source.should_not be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not disable if that is a commented out directive" do
|
it "does not disable if that is a commented out directive" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
# # ameba:disable #{NamedRule.name}
|
# # ameba:disable #{NamedRule.name}
|
||||||
Time.epoch(1483859302)
|
Time.epoch(1483859302)
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(NamedRule.new, location: {3, 12}, message: "")
|
source.add_issue(NamedRule.new, location: {3, 12}, message: "")
|
||||||
s.should_not be_valid
|
source.should_not be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not disable if that is an inline commented out directive" do
|
it "does not disable if that is an inline commented out directive" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
a = 1 # Disable it: # ameba:disable #{NamedRule.name}
|
a = 1 # Disable it: # ameba:disable #{NamedRule.name}
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(NamedRule.new, location: {2, 12}, message: "")
|
source.add_issue(NamedRule.new, location: {2, 12}, message: "")
|
||||||
s.should_not be_valid
|
source.should_not be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with group name" do
|
context "with group name" do
|
||||||
it "disables one rule with a group" do
|
it "disables one rule with a group" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
a = 1 # ameba:disable #{DummyRule.rule_name}
|
a = 1 # ameba:disable #{DummyRule.rule_name}
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(DummyRule.new, location: {1, 12}, message: "")
|
source.add_issue(DummyRule.new, location: {1, 12}, message: "")
|
||||||
s.should be_valid
|
source.should be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't disable others rules" do
|
it "doesn't disable others rules" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
a = 1 # ameba:disable #{DummyRule.rule_name}
|
a = 1 # ameba:disable #{DummyRule.rule_name}
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(NamedRule.new, location: {2, 12}, message: "")
|
source.add_issue(NamedRule.new, location: {2, 12}, message: "")
|
||||||
s.should_not be_valid
|
source.should_not be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "disables a hole group of rules" do
|
it "disables a hole group of rules" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
a = 1 # ameba:disable #{DummyRule.group_name}
|
a = 1 # ameba:disable #{DummyRule.group_name}
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(DummyRule.new, location: {1, 12}, message: "")
|
source.add_issue(DummyRule.new, location: {1, 12}, message: "")
|
||||||
s.should be_valid
|
source.should be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not disable rules which do not belong to the group" do
|
it "does not disable rules which do not belong to the group" do
|
||||||
s = Source.new %Q(
|
source = Source.new <<-CRYSTAL
|
||||||
a = 1 # ameba:disable Lint
|
a = 1 # ameba:disable Lint
|
||||||
)
|
CRYSTAL
|
||||||
s.add_issue(DummyRule.new, location: {2, 12}, message: "")
|
source.add_issue(DummyRule.new, location: {2, 12}, message: "")
|
||||||
s.should_not be_valid
|
source.should_not be_valid
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,12 +24,12 @@ module Ameba::Rule::Lint
|
||||||
end
|
end
|
||||||
|
|
||||||
it "reports rule, pos and message" do
|
it "reports rule, pos and message" do
|
||||||
source = Source.new %(
|
source = Source.new <<-CRYSTAL, "source.cr"
|
||||||
require "./thing"
|
require "./thing"
|
||||||
require "./thing"
|
require "./thing"
|
||||||
require "./another_thing"
|
require "./another_thing"
|
||||||
require "./another_thing"
|
require "./another_thing"
|
||||||
), "source.cr"
|
CRYSTAL
|
||||||
|
|
||||||
subject.catch(source).should_not be_valid
|
subject.catch(source).should_not be_valid
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ module Ameba
|
||||||
|
|
||||||
describe Rule::Lint::EmptyExpression do
|
describe Rule::Lint::EmptyExpression do
|
||||||
it "passes if there is no empty expression" do
|
it "passes if there is no empty expression" do
|
||||||
s = Source.new %(
|
s = Source.new <<-CRYSTAL
|
||||||
def method()
|
def method()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ module Ameba
|
||||||
|
|
||||||
begin "" end
|
begin "" end
|
||||||
[nil] << nil
|
[nil] << nil
|
||||||
)
|
CRYSTAL
|
||||||
subject.catch(s).should be_valid
|
subject.catch(s).should be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ module Ameba::Rule::Performance
|
||||||
|
|
||||||
context "properties" do
|
context "properties" do
|
||||||
it "allows to configure object_call_names" do
|
it "allows to configure object_call_names" do
|
||||||
rule = Rule::Performance::AnyAfterFilter.new
|
rule = AnyAfterFilter.new
|
||||||
rule.filter_names = %w(select)
|
rule.filter_names = %w(select)
|
||||||
|
|
||||||
expect_no_issues rule, <<-CRYSTAL
|
expect_no_issues rule, <<-CRYSTAL
|
||||||
|
|
|
@ -63,7 +63,7 @@ module Ameba::Rule::Performance
|
||||||
|
|
||||||
context "properties" do
|
context "properties" do
|
||||||
it "allows to configure object_call_names" do
|
it "allows to configure object_call_names" do
|
||||||
rule = Rule::Performance::FirstLastAfterFilter.new
|
rule = FirstLastAfterFilter.new
|
||||||
rule.filter_names = %w(reject)
|
rule.filter_names = %w(reject)
|
||||||
|
|
||||||
expect_no_issues rule, <<-CRYSTAL
|
expect_no_issues rule, <<-CRYSTAL
|
||||||
|
|
|
@ -45,7 +45,7 @@ module Ameba::Rule::Performance
|
||||||
|
|
||||||
context "properties" do
|
context "properties" do
|
||||||
it "allows to configure object caller names" do
|
it "allows to configure object caller names" do
|
||||||
rule = Rule::Performance::SizeAfterFilter.new
|
rule = SizeAfterFilter.new
|
||||||
rule.filter_names = %w(select)
|
rule.filter_names = %w(select)
|
||||||
|
|
||||||
expect_no_issues rule, <<-CRYSTAL
|
expect_no_issues rule, <<-CRYSTAL
|
||||||
|
|
|
@ -45,6 +45,7 @@ module Ameba::Rule::Style
|
||||||
it "allows to configure filter_names" do
|
it "allows to configure filter_names" do
|
||||||
rule = IsAFilter.new
|
rule = IsAFilter.new
|
||||||
rule.filter_names = %w(select)
|
rule.filter_names = %w(select)
|
||||||
|
|
||||||
expect_no_issues rule, <<-CRYSTAL
|
expect_no_issues rule, <<-CRYSTAL
|
||||||
[1, 2, nil].reject(&.nil?)
|
[1, 2, nil].reject(&.nil?)
|
||||||
CRYSTAL
|
CRYSTAL
|
||||||
|
|
|
@ -51,7 +51,7 @@ module Ameba::Rule::Style
|
||||||
end
|
end
|
||||||
|
|
||||||
it "allows to configure assignments" do
|
it "allows to configure assignments" do
|
||||||
rule = Rule::Style::ParenthesesAroundCondition.new
|
rule = ParenthesesAroundCondition.new
|
||||||
rule.exclude_ternary = false
|
rule.exclude_ternary = false
|
||||||
|
|
||||||
expect_issue rule, <<-CRYSTAL
|
expect_issue rule, <<-CRYSTAL
|
||||||
|
@ -98,7 +98,7 @@ module Ameba::Rule::Style
|
||||||
end
|
end
|
||||||
|
|
||||||
it "allows to configure assignments" do
|
it "allows to configure assignments" do
|
||||||
rule = Rule::Style::ParenthesesAroundCondition.new
|
rule = ParenthesesAroundCondition.new
|
||||||
rule.allow_safe_assignment = true
|
rule.allow_safe_assignment = true
|
||||||
|
|
||||||
expect_issue rule, <<-CRYSTAL
|
expect_issue rule, <<-CRYSTAL
|
||||||
|
|
|
@ -211,7 +211,7 @@ module Ameba::Rule::Style
|
||||||
end
|
end
|
||||||
|
|
||||||
it "allows to configure multi next statements" do
|
it "allows to configure multi next statements" do
|
||||||
rule = Rule::Style::RedundantNext.new
|
rule = RedundantNext.new
|
||||||
rule.allow_multi_next = false
|
rule.allow_multi_next = false
|
||||||
source = expect_issue rule, <<-CRYSTAL
|
source = expect_issue rule, <<-CRYSTAL
|
||||||
block do |a, b|
|
block do |a, b|
|
||||||
|
@ -238,7 +238,7 @@ module Ameba::Rule::Style
|
||||||
end
|
end
|
||||||
|
|
||||||
it "allows to configure empty next statements" do
|
it "allows to configure empty next statements" do
|
||||||
rule = Rule::Style::RedundantNext.new
|
rule = RedundantNext.new
|
||||||
rule.allow_empty_next = false
|
rule.allow_empty_next = false
|
||||||
source = expect_issue rule, <<-CRYSTAL
|
source = expect_issue rule, <<-CRYSTAL
|
||||||
block do
|
block do
|
||||||
|
|
|
@ -294,7 +294,7 @@ module Ameba::Rule::Style
|
||||||
end
|
end
|
||||||
|
|
||||||
it "allows to configure multi returns" do
|
it "allows to configure multi returns" do
|
||||||
rule = Rule::Style::RedundantReturn.new
|
rule = RedundantReturn.new
|
||||||
rule.allow_multi_return = false
|
rule.allow_multi_return = false
|
||||||
source = expect_issue rule, <<-CRYSTAL
|
source = expect_issue rule, <<-CRYSTAL
|
||||||
def method(a, b)
|
def method(a, b)
|
||||||
|
@ -321,7 +321,7 @@ module Ameba::Rule::Style
|
||||||
end
|
end
|
||||||
|
|
||||||
it "allows to configure empty returns" do
|
it "allows to configure empty returns" do
|
||||||
rule = Rule::Style::RedundantReturn.new
|
rule = RedundantReturn.new
|
||||||
rule.allow_empty_return = false
|
rule.allow_empty_return = false
|
||||||
source = expect_issue rule, <<-CRYSTAL
|
source = expect_issue rule, <<-CRYSTAL
|
||||||
def method
|
def method
|
||||||
|
|
|
@ -64,10 +64,12 @@ module Ameba::Rule::Style
|
||||||
context "properties" do
|
context "properties" do
|
||||||
it "#exclude_calls_with_block" do
|
it "#exclude_calls_with_block" do
|
||||||
rule = VerboseBlock.new
|
rule = VerboseBlock.new
|
||||||
|
|
||||||
rule.exclude_calls_with_block = true
|
rule.exclude_calls_with_block = true
|
||||||
expect_no_issues rule, <<-CRYSTAL
|
expect_no_issues rule, <<-CRYSTAL
|
||||||
(1..3).in_groups_of(1) { |i| i.map(&.to_s) }
|
(1..3).in_groups_of(1) { |i| i.map(&.to_s) }
|
||||||
CRYSTAL
|
CRYSTAL
|
||||||
|
|
||||||
rule.exclude_calls_with_block = false
|
rule.exclude_calls_with_block = false
|
||||||
source = expect_issue rule, <<-CRYSTAL
|
source = expect_issue rule, <<-CRYSTAL
|
||||||
(1..3).in_groups_of(1) { |i| i.map(&.to_s) }
|
(1..3).in_groups_of(1) { |i| i.map(&.to_s) }
|
||||||
|
@ -81,12 +83,14 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
it "#exclude_multiple_line_blocks" do
|
it "#exclude_multiple_line_blocks" do
|
||||||
rule = VerboseBlock.new
|
rule = VerboseBlock.new
|
||||||
|
|
||||||
rule.exclude_multiple_line_blocks = true
|
rule.exclude_multiple_line_blocks = true
|
||||||
expect_no_issues rule, <<-CRYSTAL
|
expect_no_issues rule, <<-CRYSTAL
|
||||||
(1..3).any? do |i|
|
(1..3).any? do |i|
|
||||||
i.odd?
|
i.odd?
|
||||||
end
|
end
|
||||||
CRYSTAL
|
CRYSTAL
|
||||||
|
|
||||||
rule.exclude_multiple_line_blocks = false
|
rule.exclude_multiple_line_blocks = false
|
||||||
source = expect_issue rule, <<-CRYSTAL
|
source = expect_issue rule, <<-CRYSTAL
|
||||||
(1..3).any? do |i|
|
(1..3).any? do |i|
|
||||||
|
@ -102,12 +106,14 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
it "#exclude_prefix_operators" do
|
it "#exclude_prefix_operators" do
|
||||||
rule = VerboseBlock.new
|
rule = VerboseBlock.new
|
||||||
|
|
||||||
rule.exclude_prefix_operators = true
|
rule.exclude_prefix_operators = true
|
||||||
expect_no_issues rule, <<-CRYSTAL
|
expect_no_issues rule, <<-CRYSTAL
|
||||||
(1..3).sum { |i| +i }
|
(1..3).sum { |i| +i }
|
||||||
(1..3).sum { |i| -i }
|
(1..3).sum { |i| -i }
|
||||||
(1..3).sum { |i| ~i }
|
(1..3).sum { |i| ~i }
|
||||||
CRYSTAL
|
CRYSTAL
|
||||||
|
|
||||||
rule.exclude_prefix_operators = false
|
rule.exclude_prefix_operators = false
|
||||||
rule.exclude_operators = false
|
rule.exclude_operators = false
|
||||||
source = expect_issue rule, <<-CRYSTAL
|
source = expect_issue rule, <<-CRYSTAL
|
||||||
|
@ -128,10 +134,12 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
it "#exclude_operators" do
|
it "#exclude_operators" do
|
||||||
rule = VerboseBlock.new
|
rule = VerboseBlock.new
|
||||||
|
|
||||||
rule.exclude_operators = true
|
rule.exclude_operators = true
|
||||||
expect_no_issues rule, <<-CRYSTAL
|
expect_no_issues rule, <<-CRYSTAL
|
||||||
(1..3).sum { |i| i * 2 }
|
(1..3).sum { |i| i * 2 }
|
||||||
CRYSTAL
|
CRYSTAL
|
||||||
|
|
||||||
rule.exclude_operators = false
|
rule.exclude_operators = false
|
||||||
source = expect_issue rule, <<-CRYSTAL
|
source = expect_issue rule, <<-CRYSTAL
|
||||||
(1..3).sum { |i| i * 2 }
|
(1..3).sum { |i| i * 2 }
|
||||||
|
@ -145,10 +153,12 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
it "#exclude_setters" do
|
it "#exclude_setters" do
|
||||||
rule = VerboseBlock.new
|
rule = VerboseBlock.new
|
||||||
|
|
||||||
rule.exclude_setters = true
|
rule.exclude_setters = true
|
||||||
expect_no_issues rule, <<-CRYSTAL
|
expect_no_issues rule, <<-CRYSTAL
|
||||||
Char::Reader.new("abc").tap { |reader| reader.pos = 0 }
|
Char::Reader.new("abc").tap { |reader| reader.pos = 0 }
|
||||||
CRYSTAL
|
CRYSTAL
|
||||||
|
|
||||||
rule.exclude_setters = false
|
rule.exclude_setters = false
|
||||||
source = expect_issue rule, <<-CRYSTAL
|
source = expect_issue rule, <<-CRYSTAL
|
||||||
Char::Reader.new("abc").tap { |reader| reader.pos = 0 }
|
Char::Reader.new("abc").tap { |reader| reader.pos = 0 }
|
||||||
|
@ -163,12 +173,14 @@ module Ameba::Rule::Style
|
||||||
it "#max_line_length" do
|
it "#max_line_length" do
|
||||||
rule = VerboseBlock.new
|
rule = VerboseBlock.new
|
||||||
rule.exclude_multiple_line_blocks = false
|
rule.exclude_multiple_line_blocks = false
|
||||||
|
|
||||||
rule.max_line_length = 60
|
rule.max_line_length = 60
|
||||||
expect_no_issues rule, <<-CRYSTAL
|
expect_no_issues rule, <<-CRYSTAL
|
||||||
(1..3).tap &.tap &.tap &.tap &.tap &.tap &.tap do |i|
|
(1..3).tap &.tap &.tap &.tap &.tap &.tap &.tap do |i|
|
||||||
i.to_s.reverse.strip.blank?
|
i.to_s.reverse.strip.blank?
|
||||||
end
|
end
|
||||||
CRYSTAL
|
CRYSTAL
|
||||||
|
|
||||||
rule.max_line_length = nil
|
rule.max_line_length = nil
|
||||||
source = expect_issue rule, <<-CRYSTAL
|
source = expect_issue rule, <<-CRYSTAL
|
||||||
(1..3).tap &.tap &.tap &.tap &.tap &.tap &.tap do |i|
|
(1..3).tap &.tap &.tap &.tap &.tap &.tap &.tap do |i|
|
||||||
|
@ -184,10 +196,12 @@ module Ameba::Rule::Style
|
||||||
|
|
||||||
it "#max_length" do
|
it "#max_length" do
|
||||||
rule = VerboseBlock.new
|
rule = VerboseBlock.new
|
||||||
|
|
||||||
rule.max_length = 30
|
rule.max_length = 30
|
||||||
expect_no_issues rule, <<-CRYSTAL
|
expect_no_issues rule, <<-CRYSTAL
|
||||||
(1..3).tap { |i| i.to_s.split.reverse.join.strip.blank? }
|
(1..3).tap { |i| i.to_s.split.reverse.join.strip.blank? }
|
||||||
CRYSTAL
|
CRYSTAL
|
||||||
|
|
||||||
rule.max_length = nil
|
rule.max_length = nil
|
||||||
source = expect_issue rule, <<-CRYSTAL
|
source = expect_issue rule, <<-CRYSTAL
|
||||||
(1..3).tap { |i| i.to_s.split.reverse.join.strip.blank? }
|
(1..3).tap { |i| i.to_s.split.reverse.join.strip.blank? }
|
||||||
|
@ -216,6 +230,7 @@ module Ameba::Rule::Style
|
||||||
it "reports call args and named_args" do
|
it "reports call args and named_args" do
|
||||||
rule = VerboseBlock.new
|
rule = VerboseBlock.new
|
||||||
rule.exclude_operators = false
|
rule.exclude_operators = false
|
||||||
|
|
||||||
source = expect_issue rule, <<-CRYSTAL
|
source = expect_issue rule, <<-CRYSTAL
|
||||||
(1..3).map { |i| i.to_s[start: 0.to_i64, count: 3]? }
|
(1..3).map { |i| i.to_s[start: 0.to_i64, count: 3]? }
|
||||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [...] `map(&.to_s.[start: 0.to_i64, count: 3]?)`
|
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [...] `map(&.to_s.[start: 0.to_i64, count: 3]?)`
|
||||||
|
@ -260,9 +275,9 @@ module Ameba::Rule::Style
|
||||||
end
|
end
|
||||||
|
|
||||||
it "reports rule, pos and message" do
|
it "reports rule, pos and message" do
|
||||||
source = Source.new path: "source.cr", code: %(
|
source = Source.new path: "source.cr", code: <<-CRYSTAL
|
||||||
(1..3).any? { |i| i.odd? }
|
(1..3).any? { |i| i.odd? }
|
||||||
)
|
CRYSTAL
|
||||||
subject.catch(source).should_not be_valid
|
subject.catch(source).should_not be_valid
|
||||||
source.issues.size.should eq 1
|
source.issues.size.should eq 1
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ module Ameba
|
||||||
rules = [AtoAA.new] of Rule::Base
|
rules = [AtoAA.new] of Rule::Base
|
||||||
source = Source.new "class A; end", "source.cr"
|
source = Source.new "class A; end", "source.cr"
|
||||||
message = "Infinite loop in source.cr caused by Ameba/AtoAA"
|
message = "Infinite loop in source.cr caused by Ameba/AtoAA"
|
||||||
|
|
||||||
expect_raises(Runner::InfiniteCorrectionLoopError, message) do
|
expect_raises(Runner::InfiniteCorrectionLoopError, message) do
|
||||||
Runner.new(rules, [source], formatter, default_severity, autocorrect: true).run
|
Runner.new(rules, [source], formatter, default_severity, autocorrect: true).run
|
||||||
end
|
end
|
||||||
|
@ -95,11 +96,11 @@ module Ameba
|
||||||
|
|
||||||
it "does not run other rules" do
|
it "does not run other rules" do
|
||||||
rules = [Rule::Lint::Syntax.new, Rule::Style::ConstantNames.new] of Rule::Base
|
rules = [Rule::Lint::Syntax.new, Rule::Style::ConstantNames.new] of Rule::Base
|
||||||
source = Source.new %q(
|
source = Source.new <<-CRYSTAL
|
||||||
MyBadConstant = 1
|
MyBadConstant = 1
|
||||||
|
|
||||||
when my_bad_syntax
|
when my_bad_syntax
|
||||||
)
|
CRYSTAL
|
||||||
|
|
||||||
Runner.new(rules, [source], formatter, default_severity).run
|
Runner.new(rules, [source], formatter, default_severity).run
|
||||||
source.should_not be_valid
|
source.should_not be_valid
|
||||||
|
@ -110,9 +111,9 @@ module Ameba
|
||||||
context "unneeded disables" do
|
context "unneeded disables" do
|
||||||
it "reports an issue if such disable exists" do
|
it "reports an issue if such disable exists" do
|
||||||
rules = [Rule::Lint::UnneededDisableDirective.new] of Rule::Base
|
rules = [Rule::Lint::UnneededDisableDirective.new] of Rule::Base
|
||||||
source = Source.new %(
|
source = Source.new <<-CRYSTAL
|
||||||
a = 1 # ameba:disable LineLength
|
a = 1 # ameba:disable LineLength
|
||||||
)
|
CRYSTAL
|
||||||
|
|
||||||
Runner.new(rules, [source], formatter, default_severity).run
|
Runner.new(rules, [source], formatter, default_severity).run
|
||||||
source.should_not be_valid
|
source.should_not be_valid
|
||||||
|
@ -134,9 +135,7 @@ module Ameba
|
||||||
it "writes the explanation if sources are not valid and location found" do
|
it "writes the explanation if sources are not valid and location found" do
|
||||||
io.clear
|
io.clear
|
||||||
rules = [ErrorRule.new] of Rule::Base
|
rules = [ErrorRule.new] of Rule::Base
|
||||||
source = Source.new %(
|
source = Source.new "a = 1", "source.cr"
|
||||||
a = 1
|
|
||||||
), "source.cr"
|
|
||||||
|
|
||||||
runner = Runner.new(rules, [source], formatter, default_severity).run
|
runner = Runner.new(rules, [source], formatter, default_severity).run
|
||||||
runner.explain({file: "source.cr", line: 1, column: 1}, io)
|
runner.explain({file: "source.cr", line: 1, column: 1}, io)
|
||||||
|
@ -146,9 +145,7 @@ module Ameba
|
||||||
it "writes nothing if sources are not valid and location is not found" do
|
it "writes nothing if sources are not valid and location is not found" do
|
||||||
io.clear
|
io.clear
|
||||||
rules = [ErrorRule.new] of Rule::Base
|
rules = [ErrorRule.new] of Rule::Base
|
||||||
source = Source.new %(
|
source = Source.new "a = 1", "source.cr"
|
||||||
a = 1
|
|
||||||
), "source.cr"
|
|
||||||
|
|
||||||
runner = Runner.new(rules, [source], formatter, default_severity).run
|
runner = Runner.new(rules, [source], formatter, default_severity).run
|
||||||
runner.explain({file: "source.cr", line: 1, column: 2}, io)
|
runner.explain({file: "source.cr", line: 1, column: 2}, io)
|
||||||
|
@ -167,10 +164,9 @@ module Ameba
|
||||||
|
|
||||||
it "returns false if there are invalid sources" do
|
it "returns false if there are invalid sources" do
|
||||||
rules = Rule.rules.map &.new.as(Rule::Base)
|
rules = Rule.rules.map &.new.as(Rule::Base)
|
||||||
s = Source.new %q(
|
source = Source.new "WrongConstant = 5"
|
||||||
WrongConstant = 5
|
|
||||||
)
|
Runner.new(rules, [source], formatter, default_severity).run.success?.should be_false
|
||||||
Runner.new(rules, [s], formatter, default_severity).run.success?.should be_false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "depends on the level of severity" do
|
it "depends on the level of severity" do
|
||||||
|
@ -183,11 +179,11 @@ module Ameba
|
||||||
|
|
||||||
it "returns false if issue is disabled" do
|
it "returns false if issue is disabled" do
|
||||||
rules = [NamedRule.new] of Rule::Base
|
rules = [NamedRule.new] of Rule::Base
|
||||||
source = Source.new %(
|
source = Source.new <<-CRYSTAL
|
||||||
def foo
|
def foo
|
||||||
bar = 1 # ameba:disable #{NamedRule.name}
|
bar = 1 # ameba:disable #{NamedRule.name}
|
||||||
end
|
end
|
||||||
)
|
CRYSTAL
|
||||||
source.add_issue NamedRule.new, location: {2, 1},
|
source.add_issue NamedRule.new, location: {2, 1},
|
||||||
message: "Useless assignment"
|
message: "Useless assignment"
|
||||||
|
|
||||||
|
@ -204,6 +200,7 @@ module Ameba
|
||||||
rules = [AtoB.new, BtoA.new]
|
rules = [AtoB.new, BtoA.new]
|
||||||
source = Source.new "class A; end", "source.cr"
|
source = Source.new "class A; end", "source.cr"
|
||||||
message = "Infinite loop in source.cr caused by Ameba/AtoB -> Ameba/BtoA"
|
message = "Infinite loop in source.cr caused by Ameba/AtoB -> Ameba/BtoA"
|
||||||
|
|
||||||
expect_raises(Runner::InfiniteCorrectionLoopError, message) do
|
expect_raises(Runner::InfiniteCorrectionLoopError, message) do
|
||||||
Runner.new(rules, [source], formatter, default_severity, autocorrect: true).run
|
Runner.new(rules, [source], formatter, default_severity, autocorrect: true).run
|
||||||
end
|
end
|
||||||
|
@ -213,11 +210,12 @@ module Ameba
|
||||||
context "if there are multiple offenses in an inspected file" do
|
context "if there are multiple offenses in an inspected file" do
|
||||||
it "aborts because of an infinite loop" do
|
it "aborts because of an infinite loop" do
|
||||||
rules = [AtoB.new, BtoA.new]
|
rules = [AtoB.new, BtoA.new]
|
||||||
source = Source.new %(
|
source = Source.new <<-CRYSTAL, "source.cr"
|
||||||
class A; end
|
class A; end
|
||||||
class A_A; end
|
class A_A; end
|
||||||
), "source.cr"
|
CRYSTAL
|
||||||
message = "Infinite loop in source.cr caused by Ameba/AtoB -> Ameba/BtoA"
|
message = "Infinite loop in source.cr caused by Ameba/AtoB -> Ameba/BtoA"
|
||||||
|
|
||||||
expect_raises(Runner::InfiniteCorrectionLoopError, message) do
|
expect_raises(Runner::InfiniteCorrectionLoopError, message) do
|
||||||
Runner.new(rules, [source], formatter, default_severity, autocorrect: true).run
|
Runner.new(rules, [source], formatter, default_severity, autocorrect: true).run
|
||||||
end
|
end
|
||||||
|
@ -230,6 +228,7 @@ module Ameba
|
||||||
rules = [ClassToModule.new, ModuleToClass.new, AtoB.new, BtoA.new]
|
rules = [ClassToModule.new, ModuleToClass.new, AtoB.new, BtoA.new]
|
||||||
source = Source.new "class A_A; end", "source.cr"
|
source = Source.new "class A_A; end", "source.cr"
|
||||||
message = "Infinite loop in source.cr caused by Ameba/ClassToModule, Ameba/AtoB -> Ameba/ModuleToClass, Ameba/BtoA"
|
message = "Infinite loop in source.cr caused by Ameba/ClassToModule, Ameba/AtoB -> Ameba/ModuleToClass, Ameba/BtoA"
|
||||||
|
|
||||||
expect_raises(Runner::InfiniteCorrectionLoopError, message) do
|
expect_raises(Runner::InfiniteCorrectionLoopError, message) do
|
||||||
Runner.new(rules, [source], formatter, default_severity, autocorrect: true).run
|
Runner.new(rules, [source], formatter, default_severity, autocorrect: true).run
|
||||||
end
|
end
|
||||||
|
@ -241,6 +240,7 @@ module Ameba
|
||||||
rules = [AtoB.new, BtoC.new, CtoA.new]
|
rules = [AtoB.new, BtoC.new, CtoA.new]
|
||||||
source = Source.new "class A; end", "source.cr"
|
source = Source.new "class A; end", "source.cr"
|
||||||
message = "Infinite loop in source.cr caused by Ameba/AtoB -> Ameba/BtoC -> Ameba/CtoA"
|
message = "Infinite loop in source.cr caused by Ameba/AtoB -> Ameba/BtoC -> Ameba/CtoA"
|
||||||
|
|
||||||
expect_raises(Runner::InfiniteCorrectionLoopError, message) do
|
expect_raises(Runner::InfiniteCorrectionLoopError, message) do
|
||||||
Runner.new(rules, [source], formatter, default_severity, autocorrect: true).run
|
Runner.new(rules, [source], formatter, default_severity, autocorrect: true).run
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
module Ameba::Rule::Lint
|
module Ameba::Rule::Lint
|
||||||
# This rule checks for mistyped shorthand assignments.
|
# This rule checks for mistyped shorthand assignments.
|
||||||
#
|
#
|
||||||
# # bad
|
# This is considered invalid:
|
||||||
|
#
|
||||||
|
# ```
|
||||||
# x = -y
|
# x = -y
|
||||||
# x = +y
|
# x = +y
|
||||||
# x = !y
|
# x = !y
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# # good
|
# And this is valid:
|
||||||
|
#
|
||||||
|
# ```
|
||||||
# x -= y # or x = -y
|
# x -= y # or x = -y
|
||||||
# x += y # or x = +y
|
# x += y # or x = +y
|
||||||
# x != y # or x = !y
|
# x != y # or x = !y
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# YAML configuration example:
|
# YAML configuration example:
|
||||||
#
|
#
|
||||||
|
@ -43,9 +49,9 @@ module Ameba::Rule::Lint
|
||||||
op_text = source_between(op_location, op_end_location, source.lines)
|
op_text = source_between(op_location, op_end_location, source.lines)
|
||||||
|
|
||||||
return unless op_text
|
return unless op_text
|
||||||
return unless MISTAKES.has_key?(op_text)
|
return unless suggestion = MISTAKES[op_text]?
|
||||||
|
|
||||||
issue_for op_location, op_end_location, MSG % MISTAKES[op_text]
|
issue_for op_location, op_end_location, MSG % suggestion
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue