From c495dc21eff131fda1da286f6ea450baeb78e9f8 Mon Sep 17 00:00:00 2001 From: banst Date: Sun, 31 Jul 2022 13:49:45 +0200 Subject: [PATCH 1/3] feat: add fmt capabilities --- server/handler/documentFormatting.go | 45 ++++++++++++++++++++++++++++ server/handler/handler.go | 1 + server/handler/initialize.go | 3 ++ 3 files changed, 49 insertions(+) create mode 100644 server/handler/documentFormatting.go diff --git a/server/handler/documentFormatting.go b/server/handler/documentFormatting.go new file mode 100644 index 0000000..e9e7683 --- /dev/null +++ b/server/handler/documentFormatting.go @@ -0,0 +1,45 @@ +package handler + +import ( + "bytes" + "os" + + "cuelang.org/go/cue/format" + "github.com/tliron/glsp" + protocol "github.com/tliron/glsp/protocol_3_16" + "go.lsp.dev/uri" +) + +func (h *Handler) documentFormatting(_ *glsp.Context, params *protocol.DocumentFormattingParams) ([]protocol.TextEdit, error) { + h.log.Debugf("Format: %s", params.TextDocument.URI) + h.log.Debugf("params: %#v", params) + + _uri, err := uri.Parse(params.TextDocument.URI) + source, err := os.ReadFile(_uri.Filename()) + if err != nil { + return nil, h.wrapError(err) + } + + h.log.Debugf("Find source of %s", _uri.Filename) + _fmt, err := format.Source(source, format.UseSpaces(2), format.TabIndent(false)) // TODO: gather from params.Options? + if err != nil { + return nil, h.wrapError(err) + } + + h.log.Debugf("Source formatted: %s", _uri.Filename) + start := protocol.Position{Line: 0, Character: 0} + + nl := []byte("\n") + ll := bytes.Count(source, nl) + end := protocol.Position{Line: uint32(ll), Character: 0} + + edit := protocol.TextEdit{ + Range: protocol.Range{ + Start: start, + End: end, + }, + NewText: string(_fmt), + } + + return []protocol.TextEdit{edit}, nil +} diff --git a/server/handler/handler.go b/server/handler/handler.go index d020547..ffd81ce 100644 --- a/server/handler/handler.go +++ b/server/handler/handler.go @@ -42,6 +42,7 @@ func New(opts ...Options) *Handler { TextDocumentHover: h.documentHover, TextDocumentDidChange: h.documentDidChange, TextDocumentDidClose: h.documentDidClose, + TextDocumentFormatting: h.documentFormatting, } return h diff --git a/server/handler/initialize.go b/server/handler/initialize.go index 960cdef..c3b0a5e 100644 --- a/server/handler/initialize.go +++ b/server/handler/initialize.go @@ -99,5 +99,8 @@ func (h *Handler) capabilities() protocol.ServerCapabilities { capabilities.DefinitionProvider = true capabilities.HoverProvider = true + // Formatting + capabilities.DocumentFormattingProvider = true + return capabilities } From 75e7edb3ef2ce18e28e75ad52452b37e5b5c620f Mon Sep 17 00:00:00 2001 From: banst Date: Wed, 3 Aug 2022 19:14:49 -0700 Subject: [PATCH 2/3] feat: get file from plan --- file/file.go | 4 +-- plan/plan.go | 19 +++++++++++--- server/handler/documentDidChange.go | 37 ++++++++++++++++++++++++++-- server/handler/documentFormatting.go | 21 +++++++++------- 4 files changed, 65 insertions(+), 16 deletions(-) diff --git a/file/file.go b/file/file.go index 1527f6b..e70adac 100644 --- a/file/file.go +++ b/file/file.go @@ -22,8 +22,8 @@ type File struct { } // New create a File and analise CUE ast in it. -func New(path string) (*File, error) { - content, err := cueparser.ParseFile(path, nil) +func New(path string, src interface{}) (*File, error) { + content, err := cueparser.ParseFile(path, src) if err != nil { return nil, err } diff --git a/plan/plan.go b/plan/plan.go index 5e35196..7f72077 100644 --- a/plan/plan.go +++ b/plan/plan.go @@ -25,6 +25,9 @@ type Plan struct { // files store the loaded files. files map[string]*file.File + // overrides store the override content of files. + overrides map[string][]byte + // Kind stores Plan's Kind. Kind Kind @@ -67,7 +70,7 @@ func New(root, filePath string) (*Plan, error) { return nil, err } - f, err := file.New(filepath.Join(root, filePath)) + f, err := file.New(filepath.Join(root, filePath), nil) if err != nil { return nil, err } @@ -80,6 +83,7 @@ func New(root, filePath string) (*Plan, error) { rootPath: root, RootFilePath: filePath, files: files, + overrides: map[string][]byte{}, Kind: k, instance: i, v: v, @@ -116,7 +120,7 @@ func (p *Plan) loadImports() error { func (p *Plan) loadFiles() error { for path := range p.files { - f, err := file.New(filepath.Join(p.rootPath, path)) + f, err := file.New(filepath.Join(p.rootPath, path), p.overrides[path]) if err != nil { return err } @@ -297,7 +301,7 @@ func (p *Plan) Reload() error { func (p *Plan) AddFile(path string) error { p.log.Debugf("Add a new file to plan: %s", path) - f, err := file.New(filepath.Join(p.rootPath, path)) + f, err := file.New(filepath.Join(p.rootPath, path), nil) if err != nil { return err } @@ -307,3 +311,12 @@ func (p *Plan) AddFile(path string) error { return nil } + +// AddOverride add content as an override for the file +func (p *Plan) AddOverride(path string, content []byte) { + p.log.Debugf("Add a new override to plan: %s", path) + + p.muFiles.Lock() + p.overrides[path] = content + p.muFiles.Unlock() +} \ No newline at end of file diff --git a/server/handler/documentDidChange.go b/server/handler/documentDidChange.go index 412eae0..7fbb8dd 100644 --- a/server/handler/documentDidChange.go +++ b/server/handler/documentDidChange.go @@ -1,10 +1,43 @@ package handler import ( + "fmt" + "os" + "github.com/tliron/glsp" protocol "github.com/tliron/glsp/protocol_3_16" + "go.lsp.dev/uri" ) -func (h *Handler) documentDidChange(_ *glsp.Context, _ *protocol.DidChangeTextDocumentParams) error { - return nil +func (h *Handler) documentDidChange(_ *glsp.Context, params *protocol.DidChangeTextDocumentParams) error { + h.log.Debugf("Document saved") + h.log.Debugf("params: %#v", params) + + _uri, err := uri.Parse(params.TextDocument.URI) + if err != nil { + return h.wrapError(err) + } + + p := h.workspace.GetPlan(_uri.Filename()) + if p == nil { + return h.wrapError(fmt.Errorf("plan not found")) + } + + ogf, err := os.ReadFile(_uri.Filename()) + if err != nil { + return h.wrapError(err) + } + content := string(ogf) + + for _, change := range params.ContentChanges { + if change_, ok := change.(protocol.TextDocumentContentChangeEvent); ok { + startIndex, endIndex := change_.Range.IndexesIn(content) + content = content[:startIndex] + change_.Text + content[endIndex:] + } else if change_, ok := change.(protocol.TextDocumentContentChangeEventWhole); ok { + content = change_.Text + } + } + p.AddOverride(h.workspace.TrimRootPath(_uri.Filename()), []byte(content)) + + return p.Reload() } diff --git a/server/handler/documentFormatting.go b/server/handler/documentFormatting.go index e9e7683..0392bc6 100644 --- a/server/handler/documentFormatting.go +++ b/server/handler/documentFormatting.go @@ -1,8 +1,7 @@ package handler import ( - "bytes" - "os" + "fmt" "cuelang.org/go/cue/format" "github.com/tliron/glsp" @@ -15,23 +14,27 @@ func (h *Handler) documentFormatting(_ *glsp.Context, params *protocol.DocumentF h.log.Debugf("params: %#v", params) _uri, err := uri.Parse(params.TextDocument.URI) - source, err := os.ReadFile(_uri.Filename()) if err != nil { return nil, h.wrapError(err) } - h.log.Debugf("Find source of %s", _uri.Filename) - _fmt, err := format.Source(source, format.UseSpaces(2), format.TabIndent(false)) // TODO: gather from params.Options? + p := h.workspace.GetPlan(_uri.Filename()) + if p == nil { + return nil, h.wrapError(fmt.Errorf("plan not found")) + } + + f := p.Files()[h.workspace.TrimRootPath(_uri.Filename())] + h.log.Debugf("File %v", f) + + _fmt, err := format.Node(f.Content(), format.UseSpaces(2), format.TabIndent(false)) // TODO: gather from params.Options? if err != nil { return nil, h.wrapError(err) } - h.log.Debugf("Source formatted: %s", _uri.Filename) + h.log.Debugf("Source formatted: %s", _uri.Filename()) start := protocol.Position{Line: 0, Character: 0} - nl := []byte("\n") - ll := bytes.Count(source, nl) - end := protocol.Position{Line: uint32(ll), Character: 0} + end := protocol.Position{Line: uint32(f.Content().End().Line()), Character: 0} edit := protocol.TextEdit{ Range: protocol.Range{ From f64ceaed2fa89f1d2ba4bcc64e42496d40971da5 Mon Sep 17 00:00:00 2001 From: banst Date: Fri, 5 Aug 2022 10:45:55 -0700 Subject: [PATCH 3/3] feat: add parse comments option --- file/file.go | 2 +- server/handler/documentDidChange.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/file/file.go b/file/file.go index e70adac..90e1a2b 100644 --- a/file/file.go +++ b/file/file.go @@ -23,7 +23,7 @@ type File struct { // New create a File and analise CUE ast in it. func New(path string, src interface{}) (*File, error) { - content, err := cueparser.ParseFile(path, src) + content, err := cueparser.ParseFile(path, src, cueparser.ParseComments) if err != nil { return nil, err } diff --git a/server/handler/documentDidChange.go b/server/handler/documentDidChange.go index 7fbb8dd..9f1c163 100644 --- a/server/handler/documentDidChange.go +++ b/server/handler/documentDidChange.go @@ -10,7 +10,7 @@ import ( ) func (h *Handler) documentDidChange(_ *glsp.Context, params *protocol.DidChangeTextDocumentParams) error { - h.log.Debugf("Document saved") + h.log.Debugf("Document changed") h.log.Debugf("params: %#v", params) _uri, err := uri.Parse(params.TextDocument.URI)