weeder/weeder.cabal

122 lines
3.3 KiB
Plaintext
Raw Normal View History

2020-06-30 16:59:14 +03:00
cabal-version: 3.0
license: BSD-3-Clause
2020-03-15 18:23:48 +03:00
license-file: LICENSE
name: weeder
author: Ollie Charles <ollie@ocharles.org.uk>
2020-03-15 21:11:18 +03:00
maintainer: Ollie Charles <ollie@ocharles.org.uk>
2020-03-15 18:23:48 +03:00
build-type: Simple
2023-08-17 20:01:18 +03:00
version: 2.7.0
2023-01-05 14:32:26 +03:00
copyright: Neil Mitchell 2017-2020, Oliver Charles 2020-2023
2020-03-15 18:23:48 +03:00
synopsis: Detect dead code
description: Find declarations.
homepage: https://github.com/ocharles/weeder#readme
bug-reports: https://github.com/ocharles/weeder/issues
2020-03-15 21:11:18 +03:00
category: Development
2020-03-15 18:23:48 +03:00
extra-doc-files:
README.md
CHANGELOG.md
extra-source-files:
test/Spec/*.toml
test/Spec/*.stdout
Add support for type class instances (#126) * Remove double addition of declarations * Implement test suite * Add mainWithConfig' * Export dotfiles of dependency graphs * Draw dotfiles to PNG via graphviz * Flag for drawing graph PNGs * Type class instances have spans and dependencies Also includes class declarations and (both regular and standalone) derived instances. Consequently, they show up in the output if unreachable. * Follow type class evidence uses back to bindings * Add failing tests (number and string literals) * Failing test for OverloadedLists * More tests, not all failing Also tested on 9.4.5. `OverloadedStringsNoSig` correctly gives no output. `Monads` incorrectly claims that the instances for `Identity'` (used by `bar`) are unreachable, while correctly giving no output on the instances for `Identity` (used by `foo`). `RangeEnum` incorrectly claims that `$fEnumColour` is unreachable. Note that what all the incorrect outputs have in common are top-level type signatures. The type signature does not have to be immediately relevant: see `OverloadedStringsNoSig` - the type of `root` and `root'` is `Char`, but explicitly writing that breaks their evidence variables for `IsString`. When type signatures are omitted, evidence usages for syntax are present in `hie` files as expected. In `Monads.hie`, this is the node corresponding to `bar`: ``` 929 │ Node@test/Spec/Monads/Monads.hs:(36,1)-(38,13): Source: From source 930 │ {(annotations: {(FunBind, HsBindLR), 931 │ (Match, Match), 932 │ (XHsBindsLR, HsBindLR)}), 933 │ (types: [304]), (identifier info: {})} ``` and this is the node for `foo`: ``` 837 │ Node@test/Spec/Monads/Monads.hs:(31,1)-(33,12): Source: From source 838 │ {(annotations: {(FunBind, HsBindLR), 839 │ (Match, Match), 840 │ (XHsBindsLR, HsBindLR)}), 841 │ (types: [302]), 842 │ (identifier info: {(name $dNum, Details: Just 3 {usage of evidence variable}), 843 │ (name $fMonadIdentity, Details: Just 167 {usage of evidence variable}), 844 │ (name $dMonad, Details: Just 167 {evidence variable bound by a let, depending on: [$fMonadIdentity] 845 │ with scope: LocalScope test/Spec/Monads/Monads.hs:(31,1)-(33,12) 846 │ bound at: test/Spec/Monads/Monads.hs:(31,1)-(33,12)}), 847 │ (name $dNum, Details: Just 3 {evidence variable bound by a let, depending on: [$dNum] 848 │ with scope: LocalScope test/Spec/Monads/Monads.hs:(31,1)-(33,12) 849 │ bound at: test/Spec/Monads/Monads.hs:(31,1)-(33,12)}), 850 │ (name $dNum, Details: Just 3 {evidence variable bound by a let, depending on: [$dNum] 851 │ with scope: LocalScope test/Spec/Monads/Monads.hs:(31,1)-(33,12) 852 │ bound at: test/Spec/Monads/Monads.hs:(31,1)-(33,12)})})} ``` The appearance of `foo` and `bar` in GHC's renamer AST does not differ in any meaningful way. In the typechecker AST, `bar` contains a (seemingly redundant) `EpAnn` annotation, which is missing in `foo`, but is otherwise the same everywhere else. For this reason I suppose the problem is not too deep within GHC and any required fixes are probably limited to modules directly handling `hie` files. * Mark tests as failing A `.failing` file should contain the current expected output of a failing test, overriding the `.stdout` file. This allows the test suite return a 0 exit code without having to disable failing tests. If the test happens to return exactly the correct output contained in the `.stdout` file, it fails with a `not expected:` failure. I think it would be worthwhile to make a small extension of `hspec` that allows marking tests as expected failures in a more polished way, assuming such an extension does not already exist. * Tests for OverloadedLabels and ApplicativeDo OverloadedLabels already works perfectly, but ApplicativeDo has the same problem as Monad * Add InstanceRoot constructor * Store pretty-printed type in InstanceRoot * Add root-instances and root-classes fields * Clean up tests * Show pretty-printed type of instances in output * Omit instance OccNames in output * MonadReader for pretty-printed instance types * MonadReader for following evidence uses * Update test/Spec/InstanceRootConstraint.toml Co-authored-by: Ollie Charles <ollie@ocharles.org.uk> --------- Co-authored-by: Ollie Charles <ollie@ocharles.org.uk>
2023-07-10 17:39:52 +03:00
test/Spec/*.failing
2019-09-10 12:23:57 +03:00
2019-09-16 11:59:37 +03:00
library
2020-03-08 16:49:48 +03:00
build-depends:
, algebraic-graphs ^>= 0.7
2024-01-24 22:39:54 +03:00
, async ^>= 2.2.5
, base ^>= 4.19.0.0
, bytestring ^>= 0.12.0.2
, containers ^>= 0.6.8
, directory ^>= 1.3.8.1
, filepath ^>= 1.4.100.4
, generic-lens ^>= 2.2.2.0
, ghc ^>= 9.8.1
, lens ^>= 5.2.3
, mtl ^>= 2.3.1
, optparse-applicative ^>= 0.18.1.0
, parallel ^>= 3.2.2.0
, regex-tdfa ^>= 1.3.2.2
, text ^>= 2.1
, toml-reader ^>= 0.2.1.0
, transformers ^>= 0.6.1.0
2019-09-10 12:23:57 +03:00
hs-source-dirs: src
2020-03-14 19:19:13 +03:00
exposed-modules:
Weeder
Weeder.Config
Weeder.Run
2020-03-14 19:19:13 +03:00
Weeder.Main
2020-05-21 23:05:04 +03:00
autogen-modules:
Paths_weeder
other-modules:
Paths_weeder
Improving performance (#137) * outputableDeclarations optimisation We now only match on declarations that can appear in the output (i.e. with a span) when evaluating `roots` and `dead` in `runWeeder`, instead of searching through all of them. * initialGraph optimisation `addAllDeclarations` turned out to largely be an unnecessary step: `define` and `addDependency` already created vertices for the involved declarations on their own. This skips that step when unused-types = false, and otherwise minimises the number of added vertices. * Compile regex in Config.hs GHC does not optimise repeated calls to `=~`, so we were recompiling the regex for every single declaration we matched on. This took up 15% of runtime and 40% of memory usage. This compiles regular expressions in advance, immediately after we parse the config file. Besides performance, this has the additional benefit of making `runWeeder` a total function: regex parse failures are now emitted alongside TOML errors. * Parallel analysis We now run most of our analysis on each `HieFile` in parallel. Doing this in batches of 100 turned out to not have any performance difference from doing this with 1 `HieFile` at a time. Given enough cores, this can almost double Weeder's performance. * getHieFiles as a stream This uses lazy IO via `getChanContents` to begin analysis in `runWeeder` before `[HieFile]` is fully read. This neither benefits nor harms performance when Weeder is given only one core, but improves performance by about the runtime of `getHieFiles` when given two or more cores. On my machine this is 15%, but this may vary depending on disk speed. As following uses of type class instances requires information from all HIE files, it is now done in a separate stage via `analyseEvidenceUses`, applied only after the initial analysis is fully evaluated. * Fix throwing exit code 2 in getHieFiles Switches `forkIO` to `async` in order to rethrow exceptions encountered by `getHieFiles`. * Replace type families with lists * Set capabilities with -j and -N * Update comments in Weeder.hs --------- Co-authored-by: Ollie Charles <ollie@ocharles.org.uk>
2023-08-10 15:57:50 +03:00
ghc-options: -Wall -fwarn-incomplete-uni-patterns -threaded
2020-03-15 21:10:33 +03:00
default-language: Haskell2010
2019-09-16 11:59:37 +03:00
2019-09-16 12:02:58 +03:00
executable weeder
2020-03-08 16:49:48 +03:00
build-depends:
2021-08-29 12:36:08 +03:00
, base
, bytestring
, containers
, directory
, filepath
, ghc
, optparse-applicative
, transformers
2020-06-30 16:59:14 +03:00
, weeder
2019-09-16 12:02:58 +03:00
main-is: Main.hs
hs-source-dirs: exe-weeder
Improving performance (#137) * outputableDeclarations optimisation We now only match on declarations that can appear in the output (i.e. with a span) when evaluating `roots` and `dead` in `runWeeder`, instead of searching through all of them. * initialGraph optimisation `addAllDeclarations` turned out to largely be an unnecessary step: `define` and `addDependency` already created vertices for the involved declarations on their own. This skips that step when unused-types = false, and otherwise minimises the number of added vertices. * Compile regex in Config.hs GHC does not optimise repeated calls to `=~`, so we were recompiling the regex for every single declaration we matched on. This took up 15% of runtime and 40% of memory usage. This compiles regular expressions in advance, immediately after we parse the config file. Besides performance, this has the additional benefit of making `runWeeder` a total function: regex parse failures are now emitted alongside TOML errors. * Parallel analysis We now run most of our analysis on each `HieFile` in parallel. Doing this in batches of 100 turned out to not have any performance difference from doing this with 1 `HieFile` at a time. Given enough cores, this can almost double Weeder's performance. * getHieFiles as a stream This uses lazy IO via `getChanContents` to begin analysis in `runWeeder` before `[HieFile]` is fully read. This neither benefits nor harms performance when Weeder is given only one core, but improves performance by about the runtime of `getHieFiles` when given two or more cores. On my machine this is 15%, but this may vary depending on disk speed. As following uses of type class instances requires information from all HIE files, it is now done in a separate stage via `analyseEvidenceUses`, applied only after the initial analysis is fully evaluated. * Fix throwing exit code 2 in getHieFiles Switches `forkIO` to `async` in order to rethrow exceptions encountered by `getHieFiles`. * Replace type families with lists * Set capabilities with -j and -N * Update comments in Weeder.hs --------- Co-authored-by: Ollie Charles <ollie@ocharles.org.uk>
2023-08-10 15:57:50 +03:00
ghc-options: -Wall -fwarn-incomplete-uni-patterns -threaded -no-rtsopts-suggestions -with-rtsopts=-N
2020-03-15 21:10:33 +03:00
default-language: Haskell2010
test-suite weeder-test
build-depends:
, aeson
, algebraic-graphs
, base
, containers
, directory
, filepath
, ghc
, hspec
, process
, text
, toml-reader
, weeder
type: exitcode-stdio-1.0
main-is: Spec.hs
hs-source-dirs: test
autogen-modules:
Paths_weeder
other-modules:
Paths_weeder
UnitTests
-- Tests
Add support for type class instances (#126) * Remove double addition of declarations * Implement test suite * Add mainWithConfig' * Export dotfiles of dependency graphs * Draw dotfiles to PNG via graphviz * Flag for drawing graph PNGs * Type class instances have spans and dependencies Also includes class declarations and (both regular and standalone) derived instances. Consequently, they show up in the output if unreachable. * Follow type class evidence uses back to bindings * Add failing tests (number and string literals) * Failing test for OverloadedLists * More tests, not all failing Also tested on 9.4.5. `OverloadedStringsNoSig` correctly gives no output. `Monads` incorrectly claims that the instances for `Identity'` (used by `bar`) are unreachable, while correctly giving no output on the instances for `Identity` (used by `foo`). `RangeEnum` incorrectly claims that `$fEnumColour` is unreachable. Note that what all the incorrect outputs have in common are top-level type signatures. The type signature does not have to be immediately relevant: see `OverloadedStringsNoSig` - the type of `root` and `root'` is `Char`, but explicitly writing that breaks their evidence variables for `IsString`. When type signatures are omitted, evidence usages for syntax are present in `hie` files as expected. In `Monads.hie`, this is the node corresponding to `bar`: ``` 929 │ Node@test/Spec/Monads/Monads.hs:(36,1)-(38,13): Source: From source 930 │ {(annotations: {(FunBind, HsBindLR), 931 │ (Match, Match), 932 │ (XHsBindsLR, HsBindLR)}), 933 │ (types: [304]), (identifier info: {})} ``` and this is the node for `foo`: ``` 837 │ Node@test/Spec/Monads/Monads.hs:(31,1)-(33,12): Source: From source 838 │ {(annotations: {(FunBind, HsBindLR), 839 │ (Match, Match), 840 │ (XHsBindsLR, HsBindLR)}), 841 │ (types: [302]), 842 │ (identifier info: {(name $dNum, Details: Just 3 {usage of evidence variable}), 843 │ (name $fMonadIdentity, Details: Just 167 {usage of evidence variable}), 844 │ (name $dMonad, Details: Just 167 {evidence variable bound by a let, depending on: [$fMonadIdentity] 845 │ with scope: LocalScope test/Spec/Monads/Monads.hs:(31,1)-(33,12) 846 │ bound at: test/Spec/Monads/Monads.hs:(31,1)-(33,12)}), 847 │ (name $dNum, Details: Just 3 {evidence variable bound by a let, depending on: [$dNum] 848 │ with scope: LocalScope test/Spec/Monads/Monads.hs:(31,1)-(33,12) 849 │ bound at: test/Spec/Monads/Monads.hs:(31,1)-(33,12)}), 850 │ (name $dNum, Details: Just 3 {evidence variable bound by a let, depending on: [$dNum] 851 │ with scope: LocalScope test/Spec/Monads/Monads.hs:(31,1)-(33,12) 852 │ bound at: test/Spec/Monads/Monads.hs:(31,1)-(33,12)})})} ``` The appearance of `foo` and `bar` in GHC's renamer AST does not differ in any meaningful way. In the typechecker AST, `bar` contains a (seemingly redundant) `EpAnn` annotation, which is missing in `foo`, but is otherwise the same everywhere else. For this reason I suppose the problem is not too deep within GHC and any required fixes are probably limited to modules directly handling `hie` files. * Mark tests as failing A `.failing` file should contain the current expected output of a failing test, overriding the `.stdout` file. This allows the test suite return a 0 exit code without having to disable failing tests. If the test happens to return exactly the correct output contained in the `.stdout` file, it fails with a `not expected:` failure. I think it would be worthwhile to make a small extension of `hspec` that allows marking tests as expected failures in a more polished way, assuming such an extension does not already exist. * Tests for OverloadedLabels and ApplicativeDo OverloadedLabels already works perfectly, but ApplicativeDo has the same problem as Monad * Add InstanceRoot constructor * Store pretty-printed type in InstanceRoot * Add root-instances and root-classes fields * Clean up tests * Show pretty-printed type of instances in output * Omit instance OccNames in output * MonadReader for pretty-printed instance types * MonadReader for following evidence uses * Update test/Spec/InstanceRootConstraint.toml Co-authored-by: Ollie Charles <ollie@ocharles.org.uk> --------- Co-authored-by: Ollie Charles <ollie@ocharles.org.uk>
2023-07-10 17:39:52 +03:00
Spec.ApplicativeDo.ApplicativeDo
Spec.BasicExample.BasicExample
Spec.ConfigInstanceModules.Module1
Spec.ConfigInstanceModules.Module2
Spec.ConfigInstanceModules.Module3
Add support for type class instances (#126) * Remove double addition of declarations * Implement test suite * Add mainWithConfig' * Export dotfiles of dependency graphs * Draw dotfiles to PNG via graphviz * Flag for drawing graph PNGs * Type class instances have spans and dependencies Also includes class declarations and (both regular and standalone) derived instances. Consequently, they show up in the output if unreachable. * Follow type class evidence uses back to bindings * Add failing tests (number and string literals) * Failing test for OverloadedLists * More tests, not all failing Also tested on 9.4.5. `OverloadedStringsNoSig` correctly gives no output. `Monads` incorrectly claims that the instances for `Identity'` (used by `bar`) are unreachable, while correctly giving no output on the instances for `Identity` (used by `foo`). `RangeEnum` incorrectly claims that `$fEnumColour` is unreachable. Note that what all the incorrect outputs have in common are top-level type signatures. The type signature does not have to be immediately relevant: see `OverloadedStringsNoSig` - the type of `root` and `root'` is `Char`, but explicitly writing that breaks their evidence variables for `IsString`. When type signatures are omitted, evidence usages for syntax are present in `hie` files as expected. In `Monads.hie`, this is the node corresponding to `bar`: ``` 929 │ Node@test/Spec/Monads/Monads.hs:(36,1)-(38,13): Source: From source 930 │ {(annotations: {(FunBind, HsBindLR), 931 │ (Match, Match), 932 │ (XHsBindsLR, HsBindLR)}), 933 │ (types: [304]), (identifier info: {})} ``` and this is the node for `foo`: ``` 837 │ Node@test/Spec/Monads/Monads.hs:(31,1)-(33,12): Source: From source 838 │ {(annotations: {(FunBind, HsBindLR), 839 │ (Match, Match), 840 │ (XHsBindsLR, HsBindLR)}), 841 │ (types: [302]), 842 │ (identifier info: {(name $dNum, Details: Just 3 {usage of evidence variable}), 843 │ (name $fMonadIdentity, Details: Just 167 {usage of evidence variable}), 844 │ (name $dMonad, Details: Just 167 {evidence variable bound by a let, depending on: [$fMonadIdentity] 845 │ with scope: LocalScope test/Spec/Monads/Monads.hs:(31,1)-(33,12) 846 │ bound at: test/Spec/Monads/Monads.hs:(31,1)-(33,12)}), 847 │ (name $dNum, Details: Just 3 {evidence variable bound by a let, depending on: [$dNum] 848 │ with scope: LocalScope test/Spec/Monads/Monads.hs:(31,1)-(33,12) 849 │ bound at: test/Spec/Monads/Monads.hs:(31,1)-(33,12)}), 850 │ (name $dNum, Details: Just 3 {evidence variable bound by a let, depending on: [$dNum] 851 │ with scope: LocalScope test/Spec/Monads/Monads.hs:(31,1)-(33,12) 852 │ bound at: test/Spec/Monads/Monads.hs:(31,1)-(33,12)})})} ``` The appearance of `foo` and `bar` in GHC's renamer AST does not differ in any meaningful way. In the typechecker AST, `bar` contains a (seemingly redundant) `EpAnn` annotation, which is missing in `foo`, but is otherwise the same everywhere else. For this reason I suppose the problem is not too deep within GHC and any required fixes are probably limited to modules directly handling `hie` files. * Mark tests as failing A `.failing` file should contain the current expected output of a failing test, overriding the `.stdout` file. This allows the test suite return a 0 exit code without having to disable failing tests. If the test happens to return exactly the correct output contained in the `.stdout` file, it fails with a `not expected:` failure. I think it would be worthwhile to make a small extension of `hspec` that allows marking tests as expected failures in a more polished way, assuming such an extension does not already exist. * Tests for OverloadedLabels and ApplicativeDo OverloadedLabels already works perfectly, but ApplicativeDo has the same problem as Monad * Add InstanceRoot constructor * Store pretty-printed type in InstanceRoot * Add root-instances and root-classes fields * Clean up tests * Show pretty-printed type of instances in output * Omit instance OccNames in output * MonadReader for pretty-printed instance types * MonadReader for following evidence uses * Update test/Spec/InstanceRootConstraint.toml Co-authored-by: Ollie Charles <ollie@ocharles.org.uk> --------- Co-authored-by: Ollie Charles <ollie@ocharles.org.uk>
2023-07-10 17:39:52 +03:00
Spec.DeriveGeneric.DeriveGeneric
Spec.InstanceRootConstraint.InstanceRootConstraint
Spec.InstanceTypeclass.InstanceTypeclass
Spec.Monads.Monads
Spec.NumInstance.NumInstance
Spec.NumInstanceLiteral.NumInstanceLiteral
Spec.OverloadedLabels.OverloadedLabels
Spec.OverloadedLists.OverloadedLists
Spec.OverloadedStrings.OverloadedStrings
Spec.RangeEnum.RangeEnum
Spec.RootClasses.RootClasses
Spec.StandaloneDeriving.StandaloneDeriving
Spec.TypeAliasGADT.TypeAliasGADT
Spec.TypeDataDecl.TypeDataDecl
Spec.Types.Types
Spec.Types.Usages
Spec.TypeFamilies.TypeFamilies
Spec.TypeFamilies.TypeFamilyUsage
Spec.TypesUnused.TypesUnused
UnitTests.Weeder.ConfigSpec
ghc-options: -Wall -fwarn-incomplete-uni-patterns -fwrite-ide-info -hiedir ./test
default-language: Haskell2010