@@ -15,7 +15,7 @@ import Control.Monad.Trans.Class (lift)
1515import Control.Monad.Trans.Maybe (runMaybeT )
1616import qualified Data.ByteString as BS
1717import Data.Hashable
18- import Data.HashMap.Strict (HashMap )
18+ import Data.HashMap.Strict (HashMap , toList )
1919import qualified Data.HashMap.Strict as HashMap
2020import qualified Data.List as List
2121import qualified Data.List.NonEmpty as NE
@@ -45,7 +45,7 @@ import Distribution.PackageDescription.Configuration (flattenPackageDe
4545import Distribution.Parsec.Error
4646import qualified Distribution.Parsec.Position as Syntax
4747import GHC.Generics
48- import Ide.Plugin.CabalProject.Parse (parseCabalProjectContents )
48+ import Ide.Plugin.CabalProject.Parse (parseCabalProjectFileContents )
4949import Ide.Plugin.Error
5050import Ide.Types
5151import qualified Language.LSP.Protocol.Lens as JL
@@ -95,16 +95,14 @@ descriptor recorder plId =
9595 \ ide vfs _ (DidOpenTextDocumentParams TextDocumentItem {_uri, _version}) -> liftIO $ do
9696 whenUriFile _uri $ \ file -> do
9797 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)
10299 restartCabalShakeSession (shakeExtras ide) vfs file " (opened)" $
103100 addFileOfInterest recorder ide file Modified {firstOpen = True }
104101 , mkPluginNotificationHandler LSP. SMethod_TextDocumentDidChange $
105102 \ ide vfs _ (DidChangeTextDocumentParams VersionedTextDocumentIdentifier {_uri} _) -> liftIO $ do
106103 whenUriFile _uri $ \ file-> do
107104 log' Debug $ LogDocModified _uri
105+ parseAndPrint (fromNormalizedFilePath file)
108106 restartCabalShakeSession (shakeExtras ide) vfs file " (changed)" $
109107 addFileOfInterest recorder ide file Modified {firstOpen = False }
110108 , mkPluginNotificationHandler LSP. SMethod_TextDocumentDidSave $
@@ -130,10 +128,20 @@ descriptor recorder plId =
130128 whenUriFile :: Uri -> (NormalizedFilePath -> IO () ) -> IO ()
131129 whenUriFile uri act = whenJust (uriToFilePath uri) $ act . toNormalizedFilePath'
132130
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
137145
138146{- | Helper function to restart the shake session, specifically for modifying .cabal files.
139147No 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
150158 keys <- actionBetweenSession
151159 return (toKey GetModificationTime file: keys)
152160
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+
153201-- ----------------------------------------------------------------
154202-- Cabal file of Interest rules and global variable
155203-- ----------------------------------------------------------------
0 commit comments