Skip to content

Commit 9600296

Browse files
committed
feat(documentSymbol): add documentSymbol support closes #28
1 parent a2919f1 commit 9600296

File tree

2 files changed

+113
-1
lines changed

2 files changed

+113
-1
lines changed

src/handles/documentSymbol.ts

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import {DocumentSymbolParams, DocumentSymbol, SymbolKind, Range, Position} from "vscode-languageserver";
2+
3+
import {workspace} from "../server/workspaces";
4+
import {IFunction} from "../server/buffer";
5+
import {documents} from "../server/documents";
6+
7+
export const documentSymbolProvider = (params: DocumentSymbolParams): DocumentSymbol[] => {
8+
const documentSymbols: DocumentSymbol[] = []
9+
const { textDocument } = params
10+
const buffer = workspace.getBufferByUri(textDocument.uri)
11+
const document = documents.get(textDocument.uri)
12+
if (!buffer || !document) {
13+
return documentSymbols
14+
}
15+
const globalFunctions = buffer.getGlobalFunctions()
16+
const scriptFunctions = buffer.getScriptFunctions()
17+
const globalVariables = buffer.getGlobalIdentifiers()
18+
const localVariables = buffer.getLocalIdentifiers()
19+
const functions = Object.values(globalFunctions).concat(Object.values(scriptFunctions)).reduce((pre, cur) => {
20+
return pre.concat(cur)
21+
}, [])
22+
let variables = Object.values(globalVariables).concat(Object.values(localVariables)).reduce((pre, cur) => {
23+
return pre.concat(cur)
24+
}, [])
25+
const sortFunctions: IFunction[] = []
26+
functions.forEach(func => {
27+
if (sortFunctions.length === 0) {
28+
return sortFunctions.push(func)
29+
}
30+
let i = 0;
31+
for (const len = sortFunctions.length; i < len; i += 1) {
32+
const sf = sortFunctions[i]
33+
if (func.range.endLine < sf.range.endLine) {
34+
sortFunctions.splice(i, 0, func)
35+
break
36+
}
37+
}
38+
if (i === sortFunctions.length) {
39+
sortFunctions.push(func)
40+
}
41+
})
42+
return sortFunctions
43+
.map(func => {
44+
const vimRange = func.range
45+
const line = document.getText(Range.create(
46+
Position.create(vimRange.endLine - 1, 0),
47+
Position.create(vimRange.endLine, 0)
48+
))
49+
const range = Range.create(
50+
Position.create(vimRange.startLine - 1, vimRange.startCol - 1),
51+
Position.create(vimRange.endLine - 1, vimRange.endCol - 1 + line.slice(vimRange.endCol - 1).split(' ')[0].length)
52+
)
53+
const ds: DocumentSymbol = {
54+
name: func.name,
55+
kind: SymbolKind.Function,
56+
range,
57+
selectionRange: range,
58+
children: []
59+
}
60+
variables = variables.filter(v => {
61+
if (v.startLine >= vimRange.startLine && v.startLine <= vimRange.endLine) {
62+
const vRange = Range.create(
63+
Position.create(v.startLine - 1, v.startCol - 1),
64+
Position.create(v.startLine, v.startCol - 1 + v.name.length)
65+
)
66+
ds.children.push({
67+
name: v.name,
68+
kind: SymbolKind.Variable,
69+
range: vRange,
70+
selectionRange: vRange
71+
})
72+
return false
73+
}
74+
return true
75+
})
76+
return ds
77+
})
78+
.reduce((res, cur) => {
79+
if (res.length === 0) {
80+
res.push(cur)
81+
} else {
82+
res = res.filter(item => {
83+
if (item.range.start.line >= cur.range.start.line && item.range.end.line <= cur.range.end.line) {
84+
cur.children.push(item)
85+
return false
86+
}
87+
return true
88+
})
89+
res.push(cur)
90+
}
91+
return res
92+
}, [] as DocumentSymbol[])
93+
.concat(
94+
variables.map(v => {
95+
const vRange = Range.create(
96+
Position.create(v.startLine - 1, v.startCol - 1),
97+
Position.create(v.startLine, v.startCol - 1 + v.name.length)
98+
)
99+
return {
100+
name: v.name,
101+
kind: SymbolKind.Variable,
102+
range: vRange,
103+
selectionRange: vRange
104+
}
105+
})
106+
)
107+
}

src/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { connection } from "./server/connection";
1818
import { documents } from "./server/documents";
1919
import { next, unsubscribe } from "./server/parser";
2020
import {selectionRangeProvider} from "./handles/selectionRange";
21+
import {documentSymbolProvider} from "./handles/documentSymbol";
2122

2223
// lsp initialize
2324
connection.onInitialize((param: InitializeParams) => {
@@ -76,6 +77,7 @@ connection.onInitialize((param: InitializeParams) => {
7677
documentHighlightProvider: true,
7778
foldingRangeProvider: true,
7879
selectionRangeProvider: true,
80+
documentSymbolProvider: true,
7981
hoverProvider: true,
8082
completionProvider: {
8183
triggerCharacters: [".", ":", "#", "[", "&", "$", "<", '"', "'"],
@@ -134,7 +136,10 @@ connection.onDocumentHighlight(documentHighlightProvider);
134136
connection.onFoldingRanges(foldingRangeProvider);
135137

136138
// select range
137-
connection.onSelectionRanges(selectionRangeProvider)
139+
connection.onSelectionRanges(selectionRangeProvider);
140+
141+
// document symbols
142+
connection.onDocumentSymbol(documentSymbolProvider);
138143

139144
// lsp start
140145
connection.listen();

0 commit comments

Comments
 (0)