Skip to content

Commit 12f4095

Browse files
committed
Allow single-line if expressions
Resolves #209
1 parent 3b2a0fd commit 12f4095

File tree

11 files changed

+150
-74
lines changed

11 files changed

+150
-74
lines changed

parser/src/AST/Expression.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ data Expr'
5959
| AccessFunction LowercaseIdentifier
6060

6161
| Lambda [(Comments, Pattern.Pattern)] Comments Expr Bool
62-
| If IfClause [(Comments, IfClause)] (Comments, Expr)
62+
| If IfClause [(Comments, IfClause)] (Comments, Expr) Multiline
6363
| Let [LetDeclaration] Comments Expr
6464
| Case (Commented Expr, Bool) [(Commented Pattern.Pattern, (Comments, Expr))]
6565

parser/src/AST/Json.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ instance ToJSON Expr where
373373
, ("body", showJSON body)
374374
]
375375

376-
If (Commented _ cond' _, Commented _ thenBody' _) rest' (_, elseBody) ->
376+
If (Commented _ cond' _, Commented _ thenBody' _) rest' (_, elseBody) _ ->
377377
let
378378
ifThenElse :: Expr -> Expr -> [(Comments, IfClause)] -> JSValue
379379
ifThenElse cond thenBody rest =

parser/src/Parse/Expression.hs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,14 @@ ifExpr elmVersion =
191191
>> whitespace
192192
in
193193
do
194-
first <- ifClause elmVersion
195-
rest <- many (try $ (,) <$> elseKeyword <*> ifClause elmVersion)
196-
final <- (,) <$> elseKeyword <*> expr elmVersion
197-
198-
return $ E.If first rest final
194+
(first, firstMultiline) <- trackNewline $ ifClause elmVersion
195+
(rest, restMultiline) <- trackNewline $ many (try $ (,) <$> elseKeyword <*> ifClause elmVersion)
196+
(final, finalMultiline) <- trackNewline $ (,) <$> elseKeyword <*> expr elmVersion
197+
198+
return $ E.If first rest final $
199+
case (firstMultiline, restMultiline, finalMultiline) of
200+
(JoinAll, JoinAll, JoinAll) -> JoinAll
201+
_ -> SplitAll
199202

200203

201204
ifClause :: ElmVersion -> IParser E.IfClause

src/AST/MapExpr.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ instance MapExpr Expr' where
8181
AccessFunction _ -> expr
8282
Lambda params pre body multi ->
8383
Lambda params pre (mapExpr f body) multi
84-
If c1 elseIfs els ->
85-
If (mapExpr f c1) (mapExpr f elseIfs) (mapExpr f els)
84+
If c1 elseIfs els multiline ->
85+
If (mapExpr f c1) (mapExpr f elseIfs) (mapExpr f els) multiline
8686
Let decls pre body ->
8787
Let (mapExpr f decls) pre body
8888
Case cond branches ->

src/ElmFormat/Render/Box.hs

Lines changed: 103 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,57 +1407,9 @@ formatExpression' elmVersion importInfo context aexpr =
14071407
(fmap (formatPreCommentedExpression elmVersion importInfo SpaceSeparated) args)
14081408
|> expressionParens SpaceSeparated context
14091409

1410-
AST.Expression.If if' elseifs (elsComments, els) ->
1411-
let
1412-
opening key cond =
1413-
case (key, cond) of
1414-
(SingleLine key', SingleLine cond') ->
1415-
line $ row
1416-
[ key'
1417-
, space
1418-
, cond'
1419-
, space
1420-
, keyword "then"
1421-
]
1422-
_ ->
1423-
stack1
1424-
[ key
1425-
, cond |> indent
1426-
, line $ keyword "then"
1427-
]
1428-
1429-
formatIf (cond, body) =
1430-
stack1
1431-
[ opening (line $ keyword "if") $ formatCommentedExpression elmVersion importInfo SyntaxSeparated cond
1432-
, indent $ formatCommented_ True (formatExpression elmVersion importInfo SyntaxSeparated) body
1433-
]
1434-
1435-
formatElseIf (ifComments, (cond, body)) =
1436-
let
1437-
key =
1438-
case (formatHeadCommented id (ifComments, line $ keyword "if")) of
1439-
SingleLine key' ->
1440-
line $ row [ keyword "else", space, key' ]
1441-
key' ->
1442-
stack1
1443-
[ line $ keyword "else"
1444-
, key'
1445-
]
1446-
in
1447-
stack1
1448-
[ blankLine
1449-
, opening key $ formatCommentedExpression elmVersion importInfo SyntaxSeparated cond
1450-
, indent $ formatCommented_ True (formatExpression elmVersion importInfo SyntaxSeparated) body
1451-
]
1452-
in
1453-
formatIf if'
1454-
|> andThen (map formatElseIf elseifs)
1455-
|> andThen
1456-
[ blankLine
1457-
, line $ keyword "else"
1458-
, indent $ formatCommented_ True (formatExpression elmVersion importInfo SyntaxSeparated) (AST.Commented elsComments els [])
1459-
]
1460-
|> expressionParens AmbiguousEnd context
1410+
AST.Expression.If if' elseifs els multiline ->
1411+
formatIfExpression elmVersion importInfo if' elseifs els multiline
1412+
|> expressionParens AmbiguousEnd context
14611413

14621414
AST.Expression.Let defs bodyComments expr ->
14631415
let
@@ -2120,6 +2072,106 @@ formatComment comment =
21202072
AST.CommentTrickBlock c ->
21212073
mustBreak $ row [ punc "{--", literal c, punc "-}" ]
21222074

2075+
formatIfExpression ::
2076+
ElmVersion
2077+
-> ImportInfo
2078+
-> AST.Expression.IfClause
2079+
-> [(AST.Comments, AST.Expression.IfClause)]
2080+
-> (AST.Comments, AST.Expression.Expr)
2081+
-> AST.Multiline
2082+
-> Box
2083+
formatIfExpression elmVersion importInfo if' elseifs (elsComments, els) multiline =
2084+
let
2085+
(cond, (AST.Commented preThen thenExpr postThen)) =
2086+
if'
2087+
2088+
then' =
2089+
concat $
2090+
[ Maybe.maybeToList $ formatComments preThen
2091+
, [ formatExpression elmVersion importInfo SyntaxSeparated thenExpr ]
2092+
, Maybe.maybeToList $ formatComments postThen
2093+
]
2094+
2095+
else' =
2096+
concat $
2097+
[ Maybe.maybeToList $ formatComments elsComments
2098+
, [ formatExpression elmVersion importInfo SyntaxSeparated els ]
2099+
]
2100+
in
2101+
case
2102+
( multiline
2103+
, formatCommentedExpression elmVersion importInfo SyntaxSeparated cond
2104+
, allSingles then'
2105+
, elseifs
2106+
, allSingles else'
2107+
)
2108+
of
2109+
(AST.JoinAll, SingleLine cond', Right singleThens, [], Right singleElses) ->
2110+
line $ row $ concat
2111+
[ [ keyword "if", space, cond', space, keyword "then", space ]
2112+
, List.intersperse space singleThens
2113+
, [ space, keyword "else", space ]
2114+
, List.intersperse space singleElses
2115+
]
2116+
2117+
(_, ifCond, thenBody, _, elseBody) ->
2118+
formatIfExpressionMultiline elmVersion importInfo ifCond thenBody elseifs elseBody
2119+
2120+
2121+
formatIfExpressionMultiline ::
2122+
ElmVersion
2123+
-> ImportInfo
2124+
-> Box
2125+
-> Either [Box] [Line]
2126+
-> [(AST.Comments, AST.Expression.IfClause)]
2127+
-> Either [Box] [Line]
2128+
-> Box
2129+
formatIfExpressionMultiline elmVersion importInfo ifCond thenBody elseifs elseBody =
2130+
let
2131+
opening (SingleLine key) (SingleLine cond') =
2132+
line $ row [ key, space, cond', space, keyword "then" ]
2133+
opening key cond' =
2134+
stack1
2135+
[ key
2136+
, cond' |> indent
2137+
, line $ keyword "then"
2138+
]
2139+
2140+
boxesOrLinesToBox boxesOrLines =
2141+
ElmStructure.forceableSpaceSepOrStack1 True $
2142+
case boxesOrLines of
2143+
Right singleLines -> map line singleLines
2144+
Left boxes -> boxes
2145+
2146+
formatElseIf (ifComments, (cond', body')) =
2147+
let
2148+
key =
2149+
case (formatHeadCommented id (ifComments, line $ keyword "if")) of
2150+
SingleLine key' ->
2151+
line $ row [ keyword "else", space, key' ]
2152+
key' ->
2153+
stack1
2154+
[ line $ keyword "else"
2155+
, key'
2156+
]
2157+
in
2158+
stack1
2159+
[ blankLine
2160+
, opening key $ formatCommentedExpression elmVersion importInfo SyntaxSeparated cond'
2161+
, indent $ formatCommented_ True (formatExpression elmVersion importInfo SyntaxSeparated) body'
2162+
]
2163+
in
2164+
stack1
2165+
[ opening (line $ keyword "if") ifCond
2166+
, indent $ boxesOrLinesToBox thenBody
2167+
]
2168+
|> andThen (map formatElseIf elseifs)
2169+
|> andThen
2170+
[ blankLine
2171+
, line $ keyword "else"
2172+
, indent $ boxesOrLinesToBox elseBody
2173+
]
2174+
21232175

21242176
formatLiteral :: ElmVersion -> AST.Literal -> Box
21252177
formatLiteral elmVersion lit =

tests/Parse/ExpressionTest.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,10 @@ tests =
259259
]
260260

261261
, testGroup "if statement"
262-
[ example "" "if x then y else z" $ at 1 1 1 19 (If (Commented [] (at 1 4 1 5 (VarExpr (VarRef [] $ LowercaseIdentifier "x"))) [],Commented [] (at 1 11 1 12 (VarExpr (VarRef [] $ LowercaseIdentifier "y"))) []) [] ([],at 1 18 1 19 (VarExpr (VarRef [] $ LowercaseIdentifier "z"))))
263-
, example "comments" "if{-A-}x{-B-}then{-C-}y{-D-}else{-E-}if{-F-}x_{-G-}then{-H-}y_{-I-}else{-J-}z" $ at 1 1 1 78 (If (Commented [BlockComment ["A"]] (at 1 8 1 9 (VarExpr (VarRef [] $ LowercaseIdentifier "x"))) [BlockComment ["B"]],Commented [BlockComment ["C"]] (at 1 23 1 24 (VarExpr (VarRef [] $ LowercaseIdentifier "y"))) [BlockComment ["D"]]) [([BlockComment ["E"]],(Commented [BlockComment ["F"]] (at 1 45 1 47 (VarExpr (VarRef [] $ LowercaseIdentifier "x_"))) [BlockComment ["G"]],Commented [BlockComment ["H"]] (at 1 61 1 63 (VarExpr (VarRef [] $ LowercaseIdentifier "y_"))) [BlockComment ["I"]]))] ([BlockComment ["J"]],at 1 77 1 78 (VarExpr (VarRef [] $ LowercaseIdentifier "z"))))
264-
, example "else if" "if x1 then y1 else if x2 then y2 else if x3 then y3 else z" $ at 1 1 1 59 (If (Commented [] (at 1 4 1 6 (VarExpr (VarRef [] $ LowercaseIdentifier "x1"))) [],Commented [] (at 1 12 1 14 (VarExpr (VarRef [] $ LowercaseIdentifier "y1"))) []) [([],(Commented [] (at 1 23 1 25 (VarExpr (VarRef [] $ LowercaseIdentifier "x2"))) [],Commented [] (at 1 31 1 33 (VarExpr (VarRef [] $ LowercaseIdentifier "y2"))) [])),([],(Commented [] (at 1 42 1 44 (VarExpr (VarRef [] $ LowercaseIdentifier "x3"))) [],Commented [] (at 1 50 1 52 (VarExpr (VarRef [] $ LowercaseIdentifier "y3"))) []))] ([],at 1 58 1 59 (VarExpr (VarRef [] $ LowercaseIdentifier "z"))))
265-
, example "newlines" "if\n x\n then\n y\n else\n z" $ at 1 1 6 3 (If (Commented [] (at 2 2 2 3 (VarExpr (VarRef [] $ LowercaseIdentifier "x"))) [],Commented [] (at 4 2 4 3 (VarExpr (VarRef [] $ LowercaseIdentifier "y"))) []) [] ([],at 6 2 6 3 (VarExpr (VarRef [] $ LowercaseIdentifier "z"))))
262+
[ example "" "if x then y else z" $ at 1 1 1 19 (If (Commented [] (at 1 4 1 5 (VarExpr (VarRef [] $ LowercaseIdentifier "x"))) [],Commented [] (at 1 11 1 12 (VarExpr (VarRef [] $ LowercaseIdentifier "y"))) []) [] ([],at 1 18 1 19 (VarExpr (VarRef [] $ LowercaseIdentifier "z"))) JoinAll)
263+
, example "comments" "if{-A-}x{-B-}then{-C-}y{-D-}else{-E-}if{-F-}x_{-G-}then{-H-}y_{-I-}else{-J-}z" $ at 1 1 1 78 (If (Commented [BlockComment ["A"]] (at 1 8 1 9 (VarExpr (VarRef [] $ LowercaseIdentifier "x"))) [BlockComment ["B"]],Commented [BlockComment ["C"]] (at 1 23 1 24 (VarExpr (VarRef [] $ LowercaseIdentifier "y"))) [BlockComment ["D"]]) [([BlockComment ["E"]],(Commented [BlockComment ["F"]] (at 1 45 1 47 (VarExpr (VarRef [] $ LowercaseIdentifier "x_"))) [BlockComment ["G"]],Commented [BlockComment ["H"]] (at 1 61 1 63 (VarExpr (VarRef [] $ LowercaseIdentifier "y_"))) [BlockComment ["I"]]))] ([BlockComment ["J"]],at 1 77 1 78 (VarExpr (VarRef [] $ LowercaseIdentifier "z"))) JoinAll)
264+
, example "else if" "if x1 then y1 else if x2 then y2 else if x3 then y3 else z" $ at 1 1 1 59 (If (Commented [] (at 1 4 1 6 (VarExpr (VarRef [] $ LowercaseIdentifier "x1"))) [],Commented [] (at 1 12 1 14 (VarExpr (VarRef [] $ LowercaseIdentifier "y1"))) []) [([],(Commented [] (at 1 23 1 25 (VarExpr (VarRef [] $ LowercaseIdentifier "x2"))) [],Commented [] (at 1 31 1 33 (VarExpr (VarRef [] $ LowercaseIdentifier "y2"))) [])),([],(Commented [] (at 1 42 1 44 (VarExpr (VarRef [] $ LowercaseIdentifier "x3"))) [],Commented [] (at 1 50 1 52 (VarExpr (VarRef [] $ LowercaseIdentifier "y3"))) []))] ([],at 1 58 1 59 (VarExpr (VarRef [] $ LowercaseIdentifier "z"))) JoinAll)
265+
, example "newlines" "if\n x\n then\n y\n else\n z" $ at 1 1 6 3 (If (Commented [] (at 2 2 2 3 (VarExpr (VarRef [] $ LowercaseIdentifier "x"))) [],Commented [] (at 4 2 4 3 (VarExpr (VarRef [] $ LowercaseIdentifier "y"))) []) [] ([],at 6 2 6 3 (VarExpr (VarRef [] $ LowercaseIdentifier "z"))) SplitAll)
266266
]
267267

268268
, testGroup "let statement"

tests/test-files/good/Elm-0.19/AllSyntax/Expressions.elm

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,16 @@ lambdaWithMultilinePattern =
273273
ifStatement =
274274
let
275275
a =
276+
if True then 1 else 2
277+
278+
b =
279+
if True then
280+
1
281+
282+
else
283+
2
284+
285+
c =
276286
if True then
277287
1
278288

@@ -282,7 +292,10 @@ ifStatement =
282292
else
283293
3
284294

285-
b =
295+
d =
296+
if {- A -} True {- B -} then {- C -} 1 {- D -} else {- E -} 2
297+
298+
e =
286299
if {- C -} True {- D -} then
287300
{- E -}
288301
1
@@ -297,7 +310,7 @@ ifStatement =
297310
{- L -}
298311
3
299312

300-
c =
313+
f =
301314
if
302315
--C
303316
True

tests/test-files/transform/Elm-0.18/Examples.elm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ ratio = graphHeight / (if range == 0 then 0.1 else toFloat range)
44

55
-- foo=(case x of {True->1;False->3})
66

7-
bar = (if if a then True else False then "a" else "b")
7+
bar = (if if a then
8+
True else False then "a" else "b")
89

910
multilineList = [1,2,3
1011
]

tests/test-files/transform/Elm-0.18/Examples.formatted.elm

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@ module Main exposing (bar, multilineList, ratio)
22

33

44
ratio =
5-
graphHeight
6-
/ (if range == 0 then
7-
0.1
8-
9-
else
10-
toFloat range
11-
)
5+
graphHeight / (if range == 0 then 0.1 else toFloat range)
126

137

148

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
x = if True then 1 else if False then 2 else 3

0 commit comments

Comments
 (0)