Skip to content

Commit 0f5dac4

Browse files
committed
refactor(internal/lsp): 调整 semanticTokens 的实现方式
现在每个元素都带有 Location.URI 字段,不再需要先比较 api.URI 再比较元素的范围,可以直接与元素的 URI 字段作比较。
1 parent 50f0bcd commit 0f5dac4

File tree

2 files changed

+35
-25
lines changed

2 files changed

+35
-25
lines changed

internal/lsp/semantic.go

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import (
88
"sort"
99
"unicode"
1010

11-
"github.com/issue9/sliceutil"
12-
1311
"github.com/caixw/apidoc/v7/core"
1412
"github.com/caixw/apidoc/v7/internal/ast"
1513
"github.com/caixw/apidoc/v7/internal/lsp/protocol"
@@ -18,7 +16,8 @@ import (
1816
)
1917

2018
type tokenBuilder struct {
21-
tag, attr, value int // 可用的 token
19+
uri core.URI // 当前 builder 对应的文件地址
20+
tag, attr, value int // 可用的 token
2221

2322
// 每个二级数组长度为 5,表示一组 semanticToken 数据。
2423
// 数据分别为 绝对行号,当前行的绝对起始位置,长度,以及 token 和 modifier。
@@ -44,25 +43,14 @@ func (s *server) textDocumentSemanticTokens(notify bool, in *protocol.SemanticTo
4443
// value 表示属性的颜色值;
4544
func semanticTokens(doc *ast.APIDoc, uri core.URI, tag, attr, value int) []int {
4645
b := &tokenBuilder{
46+
uri: uri,
4747
tag: tag,
4848
attr: attr,
4949
value: value,
5050
tokens: make([][]int, 0, 100),
5151
}
5252

53-
if doc.URI == uri {
54-
b.parse(reflect.ValueOf(doc), "APIs")
55-
}
56-
57-
for _, api := range doc.APIs {
58-
matched := api.URI == uri || (api.URI == "" && doc.URI == uri)
59-
if !matched {
60-
continue
61-
}
62-
63-
b.parse(reflect.ValueOf(api))
64-
}
65-
53+
b.parse(reflect.ValueOf(doc))
6654
b.sort()
6755
return b.build()
6856
}
@@ -108,20 +96,18 @@ func (b *tokenBuilder) sort() {
10896
})
10997
}
11098

111-
func (b *tokenBuilder) parse(v reflect.Value, exclude ...string) {
99+
func (b *tokenBuilder) parse(v reflect.Value) {
112100
v = node.RealValue(v)
113-
t := v.Type()
114-
if t.Kind() != reflect.Struct {
101+
if !b.matched(v) {
115102
return
116103
}
117104

118105
b.parseAnonymous(v)
119106

107+
t := v.Type()
120108
for i := 0; i < t.NumField(); i++ {
121109
tf := t.Field(i)
122-
if tf.Anonymous ||
123-
unicode.IsLower(rune(tf.Name[0])) ||
124-
sliceutil.Count(exclude, func(i int) bool { return exclude[i] == tf.Name }) > 0 { // 需要过滤的字段
110+
if tf.Anonymous || unicode.IsLower(rune(tf.Name[0])) {
125111
continue
126112
}
127113

@@ -136,6 +122,23 @@ func (b *tokenBuilder) parse(v reflect.Value, exclude ...string) {
136122
}
137123
}
138124

125+
func (b *tokenBuilder) matched(v reflect.Value) bool {
126+
if v.Kind() != reflect.Struct {
127+
return false
128+
}
129+
130+
if s, ok := v.Interface().(core.Searcher); ok && s.Loc().URI == b.uri {
131+
return true
132+
}
133+
134+
if !v.CanAddr() {
135+
return false
136+
}
137+
138+
s, ok := v.Addr().Interface().(core.Searcher)
139+
return ok && s.Loc().URI == b.uri
140+
}
141+
139142
func (b *tokenBuilder) parseAnonymous(v reflect.Value) {
140143
t := v.Type()
141144
switch elem := v.Interface().(type) {

internal/lsp/semantic_test.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,11 @@ func TestTokenBuilder_sort(t *testing.T) {
9090
})
9191
}
9292

93-
func TestTokens(t *testing.T) {
93+
func TestSemanticTokens(t *testing.T) {
9494
a := assert.New(t)
9595

96-
b := `<apidoc version="1.1.1">
96+
// NOTE 此处的 apidoc 属性值必须与当前的文档主版本号相同
97+
b := `<apidoc version="1.1.1" apidoc="6.0.0" created="2020-01-02T13:12:11+08:00">
9798
<title>标题</title>
9899
<mimetype>xml</mimetype>
99100
<api method="GET">
@@ -103,7 +104,7 @@ func TestTokens(t *testing.T) {
103104
104105
<api method="POST">
105106
<path path="/users" />
106-
<response status="200" />
107+
<response status="200" type="number" />
107108
</api>
108109
</apidoc>`
109110
blk := core.Block{Data: []byte(b), Location: core.Location{URI: "doc.go"}}
@@ -117,6 +118,10 @@ func TestTokens(t *testing.T) {
117118
0, 1, 6, 1, 0, // apidoc
118119
0, 7, 7, 2, 0,
119120
0, 9, 5, 3, 0,
121+
0, 7, 6, 2, 0,
122+
0, 8, 5, 3, 0,
123+
0, 7, 7, 2, 0,
124+
0, 9, 25, 3, 0,
120125

121126
1, 2, 5, 1, 0, // <title>
122127
// {1, 8, 2, 0, 0}, // 元素内容不作解析,直接采用默认的注释颜色
@@ -151,6 +156,8 @@ func TestTokens(t *testing.T) {
151156
1, 3, 8, 1, 0, // response
152157
0, 9, 6, 2, 0,
153158
0, 8, 3, 3, 0,
159+
0, 5, 4, 2, 0,
160+
0, 6, 6, 3, 0,
154161

155162
1, 3, 3, 1, 0, // </api>
156163

0 commit comments

Comments
 (0)