Skip to content

Commit

Permalink
refactor(internal/lsp): 防止同时访问和修改 folder.doc
Browse files Browse the repository at this point in the history
  • Loading branch information
caixw committed Jul 29, 2020
1 parent 1990e37 commit 8c56a05
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 15 deletions.
10 changes: 10 additions & 0 deletions internal/lsp/folder.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"strings"
"sync"

"github.com/issue9/sliceutil"

Expand All @@ -27,6 +28,8 @@ type folder struct {
cfg *build.Config
srv *server

parsedMux sync.Mutex

// 保存着错误和警告的信息
errors, warns []*core.SyntaxError
}
Expand All @@ -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 {
Expand All @@ -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) {
Expand Down Expand Up @@ -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
Expand Down
6 changes: 1 addition & 5 deletions internal/lsp/search/hover.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand All @@ -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
}
}

Expand All @@ -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 位置的元素,如果找到匹配项,还会查找其子项,是不是匹配度更高。
Expand Down
8 changes: 4 additions & 4 deletions internal/lsp/search/hover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -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},
Expand All @@ -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},
Expand All @@ -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},
Expand Down
22 changes: 16 additions & 6 deletions internal/lsp/textdocument.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -86,14 +90,17 @@ 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)
if f.doc.URI == uri {
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 {
Expand All @@ -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
}

0 comments on commit 8c56a05

Please sign in to comment.