Skip to content
Run HLint as part of normal compilation
Haskell
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
example Better error messages Aug 11, 2018
plugin
README.md Better error messages Aug 11, 2018
cabal.project MVP Aug 11, 2018

README.md

hlint-source-plugin

This repository contains a proof-of-concept for a source plugin that calls HLint. This means that at compilation time, HLint is called, rather than having HLint being a separate extra compilation step.

Example

There is an example project in example, which demonstrates many coding practices that can be detected by HLint. When you compile this module, you'll see HLint warnings:

$ cabal new-build all
Build profile: -w ghc-8.6.1.20180716 -O1
In order, the following will be built (use -v for more details):
 - example-0.1.0.0 (exe:example) (dependency rebuilt)
Preprocessing executable 'example' for example-0.1.0.0..
Building executable 'example' for example-0.1.0.0..
[1 of 1] Compiling Main             ( Main.hs, /home/ollie/work/hlint-source-plugin/dist-newstyle/build/x86_64-linux/ghc-8.6.1.20180716/example-0.1.0.0/x/example/build/example/example-tmp/Main.o ) [Plugin forced recompilation]
Main.hs:4:8: warning:
    • Redundant do
    • Why not: (putStrLn $ (show "Hello"))
  |
4 | main = do
  |        ^^...

Main.hs:4:8: warning:
    • Redundant bracket
    • Why not: do putStrLn $ (show "Hello")
  |
4 | main = do
  |        ^^...

Main.hs:5:4: warning:
    • Use print
    • Why not: print "Hello"
  |
5 |   (putStrLn $ (show "Hello"))
  |    ^^^^^^^^^^^^^^^^^^^^^^^^^

Main.hs:5:4: warning:
    • Redundant bracket
    • Why not: putStrLn $ show "Hello"
  |
5 |   (putStrLn $ (show "Hello"))
  |    ^^^^^^^^^^^^^^^^^^^^^^^^^

Main.hs:5:4: warning:
    • Redundant $
    • Why not: putStrLn (show "Hello")
  |
5 |   (putStrLn $ (show "Hello"))
  |    ^^^^^^^^^^^^^^^^^^^^^^^^^

Here we see that HLint has detected a redundant do, and this has been turned into a GHC warning.

Future Work

Currently this plugin simply hooks into the parse stage and calls HLint with a file path. This means HLint will re-parse all source code. The next logical step is to use the actual parse tree, as given to us by GHC, and HLint that. This means that HLint can lose the special logic to run CPP, along with the hacky handling of fixity resolution (we get that done correctly by GHC's renaming phase).

This isn't hard work, just fairly tedious. Contributions welcome!

You can’t perform that action at this time.