Skip to content

Commit 5d43968

Browse files
V901-009: Revamp storage of param/designators
Previously, we were using: Unnamed_Params => Natural (Number of unnamed params at the start) Designators => Vector of Ada_Node with No_Ada_Node in the end for parameters not yet named We were lacking information related to unnamed parameters. Now: Use a vector of either Ada_Node for designators and End_Sloc for unnamed params.
1 parent 89c59e3 commit 5d43968

6 files changed

+264
-229
lines changed

source/ada/lsp-ada_completions-generic_assoc.adb

Lines changed: 130 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
with GNATCOLL.Utils;
1919
with GNATCOLL.Traces;
20+
with Laltools.Common;
2021
with Libadalang.Doc_Utils;
2122
with LSP.Ada_Documents;
2223
with LSP.Common;
@@ -29,14 +30,19 @@ with VSS.Unicode;
2930
package body LSP.Ada_Completions.Generic_Assoc is
3031

3132
Me_Debug : constant GNATCOLL.Traces.Trace_Handle :=
32-
GNATCOLL.Traces.Create ("LSP.GENERIC_ASSOC.DEBUG", GNATCOLL.Traces.On);
33+
GNATCOLL.Traces.Create ("LSP.GENERIC_ASSOC.DEBUG", GNATCOLL.Traces.Off);
3334

3435
function Match_Designators
35-
(Child : Laltools.Common.Node_Vectors.Vector;
36-
Parent : Laltools.Common.Node_Vectors.Vector)
37-
return Boolean;
36+
(Children : LSP.Ada_Completions.Generic_Assoc_Utils.Param_Vectors.Vector;
37+
Parent : Laltools.Common.Node_Vectors.Vector)
38+
return Boolean;
3839
-- Return True if all the designators of Child are also in Parent
3940

41+
function In_Parameters
42+
(Node : Libadalang.Analysis.Ada_Node;
43+
Params : LSP.Ada_Completions.Generic_Assoc_Utils.Param_Vectors.Vector)
44+
return Boolean;
45+
4046
function In_Parent
4147
(Desg : Libadalang.Analysis.Ada_Node;
4248
Parent : Laltools.Common.Node_Vectors.Vector) return Boolean;
@@ -55,8 +61,8 @@ package body LSP.Ada_Completions.Generic_Assoc is
5561
(Elem_Node : Libadalang.Analysis.Ada_Node'Class;
5662
Cursor : Langkit_Support.Slocs.Source_Location;
5763
Prefixed : Boolean;
58-
Unnamed_Params : LSP.Types.LSP_Number;
59-
Designators : Laltools.Common.Node_Vectors.Vector;
64+
Parameters :
65+
LSP.Ada_Completions.Generic_Assoc_Utils.Param_Vectors.Vector;
6066
Cursor_Position : out LSP.Types.LSP_Number;
6167
Current_Designator : out Libadalang.Analysis.Ada_Node);
6268

@@ -71,13 +77,14 @@ package body LSP.Ada_Completions.Generic_Assoc is
7177
-----------------------
7278

7379
function Match_Designators
74-
(Child : Laltools.Common.Node_Vectors.Vector;
75-
Parent : Laltools.Common.Node_Vectors.Vector)
76-
return Boolean is
80+
(Children : LSP.Ada_Completions.Generic_Assoc_Utils.Param_Vectors.Vector;
81+
Parent : Laltools.Common.Node_Vectors.Vector)
82+
return Boolean is
7783
begin
78-
for C of Child loop
79-
if not C.Is_Null
80-
and then not In_Parent (C, Parent)
84+
for C of Children loop
85+
if C.Is_Named
86+
and then not C.Node.Is_Null
87+
and then not In_Parent (C.Node, Parent)
8188
then
8289
return False;
8390
end if;
@@ -86,6 +93,26 @@ package body LSP.Ada_Completions.Generic_Assoc is
8693
return True;
8794
end Match_Designators;
8895

96+
-------------------
97+
-- In_Parameters --
98+
-------------------
99+
100+
function In_Parameters
101+
(Node : Libadalang.Analysis.Ada_Node;
102+
Params : LSP.Ada_Completions.Generic_Assoc_Utils.Param_Vectors.Vector)
103+
return Boolean
104+
is
105+
Node_Text : constant Langkit_Support.Text.Text_Type := Node.Text;
106+
begin
107+
for P of Params loop
108+
if P.Is_Named and then P.Node.Text = Node_Text then
109+
return True;
110+
end if;
111+
end loop;
112+
113+
return False;
114+
end In_Parameters;
115+
89116
---------------
90117
-- In_Parent --
91118
---------------
@@ -130,12 +157,16 @@ package body LSP.Ada_Completions.Generic_Assoc is
130157
Whitespace_Prefix : VSS.Strings.Virtual_String;
131158
-- Empty if we already have a whitespace before a ","
132159

133-
Designators : Laltools.Common.Node_Vectors.Vector;
134-
-- Current list of designators
160+
Parameters :
161+
LSP.Ada_Completions.Generic_Assoc_Utils.Param_Vectors.Vector;
162+
-- Current list of parameters
135163

136-
Unnamed_Params : Natural;
164+
Unnamed_Params : Natural := 0;
137165
-- The number of parameters without designators already present
138166

167+
Using_Name : Boolean := False;
168+
-- Are we already using name notation
169+
139170
Prefix : VSS.Strings.Virtual_String;
140171
-- The whole string before the snippet (including whitespaces)
141172

@@ -145,7 +176,11 @@ package body LSP.Ada_Completions.Generic_Assoc is
145176
Prefix_Span : LSP.Messages.Span;
146177
-- The span covering Prefix.
147178

148-
Dummy : Boolean;
179+
Prefixed : Boolean;
180+
181+
function Has_Designator (Unnamed_Params : out Natural) return Boolean;
182+
-- Return True if we have at least one named designator
183+
-- Also compute the number of unnamed parameters.
149184

150185
procedure Generate_Snippets
151186
(Spec_Designators : Laltools.Common.Node_Vectors.Vector;
@@ -155,6 +190,28 @@ package body LSP.Ada_Completions.Generic_Assoc is
155190
Snippet_Prefix : VSS.Strings.Virtual_String;
156191
Completion_Prefix : VSS.Strings.Virtual_String);
157192

193+
--------------------
194+
-- Has_Designator --
195+
--------------------
196+
197+
function Has_Designator (Unnamed_Params : out Natural) return Boolean
198+
is
199+
use type Langkit_Support.Slocs.Source_Location;
200+
begin
201+
Unnamed_Params := 0;
202+
203+
for Param of Parameters loop
204+
if Param.Is_Named then
205+
return True;
206+
elsif Langkit_Support.Slocs.Start_Sloc (Param.Loc) < Sloc then
207+
-- Prevent adding fake node because of LAL recovery
208+
Unnamed_Params := Unnamed_Params + 1;
209+
end if;
210+
end loop;
211+
212+
return False;
213+
end Has_Designator;
214+
158215
-----------------------
159216
-- Generate_Snippets --
160217
-----------------------
@@ -171,19 +228,19 @@ package body LSP.Ada_Completions.Generic_Assoc is
171228
Snippet_Index : Integer :=
172229
Integer (Spec_Designators.Length);
173230
Use_Named_Notation : constant Boolean :=
174-
(not Designators.Is_Empty)
231+
Using_Name
175232
or else (Limit > 0
176233
and then (Snippet_Index = 1
177234
or else Snippet_Index >= Limit));
178235

179236
Nb_Params : Natural := Unnamed_Params;
180-
-- We already have Skip params
237+
-- We already have some unnamed params and we can be prefixed by one
181238

182239
Total_Params : constant Natural :=
183240
Natural (Spec_Designators.Length);
184241
-- The maximum number of params
185242
begin
186-
if Match_Designators (Designators, Spec_Designators) then
243+
if Match_Designators (Parameters, Spec_Designators) then
187244

188245
for Desg of reverse Spec_Designators loop
189246
declare
@@ -199,7 +256,7 @@ package body LSP.Ada_Completions.Generic_Assoc is
199256
Doc : VSS.Strings.Virtual_String;
200257
begin
201258
-- Check if Desg is already present
202-
if not In_Parent (Desg, Designators) then
259+
if not In_Parameters (Desg, Parameters) then
203260
-- Add snippet for Desg if it matches the
204261
-- current prefix
205262
if Token_Kind in Ada_Par_Open | Ada_Comma
@@ -355,8 +412,8 @@ package body LSP.Ada_Completions.Generic_Assoc is
355412
Prefix := Self.Document.Get_Text_At
356413
(Prefix_Span.first, Prefix_Span.last);
357414

358-
Designators :=
359-
Get_Designators (Elem_Node, Sloc, Dummy, Unnamed_Params);
415+
Parameters := Get_Parameters (Elem_Node, Prefixed);
416+
Using_Name := Has_Designator (Unnamed_Params);
360417

361418
if Token_Kind = Ada_Whitespace then
362419
Token_Kind := Kind (Data (Previous (Token, Exclude_Trivia => True)));
@@ -376,7 +433,7 @@ package body LSP.Ada_Completions.Generic_Assoc is
376433
loop
377434
-- Too many params to match Spec
378435
if Natural (Spec.Param_Vector.Length)
379-
> Natural (Designators.Length) + Unnamed_Params
436+
> Natural (Parameters.Length)
380437
then
381438
Generate_Snippets
382439
(Spec_Designators => Spec.Param_Vector,
@@ -407,12 +464,10 @@ package body LSP.Ada_Completions.Generic_Assoc is
407464

408465
Elem_Node : constant Element := Search_Element (Node);
409466

410-
Designators : Laltools.Common.Node_Vectors.Vector;
467+
Parameters :
468+
LSP.Ada_Completions.Generic_Assoc_Utils.Param_Vectors.Vector;
411469
-- Current list of designators
412470

413-
Unnamed_Params : Natural;
414-
-- The number of parameters without designators already present
415-
416471
Prefixed : Boolean;
417472
-- Are we prefixed by a parameter? (for example: dot call)
418473

@@ -521,30 +576,26 @@ package body LSP.Ada_Completions.Generic_Assoc is
521576

522577
Res.signatures.Clear;
523578
Res.activeParameter := (Is_Set => True, Value => 0);
524-
Designators :=
525-
Get_Designators (Elem_Node, Cursor, Prefixed, Unnamed_Params);
579+
Parameters := Get_Parameters (Elem_Node, Prefixed);
526580

527581
Find_Cursor_Position
528582
(Elem_Node => To_Node (Elem_Node),
529583
Cursor => Cursor,
530584
Prefixed => Prefixed,
531-
Unnamed_Params => LSP.Types.LSP_Number (Unnamed_Params),
532-
Designators => Designators,
585+
Parameters => Parameters,
533586
Cursor_Position => Cursor_Position,
534587
Current_Designator => Current_Designator);
535588

536589
if Me_Debug.Active then
537590
GNATCOLL.Traces.Trace
538591
(Me_Debug, "Cursor: " & Cursor'Image);
539592
GNATCOLL.Traces.Trace
540-
(Me_Debug, "Unnamed Parameter:" & Unnamed_Params'Image);
541-
GNATCOLL.Traces.Trace
542-
(Me_Debug, "Designators:" & Designators.Length'Image);
543-
for Desg of Designators loop
544-
if Desg.Is_Null then
545-
GNATCOLL.Traces.Trace (Me_Debug, "Not yet named");
593+
(Me_Debug, "Designators:" & Parameters.Length'Image);
594+
for Param of Parameters loop
595+
if not Param.Is_Named then
596+
GNATCOLL.Traces.Trace (Me_Debug, "No name: " & Param.Loc'Image);
546597
else
547-
GNATCOLL.Traces.Trace (Me_Debug, Desg.Parent.Image);
598+
GNATCOLL.Traces.Trace (Me_Debug, Param.Node.Parent.Image);
548599
end if;
549600
end loop;
550601
end if;
@@ -561,14 +612,14 @@ package body LSP.Ada_Completions.Generic_Assoc is
561612
loop
562613
if
563614
-- Enough params in Spec
564-
Natural (Designators.Length) + Unnamed_Params
615+
Natural (Parameters.Length)
565616
<= Natural (Spec.Param_Vector.Length)
566617
-- Cursor can't point to Length (Spec), it starts at 0
567618
and then Cursor_Position /= -1
568619
and then Cursor_Position <
569620
LSP.Types.LSP_Number (Spec.Param_Vector.Length)
570621
-- The designators matched
571-
and then Match_Designators (Designators, Spec.Param_Vector)
622+
and then Match_Designators (Parameters, Spec.Param_Vector)
572623
then
573624
if Signature_Added and then Lazy then
574625
-- One signature is enough in this case, they are just
@@ -691,11 +742,12 @@ package body LSP.Ada_Completions.Generic_Assoc is
691742
(Elem_Node : Libadalang.Analysis.Ada_Node'Class;
692743
Cursor : Langkit_Support.Slocs.Source_Location;
693744
Prefixed : Boolean;
694-
Unnamed_Params : LSP.Types.LSP_Number;
695-
Designators : Laltools.Common.Node_Vectors.Vector;
745+
Parameters :
746+
LSP.Ada_Completions.Generic_Assoc_Utils.Param_Vectors.Vector;
696747
Cursor_Position : out LSP.Types.LSP_Number;
697748
Current_Designator : out Libadalang.Analysis.Ada_Node)
698749
is
750+
use Langkit_Support.Slocs;
699751
use type LSP.Types.LSP_Number;
700752

701753
Is_New_Param : Boolean := False;
@@ -714,7 +766,6 @@ package body LSP.Ada_Completions.Generic_Assoc is
714766
function Cursor_On_Last_Par return Boolean is
715767
Open_Cpt : Natural := 0;
716768
Close_Cpt : Natural := 0;
717-
use type Langkit_Support.Slocs.Source_Location;
718769
begin
719770
for C of Elem_Node.Text loop
720771
-- Count the open/closing parentheses
@@ -743,9 +794,7 @@ package body LSP.Ada_Completions.Generic_Assoc is
743794
--------------------
744795

745796
function Cursor_In_Node
746-
(N : Libadalang.Analysis.Ada_Node'Class) return Boolean
747-
is
748-
use Langkit_Support.Slocs;
797+
(N : Libadalang.Analysis.Ada_Node'Class) return Boolean is
749798
begin
750799
case Libadalang.Analysis.Compare (N, Cursor) is
751800
when Inside =>
@@ -773,38 +822,46 @@ package body LSP.Ada_Completions.Generic_Assoc is
773822
return;
774823
end if;
775824

776-
Cursor_Position := Unnamed_Params;
825+
Cursor_Position := 0;
777826

778-
if not Designators.Is_Empty then
779-
if Designators.Last_Element.Is_Null then
780-
Cursor_Position :=
781-
Cursor_Position + LSP.Types.LSP_Number (Designators.Length);
782-
else
783-
for D of Designators loop
784-
declare
785-
P : Libadalang.Analysis.Ada_Node := D.Parent;
786-
begin
787-
if P.Kind in Libadalang.Common.Ada_Alternatives_List_Range
788-
then
789-
-- Special case for aggregate:
790-
-- Aggr_Assoc : X => Y
791-
-- AlternativesList : X
792-
-- Identifier : X
793-
P := P.Parent;
794-
end if;
827+
for Param of Parameters loop
828+
if Param.Is_Named then
829+
declare
830+
Parent : Libadalang.Analysis.Ada_Node := Param.Node.Parent;
831+
begin
832+
if Parent.Kind in Libadalang.Common.Ada_Alternatives_List_Range
833+
then
834+
-- Special case for aggregate:
835+
-- Aggr_Assoc : X => Y
836+
-- AlternativesList : X
837+
-- Identifier : X
838+
Parent := Parent.Parent;
839+
end if;
795840

796-
if Cursor_In_Node (P) then
797-
Current_Designator := D;
798-
exit;
799-
else
800-
Cursor_Position := Cursor_Position + 1;
801-
end if;
802-
end;
803-
end loop;
841+
if Cursor_In_Node (Parent) then
842+
Current_Designator := Param.Node;
843+
exit;
844+
end if;
845+
end;
846+
else
847+
if Compare (Param.Loc, Cursor) = Inside then
848+
-- The cursor is inside an unnamed param
849+
Current_Designator := Libadalang.Analysis.No_Ada_Node;
850+
exit;
851+
end if;
804852
end if;
853+
854+
Cursor_Position := Cursor_Position + 1;
855+
end loop;
856+
857+
-- New param is only considered if we are using all the previous params
858+
if LSP.Types.LSP_Number (Parameters.Length) = Cursor_Position
859+
and then Is_New_Param
860+
then
861+
Cursor_Position := Cursor_Position + 1;
805862
end if;
806863

807-
-- The current position is ~(Unamed_Param + Designators.Length - 1)
864+
-- Cursor_Positon starts at 0
808865
if Cursor_Position > 0 then
809866
Cursor_Position := Cursor_Position - 1;
810867
end if;
@@ -813,9 +870,6 @@ package body LSP.Ada_Completions.Generic_Assoc is
813870
Cursor_Position := Cursor_Position + 1;
814871
end if;
815872

816-
if Is_New_Param then
817-
Cursor_Position := Cursor_Position + 1;
818-
end if;
819873
end Find_Cursor_Position;
820874

821875
------------------------------

0 commit comments

Comments
 (0)