Skip to content

Commit f3fcb0a

Browse files
committed
refactor(internal/lsp): 合并相似代码
1 parent 0f5dac4 commit f3fcb0a

File tree

6 files changed

+43
-157
lines changed

6 files changed

+43
-157
lines changed

internal/lsp/hover.go

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"reflect"
77

88
"github.com/caixw/apidoc/v7/core"
9-
"github.com/caixw/apidoc/v7/internal/ast"
109
"github.com/caixw/apidoc/v7/internal/lsp/protocol"
1110
)
1211

@@ -17,22 +16,6 @@ type usager interface {
1716

1817
var usagerType = reflect.TypeOf((*usager)(nil)).Elem()
1918

20-
func hover(doc *ast.APIDoc, uri core.URI, pos core.Position, h *protocol.Hover) {
21-
u := doc.Search(uri, pos, usagerType)
22-
if u == nil {
23-
return
24-
}
25-
26-
usage := u.(usager)
27-
if v := usage.Usage(); v != "" {
28-
h.Range = usage.Loc().Range
29-
h.Contents = protocol.MarkupContent{
30-
Kind: protocol.MarkupKindMarkdown,
31-
Value: v,
32-
}
33-
}
34-
}
35-
3619
// textDocument/hover
3720
//
3821
// https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover
@@ -46,6 +29,15 @@ func (s *server) textDocumentHover(notify bool, in *protocol.HoverParams, out *p
4629
f.parsedMux.RLock()
4730
defer f.parsedMux.RUnlock()
4831

49-
hover(f.doc, in.TextDocument.URI, in.TextDocumentPositionParams.Position, out)
32+
if u := f.doc.Search(in.TextDocument.URI, in.TextDocumentPositionParams.Position, usagerType); u != nil {
33+
usage := u.(usager)
34+
if v := usage.Usage(); v != "" {
35+
out.Range = usage.Loc().Range
36+
out.Contents = protocol.MarkupContent{
37+
Kind: protocol.MarkupKindMarkdown,
38+
Value: v,
39+
}
40+
}
41+
}
5042
return nil
5143
}

internal/lsp/hover_test.go

Lines changed: 8 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ import (
1616
"github.com/caixw/apidoc/v7/internal/lsp/protocol"
1717
)
1818

19-
func loadHoverDoc(a *assert.Assertion) *ast.APIDoc {
19+
func TestServer_textDocumentHover(t *testing.T) {
20+
a := assert.New(t)
21+
s := newTestServer(true, log.New(ioutil.Discard, "", 0), log.New(ioutil.Discard, "", 0))
22+
h := &protocol.Hover{}
23+
err := s.textDocumentHover(false, &protocol.HoverParams{}, h)
24+
a.Nil(err)
25+
2026
const b = `<apidoc version="1.1.1">
2127
<title>标题</title>
2228
<mimetype>xml</mimetype>
@@ -30,28 +36,17 @@ func loadHoverDoc(a *assert.Assertion) *ast.APIDoc {
3036
<response status="200" />
3137
</api>
3238
</apidoc>`
33-
3439
blk := core.Block{Data: []byte(b), Location: core.Location{URI: "file:///test/doc.go"}}
3540
rslt := messagetest.NewMessageHandler()
3641
doc := &ast.APIDoc{}
3742
doc.Parse(rslt.Handler, blk)
3843
rslt.Handler.Stop()
3944
a.Empty(rslt.Errors)
4045

41-
return doc
42-
}
43-
44-
func TestServer_textDocumentHover(t *testing.T) {
45-
a := assert.New(t)
46-
s := newTestServer(true, log.New(ioutil.Discard, "", 0), log.New(ioutil.Discard, "", 0))
47-
h := &protocol.Hover{}
48-
err := s.textDocumentHover(false, &protocol.HoverParams{}, h)
49-
a.Nil(err)
50-
5146
s.folders = []*folder{
5247
{
5348
WorkspaceFolder: protocol.WorkspaceFolder{Name: "test", URI: "file:///test"},
54-
doc: loadHoverDoc(a),
49+
doc: doc,
5550
},
5651
}
5752

@@ -67,58 +62,3 @@ func TestServer_textDocumentHover(t *testing.T) {
6762
})
6863
a.Equal(h.Contents.Value, locale.Sprintf("usage-apidoc-title"))
6964
}
70-
71-
func TestHover(t *testing.T) {
72-
a := assert.New(t)
73-
74-
doc := loadHoverDoc(a)
75-
76-
// 超出范围
77-
h := &protocol.Hover{}
78-
pos := core.Position{Line: 1000, Character: 1}
79-
hover(doc, core.URI("file:///test/doc.go"), pos, h)
80-
a.True(h.Range.IsEmpty()).Empty(h.Contents.Value)
81-
82-
// title
83-
h = &protocol.Hover{}
84-
pos = core.Position{Line: 1, Character: 1}
85-
hover(doc, core.URI("file:///test/doc.go"), pos, h)
86-
a.Equal(h.Range, core.Range{
87-
Start: core.Position{Line: 1, Character: 1},
88-
End: core.Position{Line: 1, Character: 18},
89-
})
90-
a.Equal(h.Contents.Value, locale.Sprintf("usage-apidoc-title"))
91-
92-
// apis[0]
93-
h = &protocol.Hover{}
94-
pos = core.Position{Line: 4, Character: 2}
95-
hover(doc, core.URI("file:///test/doc.go"), pos, h)
96-
a.Equal(h.Range, core.Range{
97-
Start: core.Position{Line: 4, Character: 1},
98-
End: core.Position{Line: 7, Character: 7},
99-
})
100-
a.Equal(h.Contents.Value, locale.Sprintf("usage-apidoc-apis"))
101-
102-
// 改变了 api[0].URI
103-
doc.APIs[0].URI = core.URI("api0.go")
104-
105-
// 改变了 api[0].URI,不再匹配 apis[0],取其父元素 apidoc
106-
h = &protocol.Hover{}
107-
pos = core.Position{Line: 4, Character: 1}
108-
hover(doc, core.URI("file:///test/doc.go"), pos, h)
109-
a.Equal(h.Range, core.Range{
110-
Start: core.Position{Line: 0, Character: 0},
111-
End: core.Position{Line: 12, Character: 9},
112-
})
113-
a.Equal(h.Contents.Value, locale.Sprintf("usage-apidoc"))
114-
115-
// 与 apis[0] 相同的 URI
116-
h = &protocol.Hover{}
117-
pos = core.Position{Line: 4, Character: 1}
118-
hover(doc, core.URI("api0.go"), pos, h)
119-
a.Equal(h.Range, core.Range{
120-
Start: core.Position{Line: 4, Character: 1},
121-
End: core.Position{Line: 7, Character: 7},
122-
})
123-
a.Equal(h.Contents.Value, locale.Sprintf("usage-apidoc-apis"))
124-
}

internal/lsp/reference.go

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ func (s *server) textDocumentDefinition(notify bool, in *protocol.DefinitionPara
4646
f.parsedMux.RLock()
4747
defer f.parsedMux.RUnlock()
4848

49-
*out = definition(f.doc, in.TextDocument.URI, in.Position)
49+
if r := f.doc.Search(in.TextDocument.URI, in.TextDocumentPositionParams.Position, definitionerType); r != nil {
50+
*out = []core.Location{r.(ast.Definitioner).Definition().Location}
51+
}
5052
return nil
5153
}
5254

@@ -67,12 +69,3 @@ func references(doc *ast.APIDoc, uri core.URI, pos core.Position, include bool)
6769

6870
return
6971
}
70-
71-
func definition(doc *ast.APIDoc, uri core.URI, pos core.Position) []core.Location {
72-
r := doc.Search(uri, pos, definitionerType)
73-
if r == nil {
74-
return []core.Location{}
75-
}
76-
77-
return []core.Location{r.(ast.Definitioner).Definition().Location}
78-
}

internal/lsp/reference_test.go

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -123,40 +123,3 @@ func TestReferences(t *testing.T) {
123123
locs = references(doc, "file:///root/doc.go", pos, true)
124124
a.Equal(len(locs), 3)
125125
}
126-
127-
func TestDefinition(t *testing.T) {
128-
a := assert.New(t)
129-
doc := loadReferencesDoc(a)
130-
131-
pos := core.Position{}
132-
locs := definition(doc, "file:///root/doc.go", pos)
133-
a.Empty(locs)
134-
135-
pos = core.Position{Line: 3, Character: 16}
136-
locs = definition(doc, "file:///root/doc.go", pos)
137-
a.Empty(locs)
138-
139-
pos = core.Position{Line: 6, Character: 2}
140-
locs = definition(doc, "file:///root/doc.go", pos)
141-
a.Equal(locs, []core.Location{
142-
{
143-
URI: "file:///root/doc.go",
144-
Range: core.Range{
145-
Start: core.Position{Line: 3, Character: 1},
146-
End: core.Position{Line: 3, Character: 31},
147-
},
148-
},
149-
})
150-
151-
pos = core.Position{Line: 12, Character: 2}
152-
locs = definition(doc, "file:///root/doc.go", pos)
153-
a.Equal(locs, []core.Location{
154-
{
155-
URI: "file:///root/doc.go",
156-
Range: core.Range{
157-
Start: core.Position{Line: 4, Character: 1},
158-
End: core.Position{Line: 4, Character: 31},
159-
},
160-
},
161-
})
162-
}

internal/xmlenc/decode.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ func Decode(p *Parser, v interface{}, namespace string) {
107107
switch elem := t.(type) {
108108
case *StartElement:
109109
if hasRoot { // 多个根元素
110-
_ = p.endElement(elem) // 找到对应的结束标签,忽略错误
111-
msg := p.NewError(elem.Location.Range.Start, p.Current().Position, elem.Name.String(), locale.ErrMultipleRootTag).
112-
AddTypes(core.ErrorTypeUnused)
110+
p.endElement(elem) // 找到对应的结束标签,忽略错误
111+
msg := core.NewError(locale.ErrMultipleRootTag).AddTypes(core.ErrorTypeUnused).WithField(elem.Name.String()).
112+
WithLocation(core.Location{URI: elem.URI, Range: core.Range{Start: elem.Location.Range.Start, End: p.Current().Position}})
113113
d.p.Warning(msg)
114114
return
115115
}
@@ -155,19 +155,19 @@ func (d *decoder) decode(n *node.Node, start *StartElement) *EndElement {
155155
func (d *decoder) checkOmitempty(n *node.Node, start, end core.Position, field string) {
156156
for _, attr := range n.Attributes {
157157
if canNotEmpty(attr) {
158-
d.p.Error(d.p.NewError(start, end, attr.Name, locale.ErrIsEmpty, attr.Name))
158+
d.p.Error(d.p.newError(start, end, attr.Name, locale.ErrIsEmpty, attr.Name))
159159
}
160160
}
161161
for _, elem := range n.Elements {
162162
if canNotEmpty(elem) {
163-
d.p.Error(d.p.NewError(start, end, elem.Name, locale.ErrIsEmpty, elem.Name))
163+
d.p.Error(d.p.newError(start, end, elem.Name, locale.ErrIsEmpty, elem.Name))
164164
}
165165
}
166166
if n.CData != nil && canNotEmpty(n.CData) {
167-
d.p.Error(d.p.NewError(start, end, "cdata", locale.ErrIsEmpty, field))
167+
d.p.Error(d.p.newError(start, end, "cdata", locale.ErrIsEmpty, field))
168168
}
169169
if n.Content != nil && canNotEmpty(n.Content) {
170-
d.p.Error(d.p.NewError(start, end, "content", locale.ErrIsEmpty, field))
170+
d.p.Error(d.p.newError(start, end, "content", locale.ErrIsEmpty, field))
171171
}
172172
}
173173

@@ -222,7 +222,7 @@ func (d *decoder) decodeElements(n *node.Node) (end *EndElement, ok bool) {
222222
t, loc, err := d.p.Token()
223223
if errors.Is(err, io.EOF) {
224224
// 应该只有 EndElement 才能返回,否则就不完整的 XML
225-
d.p.Error(d.p.NewError(d.p.Current().Position, d.p.Current().Position, "", locale.ErrNotFoundEndTag))
225+
d.p.Error(d.p.newError(d.p.Current().Position, d.p.Current().Position, "", locale.ErrNotFoundEndTag))
226226
return nil, false
227227
} else if err != nil {
228228
d.p.Error(err)
@@ -234,7 +234,7 @@ func (d *decoder) decodeElements(n *node.Node) (end *EndElement, ok bool) {
234234
if (elem.Name.Local.Value == n.Value.Name) && (elem.Name.Prefix.Value == d.prefix) {
235235
return elem, true
236236
}
237-
d.p.Error(d.p.NewError(elem.Location.Range.Start, elem.Location.Range.End, n.Value.Name, locale.ErrNotFoundEndTag))
237+
d.p.Error(d.p.newError(elem.Location.Range.Start, elem.Location.Range.End, n.Value.Name, locale.ErrNotFoundEndTag))
238238
return nil, false
239239
case *CData:
240240
if n.CData != nil {
@@ -252,7 +252,7 @@ func (d *decoder) decodeElements(n *node.Node) (end *EndElement, ok bool) {
252252
return nil, false
253253
}
254254

255-
e := d.p.NewError(elem.Location.Range.Start, d.p.Current().Position, elem.Name.String(), locale.ErrInvalidTag).
255+
e := d.p.newError(elem.Location.Range.Start, d.p.Current().Position, elem.Name.String(), locale.ErrInvalidTag).
256256
AddTypes(core.ErrorTypeUnused)
257257
d.p.Warning(e)
258258
break // 忽略不存在的子元素

internal/xmlenc/parser.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func (p *Parser) parseComment(pos lexer.Position) (*Comment, core.Location, erro
103103

104104
data, found := p.DelimString("-->", false)
105105
if !found {
106-
return nil, core.Location{}, p.NewError(p.Current().Position, p.Current().Position, "<!--", locale.ErrNotFoundEndTag)
106+
return nil, core.Location{}, p.newError(p.Current().Position, p.Current().Position, "<!--", locale.ErrNotFoundEndTag)
107107
}
108108
end := p.Current()
109109
p.Next(3) // 跳过 --> 三个字符
@@ -127,7 +127,7 @@ func (p *Parser) parseStartElement(pos lexer.Position) (*StartElement, core.Loca
127127
start := p.Current()
128128
name, found := p.DelimFunc(func(r rune) bool { return unicode.IsSpace(r) || r == '/' || r == '>' }, false)
129129
if !found || len(name) == 0 {
130-
return nil, core.Location{}, p.NewError(p.Current().Position, p.Current().Position, "", locale.ErrInvalidXML)
130+
return nil, core.Location{}, p.newError(p.Current().Position, p.Current().Position, "", locale.ErrInvalidXML)
131131
}
132132

133133
elem := &StartElement{
@@ -152,7 +152,7 @@ func (p *Parser) parseStartElement(pos lexer.Position) (*StartElement, core.Loca
152152
return elem, elem.Location, nil
153153
}
154154

155-
return nil, core.Location{}, p.NewError(p.Current().Position, p.Current().Position, string(name), locale.ErrNotFoundEndTag)
155+
return nil, core.Location{}, p.newError(p.Current().Position, p.Current().Position, string(name), locale.ErrNotFoundEndTag)
156156
}
157157

158158
func parseName(name []byte, uri core.URI, start, end core.Position) Name {
@@ -188,7 +188,7 @@ func (p *Parser) parseEndElement(pos lexer.Position) (*EndElement, core.Location
188188

189189
name, found := p.Delim('>', false)
190190
if !found || len(name) == 0 {
191-
return nil, core.Location{}, p.NewError(p.Current().Position, p.Current().Position, "", locale.ErrInvalidXML)
191+
return nil, core.Location{}, p.newError(p.Current().Position, p.Current().Position, "", locale.ErrInvalidXML)
192192
}
193193
end := p.Current()
194194
p.Next(1) // 去掉 > 符号
@@ -211,7 +211,7 @@ func (p *Parser) parseCData(pos lexer.Position) (*CData, core.Location, error) {
211211
for {
212212
v, found := p.DelimString(cdataEnd, false)
213213
if !found {
214-
return nil, core.Location{}, p.NewError(pos.Position, p.Current().Position, cdataStart, locale.ErrNotFoundEndTag)
214+
return nil, core.Location{}, p.newError(pos.Position, p.Current().Position, cdataStart, locale.ErrNotFoundEndTag)
215215
}
216216
value = append(value, v...)
217217

@@ -291,7 +291,7 @@ func (p *Parser) parseCData(pos lexer.Position) (*CData, core.Location, error) {
291291
func (p *Parser) parseInstruction(pos lexer.Position) (*Instruction, core.Location, error) {
292292
name, nameRange := p.getName()
293293
if len(name) == 0 {
294-
return nil, core.Location{}, p.NewError(p.Current().Position, p.Current().Position, "", locale.ErrInvalidXML)
294+
return nil, core.Location{}, p.newError(p.Current().Position, p.Current().Position, "", locale.ErrInvalidXML)
295295
}
296296
elem := &Instruction{
297297
Location: core.Location{URI: p.Location.URI},
@@ -316,7 +316,7 @@ func (p *Parser) parseInstruction(pos lexer.Position) (*Instruction, core.Locati
316316
return elem, elem.Location, nil
317317
}
318318

319-
return nil, core.Location{}, p.NewError(p.Current().Position, p.Current().Position, "<?", locale.ErrNotFoundEndTag)
319+
return nil, core.Location{}, p.newError(p.Current().Position, p.Current().Position, "<?", locale.ErrNotFoundEndTag)
320320
}
321321

322322
func (p *Parser) parseAttributes() (attrs []*Attribute, err error) {
@@ -351,18 +351,18 @@ func (p *Parser) parseAttribute() (*Attribute, error) {
351351

352352
p.Spaces(0)
353353
if !p.Match("=") {
354-
return nil, p.NewError(p.Current().Position, p.Current().Position, "", locale.ErrInvalidXML)
354+
return nil, p.newError(p.Current().Position, p.Current().Position, "", locale.ErrInvalidXML)
355355
}
356356

357357
p.Spaces(0)
358358
if !p.Match("\"") {
359-
return nil, p.NewError(p.Current().Position, p.Current().Position, "", locale.ErrInvalidXML)
359+
return nil, p.newError(p.Current().Position, p.Current().Position, "", locale.ErrInvalidXML)
360360
}
361361

362362
pos = p.Current()
363363
value, found := p.Delim('"', true)
364364
if !found || len(value) == 0 {
365-
return nil, p.NewError(p.Current().Position, p.Current().Position, "", locale.ErrInvalidXML)
365+
return nil, p.newError(p.Current().Position, p.Current().Position, "", locale.ErrInvalidXML)
366366
}
367367
end := p.Current().SubRune('"') // 不包含 " 符号
368368
attr.Value = String{
@@ -438,10 +438,8 @@ func (p *Parser) endElement(start *StartElement) error {
438438
}
439439
}
440440

441-
// NewError 生成 *core.Error 对象
442-
//
443-
// 其中的 URI 来自于 p.Location.URI
444-
func (p *Parser) NewError(start, end core.Position, field string, key message.Reference, v ...interface{}) *core.Error {
441+
// newError 生成 *core.Error 对象,其中的 URI 来自于 p.Location.URI。
442+
func (p *Parser) newError(start, end core.Position, field string, key message.Reference, v ...interface{}) *core.Error {
445443
return core.NewError(key, v...).
446444
WithField(field).
447445
WithLocation(core.Location{

0 commit comments

Comments
 (0)