{- |
Copyright: (c) 2020 Kowainik
SPDX-License-Identifier: MPL-2.0
Maintainer: Kowainik <xrom.xkov@gmail.com>

File (or module) specific information.
-}

module Stan.FileInfo
    ( FileMap
    , FileInfo (..)

    , extensionsToText
    , isExtensionDisabled
    ) where

import Data.Aeson.Micro (ToJSON (..), object, (.=))
import Extensions (Extensions (..), ExtensionsError, ExtensionsResult, OnOffExtension (..),
                   ParsedExtensions (..), showOnOffExtension)
import GHC.LanguageExtensions.Type (Extension)

import Stan.Core.ModuleName (ModuleName)
import Stan.Observation (Observations)

import qualified Data.Set as Set


-- | File specific information.
data FileInfo = FileInfo
    { FileInfo -> FilePath
fileInfoPath             :: !FilePath
    , FileInfo -> ModuleName
fileInfoModuleName       :: !ModuleName
    , FileInfo -> Int
fileInfoLoc              :: !Int
    , FileInfo -> Either ExtensionsError ParsedExtensions
fileInfoCabalExtensions  :: !(Either ExtensionsError ParsedExtensions)
    , FileInfo -> Either ExtensionsError ParsedExtensions
fileInfoExtensions       :: !(Either ExtensionsError ParsedExtensions)
    , FileInfo -> ExtensionsResult
fileInfoMergedExtensions :: !ExtensionsResult
    , FileInfo -> Observations
fileInfoObservations     :: !Observations
    } deriving stock (Int -> FileInfo -> ShowS
[FileInfo] -> ShowS
FileInfo -> FilePath
(Int -> FileInfo -> ShowS)
-> (FileInfo -> FilePath) -> ([FileInfo] -> ShowS) -> Show FileInfo
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FileInfo -> ShowS
showsPrec :: Int -> FileInfo -> ShowS
$cshow :: FileInfo -> FilePath
show :: FileInfo -> FilePath
$cshowList :: [FileInfo] -> ShowS
showList :: [FileInfo] -> ShowS
Show, FileInfo -> FileInfo -> Bool
(FileInfo -> FileInfo -> Bool)
-> (FileInfo -> FileInfo -> Bool) -> Eq FileInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FileInfo -> FileInfo -> Bool
== :: FileInfo -> FileInfo -> Bool
$c/= :: FileInfo -> FileInfo -> Bool
/= :: FileInfo -> FileInfo -> Bool
Eq)

instance ToJSON FileInfo where
    toJSON :: FileInfo -> Value
toJSON FileInfo{Int
FilePath
Either ExtensionsError ParsedExtensions
ExtensionsResult
Observations
ModuleName
fileInfoPath :: FileInfo -> FilePath
fileInfoModuleName :: FileInfo -> ModuleName
fileInfoLoc :: FileInfo -> Int
fileInfoCabalExtensions :: FileInfo -> Either ExtensionsError ParsedExtensions
fileInfoExtensions :: FileInfo -> Either ExtensionsError ParsedExtensions
fileInfoMergedExtensions :: FileInfo -> ExtensionsResult
fileInfoObservations :: FileInfo -> Observations
fileInfoPath :: FilePath
fileInfoModuleName :: ModuleName
fileInfoLoc :: Int
fileInfoCabalExtensions :: Either ExtensionsError ParsedExtensions
fileInfoExtensions :: Either ExtensionsError ParsedExtensions
fileInfoMergedExtensions :: ExtensionsResult
fileInfoObservations :: Observations
..} = [Pair] -> Value
object
        [ Text
"path"            Text -> Text -> Pair
forall v. ToJSON v => Text -> v -> Pair
.= FilePath -> Text
forall a. ToText a => a -> Text
toText FilePath
fileInfoPath
        , Text
"moduleName"      Text -> ModuleName -> Pair
forall v. ToJSON v => Text -> v -> Pair
.= ModuleName
fileInfoModuleName
        , Text
"loc"             Text -> Int -> Pair
forall v. ToJSON v => Text -> v -> Pair
.= Int
fileInfoLoc
        , Text
"cabalExtensions" Text -> [Text] -> Pair
forall v. ToJSON v => Text -> v -> Pair
.= Either ExtensionsError ParsedExtensions -> [Text]
extensionsToText Either ExtensionsError ParsedExtensions
fileInfoCabalExtensions
        , Text
"extensions"      Text -> [Text] -> Pair
forall v. ToJSON v => Text -> v -> Pair
.= Either ExtensionsError ParsedExtensions -> [Text]
extensionsToText Either ExtensionsError ParsedExtensions
fileInfoExtensions
        , Text
"observations"    Text -> [Observation] -> Pair
forall v. ToJSON v => Text -> v -> Pair
.= Observations -> [Observation]
forall a. Slist a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Observations
fileInfoObservations
        ]

type FileMap = Map FilePath FileInfo

-- | Return the list of pretty-printed extensions.
extensionsToText :: Either ExtensionsError ParsedExtensions -> [Text]
extensionsToText :: Either ExtensionsError ParsedExtensions -> [Text]
extensionsToText = \case
    Left ExtensionsError
_ -> [Text
"Unable to extract extensions"]
    Right ParsedExtensions{[OnOffExtension]
Maybe SafeHaskellExtension
parsedExtensionsAll :: [OnOffExtension]
parsedExtensionsSafe :: Maybe SafeHaskellExtension
parsedExtensionsAll :: ParsedExtensions -> [OnOffExtension]
parsedExtensionsSafe :: ParsedExtensions -> Maybe SafeHaskellExtension
..} ->
        let exts :: [Text]
exts = (OnOffExtension -> Text) -> [OnOffExtension] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map OnOffExtension -> Text
showOnOffExtension [OnOffExtension]
parsedExtensionsAll in
        case Maybe SafeHaskellExtension
parsedExtensionsSafe of
            Just SafeHaskellExtension
s  -> SafeHaskellExtension -> Text
forall b a. (Show a, IsString b) => a -> b
show SafeHaskellExtension
s Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text]
exts
            Maybe SafeHaskellExtension
Nothing -> [Text]
exts

{- | Check whether the given extension is disabled
-}
isExtensionDisabled :: Extension -> ExtensionsResult -> Bool
isExtensionDisabled :: Extension -> ExtensionsResult -> Bool
isExtensionDisabled Extension
ext = \case
    Left ExtensionsError
_ -> Bool
True  -- no info about extensions, consider it disabled
    Right Extensions{Maybe SafeHaskellExtension
Set OnOffExtension
extensionsAll :: Set OnOffExtension
extensionsSafe :: Maybe SafeHaskellExtension
extensionsAll :: Extensions -> Set OnOffExtension
extensionsSafe :: Extensions -> Maybe SafeHaskellExtension
..} ->
           OnOffExtension -> Set OnOffExtension -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.notMember (Extension -> OnOffExtension
On Extension
ext) Set OnOffExtension
extensionsAll
        Bool -> Bool -> Bool
|| OnOffExtension -> Set OnOffExtension -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member (Extension -> OnOffExtension
Off Extension
ext) Set OnOffExtension
extensionsAll