mirror of
https://gitea.invidious.io/iv-org/shard-ameba.git
synced 2024-08-15 00:53:29 +00:00
Implement Scope#visibility
This commit is contained in:
parent
85c3db4d74
commit
4c740f394a
4 changed files with 62 additions and 1 deletions
|
@ -2,6 +2,17 @@ require "../../../spec_helper"
|
||||||
|
|
||||||
module Ameba::AST
|
module Ameba::AST
|
||||||
describe ScopeVisitor do
|
describe ScopeVisitor do
|
||||||
|
{% for type in %w[class module enum].map(&.id) %}
|
||||||
|
it "creates a scope for the {{ type }} def" do
|
||||||
|
rule = ScopeRule.new
|
||||||
|
ScopeVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
|
{{ type }} Foo
|
||||||
|
end
|
||||||
|
CRYSTAL
|
||||||
|
rule.scopes.size.should eq 1
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
|
||||||
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 <<-CRYSTAL
|
ScopeVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
|
@ -54,5 +65,31 @@ module Ameba::AST
|
||||||
outer_block.outer_scope.should be_nil
|
outer_block.outer_scope.should be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "#visibility" do
|
||||||
|
it "is being properly set" do
|
||||||
|
rule = ScopeRule.new
|
||||||
|
ScopeVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
|
private class Foo
|
||||||
|
end
|
||||||
|
CRYSTAL
|
||||||
|
rule.scopes.size.should eq 1
|
||||||
|
rule.scopes.first.visibility.should eq Crystal::Visibility::Private
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is being inherited from the outer scope(s)" do
|
||||||
|
rule = ScopeRule.new
|
||||||
|
ScopeVisitor.new rule, Source.new <<-CRYSTAL
|
||||||
|
private class Foo
|
||||||
|
class Bar
|
||||||
|
def baz
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
CRYSTAL
|
||||||
|
rule.scopes.size.should eq 3
|
||||||
|
rule.scopes.each &.visibility.should eq Crystal::Visibility::Private
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -43,6 +43,9 @@ module Ameba
|
||||||
description "Internal rule to test scopes"
|
description "Internal rule to test scopes"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test(source, node : Crystal::VisibilityModifier, scope : AST::Scope)
|
||||||
|
end
|
||||||
|
|
||||||
def test(source, node : Crystal::ASTNode, scope : AST::Scope)
|
def test(source, node : Crystal::ASTNode, scope : AST::Scope)
|
||||||
@scopes << scope
|
@scopes << scope
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,9 @@ module Ameba::AST
|
||||||
# Whether the scope yields.
|
# Whether the scope yields.
|
||||||
setter yields = false
|
setter yields = false
|
||||||
|
|
||||||
|
# Scope visibility level
|
||||||
|
setter visibility : Crystal::Visibility?
|
||||||
|
|
||||||
# Link to local variables
|
# Link to local variables
|
||||||
getter variables = [] of Variable
|
getter variables = [] of Variable
|
||||||
|
|
||||||
|
@ -172,6 +175,11 @@ module Ameba::AST
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns visibility of the current scope (could be inherited from the outer scope).
|
||||||
|
def visibility
|
||||||
|
@visibility || outer_scope.try(&.visibility)
|
||||||
|
end
|
||||||
|
|
||||||
# Returns `true` if current scope is a def, `false` otherwise.
|
# Returns `true` if current scope is a def, `false` otherwise.
|
||||||
def def?
|
def def?
|
||||||
node.is_a?(Crystal::Def)
|
node.is_a?(Crystal::Def)
|
||||||
|
|
|
@ -25,6 +25,7 @@ module Ameba::AST
|
||||||
@scope_queue = [] of Scope
|
@scope_queue = [] of Scope
|
||||||
@current_scope : Scope
|
@current_scope : Scope
|
||||||
@current_assign : Crystal::ASTNode?
|
@current_assign : Crystal::ASTNode?
|
||||||
|
@visibility_modifier : Crystal::Visibility?
|
||||||
@skip : Array(Crystal::ASTNode.class)?
|
@skip : Array(Crystal::ASTNode.class)?
|
||||||
|
|
||||||
def initialize(@rule, @source, skip = nil)
|
def initialize(@rule, @source, skip = nil)
|
||||||
|
@ -36,12 +37,18 @@ module Ameba::AST
|
||||||
|
|
||||||
private def on_scope_enter(node)
|
private def on_scope_enter(node)
|
||||||
return if skip?(node)
|
return if skip?(node)
|
||||||
@current_scope = Scope.new(node, @current_scope)
|
|
||||||
|
scope = Scope.new(node, @current_scope)
|
||||||
|
scope.visibility = @visibility_modifier
|
||||||
|
|
||||||
|
@current_scope = scope
|
||||||
end
|
end
|
||||||
|
|
||||||
private def on_scope_end(node)
|
private def on_scope_end(node)
|
||||||
@scope_queue << @current_scope
|
@scope_queue << @current_scope
|
||||||
|
|
||||||
|
@visibility_modifier = nil
|
||||||
|
|
||||||
# go up if this is not a top level scope
|
# go up if this is not a top level scope
|
||||||
return unless outer_scope = @current_scope.outer_scope
|
return unless outer_scope = @current_scope.outer_scope
|
||||||
@current_scope = outer_scope
|
@current_scope = outer_scope
|
||||||
|
@ -64,6 +71,12 @@ module Ameba::AST
|
||||||
end
|
end
|
||||||
{% end %}
|
{% end %}
|
||||||
|
|
||||||
|
# :nodoc:
|
||||||
|
def visit(node : Crystal::VisibilityModifier)
|
||||||
|
@visibility_modifier = node.modifier
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
# :nodoc:
|
# :nodoc:
|
||||||
def visit(node : Crystal::Yield)
|
def visit(node : Crystal::Yield)
|
||||||
@current_scope.yields = true
|
@current_scope.yields = true
|
||||||
|
|
Loading…
Reference in a new issue