@@ -15,7 +15,7 @@ import Control.Monad.Trans.Class (lift)
15
15
import Control.Monad.Trans.Maybe (runMaybeT )
16
16
import qualified Data.ByteString as BS
17
17
import Data.Hashable
18
- import Data.HashMap.Strict (HashMap )
18
+ import Data.HashMap.Strict (HashMap , toList )
19
19
import qualified Data.HashMap.Strict as HashMap
20
20
import qualified Data.List as List
21
21
import qualified Data.List.NonEmpty as NE
@@ -45,7 +45,7 @@ import Distribution.PackageDescription.Configuration (flattenPackageDe
45
45
import Distribution.Parsec.Error
46
46
import qualified Distribution.Parsec.Position as Syntax
47
47
import GHC.Generics
48
- import Ide.Plugin.CabalProject.Parse (parseCabalProjectContents )
48
+ import Ide.Plugin.CabalProject.Parse (parseCabalProjectFileContents )
49
49
import Ide.Plugin.Error
50
50
import Ide.Types
51
51
import qualified Language.LSP.Protocol.Lens as JL
@@ -95,16 +95,14 @@ descriptor recorder plId =
95
95
\ ide vfs _ (DidOpenTextDocumentParams TextDocumentItem {_uri, _version}) -> liftIO $ do
96
96
whenUriFile _uri $ \ file -> do
97
97
log' Debug $ LogDocOpened _uri
98
- result <- parseCabalProjectContents (fromNormalizedFilePath file)
99
- case result of
100
- Left err -> putStrLn $ " Cabal project parse failed: " ++ err
101
- Right project -> putStrLn $ " Cabal project parsed successfully: " ++ show project
98
+ parseAndPrint (fromNormalizedFilePath file)
102
99
restartCabalShakeSession (shakeExtras ide) vfs file " (opened)" $
103
100
addFileOfInterest recorder ide file Modified {firstOpen = True }
104
101
, mkPluginNotificationHandler LSP. SMethod_TextDocumentDidChange $
105
102
\ ide vfs _ (DidChangeTextDocumentParams VersionedTextDocumentIdentifier {_uri} _) -> liftIO $ do
106
103
whenUriFile _uri $ \ file-> do
107
104
log' Debug $ LogDocModified _uri
105
+ parseAndPrint (fromNormalizedFilePath file)
108
106
restartCabalShakeSession (shakeExtras ide) vfs file " (changed)" $
109
107
addFileOfInterest recorder ide file Modified {firstOpen = False }
110
108
, mkPluginNotificationHandler LSP. SMethod_TextDocumentDidSave $
@@ -130,10 +128,20 @@ descriptor recorder plId =
130
128
whenUriFile :: Uri -> (NormalizedFilePath -> IO () ) -> IO ()
131
129
whenUriFile uri act = whenJust (uriToFilePath uri) $ act . toNormalizedFilePath'
132
130
133
- cabalRules :: Recorder (WithPriority Log ) -> PluginId -> Rules ()
134
- cabalRules recorder _ = do
135
- ofInterestRules recorder
136
- -- cabalProjectParseRules recorder
131
+ parseAndPrint :: FilePath -> IO ()
132
+ parseAndPrint file = do
133
+ (warnings, res) <- parseCabalProjectFileContents file
134
+
135
+ mapM_ (putStrLn . (" [Cabal warning] " ++ ) . show ) warnings
136
+
137
+ case res of
138
+ Left (_mbSpecVer, errs) ->
139
+ putStrLn $
140
+ " Cabal project parse failed:\n " ++ unlines (map show (NE. toList errs))
141
+
142
+ Right project ->
143
+ putStrLn $
144
+ " Cabal project parsed successfully:\n " ++ show project
137
145
138
146
{- | Helper function to restart the shake session, specifically for modifying .cabal files.
139
147
No special logic, just group up a bunch of functions you need for the base
@@ -150,6 +158,46 @@ restartCabalShakeSession shakeExtras vfs file actionMsg actionBetweenSession = d
150
158
keys <- actionBetweenSession
151
159
return (toKey GetModificationTime file: keys)
152
160
161
+
162
+ cabalRules :: Recorder (WithPriority Log ) -> PluginId -> Rules ()
163
+ cabalRules recorder _ = do
164
+ -- Make sure we initialise the cabal files-of-interest.
165
+ ofInterestRules recorder
166
+ -- Rule to produce diagnostics for cabal files.
167
+ define (cmapWithPrio LogShake recorder) $ \ ParseCabalProjectFields file -> do
168
+ config <- getPluginConfigAction plId
169
+ if not (plcGlobalOn config && plcDiagnosticsOn config)
170
+ then pure ([] , Nothing )
171
+ else do
172
+ -- whenever this key is marked as dirty (e.g., when a user writes stuff to it),
173
+ -- we rerun this rule because this rule *depends* on GetModificationTime.
174
+ (t, mCabalSource) <- use_ GetFileContents file
175
+ log' Debug $ LogModificationTime file t
176
+ contents <- case mCabalSource of
177
+ Just sources ->
178
+ pure $ Encoding. encodeUtf8 $ Rope. toText sources
179
+ Nothing -> do
180
+ liftIO $ BS. readFile $ fromNormalizedFilePath file
181
+
182
+ case Parse. readCabalProjectFields file contents of
183
+ Left _ ->
184
+ pure ([] , Nothing )
185
+ Right fields ->
186
+ pure ([] , Just fields)
187
+
188
+ {- | This is the kick function for the cabal plugin.
189
+ We run this action, whenever we shake session us run/restarted, which triggers
190
+ actions to produce diagnostics for cabal files.
191
+
192
+ It is paramount that this kick-function can be run quickly, since it is a blocking
193
+ function invocation.
194
+ -}
195
+ kick :: Action ()
196
+ kick = do
197
+ files <- HashMap. keys <$> getCabalFilesOfInterestUntracked
198
+ Shake. runWithSignal (Proxy @ " kick/start/cabal-project" ) (Proxy @ " kick/done/cabal-project" ) files Types. ParseCabalProjectFile
199
+
200
+
153
201
-- ----------------------------------------------------------------
154
202
-- Cabal file of Interest rules and global variable
155
203
-- ----------------------------------------------------------------
0 commit comments