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 new file mode 100644 index 0000000..3a40a14 --- /dev/null +++ b/langserver/codeLens.go @@ -0,0 +1,74 @@ +// Copyright 2020 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. // You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +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, params *protocol.CodeLensParams) ([]protocol.CodeLens, error) { + // 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/general.go b/langserver/general.go index 5a924cf..47e564f 100644 --- a/langserver/general.go +++ b/langserver/general.go @@ -23,7 +23,7 @@ import ( // Initialize handles a call from the client to initialize the server. // Required by the protocol.Server interface. -func (s *server) Initialize(_ context.Context, _ *protocol.ParamInitialize) (*protocol.InitializeResult, error) { +func (s *server) Initialize(_ context.Context, paramInitialize *protocol.ParamInitialize) (*protocol.InitializeResult, error) { s.stateMu.Lock() defer s.stateMu.Unlock() @@ -35,6 +35,8 @@ func (s *server) Initialize(_ context.Context, _ *protocol.ParamInitialize) (*pr s.cache.Init() + s.initializeParams = paramInitialize.InitializeParams + return &protocol.InitializeResult{ Capabilities: protocol.ServerCapabilities{ TextDocumentSync: &protocol.TextDocumentSyncOptions{ 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() } diff --git a/langserver/notImplemented.go b/langserver/notImplemented.go index b7d19bd..6103dbb 100644 --- a/langserver/notImplemented.go +++ b/langserver/notImplemented.go @@ -141,15 +141,6 @@ func (s *server) Symbol(_ context.Context, _ *protocol.WorkspaceSymbolParams) ([ return nil, notImplemented("Symbol") } -// CodeLens is required by the protocol.Server interface. -func (s *server) CodeLens(_ context.Context, _ *protocol.CodeLensParams) ([]protocol.CodeLens, error) { - // As of version 0.4.0 of gopls it is not possible to instruct the language - // client to stop asking for Code Lenses and Document Links. To prevent - // VS Code from showing error messages, this feature is implemented by - // returning empty values. - return nil, nil -} - // ResolveCodeLens is required by the protocol.Server interface. func (s *server) ResolveCodeLens(_ context.Context, _ *protocol.CodeLens) (*protocol.CodeLens, error) { return nil, notImplemented("ResolveCodeLens") diff --git a/langserver/server.go b/langserver/server.go index a030d83..bce4bea 100644 --- a/langserver/server.go +++ b/langserver/server.go @@ -54,8 +54,9 @@ type server struct { Conn *jsonrpc2.Conn client protocol.Client - state serverState - stateMu sync.Mutex + state serverState + stateMu sync.Mutex + initializeParams protocol.InitializeParams cache cache.DocumentCache