Skip to content

Commit 5ede42a

Browse files
Merge branch 'topic/workspace_pop' into 'master'
Add all the missing workspace directories at once See merge request eng/ide/ada_language_server!1471
2 parents ecb5c52 + 9a15be7 commit 5ede42a

File tree

9 files changed

+214
-92
lines changed

9 files changed

+214
-92
lines changed

.vscode/launch.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,41 @@
107107
// Switch to Debug Console to see test results
108108
"internalConsoleOptions": "openOnSessionStart"
109109
},
110+
{
111+
"name": "(vscode) Run testsuite 'workspace_missing_dirs'",
112+
"type": "extensionHost",
113+
"request": "launch",
114+
"runtimeExecutable": "${execPath}",
115+
"outFiles": [
116+
"${workspaceFolder}/integration/vscode/ada/out/**/*.js",
117+
"!**/node_modules/**"
118+
],
119+
"args": [
120+
"--extensionDevelopmentPath=${workspaceFolder}/integration/vscode/ada",
121+
"--extensionTestsPath=${workspaceFolder}/integration/vscode/ada/out/test/suite/workspace_missing_dirs/index",
122+
"${workspaceFolder}/integration/vscode/ada/test/workspaces/workspace_missing_dirs"
123+
],
124+
// Below we make the executables of node modules visible to the tests.
125+
// In particular, vscode-tmgrammar-snap is used for syntax highlighting
126+
// tests.
127+
"env": {
128+
"MOCHA_GREP": "${input:testPattern}",
129+
// This is necessary to make the "child" vscode inherit the PATH
130+
// variable set in the workspace settings. Without it in some setups
131+
// (e.g. vscode remote) the child vscode does not get visibility
132+
// over the Ada toolchain available in the parent vscode
133+
// environment.
134+
"PATH": "${env:PATH}",
135+
// This is custom env var that we use in
136+
// integration/vscode/ada/test/suite/index.ts to prevent timeouts in
137+
// tests when debugging
138+
"MOCHA_TIMEOUT": "0",
139+
"MOCHA_ALS_UPDATE": "${input:updateTestRefs}"
140+
},
141+
"preLaunchTask": "npm: pretest - integration/vscode/ada",
142+
// Switch to Debug Console to see test results
143+
"internalConsoleOptions": "openOnSessionStart"
144+
},
110145
{
111146
"name": "(npm) Launch all vscode tests with npm",
112147
"type": "node",

integration/vscode/ada/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,11 @@
693693
"title": "Ada: Show GPR Language Server output",
694694
"when": "ADA_PROJECT_CONTEXT"
695695
},
696+
{
697+
"command": "ada.addMissingDirsToWorkspace",
698+
"title": "Ada: Add missing source directories to workspace",
699+
"when": "ADA_PROJECT_CONTEXT"
700+
},
696701
{
697702
"command": "ada.runMainAsk",
698703
"title": "Ada: Build and run project main...",

integration/vscode/ada/src/commands.ts

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { getOrAskForProgram } from './debugConfigProvider';
99
import { adaExtState, mainOutputChannel } from './extension';
1010
import { getProjectFileRelPath } from './helpers';
1111
import { CustomTaskDefinition, getEnclosingSymbol } from './taskProviders';
12+
import { LanguageClient } from 'vscode-languageclient/node';
1213

1314
export function registerCommands(context: vscode.ExtensionContext, clients: ExtensionState) {
1415
context.subscriptions.push(vscode.commands.registerCommand('ada.otherFile', otherFileHandler));
@@ -45,6 +46,24 @@ export function registerCommands(context: vscode.ExtensionContext, clients: Exte
4546
return p;
4647
})
4748
);
49+
50+
context.subscriptions.push(
51+
vscode.commands.registerCommand(
52+
'ada.addMissingDirsToWorkspace',
53+
async (
54+
// eslint-disable-next-line @typescript-eslint/no-inferrable-types
55+
displayPopupWhenMissing: boolean = false,
56+
// eslint-disable-next-line @typescript-eslint/no-inferrable-types
57+
displayPopupOnSuccess: boolean = true
58+
) => {
59+
await checkSrcDirectories(
60+
clients.adaClient,
61+
displayPopupWhenMissing,
62+
displayPopupOnSuccess
63+
);
64+
}
65+
)
66+
);
4867
}
4968
/**
5069
* Add a subprogram box above the subprogram enclosing the cursor's position, if any.
@@ -335,3 +354,110 @@ const otherFileHandler = () => {
335354
],
336355
});
337356
};
357+
358+
/**
359+
*
360+
* Check if we need to add some source directories to the workspace (e.g: when imported
361+
* projects' source directories are not placed under the root project's directory).
362+
* Do nothing if the user did not setup any workspace file.
363+
*
364+
* @param alsClient - the running ALS client
365+
* @param displayPopupWhenMissing - whether or not we should display a yes/no popup
366+
* when missing directories
367+
* @param displayPopupOnSuccess - whether or not we should display a popup to notify
368+
* the user that there is no missing directory
369+
*/
370+
export async function checkSrcDirectories(
371+
alsClient: LanguageClient,
372+
displayPopupWhenMissing = true,
373+
displayPopupOnSuccess = true
374+
) {
375+
type ALSSourceDirDescription = {
376+
name: string;
377+
uri: string;
378+
};
379+
380+
const foldersInSettings = vscode.workspace.getConfiguration().get('folders');
381+
382+
// Don't propose any popup if we multi-root workspace folders are already set
383+
// explicitly in the workspace's settings.
384+
if (foldersInSettings === undefined) {
385+
const sourceDirs: ALSSourceDirDescription[] = (await alsClient.sendRequest(
386+
ExecuteCommandRequest.type,
387+
{
388+
command: 'als-source-dirs',
389+
}
390+
)) as ALSSourceDirDescription[];
391+
392+
const isSubdirectory = (dir: string, parent: string) => {
393+
// Use lower-case on Windows since drives can be specified in VS Code
394+
// either with lower or upper case characters.
395+
if (process.platform == 'win32') {
396+
dir = dir.toLowerCase();
397+
parent = parent.toLowerCase();
398+
}
399+
400+
return dir.startsWith(parent + '/');
401+
};
402+
403+
const workspaceFolders = vscode.workspace.workspaceFolders ?? [];
404+
const workspaceDirsToAdd: { uri: vscode.Uri; name?: string | undefined }[] = [];
405+
406+
for (const source_dir of sourceDirs) {
407+
const sourceDirURI = vscode.Uri.parse(source_dir.uri);
408+
const sourceDirPath = sourceDirURI.path;
409+
410+
// If the source directory is not under one of the workspace folders and
411+
// if it's not already present in the workspace's folders, push
412+
// this source directory to the workspace folders to add later.
413+
if (
414+
!workspaceFolders.some(
415+
(workspaceFolder) =>
416+
workspaceFolder.uri.path == sourceDirPath ||
417+
isSubdirectory(sourceDirPath, workspaceFolder.uri.path)
418+
)
419+
) {
420+
workspaceDirsToAdd.push({
421+
name: source_dir.name,
422+
uri: sourceDirURI,
423+
});
424+
}
425+
}
426+
427+
// If there are some source directories missing in the workspace, ask the user
428+
// to add them in his workspace.
429+
if (workspaceDirsToAdd.length > 0) {
430+
let doAdd = true;
431+
432+
if (displayPopupWhenMissing) {
433+
await vscode.window
434+
.showInformationMessage(
435+
'Some project source directories are not \
436+
listed in your workspace: do you want to add them?',
437+
'Yes',
438+
'No'
439+
)
440+
.then((answer) => {
441+
if (answer !== 'Yes') {
442+
doAdd = false;
443+
}
444+
});
445+
}
446+
447+
if (doAdd) {
448+
vscode.workspace.updateWorkspaceFolders(
449+
vscode.workspace.workspaceFolders
450+
? vscode.workspace.workspaceFolders.length
451+
: 0,
452+
null,
453+
...workspaceDirsToAdd
454+
);
455+
}
456+
} else if (displayPopupOnSuccess) {
457+
void vscode.window.showInformationMessage(
458+
"All the project's source directories are already \
459+
available in the current workspace."
460+
);
461+
}
462+
}
463+
}

integration/vscode/ada/src/extension.ts

Lines changed: 2 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616
-- of the license. --
1717
----------------------------------------------------------------------------*/
1818

19-
import * as process from 'process';
2019
import * as vscode from 'vscode';
2120

2221
import { MESSAGE } from 'triple-beam';
23-
import { ExecuteCommandRequest, LanguageClient, Middleware } from 'vscode-languageclient/node';
22+
import { Middleware } from 'vscode-languageclient/node';
2423
import winston, { format, transports } from 'winston';
2524
import Transport from 'winston-transport';
2625
import { ExtensionState } from './ExtensionState';
@@ -172,7 +171,7 @@ async function activateExtension(context: vscode.ExtensionContext) {
172171
/**
173172
* This can display a dialog to the User so don't wait on the result.
174173
*/
175-
void checkSrcDirectories(adaExtState.adaClient);
174+
void vscode.commands.executeCommand('ada.addMissingDirsToWorkspace', true, false);
176175
}
177176

178177
function setUpLogging(context: vscode.ExtensionContext) {
@@ -254,90 +253,3 @@ function setUpLogging(context: vscode.ExtensionContext) {
254253
export async function deactivate() {
255254
await vscode.commands.executeCommand('setContext', ADA_CONTEXT, undefined);
256255
}
257-
258-
type ALSSourceDirDescription = {
259-
name: string;
260-
uri: string;
261-
};
262-
263-
/**
264-
*
265-
* Check if we need to add some source directories to the workspace (e.g: when imported
266-
* projects' source directories are not placed under the root project's directory).
267-
* Do nothing is the user did not setup any workspace file.
268-
*
269-
*/
270-
async function checkSrcDirectories(alsClient: LanguageClient) {
271-
const foldersInSettings = vscode.workspace.getConfiguration().get('folders') ?? [];
272-
273-
// Don't propose any popup if we multi-root workspace folders are already set
274-
// explicitly in the workspace's settings.
275-
if (foldersInSettings !== undefined) {
276-
const sourceDirs: ALSSourceDirDescription[] = (await alsClient.sendRequest(
277-
ExecuteCommandRequest.type,
278-
{
279-
command: 'als-source-dirs',
280-
}
281-
)) as ALSSourceDirDescription[];
282-
283-
const isSubdirectory = (dir: string, parent: string) => {
284-
// Use lower-case on Windows since drives can be specified in VS Code
285-
// either with lower or upper case characters.
286-
if (process.platform == 'win32') {
287-
dir = dir.toLowerCase();
288-
parent = parent.toLowerCase();
289-
}
290-
291-
return dir.startsWith(parent + '/');
292-
};
293-
294-
const workspaceFolders = vscode.workspace.workspaceFolders ?? [];
295-
const workspaceDirsToAdd: { uri: vscode.Uri; name?: string | undefined }[] = [];
296-
297-
for (const source_dir of sourceDirs) {
298-
const sourceDirURI = vscode.Uri.parse(source_dir.uri);
299-
const sourceDirPath = sourceDirURI.path;
300-
301-
// If the source directory is not under one of the workspace folders and
302-
// if it's not already present in the workspace's folders, push
303-
// this source directory to the workspace folders to add later.
304-
if (
305-
!workspaceFolders.some(
306-
(workspaceFolder) =>
307-
workspaceFolder.uri.path == sourceDirPath ||
308-
isSubdirectory(sourceDirPath, workspaceFolder.uri.path)
309-
)
310-
) {
311-
workspaceDirsToAdd.push({
312-
name: source_dir.name,
313-
uri: sourceDirURI,
314-
});
315-
}
316-
}
317-
318-
// If there are some source directories missing in the workspace, ask the user
319-
// to add them in his workspace.
320-
if (workspaceDirsToAdd.length > 0) {
321-
await vscode.window
322-
.showInformationMessage(
323-
'Some project source directories are not \
324-
listed in your workspace: do you want to add them?',
325-
'Yes',
326-
'No'
327-
)
328-
.then((answer) => {
329-
if (answer === 'Yes') {
330-
for (const workspaceDir of workspaceDirsToAdd) {
331-
vscode.workspace.updateWorkspaceFolders(
332-
vscode.workspace.workspaceFolders
333-
? vscode.workspace.workspaceFolders.length
334-
: 0,
335-
null,
336-
workspaceDir
337-
);
338-
}
339-
}
340-
});
341-
}
342-
}
343-
}

integration/vscode/ada/test/runTest.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ async function main() {
99
// Passed to `--extensionDevelopmentPath`
1010
const extensionDevelopmentPath = path.resolve(__dirname, '../../');
1111

12-
const testsuites = ['general', 'gnattest'];
12+
const testsuites = ['general', 'gnattest', 'workspace_missing_dirs'];
1313

1414
let someTestsuiteFailed = false;
1515

@@ -21,7 +21,7 @@ async function main() {
2121
`out/test/suite/${testsuite}`
2222
);
2323

24-
// The workspace that will be openned in VSCode
24+
// The workspace that will be opened in VSCode
2525
// Passed as an argument
2626
const testWorkspace = path.resolve(
2727
extensionDevelopmentPath,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { runMochaTestsuite } from '../utils';
2+
3+
export function run(): Promise<void> {
4+
return runMochaTestsuite('workspace_missing_dirs', __dirname);
5+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import * as assert from 'assert';
2+
import { suite, test } from 'mocha';
3+
import { activate } from '../utils';
4+
5+
import * as vscode from 'vscode';
6+
7+
suite('Extensions Advanced Test Suite', function () {
8+
// Make sure the extension is activated
9+
this.beforeAll(async () => {
10+
await activate();
11+
});
12+
test('Test Add Missing Source Dirs To Workspace', async () => {
13+
if (vscode.workspace.workspaceFolders !== undefined) {
14+
let folders = vscode.workspace.workspaceFolders;
15+
16+
// We should start with only one workspace folder (the root one)
17+
assert.strictEqual(folders.length, 1);
18+
19+
// Execute the 'ada.addMissingDirsToWorkspace' command, that imports the missing
20+
// source directories into the current workspace if needed
21+
await vscode.commands.executeCommand('ada.addMissingDirsToWorkspace', false);
22+
23+
// Check that we have 3 workspace folders after executing the command
24+
folders = vscode.workspace.workspaceFolders;
25+
assert.strictEqual(folders.length, 3);
26+
} else {
27+
throw new Error('No workspace folder found for the specified URI');
28+
}
29+
});
30+
});
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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- This .gpr file is used to test the command that displays a popup
2+
-- to adds source directories not located under the workspace's root folder.
3+
project Workspace is
4+
for Source_Dirs use (".", "../general/src/", "../gnattest/");
5+
end Workspace;

0 commit comments

Comments
 (0)