1717
1818with GNATCOLL.Utils ;
1919with GNATCOLL.Traces ;
20+ with Laltools.Common ;
2021with Libadalang.Doc_Utils ;
2122with LSP.Ada_Documents ;
2223with LSP.Common ;
@@ -29,14 +30,19 @@ with VSS.Unicode;
2930package 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