module Language.PureScript.Ide.Externs
(
ExternDecl(..),
ModuleIdent,
DeclIdent,
Type,
Fixity(..),
readExternFile,
convertExterns,
unwrapPositioned,
unwrapPositionedRef
) where
import Prelude ()
import Prelude.Compat
import Control.Monad.Error.Class
import Control.Monad.IO.Class
import Data.Maybe (mapMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified Language.PureScript.AST.Declarations as D
import qualified Language.PureScript.Externs as PE
import Language.PureScript.Ide.CodecJSON
import Language.PureScript.Ide.Error (PscIdeError (..))
import Language.PureScript.Ide.Types
import qualified Language.PureScript.Names as N
import qualified Language.PureScript.Pretty as PP
readExternFile :: (Applicative m, MonadIO m, MonadError PscIdeError m) =>
FilePath -> m PE.ExternsFile
readExternFile fp = do
parseResult <- liftIO (decodeT <$> T.readFile fp)
case parseResult of
Nothing -> throwError . GeneralError $ "Parsing the extern at: " ++ fp ++ " failed"
Just externs -> pure externs
moduleNameToText :: N.ModuleName -> Text
moduleNameToText = T.pack . N.runModuleName
properNameToText :: N.ProperName a -> Text
properNameToText = T.pack . N.runProperName
identToText :: N.Ident -> Text
identToText = T.pack . N.runIdent
convertExterns :: PE.ExternsFile -> Module
convertExterns ef = (moduleName, exportDecls ++ importDecls ++ otherDecls)
where
moduleName = moduleNameToText (PE.efModuleName ef)
importDecls = convertImport <$> PE.efImports ef
exportDecls = mapMaybe (convertExport . unwrapPositionedRef) (PE.efExports ef)
otherDecls = mapMaybe convertDecl (PE.efDeclarations ef)
convertImport :: PE.ExternsImport -> ExternDecl
convertImport ei = Dependency
(moduleNameToText (PE.eiModule ei))
[]
(moduleNameToText <$> PE.eiImportedAs ei)
convertExport :: D.DeclarationRef -> Maybe ExternDecl
convertExport (D.ModuleRef mn) = Just (Export (moduleNameToText mn))
convertExport _ = Nothing
convertDecl :: PE.ExternsDeclaration -> Maybe ExternDecl
convertDecl PE.EDType{..} = Just $
DataDecl
(properNameToText edTypeName)
(packAndStrip (PP.prettyPrintKind edTypeKind))
convertDecl PE.EDTypeSynonym{..} = Just $
DataDecl
(properNameToText edTypeSynonymName)
(packAndStrip (PP.prettyPrintType edTypeSynonymType))
convertDecl PE.EDDataConstructor{..} = Just $
DataDecl
(properNameToText edDataCtorName)
(packAndStrip (PP.prettyPrintType edDataCtorType))
convertDecl PE.EDValue{..} = Just $
FunctionDecl
(identToText edValueName)
(packAndStrip (PP.prettyPrintType edValueType))
convertDecl _ = Nothing
packAndStrip :: String -> Text
packAndStrip = T.unwords . fmap T.strip . T.lines . T.pack
unwrapPositioned :: D.Declaration -> D.Declaration
unwrapPositioned (D.PositionedDeclaration _ _ x) = x
unwrapPositioned x = x
unwrapPositionedRef :: D.DeclarationRef -> D.DeclarationRef
unwrapPositionedRef (D.PositionedDeclarationRef _ _ x) = x
unwrapPositionedRef x = x