diff --git a/langserver/cache/cache_test.go b/langserver/cache/cache_test.go index 655b9ae..8dae1d4 100644 --- a/langserver/cache/cache_test.go +++ b/langserver/cache/cache_test.go @@ -236,7 +236,7 @@ groups: Line: 9.0, Character: 0.0, }, - End: endOfLine(protocol.Position{ + End: EndOfLine(protocol.Position{ Line: 10.0, Character: 0.1, }), diff --git a/langserver/cache/position.go b/langserver/cache/position.go index 76e1672..7e6f276 100644 --- a/langserver/cache/position.go +++ b/langserver/cache/position.go @@ -126,8 +126,8 @@ func (d *DocumentHandle) yamlPositionToTokenPos(line int, column int, lineOffset } } -// endOfLine returns the end of the Line of the given protocol.Position. -func endOfLine(p protocol.Position) protocol.Position { +// EndOfLine returns the end of the Line of the given protocol.Position. +func EndOfLine(p protocol.Position) protocol.Position { return protocol.Position{ Line: p.Line + 1, Character: 0, diff --git a/langserver/codeLens.go b/langserver/codeLens.go index 438edb4..cce45cc 100644 --- a/langserver/codeLens.go +++ b/langserver/codeLens.go @@ -14,12 +14,63 @@ package langserver import ( "context" + "fmt" + "net/url" + "strings" "github.com/prometheus-community/promql-langserver/internal/vendored/go-tools/lsp/protocol" + "github.com/prometheus-community/promql-langserver/langserver/cache" ) // CodeLens is required by the protocol.Server interface. -func (s *server) CodeLens(_ context.Context, _ *protocol.CodeLensParams) ([]protocol.CodeLens, error) { +func (s *server) CodeLens(_ context.Context, params *protocol.CodeLensParams) ([]protocol.CodeLens, error) { - return nil, nil + // Currently Code Lenses are only supported for VS Code + if s.initializeParams.ClientInfo.Name != "vscode" { + return nil, nil + } + + promURL := s.metadataService.GetURL() + + if promURL == "" { + return nil, nil + } + + doc, err := s.cache.GetDocument(params.TextDocument.URI) + if err != nil { + return nil, nil + } + + queries, err := doc.GetQueries() + if err != nil { + return nil, nil + } + + codeLenses := make([]protocol.CodeLens, 0, len(queries)) + + for _, query := range queries { + + pos, err := doc.PosToProtocolPosition(query.Pos) + if err != nil { + return nil, nil + } + + qText := query.Content + qTextEncoded := url.QueryEscape(strings.TrimSpace(qText)) + target := fmt.Sprint(promURL, "/graph?g0.expr=", qTextEncoded) + + codeLenses = append(codeLenses, protocol.CodeLens{ + Range: protocol.Range{ + Start: pos, + End: cache.EndOfLine(pos), + }, + Command: protocol.Command{ + Title: "▶ PromQL Query: View in expression Browser", + Command: "vscode-promql.openURL", + Arguments: []interface{}{target}, + }, + }) + } + + return codeLenses, nil } diff --git a/langserver/hover.go b/langserver/hover.go index b16c352..2081990 100644 --- a/langserver/hover.go +++ b/langserver/hover.go @@ -17,10 +17,8 @@ import ( "bytes" "context" "fmt" - "go/token" "log" "net/http" - "net/url" "strings" "github.com/pkg/errors" @@ -138,30 +136,6 @@ func (s *server) nodeToDocMarkdown(ctx context.Context, location *cache.Location } } - promURL := s.metadataService.GetURL() - - if promURL != "" && !s.headless { - loc := *location - - loc.Node = loc.Query.Ast - - qText, err := location.Doc.GetSubstring(loc.Query.Pos+token.Pos(loc.Node.PositionRange().Start), loc.Query.Pos+token.Pos(loc.Node.PositionRange().End)) - if err != nil { - return "" - } - - qTextEncoded := url.QueryEscape(qText) - - target := fmt.Sprint(promURL, "/graph?g0.expr=", qTextEncoded) - - linkText := fmt.Sprintf("---\n[evaluate query](%s)\n\n", target) - - _, err = ret.WriteString(linkText) - if err != nil { - return "" - } - } - return ret.String() }