Skip to content

Update #302

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- name: Installing Extension
run: yarn install
run: npm ci
- name: Compile
run: yarn compile
run: npm run compile
- name: Linting
run: yarn lint
run: npm run lint
- name: Test Syntax Highlighting
run: yarn test:grammar
run: npm run test:grammar
- name: Test Unittests
uses: GabrielBB/xvfb-action@v1
with:
run: yarn test
run: npm test
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ First of all, this is a Visual Studio Code extension that uses TypeScript and to
1. Fork the repo
2. Clone your fork
3. Create a branch
4. Run `yarn install`
5. To test the extension run `yarn test:grammar && yarn test`
4. Run `npm install`
5. To test the extension run `npm run test:grammar && npm test`
39 changes: 6 additions & 33 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ import FortranHoverProvider from './features/hover-provider';
import { FortranCompletionProvider } from './features/completion-provider';
import { FortranDocumentSymbolProvider } from './features/document-symbol-provider';

import { FortranLangServer } from './lang-server';
import { FORTRAN_DOCUMENT_SELECTOR, EXTENSION_ID, promptForMissingTool } from './lib/helper';
import { LoggingService } from './services/logging-service';
import * as pkg from '../package.json';
import { LANG_SERVER_TOOL_ID } from './lib/tools';
import { FortranFormattingProvider } from './features/formatting-provider';
import { EXTENSION_ID, FortranDocumentSelector, promptForMissingTool } from './lib/tools';

// Make it global to catch errors when activation fails
const loggingService = new LoggingService();
Expand All @@ -26,15 +25,15 @@ export function activate(context: vscode.ExtensionContext) {
if (extensionConfig.get('linterEnabled', true)) {
const linter = new FortranLintingProvider(loggingService);
linter.activate(context.subscriptions);
vscode.languages.registerCodeActionsProvider(FORTRAN_DOCUMENT_SELECTOR, linter);
vscode.languages.registerCodeActionsProvider(FortranDocumentSelector(), linter);
loggingService.logInfo('Linter is enabled');
} else {
loggingService.logInfo('Linter is not enabled');
}

if (extensionConfig.get('formatter') !== 'Disabled') {
const disposable: vscode.Disposable = vscode.languages.registerDocumentFormattingEditProvider(
FORTRAN_DOCUMENT_SELECTOR,
FortranDocumentSelector(),
new FortranFormattingProvider(loggingService)
);
context.subscriptions.push(disposable);
Expand All @@ -45,22 +44,22 @@ export function activate(context: vscode.ExtensionContext) {

if (extensionConfig.get('provideCompletion', true)) {
const completionProvider = new FortranCompletionProvider(loggingService);
vscode.languages.registerCompletionItemProvider(FORTRAN_DOCUMENT_SELECTOR, completionProvider);
vscode.languages.registerCompletionItemProvider(FortranDocumentSelector(), completionProvider);
} else {
loggingService.logInfo('Completion Provider is not enabled');
}

if (extensionConfig.get('provideHover', true)) {
const hoverProvider = new FortranHoverProvider(loggingService);
vscode.languages.registerHoverProvider(FORTRAN_DOCUMENT_SELECTOR, hoverProvider);
vscode.languages.registerHoverProvider(FortranDocumentSelector(), hoverProvider);
loggingService.logInfo('Hover Provider is enabled');
} else {
loggingService.logInfo('Hover Provider is not enabled');
}

if (extensionConfig.get('provideSymbols', true)) {
const symbolProvider = new FortranDocumentSymbolProvider();
vscode.languages.registerDocumentSymbolProvider(FORTRAN_DOCUMENT_SELECTOR, symbolProvider);
vscode.languages.registerDocumentSymbolProvider(FortranDocumentSelector(), symbolProvider);
loggingService.logInfo('Symbol Provider is enabled');
} else {
loggingService.logInfo('Symbol Provider is not enabled');
Expand All @@ -74,30 +73,4 @@ export function activate(context: vscode.ExtensionContext) {
https://github.com/hansec/fortran-language-server`;
promptForMissingTool(LANG_SERVER_TOOL_ID, msg, 'Python', loggingService);
}

// Check that Fortran Intellisense is installed and if not prompt to install
if (!vscode.extensions.getExtension('hansec.fortran-ls')) {
const msg = `It is highly recommended to install the Fortran IntelliSense
extension. The extension is used to interface with the
fortran-language-server.
For a full list of features provided by the extension see:
https://github.com/hansec/vscode-fortran-ls`;
promptForMissingTool('hansec.fortran-ls', msg, 'VSExt', loggingService);
}

// Our interface with `fortls` has been disabled in favour of the @hansec's
// VS Code extension Fortran IntelliSense
const useInternalFLInterface = false;
if (useInternalFLInterface) {
const langServer = new FortranLangServer(context, extensionConfig);
langServer.start();
langServer.onReady().then(() => {
const capabilities = langServer.getCapabilities();
if (!capabilities) {
return vscode.window.showErrorMessage(
'The language server is not able to serve any features at the moment.'
);
}
});
}
}
2 changes: 1 addition & 1 deletion src/features/completion-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as vscode from 'vscode';
import { isPositionInString, intrinsics, FORTRAN_KEYWORDS } from '../lib/helper';
import { getDeclaredFunctions } from '../lib/functions';

import { EXTENSION_ID } from '../lib/helper';
import { EXTENSION_ID } from '../lib/tools';
import { LoggingService } from '../services/logging-service';

class CaseCoverter {
Expand Down
3 changes: 1 addition & 2 deletions src/features/formatting-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import * as which from 'which';
import * as vscode from 'vscode';
import * as cp from 'child_process';

import { FORMATTERS } from '../lib/tools';
import { LoggingService } from '../services/logging-service';
import { EXTENSION_ID, promptForMissingTool } from '../lib/helper';
import { FORMATTERS, EXTENSION_ID, promptForMissingTool } from '../lib/tools';

export class FortranFormattingProvider implements vscode.DocumentFormattingEditProvider {
constructor(private logger: LoggingService) {}
Expand Down
13 changes: 8 additions & 5 deletions src/features/linter-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

import * as path from 'path';
import * as cp from 'child_process';
import { FORTRAN_DOCUMENT_SELECTOR, getIncludeParams } from '../lib/helper';

import * as vscode from 'vscode';
import { LoggingService } from '../services/logging-service';
import { resolveVariables } from '../lib/tools';
import { FortranDocumentSelector, resolveVariables } from '../lib/tools';
import * as fg from 'fast-glob';
import { glob } from 'glob';

Expand All @@ -21,8 +20,8 @@ export default class FortranLintingProvider {

// Only lint Fortran (free, fixed) format files
if (
!FORTRAN_DOCUMENT_SELECTOR.some(e => e.scheme === textDocument.uri.scheme) ||
!FORTRAN_DOCUMENT_SELECTOR.some(e => e.language === textDocument.languageId)
!FortranDocumentSelector().some(e => e.scheme === textDocument.uri.scheme) ||
!FortranDocumentSelector().some(e => e.language === textDocument.languageId)
) {
return;
}
Expand Down Expand Up @@ -111,7 +110,7 @@ export default class FortranLintingProvider {
const fileNameWithoutExtension = textDocument.fileName.substring(0, extensionIndex);
const argList = [
...args,
...getIncludeParams(includePaths), // include paths
...this.getIncludeParams(includePaths), // include paths
textDocument.fileName,
`-o ${fileNameWithoutExtension}.mod`,
];
Expand Down Expand Up @@ -222,4 +221,8 @@ export default class FortranLintingProvider {
this.loggingService.logInfo(`Linter.arguments:\n${args.join('\r\n')}`);
return args.map(e => resolveVariables(e));
}

private getIncludeParams = (paths: string[]) => {
return paths.map(path => `-I${path}`);
};
}
37 changes: 0 additions & 37 deletions src/lang-server.ts

This file was deleted.

58 changes: 0 additions & 58 deletions src/lib/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,7 @@ import { installPythonTool } from './tools';
import intrinsics from './fortran-intrinsics';
import { LoggingService } from '../services/logging-service';

// IMPORTANT: this should match the value
// on the package.json otherwise the extension won't
// work at all
export const FORTRAN_DOCUMENT_SELECTOR = [
{ scheme: 'file', language: 'FortranFreeForm' },
{ scheme: 'file', language: 'FortranFixedForm' },
];
export { intrinsics };
export const EXTENSION_ID = 'fortran';

export const FORTRAN_KEYWORDS = [
'FUNCTION',
Expand Down Expand Up @@ -84,10 +76,6 @@ export const _loadDocString = (keyword: string) => {
return docText;
};

export const getIncludeParams = (paths: string[]) => {
return paths.map(path => `-I${path}`);
};

export function isPositionInString(
document: vscode.TextDocument,
position: vscode.Position
Expand All @@ -112,52 +100,6 @@ const saveKeywordToJson = keyword => {
});
};

/**
* Install a package either a Python pip package or a VS Marketplace Extension.
*
* For the Python install supply the name of the package in PyPi
* e.g. fortran-language-server
*
* For the VS Extension to be installed supply the id of the extension
* e.g 'hansec.fortran-ls'
*
* @param tool name of the tool e.g. fortran-language-server
* @param msg optional message for installing said package
* @param toolType type of tool, supports `Python` (through pip) and 'VSExt'
*/
export function promptForMissingTool(
tool: string,
msg: string,
toolType: string,
logger?: LoggingService
) {
const items = ['Install'];
return new Promise((resolve, reject) => {
resolve(
vscode.window.showInformationMessage(msg, ...items).then(selected => {
if (selected === 'Install') {
switch (toolType) {
case 'Python':
installPythonTool(tool, logger);
break;

case 'VSExt':
logger.logInfo(`Installing VS Marketplace Extension with id: ${tool}`);
vscode.commands.executeCommand('extension.open', tool);
vscode.commands.executeCommand('workbench.extensions.installExtension', tool);
logger.logInfo(`Extension ${tool} successfully installed`);
break;

default:
logger.logError(`Failed to install tool: ${tool}`);
break;
}
}
})
);
});
}

export function isUri(input: any): input is vscode.Uri {
return input && input instanceof vscode.Uri;
}
Expand Down
Empty file removed src/lib/linter.ts
Empty file.
85 changes: 82 additions & 3 deletions src/lib/tools.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,95 @@
export const LANG_SERVER_TOOL_ID = 'fortran-language-server';
export const FORMATTERS = ['Disabled', 'findent', 'fprettify'];

import * as os from 'os';
import * as vscode from 'vscode';
import * as assert from 'assert';
import * as cp from 'child_process';
import { LoggingService } from '../services/logging-service';
import { isString, isArrayOfString } from './helper';

export const EXTENSION_ID = 'fortran';
export const LANG_SERVER_TOOL_ID = 'fortran-language-server';
export const FORMATTERS = ['Disabled', 'findent', 'fprettify'];

// Platform-specific environment variable delimiter
export const envDelimiter: string = process.platform === 'win32' ? ';' : ':';

/**
* Generates a document selector for the supported file and languages
* if the folder is present then a glob pattern for all the files in the workspace
* is included
*
* @warning this should match the value on the package.json otherwise the extension
* won't work at all
*
* @param folder `optional` WorkspaceFolder to search
* @returns tuple of DocumentSelector
*/
export function FortranDocumentSelector(folder?: vscode.WorkspaceFolder) {
if (folder) {
return [
{ scheme: 'file', language: 'FortranFreeForm', pattern: `${folder.uri.fsPath}/**/*` },
{ scheme: 'file', language: 'FortranFixedForm', pattern: `${folder.uri.fsPath}/**/*` },
];
} else {
return [
{ scheme: 'file', language: 'FortranFreeForm' },
{ scheme: 'file', language: 'FortranFixedForm' },
];
}
}

/**
* Install a package either a Python pip package or a VS Marketplace Extension.
*
* For the Python install supply the name of the package in PyPi
* e.g. fortran-language-server
*
* For the VS Extension to be installed supply the id of the extension
* e.g 'hansec.fortran-ls'
*
* @param tool name of the tool e.g. fortran-language-server
* @param msg optional message for installing said package
* @param toolType type of tool, supports `Python` (through pip) and 'VSExt'
*/
export function promptForMissingTool(
tool: string,
msg: string,
toolType: string,
logger?: LoggingService
) {
const items = ['Install'];
return new Promise((resolve, reject) => {
resolve(
vscode.window.showInformationMessage(msg, ...items).then(selected => {
if (selected === 'Install') {
switch (toolType) {
case 'Python':
installPythonTool(tool, logger);
break;

case 'VSExt':
logger.logInfo(`Installing VS Marketplace Extension with id: ${tool}`);
vscode.commands.executeCommand('extension.open', tool);
vscode.commands.executeCommand('workbench.extensions.installExtension', tool);
logger.logInfo(`Extension ${tool} successfully installed`);
break;

default:
logger.logError(`Failed to install tool: ${tool}`);
break;
}
}
})
);
});
}

/**
* A wrapper around a call to `pip` for installing external tools.
* Does not explicitly check if `pip` is installed.
*
* @param pyPackage name of python package in PyPi
* @param logger `optional` logging channel for output
*/
export function installPythonTool(pyPackage: string, logger?: LoggingService) {
const installProcess = cp.spawn('pip', 'install --user --upgrade '.concat(pyPackage).split(' '));
installProcess.stdout.on('data', data => {
Expand Down
Loading