Skip to content

Commit 0b226d4

Browse files
Add hls-cabal-project-plugin for cabal.project file support
1 parent 7d5a8e4 commit 0b226d4

File tree

4 files changed

+179
-0
lines changed

4 files changed

+179
-0
lines changed

haskell-language-server.cabal

+52
Original file line numberDiff line numberDiff line change
@@ -2260,3 +2260,55 @@ test-suite ghcide-bench-test
22602260
OverloadedStrings
22612261
RecordWildCards
22622262
ViewPatterns
2263+
2264+
flag cabalProject
2265+
description: Enable cabal project plugin
2266+
default: True
2267+
manual: True
2268+
2269+
common cabalProject
2270+
if flag(cabalProject)
2271+
build-depends: haskell-language-server:hls-cabal-project-plugin
2272+
cpp-options: -Dhls_cabalProject
2273+
2274+
library hls-cabal-project-plugin
2275+
import: defaults, pedantic, warnings
2276+
if !flag(cabalProject)
2277+
buildable: False
2278+
exposed-modules: Ide.Plugin.CabalProject
2279+
hs-source-dirs: plugins/hls-cabal-project-plugin/src
2280+
build-depends:
2281+
, base
2282+
, bytestring
2283+
, containers
2284+
, deepseq
2285+
, directory
2286+
, filepath
2287+
, ghcide == 2.10.0.0
2288+
, hls-plugin-api == 2.10.0.0
2289+
, lens
2290+
, lsp ^>=2.7
2291+
, lsp-types ^>=2.3
2292+
, text
2293+
, text-rope
2294+
, transformers
2295+
, unordered-containers >=0.2.10.0
2296+
2297+
default-extensions:
2298+
DataKinds
2299+
OverloadedStrings
2300+
RecordWildCards
2301+
2302+
test-suite hls-cabal-project-plugin-tests
2303+
import: defaults, pedantic, test-defaults, warnings
2304+
if !flag(cabalProject)
2305+
buildable: False
2306+
type: exitcode-stdio-1.0
2307+
hs-source-dirs: plugins/hls-cabal-project-plugin/test
2308+
main-is: Main.hs
2309+
build-depends:
2310+
, base
2311+
, filepath
2312+
, haskell-language-server:hls-cabal-project-plugin
2313+
, hls-test-utils == 2.10.0.0
2314+
, text
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
cabal-version: 3.0
2+
name: hls-cabal-project-plugin
3+
version: 2.10.0.0
4+
synopsis: Cabal project file support for Haskell Language Server
5+
description: Please see the README on GitHub at <https://github.com/haskell/haskell-language-server#readme>
6+
category: Development
7+
homepage: https://github.com/haskell/haskell-language-server#readme
8+
bug-reports: https://github.com/haskell/haskell-language-server/issues
9+
author: The Haskell IDE Team
10+
maintainer: https://github.com/haskell/haskell-language-server/graphs/contributors
11+
license: Apache-2.0
12+
license-file: LICENSE
13+
build-type: Simple
14+
15+
library
16+
import: defaults, pedantic, warnings
17+
exposed-modules: Ide.Plugin.CabalProject
18+
hs-source-dirs: src
19+
build-depends:
20+
, base
21+
, bytestring
22+
, containers
23+
, deepseq
24+
, directory
25+
, filepath
26+
, ghcide == 2.10.0.0
27+
, hls-plugin-api == 2.10.0.0
28+
, lens
29+
, lsp ^>=2.7
30+
, lsp-types ^>=2.3
31+
, text
32+
, text-rope
33+
, transformers
34+
, unordered-containers >=0.2.10.0
35+
36+
default-extensions:
37+
DataKinds
38+
OverloadedStrings
39+
RecordWildCards
40+
41+
test-suite hls-cabal-project-plugin-tests
42+
import: defaults, pedantic, test-defaults, warnings
43+
type: exitcode-stdio-1.0
44+
hs-source-dirs: test
45+
main-is: Main.hs
46+
build-depends:
47+
, base
48+
, filepath
49+
, haskell-language-server:hls-cabal-project-plugin
50+
, hls-test-utils == 2.10.0.0
51+
, text
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{-# LANGUAGE DataKinds #-}
2+
{-# LANGUAGE DuplicateRecordFields #-}
3+
{-# LANGUAGE LambdaCase #-}
4+
{-# LANGUAGE OverloadedStrings #-}
5+
{-# LANGUAGE TypeFamilies #-}
6+
7+
module Ide.Plugin.CabalProject (descriptor, Log (..)) where
8+
9+
import Control.DeepSeq
10+
import Control.Lens ((^.))
11+
import Control.Monad.Extra
12+
import Control.Monad.IO.Class
13+
import qualified Data.ByteString as BS
14+
import qualified Data.Text as T
15+
import qualified Data.Text.Encoding as Encoding
16+
import Data.Text.Utf16.Rope.Mixed as Rope
17+
import Development.IDE as D
18+
import Development.IDE.Core.PluginUtils
19+
import qualified Development.IDE.Core.Shake as Shake
20+
import Development.IDE.Graph (Key, alwaysRerun)
21+
import Ide.Types
22+
import qualified Language.LSP.Protocol.Lens as JL
23+
import qualified Language.LSP.Protocol.Message as LSP
24+
import Language.LSP.Protocol.Types
25+
import qualified Language.LSP.VFS as VFS
26+
27+
data Log
28+
= LogModificationTime NormalizedFilePath FileVersion
29+
| LogShake Shake.Log
30+
| LogDocOpened Uri
31+
| LogDocModified Uri
32+
deriving (Show)
33+
34+
instance Pretty Log where
35+
pretty = \case
36+
LogShake log' -> pretty log'
37+
LogModificationTime nfp modTime ->
38+
"Modified:" <+> pretty (fromNormalizedFilePath nfp) <+> pretty (show modTime)
39+
LogDocOpened uri ->
40+
"Opened text document:" <+> pretty (getUri uri)
41+
LogDocModified uri ->
42+
"Modified text document:" <+> pretty (getUri uri)
43+
44+
descriptor :: Recorder (WithPriority Log) -> PluginId -> PluginDescriptor IdeState
45+
descriptor recorder plId = (defaultPluginDescriptor plId "Cabal Project File Support")
46+
{ pluginHandlers = mkPluginHandler LSP.SMethod_TextDocumentDidOpen $
47+
\ideState _ vfs (DidOpenTextDocumentParams TextDocumentItem{_uri,_version,_text}) -> do
48+
let filePath = toNormalizedUri _uri
49+
logWith recorder Debug $ LogDocOpened _uri
50+
when (isCabalProjectFile filePath) $ do
51+
-- TODO: Initialize project file handling
52+
pure ()
53+
, pluginHandlers = mkPluginHandler LSP.SMethod_TextDocumentDidChange $
54+
\ideState _ vfs (DidChangeTextDocumentParams TextDocumentIdentifier{_uri} _ _) -> do
55+
let filePath = toNormalizedUri _uri
56+
logWith recorder Debug $ LogDocModified _uri
57+
when (isCabalProjectFile filePath) $ do
58+
-- TODO: Handle file changes
59+
pure ()
60+
, pluginRules = cabalProjectRules recorder plId
61+
}
62+
63+
isCabalProjectFile :: NormalizedFilePath -> Bool
64+
isCabalProjectFile filePath = "cabal.project" `T.isSuffixOf` T.pack (fromNormalizedFilePath filePath)
65+
66+
cabalProjectRules :: Recorder (WithPriority Log) -> PluginId -> Rules ()
67+
cabalProjectRules recorder plId = do
68+
-- TODO: Add rules for parsing and validating cabal.project files
69+
pure ()

src/HlsPlugins.hs

+7
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ import qualified Ide.Plugin.OverloadedRecordDot as OverloadedRecordDot
9797
import qualified Ide.Plugin.Notes as Notes
9898
#endif
9999

100+
#if hls_cabalProject
101+
import qualified Ide.Plugin.CabalProject as CabalProject
102+
#endif
103+
100104
-- formatters
101105

102106
#if hls_floskell
@@ -247,6 +251,9 @@ idePlugins recorder = pluginDescToIdePlugins allPlugins
247251
#endif
248252
#if hls_notes
249253
let pId = "notes" in Notes.descriptor (pluginRecorder pId) pId :
254+
#endif
255+
#if hls_cabalProject
256+
let pId = "cabal-project" in CabalProject.descriptor (pluginRecorder pId) pId :
250257
#endif
251258
GhcIde.descriptors (pluginRecorder "ghcide")
252259

0 commit comments

Comments
 (0)