{-# LANGUAGE RecordWildCards #-}
module Ormolu.Utils.Fixity
( getFixityOverridesForSourceFile,
parseFixityDeclarationStr,
)
where
import Control.Exception (throwIO)
import Control.Monad.IO.Class
import Data.Bifunctor (first)
import Data.IORef
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Text qualified as T
import Ormolu.Exception
import Ormolu.Fixity
import Ormolu.Fixity.Parser
import Ormolu.Utils.Cabal
import Ormolu.Utils.IO (readFileUtf8)
import System.Directory
import System.FilePath
import System.IO.Unsafe (unsafePerformIO)
import Text.Megaparsec (errorBundlePretty)
cacheRef :: IORef (Map FilePath FixityMap)
cacheRef :: IORef (Map FilePath FixityMap)
cacheRef = forall a. IO a -> a
unsafePerformIO (forall a. a -> IO (IORef a)
newIORef forall k a. Map k a
Map.empty)
{-# NOINLINE cacheRef #-}
getFixityOverridesForSourceFile ::
(MonadIO m) =>
CabalInfo ->
m FixityMap
getFixityOverridesForSourceFile :: forall (m :: * -> *). MonadIO m => CabalInfo -> m FixityMap
getFixityOverridesForSourceFile CabalInfo {FilePath
[DynOption]
PackageName
Set PackageName
ciCabalFilePath :: CabalInfo -> FilePath
ciDependencies :: CabalInfo -> Set PackageName
ciDynOpts :: CabalInfo -> [DynOption]
ciPackageName :: CabalInfo -> PackageName
ciCabalFilePath :: FilePath
ciDependencies :: Set PackageName
ciDynOpts :: [DynOption]
ciPackageName :: PackageName
..} = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
Map FilePath FixityMap
cache <- forall a. IORef a -> IO a
readIORef IORef (Map FilePath FixityMap)
cacheRef
case forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup FilePath
ciCabalFilePath Map FilePath FixityMap
cache of
Maybe FixityMap
Nothing -> do
let dotOrmolu :: FilePath
dotOrmolu = FilePath -> FilePath -> FilePath
replaceFileName FilePath
ciCabalFilePath FilePath
".ormolu"
Bool
exists <- FilePath -> IO Bool
doesFileExist FilePath
dotOrmolu
if Bool
exists
then do
FilePath
dotOrmoluRelative <- FilePath -> IO FilePath
makeRelativeToCurrentDirectory FilePath
dotOrmolu
Text
contents <- forall (m :: * -> *). MonadIO m => FilePath -> m Text
readFileUtf8 FilePath
dotOrmolu
case FilePath -> Text -> Either (ParseErrorBundle Text Void) FixityMap
parseFixityMap FilePath
dotOrmoluRelative Text
contents of
Left ParseErrorBundle Text Void
errorBundle ->
forall e a. Exception e => e -> IO a
throwIO (ParseErrorBundle Text Void -> OrmoluException
OrmoluFixityOverridesParseError ParseErrorBundle Text Void
errorBundle)
Right FixityMap
x -> do
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef (Map FilePath FixityMap)
cacheRef (forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert FilePath
ciCabalFilePath FixityMap
x)
forall (m :: * -> *) a. Monad m => a -> m a
return FixityMap
x
else forall (m :: * -> *) a. Monad m => a -> m a
return forall k a. Map k a
Map.empty
Just FixityMap
x -> forall (m :: * -> *) a. Monad m => a -> m a
return FixityMap
x
parseFixityDeclarationStr ::
String ->
Either String [(OpName, FixityInfo)]
parseFixityDeclarationStr :: FilePath -> Either FilePath [(OpName, FixityInfo)]
parseFixityDeclarationStr =
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first forall s e.
(VisualStream s, TraversableStream s, ShowErrorComponent e) =>
ParseErrorBundle s e -> FilePath
errorBundlePretty forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either (ParseErrorBundle Text Void) [(OpName, FixityInfo)]
parseFixityDeclaration forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Text
T.pack