packages feed

unused 0.7.0.0 → 0.8.0.0

raw patch · 16 files changed

+114/−61 lines, 16 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Unused.TermSearch: Ag :: SearchBackend
+ Unused.TermSearch: Rg :: SearchBackend
+ Unused.TermSearch: data SearchBackend
+ Unused.TermSearch.Types: Ag :: SearchBackend
+ Unused.TermSearch.Types: Rg :: SearchBackend
+ Unused.TermSearch.Types: data SearchBackend
- Unused.CLI.Search: executeSearch :: SearchRunner -> [SearchTerm] -> IO SearchResults
+ Unused.CLI.Search: executeSearch :: SearchBackend -> SearchRunner -> [SearchTerm] -> IO SearchResults
- Unused.TermSearch: search :: SearchTerm -> IO SearchResults
+ Unused.TermSearch: search :: SearchBackend -> SearchTerm -> IO SearchResults
- Unused.TermSearch.Internal: commandLineOptions :: String -> [String]
+ Unused.TermSearch.Internal: commandLineOptions :: SearchBackend -> String -> [String]
- Unused.TermSearch.Internal: parseSearchResult :: SearchTerm -> String -> Maybe TermMatch
+ Unused.TermSearch.Internal: parseSearchResult :: SearchBackend -> SearchTerm -> String -> Maybe TermMatch

Files

LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2016 Josh Clayton+Copyright (c) 2016-2017 Josh Clayton  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 
app/App.hs view
@@ -21,7 +21,7 @@ import           Unused.ResponseFilter (withOneOccurrence, withLikelihoods, ignoringPaths) import           Unused.ResultsClassifier (ParseConfigError, LanguageConfiguration(..), loadAllConfigurations) import           Unused.TagsSource (TagSearchOutcome, loadTagsFromFile, loadTagsFromPipe)-import           Unused.TermSearch (SearchResults(..), SearchTerm, fromResults)+import           Unused.TermSearch (SearchResults(..), SearchBackend(..), SearchTerm, fromResults) import           Unused.Types (TermMatchSet, RemovalLikelihood(..))  type AppConfig = MonadReader Options@@ -45,6 +45,7 @@     , oWithoutCache :: Bool     , oFromStdIn :: Bool     , oCommitCount :: Maybe Int+    , oSearchBackend :: SearchBackend     }  runProgram :: Options -> IO ()@@ -57,9 +58,13 @@     terms <- termsWithAlternatesFromConfig      liftIO $ renderHeader terms-    results <- withCache . (`executeSearch` terms) =<< searchRunner+    backend <- searchBackend+    results <- withCache . flip (executeSearch backend) terms =<< searchRunner      printResults =<< retrieveGitContext =<< fmap (`parseResults` results) loadAllConfigs++searchBackend :: AppConfig m => m SearchBackend+searchBackend = asks oSearchBackend  termsWithAlternatesFromConfig :: App [SearchTerm] termsWithAlternatesFromConfig = do
app/Main.hs view
@@ -6,6 +6,7 @@ import           Options.Applicative import           Unused.CLI (SearchRunner(..)) import           Unused.Grouping (CurrentGrouping(..))+import           Unused.TermSearch (SearchBackend(..)) import           Unused.Types (RemovalLikelihood(..)) import           Unused.Util (stringToInt) @@ -38,6 +39,7 @@     <*> parseWithoutCache     <*> parseFromStdIn     <*> parseCommitCount+    <*> parseSearchBackend  parseSearchRunner :: Parser SearchRunner parseSearchRunner =@@ -116,3 +118,17 @@     commitParser = optional $ strOption $         long "commits"         <> help "Number of recent commit SHAs to display per token"++parseSearchBackend :: Parser SearchBackend+parseSearchBackend = M.fromMaybe Ag <$> maybeBackend+  where+    maybeBackend = optional $ parseBackend <$> parseBackendOption+    parseBackendOption =+        strOption $+        long "search"+        <> help "[Allowed: ag, rg] Select searching backend"++parseBackend :: String -> SearchBackend+parseBackend "ag" = Ag+parseBackend "rg" = Rg+parseBackend _ = Ag
src/Unused/Aliases.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE OverloadedStrings #-}- module Unused.Aliases     ( groupedTermsAndAliases     , termsAndAliases
src/Unused/CLI/Search.hs view
@@ -16,11 +16,11 @@     U.resetScreen     V.analysisHeader terms -executeSearch :: SearchRunner -> [TS.SearchTerm] -> IO TS.SearchResults-executeSearch runner terms = do+executeSearch :: TS.SearchBackend -> SearchRunner -> [TS.SearchTerm] -> IO TS.SearchResults+executeSearch backend runner terms = do     renderHeader terms-    runSearch runner terms <* U.resetScreen+    runSearch backend runner terms <* U.resetScreen -runSearch :: SearchRunner -> [TS.SearchTerm] -> IO TS.SearchResults-runSearch SearchWithProgress    = I.progressWithIndicator TS.search I.createProgressBar-runSearch SearchWithoutProgress = I.progressWithIndicator TS.search I.createSpinner+runSearch :: TS.SearchBackend -> SearchRunner -> [TS.SearchTerm] -> IO TS.SearchResults+runSearch b SearchWithProgress    = I.progressWithIndicator (TS.search b) I.createProgressBar+runSearch b SearchWithoutProgress = I.progressWithIndicator (TS.search b) I.createSpinner
src/Unused/Cache.hs view
@@ -23,21 +23,19 @@ writeCache :: ToRecord a => [a] -> Cache [a] writeCache [] = return [] writeCache contents = do-    liftIO $ D.createDirectoryIfMissing True cacheDirectory-    (CacheFileName fileName) <- ask-    liftIO $ BS.writeFile fileName $ encode contents+    ensureCacheDirectoryExists+    writeContentsToCacheFile contents =<< ask     return contents  readCache :: FromRecord a => Cache (Maybe [a])-readCache = do-    (CacheFileName fileName) <- ask-+readCache =     either         (const Nothing)         (processCsv . decode NoHeader)-        <$> liftIO (safeReadFile fileName)+        <$> (readFromCache =<< ask)   where     processCsv = either (const Nothing) (Just . V.toList)+    readFromCache (CacheFileName fileName) = liftIO $ safeReadFile fileName  cacheFileName :: String -> IO (Either FingerprintOutcome CacheFileName) cacheFileName context = do@@ -48,3 +46,11 @@  cacheDirectory :: String cacheDirectory = "tmp/unused"++ensureCacheDirectoryExists :: Cache ()+ensureCacheDirectoryExists =+    liftIO $ D.createDirectoryIfMissing True cacheDirectory++writeContentsToCacheFile :: ToRecord a => [a] -> CacheFileName -> Cache ()+writeContentsToCacheFile contents (CacheFileName fileName) =+    liftIO $ BS.writeFile fileName $ encode contents
src/Unused/GitContext.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE OverloadedStrings #-}- module Unused.GitContext     ( gitContextForResults     ) where
src/Unused/Projection.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE OverloadedStrings #-}- module Unused.Projection where  import qualified Data.Bifunctor as BF
src/Unused/ResultsClassifier/Types.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleInstances #-}  module Unused.ResultsClassifier.Types@@ -14,8 +13,8 @@ import qualified Control.Monad as M import qualified Data.HashMap.Strict as HM import qualified Data.List as L-import qualified Data.Text as T import           Data.Text (Text)+import qualified Data.Text as T import           Data.Yaml (FromJSON(..), (.:), (.:?), (.!=)) import qualified Data.Yaml as Y import           Unused.Projection
src/Unused/TagsSource.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE OverloadedStrings #-}- module Unused.TagsSource     ( TagSearchOutcome(..)     , loadTagsFromFile
src/Unused/TermSearch.hs view
@@ -1,20 +1,33 @@ module Unused.TermSearch     ( SearchResults(..)+    , SearchBackend(..)     , SearchTerm     , search     ) where  import qualified Data.Maybe as M+import           GHC.IO.Exception (ExitCode(ExitSuccess)) import qualified System.Process as P import           Unused.TermSearch.Internal (commandLineOptions, parseSearchResult)-import           Unused.TermSearch.Types (SearchResults(..))+import           Unused.TermSearch.Types (SearchResults(..), SearchBackend(..)) import           Unused.Types (SearchTerm, searchTermToString) -search :: SearchTerm -> IO SearchResults-search t =-    SearchResults . M.mapMaybe (parseSearchResult t) <$> (lines <$> ag (searchTermToString t))+search :: SearchBackend -> SearchTerm -> IO SearchResults+search backend t =+    SearchResults . M.mapMaybe (parseSearchResult backend t) <$> (lines <$> performSearch backend (searchTermToString t)) -ag :: String -> IO String-ag t = do-  (_, results, _) <- P.readProcessWithExitCode "ag" (commandLineOptions t) ""-  return results+performSearch :: SearchBackend -> String -> IO String+performSearch b t = extractSearchResults b <$> searchOutcome+  where+    searchOutcome =+        P.readProcessWithExitCode+            (backendToCommand b)+            (commandLineOptions b t)+            ""+    backendToCommand Rg = "rg"+    backendToCommand Ag = "ag"++extractSearchResults :: SearchBackend -> (ExitCode, String, String) -> String+extractSearchResults Rg (ExitSuccess, stdout, _) = stdout+extractSearchResults Rg (_, _, stderr) = stderr+extractSearchResults Ag (_, stdout, _) = stdout
src/Unused/TermSearch/Internal.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE OverloadedStrings #-}- module Unused.TermSearch.Internal     ( commandLineOptions     , parseSearchResult@@ -8,26 +6,38 @@ import qualified Data.Char as C import qualified Data.Maybe as M import qualified Data.Text as T+import           Unused.TermSearch.Types (SearchBackend(..)) import           Unused.Types (SearchTerm(..), TermMatch(..)) import           Unused.Util (stringToInt) -commandLineOptions :: String -> [String]-commandLineOptions t =+commandLineOptions :: SearchBackend -> String -> [String]+commandLineOptions backend t =     if regexSafeTerm t-        then ["(\\W|^)" ++ t ++ "(\\W|$)", "."] ++ baseFlags-        else [t, ".", "-Q"] ++ baseFlags-  where-    baseFlags = ["-c", "--ackmate", "--ignore-dir", "tmp/unused"]+        then regexFlags backend t ++ baseFlags backend+        else nonRegexFlags backend t ++ baseFlags backend -parseSearchResult :: SearchTerm -> String -> Maybe TermMatch-parseSearchResult term =-    maybeTermMatch . map T.unpack . T.splitOn ":" . T.pack+parseSearchResult :: SearchBackend -> SearchTerm -> String -> Maybe TermMatch+parseSearchResult backend term =+    maybeTermMatch backend . map T.unpack . T.splitOn ":" . T.pack   where-    maybeTermMatch [_, path, count] = Just $ toTermMatch term path $ countInt count-    maybeTermMatch _ = Nothing+    maybeTermMatch Rg [path, count] = Just $ toTermMatch term path $ countInt count+    maybeTermMatch Rg _ = Nothing+    maybeTermMatch Ag [_, path, count] = Just $ toTermMatch term path $ countInt count+    maybeTermMatch Ag _ = Nothing     countInt = M.fromMaybe 0 . stringToInt     toTermMatch (OriginalTerm t) path = TermMatch t path Nothing     toTermMatch (AliasTerm t a) path = TermMatch t path (Just a)  regexSafeTerm :: String -> Bool regexSafeTerm = all (\c -> C.isAlphaNum c || c == '_' || c == '-')++nonRegexFlags :: SearchBackend -> String -> [String]+nonRegexFlags Rg t = [t, ".", "-F"]+nonRegexFlags Ag t = [t, ".", "-Q"]++baseFlags :: SearchBackend -> [String]+baseFlags Rg = ["-c", "-j", "1"]+baseFlags Ag = ["-c", "--ackmate", "--ignore-dir", "tmp/unused"]++regexFlags :: SearchBackend -> String -> [String]+regexFlags _ t = ["(\\W|^)" ++ t ++ "(\\W|$)", "."]
src/Unused/TermSearch/Types.hs view
@@ -2,8 +2,11 @@  module Unused.TermSearch.Types     ( SearchResults(..)+    , SearchBackend(..)     ) where  import Unused.Types (TermMatch)++data SearchBackend = Ag | Rg  newtype SearchResults = SearchResults { fromResults :: [TermMatch] } deriving (Monoid)
test/Unused/AliasesSpec.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE OverloadedStrings #-}- module Unused.AliasesSpec where  import Data.Monoid ((<>))
test/Unused/TermSearch/InternalSpec.hs view
@@ -5,6 +5,7 @@  import Test.Hspec import Unused.TermSearch.Internal+import Unused.TermSearch.Types import Unused.Types  main :: IO ()@@ -14,17 +15,25 @@ spec = parallel $ do     describe "commandLineOptions" $ do         it "does not use regular expressions when the term contains non-word characters" $ do-            commandLineOptions "can_do_things?" `shouldBe` ["can_do_things?", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]-            commandLineOptions "no_way!" `shouldBe` ["no_way!", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]-            commandLineOptions "[]=" `shouldBe` ["[]=", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]-            commandLineOptions "window.globalOverride" `shouldBe` ["window.globalOverride", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]+            commandLineOptions Ag "can_do_things?" `shouldBe` ["can_do_things?", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]+            commandLineOptions Ag "no_way!" `shouldBe` ["no_way!", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]+            commandLineOptions Ag "[]=" `shouldBe` ["[]=", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]+            commandLineOptions Ag "window.globalOverride" `shouldBe` ["window.globalOverride", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"] -        it "uses regular expression match with surrounding non-word matches for accuracy" $-            commandLineOptions "awesome_method" `shouldBe` ["(\\W|^)awesome_method(\\W|$)", ".", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]+            commandLineOptions Rg "can_do_things?" `shouldBe` ["can_do_things?", ".", "-F", "-c", "-j", "1"]+            commandLineOptions Rg "no_way!" `shouldBe` ["no_way!", ".", "-F", "-c", "-j", "1"]+            commandLineOptions Rg "[]=" `shouldBe` ["[]=", ".", "-F", "-c", "-j", "1"]+            commandLineOptions Rg "window.globalOverride" `shouldBe` ["window.globalOverride", ".", "-F", "-c", "-j", "1"] +        it "uses regular expression match with surrounding non-word matches for accuracy" $ do+            commandLineOptions Ag "awesome_method" `shouldBe` ["(\\W|^)awesome_method(\\W|$)", ".", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]+            commandLineOptions Rg "awesome_method" `shouldBe` ["(\\W|^)awesome_method(\\W|$)", ".", "-c", "-j", "1"]+     describe "parseSearchResult" $ do-        it "parses normal results from `ag` to a TermMatch" $-            parseSearchResult (OriginalTerm "method_name") ":app/models/foo.rb:123" `shouldBe` (Just $ TermMatch "method_name" "app/models/foo.rb" Nothing 123)+        it "parses normal results from `ag` to a TermMatch" $ do+            parseSearchResult Ag (OriginalTerm "method_name") ":app/models/foo.rb:123" `shouldBe` (Just $ TermMatch "method_name" "app/models/foo.rb" Nothing 123)+            parseSearchResult Rg (OriginalTerm "method_name") "app/models/foo.rb:123" `shouldBe` (Just $ TermMatch "method_name" "app/models/foo.rb" Nothing 123) -        it "returns Nothing when it cannot parse" $-            parseSearchResult (OriginalTerm "method_name") "" `shouldBe` Nothing+        it "returns Nothing when it cannot parse" $ do+            parseSearchResult Ag (OriginalTerm "method_name") "" `shouldBe` Nothing+            parseSearchResult Rg (OriginalTerm "method_name") "" `shouldBe` Nothing
unused.cabal view
@@ -1,5 +1,5 @@ name:                unused-version:             0.7.0.0+version:             0.8.0.0 synopsis:            A command line tool to identify unused code. description:         Please see README.md homepage:            https://github.com/joshuaclayton/unused#readme@@ -7,7 +7,7 @@ license-file:        LICENSE author:              Josh Clayton maintainer:          sayhi@joshuaclayton.me-copyright:           2016 Josh Clayton+copyright:           2016-2017 Josh Clayton category:            CLI build-type:          Simple -- extra-source-files:@@ -84,6 +84,7 @@                      , file-embed   ghc-options:         -Wall   default-language:    Haskell2010+  default-extensions:  OverloadedStrings  executable unused   hs-source-dirs:      app@@ -117,6 +118,7 @@                      , Unused.AliasesSpec   ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall   default-language:    Haskell2010+  default-extensions:  OverloadedStrings  source-repository head   type:     git