@@ -12,6 +12,7 @@ import (
12
12
"go/constant"
13
13
"go/doc"
14
14
"go/format"
15
+ "go/printer"
15
16
"go/token"
16
17
"go/types"
17
18
"go/version"
@@ -241,10 +242,15 @@ func hover(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, pp pro
241
242
return * hoverRange , hoverRes , nil // (hoverRes may be nil)
242
243
}
243
244
}
244
- // Handle hovering over (non-import-path) literals.
245
+
246
+ // Handle hovering over various special kinds of syntax node.
245
247
if path , _ := astutil .PathEnclosingInterval (pgf .File , pos , pos ); len (path ) > 0 {
246
- if lit , _ := path [0 ].(* ast.BasicLit ); lit != nil {
247
- return hoverLit (pgf , lit , pos )
248
+ switch node := path [0 ].(type ) {
249
+ // Handle hovering over (non-import-path) literals.
250
+ case * ast.BasicLit :
251
+ return hoverLit (pgf , node , pos )
252
+ case * ast.ReturnStmt :
253
+ return hoverReturnStatement (pgf , path , node )
248
254
}
249
255
}
250
256
@@ -925,6 +931,45 @@ func hoverLit(pgf *parsego.File, lit *ast.BasicLit, pos token.Pos) (protocol.Ran
925
931
}, nil
926
932
}
927
933
934
+ func hoverReturnStatement (pgf * parsego.File , path []ast.Node , ret * ast.ReturnStmt ) (protocol.Range , * hoverResult , error ) {
935
+ var funcType * ast.FuncType
936
+ // Find innermost enclosing function.
937
+ for _ , n := range path {
938
+ switch n := n .(type ) {
939
+ case * ast.FuncLit :
940
+ funcType = n .Type
941
+ case * ast.FuncDecl :
942
+ funcType = n .Type
943
+ }
944
+ if funcType != nil {
945
+ break
946
+ }
947
+ }
948
+ // Inv: funcType != nil because a ReturnStmt is always enclosed by a function.
949
+ if funcType .Results == nil {
950
+ return protocol.Range {}, nil , nil // no result variables
951
+ }
952
+ rng , err := pgf .PosRange (ret .Pos (), ret .End ())
953
+ if err != nil {
954
+ return protocol.Range {}, nil , err
955
+ }
956
+ // Format the function's result type.
957
+ var buf strings.Builder
958
+ var cfg printer.Config
959
+ fset := token .NewFileSet ()
960
+ buf .WriteString ("returns (" )
961
+ for i , field := range funcType .Results .List {
962
+ if i > 0 {
963
+ buf .WriteString (", " )
964
+ }
965
+ cfg .Fprint (& buf , fset , field .Type )
966
+ }
967
+ buf .WriteByte (')' )
968
+ return rng , & hoverResult {
969
+ signature : buf .String (),
970
+ }, nil
971
+ }
972
+
928
973
// hoverEmbed computes hover information for a filepath.Match pattern.
929
974
// Assumes that the pattern is relative to the location of fh.
930
975
func hoverEmbed (fh file.Handle , rng protocol.Range , pattern string ) (protocol.Range , * hoverResult , error ) {
0 commit comments