Export to GitHub

ndmitchell - issue #134

Automatically apply changes


Posted on Jan 15, 2009 by Quick Wombat

Recently I got GHC 6.10 working, and I could at last run hlint for myself. I ran it over the Darcs repository and got lots of suggetions back:

find \( -name \*.lhs -o -name \*.hs \) -exec hlint {} +

It would be really cool if rather than just reporting a change, hlint would actually integrate into darcs and MAKE the change, then record it with predictable commit metadata. For example, it would apply one change and then run

darcs record --author hlint -m 'Eta reduction'

Which would then let me choose whether I agreed with the hint (by picking "y" when darcs prompts me), or wanted to ignore that hint (by picking "n" when darcs prompts me).

Or, it could just ALWAYS record the hints, and then I would choose which hints to "darcs pull" into my main repository.

Right now I'm not sure how to build this feature as a wrapper around hlint's existing text output, because that would require a lot of parsing of that output. That's why I'm suggesting it for including in hlint itself.

Comment #1

Posted on Jan 15, 2009 by Happy Wombat

Perhaps the best way would be to emit XML - something like -id a = a\n+\n?

So a hypothetical tool would call hlint with --xml-output, filter out changes based on the type (perhaps the user doesn't want to automatically make eta-reductions even if he's willing to see them in the normal output), and then runs 'patch' on each file/diff pair, and then runs 'darcs record --author hlint -m (file ++ type) file' etc.

(Or if not XML, then perhaps via Read/Show, if it doesn't mangle the diff information.)

Comment #2

Posted on Jan 15, 2009 by Quick Wombat

I have another idea about how to implement this.

Firstly, there needs to be a way to list all the hint names that have any matches (but not listing what the suggestions are):

$ hlint --list-hints
Eta reduce
Use a string literal

Then there needs to be a way to actually modify the files, rather than listing the hints, and a way to only apply one kind of hint:

$ cksum x.hs
1 x.hs
$ hlint --in-place --hint 'Eta reduce' *.hs
$ cksum x.hs
2 x.hs

Then the wrapper merely needs to iterate over the list:

$ hlint --list-hints |
  while read hint
  do  hlint --in-place --hint "$hint" *.hs
      darcs record --author hlint -m "$hint."
  done

Comment #3

Posted on Jan 15, 2009 by Quick Hippo

The idea of integrating with darcs is fantatic, and a great way to do it. However, I think the underlying issue is to get HLint to apply changes to a source file. I don't have too much interest in doing that personally, since I worry the hints may be wrong, I don't have perfect source code info and comments etc have been deleted from the AST. I'd accept a patch :-)

The wrapper around that should be fairly easy to do.

Comment #4

Posted on Jan 15, 2009 by Quick Wombat

I think the underlying issue is to get HLint to apply changes

Agreed.

I don't have too much interest in doing that personally, since I worry the hints may be wrong,

That's not a problem, because the bad hints can be reverted by the VCS.

I don't have perfect source code info and comments etc have been deleted from the AST.

That is indeed more of a problem, since the editing the file should only change the bit the hint refers to, rather than rewriting the whole file.

I'd accept a patch :-)

Ah, that will probably have to wait quite a while, as this is not something I have experience with and I have lots of other stuff to work on. :-(

I guess the first step might be to get hlint to emit a standard patch notation such as that accepted by patch(1) or ed(1); then the actual editing of the file could be handed off to such a utility. Guessing how the parsing library you're using works, though, I suspect that's going to be nearly as difficult...

Comment #5

Posted on Jan 15, 2009 by Quick Hippo

(No comment was entered for this change.)

Comment #6

Posted on Sep 2, 2011 by Quick Hippo

More people are asking for this feature, and in conjunction with the HLint API, it could prove quite useful. I think it could be done on top of the general purpose function:

reconstructModule :: String -> Module () -> String

Where parseModule (reconstructModule s m) == m, but using as much lexical information (comments/positions) from s as possible. With that function you probably just then want an --interactive switch to HLint and do darcs style step through. Once you apply one hint, you should purge all hints and try again.

Comment #7

Posted on Sep 2, 2011 by Quick Hippo

Talking to Malcolm, we came up with the "trick" that makes this feasible. You take Module (), pretty print it, parse it using the exact parser to give Module SrcSpan, then you try and merge information from the original tree over to the second tree. That way you aren't too dependent on the details of HSE's SrcSpanInfo's.

Comment #8

Posted on Mar 24, 2012 by Happy Camel

For reference, JPMoresmau EclipseFP (hosted on github) does take HLint suggestions and apply them to source code, using (I assume) Eclipse/Java APIs to edit source code. I doubt there's much code reuse opportunity from there to here, but it might be helpful to look at EclipseFP as an example implementation and also as a potential use case for this feature.

Comment #9

Posted on Jun 13, 2015 by Quick Hippo

https://github.com/ndmitchell/hlint/issues/135

Status: Moved

Labels:
Type-Enhancement Priority-Medium Proj-HLint