on master help sign in
Improve code that extracts code from source in errors
3f6ffc3Evan Czaplicki
src/Elm/Compiler.hs+4−4
@@ -158,12 +158,12 @@ newtype Error =
158 Error (A.Located Error.Error)
158 Error (A.Located Error.Error)
159
159
160
160
161−errorToString :: Localizer -> String -> String -> Error -> String
161+errorToString :: Localizer -> String -> Text -> Error -> String
162errorToString (Localizer localizer) location source (Error (A.A region err)) =
162errorToString (Localizer localizer) location source (Error (A.A region err)) =
163 Report.toString location region (Error.toReport localizer err) source
163 Report.toString location region (Error.toReport localizer err) source
164
164
165
165
166−printError :: Handle -> Localizer -> String -> String -> Error -> IO ()
166+printError :: Handle -> Localizer -> String -> Text -> Error -> IO ()
167printError handle (Localizer localizer) location source (Error (A.A region err)) =
167printError handle (Localizer localizer) location source (Error (A.A region err)) =
168 Report.toHandle handle location region (Error.toReport localizer err) source
168 Report.toHandle handle location region (Error.toReport localizer err) source
169
169
@@ -181,12 +181,12 @@ newtype Warning =
181 Warning (A.Located Warning.Warning)
181 Warning (A.Located Warning.Warning)
182
182
183
183
184−warningToString :: Localizer -> String -> String -> Warning -> String
184+warningToString :: Localizer -> String -> Text -> Warning -> String
185warningToString (Localizer localizer) location source (Warning (A.A region wrn)) =
185warningToString (Localizer localizer) location source (Warning (A.A region wrn)) =
186 Report.toString location region (Warning.toReport localizer wrn) source
186 Report.toString location region (Warning.toReport localizer wrn) source
187
187
188
188
189−printWarning :: Handle -> Localizer -> String -> String -> Warning -> IO ()
189+printWarning :: Handle -> Localizer -> String -> Text -> Warning -> IO ()
190printWarning handle (Localizer localizer) location source (Warning (A.A region wrn)) =
190printWarning handle (Localizer localizer) location source (Warning (A.A region wrn)) =
191 Report.toHandle handle location region (Warning.toReport localizer wrn) source
191 Report.toHandle handle location region (Warning.toReport localizer wrn) source
192
192
src/Reporting/Render/Code.hs+52−73
@@ -1,13 +1,13 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2−module Reporting.Render.Code
2+module Reporting.Render.Code (render) where
3− ( render
4− )
5− where
6
3
7−import Control.Applicative ((<|>))
4+import Data.Text (Text)
5+import qualified Data.Text as Text
6+import Text.PrettyPrint.ANSI.Leijen
8−import Text.PrettyPrint.ANSI.Leijen (Doc, (<>), hardline, dullred, empty, text)
7+ ( Doc, (<>), hardline, dullred, empty, text )
9
8
10import qualified Reporting.Region as R
9import qualified Reporting.Region as R
10+import qualified Reporting.Helpers as H
11
11
12
12
13(|>) :: a -> (a -> b) -> b
13(|>) :: a -> (a -> b) -> b
@@ -20,59 +20,62 @@ import qualified Reporting.Region as R
20 a <> hardline <> b
20 a <> hardline <> b
21
21
22
22
23−render :: Maybe R.Region -> R.Region -> String -> Doc
23+render :: Maybe R.Region -> R.Region -> Text -> Doc
24render maybeSubRegion region@(R.Region start end) source =
24render maybeSubRegion region@(R.Region start end) source =
25 let
25 let
26− (R.Position startLine startColumn) = start
26+ (R.Position startLine _) = start
27− (R.Position endLine endColumn) = end
27+ (R.Position endLine _) = end
28
28
29 relevantLines =
29 relevantLines =
30− lines source
30+ (Text.lines source ++ [Text.empty])
31+ |> take endLine
31− |> drop (startLine - 1)
32+ |> drop (startLine - 1)
32− |> take (endLine - startLine + 1)
33+ |> zip [startLine .. endLine + 1]
34+
35+ width =
36+ length (show (fst (last relevantLines)))
37+
38+ smallerRegion =
39+ maybe region id maybeSubRegion
33 in
40 in
34− case relevantLines of
41+ case makeUnderline width endLine smallerRegion of
35− [] ->
42+ Nothing ->
36− empty
43+ drawLines True width smallerRegion relevantLines empty
37
44
38− [sourceLine] ->
45+ Just underline ->
39− singleLineRegion startLine sourceLine $
46+ drawLines False width smallerRegion relevantLines underline
40− case maybeSubRegion of
41− Nothing ->
42− (0, startColumn, endColumn, length sourceLine)
43
47
44− Just (R.Region s e) ->
45− (startColumn, R.column s, R.column e, endColumn)
46
48
47− firstLine : rest ->
49+makeUnderline :: Int -> Int -> R.Region -> Maybe Doc
48− let
50+makeUnderline width realEndLine (R.Region (R.Position start c1) (R.Position end c2)) =
49− filteredFirstLine =
51+ if start /= end || end < realEndLine then
50− replicate (startColumn - 1) ' '
52+ Nothing
51− ++ drop (startColumn - 1) firstLine
52
53
53− filteredLastLine =
54+ else
54− take (endColumn) (last rest)
55+ let
56+ spaces = replicate (c1 + width + 1) ' '
57+ zigzag = replicate (max 1 (c2 - c1)) '^'
58+ in
59+ Just (text spaces <> dullred (text zigzag))
55
60
56− focusedRelevantLines =
57− filteredFirstLine : init rest ++ [filteredLastLine]
58
61
59− lineNumbersWidth =
62+drawLines :: Bool -> Int -> R.Region -> [(Int, Text)] -> Doc -> Doc
60− length (show endLine)
63+drawLines addZigZag width (R.Region start end) sourceLines finalLine =
64+ let
65+ (R.Position startLine _) = start
66+ (R.Position endLine _) = end
67+ in
68+ foldr (<==>) finalLine $
69+ map (drawLine addZigZag width startLine endLine) sourceLines
61
70
62− subregion =
63− maybeSubRegion <|> Just region
64
71
65− numberedLines =
72+drawLine :: Bool -> Int -> Int -> Int -> (Int, Text) -> Doc
66− zipWith
73+drawLine addZigZag width startLine endLine (n, line) =
67− (addLineNumber subregion lineNumbersWidth)
74+ addLineNumber addZigZag width startLine endLine n (H.text line)
68− [startLine .. endLine]
69− focusedRelevantLines
70− in
71− foldr (<==>) empty numberedLines
72
75
73
76
74−addLineNumber :: Maybe R.Region -> Int -> Int -> String -> Doc
77+addLineNumber :: Bool -> Int -> Int -> Int -> Int -> Doc -> Doc
75−addLineNumber maybeSubRegion width n line =
78+addLineNumber addZigZag width start end n line =
76 let
79 let
77 number =
80 number =
78 if n < 0 then " " else show n
81 if n < 0 then " " else show n
@@ -80,34 +83,10 @@ addLineNumber maybeSubRegion width n line =
80 lineNumber =
83 lineNumber =
81 replicate (width - length number) ' ' ++ number ++ "|"
84 replicate (width - length number) ' ' ++ number ++ "|"
82
85
83− spacer (R.Region start end) =
86+ spacer =
84− if R.line start <= n && n <= R.line end then
87+ if addZigZag && start <= n && n <= end then
85− dullred (text ">")
88+ dullred (text ">")
86 else
89 else
87− text " "
90+ text " "
88− in
89− text lineNumber
90− <> maybe (text " ") spacer maybeSubRegion
91− <> text line
92−
93−
94−singleLineRegion :: Int -> String -> (Int, Int, Int, Int) -> Doc
95−singleLineRegion lineNum sourceLine (start, innerStart, innerEnd, end) =
96− let
97− width =
98− length (show lineNum)
99−
100− underline =
101− text (replicate (innerStart + width + 1) ' ')
102− <>
103− dullred (text (replicate (max 1 (innerEnd - innerStart)) '^'))
104−
105− trimmedSourceLine =
106− sourceLine
107− |> drop (start - 1)
108− |> take (end - start + 1)
109− |> (++) (replicate (start - 1) ' ')
110 in
91 in
111− addLineNumber Nothing width lineNum trimmedSourceLine
92+ text lineNumber <> spacer <> line
112− <==>
113− underline
src/Reporting/Report.hs+3−3
@@ -61,7 +61,7 @@ toJson extraFields (Report title subregion pre post) =
61-- REPORT TO DOC
61-- REPORT TO DOC
62
62
63
63
64−toDoc :: String -> R.Region -> Report -> String -> Doc
64+toDoc :: String -> R.Region -> Report -> Text -> Doc
65toDoc location region (Report title highlight preHint postHint) source =
65toDoc location region (Report title highlight preHint postHint) source =
66 messageBar title location
66 messageBar title location
67 <> hardline <> hardline <>
67 <> hardline <> hardline <>
@@ -89,14 +89,14 @@ messageBar tag location =
89-- RENDER DOCS
89-- RENDER DOCS
90
90
91
91
92−toHandle :: Handle -> String -> R.Region -> Report -> String -> IO ()
92+toHandle :: Handle -> String -> R.Region -> Report -> Text -> IO ()
93toHandle handle location region rprt source =
93toHandle handle location region rprt source =
94 displayIO
94 displayIO
95 handle
95 handle
96 (renderPretty 1 80 (toDoc location region rprt source))
96 (renderPretty 1 80 (toDoc location region rprt source))
97
97
98
98
99−toString :: String -> R.Region -> Report -> String -> String
99+toString :: String -> R.Region -> Report -> Text -> String
100toString location region rprt source =
100toString location region rprt source =
101 nonAnsiRender (toDoc location region rprt source)
101 nonAnsiRender (toDoc location region rprt source)
102
102
tests/Test/Compiler.hs+1−2
@@ -9,7 +9,6 @@ import qualified Data.Text.Lazy as LText
9import qualified Data.Text.Lazy.IO as LText
9import qualified Data.Text.Lazy.IO as LText
10import qualified Data.Map as Map
10import qualified Data.Map as Map
11import Data.Maybe (isJust)
11import Data.Maybe (isJust)
12−import qualified Data.Text as Text
13import qualified Data.Text.IO as Text
12import qualified Data.Text.IO as Text
14import Data.Text (Text)
13import Data.Text (Text)
15
14
@@ -112,7 +111,7 @@ compile filePath source =
112 (dealiaser, _warnings, result) =
111 (dealiaser, _warnings, result) =
113 Compiler.compile context source essentialInterfaces
112 Compiler.compile context source essentialInterfaces
114 formatErrors errors =
113 formatErrors errors =
115− concatMap (Compiler.errorToString dealiaser filePath (Text.unpack source)) errors
114+ concatMap (Compiler.errorToString dealiaser filePath source) errors
116 in
115 in
117 either (Left . formatErrors) Right result
116 either (Left . formatErrors) Right result
118
117