Skip to content

Commit 501ffe3

Browse files
authored
Merge pull request #610 from fortran-lang/feat/improve-downloads
feat: uses a vscode.Task for downloading
2 parents f2daba1 + 7aa0939 commit 501ffe3

File tree

6 files changed

+81
-55
lines changed

6 files changed

+81
-55
lines changed

Diff for: CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1616

1717
### Changed
1818

19+
- Changed packaging download to use `vscode.Tasks`
20+
([#608](https://github.com/fortran-lang/vscode-fortran-support/issues/608))
1921
- Renamed the default repository branch from `master` to `main`
2022
([#590](https://github.com/fortran-lang/vscode-fortran-support/issues/590))
2123
- Changed the way messages are logged and added `log` syntax highlighting

Diff for: README.md

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
[![Downloads](https://vsmarketplacebadge.apphb.com/downloads-short/fortran-lang.linter-gfortran.svg)](https://marketplace.visualstudio.com/items?itemName=fortran-lang.linter-gfortran)
88
[![Installs](https://vsmarketplacebadge.apphb.com/installs-short/fortran-lang.linter-gfortran.svg)](https://marketplace.visualstudio.com/items?itemName=fortran-lang.linter-gfortran)
9-
[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
109
[![GitHub Actions](https://github.com/fortran-lang/vscode-fortran-support/actions/workflows/main.yaml/badge.svg)](https://github.com/fortran-lang/vscode-fortran-support/actions)
1110
[![VS Marketplace](https://vsmarketplacebadge.apphb.com/version-short/fortran-lang.linter-gfortran.svg)](https://marketplace.visualstudio.com/items?itemName=fortran-lang.linter-gfortran)
1211
[![MIT License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://raw.githubusercontent.com/fortran-lang/vscode-fortran-support/master/LICENSE)

Diff for: src/features/formatting-provider.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ export class FortranFormattingProvider implements vscode.DocumentFormattingEditP
4646
private async doFormatFprettify(document: vscode.TextDocument): Promise<vscode.TextEdit[]> {
4747
// fprettify can only do FortranFreeFrom
4848
if (document.languageId !== 'FortranFreeForm') {
49-
this.logger.error(`[format] fprettify can only format FortranFreeForm, change
50-
to findent for FortranFixedForm formatting`);
49+
this.logger.error(
50+
`[format] fprettify can only format FortranFreeForm, change to findent for FortranFixedForm formatting`
51+
);
5152
return undefined;
5253
}
5354

@@ -58,7 +59,7 @@ export class FortranFormattingProvider implements vscode.DocumentFormattingEditP
5859
if (!which.sync(formatter, { nothrow: true })) {
5960
this.logger.warn(`[format] ${formatterName} not found. Attempting to install now.`);
6061
const msg = `Installing ${formatterName} through pip with --user option`;
61-
promptForMissingTool(formatterName, msg, 'Python', ['Install'], this.logger);
62+
promptForMissingTool(formatterName, msg, 'Python', ['Install']);
6263
}
6364

6465
const args: string[] = ['--stdout', ...this.getFormatterArgs()];
@@ -83,7 +84,7 @@ export class FortranFormattingProvider implements vscode.DocumentFormattingEditP
8384
if (!which.sync(formatter, { nothrow: true })) {
8485
this.logger.warn(`[format] ${formatterName} not found! Attempting to install now.`);
8586
const msg = `Installing ${formatterName} through pip with --user option`;
86-
promptForMissingTool(formatterName, msg, 'Python', ['Install'], this.logger);
87+
promptForMissingTool(formatterName, msg, 'Python', ['Install']);
8788
}
8889

8990
const args: string[] = this.getFormatterArgs();

Diff for: src/lib/tools.ts

+41-37
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import * as os from 'os';
22
import * as vscode from 'vscode';
33
import * as assert from 'assert';
44
import * as cp from 'child_process';
5-
import { Logger } from '../services/logging';
65
import { isString, isArrayOfString } from './helper';
76

87
export const LS_NAME = 'fortls';
@@ -98,36 +97,31 @@ export function getOuterMostWorkspaceFolder(
9897
* @param msg message for installing said package
9998
* @param toolType type of tool, supports `Python` (through pip) and 'VSExt'
10099
* @param opts options for the prompt. "Install" and "Don't Show Again" are coded
101-
* @param logger log channel output
102100
* @param action a void function for an action to perform when "Don't Show Again" is pressed
103101
*/
104102
export async function promptForMissingTool(
105103
tool: string,
106104
msg: string,
107105
toolType: string,
108106
opts: string[],
109-
logger?: Logger,
110107
action?: () => void
111108
) {
112109
const items = ['Install'];
113-
return vscode.window.showInformationMessage(msg, ...opts).then(selected => {
110+
return vscode.window.showInformationMessage(msg, ...opts).then(async selected => {
114111
if (selected === 'Install') {
115-
switch (toolType) {
116-
case 'Python':
117-
installPythonTool(tool, logger);
118-
break;
119-
120-
case 'VSExt':
121-
logger.info(`Installing VS Marketplace Extension with id: ${tool}`);
122-
vscode.commands.executeCommand('extension.open', tool);
123-
vscode.commands.executeCommand('workbench.extensions.installExtension', tool);
124-
logger.info(`Extension ${tool} successfully installed`);
125-
break;
126-
127-
default:
128-
logger.error(`Failed to install tool: ${tool}`);
129-
vscode.window.showErrorMessage(`Failed to install tool: ${tool}`);
130-
break;
112+
if (toolType === 'Python') {
113+
try {
114+
const inst_msg = await pipInstall(tool);
115+
vscode.window.showInformationMessage(inst_msg);
116+
} catch (error) {
117+
vscode.window.showErrorMessage(error);
118+
}
119+
} else if (toolType === 'VSExt') {
120+
// Installing VS Marketplace Extension
121+
vscode.commands.executeCommand('extension.open', tool);
122+
vscode.commands.executeCommand('workbench.extensions.installExtension', tool);
123+
} else {
124+
vscode.window.showErrorMessage(`Failed to install tool: ${tool}`);
131125
}
132126
} else if (selected === "Don't Show Again") {
133127
action();
@@ -140,25 +134,35 @@ export async function promptForMissingTool(
140134
* Does not explicitly check if `pip` is installed.
141135
*
142136
* @param pyPackage name of python package in PyPi
143-
* @param logger `optional` logging channel for output
144137
*/
145-
export function installPythonTool(pyPackage: string, logger?: Logger) {
146-
const installProcess = cp.spawnSync(
147-
'pip',
148-
'install --user --upgrade '.concat(pyPackage).split(' ')
138+
export async function pipInstall(pyPackage: string): Promise<string> {
139+
const py = 'python3'; // Fetches the top-most python in the Shell
140+
const args = ['-m', 'pip', 'install', '--user', '--upgrade', pyPackage];
141+
return await shellTask(py, args, `pip: ${pyPackage}`);
142+
}
143+
144+
export async function shellTask(command: string, args: string[], name: string): Promise<string> {
145+
const task = new vscode.Task(
146+
{ type: 'shell' },
147+
vscode.TaskScope.Workspace,
148+
name,
149+
'Modern Fortran',
150+
new vscode.ShellExecution(command, args)
149151
);
150-
if (installProcess.error) {
151-
logger.error(
152-
`Python package ${pyPackage} failed to install with code: ${installProcess.error}`
153-
);
154-
}
155-
if (installProcess.stdout) {
156-
const sep = '-'.repeat(80);
157-
logger.info(
158-
`pip install --user --upgrade ${pyPackage}:\n${sep}\n${installProcess.stdout}${sep}`
159-
);
160-
logger.info(`pip install was successful`);
161-
}
152+
// Temporay fix to https://github.com/microsoft/vscode/issues/157756
153+
(<vscode.Task>task).definition = { type: 'shell', command: command };
154+
const execution = await vscode.tasks.executeTask(task);
155+
return await new Promise<string>((resolve, reject) => {
156+
const disposable = vscode.tasks.onDidEndTaskProcess(e => {
157+
if (e.execution === execution) {
158+
disposable.dispose();
159+
if (e.exitCode !== 0) {
160+
reject(`ERROR: ${e.execution.task.name} failed with code ${e.exitCode}`);
161+
}
162+
resolve(`${name}: shell task completed successfully.`);
163+
}
164+
});
165+
});
162166
}
163167

164168
/**

Diff for: src/lsp/client.ts

+14-13
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
LS_NAME,
1212
isFortran,
1313
getOuterMostWorkspaceFolder,
14+
pipInstall,
1415
} from '../lib/tools';
1516
import { Logger } from '../services/logging';
1617
import { RestartLS } from '../features/commands';
@@ -310,26 +311,26 @@ export class FortlsClient {
310311
const msg = `It is highly recommended to use the fortls to enable IDE features like hover, peeking, GoTos and many more.
311312
For a full list of features the language server adds see: https://github.com/gnikit/fortls`;
312313
return new Promise<boolean>(resolve => {
313-
let fortlsDisabled = false;
314314
if (results.error) {
315315
const selection = window.showInformationMessage(msg, 'Install', 'Disable');
316-
selection.then(opt => {
316+
selection.then(async opt => {
317317
if (opt === 'Install') {
318-
const install = spawnSync('pip', ['install', '--user', '--upgrade', LS_NAME]);
319-
if (install.error) {
320-
this.logger.error(`[lsp.client] Unable to install fortls:`, install.error);
321-
window.showErrorMessage('Had trouble installing fortls, please install manually');
322-
fortlsDisabled = true;
323-
}
324-
if (install.stdout) {
325-
this.logger.info(`[lsp.client] ${install.stdout.toString()}`);
326-
fortlsDisabled = false;
318+
try {
319+
this.logger.info(`[lsp.client] Downloading ${LS_NAME}`);
320+
const msg = await pipInstall(LS_NAME);
321+
window.showInformationMessage(msg);
322+
this.logger.info(`[lsp.client] ${LS_NAME} installed`);
323+
resolve(false);
324+
} catch (error) {
325+
this.logger.error(`[lsp.client] Error installing ${LS_NAME}: ${error}`);
326+
window.showErrorMessage(error);
327+
resolve(true);
327328
}
328329
} else if (opt == 'Disable') {
329330
config.update('fortls.disabled', true);
330-
fortlsDisabled = true;
331+
this.logger.info(`[lsp.client] ${LS_NAME} disabled in settings`);
332+
resolve(true);
331333
}
332-
resolve(fortlsDisabled);
333334
});
334335
} else {
335336
resolve(false);

Diff for: test/tools.test.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as assert from 'assert';
2+
import { shellTask } from '../src/lib/tools';
3+
4+
suite('Tools tests', () => {
5+
test('shellTask returns correct output', async () => {
6+
const name = 'pip: fortls';
7+
const output = await shellTask(
8+
'python3',
9+
['-m', 'pip', 'install', '--upgrade', '--force', 'fortls'],
10+
name
11+
);
12+
assert.strictEqual(output, `${name}: shell task completed successfully.`);
13+
});
14+
15+
test('shellTask returns rejected promise', async () => {
16+
const name = 'pip: fortls';
17+
assert.rejects(shellTask('python3', ['-m', 'pip', 'install', 'fortls2'], name));
18+
});
19+
});

0 commit comments

Comments
 (0)