@@ -113,6 +113,20 @@ const (
113
113
opObj = 'O' // .Obj() (Named, TypeParam)
114
114
)
115
115
116
+ // For is equivalent to new(Encoder).For(obj).
117
+ //
118
+ // It may be more efficient to reuse a single Encoder across several calls.
119
+ func For (obj types.Object ) (Path , error ) {
120
+ return new (Encoder ).For (obj )
121
+ }
122
+
123
+ // An Encoder amortizes the cost of encoding the paths of multiple objects.
124
+ // The zero value of an Encoder is ready to use.
125
+ type Encoder struct {
126
+ scopeNamesMemo map [* types.Scope ][]string // memoization of Scope.Names()
127
+ namedMethodsMemo map [* types.Named ][]* types.Func // memoization of namedMethods()
128
+ }
129
+
116
130
// For returns the path to an object relative to its package,
117
131
// or an error if the object is not accessible from the package's Scope.
118
132
//
@@ -145,24 +159,7 @@ const (
145
159
// .Type().Field(0) (field Var X)
146
160
//
147
161
// where p is the package (*types.Package) to which X belongs.
148
- func For (obj types.Object ) (Path , error ) {
149
- return newEncoderFor ()(obj )
150
- }
151
-
152
- // An encoder amortizes the cost of encoding the paths of multiple objects.
153
- // Nonexported pending approval of proposal 58668.
154
- type encoder struct {
155
- scopeNamesMemo map [* types.Scope ][]string // memoization of Scope.Names()
156
- namedMethodsMemo map [* types.Named ][]* types.Func // memoization of namedMethods()
157
- }
158
-
159
- // Exposed to gopls via golang.org/x/tools/internal/typesinternal
160
- // pending approval of proposal 58668.
161
- //
162
- //go:linkname newEncoderFor
163
- func newEncoderFor () func (types.Object ) (Path , error ) { return new (encoder ).For }
164
-
165
- func (enc * encoder ) For (obj types.Object ) (Path , error ) {
162
+ func (enc * Encoder ) For (obj types.Object ) (Path , error ) {
166
163
pkg := obj .Pkg ()
167
164
168
165
// This table lists the cases of interest.
@@ -341,7 +338,7 @@ func appendOpArg(path []byte, op byte, arg int) []byte {
341
338
// This function is just an optimization that avoids the general scope walking
342
339
// approach. You are expected to fall back to the general approach if this
343
340
// function fails.
344
- func (enc * encoder ) concreteMethod (meth * types.Func ) (Path , bool ) {
341
+ func (enc * Encoder ) concreteMethod (meth * types.Func ) (Path , bool ) {
345
342
// Concrete methods can only be declared on package-scoped named types. For
346
343
// that reason we can skip the expensive walk over the package scope: the
347
344
// path will always be package -> named type -> method. We can trivially get
@@ -730,23 +727,8 @@ func namedMethods(named *types.Named) []*types.Func {
730
727
return methods
731
728
}
732
729
733
- // scopeNames is a memoization of scope.Names. Callers must not modify the result.
734
- func (enc * encoder ) scopeNames (scope * types.Scope ) []string {
735
- m := enc .scopeNamesMemo
736
- if m == nil {
737
- m = make (map [* types.Scope ][]string )
738
- enc .scopeNamesMemo = m
739
- }
740
- names , ok := m [scope ]
741
- if ! ok {
742
- names = scope .Names () // allocates and sorts
743
- m [scope ] = names
744
- }
745
- return names
746
- }
747
-
748
730
// namedMethods is a memoization of the namedMethods function. Callers must not modify the result.
749
- func (enc * encoder ) namedMethods (named * types.Named ) []* types.Func {
731
+ func (enc * Encoder ) namedMethods (named * types.Named ) []* types.Func {
750
732
m := enc .namedMethodsMemo
751
733
if m == nil {
752
734
m = make (map [* types.Named ][]* types.Func )
@@ -758,5 +740,19 @@ func (enc *encoder) namedMethods(named *types.Named) []*types.Func {
758
740
m [named ] = methods
759
741
}
760
742
return methods
743
+ }
761
744
745
+ // scopeNames is a memoization of scope.Names. Callers must not modify the result.
746
+ func (enc * Encoder ) scopeNames (scope * types.Scope ) []string {
747
+ m := enc .scopeNamesMemo
748
+ if m == nil {
749
+ m = make (map [* types.Scope ][]string )
750
+ enc .scopeNamesMemo = m
751
+ }
752
+ names , ok := m [scope ]
753
+ if ! ok {
754
+ names = scope .Names () // allocates and sorts
755
+ m [scope ] = names
756
+ }
757
+ return names
762
758
}
0 commit comments