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