Skip to content

Commit 555ef70

Browse files
committed
Merge branch 'topic/Q817-007' into 'master'
Q817-007 Add Replace Type tool initial implementation See merge request eng/ide/ada_language_server!1095
2 parents c039ff3 + 6c5fc28 commit 555ef70

17 files changed

+1047
-150
lines changed

integration/vscode/ada/src/alsClientFeatures.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*----------------------------------------------------------------------------
22
-- Language Server Protocol --
33
-- --
4-
-- Copyright (C) 2021-2022, AdaCore --
4+
-- Copyright (C) 2021-2023, AdaCore --
55
-- --
66
-- This is free software; you can redistribute it and/or modify it under --
77
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -47,22 +47,20 @@ export class ALSClientFeatures implements StaticFeature {
4747
* that this client can provide user inputs
4848
*/
4949
fillClientCapabilities(capabilities: ClientCapabilities): void {
50+
const advanced_refactorings = [
51+
'add_parameter',
52+
'change_parameters_type',
53+
'change_parameters_default_value',
54+
'replace_type',
55+
];
5056
if (capabilities.experimental === undefined) {
5157
capabilities.experimental = {
52-
advanced_refactorings: [
53-
'add_parameter',
54-
'change_parameters_type',
55-
'change_parameters_default_value',
56-
],
58+
advanced_refactorings: advanced_refactorings,
5759
};
5860
} else {
5961
(
6062
capabilities.experimental as { advanced_refactorings: string[] }
61-
).advanced_refactorings = [
62-
'add_parameter',
63-
'change_parameters_type',
64-
'change_parameters_default_value',
65-
];
63+
).advanced_refactorings = advanced_refactorings;
6664
}
6765
}
6866

integration/vscode/ada/src/alsExecuteCommand.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*----------------------------------------------------------------------------
22
-- Language Server Protocol --
33
-- --
4-
-- Copyright (C) 2021-2022, AdaCore --
4+
-- Copyright (C) 2021-2023, AdaCore --
55
-- --
66
-- This is free software; you can redistribute it and/or modify it under --
77
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -35,6 +35,10 @@ import {
3535
alsChangeParametersDefaultValueCommandExecutor,
3636
ChangeParametersDefaultValueCommandArgs,
3737
} from './refactoring/alsChangeParametersDefaultValueCommand';
38+
import {
39+
alsReplaceTypeCommandExecutor,
40+
ReplaceTypeCommandArgs,
41+
} from './refactoring/alsReplaceTypeCommand';
3842

3943
/**
4044
* Type alias for a function that intercepts a command and executes it by return a promise that
@@ -80,6 +84,12 @@ export const alsCommandExecutor = (client: LanguageClient): CommandExecutor => {
8084
args[0] as ChangeParametersDefaultValueCommandArgs
8185
);
8286
if (!proceedWithExecution) return Promise.resolve(undefined);
87+
} else if (command === 'als-refactor-replace-type') {
88+
const proceedWithExecution = await alsReplaceTypeCommandExecutor(
89+
client,
90+
args[0] as ReplaceTypeCommandArgs
91+
);
92+
if (!proceedWithExecution) return Promise.resolve(undefined);
8393
}
8494
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
8595
return next(command, args);

integration/vscode/ada/src/alsProtocolExtensions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*----------------------------------------------------------------------------
22
-- Language Server Protocol --
33
-- --
4-
-- Copyright (C) 2021-2022, AdaCore --
4+
-- Copyright (C) 2021-2023, AdaCore --
55
-- --
66
-- This is free software; you can redistribute it and/or modify it under --
77
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -32,6 +32,7 @@ import { LanguageClient } from 'vscode-languageclient/node';
3232
export enum AdaGrammarRule {
3333
Defining_Id_Rule = 'Defining_Id_Rule',
3434
Defining_Id_List_Rule = 'Defining_Id_List_Rule',
35+
Defining_Name_Rule = 'Defining_Name_Rule',
3536
Param_Spec_Rule = 'Param_Spec_Rule',
3637
Anonymous_Type_Rule = 'Anonymous_Type_Rule',
3738
Subtype_Indication_Rule = 'Subtype_Indication_Rule',

integration/vscode/ada/src/cleanTaskProvider.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*----------------------------------------------------------------------------
22
-- Language Server Protocol --
33
-- --
4-
-- Copyright (C) 2018-2021, AdaCore --
4+
-- Copyright (C) 2018-2023, AdaCore --
55
-- --
66
-- This is free software; you can redistribute it and/or modify it under --
77
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -17,7 +17,6 @@
1717

1818
import * as vscode from 'vscode';
1919

20-
2120
export default class cleanTaskProvider implements vscode.TaskProvider<vscode.Task> {
2221
public static cleanTaskType = 'gprclean';
2322
cleanTasks: vscode.Task[] | undefined;

integration/vscode/ada/src/extension.ts

Lines changed: 105 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*----------------------------------------------------------------------------
22
-- Language Server Protocol --
33
-- --
4-
-- Copyright (C) 2018-2021, AdaCore --
4+
-- Copyright (C) 2018-2023, AdaCore --
55
-- --
66
-- This is free software; you can redistribute it and/or modify it under --
77
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -22,7 +22,6 @@ import {
2222
LanguageClientOptions,
2323
Middleware,
2424
ServerOptions,
25-
ExecutableOptions
2625
} from 'vscode-languageclient/node';
2726
import { platform } from 'os';
2827
import * as process from 'process';
@@ -32,7 +31,6 @@ import gnatproveTaskProvider from './gnatproveTaskProvider';
3231
import { getSubprogramSymbol } from './gnatproveTaskProvider';
3332
import { alsCommandExecutor } from './alsExecuteCommand';
3433
import { ALSClientFeatures } from './alsClientFeatures';
35-
import { string } from 'fp-ts';
3634

3735
let alsTaskProvider: vscode.Disposable[] = [
3836
vscode.tasks.registerTaskProvider(GPRTaskProvider.gprBuildType, new GPRTaskProvider()),
@@ -47,45 +45,55 @@ let alsTaskProvider: vscode.Disposable[] = [
4745
/**
4846
* Add a subprogram box above the subprogram enclosing the cursor's position, if any.
4947
*
50-
* @example:
48+
* @example
5149
*
5250
* -------
5351
* - Foo -
5452
* -------
5553
*
5654
* procedure Foo is
5755
*/
58-
function addSupbrogramBox() {
56+
async function addSupbrogramBox() {
5957
const activeEditor = vscode.window.activeTextEditor;
6058

61-
getSubprogramSymbol(activeEditor)
62-
.then(symbol => {
63-
if (symbol !== null) {
64-
const name: string = symbol.name ?? ""
65-
const insertPos = new vscode.Position(symbol.range.start.line, 0);
66-
const indentationRange = new vscode.Range(insertPos, symbol.range.start)
67-
const indentation: string = activeEditor?.document.getText(indentationRange) ?? ""
68-
const eol: string = activeEditor?.document.eol == vscode.EndOfLine.CRLF ? "\r\n" : "\n";
59+
await getSubprogramSymbol(activeEditor).then(async (symbol) => {
60+
if (symbol !== null) {
61+
const name: string = symbol.name ?? '';
62+
const insertPos = new vscode.Position(symbol.range.start.line, 0);
63+
const indentationRange = new vscode.Range(insertPos, symbol.range.start);
64+
const indentation: string = activeEditor?.document.getText(indentationRange) ?? '';
65+
const eol: string = activeEditor?.document.eol == vscode.EndOfLine.CRLF ? '\r\n' : '\n';
6966

70-
// Generate the subprogram box after retrieving the indentation of the line of
71-
// the subprogram's body declaration.
72-
let text: string = indentation + "---" + '-'.repeat(name.length) + "---" + eol
73-
+ indentation + "-- " + name + " --" + eol
74-
+ indentation + "---" + '-'.repeat(name.length) + "---" + eol
75-
+ eol;
67+
// Generate the subprogram box after retrieving the indentation of the line of
68+
// the subprogram's body declaration.
69+
const text: string =
70+
indentation +
71+
'---' +
72+
'-'.repeat(name.length) +
73+
'---' +
74+
eol +
75+
indentation +
76+
'-- ' +
77+
name +
78+
' --' +
79+
eol +
80+
indentation +
81+
'---' +
82+
'-'.repeat(name.length) +
83+
'---' +
84+
eol +
85+
eol;
7686

77-
activeEditor?.document.eol.toString
78-
if (activeEditor) {
79-
80-
activeEditor.edit(editBuilder => {
81-
editBuilder.insert(insertPos, text);
82-
});
83-
}
87+
if (activeEditor) {
88+
await activeEditor.edit((editBuilder) => {
89+
editBuilder.insert(insertPos, text);
90+
});
8491
}
85-
})
92+
}
93+
});
8694
}
8795

88-
export function activate(context: vscode.ExtensionContext): void {
96+
export async function activate(context: vscode.ExtensionContext): Promise<void> {
8997
function createClient(id: string, name: string, extra: string[], pattern: string) {
9098
let serverModule = context.asAbsolutePath(process.platform + '/ada_language_server');
9199
if (process.env.ALS) serverModule = process.env.ALS;
@@ -97,28 +105,32 @@ export function activate(context: vscode.ExtensionContext): void {
97105
// Retrieve the user's custom environment variables if specified in their
98106
// settings/workspace: we'll then launch any child process with this custom
99107
// environment
100-
var user_platform = platform();
101-
var env_config_name: string = "terminal.integrated.env.linux";
108+
const user_platform = platform();
109+
let env_config_name = 'terminal.integrated.env.linux';
102110

103111
switch (user_platform) {
104-
case 'darwin': env_config_name = "terminal.integrated.env.osx"
112+
case 'darwin':
113+
env_config_name = 'terminal.integrated.env.osx';
105114
break;
106-
case 'win32': env_config_name = "terminal.integrated.env.windows";
115+
case 'win32':
116+
env_config_name = 'terminal.integrated.env.windows';
107117
break;
108-
default: env_config_name = "terminal.integrated.env.linux";
118+
default:
119+
env_config_name = 'terminal.integrated.env.linux';
109120
}
110121

111-
const custom_env = vscode.workspace.getConfiguration().get(
112-
env_config_name) ?? Object.create(null)
122+
const custom_env = vscode.workspace.getConfiguration().get<[string]>(env_config_name);
113123

114-
for (let var_name in custom_env) {
115-
process.env[var_name] = custom_env[var_name];
124+
if (custom_env) {
125+
for (const var_name in custom_env) {
126+
process.env[var_name] = custom_env[var_name];
127+
}
116128
}
117129

118130
// Options to control the server
119131
const serverOptions: ServerOptions = {
120132
run: { command: serverModule, args: extra },
121-
debug: { command: serverModule, args: extra }
133+
debug: { command: serverModule, args: extra },
122134
};
123135

124136
// Options to control the language client
@@ -193,63 +205,82 @@ export function activate(context: vscode.ExtensionContext): void {
193205

194206
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(configChanged));
195207
context.subscriptions.push(vscode.commands.registerCommand('ada.otherFile', otherFileHandler));
196-
context.subscriptions.push(vscode.commands.registerCommand('ada.subprogramBox', addSupbrogramBox));
208+
context.subscriptions.push(
209+
vscode.commands.registerCommand('ada.subprogramBox', addSupbrogramBox)
210+
);
211+
212+
type ALSSourceDirDescription = {
213+
name: string;
214+
uri: string;
215+
};
197216

198-
// Check if we need to add some source directories to the workspace (e.g: when imported projects'
199-
// source directories are not placed under the root project's directory).
217+
// Check if we need to add some source directories to the workspace (e.g: when imported
218+
// projects' source directories are not placed under the root project's directory).
200219
// Do nothing is the user did not setup any workspace file.
201220
if (vscode.workspace.workspaceFile !== undefined) {
202-
client.onReady().then(() => {
203-
client.sendRequest("workspace/alsSourceDirs").then(
204-
data => {
205-
const source_dirs = JSON.parse(JSON.stringify(data));
206-
const workspace_folders = vscode.workspace.workspaceFolders ?? []
207-
let workspace_dirs_to_add: { uri: vscode.Uri, name?: string | undefined }[] = []
221+
await client.onReady().then(async () => {
222+
await client
223+
.sendRequest<[ALSSourceDirDescription]>('workspace/alsSourceDirs')
224+
.then(async (source_dirs) => {
225+
const workspace_folders = vscode.workspace.workspaceFolders ?? [];
226+
const workspace_dirs_to_add: { uri: vscode.Uri; name?: string | undefined }[] =
227+
[];
208228

209-
for (var source_dir of source_dirs) {
210-
const source_dir_uri = vscode.Uri.parse(source_dir.uri)
211-
let source_dir_path = source_dir_uri.path
212-
let workspace_folder_path = workspace_folders[0].uri.path
229+
for (const source_dir of source_dirs) {
230+
const source_dir_uri = vscode.Uri.parse(source_dir.uri);
231+
const source_dir_path = source_dir_uri.path;
213232

214-
function is_subdirectory(dir: string, parent: string) {
215-
// Use lower-case on Windows since drives can be specified in VS Code either
216-
// with lower or upper case characters.
217-
if (process.platform == "win32") {
233+
const is_subdirectory = (dir: string, parent: string) => {
234+
// Use lower-case on Windows since drives can be specified in VS Code
235+
// either with lower or upper case characters.
236+
if (process.platform == 'win32') {
218237
dir = dir.toLowerCase();
219238
parent = parent.toLowerCase();
220239
}
221240

222241
return dir.startsWith(parent + '/');
242+
};
223243

224-
}
225-
226-
// If the source directory is not under one of the workspace folders, push this
227-
// source directory to the workspace folders to add later.
228-
if (!workspace_folders.some(workspace_folder =>
229-
is_subdirectory(source_dir_path, workspace_folder.uri.path))) {
230-
workspace_dirs_to_add.push({ name: source_dir.name, uri: source_dir_uri });
244+
// If the source directory is not under one of the workspace folders, push
245+
// this source directory to the workspace folders to add later.
246+
if (
247+
!workspace_folders.some((workspace_folder) =>
248+
is_subdirectory(source_dir_path, workspace_folder.uri.path)
249+
)
250+
) {
251+
workspace_dirs_to_add.push({
252+
name: source_dir.name,
253+
uri: source_dir_uri,
254+
});
231255
}
232256
}
233257

234258
// If there are some source directories missing in the workspace, ask the user
235259
// to add them in his workspace.
236260
if (workspace_dirs_to_add.length > 0) {
237-
vscode.window
238-
.showInformationMessage("Some project source directories are not "
239-
+ "listed in your workspace: do you want to add them?", "Yes", "No")
240-
.then(answer => {
241-
if (answer === "Yes") {
242-
for (var workspace_dir of workspace_dirs_to_add) {
261+
await vscode.window
262+
.showInformationMessage(
263+
'Some project source directories are not ' +
264+
'listed in your workspace: do you want to add them?',
265+
'Yes',
266+
'No'
267+
)
268+
.then((answer) => {
269+
if (answer === 'Yes') {
270+
for (const workspace_dir of workspace_dirs_to_add) {
243271
vscode.workspace.updateWorkspaceFolders(
244-
vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders.length : 0, null,
245-
workspace_dir);
272+
vscode.workspace.workspaceFolders
273+
? vscode.workspace.workspaceFolders.length
274+
: 0,
275+
null,
276+
workspace_dir
277+
);
246278
}
247279
}
248-
})
280+
});
249281
}
250-
}
251-
)
252-
})
282+
});
283+
});
253284
}
254285
}
255286

0 commit comments

Comments
 (0)