forked from google/wire
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Write types and helper functions for implementing LSP
- Loading branch information
1 parent
8849d66
commit cba9dd6
Showing
2 changed files
with
181 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package lsp | ||
|
||
import ( | ||
"bufio" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"os" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
func ReadBuffer(reader *bufio.Reader) ([]byte, bool) { | ||
var length int | ||
for { | ||
header, err := reader.ReadString('\n') | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "error reading header: %v\n", err) | ||
return nil, false | ||
} | ||
if header == "\r\n" { | ||
break | ||
} | ||
// TODO: trim the remaining \r also | ||
header = strings.TrimSpace(header) | ||
switch { | ||
case strings.HasPrefix(header, "Content-Length: "): | ||
value := strings.TrimPrefix(header, "Content-Length: ") | ||
length, err = strconv.Atoi(value) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Content-Length is not a valid integer: %v\n", err) | ||
return nil, false | ||
} | ||
case strings.HasPrefix(header, "Content-Type: "): | ||
value := strings.TrimPrefix(header, "Content-Type: ") | ||
if value != "application/vscode-jsonrpc; charset=utf-8" { | ||
fmt.Fprintf(os.Stderr, "Content-Type is invalid: %v\n", value) | ||
return nil, false | ||
} | ||
default: | ||
fmt.Fprintf(os.Stderr, "header field name is invalid: %v", header) | ||
return nil, false | ||
} | ||
} | ||
// Read len bytes of content | ||
buf := make([]byte, length) | ||
n, err := io.ReadFull(reader, buf) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "error reading content %v\n", err) | ||
return nil, false | ||
} | ||
if n != length { | ||
fmt.Fprintln(os.Stderr, "Content-Length and content length do not match") | ||
return nil, false | ||
} | ||
return buf, true | ||
} | ||
|
||
func ParseMessage(buf []byte) (map[string]interface{}, bool) { | ||
in := make(map[string]interface{}) | ||
if err := json.Unmarshal(buf, &in); err != nil { | ||
fmt.Fprintf(os.Stderr, "error deserializing request: %v\n", err) | ||
return nil, false | ||
} | ||
return in, true | ||
} | ||
|
||
func ParseRequest(buf []byte, req interface{}) bool { | ||
if err := json.Unmarshal(buf, req); err != nil { | ||
fmt.Fprintf(os.Stderr, "Error parsing request: %v\n", err) | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
func StringifyResponse(res interface{}) bool { | ||
bytes, err := json.Marshal(res) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "error serializing response: %v\n", err) | ||
return false | ||
} | ||
fmt.Printf("Content-Length: %d\r\n", len(bytes)) | ||
fmt.Printf("\r\n") | ||
// TODO: \r\n at the end is redundant | ||
fmt.Print(string(bytes) + "\r\n") | ||
return true | ||
} | ||
|
||
// func calculatePos(fset *token.FileSet, path string, line int, char int) token.Pos { | ||
// var file *token.File | ||
// fset.Iterate(func(f *token.File) bool { | ||
// if f.Name() == path { | ||
// file = f | ||
// return false | ||
// } | ||
// return true | ||
// }) | ||
// offset := int(file.LineStart(line)) - int(file.Base()) | ||
// offset += char | ||
// return file.Pos(offset) | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package lsp | ||
|
||
type InitializeRequest struct { | ||
Jsonrpc string `json:"jsonrpc"` | ||
Id int `json:"id"` | ||
Method string `json:"method"` | ||
Params InitializeParams `json:"params"` | ||
} | ||
|
||
type InitializeParams struct { | ||
Capabilities ClientCapabilities `json:"capabilities"` | ||
} | ||
|
||
type ClientCapabilities struct { | ||
Workspace WorkspaceClientCapabilities `json:"workspace"` | ||
} | ||
|
||
type WorkspaceClientCapabilities struct { | ||
Configuration bool `json:"configuration"` | ||
WorkspaceFolders bool `json:"workspaceFolders"` | ||
} | ||
|
||
type InitializeResponse struct { | ||
Jsonrpc string `json:"jsonrpc"` | ||
Id int `json:"id"` | ||
Result InitializeResult `json:"result"` | ||
} | ||
type InitializeResult struct { | ||
Capabilities ServerCapabilities `json:"capabilities"` | ||
} | ||
|
||
type ServerCapabilities struct { | ||
TextDocumentSync int `json:"textDocumentSync"` | ||
HoverProvider bool `json:"hoverProvider"` | ||
Workspace WorkspaceServerCapabilities `json:"workspace"` | ||
} | ||
|
||
type WorkspaceServerCapabilities struct { | ||
WorkspaceFolders WorkspaceFoldersServerCapabilities `json:"workspaceFolders"` | ||
} | ||
|
||
type WorkspaceFoldersServerCapabilities struct { | ||
Supported bool `json:"supported"` | ||
} | ||
|
||
type HoverRequest struct { | ||
Jsonrpc string `json:"jsonrpc"` | ||
Id int `json:"id"` | ||
Method string `json:"method"` | ||
Params HoverParams `json:"Params"` | ||
} | ||
|
||
type HoverParams struct { | ||
TextDocument TextDocumentIdentifier `json:"textDocument"` | ||
Position Position `json:"position"` | ||
} | ||
|
||
type TextDocumentIdentifier struct { | ||
Uri string `json:"uri"` | ||
} | ||
|
||
type Position struct { | ||
Line int `json:"line"` | ||
Character int `json:"character"` | ||
} | ||
|
||
type HoverResponse struct { | ||
Jsonrpc string `json:"jsonrpc"` | ||
Id int `json:"id"` | ||
Result HoverResult `json:"result"` | ||
} | ||
|
||
type HoverResult struct { | ||
Contents MarkupContent `json:"contents"` | ||
} | ||
|
||
type MarkupContent struct { | ||
Kind string `json:"kind"` | ||
Value string `json:"value"` | ||
} |