@@ -143,7 +143,7 @@ func hover(ctx context.Context, snapshot Snapshot, fh FileHandle, pp protocol.Po
143
143
// There's not much useful information to provide.
144
144
if selectedType != nil {
145
145
fakeObj := types .NewVar (obj .Pos (), obj .Pkg (), obj .Name (), selectedType )
146
- signature := objectString (fakeObj , qf , nil )
146
+ signature := types . ObjectString (fakeObj , qf )
147
147
return rng , & HoverJSON {
148
148
Signature : signature ,
149
149
SingleLine : signature ,
@@ -168,10 +168,15 @@ func hover(ctx context.Context, snapshot Snapshot, fh FileHandle, pp protocol.Po
168
168
docText := comment .Text ()
169
169
170
170
// By default, types.ObjectString provides a reasonable signature.
171
- signature := objectString (obj , qf , nil )
171
+ signature := objectString (obj , qf , declPos , declPGF .Tok , spec )
172
+ singleLineSignature := signature
173
+
172
174
// TODO(rfindley): we could do much better for inferred signatures.
173
175
if inferred := inferredSignature (pkg .GetTypesInfo (), ident ); inferred != nil {
174
- signature = objectString (obj , qf , inferred )
176
+ s := inferredSignatureString (obj , qf , inferred )
177
+ if s != "" {
178
+ signature = s
179
+ }
175
180
}
176
181
177
182
// For "objects defined by a type spec", the signature produced by
@@ -214,7 +219,7 @@ func hover(ctx context.Context, snapshot Snapshot, fh FileHandle, pp protocol.Po
214
219
if (m .Obj ().Exported () || m .Obj ().Pkg () == pkg .GetTypes ()) && len (m .Index ()) == 1 {
215
220
b .WriteString (sep )
216
221
sep = "\n "
217
- b .WriteString (objectString (m .Obj (), qf , nil ))
222
+ b .WriteString (types . ObjectString (m .Obj (), qf ))
218
223
}
219
224
}
220
225
}
@@ -321,7 +326,7 @@ func hover(ctx context.Context, snapshot Snapshot, fh FileHandle, pp protocol.Po
321
326
return rng , & HoverJSON {
322
327
Synopsis : doc .Synopsis (docText ),
323
328
FullDocumentation : docText ,
324
- SingleLine : objectString ( obj , qf , nil ) ,
329
+ SingleLine : singleLineSignature ,
325
330
SymbolName : linkName ,
326
331
Signature : signature ,
327
332
LinkPath : linkPath ,
@@ -577,12 +582,10 @@ func hoverLit(pgf *ParsedGoFile, lit *ast.BasicLit, pos token.Pos) (protocol.Ran
577
582
}, nil
578
583
}
579
584
580
- // objectString is a wrapper around the types.ObjectString function.
581
- // It handles adding more information to the object string.
582
- //
583
- // TODO(rfindley): this function does too much. We should lift the special
584
- // handling to callsites.
585
- func objectString (obj types.Object , qf types.Qualifier , inferred * types.Signature ) string {
585
+ // inferredSignatureString is a wrapper around the types.ObjectString function
586
+ // that adds more information to inferred signatures. It will return an empty string
587
+ // if passed types.Object is not a signature.
588
+ func inferredSignatureString (obj types.Object , qf types.Qualifier , inferred * types.Signature ) string {
586
589
// If the signature type was inferred, prefer the inferred signature with a
587
590
// comment showing the generic signature.
588
591
if sig , _ := obj .Type ().(* types.Signature ); sig != nil && typeparams .ForSignature (sig ).Len () > 0 && inferred != nil {
@@ -597,22 +600,58 @@ func objectString(obj types.Object, qf types.Qualifier, inferred *types.Signatur
597
600
str += "// " + types .TypeString (sig , qf )
598
601
return str
599
602
}
603
+ return ""
604
+ }
605
+
606
+ // objectString is a wrapper around the types.ObjectString function.
607
+ // It handles adding more information to the object string.
608
+ func objectString (obj types.Object , qf types.Qualifier , declPos token.Pos , file * token.File , spec ast.Spec ) string {
600
609
str := types .ObjectString (obj , qf )
610
+
601
611
switch obj := obj .(type ) {
602
612
case * types.Const :
603
- str = fmt . Sprintf ( "%s = %s" , str , obj .Val ())
613
+ declaration := obj .Val (). String ( )
604
614
605
- // Try to add a formatted duration as an inline comment
606
- typ , ok := obj .Type ().(* types.Named )
607
- if ! ok {
608
- break
615
+ // Try to use the original declaration.
616
+ switch obj .Val ().Kind () {
617
+ case constant .String :
618
+ // Usually the original declaration of a string doesn't carry much information.
619
+ // Also strings can be very long. So, just use the constant's value.
620
+
621
+ default :
622
+ if file == nil || spec == nil {
623
+ break
624
+ }
625
+
626
+ switch spec := spec .(type ) {
627
+ case * ast.ValueSpec :
628
+ for i , name := range spec .Names {
629
+ if declPos == name .Pos () {
630
+ if i < len (spec .Values ) {
631
+ declaration = FormatNodeFile (file , spec .Values [i ])
632
+ }
633
+ break
634
+ }
635
+ }
636
+ }
609
637
}
610
- pkg := typ .Obj ().Pkg ()
611
- if pkg .Path () == "time" && typ .Obj ().Name () == "Duration" {
612
- if d , ok := constant .Int64Val (obj .Val ()); ok {
613
- str += " // " + time .Duration (d ).String ()
638
+
639
+ comment := obj .Val ().String ()
640
+ switch typ := obj .Type ().(type ) {
641
+ case * types.Named :
642
+ // Try to add a formatted duration as an inline comment.
643
+ pkg := typ .Obj ().Pkg ()
644
+ if pkg .Path () == "time" && typ .Obj ().Name () == "Duration" {
645
+ if d , ok := constant .Int64Val (obj .Val ()); ok {
646
+ comment = time .Duration (d ).String ()
647
+ }
614
648
}
615
649
}
650
+
651
+ str += " = " + declaration
652
+ if declaration != comment {
653
+ str += " // " + comment
654
+ }
616
655
}
617
656
return str
618
657
}
@@ -708,28 +747,6 @@ func parseFull(ctx context.Context, snapshot Snapshot, fset *token.FileSet, pos
708
747
return pgf , fullPos , nil
709
748
}
710
749
711
- // extractFieldList recursively tries to extract a field list.
712
- // If it is not found, nil is returned.
713
- func extractFieldList (specType ast.Expr ) * ast.FieldList {
714
- switch t := specType .(type ) {
715
- case * ast.StructType :
716
- return t .Fields
717
- case * ast.InterfaceType :
718
- return t .Methods
719
- case * ast.ArrayType :
720
- return extractFieldList (t .Elt )
721
- case * ast.MapType :
722
- // Map value has a greater chance to be a struct
723
- if fields := extractFieldList (t .Value ); fields != nil {
724
- return fields
725
- }
726
- return extractFieldList (t .Key )
727
- case * ast.ChanType :
728
- return extractFieldList (t .Value )
729
- }
730
- return nil
731
- }
732
-
733
750
func formatHover (h * HoverJSON , options * Options ) (string , error ) {
734
751
signature := formatSignature (h , options )
735
752
0 commit comments