Skip to content

Commit a2e837c

Browse files
committed
Merge branch 'topic/vadim/immutable' into 'master'
Use arrays to speedup execution. See merge request eng/ide/ada_language_server!2057
2 parents 3537409 + 0c775dd commit a2e837c

File tree

1 file changed

+58
-19
lines changed

1 file changed

+58
-19
lines changed

source/server/lsp-text_documents.adb

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
------------------------------------------------------------------------------
22
-- Language Server Protocol --
33
-- --
4-
-- Copyright (C) 2023, AdaCore --
4+
-- Copyright (C) 2023-2025, AdaCore --
55
-- --
66
-- This is free software; you can redistribute it and/or modify it under --
77
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -178,22 +178,55 @@ package body LSP.Text_Documents is
178178
Old_First_Line : Natural;
179179
New_First_Line : Natural;
180180

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;
182191
Old_Length, New_Length : Natural;
183192

184193
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;
193226

194227
if Old_Span = Empty_Range then
195228
Old_First_Line := 1;
196-
Old_Length := Old_Lines.Length;
229+
Old_Length := Old_Lines'Length;
197230

198231
else
199232
Old_First_Line := Natural (Old_Span.start.line + 1);
@@ -203,7 +236,7 @@ package body LSP.Text_Documents is
203236

204237
if New_Span = Empty_Range then
205238
New_First_Line := 1;
206-
New_Length := New_Lines.Length;
239+
New_Length := New_Lines'Length;
207240
else
208241
New_First_Line := Natural (New_Span.start.line + 1);
209242
New_Length :=
@@ -336,8 +369,8 @@ package body LSP.Text_Documents is
336369
then
337370
-- both has lines
338371

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)
341374
then
342375
-- lines are equal, add Text_Edit after current line
343376
-- if any is already prepared
@@ -348,7 +381,7 @@ package body LSP.Text_Documents is
348381
-- the beginning of the next line
349382
Prepare
350383
(Old_Natural,
351-
New_Lines.Element (New_First_Line + New_Index - 1));
384+
New_Lines (New_First_Line + New_Index - 1));
352385
end if;
353386

354387
-- move lines cursor backward
@@ -376,7 +409,7 @@ package body LSP.Text_Documents is
376409
-- additional line not present in the old document
377410
Prepare
378411
(Old_Natural,
379-
New_Lines.Element (New_First_Line + New_Index - 1));
412+
New_Lines (New_First_Line + New_Index - 1));
380413

381414
New_Index := New_Index - 1;
382415
end if;
@@ -396,7 +429,7 @@ package body LSP.Text_Documents is
396429

397430
Prepare
398431
(Old_Natural,
399-
New_Lines.Element (New_First_Line + New_Index - 1));
432+
New_Lines (New_First_Line + New_Index - 1));
400433

401434
New_Index := New_Index - 1;
402435
end loop;
@@ -416,7 +449,7 @@ package body LSP.Text_Documents is
416449
declare
417450
Element : LSP.Structures.TextEdit := Edit.Last_Element;
418451
Last_Line : constant VSS.Strings.Virtual_String :=
419-
Old_Lines (Old_Lines.Length);
452+
Old_Lines (Old_Lines'Last);
420453
Iterator :
421454
constant VSS.Strings.Character_Iterators.Character_Iterator :=
422455
Last_Line.At_Last_Character;
@@ -425,15 +458,21 @@ package body LSP.Text_Documents is
425458
-- Replace the wrong location by the end of the buffer
426459

427460
Element.a_range.an_end :=
428-
(line => Old_Lines.Length - 1,
461+
(line => Old_Lines'Length - 1,
429462
character => Natural (Iterator.Last_UTF16_Offset) + 1);
430463
Edit.Replace_Element (Edit.Last, Element);
431464
end;
432465
end if;
433466

467+
Free (Old_Lines);
468+
Free (New_Lines);
469+
434470
exception
435471
when others =>
436472
Free (LCS);
473+
Free (Old_Lines);
474+
Free (New_Lines);
475+
437476
raise;
438477
end;
439478
end Diff;

0 commit comments

Comments
 (0)