@@ -340,17 +340,42 @@ func describeValue(qpos *queryPos, path []ast.Node) (*describeValueResult, error
340
340
qpos : qpos ,
341
341
expr : expr ,
342
342
typ : typ ,
343
+ names : appendNames (nil , typ ),
343
344
constVal : constVal ,
344
345
obj : obj ,
345
346
methods : accessibleMethods (typ , qpos .info .Pkg ),
346
347
fields : accessibleFields (typ , qpos .info .Pkg ),
347
348
}, nil
348
349
}
349
350
351
+ // appendNames returns named types found within the Type by
352
+ // removing map, pointer, channel, slice, and array constructors.
353
+ // It does not descend into structs or interfaces.
354
+ func appendNames (names []* types.Named , typ types.Type ) []* types.Named {
355
+ // elemType specifies type that has some element in it
356
+ // such as array, slice, chan, pointer
357
+ type elemType interface {
358
+ Elem () types.Type
359
+ }
360
+
361
+ switch t := typ .(type ) {
362
+ case * types.Named :
363
+ names = append (names , t )
364
+ case * types.Map :
365
+ names = appendNames (names , t .Key ())
366
+ names = appendNames (names , t .Elem ())
367
+ case elemType :
368
+ names = appendNames (names , t .Elem ())
369
+ }
370
+
371
+ return names
372
+ }
373
+
350
374
type describeValueResult struct {
351
375
qpos * queryPos
352
376
expr ast.Expr // query node
353
377
typ types.Type // type of expression
378
+ names []* types.Named // named types within typ
354
379
constVal constant.Value // value of expression, if constant
355
380
obj types.Object // var/func/const object, if expr was Ident
356
381
methods []* types.Selection
@@ -398,6 +423,7 @@ func (r *describeValueResult) PrintPlain(printf printfFunc) {
398
423
399
424
printMethods (printf , r .expr , r .methods )
400
425
printFields (printf , r .expr , r .fields )
426
+ printNamedTypes (printf , r .expr , r .names )
401
427
}
402
428
403
429
func (r * describeValueResult ) JSON (fset * token.FileSet ) []byte {
@@ -409,14 +435,23 @@ func (r *describeValueResult) JSON(fset *token.FileSet) []byte {
409
435
objpos = fset .Position (r .obj .Pos ()).String ()
410
436
}
411
437
438
+ typesPos := make ([]serial.Definition , len (r .names ))
439
+ for i , t := range r .names {
440
+ typesPos [i ] = serial.Definition {
441
+ ObjPos : fset .Position (t .Obj ().Pos ()).String (),
442
+ Desc : r .qpos .typeString (t ),
443
+ }
444
+ }
445
+
412
446
return toJSON (& serial.Describe {
413
447
Desc : astutil .NodeDescription (r .expr ),
414
448
Pos : fset .Position (r .expr .Pos ()).String (),
415
449
Detail : "value" ,
416
450
Value : & serial.DescribeValue {
417
- Type : r .qpos .typeString (r .typ ),
418
- Value : value ,
419
- ObjPos : objpos ,
451
+ Type : r .qpos .typeString (r .typ ),
452
+ TypesPos : typesPos ,
453
+ Value : value ,
454
+ ObjPos : objpos ,
420
455
},
421
456
})
422
457
}
@@ -524,6 +559,19 @@ func printFields(printf printfFunc, node ast.Node, fields []describeField) {
524
559
}
525
560
}
526
561
562
+ func printNamedTypes (printf printfFunc , node ast.Node , names []* types.Named ) {
563
+ if len (names ) > 0 {
564
+ printf (node , "Named types:" )
565
+ }
566
+
567
+ for _ , t := range names {
568
+ // Print the type relative to the package
569
+ // in which it was defined, not the query package,
570
+ printf (t .Obj (), "\t type %s defined here" ,
571
+ types .TypeString (t .Obj ().Type (), types .RelativeTo (t .Obj ().Pkg ())))
572
+ }
573
+ }
574
+
527
575
func (r * describeTypeResult ) PrintPlain (printf printfFunc ) {
528
576
printf (r .node , "%s" , r .description )
529
577
0 commit comments