Files
zyedidia.micro/internal/lsp/requests.go
Zachary Yedidia 8f6f336b6c Range format
2020-08-12 16:56:57 -04:00

199 lines
4.2 KiB
Go

package lsp
import (
"encoding/json"
"errors"
lsp "go.lsp.dev/protocol"
"go.lsp.dev/uri"
)
var ErrNotSupported = errors.New("Operation not supported by language server")
type RPCCompletion struct {
RPCVersion string `json:"jsonrpc"`
ID int `json:"id"`
Result lsp.CompletionList `json:"result"`
}
type RPCCompletionAlternate struct {
RPCVersion string `json:"jsonrpc"`
ID int `json:"id"`
Result []lsp.CompletionItem `json:"result"`
}
type RPCHover struct {
RPCVersion string `json:"jsonrpc"`
ID int `json:"id"`
Result lsp.Hover `json:"result"`
}
type RPCFormat struct {
RPCVersion string `json:"jsonrpc"`
ID int `json:"id"`
Result []lsp.TextEdit `json:"result"`
}
type hoverAlternate struct {
// Contents is the hover's content
Contents []interface{} `json:"contents"`
// Range an optional range is a range inside a text document
// that is used to visualize a hover, e.g. by changing the background color.
Range lsp.Range `json:"range,omitempty"`
}
type RPCHoverAlternate struct {
RPCVersion string `json:"jsonrpc"`
ID int `json:"id"`
Result hoverAlternate `json:"result"`
}
func Position(x, y int) lsp.Position {
return lsp.Position{
Line: float64(y),
Character: float64(x),
}
}
func (s *Server) DocumentFormat(filename string, options lsp.FormattingOptions) ([]lsp.TextEdit, error) {
if !s.capabilities.DocumentFormattingProvider {
return nil, ErrNotSupported
}
doc := lsp.TextDocumentIdentifier{
URI: uri.File(filename),
}
params := lsp.DocumentFormattingParams{
Options: options,
TextDocument: doc,
}
resp, err := s.sendRequest(lsp.MethodTextDocumentFormatting, params)
if err != nil {
return nil, err
}
var r RPCFormat
err = json.Unmarshal(resp, &r)
if err != nil {
return nil, err
}
return r.Result, nil
}
func (s *Server) DocumentRangeFormat(filename string, r lsp.Range, options lsp.FormattingOptions) ([]lsp.TextEdit, error) {
if !s.capabilities.DocumentRangeFormattingProvider {
return nil, ErrNotSupported
}
doc := lsp.TextDocumentIdentifier{
URI: uri.File(filename),
}
params := lsp.DocumentRangeFormattingParams{
Options: options,
Range: r,
TextDocument: doc,
}
resp, err := s.sendRequest(lsp.MethodTextDocumentFormatting, params)
if err != nil {
return nil, err
}
var rpc RPCFormat
err = json.Unmarshal(resp, &rpc)
if err != nil {
return nil, err
}
return rpc.Result, nil
}
func (s *Server) Completion(filename string, pos lsp.Position) ([]lsp.CompletionItem, error) {
if s.capabilities.CompletionProvider == nil {
return nil, ErrNotSupported
}
cc := lsp.CompletionContext{
TriggerKind: lsp.Invoked,
}
docpos := lsp.TextDocumentPositionParams{
TextDocument: lsp.TextDocumentIdentifier{
URI: uri.File(filename),
},
Position: pos,
}
params := lsp.CompletionParams{
TextDocumentPositionParams: docpos,
Context: &cc,
}
resp, err := s.sendRequest(lsp.MethodTextDocumentCompletion, params)
if err != nil {
return nil, err
}
var r RPCCompletion
err = json.Unmarshal(resp, &r)
if err == nil {
return r.Result.Items, nil
}
var ra RPCCompletionAlternate
err = json.Unmarshal(resp, &ra)
if err != nil {
return nil, err
}
return ra.Result, nil
}
func (s *Server) CompletionResolve() {
}
func (s *Server) Hover(filename string, pos lsp.Position) (string, error) {
if !s.capabilities.HoverProvider {
return "", ErrNotSupported
}
params := lsp.TextDocumentPositionParams{
TextDocument: lsp.TextDocumentIdentifier{
URI: uri.File(filename),
},
Position: pos,
}
resp, err := s.sendRequest(lsp.MethodTextDocumentHover, params)
if err != nil {
return "", err
}
var r RPCHover
err = json.Unmarshal(resp, &r)
if err == nil {
return r.Result.Contents.Value, nil
}
var ra RPCHoverAlternate
err = json.Unmarshal(resp, &ra)
if err != nil {
return "", err
}
for _, c := range ra.Result.Contents {
switch t := c.(type) {
case string:
return t, nil
case map[string]interface{}:
s, ok := t["value"].(string)
if ok {
return s, nil
}
}
}
return "", nil
}