Skip to content
This repository has been archived by the owner on May 29, 2024. It is now read-only.

Commit

Permalink
Definition support for symbols
Browse files Browse the repository at this point in the history
Implement initial definition support, enabling users to navigate
to symbol definitions.
  • Loading branch information
harry-hov committed Jan 6, 2024
1 parent 00aff27 commit b629683
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 9 deletions.
29 changes: 20 additions & 9 deletions internal/lsp/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

"go.lsp.dev/jsonrpc2"
"go.lsp.dev/protocol"
"go.lsp.dev/uri"
)

type CompletionStore struct {
Expand Down Expand Up @@ -69,6 +70,8 @@ type Package struct {
}

type Symbol struct {
Position token.Position
FileURI uri.URI
Name string
Doc string
Signature string
Expand Down Expand Up @@ -172,11 +175,13 @@ func InitCompletionStore(dirs []string) *CompletionStore {

func getSymbols(fname string) []*Symbol {
var symbols []*Symbol

bsrc, err := os.ReadFile(fname)
absPath, err := filepath.Abs(fname)
if err != nil {
// Ignore error and return empty symbol list
return symbols
return symbols // Ignore error and return empty symbol list
}
bsrc, err := os.ReadFile(absPath)
if err != nil {
return symbols // Ignore error and return empty symbol list
}
text := string(bsrc)

Expand All @@ -192,17 +197,19 @@ func getSymbols(fname string) []*Symbol {
ast.FileExports(file)

ast.Inspect(file, func(n ast.Node) bool {
var found *Symbol
var symbol *Symbol

switch n.(type) {
case *ast.FuncDecl:
found = function(n, text)
symbol = function(n, text)
case *ast.GenDecl:
found = declaration(n, text)
symbol = declaration(n, text)
}

if found != nil {
symbols = append(symbols, found)
if symbol != nil {
symbol.FileURI = getURI(absPath)
symbol.Position = fset.Position(n.Pos())
symbols = append(symbols, symbol)
}

return true
Expand Down Expand Up @@ -255,3 +262,7 @@ func typeName(t ast.TypeSpec) string {
return "type"
}
}

func getURI(absFilePath string) uri.URI {
return uri.URI("file://" + absFilePath)
}
84 changes: 84 additions & 0 deletions internal/lsp/definition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package lsp

import (
"context"
"encoding/json"
"errors"
"log/slog"
"strings"

"go.lsp.dev/jsonrpc2"
"go.lsp.dev/protocol"
)

func (s *server) Definition(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {
var params protocol.DefinitionParams
if err := json.Unmarshal(req.Params(), &params); err != nil {
sendParseError(ctx, reply, err)
}

uri := params.TextDocument.URI
file, ok := s.snapshot.Get(uri.Filename())
if !ok {
return reply(ctx, nil, errors.New("snapshot not found"))
}

offset := file.PositionToOffset(params.Position)
slog.Info("definition", "offset", offset)

pgf, err := file.ParseGno(ctx)
if err != nil {
return reply(ctx, nil, errors.New("cannot parse gno file"))
}

for _, spec := range pgf.File.Imports {
slog.Info("definition", "spec", spec.Path.Value, "pos", spec.Path.Pos(), "end", spec.Path.End())
if int(spec.Path.Pos()) <= offset && offset <= int(spec.Path.End()) {
// TODO: handle definition for imports
slog.Info("definition", "import", spec.Path.Value)
return reply(ctx, nil, nil)
}
}

token, err := file.TokenAt(params.Position)
if err != nil {
return reply(ctx, protocol.Hover{}, err)
}
text := strings.TrimSpace(token.Text)

// FIXME: Use the AST package to do this + get type of token.
//
// This is just a quick PoC to get something working.

// strings.Split(p.Body,
text = strings.Split(text, "(")[0]

text = strings.TrimSuffix(text, ",")
text = strings.TrimSuffix(text, ")")

// *mux.Request
text = strings.TrimPrefix(text, "*")

slog.Info("definition", "pkg", len(s.completionStore.pkgs))

parts := strings.Split(text, ".")
if len(parts) == 2 {
pkg := parts[0]
sym := parts[1]

slog.Info("definition", "pkg", pkg, "sym", sym)
symbol := s.completionStore.lookupSymbol(pkg, sym)
if symbol != nil {
slog.Info("definition", "URI", symbol.FileURI)
return reply(ctx, protocol.Location{
URI: symbol.FileURI,
Range: *posToRange(
symbol.Position.Line,
[]int{0, 0},
),
}, nil)
}
}

return reply(ctx, nil, nil)
}
3 changes: 3 additions & 0 deletions internal/lsp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ func (s *server) ServerHandler(ctx context.Context, reply jsonrpc2.Replier, req
return s.Hover(ctx, reply, req)
case "textDocument/completion":
return s.Completion(ctx, reply, req)
case "textDocument/definition":
return s.Definition(ctx, reply, req)
default:
return jsonrpc2.MethodNotFoundHandler(ctx, reply, req)
}
Expand Down Expand Up @@ -103,6 +105,7 @@ func (s *server) Initialize(ctx context.Context, reply jsonrpc2.Replier, req jso
"gnopls.version",
},
},
DefinitionProvider: true,
DocumentFormattingProvider: true,
},
}, nil)
Expand Down

0 comments on commit b629683

Please sign in to comment.