1
1
import type { CodeMapping , VirtualCode } from "@volar/language-core" ;
2
- import type { Language } from "tree-sitter" ;
2
+ import type { Language , Tree } from "tree-sitter" ;
3
3
import type ts from "typescript" ;
4
+ import type { Position } from "vscode-languageserver-textdocument" ;
4
5
import Parser from "tree-sitter" ;
5
6
import _Rust from "tree-sitter-rust" ;
7
+ import { TextDocument } from "vscode-languageserver-textdocument" ;
6
8
import { generateRoot } from "./codegen" ;
7
9
import { resolveCodes } from "./utils/resolveCodes" ;
8
10
9
- // eslint-disable-next-line ts/no-require-imports
10
- const Rust : Language = typeof _Rust === "string" ? require ( _Rust ) : _Rust ;
11
-
12
11
let parser : Parser | undefined ;
12
+ function getRustParser ( ) {
13
+ if ( ! parser ) {
14
+ // eslint-disable-next-line ts/no-require-imports
15
+ const Rust : Language = typeof _Rust === "string" ? require ( _Rust ) : _Rust ;
16
+ parser = new Parser ( ) ;
17
+ parser . setLanguage ( Rust ) ;
18
+ }
19
+ return parser ;
20
+ }
13
21
14
22
export class JsrsVirtualCode implements VirtualCode {
15
23
id = "root" ;
16
24
languageId = "jsrs" ;
17
- embeddedCodes : VirtualCode [ ] = [ ] ;
25
+ embeddedCodes ! : VirtualCode [ ] ;
26
+ snapshot : ts . IScriptSnapshot ;
18
27
mappings : CodeMapping [ ] ;
19
- tree : Parser . Tree ;
28
+ tree : Tree ;
29
+ document : TextDocument ;
20
30
21
- constructor ( public snapshot : ts . IScriptSnapshot ) {
31
+ constructor ( snapshot : ts . IScriptSnapshot ) {
32
+ this . snapshot = snapshot ;
22
33
this . mappings = [
23
34
{
24
35
sourceOffsets : [ 0 ] ,
@@ -35,14 +46,44 @@ export class JsrsVirtualCode implements VirtualCode {
35
46
} ,
36
47
] ;
37
48
38
- parser ??= new Parser ( ) ;
39
- parser . setLanguage ( Rust ) ;
40
-
41
49
const content = snapshot . getText ( 0 , snapshot . getLength ( ) ) ;
42
- this . tree = parser . parse ( content ) ;
50
+ this . tree = getRustParser ( ) . parse ( content ) ;
51
+ this . document = TextDocument . create ( "file://temp.jsrs" , "jsrs" , 0 , content ) ;
52
+ this . updateEmbeddedCodes ( ) ;
53
+ }
54
+
55
+ update ( newSnapshot : ts . IScriptSnapshot ) {
56
+ const newContent = newSnapshot . getText ( 0 , newSnapshot . getLength ( ) ) ;
57
+ const changeRange = newSnapshot . getChangeRange ( this . snapshot ) ;
58
+ this . snapshot = newSnapshot ;
59
+ if ( changeRange ) {
60
+ const newDocument = TextDocument . create ( "file://temp.jsrs" , "jsrs" , 0 , newContent ) ;
61
+ this . tree . edit ( {
62
+ startIndex : changeRange . span . start ,
63
+ oldEndIndex : changeRange . span . start + changeRange . span . length ,
64
+ newEndIndex : changeRange . span . start + changeRange . newLength ,
65
+ startPosition : positionToPoint ( this . document . positionAt ( changeRange . span . start ) ) ,
66
+ oldEndPosition : positionToPoint ( this . document . positionAt ( changeRange . span . start + changeRange . span . length ) ) ,
67
+ newEndPosition : positionToPoint ( newDocument . positionAt ( changeRange . span . start + changeRange . newLength ) ) ,
68
+ } ) ;
69
+ this . tree = getRustParser ( ) . parse ( newContent , this . tree ) ;
70
+ this . document = newDocument ;
71
+ }
72
+ else {
73
+ // Cannot be incrementally updated, just recreate the tree
74
+ this . tree = getRustParser ( ) . parse ( newContent ) ;
75
+ this . document = TextDocument . create ( "file://temp.jsrs" , "jsrs" , 0 , newContent ) ;
76
+ }
77
+ this . updateEmbeddedCodes ( ) ;
78
+ }
43
79
80
+ updateEmbeddedCodes ( ) {
44
81
this . embeddedCodes = [
45
82
resolveCodes ( "jsrs" , "typescript" , generateRoot ( this . tree . rootNode ) ) ,
46
83
] ;
47
84
}
48
85
}
86
+
87
+ function positionToPoint ( position : Position ) {
88
+ return { row : position . line , column : position . character } ;
89
+ }
0 commit comments