Skip to content

Commit 2fc9fa8

Browse files
U622-021: Compute some completion items properties lazily
Use the newly added completionItem/resolve request to compute the 'documentation' and 'detail' fieds of completion items lazily when the client supports it (i.e: when a given item gets selected in the completion window). This makes the ALS way faster to return completion items for packages that contain a huge number of declarations (e.g: Libadalang.Common). VS Code already supports this lazy computation method but not other clients.
1 parent 41f417a commit 2fc9fa8

File tree

116 files changed

+445
-138
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+445
-138
lines changed

scripts/generate.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@
257257
'CodeAction_Response'),
258258
('textDocument/completion', 'Completion', 'TextDocumentPositionParams',
259259
'Completion_Response'),
260+
('completionItem/resolve', 'CompletionItemResolve', 'CompletionItem',
261+
'CompletionItemResolve_Response'),
260262
('textDocument/definition', 'Definition', 'DefinitionParams',
261263
'Location_Link_Response'),
262264
('textDocument/declaration', 'Declaration', 'DeclarationParams',

source/ada/lsp-ada_completions.adb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ package body LSP.Ada_Completions is
4343
(Context : LSP.Ada_Contexts.Context;
4444
Names : Completion_Maps.Map;
4545
Named_Notation_Threshold : Natural;
46+
Compute_Doc_And_Details : Boolean;
4647
Result : in out LSP.Messages.CompletionItem_Vector)
4748
is
4849
function Hash (Value : VSS.Strings.Virtual_String)
@@ -91,6 +92,7 @@ package body LSP.Ada_Completions is
9192
BD => Name.P_Basic_Decl,
9293
Label => Label,
9394
Use_Snippets => Info.Use_Snippets,
95+
Compute_Doc_And_Details => Compute_Doc_And_Details,
9496
Named_Notation_Threshold => Named_Notation_Threshold,
9597
Is_Dot_Call => Info.Is_Dot_Call,
9698
Is_Visible => Info.Is_Visible,

source/ada/lsp-ada_completions.ads

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,15 @@ package LSP.Ada_Completions is
8888
(Context : LSP.Ada_Contexts.Context;
8989
Names : Completion_Maps.Map;
9090
Named_Notation_Threshold : Natural;
91+
Compute_Doc_And_Details : Boolean;
9192
Result : in out LSP.Messages.CompletionItem_Vector);
93+
-- Convert all the completion Names into LSP completion items' results.
94+
-- Named_Notation_Threshold defines the number of parameters/components at
95+
-- which point named notation is used for subprogram/aggregate completion
96+
-- snippets.
97+
-- If Compute_Doc_And_Details is True, the 'detail' and 'documentation'
98+
-- fields for all the resulting completion items will be computed
99+
-- immediately, which might take time.
92100

93101
generic
94102
with function Has_Been_Canceled return Boolean;

source/ada/lsp-ada_documents.adb

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ with Langkit_Support.Symbols;
3030
with Langkit_Support.Text;
3131
with Libadalang.Analysis; use Libadalang.Analysis;
3232
with Libadalang.Sources;
33-
with Libadalang.Doc_Utils;
3433
with Libadalang.Iterators;
3534

3635
with VSS.String_Vectors;
@@ -1764,6 +1763,7 @@ package body LSP.Ada_Documents is
17641763
BD : Libadalang.Analysis.Basic_Decl;
17651764
Label : VSS.Strings.Virtual_String;
17661765
Use_Snippets : Boolean;
1766+
Compute_Doc_And_Details : Boolean;
17671767
Named_Notation_Threshold : Natural;
17681768
Is_Dot_Call : Boolean;
17691769
Is_Visible : Boolean;
@@ -1776,8 +1776,6 @@ package body LSP.Ada_Documents is
17761776

17771777
Item : CompletionItem;
17781778
Subp_Spec_Node : Base_Subp_Spec;
1779-
Doc_Text : VSS.Strings.Virtual_String;
1780-
Loc_Text : VSS.Strings.Virtual_String;
17811779
Min_Width : constant Natural := Completions_Count'Img'Length - 1;
17821780

17831781
function Get_Sort_text (Base_Label : LSP_String) return LSP_String;
@@ -1815,9 +1813,6 @@ package body LSP.Ada_Documents is
18151813
Item.label := Label;
18161814
Item.kind := (True, To_Completion_Kind
18171815
(LSP.Lal_Utils.Get_Decl_Kind (BD)));
1818-
Item.detail := (True,
1819-
LSP.Types.To_LSP_String
1820-
(LSP.Lal_Utils.Compute_Completion_Detail (BD)));
18211816

18221817
declare
18231818
Base_Label : constant LSP_String := LSP.Types.To_LSP_String
@@ -1836,41 +1831,39 @@ package body LSP.Ada_Documents is
18361831
end if;
18371832
end;
18381833

1839-
-- Property_Errors can occur when calling
1840-
-- Get_Documentation on unsupported docstrings, so
1841-
-- add an exception handler to catch them and recover.
1842-
1843-
begin
1844-
Doc_Text :=
1845-
VSS.Strings.To_Virtual_String
1846-
(Libadalang.Doc_Utils.Get_Documentation
1847-
(BD).Doc.To_String);
1848-
1849-
-- Append the declaration's location.
1850-
-- In addition, append the project's name if we are dealing with an
1851-
-- aggregate project.
1852-
1853-
Loc_Text.Append (LSP.Lal_Utils.Node_Location_Image (BD));
1854-
1855-
if not Doc_Text.Is_Empty then
1856-
Loc_Text.Append
1857-
(VSS.Strings.To_Virtual_String
1858-
((1 .. 2 => Ada.Characters.Wide_Wide_Latin_1.LF)));
1859-
1860-
Loc_Text.Append (Doc_Text);
1861-
end if;
1862-
1863-
Item.documentation :=
1864-
(Is_Set => True,
1865-
Value => String_Or_MarkupContent'
1866-
(Is_String => True,
1867-
String => Loc_Text));
1868-
1869-
exception
1870-
when E : Libadalang.Common.Property_Error =>
1871-
LSP.Common.Log (Context.Trace, E);
1872-
Item.documentation := (others => <>);
1873-
end;
1834+
-- Compute the 'documentation' and 'detail' fields immediately if
1835+
-- requested (i.e: when the client does not support lazy computation
1836+
-- for these fields).
1837+
if Compute_Doc_And_Details then
1838+
Item.detail :=
1839+
(True,
1840+
LSP.Types.To_LSP_String
1841+
(LSP.Lal_Utils.Compute_Completion_Detail (BD)));
1842+
1843+
-- Property_Errors can occur when calling
1844+
-- Get_Documentation on unsupported docstrings, so
1845+
-- add an exception handler to catch them and recover.
1846+
begin
1847+
Item.documentation :=
1848+
(Is_Set => True,
1849+
Value => String_Or_MarkupContent'
1850+
(Is_String => True,
1851+
String => LSP.Lal_Utils.Compute_Completion_Doc (BD)));
1852+
1853+
exception
1854+
when E : Libadalang.Common.Property_Error =>
1855+
LSP.Common.Log (Context.Trace, E);
1856+
Item.documentation := (others => <>);
1857+
end;
1858+
else
1859+
-- Set node's location to the 'data' field of the completion item, so
1860+
-- that we can retrieve it in the completionItem/resolve handler.
1861+
Item.data :=
1862+
(True,
1863+
(uri => File_To_URI (BD.Unit.Get_Filename),
1864+
span => LSP.Lal_Utils.To_Span (BD.Sloc_Range),
1865+
others => <>));
1866+
end if;
18741867

18751868
-- Return immediately if we should not use snippets (e.g: completion for
18761869
-- invisible symbols).

source/ada/lsp-ada_documents.ads

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ package LSP.Ada_Documents is
235235
BD : Libadalang.Analysis.Basic_Decl;
236236
Label : VSS.Strings.Virtual_String;
237237
Use_Snippets : Boolean;
238+
Compute_Doc_And_Details : Boolean;
238239
Named_Notation_Threshold : Natural;
239240
Is_Dot_Call : Boolean;
240241
Is_Visible : Boolean;

source/ada/lsp-ada_handlers.adb

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ with GNAT.Strings;
2828
with GNATCOLL.JSON;
2929
with GNATCOLL.Utils; use GNATCOLL.Utils;
3030

31-
with VSS.String_Vectors;
3231
with VSS.Strings;
3332
with VSS.Strings.Conversions;
3433
with VSS.Unicode;
@@ -706,7 +705,7 @@ package body LSP.Ada_Handlers is
706705
workDoneProgress => LSP.Types.None));
707706
Response.result.capabilities.completionProvider :=
708707
(True,
709-
(resolveProvider => LSP.Types.False,
708+
(resolveProvider => LSP.Types.True,
710709
triggerCharacters => (True, Empty_Vector & (+".") & (+"(")),
711710
allCommitCharacters => (Is_Set => False),
712711
workDoneProgress => LSP.Types.None));
@@ -776,6 +775,15 @@ package body LSP.Ada_Handlers is
776775
Self.Completion_Snippets_Enabled := True;
777776
end if;
778777

778+
if Value.capabilities.textDocument.completion.completionItem.Is_Set
779+
and then Value.capabilities.textDocument.completion.
780+
completionItem.Value.resolveSupport.Is_Set
781+
then
782+
Self.Completion_Resolve_Properties :=
783+
Value.capabilities.textDocument.completion.
784+
completionItem.Value.resolveSupport.Value.properties;
785+
end if;
786+
779787
if Value.capabilities.workspace.didChangeWatchedFiles
780788
.dynamicRegistration = True
781789
then
@@ -3875,8 +3883,23 @@ package body LSP.Ada_Handlers is
38753883

38763884
Response : LSP.Messages.Server_Responses.Completion_Response
38773885
(Is_Error => False);
3886+
Compute_Doc_And_Details : Boolean := True;
3887+
38783888
begin
38793889

3890+
-- If lazy computation for the 'detail' and 'documentation' fields is
3891+
-- supported by the client, set the Compute_Doc_And_Details flag to
3892+
-- False.
3893+
3894+
if Self.Completion_Resolve_Properties.Contains
3895+
(VSS.Strings.Conversions.To_Virtual_String ("detail"))
3896+
and then
3897+
Self.Completion_Resolve_Properties.Contains
3898+
(VSS.Strings.Conversions.To_Virtual_String ("documentation"))
3899+
then
3900+
Compute_Doc_And_Details := False;
3901+
end if;
3902+
38803903
Document.Get_Completions_At
38813904
(Context => Context.all,
38823905
Providers => Providers,
@@ -3888,13 +3911,75 @@ package body LSP.Ada_Handlers is
38883911
(Context => Context.all,
38893912
Names => Names,
38903913
Named_Notation_Threshold => Self.Named_Notation_Threshold,
3914+
Compute_Doc_And_Details => Compute_Doc_And_Details,
38913915
Result => Response.result.items);
38923916

38933917
Response.result.isIncomplete := Names.Length >= Limit;
38943918

38953919
return Response;
38963920
end On_Completion_Request;
38973921

3922+
--------------------------------------
3923+
-- On_CompletionItemResolve_Request --
3924+
--------------------------------------
3925+
3926+
overriding function On_CompletionItemResolve_Request
3927+
(Self : access Message_Handler;
3928+
Request : LSP.Messages.Server_Requests.CompletionItemResolve_Request)
3929+
return LSP.Messages.Server_Responses.CompletionItemResolve_Response
3930+
is
3931+
Item : LSP.Messages.CompletionItem :=
3932+
Request.params;
3933+
Response : LSP.Messages.Server_Responses.CompletionItemResolve_Response
3934+
(Is_Error => False);
3935+
C : constant Context_Access :=
3936+
Self.Contexts.Get_Best_Context (Item.data.Value.uri);
3937+
Node : Libadalang.Analysis.Ada_Node := Get_Node_At
3938+
(Self => C.all,
3939+
Document => null,
3940+
Position => LSP.Messages.TextDocumentPositionParams'
3941+
(textDocument => (uri => Item.data.Value.uri),
3942+
position => Item.data.Value.span.first));
3943+
begin
3944+
-- Retrieve the Basic_Decl from the completion item's SLOC
3945+
while not Node.Is_Null
3946+
and then Node.Kind not in Libadalang.Common.Ada_Basic_Decl
3947+
loop
3948+
Node := Node.Parent;
3949+
end loop;
3950+
3951+
-- Compute the completion item's details
3952+
if not Node.Is_Null then
3953+
declare
3954+
BD : constant Libadalang.Analysis.Basic_Decl :=
3955+
Node.As_Basic_Decl;
3956+
begin
3957+
Item.detail :=
3958+
(True,
3959+
To_LSP_String (Compute_Completion_Detail (BD)));
3960+
3961+
-- Property_Errors can occur when calling
3962+
-- Get_Documentation on unsupported docstrings, so
3963+
-- add an exception handler to catch them and recover.
3964+
3965+
Item.documentation :=
3966+
(Is_Set => True,
3967+
Value => LSP.Messages.String_Or_MarkupContent'
3968+
(Is_String => True,
3969+
String => LSP.Lal_Utils.Compute_Completion_Doc (BD)));
3970+
3971+
exception
3972+
when E : Libadalang.Common.Property_Error =>
3973+
LSP.Common.Log (C.Trace, E);
3974+
Item.documentation := (others => <>);
3975+
end;
3976+
3977+
Response.result := Item;
3978+
end if;
3979+
3980+
return Response;
3981+
end On_CompletionItemResolve_Request;
3982+
38983983
---------------------------
38993984
-- On_Formatting_Request --
39003985
---------------------------

source/ada/lsp-ada_handlers.ads

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
with Ada.Containers.Hashed_Maps;
2222
with Ada.Containers.Hashed_Sets;
23+
with VSS.String_Vectors;
2324

2425
with GNATCOLL.VFS; use GNATCOLL.VFS;
2526
with GNATCOLL.Projects;
@@ -200,6 +201,11 @@ private
200201
Completion_Snippets_Enabled : Boolean := False;
201202
-- True if the client supports completion snippets
202203

204+
Completion_Resolve_Properties : VSS.String_Vectors.Virtual_String_Vector;
205+
-- The list of CompletionItem properties that can be resolved
206+
-- lazily (i.e: when the item is selected on client-side) via
207+
-- the completionItem/resolve request.
208+
203209
Range_Formatting_Enabled : Boolean := False;
204210
-- True if the handler has registered rangeFormatting provider
205211

@@ -272,6 +278,11 @@ private
272278
Request : LSP.Messages.Server_Requests.Completion_Request)
273279
return LSP.Messages.Server_Responses.Completion_Response;
274280

281+
overriding function On_CompletionItemResolve_Request
282+
(Self : access Message_Handler;
283+
Request : LSP.Messages.Server_Requests.CompletionItemResolve_Request)
284+
return LSP.Messages.Server_Responses.CompletionItemResolve_Response;
285+
275286
overriding function On_Definition_Request
276287
(Self : access Message_Handler;
277288
Request : LSP.Messages.Server_Requests.Definition_Request)

source/ada/lsp-error_decorators.adb

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,27 @@ package body LSP.Error_Decorators is
136136
(Self : access Error_Decorator;
137137
Request : LSP.Messages.Server_Requests.Completion_Request)
138138
return LSP.Messages.Server_Responses.Completion_Response
139-
renames Completion_Request;
139+
renames Completion_Request;
140+
141+
-----------------------------------
142+
-- CompletionItemResolve_Request --
143+
-----------------------------------
144+
145+
function CompletionItemResolve_Request is new Generic_Request
146+
(Request =>
147+
LSP.Messages.Server_Requests.CompletionItemResolve_Request,
148+
Response =>
149+
LSP.Messages.Server_Responses.CompletionItemResolve_Response,
150+
Handler =>
151+
LSP.Server_Request_Handlers.Server_Request_Handler,
152+
On_Request =>
153+
LSP.Server_Request_Handlers.On_CompletionItemResolve_Request);
154+
155+
overriding function On_CompletionItemResolve_Request
156+
(Self : access Error_Decorator;
157+
Request : LSP.Messages.Server_Requests.CompletionItemResolve_Request)
158+
return LSP.Messages.Server_Responses.CompletionItemResolve_Response
159+
renames CompletionItemResolve_Request;
140160

141161
---------------------------
142162
-- On_Declaration_Request --

source/ada/lsp-error_decorators.ads

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ package LSP.Error_Decorators is
5858
Request : LSP.Messages.Server_Requests.Completion_Request)
5959
return LSP.Messages.Server_Responses.Completion_Response;
6060

61+
overriding function On_CompletionItemResolve_Request
62+
(Self : access Error_Decorator;
63+
Request : LSP.Messages.Server_Requests.CompletionItemResolve_Request)
64+
return LSP.Messages.Server_Responses.CompletionItemResolve_Response;
65+
6166
overriding function On_Definition_Request
6267
(Self : access Error_Decorator;
6368
Request : LSP.Messages.Server_Requests.Definition_Request)

0 commit comments

Comments
 (0)