module Unused.ResponseFilter ( withOneOccurrence , withLikelihoods , oneOccurence , ignoringPaths , isClassOrModule , autoLowLikelihood , updateMatches ) where import qualified Data.Char as C import qualified Data.List as L import qualified Data.Map.Strict as Map import Unused.ResultsClassifier (Position(..), Matcher(..), LanguageConfiguration(..), LowLikelihoodMatch(..)) import Unused.Types (TermResults(..), TermMatchSet, TermMatch(..), RemovalLikelihood, Removal(..), totalOccurrenceCount, appOccurrenceCount) withOneOccurrence :: TermMatchSet -> TermMatchSet withOneOccurrence = Map.filterWithKey (const oneOccurence) oneOccurence :: TermResults -> Bool oneOccurence = (== 1) . totalOccurrenceCount withLikelihoods :: [RemovalLikelihood] -> TermMatchSet -> TermMatchSet withLikelihoods [] = id withLikelihoods l = Map.filterWithKey (const $ includesLikelihood l) ignoringPaths :: [String] -> TermMatchSet -> TermMatchSet ignoringPaths xs = updateMatches newMatches where newMatches = filter (not . matchesPath . tmPath) matchesPath p = any (`L.isInfixOf` p) xs includesLikelihood :: [RemovalLikelihood] -> TermResults -> Bool includesLikelihood l = (`elem` l) . rLikelihood . trRemoval isClassOrModule :: TermResults -> Bool isClassOrModule = startsWithUpper . trTerm where startsWithUpper [] = False startsWithUpper (a:_) = C.isUpper a autoLowLikelihood :: LanguageConfiguration -> TermResults -> Bool autoLowLikelihood l r = isAllowedTerm r allowedTerms || or anySinglesOkay where allowedTerms = lcAllowedTerms l anySinglesOkay = map (\sm -> classOrModule sm r && matchesToBool (smMatchers sm)) singles singles = lcAutoLowLikelihood l classOrModule = classOrModuleFunction . smClassOrModule matchesToBool :: [Matcher] -> Bool matchesToBool [] = False matchesToBool a = all (`matcherToBool` r) a classOrModuleFunction :: Bool -> TermResults -> Bool classOrModuleFunction True = isClassOrModule classOrModuleFunction False = const True matcherToBool :: Matcher -> TermResults -> Bool matcherToBool (Path p v) = any (positionToTest p v) . paths matcherToBool (Term p v) = positionToTest p v . trTerm matcherToBool (AppOccurrences i) = (== i) . appOccurrenceCount matcherToBool (AllowedTerms ts) = (`isAllowedTerm` ts) positionToTest :: Position -> (String -> String -> Bool) positionToTest StartsWith = L.isPrefixOf positionToTest EndsWith = L.isSuffixOf positionToTest Equals = (==) paths :: TermResults -> [String] paths = fmap tmPath . trMatches updateMatches :: ([TermMatch] -> [TermMatch]) -> TermMatchSet -> TermMatchSet updateMatches fm = Map.map (updateMatchesWith $ fm . trMatches) where updateMatchesWith f tr = tr { trMatches = f tr } isAllowedTerm :: TermResults -> [String] -> Bool isAllowedTerm = elem . trTerm