@@ -218,7 +218,7 @@ func fromCallExpr(fset *token.FileSet, info *types.Info, pos token.Pos, call *as
218
218
return nil
219
219
}
220
220
221
- concType , pointer := concreteType (arg , info )
221
+ concType , pointer := concreteType (info , arg )
222
222
if concType == nil || concType .Obj ().Pkg () == nil {
223
223
return nil
224
224
}
@@ -272,7 +272,7 @@ func fromReturnStmt(fset *token.FileSet, info *types.Info, pos token.Pos, path [
272
272
return nil , fmt .Errorf ("pos %d not within return statement bounds: [%d-%d]" , pos , ret .Pos (), ret .End ())
273
273
}
274
274
275
- concType , pointer := concreteType (ret .Results [returnIdx ], info )
275
+ concType , pointer := concreteType (info , ret .Results [returnIdx ])
276
276
if concType == nil || concType .Obj ().Pkg () == nil {
277
277
return nil , nil // result is not a named or *named or alias thereof
278
278
}
@@ -330,7 +330,7 @@ func fromValueSpec(fset *token.FileSet, info *types.Info, spec *ast.ValueSpec, p
330
330
ifaceNode = call .Fun
331
331
rhs = call .Args [0 ]
332
332
}
333
- concType , pointer := concreteType (rhs , info )
333
+ concType , pointer := concreteType (info , rhs )
334
334
if concType == nil || concType .Obj ().Pkg () == nil {
335
335
return nil
336
336
}
@@ -385,7 +385,7 @@ func fromAssignStmt(fset *token.FileSet, info *types.Info, assign *ast.AssignStm
385
385
if ifaceObj == nil {
386
386
return nil
387
387
}
388
- concType , pointer := concreteType (rhs , info )
388
+ concType , pointer := concreteType (info , rhs )
389
389
if concType == nil || concType .Obj ().Pkg () == nil {
390
390
return nil
391
391
}
@@ -434,7 +434,7 @@ func ifaceObjFromType(t types.Type) *types.TypeName {
434
434
// method will return a nil *types.Named. The second return parameter
435
435
// is a boolean that indicates whether the concreteType was defined as a
436
436
// pointer or value.
437
- func concreteType (e ast. Expr , info * types.Info ) (* types.Named , bool ) {
437
+ func concreteType (info * types.Info , e ast. Expr ) (* types.Named , bool ) {
438
438
tv , ok := info .Types [e ]
439
439
if ! ok {
440
440
return nil , false
@@ -451,6 +451,7 @@ func concreteType(e ast.Expr, info *types.Info) (*types.Named, bool) {
451
451
return named , isPtr
452
452
}
453
453
454
+ // GetFieldStubInfo creates a StructFieldInfo instance to generate a struct field in a given SelectorExpr
454
455
func GetFieldStubInfo (fset * token.FileSet , info * types.Info , path []ast.Node ) * StructFieldInfo {
455
456
for _ , node := range path {
456
457
s , ok := node .(* ast.SelectorExpr )
@@ -460,43 +461,25 @@ func GetFieldStubInfo(fset *token.FileSet, info *types.Info, path []ast.Node) *S
460
461
// If recvExpr is a package name, compiler error would be
461
462
// e.g., "undefined: http.bar", thus will not hit this code path.
462
463
recvExpr := s .X
463
- recvType , _ := concreteType (recvExpr , info )
464
+ recvNamed , _ := concreteType (info , recvExpr )
464
465
465
- if recvType == nil || recvType .Obj ().Pkg () == nil {
466
+ if recvNamed == nil || recvNamed .Obj ().Pkg () == nil {
466
467
return nil
467
468
}
468
469
469
- // A method of a function-local type cannot be stubbed
470
- // since there's nowhere to put the methods.
471
- recv := recvType .Obj ()
472
- if recv .Parent () != recv .Pkg ().Scope () {
473
- return nil
474
- }
475
-
476
- obj := types .Object (recv )
477
- tv , ok := info .Types [s .X ]
478
- if ! ok {
479
- break
480
- }
481
-
482
- named , ok := tv .Type .(* types.Named )
483
- if ! ok {
484
- break
485
- }
486
-
487
- structType , ok := named .Underlying ().(* types.Struct )
470
+ structType , ok := recvNamed .Underlying ().(* types.Struct )
488
471
if ! ok {
489
472
break
490
473
}
491
474
475
+ // Have: x.f where x has a named struct type.
492
476
return & StructFieldInfo {
493
- Fset : fset ,
494
- Expr : s ,
495
- Struct : structType ,
496
- Named : named ,
497
- Info : info ,
498
- Path : path ,
499
- Object : obj ,
477
+ Fset : fset ,
478
+ Expr : s ,
479
+ Named : recvNamed ,
480
+ info : info ,
481
+ path : path ,
482
+ structType : structType ,
500
483
}
501
484
}
502
485
@@ -505,13 +488,18 @@ func GetFieldStubInfo(fset *token.FileSet, info *types.Info, path []ast.Node) *S
505
488
506
489
// StructFieldInfo describes f field in x.f where x has a named struct type
507
490
type StructFieldInfo struct {
508
- Fset * token.FileSet
509
- Expr * ast.SelectorExpr
510
- Struct * types.Struct
511
- Named * types.Named
512
- Info * types.Info
513
- Path []ast.Node
514
- Object types.Object
491
+ // Fset is a file set to provide a file where the struct field is accessed
492
+ Fset * token.FileSet
493
+ // Expr is a selector expression
494
+ Expr * ast.SelectorExpr
495
+ // Named is a selected struct type
496
+ Named * types.Named
497
+
498
+ info * types.Info
499
+ // path is a node path to SelectorExpr
500
+ path []ast.Node
501
+ // structType is an underlying struct type, makes sure the receiver is a struct
502
+ structType * types.Struct
515
503
}
516
504
517
505
// Emit writes to out the missing field based on type info.
@@ -521,22 +509,18 @@ func (si *StructFieldInfo) Emit(out *bytes.Buffer, qual types.Qualifier) error {
521
509
}
522
510
523
511
// Get types from context at the selector expression position
524
- typesFromContext := typesutil .TypesFromContext (si .Info , si .Path , si .Expr .Pos ())
512
+ typesFromContext := typesutil .TypesFromContext (si .info , si .path , si .Expr .Pos ())
525
513
526
- // Default to interface{} if we couldn't determine the type from context
514
+ // Default to any if we couldn't determine the type from context
527
515
var fieldType types.Type
528
516
if len (typesFromContext ) > 0 {
529
517
fieldType = typesFromContext [0 ]
530
518
} else {
531
- // Create a new interface{} type
532
519
fieldType = types .Universe .Lookup ("any" ).Type ()
533
520
}
534
521
535
- out .Write ([]byte {'\n' , '\t' })
536
- out .WriteString (si .Expr .Sel .Name )
537
- out .WriteByte (' ' )
538
- out .WriteString (types .TypeString (fieldType , qual ))
539
- if si .Struct .NumFields () == 0 {
522
+ fmt .Fprintf (out , "\n \t %s %s" , si .Expr .Sel .Name , types .TypeString (fieldType , qual ))
523
+ if si .structType .NumFields () == 0 {
540
524
out .WriteByte ('\n' )
541
525
}
542
526
return nil
0 commit comments