-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
initial language server protocol implementation #27
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"log" | ||
"os" | ||
|
||
"github.com/haya14busa/go-vimlparser/langserver" | ||
"github.com/sourcegraph/jsonrpc2" | ||
) | ||
|
||
func main() { | ||
log.Println("langserver-vim: reading on stdin, writing on stdout") | ||
var connOpt []jsonrpc2.ConnOpt | ||
<-jsonrpc2.NewConn(context.Background(), jsonrpc2.NewBufferedStream(stdrwc{}, jsonrpc2.VSCodeObjectCodec{}), langserver.NewHandler(), connOpt...).DisconnectNotify() | ||
log.Println("langserver-vim: connections closed") | ||
} | ||
|
||
type stdrwc struct{} | ||
|
||
func (stdrwc) Read(p []byte) (int, error) { | ||
return os.Stdin.Read(p) | ||
} | ||
|
||
func (stdrwc) Write(p []byte) (int, error) { | ||
return os.Stdout.Write(p) | ||
} | ||
|
||
func (stdrwc) Close() error { | ||
if err := os.Stdin.Close(); err != nil { | ||
return err | ||
} | ||
return os.Stdout.Close() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package langserver | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
|
||
"github.com/sourcegraph/jsonrpc2" | ||
) | ||
|
||
func (h *LangHandler) handleInitialize(ctx context.Context, conn *jsonrpc2.Conn, req *jsonrpc2.Request) (result interface{}, err error) { | ||
if req.Params == nil { | ||
return nil, &jsonrpc2.Error{Code: jsonrpc2.CodeInvalidParams} | ||
} | ||
|
||
var params InitializeParams | ||
if err := json.Unmarshal(*req.Params, ¶ms); err != nil { | ||
return nil, err | ||
} | ||
|
||
return InitializeResult{ | ||
Capabilities: ServerCapabilities{ | ||
TextDocumentSync: TDSKFull, | ||
DocumentSymbolProvider: true, | ||
}, | ||
}, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package langserver | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
|
||
"github.com/sourcegraph/jsonrpc2" | ||
) | ||
|
||
func (h *LangHandler) handleTextDocumentDidOpen(ctx context.Context, conn *jsonrpc2.Conn, req *jsonrpc2.Request) (result interface{}, err error) { | ||
if req.Params == nil { | ||
return nil, &jsonrpc2.Error{Code: jsonrpc2.CodeInvalidParams} | ||
} | ||
|
||
var params DidOpenTextDocumentParams | ||
if err := json.Unmarshal(*req.Params, ¶ms); err != nil { | ||
return nil, err | ||
} | ||
|
||
f, err := newVimFile(params.TextDocument) | ||
if err != nil { | ||
return nil, err | ||
} | ||
h.files[params.TextDocument.URI] = f | ||
return nil, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package langserver | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/haya14busa/go-vimlparser/ast" | ||
|
||
"github.com/sourcegraph/jsonrpc2" | ||
) | ||
|
||
func (h *LangHandler) handleTextDocumentSymbols(ctx context.Context, conn *jsonrpc2.Conn, req *jsonrpc2.Request) (result interface{}, err error) { | ||
if req.Params == nil { | ||
return nil, &jsonrpc2.Error{Code: jsonrpc2.CodeInvalidParams} | ||
} | ||
|
||
var params DocumentSymbolParams | ||
if err := json.Unmarshal(*req.Params, ¶ms); err != nil { | ||
return nil, err | ||
} | ||
|
||
if f, ok := h.files[params.TextDocument.URI]; ok { | ||
node, err := f.GetAst() | ||
if err != nil { | ||
return nil, err | ||
} | ||
return getDocumentSymbols(params, node), nil | ||
} | ||
return nil, fmt.Errorf("%s not open", params.TextDocument.URI) | ||
} | ||
|
||
func getDocumentSymbols(params DocumentSymbolParams, node ast.Node) []SymbolInformation { | ||
var symbols []SymbolInformation | ||
ast.Inspect(node, func(n ast.Node) bool { | ||
var name string | ||
var kind SymbolKind | ||
var pos ast.Pos | ||
switch x := n.(type) { | ||
case *ast.Function: | ||
switch y := x.Name.(type) { | ||
case *ast.Ident: | ||
kind = SKFunction | ||
name = y.Name | ||
pos = y.NamePos | ||
} | ||
|
||
if name != "" { | ||
symbols = append(symbols, SymbolInformation{ | ||
Name: name, | ||
Kind: kind, | ||
Location: Location{ | ||
URI: params.TextDocument.URI, | ||
Range: Range{ | ||
Start: Position{ | ||
Line: pos.Line - 1, | ||
Character: pos.Column - 1, | ||
}, | ||
End: Position{ | ||
Line: pos.Line - 1, | ||
Character: pos.Column + len(name) - 1, | ||
}, | ||
}, | ||
}, | ||
}) | ||
return false | ||
} | ||
} | ||
return true | ||
}) | ||
return symbols | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package langserver | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
|
||
"github.com/haya14busa/go-vimlparser" | ||
"github.com/haya14busa/go-vimlparser/ast" | ||
|
||
"github.com/sourcegraph/jsonrpc2" | ||
) | ||
|
||
func NewHandler() jsonrpc2.Handler { | ||
var langHandler = &LangHandler{ | ||
files: make(map[string]*vimfile), | ||
} | ||
return jsonrpc2.HandlerWithError(langHandler.handle) | ||
} | ||
|
||
type LangHandler struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
files map[string]*vimfile | ||
} | ||
|
||
type vimfile struct { | ||
TextDocumentItem | ||
Ast *ast.File | ||
AstError error | ||
} | ||
|
||
func newVimFile(textDocumentItem TextDocumentItem) (result *vimfile, error error) { | ||
return &vimfile{ | ||
TextDocumentItem: textDocumentItem, | ||
Ast: nil, | ||
AstError: nil, | ||
}, nil | ||
} | ||
|
||
func (f *vimfile) GetAst() (result *ast.File, error error) { | ||
if f.AstError != nil { | ||
return nil, f.AstError | ||
} else if f.Ast != nil { | ||
return f.Ast, nil | ||
} else { | ||
opt := &vimlparser.ParseOption{Neovim: false} | ||
r := bytes.NewBufferString(f.Text) | ||
ast, err := vimlparser.ParseFile(r, f.URI, opt) | ||
f.Ast = ast | ||
f.AstError = err | ||
return ast, err | ||
} | ||
} | ||
|
||
func (h *LangHandler) handle(ctx context.Context, conn *jsonrpc2.Conn, req *jsonrpc2.Request) (result interface{}, err error) { | ||
switch req.Method { | ||
case "initialize": | ||
return h.handleInitialize(ctx, conn, req) | ||
case "textDocument/didOpen": | ||
return h.handleTextDocumentDidOpen(ctx, conn, req) | ||
case "textDocument/documentSymbol": | ||
return h.handleTextDocumentSymbols(ctx, conn, req) | ||
} | ||
|
||
return nil, &jsonrpc2.Error{Code: jsonrpc2.CodeMethodNotFound, Message: fmt.Sprintf("method not supported: %s", req.Method)} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package langserver | ||
|
||
type InitializeParams struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
ProcessID int `json:"processId,omitempty"` | ||
RootPath string `json:"rootPath,omitempty"` | ||
InitializationOptions InitializeOptions `json:"initializationOptions,omitempty"` | ||
Capabilities ClientCapabilities `json:"capabilities,omitempty"` | ||
Trace string `json:"trace,omitempty"` | ||
} | ||
|
||
type InitializeOptions struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
} | ||
|
||
type ClientCapabilities struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
} | ||
|
||
type InitializeResult struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
Capabilities ServerCapabilities `json:"capabilities,omitempty"` | ||
} | ||
|
||
type TextDocumentSyncKind int | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
|
||
const ( | ||
TDSKNone TextDocumentSyncKind = 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
TDSKFull = 1 | ||
TDSKIncremental = 2 | ||
) | ||
|
||
type ServerCapabilities struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
TextDocumentSync TextDocumentSyncKind `json:"textDocumentSync,omitempty"` | ||
DocumentSymbolProvider bool `json:"documentSymbolProvider,omitempty"` | ||
} | ||
|
||
type TextDocumentItem struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
URI string `json:"uri"` | ||
LanguageID string `json:"languageId"` | ||
Version int `json:"version"` | ||
Text string `json:"text"` | ||
} | ||
|
||
type TextDocumentIdentifier struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
URI string `json:"uri"` | ||
} | ||
|
||
type DidOpenTextDocumentParams struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
TextDocument TextDocumentItem `json:"textDocument"` | ||
} | ||
|
||
type DocumentSymbolParams struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
TextDocument TextDocumentIdentifier | ||
} | ||
|
||
type SymbolKind int | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
|
||
const ( | ||
SKFile SymbolKind = 1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
SKModule SymbolKind = 2 | ||
SKNamespace SymbolKind = 3 | ||
SKPackage SymbolKind = 4 | ||
SKClass SymbolKind = 5 | ||
SKMethod SymbolKind = 6 | ||
SKProperty SymbolKind = 7 | ||
SKField SymbolKind = 8 | ||
SKConstructor SymbolKind = 9 | ||
SKEnum SymbolKind = 10 | ||
SKInterface SymbolKind = 11 | ||
SKFunction SymbolKind = 12 | ||
SKVariable SymbolKind = 13 | ||
SKConstant SymbolKind = 14 | ||
SKString SymbolKind = 15 | ||
SKNumber SymbolKind = 16 | ||
SKBoolean SymbolKind = 17 | ||
SKArray SymbolKind = 18 | ||
) | ||
|
||
type SymbolInformation struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
Name string `json:"name"` | ||
Kind SymbolKind `json:"kind"` | ||
Location Location `json:"location"` | ||
} | ||
|
||
type Location struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
URI string `json:"uri"` | ||
Range Range `json:"range"` | ||
} | ||
|
||
type Range struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
Start Position `json:"start"` | ||
End Position `json:"end"` | ||
} | ||
|
||
type Position struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [golint] reported by reviewdog 🐶 |
||
Line int `json:"line"` | ||
Character int `json:"character"` | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[golint] reported by reviewdog 🐶
exported function NewHandler should have comment or be unexported