This repository has been archived by the owner on May 29, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Handle
didOpen
didClose
didChange
didDave
- Loading branch information
Showing
6 changed files
with
242 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
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
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,75 @@ | ||
package lsp | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"errors" | ||
"log/slog" | ||
|
||
"go.lsp.dev/jsonrpc2" | ||
"go.lsp.dev/protocol" | ||
) | ||
|
||
func (s *server) DidOpen(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error { | ||
var params protocol.DidOpenTextDocumentParams | ||
if err := json.Unmarshal(req.Params(), ¶ms); err != nil { | ||
return sendParseError(ctx, reply, err) | ||
} | ||
|
||
uri := params.TextDocument.URI | ||
file := &GnoFile{ | ||
URI: uri, | ||
Src: []byte(params.TextDocument.Text), | ||
} | ||
s.snapshot.file.Set(uri.Filename(), file) | ||
|
||
slog.Info("open " + string(params.TextDocument.URI.Filename())) | ||
return reply(ctx, nil, nil) | ||
} | ||
|
||
func (s *server) DidClose(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error { | ||
var params protocol.DidChangeTextDocumentParams | ||
if err := json.Unmarshal(req.Params(), ¶ms); err != nil { | ||
return sendParseError(ctx, reply, err) | ||
} | ||
|
||
slog.Info("close" + string(params.TextDocument.URI.Filename())) | ||
return reply(ctx, s.conn.Notify(ctx, protocol.MethodTextDocumentDidClose, nil), nil) | ||
} | ||
|
||
func (s *server) DidChange(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error { | ||
var params protocol.DidChangeTextDocumentParams | ||
if err := json.Unmarshal(req.Params(), ¶ms); err != nil { | ||
return sendParseError(ctx, reply, err) | ||
} | ||
|
||
uri := params.TextDocument.URI | ||
_, ok := s.snapshot.Get(uri.Filename()) | ||
if !ok { | ||
return reply(ctx, nil, errors.New("snapshot not found")) | ||
} | ||
|
||
file := &GnoFile{ | ||
URI: uri, | ||
Src: []byte(params.ContentChanges[0].Text), | ||
} | ||
s.snapshot.file.Set(uri.Filename(), file) | ||
|
||
slog.Info("change " + string(params.TextDocument.URI.Filename())) | ||
return reply(ctx, nil, nil) | ||
} | ||
|
||
func (s *server) DidSave(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error { | ||
var params protocol.DidSaveTextDocumentParams | ||
if err := json.Unmarshal(req.Params(), ¶ms); err != nil { | ||
return sendParseError(ctx, reply, err) | ||
} | ||
|
||
uri := params.TextDocument.URI | ||
file, ok := s.snapshot.Get(uri.Filename()) | ||
if !ok { | ||
return reply(ctx, nil, errors.New("snapshot not found")) | ||
} | ||
|
||
slog.Info("save " + string(uri.Filename())) | ||
} |
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
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,124 @@ | ||
package lsp | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"go/ast" | ||
"go/parser" | ||
"go/token" | ||
"log/slog" | ||
"strings" | ||
"unicode/utf8" | ||
|
||
"go.lsp.dev/protocol" | ||
"golang.org/x/mod/modfile" | ||
|
||
cmap "github.com/orcaman/concurrent-map/v2" | ||
) | ||
|
||
type Snapshot struct { | ||
file cmap.ConcurrentMap[string, *GnoFile] | ||
} | ||
|
||
func NewSnapshot() *Snapshot { | ||
return &Snapshot{ | ||
file: cmap.New[*GnoFile](), | ||
} | ||
} | ||
|
||
func (s *Snapshot) Get(filePath string) (*GnoFile, bool) { | ||
return s.file.Get(filePath) | ||
} | ||
|
||
// contains gno file. | ||
type GnoFile struct { | ||
URI protocol.DocumentURI | ||
Src []byte | ||
} | ||
|
||
// contains parsed gno file. | ||
type ParsedGnoFile struct { | ||
URI protocol.DocumentURI | ||
File *ast.File | ||
|
||
Src []byte | ||
} | ||
|
||
func (f *GnoFile) ParseGno(ctx context.Context) (*ParsedGnoFile, error) { | ||
fset := token.NewFileSet() | ||
ast, err := parser.ParseFile(fset, f.URI.Filename(), nil, parser.ParseComments) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
pgf := &ParsedGnoFile{ | ||
URI: f.URI, | ||
|
||
File: ast, | ||
Src: f.Src, | ||
} | ||
|
||
return pgf, nil | ||
} | ||
|
||
// contains parsed gno.mod file. | ||
type ParsedGnoMod struct { | ||
URI string | ||
File *modfile.File | ||
} | ||
|
||
func (f *GnoFile) TokenAt(pos protocol.Position) (*HoveredToken, error) { | ||
lines := strings.SplitAfter(string(f.Src), "\n") | ||
|
||
size := uint32(len(lines)) | ||
if pos.Line >= size { | ||
return nil, errors.New("line out of range") | ||
} | ||
|
||
line := lines[pos.Line] | ||
lineLen := uint32(len(line)) | ||
|
||
// TODO: fix it. should not happen? | ||
if len(line) == 0 { | ||
return nil, errors.New("no token found") | ||
} | ||
|
||
index := pos.Character | ||
start := index | ||
// TODO: fix it. should not happen? | ||
if lineLen < start { | ||
return nil, errors.New("start is greater than len") | ||
} | ||
for start > 0 && line[start-1] != ' ' { | ||
start-- | ||
} | ||
|
||
end := index | ||
slog.Info(fmt.Sprintf("end: %d", end)) | ||
for end < lineLen && line[end] != ' ' { | ||
end++ | ||
} | ||
|
||
if start == end { | ||
return nil, errors.New("no token found") | ||
} | ||
|
||
return &HoveredToken{ | ||
Text: line[start:end], | ||
Start: int(start), | ||
End: int(end), | ||
}, nil | ||
} | ||
|
||
func (f *GnoFile) PositionToOffset(pos protocol.Position) int { | ||
lines := strings.SplitAfter(string(f.Src), "\n") | ||
offset := 0 | ||
for i, l := range lines { | ||
if i == int(pos.Line) { | ||
break | ||
} | ||
offset += utf8.RuneCountInString(l) | ||
} | ||
return offset + int(pos.Character) | ||
} |
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,9 @@ | ||
package tools | ||
|
||
type FormattingOption int | ||
|
||
const ( | ||
Gofmt FormattingOption = iota | ||
Gofumpt | ||
) | ||
|