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