diff --git a/internal/lsp/check.go b/internal/lsp/check.go index 7b607a3..7d7cefc 100644 --- a/internal/lsp/check.go +++ b/internal/lsp/check.go @@ -260,6 +260,8 @@ func mode(tv types.TypeAndValue) string { return "mapindex" case tv.IsValue(): return "value" + case tv.IsType(): + return "type" default: return "unknown" } diff --git a/internal/lsp/completion.go b/internal/lsp/completion.go index 056b6e6..7189f63 100644 --- a/internal/lsp/completion.go +++ b/internal/lsp/completion.go @@ -267,7 +267,7 @@ func PackageFromDir(path string, onlyExports bool) (*Package, error) { if t.Recv.NumFields() > 0 && t.Recv.List[0].Type != nil { switch rt := t.Recv.List[0].Type.(type) { case *ast.StarExpr: - k := fmt.Sprintf("*%s", rt.X) + k := fmt.Sprintf("%s", rt.X) m := &Method{ Position: fset.Position(t.Pos()), FileURI: getURI(absPath), diff --git a/internal/lsp/hover.go b/internal/lsp/hover.go index c600619..e3a94a7 100644 --- a/internal/lsp/hover.go +++ b/internal/lsp/hover.go @@ -79,8 +79,14 @@ func (s *server) Hover(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2 break } typeStr := tv.Type.String() + m := mode(*tv) - // local + // local type + if (strings.HasPrefix(typeStr, pkg.ImportPath) || + strings.HasPrefix(typeStr, "*"+pkg.ImportPath)) && m == "type" { + typeStr := parseType(typeStr, pkg.ImportPath) + return hoverLocalTypes(ctx, reply, params, pkg, i, tv, typeStr) + } // Handle builtins if doc, ok := isBuiltin(i, tv); ok { @@ -262,6 +268,45 @@ func (s *server) Hover(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2 return reply(ctx, nil, nil) } +func hoverLocalTypes(ctx context.Context, reply jsonrpc2.Replier, params protocol.HoverParams, pkg *Package, i *ast.Ident, tv *types.TypeAndValue, typeName string) error { + // Look into structures + var structure *Structure + for _, st := range pkg.Structures { + if st.Name == fmt.Sprintf("%s", typeName) { + structure = st + break + } + } + if structure == nil { + return reply(ctx, nil, nil) + } + var header, body string + header = fmt.Sprintf("%s %s %s\n\n", mode(*tv), structure.Name, structure.String) + + methods, ok := pkg.Methods.Get(typeName) + if ok { + body = "```gno\n" + for _, m := range methods { + if m.IsExported() { + body += fmt.Sprintf("%s\n", m.Signature) + } + } + body += "```\n" + body += structure.Doc + "\n" + } + + return reply(ctx, protocol.Hover{ + Contents: protocol.MarkupContent{ + Kind: protocol.Markdown, + Value: FormatHoverContent(header, body), + }, + Range: posToRange( + int(params.Position.Line), + []int{int(i.Pos()), int(i.End())}, + ), + }, nil) +} + func hoverBuiltinTypes(ctx context.Context, reply jsonrpc2.Replier, params protocol.HoverParams, i *ast.Ident, tv *types.TypeAndValue, doc string) error { t := tv.Type.String() m := mode(*tv) @@ -537,3 +582,9 @@ func pathEnclosingObjNode(f *ast.File, pos token.Pos) []ast.Node { return path } +// parseType parses the type name from full path and return +// the type as string and if it is isStar expr. +func parseType(t, importpath string) string { + return strings.TrimPrefix(strings.TrimPrefix(t, "*"), importpath+".") +} +