From 8c56a055d78d50d1826c88b50837cfdb5751fc2f Mon Sep 17 00:00:00 2001 From: caixw Date: Wed, 29 Jul 2020 15:08:09 +0800 Subject: [PATCH] =?UTF-8?q?refactor(internal/lsp):=20=E9=98=B2=E6=AD=A2?= =?UTF-8?q?=E5=90=8C=E6=97=B6=E8=AE=BF=E9=97=AE=E5=92=8C=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=20folder.doc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/lsp/folder.go | 10 ++++++++++ internal/lsp/search/hover.go | 6 +----- internal/lsp/search/hover_test.go | 8 ++++---- internal/lsp/textdocument.go | 22 ++++++++++++++++------ 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/internal/lsp/folder.go b/internal/lsp/folder.go index 042a533e..f85fadb3 100644 --- a/internal/lsp/folder.go +++ b/internal/lsp/folder.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" "strings" + "sync" "github.com/issue9/sliceutil" @@ -27,6 +28,8 @@ type folder struct { cfg *build.Config srv *server + parsedMux sync.Mutex + // 保存着错误和警告的信息 errors, warns []*core.SyntaxError } @@ -37,6 +40,9 @@ func (f *folder) close() { } func (f *folder) parseBlock(block core.Block) { + f.parsedMux.Lock() + defer f.parsedMux.Unlock() + var input *build.Input ext := filepath.Ext(block.Location.URI.String()) for _, i := range f.cfg.Inputs { @@ -52,6 +58,7 @@ func (f *folder) parseBlock(block core.Block) { f.doc.ParseBlocks(f.h, func(blocks chan core.Block) { input.Parse(blocks, f.h, block) }) + } func (f *folder) messageHandler(msg *core.Message) { @@ -116,6 +123,9 @@ func (s *server) appendFolders(folders ...protocol.WorkspaceFolder) (err error) // 删除与 uri 相关的数据 func (f *folder) deleteURI(uri core.URI) (found bool) { + f.parsedMux.Lock() + defer f.parsedMux.Unlock() + // 清除相关的警告和错误信息 size := sliceutil.QuickDelete(f.warns, func(i int) bool { return f.warns[i].Location.URI == uri diff --git a/internal/lsp/search/hover.go b/internal/lsp/search/hover.go index 5acbaf99..407e6169 100644 --- a/internal/lsp/search/hover.go +++ b/internal/lsp/search/hover.go @@ -20,7 +20,7 @@ var baseType = reflect.TypeOf(xmlenc.Base{}) // Hover 从 doc 查找最符合 uri 和 pos 条件的元素并赋值给 hover // // 返回值表示是否找到了相应在的元素。 -func Hover(doc *ast.APIDoc, uri core.URI, pos core.Position, hover *protocol.Hover) (ok bool) { +func Hover(doc *ast.APIDoc, uri core.URI, pos core.Position, hover *protocol.Hover) { setHover := func(b *xmlenc.Base) { hover.Range = b.Range hover.Contents = protocol.MarkupContent{ @@ -32,7 +32,6 @@ func Hover(doc *ast.APIDoc, uri core.URI, pos core.Position, hover *protocol.Hov if doc.URI == uri { if b := usage(reflect.ValueOf(doc), pos, "APIs"); b != nil { setHover(b) - ok = true } } @@ -44,11 +43,8 @@ func Hover(doc *ast.APIDoc, uri core.URI, pos core.Position, hover *protocol.Hov if b := usage(reflect.ValueOf(api), pos); b != nil { setHover(b) - return true } } - - return ok } // 从 v 中查找最匹配 pos 位置的元素,如果找到匹配项,还会查找其子项,是不是匹配度更高。 diff --git a/internal/lsp/search/hover_test.go b/internal/lsp/search/hover_test.go index 9d196c79..d0a6a283 100644 --- a/internal/lsp/search/hover_test.go +++ b/internal/lsp/search/hover_test.go @@ -41,7 +41,7 @@ func TestHover(t *testing.T) { // title hover := &protocol.Hover{} pos := core.Position{Line: 1, Character: 1} - a.True(Hover(doc, core.URI("doc.go"), pos, hover)) + Hover(doc, core.URI("doc.go"), pos, hover) a.Equal(hover.Range, core.Range{ Start: core.Position{Line: 1, Character: 1}, End: core.Position{Line: 1, Character: 18}, @@ -51,7 +51,7 @@ func TestHover(t *testing.T) { // apis[0] hover = &protocol.Hover{} pos = core.Position{Line: 4, Character: 2} - a.True(Hover(doc, core.URI("doc.go"), pos, hover)) + Hover(doc, core.URI("doc.go"), pos, hover) a.Equal(hover.Range, core.Range{ Start: core.Position{Line: 4, Character: 1}, End: core.Position{Line: 7, Character: 7}, @@ -64,7 +64,7 @@ func TestHover(t *testing.T) { // 改变了 api[0].URI,不再匹配 apis[0],取其父元素 apidoc hover = &protocol.Hover{} pos = core.Position{Line: 4, Character: 1} - a.True(Hover(doc, core.URI("doc.go"), pos, hover)) + Hover(doc, core.URI("doc.go"), pos, hover) a.Equal(hover.Range, core.Range{ Start: core.Position{Line: 0, Character: 0}, End: core.Position{Line: 12, Character: 9}, @@ -74,7 +74,7 @@ func TestHover(t *testing.T) { // 与 apis[0] 相同的 URI hover = &protocol.Hover{} pos = core.Position{Line: 4, Character: 1} - a.True(Hover(doc, core.URI("api0.go"), pos, hover)) + Hover(doc, core.URI("api0.go"), pos, hover) a.Equal(hover.Range, core.Range{ Start: core.Position{Line: 4, Character: 1}, End: core.Position{Line: 7, Character: 7}, diff --git a/internal/lsp/textdocument.go b/internal/lsp/textdocument.go index 51405d8e..2ee22666 100644 --- a/internal/lsp/textdocument.go +++ b/internal/lsp/textdocument.go @@ -33,11 +33,15 @@ func (s *server) textDocumentDidChange(notify bool, in *protocol.DidChangeTextDo // // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover func (s *server) textDocumentHover(notify bool, in *protocol.HoverParams, out *protocol.Hover) error { - for _, f := range s.folders { - if search.Hover(f.doc, in.TextDocument.URI, in.TextDocumentPositionParams.Position, out) { - return nil - } + f := s.findFolder(in.TextDocument.URI) + if f == nil { + return newError(ErrInvalidRequest, locale.ErrFileNotFound, in.TextDocument.URI) } + + f.parsedMux.Lock() + defer f.parsedMux.Unlock() + + search.Hover(f.doc, in.TextDocument.URI, in.TextDocumentPositionParams.Position, out) return nil } @@ -86,7 +90,7 @@ func (s *server) textDocumentFoldingRange(notify bool, in *protocol.FoldingRange f := s.findFolder(uri) if f == nil { - return nil + return newError(ErrInvalidRequest, locale.ErrFileNotFound, in.TextDocument.URI) } fr := make([]protocol.FoldingRange, 0, 10) @@ -94,6 +98,9 @@ func (s *server) textDocumentFoldingRange(notify bool, in *protocol.FoldingRange fr = append(fr, protocol.BuildFoldingRange(f.doc.Base, lineFoldingOnly)) } + f.parsedMux.Lock() + defer f.parsedMux.Unlock() + for _, api := range f.doc.APIs { matched := api.URI == uri || (api.URI == "" && f.doc.URI == uri) if !matched { @@ -120,9 +127,12 @@ func (s *server) textDocumentCompletion(notify bool, in *protocol.CompletionPara func (s *server) textDocumentSemanticTokens(notify bool, in *protocol.SemanticTokensParams, out *protocol.SemanticTokens) error { f := s.findFolder(in.TextDocument.URI) if f == nil { - return nil + return newError(ErrInvalidRequest, locale.ErrFileNotFound, in.TextDocument.URI) } + f.parsedMux.Lock() + defer f.parsedMux.Unlock() + out.Data = search.Tokens(f.doc, in.TextDocument.URI, 0, 1, 2) return nil }