Skip to content

Commit e9adae9

Browse files
committed
add cache and reverse pointer to Universe to Type
1 parent 85fd79d commit e9adae9

File tree

2 files changed

+62
-15
lines changed

2 files changed

+62
-15
lines changed

v2/parser/parse.go

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"path/filepath"
2727
"sort"
2828
"strings"
29+
"sync"
2930
"time"
3031

3132
"golang.org/x/tools/go/packages"
@@ -637,6 +638,13 @@ func (p *Parser) convertSignature(u types.Universe, t *gotypes.Signature) *types
637638

638639
// walkType adds the type, and any necessary child types.
639640
func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type) *types.Type {
641+
var out *types.Type
642+
defer func() {
643+
out.Universe = &u
644+
out.PointerTypeCache = &types.PointerTypeCache{
645+
Mu: sync.Mutex{},
646+
}
647+
}()
640648
// Most of the cases are underlying types of the named type.
641649
name := goNameToName(in.String())
642650
if useName != nil {
@@ -645,13 +653,13 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
645653

646654
// Handle alias types conditionally on go1.22+.
647655
// Inline this once the minimum supported version is go1.22
648-
if out := p.walkAliasType(u, in); out != nil {
656+
if out = p.walkAliasType(u, in); out != nil {
649657
return out
650658
}
651659

652660
switch t := in.(type) {
653661
case *gotypes.Struct:
654-
out := u.Type(name)
662+
out = u.Type(name)
655663
out.GoType = in
656664
if out.Kind != types.Unknown {
657665
return out
@@ -670,7 +678,7 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
670678
}
671679
return out
672680
case *gotypes.Map:
673-
out := u.Type(name)
681+
out = u.Type(name)
674682
out.GoType = in
675683
if out.Kind != types.Unknown {
676684
return out
@@ -680,7 +688,7 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
680688
out.Key = p.walkType(u, nil, t.Key())
681689
return out
682690
case *gotypes.Pointer:
683-
out := u.Type(name)
691+
out = u.Type(name)
684692
out.GoType = in
685693
if out.Kind != types.Unknown {
686694
return out
@@ -689,7 +697,7 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
689697
out.Elem = p.walkType(u, nil, t.Elem())
690698
return out
691699
case *gotypes.Slice:
692-
out := u.Type(name)
700+
out = u.Type(name)
693701
out.GoType = in
694702
if out.Kind != types.Unknown {
695703
return out
@@ -698,7 +706,7 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
698706
out.Elem = p.walkType(u, nil, t.Elem())
699707
return out
700708
case *gotypes.Array:
701-
out := u.Type(name)
709+
out = u.Type(name)
702710
out.GoType = in
703711
if out.Kind != types.Unknown {
704712
return out
@@ -708,7 +716,7 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
708716
out.Len = in.(*gotypes.Array).Len()
709717
return out
710718
case *gotypes.Chan:
711-
out := u.Type(name)
719+
out = u.Type(name)
712720
out.GoType = in
713721
if out.Kind != types.Unknown {
714722
return out
@@ -719,7 +727,7 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
719727
// cannot be properly written.
720728
return out
721729
case *gotypes.Basic:
722-
out := u.Type(types.Name{
730+
out = u.Type(types.Name{
723731
Package: "", // This is a magic package name in the Universe.
724732
Name: t.Name(),
725733
})
@@ -730,7 +738,7 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
730738
out.Kind = types.Unsupported
731739
return out
732740
case *gotypes.Signature:
733-
out := u.Type(name)
741+
out = u.Type(name)
734742
out.GoType = in
735743
if out.Kind != types.Unknown {
736744
return out
@@ -739,7 +747,7 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
739747
out.Signature = p.convertSignature(u, t)
740748
return out
741749
case *gotypes.Interface:
742-
out := u.Type(name)
750+
out = u.Type(name)
743751
out.GoType = in
744752
if out.Kind != types.Unknown {
745753
return out
@@ -758,7 +766,6 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
758766
}
759767
return out
760768
case *gotypes.Named:
761-
var out *types.Type
762769
switch t.Underlying().(type) {
763770
case *gotypes.Named, *gotypes.Basic, *gotypes.Map, *gotypes.Slice:
764771
name := goNameToName(t.String())
@@ -785,7 +792,7 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
785792
name.Name = fmt.Sprintf("%s[%s]", strings.SplitN(name.Name, "[", 2)[0], strings.Join(tpNames, ","))
786793
}
787794

788-
if out := u.Type(name); out.Kind != types.Unknown {
795+
if out = u.Type(name); out.Kind != types.Unknown {
789796
out.GoType = in
790797
return out // short circuit if we've already made this.
791798
}
@@ -797,7 +804,7 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
797804
// "feature" for users. This flattens those types
798805
// together.
799806
name := goNameToName(t.String())
800-
if out := u.Type(name); out.Kind != types.Unknown {
807+
if out = u.Type(name); out.Kind != types.Unknown {
801808
return out // short circuit if we've already made this.
802809
}
803810
out = p.walkType(u, &name, t.Underlying())
@@ -827,7 +834,7 @@ func (p *Parser) walkType(u types.Universe, useName *types.Name, in gotypes.Type
827834
Kind: types.TypeParam,
828835
}
829836
default:
830-
out := u.Type(name)
837+
out = u.Type(name)
831838
out.GoType = in
832839
if out.Kind != types.Unknown {
833840
return out

v2/types/types.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package types
1919
import (
2020
gotypes "go/types"
2121
"strings"
22+
"sync"
2223
)
2324

2425
// Ref makes a reference to the given type. It can only be used for e.g.
@@ -289,6 +290,13 @@ func (u Universe) Package(packagePath string) *Package {
289290
return p
290291
}
291292

293+
type PointerTypeCache struct {
294+
// mutex to protect concurrent update to the cache
295+
Mu sync.Mutex
296+
// A pointer Type for the Type
297+
PointerType *Type
298+
}
299+
292300
// Type represents a subset of possible go types.
293301
type Type struct {
294302
// There are two general categories of types, those explicitly named
@@ -364,6 +372,12 @@ type Type struct {
364372

365373
// The underlying Go type.
366374
GoType gotypes.Type
375+
376+
// Revevrse reference to Universe
377+
Universe *Universe
378+
379+
// A pointer type cache
380+
PointerTypeCache *PointerTypeCache
367381
}
368382

369383
// String returns the name of the type.
@@ -556,13 +570,39 @@ var (
556570
)
557571

558572
func PointerTo(t *Type) *Type {
559-
return &Type{
573+
for _, pkg := range *t.Universe {
574+
for _, tp := range pkg.Types {
575+
existingTypeName := tp.Name.String()
576+
if strings.HasPrefix(existingTypeName, "*") {
577+
if existingTypeName[1:] == t.Name.String() {
578+
return tp
579+
}
580+
}
581+
}
582+
}
583+
cache := t.PointerTypeCache
584+
if cache != nil && cache.PointerType != nil {
585+
return cache.PointerType
586+
}
587+
out := &Type{
560588
Name: Name{
561589
Name: "*" + t.Name.String(),
562590
},
563591
Kind: Pointer,
564592
Elem: t,
565593
}
594+
// PointerTypeCache should not be empty at this point. This is a sanity processing.
595+
if cache == nil {
596+
cache = &PointerTypeCache{
597+
Mu: sync.Mutex{},
598+
}
599+
}
600+
if cache.PointerType == nil {
601+
cache.Mu.Lock()
602+
cache.PointerType = out
603+
cache.Mu.Unlock()
604+
}
605+
return out
566606
}
567607

568608
func IsInteger(t *Type) bool {

0 commit comments

Comments
 (0)