17
17
18
18
with GNATCOLL.Utils ;
19
19
with GNATCOLL.Traces ;
20
+ with Laltools.Common ;
20
21
with Libadalang.Doc_Utils ;
21
22
with LSP.Ada_Documents ;
22
23
with LSP.Common ;
@@ -29,14 +30,19 @@ with VSS.Unicode;
29
30
package body LSP.Ada_Completions.Generic_Assoc is
30
31
31
32
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 );
33
34
34
35
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;
38
39
-- Return True if all the designators of Child are also in Parent
39
40
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
+
40
46
function In_Parent
41
47
(Desg : Libadalang.Analysis.Ada_Node;
42
48
Parent : Laltools.Common.Node_Vectors.Vector) return Boolean;
@@ -55,8 +61,8 @@ package body LSP.Ada_Completions.Generic_Assoc is
55
61
(Elem_Node : Libadalang.Analysis.Ada_Node'Class;
56
62
Cursor : Langkit_Support.Slocs.Source_Location;
57
63
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;
60
66
Cursor_Position : out LSP.Types.LSP_Number;
61
67
Current_Designator : out Libadalang.Analysis.Ada_Node);
62
68
@@ -71,13 +77,14 @@ package body LSP.Ada_Completions.Generic_Assoc is
71
77
-- ---------------------
72
78
73
79
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
77
83
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)
81
88
then
82
89
return False;
83
90
end if ;
@@ -86,6 +93,26 @@ package body LSP.Ada_Completions.Generic_Assoc is
86
93
return True;
87
94
end Match_Designators ;
88
95
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
+
89
116
-- -------------
90
117
-- In_Parent --
91
118
-- -------------
@@ -130,12 +157,16 @@ package body LSP.Ada_Completions.Generic_Assoc is
130
157
Whitespace_Prefix : VSS.Strings.Virtual_String;
131
158
-- Empty if we already have a whitespace before a ","
132
159
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
135
163
136
- Unnamed_Params : Natural;
164
+ Unnamed_Params : Natural := 0 ;
137
165
-- The number of parameters without designators already present
138
166
167
+ Using_Name : Boolean := False;
168
+ -- Are we already using name notation
169
+
139
170
Prefix : VSS.Strings.Virtual_String;
140
171
-- The whole string before the snippet (including whitespaces)
141
172
@@ -145,7 +176,11 @@ package body LSP.Ada_Completions.Generic_Assoc is
145
176
Prefix_Span : LSP.Messages.Span;
146
177
-- The span covering Prefix.
147
178
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.
149
184
150
185
procedure Generate_Snippets
151
186
(Spec_Designators : Laltools.Common.Node_Vectors.Vector;
@@ -155,6 +190,28 @@ package body LSP.Ada_Completions.Generic_Assoc is
155
190
Snippet_Prefix : VSS.Strings.Virtual_String;
156
191
Completion_Prefix : VSS.Strings.Virtual_String);
157
192
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
+
158
215
-- ---------------------
159
216
-- Generate_Snippets --
160
217
-- ---------------------
@@ -171,19 +228,19 @@ package body LSP.Ada_Completions.Generic_Assoc is
171
228
Snippet_Index : Integer :=
172
229
Integer (Spec_Designators.Length);
173
230
Use_Named_Notation : constant Boolean :=
174
- ( not Designators.Is_Empty)
231
+ Using_Name
175
232
or else (Limit > 0
176
233
and then (Snippet_Index = 1
177
234
or else Snippet_Index >= Limit));
178
235
179
236
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
181
238
182
239
Total_Params : constant Natural :=
183
240
Natural (Spec_Designators.Length);
184
241
-- The maximum number of params
185
242
begin
186
- if Match_Designators (Designators , Spec_Designators) then
243
+ if Match_Designators (Parameters , Spec_Designators) then
187
244
188
245
for Desg of reverse Spec_Designators loop
189
246
declare
@@ -199,7 +256,7 @@ package body LSP.Ada_Completions.Generic_Assoc is
199
256
Doc : VSS.Strings.Virtual_String;
200
257
begin
201
258
-- Check if Desg is already present
202
- if not In_Parent (Desg, Designators ) then
259
+ if not In_Parameters (Desg, Parameters ) then
203
260
-- Add snippet for Desg if it matches the
204
261
-- current prefix
205
262
if Token_Kind in Ada_Par_Open | Ada_Comma
@@ -355,8 +412,8 @@ package body LSP.Ada_Completions.Generic_Assoc is
355
412
Prefix := Self.Document.Get_Text_At
356
413
(Prefix_Span.first, Prefix_Span.last);
357
414
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);
360
417
361
418
if Token_Kind = Ada_Whitespace then
362
419
Token_Kind := Kind (Data (Previous (Token, Exclude_Trivia => True)));
@@ -376,7 +433,7 @@ package body LSP.Ada_Completions.Generic_Assoc is
376
433
loop
377
434
-- Too many params to match Spec
378
435
if Natural (Spec.Param_Vector.Length)
379
- > Natural (Designators .Length) + Unnamed_Params
436
+ > Natural (Parameters .Length)
380
437
then
381
438
Generate_Snippets
382
439
(Spec_Designators => Spec.Param_Vector,
@@ -407,12 +464,10 @@ package body LSP.Ada_Completions.Generic_Assoc is
407
464
408
465
Elem_Node : constant Element := Search_Element (Node);
409
466
410
- Designators : Laltools.Common.Node_Vectors.Vector;
467
+ Parameters :
468
+ LSP.Ada_Completions.Generic_Assoc_Utils.Param_Vectors.Vector;
411
469
-- Current list of designators
412
470
413
- Unnamed_Params : Natural;
414
- -- The number of parameters without designators already present
415
-
416
471
Prefixed : Boolean;
417
472
-- Are we prefixed by a parameter? (for example: dot call)
418
473
@@ -521,30 +576,26 @@ package body LSP.Ada_Completions.Generic_Assoc is
521
576
522
577
Res.signatures.Clear;
523
578
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);
526
580
527
581
Find_Cursor_Position
528
582
(Elem_Node => To_Node (Elem_Node),
529
583
Cursor => Cursor,
530
584
Prefixed => Prefixed,
531
- Unnamed_Params => LSP.Types.LSP_Number (Unnamed_Params),
532
- Designators => Designators,
585
+ Parameters => Parameters,
533
586
Cursor_Position => Cursor_Position,
534
587
Current_Designator => Current_Designator);
535
588
536
589
if Me_Debug.Active then
537
590
GNATCOLL.Traces.Trace
538
591
(Me_Debug, " Cursor: " & Cursor'Image);
539
592
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);
546
597
else
547
- GNATCOLL.Traces.Trace (Me_Debug, Desg .Parent.Image);
598
+ GNATCOLL.Traces.Trace (Me_Debug, Param.Node .Parent.Image);
548
599
end if ;
549
600
end loop ;
550
601
end if ;
@@ -561,14 +612,14 @@ package body LSP.Ada_Completions.Generic_Assoc is
561
612
loop
562
613
if
563
614
-- Enough params in Spec
564
- Natural (Designators .Length) + Unnamed_Params
615
+ Natural (Parameters .Length)
565
616
<= Natural (Spec.Param_Vector.Length)
566
617
-- Cursor can't point to Length (Spec), it starts at 0
567
618
and then Cursor_Position /= -1
568
619
and then Cursor_Position <
569
620
LSP.Types.LSP_Number (Spec.Param_Vector.Length)
570
621
-- The designators matched
571
- and then Match_Designators (Designators , Spec.Param_Vector)
622
+ and then Match_Designators (Parameters , Spec.Param_Vector)
572
623
then
573
624
if Signature_Added and then Lazy then
574
625
-- One signature is enough in this case, they are just
@@ -691,11 +742,12 @@ package body LSP.Ada_Completions.Generic_Assoc is
691
742
(Elem_Node : Libadalang.Analysis.Ada_Node'Class;
692
743
Cursor : Langkit_Support.Slocs.Source_Location;
693
744
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;
696
747
Cursor_Position : out LSP.Types.LSP_Number;
697
748
Current_Designator : out Libadalang.Analysis.Ada_Node)
698
749
is
750
+ use Langkit_Support.Slocs;
699
751
use type LSP.Types.LSP_Number;
700
752
701
753
Is_New_Param : Boolean := False;
@@ -714,7 +766,6 @@ package body LSP.Ada_Completions.Generic_Assoc is
714
766
function Cursor_On_Last_Par return Boolean is
715
767
Open_Cpt : Natural := 0 ;
716
768
Close_Cpt : Natural := 0 ;
717
- use type Langkit_Support.Slocs.Source_Location;
718
769
begin
719
770
for C of Elem_Node.Text loop
720
771
-- Count the open/closing parentheses
@@ -743,9 +794,7 @@ package body LSP.Ada_Completions.Generic_Assoc is
743
794
-- ------------------
744
795
745
796
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
749
798
begin
750
799
case Libadalang.Analysis.Compare (N, Cursor) is
751
800
when Inside =>
@@ -773,38 +822,46 @@ package body LSP.Ada_Completions.Generic_Assoc is
773
822
return ;
774
823
end if ;
775
824
776
- Cursor_Position := Unnamed_Params ;
825
+ Cursor_Position := 0 ;
777
826
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 ;
795
840
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 ;
804
852
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 ;
805
862
end if ;
806
863
807
- -- The current position is ~(Unamed_Param + Designators.Length - 1)
864
+ -- Cursor_Positon starts at 0
808
865
if Cursor_Position > 0 then
809
866
Cursor_Position := Cursor_Position - 1 ;
810
867
end if ;
@@ -813,9 +870,6 @@ package body LSP.Ada_Completions.Generic_Assoc is
813
870
Cursor_Position := Cursor_Position + 1 ;
814
871
end if ;
815
872
816
- if Is_New_Param then
817
- Cursor_Position := Cursor_Position + 1 ;
818
- end if ;
819
873
end Find_Cursor_Position ;
820
874
821
875
-- ----------------------------
0 commit comments