1
1
-- ----------------------------------------------------------------------------
2
2
-- Language Server Protocol --
3
3
-- --
4
- -- Copyright (C) 2023, AdaCore --
4
+ -- Copyright (C) 2023-2025 , AdaCore --
5
5
-- --
6
6
-- This is free software; you can redistribute it and/or modify it under --
7
7
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -178,22 +178,55 @@ package body LSP.Text_Documents is
178
178
Old_First_Line : Natural;
179
179
New_First_Line : Natural;
180
180
181
- Old_Lines, New_Lines : VSS.String_Vectors.Virtual_String_Vector;
181
+ type Virtual_String_Array is
182
+ array (Positive range <>) of VSS.Strings.Virtual_String;
183
+
184
+ type Virtual_String_Array_Access is access all Virtual_String_Array;
185
+
186
+ procedure Free is
187
+ new Ada.Unchecked_Deallocation
188
+ (Virtual_String_Array, Virtual_String_Array_Access);
189
+
190
+ Old_Lines, New_Lines : Virtual_String_Array_Access;
182
191
Old_Length, New_Length : Natural;
183
192
184
193
begin
185
- Old_Lines :=
186
- Self.Text.Split_Lines
187
- (Terminators => LSP_New_Line_Function_Set,
188
- Keep_Terminator => True);
189
- New_Lines :=
190
- New_Text.Split_Lines
191
- (Terminators => LSP_New_Line_Function_Set,
192
- Keep_Terminator => True);
194
+ -- Populate arrays of old and new content.
195
+ --
196
+ -- As of 20250720, `Virtual_String_Vector`.`Element` takes a lot of time
197
+ -- to construct object to return and to finalize object after check of
198
+ -- lines equality. Standard `Ada.Containers.Vectors.Element` works a bit
199
+ -- faster, however, use of arrays speed up execution many times.
200
+
201
+ declare
202
+ Aux_Old_Lines : VSS.String_Vectors.Virtual_String_Vector;
203
+ Aux_New_Lines : VSS.String_Vectors.Virtual_String_Vector;
204
+
205
+ begin
206
+ Aux_Old_Lines :=
207
+ Self.Text.Split_Lines
208
+ (Terminators => LSP_New_Line_Function_Set,
209
+ Keep_Terminator => True);
210
+ Old_Lines := new Virtual_String_Array (1 .. Aux_Old_Lines.Length);
211
+
212
+ for J in Old_Lines'Range loop
213
+ Old_Lines (J) := Aux_Old_Lines (J);
214
+ end loop ;
215
+
216
+ Aux_New_Lines :=
217
+ New_Text.Split_Lines
218
+ (Terminators => LSP_New_Line_Function_Set,
219
+ Keep_Terminator => True);
220
+ New_Lines := new Virtual_String_Array (1 .. Aux_New_Lines.Length);
221
+
222
+ for J in New_Lines'Range loop
223
+ New_Lines (J) := Aux_New_Lines (J);
224
+ end loop ;
225
+ end ;
193
226
194
227
if Old_Span = Empty_Range then
195
228
Old_First_Line := 1 ;
196
- Old_Length := Old_Lines. Length;
229
+ Old_Length := Old_Lines' Length;
197
230
198
231
else
199
232
Old_First_Line := Natural (Old_Span.start.line + 1 );
@@ -203,7 +236,7 @@ package body LSP.Text_Documents is
203
236
204
237
if New_Span = Empty_Range then
205
238
New_First_Line := 1 ;
206
- New_Length := New_Lines. Length;
239
+ New_Length := New_Lines' Length;
207
240
else
208
241
New_First_Line := Natural (New_Span.start.line + 1 );
209
242
New_Length :=
@@ -336,8 +369,8 @@ package body LSP.Text_Documents is
336
369
then
337
370
-- both has lines
338
371
339
- if New_Lines.Element (New_First_Line + New_Index - 1 ) =
340
- Old_Lines.Element (Old_First_Line + Old_Index - 1 )
372
+ if New_Lines (New_First_Line + New_Index - 1 ) =
373
+ Old_Lines (Old_First_Line + Old_Index - 1 )
341
374
then
342
375
-- lines are equal, add Text_Edit after current line
343
376
-- if any is already prepared
@@ -348,7 +381,7 @@ package body LSP.Text_Documents is
348
381
-- the beginning of the next line
349
382
Prepare
350
383
(Old_Natural,
351
- New_Lines.Element (New_First_Line + New_Index - 1 ));
384
+ New_Lines (New_First_Line + New_Index - 1 ));
352
385
end if ;
353
386
354
387
-- move lines cursor backward
@@ -376,7 +409,7 @@ package body LSP.Text_Documents is
376
409
-- additional line not present in the old document
377
410
Prepare
378
411
(Old_Natural,
379
- New_Lines.Element (New_First_Line + New_Index - 1 ));
412
+ New_Lines (New_First_Line + New_Index - 1 ));
380
413
381
414
New_Index := New_Index - 1 ;
382
415
end if ;
@@ -396,7 +429,7 @@ package body LSP.Text_Documents is
396
429
397
430
Prepare
398
431
(Old_Natural,
399
- New_Lines.Element (New_First_Line + New_Index - 1 ));
432
+ New_Lines (New_First_Line + New_Index - 1 ));
400
433
401
434
New_Index := New_Index - 1 ;
402
435
end loop ;
@@ -416,7 +449,7 @@ package body LSP.Text_Documents is
416
449
declare
417
450
Element : LSP.Structures.TextEdit := Edit.Last_Element;
418
451
Last_Line : constant VSS.Strings.Virtual_String :=
419
- Old_Lines (Old_Lines.Length );
452
+ Old_Lines (Old_Lines'Last );
420
453
Iterator :
421
454
constant VSS.Strings.Character_Iterators.Character_Iterator :=
422
455
Last_Line.At_Last_Character;
@@ -425,15 +458,21 @@ package body LSP.Text_Documents is
425
458
-- Replace the wrong location by the end of the buffer
426
459
427
460
Element.a_range.an_end :=
428
- (line => Old_Lines. Length - 1 ,
461
+ (line => Old_Lines' Length - 1 ,
429
462
character => Natural (Iterator.Last_UTF16_Offset) + 1 );
430
463
Edit.Replace_Element (Edit.Last, Element);
431
464
end ;
432
465
end if ;
433
466
467
+ Free (Old_Lines);
468
+ Free (New_Lines);
469
+
434
470
exception
435
471
when others =>
436
472
Free (LCS);
473
+ Free (Old_Lines);
474
+ Free (New_Lines);
475
+
437
476
raise ;
438
477
end ;
439
478
end Diff ;
0 commit comments