Skip to content

Commit 527b8e2

Browse files
committed
add event symbols
1 parent 7a49acf commit 527b8e2

8 files changed

+279
-8
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ appear here and there.
2424
- Message box text overflow checking
2525
- Completions
2626
- Event folding
27+
- Event symbols (outline + go to event)
2728

2829
## Getting Started
2930

@@ -63,11 +64,18 @@ handler
6364
handler and sends error/warning diagnostics to the client
6465
- `textDocument/completion` - sends a list of TSC commands that can be used from
6566
within the editor's autocompletion feature
67+
- `textDocument/documentSymbol` - sends a list of TSC events that can be found
68+
in the opened file
69+
- `textDocument/foldingRange` - sends a list of event ranges that can be used
70+
for folding
6671
- `textDocument/hover` - provides hover information for commands and events
6772
- `tsc/setConfig` - updates the LSP's default configuration with overrides from
6873
the workspace's `.tscrc.json` file
6974
- `tsc/resetConfig` - reverts to the LSP's built-in (standard) TSC configuration
7075

76+
Additionally, some required methods are also exposed, such as `initialize`,
77+
`initialized`, `shutdown`, `exit`, and `$/cancelRequest`.
78+
7179
## Credits
7280

7381
- [Studio Pixel][studio-pixel] and [Nicalis][nicalis] for Cave Story and the TSC

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ require (
66
github.com/creachadair/jrpc2 v0.10.3
77
github.com/spf13/afero v1.4.1
88
github.com/urfave/cli/v2 v2.2.0
9-
pkg.nimblebun.works/go-lsp v1.0.3
9+
pkg.nimblebun.works/go-lsp v1.0.4
1010
)

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,5 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N
4141
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
4242
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
4343
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
44-
pkg.nimblebun.works/go-lsp v1.0.3 h1:tKYx+vhdwgA6+2rDBFfZXEg4XuQBvB5GpbKZYKiE+NA=
45-
pkg.nimblebun.works/go-lsp v1.0.3/go.mod h1:Suh759Ki+DjU0zwf0xkl1H6Ln1C6/+GtYyNofbtfcug=
44+
pkg.nimblebun.works/go-lsp v1.0.4 h1:kugzdbrgG+sUWSLnNxW/TRER1SfbJnVunAKWjfmbgXQ=
45+
pkg.nimblebun.works/go-lsp v1.0.4/go.mod h1:Suh759Ki+DjU0zwf0xkl1H6Ln1C6/+GtYyNofbtfcug=
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package handlers
2+
3+
import (
4+
"context"
5+
6+
"github.com/creachadair/jrpc2"
7+
"pkg.nimblebun.works/go-lsp"
8+
lsctx "pkg.nimblebun.works/tsc-language-server/langserver/context"
9+
"pkg.nimblebun.works/tsc-language-server/langserver/filesystem/filehandler"
10+
"pkg.nimblebun.works/tsc-language-server/tsc"
11+
)
12+
13+
// TextDocumentSymbol is the callback that runs on the
14+
// "textDocument/documentSymbol" method.
15+
func (mh *MethodHandler) TextDocumentSymbol(ctx context.Context, req *jrpc2.Request) ([]lsp.DocumentSymbol, error) {
16+
var symbols []lsp.DocumentSymbol
17+
18+
var params lsp.DocumentSymbolParams
19+
err := req.UnmarshalParams(jrpc2.NonStrict(&params))
20+
if err != nil {
21+
return symbols, err
22+
}
23+
24+
fs, err := lsctx.FileSystem(ctx)
25+
if err != nil {
26+
return symbols, err
27+
}
28+
29+
handler := filehandler.FromDocumentURI(params.TextDocument.URI)
30+
31+
path, err := handler.FullPath()
32+
if err != nil {
33+
return symbols, err
34+
}
35+
36+
data, err := fs.ReadFile(path)
37+
if err != nil {
38+
return symbols, err
39+
}
40+
41+
contents := string(data)
42+
43+
doc := lsp.TextDocumentItem{
44+
URI: params.TextDocument.URI,
45+
LanguageID: "tsc",
46+
Text: contents,
47+
}
48+
49+
symbols = tsc.GetEventSymbols(contents, doc)
50+
51+
return symbols, nil
52+
}

langserver/handlers/initialize.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ func (mh *MethodHandler) Initialize(ctx context.Context, _ *jrpc2.Request) (lsp.
1818
CompletionProvider: &lsp.CompletionOptions{
1919
ResolveProvider: false,
2020
},
21-
HoverProvider: &lsp.HoverOptions{},
22-
FoldingRangeProvider: &lsp.FoldingRangeRegistrationOptions{},
21+
HoverProvider: &lsp.HoverOptions{},
22+
FoldingRangeProvider: &lsp.FoldingRangeRegistrationOptions{},
23+
DocumentSymbolProvider: &lsp.DocumentSymbolRegistrationOptions{},
2324
},
2425
}
2526

langserver/handlers/service.go

+14-3
Original file line numberDiff line numberDiff line change
@@ -144,16 +144,15 @@ func (service *Service) Assigner() (jrpc2.Assigner, error) {
144144
return handle(ctx, req, TextDocumentCompletion)
145145
},
146146

147-
"textDocument/hover": func(ctx context.Context, req *jrpc2.Request) (interface{}, error) {
147+
"textDocument/documentSymbol": func(ctx context.Context, req *jrpc2.Request) (interface{}, error) {
148148
err := sess.EnsureInitialized()
149149
if err != nil {
150150
return nil, err
151151
}
152152

153-
ctx = lsctx.WithConfig(ctx, &conf)
154153
ctx = lsctx.WithFileSystem(ctx, fs)
155154

156-
return handle(ctx, req, mh.TextDocumentHover)
155+
return handle(ctx, req, mh.TextDocumentSymbol)
157156
},
158157

159158
"textDocument/foldingRange": func(ctx context.Context, req *jrpc2.Request) (interface{}, error) {
@@ -167,6 +166,18 @@ func (service *Service) Assigner() (jrpc2.Assigner, error) {
167166
return handle(ctx, req, mh.TextDocumentFoldingRange)
168167
},
169168

169+
"textDocument/hover": func(ctx context.Context, req *jrpc2.Request) (interface{}, error) {
170+
err := sess.EnsureInitialized()
171+
if err != nil {
172+
return nil, err
173+
}
174+
175+
ctx = lsctx.WithConfig(ctx, &conf)
176+
ctx = lsctx.WithFileSystem(ctx, fs)
177+
178+
return handle(ctx, req, mh.TextDocumentHover)
179+
},
180+
170181
"tsc/setConfig": func(ctx context.Context, req *jrpc2.Request) (interface{}, error) {
171182
err := sess.EnsureInitialized()
172183
if err != nil {

tsc/event_symbols.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package tsc
2+
3+
import (
4+
"regexp"
5+
6+
"pkg.nimblebun.works/go-lsp"
7+
"pkg.nimblebun.works/tsc-language-server/langserver/textdocument"
8+
)
9+
10+
// GetEventSymbols will return a list of events as LSP-compatible symbols.
11+
func GetEventSymbols(text string, textDocumentItem lsp.TextDocumentItem) []lsp.DocumentSymbol {
12+
document := textdocument.From(textDocumentItem)
13+
14+
// this will match #0000 until the end of the line
15+
re := regexp.MustCompile("#(?:[0-9]{4}).*")
16+
17+
symbols := make([]lsp.DocumentSymbol, 0)
18+
19+
for _, match := range re.FindAllStringIndex(text, -1) {
20+
from, to := match[0], match[1]
21+
eventDeclaration := text[from:to]
22+
23+
symbolRange := &lsp.Range{
24+
Start: document.PositionAt(from),
25+
End: document.PositionAt(to),
26+
}
27+
28+
symbol := lsp.DocumentSymbol{
29+
Name: eventDeclaration,
30+
Kind: lsp.SKEvent,
31+
Range: symbolRange,
32+
SelectionRange: symbolRange,
33+
}
34+
35+
symbols = append(symbols, symbol)
36+
}
37+
38+
return symbols
39+
}

tsc/event_symbols_test.go

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package tsc_test
2+
3+
import (
4+
"testing"
5+
6+
"pkg.nimblebun.works/go-lsp"
7+
"pkg.nimblebun.works/tsc-language-server/tsc"
8+
)
9+
10+
func TestGetEventSymbols(t *testing.T) {
11+
const text = `#0090fadein_from_left
12+
<MNA<CMU0000<FAI0000<END
13+
#0091fadein_from_up
14+
<MNA<CMU0000<FAI0001<END
15+
#0092fadein_from_right
16+
<MNA<CMU0000<FAI0002<END
17+
#0093fadein_from_down
18+
<MNA<CMU0000<FAI0003<END
19+
#0094fadein_from_center
20+
<MNA<CMU0000<FAI0004<END`
21+
22+
document := lsp.TextDocumentItem{
23+
Text: text,
24+
}
25+
26+
symbols := tsc.GetEventSymbols(text, document)
27+
28+
t.Run("should return correct number of symbols", func(t *testing.T) {
29+
if len(symbols) != 5 {
30+
t.Errorf(
31+
"tsc.GetEventSymbols(text, document) length got %v, want %v",
32+
len(symbols),
33+
5,
34+
)
35+
}
36+
})
37+
38+
t.Run("should return correct event names and locations", func(t *testing.T) {
39+
data := []lsp.DocumentSymbol{
40+
{
41+
Name: "#0090fadein_from_left",
42+
Range: &lsp.Range{
43+
Start: lsp.Position{
44+
Line: 0,
45+
Character: 0,
46+
},
47+
End: lsp.Position{
48+
Line: 0,
49+
Character: 21,
50+
},
51+
},
52+
},
53+
54+
{
55+
Name: "#0091fadein_from_up",
56+
Range: &lsp.Range{
57+
Start: lsp.Position{
58+
Line: 2,
59+
Character: 0,
60+
},
61+
End: lsp.Position{
62+
Line: 2,
63+
Character: 19,
64+
},
65+
},
66+
},
67+
68+
{
69+
Name: "#0092fadein_from_right",
70+
Range: &lsp.Range{
71+
Start: lsp.Position{
72+
Line: 4,
73+
Character: 0,
74+
},
75+
End: lsp.Position{
76+
Line: 4,
77+
Character: 22,
78+
},
79+
},
80+
},
81+
82+
{
83+
Name: "#0093fadein_from_down",
84+
Range: &lsp.Range{
85+
Start: lsp.Position{
86+
Line: 6,
87+
Character: 0,
88+
},
89+
End: lsp.Position{
90+
Line: 6,
91+
Character: 21,
92+
},
93+
},
94+
},
95+
96+
{
97+
Name: "#0094fadein_from_center",
98+
Range: &lsp.Range{
99+
Start: lsp.Position{
100+
Line: 8,
101+
Character: 0,
102+
},
103+
End: lsp.Position{
104+
Line: 8,
105+
Character: 23,
106+
},
107+
},
108+
},
109+
}
110+
111+
for idx, symbol := range symbols {
112+
expected := data[idx]
113+
114+
if symbol.Name != expected.Name {
115+
t.Errorf(
116+
"tsc.GetEventSymbols(text, document) @ %d -> name: got %v, want %v",
117+
idx,
118+
symbol.Name,
119+
expected.Name,
120+
)
121+
}
122+
123+
if symbol.Range.Start.Line != expected.Range.Start.Line {
124+
t.Errorf(
125+
"tsc.GetEventSymbols(text, document) @ %d -> range start line: got %v, want %v",
126+
idx,
127+
symbol.Range.Start.Line,
128+
expected.Range.Start.Line,
129+
)
130+
}
131+
132+
if symbol.Range.Start.Character != expected.Range.Start.Character {
133+
t.Errorf(
134+
"tsc.GetEventSymbols(text, document) @ %d -> range start character: got %v, want %v",
135+
idx,
136+
symbol.Range.Start.Character,
137+
expected.Range.Start.Character,
138+
)
139+
}
140+
141+
if symbol.Range.End.Line != expected.Range.End.Line {
142+
t.Errorf(
143+
"tsc.GetEventSymbols(text, document) @ %d -> range end line: got %v, want %v",
144+
idx,
145+
symbol.Range.End.Line,
146+
expected.Range.End.Line,
147+
)
148+
}
149+
150+
if symbol.Range.End.Character != expected.Range.End.Character {
151+
t.Errorf(
152+
"tsc.GetEventSymbols(text, document) @ %d -> range end character: got %v, want %v",
153+
idx,
154+
symbol.Range.End.Character,
155+
expected.Range.End.Character,
156+
)
157+
}
158+
}
159+
})
160+
}

0 commit comments

Comments
 (0)