haskell / haskell-language-server

Official haskell ide support via language server (LSP). Successor of ghcide & haskell-ide-engine.
Apache License 2.0
2.71k stars 368 forks source link

Some features do not work without `initializationOptions.haskell` or `initializationOptions.languageServerHaskell` in CocConfig #651

Closed deej-io closed 10 months ago

deej-io commented 3 years ago

Hi folks,

I've just managed to debug an issue that was preventing my from using all of the features with coc.nvim.

I copied the coc-settings.json config from the README and found that the formatter was not working.

It looks like the language server fails to parse this config correctly unless there is the initializationOptions block with a haskell or languageServerHaskell block inside.

If I add this block to the config, everything works as expected.

Your environment

Output of haskell-language-server --probe-tools or haskell-language-server-wrapper --probe-tools:

haskell-language-server version: 0.6.0.0 (GHC: 8.10.1) (PATH: /home/djr/.ghcup/bin/haskell-language-server-wrapper-0.6.0) (GIT hash: 372a12e797069dc3ac4fa33dcaabe3b992999d7c)
Tool versions found on the $PATH
cabal:          Not found
stack:          2.5.1
ghc:            Not found

Which lsp-client do you use: Vim with coc.nvim

Contents of hie.yaml: None

Steps to reproduce

  1. Create this minimal CocConfig from the README
{
    "languageserver": {
        "haskell": {
            "command": "haskell-language-server-wrapper",
            "args": ["--lsp"],
            "rootPatterns": ["*.cabal", "stack.yaml", "cabal.project", "package.yaml", "hie.yaml"],
            "filetypes": ["haskell", "lhaskell"]
        }
    }
}
  1. Open a file from a haskell workspace in vim and run :call CocAction('format') to try and format it.

Expected behaviour

The file should be formatted with the default ormolu formatter.

Actual behaviour

The language server boots, but has a config parse error and the format command doesn't work.

If I add the initializationOptions block, everything then works as expected e.g.

{
    "languageserver": {
        "haskell": {
            "command": "haskell-language-server-wrapper",
            "args": ["--lsp"],
            "rootPatterns": ["*.cabal", "stack.yaml", "cabal.project", "package.yaml", "hie.yaml"],
            "filetypes": ["haskell", "lhaskell"],
            "initializationOptions": {
                "haskell": {}
            }
        }
    }
}

Include debug information

Execute in the root of your project the command haskell-language-server --debug . and paste the logs here:

Debug output: ``` Module "/home/djr/dev/aoc-2020/haskell/a" is loaded by Cradle: Cradle {cradleRootDir = "/home/djr/dev/aoc-2020/haskell", cradleOptsProg = CradleAction: Stack} Run entered for haskell-language-server-wrapper(haskell-language-server-wrapper) Version 0.6.0.0, Git revision 372a12e797069dc3ac4fa33dcaabe3b992999d7c (dirty) x86_64 ghc-8.10.1 Current directory: /home/djr/dev/aoc-2020/haskell Operating system: linux Arguments: ["--debug"] Cradle directory: /home/djr/dev/aoc-2020/haskell Cradle type: Stack Tool versions found on the $PATH cabal: Not found stack: 2.5.1 ghc: Not found Consulting the cradle to get project GHC version... Project GHC version: 8.8.4 haskell-language-server exe candidates: ["haskell-language-server-8.8.4","haskell-language-server-8.8","haskell-language-server"] Launching haskell-language-server exe at:/home/djr/.ghcup/bin/haskell-language-server-8.8.4 haskell-language-server version: 0.6.0.0 (GHC: 8.8.4) (PATH: /home/djr/.ghcup/bin/haskell-language-server-8.8.4~0.6.0) (GIT hash: 372a12e797069dc3ac4fa33dcaabe3b992999d7c) (haskell-language-server)Ghcide setup tester in /home/djr/dev/aoc-2020/haskell. Report bugs at https://github.com/haskell/haskell-language-server/issues Tool versions found on the $PATH cabal: Not found stack: 2.5.1 ghc: Not found Step 1/4: Finding files to test in /home/djr/dev/aoc-2020/haskell Found 3 files Step 2/4: Looking for hie.yaml files that control setup Found 1 cradle Step 3/4: Initializing the IDE Step 4/4: Type checking the files [INFO] Consulting the cradle for "Setup.hs" NotShowMessage (NotificationMessage {_jsonrpc = "2.0", _method = WindowShowMessage, _params = ShowMessageParams {_xtype = MtInfo, _message = "No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for Setup.hs.\n Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).\nYou should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error."}}) Output from setting up the cradle Cradle {cradleRootDir = "/home/djr/dev/aoc-2020/haskell", cradleOptsProg = CradleAction: Stack} File: /home/djr/dev/aoc-2020/haskell/Setup.hs Hidden: no Range: 1:1-2:1 Source: cradle Severity: DsError Message: Multi Cradle: No prefixes matched pwd: /home/djr/dev/aoc-2020/haskell filepath: /home/djr/dev/aoc-2020/haskell/Setup.hs prefixes: ("./src/day01/Main.hs",Stack {component = Just "aoc2020:exe:day01", stackYaml = Nothing}) ("./src/day04/Main.hs",Stack {component = Just "aoc2020:exe:day04", stackYaml = Nothing}) [INFO] Consulting the cradle for "src/day01/Main.hs" NotShowMessage (NotificationMessage {_jsonrpc = "2.0", _method = WindowShowMessage, _params = ShowMessageParams {_xtype = MtInfo, _message = "No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for src/day01/Main.hs.\n Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).\nYou should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error."}}) Output from setting up the cradle Cradle {cradleRootDir = "/home/djr/dev/aoc-2020/haskell", cradleOptsProg = CradleAction: Stack} > Cabal file warning in/home/djr/dev/aoc-2020/haskell/aoc2020.cabal@32:10: Tabs used as indentation at 32:10, 33:10 > Using main module: 1. Package `aoc2020' component aoc2020:exe:day01 with main-is file: /home/djr/dev/aoc-2020/haskell/src/day01/Main.hs > aoc2020> configure (exe) > Warning: aoc2020.cabal:32:10: Tabs used as indentation at 32:10, 33:10 > Configuring aoc2020-0.1.0.0... > aoc2020> initial-build-steps (exe) > Configuring GHCi with the following packages: aoc2020 > /home/djr/dev/aoc-2020/haskell/.stack-work/install/x86_64-linux-tinfo6/072c751322025d6ebf9f931faab426dca00c54bb1ad4475a6d670eb531251d00/8.8.4/pkgdb:/home/djr/.stack/snapshots/x86_64-linux-tinfo6/072c751322025d6ebf9f931faab426dca00c54bb1ad4475a6d670eb531251d00/8.8.4/pkgdb:/home/djr/.stack/programs/x86_64-linux/ghc-tinfo6-8.8.4/lib/ghc-8.8.4/package.conf.d [INFO] Using interface files cache dir: /home/djr/.cache/ghcide/main-0c960677381e46d769507bd9a5182677d97b529b [INFO] Making new HscEnv[main] [INFO] Consulting the cradle for "Setup.hs" NotShowMessage (NotificationMessage {_jsonrpc = "2.0", _method = WindowShowMessage, _params = ShowMessageParams {_xtype = MtInfo, _message = "No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for Setup.hs.\n Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).\nYou should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error."}}) Output from setting up the cradle Cradle {cradleRootDir = "/home/djr/dev/aoc-2020/haskell", cradleOptsProg = CradleAction: Stack} [INFO] Consulting the cradle for "src/day04/Main.hs" NotShowMessage (NotificationMessage {_jsonrpc = "2.0", _method = WindowShowMessage, _params = ShowMessageParams {_xtype = MtInfo, _message = "No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for src/day04/Main.hs.\n Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).\nYou should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error."}}) Output from setting up the cradle Cradle {cradleRootDir = "/home/djr/dev/aoc-2020/haskell", cradleOptsProg = CradleAction: Stack} > Cabal file warning in/home/djr/dev/aoc-2020/haskell/aoc2020.cabal@32:10: Tabs used as indentation at 32:10, 33:10 > Using main module: 1. Package `aoc2020' component aoc2020:exe:day04 with main-is file: /home/djr/dev/aoc-2020/haskell/src/day04/Main.hs > aoc2020> configure (exe) > Warning: aoc2020.cabal:32:10: Tabs used as indentation at 32:10, 33:10 > Configuring aoc2020-0.1.0.0... > aoc2020> initial-build-steps (exe) > Configuring GHCi with the following packages: aoc2020 > /home/djr/dev/aoc-2020/haskell/.stack-work/install/x86_64-linux-tinfo6/072c751322025d6ebf9f931faab426dca00c54bb1ad4475a6d670eb531251d00/8.8.4/pkgdb:/home/djr/.stack/snapshots/x86_64-linux-tinfo6/072c751322025d6ebf9f931faab426dca00c54bb1ad4475a6d670eb531251d00/8.8.4/pkgdb:/home/djr/.stack/programs/x86_64-linux/ghc-tinfo6-8.8.4/lib/ghc-8.8.4/package.conf.d [INFO] Using interface files cache dir: /home/djr/.cache/ghcide/main-bd460570bfcf2c2a9793cd21c527aaf81a754181 [INFO] Using interface files cache dir: /home/djr/.cache/ghcide/main-bd460570bfcf2c2a9793cd21c527aaf81a754181 [INFO] Making new HscEnv[main,main] [INFO] Consulting the cradle for "Setup.hs" NotShowMessage (NotificationMessage {_jsonrpc = "2.0", _method = WindowShowMessage, _params = ShowMessageParams {_xtype = MtInfo, _message = "No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for Setup.hs.\n Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).\nYou should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error."}}) Output from setting up the cradle Cradle {cradleRootDir = "/home/djr/dev/aoc-2020/haskell", cradleOptsProg = CradleAction: Stack} Files that failed: * /home/djr/dev/aoc-2020/haskell/Setup.hs [INFO] finish: User TypeCheck (took 0.13s)Completed (2 files worked, 1 file failed) haskell-language-server-wrapper: callProcess: /home/djr/.ghcup/bin/haskell-language-server-8.8.4 "--debug" (exit 1): failed ```

Paste the logs from the lsp-client, e.g. for VS Code

LSP logs: ``` [Error - 23:23:25] haskell-lsp:configuration parse error. RequestMessage {_jsonrpc = "2.0", _id = IdInt 0, _method = Initialize, _params = InitializeParams {_processId = Just 80824, _rootPath = Just "/home/djr/dev/aoc-2020/haskell", _rootUri = Just (Uri {getUri = "file:///home/djr/dev/aoc-2020/haskell"}), _initializationOptions = Just (Object (fromList [])), _capabilities = ClientCapabilities {_workspace = Just (WorkspaceClientCapabilities {_applyEdit = Just True, _workspaceEdit = Just (WorkspaceEditClientCapabilities {_documentChanges = Just True}), _didChangeConfiguration = Just (DidChangeConfigurationClientCapabilities {_dynamicRegistration = Just True}), _didChangeWatchedFiles = Just (DidChangeWatchedFilesClientCapabilities {_dynamicRegistration = Just True}), _symbol = Just (SymbolClientCapabilities {_dynamicRegistration = Just True, _symbolKind = Just (SymbolKindClientCapabilities {_valueSet = Just (List [SkFile,SkModule,SkNamespace,SkPackage,SkClass,SkMethod,SkProperty,SkField,SkConstructor,SkEnum,SkInterface,SkFunction,SkVariable,SkConstant,SkString,SkNumber,SkBoolean,SkArray,SkObject,SkKey,SkNull,SkEnumMember,SkStruct,SkEvent,SkOperator,SkTypeParameter])})}), _executeCommand = Just (ExecuteClientCapabilities {_dynamicRegistration = Just True}), _workspaceFolders = Just True, _configuration = Just True}), _textDocument = Just (TextDocumentClientCapabilities {_synchronization = Just (SynchronizationTextDocumentClientCapabilities {_dynamicRegistration = Just True, _willSave = Just True, _willSaveWaitUntil = Just True, _didSave = Just True}), _completion = Just (CompletionClientCapabilities {_dynamicRegistration = Just True, _completionItem = Just (CompletionItemClientCapabilities {_snippetSupport = Just True, _commitCharactersSupport = Just True, _documentationFormat = Just (List [MkMarkdown,MkPlainText]), _deprecatedSupport = Just True, _preselectSupport = Just True, _tagSupport = Nothing}), _completionItemKind = Just (CompletionItemKindClientCapabilities {_valueSet = Just (List [CiText,CiMethod,CiFunction,CiConstructor,CiField,CiVariable,CiClass,CiInterface,CiModule,CiProperty,CiUnit,CiValue,CiEnum,CiKeyword,CiSnippet,CiColor,CiFile,CiReference,CiFolder,CiEnumMember,CiConstant,CiStruct,CiEvent,CiOperator,CiTypeParameter])}), _contextSupport = Just True}), _hover = Just (HoverClientCapabilities {_dynamicRegistration = Just True, _contentFormat = Just (List [MkMarkdown,MkPlainText])}), _signatureHelp = Just (SignatureHelpClientCapabilities {_dynamicRegistration = Just True, _signatureInformation = Just (SignatureInformationClientCapabilities {documentationFormat = Nothing})}), _references = Just (ReferencesClientCapabilities {_dynamicRegistration = Just True}), _documentHighlight = Just (DocumentHighlightClientCapabilities {_dynamicRegistration = Just True}), _documentSymbol = Just (DocumentSymbolClientCapabilities {_dynamicRegistration = Just True, _symbolKind = Just (DocumentSymbolKindClientCapabilities {_valueSet = Just (List [SkFile,SkModule,SkNamespace,SkPackage,SkClass,SkMethod,SkProperty,SkField,SkConstructor,SkEnum,SkInterface,SkFunction,SkVariable,SkConstant,SkString,SkNumber,SkBoolean,SkArray,SkObject,SkKey,SkNull,SkEnumMember,SkStruct,SkEvent,SkOperator,SkTypeParameter])}), _hierarchicalDocumentSymbolSupport = Just True}), _formatting = Just (FormattingClientCapabilities {_dynamicRegistration = Just True}), _rangeFormatting = Just (RangeFormattingClientCapabilities {_dynamicRegistration = Just True}), _onTypeFormatting = Just (OnTypeFormattingClientCapabilities {_dynamicRegistration = Just True}), _definition = Just (DefinitionClientCapabilities {_dynamicRegistration = Just True}), _typeDefinition = Just (TypeDefinitionClientCapabilities {_dynamicRegistration = Just True}), _implementation = Just (ImplementationClientCapabilities {_dynamicRegistration = Just True}), _codeAction = Just (CodeActionClientCapabilities {_dynamicRegistration = Just True, _codeActionLiteralSupport = Just (CodeActionLiteralSupport {_codeActionKind = CodeActionKindClientCapabilities {_valueSet = List [CodeActionUnknown "",CodeActionQuickFix,CodeActionRefactor,CodeActionRefactorExtract,CodeActionRefactorInline,CodeActionRefactorRewrite,CodeActionSource,CodeActionSourceOrganizeImports]}})}), _codeLens = Just (CodeLensClientCapabilities {_dynamicRegistration = Just True}), _documentLink = Just (DocumentLinkClientCapabilities {_dynamicRegistration = Just True}), _colorProvider = Just (ColorProviderClientCapabilities {_dynamicRegistration = Just True}), _rename = Just (RenameClientCapabilities {_dynamicRegistration = Just True, _prepareSupport = Just True}), _publishDiagnostics = Just (PublishDiagnosticsClientCapabilities {_relatedInformation = Just True, _tagSupport = Just (PublishDiagnosticsTagsClientCapabilities {_valueSet = List [DtUnnecessary,DtDeprecated]})}), _foldingRange = Just (FoldingRangeClientCapabilities {_dynamicRegistration = Just True, _rangeLimit = Just 5000, _lineFoldingOnly = Just True})}), _window = Just (WindowClientCapabilities {_workDoneProgress = Just True}), _experimental = Nothing}, _trace = Just TraceOff, _workspaceFolders = Just (List [WorkspaceFolder {_uri = "file:///home/djr/dev/aoc-2020/haskell", _name = "haskell"}])}} "key \"languageServerHaskell\" not found" ```
jneira commented 3 years ago

Many thanks for reporting the issue including the possible solution. Maybe the config snipet should be corrected, are you interested in submit a pr?

deej-io commented 3 years ago

Hi @jneira,

I'd be fine to submit a PR for the README change, but I feel the proper solution would be to handle the missing keys gracefully in the config parsing. I am happy to make an attempt at that as well, but it would take me a while to understand where and how to do the fix.

expipiplus1 commented 3 years ago

This is surprising as it works for me without this option (HLS master from today):

https://github.com/expipiplus1/dotfiles/blob/5dd9fd913b586932f83c6efc602d75c9a60e7011/config/nixpkgs/home/coc-nvim.nix#L177-L188

Perhaps because I'm using the coc plugin?

michaelpj commented 10 months ago

I think this should now be fine