Skip to content

Commit 3fb557d

Browse files
author
Philippe Gil
committed
Display GPR variables/types comment in tooltip
LSP.GPR_Documentation.Get_Tooltip_Text: add variable/types declaration comment on variable references - Add Type_Id to LSP.GPR_Files API - Add Referenced_Type getter. - Let type definition be a type reference. - Add type reference to GPR2.Project.Typ.Object converter - Add type reference tooltip handling - Return structured tooltip declaration/location/documentation Closes eng/ide/ada_language_server#1352
1 parent 6084fa1 commit 3fb557d

16 files changed

+988
-79
lines changed

source/gpr/lsp-gpr_documentation.adb

Lines changed: 179 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
------------------------------------------------------------------------------
22
-- Language Server Protocol --
33
-- --
4-
-- Copyright (C) 2023-2024, AdaCore --
4+
-- Copyright (C) 2023-2024, AdaCore --
55
-- --
66
-- This is free software; you can redistribute it and/or modify it under --
77
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -17,10 +17,15 @@
1717

1818
with Ada.Characters.Conversions;
1919
with Ada.Characters.Latin_1;
20+
with Ada.Characters.Wide_Wide_Latin_1;
21+
2022
with GPR2.Project.Attribute;
23+
with GPR2.Project.Typ;
2124
with GPR2.Project.Variable;
25+
with GPR2.Source_Reference;
2226

2327
with Gpr_Parser.Common;
28+
with Gpr_Parser_Support.Slocs;
2429

2530
with GPR2.Project.Registry.Attribute.Description;
2631
with GPR2.Project.Registry.Pack.Description;
@@ -32,12 +37,119 @@ with VSS.Strings.Conversions;
3237

3338
package body LSP.GPR_Documentation is
3439

40+
function Get_Documentation
41+
(Ref : Gpr_Parser.Common.Token_Reference;
42+
Style : GNATdoc.Comments.Options.Documentation_Style)
43+
return VSS.Strings.Virtual_String;
44+
-- Get variable/type declaration comment.
45+
46+
-----------------------
47+
-- Get_Documentation --
48+
-----------------------
49+
50+
function Get_Documentation
51+
(Ref : Gpr_Parser.Common.Token_Reference;
52+
Style : GNATdoc.Comments.Options.Documentation_Style)
53+
return VSS.Strings.Virtual_String
54+
is
55+
Documentation : VSS.Strings.Virtual_String;
56+
Add_LF : Boolean := False;
57+
package Slocs renames Gpr_Parser_Support.Slocs;
58+
use type Slocs.Line_Number;
59+
60+
Line : Slocs.Line_Number := Ref.Data.Sloc_Range.Start_Line;
61+
Token : Gpr_Parser.Common.Token_Reference := Ref;
62+
63+
use type GNATdoc.Comments.Options.Documentation_Style;
64+
65+
function Next return Gpr_Parser.Common.Token_Reference is
66+
(if Style = GNATdoc.Comments.Options.GNAT
67+
then Token.Next
68+
else Token.Previous);
69+
-- Go to next or previous token depending on 'Style' value
70+
71+
function Valid_Comment return Boolean;
72+
-- Return True if comment token is still part of 'Ref' comment.
73+
74+
-------------------
75+
-- Valid_Comment --
76+
-------------------
77+
78+
function Valid_Comment return Boolean is
79+
Current_Line : constant Slocs.Line_Number :=
80+
Token.Data.Sloc_Range.Start_Line;
81+
Valid : Boolean := False;
82+
begin
83+
case Style is
84+
when GNATdoc.Comments.Options.GNAT =>
85+
if Current_Line <= Line + 1 then
86+
Valid := True;
87+
end if;
88+
when GNATdoc.Comments.Options.Leading =>
89+
if Current_Line >= Line - 1 then
90+
Valid := True;
91+
end if;
92+
end case;
93+
if Valid then
94+
-- update Line to allow next/previous comment to still be valid
95+
Line := Current_Line;
96+
end if;
97+
return Valid;
98+
end Valid_Comment;
99+
100+
use type Gpr_Parser.Common.Token_Reference;
101+
use type Gpr_Parser.Common.Token_Kind;
102+
begin
103+
Token := Next;
104+
while Token /= Gpr_Parser.Common.No_Token loop
105+
if Token.Data.Kind = Gpr_Parser.Common.Gpr_Comment
106+
then
107+
if Valid_Comment then
108+
case Style is
109+
when GNATdoc.Comments.Options.GNAT =>
110+
if Add_LF then
111+
Documentation.Append
112+
(VSS.Strings.To_Virtual_String
113+
(Ada.Characters.Wide_Wide_Latin_1.LF & Token.Text));
114+
else
115+
Documentation.Append
116+
(VSS.Strings.To_Virtual_String
117+
(Token.Text));
118+
end if;
119+
when GNATdoc.Comments.Options.Leading =>
120+
if Add_LF then
121+
Documentation.Prepend
122+
(VSS.Strings.To_Virtual_String
123+
(Token.Text & Ada.Characters.Wide_Wide_Latin_1.LF));
124+
else
125+
Documentation.Prepend
126+
(VSS.Strings.To_Virtual_String
127+
(Token.Text));
128+
end if;
129+
end case;
130+
Add_LF := True;
131+
else
132+
exit;
133+
end if;
134+
end if;
135+
Token := Next;
136+
end loop;
137+
return Documentation;
138+
end Get_Documentation;
139+
140+
----------------------
141+
-- Get_Tooltip_Text --
142+
----------------------
143+
35144
procedure Get_Tooltip_Text
36-
(Self : LSP.GPR_Files.File_Access;
37-
URI : LSP.Structures.DocumentUri;
38-
Document_Provider : LSP.GPR_Documents.Document_Provider_Access;
39-
Position : LSP.Structures.Position;
40-
Tooltip_Text : out VSS.Strings.Virtual_String) is
145+
(Self : LSP.GPR_Files.File_Access;
146+
URI : LSP.Structures.DocumentUri;
147+
Document_Provider : LSP.GPR_Documents.Document_Provider_Access;
148+
Position : LSP.Structures.Position;
149+
Style : GNATdoc.Comments.Options.Documentation_Style;
150+
Declaration_Text : out VSS.Strings.Virtual_String;
151+
Documentation_Text : out VSS.Strings.Virtual_String;
152+
Location_Text : out VSS.Strings.Virtual_String) is
41153
use Gpr_Parser.Common;
42154

43155
package LKD renames LSP.Text_Documents.Langkit_Documents;
@@ -69,6 +181,7 @@ package body LSP.GPR_Documentation is
69181
begin
70182
if Reference.Is_Variable_Reference
71183
or else Reference.Is_Attribute_Reference
184+
or else Reference.Is_Type_Reference
72185
then
73186
declare
74187
Document : constant LSP.GPR_Documents.Document_Access :=
@@ -85,9 +198,27 @@ package body LSP.GPR_Documentation is
85198
Reference => Reference);
86199
begin
87200
if Variable.Is_Defined then
88-
Tooltip_Text.Append
201+
Declaration_Text.Append
89202
(VSS.Strings.Conversions.To_Virtual_String
90203
(GPR2.Project.Variable.Image (Variable)));
204+
Location_Text.Append
205+
(VSS.Strings.Conversions.To_Virtual_String
206+
(GPR2.Source_Reference.Format
207+
(GPR2.Source_Reference.Object
208+
(Variable))));
209+
if Variable.Has_Type then
210+
declare
211+
Typ : constant GPR2.Project.Typ.Object :=
212+
Variable.Typ;
213+
begin
214+
if Typ.Is_Defined then
215+
Declaration_Text.Prepend
216+
(VSS.Strings.Conversions.To_Virtual_String
217+
(GPR2.Project.Typ.Image (Typ)
218+
& Ada.Characters.Latin_1.CR));
219+
end if;
220+
end;
221+
end if;
91222
end if;
92223
end;
93224
elsif Reference.Is_Attribute_Reference then
@@ -98,12 +229,39 @@ package body LSP.GPR_Documentation is
98229
Reference => Reference);
99230
begin
100231
if Attribute.Is_Defined then
101-
Tooltip_Text.Append
232+
Declaration_Text.Append
102233
(VSS.Strings.Conversions.To_Virtual_String
103234
(GPR2.Project.Attribute.Image (Attribute)
104235
& Ada.Characters.Latin_1.CR));
236+
Location_Text.Append
237+
(VSS.Strings.Conversions.To_Virtual_String
238+
(GPR2.Source_Reference.Format
239+
(GPR2.Source_Reference.Object
240+
(Attribute))));
241+
end if;
242+
243+
end;
244+
elsif Reference.Is_Type_Reference then
245+
declare
246+
Typ : constant GPR2.Project.Typ.Object :=
247+
Document.Get_Type
248+
249+
(Root_File => Self,
250+
Reference => Reference);
251+
begin
252+
if Typ.Is_Defined then
253+
Declaration_Text.Append
254+
(VSS.Strings.Conversions.To_Virtual_String
255+
(GPR2.Project.Typ.Image (Typ)
256+
& Ada.Characters.Latin_1.CR));
257+
Location_Text.Append
258+
(VSS.Strings.Conversions.To_Virtual_String
259+
(GPR2.Source_Reference.Format
260+
(GPR2.Source_Reference.Object
261+
(Typ))));
105262
end if;
106263
end;
264+
107265
end if;
108266
end if;
109267
end;
@@ -112,8 +270,6 @@ package body LSP.GPR_Documentation is
112270

113271
begin
114272

115-
Tooltip_Text.Clear;
116-
117273
if Token /= No_Token and then Token.Data.Kind = Gpr_Identifier then
118274
declare
119275
Reference : constant FR.Reference :=
@@ -127,14 +283,14 @@ package body LSP.GPR_Documentation is
127283
if Previous /= No_Token then
128284
case Previous.Data.Kind is
129285
when Gpr_Package | Gpr_End =>
130-
Tooltip_Text.Append
286+
Documentation_Text.Append
131287
(VSS.Strings.Conversions.To_Virtual_String
132288
(Get_Package_Description
133289
(Self.Get_Package (Position))));
134290

135291
when Gpr_For =>
136292
Append_Value (Reference);
137-
Tooltip_Text.Append
293+
Documentation_Text.Append
138294
(VSS.Strings.Conversions.To_Virtual_String
139295
(Get_Attribute_Description ((
140296
Self.Get_Package (Position),
@@ -143,24 +299,32 @@ package body LSP.GPR_Documentation is
143299
when others =>
144300
Append_Value (Reference);
145301
if Reference.Is_Package_Reference then
146-
Tooltip_Text.Append
302+
Documentation_Text.Append
147303
(VSS.Strings.Conversions.To_Virtual_String
148304
(Get_Package_Description
149305
(Reference.Referenced_Package)));
150-
else
306+
elsif Reference.Is_Attribute_Reference then
151307
declare
152308
Attribute : constant FR.Attribute_Definition :=
153309
Reference.Referenced_Attribute;
154310

155311
use type FR.Attribute_Definition;
156312
begin
157313
if Attribute /= FR.No_Attribute_Definition then
158-
Tooltip_Text.Append
314+
Documentation_Text.Append
159315
(VSS.Strings.Conversions.To_Virtual_String
160316
(Get_Attribute_Description
161317
(Attribute.Name)));
162318
end if;
163319
end;
320+
elsif Reference.Is_Variable_Reference
321+
or else Reference.Is_Type_Reference
322+
then
323+
Documentation_Text.Append
324+
(Get_Documentation
325+
(LSP.GPR_Files.References.Token_Reference
326+
(Self, Position),
327+
Style));
164328
end if;
165329
end case;
166330
end if;

source/gpr/lsp-gpr_documentation.ads

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
-- Subprogram to obtain documentation for packages & attributes.
1919

20+
with GNATdoc.Comments.Options;
21+
2022
with LSP.GPR_Documents;
2123
with LSP.GPR_Files;
2224
with LSP.Structures;
@@ -26,11 +28,14 @@ with VSS.Strings;
2628
package LSP.GPR_Documentation is
2729

2830
procedure Get_Tooltip_Text
29-
(Self : LSP.GPR_Files.File_Access;
30-
URI : LSP.Structures.DocumentUri;
31-
Document_Provider : LSP.GPR_Documents.Document_Provider_Access;
32-
Position : LSP.Structures.Position;
33-
Tooltip_Text : out VSS.Strings.Virtual_String);
31+
(Self : LSP.GPR_Files.File_Access;
32+
URI : LSP.Structures.DocumentUri;
33+
Document_Provider : LSP.GPR_Documents.Document_Provider_Access;
34+
Position : LSP.Structures.Position;
35+
Style : GNATdoc.Comments.Options.Documentation_Style;
36+
Declaration_Text : out VSS.Strings.Virtual_String;
37+
Documentation_Text : out VSS.Strings.Virtual_String;
38+
Location_Text : out VSS.Strings.Virtual_String);
3439
-- Get all the information needed to produce tooltips (hover and completion
3540
-- requests)
3641

source/gpr/lsp-gpr_documents.adb

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,4 +368,73 @@ package body LSP.GPR_Documents is
368368
return GPR2.Project.Attribute.Undefined;
369369
end Get_Attribute;
370370

371+
--------------
372+
-- Get_Type --
373+
--------------
374+
375+
function Get_Type
376+
(Self : Document'Class;
377+
Root_File : LSP.GPR_Files.File_Access;
378+
Reference : LSP.GPR_Files.References.Reference)
379+
return GPR2.Project.Typ.Object is
380+
381+
function Typ
382+
(View : GPR2.Project.View.Object) return GPR2.Project.Typ.Object;
383+
384+
---------
385+
-- Typ --
386+
---------
387+
388+
function Typ
389+
(View : GPR2.Project.View.Object) return GPR2.Project.Typ.Object
390+
is
391+
Name : constant GPR2.Optional_Name_Type :=
392+
GPR2.Optional_Name_Type
393+
(VSS.Strings.Conversions.To_UTF_8_String
394+
(LSP.GPR_Files.Image (Reference.Referenced_Type)));
395+
396+
begin
397+
if View.Has_Types (Name) then
398+
return View.Typ (Name);
399+
else
400+
return GPR2.Project.Typ.Undefined;
401+
end if;
402+
end Typ;
403+
404+
begin
405+
if LSP.GPR_Files.References.Is_Type_Reference (Reference)
406+
and then not Self.Tree.Log_Messages.Has_Error
407+
then
408+
declare
409+
File : constant LSP.GPR_Files.File_Access :=
410+
LSP.GPR_Files.References.Referenced_File
411+
(File => Root_File,
412+
Reference => Reference);
413+
Path : constant GPR2.Path_Name.Object :=
414+
LSP.GPR_Files.Path (File.all);
415+
Root : constant GPR2.Project.View.Object := Self.Tree.Root_Project;
416+
begin
417+
if Root.Path_Name = Path then
418+
return Typ (Root);
419+
end if;
420+
if Root.Is_Extended then
421+
declare
422+
Extending : constant GPR2.Project.View.Object :=
423+
Root.Extending;
424+
begin
425+
if Extending.Path_Name = Path then
426+
return Typ (Extending);
427+
end if;
428+
end;
429+
end if;
430+
for Import of Root.Imports loop
431+
if Import.Path_Name = Path then
432+
return Typ (Import);
433+
end if;
434+
end loop;
435+
end;
436+
end if;
437+
return GPR2.Project.Typ.Undefined;
438+
end Get_Type;
439+
371440
end LSP.GPR_Documents;

0 commit comments

Comments
 (0)