Skip to content

Commit 98ec0ee

Browse files
committed
Support resetting settings to the initial state
1 parent d372737 commit 98ec0ee

File tree

6 files changed

+99
-30
lines changed

6 files changed

+99
-30
lines changed

doc/settings.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
## Configuration Sources
44

5-
The ALS loads configuration settings from different sources in the following order:
5+
The ALS loads configuration settings from different sources. All configuration sources are loaded in the following order:
66

7-
1. The file `$XDG_CONFIG_HOME/als/config.json`, if it exists.
7+
1. A global user configuration file `$XDG_CONFIG_HOME/als/config.json`, if it exists.
88

9-
1. The file `.als.json` in the directory where ALS is spawned, if it exists.
9+
1. A workspace-specific `.als.json` file in the directory where ALS is spawned, if it exists.
1010

1111
This is the prefered location to store project-specific settings that are tracked in version control and shared among developers.
1212

@@ -16,7 +16,11 @@ The ALS loads configuration settings from different sources in the following ord
1616

1717
1. In `workspace/didChangeConfiguration` LSP notifications, if specified.
1818

19-
If given, the configuration file must be a JSON file with the following structure:
19+
Each configuration source can contain a partial list of settings. Thus each
20+
configuration source can override individual settings while preserving
21+
previously loaded settings.
22+
23+
Configuration files must be JSON files matching [this JSON schema](integration/vscode/ada/schemas/als-settings-schema.json). Roughly the structure looks like this:
2024

2125
```json
2226
{
@@ -61,6 +65,12 @@ Similarly, settings passed in `workspace/didChangeConfiguration` notifications s
6165
}
6266
```
6367

68+
## Base Configuration
69+
70+
The *base configuration* is the one that ALS reaches after loading configuration files (i.e. global user configuration, workspace-specific `.als.json` file, and `--config` command line argument).
71+
72+
After that the ALS may receive configuration changes through the `initialize` request, or the `workspace/didChangeConfiguration` notification. In those messages, if settings have the value `null`, ALS reverts their value to the base configuration. This allows clients to temporarily override settings, and revert them back in the same session.
73+
6474
## Visual Studio Code
6575

6676
In the context of Visual Studio Code, configuration settings can be set in the

integration/vscode/ada/test/dot-als-json/dot_als_json.test.ts

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import assert from 'assert';
2-
import { adaExtState } from '../../src/extension';
3-
import { activate } from '../utils';
42
import path from 'path';
53
import { ConfigurationTarget, workspace } from 'vscode';
4+
import { adaExtState } from '../../src/extension';
5+
import { activate } from '../utils';
66

77
suite('dot-als-json', function () {
88
this.beforeAll(async function () {
99
await activate();
1010
});
1111

12+
const alsDotJsonValue = 'als-dot-json-value';
13+
const settingsDotJsonValue = 'settings-json-value';
14+
1215
/**
1316
* The goal of this testsuite is to verify the interaction between settings
1417
* coming from .als.json and .vscode/settings.json.
@@ -35,24 +38,22 @@ suite('dot-als-json', function () {
3538
* Initially the scenario variable is set in .als.json but not in settings.json
3639
*/
3740
const objDir = path.basename(await adaExtState.getObjectDir());
38-
const expected = 'als-dot-json-value';
41+
const expected = alsDotJsonValue;
3942
assert.equal(objDir, expected);
4043
});
4144

4245
test('case-2', async function () {
4346
const initial = workspace.getConfiguration('ada').get('scenarioVariables');
4447
try {
45-
/**
46-
* First we change the VS Code settings to override the scenario variable.
47-
*/
48-
const sentinel = 'settings-json-value';
49-
await workspace.getConfiguration('ada').update('scenarioVariables', { Var: sentinel });
48+
await workspace
49+
.getConfiguration('ada')
50+
.update('scenarioVariables', { Var: settingsDotJsonValue });
5051

5152
/**
5253
* Check that the change overwrote the .als.json value
5354
*/
5455
const objDir = path.basename(await adaExtState.getObjectDir());
55-
assert.equal(objDir, sentinel);
56+
assert.equal(objDir, settingsDotJsonValue);
5657
} finally {
5758
/**
5859
* Restore the initial value of the setting.
@@ -70,33 +71,26 @@ suite('dot-als-json', function () {
7071
test('undo-override', async function () {
7172
const initial = workspace.getConfiguration('ada').get('scenarioVariables');
7273
try {
73-
/**
74-
* First we change the VS Code settings to override the scenario variable.
75-
*/
76-
const sentinel = 'settings-json-value';
77-
await workspace.getConfiguration('ada').update('scenarioVariables', { Var: sentinel });
74+
await workspace
75+
.getConfiguration('ada')
76+
.update('scenarioVariables', { Var: settingsDotJsonValue });
7877

7978
/**
8079
* Check that the change overwrote the .als.json value
8180
*/
8281
let objDir = path.basename(await adaExtState.getObjectDir());
83-
assert.equal(objDir, sentinel);
82+
assert.equal(objDir, settingsDotJsonValue);
8483

8584
/**
8685
* Now let's undo the override.
8786
*/
8887
await workspace.getConfiguration('ada').update('scenarioVariables', undefined);
8988

9089
/**
91-
* Ideally we would want the ALS to switch back to the setting from
92-
* .als.json but this is not the current behavior.
93-
*
94-
* Currently the didChangeConfiguration notification contains \{
95-
* "scenarioVariables": null \} which makes ALS ignore the provided
96-
* value and retain the last stored value.
90+
* The value should go back to the .als.json value
9791
*/
9892
objDir = path.basename(await adaExtState.getObjectDir());
99-
assert.equal(objDir, sentinel);
93+
assert.equal(objDir, alsDotJsonValue);
10094
} finally {
10195
/**
10296
* Restore the initial value of the setting.

source/ada/lsp-ada_did_change_configurations.adb

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
-- of the license. --
1616
------------------------------------------------------------------------------
1717

18+
with GPR2.Context;
1819
with LSP.Ada_Configurations;
1920
with LSP.Client_Message_Receivers;
2021
with LSP.Server_Notifications.DidChangeConfiguration;
22+
with VSS.Strings;
2123

2224
package body LSP.Ada_Did_Change_Configurations is
2325

@@ -75,24 +77,61 @@ package body LSP.Ada_Did_Change_Configurations is
7577
Message : LSP.Server_Messages.Server_Message_Access)
7678
return LSP.Server_Jobs.Server_Job_Access
7779
is
80+
use type VSS.Strings.Virtual_String;
81+
use type GPR2.Context.Object;
82+
7883
Value : LSP.Server_Notifications.DidChangeConfiguration.Notification
7984
renames LSP.Server_Notifications.DidChangeConfiguration.Notification
8085
(Message.all);
8186

8287
Result : constant Apply_Config_Job_Access :=
8388
new Apply_Config_Job (Self'Unchecked_Access);
8489

85-
Reload : Boolean renames Result.Reload;
86-
begin
87-
Result.Configuration :=
90+
Base_Config : constant LSP.Ada_Configurations.Configuration :=
91+
LSP.Ada_Configurations.Configuration
92+
(Self.Context.Get_Base_Configuration.all);
93+
94+
Current_Config : constant LSP.Ada_Configurations.Configuration :=
8895
LSP.Ada_Configurations.Configuration
8996
(Self.Context.Get_Configuration.all);
9097

91-
Result.Configuration.Read_JSON (Value.Params.settings, Reload);
98+
New_Config : LSP.Ada_Configurations.Configuration
99+
renames Result.Configuration;
100+
Reload : Boolean renames Result.Reload;
101+
begin
102+
103+
-- The configuration loading logic offers a Reload output boolean that
104+
-- indicates if values were changed that require reloading the project.
105+
-- However this doesn't work when a 'null' value is received. 'null'
106+
-- values are ignored by the configuration parser and thus don't signal
107+
-- the Reload flag.
108+
--
109+
-- To address that we have to compare the relevant configuration
110+
-- settings after they are parsed and cannot rely on the configuration
111+
-- parsing logic.
112+
113+
-- Start with the base configuration.
114+
New_Config := Base_Config;
115+
116+
-- Read the new received configuration. 'null' values will be ignored
117+
-- and thus keep the value from the base config.
118+
New_Config.Read_JSON (Value.Params.settings, Reload);
92119

93120
-- Always reload project if Project_Tree isn't ready
94121
Reload := Reload or not Self.Context.Project_Tree_Is_Defined;
95122

123+
-- Compare with the current configuration to see if a reload is
124+
-- necessary
125+
Reload :=
126+
Reload
127+
or else New_Config.Relocate_Build_Tree
128+
/= Current_Config.Relocate_Build_Tree
129+
or else New_Config.Relocate_Root /= Current_Config.Relocate_Root
130+
or else New_Config.Project_File /= Current_Config.Project_File
131+
or else New_Config.Context /= Current_Config.Context
132+
or else New_Config.Charset /= Current_Config.Charset
133+
or else New_Config.Follow_Symlinks /= Current_Config.Follow_Symlinks;
134+
96135
if Reload then
97136
-- Stop indexing by changing project stamp
98137
Self.Context.Increment_Project_Timestamp;

source/ada/lsp-ada_handlers.adb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,11 @@ package body LSP.Ada_Handlers is
434434
Self.Client.Set_Root_If_Empty (
435435
To_Virtual_String (ALS_Workspace_Config_File.Get_Parent));
436436
end if;
437+
438+
-- Save the initial configuration so that we can restore individual
439+
-- settings back to the initial state when 'onDidChangeConfiguration'
440+
-- provides null values.
441+
Self.Base_Configuration := Self.Configuration;
437442
end Load_Config_Files;
438443

439444
-------------------

source/ada/lsp-ada_handlers.ads

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,17 @@ private
177177
and LSP.Ada_Job_Contexts.Ada_Job_Context
178178
with record
179179
Client : aliased LSP.Ada_Client_Capabilities.Client_Capability;
180+
181+
Base_Configuration : aliased LSP.Ada_Configurations.Configuration;
182+
-- This is the initial configuration loaded at process startup from
183+
-- configuration files (global, local .als.json, CLI --config). Later
184+
-- on the configuration may be overwritten by the 'initialize' request
185+
-- or 'onDidChangeConfiguration' notifications so saving this initial
186+
-- configuration allows to revert settings back when a null value is
187+
-- received in an `onDidChangeConfiguration` notification.
188+
180189
Configuration : aliased LSP.Ada_Configurations.Configuration;
190+
-- The current configuration in use.
181191

182192
Contexts : LSP.Ada_Context_Sets.Context_Set;
183193
-- There is one context in this list per loaded project.
@@ -424,6 +434,10 @@ private
424434
access constant LSP.Ada_Client_Capabilities.Client_Capability'Class
425435
is (Self.Client'Unchecked_Access);
426436

437+
overriding function Get_Base_Configuration (Self : Message_Handler)
438+
return access constant LSP.Ada_Configurations.Configuration'Class
439+
is (Self.Base_Configuration'Unchecked_Access);
440+
427441
overriding function Get_Configuration (Self : Message_Handler)
428442
return access constant LSP.Ada_Configurations.Configuration'Class is
429443
(Self.Configuration'Unchecked_Access);

source/ada/lsp-ada_job_contexts.ads

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,16 @@ package LSP.Ada_Job_Contexts is
5353
access constant LSP.Ada_Client_Capabilities.Client_Capability'Class
5454
is abstract;
5555

56+
function Get_Base_Configuration (Self : Ada_Job_Context)
57+
return access constant LSP.Ada_Configurations.Configuration'Class
58+
is abstract;
59+
-- The base configuration loaded at process startup from configuration
60+
-- files.
61+
5662
function Get_Configuration (Self : Ada_Job_Context)
5763
return access constant LSP.Ada_Configurations.Configuration'Class
5864
is abstract;
65+
-- The current applicable configuration.
5966

6067
procedure Set_Configuration
6168
(Self : in out Ada_Job_Context;

0 commit comments

Comments
 (0)