module Importify.Syntax.Import
( getImportModuleName
, importNamesWithTables
, importSlice
, isImportImplicit
, switchHidingImports
) where
import Universum
import qualified Data.List.NonEmpty as NE
import Language.Haskell.Exts (Extension (DisableExtension),
ImportDecl (..),
ImportSpecList (..),
KnownExtension (ImplicitPrelude),
Module (..), ModuleName,
ModuleName (..),
ModulePragma (LanguagePragma),
Name (Ident), SrcSpan (..),
SrcSpanInfo (..), combSpanInfo,
noSrcSpan, prettyExtension)
import Language.Haskell.Names (NameInfo (Import))
import Language.Haskell.Names.GlobalSymbolTable (Table)
import Importify.Syntax.Module (isInsideExport)
import Importify.Syntax.Scoped (InScoped, pullScopedInfo)
getImportModuleName :: ImportDecl l -> ModuleName ()
getImportModuleName ImportDecl{..} = () <$ importModule
isImportImplicit :: ImportDecl l -> Bool
isImportImplicit ImportDecl{ importQualified = True } = False
isImportImplicit ImportDecl{ importSpecs = Nothing } = True
isImportImplicit ImportDecl{ importSpecs = Just (ImportSpecList _ True _) } = True
isImportImplicit _ = False
importReferenceName :: ImportDecl l -> ModuleName ()
importReferenceName ImportDecl{ importAs = Nothing, .. } = () <$ importModule
importReferenceName ImportDecl{ importAs = Just name } = () <$ name
switchHidingImports :: Module SrcSpanInfo -> Module SrcSpanInfo
switchHidingImports (Module ml mhead mpragmas mimports mdecls) =
Module ml
mhead
( LanguagePragma noSrcSpan
[ Ident noSrcSpan
$ prettyExtension
$ DisableExtension ImplicitPrelude
]
: mpragmas)
(mapMaybe unhide mimports)
mdecls
where
unhide :: ImportDecl SrcSpanInfo -> Maybe (ImportDecl SrcSpanInfo)
unhide decl = do
ImportSpecList l isHiding imports <- importSpecs decl
guard isHiding
guard $ not $ isInsideExport mhead (importReferenceName decl)
pure $ decl { importSpecs = Just $ ImportSpecList l False imports }
switchHidingImports m = m
importNamesWithTables :: [InScoped ImportDecl] -> [(ModuleName (), Table)]
importNamesWithTables = map (getImportModuleName &&& getImportedSymbols)
where
getImportedSymbols :: InScoped ImportDecl -> Table
getImportedSymbols = fromImportInfo . pullScopedInfo
fromImportInfo :: NameInfo l -> Table
fromImportInfo (Import dict) = dict
fromImportInfo _ = mempty
importSlice :: [ImportDecl SrcSpanInfo] -> Maybe (Int, Int)
importSlice [] = Nothing
importSlice [ImportDecl{..}] = Just $ startAndEndLines importAnn
importSlice (x:y:xs) = Just $ startAndEndLines
$ combSpanInfo (importAnn x) (importAnn $ NE.last (y :| xs))
startAndEndLines :: SrcSpanInfo -> (Int, Int)
startAndEndLines (SrcSpanInfo SrcSpan{..} _) = (srcSpanStartLine, srcSpanEndLine)