Correctly expand lines with multiple tabs
authorPhil Ruffwind <rf@rufflewind.com>
Sat, 20 May 2017 16:48:26 +0000 (12:48 -0400)
committerBen Gamari <ben@smart-cactus.org>
Sat, 20 May 2017 20:29:18 +0000 (16:29 -0400)
rwbarton pointed out that tab expansions can affect the column numbers
of subsequent characters, so a unstateful map + zip won't do.  This
commit hopefully fixes that.  It also adds a test for this particular
case.

Test Plan: validate

Reviewers: bgamari, rwbarton, austin

Reviewed By: bgamari

Subscribers: dfeuer, thomie

Differential Revision: https://phabricator.haskell.org/D3578

compiler/main/ErrUtils.hs
testsuite/tests/warnings/should_fail/CaretDiagnostics1.hs
testsuite/tests/warnings/should_fail/CaretDiagnostics1.stderr

index d87d2b2..b0bbe3c 100644 (file)
@@ -278,13 +278,16 @@ getCaretDiagnostic severity (RealSrcSpan span) = do
 
       where
 
-        fixWhitespace (i, c)
-          | c == '\n' = ""
-            -- show tabs in a device-independent manner #13664
-          | c == '\t' = replicate (8 - i `mod` 8) ' '
-          | otherwise = [c]
-
-        srcLine = concat (map fixWhitespace (zip [0..] srcLineWithNewline))
+        -- expand tabs in a device-independent manner #13664
+        expandTabs tabWidth i s =
+          case s of
+            ""        -> ""
+            '\t' : cs -> replicate effectiveWidth ' ' ++
+                         expandTabs tabWidth (i + effectiveWidth) cs
+            c    : cs -> c : expandTabs tabWidth (i + 1) cs
+          where effectiveWidth = tabWidth - i `mod` tabWidth
+
+        srcLine = filter (/= '\n') (expandTabs 8 0 srcLineWithNewline)
 
         start = srcSpanStartCol span - 1
         end | multiline = length srcLine
index 3ebb5ee..baa8a33 100644 (file)
@@ -18,3 +18,6 @@ fóo = ()
 
 tabby :: Int
 tabby =        ()
+
+tabby2 :: Int
+tabby2 =               ()
index 600b7c7..15dedf0 100644 (file)
@@ -78,3 +78,11 @@ CaretDiagnostics1.hs:20:17-18: error:
    |
 20 | tabby =         ()
    |                 ^^
+
+CaretDiagnostics1.hs:23:25-26: error:
+    • Couldn't match expected type ‘Int’ with actual type ‘()’
+    • In the expression: ()
+      In an equation for ‘tabby2’: tabby2 = ()
+   |
+23 | tabby2 =                ()
+   |                         ^^