Looking better

This commit is contained in:
Ollie Charles 2020-03-14 17:15:11 +00:00
parent d4e1d84472
commit 6a1f35573d
12 changed files with 322 additions and 413 deletions

17
atomic-write.nix Normal file
View File

@ -0,0 +1,17 @@
{ mkDerivation, base, bytestring, directory, filepath, hspec
, stdenv, temporary, text, unix-compat
}:
mkDerivation {
pname = "atomic-write";
version = "0.2.0.7";
sha256 = "b5f5c77884bc0332306fab89acf1c8a8582d76eabaa303c91b1c4072621c960d";
libraryHaskellDepends = [
base bytestring directory filepath temporary text unix-compat
];
testHaskellDepends = [
base bytestring filepath hspec temporary text unix-compat
];
homepage = "https://github.com/stackbuilders/atomic-write";
description = "Atomically write to a file";
license = stdenv.lib.licenses.mit;
}

21
cborg-json.nix Normal file
View File

@ -0,0 +1,21 @@
{ mkDerivation, aeson, aeson-pretty, base, bytestring, cborg
, criterion, deepseq, directory, process, scientific, stdenv, text
, unordered-containers, vector, zlib
}:
mkDerivation {
pname = "cborg-json";
version = "0.2.2.0";
sha256 = "ab68a2457cb71a76699d7a8df07a880ea70c51d2c1a891b12669ca9ccfa7517b";
libraryHaskellDepends = [
aeson aeson-pretty base cborg scientific text unordered-containers
vector
];
benchmarkHaskellDepends = [
aeson base bytestring cborg criterion deepseq directory process
zlib
];
doCheck = false;
homepage = "https://github.com/well-typed/cborg";
description = "A library for encoding JSON as CBOR";
license = stdenv.lib.licenses.bsd3;
}

22
cborg.nix Normal file
View File

@ -0,0 +1,22 @@
{ mkDerivation, aeson, array, base, base-orphans, base16-bytestring
, base64-bytestring, bytestring, containers, deepseq, ghc-prim
, half, integer-gmp, primitive, QuickCheck, random, scientific
, stdenv, tasty, tasty-hunit, tasty-quickcheck, text, vector
}:
mkDerivation {
pname = "cborg";
version = "0.2.2.1";
sha256 = "ba920d368892fe14e048cd6ac4270ce4ea1aea0fb6a4998c5c97fe106e6c6183";
libraryHaskellDepends = [
array base bytestring containers deepseq ghc-prim half integer-gmp
primitive text
];
testHaskellDepends = [
aeson array base base-orphans base16-bytestring base64-bytestring
bytestring deepseq half QuickCheck random scientific tasty
tasty-hunit tasty-quickcheck text vector
];
doCheck = false;
description = "Concise Binary Object Representation (CBOR)";
license = stdenv.lib.licenses.bsd3;
}

51
dhall.nix Normal file
View File

@ -0,0 +1,51 @@
{ mkDerivation, aeson, aeson-pretty, ansi-terminal, atomic-write
, base, bytestring, case-insensitive, cborg, cborg-json, containers
, contravariant, cryptonite, data-fix, deepseq, Diff, directory
, doctest, dotgen, either, exceptions, filepath, foldl, gauge
, generic-random, hashable, haskeline, http-client, http-client-tls
, http-types, lens-family-core, megaparsec, memory, mockery, mtl
, network-uri, optparse-applicative, parser-combinators, parsers
, pretty-simple, prettyprinter, prettyprinter-ansi-terminal
, profunctors, QuickCheck, quickcheck-instances, repline
, scientific, semigroups, serialise, special-values, spoon, stdenv
, tasty, tasty-expected-failure, tasty-hunit, tasty-quickcheck
, template-haskell, text, th-lift-instances, transformers
, transformers-compat, turtle, unordered-containers, uri-encode
, vector
}:
mkDerivation {
pname = "dhall";
version = "1.30.0";
sha256 = "f2be9599ddd88602c1577b0ca57849c9827c9e700e105102cecc17c56b7c4a81";
revision = "1";
editedCabalFile = "1pazhb3h1rabb80wxh29k5yfp915zqp1gmhcv4mx7ibzv9zw7miq";
isLibrary = true;
isExecutable = true;
libraryHaskellDepends = [
aeson aeson-pretty ansi-terminal atomic-write base bytestring
case-insensitive cborg cborg-json containers contravariant
cryptonite data-fix deepseq Diff directory dotgen either exceptions
filepath hashable haskeline http-client http-client-tls http-types
lens-family-core megaparsec memory mtl network-uri
optparse-applicative parser-combinators parsers pretty-simple
prettyprinter prettyprinter-ansi-terminal profunctors repline
scientific serialise template-haskell text th-lift-instances
transformers transformers-compat unordered-containers uri-encode
vector
];
executableHaskellDepends = [ base ];
testHaskellDepends = [
base bytestring cborg containers data-fix deepseq directory doctest
either filepath foldl generic-random lens-family-core megaparsec
mockery prettyprinter QuickCheck quickcheck-instances scientific
semigroups serialise special-values spoon tasty
tasty-expected-failure tasty-hunit tasty-quickcheck text
transformers turtle unordered-containers vector
];
benchmarkHaskellDepends = [
base bytestring containers directory gauge serialise text
];
doCheck = false;
description = "A configuration language guaranteed to terminate";
license = stdenv.lib.licenses.bsd3;
}

View File

@ -1,235 +1,2 @@
{-# language ApplicativeDo #-}
{-# language BlockArguments #-}
{-# language FlexibleContexts #-}
{-# language LambdaCase #-}
{-# language NamedFieldPuns #-}
{-# language OverloadedStrings #-}
{-# language PackageImports #-}
module Main ( main ) where
import "base" Control.Applicative ( (<**>), liftA2, many, some )
import "base" Control.Monad ( guard )
import "base" Control.Monad.IO.Class ( liftIO )
import "base" Data.Foldable ( fold, for_ )
import qualified "containers" Data.Map.Strict as Map
import "containers" Data.Set ( Set )
import qualified "containers" Data.Set as Set
import "directory" System.Directory ( doesPathExist, withCurrentDirectory, canonicalizePath, listDirectory, doesFileExist, doesDirectoryExist )
import "filepath" System.FilePath ( isExtensionOf )
import "ghc" FastString ( unpackFS )
import "ghc" HieBin ( HieFileResult( HieFileResult, hie_file_result ) )
import "ghc" HieBin ( readHieFile )
import "ghc" Module
( DefUnitId( DefUnitId )
, Module( Module )
, UnitId( DefiniteUnitId )
, mkModuleName
, moduleUnitId
, stringToInstalledUnitId
, unitIdFS
)
import "ghc" NameCache ( initNameCache )
import "ghc" OccName
( mkOccName
, occNameString
, varName
)
import "ghc" SrcLoc ( srcLocLine, srcLocCol, realSrcSpanStart )
import "ghc" UniqSupply ( mkSplitUniqSupply )
import "optparse-applicative" Options.Applicative
( Parser
, execParser
, fullDesc
, header
, help
, helper
, info
, long
, maybeReader
, metavar
, option
, strArgument
, strOption
)
import "transformers" Control.Monad.Trans.State.Strict ( execStateT )
import Weeder
data CommandLineArguments =
CommandLineArguments
{ hiePaths :: [ FilePath ]
, roots :: Set Root
, units :: Set String
}
commandLineArgumentsParser :: Parser CommandLineArguments
commandLineArgumentsParser = do
hiePaths <-
some
( strArgument
( metavar "HIE"
<> help "A path to a .hie file, or a directory containing .hie files"
)
)
roots <-
many
( option
( maybeReader \str ->
case words str of
[ unitId, moduleName, sym ] ->
return $
DeclarationRoot $
Declaration
{ declModule =
Module
( DefiniteUnitId ( DefUnitId ( stringToInstalledUnitId unitId ) ) )
( mkModuleName moduleName )
, declOccName =
mkOccName varName sym
}
[ unitId, moduleName ] ->
return $
ModuleRoot $
Module
( DefiniteUnitId ( DefUnitId ( stringToInstalledUnitId unitId ) ) )
( mkModuleName moduleName )
_ ->
Nothing
)
( long "root"
<> help "A symbol that should be added to the root set. Symbols are of the form unit$Module.symbol"
)
)
units <-
many
( strOption
( long "report-unit"
<> help "Report unused declarations in this unit. If ommitted, all units will be reported. Can be supplied multiple times."
)
)
return
CommandLineArguments
{ hiePaths
, roots = Set.fromList roots
, units = Set.fromList units
}
main :: IO ()
main = do
CommandLineArguments{ hiePaths, roots, units } <-
execParser
( info
( commandLineArgumentsParser <**> helper )
( fullDesc
<> header "Find unused declarations in Haskell projects"
)
)
hieFilePaths <-
foldMap getHieFilesIn hiePaths
nameCache <- do
uniqSupply <- mkSplitUniqSupply 'z'
return ( initNameCache uniqSupply [] )
analysis <-
flip execStateT emptyAnalysis do
for_ hieFilePaths \hieFilePath -> do
( HieFileResult{ hie_file_result }, _ ) <-
liftIO ( readHieFile nameCache hieFilePath )
analyseHieFile hie_file_result
let
reachableSet =
reachable
analysis
( roots <> Set.map DeclarationRoot ( implicitRoots analysis ) )
dead =
Set.filter
( \d ->
if Set.null units then
True
else
Set.member
( unpackFS ( unitIdFS ( moduleUnitId ( declModule d ) ) ) )
units
)
( allDeclarations analysis Set.\\ reachableSet )
warnings =
Map.unionsWith (++) $
foldMap
( \d ->
fold $ do
moduleFilePath <- Map.lookup ( declModule d ) ( modulePaths analysis )
spans <- Map.lookup d ( declarationSites analysis )
guard $ not $ null spans
return [ Map.singleton moduleFilePath ( liftA2 (,) (Set.toList spans) (pure d) ) ]
)
dead
for_ ( Map.toList warnings ) \( path, declarations ) ->
for_ declarations \( srcSpan, d ) -> do
let start = realSrcSpanStart srcSpan
putStrLn $
unwords
[ foldMap ( <> ":" ) [ path, show ( srcLocLine start ), show ( srcLocCol start ) ]
, occNameString ( declOccName d )
]
-- | Recursively search for .hie files in given directory
getHieFilesIn :: FilePath -> IO [FilePath]
getHieFilesIn path = do
exists <-
doesPathExist path
if exists
then do
isFile <-
doesFileExist path
if isFile && "hie" `isExtensionOf` path
then do
path' <-
canonicalizePath path
return [ path' ]
else do
isDir <-
doesDirectoryExist path
if isDir
then do
cnts <-
listDirectory path
withCurrentDirectory path ( foldMap getHieFilesIn cnts )
else
return []
else
return []
import Weeder.Main

24
prettyprinter.nix Normal file
View File

@ -0,0 +1,24 @@
{ mkDerivation, ansi-wl-pprint, base, base-compat, bytestring
, containers, deepseq, doctest, gauge, mtl, pgp-wordlist
, QuickCheck, quickcheck-instances, random, stdenv, tasty
, tasty-hunit, tasty-quickcheck, text, transformers
}:
mkDerivation {
pname = "prettyprinter";
version = "1.6.1";
sha256 = "3f9765764db7b55db8fb29b92ad26a02f08364e5947a89e2e1aa6d8a6087d781";
isLibrary = true;
isExecutable = true;
libraryHaskellDepends = [ base text ];
testHaskellDepends = [
base bytestring doctest pgp-wordlist QuickCheck
quickcheck-instances tasty tasty-hunit tasty-quickcheck text
];
benchmarkHaskellDepends = [
ansi-wl-pprint base base-compat containers deepseq gauge mtl
QuickCheck random text transformers
];
homepage = "http://github.com/quchen/prettyprinter";
description = "A modern, easy to use, well-documented, extensible pretty-printer";
license = stdenv.lib.licenses.bsd2;
}

View File

@ -14,18 +14,31 @@ let
)
( self:
super:
{ weeder =
{ dhall =
self.callPackage ./dhall.nix {};
weeder =
self.callCabal2nix
"weeder"
( cleanSource ./. )
{};
ghcide =
haskell.lib.dontCheck super.ghcide;
cborg =
self.callPackage ./cborg.nix {};
cborg-json =
self.callPackage ./cborg-json.nix {};
prettyprinter =
self.callPackage ./prettyprinter.nix {};
atomic-write =
self.callPackage ./atomic-write.nix {};
}
);
};
in
haskellPackages.weeder.env.overrideAttrs
( old: { buildInputs = old.buildInputs or [] ++ [ haskellPackages.ghcide ]; } )
haskellPackages.weeder.env
# .overrideAttrs
# ( old: { buildInputs = old.buildInputs or [] ++ [ haskellPackages.ghcide ]; } )

View File

@ -25,26 +25,26 @@ module Weeder
)
where
import "algebraic-graphs" Algebra.Graph ( Graph, edge, empty, overlay, vertex, vertexList )
import "algebraic-graphs" Algebra.Graph.ToGraph ( dfs )
import Algebra.Graph ( Graph, edge, empty, overlay, vertex, vertexList )
import Algebra.Graph.ToGraph ( dfs )
import "base" Control.Applicative ( Alternative )
import "base" Control.Monad ( guard, msum, when )
import "base" Data.Foldable ( for_, traverse_ )
import "base" Data.List ( intercalate )
import "base" Data.Monoid ( First( First ) )
import "base" GHC.Generics ( Generic )
import "base" Prelude hiding ( span )
import Control.Applicative ( Alternative )
import Control.Monad ( guard, msum, when )
import Data.Foldable ( for_, traverse_ )
import Data.List ( intercalate )
import Data.Monoid ( First( First ) )
import GHC.Generics ( Generic )
import Prelude hiding ( span )
import "containers" Data.Map.Strict ( Map )
import qualified "containers" Data.Map.Strict as Map
import "containers" Data.Sequence ( Seq )
import "containers" Data.Set ( Set )
import qualified "containers" Data.Set as Set
import Data.Map.Strict ( Map )
import qualified Data.Map.Strict as Map
import Data.Sequence ( Seq )
import Data.Set ( Set )
import qualified Data.Set as Set
import "ghc" Avail ( AvailInfo( Avail, AvailTC ) )
import "ghc" FieldLabel ( FieldLbl( FieldLabel, flSelector ) )
import "ghc" HieTypes
import Avail ( AvailInfo( Avail, AvailTC ) )
import FieldLabel ( FieldLbl( FieldLabel, flSelector ) )
import HieTypes
( BindType( RegularBind )
, DeclType( DataDec, ClassDec, ConDec )
, ContextInfo( Decl, ValBind, PatternBind, Use, TyDecl, ClassTyDecl )
@ -55,9 +55,9 @@ import "ghc" HieTypes
, NodeInfo( NodeInfo, nodeIdentifiers, nodeAnnotations )
, Scope( ModuleScope )
)
import "ghc" Module ( Module, moduleStableString )
import "ghc" Name ( Name, nameOccName, nameModule_maybe )
import "ghc" OccName
import Module ( Module, moduleStableString )
import Name ( Name, nameOccName, nameModule_maybe )
import OccName
( OccName
, isDataOcc
, isDataSymOcc
@ -66,15 +66,15 @@ import "ghc" OccName
, isVarOcc
, occNameString
)
import "ghc" SrcLoc ( RealSrcSpan, realSrcSpanStart, realSrcSpanEnd )
import SrcLoc ( RealSrcSpan, realSrcSpanStart, realSrcSpanEnd )
import "generic-lens" Data.Generics.Labels ()
import Data.Generics.Labels ()
import "lens" Control.Lens ( (%=) )
import Control.Lens ( (%=) )
import "mtl" Control.Monad.State.Class ( MonadState )
import Control.Monad.State.Class ( MonadState )
import "transformers" Control.Monad.Trans.Maybe ( runMaybeT )
import Control.Monad.Trans.Maybe ( runMaybeT )
data Declaration =

View File

@ -22,25 +22,39 @@ import Data.Set ( Set )
import qualified Data.Set as Set
-- | Configuration for Weeder analysis.
data Config = Config
{ ignore :: Set Declaration
-- ^ The set of declarations that should not be reported to be weeds.
, roots :: Set Root
-- ^ The set of roots to consider always alive.
, strict :: Bool
-- ^ Enable strict analysis. Strict analysis means:
--
-- * The set of ignored declarations must be a subset of reported weeds
-- (i.e., you are not trying to ignore something that is not considered
-- a weed)
-- * The set of roots only mentions declarations that Weeder can find
-- (i.e., all mentioned roots point to known declarations or modules).
, typeClassRoots :: Bool
-- ^ If True, consider all declarations in a type class as part of the root
-- set. Weeder is currently unable to identify whether or not a type class
-- instance is used - enabling this option can prevent false positives.
}
config :: Dhall.Type Config
config :: Dhall.Decoder Config
config =
Dhall.record do
ignore <- Set.fromList <$> Dhall.field "ignore" ( Dhall.list declaration )
roots <- Set.fromList <$> Dhall.field "roots" ( Dhall.list root )
strict <- Dhall.field "strict" Dhall.bool
typeClassRoots <- Dhall.field "type-class-roots" Dhall.bool
return Config{..}
declaration :: Dhall.Type Declaration
declaration :: Dhall.Decoder Declaration
declaration =
Dhall.record do
unitId <- Dhall.field "unit-id" Dhall.string
@ -58,7 +72,7 @@ declaration =
}
root :: Dhall.Type Root
root :: Dhall.Decoder Root
root =
Dhall.union $ mconcat
[ ModuleRoot <$> Dhall.constructor "Module" moduleDecoder
@ -66,7 +80,7 @@ root =
]
moduleDecoder :: Dhall.Type Module
moduleDecoder :: Dhall.Decoder Module
moduleDecoder =
Dhall.record do
unitId <- Dhall.field "unit-id" Dhall.string

View File

@ -1,70 +1,38 @@
{-# language ApplicativeDo #-}
{-# language LambdaCase #-}
{-# language BlockArguments #-}
{-# language FlexibleContexts #-}
{-# language LambdaCase #-}
{-# language NamedFieldPuns #-}
{-# language OverloadedStrings #-}
{-# language PackageImports #-}
module Weeder.Main ( mainWith ) where
module Weeder.Main ( main, mainWithConfig ) where
import "base" Control.Applicative ( (<**>), liftA2, many, some )
import "base" Control.Monad ( guard )
import "base" Control.Monad.IO.Class ( liftIO )
import "base" Data.Foldable ( fold, for_ )
import Control.Monad ( guard )
import Control.Monad.IO.Class ( liftIO )
import qualified "containers" Data.Map.Strict as Map
import "containers" Data.Set ( Set )
import qualified "containers" Data.Set as Set
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import "directory" System.Directory ( doesPathExist, withCurrentDirectory, canonicalizePath, listDirectory, doesFileExist, doesDirectoryExist )
import System.Directory ( doesPathExist, withCurrentDirectory, canonicalizePath, listDirectory, doesFileExist, doesDirectoryExist )
import "filepath" System.FilePath ( isExtensionOf )
import System.FilePath ( isExtensionOf )
import "ghc" FastString ( unpackFS )
import "ghc" HieBin ( HieFileResult( HieFileResult, hie_file_result ) )
import "ghc" HieBin ( readHieFile )
import "ghc" Module
( DefUnitId( DefUnitId )
, Module( Module )
, UnitId( DefiniteUnitId )
, mkModuleName
, moduleUnitId
, stringToInstalledUnitId
, unitIdFS
)
import "ghc" NameCache ( initNameCache )
import "ghc" OccName
( mkOccName
, occNameString
, varName
)
import "ghc" SrcLoc ( srcLocLine, srcLocCol, realSrcSpanStart )
import "ghc" UniqSupply ( mkSplitUniqSupply )
import HieBin ( HieFileResult( HieFileResult, hie_file_result ) )
import HieBin ( readHieFile )
import NameCache ( initNameCache )
import OccName ( occNameString )
import SrcLoc ( srcLocLine, srcLocCol, realSrcSpanStart )
import UniqSupply ( mkSplitUniqSupply )
import "optparse-applicative" Options.Applicative
( Parser
, execParser
, fullDesc
, header
, help
, helper
, info
, long
, maybeReader
, metavar
, option
, strArgument
, strOption
)
import "transformers" Control.Monad.Trans.State.Strict ( execStateT )
import Control.Monad.Trans.State.Strict ( execStateT )
import Weeder
import Weeder.Config
data Mode = Run Config
import qualified Dhall
import Options.Applicative
import Data.Foldable
import Data.Bool
main :: IO ()
@ -72,113 +40,101 @@ main = do
configExpr <-
execParser $
info
( asum
[ Run <$>
strOption
( long "config"
<> help "A Dhall expression for Weeder's configuration. Can either be a file path (a Dhall import) or a literal Dhall expression."
)
, GenerateConfig
]
( strOption
( long "config"
<> help "A Dhall expression for Weeder's configuration. Can either be a file path (a Dhall import) or a literal Dhall expression."
<> value "./weeder.dhall"
)
)
mempty
Dhall.input config configExpr >>= mainWithConfig
mainWithConfig :: Config -> [ FilePath ] -> IO ()
mainWithConfig Config{} hiePaths = do
mainWithConfig :: Config -> IO ()
mainWithConfig Config{ roots, typeClassRoots, ignore } = do
hieFilePaths <-
foldMap getHieFilesIn hiePaths
getHieFilesIn "./."
nameCache <- do
uniqSupply <- mkSplitUniqSupply 'z'
return ( initNameCache uniqSupply [] )
-- analysis <-
-- flip execStateT emptyAnalysis do
-- for_ hieFilePaths \hieFilePath -> do
-- ( HieFileResult{ hie_file_result }, _ ) <-
-- liftIO ( readHieFile nameCache hieFilePath )
analysis <-
flip execStateT emptyAnalysis do
for_ hieFilePaths \hieFilePath -> do
( HieFileResult{ hie_file_result }, _ ) <-
liftIO ( readHieFile nameCache hieFilePath )
-- analyseHieFile hie_file_result
analyseHieFile hie_file_result
-- let
-- reachableSet =
-- reachable
-- analysis
-- ( roots <> Set.map DeclarationRoot ( implicitRoots analysis ) )
let
reachableSet =
reachable
analysis
( roots <> bool mempty ( Set.map DeclarationRoot ( implicitRoots analysis ) ) typeClassRoots )
-- dead =
-- Set.filter
-- ( \d ->
-- if Set.null units then
-- True
dead =
Set.filter
( not . ( `Set.member` ignore ) )
( allDeclarations analysis Set.\\ reachableSet )
-- else
-- Set.member
-- ( unpackFS ( unitIdFS ( moduleUnitId ( declModule d ) ) ) )
-- units
-- )
-- ( allDeclarations analysis Set.\\ reachableSet )
warnings =
Map.unionsWith (++) $
foldMap
( \d ->
fold $ do
moduleFilePath <- Map.lookup ( declModule d ) ( modulePaths analysis )
-- warnings =
-- Map.unionsWith (++) $
-- foldMap
-- ( \d ->
-- fold $ do
-- moduleFilePath <- Map.lookup ( declModule d ) ( modulePaths analysis )
spans <- Map.lookup d ( declarationSites analysis )
guard $ not $ null spans
-- spans <- Map.lookup d ( declarationSites analysis )
-- guard $ not $ null spans
return [ Map.singleton moduleFilePath ( liftA2 (,) (Set.toList spans) (pure d) ) ]
)
dead
-- return [ Map.singleton moduleFilePath ( liftA2 (,) (Set.toList spans) (pure d) ) ]
-- )
-- dead
for_ ( Map.toList warnings ) \( path, declarations ) ->
for_ declarations \( srcSpan, d ) -> do
let start = realSrcSpanStart srcSpan
-- for_ ( Map.toList warnings ) \( path, declarations ) ->
-- for_ declarations \( srcSpan, d ) -> do
-- let start = realSrcSpanStart srcSpan
-- putStrLn $
-- unwords
-- [ foldMap ( <> ":" ) [ path, show ( srcLocLine start ), show ( srcLocCol start ) ]
-- , occNameString ( declOccName d )
-- ]
putStrLn $
unwords
[ foldMap ( <> ":" ) [ path, show ( srcLocLine start ), show ( srcLocCol start ) ]
, occNameString ( declOccName d )
]
-- -- | Recursively search for .hie files in given directory
-- getHieFilesIn :: FilePath -> IO [FilePath]
-- getHieFilesIn path = do
-- exists <-
-- doesPathExist path
-- | Recursively search for .hie files in given directory
getHieFilesIn :: FilePath -> IO [FilePath]
getHieFilesIn path = do
exists <-
doesPathExist path
-- if exists
-- then do
-- isFile <-
-- doesFileExist path
if exists
then do
isFile <-
doesFileExist path
-- if isFile && "hie" `isExtensionOf` path
-- then do
-- path' <-
-- canonicalizePath path
if isFile && "hie" `isExtensionOf` path
then do
path' <-
canonicalizePath path
-- return [ path' ]
return [ path' ]
-- else do
-- isDir <-
-- doesDirectoryExist path
else do
isDir <-
doesDirectoryExist path
-- if isDir
-- then do
-- cnts <-
-- listDirectory path
if isDir
then do
cnts <-
listDirectory path
-- withCurrentDirectory path ( foldMap getHieFilesIn cnts )
withCurrentDirectory path ( foldMap getHieFilesIn cnts )
-- else
-- return []
else
return []
-- else
-- return []
else
return []

View File

@ -5,17 +5,18 @@ version: 1.0
library
build-depends:
algebraic-graphs ^>= 0.5 ,
base ^>= 4.13.0.0 ,
containers ^>= 0.6.2.1 ,
dhall ^>= 1.26.1 ,
directory ^>= 1.3.3.2 ,
filepath ^>= 1.4.2.1 ,
generic-lens ^>= 1.1.0.0 || ^>= 2.0.0.0 ,
ghc ^>= 8.8.1 ,
lens ^>= 4.18.1 ,
mtl ^>= 2.2.2 ,
transformers ^>= 0.5.6.2
algebraic-graphs ^>= 0.4 ,
base ^>= 4.13.0.0 ,
containers ^>= 0.6.2.1 ,
dhall ^>= 1.30.0 ,
directory ^>= 1.3.3.2 ,
filepath ^>= 1.4.2.1 ,
generic-lens ^>= 1.1.0.0 || ^>= 2.0.0.0 ,
ghc ^>= 8.8.1 ,
lens ^>= 4.18.1 ,
mtl ^>= 2.2.2 ,
optparse-applicative ^>= 0.14.3.0 ,
transformers ^>= 0.5.6.2
hs-source-dirs: src
exposed-modules:
Weeder
@ -31,7 +32,7 @@ executable weeder
directory ^>= 1.3.3.2 ,
filepath ^>= 1.4.2.1 ,
ghc ^>= 8.8.1 ,
optparse-applicative ^>= 0.15.0.0 ,
optparse-applicative ^>= 0.14.3.0 ,
transformers ^>= 0.5.6.2 ,
weeder
main-is: Main.hs

23
weeder.dhall Normal file
View File

@ -0,0 +1,23 @@
let Module
: Type
= { unit-id : Text, module : Text }
let Declaration
: Type
= Module ⩓ { symbol : Text }
let Root
: Type
= < Declaration : Declaration | Module : Module >
in { ignore = [] : List Declaration
, roots =
[ Root.Declaration
{ unit-id = "weeder-1.0-inplace"
, module = "Weeder.Main"
, symbol = "main"
}
]
, strict = True
, type-class-roots = True
}