Skip to content

Commit a1d31c9

Browse files
Display error messages when 'als-other-file' fails
In particular when the queried file does not belong to the loaded project or when it does not have another file (e.g: package with only an .ads file, without any .adb). Add tests for all the error messages. For eng/ide/ada_language_server#1460
1 parent 826f551 commit a1d31c9

File tree

8 files changed

+290
-30
lines changed

8 files changed

+290
-30
lines changed

source/ada/lsp-ada_handlers-other_file_commands.adb

Lines changed: 103 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,19 @@
1515
-- of the license. --
1616
------------------------------------------------------------------------------
1717

18+
with GPR2; use GPR2;
19+
with GPR2.Build.Source;
1820
with GPR2.Build.Unit_Info;
1921
with GPR2.Project.View;
2022
with VSS.JSON.Streams;
2123

22-
with GNATCOLL.VFS; use GNATCOLL.VFS;
24+
with GNATCOLL.VFS; use GNATCOLL.VFS;
2325

2426
with GPR2.Build.Compilation_Unit;
2527
with GPR2.Path_Name;
2628

2729
with LSP.Constants;
30+
with LSP.Enumerations;
2831
with LSP.Servers;
2932

3033
package body LSP.Ada_Handlers.Other_File_Commands is
@@ -85,13 +88,23 @@ package body LSP.Ada_Handlers.Other_File_Commands is
8588
File : constant GNATCOLL.VFS.Virtual_File :=
8689
Handler.To_File (Self.URI);
8790

88-
function Other_File return GNATCOLL.VFS.Virtual_File;
91+
function Get_Other_File
92+
(Success : out Boolean;
93+
Error_Msg : out VSS.Strings.Virtual_String)
94+
return GNATCOLL.VFS.Virtual_File;
95+
-- Return File's other file. If it does not exist,
96+
-- Success is set to False and it will return No_File,
97+
-- with an Error_Msg explaining why the other file could not be found.
8998

90-
----------------
91-
-- Other_File --
92-
----------------
99+
--------------------
100+
-- Get_Other_File --
101+
--------------------
93102

94-
function Other_File return GNATCOLL.VFS.Virtual_File is
103+
function Get_Other_File
104+
(Success : out Boolean;
105+
Error_Msg : out VSS.Strings.Virtual_String)
106+
return GNATCOLL.VFS.Virtual_File
107+
is
95108

96109
F : constant GPR2.Path_Name.Object := GPR2.Path_Name.Create (File);
97110

@@ -100,9 +113,12 @@ package body LSP.Ada_Handlers.Other_File_Commands is
100113
return GNATCOLL.VFS.Virtual_File;
101114
-- Return the other file, knowing that the original file was
102115
-- related to Unit.
116+
-- Return No_File if no other file has been found
117+
-- (e.g: when querying the other file of a package that has only a
118+
-- a specification file).
103119

104120
function Unit_For_File return GPR2.Build.Compilation_Unit.Object;
105-
-- File the Unit object corresponding to File.
121+
-- Return the Unit object corresponding to File
106122

107123
--------------------------
108124
-- Other_File_From_Unit --
@@ -115,8 +131,11 @@ package body LSP.Ada_Handlers.Other_File_Commands is
115131
Spec_File : Virtual_File;
116132
Body_File : Virtual_File;
117133
begin
118-
Spec_File := Unit.Spec.Source.Virtual_File;
119-
Body_File := Unit.Main_Body.Source.Virtual_File;
134+
Spec_File := (if Unit.Has_Part (S_Spec) then
135+
Unit.Spec.Source.Virtual_File else No_File);
136+
Body_File := (if Unit.Has_Part (S_Body) then
137+
Unit.Main_Body.Source.Virtual_File else No_File);
138+
120139
if File = Spec_File then
121140
return Body_File;
122141
else
@@ -128,48 +147,102 @@ package body LSP.Ada_Handlers.Other_File_Commands is
128147
-- Unit_For_File --
129148
-------------------
130149

131-
function Unit_For_File return GPR2.Build.Compilation_Unit.Object is
150+
function Unit_For_File
151+
return GPR2.Build.Compilation_Unit.Object is
132152
begin
133153
-- Check in the root project's closure for a visible source
134154
-- corresponding to this file.
135155
-- Not that the root's project closure includes the runtime.
136156
if Handler.Project_Tree.Is_Defined then
137157
declare
138-
View : constant GPR2.Project.View.Object :=
158+
View : constant GPR2.Project.View.Object :=
139159
Handler.Project_Tree.Root_Project;
140-
Unit_Info : constant GPR2.Build.Unit_Info.Object :=
141-
View.Visible_Source (F.Simple_Name).Unit;
142-
Unit : GPR2.Build.Compilation_Unit.Object :=
160+
Visible_Source : constant GPR2.Build.Source.Object :=
161+
View.Visible_Source (F.Simple_Name);
162+
Unit : GPR2.Build.Compilation_Unit.Object :=
143163
GPR2.Build.Compilation_Unit.Undefined;
144164
begin
145-
if Unit_Info.Is_Defined then
146-
Unit := View.Namespace_Roots.First_Element.Unit
147-
(Unit_Info.Name);
165+
-- The source is not visible from the root project (e.g:
166+
-- when querying the other file of an Ada file that
167+
-- does not belong to the loaded project).
168+
if not Visible_Source.Is_Defined then
169+
return GPR2.Build.Compilation_Unit.Undefined;
148170
end if;
149171

150-
return Unit;
172+
declare
173+
Unit_Info : constant GPR2.Build.Unit_Info.Object :=
174+
Visible_Source.Unit;
175+
begin
176+
if Unit_Info.Is_Defined then
177+
Unit :=
178+
View.Namespace_Roots.First_Element.Unit
179+
(Unit_Info.Name);
180+
end if;
181+
182+
return Unit;
183+
end;
151184
end;
152185
else
153186
return GPR2.Build.Compilation_Unit.Undefined;
154187
end if;
155188
end Unit_For_File;
156189

190+
Unit : constant GPR2.Build.Compilation_Unit.Object := Unit_For_File;
191+
Other_File : Virtual_File;
157192
begin
158-
return Other_File_From_Unit (Unit_For_File);
159-
end Other_File;
160-
161-
URI : constant LSP.Structures.DocumentUri :=
162-
Handler.To_URI (Other_File.Display_Full_Name);
193+
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;
202+
else
203+
Other_File := Other_File_From_Unit (Unit => Unit);
204+
205+
if Other_File = No_File then
206+
Success := False;
207+
Error_Msg :=
208+
VSS.Strings.Conversions.To_Virtual_String
209+
("Could not find other file for '"
210+
& File.Display_Base_Name
211+
& "': the unit has no other part.");
212+
else
213+
Success := True;
214+
end if;
163215

164-
Message : constant LSP.Structures.ShowDocumentParams :=
165-
(uri => (VSS.Strings.Virtual_String (URI) with null record),
166-
takeFocus => LSP.Constants.True,
167-
others => <>);
216+
return Other_File;
217+
end if;
218+
end Get_Other_File;
168219

169-
New_Id : constant LSP.Structures.Integer_Or_Virtual_String :=
170-
Handler.Server.Allocate_Request_Id;
220+
Success : Boolean;
221+
Error_Msg : VSS.Strings.Virtual_String;
222+
Other_File : constant Virtual_File := Get_Other_File (Success, Error_Msg);
171223
begin
172-
Handler.Sender.On_ShowDocument_Request (New_Id, Message);
224+
if not Success then
225+
Error :=
226+
(Is_Set => True,
227+
Value =>
228+
(code => LSP.Enumerations.InternalError, message => Error_Msg));
229+
return;
230+
end if;
231+
232+
declare
233+
URI : constant LSP.Structures.DocumentUri :=
234+
Handler.To_URI (Other_File.Display_Full_Name);
235+
236+
Message : constant LSP.Structures.ShowDocumentParams :=
237+
(uri => (VSS.Strings.Virtual_String (URI) with null record),
238+
takeFocus => LSP.Constants.True,
239+
others => <>);
240+
241+
New_Id : constant LSP.Structures.Integer_Or_Virtual_String :=
242+
Handler.Server.Allocate_Request_Id;
243+
begin
244+
Handler.Sender.On_ShowDocument_Request (New_Id, Message);
245+
end;
173246
end Execute;
174247

175248
----------------
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
project Default is
2+
for Source_Dirs use ("src");
3+
end Default;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package body Not_A_Source is
2+
procedure Do_Something is null;
3+
end Not_A_Source;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package Not_A_Source is
2+
procedure Do_Something;
3+
end Not_A_Source;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
package A with Pure is
2+
end A;
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: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
[
2+
{
3+
"comment": [
4+
"Check that the 'als-other-file' command displays proper error messages ",
5+
"when failing."
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": "workspace/didChangeConfiguration",
45+
"params": {
46+
"settings": {
47+
"ada": {
48+
"projectFile": "default.gpr",
49+
"scenarioVariables": {},
50+
"enableDiagnostics": false,
51+
"defaultCharset": "UTF-8"
52+
}
53+
}
54+
}
55+
},
56+
"wait": [
57+
{
58+
"jsonrpc": "2.0",
59+
"id": 1,
60+
"method": "window/workDoneProgress/create",
61+
"params": {
62+
"token": "<ANY>"
63+
}
64+
}
65+
]
66+
}
67+
},
68+
{
69+
"send": {
70+
"request": {
71+
"jsonrpc": "2.0",
72+
"id": "sw1",
73+
"method": "workspace/executeCommand",
74+
"params": {
75+
"command": "als-other-file",
76+
"arguments": [
77+
{
78+
"uri": "$URI{src/a.ads}"
79+
}
80+
]
81+
}
82+
},
83+
"wait": [
84+
{
85+
"error": {
86+
"code": -32603,
87+
"message": "Could not find other file for 'a.ads': the unit has no other part."
88+
},
89+
"id": "sw1",
90+
"jsonrpc": "2.0"
91+
}
92+
]
93+
}
94+
},
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+
},
122+
{
123+
"send": {
124+
"request": {
125+
"jsonrpc": "2.0",
126+
"id": "sw2",
127+
"method": "workspace/executeCommand",
128+
"params": {
129+
"command": "als-other-file",
130+
"arguments": [
131+
{
132+
"uri": "$URI{main.adb}"
133+
}
134+
]
135+
}
136+
},
137+
"wait": [
138+
{
139+
"error": {
140+
"code": -32603,
141+
"message": "Could not find other file for 'main.adb': the unit has no other part."
142+
},
143+
"id": "sw2",
144+
"jsonrpc": "2.0"
145+
}
146+
]
147+
}
148+
},
149+
{
150+
"send": {
151+
"request": {
152+
"jsonrpc": "2.0",
153+
"id": "shutdown",
154+
"method": "shutdown",
155+
"params": null
156+
},
157+
"wait": [{ "id": "shutdown", "result": null }]
158+
}
159+
},
160+
{
161+
"send": {
162+
"request": { "jsonrpc": "2.0", "method": "exit" },
163+
"wait": []
164+
}
165+
},
166+
{
167+
"stop": {
168+
"exit_code": 0
169+
}
170+
}
171+
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
title: 'commands.other_file.error_messages'

0 commit comments

Comments
 (0)