-
Notifications
You must be signed in to change notification settings - Fork 263
Expand file tree
/
Copy pathsymbolHoverTargetsExtension.ts
More file actions
83 lines (77 loc) · 2.33 KB
/
symbolHoverTargetsExtension.ts
File metadata and controls
83 lines (77 loc) · 2.33 KB
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
import { StateField, Range } from "@codemirror/state";
import { Decoration, DecorationSet, EditorView } from "@codemirror/view";
import { ensureSyntaxTree } from "@codemirror/language";
import { measureSync } from "@/lib/utils";
export const SYMBOL_HOVER_TARGET_DATA_ATTRIBUTE = "data-symbol-hover-target";
const decoration = Decoration.mark({
class: "cm-underline-hover",
attributes: { [SYMBOL_HOVER_TARGET_DATA_ATTRIBUTE]: "true" }
});
const NODE_TYPES = [
// Typescript + Python
"VariableName",
"VariableDefinition",
"TypeDefinition",
"TypeName",
"PropertyName",
"PropertyDefinition",
"JSXIdentifier",
"Identifier",
// C#
"VarName",
"TypeIdentifier",
"PropertyName",
"MethodName",
"Ident",
"ParamName",
"AttrsNamedArg",
// C/C++
"Identifier",
"NamespaceIdentifier",
"FieldIdentifier",
// Objective-C
"variableName",
"variableName.definition",
// Java
"Definition",
// Rust
"BoundIdentifier",
// Go
"DefName",
"FieldName",
// PHP
"ClassMemberName",
"Name",
// Tcl
"ProcName",
"ProcInvocation",
"PackageName",
"Variable"
]
export const symbolHoverTargetsExtension = StateField.define<DecorationSet>({
create(state) {
// @note: we need to use `ensureSyntaxTree` here (as opposed to `syntaxTree`)
// because we want to parse the entire document, not just the text visible in
// the current viewport.
const { data: tree } = measureSync(() => ensureSyntaxTree(state, state.doc.length, Infinity), "ensureSyntaxTree");
const decorations: Range<Decoration>[] = [];
// @note: useful for debugging
// const getTextAt = (from: number, to: number) => {
// const doc = state.doc;
// return doc.sliceString(from, to);
// }
tree?.iterate({
enter: (node) => {
// console.log(node.type.name, getTextAt(node.from, node.to));
if (NODE_TYPES.includes(node.type.name) && node.from < node.to) {
decorations.push(decoration.range(node.from, node.to));
}
},
});
return Decoration.set(decorations);
},
update(deco, tr) {
return deco.map(tr.changes);
},
provide: field => EditorView.decorations.from(field),
});