diff --git a/lsp/handlers.go b/lsp/handlers.go index cd81946..8a6b72b 100644 --- a/lsp/handlers.go +++ b/lsp/handlers.go @@ -90,6 +90,41 @@ func (s *Server) hover(p hoverParams) *Hover { } } +// definition returns the location of the label definition for a label reference. +func (s *Server) definition(p definitionParams) []Location { + text := s.docs[p.TextDocument.URI] + word, _ := wordAt(text, p.Position) + if word == "" { + return nil + } + + // Parse the document to find label definitions. + f, errs := parser.Parse(uriPath(p.TextDocument.URI), text) + if f == nil || len(errs) > 0 { + return nil + } + + // Find the label definition. + for _, d := range f.Decls { + if t, ok := d.(*ast.Text); ok { + for _, stmt := range t.Body { + if lbl, ok := stmt.(*ast.Label); ok { + if lbl.Name.Text == word { + return []Location{{ + URI: p.TextDocument.URI, + Range: Range{ + Start: Position{Line: lbl.Name.Pos.Line - 1, Character: lbl.Name.Pos.Column - 1}, + End: Position{Line: lbl.Name.Pos.Line - 1, Character: lbl.Name.Pos.Column - 1 + len(word)}, + }, + }} + } + } + } + } + } + return nil +} + // documentSymbols returns functions and their labels, plus global symbols. func (s *Server) documentSymbols(p documentSymbolParams) []DocumentSymbol { text := s.docs[p.TextDocument.URI] diff --git a/lsp/protocol.go b/lsp/protocol.go index 5b441f0..75c83b8 100644 --- a/lsp/protocol.go +++ b/lsp/protocol.go @@ -152,6 +152,11 @@ type hoverParams struct { Position Position `json:"position"` } +type definitionParams struct { + TextDocument textDocumentIdentifier `json:"textDocument"` + Position Position `json:"position"` +} + // Hover is the hover response. type Hover struct { Contents markupContent `json:"contents"` diff --git a/lsp/server.go b/lsp/server.go index fcdef5e..55ab5e3 100644 --- a/lsp/server.go +++ b/lsp/server.go @@ -170,6 +170,11 @@ func (s *Server) dispatch(msg *rpcMessage) (exit bool) { json.Unmarshal(msg.Params, &p) s.respond(msg.ID, s.hover(p)) + case "textDocument/definition": + var p definitionParams + json.Unmarshal(msg.Params, &p) + s.respond(msg.ID, s.definition(p)) + case "textDocument/documentSymbol": var p documentSymbolParams json.Unmarshal(msg.Params, &p)