@@ -39,18 +39,24 @@ import Parser from 'web-tree-sitter';
3939import * as fs from 'node:fs/promises' ;
4040import * as TreeSitterUtil from '../util/tree-sitter' ;
4141
42- import { pathToUri , uriToPath } from '../util' ;
4342import { logger } from '../util/logger' ;
4443import { ModelicaLibrary } from './library' ;
4544import { ModelicaProject } from './project' ;
45+ import { positionToPoint } from '../util/tree-sitter' ;
46+ import { pathToUri , uriToPath } from '../util' ;
4647
4748export class ModelicaDocument implements TextDocument {
4849 readonly #project: ModelicaProject ;
4950 readonly #library: ModelicaLibrary | null ;
5051 readonly #document: TextDocument ;
5152 #tree: Parser . Tree ;
5253
53- public constructor ( project : ModelicaProject , library : ModelicaLibrary | null , document : TextDocument , tree : Parser . Tree ) {
54+ public constructor (
55+ project : ModelicaProject ,
56+ library : ModelicaLibrary | null ,
57+ document : TextDocument ,
58+ tree : Parser . Tree ,
59+ ) {
5460 this . #project = project ;
5561 this . #library = library ;
5662 this . #document = document ;
@@ -90,12 +96,54 @@ export class ModelicaDocument implements TextDocument {
9096
9197 /**
9298 * Updates a document.
99+ *
93100 * @param text the modification
101+ * @param range the range to update, or `undefined` to replace the whole file
94102 */
95- public async update ( text : string ) : Promise < void > {
96- TextDocument . update ( this . #document, [ { text } ] , this . version + 1 ) ;
97- this . #tree = this . project . parser . parse ( text ) ;
98- return ;
103+ public async update ( text : string , range ?: LSP . Range ) : Promise < void > {
104+ if ( range === undefined ) {
105+ TextDocument . update ( this . #document, [ { text } ] , this . version + 1 ) ;
106+ this . #tree = this . project . parser . parse ( text ) ;
107+ return ;
108+ }
109+
110+ const startIndex = this . offsetAt ( range . start ) ;
111+ const startPosition = positionToPoint ( range . start ) ;
112+ const oldEndIndex = this . offsetAt ( range . end ) ;
113+ const oldEndPosition = positionToPoint ( range . end ) ;
114+ const newEndIndex = startIndex + text . length ;
115+
116+ TextDocument . update ( this . #document, [ { text, range } ] , this . version + 1 ) ;
117+ const newEndPosition = positionToPoint ( this . positionAt ( newEndIndex ) ) ;
118+
119+ this . #tree. edit ( {
120+ startIndex,
121+ startPosition,
122+ oldEndIndex,
123+ oldEndPosition,
124+ newEndIndex,
125+ newEndPosition,
126+ } ) ;
127+
128+ this . #tree = this . project . parser . parse ( ( index : number , position ?: Parser . Point ) => {
129+ if ( position ) {
130+ return this . getText ( {
131+ start : {
132+ character : position . column ,
133+ line : position . row ,
134+ } ,
135+ end : {
136+ character : position . column + 1 ,
137+ line : position . row ,
138+ } ,
139+ } ) ;
140+ } else {
141+ return this . getText ( {
142+ start : this . positionAt ( index ) ,
143+ end : this . positionAt ( index + 1 ) ,
144+ } ) ;
145+ }
146+ } , this . #tree) ;
99147 }
100148
101149 public getText ( range ?: LSP . Range | undefined ) : string {
@@ -138,19 +186,19 @@ export class ModelicaDocument implements TextDocument {
138186 public get within ( ) : string [ ] {
139187 const withinClause = this . #tree. rootNode . children
140188 . find ( ( node ) => node . type === 'within_clause' )
141- ?. childForFieldName ( " name" ) ;
189+ ?. childForFieldName ( ' name' ) ;
142190 if ( ! withinClause ) {
143191 return [ ] ;
144192 }
145193
146194 // TODO: Use a helper function from TreeSitterUtil
147195 const identifiers : string [ ] = [ ] ;
148196 TreeSitterUtil . forEach ( withinClause , ( node ) => {
149- if ( node . type === " name" ) {
197+ if ( node . type === ' name' ) {
150198 return true ;
151199 }
152200
153- if ( node . type === " IDENT" ) {
201+ if ( node . type === ' IDENT' ) {
154202 identifiers . push ( node . text ) ;
155203 }
156204
0 commit comments