Skip to content

Commit 91815f4

Browse files
authored
Track context package/type to make dst.Decorator.ResolveLocalPath unnecessary (#109)
* Track context package/type to make dst.Decorator.ResolveLocalPath unnecessary * Revert accidental code gen change from a later PR * Reduce duplication in tests * Appease various linters * Fix test reference issue * Remove mock for future change * ~~Remove mock for future change~~ Just make the mock accurate for current interface
1 parent d78281d commit 91815f4

22 files changed

Lines changed: 16200 additions & 6630 deletions

ast/cache.go

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -194,18 +194,19 @@ func (c *Cache) Type(id dst.Ident, contextPkg string, testImport bool) (TypeInfo
194194
}, nil
195195
}
196196

197-
// IsComparable determines if an expression is comparable
198-
func (c *Cache) IsComparable(expr dst.Expr) (bool, error) {
199-
return c.isDefaultComparable(expr, true)
197+
// IsComparable determines if an expression is comparable. The optional
198+
// parentType can be used to supply type parameters.
199+
func (c *Cache) IsComparable(expr dst.Expr, parentType TypeInfo) (bool, error) {
200+
return c.isDefaultComparable(expr, &parentType, true)
200201
}
201202

202203
// IsDefaultComparable determines if an expression is comparable. Returns the
203204
// same results as IsComparable but pointers and interfaces are not comparable
204205
// by default (interface implementations that are not comparable and put into a
205206
// map key will panic at runtime and by default pointers use a deep hash to be
206207
// comparable).
207-
func (c *Cache) IsDefaultComparable(expr dst.Expr) (bool, error) {
208-
return c.isDefaultComparable(expr, false)
208+
func (c *Cache) IsDefaultComparable(expr dst.Expr, parentType TypeInfo) (bool, error) {
209+
return c.isDefaultComparable(expr, &parentType, false)
209210
}
210211

211212
// FindPackage finds the package for a given directory
@@ -363,17 +364,21 @@ func isExported(name, pkgPath string) bool {
363364
return false
364365
}
365366

366-
func (c *Cache) isDefaultComparable(expr dst.Expr, interfacePointerDefault bool) (bool, error) {
367+
func (c *Cache) isDefaultComparable(
368+
expr dst.Expr,
369+
parentType *TypeInfo,
370+
interfacePointerDefault bool,
371+
) (bool, error) {
367372
switch e := expr.(type) {
368373
case *dst.ArrayType:
369374
if e.Len == nil {
370375
return false, nil
371376
}
372-
return c.isDefaultComparable(e.Elt, interfacePointerDefault)
373-
case *dst.MapType, *dst.Ellipsis, *dst.FuncType:
377+
return c.isDefaultComparable(e.Elt, parentType, interfacePointerDefault)
378+
case *dst.Ellipsis:
379+
return false, nil
380+
case *dst.FuncType:
374381
return false, nil
375-
case *dst.StarExpr:
376-
return interfacePointerDefault, nil
377382
case *dst.InterfaceType:
378383
return interfacePointerDefault, nil
379384
case *dst.Ident:
@@ -387,11 +392,22 @@ func (c *Cache) isDefaultComparable(expr dst.Expr, interfacePointerDefault bool)
387392
return true, nil
388393
}
389394

390-
return c.isDefaultComparable(typ.Type, interfacePointerDefault)
395+
return c.isDefaultComparable(typ.Type, parentType, interfacePointerDefault)
391396
}
397+
pkgPath := e.Path
392398
typ, ok := c.typesByIdent[e.String()]
399+
if !ok && e.Path == "" && parentType != nil {
400+
pkgPath = parentType.PkgPath
401+
typ, ok = c.typesByIdent[IdPath(e.Name, parentType.PkgPath).String()]
402+
}
393403
if ok {
394-
return c.isDefaultComparable(typ.typ.Type, interfacePointerDefault)
404+
tInfo := &TypeInfo{
405+
Type: typ.typ,
406+
PkgPath: pkgPath,
407+
Exported: isExported(e.Name, pkgPath),
408+
Fabricated: false,
409+
}
410+
return c.isDefaultComparable(typ.typ.Type, tInfo, interfacePointerDefault)
395411
}
396412

397413
// Builtin type?
@@ -412,10 +428,18 @@ func (c *Cache) isDefaultComparable(expr dst.Expr, interfacePointerDefault bool)
412428

413429
typ, ok = c.typesByIdent[e.String()]
414430
if ok {
415-
return c.isDefaultComparable(typ.typ.Type, interfacePointerDefault)
431+
tInfo := &TypeInfo{
432+
Type: typ.typ,
433+
PkgPath: e.Path,
434+
Exported: isExported(e.Name, e.Path),
435+
Fabricated: false,
436+
}
437+
return c.isDefaultComparable(typ.typ.Type, tInfo, interfacePointerDefault)
416438
}
417439

418440
return true, nil
441+
case *dst.MapType:
442+
return false, nil
419443
case *dst.SelectorExpr:
420444
ex, ok := e.X.(*dst.Ident)
421445
if !ok {
@@ -429,14 +453,16 @@ func (c *Cache) isDefaultComparable(expr dst.Expr, interfacePointerDefault bool)
429453

430454
typ, ok := c.typesByIdent[IdPath(e.Sel.Name, path).String()]
431455
if ok {
432-
return c.isDefaultComparable(typ.typ.Type, interfacePointerDefault)
456+
return c.isDefaultComparable(typ.typ.Type, parentType, interfacePointerDefault)
433457
}
434458

435459
// Builtin type?
436460
return true, nil
461+
case *dst.StarExpr:
462+
return interfacePointerDefault, nil
437463
case *dst.StructType:
438464
for _, f := range e.Fields.List {
439-
comp, err := c.isDefaultComparable(f.Type, interfacePointerDefault)
465+
comp, err := c.isDefaultComparable(f.Type, parentType, interfacePointerDefault)
440466
if err != nil || !comp {
441467
return false, err
442468
}
@@ -501,19 +527,6 @@ func (c *Cache) loadTypes(loadPkg string, testImport bool) (string, error) {
501527
}
502528

503529
func (c *Cache) loadAST(loadPkg string, testImport bool) ([]*pkgInfo, error) {
504-
if dp, ok := c.loadedPkgs[loadPkg]; ok {
505-
// If we already loaded the test types or if the test types aren't
506-
// requested, we're done
507-
if dp.loadTestPkgs || !testImport {
508-
// If we direct loaded, we're done
509-
if dp.directLoaded {
510-
c.metrics.ASTTypeCacheHitsInc()
511-
return []*pkgInfo{dp}, nil
512-
}
513-
}
514-
}
515-
c.metrics.ASTTypeCacheMissesInc()
516-
517530
start := time.Now()
518531
pkgs, err := c.load(&packages.Config{
519532
Mode: packages.NeedName |
@@ -597,7 +610,6 @@ func (c *Cache) convert(pkg *packages.Package, testImport, directLoaded bool) (*
597610

598611
start := time.Now()
599612
p.pkg.Decorator = decorator.NewDecoratorFromPackage(pkg)
600-
p.pkg.Decorator.ResolveLocalPath = true
601613
for _, f := range pkg.Syntax {
602614
fpath := pkg.Fset.File(f.Pos()).Name()
603615
if !goFiles[fpath] {

0 commit comments

Comments
 (0)