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
|
||||
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
|
||||
rule = ScopeRule.new
|
||||
ScopeVisitor.new rule, Source.new <<-CRYSTAL
|
||||
|
@ -54,5 +65,31 @@ module Ameba::AST
|
|||
outer_block.outer_scope.should be_nil
|
||||
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
|
||||
|
|
|
@ -43,6 +43,9 @@ module Ameba
|
|||
description "Internal rule to test scopes"
|
||||
end
|
||||
|
||||
def test(source, node : Crystal::VisibilityModifier, scope : AST::Scope)
|
||||
end
|
||||
|
||||
def test(source, node : Crystal::ASTNode, scope : AST::Scope)
|
||||
@scopes << scope
|
||||
end
|
||||
|
|
|
@ -7,6 +7,9 @@ module Ameba::AST
|
|||
# Whether the scope yields.
|
||||
setter yields = false
|
||||
|
||||
# Scope visibility level
|
||||
setter visibility : Crystal::Visibility?
|
||||
|
||||
# Link to local variables
|
||||
getter variables = [] of Variable
|
||||
|
||||
|
@ -172,6 +175,11 @@ module Ameba::AST
|
|||
false
|
||||
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.
|
||||
def def?
|
||||
node.is_a?(Crystal::Def)
|
||||
|
|
|
@ -25,6 +25,7 @@ module Ameba::AST
|
|||
@scope_queue = [] of Scope
|
||||
@current_scope : Scope
|
||||
@current_assign : Crystal::ASTNode?
|
||||
@visibility_modifier : Crystal::Visibility?
|
||||
@skip : Array(Crystal::ASTNode.class)?
|
||||
|
||||
def initialize(@rule, @source, skip = nil)
|
||||
|
@ -36,12 +37,18 @@ module Ameba::AST
|
|||
|
||||
private def on_scope_enter(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
|
||||
|
||||
private def on_scope_end(node)
|
||||
@scope_queue << @current_scope
|
||||
|
||||
@visibility_modifier = nil
|
||||
|
||||
# go up if this is not a top level scope
|
||||
return unless outer_scope = @current_scope.outer_scope
|
||||
@current_scope = outer_scope
|
||||
|
@ -64,6 +71,12 @@ module Ameba::AST
|
|||
end
|
||||
{% end %}
|
||||
|
||||
# :nodoc:
|
||||
def visit(node : Crystal::VisibilityModifier)
|
||||
@visibility_modifier = node.modifier
|
||||
true
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
def visit(node : Crystal::Yield)
|
||||
@current_scope.yields = true
|
||||
|
|
Loading…
Reference in a new issue