elm-review/tests/Util.elm
2020-08-09 18:56:12 +02:00

122 lines
4.3 KiB
Elm

module Util exposing (expressionToString)
import Elm.Syntax.Expression as Expression exposing (Expression)
import Elm.Syntax.Node as Node exposing (Node)
import Elm.Syntax.Range exposing (Range)
import Elm.Writer as Writer
expressionToString : Range -> Expression -> String
expressionToString range expr =
Node.Node range expr
-- Writer expects a slightly different AST than parsing produces
-- TODO: log issue!
|> fixAst
|> Writer.writeExpression
|> Writer.write
-- To make things more parseable by our dear old elm-format, we indent all extra
-- lines so they appear to the right of where we're starting at
|> reindent range.start.column
fixAst : Node Expression -> Node Expression
fixAst ((Node.Node range expr) as node) =
case expr of
Expression.Application nodes ->
Node.Node range (Expression.Application (List.map fixAst nodes))
Expression.OperatorApplication op dir left right ->
Node.Node range
(Expression.OperatorApplication op dir (fixAst left) (fixAst right))
Expression.IfBlock cond trueBranch falseBranch ->
Node.Node range
(Expression.IfBlock (fixAst cond) (fixAst trueBranch) (fixAst falseBranch))
Expression.Negation inner ->
Node.Node range (Expression.Negation (fixAst inner))
Expression.TupledExpression nodes ->
Node.Node range (Expression.TupledExpression (List.map fixAst nodes))
Expression.ParenthesizedExpression inner ->
Node.Node range (Expression.ParenthesizedExpression (fixAst inner))
Expression.LetExpression { declarations, expression } ->
Node.Node range
(Expression.LetExpression
{ declarations = List.map fixLetDeclarationAst declarations
, expression = fixAst expression
}
)
Expression.CaseExpression { expression, cases } ->
Node.Node range
(Expression.CaseExpression
{ expression = fixAst expression
, cases = List.map fixCaseAst cases
}
)
Expression.LambdaExpression { args, expression } ->
Node.Node range
(Expression.LambdaExpression
{ args = args
, expression = fixAst expression
}
)
Expression.RecordExpr setters ->
Node.Node range
(Expression.RecordExpr (List.map fixSetterAst setters))
Expression.ListExpr nodes ->
Node.Node range (Expression.ListExpr (List.map fixAst nodes))
Expression.RecordAccess which field ->
Node.Node range (Expression.RecordAccess (fixAst which) field)
Expression.RecordAccessFunction field ->
-- Writer expects a record-access function to be `"foo"` whereas the parser produces `".foo"`
Node.Node range (Expression.RecordAccessFunction (String.dropLeft 1 field))
Expression.RecordUpdateExpression record setters ->
Node.Node range (Expression.RecordUpdateExpression record (List.map fixSetterAst setters))
_ ->
node
fixCaseAst : Expression.Case -> Expression.Case
fixCaseAst ( pat, node ) =
( pat, fixAst node )
fixLetDeclarationAst : Node Expression.LetDeclaration -> Node Expression.LetDeclaration
fixLetDeclarationAst (Node.Node range decl) =
case decl of
Expression.LetFunction ({ declaration } as f) ->
let
(Node.Node iRange iDecl) =
declaration
in
Node.Node range
(Expression.LetFunction
{ f
| declaration = Node.Node iRange { iDecl | expression = fixAst iDecl.expression }
}
)
Expression.LetDestructuring pat node ->
Node.Node range (Expression.LetDestructuring pat (fixAst node))
fixSetterAst : Node Expression.RecordSetter -> Node Expression.RecordSetter
fixSetterAst (Node.Node range ( name, node )) =
Node.Node range ( name, fixAst node )
reindent : Int -> String -> String
reindent amount =
String.lines >> String.join ("\n" ++ String.repeat (amount - 1) " ")