mirror of
https://github.com/joshuaclayton/unused.git
synced 2024-07-14 16:10:28 +03:00
Replace Cabal-managed config loading with FileEmbed
This uses the file-embed package and TemplateHaskell to load custom configuration during compilation instead of loading it at runtime.
This commit is contained in:
parent
8b50f5dd68
commit
fde9f69a64
@ -1,31 +1,32 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
|
||||
module Unused.ResultsClassifier.Config
|
||||
( loadConfig
|
||||
, loadAllConfigurations
|
||||
) where
|
||||
|
||||
import qualified Data.Bifunctor as BF
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.Either as E
|
||||
import qualified Data.FileEmbed as FE
|
||||
import qualified Data.Yaml as Y
|
||||
import qualified Paths_unused as Paths
|
||||
import qualified System.Directory as D
|
||||
import System.FilePath ((</>))
|
||||
import Unused.ResultsClassifier.Types (LanguageConfiguration, ParseConfigError(..))
|
||||
import Unused.Util (safeReadFile)
|
||||
|
||||
loadConfig :: IO (Either String [LanguageConfiguration])
|
||||
loadConfig = do
|
||||
configFileName <- Paths.getDataFileName ("data" </> "config.yml")
|
||||
loadConfig :: Either String [LanguageConfiguration]
|
||||
loadConfig = Y.decodeEither defaultConfigFile
|
||||
|
||||
either
|
||||
(const $ Left "default config not found")
|
||||
Y.decodeEither
|
||||
<$> safeReadFile configFileName
|
||||
defaultConfigFile :: BS.ByteString
|
||||
defaultConfigFile = $(FE.embedFile "data/config.yml")
|
||||
|
||||
loadAllConfigurations :: IO (Either [ParseConfigError] [LanguageConfiguration])
|
||||
loadAllConfigurations = do
|
||||
homeDir <- D.getHomeDirectory
|
||||
|
||||
defaultConfig <- addSourceToLeft "default config" <$> loadConfig
|
||||
let defaultConfig = addSourceToLeft "default config" loadConfig
|
||||
|
||||
localConfig <- loadConfigFromFile ".unused.yml"
|
||||
userConfig <- loadConfigFromFile $ homeDir </> ".unused.yml"
|
||||
|
||||
|
@ -16,10 +16,10 @@ spec = parallel $
|
||||
describe "calculateLikelihood" $ do
|
||||
it "prefers language-specific checks first" $ do
|
||||
let railsMatches = [ TermMatch "ApplicationController" "app/controllers/application_controller.rb" Nothing 1 ]
|
||||
removalLikelihood' railsMatches `shouldReturn` Low
|
||||
removalLikelihood' railsMatches `shouldBe` Low
|
||||
|
||||
let elixirMatches = [ TermMatch "AwesomeView" "web/views/awesome_view.ex" Nothing 1 ]
|
||||
removalLikelihood' elixirMatches `shouldReturn` Low
|
||||
removalLikelihood' elixirMatches `shouldBe` Low
|
||||
|
||||
it "weighs widely-used methods as low likelihood" $ do
|
||||
let matches = [ TermMatch "full_name" "app/models/user.rb" Nothing 4
|
||||
@ -28,19 +28,19 @@ spec = parallel $
|
||||
, TermMatch "full_name" "spec/models/user_spec.rb" Nothing 10
|
||||
]
|
||||
|
||||
removalLikelihood' matches `shouldReturn` Low
|
||||
removalLikelihood' matches `shouldBe` Low
|
||||
|
||||
it "weighs only-occurs-once methods as high likelihood" $ do
|
||||
let matches = [ TermMatch "obscure_method" "app/models/user.rb" Nothing 1 ]
|
||||
|
||||
removalLikelihood' matches `shouldReturn` High
|
||||
removalLikelihood' matches `shouldBe` High
|
||||
|
||||
it "weighs methods that seem to only be tested and never used as high likelihood" $ do
|
||||
let matches = [ TermMatch "obscure_method" "app/models/user.rb" Nothing 1
|
||||
, TermMatch "obscure_method" "spec/models/user_spec.rb" Nothing 5
|
||||
]
|
||||
|
||||
removalLikelihood' matches `shouldReturn` High
|
||||
removalLikelihood' matches `shouldBe` High
|
||||
|
||||
it "weighs methods that seem to only be tested and used in one other area as medium likelihood" $ do
|
||||
let matches = [ TermMatch "obscure_method" "app/models/user.rb" Nothing 1
|
||||
@ -49,14 +49,15 @@ spec = parallel $
|
||||
, TermMatch "obscure_method" "spec/controllers/user_controller_spec.rb" Nothing 5
|
||||
]
|
||||
|
||||
removalLikelihood' matches `shouldReturn` Medium
|
||||
removalLikelihood' matches `shouldBe` Medium
|
||||
|
||||
it "doesn't mis-categorize allowed terms from different languages" $ do
|
||||
let matches = [ TermMatch "t" "web/models/foo.ex" Nothing 1 ]
|
||||
|
||||
removalLikelihood' matches `shouldReturn` High
|
||||
removalLikelihood' matches `shouldBe` High
|
||||
|
||||
removalLikelihood' :: [TermMatch] -> IO RemovalLikelihood
|
||||
removalLikelihood' ms = do
|
||||
(Right config) <- loadConfig
|
||||
return $ rLikelihood $ trRemoval $ calculateLikelihood config $ resultsFromMatches ms
|
||||
removalLikelihood' :: [TermMatch] -> RemovalLikelihood
|
||||
removalLikelihood' =
|
||||
rLikelihood . trRemoval . calculateLikelihood config . resultsFromMatches
|
||||
where
|
||||
(Right config) = loadConfig
|
||||
|
@ -23,7 +23,7 @@ spec = parallel $
|
||||
let r2Matches = [ TermMatch "other" "app/path/other.rb" Nothing 1 ]
|
||||
let r2Results = TermResults "other" ["other"] r2Matches (Occurrences 0 0) (Occurrences 1 1) (Occurrences 1 1) (Removal High "occurs once") Nothing
|
||||
|
||||
(Right config) <- loadConfig
|
||||
let (Right config) = loadConfig
|
||||
|
||||
let result = parseResults config $ SearchResults $ r1Matches ++ r2Matches
|
||||
|
||||
@ -50,7 +50,7 @@ spec = parallel $
|
||||
]
|
||||
|
||||
|
||||
(Right config) <- loadConfig
|
||||
let (Right config) = loadConfig
|
||||
let searchResults = r1Matches ++ r2Matches
|
||||
|
||||
let result = parseResults config $ SearchResults searchResults
|
||||
@ -60,6 +60,6 @@ spec = parallel $
|
||||
Map.fromList [ ("admin?|be_admin", results) ]
|
||||
|
||||
it "handles empty input" $ do
|
||||
(Right config) <- loadConfig
|
||||
let (Right config) = loadConfig
|
||||
let result = parseResults config $ SearchResults []
|
||||
result `shouldBe` Map.fromList []
|
||||
|
@ -19,114 +19,114 @@ spec = parallel $ do
|
||||
let match = TermMatch "ApplicationController" "app/controllers/application_controller.rb" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
railsAutoLowLikelihood result `shouldReturn` True
|
||||
railsAutoLowLikelihood result `shouldBe` True
|
||||
|
||||
it "allows helpers" $ do
|
||||
let match = TermMatch "ApplicationHelper" "app/helpers/application_helper.rb" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
railsAutoLowLikelihood result `shouldReturn` True
|
||||
railsAutoLowLikelihood result `shouldBe` True
|
||||
|
||||
it "allows migrations" $ do
|
||||
let match = TermMatch "CreateUsers" "db/migrate/20160101120000_create_users.rb" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
railsAutoLowLikelihood result `shouldReturn` True
|
||||
railsAutoLowLikelihood result `shouldBe` True
|
||||
|
||||
it "disallows service objects" $ do
|
||||
let match = TermMatch "CreatePostWithNotifications" "app/services/create_post_with_notifications.rb" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
railsAutoLowLikelihood result `shouldReturn` False
|
||||
railsAutoLowLikelihood result `shouldBe` False
|
||||
|
||||
it "disallows methods" $ do
|
||||
let match = TermMatch "my_method" "app/services/create_post_with_notifications.rb" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
railsAutoLowLikelihood result `shouldReturn` False
|
||||
railsAutoLowLikelihood result `shouldBe` False
|
||||
|
||||
it "disallows models that occur in migrations" $ do
|
||||
let model = TermMatch "User" "app/models/user.rb" Nothing 1
|
||||
let migration = TermMatch "User" "db/migrate/20160101120000_create_users.rb" Nothing 1
|
||||
let result = resultsFromMatches [model, migration]
|
||||
|
||||
railsAutoLowLikelihood result `shouldReturn` False
|
||||
railsAutoLowLikelihood result `shouldBe` False
|
||||
|
||||
it "allows matches intermixed with other results" $ do
|
||||
let appToken = TermMatch "ApplicationHelper" "app/helpers/application_helper.rb" Nothing 1
|
||||
let testToken = TermMatch "ApplicationHelper" "spec/helpers/application_helper_spec.rb" Nothing 10
|
||||
let result = resultsFromMatches [appToken, testToken]
|
||||
|
||||
railsAutoLowLikelihood result `shouldReturn` True
|
||||
railsAutoLowLikelihood result `shouldBe` True
|
||||
|
||||
describe "elixirAutoLowLikelihood" $ do
|
||||
it "disallows controllers" $ do
|
||||
let match = TermMatch "PageController" "web/controllers/page_controller.rb" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
elixirAutoLowLikelihood result `shouldReturn` False
|
||||
elixirAutoLowLikelihood result `shouldBe` False
|
||||
|
||||
it "allows views" $ do
|
||||
let match = TermMatch "PageView" "web/views/page_view.rb" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
elixirAutoLowLikelihood result `shouldReturn` True
|
||||
elixirAutoLowLikelihood result `shouldBe` True
|
||||
|
||||
it "allows migrations" $ do
|
||||
let match = TermMatch "CreateUsers" "priv/repo/migrations/20160101120000_create_users.exs" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
elixirAutoLowLikelihood result `shouldReturn` True
|
||||
elixirAutoLowLikelihood result `shouldBe` True
|
||||
|
||||
it "allows tests" $ do
|
||||
let match = TermMatch "UserTest" "test/models/user_test.exs" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
elixirAutoLowLikelihood result `shouldReturn` True
|
||||
elixirAutoLowLikelihood result `shouldBe` True
|
||||
|
||||
it "allows Mixfile" $ do
|
||||
let match = TermMatch "Mixfile" "mix.exs" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
elixirAutoLowLikelihood result `shouldReturn` True
|
||||
elixirAutoLowLikelihood result `shouldBe` True
|
||||
|
||||
it "allows __using__" $ do
|
||||
let match = TermMatch "__using__" "web/web.ex" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
elixirAutoLowLikelihood result `shouldReturn` True
|
||||
elixirAutoLowLikelihood result `shouldBe` True
|
||||
|
||||
it "disallows service modules" $ do
|
||||
let match = TermMatch "CreatePostWithNotifications" "web/services/create_post_with_notifications.ex" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
elixirAutoLowLikelihood result `shouldReturn` False
|
||||
elixirAutoLowLikelihood result `shouldBe` False
|
||||
|
||||
it "disallows functions" $ do
|
||||
let match = TermMatch "my_function" "web/services/create_post_with_notifications.ex" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
elixirAutoLowLikelihood result `shouldReturn` False
|
||||
elixirAutoLowLikelihood result `shouldBe` False
|
||||
|
||||
it "allows matches intermixed with other results" $ do
|
||||
let appToken = TermMatch "UserView" "web/views/user_view.ex" Nothing 1
|
||||
let testToken = TermMatch "UserView" "test/views/user_view_test.exs" Nothing 10
|
||||
let result = resultsFromMatches [appToken, testToken]
|
||||
|
||||
elixirAutoLowLikelihood result `shouldReturn` True
|
||||
elixirAutoLowLikelihood result `shouldBe` True
|
||||
|
||||
describe "haskellAutoLowLikelihood" $ do
|
||||
it "allows instance" $ do
|
||||
let match = TermMatch "instance" "src/Lib/Types.hs" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
haskellAutoLowLikelihood result `shouldReturn` True
|
||||
haskellAutoLowLikelihood result `shouldBe` True
|
||||
|
||||
it "allows items in the *.cabal file" $ do
|
||||
let match = TermMatch "Lib.SomethingSpec" "lib.cabal" Nothing 1
|
||||
let result = resultsFromMatches [match]
|
||||
|
||||
haskellAutoLowLikelihood result `shouldReturn` True
|
||||
haskellAutoLowLikelihood result `shouldBe` True
|
||||
|
||||
describe "autoLowLikelihood" $
|
||||
it "doesn't qualify as low when no matchers are present in a language config" $ do
|
||||
@ -136,18 +136,17 @@ spec = parallel $ do
|
||||
|
||||
autoLowLikelihood languageConfig result `shouldBe` False
|
||||
|
||||
configByName :: String -> IO LanguageConfiguration
|
||||
configByName s = do
|
||||
(Right config) <- loadConfig
|
||||
let (Just config') = find ((==) s . lcName) config
|
||||
configByName :: String -> LanguageConfiguration
|
||||
configByName s = config'
|
||||
where
|
||||
(Right config) = loadConfig
|
||||
(Just config') = find ((==) s . lcName) config
|
||||
|
||||
return config'
|
||||
railsAutoLowLikelihood :: TermResults -> Bool
|
||||
railsAutoLowLikelihood = autoLowLikelihood (configByName "Rails")
|
||||
|
||||
railsAutoLowLikelihood :: TermResults -> IO Bool
|
||||
railsAutoLowLikelihood r = (`autoLowLikelihood` r) <$> configByName "Rails"
|
||||
elixirAutoLowLikelihood :: TermResults -> Bool
|
||||
elixirAutoLowLikelihood = autoLowLikelihood (configByName "Phoenix")
|
||||
|
||||
elixirAutoLowLikelihood :: TermResults -> IO Bool
|
||||
elixirAutoLowLikelihood r = (`autoLowLikelihood` r) <$> configByName "Phoenix"
|
||||
|
||||
haskellAutoLowLikelihood :: TermResults -> IO Bool
|
||||
haskellAutoLowLikelihood r = (`autoLowLikelihood` r) <$> configByName "Haskell"
|
||||
haskellAutoLowLikelihood :: TermResults -> Bool
|
||||
haskellAutoLowLikelihood = autoLowLikelihood (configByName "Haskell")
|
||||
|
@ -12,7 +12,6 @@ category: CLI
|
||||
build-type: Simple
|
||||
-- extra-source-files:
|
||||
cabal-version: >=1.10
|
||||
data-files: data/config.yml
|
||||
|
||||
library
|
||||
hs-source-dirs: src
|
||||
@ -60,7 +59,6 @@ library
|
||||
, Unused.CLI.ProgressIndicator
|
||||
, Unused.CLI.ProgressIndicator.Internal
|
||||
, Unused.CLI.ProgressIndicator.Types
|
||||
other-modules: Paths_unused
|
||||
build-depends: base >= 4.7 && < 5
|
||||
, process
|
||||
, containers
|
||||
@ -81,6 +79,7 @@ library
|
||||
, transformers
|
||||
, megaparsec
|
||||
, inflections
|
||||
, file-embed
|
||||
ghc-options: -Wall
|
||||
default-language: Haskell2010
|
||||
|
||||
@ -114,7 +113,6 @@ test-suite unused-test
|
||||
, Unused.UtilSpec
|
||||
, Unused.Cache.FindArgsFromIgnoredPathsSpec
|
||||
, Unused.AliasesSpec
|
||||
, Paths_unused
|
||||
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall
|
||||
default-language: Haskell2010
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user