Skip to content

Commit

Permalink
Allow inplace refactoring of multiple files (#1635)
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-mckenna authored Feb 16, 2025
1 parent 88b8e82 commit cf89a66
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 18 deletions.
6 changes: 0 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,6 @@ If you're using git, it may be helpful to only run hlint on changed files. This
{ git diff --diff-filter=d --name-only $(git merge-base HEAD origin/master) -- "***.hs" && git ls-files -o --exclude-standard -- "***.hs"; } | xargs hlint
```

Because hlint's `--refactor` option only works when you pass a single file, this approach is also helpful to enable refactoring many files in a single command:

```bash
{ git diff --diff-filter=d --name-only $(git merge-base HEAD origin/master) -- "***.hs" && git ls-files -o --exclude-standard -- "***.hs"; } | xargs -I file hlint file --refactor --refactor-options="--inplace --step"
```

### Configuration

#### Why doesn't HLint know the fixity for my custom !@%$ operator?
Expand Down
27 changes: 15 additions & 12 deletions src/HLint.hs
Original file line number Diff line number Diff line change
Expand Up @@ -209,18 +209,21 @@ getIdeas cmd@CmdMain{..} settings = do
-- #746: run refactor even if no hint, which ensures consistent output
-- whether there are hints or not.
handleRefactoring :: [Idea] -> [String] -> Cmd -> IO ()
handleRefactoring ideas files cmd@CmdMain{..} =
case cmdFiles of
[file] -> do
-- Ensure that we can find the executable
path <- checkRefactor (if cmdWithRefactor == "" then Nothing else Just cmdWithRefactor)
-- writeFile "hlint.refact"
let hints = show $ map (show &&& ideaRefactoring) ideas
withTempFile $ \f -> do
writeFile f hints
let ParseFlags{enabledExtensions, disabledExtensions} = cmdParseFlags cmd
exitWith =<< runRefactoring path file f enabledExtensions disabledExtensions cmdRefactorOptions
_ -> errorIO "Refactor flag can only be used with an individual file"
handleRefactoring ideas files cmd@CmdMain{..} = do
-- Ensure that we can find the executable
path <- checkRefactor (if cmdWithRefactor == "" then Nothing else Just cmdWithRefactor)
forM_ cmdFiles $ \file -> do
-- writeFile "hlint.refact"
let fileIdeas = filter (\i -> file == ideaFile i) ideas
let hints = show $ map (show &&& ideaRefactoring) fileIdeas
withTempFile $ \f -> do
writeFile f hints
let ParseFlags{enabledExtensions, disabledExtensions} = cmdParseFlags cmd
exitCode <- runRefactoring path file f enabledExtensions disabledExtensions cmdRefactorOptions

case exitCode of
ExitSuccess -> pure ()
ExitFailure _ -> exitWith exitCode

handleReporting :: [Idea] -> Cmd -> IO ()
handleReporting showideas cmd@CmdMain{..} = do
Expand Down
8 changes: 8 additions & 0 deletions src/Idea.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Idea(
rawIdea, idea, suggest, suggestRemove, ideaRemove, warn, ignore,
rawIdeaN, suggestN, ignoreNoSuggestion,
showIdeasJson, showIdeaANSI,
ideaFile,
Note(..), showNotes,
Severity(..),
) where
Expand All @@ -16,6 +17,7 @@ import HsColour
import Refact.Types hiding (SrcSpan)
import Refact.Types qualified as R
import Prelude
import GHC.Data.FastString
import GHC.Types.SrcLoc
import GHC.Utils.Outputable
import GHC.Util
Expand All @@ -36,6 +38,12 @@ data Idea = Idea
}
deriving Eq

ideaFile :: Idea -> String
ideaFile idea =
case srcSpanFileName_maybe (ideaSpan idea) of
Just file -> unpackFS file
Nothing -> error "SrcSpan has no associated file"

-- I don't use aeson here for 2 reasons:
-- 1) Aeson doesn't escape unicode characters, and I want to (allows me to ignore encoding)
-- 2) I want to control the format so it's slightly human readable as well
Expand Down

0 comments on commit cf89a66

Please sign in to comment.