Source file src/go/types/scope2.go

     1  // Copyright 2024 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This file implements go/types-specific scope methods.
     6  // These methods do not exist in types2.
     7  
     8  package types
     9  
    10  import "go/token"
    11  
    12  // LookupParent follows the parent chain of scopes starting with s until
    13  // it finds a scope where Lookup(name) returns a non-nil object, and then
    14  // returns that scope and object. If a valid position pos is provided,
    15  // only objects that were declared at or before pos are considered.
    16  // If no such scope and object exists, the result is (nil, nil).
    17  // The results are guaranteed to be valid only if the type-checked
    18  // AST has complete position information.
    19  //
    20  // Note that obj.Parent() may be different from the returned scope if the
    21  // object was inserted into the scope and already had a parent at that
    22  // time (see Insert). This can only happen for dot-imported objects
    23  // whose parent is the scope of the package that exported them.
    24  func (s *Scope) LookupParent(name string, pos token.Pos) (*Scope, Object) {
    25  	for ; s != nil; s = s.parent {
    26  		if obj := s.Lookup(name); obj != nil && (!pos.IsValid() || cmpPos(obj.scopePos(), pos) <= 0) {
    27  			return s, obj
    28  		}
    29  	}
    30  	return nil, nil
    31  }
    32  
    33  // Pos and End describe the scope's source code extent [pos, end).
    34  // The results are guaranteed to be valid only if the type-checked
    35  // AST has complete position information. The extent is undefined
    36  // for Universe and package scopes.
    37  func (s *Scope) Pos() token.Pos { return s.pos }
    38  func (s *Scope) End() token.Pos { return s.end }
    39  
    40  // Contains reports whether pos is within the scope's extent.
    41  // The result is guaranteed to be valid only if the type-checked
    42  // AST has complete position information.
    43  func (s *Scope) Contains(pos token.Pos) bool {
    44  	return cmpPos(s.pos, pos) <= 0 && cmpPos(pos, s.end) < 0
    45  }
    46  
    47  // Innermost returns the innermost (child) scope containing
    48  // pos. If pos is not within any scope, the result is nil.
    49  // The result is also nil for the Universe scope.
    50  // The result is guaranteed to be valid only if the type-checked
    51  // AST has complete position information.
    52  func (s *Scope) Innermost(pos token.Pos) *Scope {
    53  	// Package scopes do not have extents since they may be
    54  	// discontiguous, so iterate over the package's files.
    55  	if s.parent == Universe {
    56  		for _, s := range s.children {
    57  			if inner := s.Innermost(pos); inner != nil {
    58  				return inner
    59  			}
    60  		}
    61  	}
    62  
    63  	if s.Contains(pos) {
    64  		for _, s := range s.children {
    65  			if s.Contains(pos) {
    66  				return s.Innermost(pos)
    67  			}
    68  		}
    69  		return s
    70  	}
    71  	return nil
    72  }
    73  

View as plain text