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 +1/−1
- app/App.hs +7/−2
- app/Main.hs +16/−0
- src/Unused/Aliases.hs +0/−2
- src/Unused/CLI/Search.hs +6/−6
- src/Unused/Cache.hs +13/−7
- src/Unused/GitContext.hs +0/−2
- src/Unused/Projection.hs +0/−2
- src/Unused/ResultsClassifier/Types.hs +1/−2
- src/Unused/TagsSource.hs +0/−2
- src/Unused/TermSearch.hs +21/−8
- src/Unused/TermSearch/Internal.hs +23/−13
- src/Unused/TermSearch/Types.hs +3/−0
- test/Unused/AliasesSpec.hs +0/−2
- test/Unused/TermSearch/InternalSpec.hs +19/−10
- unused.cabal +4/−2
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