Skip to content

Commit 567d5b4

Browse files
UB25-027: Add a custom request to list source directories
Allowing the extension to query them in order to add them to the workspace if not already present. This allows to search for files that come from imported projects that might not be under the workspace root directory. This works only for importing non-externally built source directories for the moment.
1 parent 9bc738e commit 567d5b4

27 files changed

+407
-13
lines changed

doc/source_dirs.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Source dirs
2+
3+
## Short introduction
4+
5+
This is a custom request used by the VS Code extension to retrieve the project's source directories, allowing to add missing directories in the workspace when needed.
6+
7+
## Change description
8+
9+
We introduce three new types to represent the request parameters and results:
10+
11+
```typescript
12+
13+
interface ALS_Unit_Description {
14+
name : string; /* The source directory's name in VS Code */
15+
uri : DocumentUri; /* The source directory's uri */
16+
}
17+
```
18+
19+
And a new request:
20+
21+
method: `workspace/alsSourceDirs`
22+
params: null
23+
24+
Returning the source directories of the loaded project like this:
25+
26+
result: `ALS_Source_Dir_Description[]`

integration/vscode/ada/src/extension.ts

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ import {
2424
ServerOptions,
2525
} from 'vscode-languageclient/node';
2626
import * as process from 'process';
27-
2827
import GPRTaskProvider from './gprTaskProvider';
2928
import cleanTaskProvider from './cleanTaskProvider';
3029
import gnatproveTaskProvider from './gnatproveTaskProvider';
3130
import { alsCommandExecutor } from './alsExecuteCommand';
3231
import { ALSClientFeatures } from './alsClientFeatures';
32+
import { string } from 'fp-ts';
3333

3434
let alsTaskProvider: vscode.Disposable[] = [
3535
vscode.tasks.registerTaskProvider(GPRTaskProvider.gprBuildType, new GPRTaskProvider()),
@@ -125,6 +125,60 @@ export function activate(context: vscode.ExtensionContext): void {
125125

126126
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(configChanged));
127127
context.subscriptions.push(vscode.commands.registerCommand('ada.otherFile', otherFileHandler));
128+
129+
// Check if we need to add some source directories to the workspace (e.g: when imported projects'
130+
// source directories are not placed under the root project's directory).
131+
client.onReady().then(() => {
132+
client.sendRequest("workspace/alsSourceDirs").then(
133+
data => {
134+
const source_dirs = JSON.parse(JSON.stringify(data));
135+
const workspace_folders = vscode.workspace.workspaceFolders ?? []
136+
let workspace_dirs_to_add: { uri: vscode.Uri, name?: string | undefined}[] = []
137+
138+
for (var source_dir of source_dirs) {
139+
const source_dir_uri = vscode.Uri.parse(source_dir.uri)
140+
let source_dir_path = source_dir_uri.path
141+
let workspace_folder_path = workspace_folders[0].uri.path
142+
143+
function is_subdirectory(dir: string, parent: string) {
144+
// Use lower-case on Windows since drives can be specified in VS Code either
145+
// with lower or upper case characters.
146+
if (process.platform == "win32") {
147+
dir = dir.toLowerCase();
148+
parent = parent.toLowerCase();
149+
}
150+
151+
return dir.startsWith(parent + '/');
152+
153+
}
154+
155+
// If the source directory is not under one of the workspace folders, push this
156+
// source directory to the workspace folders to add later.
157+
if (!workspace_folders.some(workspace_folder =>
158+
is_subdirectory(source_dir_path, workspace_folder.uri.path))) {
159+
workspace_dirs_to_add.push({name: source_dir.name, uri: source_dir_uri});
160+
}
161+
}
162+
163+
// If there are some source directories missing in the workspace, ask the user
164+
// to add them in his workspace.
165+
if (workspace_dirs_to_add.length > 0) {
166+
vscode.window
167+
.showInformationMessage("Some project source directories are not "
168+
+ "listed in your workspace: do you want to add them?", "Yes", "No")
169+
.then(answer => {
170+
if (answer === "Yes") {
171+
for (var workspace_dir of workspace_dirs_to_add) {
172+
vscode.workspace.updateWorkspaceFolders(
173+
vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders.length : 0, null,
174+
workspace_dir);
175+
}
176+
}
177+
})
178+
}
179+
}
180+
)
181+
})
128182
}
129183

130184
export function deactivate(): void {

scripts/generate.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@
322322
('textDocument/alsShowDependencies', 'ALS_Show_Dependencies',
323323
'ALS_ShowDependenciesParams',
324324
'ALS_ShowDependencies_Response'),
325+
('workspace/alsSourceDirs', 'ALS_Source_Dirs',
326+
None,
327+
'ALS_SourceDirs_Response'),
325328
('$/alsDebug', 'ALS_Debug', 'ALSDebugParams', 'ALS_Debug_Response'),
326329
('$/alsCheckSyntax', 'ALS_Check_Syntax', 'ALS_Check_Syntax_Params',
327330
'ALS_Check_Syntax_Response'),

source/ada/lsp-ada_context_sets.adb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,16 @@ package body LSP.Ada_Context_Sets is
158158
----------------------------
159159

160160
function All_Source_Directories
161-
(Self : Context_Set'Class) return GNATCOLL.VFS.File_Array
161+
(Self : Context_Set'Class;
162+
Include_Externally_Built : Boolean := False)
163+
return GNATCOLL.VFS.File_Array
162164
is
163165
Consolidated_Set : LSP.Ada_File_Sets.File_Sets.Set;
164166
begin
165167
for C of Self.Contexts loop
166-
Consolidated_Set.Union (C.List_Source_Directories);
168+
Consolidated_Set.Union
169+
(C.List_Source_Directories
170+
(Include_Externally_Built => Include_Externally_Built));
167171
end loop;
168172

169173
declare

source/ada/lsp-ada_context_sets.ads

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,13 @@ package LSP.Ada_Context_Sets is
5959
-- Number of files in all contexts
6060

6161
function All_Source_Directories
62-
(Self : Context_Set'Class) return GNATCOLL.VFS.File_Array;
63-
-- Return the list of all source directories for writable projects
64-
-- in the context (ie, excluding externally-built projects). Each
65-
-- dirctory is present only once in the resulting array.
62+
(Self : Context_Set'Class;
63+
Include_Externally_Built : Boolean := False)
64+
return GNATCOLL.VFS.File_Array;
65+
-- Return the list of all source directories for writable projects in the
66+
-- context, including externally built projects' source directories when
67+
-- Include_Externally_Built is set to True.
68+
-- Each dirctory is present only once in the resulting array.
6669

6770
procedure Cleanup (Self : in out Context_Set'Class);
6871
-- Free memory referenced by Self

source/ada/lsp-ada_contexts.adb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,15 @@ package body LSP.Ada_Contexts is
237237
-----------------------------
238238

239239
function List_Source_Directories
240-
(Self : Context) return LSP.Ada_File_Sets.File_Sets.Set is
240+
(Self : Context;
241+
Include_Externally_Built : Boolean := False)
242+
return LSP.Ada_File_Sets.File_Sets.Set is
241243
begin
242-
return Self.Source_Dirs;
244+
if Include_Externally_Built then
245+
return Self.External_Source_Dirs;
246+
else
247+
return Self.Source_Dirs;
248+
end if;
243249
end List_Source_Directories;
244250

245251
-------------------------
@@ -651,13 +657,23 @@ package body LSP.Ada_Contexts is
651657
end loop;
652658

653659
Self.Source_Dirs.Clear;
660+
Self.External_Source_Dirs.Clear;
661+
654662
for Dir of Source_Dirs
655663
(Project => Root,
656664
Recursive => True,
657665
Include_Externally_Built => False)
658666
loop
659667
Self.Source_Dirs.Include (Dir);
660668
end loop;
669+
670+
for Dir of Source_Dirs
671+
(Project => Root,
672+
Recursive => True,
673+
Include_Externally_Built => True)
674+
loop
675+
Self.External_Source_Dirs.Include (Dir);
676+
end loop;
661677
end Update_Source_Files;
662678

663679
--------------------------

source/ada/lsp-ada_contexts.ads

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,11 @@ package LSP.Ada_Contexts is
196196
-- Return the analysis units for all Ada sources known to this context
197197

198198
function List_Source_Directories
199-
(Self : Context) return LSP.Ada_File_Sets.File_Sets.Set;
200-
-- List the source directories in non-externally-built projects
199+
(Self : Context;
200+
Include_Externally_Built : Boolean := False)
201+
return LSP.Ada_File_Sets.File_Sets.Set;
202+
-- List the source directories, including externally built projects' source
203+
-- directories when Include_Externally_Built is set to True.
201204

202205
function Get_AU
203206
(Self : Context;
@@ -298,6 +301,9 @@ private
298301
-- All the source dirs in the loaded project, not including
299302
-- the externally built projects
300303

304+
External_Source_Dirs : LSP.Ada_File_Sets.File_Sets.Set;
305+
-- All the source dirs coming from externally built projects
306+
301307
PP_Options : Utils.Command_Lines.Command_Line
302308
(Pp.Command_Lines.Descriptor'Access);
303309
-- Object to keep gnatpp options

source/ada/lsp-ada_handlers.adb

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3098,9 +3098,40 @@ package body LSP.Ada_Handlers is
30983098
return Response;
30993099
end On_References_Request;
31003100

3101-
----------------------------------
3101+
--------------------------------
3102+
-- On_ALS_Source_Dirs_Request --
3103+
--------------------------------
3104+
3105+
overriding function On_ALS_Source_Dirs_Request
3106+
(Self : access Message_Handler;
3107+
Request : LSP.Messages.Server_Requests.ALS_Source_Dirs_Request)
3108+
return LSP.Messages.Server_Responses.ALS_SourceDirs_Response
3109+
is
3110+
Response : LSP.Messages.Server_Responses.ALS_SourceDirs_Response
3111+
(Is_Error => False);
3112+
Unit_Desc : LSP.Messages.ALS_Source_Dir_Description;
3113+
Source_Dirs : constant GNATCOLL.VFS.File_Array :=
3114+
Self.Contexts.All_Source_Directories
3115+
(Include_Externally_Built => True);
3116+
begin
3117+
for Dir of Source_Dirs loop
3118+
Unit_Desc :=
3119+
(name => VSS.Strings.Conversions.To_Virtual_String
3120+
(+Dir.Base_Dir_Name),
3121+
uri =>
3122+
File_To_URI (Dir.Display_Full_Name));
3123+
Response.result.Append (Unit_Desc);
3124+
end loop;
3125+
3126+
Self.Trace.Trace
3127+
("Response.result.length: " & Response.result.Length'Img);
3128+
3129+
return Response;
3130+
end On_ALS_Source_Dirs_Request;
3131+
3132+
--------------------------------------
31023133
-- On_ALS_Show_Dependencies_Request --
3103-
----------------------------------
3134+
--------------------------------------
31043135

31053136
overriding function On_ALS_Show_Dependencies_Request
31063137
(Self : access Message_Handler;

source/ada/lsp-ada_handlers.ads

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,11 @@ private
526526
Request : LSP.Messages.Server_Requests.ALS_Show_Dependencies_Request)
527527
return LSP.Messages.Server_Responses.ALS_ShowDependencies_Response;
528528

529+
overriding function On_ALS_Source_Dirs_Request
530+
(Self : access Message_Handler;
531+
Request : LSP.Messages.Server_Requests.ALS_Source_Dirs_Request)
532+
return LSP.Messages.Server_Responses.ALS_SourceDirs_Response;
533+
529534
overriding function On_ALS_Debug_Request
530535
(Self : access Message_Handler;
531536
Request : LSP.Messages.Server_Requests.ALS_Debug_Request)

source/ada/lsp-error_decorators.adb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,26 @@ package body LSP.Error_Decorators is
626626
return LSP.Messages.Server_Responses.ALS_ShowDependencies_Response
627627
renames ALS_Show_Dependencies_Request;
628628

629+
-----------------------------
630+
-- ALS_Source_Dirs_Request --
631+
-----------------------------
632+
633+
function ALS_Source_Dirs_Request is new Generic_Request
634+
(Request =>
635+
LSP.Messages.Server_Requests.ALS_Source_Dirs_Request,
636+
Response =>
637+
LSP.Messages.Server_Responses.ALS_SourceDirs_Response,
638+
Handler =>
639+
LSP.Server_Request_Handlers.Server_Request_Handler,
640+
On_Request =>
641+
LSP.Server_Request_Handlers.On_ALS_Source_Dirs_Request);
642+
643+
overriding function On_ALS_Source_Dirs_Request
644+
(Self : access Error_Decorator;
645+
Request : LSP.Messages.Server_Requests.ALS_Source_Dirs_Request)
646+
return LSP.Messages.Server_Responses.ALS_SourceDirs_Response
647+
renames ALS_Source_Dirs_Request;
648+
629649
--------------------------
630650
-- On_ALS_Debug_Request --
631651
--------------------------

0 commit comments

Comments
 (0)