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
|
2023-06-23 23:54:10 +03:00
|
|
|
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:
|
2023-06-23 14:12:16 +03:00
|
|
|
, 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
|
2023-08-10 15:45:06 +03:00
|
|
|
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
|
2023-06-23 23:54:10 +03:00
|
|
|
|
|
|
|
test-suite weeder-test
|
|
|
|
build-depends:
|
|
|
|
, aeson
|
|
|
|
, algebraic-graphs
|
|
|
|
, base
|
2023-07-20 15:15:12 +03:00
|
|
|
, containers
|
2023-06-23 23:54:10 +03:00
|
|
|
, 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
|
2023-07-20 15:15:12 +03:00
|
|
|
UnitTests
|
2023-06-23 23:54:10 +03:00
|
|
|
-- 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
|
2023-06-23 23:54:10 +03:00
|
|
|
Spec.BasicExample.BasicExample
|
2023-07-20 15:15:12 +03:00
|
|
|
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
|
2023-07-22 15:44:28 +03:00
|
|
|
Spec.TypeAliasGADT.TypeAliasGADT
|
|
|
|
Spec.TypeDataDecl.TypeDataDecl
|
|
|
|
Spec.Types.Types
|
|
|
|
Spec.Types.Usages
|
|
|
|
Spec.TypeFamilies.TypeFamilies
|
|
|
|
Spec.TypeFamilies.TypeFamilyUsage
|
|
|
|
Spec.TypesUnused.TypesUnused
|
2023-07-20 15:15:12 +03:00
|
|
|
UnitTests.Weeder.ConfigSpec
|
2023-06-23 23:54:10 +03:00
|
|
|
ghc-options: -Wall -fwarn-incomplete-uni-patterns -fwrite-ide-info -hiedir ./test
|
|
|
|
default-language: Haskell2010
|