From fd2beaadfad5f01fade9cdb344bd3fe750f8e509 Mon Sep 17 00:00:00 2001 From: Vidar Holen Date: Wed, 9 Jan 2019 18:08:59 -0800 Subject: [PATCH] Make Fixer responsible for realigning tab stops --- src/ShellCheck/Fixer.hs | 37 +++++++++++++++++++++++++++--- src/ShellCheck/Formatter/Format.hs | 26 +-------------------- src/ShellCheck/Formatter/TTY.hs | 20 ++++------------ 3 files changed, 39 insertions(+), 44 deletions(-) diff --git a/src/ShellCheck/Fixer.hs b/src/ShellCheck/Fixer.hs index 22b528b..12de3c2 100644 --- a/src/ShellCheck/Fixer.hs +++ b/src/ShellCheck/Fixer.hs @@ -19,7 +19,7 @@ -} {-# LANGUAGE TemplateHaskell #-} -module ShellCheck.Fixer (applyFix, mapPositions, Ranged(..), runTests) where +module ShellCheck.Fixer (applyFix, removeTabStops, mapPositions, Ranged(..), runTests) where import ShellCheck.Interface import Control.Monad.State @@ -111,6 +111,30 @@ mapPositions f = adjustFix fixReplacements = map adjustReplacement $ fixReplacements fix } +-- Rewrite a Ranged from a tabstop of 8 to 1 +removeTabStops :: Ranged a => a -> Array Int String -> a +removeTabStops range ls = + let startColumn = realignColumn lineNo colNo range + endColumn = realignColumn endLineNo endColNo range + startPosition = (start range) { posColumn = startColumn } + endPosition = (end range) { posColumn = endColumn } in + setRange (startPosition, endPosition) range + where + realignColumn lineNo colNo c = + if lineNo c > 0 && lineNo c <= fromIntegral (length ls) + then real (ls ! fromIntegral (lineNo c)) 0 0 (colNo c) + else colNo c + real _ r v target | target <= v = r + -- hit this case at the end of line, and if we don't hit the target + -- return real + (target - v) + real [] r v target = r + (target - v) + real ('\t':rest) r v target = real rest (r+1) (v + 8 - (v `mod` 8)) target + real (_:rest) r v target = real rest (r+1) (v+1) target + lineNo = posLine . start + endLineNo = posLine . end + colNo = posColumn . start + endColNo = posColumn . end + -- A replacement that spans multiple line is applied by: -- 1. merging the affected lines into a single string using `unlines` @@ -154,8 +178,15 @@ multiToSingleLine fixes lines = -- the function does not return an array. applyFix :: Fix -> Array Int String -> [String] applyFix fix fileLines = - let (adjustedFixes, singleLine) = multiToSingleLine [fix] fileLines - in lines . runFixer $ applyFixes2 adjustedFixes singleLine + let + untabbed = fix { + fixReplacements = + map (\c -> removeTabStops c fileLines) $ + fixReplacements fix + } + (adjustedFixes, singleLine) = multiToSingleLine [untabbed] fileLines + in + lines . runFixer $ applyFixes2 adjustedFixes singleLine -- start and end comes from pos, which is 1 based diff --git a/src/ShellCheck/Formatter/Format.hs b/src/ShellCheck/Formatter/Format.hs index 1e2b57f..57b9d71 100644 --- a/src/ShellCheck/Formatter/Format.hs +++ b/src/ShellCheck/Formatter/Format.hs @@ -54,29 +54,5 @@ makeNonVirtual comments contents = where list = lines contents arr = listArray (1, length list) list - fix c = realign c arr - --- Realign a Ranged from a tabstop of 8 to 1 -realign :: Ranged a => a -> Array Int String -> a -realign range ls = - let startColumn = realignColumn lineNo colNo range - endColumn = realignColumn endLineNo endColNo range - startPosition = (start range) { posColumn = startColumn } - endPosition = (end range) { posColumn = endColumn } in - setRange (startPosition, endPosition) range - where - realignColumn lineNo colNo c = - if lineNo c > 0 && lineNo c <= fromIntegral (length ls) - then real (ls ! fromIntegral (lineNo c)) 0 0 (colNo c) - else colNo c - real _ r v target | target <= v = r - -- hit this case at the end of line, and if we don't hit the target - -- return real + (target - v) - real [] r v target = r + (target - v) - real ('\t':rest) r v target = real rest (r+1) (v + 8 - (v `mod` 8)) target - real (_:rest) r v target = real rest (r+1) (v+1) target - lineNo = posLine . start - endLineNo = posLine . end - colNo = posColumn . start - endColNo = posColumn . end + fix c = removeTabStops c arr diff --git a/src/ShellCheck/Formatter/TTY.hs b/src/ShellCheck/Formatter/TTY.hs index 254287f..4e9c272 100644 --- a/src/ShellCheck/Formatter/TTY.hs +++ b/src/ShellCheck/Formatter/TTY.hs @@ -163,25 +163,13 @@ showFixedString color comments lineNum fileLines = [] -> return () fixes -> do -- Folding automatically removes overlap - let mergedFix = realignFix $ fold fixes - -- We show the complete, associated fixes, whether or not it includes this and/or unrelated lines. + let mergedFix = fold fixes + -- We show the complete, associated fixes, whether or not it includes this + -- and/or other unrelated lines. let (excerptFix, excerpt) = sliceFile mergedFix fileLines -- in the spirit of error prone putStrLn $ color "message" "Did you mean: " - putStrLn $ unlines $ fixedString excerptFix excerpt - where - -- FIXME: This should be handled by Fixer - realignFix f = f { fixReplacements = map fix (fixReplacements f) } - fix r = realign r fileLines - -fixedString :: Fix -> Array Int String -> [String] -fixedString fix fileLines = - case (fixReplacements fix) of - [] -> [] - reps -> - -- applyReplacement returns the full update file, we really only care about the changed lines - -- so we calculate overlapping lines using replacements - applyFix fix fileLines + putStrLn $ unlines $ applyFix excerptFix excerpt cuteIndent :: PositionedComment -> String cuteIndent comment =