Skip to content

Commit 9d720be

Browse files
U913-028: Completion provider for parameters
For a function call, propose a snippet with all parameters or the parameters individually. The choices are filtered using the previous designators. Add a test.
1 parent 0cde301 commit 9d720be

File tree

10 files changed

+960
-44
lines changed

10 files changed

+960
-44
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
------------------------------------------------------------------------------
2+
-- Language Server Protocol --
3+
-- --
4+
-- Copyright (C) 2021, AdaCore --
5+
-- --
6+
-- This is free software; you can redistribute it and/or modify it under --
7+
-- terms of the GNU General Public License as published by the Free Soft- --
8+
-- ware Foundation; either version 3, or (at your option) any later ver- --
9+
-- sion. This software is distributed in the hope that it will be useful, --
10+
-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
11+
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public --
12+
-- License for more details. You should have received a copy of the GNU --
13+
-- General Public License distributed with this software; see file --
14+
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy --
15+
-- of the license. --
16+
------------------------------------------------------------------------------
17+
18+
with Ada.Strings.UTF_Encoding;
19+
20+
with GNATCOLL.Utils;
21+
22+
with Langkit_Support.Text; use Langkit_Support.Text;
23+
with Laltools.Common;
24+
with Libadalang.Common;
25+
26+
with LSP.Ada_Completions.Filters;
27+
with LSP.Lal_Utils;
28+
with LSP.Types; use LSP.Types;
29+
30+
package body LSP.Ada_Completions.Parameters is
31+
32+
------------------------
33+
-- Propose_Completion --
34+
------------------------
35+
36+
overriding procedure Propose_Completion
37+
(Self : Parameter_Completion_Provider;
38+
Sloc : Langkit_Support.Slocs.Source_Location;
39+
Token : Libadalang.Common.Token_Reference;
40+
Node : Libadalang.Analysis.Ada_Node;
41+
Filter : in out LSP.Ada_Completions.Filters.Filter;
42+
Names : out Ada_Completions.Completion_Maps.Map;
43+
Result : out LSP.Messages.CompletionList)
44+
is
45+
pragma Unreferenced (Filter, Names);
46+
use Libadalang.Analysis;
47+
use Libadalang.Common;
48+
49+
Call_Expr_Node : constant Libadalang.Analysis.Call_Expr :=
50+
LSP.Lal_Utils.Get_Call_Expr (Node);
51+
Token_Kind : Libadalang.Common.Token_Kind :=
52+
Kind (Data (Token));
53+
Designators : Laltools.Common.Node_Vectors.Vector;
54+
55+
function Is_Present (Id_Text : Text_Type) return Boolean;
56+
-- Return True if Id_Name match one of the designators
57+
58+
----------------
59+
-- Is_Present --
60+
----------------
61+
62+
function Is_Present (Id_Text : Text_Type) return Boolean is
63+
begin
64+
for Desig of Designators loop
65+
if Id_Text = Desig.Text then
66+
return True;
67+
end if;
68+
end loop;
69+
return False;
70+
end Is_Present;
71+
72+
begin
73+
if Call_Expr_Node = No_Ada_Node then
74+
return;
75+
end if;
76+
77+
Designators := LSP.Lal_Utils.Get_Call_Designators (Call_Expr_Node);
78+
79+
if Token_Kind = Ada_Whitespace then
80+
Token_Kind := Kind (Data (Previous (Token, Exclude_Trivia => True)));
81+
end if;
82+
83+
declare
84+
Item : LSP.Messages.CompletionItem;
85+
Prefix : constant Ada.Strings.UTF_Encoding.UTF_8_String :=
86+
Langkit_Support.Text.To_UTF8 (Node.Text);
87+
Name_Node : constant Libadalang.Analysis.Name :=
88+
Call_Expr_Node.F_Name;
89+
begin
90+
for N of Self.Context.Find_All_Env_Elements (Name_Node) loop
91+
if N.Kind in Ada_Basic_Subp_Decl then
92+
declare
93+
Params_Snippet : LSP_String := Empty_LSP_String;
94+
Snippet_Name : LSP_String := Empty_LSP_String;
95+
-- $0 is used for the final tab stop
96+
Index : Positive := 1;
97+
Spec : constant Libadalang.Analysis.Base_Subp_Spec
98+
:= N.As_Basic_Decl.P_Subp_Spec_Or_Null;
99+
begin
100+
if Spec /= Libadalang.Analysis.No_Base_Subp_Spec
101+
and then LSP.Lal_Utils.Match_Designators
102+
(Spec.P_Params, Designators)
103+
then
104+
for Param of Spec.P_Params loop
105+
for Id of Param.F_Ids loop
106+
declare
107+
Name_Text : constant Text_Type := Id.Text;
108+
Name : constant LSP_String :=
109+
To_LSP_String (Name_Text);
110+
begin
111+
if not Is_Present (Name_Text) then
112+
if Token_Kind in Ada_Par_Open | Ada_Comma
113+
or else
114+
LSP.Types.Starts_With
115+
(Text => Name,
116+
Prefix => Prefix,
117+
Case_Sensitive => False)
118+
then
119+
Item.label := To_Virtual_String (Name);
120+
Item.insertTextFormat :=
121+
(True, LSP.Messages.PlainText);
122+
Item.insertText := (True, Name & " => ");
123+
Item.kind := (True, LSP.Messages.Text);
124+
Result.items.Append (Item);
125+
end if;
126+
127+
Params_Snippet := Params_Snippet
128+
& Name
129+
& " => "
130+
& "$"
131+
& To_LSP_String
132+
(GNATCOLL.Utils.Image
133+
(Index, Min_Width => 1))
134+
& ", ";
135+
Index := Index + 1;
136+
end if;
137+
end;
138+
end loop;
139+
end loop;
140+
141+
-- If the string is empty => nothing to do
142+
if Params_Snippet /= Empty_LSP_String then
143+
-- Remove the last 2 characters which are ", " and
144+
-- replace it by ")" and the final tab stop
145+
Params_Snippet := Unbounded_Slice
146+
(Params_Snippet,
147+
1,
148+
Length (Params_Snippet) - 2);
149+
Params_Snippet := Params_Snippet & ")$0";
150+
151+
Snippet_Name :=
152+
Snippet_Name
153+
& "Params of "
154+
& To_LSP_String (Name_Node.Text);
155+
Item.label := To_Virtual_String
156+
(Snippet_Name);
157+
Item.insertTextFormat :=
158+
(True, LSP.Messages.Snippet);
159+
Item.insertText := (True, Params_Snippet);
160+
Item.kind := (True, LSP.Messages.Snippet);
161+
Result.items.Append (Item);
162+
end if;
163+
end if;
164+
end;
165+
end if;
166+
end loop;
167+
end;
168+
end Propose_Completion;
169+
170+
end LSP.Ada_Completions.Parameters;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
------------------------------------------------------------------------------
2+
-- Language Server Protocol --
3+
-- --
4+
-- Copyright (C) 2021, AdaCore --
5+
-- --
6+
-- This is free software; you can redistribute it and/or modify it under --
7+
-- terms of the GNU General Public License as published by the Free Soft- --
8+
-- ware Foundation; either version 3, or (at your option) any later ver- --
9+
-- sion. This software is distributed in the hope that it will be useful, --
10+
-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
11+
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public --
12+
-- License for more details. You should have received a copy of the GNU --
13+
-- General Public License distributed with this software; see file --
14+
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy --
15+
-- of the license. --
16+
------------------------------------------------------------------------------
17+
-- A completion provider for parameters inside a call
18+
19+
with LSP.Ada_Handlers;
20+
21+
package LSP.Ada_Completions.Parameters is
22+
23+
type Parameter_Completion_Provider
24+
(Context : not null LSP.Ada_Handlers.Context_Access)
25+
is new Completion_Provider with null record;
26+
27+
overriding procedure Propose_Completion
28+
(Self : Parameter_Completion_Provider;
29+
Sloc : Langkit_Support.Slocs.Source_Location;
30+
Token : Libadalang.Common.Token_Reference;
31+
Node : Libadalang.Analysis.Ada_Node;
32+
Filter : in out LSP.Ada_Completions.Filters.Filter;
33+
Names : out Ada_Completions.Completion_Maps.Map;
34+
Result : out LSP.Messages.CompletionList);
35+
-- Get completion for keywords, filtering them with the prefix.
36+
37+
end LSP.Ada_Completions.Parameters;

source/ada/lsp-ada_handlers.adb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ with LSP.Ada_Completions.Aggregates;
4040
with LSP.Ada_Completions.Aspects;
4141
with LSP.Ada_Completions.Keywords;
4242
with LSP.Ada_Completions.Names;
43+
with LSP.Ada_Completions.Parameters;
4344
with LSP.Ada_Completions.Pragmas;
4445
with LSP.Ada_Handlers.Invisibles;
4546
with LSP.Ada_Handlers.Named_Parameters_Commands;
@@ -4037,17 +4038,19 @@ package body LSP.Ada_Handlers is
40374038
P4 : aliased LSP.Ada_Completions.Keywords.Keyword_Completion_Provider;
40384039
P5 : aliased LSP.Ada_Completions.Names.Name_Completion_Provider
40394040
(Self.Completion_Snippets_Enabled);
4040-
40414041
P6 : aliased LSP.Ada_Handlers.Invisibles.Invisible_Completion_Provider
40424042
(Self, Context);
4043+
P7 : aliased
4044+
LSP.Ada_Completions.Parameters.Parameter_Completion_Provider (Context);
40434045

40444046
Providers : constant LSP.Ada_Completions.Completion_Provider_List :=
40454047
(P1'Unchecked_Access,
40464048
P2'Unchecked_Access,
40474049
P3'Unchecked_Access,
40484050
P4'Unchecked_Access,
40494051
P5'Unchecked_Access,
4050-
P6'Unchecked_Access);
4052+
P6'Unchecked_Access,
4053+
P7'Unchecked_Access);
40514054

40524055
Document : constant LSP.Ada_Documents.Document_Access :=
40534056
Get_Open_Document (Self, Value.textDocument.uri);

0 commit comments

Comments
 (0)