Skip to content

Commit

Permalink
Allow single-line if expressions
Browse files Browse the repository at this point in the history
Resolves #209
  • Loading branch information
rlefevre committed Nov 18, 2019
1 parent 3b2a0fd commit c541461
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 84 deletions.
2 changes: 1 addition & 1 deletion parser/src/AST/Expression.hs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ data Expr'
| AccessFunction LowercaseIdentifier

| Lambda [(Comments, Pattern.Pattern)] Comments Expr Bool
| If IfClause [(Comments, IfClause)] (Comments, Expr)
| If IfClause [(Comments, IfClause)] (Comments, Expr) Multiline
| Let [LetDeclaration] Comments Expr
| Case (Commented Expr, Bool) [(Commented Pattern.Pattern, (Comments, Expr))]

Expand Down
2 changes: 1 addition & 1 deletion parser/src/AST/Json.hs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ instance ToJSON Expr where
, ("body", showJSON body)
]

If (Commented _ cond' _, Commented _ thenBody' _) rest' (_, elseBody) ->
If (Commented _ cond' _, Commented _ thenBody' _) rest' (_, elseBody) _ ->
let
ifThenElse :: Expr -> Expr -> [(Comments, IfClause)] -> JSValue
ifThenElse cond thenBody rest =
Expand Down
13 changes: 8 additions & 5 deletions parser/src/Parse/Expression.hs
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,14 @@ ifExpr elmVersion =
>> whitespace
in
do
first <- ifClause elmVersion
rest <- many (try $ (,) <$> elseKeyword <*> ifClause elmVersion)
final <- (,) <$> elseKeyword <*> expr elmVersion

return $ E.If first rest final
(first, firstMultiline) <- trackNewline $ ifClause elmVersion
(rest, restMultiline) <- trackNewline $ many (try $ (,) <$> elseKeyword <*> ifClause elmVersion)
(final, finalMultiline) <- trackNewline $ (,) <$> elseKeyword <*> expr elmVersion

return $ E.If first rest final $
case (firstMultiline, restMultiline, finalMultiline) of
(JoinAll, JoinAll, JoinAll) -> JoinAll
_ -> SplitAll


ifClause :: ElmVersion -> IParser E.IfClause
Expand Down
4 changes: 2 additions & 2 deletions src/AST/MapExpr.hs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ instance MapExpr Expr' where
AccessFunction _ -> expr
Lambda params pre body multi ->
Lambda params pre (mapExpr f body) multi
If c1 elseIfs els ->
If (mapExpr f c1) (mapExpr f elseIfs) (mapExpr f els)
If c1 elseIfs els multiline ->
If (mapExpr f c1) (mapExpr f elseIfs) (mapExpr f els) multiline
Let decls pre body ->
Let (mapExpr f decls) pre body
Case cond branches ->
Expand Down
154 changes: 103 additions & 51 deletions src/ElmFormat/Render/Box.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1407,57 +1407,9 @@ formatExpression' elmVersion importInfo context aexpr =
(fmap (formatPreCommentedExpression elmVersion importInfo SpaceSeparated) args)
|> expressionParens SpaceSeparated context

AST.Expression.If if' elseifs (elsComments, els) ->
let
opening key cond =
case (key, cond) of
(SingleLine key', SingleLine cond') ->
line $ row
[ key'
, space
, cond'
, space
, keyword "then"
]
_ ->
stack1
[ key
, cond |> indent
, line $ keyword "then"
]

formatIf (cond, body) =
stack1
[ opening (line $ keyword "if") $ formatCommentedExpression elmVersion importInfo SyntaxSeparated cond
, indent $ formatCommented_ True (formatExpression elmVersion importInfo SyntaxSeparated) body
]

formatElseIf (ifComments, (cond, body)) =
let
key =
case (formatHeadCommented id (ifComments, line $ keyword "if")) of
SingleLine key' ->
line $ row [ keyword "else", space, key' ]
key' ->
stack1
[ line $ keyword "else"
, key'
]
in
stack1
[ blankLine
, opening key $ formatCommentedExpression elmVersion importInfo SyntaxSeparated cond
, indent $ formatCommented_ True (formatExpression elmVersion importInfo SyntaxSeparated) body
]
in
formatIf if'
|> andThen (map formatElseIf elseifs)
|> andThen
[ blankLine
, line $ keyword "else"
, indent $ formatCommented_ True (formatExpression elmVersion importInfo SyntaxSeparated) (AST.Commented elsComments els [])
]
|> expressionParens AmbiguousEnd context
AST.Expression.If if' elseifs els multiline ->
formatIfExpression elmVersion importInfo if' elseifs els multiline
|> expressionParens AmbiguousEnd context

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

formatIfExpression ::
ElmVersion
-> ImportInfo
-> AST.Expression.IfClause
-> [(AST.Comments, AST.Expression.IfClause)]
-> (AST.Comments, AST.Expression.Expr)
-> AST.Multiline
-> Box
formatIfExpression elmVersion importInfo if' elseifs (elsComments, els) multiline =
let
(cond, (AST.Commented preThen thenExpr postThen)) =
if'

then' =
concat $
[ Maybe.maybeToList $ formatComments preThen
, [ formatExpression elmVersion importInfo SyntaxSeparated thenExpr ]
, Maybe.maybeToList $ formatComments postThen
]

else' =
concat $
[ Maybe.maybeToList $ formatComments elsComments
, [ formatExpression elmVersion importInfo SyntaxSeparated els ]
]
in
case
( multiline
, formatCommentedExpression elmVersion importInfo SyntaxSeparated cond
, allSingles then'
, elseifs
, allSingles else'
)
of
(AST.JoinAll, SingleLine cond', Right singleThens, [], Right singleElses) ->
line $ row $ concat
[ [ keyword "if", space, cond', space, keyword "then", space ]
, List.intersperse space singleThens
, [ space, keyword "else", space ]
, List.intersperse space singleElses
]

(_, ifCond, thenBody, _, elseBody) ->
formatIfExpressionMultiline elmVersion importInfo ifCond thenBody elseifs elseBody


formatIfExpressionMultiline ::
ElmVersion
-> ImportInfo
-> Box
-> Either [Box] [Line]
-> [(AST.Comments, AST.Expression.IfClause)]
-> Either [Box] [Line]
-> Box
formatIfExpressionMultiline elmVersion importInfo ifCond thenBody elseifs elseBody =
let
opening (SingleLine key) (SingleLine cond') =
line $ row [ key, space, cond', space, keyword "then" ]
opening key cond' =
stack1
[ key
, cond' |> indent
, line $ keyword "then"
]

boxesOrLinesToBox boxesOrLines =
ElmStructure.forceableSpaceSepOrStack1 True $
case boxesOrLines of
Right singleLines -> map line singleLines
Left boxes -> boxes

formatElseIf (ifComments, (cond', body')) =
let
key =
case (formatHeadCommented id (ifComments, line $ keyword "if")) of
SingleLine key' ->
line $ row [ keyword "else", space, key' ]
key' ->
stack1
[ line $ keyword "else"
, key'
]
in
stack1
[ blankLine
, opening key $ formatCommentedExpression elmVersion importInfo SyntaxSeparated cond'
, indent $ formatCommented_ True (formatExpression elmVersion importInfo SyntaxSeparated) body'
]
in
stack1
[ opening (line $ keyword "if") ifCond
, indent $ boxesOrLinesToBox thenBody
]
|> andThen (map formatElseIf elseifs)
|> andThen
[ blankLine
, line $ keyword "else"
, indent $ boxesOrLinesToBox elseBody
]


formatLiteral :: ElmVersion -> AST.Literal -> Box
formatLiteral elmVersion lit =
Expand Down
8 changes: 4 additions & 4 deletions tests/Parse/ExpressionTest.hs
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,10 @@ tests =
]

, testGroup "if statement"
[ 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"))))
, 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"))))
, 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"))))
, 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"))))
[ 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)
, 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)
, 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)
, 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)
]

, testGroup "let statement"
Expand Down
17 changes: 15 additions & 2 deletions tests/test-files/good/Elm-0.19/AllSyntax/Expressions.elm
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,16 @@ lambdaWithMultilinePattern =
ifStatement =
let
a =
if True then 1 else 2

b =
if True then
1

else
2

c =
if True then
1

Expand All @@ -282,7 +292,10 @@ ifStatement =
else
3

b =
d =
if {- A -} True {- B -} then {- C -} 1 {- D -} else {- E -} 2

e =
if {- C -} True {- D -} then
{- E -}
1
Expand All @@ -297,7 +310,7 @@ ifStatement =
{- L -}
3

c =
f =
if
--C
True
Expand Down
20 changes: 2 additions & 18 deletions tests/test-files/transform/Elm-0.18/Examples.formatted.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,15 @@ module Main exposing (bar, multilineList, ratio)


ratio =
graphHeight
/ (if range == 0 then
0.1

else
toFloat range
)
graphHeight / (if range == 0 then 0.1 else toFloat range)



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


bar =
if
if a then
True

else
False
then
"a"

else
"b"
if if a then True else False then "a" else "b"


multilineList =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x = if True then 1 else if False then 2 else 3
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Main exposing (x)


x =
if True then
1

else if False then
2

else
3

0 comments on commit c541461

Please sign in to comment.