Skip to content

Commit fba2f31

Browse files
committed
Introduce 'automatic' mode for 'supportCabalFiles' option
Add option to automatically determine whether the Haskell Language Server binary we are about to launch supports '.cabal' files. If not, i.e. the HLS binary is older than '1.9.0.0', then we do not send file notifications for '.cabal' files. Otherwise, we do send these notifications. The user can explicitly overwrite this option in order to avoid the version check.
1 parent a5605c6 commit fba2f31

File tree

3 files changed

+50
-14
lines changed

3 files changed

+50
-14
lines changed

package.json

+13-3
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,19 @@
236236
},
237237
"haskell.supportCabalFiles": {
238238
"scope": "resource",
239-
"default": true,
240-
"type": "boolean",
241-
"description": "Enable Language Server support for `.cabal` files. Requires Haskell Language Server version >= 2.0.0.0."
239+
"default": "automatic",
240+
"type": "string",
241+
"enum": [
242+
"enable",
243+
"disable",
244+
"automatic"
245+
],
246+
"description": "Enable Language Server support for `.cabal` files. Requires Haskell Language Server version >= 1.9.0.0.",
247+
"enumDescriptions": [
248+
"Enable Language Server support for `.cabal` files",
249+
"Disable Language Server support for `.cabal` files",
250+
"Enable Language Server support for `.cabal` files if the HLS version supports it."
251+
]
242252
},
243253
"haskell.maxCompletions": {
244254
"scope": "resource",

src/extension.ts

+36-10
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import {
2121
import { RestartServerCommandName, StartServerCommandName, StopServerCommandName } from './commands/constants';
2222
import * as DocsBrowser from './docsBrowser';
2323
import { HlsError, MissingToolError, NoMatchingHls } from './errors';
24-
import { findHaskellLanguageServer, IEnvVars } from './hlsBinaries';
25-
import { addPathToProcessPath, expandHomeDir, ExtensionLogger } from './utils';
24+
import { callAsync, findHaskellLanguageServer, IEnvVars } from './hlsBinaries';
25+
import { addPathToProcessPath, comparePVP, expandHomeDir, ExtensionLogger } from './utils';
2626

2727
// The current map of documents & folders to language servers.
2828
// It may be null to indicate that we are in the process of launching a server,
@@ -205,8 +205,11 @@ async function activateServerForFolder(context: ExtensionContext, uri: Uri, fold
205205
args = args.concat(extraArgs.split(' '));
206206
}
207207

208-
const cabalFileSupport: boolean = workspace.getConfiguration('haskell', uri).supportCabalFiles;
209-
logger.info(`Support for '.cabal' files enabled: ${cabalFileSupport ? 'yes' : 'no'}`);
208+
const cabalFileSupport: 'automatic' | 'enable' | 'disable' = workspace.getConfiguration(
209+
'haskell',
210+
uri,
211+
).supportCabalFiles;
212+
logger.info(`Support for '.cabal' files: ${cabalFileSupport}`);
210213

211214
// If we're operating on a standalone file (i.e. not in a folder) then we need
212215
// to launch the server in a reasonable current directory. Otherwise the cradle
@@ -257,20 +260,43 @@ async function activateServerForFolder(context: ExtensionContext, uri: Uri, fold
257260
const pat = folder ? `${folder.uri.fsPath}/**/*` : '**/*';
258261
logger.log(`document selector patten: ${pat}`);
259262

260-
261-
const cabalDocumentSelector = cabalFileSupport ? [{ scheme: 'file', language: 'cabal', pattern: pat }] : [];
263+
const cabalDocumentSelector = { scheme: 'file', language: 'cabal', pattern: pat };
262264
const haskellDocumentSelector = [
263265
{ scheme: 'file', language: 'haskell', pattern: pat },
264266
{ scheme: 'file', language: 'literate haskell', pattern: pat },
265267
];
266268

269+
const documentSelector = [...haskellDocumentSelector];
270+
271+
switch (cabalFileSupport) {
272+
case 'automatic':
273+
const hlsVersion = await callAsync(
274+
serverExecutable,
275+
['--numeric-version'],
276+
logger,
277+
currentWorkingDir,
278+
undefined /* this command is very fast, don't show anything */,
279+
false,
280+
serverEnvironment,
281+
);
282+
if (comparePVP(hlsVersion, '1.9.0.0') >= 0) {
283+
// If hlsVersion is >= '1.9.0.0'
284+
documentSelector.push(cabalDocumentSelector);
285+
}
286+
break;
287+
case 'enable':
288+
documentSelector.push(cabalDocumentSelector);
289+
break;
290+
case 'disable':
291+
break;
292+
default:
293+
break;
294+
}
295+
267296
const clientOptions: LanguageClientOptions = {
268297
// Use the document selector to only notify the LSP on files inside the folder
269298
// path for the specific workspace.
270-
documentSelector:
271-
[ ... haskellDocumentSelector
272-
, ... cabalDocumentSelector
273-
],
299+
documentSelector: [...documentSelector],
274300
synchronize: {
275301
// Synchronize the setting section 'haskell' to the server.
276302
configurationSection: 'haskell',

src/hlsBinaries.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ type ProcessCallback = (
5858
* @param callback Upon process termination, execute this callback. If given, must resolve promise. On error, stderr and stdout are logged regardless of whether the callback has been specified.
5959
* @returns Stdout of the process invocation, trimmed off newlines, or whatever the `callback` resolved to.
6060
*/
61-
async function callAsync(
61+
export async function callAsync(
6262
binary: string,
6363
args: string[],
6464
logger: Logger,

0 commit comments

Comments
 (0)