{"id":13616987,"url":"https://github.com/haskell/lsp","last_synced_at":"2025-12-11T23:30:34.565Z","repository":{"id":37011144,"uuid":"69054227","full_name":"haskell/lsp","owner":"haskell","description":"Haskell library for the Microsoft Language Server Protocol","archived":false,"fork":false,"pushed_at":"2025-03-19T21:30:41.000Z","size":4055,"stargazers_count":384,"open_issues_count":52,"forks_count":95,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-04-11T04:59:58.565Z","etag":null,"topics":["haskell-library","language-server-protocol"],"latest_commit_sha":null,"homepage":null,"language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/haskell.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-09-23T19:21:01.000Z","updated_at":"2025-04-01T10:00:54.000Z","dependencies_parsed_at":"2023-02-15T16:15:50.444Z","dependency_job_id":"e91e7b31-f18c-4e8b-83ac-fee30a9a94f6","html_url":"https://github.com/haskell/lsp","commit_stats":{"total_commits":1276,"total_committers":68,"mean_commits":"18.764705882352942","dds":0.5987460815047022,"last_synced_commit":"d1b2785601bd54de120f55c476118a295559030d"},"previous_names":["alanz/haskell-lsp"],"tags_count":66,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haskell%2Flsp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haskell%2Flsp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haskell%2Flsp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haskell%2Flsp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/haskell","download_url":"https://codeload.github.com/haskell/lsp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248345273,"owners_count":21088244,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["haskell-library","language-server-protocol"],"created_at":"2024-08-01T20:01:35.631Z","updated_at":"2025-12-11T23:30:29.546Z","avatar_url":"https://github.com/haskell.png","language":"Haskell","funding_links":[],"categories":["Haskell"],"sub_categories":[],"readme":"![CI](https://github.com/alanz/lsp/workflows/Haskell%20CI/badge.svg)\n[![Hackage](https://img.shields.io/hackage/v/lsp?label=lsp)](https://hackage.haskell.org/package/lsp)\n[![Hackage](https://img.shields.io/hackage/v/lsp-types?label=lsp-types)](https://hackage.haskell.org/package/lsp-types)\n[![Hackage](https://img.shields.io/hackage/v/lsp-test?label=lsp-test)](https://hackage.haskell.org/package/lsp-test)\n\n# lsp\nHaskell library for the Microsoft Language Server Protocol.\nIt currently implements all of the [3.15 specification](https://microsoft.github.io/language-server-protocol/specifications/specification-3-15/).\n\nIt is split into three separate packages, `lsp`, `lsp-types`, and `lsp-test`:\n- `lsp-types` provides *type-safe* definitions that match up with the\ntypescript definitions laid out in the specification\n- `lsp` is a library for building language servers, handling:\n  - JSON-RPC transport\n  - Keeping track of the document state in memory with the Virtual File System (VFS)\n  - Responding to notifications and requests via handlers\n  - Setting the server capabilities in the initialize request based on registered handlers\n  - Dynamic registration of capabilities\n  - Cancellable requests and progress notifications\n  - Publishing and flushing of diagnostics\n- `lsp-test` is a functional testing framework for Language Server Protocol servers.\n\n## Language servers built on lsp\n- [haskell-language-server](https://github.com/haskell/haskell-language-server)\n- [dhall-lsp-server](https://github.com/dhall-lang/dhall-haskell/tree/master/dhall-lsp-server#readme)\n- [swarm](https://github.com/byorgey/swarm/blob/main/src/Swarm/Language/LSP.hs)\n- [curry-language-server](https://github.com/fwcd/curry-language-server)\n\n## Example language servers\nThere are two example language servers in the `lsp/example/` folder. `Simple.hs` provides a minimal example:\n\n```haskell\n{-# LANGUAGE DuplicateRecordFields #-}\n{-# LANGUAGE LambdaCase #-}\n{-# LANGUAGE OverloadedStrings #-}\n\nimport Control.Monad.IO.Class\nimport Data.Text qualified as T\nimport Language.LSP.Protocol.Message\nimport Language.LSP.Protocol.Types\nimport Language.LSP.Server\n\nhandlers :: Handlers (LspM ())\nhandlers =\n  mconcat\n    [ notificationHandler SMethod_Initialized $ \\_not -\u003e do\n        let params =\n              ShowMessageRequestParams\n                MessageType_Info\n                \"Turn on code lenses?\"\n                (Just [MessageActionItem \"Turn on\", MessageActionItem \"Don't\"])\n        _ \u003c- sendRequest SMethod_WindowShowMessageRequest params $ \\case\n          Right (InL (MessageActionItem \"Turn on\")) -\u003e do\n            let regOpts = CodeLensRegistrationOptions (InR Null) Nothing (Just False)\n\n            _ \u003c- registerCapability mempty SMethod_TextDocumentCodeLens regOpts $ \\_req responder -\u003e do\n              let cmd = Command \"Say hello\" \"lsp-hello-command\" Nothing\n                  rsp = [CodeLens (mkRange 0 0 0 100) (Just cmd) Nothing]\n              responder $ Right $ InL rsp\n            pure ()\n          Right _ -\u003e\n            sendNotification SMethod_WindowShowMessage (ShowMessageParams MessageType_Info \"Not turning on code lenses\")\n          Left err -\u003e\n            sendNotification SMethod_WindowShowMessage (ShowMessageParams MessageType_Error $ \"Something went wrong!\\n\" \u003c\u003e T.pack (show err))\n        pure ()\n    , requestHandler SMethod_TextDocumentHover $ \\req responder -\u003e do\n        let TRequestMessage _ _ _ (HoverParams _doc pos _workDone) = req\n            Position _l _c' = pos\n            rsp = Hover (InL ms) (Just range)\n            ms = mkMarkdown \"Hello world\"\n            range = Range pos pos\n        responder (Right $ InL rsp)\n    ]\n\nmain :: IO Int\nmain =\n  runServer $\n    ServerDefinition\n      { parseConfig = const $ const $ Right ()\n      , onConfigChange = const $ pure ()\n      , defaultConfig = ()\n      , configSection = \"demo\"\n      , doInitialize = \\env _req -\u003e pure $ Right env\n      , staticHandlers = \\_caps -\u003e handlers\n      , interpretHandler = \\env -\u003e Iso (runLspT env) liftIO\n      , options = defaultOptions\n      }\n```\n\nWhilst `Reactor.hs` shows how a reactor design can be used to handle all\nrequests on a separate thread, such in a way that we could then execute them on\nmultiple threads without blocking server communication. They can be installed\nfrom source with\n\n    cabal install lsp-demo-simple-server lsp-demo-reactor-server\n    stack install :lsp-demo-simple-server :lsp-demo-reactor-server --flag haskell-lsp:demo\n    \n## Examples of using lsp-test\n\n### Setting up a session\n\n```haskell\nimport Language.LSP.Test\nmain = runSession \"hie\" fullCaps \"proj/dir\" $ do\n  doc \u003c- openDoc \"Foo.hs\" \"haskell\"\n  skipMany anyNotification\n  symbols \u003c- getDocumentSymbols doc\n```\n\n### Unit tests with HSpec\n\n```haskell\ndescribe \"diagnostics\" $\n  it \"report errors\" $ runSession \"hie\" fullCaps \"test/data\" $ do\n    openDoc \"Error.hs\" \"haskell\"\n    [diag] \u003c- waitForDiagnosticsSource \"ghcmod\"\n    liftIO $ do\n      diag ^. severity `shouldBe` Just DsError\n      diag ^. source `shouldBe` Just \"ghcmod\"\n```\n\n### Replaying captured session\n```haskell\nreplaySession \"hie\" \"test/data/renamePass\"\n```\n\n### Parsing with combinators\n```haskell\nskipManyTill loggingNotification publishDiagnosticsNotification\ncount 4 (message :: Session ApplyWorkspaceEditRequest)\nanyRequest \u003c|\u003e anyResponse\n```\n\nTry out the example tests in the `lsp-test/example` directory with `cabal test`.\nFor more examples check the [Wiki](https://github.com/bubba/lsp-test/wiki/Introduction), or see this [introductory blog post](https://lukelau.me/haskell/posts/lsp-test/).\n\nWhilst writing your tests you may want to debug them to see what's going wrong.\nYou can set the `logMessages` and `logStdErr` options in `SessionConfig` to see what the server is up to.\nThere are also corresponding environment variables so you can turn them on from the command line:\n```\nLSP_TEST_LOG_MESSAGES=1 LSP_TEST_LOG_STDERR=1 cabal test\n```\n\n## Troubleshooting\nSeeing funny stuff when running lsp-test via stack? If your server is built upon Haskell tooling, [keep in mind that stack sets some environment variables related to GHC, and you may want to unset them.](https://github.com/alanz/haskell-ide-engine/blob/bfb16324d396da71000ef81d51acbebbdaa854ab/test/utils/TestUtils.hs#L290-L298)\n\n## Useful links\n\n- [Language Server Protocol Specification](https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md)\n\n## Other resources\n\nSee #haskell-language-server  on IRC freenode.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhaskell%2Flsp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhaskell%2Flsp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhaskell%2Flsp/lists"}