{-# LANGUAGE TemplateHaskell, OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module HsDev.Tools.AutoFix ( corrections, CorrectorMatch, correctors, match, findCorrector, module Data.Text.Region, module HsDev.Tools.Refact, module HsDev.Tools.Types ) where import Control.Applicative import Control.Lens hiding ((.=), at) import Data.Maybe (listToMaybe, mapMaybe) import Data.String (fromString) import Data.Text (Text) import Data.Text.Lens (unpacked) import Data.Text.Region hiding (Region(..), update) import qualified Data.Text.Region as R import HsDev.Tools.Refact import HsDev.Tools.Base import HsDev.Tools.Types instance Regioned a => Regioned (Note a) where regions = note . regions corrections :: [Note OutputMessage] -> [Note Refact] corrections = mapMaybe toRefact where toRefact :: Note OutputMessage -> Maybe (Note Refact) toRefact n = useSuggestion <|> findCorrector n where -- Use existing suggestion useSuggestion :: Maybe (Note Refact) useSuggestion = do sugg <- view (note . messageSuggestion) n return $ set note (Refact (view (note . message) n) (replace (fromRegion $ view noteRegion n) sugg)) n type CorrectorMatch = Note OutputMessage -> Maybe (Note Refact) correctors :: [CorrectorMatch] correctors = [ match "^The (?:qualified )?import of .([\\w\\.]+). is redundant" $ \_ rgn -> Refact -- There are different quotes in Windows/Linux "Redundant import" (cut (expandLines rgn)), match "^(.*?)\nFound:\n (.*?)\nWhy not:\n (.*?)$" $ \g rgn -> Refact (g `at` 1) (replace ((rgn ^. regionFrom) `regionSize` pt 0 (contentsLength $ g `at` 2)) (g `at` 3))] match :: String -> ((Int -> Maybe Text) -> R.Region -> Refact) -> CorrectorMatch match pat f n = do g <- matchRx pat (view (note . message . unpacked) n) return $ set note (f (fmap fromString . g) (fromRegion $ view noteRegion n)) n findCorrector :: Note OutputMessage -> Maybe (Note Refact) findCorrector n = listToMaybe $ mapMaybe ($ n) correctors