{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Language.PureScript.Ide.Filter
( Filter
, declarationTypeFilter
, namespaceFilter
, moduleFilter
, prefixFilter
, equalityFilter
, applyFilters
) where
import Protolude hiding (isPrefixOf)
import Data.Aeson
import Data.List.NonEmpty (NonEmpty)
import Data.Text (isPrefixOf)
import qualified Language.PureScript.Ide.Filter.Declaration as D
import Language.PureScript.Ide.Types
import Language.PureScript.Ide.Util
import qualified Language.PureScript as P
newtype Filter = Filter (Endo [Module])
deriving (Monoid)
type Module = (P.ModuleName, [IdeDeclarationAnn])
mkFilter :: ([Module] -> [Module]) -> Filter
mkFilter = Filter . Endo
namespaceFilter :: NonEmpty IdeNamespace -> Filter
namespaceFilter namespaces =
mkFilter (filterModuleDecls filterNamespaces)
where
filterNamespaces :: IdeDeclaration -> Bool
filterNamespaces decl = elem (namespaceForDeclaration decl) namespaces
moduleFilter :: [P.ModuleName] -> Filter
moduleFilter =
mkFilter . moduleFilter'
moduleFilter' :: [P.ModuleName] -> [Module] -> [Module]
moduleFilter' moduleIdents = filter (flip elem moduleIdents . fst)
prefixFilter :: Text -> Filter
prefixFilter "" = mkFilter identity
prefixFilter t =
mkFilter $ declarationFilter prefix t
where
prefix :: IdeDeclaration -> Text -> Bool
prefix ed search = search `isPrefixOf` identifierFromIdeDeclaration ed
equalityFilter :: Text -> Filter
equalityFilter =
mkFilter . declarationFilter equality
where
equality :: IdeDeclaration -> Text -> Bool
equality ed search = identifierFromIdeDeclaration ed == search
declarationFilter :: (IdeDeclaration -> Text -> Bool) -> Text -> [Module] -> [Module]
declarationFilter predicate search =
filterModuleDecls (flip predicate search)
declarationTypeFilter :: [D.IdeDeclaration] -> Filter
declarationTypeFilter [] = mkFilter identity
declarationTypeFilter decls =
mkFilter $ filterModuleDecls filterDecls
where
filterDecls :: IdeDeclaration -> Bool
filterDecls decl = D.typeDeclarationForDeclaration decl `elem` decls
filterModuleDecls :: (IdeDeclaration -> Bool) -> [Module] -> [Module]
filterModuleDecls predicate =
filter (not . null . snd) . fmap filterDecls
where
filterDecls (moduleIdent, decls) = (moduleIdent, filter (predicate . discardAnn) decls)
runFilter :: Filter -> [Module] -> [Module]
runFilter (Filter f) = appEndo f
applyFilters :: [Filter] -> [Module] -> [Module]
applyFilters = runFilter . fold
instance FromJSON Filter where
parseJSON = withObject "filter" $ \o -> do
(filter' :: Text) <- o .: "filter"
case filter' of
"exact" -> do
params <- o .: "params"
search <- params .: "search"
return $ equalityFilter search
"prefix" -> do
params <- o.: "params"
search <- params .: "search"
return $ prefixFilter search
"modules" -> do
params <- o .: "params"
modules <- map P.moduleNameFromString <$> params .: "modules"
return $ moduleFilter modules
"namespace" -> do
params <- o .: "params"
namespaces <- params .: "namespaces"
return $ namespaceFilter namespaces
"declarations" -> do
declarations <- o.: "params"
return $ declarationTypeFilter declarations
_ -> mzero