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…
	
	Add table
		Add a link
		
	
		Reference in a new issue