Skip to content

Commit 17570ff

Browse files
Merge branch 'topic/#1467' into 'master'
Add fallback mechanism for 'als-other-file' command See merge request eng/ide/ada_language_server!1738
2 parents 1b2924a + 7be9733 commit 17570ff

File tree

10 files changed

+228
-50
lines changed

10 files changed

+228
-50
lines changed

source/ada/lsp-ada_contexts.adb

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -909,8 +909,26 @@ package body LSP.Ada_Contexts is
909909
Attribute : GPR2.Q_Attribute_Id;
910910
Index : String := "";
911911
Default : String := "";
912-
Use_Extended : Boolean := False) return String
913-
is
912+
Use_Extended : Boolean := False) return String is
913+
begin
914+
return Project_Attribute_Value
915+
(View => Self.Tree.Root_Project,
916+
Attribute => Attribute,
917+
Index => Index,
918+
Default => Default,
919+
Use_Extended => Use_Extended);
920+
end Project_Attribute_Value;
921+
922+
-----------------------------
923+
-- Project_Attribute_Value --
924+
-----------------------------
925+
926+
function Project_Attribute_Value
927+
(View : GPR2.Project.View.Object;
928+
Attribute : GPR2.Q_Attribute_Id;
929+
Index : String := "";
930+
Default : String := "";
931+
Use_Extended : Boolean := False) return String is
914932
Attribute_Index : constant GPR2.Project.Attribute_Index.Object :=
915933
(if Index = ""
916934
then GPR2.Project.Attribute_Index.Undefined
@@ -919,19 +937,19 @@ package body LSP.Ada_Contexts is
919937
Attribute_Value : GPR2.Project.Attribute.Object;
920938

921939
begin
922-
if Self.Tree.Root_Project.Check_Attribute
940+
if View.Check_Attribute
923941
(Name => Attribute,
924942
Index => Attribute_Index,
925943
Result => Attribute_Value)
926944
then
927945
return Attribute_Value.Value.Text;
928-
elsif Use_Extended and then Self.Tree.Root_Project.Is_Extending then
929-
-- Look at Extended project list as attribute not found in
930-
-- Root_Project and Use_Extended requested.
946+
elsif Use_Extended and then View.Is_Extending then
947+
-- Look at Extended project list as attribute not found in
948+
-- Root_Project and Use_Extended requested.
931949

932950
declare
933951
Extended_Root : GPR2.Project.View.Object :=
934-
Self.Tree.Root_Project.Extended_Root;
952+
View.Extended_Root;
935953
begin
936954
while Extended_Root.Is_Defined loop
937955
if Extended_Root.Check_Attribute

source/ada/lsp-ada_contexts.ads

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,15 @@ package LSP.Ada_Contexts is
285285
-- itself, then the attribute is looked up in the project extended by
286286
-- Project (if any).
287287

288+
function Project_Attribute_Value
289+
(View : GPR2.Project.View.Object;
290+
Attribute : GPR2.Q_Attribute_Id;
291+
Index : String := "";
292+
Default : String := "";
293+
Use_Extended : Boolean := False) return String;
294+
-- Same as above, but computing the value from the given view instead
295+
-- of the context's root project.
296+
288297
private
289298

290299
type Context (Tracer : not null LSP.Tracers.Tracer_Access) is tagged limited

source/ada/lsp-ada_handlers-other_file_commands.adb

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
-- of the license. --
1616
------------------------------------------------------------------------------
1717

18+
with GNATCOLL.Utils;
1819
with GPR2; use GPR2;
1920
with GPR2.Build.Source;
2021
with GPR2.Build.Unit_Info;
@@ -190,15 +191,54 @@ package body LSP.Ada_Handlers.Other_File_Commands is
190191
Unit : constant GPR2.Build.Compilation_Unit.Object := Unit_For_File;
191192
Other_File : Virtual_File;
192193
begin
194+
Success := True;
195+
196+
-- The unit is defined for the loaded project: fallback to a simple
197+
-- heuristic which tries to deduce the other file from the queried
198+
-- file, switching the specification/implementation extensions at
199+
-- the end of the filename.
200+
-- If the computed other file's URI does not exist, the client will
201+
-- simply not open it, which is ok.
202+
193203
if not Unit.Is_Defined then
194-
Success := False;
195-
Error_Msg :=
196-
VSS.Strings.Conversions.To_Virtual_String
197-
("Could not find other file for '"
198-
& File.Display_Base_Name
199-
& "': this file is not visible from the current project.");
200-
201-
return No_File;
204+
declare
205+
Impl_Suffix_Attr_Id : constant GPR2.Q_Optional_Attribute_Id :=
206+
((Pack => GPR2."+" ("Naming"),
207+
Attr => GPR2."+" ("Implementation_Suffix")));
208+
Spec_Suffix_Attr_Id : constant GPR2.Q_Optional_Attribute_Id :=
209+
((Pack => GPR2."+" ("Naming"),
210+
Attr => GPR2."+" ("Specification_Suffix")));
211+
Spec_Ext : constant String :=
212+
LSP.Ada_Contexts.Project_Attribute_Value
213+
(View => Handler.Project_Tree.Root_Project,
214+
Attribute => Spec_Suffix_Attr_Id,
215+
Index => "ada",
216+
Default => ".ads",
217+
Use_Extended => True);
218+
Impl_Ext : constant String :=
219+
LSP.Ada_Contexts.Project_Attribute_Value
220+
(View => Handler.Project_Tree.Root_Project,
221+
Attribute => Impl_Suffix_Attr_Id,
222+
Index => "ada",
223+
Default => ".adb",
224+
Use_Extended => True);
225+
begin
226+
if GNATCOLL.Utils.Ends_With
227+
(File.Display_Full_Name, Impl_Ext)
228+
then
229+
return GNATCOLL.VFS.Create
230+
(Full_Filename => +GNATCOLL.Utils.Replace
231+
(S => File.Display_Full_Name,
232+
Pattern => Impl_Ext,
233+
Replacement => Spec_Ext));
234+
else
235+
return GNATCOLL.VFS.Create
236+
(Full_Filename => +GNATCOLL.Utils.Replace
237+
(S => File.Display_Full_Name,
238+
Pattern => Spec_Ext,
239+
Replacement => Impl_Ext));
240+
end if;
241+
end;
202242
else
203243
Other_File := Other_File_From_Unit (Unit => Unit);
204244

@@ -209,8 +249,6 @@ package body LSP.Ada_Handlers.Other_File_Commands is
209249
("Could not find other file for '"
210250
& File.Display_Base_Name
211251
& "': the unit has no other part.");
212-
else
213-
Success := True;
214252
end if;
215253

216254
return Other_File;
@@ -219,13 +257,15 @@ package body LSP.Ada_Handlers.Other_File_Commands is
219257

220258
Success : Boolean;
221259
Error_Msg : VSS.Strings.Virtual_String;
222-
Other_File : constant Virtual_File := Get_Other_File (Success, Error_Msg);
260+
Other_File : constant Virtual_File :=
261+
Get_Other_File (Success, Error_Msg);
223262
begin
224263
if not Success then
225264
Error :=
226265
(Is_Set => True,
227266
Value =>
228-
(code => LSP.Enumerations.InternalError, message => Error_Msg));
267+
(code => LSP.Enumerations.InternalError,
268+
message => Error_Msg));
229269
return;
230270
end if;
231271

testsuite/ada_lsp/commands.other_file.error_messages/not_a_source.ads

Lines changed: 0 additions & 3 deletions
This file was deleted.

testsuite/ada_lsp/commands.other_file.error_messages/test.json

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -92,33 +92,6 @@
9292
]
9393
}
9494
},
95-
{
96-
"send": {
97-
"request": {
98-
"jsonrpc": "2.0",
99-
"id": "sw3",
100-
"method": "workspace/executeCommand",
101-
"params": {
102-
"command": "als-other-file",
103-
"arguments": [
104-
{
105-
"uri": "$URI{no_a_source.adb}"
106-
}
107-
]
108-
}
109-
},
110-
"wait": [
111-
{
112-
"error": {
113-
"code": -32603,
114-
"message": "Could not find other file for 'no_a_source.adb': this file is not visible from the current project."
115-
},
116-
"id": "sw3",
117-
"jsonrpc": "2.0"
118-
}
119-
]
120-
}
121-
},
12295
{
12396
"send": {
12497
"request": {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
project Default is
2+
for Source_Dirs use ("src");
3+
4+
package Naming is
5+
for Specification_Suffix ("ada") use ".ada_spec";
6+
end Naming;
7+
8+
end Default;

testsuite/ada_lsp/commands.other_file.error_messages/not_a_source.adb renamed to testsuite/ada_lsp/commands.other_file.not_from_project/not_a_source.adb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
package body Not_A_Source is
2-
procedure Do_Something is null;
2+
3+
procedure Do_Nothing is null;
4+
35
end Not_A_Source;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
procedure Main is
2+
begin
3+
null;
4+
end Main;
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
[
2+
{
3+
"comment": [
4+
"This test checks that 'als-other-file' is able to compute the other file",
5+
"of Ada files that do not belong to the project, using its fallback mechanism"
6+
]
7+
},
8+
{
9+
"start": {
10+
"cmd": ["${ALS}"]
11+
}
12+
},
13+
{
14+
"send": {
15+
"request": {
16+
"jsonrpc": "2.0",
17+
"id": 0,
18+
"method": "initialize",
19+
"params": {
20+
"processId": 1,
21+
"rootUri": "$URI{.}",
22+
"capabilities": {}
23+
}
24+
},
25+
"wait": [
26+
{
27+
"id": 0,
28+
"result": {
29+
"capabilities": {
30+
"textDocumentSync": 2,
31+
"executeCommandProvider": {
32+
"commands": ["<HAS>", "als-other-file"]
33+
}
34+
}
35+
}
36+
}
37+
]
38+
}
39+
},
40+
{
41+
"send": {
42+
"request": {
43+
"jsonrpc": "2.0",
44+
"method": "initialized",
45+
"params": {}
46+
},
47+
"wait": []
48+
}
49+
},
50+
{
51+
"send": {
52+
"request": {
53+
"jsonrpc": "2.0",
54+
"method": "workspace/didChangeConfiguration",
55+
"params": {
56+
"settings": {
57+
"ada": {
58+
"projectFile": "default.gpr",
59+
"scenarioVariables": {},
60+
"enableDiagnostics": false,
61+
"defaultCharset": "UTF-8"
62+
}
63+
}
64+
}
65+
},
66+
"wait": [
67+
{
68+
"jsonrpc": "2.0",
69+
"id": 1,
70+
"method": "window/workDoneProgress/create",
71+
"params": {
72+
"token": "<ANY>"
73+
}
74+
}
75+
]
76+
}
77+
},
78+
{
79+
"send": {
80+
"request": {
81+
"jsonrpc": "2.0",
82+
"method": "textDocument/didOpen",
83+
"params": {
84+
"textDocument": {
85+
"uri": "$URI{not_a_source.ada_spec}",
86+
"languageId": "ada",
87+
"version": 1,
88+
"text": "package Not_A_Source is\n procedure Do_Nothing;\nend Not_A_Source;\n"
89+
}
90+
}
91+
},
92+
"wait": []
93+
}
94+
},
95+
{
96+
"send": {
97+
"request": {
98+
"jsonrpc": "2.0",
99+
"id": 2,
100+
"method": "workspace/executeCommand",
101+
"params": {
102+
"command": "als-other-file",
103+
"arguments": [
104+
{
105+
"uri": "$URI{not_a_source.adb}"
106+
}
107+
]
108+
}
109+
},
110+
"wait": [
111+
{
112+
"method": "window/showDocument",
113+
"params": {
114+
"uri": "$URI{not_a_source.ada_spec}",
115+
"takeFocus": true
116+
}
117+
}
118+
]
119+
}
120+
},
121+
{
122+
"stop": {
123+
"exit_code": 0
124+
}
125+
}
126+
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
title: 'commands.other_file.not_from_project'

0 commit comments

Comments
 (0)