Skip to content

Commit c733dc7

Browse files
author
automatic-merge
committed
Merge remote branch 'origin/master' into edge
2 parents d037b05 + f948bb5 commit c733dc7

File tree

14 files changed

+471
-122
lines changed

14 files changed

+471
-122
lines changed

source/ada/lsp-ada_configurations.ads

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ with GPR2.Path_Name;
3030
package LSP.Ada_Configurations is
3131

3232
type Configuration is tagged private;
33+
-- Type representing the server's configuration, containing all the
34+
-- settings that can be set through the 'initialize' and
35+
-- 'didChangeConfiguration' notifications.
3336

3437
function Needs_Reload
3538
(Self : Configuration; Other : Configuration'Class) return Boolean;

source/ada/lsp-ada_handlers.adb

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,8 @@ package body LSP.Ada_Handlers is
438438
To_Virtual_String (ALS_Workspace_Config_File),
439439
To_Virtual_String (CLI_Config_File)];
440440

441+
Config_File_Processed : Boolean := False;
442+
New_Configuration : LSP.Ada_Configurations.Configuration;
441443
begin
442444
for F_Path of Candidates loop
443445
if not F_Path.Is_Empty then
@@ -448,7 +450,8 @@ package body LSP.Ada_Handlers is
448450
Self.Tracer.Trace_Text ("Trying config file: " & F_Path);
449451
if F.Is_Regular_File then
450452
Self.Tracer.Trace_Text ("Loading config file: " & F_Path);
451-
Self.Configuration.Read_File (F_Path);
453+
New_Configuration.Read_File (F_Path);
454+
Config_File_Processed := True;
452455
else
453456
Self.Tracer.Trace_Text (F_Path & " doesn't exist");
454457
end if;
@@ -461,16 +464,20 @@ package body LSP.Ada_Handlers is
461464
-- overwritten if a value is provided in the initialize request.
462465
-- Prioritize the config file given on the CLI.
463466
if CLI_Config_File.Is_Regular_File then
464-
Self.Client.Set_Root_If_Empty (To_Virtual_String (CLI_Config_File.Dir));
467+
Self.Client.Set_Root_If_Empty
468+
(To_Virtual_String (CLI_Config_File.Dir));
465469
elsif ALS_Workspace_Config_File.Is_Regular_File then
466-
Self.Client.Set_Root_If_Empty (
467-
To_Virtual_String (ALS_Workspace_Config_File.Get_Parent));
470+
Self.Client.Set_Root_If_Empty
471+
(To_Virtual_String (ALS_Workspace_Config_File.Get_Parent));
468472
end if;
469473

470-
-- Save the initial configuration so that we can restore individual
471-
-- settings back to the initial state when 'onDidChangeConfiguration'
472-
-- provides null values.
473-
Self.Base_Configuration := Self.Configuration;
474+
-- Set it as the current configuration.
475+
-- This will also save it as the initial configuration so that
476+
-- we can restore individual settings back to the initial state when
477+
-- 'onDidChangeConfiguration' provides null values.
478+
if Config_File_Processed then
479+
Self.Set_Configuration (New_Configuration);
480+
end if;
474481
end Load_Config_Files;
475482

476483
-------------------
@@ -2425,7 +2432,19 @@ package body LSP.Ada_Handlers is
24252432
-- ...
24262433
-- }
24272434
-- }
2428-
Self.Configuration.Read_JSON (Value.initializationOptions);
2435+
declare
2436+
New_Configuration : LSP.Ada_Configurations.Configuration;
2437+
begin
2438+
-- Parse the configuration.
2439+
New_Configuration.Read_JSON (Value.initializationOptions);
2440+
2441+
-- Set it as the current configuration.
2442+
-- This will also save it as the initial configuration (if not done
2443+
-- yet through config files) so that we can restore individual
2444+
-- settings back to the initial state when
2445+
-- 'onDidChangeConfiguration' provides null values.
2446+
Self.Set_Configuration (New_Configuration);
2447+
end;
24292448

24302449
-- We don't load the project here because we can't send progress
24312450
-- notifications to the client before receiving the 'initialized'
@@ -3783,6 +3802,14 @@ package body LSP.Ada_Handlers is
37833802
Value : LSP.Ada_Configurations.Configuration'Class) is
37843803
begin
37853804
Self.Configuration := LSP.Ada_Configurations.Configuration (Value);
3805+
3806+
-- The base configuration is still the default one, meaning that
3807+
-- we did not receive any user configuration previously: use
3808+
-- the new configuration as the base one.
3809+
if not Self.Base_Configuration_Received then
3810+
Self.Base_Configuration := Self.Configuration;
3811+
Self.Base_Configuration_Received := True;
3812+
end if;
37863813
end Set_Configuration;
37873814

37883815
-----------------------

source/ada/lsp-ada_handlers.ads

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,11 @@ private
191191
Configuration : aliased LSP.Ada_Configurations.Configuration;
192192
-- The current configuration in use.
193193

194+
Base_Configuration_Received : Boolean := False;
195+
-- Set to true once we receive the user's base configuration, either
196+
-- through config files, the 'initialize' request or the first
197+
-- 'didChangeConfiguration' notification.
198+
194199
Contexts : LSP.Ada_Context_Sets.Context_Set;
195200
-- There is one context in this list per loaded project.
196201
-- There should always be at least one "project" context - if no .gpr

testsuite/ada_lsp/called_by_dispatching/test.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
URI,
55
ALSLanguageClient,
66
assertLocationsList,
7-
callHierarchyIncomingCallsParams,
8-
callHierarchyPrepareParams,
97
didOpenTextDocumentParams,
108
test,
119
)
@@ -19,18 +17,14 @@ async def test_called_by(lsp: ALSLanguageClient):
1917
lsp.text_document_did_open(open_params)
2018

2119
# Send a textDocument/prepareCallHierarchy request
22-
result1 = await lsp.text_document_prepare_call_hierarchy_async(
23-
callHierarchyPrepareParams(main_adb_uri, 7, 4)
24-
)
20+
result1 = await lsp.prepareCallHierarchy(main_adb_uri, 7, 4)
2521
assert result1
2622

2723
# Expect these locations
2824
assertLocationsList(result1, [("root.ads", 5)])
2925

3026
# Now send the callHierarchy/incomingCalls request
31-
result2 = await lsp.call_hierarchy_incoming_calls_async(
32-
callHierarchyIncomingCallsParams(root_ads_uri, 5, 14)
33-
)
27+
result2 = await lsp.callHierarchyIncomingCalls(root_ads_uri, 5, 14)
3428
assert result2
3529

3630
# Expect these locations
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"$schema": "../../../integration/vscode/ada/schemas/als-settings-schema.json",
3+
"scenarioVariables": {
4+
"Var": "value-from-config-file"
5+
}
6+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- We need a source file in the project to trigger indexing
2+
package Pkg is
3+
pragma Pure;
4+
end Pkg;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
project Prj is
2+
for Object_Dir use external("Var", "value-from-prj");
3+
end Prj;
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
"""
2+
The goal of these tests is to check that ALS remembers a base configuration to which it
3+
can revert settings when receiving null values in didChangeConfiguration notifiactions.
4+
5+
It's important to check that the base configuration can be obtained both when there are
6+
config files (.als.json or User config file), and when there aren't - i.e. when settings
7+
are sent with the initialize request, or with the first didChangeConfiguration
8+
notification.
9+
10+
To observe the active configuration, we use a project file where the object directory is
11+
defined via an external scenario variable and we use the als-object-dir command to query
12+
that.
13+
14+
We also need a way to wait until the project has finished loading in order to query its
15+
object dir. To do that we add at least one source file and await the end of indexing.
16+
17+
The scenarios we want to test:
18+
19+
1. There is a config file. Then the initialize request also provides settings, but the
20+
base config should be the config file.
21+
22+
2. There are no config files, and the initialize request contains settings with non-null
23+
values that should be the base config.
24+
25+
3. There are no config files, and the initialize request contains settings with all null
26+
values. This is the case when no ada.* settings are set in VS Code. The config at
27+
initialize should be considered the base config.
28+
29+
4. There are no config files. The initialize request doesn't contain any settings. The
30+
first didChangeConfig notification should be considered as the base config.
31+
"""
32+
33+
import os
34+
from lsprotocol.types import ClientCapabilities, InitializeParams
35+
from drivers.pylsp import (
36+
URI,
37+
ALSClientServerConfig,
38+
ALSLanguageClient,
39+
ALSSettings,
40+
assertEqual,
41+
test,
42+
)
43+
44+
45+
@test(
46+
config=ALSClientServerConfig(
47+
server_command=[
48+
os.environ.get("ALS", "ada_language_server"),
49+
"--config",
50+
"my_config.json",
51+
],
52+
),
53+
initialize=False,
54+
)
55+
async def test1(lsp: ALSLanguageClient) -> None:
56+
# Even if we send settings in the initialize request, the config file should
57+
# constitue the base config.
58+
settings: ALSSettings = {
59+
"scenarioVariables": {"Var": "value-from-init"},
60+
}
61+
await lsp.initialize_session(
62+
InitializeParams(
63+
ClientCapabilities(),
64+
root_uri=URI(os.getcwd()),
65+
initialization_options={"ada": settings},
66+
)
67+
)
68+
# Because no project file was set, we need a didOpen to load the project
69+
lsp.didOpenVirtual()
70+
await lsp.awaitIndexingEnd()
71+
assertEqual(await lsp.getObjDirBasename(), "value-from-init")
72+
73+
# Now let's change the settings
74+
lsp.didChangeConfig({"scenarioVariables": {"Var": "new-value"}})
75+
await lsp.awaitIndexingEnd()
76+
assertEqual(await lsp.getObjDirBasename(), "new-value")
77+
78+
# Now we send a null value to revert to the base config which should be the config
79+
# file, not the initialize request.
80+
lsp.didChangeConfig({"scenarioVariables": None})
81+
await lsp.awaitIndexingEnd()
82+
assertEqual(await lsp.getObjDirBasename(), "value-from-config-file")
83+
84+
85+
@test(initialize=False)
86+
async def test2(lsp: ALSLanguageClient) -> None:
87+
# In this scenario there are no config files. The settings in the initialize request
88+
# should constitute the base config.
89+
settings: ALSSettings = {
90+
"scenarioVariables": {"Var": "value-from-init"},
91+
}
92+
await lsp.initialize_session(
93+
InitializeParams(
94+
ClientCapabilities(),
95+
root_uri=URI(os.getcwd()),
96+
initialization_options={"ada": settings},
97+
)
98+
)
99+
# Because no project file was set, we need a didOpen to load the project
100+
lsp.didOpenVirtual()
101+
await lsp.awaitIndexingEnd()
102+
assertEqual(await lsp.getObjDirBasename(), "value-from-init")
103+
104+
# Now let's change the settings and revert back to see if we revert to the right
105+
# value.
106+
lsp.didChangeConfig({"scenarioVariables": {"Var": "new-value"}})
107+
await lsp.awaitIndexingEnd()
108+
assertEqual(await lsp.getObjDirBasename(), "new-value")
109+
110+
lsp.didChangeConfig({"scenarioVariables": None})
111+
await lsp.awaitIndexingEnd()
112+
assertEqual(await lsp.getObjDirBasename(), "value-from-init")
113+
114+
115+
@test(initialize=False)
116+
async def test3(lsp: ALSLanguageClient) -> None:
117+
# This scenario reproduces what happens in VS Code when there are no ada.* settings
118+
#
119+
# The settings in the initialize request are null
120+
settings: ALSSettings = {
121+
"scenarioVariables": None,
122+
}
123+
await lsp.initialize_session(
124+
InitializeParams(
125+
ClientCapabilities(),
126+
root_uri=URI(os.getcwd()),
127+
initialization_options={"ada": settings},
128+
)
129+
)
130+
# Because no project file was set, we need a didOpen to load the project
131+
lsp.didOpenVirtual()
132+
await lsp.awaitIndexingEnd()
133+
# No value was provided for the scenario variable, so we should get the default
134+
# value defined in the project.
135+
assertEqual(await lsp.getObjDirBasename(), "value-from-prj")
136+
137+
# Now let's change the settings and revert back to see if we revert to the right
138+
# value.
139+
lsp.didChangeConfig({"scenarioVariables": {"Var": "new-value"}})
140+
await lsp.awaitIndexingEnd()
141+
assertEqual(await lsp.getObjDirBasename(), "new-value")
142+
143+
lsp.didChangeConfig({"scenarioVariables": None})
144+
await lsp.awaitIndexingEnd()
145+
assertEqual(await lsp.getObjDirBasename(), "value-from-prj")
146+
147+
148+
@test(initialize=False)
149+
async def test4(lsp: ALSLanguageClient) -> None:
150+
# There is no config file
151+
await lsp.initialize_session(
152+
InitializeParams(
153+
ClientCapabilities(),
154+
root_uri=URI(os.getcwd()),
155+
# initialize has no settings
156+
)
157+
)
158+
# Because no project file was set, we need a didOpen to load the project
159+
lsp.didOpenVirtual()
160+
await lsp.awaitIndexingEnd()
161+
# No value was provided for the scenario variable, so we should get the default
162+
# value defined in the project.
163+
assertEqual(await lsp.getObjDirBasename(), "value-from-prj")
164+
165+
# Now let's send the first didChangeConfiguration. This should constitute the base
166+
# config.
167+
lsp.didChangeConfig(
168+
{"scenarioVariables": {"Var": "value-from-first-config-change"}}
169+
)
170+
await lsp.awaitIndexingEnd()
171+
assertEqual(await lsp.getObjDirBasename(), "value-from-first-config-change")
172+
173+
# Now we change to another value, and revert with a null value.
174+
lsp.didChangeConfig({"scenarioVariables": {"Var": "new-value"}})
175+
await lsp.awaitIndexingEnd()
176+
assertEqual(await lsp.getObjDirBasename(), "new-value")
177+
178+
lsp.didChangeConfig({"scenarioVariables": None})
179+
await lsp.awaitIndexingEnd()
180+
assertEqual(await lsp.getObjDirBasename(), "value-from-first-config-change")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
driver: pylsp

testsuite/ada_lsp/config_cli/test.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@
1717
from drivers.pylsp import (
1818
URI,
1919
ALSClientServerConfig,
20-
LanguageClient,
20+
ALSLanguageClient,
2121
assertEqual,
22-
getCurrentProject,
2322
test,
2423
)
2524

@@ -29,7 +28,7 @@
2928
[os.environ.get("ALS", "ada_language_server"), "--config", "my_config.json"]
3029
)
3130
)
32-
async def test_func(lsp: LanguageClient) -> None:
33-
response = await lsp.workspace_execute_command_async(getCurrentProject())
31+
async def test_func(lsp: ALSLanguageClient) -> None:
32+
response = await lsp.getCurrentProject()
3433
assert response
3534
assertEqual(response, URI("non-root/p2.gpr"))

0 commit comments

Comments
 (0)