-
Notifications
You must be signed in to change notification settings - Fork 131
/
Copy pathtree-sitter.ts
108 lines (96 loc) · 2.68 KB
/
tree-sitter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { Range } from 'vscode-languageserver/lib/main'
import { Point, SyntaxNode } from 'web-tree-sitter'
export function forEach(node: SyntaxNode, cb: (n: SyntaxNode) => void) {
cb(node)
if (node.children.length) {
node.children.forEach(n => forEach(n, cb))
}
}
export function range(n: SyntaxNode): Range {
return Range.create(
n.startPosition.row,
n.startPosition.column,
n.endPosition.row,
n.endPosition.column,
)
}
export function isDefinition(n: SyntaxNode): boolean {
switch (n.type) {
// For now. Later we'll have a command_declaration take precedence over
// variable_assignment
case 'variable_assignment':
case 'function_definition':
return true
default:
return false
}
}
export function isReference(n: SyntaxNode): boolean {
switch (n.type) {
case 'variable_name':
case 'command_name':
return true
default:
return false
}
}
export function findParent(
start: SyntaxNode,
predicate: (n: SyntaxNode) => boolean,
): SyntaxNode | null {
let node = start.parent
while (node !== null) {
if (predicate(node)) {
return node
}
node = node.parent
}
return null
}
/**
* Given a tree and a point, try to find the named leaf node that the point corresponds to.
* This is a helper for wordAtPoint, useful in cases where the point occurs at the boundary of
* a word so the normal behavior of "namedDescendantForPosition" does not find the desired leaf.
* For example, if you do
* > (new Parser()).setLanguage(bash).parse("echo 42").rootNode.descendantForIndex(4).text
* then you get 'echo 42', not the leaf node for 'echo'.
*
* TODO: the need for this function might reveal a flaw in tree-sitter-bash.
*/
export function namedLeafDescendantForPosition(
point: Point,
rootNode: SyntaxNode,
): SyntaxNode | null {
const node = rootNode.namedDescendantForPosition(point)
if (node.childCount === 0) {
return node
} else {
// The node wasn't a leaf. Try to figure out what word we should use.
const nodeToUse = searchForLeafNode(point, node)
if (nodeToUse) {
return nodeToUse
} else {
return null
}
}
}
function searchForLeafNode(point: Point, parent: SyntaxNode): SyntaxNode | null {
let child = parent.firstNamedChild
while (child) {
if (
pointsEqual(child.startPosition, point) ||
pointsEqual(child.endPosition, point)
) {
if (child.childCount === 0) {
return child
} else {
return searchForLeafNode(point, child)
}
}
child = child.nextNamedSibling
}
return null
}
function pointsEqual(point1: Point, point2: Point) {
return point1.row === point2.row && point1.column === point2.column
}