Skip to content

Commit 5788da7

Browse files
committed
feat: local path resolution
Fixes #667
1 parent f737832 commit 5788da7

File tree

4 files changed

+36
-5
lines changed

4 files changed

+36
-5
lines changed

CHANGELOG.md

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

1010
### Added
1111

12+
- Added local path resolution for `fortls`, `findent` and `fprettify` executables
13+
([#667](https://github.com/fortran-lang/vscode-fortran-support/issues/667))
1214
- Added support for variable resolution in `fortls`
1315
([#664](https://github.com/fortran-lang/vscode-fortran-support/issues/664))
1416
- Added Run and Debug buttons for single Fortran files based on linter settings

src/features/formatting-provider.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
promptForMissingTool,
1414
getWholeFileRange,
1515
spawnAsPromise,
16+
pathRelToAbs,
1617
} from '../lib/tools';
1718

1819
export class FortranFormattingProvider implements vscode.DocumentFormattingEditProvider {
@@ -53,7 +54,8 @@ export class FortranFormattingProvider implements vscode.DocumentFormattingEditP
5354
}
5455

5556
const formatterName = process.platform !== 'win32' ? 'fprettify' : 'fprettify.exe';
56-
const formatterPath: string = this.getFormatterPath();
57+
const formatterPath: string =
58+
this.formatterPath === '' ? '' : pathRelToAbs(this.formatterPath, document.uri);
5759
const formatter: string = path.join(formatterPath, formatterName);
5860
// If no formatter is detected try and install it
5961
if (!which.sync(formatter, { nothrow: true })) {
@@ -78,7 +80,8 @@ export class FortranFormattingProvider implements vscode.DocumentFormattingEditP
7880
*/
7981
private async doFormatFindent(document: vscode.TextDocument): Promise<vscode.TextEdit[]> {
8082
const formatterName = process.platform !== 'win32' ? 'findent' : 'findent.exe';
81-
const formatterPath: string = this.getFormatterPath();
83+
const formatterPath: string =
84+
this.formatterPath === '' ? '' : pathRelToAbs(this.formatterPath, document.uri);
8285
const formatter: string = path.join(formatterPath, formatterName);
8386
// If no formatter is detected try and install it
8487
if (!which.sync(formatter, { nothrow: true })) {
@@ -128,7 +131,7 @@ export class FortranFormattingProvider implements vscode.DocumentFormattingEditP
128131
*
129132
* @returns {string} path of formatter
130133
*/
131-
private getFormatterPath(): string {
134+
private get formatterPath(): string {
132135
const formatterPath: string = this.workspace.get('formatting.path', '');
133136
if (formatterPath !== '') {
134137
this.logger.info(`[format] Formatter located in: ${formatterPath}`);

src/lib/tools.ts

+17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as os from 'os';
2+
import * as path from 'path';
23
import * as vscode from 'vscode';
34
import * as assert from 'assert';
45
import * as cp from 'child_process';
@@ -262,6 +263,22 @@ export function resolveVariables(
262263
// return new Promise<string>((resolve) => { resolve(ret) });
263264
}
264265

266+
/**
267+
* Resolves a path relative to the workspace folder, an optional `uri`
268+
* can be provided to help retrieve the correct workspace folder when working
269+
* with multi-root workspaces, else the first workspace folder is used.
270+
*
271+
* @param relPath relative path to resolve against the workspace folder
272+
* @param uri optional uri of a file/folder within the workspace folder
273+
* usefull when using multiroot workspaces to pick the right workspace root
274+
* @returns absolute path relative to the workspace root
275+
*/
276+
export function pathRelToAbs(relPath: string, uri: vscode.Uri): string | undefined {
277+
const root = getOuterMostWorkspaceFolder(vscode.workspace.getWorkspaceFolder(uri));
278+
if (root === undefined) return undefined;
279+
return path.join(root.uri.fsPath, relPath);
280+
}
281+
265282
export function getWholeFileRange(document: vscode.TextDocument): vscode.Range {
266283
return new vscode.Range(0, 0, document.lineCount, 0);
267284
}

src/lsp/client.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
getOuterMostWorkspaceFolder,
1414
pipInstall,
1515
resolveVariables,
16+
pathRelToAbs,
1617
} from '../lib/tools';
1718
import { Logger } from '../services/logging';
1819
import { RestartLS } from '../features/commands';
@@ -84,7 +85,8 @@ export class FortlsClient {
8485

8586
const args: string[] = await this.fortlsArguments();
8687
const fortlsPath = workspace.getConfiguration(EXTENSION_ID).get<string>('fortls.path');
87-
const executablePath = resolveVariables(fortlsPath);
88+
let executablePath = resolveVariables(fortlsPath);
89+
if (fortlsPath !== 'fortls') executablePath = pathRelToAbs(fortlsPath, document.uri);
8890

8991
// Detect language server version and verify selected options
9092
this.version = this.getLSVersion(executablePath, args);
@@ -306,7 +308,14 @@ export class FortlsClient {
306308
*/
307309
private async fortlsDownload(): Promise<boolean> {
308310
const config = workspace.getConfiguration(EXTENSION_ID);
309-
const ls = resolveVariables(config.get<string>('fortls.path'));
311+
let ls = resolveVariables(config.get<string>('fortls.path'));
312+
// The path can be resolved as a relative path if it's part of a workspace
313+
// AND it does not have the default value `fortls` or is an absolute path
314+
if (workspace.workspaceFolders == undefined && ls !== 'fortls' && !path.isAbsolute(ls)) {
315+
const root = workspace.workspaceFolders[0];
316+
this.logger.debug(`[lsp.client] Assuming relative fortls path is to ${root.uri.fsPath}`);
317+
ls = pathRelToAbs(ls, root.uri);
318+
}
310319

311320
// Check for version, if this fails fortls provided is invalid
312321
const results = spawnSync(ls, ['--version']);

0 commit comments

Comments
 (0)