From a37a7df2178cf4a6c8f31fb7f5cda67860fed33e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 28 Jan 2016 22:03:44 -0600 Subject: [PATCH 01/31] Readying for release --- CHANGELOG.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0fab5f..941d166 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# v2.2.0-dev +# v2.2.0 * Enhancements: * Added structs for JSX AST diff --git a/mix.exs b/mix.exs index 88ddc0b..d00e987 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule ESTree.Mixfile do def project do [app: :estree, - version: "2.2.0-dev", + version: "2.2.0", elixir: "~> 1.0", deps: deps, description: description, From 58e7de2a5a854161742d3b1ef608a201a3901700 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 5 Mar 2016 07:28:08 -0600 Subject: [PATCH 02/31] Added assignment property --- CHANGELOG.md | 5 +++++ lib/es_tree/assignment_expression.ex | 14 +++++++------- lib/es_tree/assignment_property.ex | 10 ++++++++++ lib/es_tree/for_in_statement.ex | 8 ++++---- lib/es_tree/for_of_statement.ex | 14 +++++++------- lib/es_tree/node.ex | 2 -- lib/es_tree/object_pattern.ex | 6 +++--- lib/es_tree/tools/builder.ex | 29 +++++++++++++++++++--------- lib/es_tree/tools/generator.ex | 9 +++++++-- mix.exs | 2 +- 10 files changed, 64 insertions(+), 35 deletions(-) create mode 100644 lib/es_tree/assignment_property.ex diff --git a/CHANGELOG.md b/CHANGELOG.md index 941d166..a03a6f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v2.3.0 +* Enhancements: + * Added AssignmentProperty for use with ObjectPattern + * Updated some typespecs to reflect updates in ESTree spec + # v2.2.0 * Enhancements: * Added structs for JSX AST diff --git a/lib/es_tree/assignment_expression.ex b/lib/es_tree/assignment_expression.ex index a68bc07..5a8a12a 100644 --- a/lib/es_tree/assignment_expression.ex +++ b/lib/es_tree/assignment_expression.ex @@ -1,14 +1,14 @@ defmodule ESTree.AssignmentExpression do - @type t :: %ESTree.AssignmentExpression{ - type: binary, + @type t :: %ESTree.AssignmentExpression{ + type: binary, loc: ESTree.SourceLocation.t | nil, operator: ESTree.assignment_operator, - left: ESTree.Pattern.t | ESTree.Expression.t, + left: ESTree.Pattern.t, right: ESTree.Expression.t } - defstruct type: "AssignmentExpression", - loc: nil, + defstruct type: "AssignmentExpression", + loc: nil, operator: nil, left: %ESTree.EmptyExpression{}, - right: %ESTree.EmptyExpression{} -end \ No newline at end of file + right: %ESTree.EmptyExpression{} +end diff --git a/lib/es_tree/assignment_property.ex b/lib/es_tree/assignment_property.ex new file mode 100644 index 0000000..6fdf9df --- /dev/null +++ b/lib/es_tree/assignment_property.ex @@ -0,0 +1,10 @@ +defmodule ESTree.AssignmentProperty do + @type t :: %ESTree.AssignmentProperty{ + type: binary, + loc: ESTree.SourceLocation.t | nil, + value: ESTree.Pattern.t + } + defstruct type: "Property", + loc: nil, + value: %ESTree.EmptyExpression{} +end diff --git a/lib/es_tree/for_in_statement.ex b/lib/es_tree/for_in_statement.ex index 7840a22..9a81902 100644 --- a/lib/es_tree/for_in_statement.ex +++ b/lib/es_tree/for_in_statement.ex @@ -1,8 +1,8 @@ defmodule ESTree.ForInStatement do - @type t :: %ESTree.ForInStatement{ - type: binary, + @type t :: %ESTree.ForInStatement{ + type: binary, loc: ESTree.SourceLocation.t | nil, - left: ESTree.VariableDeclaration.t | ESTree.Expression.t , + left: ESTree.VariableDeclaration.t | ESTree.Pattern.t , right: ESTree.Expression.t , body: ESTree.Statement.t } @@ -11,4 +11,4 @@ defmodule ESTree.ForInStatement do left: %ESTree.EmptyExpression{}, right: %ESTree.EmptyExpression{}, body: %ESTree.EmptyStatement{} -end \ No newline at end of file +end diff --git a/lib/es_tree/for_of_statement.ex b/lib/es_tree/for_of_statement.ex index d3ceef9..7649a54 100644 --- a/lib/es_tree/for_of_statement.ex +++ b/lib/es_tree/for_of_statement.ex @@ -1,14 +1,14 @@ defmodule ESTree.ForOfStatement do - @type t :: %ESTree.ForOfStatement{ - type: binary, + @type t :: %ESTree.ForOfStatement{ + type: binary, loc: ESTree.SourceLocation.t | nil, - left: ESTree.VariableDeclaration.t | ESTree.Expression.t , + left: ESTree.VariableDeclaration.t | ESTree.Pattern.t , right: ESTree.Expression.t , - body: ESTree.Statement.t + body: ESTree.Statement.t } - defstruct type: "ForOfStatement", - loc: nil, + defstruct type: "ForOfStatement", + loc: nil, left: %ESTree.EmptyExpression{}, right: %ESTree.EmptyExpression{}, body: %ESTree.EmptyStatement{} -end \ No newline at end of file +end diff --git a/lib/es_tree/node.ex b/lib/es_tree/node.ex index 5578027..46f3da3 100644 --- a/lib/es_tree/node.ex +++ b/lib/es_tree/node.ex @@ -8,8 +8,6 @@ defmodule ESTree.Node do ESTree.Pattern.t | ESTree.SwitchCase.t | ESTree.CatchClause.t | - ESTree.Identifier.t | - ESTree.Literal.t | ESTree.MethodDefinition.t | ESTree.Class.t | ESTree.ClassBody.t | diff --git a/lib/es_tree/object_pattern.ex b/lib/es_tree/object_pattern.ex index 619edeb..196d422 100644 --- a/lib/es_tree/object_pattern.ex +++ b/lib/es_tree/object_pattern.ex @@ -1,10 +1,10 @@ defmodule ESTree.ObjectPattern do - @type t :: %ESTree.ObjectPattern{ + @type t :: %ESTree.ObjectPattern{ type: binary, loc: ESTree.SourceLocation.t | nil, - properties: [ESTree.Property.t] + properties: [ESTree.AssignmentProperty.t] } defstruct type: "ObjectPattern", loc: nil, properties: [] -end +end diff --git a/lib/es_tree/tools/builder.ex b/lib/es_tree/tools/builder.ex index 7363003..80cd31b 100644 --- a/lib/es_tree/tools/builder.ex +++ b/lib/es_tree/tools/builder.ex @@ -28,24 +28,35 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ArrowFunctionExpression.t def arrow_function_expression(params, defaults, body, generator \\ false, expression \\ false, loc \\ nil) do - %ESTree.ArrowFunctionExpression{ - params: params, defaults: defaults, - body: body, generator: generator, expression: expression, loc: loc + %ESTree.ArrowFunctionExpression{ + params: params, defaults: defaults, + body: body, generator: generator, expression: expression, loc: loc } end @spec assignment_expression( - ESTree.assignment_operator, - ESTree.Pattern.t | ESTree.Expression.t, + ESTree.assignment_operator, + ESTree.Pattern.t, ESTree.Expression.t, ESTree.SourceLocation.t | nil ) :: ESTree.AssignmentExpression.t def assignment_expression(operator, left, right, loc \\ nil) do - %ESTree.AssignmentExpression{ + %ESTree.AssignmentExpression{ operator: operator, left: left, right: right, loc: loc } end + @spec assignment_property( + ESTree.Pattern.t, + ESTree.SourceLocation.t | nil + ) :: ESTree.AssignmentProperty.t + def assignment_property(value, loc \\ nil) do + %ESTree.AssignmentProperty{ + value: value, loc: loc + } + end + + @spec await_expression( ESTree.Expression.t | nil, boolean, @@ -259,19 +270,19 @@ defmodule ESTree.Tools.Builder do end @spec for_in_statement( - ESTree.VariableDeclaration.t | ESTree.Expression.t, + ESTree.VariableDeclaration.t | ESTree.Pattern.t, ESTree.Expression.t, ESTree.Statement.t, ESTree.SourceLocation.t | nil ) :: ESTree.ForInStatement.t def for_in_statement(left, right, body, loc \\ nil) do - %ESTree.ForInStatement{ + %ESTree.ForInStatement{ left: left, right: right, body: body, loc: loc } end @spec for_of_statement( - ESTree.VariableDeclaration.t | ESTree.Expression.t, + ESTree.VariableDeclaration.t | ESTree.Pattern.t, ESTree.Expression.t, ESTree.Statement.t, ESTree.SourceLocation.t | nil diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index efa9b48..6b7b97f 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -456,9 +456,9 @@ defmodule ESTree.Tools.Generator do else "" end - + params = params_and_defaults(ast.params, ast.defaults) - + "(#{params})#{generator} => #{generate(ast.body)}" end @@ -474,6 +474,11 @@ defmodule ESTree.Tools.Generator do "{" <> Enum.map_join(properties, ",", &generate(&1)) <> "}" end + def do_generate(%ESTree.AssignmentProperty{ value: value }, _) do + value = generate(value) + "#{value}" + end + def do_generate(%ESTree.ArrayPattern{elements: elements}, level) do "[" <> Enum.map_join(elements, ",", &generate(&1)) <> "]" end diff --git a/mix.exs b/mix.exs index d00e987..1009eb2 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule ESTree.Mixfile do def project do [app: :estree, - version: "2.2.0", + version: "2.3.0", elixir: "~> 1.0", deps: deps, description: description, From e6d055d521e400134a5d104fc3e203c39f3024c4 Mon Sep 17 00:00:00 2001 From: Bob Long Date: Tue, 21 Jun 2016 19:28:28 +0100 Subject: [PATCH 03/31] Fix tests by making formatting levels optional --- lib/es_tree/tools/generator.ex | 78 ++++++++++++------- test/tools/generator/while_statement_test.exs | 2 +- 2 files changed, 52 insertions(+), 28 deletions(-) diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index 6b7b97f..dd96cd6 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -16,8 +16,8 @@ defmodule ESTree.Tools.Generator do @indent " " @spec generate(ESTree.operator | ESTree.Node.t, integer) :: binary - def generate(value, level \\ 0) do - "#{indent(level)}#{do_generate(value, level + 1)}" + def generate(value, level \\ nil) do + "#{indent(level)}#{do_generate(value, calculate_next_level(level))}" end def do_generate(nil, level)do @@ -63,7 +63,7 @@ defmodule ESTree.Tools.Generator do end def do_generate(%ESTree.Program{body: body}, level) do - Enum.map_join(body, "\n", &generate(&1, level + 1)) + Enum.map_join(body, newline(level), &generate(&1, calculate_next_level(level))) end def do_generate(%ESTree.FunctionDeclaration{} = ast, level) do @@ -73,7 +73,7 @@ defmodule ESTree.Tools.Generator do params = params_and_defaults(ast.params, ast.defaults) id = generate(ast.id) - "#{async}function#{generator} #{id}(#{params})#{generate(ast.body, level + 1)}" + "#{async}function#{generator} #{id}(#{params})#{generate(ast.body, calculate_next_level(level))}" end def do_generate(%ESTree.FunctionExpression{} = ast, level) do @@ -81,7 +81,7 @@ defmodule ESTree.Tools.Generator do async = if ast.async, do: "async ", else: "" params = params_and_defaults(ast.params, ast.defaults) - "#{async}function#{generator}(#{params})#{generate(ast.body, level + 1)}" + "#{async}function#{generator}(#{params})#{generate(ast.body, calculate_next_level(level))}" end def do_generate(%ESTree.EmptyStatement{}, level) do @@ -89,7 +89,7 @@ defmodule ESTree.Tools.Generator do end def do_generate(%ESTree.BlockStatement{body: body}, level) do - "{\n#{indent(level + 1)}" <> Enum.map_join(body, "\n#{indent(level + 1)}", &generate(&1)) <> "\n#{indent(level)}}" + "{#{newline(level)}#{indent(calculate_next_level(level))}" <> Enum.map_join(body, "#{newline(level)}#{indent(calculate_next_level(level))}", &generate(&1)) <> "#{newline(level)}#{indent(level)}}" end def do_generate(%ESTree.ExpressionStatement{expression: expression}, level) do @@ -98,11 +98,11 @@ defmodule ESTree.Tools.Generator do def do_generate(%ESTree.IfStatement{test: test, consequent: consequent, alternate: alternate}, level) do test = generate(test) - consequent = generate(consequent, level + 1) + consequent = generate(consequent, calculate_next_level(level)) result = "if(#{test}) #{consequent}" if alternate do - result = result <> " else #{generate(alternate, level + 1)}" + result = result <> " else #{generate(alternate, calculate_next_level(level))}" end result @@ -111,7 +111,7 @@ defmodule ESTree.Tools.Generator do def do_generate(%ESTree.LabeledStatement{label: label, body: body}, level) do """ #{generate(label, level)}: - #{generate(body, level + 1)} + #{generate(body, calculate_next_level(level))} """ end @@ -132,47 +132,47 @@ defmodule ESTree.Tools.Generator do end def do_generate(%ESTree.WithStatement{object: object, body: body}, level) do - "with(#{generate(object)})#{generate(body, level + 1)}" + "with(#{generate(object)})#{generate(body, calculate_next_level(level))}" end def do_generate(%ESTree.SwitchStatement{discriminant: discriminant, cases: cases}, level) do - cases = Enum.map_join(cases, "\n", &generate(&1, level + 1)) + cases = Enum.map_join(cases, newline(level), &generate(&1, calculate_next_level(level))) "switch(#{generate(discriminant)}){ #{cases} }" end def do_generate(%ESTree.ReturnStatement{argument: argument}, level) do - "return #{generate(argument, level + 1)};" + "return #{generate(argument, calculate_next_level(level))};" end def do_generate(%ESTree.ThrowStatement{argument: argument}, level) do - "throw #{generate(argument, level + 1)};" + "throw #{generate(argument, calculate_next_level(level))};" end def do_generate(%ESTree.TryStatement{block: block, handler: handler, finalizer: nil}, level) do - "try#{generate(block, level + 1)}#{generate(handler, level + 1)}" + "try#{generate(block, calculate_next_level(level))}#{generate(handler, calculate_next_level(level))}" end def do_generate(%ESTree.TryStatement{block: block, handler: nil, finalizer: finalizer}, level) do - "try#{generate(block, level + 1)}finally#{generate(finalizer, level + 1)}" + "try#{generate(block, calculate_next_level(level))}finally#{generate(finalizer, calculate_next_level(level))}" end def do_generate(%ESTree.TryStatement{block: block, handler: handler, finalizer: finalizer}, level) do - "try#{generate(block, level + 1)}#{generate(handler, level + 1)}finally#{generate(finalizer, level + 1)}" + "try#{generate(block, calculate_next_level(level))}#{generate(handler, calculate_next_level(level))}finally#{generate(finalizer, calculate_next_level(level))}" end def do_generate(%ESTree.WhileStatement{test: test, body: body}, level) do - "while(#{generate(test)}) #{generate(body, level + 1)}" + "while(#{generate(test)}) #{generate(body, calculate_next_level(level))}" end def do_generate(%ESTree.DoWhileStatement{test: test, body: body}, level) do - "do #{generate(body, level + 1)} while(#{generate(test, level)});" + "do #{generate(body, calculate_next_level(level))} while(#{generate(test, level)});" end def do_generate(%ESTree.ForStatement{init: init, test: test, update: update, body: body}, level) do init = generate(init) test = generate(test) update = generate(update) - body = generate(body, level + 1) + body = generate(body, calculate_next_level(level)) "for(#{init}; #{test}; #{update}) #{body}" end @@ -180,7 +180,7 @@ defmodule ESTree.Tools.Generator do def do_generate(%ESTree.ForInStatement{left: left, right: right, body: body}, level) do left = generate(left) |> String.replace(";","") right = generate(right) - body = generate(body, level + 1) + body = generate(body, calculate_next_level(level)) "for(#{left} in #{right}) #{body}" end @@ -232,7 +232,7 @@ defmodule ESTree.Tools.Generator do end def do_generate(%ESTree.ObjectExpression{properties: properties}, level) do - "{\n#{indent(level + 1)}" <> Enum.map_join(properties, ", ", &generate(&1, level + 1)) <> "\n#{indent(level)}}" + "{#{newline(level)}#{indent(calculate_next_level(level))}" <> Enum.map_join(properties, ", ", &generate(&1, calculate_next_level(level))) <> "#{newline(level)}#{indent(level)}}" end def do_generate(%ESTree.Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: false}, level) do @@ -409,7 +409,7 @@ defmodule ESTree.Tools.Generator do end def do_generate(%ESTree.SwitchCase{test: nil, consequent: consequent}, level) do - consequent = Enum.map_join(consequent, "\n", &generate(&1)) + consequent = Enum.map_join(consequent, newline(level), &generate(&1)) """ default: #{consequent} @@ -418,7 +418,7 @@ defmodule ESTree.Tools.Generator do def do_generate(%ESTree.SwitchCase{test: test, consequent: consequent}, level) do test = generate(test) - consequent = Enum.map_join(consequent, "\n", &generate(&1)) + consequent = Enum.map_join(consequent, newline(level), &generate(&1)) """ case #{test}: @@ -523,7 +523,7 @@ defmodule ESTree.Tools.Generator do end def do_generate(%ESTree.ClassBody{body: body}, level) do - body = Enum.map_join(body, "\n", &generate(&1)) + body = Enum.map_join(body, newline(level), &generate(&1)) "{ #{body} }" end @@ -728,8 +728,12 @@ defmodule ESTree.Tools.Generator do def do_generate(%ESTree.JSXOpeningElement{ name: name, attributes: attributes, selfClosing: selfClosing }, level) do selfClosing = if selfClosing, do: "/", else: "" - - "<#{generate(name)} #{ Enum.map(attributes, &generate(&1)) |> Enum.join(" ") }#{selfClosing}>" + attributesValue = cond do + Enum.empty?(attributes) -> "" + true -> + " #{Enum.map(attributes, &generate(&1)) |> Enum.join(" ")}" + end + "<#{generate(name)}#{attributesValue}#{selfClosing}>" end def do_generate(%ESTree.JSXClosingElement{ name: name }, level) do @@ -745,7 +749,7 @@ defmodule ESTree.Tools.Generator do end def do_generate(%ESTree.JSXElement{ openingElement: openingElement, children: children, closingElement: closingElement }, level) do - "#{ generate(openingElement) } #{ Enum.map(children, &generate(&1, level + 1)) |> Enum.join(" ") } #{ generate(closingElement) }" + "#{ generate(openingElement) }#{ Enum.map(children, &generate(&1, calculate_next_level(level))) |> Enum.join(" ") }#{ generate(closingElement) }" end defp convert_string_characters(str) do @@ -765,7 +769,27 @@ defmodule ESTree.Tools.Generator do end) end + defp indent(nil) do + "" + end + defp indent(level) do String.duplicate(" ", level) end + + defp calculate_next_level(nil) do + nil + end + + defp calculate_next_level(level) do + level + 1 + end + + defp newline(nil) do + "" + end + + defp newline(level) do + "\n" + end end diff --git a/test/tools/generator/while_statement_test.exs b/test/tools/generator/while_statement_test.exs index 4af7991..789ede3 100644 --- a/test/tools/generator/while_statement_test.exs +++ b/test/tools/generator/while_statement_test.exs @@ -17,7 +17,7 @@ defmodule ESTree.Tools.Generator.WhileStatement.Test do Builder.block_statement([]), Builder.identifier(:test) ) - assert Generator.generate(ast) == "do {} while(test)" + assert Generator.generate(ast) == "do {} while(test);" end end From 105e8124177eccea6115135ab4c9697216de72a2 Mon Sep 17 00:00:00 2001 From: Bob Long Date: Wed, 22 Jun 2016 15:44:38 +0100 Subject: [PATCH 04/31] Fixup and spec for object formatting --- lib/es_tree/tools/generator.ex | 21 ++++++-- test/tools/generator/formatting_test.exs | 50 +++++++++++++++++++ .../generator/object_expression_test.exs | 6 +-- 3 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 test/tools/generator/formatting_test.exs diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index dd96cd6..f736e36 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -17,7 +17,7 @@ defmodule ESTree.Tools.Generator do @spec generate(ESTree.operator | ESTree.Node.t, integer) :: binary def generate(value, level \\ nil) do - "#{indent(level)}#{do_generate(value, calculate_next_level(level))}" + "#{do_generate(value, calculate_next_level(level))}" end def do_generate(nil, level)do @@ -232,7 +232,10 @@ defmodule ESTree.Tools.Generator do end def do_generate(%ESTree.ObjectExpression{properties: properties}, level) do - "{#{newline(level)}#{indent(calculate_next_level(level))}" <> Enum.map_join(properties, ", ", &generate(&1, calculate_next_level(level))) <> "#{newline(level)}#{indent(level)}}" + next_level = calculate_next_level(level) + previous_level = calculate_previous_level(level) + key_value_separator = ",#{newline(level)}#{indent(level)}" + "{#{newline(level)}#{indent(level)}" <> Enum.map_join(properties, key_value_separator, &generate(&1)) <> "#{newline(level)}#{indent(previous_level)}}" end def do_generate(%ESTree.Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: false}, level) do @@ -360,8 +363,8 @@ defmodule ESTree.Tools.Generator do end def do_generate(%ESTree.CallExpression{callee: %ESTree.MemberExpression{ object: %ESTree.FunctionExpression{} } = callee, arguments: arguments}, level) do - callee = generate(callee) - arguments = Enum.map_join(arguments, ",", &generate(&1)) + callee = generate(callee, level) + arguments = Enum.map_join(arguments, ",", &generate(&1, level)) "(#{callee}(#{arguments}))" end @@ -374,7 +377,7 @@ defmodule ESTree.Tools.Generator do def do_generate(%ESTree.CallExpression{callee: callee, arguments: arguments}, level) do callee = generate(callee) - arguments = Enum.map_join(arguments, ",", &generate(&1)) + arguments = Enum.map_join(arguments, ",", &generate(&1, calculate_previous_level(level))) "#{callee}(#{arguments})" end @@ -785,6 +788,14 @@ defmodule ESTree.Tools.Generator do level + 1 end + defp calculate_previous_level(nil) do + nil + end + + defp calculate_previous_level(level) do + level - 1 + end + defp newline(nil) do "" end diff --git a/test/tools/generator/formatting_test.exs b/test/tools/generator/formatting_test.exs new file mode 100644 index 0000000..08c3f79 --- /dev/null +++ b/test/tools/generator/formatting_test.exs @@ -0,0 +1,50 @@ +defmodule ESTree.Tools.Generator.Formatting.Test do + use ShouldI + alias ESTree.Tools.Builder + alias ESTree.Tools.Generator + + should "format objects" do + ast = Builder.object_expression([ + Builder.property( + Builder.identifier(:key), + Builder.identifier(:value) + ), + Builder.property( + Builder.identifier(:key), + Builder.identifier(:value) + ) + ]) + assert Generator.generate(ast, 0) <> "\n" == +""" +{ + key: value, + key: value +} +""" + end + + should "format objects in function calls" do + ast = Builder.call_expression( + Builder.identifier(:foo), + [ + Builder.object_expression([ + Builder.property( + Builder.identifier(:key), + Builder.identifier(:value) + ), + Builder.property( + Builder.identifier(:key), + Builder.identifier(:value) + ) + ]) + ] + ) + assert Generator.generate(ast, 0) <> "\n" == +""" +foo({ + key: value, + key: value +}) +""" + end +end diff --git a/test/tools/generator/object_expression_test.exs b/test/tools/generator/object_expression_test.exs index 677aec3..0ff67df 100644 --- a/test/tools/generator/object_expression_test.exs +++ b/test/tools/generator/object_expression_test.exs @@ -34,7 +34,7 @@ defmodule ESTree.Tools.Generator.ObjectExpression.Test do Builder.identifier(:value1) ) ]) - assert Generator.generate(ast) == "{key: value, key1: value1}" + assert Generator.generate(ast) == "{key: value,key1: value1}" end @@ -51,7 +51,7 @@ defmodule ESTree.Tools.Generator.ObjectExpression.Test do :set ), ]) - assert Generator.generate(ast) == "{get key() {}, set key(p) {}}" + assert Generator.generate(ast) == "{get key() {},set key(p) {}}" end should "convert object when properties contains getter and setter methods" do @@ -71,7 +71,7 @@ defmodule ESTree.Tools.Generator.ObjectExpression.Test do true ), ]) - assert Generator.generate(ast) == "{key() {}, key(p) {}}" + assert Generator.generate(ast) == "{key() {},key(p) {}}" end should "convert object when properties contains shorthand properties" do From dae554c5098b9ecbbe7e4a24f7710a3796a2b301 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 9 Jul 2016 14:50:26 -0500 Subject: [PATCH 05/31] Add exponential operator --- CHANGELOG.md | 8 ++++++-- lib/es_tree.ex | 14 +++++++------- mix.exs | 4 ++-- mix.lock | 8 ++++---- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a03a6f7..c05b3ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v2.4.0 +* Enhancements: + * Added exponential operators from ES2016 + # v2.3.0 * Enhancements: * Added AssignmentProperty for use with ObjectPattern @@ -10,7 +14,7 @@ # v2.1.2 * Bug fixes - * ESTree.Tools.Generator: updated UnaryExpression to put space in when operator is :typeof + * ESTree.Tools.Generator: updated UnaryExpression to put space in when operator is :typeof # v2.1.1 @@ -47,5 +51,5 @@ # v1.0.0 * Enhancements - * Has the Node definitions from the [ESTree Spec](https://github.com/estree/estree) + * Has the Node definitions from the [ESTree Spec](https://github.com/estree/estree) * Fills in ES6 Node definitions from [ast-types](https://github.com/benjamn/ast-types) and some from testing with [acorn](https://github.com/marijnh/acorn) diff --git a/lib/es_tree.ex b/lib/es_tree.ex index 6e86ec8..aaf89db 100644 --- a/lib/es_tree.ex +++ b/lib/es_tree.ex @@ -1,6 +1,6 @@ defmodule ESTree do @moduledoc """ - Defines structs that represent the JavaScript AST nodes from the ESTree spec. + Defines structs that represent the JavaScript AST nodes from the ESTree spec. [ESTree Spec](https://github.com/estree/estree) @@ -20,15 +20,15 @@ defmodule ESTree do @type unary_operator :: :- | :+ | :! | :"~" | :typeof | :void | :delete - @type binary_operator :: :== | :!= | :=== | :!== | :< | :<= | :> | :>= | - :"<<" | :">>" | :>>> | :+ | :- | :* | :/ | :% | :| | - :^ | :& | :in | :instanceof + @type binary_operator :: :== | :!= | :=== | :!== | :< | :<= | :> | :>= | + :"<<" | :">>" | :>>> | :+ | :- | :* | :/ | :% | :| | + :^ | :& | :in | :instanceof | :"**" @type logical_operator :: :|| | :&& - @type assignment_operator :: := | :"+=" | :"-=" | :"*=" | :"/=" | :"%=" | - :"<<=" | :">>=" | :">>>=" | - :"|=" | :"^=" | :"&=" + @type assignment_operator :: := | :"+=" | :"-=" | :"*=" | :"/=" | :"%=" | + :"<<=" | :">>=" | :">>>=" | + :"|=" | :"^=" | :"&=" | :"**=" @type update_operator :: :++ | :-- diff --git a/mix.exs b/mix.exs index 1009eb2..21975c1 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule ESTree.Mixfile do def project do [app: :estree, - version: "2.3.0", + version: "2.4.0", elixir: "~> 1.0", deps: deps, description: description, @@ -18,7 +18,7 @@ defmodule ESTree.Mixfile do defp deps do [ {:earmark, "~> 0.2", only: :dev}, - {:ex_doc, "~> 0.11", only: :dev}, + {:ex_doc, "~> 0.12", only: :dev}, {:dialyze, "~> 0.2", only: :dev}, {:shouldi, only: :test} ] diff --git a/mix.lock b/mix.lock index f15309b..250ff14 100644 --- a/mix.lock +++ b/mix.lock @@ -1,4 +1,4 @@ -%{"dialyze": {:hex, :dialyze, "0.2.0"}, - "earmark": {:hex, :earmark, "0.2.0"}, - "ex_doc": {:hex, :ex_doc, "0.11.3"}, - "shouldi": {:hex, :shouldi, "0.3.0"}} +%{"dialyze": {:hex, :dialyze, "0.2.1", "9fb71767f96649020d769db7cbd7290059daff23707d6e851e206b1fdfa92f9d", [:mix], []}, + "earmark": {:hex, :earmark, "0.2.1", "ba6d26ceb16106d069b289df66751734802777a3cbb6787026dd800ffeb850f3", [:mix], []}, + "ex_doc": {:hex, :ex_doc, "0.12.0", "b774aabfede4af31c0301aece12371cbd25995a21bb3d71d66f5c2fe074c603f", [:mix], [{:earmark, "~> 0.2", [hex: :earmark, optional: false]}]}, + "shouldi": {:hex, :shouldi, "0.3.0", "ae3fb3cec3328057377a0aa750aa1bb9f8b321ba054e1e2c7211512c383fb6ff", [:mix], []}} From 9fb640da30110f04a9c1f386e066c35c7e0b0164 Mon Sep 17 00:00:00 2001 From: Sergio Zharinov Date: Sun, 25 Sep 2016 03:45:57 +0300 Subject: [PATCH 06/31] Handle edge case when string literal is a JSX child This commit allows to render `
foo
` instead of `
'foo'
`. --- lib/es_tree/tools/generator.ex | 21 ++++++++++++++++++++- test/tools/generator/jsx_test.exs | 24 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index f736e36..e382a31 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -752,7 +752,26 @@ defmodule ESTree.Tools.Generator do end def do_generate(%ESTree.JSXElement{ openingElement: openingElement, children: children, closingElement: closingElement }, level) do - "#{ generate(openingElement) }#{ Enum.map(children, &generate(&1, calculate_next_level(level))) |> Enum.join(" ") }#{ generate(closingElement) }" + "#{ generate(openingElement) }#{ generate_jsx_children(children, calculate_next_level(level)) }#{ generate(closingElement) }" + end + + defp generate_jsx_children(children, level) do + gen_fn = fn + %ESTree.Literal{value: value} when is_binary(value) -> + convert_jsx_text(value) + other -> + generate(other, level) + end + + children |> Enum.map(gen_fn) |> Enum.join + end + + defp convert_jsx_text(str) do + str + |> String.replace("{", "{") + |> String.replace("}", "}") + |> String.replace("<", "<") + |> String.replace(">", ">") end defp convert_string_characters(str) do diff --git a/test/tools/generator/jsx_test.exs b/test/tools/generator/jsx_test.exs index d08a9ff..c1ebea8 100644 --- a/test/tools/generator/jsx_test.exs +++ b/test/tools/generator/jsx_test.exs @@ -148,4 +148,28 @@ defmodule ESTree.Tools.Generator.JSX.Test do assert Generator.generate(ast) == "
" end + + should "handle inner text" do + ast = Builder.jsx_element( + Builder.jsx_opening_element( + Builder.jsx_identifier( + "Test" + ) + ), + [ + Builder.literal("counter: "), + Builder.jsx_expression_container( + Builder.identifier(:count) + ), + Builder.literal("."), + ], + Builder.jsx_closing_element( + Builder.jsx_identifier( + "Test" + ) + ) + ) + + assert Generator.generate(ast) == "counter: {count}." + end end From 3fe3141ebc98a2462c8b61c28adb0bc306007d50 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 12 Oct 2016 18:54:52 -0500 Subject: [PATCH 07/31] Update change log --- CHANGELOG.md | 4 ++++ mix.exs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c05b3ee..6b07865 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v2.4.1 +* Fixes + * Handle edge case when string literal is a JSX child + # v2.4.0 * Enhancements: * Added exponential operators from ES2016 diff --git a/mix.exs b/mix.exs index 21975c1..09d1a91 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule ESTree.Mixfile do def project do [app: :estree, - version: "2.4.0", + version: "2.4.1", elixir: "~> 1.0", deps: deps, description: description, From 4509c63bad5acc4ffc75eee306f453db01211e9b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 12 Oct 2016 18:56:29 -0500 Subject: [PATCH 08/31] Update hex config --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index 09d1a91..bab6806 100644 --- a/mix.exs +++ b/mix.exs @@ -33,7 +33,7 @@ defmodule ESTree.Mixfile do defp package do [ # These are the default files included in the package - files: ["lib", "mix.exs", "README*", "readme*", "LICENSE*", "license*", "CHANGELOG*"], + files: ["lib", "mix.exs", "README.md", "CHANGELOG.md"], maintainers: ["Bryan Joseph"], licenses: ["MIT"], links: %{ "GitHub" => "https://github.com/bryanjos/elixir-estree" } From 1f2027b6a35bf2989ff3355e41c9a6bbfc1a5587 Mon Sep 17 00:00:00 2001 From: Mikalai Seva Date: Mon, 5 Dec 2016 21:55:21 +0300 Subject: [PATCH 09/31] Fixes a bucket of warnings --- lib/es_tree/tools/generator.ex | 302 ++++++++++++++++----------------- 1 file changed, 151 insertions(+), 151 deletions(-) diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index e382a31..4debb05 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -6,10 +6,10 @@ defmodule ESTree.Tools.Generator do @operators [ :-, :+ , :! , :"~" , :typeof , :void , :delete, - :== , :!= , :=== , :!== , :< , :<= , :> , :>= , - :"<<" , :">>" , :>>> , :+ , :- , :* , :/ , :% , :| , - :^ , :& , :in , :instanceof, :|| , :&&, := , :"+=" , - :"-=" , :"*=" , :"/=" , :"%=" , :"<<=" , :">>=" , + :== , :!= , :=== , :!== , :< , :<= , :> , :>= , + :"<<" , :">>" , :>>> , :+ , :- , :* , :/ , :% , :| , + :^ , :& , :in , :instanceof, :|| , :&&, := , :"+=" , + :"-=" , :"*=" , :"/=" , :"%=" , :"<<=" , :">>=" , :">>>=" , :"|=" , :"^=" , :"&=", :++, :-- ] @@ -20,48 +20,48 @@ defmodule ESTree.Tools.Generator do "#{do_generate(value, calculate_next_level(level))}" end - def do_generate(nil, level)do + def do_generate(nil, _level) do "" end - def do_generate(operator, level) when operator in @operators do + def do_generate(operator, _level) when operator in @operators do to_string(operator) end - - def do_generate(%ESTree.Identifier{name: name}, level) do + + def do_generate(%ESTree.Identifier{name: name}, _level) do to_string(name) end - def do_generate(%ESTree.Literal{value: nil}, level) do + def do_generate(%ESTree.Literal{value: nil}, _level) do "null" end - - def do_generate(%ESTree.Literal{value: %{}, regex: regex}, level) do + + def do_generate(%ESTree.Literal{value: %{}, regex: regex}, _level) do "/#{regex.pattern}/#{regex.flags}" end - def do_generate(%ESTree.Literal{value: value}, level) when is_boolean(value) do + def do_generate(%ESTree.Literal{value: value}, _level) when is_boolean(value) do "#{to_string(value)}" end - - def do_generate(%ESTree.Literal{value: value}, level) when is_atom(value) do + + def do_generate(%ESTree.Literal{value: value}, _level) when is_atom(value) do "'#{to_string(value)}'" end - - def do_generate(%ESTree.Literal{value: value}, level) when is_binary(value) do + + def do_generate(%ESTree.Literal{value: value}, _level) when is_binary(value) do value = convert_string_characters(value) - + "'#{value}'" end - def do_generate(%ESTree.Literal{value: value}, level) do + def do_generate(%ESTree.Literal{value: value}, _level) do to_string(value) end - def do_generate(%ESTree.Program{body: []}, level) do + def do_generate(%ESTree.Program{body: []}, _level) do "" end - + def do_generate(%ESTree.Program{body: body}, level) do Enum.map_join(body, newline(level), &generate(&1, calculate_next_level(level))) end @@ -69,10 +69,10 @@ defmodule ESTree.Tools.Generator do def do_generate(%ESTree.FunctionDeclaration{} = ast, level) do generator = if ast.generator, do: "*", else: "" async = if ast.async, do: "async ", else: "" - + params = params_and_defaults(ast.params, ast.defaults) id = generate(ast.id) - + "#{async}function#{generator} #{id}(#{params})#{generate(ast.body, calculate_next_level(level))}" end @@ -80,19 +80,19 @@ defmodule ESTree.Tools.Generator do generator = if ast.generator, do: "*", else: "" async = if ast.async, do: "async ", else: "" params = params_and_defaults(ast.params, ast.defaults) - + "#{async}function#{generator}(#{params})#{generate(ast.body, calculate_next_level(level))}" end - - def do_generate(%ESTree.EmptyStatement{}, level) do + + def do_generate(%ESTree.EmptyStatement{}, _level) do ";" end - + def do_generate(%ESTree.BlockStatement{body: body}, level) do "{#{newline(level)}#{indent(calculate_next_level(level))}" <> Enum.map_join(body, "#{newline(level)}#{indent(calculate_next_level(level))}", &generate(&1)) <> "#{newline(level)}#{indent(level)}}" end - - def do_generate(%ESTree.ExpressionStatement{expression: expression}, level) do + + def do_generate(%ESTree.ExpressionStatement{expression: expression}, _level) do "#{generate(expression)};" end @@ -102,10 +102,10 @@ defmodule ESTree.Tools.Generator do result = "if(#{test}) #{consequent}" if alternate do - result = result <> " else #{generate(alternate, calculate_next_level(level))}" + result <> " else #{generate(alternate, calculate_next_level(level))}" + else + result end - - result end def do_generate(%ESTree.LabeledStatement{label: label, body: body}, level) do @@ -115,19 +115,19 @@ defmodule ESTree.Tools.Generator do """ end - def do_generate(%ESTree.BreakStatement{label: nil}, level) do + def do_generate(%ESTree.BreakStatement{label: nil}, _level) do "break;" end - - def do_generate(%ESTree.BreakStatement{label: label}, level) do + + def do_generate(%ESTree.BreakStatement{label: label}, _level) do "break #{generate(label)};" end - def do_generate(%ESTree.ContinueStatement{label: nil}, level) do + def do_generate(%ESTree.ContinueStatement{label: nil}, _level) do "continue;" end - - def do_generate(%ESTree.ContinueStatement{label: label}, level) do + + def do_generate(%ESTree.ContinueStatement{label: label}, _level) do "continue #{generate(label)};" end @@ -155,11 +155,11 @@ defmodule ESTree.Tools.Generator do def do_generate(%ESTree.TryStatement{block: block, handler: nil, finalizer: finalizer}, level) do "try#{generate(block, calculate_next_level(level))}finally#{generate(finalizer, calculate_next_level(level))}" end - + def do_generate(%ESTree.TryStatement{block: block, handler: handler, finalizer: finalizer}, level) do "try#{generate(block, calculate_next_level(level))}#{generate(handler, calculate_next_level(level))}finally#{generate(finalizer, calculate_next_level(level))}" end - + def do_generate(%ESTree.WhileStatement{test: test, body: body}, level) do "while(#{generate(test)}) #{generate(body, calculate_next_level(level))}" end @@ -185,95 +185,95 @@ defmodule ESTree.Tools.Generator do "for(#{left} in #{right}) #{body}" end - def do_generate(%ESTree.DebuggerStatement{}, level) do + def do_generate(%ESTree.DebuggerStatement{}, _level) do "debugger;" end - def do_generate(%ESTree.VariableDeclaration{kind: kind, declarations: [declaration]}, level) when kind in [:var, :let, :const] do + def do_generate(%ESTree.VariableDeclaration{kind: kind, declarations: [declaration]}, _level) when kind in [:var, :let, :const] do declaration = generate(declaration) "#{to_string(kind)} #{declaration};" end - - def do_generate(%ESTree.VariableDeclaration{kind: kind, declarations: declarations}, level) when kind in [:var, :let, :const] do + + def do_generate(%ESTree.VariableDeclaration{kind: kind, declarations: declarations}, _level) when kind in [:var, :let, :const] do ids = Enum.map_join(declarations, ",", fn(x) -> generate(x.id) end) - inits = Enum.map_join(declarations, ",", fn(x) -> generate(x.init) end) + inits = Enum.map_join(declarations, ",", fn(x) -> generate(x.init) end) "#{to_string(kind)} #{ids} = #{inits};" end - def do_generate(%ESTree.VariableDeclarator{id: id, init: nil}, level) do + def do_generate(%ESTree.VariableDeclarator{id: id, init: nil}, _level) do generate(id) end - - def do_generate(%ESTree.VariableDeclarator{id: id, init: init}, level) do + + def do_generate(%ESTree.VariableDeclarator{id: id, init: init}, _level) do "#{generate(id)} = #{generate(init)}" end - def do_generate(%ESTree.ThisExpression{}, level) do + def do_generate(%ESTree.ThisExpression{}, _level) do "this" end - def do_generate(%ESTree.ArrayExpression{elements: nil}, level) do + def do_generate(%ESTree.ArrayExpression{elements: nil}, _level) do "[]" end - - def do_generate(%ESTree.ArrayExpression{elements: elements}, level) do + + def do_generate(%ESTree.ArrayExpression{elements: elements}, _level) do "[" <> Enum.map_join(elements, ", ", &generate(&1)) <> "]" end - def do_generate(%ESTree.ObjectExpression{properties: nil}, level) do + def do_generate(%ESTree.ObjectExpression{properties: nil}, _level) do "{}" end - def do_generate(%ESTree.ObjectExpression{properties: []}, level) do + def do_generate(%ESTree.ObjectExpression{properties: []}, _level) do "{}" end - + def do_generate(%ESTree.ObjectExpression{properties: properties}, level) do - next_level = calculate_next_level(level) + _next_level = calculate_next_level(level) previous_level = calculate_previous_level(level) key_value_separator = ",#{newline(level)}#{indent(level)}" "{#{newline(level)}#{indent(level)}" <> Enum.map_join(properties, key_value_separator, &generate(&1)) <> "#{newline(level)}#{indent(previous_level)}}" end - def do_generate(%ESTree.Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: false}, level) do + def do_generate(%ESTree.Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: false}, _level) do key = generate(key) value = generate(value) "#{key}: #{value}" end - def do_generate(%ESTree.Property{key: key, value: _, kind: :init, shorthand: true, method: false, computed: false}, level) do + def do_generate(%ESTree.Property{key: key, value: _, kind: :init, shorthand: true, method: false, computed: false}, _level) do key = generate(key) "#{key}" end - def do_generate(%ESTree.Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: true}, level) do + def do_generate(%ESTree.Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: true}, _level) do key = generate(key) value = generate(value) "[#{key}]: #{value}" end - def do_generate(%ESTree.Property{key: key, value: %ESTree.FunctionExpression{body: body}, kind: :get, shorthand: false, method: true, computed: false}, level) do + def do_generate(%ESTree.Property{key: key, value: %ESTree.FunctionExpression{body: body}, kind: :get, shorthand: false, method: true, computed: false}, _level) do key = generate(key) value = generate(body) "#{key}() #{value}" end - - def do_generate(%ESTree.Property{key: key, value: %ESTree.FunctionExpression{body: body}, kind: :get}, level) do + + def do_generate(%ESTree.Property{key: key, value: %ESTree.FunctionExpression{body: body}, kind: :get}, _level) do key = generate(key) value = generate(body) "get #{key}() #{value}" end - def do_generate(%ESTree.Property{key: key, value: %ESTree.FunctionExpression{params: params, body: body}, kind: :set, shorthand: false, method: true, computed: false}, level) do + def do_generate(%ESTree.Property{key: key, value: %ESTree.FunctionExpression{params: params, body: body}, kind: :set, shorthand: false, method: true, computed: false}, _level) do key = generate(key) param = generate(hd(params)) value = generate(body) @@ -281,8 +281,8 @@ defmodule ESTree.Tools.Generator do "#{key}(#{param}) #{value}" end - - def do_generate(%ESTree.Property{key: key, value: %ESTree.FunctionExpression{params: params, body: body}, kind: :set}, level) do + + def do_generate(%ESTree.Property{key: key, value: %ESTree.FunctionExpression{params: params, body: body}, kind: :set}, _level) do key = generate(key) param = generate(hd(params)) value = generate(body) @@ -290,39 +290,39 @@ defmodule ESTree.Tools.Generator do "set #{key}(#{param}) #{value}" end - def do_generate(%ESTree.SequenceExpression{expressions: expressions}, level) do + def do_generate(%ESTree.SequenceExpression{expressions: expressions}, _level) do Enum.map_join(expressions, ",", &generate(&1)) end - def do_generate(%ESTree.UnaryExpression{operator: :typeof, prefix: true, argument: argument}, level) do + def do_generate(%ESTree.UnaryExpression{operator: :typeof, prefix: true, argument: argument}, _level) do "#{generate(:typeof)} #{generate(argument)}" end - def do_generate(%ESTree.UnaryExpression{operator: operator, prefix: true, argument: argument}, level) do + def do_generate(%ESTree.UnaryExpression{operator: operator, prefix: true, argument: argument}, _level) do "#{generate(operator)}#{generate(argument)}" end - def do_generate(%ESTree.UnaryExpression{operator: operator, prefix: false, argument: argument}, level) do + def do_generate(%ESTree.UnaryExpression{operator: operator, prefix: false, argument: argument}, _level) do "#{generate(argument)}#{generate(operator)}" end - - def do_generate(%ESTree.BinaryExpression{operator: operator, left: %ESTree.BinaryExpression{} = left, right: %ESTree.BinaryExpression{} = right}, level) do + + def do_generate(%ESTree.BinaryExpression{operator: operator, left: %ESTree.BinaryExpression{} = left, right: %ESTree.BinaryExpression{} = right}, _level) do operator = generate(operator) left = generate(left) right = generate(right) "(#{left}) #{operator} (#{right})" end - - def do_generate(%ESTree.BinaryExpression{operator: operator, left: left, right: %ESTree.BinaryExpression{} = right}, level) do + + def do_generate(%ESTree.BinaryExpression{operator: operator, left: left, right: %ESTree.BinaryExpression{} = right}, _level) do operator = generate(operator) left = generate(left) right = generate(right) "#{left} #{operator} (#{right})" end - - def do_generate(%ESTree.BinaryExpression{operator: operator, left: left, right: right}, level) do + + def do_generate(%ESTree.BinaryExpression{operator: operator, left: left, right: right}, _level) do operator = generate(operator) left = generate(left) right = generate(right) @@ -330,7 +330,7 @@ defmodule ESTree.Tools.Generator do "#{left} #{operator} #{right}" end - def do_generate(%ESTree.AssignmentExpression{operator: operator, left: left, right: right}, level) do + def do_generate(%ESTree.AssignmentExpression{operator: operator, left: left, right: right}, _level) do operator = generate(operator) left = generate(left) right = generate(right) @@ -338,15 +338,15 @@ defmodule ESTree.Tools.Generator do "#{left} #{operator} #{right}" end - def do_generate(%ESTree.UpdateExpression{operator: operator, prefix: true, argument: argument}, level) do + def do_generate(%ESTree.UpdateExpression{operator: operator, prefix: true, argument: argument}, _level) do "#{generate(operator)}#{generate(argument)}" end - def do_generate(%ESTree.UpdateExpression{operator: operator, prefix: false, argument: argument}, level) do + def do_generate(%ESTree.UpdateExpression{operator: operator, prefix: false, argument: argument}, _level) do "#{generate(argument)}#{generate(operator)}" end - def do_generate(%ESTree.LogicalExpression{operator: operator, left: left, right: right}, level) do + def do_generate(%ESTree.LogicalExpression{operator: operator, left: left, right: right}, _level) do operator = generate(operator) left = generate(left) right = generate(right) @@ -354,7 +354,7 @@ defmodule ESTree.Tools.Generator do "#{left} #{operator} #{right}" end - def do_generate(%ESTree.ConditionalStatement{test: test, alternate: alternate, consequent: consequent}, level) do + def do_generate(%ESTree.ConditionalStatement{test: test, alternate: alternate, consequent: consequent}, _level) do test = generate(test) alternate = generate(alternate) consequent = generate(consequent) @@ -369,12 +369,12 @@ defmodule ESTree.Tools.Generator do "(#{callee}(#{arguments}))" end - def do_generate(%ESTree.CallExpression{callee: %ESTree.Super{}, arguments: arguments}, level) do + def do_generate(%ESTree.CallExpression{callee: %ESTree.Super{}, arguments: arguments}, _level) do arguments = Enum.map_join(arguments, ",", &generate(&1)) "super(#{arguments})" end - + def do_generate(%ESTree.CallExpression{callee: callee, arguments: arguments}, level) do callee = generate(callee) arguments = Enum.map_join(arguments, ",", &generate(&1, calculate_previous_level(level))) @@ -382,30 +382,30 @@ defmodule ESTree.Tools.Generator do "#{callee}(#{arguments})" end - def do_generate(%ESTree.NewExpression{callee: callee, arguments: arguments}, level) do + def do_generate(%ESTree.NewExpression{callee: callee, arguments: arguments}, _level) do callee = generate(callee) arguments = Enum.map_join(arguments, ",", &generate(&1)) "new #{callee}(#{arguments})" end - def do_generate(%ESTree.MemberExpression{object: %ESTree.Super{}, property: property, computed: true}, level) do + def do_generate(%ESTree.MemberExpression{object: %ESTree.Super{}, property: property, computed: true}, _level) do property = generate(property) "super[#{property}]" end - def do_generate(%ESTree.MemberExpression{object: object, property: property, computed: true}, level) do + def do_generate(%ESTree.MemberExpression{object: object, property: property, computed: true}, _level) do object = generate(object) property = generate(property) "#{object}[#{property}]" end - def do_generate(%ESTree.MemberExpression{object: %ESTree.Super{}, property: property, computed: false}, level) do + def do_generate(%ESTree.MemberExpression{object: %ESTree.Super{}, property: property, computed: false}, _level) do property = generate(property) "super.#{property}" end - - def do_generate(%ESTree.MemberExpression{object: object, property: property, computed: false}, level) do + + def do_generate(%ESTree.MemberExpression{object: object, property: property, computed: false}, _level) do object = generate(object) property = generate(property) "#{object}.#{property}" @@ -418,7 +418,7 @@ defmodule ESTree.Tools.Generator do #{consequent} """ end - + def do_generate(%ESTree.SwitchCase{test: test, consequent: consequent}, level) do test = generate(test) consequent = Enum.map_join(consequent, newline(level), &generate(&1)) @@ -429,14 +429,14 @@ defmodule ESTree.Tools.Generator do """ end - def do_generate(%ESTree.CatchClause{param: param, body: body}, level) do + def do_generate(%ESTree.CatchClause{param: param, body: body}, _level) do param = generate(param) body = generate(body) "catch(#{param}) #{body}" end - def do_generate(%ESTree.ForOfStatement{left: left, right: right, body: body}, level) do + def do_generate(%ESTree.ForOfStatement{left: left, right: right, body: body}, _level) do left = generate(left) |> String.replace(";","") right = generate(right) body = generate(body) @@ -444,15 +444,15 @@ defmodule ESTree.Tools.Generator do "for(#{left} of #{right}) #{body}" end - def do_generate(%ESTree.SpreadElement{argument: argument}, level) do + def do_generate(%ESTree.SpreadElement{argument: argument}, _level) do "...#{generate(argument)}" end - def do_generate(%ESTree.RestElement{argument: argument}, level) do + def do_generate(%ESTree.RestElement{argument: argument}, _level) do "...#{generate(argument)}" end - def do_generate(%ESTree.ArrowFunctionExpression{} = ast, level) do + def do_generate(%ESTree.ArrowFunctionExpression{} = ast, _level) do generator = if ast.generator do "*" @@ -465,15 +465,15 @@ defmodule ESTree.Tools.Generator do "(#{params})#{generator} => #{generate(ast.body)}" end - def do_generate(%ESTree.YieldExpression{argument: argument, delegate: false}, level) do + def do_generate(%ESTree.YieldExpression{argument: argument, delegate: false}, _level) do "yield #{generate(argument)}" end - def do_generate(%ESTree.YieldExpression{argument: argument, delegate: true}, level) do + def do_generate(%ESTree.YieldExpression{argument: argument, delegate: true}, _level) do "yield* #{generate(argument)}" end - def do_generate(%ESTree.ObjectPattern{properties: properties}, level) do + def do_generate(%ESTree.ObjectPattern{properties: properties}, _level) do "{" <> Enum.map_join(properties, ",", &generate(&1)) <> "}" end @@ -482,27 +482,27 @@ defmodule ESTree.Tools.Generator do "#{value}" end - def do_generate(%ESTree.ArrayPattern{elements: elements}, level) do + def do_generate(%ESTree.ArrayPattern{elements: elements}, _level) do "[" <> Enum.map_join(elements, ",", &generate(&1)) <> "]" end - def do_generate(%ESTree.AssignmentPattern{left: left, right: right}, level) do + def do_generate(%ESTree.AssignmentPattern{left: left, right: right}, _level) do left = generate(left) right = generate(right) "#{left} = #{right}" end - - def do_generate(%ESTree.ClassDeclaration{id: id, body: body, superClass: nil}, level) do + + def do_generate(%ESTree.ClassDeclaration{id: id, body: body, superClass: nil}, _level) do id = generate(id) body = generate(body) "class #{id} #{body}" end - - def do_generate(%ESTree.ClassDeclaration{id: id, body: body, superClass: superClass}, level) do + + def do_generate(%ESTree.ClassDeclaration{id: id, body: body, superClass: superClass}, _level) do id = generate(id) body = generate(body) superClass = generate(superClass) @@ -511,14 +511,14 @@ defmodule ESTree.Tools.Generator do end - def do_generate(%ESTree.ClassExpression{body: body, superClass: nil}, level) do + def do_generate(%ESTree.ClassExpression{body: body, superClass: nil}, _level) do body = generate(body) "class #{body}" end - - def do_generate(%ESTree.ClassExpression{body: body, superClass: superClass}, level) do + + def do_generate(%ESTree.ClassExpression{body: body, superClass: superClass}, _level) do body = generate(body) superClass = generate(superClass) @@ -531,14 +531,14 @@ defmodule ESTree.Tools.Generator do "{ #{body} }" end - def do_generate(%ESTree.MethodDefinition{key: _key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :constructor}, level) do + def do_generate(%ESTree.MethodDefinition{key: _key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :constructor}, _level) do params = params_and_defaults(params, defaults) body = generate(body) - "constructor(#{params})#{body}" + "constructor(#{params})#{body}" end - - def do_generate(%ESTree.MethodDefinition{key: key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :method, computed: false, static: false}, level) do + + def do_generate(%ESTree.MethodDefinition{key: key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :method, computed: false, static: false}, _level) do key = generate(key) params = params_and_defaults(params, defaults) body = generate(body) @@ -546,7 +546,7 @@ defmodule ESTree.Tools.Generator do "#{key}(#{params})#{body}" end - def do_generate(%ESTree.MethodDefinition{key: key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :method, computed: false, static: true}, level) do + def do_generate(%ESTree.MethodDefinition{key: key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :method, computed: false, static: true}, _level) do key = generate(key) params = params_and_defaults(params, defaults) body = generate(body) @@ -554,7 +554,7 @@ defmodule ESTree.Tools.Generator do "static #{key}(#{params})#{body}" end - def do_generate(%ESTree.MethodDefinition{key: key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :method, computed: true, static: false}, level) do + def do_generate(%ESTree.MethodDefinition{key: key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :method, computed: true, static: false}, _level) do key = generate(key) params = params_and_defaults(params, defaults) body = generate(body) @@ -562,7 +562,7 @@ defmodule ESTree.Tools.Generator do "[#{key}](#{params})#{body}" end - def do_generate(%ESTree.MethodDefinition{key: key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :method, computed: true, static: true}, level) do + def do_generate(%ESTree.MethodDefinition{key: key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :method, computed: true, static: true}, _level) do key = generate(key) params = params_and_defaults(params, defaults) body = generate(body) @@ -570,36 +570,36 @@ defmodule ESTree.Tools.Generator do "static [#{key}](#{params})#{body}" end - def do_generate(%ESTree.MetaProperty{meta: meta, property: property}, level) do + def do_generate(%ESTree.MetaProperty{meta: meta, property: property}, _level) do meta = generate(meta) property = generate(property) "#{meta}.#{property}" end - def do_generate(%ESTree.ImportDeclaration{specifiers: [%ESTree.ImportDefaultSpecifier{}] = specifiers, source: source}, level) do + def do_generate(%ESTree.ImportDeclaration{specifiers: [%ESTree.ImportDefaultSpecifier{}] = specifiers, source: source}, _level) do specifiers = Enum.map_join(specifiers, ", ", &generate(&1)) source = generate(source) "import #{specifiers} from #{source};" end - def do_generate(%ESTree.ImportDeclaration{specifiers: [%ESTree.ImportNamespaceSpecifier{}] = specifiers, source: source}, level) do + def do_generate(%ESTree.ImportDeclaration{specifiers: [%ESTree.ImportNamespaceSpecifier{}] = specifiers, source: source}, _level) do specifiers = Enum.map_join(specifiers, ", ", &generate(&1)) source = generate(source) "import #{specifiers} from #{source};" end - - def do_generate(%ESTree.ImportDeclaration{specifiers: specifiers, source: source}, level) do + + def do_generate(%ESTree.ImportDeclaration{specifiers: specifiers, source: source}, _level) do specifiers = Enum.map_join(specifiers, ", ", &generate(&1)) source = generate(source) "import { #{specifiers} } from #{source};" end - - def do_generate(%ESTree.ImportSpecifier{local: local, imported: imported}, level) do + + def do_generate(%ESTree.ImportSpecifier{local: local, imported: imported}, _level) do local = generate(local) imported = generate(imported) @@ -610,40 +610,40 @@ defmodule ESTree.Tools.Generator do end end - def do_generate(%ESTree.ImportDefaultSpecifier{local: local}, level) do + def do_generate(%ESTree.ImportDefaultSpecifier{local: local}, _level) do generate(local) end - def do_generate(%ESTree.ImportNamespaceSpecifier{local: local}, level) do + def do_generate(%ESTree.ImportNamespaceSpecifier{local: local}, _level) do local = generate(local) "* as #{local}" end - def do_generate(%ESTree.ExportNamedDeclaration{declaration: %ESTree.FunctionDeclaration{} = declaration, specifiers: [], source: nil}, level) do + def do_generate(%ESTree.ExportNamedDeclaration{declaration: %ESTree.FunctionDeclaration{} = declaration, specifiers: [], source: nil}, _level) do declaration = generate(declaration) "export #{declaration}" end - - def do_generate(%ESTree.ExportNamedDeclaration{declaration: declaration, specifiers: [], source: nil}, level) do + + def do_generate(%ESTree.ExportNamedDeclaration{declaration: declaration, specifiers: [], source: nil}, _level) do declaration = generate(declaration) "export #{declaration};" end - - def do_generate(%ESTree.ExportNamedDeclaration{declaration: nil, specifiers: specifiers, source: nil} = ast, level) do + + def do_generate(%ESTree.ExportNamedDeclaration{declaration: nil, specifiers: specifiers, source: nil} = _ast, _level) do specifiers = Enum.map_join(specifiers, ", ", &generate(&1)) "export { #{specifiers} };" end - def do_generate(%ESTree.ExportNamedDeclaration{declaration: nil, specifiers: specifiers, source: source}, level) do + def do_generate(%ESTree.ExportNamedDeclaration{declaration: nil, specifiers: specifiers, source: source}, _level) do specifiers = Enum.map_join(specifiers, ", ", &generate(&1)) source = generate(source) - + "export { #{specifiers} } from #{source};" end - - def do_generate(%ESTree.ExportSpecifier{local: local, exported: exported}, level) do + + def do_generate(%ESTree.ExportSpecifier{local: local, exported: exported}, _level) do local = generate(local) exported = generate(exported) @@ -654,39 +654,39 @@ defmodule ESTree.Tools.Generator do end end - def do_generate(%ESTree.ExportDefaultDeclaration{declaration: declaration}, level) do + def do_generate(%ESTree.ExportDefaultDeclaration{declaration: declaration}, _level) do declaration = generate(declaration) "export default #{declaration};" end - def do_generate(%ESTree.ExportAllDeclaration{source: source}, level) do + def do_generate(%ESTree.ExportAllDeclaration{source: source}, _level) do source = generate(source) "export * from #{source};" end - def do_generate(%ESTree.TaggedTemplateExpression{tag: tag, quasi: quasi}, level) do + def do_generate(%ESTree.TaggedTemplateExpression{tag: tag, quasi: quasi}, _level) do tag = generate(tag) quasi = generate(quasi) "#{tag} #{quasi}" end - def do_generate(%ESTree.TemplateLiteral{expressions: [], quasis: []}, level) do + def do_generate(%ESTree.TemplateLiteral{expressions: [], quasis: []}, _level) do "``" end - def do_generate(%ESTree.TemplateLiteral{expressions: [expression], quasis: []}, level) do + def do_generate(%ESTree.TemplateLiteral{expressions: [expression], quasis: []}, _level) do expression = generate(expression) "`${#{expression}}`" end - def do_generate(%ESTree.TemplateLiteral{expressions: [], quasis: [quasi]}, level) do + def do_generate(%ESTree.TemplateLiteral{expressions: [], quasis: [quasi]}, _level) do quasi = convert_string_characters(quasi.value.raw) "`#{quasi}`" end - def do_generate(%ESTree.TemplateLiteral{expressions: expressions, quasis: quasis}, level) do + def do_generate(%ESTree.TemplateLiteral{expressions: expressions, quasis: quasis}, _level) do elements = expressions ++ quasis literal = Enum.sort(elements, fn(one, two) -> @@ -705,31 +705,31 @@ defmodule ESTree.Tools.Generator do "`#{literal}`" end - def do_generate(%ESTree.AwaitExpression{ argument: argument, all: all }, level) do + def do_generate(%ESTree.AwaitExpression{ argument: argument, all: _all }, _level) do "await #{generate(argument)}" end - def do_generate(%ESTree.JSXIdentifier{ name: name }, level) do + def do_generate(%ESTree.JSXIdentifier{ name: name }, _level) do "#{name}" end - def do_generate(%ESTree.JSXMemberExpression{ object: object, property: property }, level) do + def do_generate(%ESTree.JSXMemberExpression{ object: object, property: property }, _level) do "#{ generate(object) }.#{ generate(property) }" end - def do_generate(%ESTree.JSXNamespacedName{ namespace: namespace, name: name }, level) do + def do_generate(%ESTree.JSXNamespacedName{ namespace: namespace, name: name }, _level) do "#{ generate(namespace) }:#{ generate(name) }" end - def do_generate(%ESTree.JSXEmptyExpression{}, level) do + def do_generate(%ESTree.JSXEmptyExpression{}, _level) do "" end - def do_generate(%ESTree.JSXExpressionContainer{ expression: expression }, level) do + def do_generate(%ESTree.JSXExpressionContainer{ expression: expression }, _level) do "{#{ generate(expression) }}" end - def do_generate(%ESTree.JSXOpeningElement{ name: name, attributes: attributes, selfClosing: selfClosing }, level) do + def do_generate(%ESTree.JSXOpeningElement{ name: name, attributes: attributes, selfClosing: selfClosing }, _level) do selfClosing = if selfClosing, do: "/", else: "" attributesValue = cond do Enum.empty?(attributes) -> "" @@ -739,15 +739,15 @@ defmodule ESTree.Tools.Generator do "<#{generate(name)}#{attributesValue}#{selfClosing}>" end - def do_generate(%ESTree.JSXClosingElement{ name: name }, level) do + def do_generate(%ESTree.JSXClosingElement{ name: name }, _level) do "" end - def do_generate(%ESTree.JSXAttribute{ name: name, value: value }, level) do + def do_generate(%ESTree.JSXAttribute{ name: name, value: value }, _level) do "#{ generate(name) }=#{ generate(value) }" end - def do_generate(%ESTree.JSXSpreadAttribute{ argument: argument }, level) do + def do_generate(%ESTree.JSXSpreadAttribute{ argument: argument }, _level) do "{...#{ generate(argument) }}" end @@ -778,11 +778,11 @@ defmodule ESTree.Tools.Generator do String.replace(str, "\n", "\\n") |> String.replace("\t", "\\t") end - + defp params_and_defaults(params, []) do Enum.map_join(params, ",", &generate(&1)) - end - + end + defp params_and_defaults(params, defaults) do Enum.zip(params, defaults) |> Enum.map_join(",", fn @@ -819,7 +819,7 @@ defmodule ESTree.Tools.Generator do "" end - defp newline(level) do + defp newline(_level) do "\n" end end From def8595d4612bf14f218272e4513553798e57e1f Mon Sep 17 00:00:00 2001 From: Mikalai Seva Date: Sun, 18 Dec 2016 19:01:49 +0100 Subject: [PATCH 10/31] Expressions can be used in variable declaration Was: var a, b, c = 1, 2, 3; Become: var a = 1, b = 2, c = 3; Can be used as: var a = 1, b, c = a + 2; --- lib/es_tree/tools/generator.ex | 14 ++---- .../generator/variable_declaration_test.exs | 49 +++++++++++++++++++ 2 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 test/tools/generator/variable_declaration_test.exs diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index 4debb05..f46230d 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -189,18 +189,14 @@ defmodule ESTree.Tools.Generator do "debugger;" end - def do_generate(%ESTree.VariableDeclaration{kind: kind, declarations: [declaration]}, _level) when kind in [:var, :let, :const] do - declaration = generate(declaration) - - "#{to_string(kind)} #{declaration};" - end - def do_generate(%ESTree.VariableDeclaration{kind: kind, declarations: declarations}, _level) when kind in [:var, :let, :const] do - ids = Enum.map_join(declarations, ",", fn(x) -> generate(x.id) end) - inits = Enum.map_join(declarations, ",", fn(x) -> generate(x.init) end) + declarators = declarations + |> Enum.map_join(", ", fn(x) -> + generate(x) + end) - "#{to_string(kind)} #{ids} = #{inits};" + "#{to_string(kind)} #{declarators};" end def do_generate(%ESTree.VariableDeclarator{id: id, init: nil}, _level) do diff --git a/test/tools/generator/variable_declaration_test.exs b/test/tools/generator/variable_declaration_test.exs new file mode 100644 index 0000000..a258bb1 --- /dev/null +++ b/test/tools/generator/variable_declaration_test.exs @@ -0,0 +1,49 @@ +defmodule ESTree.Tools.Generator.VariableDeclaration.Test do + use ShouldI + + alias ESTree.Tools.{Builder, Generator} + + should "emit var declaration" do + ast = Builder.variable_declaration([]) + + assert Generator.generate(ast) == "var ;" + end + + should "emit let declaration" do + ast = Builder.variable_declaration([], :let) + + assert Generator.generate(ast) == "let ;" + end + + should "emit const declaration" do + ast = Builder.variable_declaration([], :const) + + assert Generator.generate(ast) == "const ;" + end + + should "add variable declarator" do + ast = Builder.variable_declaration([ + Builder.variable_declarator(Builder.identifier(:a)) + ]) + + assert Generator.generate(ast) == "var a;" + end + + should "add variable declarators with corresponding inits" do + ast = Builder.variable_declaration([ + Builder.variable_declarator(Builder.identifier(:a), Builder.literal(1)), + Builder.variable_declarator(Builder.identifier(:b)), + Builder.variable_declarator( + Builder.identifier(:c), + Builder.binary_expression( + :+, + Builder.identifier(:a), + Builder.literal(2) + ) + ) + ]) + + assert Generator.generate(ast) == "var a = 1, b, c = a + 2;" + end + +end From 8d9a8e0404043df3d52fd4553c574b6f769baebc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 19 Dec 2016 13:43:11 -0600 Subject: [PATCH 11/31] Release 2.4.2 --- CHANGELOG.md | 4 ++++ mix.exs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b07865..6efd8f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v2.4.2 +* Fixes + * [Expressions in variable declarations](https://github.com/bryanjos/elixir-estree/pull/13) + # v2.4.1 * Fixes * Handle edge case when string literal is a JSX child diff --git a/mix.exs b/mix.exs index bab6806..1df116f 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule ESTree.Mixfile do def project do [app: :estree, - version: "2.4.1", + version: "2.4.2", elixir: "~> 1.0", deps: deps, description: description, From 8ae49bc8d2254c9a7855dbd563ca92fb782b2449 Mon Sep 17 00:00:00 2001 From: Mikalai Seva Date: Thu, 5 Jan 2017 20:45:37 +0100 Subject: [PATCH 12/31] Recreated generator module + better test coverage --- lib/es_tree/tools/generator.ex | 1601 ++++++++++++----- test/support.ex | 14 + test/test_helper.exs | 2 + .../tools/generator/array_expression_test.exs | 22 +- test/tools/generator/array_pattern_test.exs | 31 + .../arrow_function_expression_test.exs | 82 + test/tools/generator/assignment_test.exs | 17 + .../generator/binary_expression_test.exs | 115 ++ test/tools/generator/block_statement_test.exs | 41 + test/tools/generator/call_expression_test.exs | 94 + test/tools/generator/class_body_test.exs | 211 +++ .../generator/class_declaration_test.exs | 54 + .../tools/generator/class_expression_test.exs | 50 + .../generator/conditional_statement_test.exs | 32 + .../generator/export_declaration_test.exs | 58 +- .../export_default_declaration_test.exs | 132 ++ .../export_named_declaration_test.exs | 141 ++ .../generator/expression_statement_test.exs | 54 + .../tools/generator/for_in_statement_test.exs | 19 + .../tools/generator/for_of_statement_test.exs | 19 + test/tools/generator/for_statement_test.exs | 40 + test/tools/generator/formatting_test.exs | 154 +- test/tools/generator/function_test.exs | 168 +- test/tools/generator/identifier_test.exs | 15 +- test/tools/generator/if_statement_test.exs | 29 +- .../generator/import_declaration_test.exs | 21 +- test/tools/generator/jsx_test.exs | 90 +- test/tools/generator/literal_test.exs | 57 +- test/tools/generator/new_expression_test.exs | 95 + .../generator/object_expression_test.exs | 92 +- test/tools/generator/object_pattern_test.exs | 57 + .../tools/generator/switch_statement_test.exs | 49 + .../tools/generator/template_literal_test.exs | 106 +- test/tools/generator/throw_statement_test.exs | 18 + test/tools/generator/try_statement_test.exs | 18 +- .../tools/generator/unary_expression_test.exs | 84 + .../generator/variable_declaration_test.exs | 19 +- test/tools/generator/while_statement_test.exs | 13 +- 38 files changed, 3153 insertions(+), 761 deletions(-) create mode 100644 test/support.ex create mode 100644 test/tools/generator/array_pattern_test.exs create mode 100644 test/tools/generator/arrow_function_expression_test.exs create mode 100644 test/tools/generator/assignment_test.exs create mode 100644 test/tools/generator/binary_expression_test.exs create mode 100644 test/tools/generator/block_statement_test.exs create mode 100644 test/tools/generator/call_expression_test.exs create mode 100644 test/tools/generator/class_body_test.exs create mode 100644 test/tools/generator/class_declaration_test.exs create mode 100644 test/tools/generator/class_expression_test.exs create mode 100644 test/tools/generator/conditional_statement_test.exs create mode 100644 test/tools/generator/export_default_declaration_test.exs create mode 100644 test/tools/generator/export_named_declaration_test.exs create mode 100644 test/tools/generator/expression_statement_test.exs create mode 100644 test/tools/generator/for_in_statement_test.exs create mode 100644 test/tools/generator/for_of_statement_test.exs create mode 100644 test/tools/generator/for_statement_test.exs create mode 100644 test/tools/generator/new_expression_test.exs create mode 100644 test/tools/generator/object_pattern_test.exs create mode 100644 test/tools/generator/switch_statement_test.exs create mode 100644 test/tools/generator/throw_statement_test.exs create mode 100644 test/tools/generator/unary_expression_test.exs diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index f46230d..bdecc9d 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -4,6 +4,137 @@ defmodule ESTree.Tools.Generator do it to JavaScript code """ + alias ESTree.ArrayExpression + alias ESTree.ArrayPattern + alias ESTree.ArrowFunctionExpression + alias ESTree.AssignmentExpression + alias ESTree.AssignmentPattern + alias ESTree.AssignmentProperty + alias ESTree.AwaitExpression + alias ESTree.BinaryExpression + alias ESTree.BlockStatement + alias ESTree.BreakStatement + alias ESTree.CallExpression + alias ESTree.CatchClause + alias ESTree.ClassBody + alias ESTree.ClassDeclaration + alias ESTree.ClassExpression + alias ESTree.ConditionalStatement + alias ESTree.ContinueStatement + alias ESTree.DebuggerStatement + alias ESTree.DoWhileStatement + alias ESTree.EmptyStatement + alias ESTree.ExportAllDeclaration + alias ESTree.ExportDefaultDeclaration + alias ESTree.ExportNamedDeclaration + alias ESTree.ExportSpecifier + alias ESTree.ExpressionStatement + alias ESTree.ForInStatement + alias ESTree.ForOfStatement + alias ESTree.ForStatement + alias ESTree.FunctionDeclaration + alias ESTree.FunctionExpression + alias ESTree.Identifier + alias ESTree.IfStatement + alias ESTree.ImportDeclaration + alias ESTree.ImportDefaultSpecifier + alias ESTree.ImportNamespaceSpecifier + alias ESTree.ImportSpecifier + alias ESTree.JSXAttribute + alias ESTree.JSXClosingElement + alias ESTree.JSXElement + alias ESTree.JSXEmptyExpression + alias ESTree.JSXExpressionContainer + alias ESTree.JSXIdentifier + alias ESTree.JSXMemberExpression + alias ESTree.JSXNamespacedName + alias ESTree.JSXOpeningElement + alias ESTree.JSXSpreadAttribute + alias ESTree.LabeledStatement + alias ESTree.Literal + alias ESTree.LogicalExpression + alias ESTree.MemberExpression + alias ESTree.MetaProperty + alias ESTree.MethodDefinition + alias ESTree.NewExpression + alias ESTree.ObjectExpression + alias ESTree.ObjectPattern + alias ESTree.Program + alias ESTree.Property + alias ESTree.RestElement + alias ESTree.ReturnStatement + alias ESTree.SequenceExpression + alias ESTree.SpreadElement + alias ESTree.Super + alias ESTree.SwitchCase + alias ESTree.SwitchStatement + alias ESTree.TaggedTemplateExpression + alias ESTree.TemplateElement + alias ESTree.TemplateLiteral + alias ESTree.ThisExpression + alias ESTree.ThrowStatement + alias ESTree.TryStatement + alias ESTree.UnaryExpression + alias ESTree.UpdateExpression + alias ESTree.VariableDeclaration + alias ESTree.VariableDeclarator + alias ESTree.WhileStatement + alias ESTree.WithStatement + alias ESTree.YieldExpression + + @operator_precedence %{ + ||: 3, + &&: 4, + |: 5, + ^: 6, + &: 7, + ==: 8, + !=: 8, + ===: 8, + !==: 8, + <: 9, + >: 9, + <=: 9, + >=: 9, + in: 9, + instanceof: 9, + "<<": 10, + ">>": 10, + >>>: 10, + +: 11, + -: 11, + *: 12, + %: 12, + /: 12, + "**": 13 + } + + @expressions_precedence %{ + ArrayExpression => 20, + TaggedTemplateExpression => 20, + ThisExpression => 20, + Identifier => 20, + Literal => 18, + TemplateLiteral => 20, + Super => 20, + SequenceExpression => 20, + MemberExpression => 19, + CallExpression => 19, + NewExpression => 19, + ArrowFunctionExpression => 18, + ClassExpression => 17, + FunctionExpression => 17, + ObjectExpression => 17, + UpdateExpression => 16, + UnaryExpression => 15, + BinaryExpression => 14, + LogicalExpression => 13, + ConditionalStatement => 4, + AssignmentExpression => 3, + YieldExpression => 2, + RestElement => 1 + } + @operators [ :-, :+ , :! , :"~" , :typeof , :void , :delete, :== , :!= , :=== , :!== , :< , :<= , :> , :>= , @@ -13,809 +144,1367 @@ defmodule ESTree.Tools.Generator do :">>>=" , :"|=" , :"^=" , :"&=", :++, :-- ] - @indent " " - @spec generate(ESTree.operator | ESTree.Node.t, integer) :: binary - def generate(value, level \\ nil) do - "#{do_generate(value, calculate_next_level(level))}" + def generate(value, beauty \\ true) do + opts = if beauty do + %{ + beauty: true, + wh_sep: " ", + comma_sep: ", ", + colon_sep: ": " + } + else + %{ + beauty: false, + wh_sep: "", + comma_sep: ",", + colon_sep: ":" + } + end + |> Map.merge( + %{indent: 0, + indent_start: 0, + indent_level: 4, + no_trailing_semicolon: false + } + ) + + value + |> do_generate(opts) + |> :erlang.iolist_to_binary() end - def do_generate(nil, _level) do - "" + def do_generate(nil, _opts) do + [] end - def do_generate(operator, _level) when operator in @operators do + def do_generate(operator, _opts) when operator in @operators do to_string(operator) end - def do_generate(%ESTree.Identifier{name: name}, _level) do - to_string(name) - end + # ArrayExpression - def do_generate(%ESTree.Literal{value: nil}, _level) do - "null" + def do_generate(%ArrayExpression{elements: nil}, _opts) do + "[]" end - def do_generate(%ESTree.Literal{value: %{}, regex: regex}, _level) do - "/#{regex.pattern}/#{regex.flags}" + def do_generate(%ArrayExpression{elements: []}, _opts) do + "[]" end - def do_generate(%ESTree.Literal{value: value}, _level) when is_boolean(value) do - "#{to_string(value)}" - end + def do_generate(%ArrayExpression{elements: elements}, opts) do + elements = elements + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(opts.comma_sep) - def do_generate(%ESTree.Literal{value: value}, _level) when is_atom(value) do - "'#{to_string(value)}'" + ["[", elements, "]"] end - def do_generate(%ESTree.Literal{value: value}, _level) when is_binary(value) do - value = convert_string_characters(value) + # ArrayPattern - "'#{value}'" + def do_generate(%ArrayPattern{elements: nil}, _opts) do + "[]" end - def do_generate(%ESTree.Literal{value: value}, _level) do - to_string(value) + def do_generate(%ArrayPattern{elements: []}, _opts) do + "[]" end - def do_generate(%ESTree.Program{body: []}, _level) do - "" - end + def do_generate(%ArrayPattern{elements: elements}, opts) do + elements = elements + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(opts.comma_sep) - def do_generate(%ESTree.Program{body: body}, level) do - Enum.map_join(body, newline(level), &generate(&1, calculate_next_level(level))) + ["[", elements, "]"] end - def do_generate(%ESTree.FunctionDeclaration{} = ast, level) do - generator = if ast.generator, do: "*", else: "" - async = if ast.async, do: "async ", else: "" + # ArrowFunctionExpression - params = params_and_defaults(ast.params, ast.defaults) - id = generate(ast.id) + def do_generate(%ArrowFunctionExpression{params: params, defaults: defaults, body: body, generator: generator} = ast, %{wh_sep: wh_sep} = opts) do + generator = if generator, do: "*", else: "" + params = params_and_defaults(params, defaults, opts) + body = if body.__struct__ == ObjectExpression do + ["(", do_generate(body, opts), ")"] + else + do_generate(body, opts) + end - "#{async}function#{generator} #{id}(#{params})#{generate(ast.body, calculate_next_level(level))}" + if not opts.beauty and length(ast.params) == 1 do + [params, generator, wh_sep, "=>", wh_sep, body] + else + ["(", params, ")", generator, wh_sep, "=>", wh_sep, body] + end end - def do_generate(%ESTree.FunctionExpression{} = ast, level) do - generator = if ast.generator, do: "*", else: "" - async = if ast.async, do: "async ", else: "" - params = params_and_defaults(ast.params, ast.defaults) + # AssignmentExpression - "#{async}function#{generator}(#{params})#{generate(ast.body, calculate_next_level(level))}" + def do_generate(%AssignmentExpression{operator: operator, left: left, right: right}, %{wh_sep: wh_sep} = opts) do + operator = do_generate(operator, opts) + left = do_generate(left, opts) + right = do_generate(right, opts) + + [left, wh_sep, operator, wh_sep, right] end - def do_generate(%ESTree.EmptyStatement{}, _level) do - ";" + # AssignmentPattern + + def do_generate(%AssignmentPattern{left: left, right: right}, %{wh_sep: wh_sep} = opts) do + left = do_generate(left, opts) + right = do_generate(right, opts) + + [left, wh_sep, "=", wh_sep, right] end - def do_generate(%ESTree.BlockStatement{body: body}, level) do - "{#{newline(level)}#{indent(calculate_next_level(level))}" <> Enum.map_join(body, "#{newline(level)}#{indent(calculate_next_level(level))}", &generate(&1)) <> "#{newline(level)}#{indent(level)}}" + # AssignmentProperty + + def do_generate(%AssignmentProperty{value: value}, opts) do + do_generate(value, opts) end - def do_generate(%ESTree.ExpressionStatement{expression: expression}, _level) do - "#{generate(expression)};" + # AwaitExpression + + def do_generate(%AwaitExpression{argument: argument, all: _all}, opts) do + ["await ", do_generate(argument, opts)] end - def do_generate(%ESTree.IfStatement{test: test, consequent: consequent, alternate: alternate}, level) do - test = generate(test) - consequent = generate(consequent, calculate_next_level(level)) - result = "if(#{test}) #{consequent}" + # BinaryExpression - if alternate do - result <> " else #{generate(alternate, calculate_next_level(level))}" + def do_generate(%BinaryExpression{operator: operator, left: left, right: right} = node, opts) when operator in [:in, :instanceof] do + operator = [" ", do_generate(operator, opts), " "] + left = format_binary_expression(left, node, false, opts) + right = format_binary_expression(right, node, true, opts) + + if node.operator == :in do + ["(", left, operator, right, ")"] else - result + [left, operator, right] end end - def do_generate(%ESTree.LabeledStatement{label: label, body: body}, level) do - """ - #{generate(label, level)}: - #{generate(body, calculate_next_level(level))} - """ - end + def do_generate(%BinaryExpression{operator: operator, left: left, right: right} = node, %{wh_sep: wh_sep} = opts) do + operator = do_generate(operator, opts) + left = format_binary_expression(left, node, false, opts) + right = format_binary_expression(right, node, true, opts) - def do_generate(%ESTree.BreakStatement{label: nil}, _level) do - "break;" + [left, wh_sep, operator, wh_sep, right] end - def do_generate(%ESTree.BreakStatement{label: label}, _level) do - "break #{generate(label)};" + # BlockStatement + + def do_generate(%BlockStatement{body: []}, _opts) do + "{}" end - def do_generate(%ESTree.ContinueStatement{label: nil}, _level) do - "continue;" + def do_generate(%BlockStatement{body: body}, opts) do + close_bracket = if opts.beauty do + ["\n", indent(opts), "}"] + else + "}" + end + + opts = next_indent(opts) + i = indent(opts) + + sep = if opts.beauty do + ["\n\n", i] + else + "" + end + + open_bracket = if opts.beauty do + ["{\n", i] + else + "{" + end + + statements = body + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(sep) + + [open_bracket, statements, close_bracket] end - def do_generate(%ESTree.ContinueStatement{label: label}, _level) do - "continue #{generate(label)};" + # BreakStatement + + def do_generate(%BreakStatement{label: nil}, _opts) do + "break;" end - def do_generate(%ESTree.WithStatement{object: object, body: body}, level) do - "with(#{generate(object)})#{generate(body, calculate_next_level(level))}" + def do_generate(%BreakStatement{label: label}, opts) do + ["break ", do_generate(label, opts), ";"] end - def do_generate(%ESTree.SwitchStatement{discriminant: discriminant, cases: cases}, level) do - cases = Enum.map_join(cases, newline(level), &generate(&1, calculate_next_level(level))) - "switch(#{generate(discriminant)}){ #{cases} }" + # CallExpression + + def do_generate(%CallExpression{callee: callee, arguments: arguments}, opts) do + precedence = Map.get(@expressions_precedence, callee.__struct__) + callee = do_generate(callee, opts) + + callee = if precedence < @expressions_precedence[CallExpression] do + ["(", callee, ")"] + else + callee + end + + arguments = arguments + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(opts.comma_sep) + + [callee, "(", arguments, ")"] end - def do_generate(%ESTree.ReturnStatement{argument: argument}, level) do - "return #{generate(argument, calculate_next_level(level))};" + # CatchClause + + def do_generate(%CatchClause{param: param, body: body}, %{wh_sep: wh_sep} = opts) do + param = do_generate(param, opts) + body = do_generate(body, opts) + + ["catch", wh_sep, "(", param, ")", wh_sep, body] end - def do_generate(%ESTree.ThrowStatement{argument: argument}, level) do - "throw #{generate(argument, calculate_next_level(level))};" + # ClassBody + + def do_generate(%ClassBody{body: []}, _opts) do + "{}" end - def do_generate(%ESTree.TryStatement{block: block, handler: handler, finalizer: nil}, level) do - "try#{generate(block, calculate_next_level(level))}#{generate(handler, calculate_next_level(level))}" + def do_generate(%ClassBody{body: body}, opts) do + close_bracket = if opts.beauty do + ["\n", indent(opts), "}"] + else + "}" + end + + opts = next_indent(opts) + i = indent(opts) + + sep = if opts.beauty do + [";\n", i] + else + ";" + end + + open_bracket = if opts.beauty do + ["{\n", i] + else + "{" + end + + statements = body + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(sep) + + [open_bracket, statements, close_bracket] end - def do_generate(%ESTree.TryStatement{block: block, handler: nil, finalizer: finalizer}, level) do - "try#{generate(block, calculate_next_level(level))}finally#{generate(finalizer, calculate_next_level(level))}" + # ClassDeclaration + + def do_generate(%ClassDeclaration{id: id, body: body, superClass: nil}, %{wh_sep: wh_sep} = opts) do + id = do_generate(id, opts) + body = do_generate(body, opts) + + ["class ", id, wh_sep, body] end - def do_generate(%ESTree.TryStatement{block: block, handler: handler, finalizer: finalizer}, level) do - "try#{generate(block, calculate_next_level(level))}#{generate(handler, calculate_next_level(level))}finally#{generate(finalizer, calculate_next_level(level))}" + def do_generate(%ClassDeclaration{id: id, body: body, superClass: super_class}, %{wh_sep: wh_sep} = opts) do + id = do_generate(id, opts) + body = do_generate(body, opts) + super_class = do_generate(super_class, opts) + + ["class ", id, " extends ", super_class, wh_sep, body] end - def do_generate(%ESTree.WhileStatement{test: test, body: body}, level) do - "while(#{generate(test)}) #{generate(body, calculate_next_level(level))}" + # ClassExpression + + def do_generate(%ClassExpression{body: body, superClass: nil}, %{wh_sep: wh_sep} = opts) do + ["class", wh_sep, do_generate(body, opts)] end - def do_generate(%ESTree.DoWhileStatement{test: test, body: body}, level) do - "do #{generate(body, calculate_next_level(level))} while(#{generate(test, level)});" + def do_generate(%ClassExpression{body: body, superClass: super_class}, %{wh_sep: wh_sep} = opts) do + super_class = do_generate(super_class, opts) + body = do_generate(body, opts) + + ["class extends ", super_class, wh_sep, body] end - def do_generate(%ESTree.ForStatement{init: init, test: test, update: update, body: body}, level) do - init = generate(init) - test = generate(test) - update = generate(update) - body = generate(body, calculate_next_level(level)) + # ConditionalStatement + + def do_generate(%ConditionalStatement{test: test, alternate: alternate, consequent: consequent}, %{wh_sep: wh_sep} = opts) do + precedence = Map.get(@expressions_precedence, test.__struct__) + test = do_generate(test, opts) + + test = if precedence < @expressions_precedence[ConditionalStatement] do + ["(", test, ")"] + else + test + end + + consequent = do_generate(consequent, opts) + alternate = do_generate(alternate, opts) - "for(#{init}; #{test}; #{update}) #{body}" + [test, wh_sep, "?", wh_sep, consequent, wh_sep, ":", wh_sep, alternate] end - def do_generate(%ESTree.ForInStatement{left: left, right: right, body: body}, level) do - left = generate(left) |> String.replace(";","") - right = generate(right) - body = generate(body, calculate_next_level(level)) + # ContinueStatement + + def do_generate(%ContinueStatement{label: nil}, _opts) do + "continue;" + end - "for(#{left} in #{right}) #{body}" + def do_generate(%ContinueStatement{label: label}, opts) do + ["continue ", do_generate(label, opts), ";"] end - def do_generate(%ESTree.DebuggerStatement{}, _level) do + # DebuggerStatement + + def do_generate(%DebuggerStatement{}, _opts) do "debugger;" end - def do_generate(%ESTree.VariableDeclaration{kind: kind, declarations: declarations}, _level) when kind in [:var, :let, :const] do + # DoWhileStatement - declarators = declarations - |> Enum.map_join(", ", fn(x) -> - generate(x) - end) + def do_generate(%DoWhileStatement{test: test, body: body}, %{wh_sep: wh_sep} = opts) do + test = do_generate(test, opts) + body = do_generate(body, opts) - "#{to_string(kind)} #{declarators};" + ["do", wh_sep, body, wh_sep, "while", wh_sep, "(", test, ");"] end - def do_generate(%ESTree.VariableDeclarator{id: id, init: nil}, _level) do - generate(id) - end + # EmptyStatement - def do_generate(%ESTree.VariableDeclarator{id: id, init: init}, _level) do - "#{generate(id)} = #{generate(init)}" + def do_generate(%EmptyStatement{}, _opts) do + ";" end - def do_generate(%ESTree.ThisExpression{}, _level) do - "this" + # ExportAllDeclaration + + def do_generate(%ExportAllDeclaration{source: source}, %{wh_sep: wh_sep} = opts) do + source = do_generate(source, opts) + + ["export", wh_sep, "*", wh_sep, "from", wh_sep, source, ";"] end - def do_generate(%ESTree.ArrayExpression{elements: nil}, _level) do - "[]" + # ExportDefaultDeclaration + + def do_generate(%ExportDefaultDeclaration{declaration: %ClassDeclaration{} = declaration}, opts) do + ["export default ", do_generate(declaration, opts)] end - def do_generate(%ESTree.ArrayExpression{elements: elements}, _level) do - "[" <> Enum.map_join(elements, ", ", &generate(&1)) <> "]" + def do_generate(%ExportDefaultDeclaration{declaration: %FunctionDeclaration{} = declaration}, opts) do + ["export default ", do_generate(declaration, opts)] end - def do_generate(%ESTree.ObjectExpression{properties: nil}, _level) do - "{}" + def do_generate(%ExportDefaultDeclaration{declaration: declaration}, opts) do + ["export default ", do_generate(declaration, opts), ";"] end - def do_generate(%ESTree.ObjectExpression{properties: []}, _level) do - "{}" + # ExportNamedDeclaration + + def do_generate(%ExportNamedDeclaration{declaration: declaration, specifiers: [], source: nil}, opts) do + ["export ", do_generate(declaration, opts)] end - def do_generate(%ESTree.ObjectExpression{properties: properties}, level) do - _next_level = calculate_next_level(level) - previous_level = calculate_previous_level(level) - key_value_separator = ",#{newline(level)}#{indent(level)}" - "{#{newline(level)}#{indent(level)}" <> Enum.map_join(properties, key_value_separator, &generate(&1)) <> "#{newline(level)}#{indent(previous_level)}}" + def do_generate(%ExportNamedDeclaration{declaration: nil, specifiers: specifiers, source: nil}, %{wh_sep: wh_sep} = opts) do + specifiers = specifiers + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(opts.comma_sep) + + ["export", wh_sep, "{", wh_sep, specifiers, wh_sep, "};"] end - def do_generate(%ESTree.Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: false}, _level) do - key = generate(key) - value = generate(value) + def do_generate(%ExportNamedDeclaration{declaration: nil, specifiers: specifiers, source: source}, %{wh_sep: wh_sep} = opts) do + specifiers = specifiers + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(opts.comma_sep) - "#{key}: #{value}" + ["export", wh_sep, "{", wh_sep, specifiers, wh_sep, "}", wh_sep, "from", wh_sep, do_generate(source, opts), ";"] end - def do_generate(%ESTree.Property{key: key, value: _, kind: :init, shorthand: true, method: false, computed: false}, _level) do - key = generate(key) + # ExportSpecifier - "#{key}" + def do_generate(%ExportSpecifier{local: local, exported: exported}, opts) do + if local == exported do + do_generate(local, opts) + else + [do_generate(exported, opts), " as ", do_generate(local, opts)] + end end - def do_generate(%ESTree.Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: true}, _level) do - key = generate(key) - value = generate(value) + # ExpressionStatement + + def do_generate(%ExpressionStatement{expression: expression}, opts) do + precedence = Map.get(@expressions_precedence, expression.__struct__) - "[#{key}]: #{value}" + if precedence == 17 or (precedence == 3 and expression.left.__struct__ == ObjectPattern) do + ["(", do_generate(expression, opts), ");"] + else + [do_generate(expression, opts), ";"] + end end - def do_generate(%ESTree.Property{key: key, value: %ESTree.FunctionExpression{body: body}, kind: :get, shorthand: false, method: true, computed: false}, _level) do - key = generate(key) - value = generate(body) + # ForInStatement - "#{key}() #{value}" + def do_generate(%ForInStatement{left: left, right: right, body: body}, %{wh_sep: wh_sep} = opts) do + left = do_generate(left, %{opts | no_trailing_semicolon: true}) + right = do_generate(right, opts) + body = do_generate(body, opts) + + ["for", wh_sep, "(", left, " in ", right, ")", wh_sep, body] end + # ForOfStatement - def do_generate(%ESTree.Property{key: key, value: %ESTree.FunctionExpression{body: body}, kind: :get}, _level) do - key = generate(key) - value = generate(body) + def do_generate(%ForOfStatement{left: left, right: right, body: body}, %{wh_sep: wh_sep} = opts) do + left = do_generate(left, %{opts | no_trailing_semicolon: true}) + right = do_generate(right, opts) + body = do_generate(body, opts) - "get #{key}() #{value}" + ["for", wh_sep, "(", left, " of ", right, ")", wh_sep, body] end - def do_generate(%ESTree.Property{key: key, value: %ESTree.FunctionExpression{params: params, body: body}, kind: :set, shorthand: false, method: true, computed: false}, _level) do - key = generate(key) - param = generate(hd(params)) - value = generate(body) + # ForStatement + + def do_generate(%ForStatement{init: init, test: test, update: update, body: body}, %{wh_sep: wh_sep} = opts) do + init = do_generate(init, %{opts | no_trailing_semicolon: true}) + test = do_generate(test, opts) + update = do_generate(update, opts) + body = do_generate(body, opts) - "#{key}(#{param}) #{value}" + ["for", wh_sep, "(", init, ";", wh_sep, test, ";", wh_sep, update, ")", wh_sep, body] end + # FunctionDeclaration + + def do_generate(%FunctionDeclaration{generator: generator, async: async, id: id, params: params, defaults: defaults, body: body}, %{wh_sep: wh_sep} = opts) do + generator = if generator, do: "*", else: "" + async = if async, do: "async ", else: "" + params = params_and_defaults(params, defaults, opts) + id = do_generate(id, opts) + body = do_generate(body, opts) - def do_generate(%ESTree.Property{key: key, value: %ESTree.FunctionExpression{params: params, body: body}, kind: :set}, _level) do - key = generate(key) - param = generate(hd(params)) - value = generate(body) + sep = if generator == "" do + " " + else + wh_sep + end - "set #{key}(#{param}) #{value}" + [async, "function", generator, sep, id, "(", params, ")", wh_sep, body] end - def do_generate(%ESTree.SequenceExpression{expressions: expressions}, _level) do - Enum.map_join(expressions, ",", &generate(&1)) + # FunctionExpression + + def do_generate(%FunctionExpression{generator: generator, async: async, params: params, defaults: defaults, body: body}, %{wh_sep: wh_sep} = opts) do + generator = if generator, do: "*", else: "" + async = if async, do: "async ", else: "" + params = params_and_defaults(params, defaults, opts) + body = do_generate(body, opts) + + [async, "function", generator, "(", params, ")", wh_sep, body] end - def do_generate(%ESTree.UnaryExpression{operator: :typeof, prefix: true, argument: argument}, _level) do - "#{generate(:typeof)} #{generate(argument)}" + # Identifier + + def do_generate(%Identifier{name: name}, _opts) do + to_string(name) end - def do_generate(%ESTree.UnaryExpression{operator: operator, prefix: true, argument: argument}, _level) do - "#{generate(operator)}#{generate(argument)}" + # IfStatement + + def do_generate(%IfStatement{test: test, consequent: consequent, alternate: nil}, %{wh_sep: wh_sep} = opts) do + test = do_generate(test, opts) + + sep_c = if opts.beauty do + ["\n", indent(next_indent(opts))] + else + "" + end + + sep_end = if opts.beauty do + "\n" + else + "" + end + + consequent = + case consequent do + %BlockStatement{} -> + [wh_sep, do_generate(consequent, opts)] + + _ -> + [sep_c, do_generate(consequent, opts), sep_end] + end + + ["if", wh_sep, "(", test, ")", consequent] end - def do_generate(%ESTree.UnaryExpression{operator: operator, prefix: false, argument: argument}, _level) do - "#{generate(argument)}#{generate(operator)}" + def do_generate(%IfStatement{test: test, consequent: consequent, alternate: alternate}, %{wh_sep: wh_sep} = opts) do + test = do_generate(test, opts) + + sep_c = if opts.beauty do + ["\n", indent(next_indent(opts))] + else + "" + end + + sep_end = if opts.beauty do + "\n" + else + "" + end + + {consequent, sep_if} = + case consequent do + %BlockStatement{} -> + {[wh_sep, do_generate(consequent, opts)], wh_sep} + + _ -> + {[sep_c, do_generate(consequent, opts), sep_end], ""} + end + + sep_a = if opts.beauty do + ["\n", indent(next_indent(opts))] + else + " " + end + + alternate = + case alternate do + %BlockStatement{} -> + [wh_sep, "else", wh_sep, do_generate(alternate, opts)] + + %IfStatement{} -> + [sep_if, "else ", do_generate(alternate, opts)] + + _ -> + ["else", sep_a, do_generate(alternate, opts)] + end + + ["if", wh_sep, "(", test, ")", consequent, alternate] end - def do_generate(%ESTree.BinaryExpression{operator: operator, left: %ESTree.BinaryExpression{} = left, right: %ESTree.BinaryExpression{} = right}, _level) do - operator = generate(operator) - left = generate(left) - right = generate(right) + # ImportDeclaration + + def do_generate(%ImportDeclaration{specifiers: [%ImportDefaultSpecifier{}] = specifiers, source: source}, %{wh_sep: wh_sep} = opts) do + specifiers = specifiers + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(opts.comma_sep) + + source = do_generate(source, opts) - "(#{left}) #{operator} (#{right})" + ["import ", specifiers, " from", wh_sep, source, ";"] end - def do_generate(%ESTree.BinaryExpression{operator: operator, left: left, right: %ESTree.BinaryExpression{} = right}, _level) do - operator = generate(operator) - left = generate(left) - right = generate(right) + def do_generate(%ImportDeclaration{specifiers: [%ImportNamespaceSpecifier{}] = specifiers, source: source}, %{wh_sep: wh_sep} = opts) do + specifiers = specifiers + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(opts.comma_sep) - "#{left} #{operator} (#{right})" + ["import", specifiers, " from", wh_sep, do_generate(source, opts), ";"] end - def do_generate(%ESTree.BinaryExpression{operator: operator, left: left, right: right}, _level) do - operator = generate(operator) - left = generate(left) - right = generate(right) + def do_generate(%ImportDeclaration{specifiers: specifiers, source: source}, %{wh_sep: wh_sep} = opts) do + specifiers = specifiers + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(opts.comma_sep) - "#{left} #{operator} #{right}" + ["import", wh_sep, "{", wh_sep, specifiers, wh_sep, "}", wh_sep, "from", wh_sep, do_generate(source, opts), ";"] end - def do_generate(%ESTree.AssignmentExpression{operator: operator, left: left, right: right}, _level) do - operator = generate(operator) - left = generate(left) - right = generate(right) + # ImportDefaultSpecifier - "#{left} #{operator} #{right}" + def do_generate(%ImportDefaultSpecifier{local: local}, opts) do + do_generate(local, opts) end - def do_generate(%ESTree.UpdateExpression{operator: operator, prefix: true, argument: argument}, _level) do - "#{generate(operator)}#{generate(argument)}" + # ImportNamespaceSpecifier + + def do_generate(%ImportNamespaceSpecifier{local: local}, %{wh_sep: wh_sep} = opts) do + [wh_sep, "*", wh_sep, "as ", do_generate(local, opts)] end - def do_generate(%ESTree.UpdateExpression{operator: operator, prefix: false, argument: argument}, _level) do - "#{generate(argument)}#{generate(operator)}" + # ImportSpecifier + + def do_generate(%ImportSpecifier{local: local, imported: imported}, opts) do + if local == imported do + do_generate(local, opts) + else + [do_generate(imported, opts), " as ", do_generate(local, opts)] + end end - def do_generate(%ESTree.LogicalExpression{operator: operator, left: left, right: right}, _level) do - operator = generate(operator) - left = generate(left) - right = generate(right) + # JSXAttribute - "#{left} #{operator} #{right}" + def do_generate(%JSXAttribute{name: name, value: value}, opts) do + [do_generate(name, opts), "=", do_generate(value, opts)] end - def do_generate(%ESTree.ConditionalStatement{test: test, alternate: alternate, consequent: consequent}, _level) do - test = generate(test) - alternate = generate(alternate) - consequent = generate(consequent) + # JSXClosingElement - "#{test} ? #{consequent} : #{alternate}" + def do_generate(%JSXClosingElement{name: name}, opts) do + [""] end - def do_generate(%ESTree.CallExpression{callee: %ESTree.MemberExpression{ object: %ESTree.FunctionExpression{} } = callee, arguments: arguments}, level) do - callee = generate(callee, level) - arguments = Enum.map_join(arguments, ",", &generate(&1, level)) + # JSXElement - "(#{callee}(#{arguments}))" + def do_generate(%JSXElement{openingElement: opening_element, children: children, closingElement: closing_element}, opts) do + opening_element = do_generate(opening_element, opts) + children = generate_jsx_children(children, opts) + closing_element = do_generate(closing_element, opts) + + [opening_element, children, closing_element] end - def do_generate(%ESTree.CallExpression{callee: %ESTree.Super{}, arguments: arguments}, _level) do - arguments = Enum.map_join(arguments, ",", &generate(&1)) + # JSXEmptyExpression - "super(#{arguments})" + def do_generate(%JSXEmptyExpression{}, _opts) do + "" end - def do_generate(%ESTree.CallExpression{callee: callee, arguments: arguments}, level) do - callee = generate(callee) - arguments = Enum.map_join(arguments, ",", &generate(&1, calculate_previous_level(level))) + # JSXExpressionContainer - "#{callee}(#{arguments})" + def do_generate(%JSXExpressionContainer{expression: expression}, opts) do + ["{", do_generate(expression, opts), "}"] end - def do_generate(%ESTree.NewExpression{callee: callee, arguments: arguments}, _level) do - callee = generate(callee) - arguments = Enum.map_join(arguments, ",", &generate(&1)) + # JSXIdentifier - "new #{callee}(#{arguments})" + def do_generate(%JSXIdentifier{name: name}, _opts) when is_binary(name) do + name + end + + def do_generate(%JSXIdentifier{name: name}, _opts) when is_atom(name) do + to_string(name) end - def do_generate(%ESTree.MemberExpression{object: %ESTree.Super{}, property: property, computed: true}, _level) do - property = generate(property) - "super[#{property}]" + # JSXMemberExpression + + def do_generate(%JSXMemberExpression{object: object, property: property}, opts) do + [do_generate(object, opts), ".", do_generate(property, opts)] end - def do_generate(%ESTree.MemberExpression{object: object, property: property, computed: true}, _level) do - object = generate(object) - property = generate(property) - "#{object}[#{property}]" + # JSXNamespacedName + + def do_generate(%JSXNamespacedName{namespace: namespace, name: name}, opts) do + [do_generate(namespace, opts), ":", do_generate(name, opts)] end - def do_generate(%ESTree.MemberExpression{object: %ESTree.Super{}, property: property, computed: false}, _level) do - property = generate(property) - "super.#{property}" + # JSXOpeningElement + + def do_generate(%JSXOpeningElement{name: name, attributes: attributes, selfClosing: self_closing}, %{wh_sep: wh_sep} = opts) do + self_closing = if self_closing, do: [wh_sep, "/"], else: "" + attributes_value = cond do + Enum.empty?(attributes) -> "" + true -> + attributes = attributes + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(" ") + + [" " | attributes] + end + + ["<", do_generate(name, opts), attributes_value, self_closing, ">"] end - def do_generate(%ESTree.MemberExpression{object: object, property: property, computed: false}, _level) do - object = generate(object) - property = generate(property) - "#{object}.#{property}" + # JSXSpreadAttribute + + def do_generate(%JSXSpreadAttribute{argument: argument}, opts) do + ["{...", do_generate(argument, opts), "}"] end - def do_generate(%ESTree.SwitchCase{test: nil, consequent: consequent}, level) do - consequent = Enum.map_join(consequent, newline(level), &generate(&1)) - """ - default: - #{consequent} - """ + # LabeledStatement + + def do_generate(%LabeledStatement{label: label, body: body}, opts) do + label = do_generate(label, opts) + body = do_generate(body, opts) + + [label, ": ", body] end - def do_generate(%ESTree.SwitchCase{test: test, consequent: consequent}, level) do - test = generate(test) - consequent = Enum.map_join(consequent, newline(level), &generate(&1)) + # Literal - """ - case #{test}: - #{consequent} - """ + def do_generate(%Literal{value: nil}, _opts) do + "null" end - def do_generate(%ESTree.CatchClause{param: param, body: body}, _level) do - param = generate(param) - body = generate(body) + def do_generate(%Literal{value: %{}, regex: regex}, _opts) do + ["/", regex.pattern, "/", regex.flags] + end - "catch(#{param}) #{body}" + def do_generate(%Literal{value: value}, _opts) when is_boolean(value) do + to_string(value) end - def do_generate(%ESTree.ForOfStatement{left: left, right: right, body: body}, _level) do - left = generate(left) |> String.replace(";","") - right = generate(right) - body = generate(body) + def do_generate(%Literal{value: value}, _opts) when is_atom(value) do + ["'", to_string(value), "'"] + end - "for(#{left} of #{right}) #{body}" + def do_generate(%Literal{value: value}, _opts) when is_binary(value) do + ["'", escape_string(value), "'"] end - def do_generate(%ESTree.SpreadElement{argument: argument}, _level) do - "...#{generate(argument)}" + def do_generate(%Literal{value: value}, _opts) do + to_string(value) end - def do_generate(%ESTree.RestElement{argument: argument}, _level) do - "...#{generate(argument)}" + # LogicalExpression + + def do_generate(%LogicalExpression{operator: operator, left: left, right: right} = node, %{wh_sep: wh_sep} = opts) do + operator = do_generate(operator, opts) + left = format_binary_expression(left, node, false, opts) + right = format_binary_expression(right, node, true, opts) + + [left, wh_sep, operator, wh_sep, right] end - def do_generate(%ESTree.ArrowFunctionExpression{} = ast, _level) do - generator = if ast.generator - do - "*" + # MemberExpression + + def do_generate(%MemberExpression{object: object, property: property, computed: computed}, opts) do + precedence = Map.get(@expressions_precedence, object.__struct__) + object = do_generate(object, opts) + + object = if precedence < @expressions_precedence[MemberExpression] do + ["(", object, ")"] else - "" + object end - params = params_and_defaults(ast.params, ast.defaults) + property = do_generate(property, opts) - "(#{params})#{generator} => #{generate(ast.body)}" + property = if computed do + ["[", property, "]"] + else + [".", property] + end + + [object, property] end - def do_generate(%ESTree.YieldExpression{argument: argument, delegate: false}, _level) do - "yield #{generate(argument)}" + # MetaProperty + + def do_generate(%MetaProperty{meta: meta, property: property}, opts) do + [do_generate(meta, opts), ".", do_generate(property, opts)] end - def do_generate(%ESTree.YieldExpression{argument: argument, delegate: true}, _level) do - "yield* #{generate(argument)}" + # MethodDefinition + + def do_generate(%MethodDefinition{key: _key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :constructor}, opts) do + params = params_and_defaults(params, defaults, opts) + body = do_generate(body, opts) + + ["constructor(", params, ")", opts.wh_sep, body] end - def do_generate(%ESTree.ObjectPattern{properties: properties}, _level) do - "{" <> Enum.map_join(properties, ",", &generate(&1)) <> "}" + def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :method, computed: false, static: false}, opts) do + key = do_generate(key, opts) + params = params_and_defaults(params, defaults, opts) + body = do_generate(body, opts) + + [key, "(", params, ")", opts.wh_sep, body] end - def do_generate(%ESTree.AssignmentProperty{ value: value }, _) do - value = generate(value) - "#{value}" + def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :method, computed: false, static: true}, opts) do + key = do_generate(key, opts) + params = params_and_defaults(params, defaults, opts) + body = do_generate(body, opts) + + ["static ", key, "(", params, ")", opts.wh_sep, body] end - def do_generate(%ESTree.ArrayPattern{elements: elements}, _level) do - "[" <> Enum.map_join(elements, ",", &generate(&1)) <> "]" + def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :method, computed: true, static: false}, opts) do + key = do_generate(key, opts) + params = params_and_defaults(params, defaults, opts) + body = do_generate(body, opts) + + ["[", key, "](", params, ")", opts.wh_sep, body] end - def do_generate(%ESTree.AssignmentPattern{left: left, right: right}, _level) do - left = generate(left) - right = generate(right) + def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :method, computed: true, static: true}, opts) do + key = generate(key, opts) + params = params_and_defaults(params, defaults, opts) + body = do_generate(body, opts) - "#{left} = #{right}" + ["static [", key, "](", params, ")", opts.wh_sep, body] end + def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{body: body}, kind: :get, static: true}, opts) do + key = generate(key, opts) + body = do_generate(body, opts) + + ["static get ", key, "()", opts.wh_sep, body] + end - def do_generate(%ESTree.ClassDeclaration{id: id, body: body, superClass: nil}, _level) do - id = generate(id) - body = generate(body) + def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :set, static: true}, opts) do + key = generate(key, opts) + params = params_and_defaults(params, defaults, opts) + body = do_generate(body, opts) - "class #{id} #{body}" + ["static set ", key, "(", params, ")", opts.wh_sep, body] end + def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{body: body}, kind: :get}, opts) do + key = generate(key, opts) + body = do_generate(body, opts) + + ["get ", key, "()", opts.wh_sep, body] + end - def do_generate(%ESTree.ClassDeclaration{id: id, body: body, superClass: superClass}, _level) do - id = generate(id) - body = generate(body) - superClass = generate(superClass) + def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :set}, opts) do + key = generate(key, opts) + params = params_and_defaults(params, defaults, opts) + body = do_generate(body, opts) - "class #{id} extends #{superClass} #{body}" + ["set ", key, "(", params, ")", opts.wh_sep, body] end + # NewExpression - def do_generate(%ESTree.ClassExpression{body: body, superClass: nil}, _level) do - body = generate(body) + def do_generate(%NewExpression{callee: callee, arguments: arguments}, opts) do + precedence = Map.get(@expressions_precedence, callee.__struct__) + + callee = if precedence < @expressions_precedence[NewExpression] or has_call_expression(callee) do + ["(", do_generate(callee, opts), ")"] + else + do_generate(callee, opts) + end - "class #{body}" + arguments = arguments + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(opts.comma_sep) + + ["new ", callee, "(", arguments, ")"] end + # ObjectExpression - def do_generate(%ESTree.ClassExpression{body: body, superClass: superClass}, _level) do - body = generate(body) - superClass = generate(superClass) + def do_generate(%ObjectExpression{properties: nil}, _opts) do + "{}" + end - "class extends #{superClass} #{body}" + def do_generate(%ObjectExpression{properties: []}, _opts) do + "{}" end - def do_generate(%ESTree.ClassBody{body: body}, level) do - body = Enum.map_join(body, newline(level), &generate(&1)) + def do_generate(%ObjectExpression{properties: properties}, opts) do + close_bracket = if opts.beauty do + ["\n", indent(opts), "}"] + else + "}" + end - "{ #{body} }" - end + opts = next_indent(opts) + i = indent(opts) - def do_generate(%ESTree.MethodDefinition{key: _key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :constructor}, _level) do - params = params_and_defaults(params, defaults) - body = generate(body) + open_bracket = if opts.beauty do + ["{\n", i] + else + "{" + end - "constructor(#{params})#{body}" - end + sep = if opts.beauty do + [",\n", i] + else + opts.comma_sep + end - def do_generate(%ESTree.MethodDefinition{key: key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :method, computed: false, static: false}, _level) do - key = generate(key) - params = params_and_defaults(params, defaults) - body = generate(body) + properties = properties + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(sep) - "#{key}(#{params})#{body}" + [open_bracket, properties, close_bracket] end - def do_generate(%ESTree.MethodDefinition{key: key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :method, computed: false, static: true}, _level) do - key = generate(key) - params = params_and_defaults(params, defaults) - body = generate(body) + # ObjectPattern + + def do_generate(%ObjectPattern{properties: properties}, opts) do + properties = properties + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(opts.comma_sep) - "static #{key}(#{params})#{body}" + ["{", properties, "}"] end - def do_generate(%ESTree.MethodDefinition{key: key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :method, computed: true, static: false}, _level) do - key = generate(key) - params = params_and_defaults(params, defaults) - body = generate(body) + # Program - "[#{key}](#{params})#{body}" + def do_generate(%Program{body: []}, _opts) do + "" end - def do_generate(%ESTree.MethodDefinition{key: key, value: %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body}, kind: :method, computed: true, static: true}, _level) do - key = generate(key) - params = params_and_defaults(params, defaults) - body = generate(body) + def do_generate(%Program{body: body}, opts) do + sep = if opts.beauty do + "\n\n" + else + "" + end - "static [#{key}](#{params})#{body}" + body + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(sep) end - def do_generate(%ESTree.MetaProperty{meta: meta, property: property}, _level) do - meta = generate(meta) - property = generate(property) + # Property + + def do_generate(%Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: false}, %{colon_sep: colon_sep} = opts) do + key = do_generate(key, opts) + value = do_generate(value, opts) - "#{meta}.#{property}" + [key, colon_sep, value] end - def do_generate(%ESTree.ImportDeclaration{specifiers: [%ESTree.ImportDefaultSpecifier{}] = specifiers, source: source}, _level) do - specifiers = Enum.map_join(specifiers, ", ", &generate(&1)) - source = generate(source) + def do_generate(%Property{key: key, value: _, kind: :init, shorthand: true, method: false, computed: false}, opts) do + do_generate(key, opts) + end + + def do_generate(%Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: true}, %{colon_sep: colon_sep} = opts) do + key = do_generate(key, opts) + value = do_generate(value, opts) - "import #{specifiers} from #{source};" + ["[", key, "]", colon_sep, value] end - def do_generate(%ESTree.ImportDeclaration{specifiers: [%ESTree.ImportNamespaceSpecifier{}] = specifiers, source: source}, _level) do - specifiers = Enum.map_join(specifiers, ", ", &generate(&1)) - source = generate(source) + def do_generate(%Property{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :init, shorthand: false, method: true, computed: true}, %{wh_sep: wh_sep} = opts) do + key = do_generate(key, opts) + params = params_and_defaults(params, defaults, opts) + body = do_generate(body, opts) - "import #{specifiers} from #{source};" + ["[", key, "]", "(", params, ")", wh_sep, body] end - def do_generate(%ESTree.ImportDeclaration{specifiers: specifiers, source: source}, _level) do - specifiers = Enum.map_join(specifiers, ", ", &generate(&1)) - source = generate(source) + def do_generate(%Property{key: key, value: %FunctionExpression{body: body}, kind: :get, shorthand: false, method: true, computed: false}, %{wh_sep: wh_sep} = opts) do + key = do_generate(key, opts) + body = do_generate(body, opts) - "import { #{specifiers} } from #{source};" + [key, "()", wh_sep, body] end + def do_generate(%Property{key: key, value: %FunctionExpression{body: body}, kind: :get}, %{wh_sep: wh_sep} = opts) do + key = do_generate(key, opts) + body = do_generate(body, opts) - def do_generate(%ESTree.ImportSpecifier{local: local, imported: imported}, _level) do - local = generate(local) - imported = generate(imported) + ["get ", key, "()", wh_sep, body] + end - if local == imported do - "#{local}" - else - "#{imported} as #{local}" - end + def do_generate(%Property{key: key, value: %FunctionExpression{params: params, body: body}, kind: :set, shorthand: false, method: true, computed: false}, %{wh_sep: wh_sep} = opts) do + key = do_generate(key, opts) + params = do_generate(hd(params), opts) + body = do_generate(body, opts) + + [key, "(", params, ")", wh_sep, body] end - def do_generate(%ESTree.ImportDefaultSpecifier{local: local}, _level) do - generate(local) + def do_generate(%Property{key: key, value: %FunctionExpression{params: params, body: body}, kind: :set}, %{wh_sep: wh_sep} = opts) do + key = do_generate(key, opts) + params = do_generate(hd(params), opts) + body = do_generate(body, opts) + + ["set ", key, "(", params, ")", wh_sep, body] end - def do_generate(%ESTree.ImportNamespaceSpecifier{local: local}, _level) do - local = generate(local) + # RestElement - "* as #{local}" + def do_generate(%RestElement{argument: argument}, opts) do + ["...", do_generate(argument, opts)] end - def do_generate(%ESTree.ExportNamedDeclaration{declaration: %ESTree.FunctionDeclaration{} = declaration, specifiers: [], source: nil}, _level) do - declaration = generate(declaration) - "export #{declaration}" + # ReturnStatement + def do_generate(%ReturnStatement{argument: nil}, _opts) do + "return;" end - def do_generate(%ESTree.ExportNamedDeclaration{declaration: declaration, specifiers: [], source: nil}, _level) do - declaration = generate(declaration) - "export #{declaration};" + def do_generate(%ReturnStatement{argument: argument}, opts) do + ["return ", do_generate(argument, opts), ";"] end - def do_generate(%ESTree.ExportNamedDeclaration{declaration: nil, specifiers: specifiers, source: nil} = _ast, _level) do - specifiers = Enum.map_join(specifiers, ", ", &generate(&1)) + # SequenceExpression - "export { #{specifiers} };" + def do_generate(%SequenceExpression{expressions: expressions}, opts) do + expressions = expressions + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(opts.comma_sep) + + ["(", expressions, ")"] end - def do_generate(%ESTree.ExportNamedDeclaration{declaration: nil, specifiers: specifiers, source: source}, _level) do - specifiers = Enum.map_join(specifiers, ", ", &generate(&1)) - source = generate(source) + # SpreadElement - "export { #{specifiers} } from #{source};" + def do_generate(%SpreadElement{argument: argument}, opts) do + ["...", do_generate(argument, opts)] end - def do_generate(%ESTree.ExportSpecifier{local: local, exported: exported}, _level) do - local = generate(local) - exported = generate(exported) + # Super - if local == exported do - "#{local}" + def do_generate(%Super{}, _opts) do + "super" + end + + # SwitchCase + + def do_generate(%SwitchCase{test: nil, consequent: consequent}, opts) do + start_sep = if opts.beauty do + indent(opts, 1) else - "#{exported} as #{local}" + "" + end + + sep = if opts.beauty do + ["\n", indent(opts)] + else + "" end + + consequent = consequent + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(sep) + + [start_sep, "default:", sep, consequent] end - def do_generate(%ESTree.ExportDefaultDeclaration{declaration: declaration}, _level) do - declaration = generate(declaration) + def do_generate(%SwitchCase{test: test, consequent: consequent}, opts) do + start_sep = if opts.beauty do + indent(opts, 1) + else + "" + end + + sep = if opts.beauty do + ["\n", indent(opts)] + else + "" + end + + test = do_generate(test, opts) - "export default #{declaration};" + consequent = consequent + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(sep) + + [start_sep, "case ", test, ":", sep, consequent] end - def do_generate(%ESTree.ExportAllDeclaration{source: source}, _level) do - source = generate(source) - "export * from #{source};" + # SwitchStatement + + def do_generate(%SwitchStatement{discriminant: discriminant, cases: cases}, %{wh_sep: wh_sep} = opts) do + open_bracket = if opts.beauty do + "{\n" + else + "{" + end + + close_bracket = if opts.beauty do + ["\n", indent(opts), "}"] + else + "}" + end + + sep = if opts.beauty do + "\n\n" + else + "" + end + + opts = next_indent(opts) + + cases = cases + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(sep) + + discriminant = do_generate(discriminant, opts) + + ["switch", wh_sep, "(", discriminant, ")", wh_sep, open_bracket, cases, close_bracket] end - def do_generate(%ESTree.TaggedTemplateExpression{tag: tag, quasi: quasi}, _level) do - tag = generate(tag) - quasi = generate(quasi) + # TaggedTemplateExpression - "#{tag} #{quasi}" + def do_generate(%TaggedTemplateExpression{tag: tag, quasi: quasi}, opts) do + [do_generate(tag, opts), " ", do_generate(quasi, opts)] end - def do_generate(%ESTree.TemplateLiteral{expressions: [], quasis: []}, _level) do + # TemplateLiteral + + def do_generate(%TemplateLiteral{expressions: [], quasis: []}, _opts) do "``" end - def do_generate(%ESTree.TemplateLiteral{expressions: [expression], quasis: []}, _level) do - expression = generate(expression) - "`${#{expression}}`" + def do_generate(%TemplateLiteral{expressions: [expression], quasis: []}, opts) do + ["`${", do_generate(expression, opts), "}`"] end - def do_generate(%ESTree.TemplateLiteral{expressions: [], quasis: [quasi]}, _level) do - quasi = convert_string_characters(quasi.value.raw) - "`#{quasi}`" + def do_generate(%TemplateLiteral{expressions: [], quasis: [quasi]}, _opts) do + ["`", escape_string(quasi.value.raw, false), "`"] end - def do_generate(%ESTree.TemplateLiteral{expressions: expressions, quasis: quasis}, _level) do + def do_generate(%TemplateLiteral{expressions: expressions, quasis: quasis}, opts) do elements = expressions ++ quasis - literal = Enum.sort(elements, fn(one, two) -> + literal = elements + |> Enum.sort(fn (one, two) -> one.loc.start.column < two.loc.start.column end) - |> Enum.reduce("", fn(el, str) -> + |> Enum.reduce("", fn (el, str) -> case el do - %ESTree.TemplateElement{} -> - str <> convert_string_characters(el.value.raw) + %TemplateElement{} -> + [str, escape_string(el.value.raw, false)] + _ -> - str <> "${#{generate(el)}}" + [str, "${", do_generate(el, opts), "}"] end end) + ["`", literal, "`"] + end + + # ThisExpression - "`#{literal}`" + def do_generate(%ThisExpression{}, _opts) do + "this" end - def do_generate(%ESTree.AwaitExpression{ argument: argument, all: _all }, _level) do - "await #{generate(argument)}" + # ThrowStatement + + def do_generate(%ThrowStatement{argument: argument}, opts) do + ["throw ", do_generate(argument, opts), ";"] end - def do_generate(%ESTree.JSXIdentifier{ name: name }, _level) do - "#{name}" + # TryStatement + + def do_generate(%TryStatement{block: block, handler: handler, finalizer: nil}, %{wh_sep: wh_sep} = opts) do + block = do_generate(block, opts) + handler = do_generate(handler, opts) + + ["try", wh_sep, block, wh_sep, handler] end - def do_generate(%ESTree.JSXMemberExpression{ object: object, property: property }, _level) do - "#{ generate(object) }.#{ generate(property) }" + def do_generate(%TryStatement{block: block, handler: nil, finalizer: finalizer}, %{wh_sep: wh_sep} = opts) do + block = do_generate(block, opts) + finalizer = do_generate(finalizer, opts) + + ["try", wh_sep, block, wh_sep, "finally", wh_sep, finalizer] end - def do_generate(%ESTree.JSXNamespacedName{ namespace: namespace, name: name }, _level) do - "#{ generate(namespace) }:#{ generate(name) }" + def do_generate(%TryStatement{block: block, handler: handler, finalizer: finalizer}, %{wh_sep: wh_sep} = opts) do + block = do_generate(block, opts) + handler = do_generate(handler, opts) + finalizer = do_generate(finalizer, opts) + + ["try", wh_sep, block, wh_sep, handler, wh_sep, "finally", wh_sep, finalizer] end - def do_generate(%ESTree.JSXEmptyExpression{}, _level) do - "" + # UnaryExpression + + def do_generate(%UnaryExpression{operator: operator, prefix: true, argument: argument}, opts) do + precedence = Map.get(@expressions_precedence, argument.__struct__) + + sep = if operator in [:delete, :typeof, :void], do: " ", else: "" + operator = do_generate(operator, opts) + argument = do_generate(argument, opts) + + if precedence < @expressions_precedence[UnaryExpression] do + [operator, sep, "(", argument, ")"] + else + [operator, sep, argument] + end end - def do_generate(%ESTree.JSXExpressionContainer{ expression: expression }, _level) do - "{#{ generate(expression) }}" + def do_generate(%UnaryExpression{operator: operator, prefix: false, argument: argument}, opts) do + [do_generate(argument, opts), do_generate(operator, opts)] end - def do_generate(%ESTree.JSXOpeningElement{ name: name, attributes: attributes, selfClosing: selfClosing }, _level) do - selfClosing = if selfClosing, do: "/", else: "" - attributesValue = cond do - Enum.empty?(attributes) -> "" - true -> - " #{Enum.map(attributes, &generate(&1)) |> Enum.join(" ")}" + # UpdateExpression + + def do_generate(%UpdateExpression{operator: operator, prefix: true, argument: argument}, opts) do + [do_generate(operator, opts), do_generate(argument, opts)] + end + + def do_generate(%UpdateExpression{operator: operator, prefix: false, argument: argument}, opts) do + [do_generate(argument, opts), do_generate(operator, opts)] + end + + # VariableDeclaration + + def do_generate(%VariableDeclaration{kind: kind, declarations: declarations}, opts) when kind in [:var, :let, :const] do + i = indent(next_indent(opts)) + sep = if opts.beauty do + if kind == :const do + [",\n", i, " "] + else + [",\n", i] + end + else + opts.comma_sep end - "<#{generate(name)}#{attributesValue}#{selfClosing}>" + + declarators = declarations + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(sep) + + semicolon = if opts.no_trailing_semicolon do + "" + else + ";" + end + + [to_string(kind), " ", declarators, semicolon] + end + + # VariableDeclarator + + def do_generate(%VariableDeclarator{id: id, init: nil}, opts) do + do_generate(id, opts) end - def do_generate(%ESTree.JSXClosingElement{ name: name }, _level) do - "" + def do_generate(%VariableDeclarator{id: id, init: %FunctionDeclaration{} = init}, %{wh_sep: wh_sep} = opts) do + opts = %{next_indent(opts) | no_trailing_semicolon: true} + + [do_generate(id, opts), wh_sep, "=", wh_sep, do_generate(init, opts)] end - def do_generate(%ESTree.JSXAttribute{ name: name, value: value }, _level) do - "#{ generate(name) }=#{ generate(value) }" + def do_generate(%VariableDeclarator{id: id, init: %FunctionExpression{} = init}, %{wh_sep: wh_sep} = opts) do + opts = %{next_indent(opts) | no_trailing_semicolon: true} + + [do_generate(id, opts), wh_sep, "=", wh_sep, do_generate(init, opts)] end - def do_generate(%ESTree.JSXSpreadAttribute{ argument: argument }, _level) do - "{...#{ generate(argument) }}" + def do_generate(%VariableDeclarator{id: id, init: init}, %{wh_sep: wh_sep} = opts) do + [do_generate(id, opts), wh_sep, "=", wh_sep, do_generate(init, opts)] end - def do_generate(%ESTree.JSXElement{ openingElement: openingElement, children: children, closingElement: closingElement }, level) do - "#{ generate(openingElement) }#{ generate_jsx_children(children, calculate_next_level(level)) }#{ generate(closingElement) }" + # WhileStatement + + def do_generate(%WhileStatement{test: test, body: body}, %{wh_sep: wh_sep} = opts) do + test = do_generate(test, opts) + body = do_generate(body, opts) + + ["while", wh_sep, "(", test, ")", wh_sep, body] end - defp generate_jsx_children(children, level) do - gen_fn = fn - %ESTree.Literal{value: value} when is_binary(value) -> - convert_jsx_text(value) - other -> - generate(other, level) - end + # WithStatement + + def do_generate(%WithStatement{object: object, body: body}, %{wh_sep: wh_sep} = opts) do + object = do_generate(object, opts) + body = do_generate(body, opts) - children |> Enum.map(gen_fn) |> Enum.join + ["with", wh_sep, "(", object, ")", wh_sep, body] end - defp convert_jsx_text(str) do - str - |> String.replace("{", "{") - |> String.replace("}", "}") - |> String.replace("<", "<") - |> String.replace(">", ">") + # YieldExpression + + def do_generate(%YieldExpression{argument: argument, delegate: false}, opts) do + ["yield ", do_generate(argument, opts)] end - defp convert_string_characters(str) do - String.replace(str, "\n", "\\n") - |> String.replace("\t", "\\t") + def do_generate(%YieldExpression{argument: argument, delegate: true}, %{wh_sep: wh_sep} = opts) do + ["yield*", wh_sep, do_generate(argument, opts)] + end + + # Helpers + + defp escape_string(string, escape_quotes \\ true) do + string = string + |> String.replace("\\", "\\\\") + |> String.replace("\n", "\\n") + |> String.replace("\r", "\\r") + |> String.replace("\t", "\\t") + |> String.replace("\b", "\\b") + |> String.replace("\f", "\\f") + |> String.replace("\v", "\\v") + |> String.replace("\u2028", "\\u2028") + |> String.replace("\u2029", "\\u2029") + |> String.replace("\ufeff", "\\ufeff") + + if escape_quotes do + string + |> String.replace("\x27", "\\'") + else + string + end end - defp params_and_defaults(params, []) do - Enum.map_join(params, ",", &generate(&1)) + defp params_and_defaults(params, [], opts) do + params + |> Enum.map(&do_generate(&1, opts)) + |> Enum.intersperse(opts.comma_sep) end - defp params_and_defaults(params, defaults) do - Enum.zip(params, defaults) - |> Enum.map_join(",", fn - {p, nil} -> "#{generate(p)}" - {p, d} -> "#{generate(p)} = #{generate(d)}" + defp params_and_defaults(params, defaults, %{wh_sep: wh_sep} = opts) do + params + |> Enum.zip(defaults) + |> Enum.map(fn + {p, nil} -> do_generate(p, opts) + {p, d} -> [do_generate(p, opts), wh_sep, "=", wh_sep, do_generate(d, opts)] end) + |> Enum.intersperse(opts.comma_sep) end - defp indent(nil) do - "" + defp format_binary_expression(node, node_parent, is_right_hand, opts) do + if parenthesis(node, node_parent, is_right_hand) do + ["(", do_generate(node, opts), ")"] + else + do_generate(node, opts) + end end - defp indent(level) do - String.duplicate(" ", level) + defp parenthesis(node, parent_node, is_right_hand) do + node_p = @expressions_precedence[node.__struct__] + parent_node_p = @expressions_precedence[parent_node.__struct__] + + cond do + node_p != parent_node_p -> + node_p < parent_node_p + + node_p != 13 and node_p != 14 -> + false + + node.operator == :'**' and parent_node.operator == :'**' -> + not is_right_hand + + is_right_hand -> + @operator_precedence[node.operator] <= @operator_precedence[parent_node.operator] + + true -> + @operator_precedence[node.operator] < @operator_precedence[parent_node.operator] + end end - defp calculate_next_level(nil) do - nil + defp generate_jsx_children(children, opts) do + children + |> Enum.map(fn + %Literal{value: value} when is_binary(value) -> + convert_jsx_text(value) + + other -> + do_generate(other, opts) + end) end - defp calculate_next_level(level) do - level + 1 + defp convert_jsx_text(string) do + string + |> String.replace("{", "{") + |> String.replace("}", "}") + |> String.replace("<", "<") + |> String.replace(">", ">") end - defp calculate_previous_level(nil) do - nil + defp indent(opts, back \\ 0) do + String.duplicate(" ", opts.indent_start + opts.indent - back * opts.indent_level) end - defp calculate_previous_level(level) do - level - 1 + defp next_indent(opts) do + %{opts | indent: opts.indent + opts.indent_level} end - defp newline(nil) do - "" + defp has_call_expression(node) when not is_map(node) do + false end - defp newline(_level) do - "\n" + defp has_call_expression(node) do + case node do + %CallExpression{} -> + true + + %MemberExpression{} -> + has_call_expression(node.object) + + _ -> + false + end end end diff --git a/test/support.ex b/test/support.ex new file mode 100644 index 0000000..ca40c54 --- /dev/null +++ b/test/support.ex @@ -0,0 +1,14 @@ +defmodule ESTree.Test.Support do + use ShouldI + + alias ESTree.Tools.Generator + + defmacro assert_gen(ast, str, opts \\ []) do + opts = Keyword.merge([beauty: true], opts) + beauty = Keyword.get(opts, :beauty) + + quote do + assert Generator.generate(unquote(ast), unquote(beauty)) == unquote(str) + end + end +end diff --git a/test/test_helper.exs b/test/test_helper.exs index 948e26c..dbfba27 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1 +1,3 @@ ExUnit.start(formatters: [ShouldI.CLIFormatter]) + +Code.require_file "support.ex", __DIR__ diff --git a/test/tools/generator/array_expression_test.exs b/test/tools/generator/array_expression_test.exs index 936d1aa..2e2a4c2 100644 --- a/test/tools/generator/array_expression_test.exs +++ b/test/tools/generator/array_expression_test.exs @@ -1,31 +1,31 @@ defmodule ESTree.Tools.Generator.ArrayExpression.Test do use ShouldI + alias ESTree.Tools.Builder - alias ESTree.Tools.Generator + import ESTree.Test.Support should "convert array when elements is nil" do - ast = Builder.array_expression(nil) - assert Generator.generate(ast) == "[]" + assert_gen Builder.array_expression(nil), "[]" end should "convert array when elements is empty" do - ast = Builder.array_expression([]) - assert Generator.generate(ast) == "[]" + assert_gen Builder.array_expression([]), "[]" end should "convert array when elements contains one element" do - ast = Builder.array_expression([ + assert_gen Builder.array_expression([ Builder.literal(1) - ]) - assert Generator.generate(ast) == "[1]" + ]), "[1]" end should "convert array when elements contains multiple elements" do ast = Builder.array_expression([ Builder.literal(1), - Builder.identifier(:a) + Builder.identifier(:a), + Builder.spread_element(Builder.identifier(:b)) ]) - assert Generator.generate(ast) == "[1, a]" - end + assert_gen ast, "[1, a, ...b]" + assert_gen ast, "[1,a,...b]", beauty: false + end end diff --git a/test/tools/generator/array_pattern_test.exs b/test/tools/generator/array_pattern_test.exs new file mode 100644 index 0000000..a360aa1 --- /dev/null +++ b/test/tools/generator/array_pattern_test.exs @@ -0,0 +1,31 @@ +defmodule ESTree.Tools.Generator.ArrayPattern.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert array pattern when elements is nil" do + assert_gen Builder.array_pattern(nil), "[]" + end + + should "convert array pattern when elements is empty" do + assert_gen Builder.array_pattern([]), "[]" + end + + should "convert array pattern when elements contains one element" do + assert_gen Builder.array_pattern([ + Builder.identifier(:a) + ]), "[a]" + end + + should "convert array pattern when elements contains multiple elements" do + ast = Builder.array_pattern([ + Builder.identifier(:a), + Builder.identifier(:b), + Builder.spread_element(Builder.identifier(:c)) + ]) + + assert_gen ast, "[a, b, ...c]" + assert_gen ast, "[a,b,...c]", beauty: false + end +end diff --git a/test/tools/generator/arrow_function_expression_test.exs b/test/tools/generator/arrow_function_expression_test.exs new file mode 100644 index 0000000..ca71323 --- /dev/null +++ b/test/tools/generator/arrow_function_expression_test.exs @@ -0,0 +1,82 @@ +defmodule ESTree.Tools.Generator.ArrowFunctionExpression.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert basic arrow function" do + ast = Builder.arrow_function_expression( + [], + [], + Builder.block_statement([]), + false, + false + ) + + assert_gen ast, "() => {}" + assert_gen ast, "()=>{}", beauty: false + end + + should "convert basic arrow function returns object" do + ast = Builder.arrow_function_expression( + [], + [], + Builder.object_expression([]), + false, + false + ) + + assert_gen ast, "() => ({})" + assert_gen ast, "()=>({})", beauty: false + end + + should "convert basic arrow function expression generator" do + ast = Builder.arrow_function_expression( + [], + [], + Builder.block_statement([]), + true, + false + ) + + assert_gen ast, "()* => {}" + assert_gen ast, "()*=>{}", beauty: false + end + + should "convert arrow function with params" do + ast = Builder.arrow_function_expression( + [Builder.identifier(:one)], + [], + Builder.block_statement([]), + false, + false + ) + + assert_gen ast, "(one) => {}" + assert_gen ast, "one=>{}", beauty: false + + ast = Builder.arrow_function_expression( + [Builder.identifier(:one), Builder.identifier(:two)], + [], + Builder.block_statement([]), + false, + false + ) + + assert_gen ast, "(one, two) => {}" + assert_gen ast, "(one,two)=>{}", beauty: false + end + + should "convert arrow function with default values" do + ast = Builder.arrow_function_expression( + [Builder.identifier(:one), Builder.identifier(:two)], + [nil, Builder.literal(1)], + Builder.block_statement([]), + false, + false + ) + + assert_gen ast, "(one, two = 1) => {}" + assert_gen ast, "(one,two=1)=>{}", beauty: false + end +end diff --git a/test/tools/generator/assignment_test.exs b/test/tools/generator/assignment_test.exs new file mode 100644 index 0000000..c4e101e --- /dev/null +++ b/test/tools/generator/assignment_test.exs @@ -0,0 +1,17 @@ +defmodule ESTree.Tools.Generator.Assignment.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert assignment expression" do + ast = Builder.assignment_expression( + :=, + Builder.identifier(:a), + Builder.literal(0) + ) + + assert_gen ast, "a = 0" + assert_gen ast, "a=0", beauty: false + end +end diff --git a/test/tools/generator/binary_expression_test.exs b/test/tools/generator/binary_expression_test.exs new file mode 100644 index 0000000..a69a1a7 --- /dev/null +++ b/test/tools/generator/binary_expression_test.exs @@ -0,0 +1,115 @@ +defmodule ESTree.Generator.BinaryExpression.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert binary expression with correct precedence" do + ast = Builder.binary_expression( + :+, + Builder.literal(1), + Builder.binary_expression( + :/, + Builder.binary_expression( + :*, + Builder.literal(2), + Builder.literal(3) + ), + Builder.literal(4) + ) + ) + + assert_gen ast, "1 + 2 * 3 / 4" + assert_gen ast, "1+2*3/4", beauty: false + + ast = Builder.binary_expression( + :+, + Builder.literal(1), + Builder.binary_expression( + :*, + Builder.literal(2), + Builder.binary_expression( + :/, + Builder.literal(3), + Builder.literal(4) + ) + ) + ) + + assert_gen ast, "1 + 2 * (3 / 4)" + assert_gen ast, "1+2*(3/4)", beauty: false + + ast = Builder.binary_expression( + :/, + Builder.binary_expression( + :*, + Builder.binary_expression( + :+, + Builder.literal(1), + Builder.literal(2) + ), + Builder.literal(3) + ), + Builder.literal(4) + ) + + assert_gen ast, "(1 + 2) * 3 / 4" + assert_gen ast, "(1+2)*3/4", beauty: false + + ast = Builder.binary_expression( + :*, + Builder.binary_expression( + :+, + Builder.literal(1), + Builder.literal(2) + ), + Builder.binary_expression( + :/, + Builder.literal(3), + Builder.literal(4) + ) + ) + + assert_gen ast, "(1 + 2) * (3 / 4)" + assert_gen ast, "(1+2)*(3/4)", beauty: false + end + + should "convert binary expression in" do + ast = Builder.binary_expression( + :in, + Builder.identifier(:a), + Builder.identifier(:b) + ) + + assert_gen ast, "(a in b)" + assert_gen ast, "(a in b)", beauty: false + end + + should "convert binary expression instanceof" do + ast = Builder.binary_expression( + :instanceof, + Builder.unary_expression( + :!, + true, + Builder.identifier(:x) + ), + Builder.identifier(:Number) + ) + + assert_gen ast, "!x instanceof Number" + assert_gen ast, "!x instanceof Number", beauty: false + + ast = Builder.unary_expression( + :!, + true, + Builder.binary_expression( + :instanceof, + Builder.identifier(:x), + Builder.identifier(:Number) + ) + ) + + assert_gen ast, "!(x instanceof Number)" + assert_gen ast, "!(x instanceof Number)", beauty: false + end +end diff --git a/test/tools/generator/block_statement_test.exs b/test/tools/generator/block_statement_test.exs new file mode 100644 index 0000000..a731c77 --- /dev/null +++ b/test/tools/generator/block_statement_test.exs @@ -0,0 +1,41 @@ +defmodule ESTree.Tools.Generator.BlockStatement.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert basic function declaration" do + ast = Builder.function_declaration( + Builder.identifier(:hello), + [], + [], + Builder.block_statement([ + Builder.variable_declaration([ + Builder.variable_declarator(Builder.identifier(:a), Builder.literal(1)), + Builder.variable_declarator(Builder.identifier(:b)), + Builder.variable_declarator( + Builder.identifier(:c), + Builder.binary_expression( + :+, + Builder.identifier(:a), + Builder.literal(2) + ) + ) + ]), + ]), + false, + false + ) + + str = """ +function hello() { + var a = 1, + b, + c = a + 2; +} +""" + + assert_gen ast, String.trim(str) + assert_gen ast, "function hello(){var a=1,b,c=a+2;}", beauty: false + end +end diff --git a/test/tools/generator/call_expression_test.exs b/test/tools/generator/call_expression_test.exs new file mode 100644 index 0000000..57add86 --- /dev/null +++ b/test/tools/generator/call_expression_test.exs @@ -0,0 +1,94 @@ +defmodule ESTree.Tools.Generator.CallExpression.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert call expression when arguments is empty" do + ast = Builder.call_expression(Builder.identifier(:x), []); + + assert_gen ast, "x()" + assert_gen ast, "x()", beauty: false + end + + should "convert call expression with one argument" do + ast = Builder.call_expression( + Builder.identifier(:x), + [ + Builder.identifier(:a) + ] + ); + + assert_gen ast, "x(a)" + assert_gen ast, "x(a)", beauty: false + end + + should "convert call expression with spread" do + ast = Builder.call_expression( + Builder.identifier(:x), + [ + Builder.spread_element(Builder.identifier(:a)) + ] + ); + + assert_gen ast, "x(...a)" + assert_gen ast, "x(...a)", beauty: false + end + + should "convert call expression with arguments" do + ast = Builder.call_expression( + Builder.identifier(:x), + [ + Builder.identifier(:a), + Builder.identifier(:b) + ] + ); + + assert_gen ast, "x(a, b)" + assert_gen ast, "x(a,b)", beauty: false + end + + should "convert call expression with arguments and spread" do + ast = Builder.call_expression( + Builder.identifier(:x), + [ + Builder.identifier(:a), + Builder.identifier(:b), + Builder.spread_element(Builder.identifier(:c)) + ] + ); + + assert_gen ast, "x(a, b, ...c)" + assert_gen ast, "x(a,b,...c)", beauty: false + end + + should "convert call expression when callee is member expression" do + ast = Builder.call_expression( + Builder.member_expression( + Builder.identifier(:x), + Builder.identifier(:y) + ), + [] + ); + + assert_gen ast, "x.y()" + assert_gen ast, "x.y()", beauty: false + end + + should "convert call expression when callee is binary expression" do + ast = Builder.call_expression( + Builder.member_expression( + Builder.binary_expression( + :+, + Builder.identifier(:a), + Builder.identifier(:b) + ), + Builder.identifier(:x) + ), + [] + ); + + assert_gen ast, "(a + b).x()" + assert_gen ast, "(a+b).x()", beauty: false + end +end diff --git a/test/tools/generator/class_body_test.exs b/test/tools/generator/class_body_test.exs new file mode 100644 index 0000000..ab98bde --- /dev/null +++ b/test/tools/generator/class_body_test.exs @@ -0,0 +1,211 @@ +defmodule ESTree.Tools.Generator.ClassBody.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert class body with method definition constructor" do + ast = Builder.class_body([ + Builder.method_definition( + nil, + Builder.function_expression( + [], + [], + Builder.block_statement([ + Builder.expression_statement( + Builder.call_expression( + Builder.super(), + [] + ) + ) + ]) + ), + :constructor + ) + ]) + + assert_gen ast, "{\n constructor() {\n super();\n }\n}" + assert_gen ast, "{constructor(){super();}}", beauty: false + end + + should "convert class body with method definition" do + ast = Builder.class_body([ + Builder.method_definition( + Builder.identifier(:method), + Builder.function_expression( + [], + [], + Builder.block_statement([]) + ) + ) + ]) + + assert_gen ast, "{\n method() {}\n}" + assert_gen ast, "{method(){}}", beauty: false + end + + should "convert class body with method definition getter" do + ast = Builder.class_body([ + Builder.method_definition( + Builder.identifier(:property), + Builder.function_expression( + [], + [], + Builder.block_statement([]) + ), + :get + ) + ]) + + assert_gen ast, "{\n get property() {}\n}" + assert_gen ast, "{get property(){}}", beauty: false + end + + should "convert class body with method definition setter" do + ast = Builder.class_body([ + Builder.method_definition( + Builder.identifier(:property), + Builder.function_expression( + [Builder.identifier(:value)], + [], + Builder.block_statement([]) + ), + :set + ) + ]) + + assert_gen ast, "{\n set property(value) {}\n}" + assert_gen ast, "{set property(value){}}", beauty: false + end + + should "convert class body with method definition computed" do + ast = Builder.class_body([ + Builder.method_definition( + Builder.member_expression(Builder.identifier(:Symbol), Builder.identifier(:iterator)), + Builder.function_expression( + [], + [], + Builder.block_statement([]) + ), + :method, + true + ) + ]) + + assert_gen ast, "{\n [Symbol.iterator]() {}\n}" + assert_gen ast, "{[Symbol.iterator](){}}", beauty: false + end + + should "convert class body with method definition computed literal" do + ast = Builder.class_body([ + Builder.method_definition( + Builder.literal(:method), + Builder.function_expression( + [], + [], + Builder.block_statement([]) + ), + :method, + true + ) + ]) + + assert_gen ast, "{\n ['method']() {}\n}" + assert_gen ast, "{['method'](){}}", beauty: false + end + + should "convert class body with method definition static" do + ast = Builder.class_body([ + Builder.method_definition( + Builder.identifier("classMethod"), + Builder.function_expression( + [], + [], + Builder.block_statement([]) + ), + :method, + false, + true + ) + ]) + + assert_gen ast, "{\n static classMethod() {}\n}" + assert_gen ast, "{static classMethod(){}}", beauty: false + end + + should "convert class body with method definition static getter" do + ast = Builder.class_body([ + Builder.method_definition( + Builder.identifier(:property), + Builder.function_expression( + [], + [], + Builder.block_statement([]) + ), + :get, + false, + true + ) + ]) + + assert_gen ast, "{\n static get property() {}\n}" + assert_gen ast, "{static get property(){}}", beauty: false + end + + should "convert class body with method definition static setter" do + ast = Builder.class_body([ + Builder.method_definition( + Builder.identifier(:property), + Builder.function_expression( + [Builder.identifier(:value)], + [], + Builder.block_statement([]) + ), + :set, + false, + true + ) + ]) + + assert_gen ast, "{\n static set property(value) {}\n}" + assert_gen ast, "{static set property(value){}}", beauty: false + end + + should "convert class body with method definition static computed" do + ast = Builder.class_body([ + Builder.method_definition( + Builder.member_expression(Builder.identifier(:Symbol), Builder.identifier(:iterator)), + Builder.function_expression( + [], + [], + Builder.block_statement([]) + ), + :method, + true, + true + ) + ]) + + assert_gen ast, "{\n static [Symbol.iterator]() {}\n}" + assert_gen ast, "{static [Symbol.iterator](){}}", beauty: false + end + + should "convert class body with method definition static computed literal" do + ast = Builder.class_body([ + Builder.method_definition( + Builder.literal(:method), + Builder.function_expression( + [], + [], + Builder.block_statement([]) + ), + :method, + true, + true + ) + ]) + + assert_gen ast, "{\n static ['method']() {}\n}" + assert_gen ast, "{static ['method'](){}}", beauty: false + end +end diff --git a/test/tools/generator/class_declaration_test.exs b/test/tools/generator/class_declaration_test.exs new file mode 100644 index 0000000..54f0b08 --- /dev/null +++ b/test/tools/generator/class_declaration_test.exs @@ -0,0 +1,54 @@ +defmodule ESTree.Tools.Generator.ClassDeclaration.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert class declaration" do + ast = Builder.class_declaration( + Builder.identifier(:X), + Builder.class_body([]) + ) + + assert_gen ast, "class X {}" + assert_gen ast, "class X{}", beauty: false + end + + should "convert class declaration when it extends identifier" do + ast = Builder.class_declaration( + Builder.identifier(:X), + Builder.class_body([]), + Builder.identifier(:Y) + ) + + assert_gen ast, "class X extends Y {}" + assert_gen ast, "class X extends Y{}", beauty: false + end + + should "convert class declaration when it extends class declaration" do + ast = Builder.class_declaration( + Builder.identifier(:X), + Builder.class_body([]), + Builder.class_declaration( + Builder.identifier(:Y), + Builder.class_body([]) + ) + ) + + assert_gen ast, "class X extends class Y {} {}" + assert_gen ast, "class X extends class Y{}{}", beauty: false + end + + should "convert class declaration when it extends class expression" do + ast = Builder.class_declaration( + Builder.identifier(:X), + Builder.class_body([]), + Builder.class_expression( + Builder.class_body([]) + ) + ) + + assert_gen ast, "class X extends class {} {}" + assert_gen ast, "class X extends class{}{}", beauty: false + end +end diff --git a/test/tools/generator/class_expression_test.exs b/test/tools/generator/class_expression_test.exs new file mode 100644 index 0000000..a0c5e37 --- /dev/null +++ b/test/tools/generator/class_expression_test.exs @@ -0,0 +1,50 @@ +defmodule ESTree.Tools.Generator.ClassExpression.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert class expression" do + ast = Builder.class_expression( + Builder.class_body([]) + ) + + assert_gen ast, "class {}" + assert_gen ast, "class{}", beauty: false + end + + should "convert class expression when it extends identifier" do + ast = Builder.class_expression( + Builder.class_body([]), + Builder.identifier(:Y) + ) + + assert_gen ast, "class extends Y {}" + assert_gen ast, "class extends Y{}", beauty: false + end + + should "convert class expression when it extends class declaration" do + ast = Builder.class_expression( + Builder.class_body([]), + Builder.class_declaration( + Builder.identifier(:Y), + Builder.class_body([]) + ) + ) + + assert_gen ast, "class extends class Y {} {}" + assert_gen ast, "class extends class Y{}{}", beauty: false + end + + should "convert class expression when it extends class expression" do + ast = Builder.class_expression( + Builder.class_body([]), + Builder.class_expression( + Builder.class_body([]) + ) + ) + + assert_gen ast, "class extends class {} {}" + assert_gen ast, "class extends class{}{}", beauty: false + end +end diff --git a/test/tools/generator/conditional_statement_test.exs b/test/tools/generator/conditional_statement_test.exs new file mode 100644 index 0000000..f65e670 --- /dev/null +++ b/test/tools/generator/conditional_statement_test.exs @@ -0,0 +1,32 @@ +defmodule ESTree.Tools.Generator.ConditionalStatement.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert conditional statement" do + ast = Builder.conditional_statement( + Builder.identifier(:test), + Builder.identifier(:alternate), + Builder.identifier(:consequent) + ) + + assert_gen ast, "test ? consequent : alternate" + assert_gen ast, "test?consequent:alternate", beauty: false + end + + should "convert conditional statement precedence" do + ast = Builder.conditional_statement( + Builder.assignment_expression( + :=, + Builder.identifier(:test), + Builder.literal(1) + ), + Builder.identifier(:alternate), + Builder.identifier(:consequent) + ) + + assert_gen ast, "(test = 1) ? consequent : alternate" + assert_gen ast, "(test=1)?consequent:alternate", beauty: false + end +end diff --git a/test/tools/generator/export_declaration_test.exs b/test/tools/generator/export_declaration_test.exs index 5fe07cf..f004a43 100644 --- a/test/tools/generator/export_declaration_test.exs +++ b/test/tools/generator/export_declaration_test.exs @@ -1,61 +1,13 @@ defmodule ESTree.Tools.Generator.ExportDeclaration.Test do use ShouldI - alias ESTree.Tools.Builder - alias ESTree.Tools.Generator - - should "convert export named declaration with a declaration" do - ast = Builder.export_named_declaration( - Builder.identifier(:test) - ) - - assert Generator.generate(ast) == "export test;" - end - - should "convert export named declaration with one specifier" do - ast = Builder.export_named_declaration(nil, [ - Builder.export_specifier( - Builder.identifier(:test), - Builder.identifier(:test) - )] - ) - - assert Generator.generate(ast) == "export { test };" - end - - should "convert export named declaration with one specifier with an alias" do - ast = Builder.export_named_declaration(nil, [ - Builder.export_specifier( - Builder.identifier(:test), - Builder.identifier(:test1) - )] - ) - - assert Generator.generate(ast) == "export { test as test1 };" - end - - should "convert export declaration with more than one specifier" do - ast = Builder.export_named_declaration(nil, - [ - Builder.export_specifier( - Builder.identifier(:top), - Builder.identifier(:top) - ), - Builder.export_specifier( - Builder.identifier(:test), - Builder.identifier(:test1) - ) - ], - Builder.literal(:test) - ) - - assert Generator.generate(ast) == "export { top, test as test1 } from 'test';" - end + alias ESTree.Tools.Builder + import ESTree.Test.Support should "convert export all declaration" do ast = Builder.export_all_declaration(Builder.literal(:test)) - assert Generator.generate(ast) == "export * from 'test';" + assert_gen ast, "export * from 'test';" + assert_gen ast, "export*from'test';", beauty: false end - -end \ No newline at end of file +end diff --git a/test/tools/generator/export_default_declaration_test.exs b/test/tools/generator/export_default_declaration_test.exs new file mode 100644 index 0000000..540aa0c --- /dev/null +++ b/test/tools/generator/export_default_declaration_test.exs @@ -0,0 +1,132 @@ +defmodule ESTree.Tools.Generator.ExportDefaultDeclaration.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert export default declaration with function declaration" do + ast = Builder.export_default_declaration( + Builder.function_declaration( + Builder.identifier(:x), + [], + [], + Builder.block_statement([]) + ) + ) + + assert_gen ast, "export default function x() {}" + assert_gen ast, "export default function x(){}", beauty: false + end + + should "convert export default declaration with function expression" do + ast = Builder.export_default_declaration( + Builder.function_expression( + [], + [], + Builder.block_statement([]) + ) + ) + + assert_gen ast, "export default function() {};" + assert_gen ast, "export default function(){};", beauty: false + end + + should "convert export default declaration with function declaration generator" do + ast = Builder.export_default_declaration( + Builder.function_declaration( + Builder.identifier(:x), + [], + [], + Builder.block_statement([]), + true + ) + ) + + assert_gen ast, "export default function* x() {}" + assert_gen ast, "export default function*x(){}", beauty: false + end + + should "convert export default declaration with function expression generator" do + ast = Builder.export_default_declaration( + Builder.function_expression( + [], + [], + Builder.block_statement([]), + true + ) + ) + + assert_gen ast, "export default function*() {};" + assert_gen ast, "export default function*(){};", beauty: false + end + + should "convert export default declaration with class declaration" do + ast = Builder.export_default_declaration( + Builder.class_declaration( + Builder.identifier(:y), + Builder.class_body([]) + ) + ) + + assert_gen ast, "export default class y {}" + assert_gen ast, "export default class y{}", beauty: false + end + + should "convert export default declaration with class declaration extends" do + ast = Builder.export_default_declaration( + Builder.class_declaration( + Builder.identifier(:y), + Builder.class_body([]), + Builder.identifier(:z) + ) + ) + + assert_gen ast, "export default class y extends z {}" + assert_gen ast, "export default class y extends z{}", beauty: false + end + + should "convert export default declaration with class expression" do + ast = Builder.export_default_declaration( + Builder.class_expression( + Builder.class_body([]) + ) + ) + + assert_gen ast, "export default class {};" + assert_gen ast, "export default class{};", beauty: false + end + + should "convert export default declaration with assignment expression" do + ast = Builder.export_default_declaration( + Builder.assignment_expression( + :=, + Builder.identifier(:x), + Builder.literal(0) + ) + ) + + assert_gen ast, "export default x = 0;" + assert_gen ast, "export default x=0;", beauty: false + end + + should "convert export default declaration with literal" do + ast = Builder.export_default_declaration( + Builder.literal(0) + ) + + assert_gen ast, "export default 0;" + assert_gen ast, "export default 0;", beauty: false + end + + should "convert export default declaration with sequence expression" do + ast = Builder.export_default_declaration( + Builder.sequence_expression([ + Builder.literal(0), + Builder.literal(1) + ]) + ) + + assert_gen ast, "export default (0, 1);" + assert_gen ast, "export default (0,1);", beauty: false + end +end diff --git a/test/tools/generator/export_named_declaration_test.exs b/test/tools/generator/export_named_declaration_test.exs new file mode 100644 index 0000000..b4e593d --- /dev/null +++ b/test/tools/generator/export_named_declaration_test.exs @@ -0,0 +1,141 @@ +defmodule ESTree.Tools.Generator.ExportNamedDeclaration.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert export named declaration with one specifier" do + ast = Builder.export_named_declaration(nil, [ + Builder.export_specifier( + Builder.identifier(:test), + Builder.identifier(:test) + )] + ) + + assert_gen ast, "export { test };" + assert_gen ast, "export{test};", beauty: false + end + + should "convert export named declaration with one specifier with an alias" do + ast = Builder.export_named_declaration(nil, [ + Builder.export_specifier( + Builder.identifier(:test), + Builder.identifier(:test1) + )] + ) + + assert_gen ast, "export { test as test1 };" + assert_gen ast, "export{test as test1};", beauty: false + end + + should "convert export named declaration with more than one specifier" do + ast = Builder.export_named_declaration(nil, + [ + Builder.export_specifier( + Builder.identifier(:top), + Builder.identifier(:top) + ), + Builder.export_specifier( + Builder.identifier(:test), + Builder.identifier(:test1) + ) + ], + Builder.literal(:test) + ) + + assert_gen ast, "export { top, test as test1 } from 'test';" + assert_gen ast, "export{top,test as test1}from'test';", beauty: false + end + + should "convert export named declaration with variable declaration" do + ast = Builder.export_named_declaration( + Builder.variable_declaration([ + Builder.variable_declarator(Builder.identifier(:a)), + Builder.variable_declarator(Builder.identifier(:b), Builder.literal(0)) + ]) + ) + + assert_gen ast, "export var a,\n b = 0;" + assert_gen ast, "export var a,b=0;", beauty: false + end + + should "convert export named declaration with let variable declaration" do + ast = Builder.export_named_declaration( + Builder.variable_declaration([ + Builder.variable_declarator(Builder.identifier(:a)), + Builder.variable_declarator(Builder.identifier(:b), Builder.literal(0)) + ], + :let) + ) + + assert_gen ast, "export let a,\n b = 0;" + assert_gen ast, "export let a,b=0;", beauty: false + end + + should "convert export named declaration with const variable declaration" do + ast = Builder.export_named_declaration( + Builder.variable_declaration([ + Builder.variable_declarator(Builder.identifier(:a)), + Builder.variable_declarator(Builder.identifier(:b), Builder.literal(0)) + ], + :const) + ) + + assert_gen ast, "export const a,\n b = 0;" + assert_gen ast, "export const a,b=0;", beauty: false + end + + should "convert export named declaration with function declaration" do + ast = Builder.export_named_declaration( + Builder.function_declaration( + Builder.identifier(:x), + [], + [], + Builder.block_statement([]) + ) + ) + + assert_gen ast, "export function x() {}" + assert_gen ast, "export function x(){}", beauty: false + end + + should "convert export named declaration with function declaration generator" do + ast = Builder.export_named_declaration( + Builder.function_declaration( + Builder.identifier(:x), + [], + [], + Builder.block_statement([]), + true + ) + ) + + assert_gen ast, "export function* x() {}" + assert_gen ast, "export function*x(){}", beauty: false + end + + should "convert export named declaration with class declaration" do + ast = Builder.export_named_declaration( + Builder.class_declaration( + Builder.identifier(:y), + Builder.class_body([]) + ) + ) + + assert_gen ast, "export class y {}" + assert_gen ast, "export class y{}", beauty: false + end + + should "convert export named declaration with class declaration extends" do + ast = Builder.export_named_declaration( + Builder.class_declaration( + Builder.identifier(:y), + Builder.class_body([]), + Builder.identifier(:z) + ) + ) + + assert_gen ast, "export class y extends z {}" + assert_gen ast, "export class y extends z{}", beauty: false + end +end diff --git a/test/tools/generator/expression_statement_test.exs b/test/tools/generator/expression_statement_test.exs new file mode 100644 index 0000000..8382f87 --- /dev/null +++ b/test/tools/generator/expression_statement_test.exs @@ -0,0 +1,54 @@ +defmodule ESTree.Tools.Generator.ExpressionStatement.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert expression statement with class expression" do + ast = Builder.expression_statement( + Builder.class_expression( + Builder.class_body([]) + ) + ) + + assert_gen ast, "(class {});" + assert_gen ast, "(class{});", beauty: false + end + + should "convert expression statement with function expression" do + ast = Builder.expression_statement( + Builder.function_expression( + [], + [], + Builder.block_statement([]) + ) + ) + + assert_gen ast, "(function() {});" + assert_gen ast, "(function(){});", beauty: false + end + + should "convert expression statement with object expression" do + ast = Builder.expression_statement( + Builder.object_expression( + [] + ) + ) + + assert_gen ast, "({});" + assert_gen ast, "({});", beauty: false + end + + should "convert expression statement with assignment expression" do + ast = Builder.expression_statement( + Builder.assignment_expression( + :=, + Builder.object_pattern([]), + Builder.identifier(:a) + ) + ) + + assert_gen ast, "({} = a);" + assert_gen ast, "({}=a);", beauty: false + end +end diff --git a/test/tools/generator/for_in_statement_test.exs b/test/tools/generator/for_in_statement_test.exs new file mode 100644 index 0000000..3d3ad5b --- /dev/null +++ b/test/tools/generator/for_in_statement_test.exs @@ -0,0 +1,19 @@ +defmodule ESTree.Tools.Generator.ForInStatement.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert for in statement" do + ast = Builder.for_in_statement( + Builder.variable_declaration([ + Builder.variable_declarator(Builder.identifier(:a)) + ]), + Builder.identifier(:b), + Builder.block_statement([]) + ) + + assert_gen ast, "for (var a in b) {}" + assert_gen ast, "for(var a in b){}", beauty: false + end +end diff --git a/test/tools/generator/for_of_statement_test.exs b/test/tools/generator/for_of_statement_test.exs new file mode 100644 index 0000000..bd51be0 --- /dev/null +++ b/test/tools/generator/for_of_statement_test.exs @@ -0,0 +1,19 @@ +defmodule ESTree.Tools.Generator.ForOfStatement.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert for of statement" do + ast = Builder.for_of_statement( + Builder.variable_declaration([ + Builder.variable_declarator(Builder.identifier(:a)) + ]), + Builder.identifier(:b), + Builder.block_statement([]) + ) + + assert_gen ast, "for (var a of b) {}" + assert_gen ast, "for(var a of b){}", beauty: false + end +end diff --git a/test/tools/generator/for_statement_test.exs b/test/tools/generator/for_statement_test.exs new file mode 100644 index 0000000..adb0bb6 --- /dev/null +++ b/test/tools/generator/for_statement_test.exs @@ -0,0 +1,40 @@ +defmodule ESTree.Tools.Generator.ForStatement.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert for statement empty" do + ast = Builder.for_statement( + nil, + nil, + nil, + Builder.block_statement([]) + ) + + assert_gen ast, "for (; ; ) {}" + assert_gen ast, "for(;;){}", beauty: false + end + + should "convert for statement" do + ast = Builder.for_statement( + Builder.variable_declaration([ + Builder.variable_declarator(Builder.identifier(:i), Builder.literal(0)) + ]), + Builder.binary_expression( + :<, + Builder.identifier(:i), + Builder.identifier(:length) + ), + Builder.unary_expression( + :++, + false, + Builder.identifier(:i) + ), + Builder.block_statement([]) + ) + + assert_gen ast, "for (var i = 0; i < length; i++) {}" + assert_gen ast, "for(var i=0;i "\n" == -""" -{ - key: value, - key: value + + str = """ +function test() { + var a, + b, + c = function() { + return 1; + }; + + if (true) { + a = -1; + } + + switch (false) { + default: + b = 0; + break; + } + + return { + a: a + 1, + b: b + 2, + c: c + 3 + }; } -""" - end - should "format objects in function calls" do - ast = Builder.call_expression( - Builder.identifier(:foo), - [ - Builder.object_expression([ - Builder.property( - Builder.identifier(:key), - Builder.identifier(:value) - ), - Builder.property( - Builder.identifier(:key), - Builder.identifier(:value) - ) - ]) - ] - ) - assert Generator.generate(ast, 0) <> "\n" == -""" -foo({ - key: value, - key: value -}) +test(); """ + + assert_gen ast, String.trim(str) + + str = "function test(){var a,b,c=function(){return 1;};if(true){a=-1;}switch(false){default:b=0;break;}return {a:a+1,b:b+2,c:c+3};}test();" + + assert_gen ast, str, beauty: false end end diff --git a/test/tools/generator/function_test.exs b/test/tools/generator/function_test.exs index a5886d3..89ecf54 100644 --- a/test/tools/generator/function_test.exs +++ b/test/tools/generator/function_test.exs @@ -1,7 +1,8 @@ defmodule ESTree.Tools.Generator.Function.Test do use ShouldI + alias ESTree.Tools.Builder - alias ESTree.Tools.Generator + import ESTree.Test.Support should "convert basic function declaration" do ast = Builder.function_declaration( @@ -10,9 +11,11 @@ defmodule ESTree.Tools.Generator.Function.Test do [], Builder.block_statement([]), false, - false) + false + ) - assert Generator.generate(ast) == "function hello(){}" + assert_gen ast, "function hello() {}" + assert_gen ast, "function hello(){}", beauty: false end should "convert basic function declaration generator" do @@ -20,11 +23,46 @@ defmodule ESTree.Tools.Generator.Function.Test do Builder.identifier(:hello), [], [], - Builder.block_statement([]), + Builder.block_statement([ + Builder.return_statement( + Builder.yield_expression( + Builder.call_expression( + Builder.identifier(:x), + [] + ) + ) + ) + ]), true, - false) + false + ) + + assert_gen ast, "function* hello() {\n return yield x();\n}" + assert_gen ast, "function*hello(){return yield x();}", beauty: false + end + + should "convert basic async function declaration" do + ast = Builder.function_declaration( + Builder.identifier(:hello), + [], + [], + Builder.block_statement([ + Builder.return_statement( + Builder.await_expression( + Builder.call_expression( + Builder.identifier(:x), + [] + ) + ) + ) + ]), + false, + false, + true + ) - assert Generator.generate(ast) == "function* hello(){}" + assert_gen ast, "async function hello() {\n return await x();\n}" + assert_gen ast, "async function hello(){return await x();}", beauty: false end should "convert function declaration with params" do @@ -34,9 +72,11 @@ defmodule ESTree.Tools.Generator.Function.Test do [], Builder.block_statement([]), false, - false) + false + ) - assert Generator.generate(ast) == "function hello(one){}" + assert_gen ast, "function hello(one) {}" + assert_gen ast, "function hello(one){}", beauty: false ast = Builder.function_declaration( Builder.identifier(:hello), @@ -44,9 +84,11 @@ defmodule ESTree.Tools.Generator.Function.Test do [], Builder.block_statement([]), false, - false) + false + ) - assert Generator.generate(ast) == "function hello(one,two){}" + assert_gen ast, "function hello(one, two) {}" + assert_gen ast, "function hello(one,two){}", beauty: false end should "convert function declaration with default values" do @@ -56,9 +98,11 @@ defmodule ESTree.Tools.Generator.Function.Test do [nil, Builder.literal(1)], Builder.block_statement([]), false, - false) + false + ) - assert Generator.generate(ast) == "function hello(one,two = 1){}" + assert_gen ast, "function hello(one, two = 1) {}" + assert_gen ast, "function hello(one,two=1){}", beauty: false end should "convert basic function expression" do @@ -67,9 +111,11 @@ defmodule ESTree.Tools.Generator.Function.Test do [], Builder.block_statement([]), false, - false) + false + ) - assert Generator.generate(ast) == "function(){}" + assert_gen ast, "function() {}" + assert_gen ast, "function(){}", beauty: false end should "convert basic function expression generator" do @@ -78,92 +124,70 @@ defmodule ESTree.Tools.Generator.Function.Test do [], Builder.block_statement([]), true, - false) + false + ) - assert Generator.generate(ast) == "function*(){}" + assert_gen ast, "function*() {}" + assert_gen ast, "function*(){}", beauty: false end - should "convert function expression with params" do + should "convert basic async function expression" do ast = Builder.function_expression( - [Builder.identifier(:one)], [], - Builder.block_statement([]), - false, - false) - - assert Generator.generate(ast) == "function(one){}" - - ast = Builder.function_expression( - [Builder.identifier(:one), Builder.identifier(:two)], [], - Builder.block_statement([]), + Builder.block_statement([ + Builder.return_statement( + Builder.await_expression( + Builder.call_expression( + Builder.identifier(:x), + [] + ) + ) + ) + ]), false, - false) - - assert Generator.generate(ast) == "function(one,two){}" - end - - should "convert function expression with default values" do - ast = Builder.function_expression( - [Builder.identifier(:one), Builder.identifier(:two)], - [nil, Builder.literal(1)], - Builder.block_statement([]), - false, - false) - - assert Generator.generate(ast) == "function(one,two = 1){}" - end - - should "convert basic arrow function" do - ast = Builder.arrow_function_expression( - [], - [], - Builder.block_statement([]), false, - false) + true + ) - assert Generator.generate(ast) == "() => {}" + assert_gen ast, "async function() {\n return await x();\n}" + assert_gen ast, "async function(){return await x();}", beauty: false end - should "convert basic arrow function expression generator" do - ast = Builder.arrow_function_expression( - [], - [], - Builder.block_statement([]), - true, - false) - - assert Generator.generate(ast) == "()* => {}" - end - - should "convert arrow function with params" do - ast = Builder.arrow_function_expression( + should "convert function expression with params" do + ast = Builder.function_expression( [Builder.identifier(:one)], [], Builder.block_statement([]), false, - false) + false + ) - assert Generator.generate(ast) == "(one) => {}" + assert_gen ast, "function(one) {}" + assert_gen ast, "function(one){}", beauty: false - ast = Builder.arrow_function_expression( + ast = Builder.function_expression( [Builder.identifier(:one), Builder.identifier(:two)], [], Builder.block_statement([]), false, - false) + false + ) - assert Generator.generate(ast) == "(one,two) => {}" + assert_gen ast, "function(one, two) {}" + assert_gen ast, "function(one,two){}", beauty: false end - should "convert arrow function with default values" do - ast = Builder.arrow_function_expression( + should "convert function expression with default values" do + ast = Builder.function_expression( [Builder.identifier(:one), Builder.identifier(:two)], [nil, Builder.literal(1)], Builder.block_statement([]), false, - false) + false + ) - assert Generator.generate(ast) == "(one,two = 1) => {}" + assert_gen ast, "function(one, two = 1) {}" + assert_gen ast, "function(one,two=1){}", beauty: false end end diff --git a/test/tools/generator/identifier_test.exs b/test/tools/generator/identifier_test.exs index 86b98f2..46a29a4 100644 --- a/test/tools/generator/identifier_test.exs +++ b/test/tools/generator/identifier_test.exs @@ -1,13 +1,20 @@ defmodule ESTree.Tools.Generator.Identifier.Test do use ShouldI + alias ESTree.Tools.Builder - alias ESTree.Tools.Generator + import ESTree.Test.Support - should "convert identifiers" do + should "convert identifiers (binary)" do ast = Builder.identifier("hello") - assert Generator.generate(ast) == "hello" + assert_gen ast, "hello" + assert_gen ast, "hello", beauty: false + end + + should "convert identifiers (atom)" do ast = Builder.identifier(:hello) - assert Generator.generate(ast) == "hello" + + assert_gen ast, "hello" + assert_gen ast, "hello", beauty: false end end diff --git a/test/tools/generator/if_statement_test.exs b/test/tools/generator/if_statement_test.exs index f5820dc..c9b4d06 100644 --- a/test/tools/generator/if_statement_test.exs +++ b/test/tools/generator/if_statement_test.exs @@ -1,14 +1,17 @@ defmodule ESTree.Tools.Generator.IfStatement.Test do use ShouldI + alias ESTree.Tools.Builder - alias ESTree.Tools.Generator + import ESTree.Test.Support should "convert if without else" do ast = Builder.if_statement( Builder.identifier(:test), Builder.block_statement([]) ) - assert Generator.generate(ast) == "if(test) {}" + + assert_gen ast, "if (test) {}" + assert_gen ast, "if(test){}", beauty: false end should "convert if with else" do @@ -17,7 +20,9 @@ defmodule ESTree.Tools.Generator.IfStatement.Test do Builder.block_statement([]), Builder.block_statement([]) ) - assert Generator.generate(ast) == "if(test) {} else {}" + + assert_gen ast, "if (test) {} else {}" + assert_gen ast, "if(test){}else{}", beauty: false end should "convert if with else if" do @@ -30,7 +35,23 @@ defmodule ESTree.Tools.Generator.IfStatement.Test do Builder.block_statement([]) ) ) - assert Generator.generate(ast) == "if(test) {} else if(test) {} else {}" + + assert_gen ast, "if (test) {} else if (test) {} else {}" + assert_gen ast, "if(test){}else if(test){}else{}", beauty: false end + should "convert if statement with short syntax" do + ast = Builder.if_statement( + Builder.identifier(:test), + Builder.return_statement(Builder.literal(1)), + Builder.if_statement( + Builder.identifier(:test2), + Builder.return_statement(Builder.literal(2)), + Builder.return_statement(Builder.literal(3)) + ) + ) + + assert_gen ast, "if (test)\n return 1;\nelse if (test2)\n return 2;\nelse\n return 3;" + assert_gen ast, "if(test)return 1;else if(test2)return 2;else return 3;", beauty: false + end end diff --git a/test/tools/generator/import_declaration_test.exs b/test/tools/generator/import_declaration_test.exs index 23d547f..fede4b6 100644 --- a/test/tools/generator/import_declaration_test.exs +++ b/test/tools/generator/import_declaration_test.exs @@ -1,7 +1,8 @@ defmodule ESTree.Tools.Generator.ImportDeclaration.Test do use ShouldI + alias ESTree.Tools.Builder - alias ESTree.Tools.Generator + import ESTree.Test.Support should "convert import declaration with one specifier" do ast = Builder.import_declaration([ @@ -12,7 +13,8 @@ defmodule ESTree.Tools.Generator.ImportDeclaration.Test do Builder.literal(:test) ) - assert Generator.generate(ast) == "import { test } from 'test';" + assert_gen ast, "import { test } from 'test';" + assert_gen ast, "import{test}from'test';", beauty: false end should "convert import declaration with one specifier with an alias" do @@ -24,7 +26,8 @@ defmodule ESTree.Tools.Generator.ImportDeclaration.Test do Builder.literal(:test) ) - assert Generator.generate(ast) == "import { test as test1 } from 'test';" + assert_gen ast, "import { test as test1 } from 'test';" + assert_gen ast, "import{test as test1}from'test';", beauty: false end should "convert import declaration with more than one specifier" do @@ -42,7 +45,8 @@ defmodule ESTree.Tools.Generator.ImportDeclaration.Test do Builder.literal(:test) ) - assert Generator.generate(ast) == "import { top, test as test1 } from 'test';" + assert_gen ast, "import { top, test as test1 } from 'test';" + assert_gen ast, "import{top,test as test1}from'test';", beauty: false end @@ -55,7 +59,8 @@ defmodule ESTree.Tools.Generator.ImportDeclaration.Test do Builder.literal(:test) ) - assert Generator.generate(ast) == "import test from 'test';" + assert_gen ast, "import test from 'test';" + assert_gen ast, "import test from'test';", beauty: false end should "convert import declaration with a namespace specifier" do @@ -66,7 +71,7 @@ defmodule ESTree.Tools.Generator.ImportDeclaration.Test do Builder.literal(:test) ) - assert Generator.generate(ast) == "import * as test from 'test';" + assert_gen ast, "import * as test from 'test';" + assert_gen ast, "import*as test from'test';", beauty: false end - -end \ No newline at end of file +end diff --git a/test/tools/generator/jsx_test.exs b/test/tools/generator/jsx_test.exs index c1ebea8..2b31ad6 100644 --- a/test/tools/generator/jsx_test.exs +++ b/test/tools/generator/jsx_test.exs @@ -1,21 +1,27 @@ defmodule ESTree.Tools.Generator.JSX.Test do use ShouldI + alias ESTree.Tools.Builder - alias ESTree.Tools.Generator + import ESTree.Test.Support + should "handle atom and binary as identifier name" do + assert_gen Builder.jsx_identifier("Test"), "Test" + assert_gen Builder.jsx_identifier(:Test), "Test" + end should "handle no closing tag" do ast = Builder.jsx_element( Builder.jsx_opening_element( Builder.jsx_identifier( - "Test" + "Test" ), [], true ) ) - assert Generator.generate(ast) == "" + assert_gen ast, "" + assert_gen ast, "", beauty: false end should "handle closing tag" do @@ -33,7 +39,8 @@ defmodule ESTree.Tools.Generator.JSX.Test do ) ) - assert Generator.generate(ast) == "" + assert_gen ast, "" + assert_gen ast, "", beauty: false end @@ -57,7 +64,7 @@ defmodule ESTree.Tools.Generator.JSX.Test do Builder.jsx_spread_attribute( Builder.array_expression([ Builder.literal(1) - ]) + ]) ) ] ), @@ -69,9 +76,43 @@ defmodule ESTree.Tools.Generator.JSX.Test do ) ) - assert Generator.generate(ast) == "" + assert_gen ast, "" + assert_gen ast, "", beauty: false end + should "handle escaped attributes value" do + ast = fn x -> + Builder.jsx_element( + Builder.jsx_opening_element( + Builder.jsx_identifier("Test"), + [ + Builder.jsx_attribute( + Builder.jsx_identifier("className"), + x + ) + ] + ), + [], + Builder.jsx_closing_element( + Builder.jsx_identifier( + "Test" + ) + ) + ) + end + + assert_gen ast.(Builder.literal("\\")), "" + assert_gen ast.(Builder.literal("\n")), "" + assert_gen ast.(Builder.literal("\r")), "" + assert_gen ast.(Builder.literal("\t")), "" + assert_gen ast.(Builder.literal("\b")), "" + assert_gen ast.(Builder.literal("\f")), "" + assert_gen ast.(Builder.literal("\v")), "" + assert_gen ast.(Builder.literal("\u2028")), "" + assert_gen ast.(Builder.literal("\u2029")), "" + assert_gen ast.(Builder.literal("\ufeff")), "" + assert_gen ast.(Builder.literal("'")), "" + end should "handle element with elements inside" do ast = Builder.jsx_element( @@ -92,10 +133,10 @@ defmodule ESTree.Tools.Generator.JSX.Test do ) ) - assert Generator.generate(ast) == "
" + assert_gen ast, "
" + assert_gen ast, "
", beauty: false end - should "handle namespaced names" do ast = Builder.jsx_element( Builder.jsx_opening_element( @@ -119,10 +160,10 @@ defmodule ESTree.Tools.Generator.JSX.Test do ) ) - assert Generator.generate(ast) == "
" + assert_gen ast, "
" + assert_gen ast, "
", beauty: false end - should "handle member names" do ast = Builder.jsx_element( Builder.jsx_opening_element( @@ -146,7 +187,8 @@ defmodule ESTree.Tools.Generator.JSX.Test do ) ) - assert Generator.generate(ast) == "
" + assert_gen ast, "
" + assert_gen ast, "
", beauty: false end should "handle inner text" do @@ -170,6 +212,30 @@ defmodule ESTree.Tools.Generator.JSX.Test do ) ) - assert Generator.generate(ast) == "counter: {count}." + assert_gen ast, "counter: {count}." + assert_gen ast, "counter: {count}.", beauty: false + end + + should "handle inner text escape" do + ast = fn x -> + Builder.jsx_element( + Builder.jsx_opening_element( + Builder.jsx_identifier( + "Test" + ) + ), + [x], + Builder.jsx_closing_element( + Builder.jsx_identifier( + "Test" + ) + ) + ) + end + + assert_gen ast.(Builder.literal("{")), "{" + assert_gen ast.(Builder.literal("}")), "}" + assert_gen ast.(Builder.literal("<")), "<" + assert_gen ast.(Builder.literal(">")), ">" end end diff --git a/test/tools/generator/literal_test.exs b/test/tools/generator/literal_test.exs index 18dc30f..ddac10a 100644 --- a/test/tools/generator/literal_test.exs +++ b/test/tools/generator/literal_test.exs @@ -1,49 +1,48 @@ defmodule ESTree.Generator.Literal.Test do use ShouldI + alias ESTree.Tools.Builder - alias ESTree.Tools.Generator + import ESTree.Test.Support should "convert numbers" do - ast = Builder.literal(1) - assert Generator.generate(ast) == "1" - - ast = Builder.literal(10) - assert Generator.generate(ast) == "10" - - ast = Builder.literal(1.012) - assert Generator.generate(ast) == "1.012" + assert_gen Builder.literal(1), "1" + assert_gen Builder.literal(10), "10" + assert_gen Builder.literal(1.012), "1.012" end should "convert booleans" do - ast = Builder.literal(true) - assert Generator.generate(ast) == "true" - - ast = Builder.literal(false) - assert Generator.generate(ast) == "false" + assert_gen Builder.literal(true), "true" + assert_gen Builder.literal(false), "false" end should "convert string" do - ast = Builder.literal("hello") - assert Generator.generate(ast) == "'hello'" + assert_gen Builder.literal("hello"), "'hello'" + assert_gen Builder.literal("goodbye"), "'goodbye'" + assert_gen Builder.literal(:hello), "'hello'" + assert_gen Builder.literal(:goodbye), "'goodbye'" + end - ast = Builder.literal("goodbye") - assert Generator.generate(ast) == "'goodbye'" + should "convert string escape" do + assert_gen Builder.literal("\\"), "'\\\\'" + assert_gen Builder.literal("\n"), "'\\n'" + assert_gen Builder.literal("\r"), "'\\r'" + assert_gen Builder.literal("\t"), "'\\t'" + assert_gen Builder.literal("\b"), "'\\b'" + assert_gen Builder.literal("\f"), "'\\f'" + assert_gen Builder.literal("\v"), "'\\v'" + assert_gen Builder.literal("\u2028"), "'\\u2028'" + assert_gen Builder.literal("\u2029"), "'\\u2029'" + assert_gen Builder.literal("\ufeff"), "'\\ufeff'" + assert_gen Builder.literal("'"), "'\\''" end should "convert null" do - ast = Builder.literal(nil) - assert Generator.generate(ast) == "null" + assert_gen Builder.literal(nil), "null" end should "convert regex" do - ast = Builder.literal(%{}, Builder.regex("^abc$", "i")) - assert Generator.generate(ast) == "/^abc$/i" - - ast = Builder.literal(%{}, Builder.regex("^abc$", "")) - assert Generator.generate(ast) == "/^abc$/" - - ast = Builder.literal(%{}, Builder.regex("", "")) - assert Generator.generate(ast) == "//" + assert_gen Builder.literal(%{}, Builder.regex("^abc$", "i")), "/^abc$/i" + assert_gen Builder.literal(%{}, Builder.regex("^abc$", "")), "/^abc$/" + assert_gen Builder.literal(%{}, Builder.regex("", "")), "//" end - end diff --git a/test/tools/generator/new_expression_test.exs b/test/tools/generator/new_expression_test.exs new file mode 100644 index 0000000..ad22e24 --- /dev/null +++ b/test/tools/generator/new_expression_test.exs @@ -0,0 +1,95 @@ +defmodule ESTree.Tools.Generator.NewExpression.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert new expression when arguments are empty" do + ast = Builder.new_expression( + Builder.identifier(:X), + [] + ) + + assert_gen ast, "new X()" + assert_gen ast, "new X()", beauty: false + end + + should "convert new expression when argument" do + ast = Builder.new_expression( + Builder.identifier(:X), + [Builder.identifier(:a)] + ) + + assert_gen ast, "new X(a)" + assert_gen ast, "new X(a)", beauty: false + end + + should "convert new expression when callee is member expression" do + ast = Builder.new_expression( + Builder.member_expression( + Builder.identifier(:x), + Builder.identifier(:Y) + ), + [] + ) + + assert_gen ast, "new x.Y()" + assert_gen ast, "new x.Y()", beauty: false + end + + should "convert new expression when callee is call expression" do + ast = Builder.new_expression( + Builder.member_expression( + Builder.call_expression( + Builder.identifier(:x), + [] + ), + Builder.identifier(:Y) + ), + [] + ) + + assert_gen ast, "new (x().Y)()" + assert_gen ast, "new (x().Y)()", beauty: false + end + + should "convert new expression when callee is new expression" do + ast = Builder.new_expression( + Builder.new_expression( + Builder.identifier(:X), + [] + ), + [] + ) + + assert_gen ast, "new new X()()" + assert_gen ast, "new new X()()", beauty: false + end + + should "convert new expression when callee is sequence expression" do + ast = Builder.new_expression( + Builder.sequence_expression([ + Builder.identifier(:X), + Builder.identifier(:Y) + ]), + [] + ) + + assert_gen ast, "new (X, Y)()" + assert_gen ast, "new (X,Y)()", beauty: false + end + + should "convert new expression when callee is conditional statement" do + ast = Builder.new_expression( + Builder.conditional_statement( + Builder.literal(true), + Builder.identifier(:Y), + Builder.identifier(:X) + ), + [] + ) + + assert_gen ast, "new (true ? X : Y)()" + assert_gen ast, "new (true?X:Y)()", beauty: false + end +end diff --git a/test/tools/generator/object_expression_test.exs b/test/tools/generator/object_expression_test.exs index 0ff67df..8c63032 100644 --- a/test/tools/generator/object_expression_test.exs +++ b/test/tools/generator/object_expression_test.exs @@ -1,16 +1,21 @@ defmodule ESTree.Tools.Generator.ObjectExpression.Test do use ShouldI + alias ESTree.Tools.Builder - alias ESTree.Tools.Generator + import ESTree.Test.Support should "convert object when properties is nil" do ast = Builder.object_expression(nil) - assert Generator.generate(ast) == "{}" + + assert_gen ast, "{}" + assert_gen ast, "{}", beauty: false end should "convert object when properties is empty" do ast = Builder.object_expression([]) - assert Generator.generate(ast) == "{}" + + assert_gen ast, "{}" + assert_gen ast, "{}", beauty: false end should "convert object when properties contains one property" do @@ -20,7 +25,45 @@ defmodule ESTree.Tools.Generator.ObjectExpression.Test do Builder.identifier(:value) ) ]) - assert Generator.generate(ast) == "{key: value}" + + assert_gen ast, "{\n key: value\n}" + assert_gen ast, "{key:value}", beauty: false + end + + should "convert object when properties contains one property string" do + ast = Builder.object_expression([ + Builder.property( + Builder.literal(:key), + Builder.identifier(:value) + ) + ]) + + assert_gen ast, "{\n 'key': value\n}" + assert_gen ast, "{'key':value}", beauty: false + end + + should "convert object when properties contains computed properties" do + ast = Builder.object_expression([ + Builder.property( + Builder.identifier(:key), + Builder.identifier(:value), + :init, + false, + false, + true + ), + Builder.property( + Builder.literal(:key), + Builder.identifier(:value), + :init, + false, + false, + true + ) + ]) + + assert_gen ast, "{\n [key]: value,\n ['key']: value\n}" + assert_gen ast, "{[key]:value,['key']:value}", beauty: false end should "convert object when properties contains multiple properties" do @@ -34,7 +77,9 @@ defmodule ESTree.Tools.Generator.ObjectExpression.Test do Builder.identifier(:value1) ) ]) - assert Generator.generate(ast) == "{key: value,key1: value1}" + + assert_gen ast, "{\n key: value,\n key1: value1\n}" + assert_gen ast, "{key:value,key1:value1}", beauty: false end @@ -51,7 +96,9 @@ defmodule ESTree.Tools.Generator.ObjectExpression.Test do :set ), ]) - assert Generator.generate(ast) == "{get key() {},set key(p) {}}" + + assert_gen ast, "{\n get key() {},\n set key(p) {}\n}" + assert_gen ast, "{get key(){},set key(p){}}", beauty: false end should "convert object when properties contains getter and setter methods" do @@ -71,7 +118,33 @@ defmodule ESTree.Tools.Generator.ObjectExpression.Test do true ), ]) - assert Generator.generate(ast) == "{key() {},key(p) {}}" + + assert_gen ast, "{\n key() {},\n key(p) {}\n}" + assert_gen ast, "{key(){},key(p){}}", beauty: false + end + + should "convert object when properties are methods computed" do + ast = Builder.object_expression([ + Builder.property( + Builder.identifier(:key), + Builder.function_expression([], [], Builder.block_statement([])), + :init, + false, + true, + true + ), + Builder.property( + Builder.literal(:key), + Builder.function_expression([], [], Builder.block_statement([])), + :init, + false, + true, + true + ), + ]) + + assert_gen ast, "{\n [key]() {},\n ['key']() {}\n}" + assert_gen ast, "{[key](){},['key'](){}}", beauty: false end should "convert object when properties contains shorthand properties" do @@ -82,7 +155,8 @@ defmodule ESTree.Tools.Generator.ObjectExpression.Test do :init, true) ]) - assert Generator.generate(ast) == "{key}" + + assert_gen ast, "{\n key\n}" + assert_gen ast, "{key}", beauty: false end - end diff --git a/test/tools/generator/object_pattern_test.exs b/test/tools/generator/object_pattern_test.exs new file mode 100644 index 0000000..348a682 --- /dev/null +++ b/test/tools/generator/object_pattern_test.exs @@ -0,0 +1,57 @@ +defmodule ESTree.Generator.ObjectPattern.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert object pattern" do + ast = Builder.object_pattern([ + Builder.property( + Builder.identifier(:i), + nil, + :init, + true + ), + Builder.property( + Builder.identifier(:j), + Builder.identifier(:k) + ) + ]) + + assert_gen ast, "{i, j: k}" + assert_gen ast, "{i,j:k}", beauty: false + + ast = Builder.object_pattern([ + Builder.property( + Builder.identifier(:a), + Builder.array_pattern([ + Builder.identifier(:b), + Builder.object_pattern([ + Builder.property( + Builder.identifier(:c), + nil, + :init, + true + ) + ]) + ]) + ) + ]) + + assert_gen ast, "{a: [b, {c}]}" + assert_gen ast, "{a:[b,{c}]}", beauty: false + + ast = Builder.object_pattern([ + Builder.property( + Builder.identifier(:g), + Builder.assignment_expression( + :=, + Builder.identifier(:h), + Builder.literal(1) + ) + ) + ]) + + assert_gen ast, "{g: h = 1}" + end +end diff --git a/test/tools/generator/switch_statement_test.exs b/test/tools/generator/switch_statement_test.exs new file mode 100644 index 0000000..2fd1677 --- /dev/null +++ b/test/tools/generator/switch_statement_test.exs @@ -0,0 +1,49 @@ +defmodule ESTree.Tools.Generator.SwitchStatement.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert switch statement" do + ast = Builder.switch_statement( + Builder.identifier(:test), + [ + Builder.switch_case( + Builder.identifier(:b), + [Builder.break_statement()] + ), + Builder.switch_case( + Builder.literal("c"), + [Builder.break_statement()] + ), + Builder.switch_case( + Builder.literal(1), + [Builder.break_statement()] + ), + Builder.switch_case( + nil, + [Builder.break_statement()] + ) + ] + ) + + str = """ +switch (test) { +case b: + break; + +case 'c': + break; + +case 1: + break; + +default: + break; +} +""" + + assert_gen ast, String.trim(str) + assert_gen ast, "switch(test){case b:break;case 'c':break;case 1:break;default:break;}", beauty: false + end +end diff --git a/test/tools/generator/template_literal_test.exs b/test/tools/generator/template_literal_test.exs index 69cd774..955aa7f 100644 --- a/test/tools/generator/template_literal_test.exs +++ b/test/tools/generator/template_literal_test.exs @@ -1,66 +1,75 @@ defmodule ESTree.Tools.Generator.TemplateLiteral.Test do use ShouldI - alias ESTree.Tools.Builder - alias ESTree.Tools.Generator + alias ESTree.Tools.Builder + import ESTree.Test.Support should "convert empty template literal" do ast = Builder.template_literal([],[]) - assert Generator.generate(ast) == "``" + + assert_gen ast, "``" + assert_gen ast, "``", beauty: false end should "convert template literal with no expressions" do ast = Builder.template_literal([ - Builder.template_element("hello ", "hello ", false, + Builder.template_element("hello ", "hello ", false, Builder.source_location( nil, Builder.position(0, 1), Builder.position(0, 5) ) ), - Builder.template_element("there", "there", true, + Builder.template_element("there", "there", true, Builder.source_location( nil, Builder.position(0, 5), Builder.position(0, 10) ) ) - ],[]) - assert Generator.generate(ast) == "`hello there`" + ], []) + + assert_gen ast, "`hello there`" + assert_gen ast, "`hello there`", beauty: false end should "convert template literal with no quasis" do - ast = Builder.template_literal([],[ - Builder.identifier(:a, - Builder.source_location( - nil, - Builder.position(0, 1), - Builder.position(0, 2) + ast = Builder.template_literal( + [], + [ + Builder.identifier(:a, + Builder.source_location( + nil, + Builder.position(0, 1), + Builder.position(0, 2) + ) ) - ) - ]) - assert Generator.generate(ast) == "`${a}`" + ] + ) + + assert_gen ast, "`${a}`" + assert_gen ast, "`${a}`", beauty: false end should "convert template literal with interlaping quasis and expressions" do ast = Builder.template_literal([ - Builder.template_element("hello ", "hello ", false, + Builder.template_element("hello ", "hello ", false, Builder.source_location( nil, Builder.position(0, 1), Builder.position(0, 5) ) ), - Builder.template_element(" there", " there", true, + Builder.template_element(" there", " there", true, Builder.source_location( nil, Builder.position(0, 6), Builder.position(0, 12) ) ) - ],[ - Builder.identifier(:a, + ], [ + Builder.identifier(:a, Builder.source_location( nil, Builder.position(0, 5), @@ -68,38 +77,41 @@ defmodule ESTree.Tools.Generator.TemplateLiteral.Test do ) ) ]) - assert Generator.generate(ast) == "`hello ${a} there`" + + assert_gen ast, "`hello ${a} there`" + assert_gen ast, "`hello ${a} there`", beauty: false end should "convert tagged template expressions" do ast = Builder.tagged_template_expression( Builder.identifier(:tag), Builder.template_literal([ - Builder.template_element("hello ", "hello ", false, - Builder.source_location( - nil, - Builder.position(0, 1), - Builder.position(0, 5) - ) - ), - Builder.template_element(" there", " there", true, - Builder.source_location( - nil, - Builder.position(0, 6), - Builder.position(0, 12) - ) - ) - ],[ - Builder.identifier(:a, - Builder.source_location( - nil, - Builder.position(0, 5), - Builder.position(0, 6) - ) - ) - ]) + Builder.template_element("hello ", "hello ", false, + Builder.source_location( + nil, + Builder.position(0, 1), + Builder.position(0, 5) + ) + ), + Builder.template_element(" there", " there", true, + Builder.source_location( + nil, + Builder.position(0, 6), + Builder.position(0, 12) + ) + ) + ],[ + Builder.identifier(:a, + Builder.source_location( + nil, + Builder.position(0, 5), + Builder.position(0, 6) + ) + ) + ]) ) - assert Generator.generate(ast) == "tag `hello ${a} there`" - end -end \ No newline at end of file + assert_gen ast, "tag `hello ${a} there`" + assert_gen ast, "tag `hello ${a} there`", beauty: false + end +end diff --git a/test/tools/generator/throw_statement_test.exs b/test/tools/generator/throw_statement_test.exs new file mode 100644 index 0000000..4ea6476 --- /dev/null +++ b/test/tools/generator/throw_statement_test.exs @@ -0,0 +1,18 @@ +defmodule ESTree.Tools.Generator.ThrowStatement.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert throw statement" do + ast = Builder.throw_statement( + Builder.new_expression( + Builder.identifier(:Error), + [Builder.literal("error")] + ) + ) + + assert_gen ast, "throw new Error('error');" + assert_gen ast, "throw new Error('error');", beauty: false + end +end diff --git a/test/tools/generator/try_statement_test.exs b/test/tools/generator/try_statement_test.exs index 3a1b4d4..002f1ab 100644 --- a/test/tools/generator/try_statement_test.exs +++ b/test/tools/generator/try_statement_test.exs @@ -1,7 +1,8 @@ defmodule ESTree.Tools.Generator.TryStatement.Test do use ShouldI + alias ESTree.Tools.Builder - alias ESTree.Tools.Generator + import ESTree.Test.Support should "convert try with catch" do ast = Builder.try_statement( @@ -11,8 +12,9 @@ defmodule ESTree.Tools.Generator.TryStatement.Test do Builder.block_statement([]) ) ) - - assert Generator.generate(ast) == "try{}catch(e) {}" + + assert_gen ast, "try {} catch (e) {}" + assert_gen ast, "try{}catch(e){}", beauty: false end should "convert try with finally" do @@ -21,8 +23,9 @@ defmodule ESTree.Tools.Generator.TryStatement.Test do nil, Builder.block_statement([]) ) - - assert Generator.generate(ast) == "try{}finally{}" + + assert_gen ast, "try {} finally {}" + assert_gen ast, "try{}finally{}", beauty: false end should "convert try catch finally" do @@ -34,7 +37,8 @@ defmodule ESTree.Tools.Generator.TryStatement.Test do ), Builder.block_statement([]) ) - - assert Generator.generate(ast) == "try{}catch(e) {}finally{}" + + assert_gen ast, "try {} catch (e) {} finally {}" + assert_gen ast, "try{}catch(e){}finally{}", beauty: false end end diff --git a/test/tools/generator/unary_expression_test.exs b/test/tools/generator/unary_expression_test.exs new file mode 100644 index 0000000..6ae3c6f --- /dev/null +++ b/test/tools/generator/unary_expression_test.exs @@ -0,0 +1,84 @@ +defmodule ESTree.Generator.UnaryExpression.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert unary expression !true" do + ast = Builder.unary_expression( + :!, + true, + Builder.literal(true) + ) + + assert_gen ast, "!true" + assert_gen ast, "!true", beauty: false + end + + should "convert unary expression !false" do + ast = Builder.unary_expression( + :!, + true, + Builder.literal(false) + ) + + assert_gen ast, "!false" + assert_gen ast, "!false", beauty: false + end + + should "convert unary expression !typeof" do + ast = Builder.unary_expression( + :!, + true, + Builder.unary_expression( + :typeof, + true, + Builder.identifier(:x) + ) + ) + + assert_gen ast, "!typeof x" + assert_gen ast, "!typeof x", beauty: false + end + + should "convert unary expression ! and typeof with binary expression" do + ast = Builder.unary_expression( + :!, + true, + Builder.binary_expression( + :===, + Builder.unary_expression( + :typeof, + true, + Builder.identifier(:x) + ), + Builder.literal("boolean") + ) + ) + + assert_gen ast, "!(typeof x === 'boolean')" + assert_gen ast, "!(typeof x==='boolean')", beauty: false + end + + should "convert unary expression delete" do + ast = Builder.unary_expression( + :delete, + true, + Builder.identifier(:a) + ) + + assert_gen ast, "delete a" + assert_gen ast, "delete a", beauty: false + end + + should "convert unary expression void" do + ast = Builder.unary_expression( + :void, + true, + Builder.identifier(:a) + ) + + assert_gen ast, "void a" + assert_gen ast, "void a", beauty: false + end +end diff --git a/test/tools/generator/variable_declaration_test.exs b/test/tools/generator/variable_declaration_test.exs index a258bb1..c9e0ac6 100644 --- a/test/tools/generator/variable_declaration_test.exs +++ b/test/tools/generator/variable_declaration_test.exs @@ -1,24 +1,28 @@ defmodule ESTree.Tools.Generator.VariableDeclaration.Test do use ShouldI - alias ESTree.Tools.{Builder, Generator} + alias ESTree.Tools.Builder + import ESTree.Test.Support should "emit var declaration" do ast = Builder.variable_declaration([]) - assert Generator.generate(ast) == "var ;" + assert_gen ast, "var ;" + assert_gen ast, "var ;", beauty: false end should "emit let declaration" do ast = Builder.variable_declaration([], :let) - assert Generator.generate(ast) == "let ;" + assert_gen ast, "let ;" + assert_gen ast, "let ;", beauty: false end should "emit const declaration" do ast = Builder.variable_declaration([], :const) - assert Generator.generate(ast) == "const ;" + assert_gen ast, "const ;" + assert_gen ast, "const ;", beauty: false end should "add variable declarator" do @@ -26,7 +30,8 @@ defmodule ESTree.Tools.Generator.VariableDeclaration.Test do Builder.variable_declarator(Builder.identifier(:a)) ]) - assert Generator.generate(ast) == "var a;" + assert_gen ast, "var a;" + assert_gen ast, "var a;", beauty: false end should "add variable declarators with corresponding inits" do @@ -43,7 +48,7 @@ defmodule ESTree.Tools.Generator.VariableDeclaration.Test do ) ]) - assert Generator.generate(ast) == "var a = 1, b, c = a + 2;" + assert_gen ast, "var a = 1,\n b,\n c = a + 2;" + assert_gen ast, "var a=1,b,c=a+2;", beauty: false end - end diff --git a/test/tools/generator/while_statement_test.exs b/test/tools/generator/while_statement_test.exs index 789ede3..0547259 100644 --- a/test/tools/generator/while_statement_test.exs +++ b/test/tools/generator/while_statement_test.exs @@ -1,15 +1,17 @@ defmodule ESTree.Tools.Generator.WhileStatement.Test do use ShouldI - alias ESTree.Tools.Builder - alias ESTree.Tools.Generator + alias ESTree.Tools.Builder + import ESTree.Test.Support should "convert while" do ast = Builder.while_statement( Builder.identifier(:test), Builder.block_statement([]) ) - assert Generator.generate(ast) == "while(test) {}" + + assert_gen ast, "while (test) {}" + assert_gen ast, "while(test){}", beauty: false end should "convert do while" do @@ -17,7 +19,8 @@ defmodule ESTree.Tools.Generator.WhileStatement.Test do Builder.block_statement([]), Builder.identifier(:test) ) - assert Generator.generate(ast) == "do {} while(test);" - end + assert_gen ast, "do {} while (test);" + assert_gen ast, "do{}while(test);", beauty: false + end end From 9c25ba4eecec5686a43c1aac9b81f65c0ac8881c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 5 Jan 2017 20:22:29 -0600 Subject: [PATCH 13/31] Ready for release --- CHANGELOG.md | 4 + lib/es_tree/tools/generator.ex | 268 ++++++++++++++++----------------- mix.exs | 5 +- mix.lock | 4 +- 4 files changed, 142 insertions(+), 139 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6efd8f4..63ffc66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v2.5.0 +* Enhancements: + * [Greatly improved formatting of generated JavaScript](https://github.com/bryanjos/elixir-estree/pull/15) + # v2.4.2 * Fixes * [Expressions in variable declarations](https://github.com/bryanjos/elixir-estree/pull/13) diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index bdecc9d..41132da 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -144,7 +144,7 @@ defmodule ESTree.Tools.Generator do :">>>=" , :"|=" , :"^=" , :"&=", :++, :-- ] - @spec generate(ESTree.operator | ESTree.Node.t, integer) :: binary + @spec generate(ESTree.operator | ESTree.Node.t, boolean) :: binary def generate(value, beauty \\ true) do opts = if beauty do %{ @@ -174,25 +174,25 @@ defmodule ESTree.Tools.Generator do |> :erlang.iolist_to_binary() end - def do_generate(nil, _opts) do + defp do_generate(nil, _opts) do [] end - def do_generate(operator, _opts) when operator in @operators do + defp do_generate(operator, _opts) when operator in @operators do to_string(operator) end # ArrayExpression - def do_generate(%ArrayExpression{elements: nil}, _opts) do + defp do_generate(%ArrayExpression{elements: nil}, _opts) do "[]" end - def do_generate(%ArrayExpression{elements: []}, _opts) do + defp do_generate(%ArrayExpression{elements: []}, _opts) do "[]" end - def do_generate(%ArrayExpression{elements: elements}, opts) do + defp do_generate(%ArrayExpression{elements: elements}, opts) do elements = elements |> Enum.map(&do_generate(&1, opts)) |> Enum.intersperse(opts.comma_sep) @@ -202,15 +202,15 @@ defmodule ESTree.Tools.Generator do # ArrayPattern - def do_generate(%ArrayPattern{elements: nil}, _opts) do + defp do_generate(%ArrayPattern{elements: nil}, _opts) do "[]" end - def do_generate(%ArrayPattern{elements: []}, _opts) do + defp do_generate(%ArrayPattern{elements: []}, _opts) do "[]" end - def do_generate(%ArrayPattern{elements: elements}, opts) do + defp do_generate(%ArrayPattern{elements: elements}, opts) do elements = elements |> Enum.map(&do_generate(&1, opts)) |> Enum.intersperse(opts.comma_sep) @@ -220,7 +220,7 @@ defmodule ESTree.Tools.Generator do # ArrowFunctionExpression - def do_generate(%ArrowFunctionExpression{params: params, defaults: defaults, body: body, generator: generator} = ast, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ArrowFunctionExpression{params: params, defaults: defaults, body: body, generator: generator} = ast, %{wh_sep: wh_sep} = opts) do generator = if generator, do: "*", else: "" params = params_and_defaults(params, defaults, opts) body = if body.__struct__ == ObjectExpression do @@ -238,7 +238,7 @@ defmodule ESTree.Tools.Generator do # AssignmentExpression - def do_generate(%AssignmentExpression{operator: operator, left: left, right: right}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%AssignmentExpression{operator: operator, left: left, right: right}, %{wh_sep: wh_sep} = opts) do operator = do_generate(operator, opts) left = do_generate(left, opts) right = do_generate(right, opts) @@ -248,7 +248,7 @@ defmodule ESTree.Tools.Generator do # AssignmentPattern - def do_generate(%AssignmentPattern{left: left, right: right}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%AssignmentPattern{left: left, right: right}, %{wh_sep: wh_sep} = opts) do left = do_generate(left, opts) right = do_generate(right, opts) @@ -257,19 +257,19 @@ defmodule ESTree.Tools.Generator do # AssignmentProperty - def do_generate(%AssignmentProperty{value: value}, opts) do + defp do_generate(%AssignmentProperty{value: value}, opts) do do_generate(value, opts) end # AwaitExpression - def do_generate(%AwaitExpression{argument: argument, all: _all}, opts) do + defp do_generate(%AwaitExpression{argument: argument, all: _all}, opts) do ["await ", do_generate(argument, opts)] end # BinaryExpression - def do_generate(%BinaryExpression{operator: operator, left: left, right: right} = node, opts) when operator in [:in, :instanceof] do + defp do_generate(%BinaryExpression{operator: operator, left: left, right: right} = node, opts) when operator in [:in, :instanceof] do operator = [" ", do_generate(operator, opts), " "] left = format_binary_expression(left, node, false, opts) right = format_binary_expression(right, node, true, opts) @@ -281,7 +281,7 @@ defmodule ESTree.Tools.Generator do end end - def do_generate(%BinaryExpression{operator: operator, left: left, right: right} = node, %{wh_sep: wh_sep} = opts) do + defp do_generate(%BinaryExpression{operator: operator, left: left, right: right} = node, %{wh_sep: wh_sep} = opts) do operator = do_generate(operator, opts) left = format_binary_expression(left, node, false, opts) right = format_binary_expression(right, node, true, opts) @@ -291,11 +291,11 @@ defmodule ESTree.Tools.Generator do # BlockStatement - def do_generate(%BlockStatement{body: []}, _opts) do + defp do_generate(%BlockStatement{body: []}, _opts) do "{}" end - def do_generate(%BlockStatement{body: body}, opts) do + defp do_generate(%BlockStatement{body: body}, opts) do close_bracket = if opts.beauty do ["\n", indent(opts), "}"] else @@ -326,17 +326,17 @@ defmodule ESTree.Tools.Generator do # BreakStatement - def do_generate(%BreakStatement{label: nil}, _opts) do + defp do_generate(%BreakStatement{label: nil}, _opts) do "break;" end - def do_generate(%BreakStatement{label: label}, opts) do + defp do_generate(%BreakStatement{label: label}, opts) do ["break ", do_generate(label, opts), ";"] end # CallExpression - def do_generate(%CallExpression{callee: callee, arguments: arguments}, opts) do + defp do_generate(%CallExpression{callee: callee, arguments: arguments}, opts) do precedence = Map.get(@expressions_precedence, callee.__struct__) callee = do_generate(callee, opts) @@ -355,7 +355,7 @@ defmodule ESTree.Tools.Generator do # CatchClause - def do_generate(%CatchClause{param: param, body: body}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%CatchClause{param: param, body: body}, %{wh_sep: wh_sep} = opts) do param = do_generate(param, opts) body = do_generate(body, opts) @@ -364,11 +364,11 @@ defmodule ESTree.Tools.Generator do # ClassBody - def do_generate(%ClassBody{body: []}, _opts) do + defp do_generate(%ClassBody{body: []}, _opts) do "{}" end - def do_generate(%ClassBody{body: body}, opts) do + defp do_generate(%ClassBody{body: body}, opts) do close_bracket = if opts.beauty do ["\n", indent(opts), "}"] else @@ -399,14 +399,14 @@ defmodule ESTree.Tools.Generator do # ClassDeclaration - def do_generate(%ClassDeclaration{id: id, body: body, superClass: nil}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ClassDeclaration{id: id, body: body, superClass: nil}, %{wh_sep: wh_sep} = opts) do id = do_generate(id, opts) body = do_generate(body, opts) ["class ", id, wh_sep, body] end - def do_generate(%ClassDeclaration{id: id, body: body, superClass: super_class}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ClassDeclaration{id: id, body: body, superClass: super_class}, %{wh_sep: wh_sep} = opts) do id = do_generate(id, opts) body = do_generate(body, opts) super_class = do_generate(super_class, opts) @@ -416,11 +416,11 @@ defmodule ESTree.Tools.Generator do # ClassExpression - def do_generate(%ClassExpression{body: body, superClass: nil}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ClassExpression{body: body, superClass: nil}, %{wh_sep: wh_sep} = opts) do ["class", wh_sep, do_generate(body, opts)] end - def do_generate(%ClassExpression{body: body, superClass: super_class}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ClassExpression{body: body, superClass: super_class}, %{wh_sep: wh_sep} = opts) do super_class = do_generate(super_class, opts) body = do_generate(body, opts) @@ -429,7 +429,7 @@ defmodule ESTree.Tools.Generator do # ConditionalStatement - def do_generate(%ConditionalStatement{test: test, alternate: alternate, consequent: consequent}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ConditionalStatement{test: test, alternate: alternate, consequent: consequent}, %{wh_sep: wh_sep} = opts) do precedence = Map.get(@expressions_precedence, test.__struct__) test = do_generate(test, opts) @@ -447,23 +447,23 @@ defmodule ESTree.Tools.Generator do # ContinueStatement - def do_generate(%ContinueStatement{label: nil}, _opts) do + defp do_generate(%ContinueStatement{label: nil}, _opts) do "continue;" end - def do_generate(%ContinueStatement{label: label}, opts) do + defp do_generate(%ContinueStatement{label: label}, opts) do ["continue ", do_generate(label, opts), ";"] end # DebuggerStatement - def do_generate(%DebuggerStatement{}, _opts) do + defp do_generate(%DebuggerStatement{}, _opts) do "debugger;" end # DoWhileStatement - def do_generate(%DoWhileStatement{test: test, body: body}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%DoWhileStatement{test: test, body: body}, %{wh_sep: wh_sep} = opts) do test = do_generate(test, opts) body = do_generate(body, opts) @@ -472,13 +472,13 @@ defmodule ESTree.Tools.Generator do # EmptyStatement - def do_generate(%EmptyStatement{}, _opts) do + defp do_generate(%EmptyStatement{}, _opts) do ";" end # ExportAllDeclaration - def do_generate(%ExportAllDeclaration{source: source}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ExportAllDeclaration{source: source}, %{wh_sep: wh_sep} = opts) do source = do_generate(source, opts) ["export", wh_sep, "*", wh_sep, "from", wh_sep, source, ";"] @@ -486,25 +486,25 @@ defmodule ESTree.Tools.Generator do # ExportDefaultDeclaration - def do_generate(%ExportDefaultDeclaration{declaration: %ClassDeclaration{} = declaration}, opts) do + defp do_generate(%ExportDefaultDeclaration{declaration: %ClassDeclaration{} = declaration}, opts) do ["export default ", do_generate(declaration, opts)] end - def do_generate(%ExportDefaultDeclaration{declaration: %FunctionDeclaration{} = declaration}, opts) do + defp do_generate(%ExportDefaultDeclaration{declaration: %FunctionDeclaration{} = declaration}, opts) do ["export default ", do_generate(declaration, opts)] end - def do_generate(%ExportDefaultDeclaration{declaration: declaration}, opts) do + defp do_generate(%ExportDefaultDeclaration{declaration: declaration}, opts) do ["export default ", do_generate(declaration, opts), ";"] end # ExportNamedDeclaration - def do_generate(%ExportNamedDeclaration{declaration: declaration, specifiers: [], source: nil}, opts) do + defp do_generate(%ExportNamedDeclaration{declaration: declaration, specifiers: [], source: nil}, opts) do ["export ", do_generate(declaration, opts)] end - def do_generate(%ExportNamedDeclaration{declaration: nil, specifiers: specifiers, source: nil}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ExportNamedDeclaration{declaration: nil, specifiers: specifiers, source: nil}, %{wh_sep: wh_sep} = opts) do specifiers = specifiers |> Enum.map(&do_generate(&1, opts)) |> Enum.intersperse(opts.comma_sep) @@ -512,7 +512,7 @@ defmodule ESTree.Tools.Generator do ["export", wh_sep, "{", wh_sep, specifiers, wh_sep, "};"] end - def do_generate(%ExportNamedDeclaration{declaration: nil, specifiers: specifiers, source: source}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ExportNamedDeclaration{declaration: nil, specifiers: specifiers, source: source}, %{wh_sep: wh_sep} = opts) do specifiers = specifiers |> Enum.map(&do_generate(&1, opts)) |> Enum.intersperse(opts.comma_sep) @@ -522,7 +522,7 @@ defmodule ESTree.Tools.Generator do # ExportSpecifier - def do_generate(%ExportSpecifier{local: local, exported: exported}, opts) do + defp do_generate(%ExportSpecifier{local: local, exported: exported}, opts) do if local == exported do do_generate(local, opts) else @@ -532,7 +532,7 @@ defmodule ESTree.Tools.Generator do # ExpressionStatement - def do_generate(%ExpressionStatement{expression: expression}, opts) do + defp do_generate(%ExpressionStatement{expression: expression}, opts) do precedence = Map.get(@expressions_precedence, expression.__struct__) if precedence == 17 or (precedence == 3 and expression.left.__struct__ == ObjectPattern) do @@ -544,7 +544,7 @@ defmodule ESTree.Tools.Generator do # ForInStatement - def do_generate(%ForInStatement{left: left, right: right, body: body}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ForInStatement{left: left, right: right, body: body}, %{wh_sep: wh_sep} = opts) do left = do_generate(left, %{opts | no_trailing_semicolon: true}) right = do_generate(right, opts) body = do_generate(body, opts) @@ -554,7 +554,7 @@ defmodule ESTree.Tools.Generator do # ForOfStatement - def do_generate(%ForOfStatement{left: left, right: right, body: body}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ForOfStatement{left: left, right: right, body: body}, %{wh_sep: wh_sep} = opts) do left = do_generate(left, %{opts | no_trailing_semicolon: true}) right = do_generate(right, opts) body = do_generate(body, opts) @@ -564,7 +564,7 @@ defmodule ESTree.Tools.Generator do # ForStatement - def do_generate(%ForStatement{init: init, test: test, update: update, body: body}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ForStatement{init: init, test: test, update: update, body: body}, %{wh_sep: wh_sep} = opts) do init = do_generate(init, %{opts | no_trailing_semicolon: true}) test = do_generate(test, opts) update = do_generate(update, opts) @@ -575,7 +575,7 @@ defmodule ESTree.Tools.Generator do # FunctionDeclaration - def do_generate(%FunctionDeclaration{generator: generator, async: async, id: id, params: params, defaults: defaults, body: body}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%FunctionDeclaration{generator: generator, async: async, id: id, params: params, defaults: defaults, body: body}, %{wh_sep: wh_sep} = opts) do generator = if generator, do: "*", else: "" async = if async, do: "async ", else: "" params = params_and_defaults(params, defaults, opts) @@ -593,7 +593,7 @@ defmodule ESTree.Tools.Generator do # FunctionExpression - def do_generate(%FunctionExpression{generator: generator, async: async, params: params, defaults: defaults, body: body}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%FunctionExpression{generator: generator, async: async, params: params, defaults: defaults, body: body}, %{wh_sep: wh_sep} = opts) do generator = if generator, do: "*", else: "" async = if async, do: "async ", else: "" params = params_and_defaults(params, defaults, opts) @@ -604,13 +604,13 @@ defmodule ESTree.Tools.Generator do # Identifier - def do_generate(%Identifier{name: name}, _opts) do + defp do_generate(%Identifier{name: name}, _opts) do to_string(name) end # IfStatement - def do_generate(%IfStatement{test: test, consequent: consequent, alternate: nil}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%IfStatement{test: test, consequent: consequent, alternate: nil}, %{wh_sep: wh_sep} = opts) do test = do_generate(test, opts) sep_c = if opts.beauty do @@ -637,7 +637,7 @@ defmodule ESTree.Tools.Generator do ["if", wh_sep, "(", test, ")", consequent] end - def do_generate(%IfStatement{test: test, consequent: consequent, alternate: alternate}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%IfStatement{test: test, consequent: consequent, alternate: alternate}, %{wh_sep: wh_sep} = opts) do test = do_generate(test, opts) sep_c = if opts.beauty do @@ -684,7 +684,7 @@ defmodule ESTree.Tools.Generator do # ImportDeclaration - def do_generate(%ImportDeclaration{specifiers: [%ImportDefaultSpecifier{}] = specifiers, source: source}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ImportDeclaration{specifiers: [%ImportDefaultSpecifier{}] = specifiers, source: source}, %{wh_sep: wh_sep} = opts) do specifiers = specifiers |> Enum.map(&do_generate(&1, opts)) |> Enum.intersperse(opts.comma_sep) @@ -694,7 +694,7 @@ defmodule ESTree.Tools.Generator do ["import ", specifiers, " from", wh_sep, source, ";"] end - def do_generate(%ImportDeclaration{specifiers: [%ImportNamespaceSpecifier{}] = specifiers, source: source}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ImportDeclaration{specifiers: [%ImportNamespaceSpecifier{}] = specifiers, source: source}, %{wh_sep: wh_sep} = opts) do specifiers = specifiers |> Enum.map(&do_generate(&1, opts)) |> Enum.intersperse(opts.comma_sep) @@ -702,7 +702,7 @@ defmodule ESTree.Tools.Generator do ["import", specifiers, " from", wh_sep, do_generate(source, opts), ";"] end - def do_generate(%ImportDeclaration{specifiers: specifiers, source: source}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ImportDeclaration{specifiers: specifiers, source: source}, %{wh_sep: wh_sep} = opts) do specifiers = specifiers |> Enum.map(&do_generate(&1, opts)) |> Enum.intersperse(opts.comma_sep) @@ -712,19 +712,19 @@ defmodule ESTree.Tools.Generator do # ImportDefaultSpecifier - def do_generate(%ImportDefaultSpecifier{local: local}, opts) do + defp do_generate(%ImportDefaultSpecifier{local: local}, opts) do do_generate(local, opts) end # ImportNamespaceSpecifier - def do_generate(%ImportNamespaceSpecifier{local: local}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ImportNamespaceSpecifier{local: local}, %{wh_sep: wh_sep} = opts) do [wh_sep, "*", wh_sep, "as ", do_generate(local, opts)] end # ImportSpecifier - def do_generate(%ImportSpecifier{local: local, imported: imported}, opts) do + defp do_generate(%ImportSpecifier{local: local, imported: imported}, opts) do if local == imported do do_generate(local, opts) else @@ -734,19 +734,19 @@ defmodule ESTree.Tools.Generator do # JSXAttribute - def do_generate(%JSXAttribute{name: name, value: value}, opts) do + defp do_generate(%JSXAttribute{name: name, value: value}, opts) do [do_generate(name, opts), "=", do_generate(value, opts)] end # JSXClosingElement - def do_generate(%JSXClosingElement{name: name}, opts) do + defp do_generate(%JSXClosingElement{name: name}, opts) do [""] end # JSXElement - def do_generate(%JSXElement{openingElement: opening_element, children: children, closingElement: closing_element}, opts) do + defp do_generate(%JSXElement{openingElement: opening_element, children: children, closingElement: closing_element}, opts) do opening_element = do_generate(opening_element, opts) children = generate_jsx_children(children, opts) closing_element = do_generate(closing_element, opts) @@ -756,41 +756,41 @@ defmodule ESTree.Tools.Generator do # JSXEmptyExpression - def do_generate(%JSXEmptyExpression{}, _opts) do + defp do_generate(%JSXEmptyExpression{}, _opts) do "" end # JSXExpressionContainer - def do_generate(%JSXExpressionContainer{expression: expression}, opts) do + defp do_generate(%JSXExpressionContainer{expression: expression}, opts) do ["{", do_generate(expression, opts), "}"] end # JSXIdentifier - def do_generate(%JSXIdentifier{name: name}, _opts) when is_binary(name) do + defp do_generate(%JSXIdentifier{name: name}, _opts) when is_binary(name) do name end - def do_generate(%JSXIdentifier{name: name}, _opts) when is_atom(name) do + defp do_generate(%JSXIdentifier{name: name}, _opts) when is_atom(name) do to_string(name) end # JSXMemberExpression - def do_generate(%JSXMemberExpression{object: object, property: property}, opts) do + defp do_generate(%JSXMemberExpression{object: object, property: property}, opts) do [do_generate(object, opts), ".", do_generate(property, opts)] end # JSXNamespacedName - def do_generate(%JSXNamespacedName{namespace: namespace, name: name}, opts) do + defp do_generate(%JSXNamespacedName{namespace: namespace, name: name}, opts) do [do_generate(namespace, opts), ":", do_generate(name, opts)] end # JSXOpeningElement - def do_generate(%JSXOpeningElement{name: name, attributes: attributes, selfClosing: self_closing}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%JSXOpeningElement{name: name, attributes: attributes, selfClosing: self_closing}, %{wh_sep: wh_sep} = opts) do self_closing = if self_closing, do: [wh_sep, "/"], else: "" attributes_value = cond do Enum.empty?(attributes) -> "" @@ -807,13 +807,13 @@ defmodule ESTree.Tools.Generator do # JSXSpreadAttribute - def do_generate(%JSXSpreadAttribute{argument: argument}, opts) do + defp do_generate(%JSXSpreadAttribute{argument: argument}, opts) do ["{...", do_generate(argument, opts), "}"] end # LabeledStatement - def do_generate(%LabeledStatement{label: label, body: body}, opts) do + defp do_generate(%LabeledStatement{label: label, body: body}, opts) do label = do_generate(label, opts) body = do_generate(body, opts) @@ -822,33 +822,33 @@ defmodule ESTree.Tools.Generator do # Literal - def do_generate(%Literal{value: nil}, _opts) do + defp do_generate(%Literal{value: nil}, _opts) do "null" end - def do_generate(%Literal{value: %{}, regex: regex}, _opts) do + defp do_generate(%Literal{value: %{}, regex: regex}, _opts) do ["/", regex.pattern, "/", regex.flags] end - def do_generate(%Literal{value: value}, _opts) when is_boolean(value) do + defp do_generate(%Literal{value: value}, _opts) when is_boolean(value) do to_string(value) end - def do_generate(%Literal{value: value}, _opts) when is_atom(value) do + defp do_generate(%Literal{value: value}, _opts) when is_atom(value) do ["'", to_string(value), "'"] end - def do_generate(%Literal{value: value}, _opts) when is_binary(value) do + defp do_generate(%Literal{value: value}, _opts) when is_binary(value) do ["'", escape_string(value), "'"] end - def do_generate(%Literal{value: value}, _opts) do + defp do_generate(%Literal{value: value}, _opts) do to_string(value) end # LogicalExpression - def do_generate(%LogicalExpression{operator: operator, left: left, right: right} = node, %{wh_sep: wh_sep} = opts) do + defp do_generate(%LogicalExpression{operator: operator, left: left, right: right} = node, %{wh_sep: wh_sep} = opts) do operator = do_generate(operator, opts) left = format_binary_expression(left, node, false, opts) right = format_binary_expression(right, node, true, opts) @@ -858,7 +858,7 @@ defmodule ESTree.Tools.Generator do # MemberExpression - def do_generate(%MemberExpression{object: object, property: property, computed: computed}, opts) do + defp do_generate(%MemberExpression{object: object, property: property, computed: computed}, opts) do precedence = Map.get(@expressions_precedence, object.__struct__) object = do_generate(object, opts) @@ -881,20 +881,20 @@ defmodule ESTree.Tools.Generator do # MetaProperty - def do_generate(%MetaProperty{meta: meta, property: property}, opts) do + defp do_generate(%MetaProperty{meta: meta, property: property}, opts) do [do_generate(meta, opts), ".", do_generate(property, opts)] end # MethodDefinition - def do_generate(%MethodDefinition{key: _key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :constructor}, opts) do + defp do_generate(%MethodDefinition{key: _key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :constructor}, opts) do params = params_and_defaults(params, defaults, opts) body = do_generate(body, opts) ["constructor(", params, ")", opts.wh_sep, body] end - def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :method, computed: false, static: false}, opts) do + defp do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :method, computed: false, static: false}, opts) do key = do_generate(key, opts) params = params_and_defaults(params, defaults, opts) body = do_generate(body, opts) @@ -902,7 +902,7 @@ defmodule ESTree.Tools.Generator do [key, "(", params, ")", opts.wh_sep, body] end - def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :method, computed: false, static: true}, opts) do + defp do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :method, computed: false, static: true}, opts) do key = do_generate(key, opts) params = params_and_defaults(params, defaults, opts) body = do_generate(body, opts) @@ -910,7 +910,7 @@ defmodule ESTree.Tools.Generator do ["static ", key, "(", params, ")", opts.wh_sep, body] end - def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :method, computed: true, static: false}, opts) do + defp do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :method, computed: true, static: false}, opts) do key = do_generate(key, opts) params = params_and_defaults(params, defaults, opts) body = do_generate(body, opts) @@ -918,7 +918,7 @@ defmodule ESTree.Tools.Generator do ["[", key, "](", params, ")", opts.wh_sep, body] end - def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :method, computed: true, static: true}, opts) do + defp do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :method, computed: true, static: true}, opts) do key = generate(key, opts) params = params_and_defaults(params, defaults, opts) body = do_generate(body, opts) @@ -926,14 +926,14 @@ defmodule ESTree.Tools.Generator do ["static [", key, "](", params, ")", opts.wh_sep, body] end - def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{body: body}, kind: :get, static: true}, opts) do + defp do_generate(%MethodDefinition{key: key, value: %FunctionExpression{body: body}, kind: :get, static: true}, opts) do key = generate(key, opts) body = do_generate(body, opts) ["static get ", key, "()", opts.wh_sep, body] end - def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :set, static: true}, opts) do + defp do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :set, static: true}, opts) do key = generate(key, opts) params = params_and_defaults(params, defaults, opts) body = do_generate(body, opts) @@ -941,14 +941,14 @@ defmodule ESTree.Tools.Generator do ["static set ", key, "(", params, ")", opts.wh_sep, body] end - def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{body: body}, kind: :get}, opts) do + defp do_generate(%MethodDefinition{key: key, value: %FunctionExpression{body: body}, kind: :get}, opts) do key = generate(key, opts) body = do_generate(body, opts) ["get ", key, "()", opts.wh_sep, body] end - def do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :set}, opts) do + defp do_generate(%MethodDefinition{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :set}, opts) do key = generate(key, opts) params = params_and_defaults(params, defaults, opts) body = do_generate(body, opts) @@ -958,7 +958,7 @@ defmodule ESTree.Tools.Generator do # NewExpression - def do_generate(%NewExpression{callee: callee, arguments: arguments}, opts) do + defp do_generate(%NewExpression{callee: callee, arguments: arguments}, opts) do precedence = Map.get(@expressions_precedence, callee.__struct__) callee = if precedence < @expressions_precedence[NewExpression] or has_call_expression(callee) do @@ -976,15 +976,15 @@ defmodule ESTree.Tools.Generator do # ObjectExpression - def do_generate(%ObjectExpression{properties: nil}, _opts) do + defp do_generate(%ObjectExpression{properties: nil}, _opts) do "{}" end - def do_generate(%ObjectExpression{properties: []}, _opts) do + defp do_generate(%ObjectExpression{properties: []}, _opts) do "{}" end - def do_generate(%ObjectExpression{properties: properties}, opts) do + defp do_generate(%ObjectExpression{properties: properties}, opts) do close_bracket = if opts.beauty do ["\n", indent(opts), "}"] else @@ -1015,7 +1015,7 @@ defmodule ESTree.Tools.Generator do # ObjectPattern - def do_generate(%ObjectPattern{properties: properties}, opts) do + defp do_generate(%ObjectPattern{properties: properties}, opts) do properties = properties |> Enum.map(&do_generate(&1, opts)) |> Enum.intersperse(opts.comma_sep) @@ -1025,11 +1025,11 @@ defmodule ESTree.Tools.Generator do # Program - def do_generate(%Program{body: []}, _opts) do + defp do_generate(%Program{body: []}, _opts) do "" end - def do_generate(%Program{body: body}, opts) do + defp do_generate(%Program{body: body}, opts) do sep = if opts.beauty do "\n\n" else @@ -1043,25 +1043,25 @@ defmodule ESTree.Tools.Generator do # Property - def do_generate(%Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: false}, %{colon_sep: colon_sep} = opts) do + defp do_generate(%Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: false}, %{colon_sep: colon_sep} = opts) do key = do_generate(key, opts) value = do_generate(value, opts) [key, colon_sep, value] end - def do_generate(%Property{key: key, value: _, kind: :init, shorthand: true, method: false, computed: false}, opts) do + defp do_generate(%Property{key: key, value: _, kind: :init, shorthand: true, method: false, computed: false}, opts) do do_generate(key, opts) end - def do_generate(%Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: true}, %{colon_sep: colon_sep} = opts) do + defp do_generate(%Property{key: key, value: value, kind: :init, shorthand: false, method: false, computed: true}, %{colon_sep: colon_sep} = opts) do key = do_generate(key, opts) value = do_generate(value, opts) ["[", key, "]", colon_sep, value] end - def do_generate(%Property{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :init, shorthand: false, method: true, computed: true}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%Property{key: key, value: %FunctionExpression{params: params, defaults: defaults, body: body}, kind: :init, shorthand: false, method: true, computed: true}, %{wh_sep: wh_sep} = opts) do key = do_generate(key, opts) params = params_and_defaults(params, defaults, opts) body = do_generate(body, opts) @@ -1069,21 +1069,21 @@ defmodule ESTree.Tools.Generator do ["[", key, "]", "(", params, ")", wh_sep, body] end - def do_generate(%Property{key: key, value: %FunctionExpression{body: body}, kind: :get, shorthand: false, method: true, computed: false}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%Property{key: key, value: %FunctionExpression{body: body}, kind: :get, shorthand: false, method: true, computed: false}, %{wh_sep: wh_sep} = opts) do key = do_generate(key, opts) body = do_generate(body, opts) [key, "()", wh_sep, body] end - def do_generate(%Property{key: key, value: %FunctionExpression{body: body}, kind: :get}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%Property{key: key, value: %FunctionExpression{body: body}, kind: :get}, %{wh_sep: wh_sep} = opts) do key = do_generate(key, opts) body = do_generate(body, opts) ["get ", key, "()", wh_sep, body] end - def do_generate(%Property{key: key, value: %FunctionExpression{params: params, body: body}, kind: :set, shorthand: false, method: true, computed: false}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%Property{key: key, value: %FunctionExpression{params: params, body: body}, kind: :set, shorthand: false, method: true, computed: false}, %{wh_sep: wh_sep} = opts) do key = do_generate(key, opts) params = do_generate(hd(params), opts) body = do_generate(body, opts) @@ -1091,7 +1091,7 @@ defmodule ESTree.Tools.Generator do [key, "(", params, ")", wh_sep, body] end - def do_generate(%Property{key: key, value: %FunctionExpression{params: params, body: body}, kind: :set}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%Property{key: key, value: %FunctionExpression{params: params, body: body}, kind: :set}, %{wh_sep: wh_sep} = opts) do key = do_generate(key, opts) params = do_generate(hd(params), opts) body = do_generate(body, opts) @@ -1101,22 +1101,22 @@ defmodule ESTree.Tools.Generator do # RestElement - def do_generate(%RestElement{argument: argument}, opts) do + defp do_generate(%RestElement{argument: argument}, opts) do ["...", do_generate(argument, opts)] end # ReturnStatement - def do_generate(%ReturnStatement{argument: nil}, _opts) do + defp do_generate(%ReturnStatement{argument: nil}, _opts) do "return;" end - def do_generate(%ReturnStatement{argument: argument}, opts) do + defp do_generate(%ReturnStatement{argument: argument}, opts) do ["return ", do_generate(argument, opts), ";"] end # SequenceExpression - def do_generate(%SequenceExpression{expressions: expressions}, opts) do + defp do_generate(%SequenceExpression{expressions: expressions}, opts) do expressions = expressions |> Enum.map(&do_generate(&1, opts)) |> Enum.intersperse(opts.comma_sep) @@ -1126,19 +1126,19 @@ defmodule ESTree.Tools.Generator do # SpreadElement - def do_generate(%SpreadElement{argument: argument}, opts) do + defp do_generate(%SpreadElement{argument: argument}, opts) do ["...", do_generate(argument, opts)] end # Super - def do_generate(%Super{}, _opts) do + defp do_generate(%Super{}, _opts) do "super" end # SwitchCase - def do_generate(%SwitchCase{test: nil, consequent: consequent}, opts) do + defp do_generate(%SwitchCase{test: nil, consequent: consequent}, opts) do start_sep = if opts.beauty do indent(opts, 1) else @@ -1158,7 +1158,7 @@ defmodule ESTree.Tools.Generator do [start_sep, "default:", sep, consequent] end - def do_generate(%SwitchCase{test: test, consequent: consequent}, opts) do + defp do_generate(%SwitchCase{test: test, consequent: consequent}, opts) do start_sep = if opts.beauty do indent(opts, 1) else @@ -1182,7 +1182,7 @@ defmodule ESTree.Tools.Generator do # SwitchStatement - def do_generate(%SwitchStatement{discriminant: discriminant, cases: cases}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%SwitchStatement{discriminant: discriminant, cases: cases}, %{wh_sep: wh_sep} = opts) do open_bracket = if opts.beauty do "{\n" else @@ -1214,25 +1214,25 @@ defmodule ESTree.Tools.Generator do # TaggedTemplateExpression - def do_generate(%TaggedTemplateExpression{tag: tag, quasi: quasi}, opts) do + defp do_generate(%TaggedTemplateExpression{tag: tag, quasi: quasi}, opts) do [do_generate(tag, opts), " ", do_generate(quasi, opts)] end # TemplateLiteral - def do_generate(%TemplateLiteral{expressions: [], quasis: []}, _opts) do + defp do_generate(%TemplateLiteral{expressions: [], quasis: []}, _opts) do "``" end - def do_generate(%TemplateLiteral{expressions: [expression], quasis: []}, opts) do + defp do_generate(%TemplateLiteral{expressions: [expression], quasis: []}, opts) do ["`${", do_generate(expression, opts), "}`"] end - def do_generate(%TemplateLiteral{expressions: [], quasis: [quasi]}, _opts) do + defp do_generate(%TemplateLiteral{expressions: [], quasis: [quasi]}, _opts) do ["`", escape_string(quasi.value.raw, false), "`"] end - def do_generate(%TemplateLiteral{expressions: expressions, quasis: quasis}, opts) do + defp do_generate(%TemplateLiteral{expressions: expressions, quasis: quasis}, opts) do elements = expressions ++ quasis literal = elements @@ -1254,33 +1254,33 @@ defmodule ESTree.Tools.Generator do # ThisExpression - def do_generate(%ThisExpression{}, _opts) do + defp do_generate(%ThisExpression{}, _opts) do "this" end # ThrowStatement - def do_generate(%ThrowStatement{argument: argument}, opts) do + defp do_generate(%ThrowStatement{argument: argument}, opts) do ["throw ", do_generate(argument, opts), ";"] end # TryStatement - def do_generate(%TryStatement{block: block, handler: handler, finalizer: nil}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%TryStatement{block: block, handler: handler, finalizer: nil}, %{wh_sep: wh_sep} = opts) do block = do_generate(block, opts) handler = do_generate(handler, opts) ["try", wh_sep, block, wh_sep, handler] end - def do_generate(%TryStatement{block: block, handler: nil, finalizer: finalizer}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%TryStatement{block: block, handler: nil, finalizer: finalizer}, %{wh_sep: wh_sep} = opts) do block = do_generate(block, opts) finalizer = do_generate(finalizer, opts) ["try", wh_sep, block, wh_sep, "finally", wh_sep, finalizer] end - def do_generate(%TryStatement{block: block, handler: handler, finalizer: finalizer}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%TryStatement{block: block, handler: handler, finalizer: finalizer}, %{wh_sep: wh_sep} = opts) do block = do_generate(block, opts) handler = do_generate(handler, opts) finalizer = do_generate(finalizer, opts) @@ -1290,7 +1290,7 @@ defmodule ESTree.Tools.Generator do # UnaryExpression - def do_generate(%UnaryExpression{operator: operator, prefix: true, argument: argument}, opts) do + defp do_generate(%UnaryExpression{operator: operator, prefix: true, argument: argument}, opts) do precedence = Map.get(@expressions_precedence, argument.__struct__) sep = if operator in [:delete, :typeof, :void], do: " ", else: "" @@ -1304,23 +1304,23 @@ defmodule ESTree.Tools.Generator do end end - def do_generate(%UnaryExpression{operator: operator, prefix: false, argument: argument}, opts) do + defp do_generate(%UnaryExpression{operator: operator, prefix: false, argument: argument}, opts) do [do_generate(argument, opts), do_generate(operator, opts)] end # UpdateExpression - def do_generate(%UpdateExpression{operator: operator, prefix: true, argument: argument}, opts) do + defp do_generate(%UpdateExpression{operator: operator, prefix: true, argument: argument}, opts) do [do_generate(operator, opts), do_generate(argument, opts)] end - def do_generate(%UpdateExpression{operator: operator, prefix: false, argument: argument}, opts) do + defp do_generate(%UpdateExpression{operator: operator, prefix: false, argument: argument}, opts) do [do_generate(argument, opts), do_generate(operator, opts)] end # VariableDeclaration - def do_generate(%VariableDeclaration{kind: kind, declarations: declarations}, opts) when kind in [:var, :let, :const] do + defp do_generate(%VariableDeclaration{kind: kind, declarations: declarations}, opts) when kind in [:var, :let, :const] do i = indent(next_indent(opts)) sep = if opts.beauty do if kind == :const do @@ -1347,29 +1347,29 @@ defmodule ESTree.Tools.Generator do # VariableDeclarator - def do_generate(%VariableDeclarator{id: id, init: nil}, opts) do + defp do_generate(%VariableDeclarator{id: id, init: nil}, opts) do do_generate(id, opts) end - def do_generate(%VariableDeclarator{id: id, init: %FunctionDeclaration{} = init}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%VariableDeclarator{id: id, init: %FunctionDeclaration{} = init}, %{wh_sep: wh_sep} = opts) do opts = %{next_indent(opts) | no_trailing_semicolon: true} [do_generate(id, opts), wh_sep, "=", wh_sep, do_generate(init, opts)] end - def do_generate(%VariableDeclarator{id: id, init: %FunctionExpression{} = init}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%VariableDeclarator{id: id, init: %FunctionExpression{} = init}, %{wh_sep: wh_sep} = opts) do opts = %{next_indent(opts) | no_trailing_semicolon: true} [do_generate(id, opts), wh_sep, "=", wh_sep, do_generate(init, opts)] end - def do_generate(%VariableDeclarator{id: id, init: init}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%VariableDeclarator{id: id, init: init}, %{wh_sep: wh_sep} = opts) do [do_generate(id, opts), wh_sep, "=", wh_sep, do_generate(init, opts)] end # WhileStatement - def do_generate(%WhileStatement{test: test, body: body}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%WhileStatement{test: test, body: body}, %{wh_sep: wh_sep} = opts) do test = do_generate(test, opts) body = do_generate(body, opts) @@ -1378,7 +1378,7 @@ defmodule ESTree.Tools.Generator do # WithStatement - def do_generate(%WithStatement{object: object, body: body}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%WithStatement{object: object, body: body}, %{wh_sep: wh_sep} = opts) do object = do_generate(object, opts) body = do_generate(body, opts) @@ -1387,11 +1387,11 @@ defmodule ESTree.Tools.Generator do # YieldExpression - def do_generate(%YieldExpression{argument: argument, delegate: false}, opts) do + defp do_generate(%YieldExpression{argument: argument, delegate: false}, opts) do ["yield ", do_generate(argument, opts)] end - def do_generate(%YieldExpression{argument: argument, delegate: true}, %{wh_sep: wh_sep} = opts) do + defp do_generate(%YieldExpression{argument: argument, delegate: true}, %{wh_sep: wh_sep} = opts) do ["yield*", wh_sep, do_generate(argument, opts)] end diff --git a/mix.exs b/mix.exs index 1df116f..f10710d 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule ESTree.Mixfile do def project do [app: :estree, - version: "2.4.2", + version: "2.5.0", elixir: "~> 1.0", deps: deps, description: description, @@ -17,8 +17,7 @@ defmodule ESTree.Mixfile do defp deps do [ - {:earmark, "~> 0.2", only: :dev}, - {:ex_doc, "~> 0.12", only: :dev}, + {:ex_doc, "~> 0.14", only: :dev}, {:dialyze, "~> 0.2", only: :dev}, {:shouldi, only: :test} ] diff --git a/mix.lock b/mix.lock index 250ff14..581a429 100644 --- a/mix.lock +++ b/mix.lock @@ -1,4 +1,4 @@ %{"dialyze": {:hex, :dialyze, "0.2.1", "9fb71767f96649020d769db7cbd7290059daff23707d6e851e206b1fdfa92f9d", [:mix], []}, - "earmark": {:hex, :earmark, "0.2.1", "ba6d26ceb16106d069b289df66751734802777a3cbb6787026dd800ffeb850f3", [:mix], []}, - "ex_doc": {:hex, :ex_doc, "0.12.0", "b774aabfede4af31c0301aece12371cbd25995a21bb3d71d66f5c2fe074c603f", [:mix], [{:earmark, "~> 0.2", [hex: :earmark, optional: false]}]}, + "earmark": {:hex, :earmark, "1.0.3", "89bdbaf2aca8bbb5c97d8b3b55c5dd0cff517ecc78d417e87f1d0982e514557b", [:mix], []}, + "ex_doc": {:hex, :ex_doc, "0.14.5", "c0433c8117e948404d93ca69411dd575ec6be39b47802e81ca8d91017a0cf83c", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]}, "shouldi": {:hex, :shouldi, "0.3.0", "ae3fb3cec3328057377a0aa750aa1bb9f8b321ba054e1e2c7211512c383fb6ff", [:mix], []}} From cf10f4fa302f44ee842d7e67d4682af6d5768cdd Mon Sep 17 00:00:00 2001 From: Mikalai Seva Date: Fri, 6 Jan 2017 13:32:03 +0100 Subject: [PATCH 14/31] Fix Elixir 1.4 warnings --- mix.exs | 10 +++++----- mix.lock | 2 +- test/test_helper.exs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mix.exs b/mix.exs index bab6806..fe85790 100644 --- a/mix.exs +++ b/mix.exs @@ -5,14 +5,14 @@ defmodule ESTree.Mixfile do [app: :estree, version: "2.4.1", elixir: "~> 1.0", - deps: deps, - description: description, - package: package, + deps: deps(), + description: description(), + package: package(), source_url: "https://github.com/bryanjos/elixir-estree"] end def application do - [applications: [:logger]] + [extra_applications: [:logger]] end defp deps do @@ -20,7 +20,7 @@ defmodule ESTree.Mixfile do {:earmark, "~> 0.2", only: :dev}, {:ex_doc, "~> 0.12", only: :dev}, {:dialyze, "~> 0.2", only: :dev}, - {:shouldi, only: :test} + {:shouldi, "~> 0.3.2", only: :test} ] end diff --git a/mix.lock b/mix.lock index 250ff14..a740b84 100644 --- a/mix.lock +++ b/mix.lock @@ -1,4 +1,4 @@ %{"dialyze": {:hex, :dialyze, "0.2.1", "9fb71767f96649020d769db7cbd7290059daff23707d6e851e206b1fdfa92f9d", [:mix], []}, "earmark": {:hex, :earmark, "0.2.1", "ba6d26ceb16106d069b289df66751734802777a3cbb6787026dd800ffeb850f3", [:mix], []}, "ex_doc": {:hex, :ex_doc, "0.12.0", "b774aabfede4af31c0301aece12371cbd25995a21bb3d71d66f5c2fe074c603f", [:mix], [{:earmark, "~> 0.2", [hex: :earmark, optional: false]}]}, - "shouldi": {:hex, :shouldi, "0.3.0", "ae3fb3cec3328057377a0aa750aa1bb9f8b321ba054e1e2c7211512c383fb6ff", [:mix], []}} + "shouldi": {:hex, :shouldi, "0.3.2", "971f614669b5f37c03507ba643bb8e59aa165ac50ca66d726c9db53be255e440", [:mix], []}} diff --git a/test/test_helper.exs b/test/test_helper.exs index dbfba27..b253595 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,3 +1,3 @@ -ExUnit.start(formatters: [ShouldI.CLIFormatter]) +ExUnit.start() Code.require_file "support.ex", __DIR__ From 036e4cd1395ced1d84a29639fe522f920b6ff42d Mon Sep 17 00:00:00 2001 From: Mikalai Seva Date: Fri, 6 Jan 2017 15:54:18 +0100 Subject: [PATCH 15/31] Correct indent if-else-if-else statements --- lib/es_tree/tools/generator.ex | 65 +++++----- test/tools/generator/formatting_test.exs | 146 ++++++++++++++++++++++- 2 files changed, 182 insertions(+), 29 deletions(-) diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index 41132da..d59cbfd 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -619,65 +619,76 @@ defmodule ESTree.Tools.Generator do "" end - sep_end = if opts.beauty do - "\n" - else - "" - end - consequent = case consequent do %BlockStatement{} -> [wh_sep, do_generate(consequent, opts)] _ -> - [sep_c, do_generate(consequent, opts), sep_end] + [sep_c, do_generate(consequent, opts)] end ["if", wh_sep, "(", test, ")", consequent] end defp do_generate(%IfStatement{test: test, consequent: consequent, alternate: alternate}, %{wh_sep: wh_sep} = opts) do - test = do_generate(test, opts) - - sep_c = if opts.beauty do - ["\n", indent(next_indent(opts))] - else - "" - end + is_cons_block = consequent.__struct__ == BlockStatement - sep_end = if opts.beauty do - "\n" - else - "" - end + i_1 = indent(opts) + i_2 = indent(next_indent(opts)) - {consequent, sep_if} = + consequent = case consequent do %BlockStatement{} -> - {[wh_sep, do_generate(consequent, opts)], wh_sep} + [wh_sep, do_generate(consequent, opts)] _ -> - {[sep_c, do_generate(consequent, opts), sep_end], ""} + indent = if opts.beauty do + ["\n", i_2] + else + "" + end + + [indent, do_generate(consequent, opts)] end - sep_a = if opts.beauty do - ["\n", indent(next_indent(opts))] + alternate_indent = if opts.beauty do + ["\n", i_2] else " " end - alternate = + alternate = if is_cons_block do case alternate do %BlockStatement{} -> [wh_sep, "else", wh_sep, do_generate(alternate, opts)] %IfStatement{} -> - [sep_if, "else ", do_generate(alternate, opts)] + [wh_sep, "else ", do_generate(alternate, opts)] + + _ -> + [wh_sep, "else", alternate_indent, do_generate(alternate, opts)] + end + else + indent = if opts.beauty do + ["\n", i_1] + else + "" + end + + case alternate do + %BlockStatement{} -> + [indent, "else", wh_sep, do_generate(alternate, opts)] + + %IfStatement{} -> + [indent, "else ", do_generate(alternate, opts)] _ -> - ["else", sep_a, do_generate(alternate, opts)] + [indent, "else", alternate_indent, do_generate(alternate, opts)] end + end + + test = do_generate(test, opts) ["if", wh_sep, "(", test, ")", consequent, alternate] end diff --git a/test/tools/generator/formatting_test.exs b/test/tools/generator/formatting_test.exs index ee28cd2..85a8737 100644 --- a/test/tools/generator/formatting_test.exs +++ b/test/tools/generator/formatting_test.exs @@ -35,7 +35,43 @@ defmodule ESTree.Tools.Generator.Formatting.Test do Builder.literal(-1) ) ) - ]) + ]), + Builder.if_statement( + Builder.literal(false), + Builder.block_statement([ + Builder.expression_statement( + Builder.assignment_expression( + :=, + Builder.identifier(:a), + Builder.literal(-2) + ) + ) + ]), + Builder.block_statement([ + Builder.expression_statement( + Builder.assignment_expression( + :=, + Builder.identifier(:a), + Builder.literal(-3) + ) + ) + ]) + ) + ), + Builder.if_statement( + Builder.literal(false), + Builder.return_statement( + Builder.literal(-1) + ), + Builder.if_statement( + Builder.literal(false), + Builder.return_statement( + Builder.literal(-2) + ), + Builder.return_statement( + Builder.literal(-3) + ) + ) ), Builder.switch_statement( Builder.literal(false), @@ -103,8 +139,19 @@ function test() { if (true) { a = -1; + } else if (false) { + a = -2; + } else { + a = -3; } + if (false) + return -1; + else if (false) + return -2; + else + return -3; + switch (false) { default: b = 0; @@ -123,7 +170,102 @@ test(); assert_gen ast, String.trim(str) - str = "function test(){var a,b,c=function(){return 1;};if(true){a=-1;}switch(false){default:b=0;break;}return {a:a+1,b:b+2,c:c+3};}test();" + str = "function test(){var a,b,c=function(){return 1;};if(true){a=-1;}else if(false){a=-2;}else{a=-3;}if(false)return -1;else if(false)return -2;else return -3;switch(false){default:b=0;break;}return {a:a+1,b:b+2,c:c+3};}test();" + + assert_gen ast, str, beauty: false + end + + should "format if statements correct" do + ast = Builder.program([ + Builder.function_declaration( + Builder.identifier(:test), + [], + [], + Builder.block_statement([ + Builder.if_statement( + Builder.literal(true), + Builder.block_statement([ + Builder.return_statement(Builder.literal(1)) + ]) + ), + Builder.if_statement( + Builder.literal(true), + Builder.return_statement(Builder.literal(1)) + ), + Builder.if_statement( + Builder.literal(true), + Builder.block_statement([ + Builder.return_statement(Builder.literal(1)) + ]), + Builder.return_statement(Builder.literal(2)) + ), + Builder.if_statement( + Builder.literal(true), + Builder.return_statement(Builder.literal(1)), + Builder.block_statement([ + Builder.return_statement(Builder.literal(2)) + ]) + ), + Builder.if_statement( + Builder.literal(true), + Builder.block_statement([ + Builder.return_statement(Builder.literal(1)) + ]), + Builder.if_statement( + Builder.literal(false), + Builder.return_statement(Builder.literal(2)) + ) + ), + Builder.if_statement( + Builder.literal(true), + Builder.return_statement(Builder.literal(1)), + Builder.if_statement( + Builder.literal(false), + Builder.block_statement([ + Builder.return_statement(Builder.literal(2)) + ]) + ) + ) + ]) + ) + ]) + + str = """ +function test() { + if (true) { + return 1; + } + + if (true) + return 1; + + if (true) { + return 1; + } else + return 2; + + if (true) + return 1; + else { + return 2; + } + + if (true) { + return 1; + } else if (false) + return 2; + + if (true) + return 1; + else if (false) { + return 2; + } +} +""" + + assert_gen ast, String.trim(str) + + str = "function test(){if(true){return 1;}if(true)return 1;if(true){return 1;}else return 2;if(true)return 1;else{return 2;}if(true){return 1;}else if(false)return 2;if(true)return 1;else if(false){return 2;}}" assert_gen ast, str, beauty: false end From 8964889670290db2346dd9f557a433f83e7524bc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 18 Feb 2017 11:10:03 -0600 Subject: [PATCH 16/31] Update version and changelog --- CHANGELOG.md | 4 ++++ mix.exs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63ffc66..da0e36d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v2.5.1 +* Enhancements: + * [Correct If statement identation](https://github.com/bryanjos/elixir-estree/pull/18) + # v2.5.0 * Enhancements: * [Greatly improved formatting of generated JavaScript](https://github.com/bryanjos/elixir-estree/pull/15) diff --git a/mix.exs b/mix.exs index 9c79d91..534e27a 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule ESTree.Mixfile do def project do [app: :estree, - version: "2.5.0", + version: "2.5.1", elixir: "~> 1.0", deps: deps(), description: description(), From da34ed68f56744df3837c8d5e3ac981318fa8bbf Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 8 Apr 2017 17:38:13 -0500 Subject: [PATCH 17/31] Add module to translate estree json into structural form --- lib/es_tree/tools/estree_json_transformer.ex | 569 +++++++++++++++++ mix.exs | 3 +- mix.lock | 1 + test/tools/estree_json_transformer_test.exs | 630 +++++++++++++++++++ 4 files changed, 1202 insertions(+), 1 deletion(-) create mode 100644 lib/es_tree/tools/estree_json_transformer.ex create mode 100644 test/tools/estree_json_transformer_test.exs diff --git a/lib/es_tree/tools/estree_json_transformer.ex b/lib/es_tree/tools/estree_json_transformer.ex new file mode 100644 index 0000000..fcf48a4 --- /dev/null +++ b/lib/es_tree/tools/estree_json_transformer.ex @@ -0,0 +1,569 @@ +defmodule ESTree.Tools.ESTreeJSONTransformer do + @moduledoc """ + Converts ESTree JSON into the Struct in the ESTree library + """ + + + @spec convert(%{}) :: ESTree.Node.t + def convert(json) + + def convert(%{"type" => "ArrayExpression"} = json) do + %ESTree.ArrayExpression{ + elements: convert_property(json, "elements", []) + } + end + + def convert(%{"type" => "ArrayPattern"} = json) do + %ESTree.ArrayPattern{ + elements: convert_property(json, "elements", []) + } + end + + def convert(%{"type" => "ArrowFunctionExpression"} = json) do + %ESTree.ArrowFunctionExpression{ + generator: convert_property(json, "generator", false), + expression: convert_property(json, "expression", false), + params: convert_property(json, "params", []), + body: convert_property(json, "body", []) + } + end + + def convert(%{"type" => "AssignmentExpression"} = json) do + %ESTree.AssignmentExpression{ + operator: convert_property_to_atom(json, "operator", "="), + left: convert_property(json, "left"), + right: convert_property(json, "right") + } + end + + def convert(%{"type" => "AssignmentPattern"} = json) do + %ESTree.AssignmentPattern{ + left: convert_property(json, "left"), + right: convert_property(json, "right") + } + end + + def convert(%{"type" => "AwaitExpression"} = json) do + %ESTree.AwaitExpression{ + argument: convert_property(json, "argument") + } + end + + def convert(%{"type" => "BinaryExpression"} = json) do + %ESTree.BinaryExpression{ + operator: convert_property_to_atom(json, "operator", "="), + left: convert_property(json, "left"), + right: convert_property(json, "right") + } + end + + def convert(%{"type" => "BlockStatement"} = json) do + %ESTree.BlockStatement{ + body: convert_property(json, "body", []) + } + end + + def convert(%{"type" => "BreakStatement"} = json) do + %ESTree.BreakStatement{ + label: convert_property(json, "label") + } + end + + def convert(%{"type" => "CallExpression"} = json) do + %ESTree.CallExpression{ + callee: convert_property(json, "callee", false), + arguments: convert_property(json, "arguments", []) + } + end + + def convert(%{"type" => "CatchClause"} = json) do + %ESTree.CatchClause{ + param: convert_property(json, "param"), + body: convert_property(json, "body") + } + end + + def convert(%{"type" => "ClassBody"} = json) do + %ESTree.ClassBody{ + body: convert_property(json, "body", []) + } + end + + def convert(%{"type" => "ClassDeclaration"} = json) do + %ESTree.ClassDeclaration{ + id: convert_property(json, "id"), + body: convert_property(json, "body"), + superClass: convert_property(json, "superClass") + } + end + + def convert(%{"type" => "ClassExpression"} = json) do + %ESTree.ClassExpression{ + body: convert_property(json, "body"), + superClass: convert_property(json, "superClass") + } + end + + def convert(%{"type" => "ConditionalStatement"} = json) do + %ESTree.ConditionalStatement{ + test: convert_property(json, "test"), + alternate: convert_property(json, "alternate"), + consequent: convert_property(json, "consequent") + } + end + + def convert(%{"type" => "ContinueStatement"} = json) do + %ESTree.ContinueStatement{ + label: convert_property(json, "label") + } + end + + def convert(%{"type" => "DebuggerStatement"}) do + %ESTree.DebuggerStatement{} + end + + def convert(%{"type" => "DoWhileStatement"} = json) do + %ESTree.DoWhileStatement{ + test: convert_property(json, "test"), + body: convert_property(json, "body") + } + end + + def convert(%{"type" => "EmptyExpression"}) do + %ESTree.EmptyExpression{} + end + + def convert(%{"type" => "EmptyStatement"}) do + %ESTree.EmptyStatement{} + end + + def convert(%{"type" => "ExportAllDeclaration"} = json) do + %ESTree.ExportAllDeclaration{ + source: convert_property(json, "source") + } + end + + def convert(%{"type" => "ExportDefaultDeclaration"} = json) do + %ESTree.ExportDefaultDeclaration{ + declaration: convert_property(json, "declaration") + } + end + + def convert(%{"type" => "ExportNamedDeclaration"} = json) do + %ESTree.ExportNamedDeclaration{ + declaration: convert_property(json, "declaration"), + specifiers: convert_property(json, "specifiers", []), + source: convert_property(json, "source") + } + end + + def convert(%{"type" => "ExportSpecifier"} = json) do + %ESTree.ExportSpecifier{ + local: convert_property(json, "local"), + exported: convert_property(json, "exported") + } + end + + def convert(%{"type" => "ExpressionStatement"} = json) do + %ESTree.ExpressionStatement{ + expression: convert_property(json, "expression") + } + end + + def convert(%{"type" => "ForInStatement"} = json) do + %ESTree.ForInStatement{ + left: convert_property(json, "left"), + right: convert_property(json, "right"), + body: convert_property(json, "body") + } + end + + def convert(%{"type" => "ForOfStatement"} = json) do + %ESTree.ForOfStatement{ + left: convert_property(json, "left"), + right: convert_property(json, "right"), + body: convert_property(json, "body") + } + end + + def convert(%{"type" => "ForStatement"} = json) do + %ESTree.ForStatement{ + init: convert_property(json, "init"), + test: convert_property(json, "test"), + update: convert_property(json, "update"), + body: convert_property(json, "body") + } + end + + def convert(%{"type" => "FunctionDeclaration"} = json) do + %ESTree.FunctionDeclaration{ + id: convert_property(json, "id"), + params: convert_property(json, "params", []), + defaults: convert_property(json, "defaults", []), + body: convert_property(json, "body"), + generator: convert_property(json, "generator", false), + expression: convert_property(json, "expression", false), + async: convert_property(json, "async", false) + } + end + + def convert(%{"type" => "FunctionExpression"} = json) do + %ESTree.FunctionExpression{ + params: convert_property(json, "params", []), + defaults: convert_property(json, "defaults", []), + body: convert_property(json, "body"), + generator: convert_property(json, "generator", false), + expression: convert_property(json, "expression", false), + async: convert_property(json, "async", false) + } + end + + def convert(%{"type" => "Identifier"} = json) do + %ESTree.Identifier{ + name: convert_property(json, "name") + } + end + + def convert(%{"type" => "IfStatement"} = json) do + %ESTree.IfStatement{ + test: convert_property(json, "test"), + consequent: convert_property(json, "consequent"), + alternate: convert_property(json, "alternate") + } + end + + def convert(%{"type" => "ImportDeclaration"} = json) do + %ESTree.ImportDeclaration{ + specifiers: convert_property(json, "specifiers", []), + source: convert_property(json, "source") + } + end + + def convert(%{"type" => "ImportDefaultSpecifier"} = json) do + %ESTree.ImportDefaultSpecifier{ + local: convert_property(json, "local") + } + end + + def convert(%{"type" => "ImportNamespaceSpecifier"} = json) do + %ESTree.ImportNamespaceSpecifier{ + local: convert_property(json, "local") + } + end + + def convert(%{"type" => "ImportSpecifier"} = json) do + %ESTree.ImportSpecifier{ + local: convert_property(json, "local"), + imported: convert_property(json, "imported") + } + end + + def convert(%{"type" => "JSXAttribute"} = json) do + %ESTree.JSXAttribute{ + name: convert_property(json, "name"), + value: convert_property(json, "value") + } + end + + def convert(%{"type" => "JSXClosingElement"} = json) do + %ESTree.JSXClosingElement{ + name: convert_property(json, "name") + } + end + + def convert(%{"type" => "JSXElement"} = json) do + %ESTree.JSXElement{ + openingElement: convert_property(json, "openingElement"), + children: convert_property(json, "children", []), + closingElement: convert_property(json, "closingElement") + } + end + + def convert(%{"type" => "JSXEmptyExpression"}) do + %ESTree.JSXEmptyExpression{} + end + + def convert(%{"type" => "JSXExpressionContainer"} = json) do + %ESTree.JSXExpressionContainer{ + expression: convert_property(json, "expression") + } + end + + def convert(%{"type" => "JSXIdentifier"} = json) do + %ESTree.JSXIdentifier{ + name: convert_property(json, "name") + } + end + + def convert(%{"type" => "JSXMemberExpression"} = json) do + %ESTree.JSXMemberExpression{ + object: convert_property(json, "object"), + property: convert_property(json, "property") + } + end + + def convert(%{"type" => "JSXNamespacedName"} = json) do + %ESTree.JSXNamespacedName{ + namespace: convert_property(json, "namespace"), + name: convert_property(json, "name") + } + end + + def convert(%{"type" => "JSXOpeningElement"} = json) do + %ESTree.JSXOpeningElement{ + name: convert_property(json, "name"), + attributes: convert_property(json, "attributes", []), + selfClosing: convert_property(json, "selfClosing", false) + } + end + + def convert(%{"type" => "JSXSpreadAttribute"} = json) do + %ESTree.JSXSpreadAttribute{ + argument: convert_property(json, "argument") + } + end + + def convert(%{"type" => "LabeledStatement"} = json) do + %ESTree.LabeledStatement{ + label: convert_property(json, "label"), + body: convert_property(json, "body") + } + end + + def convert(%{"type" => "Literal"} = json) do + %ESTree.Literal{ + value: convert_property(json, "value") + } + end + + def convert(%{"type" => "LogicalExpression"} = json) do + %ESTree.LogicalExpression{ + operator: convert_property_to_atom(json, "operator", ""), + left: convert_property(json, "left"), + right: convert_property(json, "right") + } + end + + def convert(%{"type" => "MemberExpression"} = json) do + %ESTree.MemberExpression{ + object: convert_property(json, "object"), + property: convert_property(json, "property"), + computed: convert_property(json, "computed", false) + } + end + + def convert(%{"type" => "MetaProperty"} = json) do + %ESTree.MetaProperty{ + meta: convert_property(json, "meta"), + property: convert_property(json, "property") + } + end + + def convert(%{"type" => "MethodDefinition"} = json) do + %ESTree.MethodDefinition{ + key: convert_property(json, "key"), + value: convert_property(json, "value"), + kind: convert_property_to_atom(json, "kind", ""), + computed: convert_property(json, "computed", false), + static: convert_property(json, "static", false) + } + end + + def convert(%{"type" => "NewExpression"} = json) do + %ESTree.NewExpression{ + callee: convert_property(json, "callee", false), + arguments: convert_property(json, "arguments", []) + } + end + + def convert(%{"type" => "ObjectExpression"} = json) do + %ESTree.ObjectExpression{ + properties: convert_property(json, "properties", []) + } + end + + def convert(%{"type" => "ObjectPattern"} = json) do + %ESTree.ObjectPattern{ + properties: convert_property(json, "properties", []) + } + end + + def convert(%{"type" => "Program"} = json) do + %ESTree.Program{ + body: convert_property(json, "body", []), + sourceType: convert_property(json, "sourceType", "module") + } + end + + def convert(%{"type" => "Property"} = json) do + %ESTree.Property{ + key: convert_property(json, "key"), + value: convert_property(json, "value"), + kind: convert_property_to_atom(json, "kind", ""), + method: convert_property(json, "method", false), + shorthand: convert_property(json, "shorthand", false), + computed: convert_property(json, "computed", false) + } + end + + def convert(%{"type" => "RestElement"} = json) do + %ESTree.RestElement{ + argument: convert_property(json, "argument") + } + end + + def convert(%{"type" => "ReturnStatement"} = json) do + %ESTree.ReturnStatement{ + argument: convert_property(json, "argument") + } + end + + def convert(%{"type" => "SequenceExpression"} = json) do + %ESTree.SequenceExpression{ + expressions: convert_property(json, "expressions", []) + } + end + + def convert(%{"type" => "SpreadElement"} = json) do + %ESTree.SpreadElement{ + argument: convert_property(json, "argument") + } + end + + def convert(%{"type" => "Super"}) do + %ESTree.Super{} + end + + def convert(%{"type" => "SwitchCase"} = json) do + %ESTree.SwitchCase{ + test: convert_property(json, "test"), + consequent: convert_property(json, "consequent") + } + end + + def convert(%{"type" => "SwitchStatement"} = json) do + %ESTree.SwitchStatement{ + discriminant: convert_property(json, "discriminant"), + cases: convert_property(json, "cases", []) + } + end + + def convert(%{"type" => "TaggedTemplateExpression"} = json) do + %ESTree.TaggedTemplateExpression{ + tag: convert_property(json, "tag"), + quasi: convert_property(json, "quasi") + } + end + + def convert(%{"type" => "TemplateElement"} = json) do + value = case Map.get(json, "value") do + map when is_map(map) -> + %{ + cooked: convert_property(map, "cooked"), + raw: convert_property(map, "raw") + } + other -> + other + end + + %ESTree.TemplateElement{ + value: value, + tail: convert_property(json, "tail", false) + } + end + + def convert(%{"type" => "TemplateLiteral"} = json) do + %ESTree.TemplateLiteral{ + quasis: convert_property(json, "quasis", []), + expressions: convert_property(json, "expressions", []) + } + end + + def convert(%{"type" => "ThisExpression"}) do + %ESTree.ThisExpression{} + end + + def convert(%{"type" => "ThrowStatement"} = json) do + %ESTree.ThrowStatement{ + argument: convert_property(json, "argument") + } + end + + def convert(%{"type" => "TryStatement"} = json) do + %ESTree.TryStatement{ + block: convert_property(json, "block"), + handler: convert_property(json, "handler"), + finalizer: convert_property(json, "finalizer") + } + end + + def convert(%{"type" => "UnaryExpression"} = json) do + %ESTree.UnaryExpression{ + operator: convert_property_to_atom(json, "operator", ""), + prefix: convert_property(json, "prefix", false), + argument: convert_property(json, "argument") + } + end + + def convert(%{"type" => "UpdateExpression"} = json) do + %ESTree.UpdateExpression{ + operator: convert_property_to_atom(json, "operator", ""), + prefix: convert_property(json, "prefix", false), + argument: convert_property(json, "argument") + } + end + + def convert(%{"type" => "VariableDeclaration"} = json) do + %ESTree.VariableDeclaration{ + kind: convert_property_to_atom(json, "kind", "var"), + declarations: convert_property(json, "declarations", []) + } + end + + def convert(%{"type" => "VariableDeclarator"} = json) do + %ESTree.VariableDeclarator{ + id: convert_property(json, "id"), + init: convert_property(json, "init") + } + end + + def convert(%{"type" => "WhileStatement"} = json) do + %ESTree.WhileStatement{ + test: convert_property(json, "test"), + body: convert_property(json, "body") + } + end + + def convert(%{"type" => "WithStatement"} = json) do + %ESTree.WithStatement{ + object: convert_property(json, "object"), + body: convert_property(json, "body") + } + end + + def convert(%{"type" => "YieldExpression"} = json) do + %ESTree.YieldExpression{ + argument: convert_property(json, "argument"), + delegate: convert_property(json, "delegate", false) + } + end + + defp convert_property_to_atom(json, property, default) do + json + |> Map.get(property, default) + |> String.to_atom() + end + + defp convert_property(json, property, default \\ nil) do + case Map.get(json, property, default) do + nil -> + nil + list when is_list(list) -> + Enum.map(list, &convert/1) + map when is_map(map) -> + convert(map) + val -> + val + end + end +end \ No newline at end of file diff --git a/mix.exs b/mix.exs index 534e27a..ebeef40 100644 --- a/mix.exs +++ b/mix.exs @@ -19,7 +19,8 @@ defmodule ESTree.Mixfile do [ {:ex_doc, "~> 0.14", only: :dev}, {:dialyze, "~> 0.2", only: :dev}, - {:shouldi, "~> 0.3.2", only: :test} + {:shouldi, "~> 0.3.2", only: :test}, + {:poison, "~> 3.0", only: :test}, ] end diff --git a/mix.lock b/mix.lock index 30849d7..8b6f498 100644 --- a/mix.lock +++ b/mix.lock @@ -1,4 +1,5 @@ %{"dialyze": {:hex, :dialyze, "0.2.1", "9fb71767f96649020d769db7cbd7290059daff23707d6e851e206b1fdfa92f9d", [:mix], []}, "earmark": {:hex, :earmark, "1.0.3", "89bdbaf2aca8bbb5c97d8b3b55c5dd0cff517ecc78d417e87f1d0982e514557b", [:mix], []}, "ex_doc": {:hex, :ex_doc, "0.14.5", "c0433c8117e948404d93ca69411dd575ec6be39b47802e81ca8d91017a0cf83c", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]}, + "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []}, "shouldi": {:hex, :shouldi, "0.3.2", "971f614669b5f37c03507ba643bb8e59aa165ac50ca66d726c9db53be255e440", [:mix], []}} diff --git a/test/tools/estree_json_transformer_test.exs b/test/tools/estree_json_transformer_test.exs new file mode 100644 index 0000000..57fdf9a --- /dev/null +++ b/test/tools/estree_json_transformer_test.exs @@ -0,0 +1,630 @@ +defmodule ESTree.Tools.ESTreeJSONTransformer.Test do + use ExUnit.Case, async: true + + alias ESTree.Tools.ESTreeJSONTransformer, as: EJT + + + test "convert json to structs" do + map = json() |> Poison.decode! + structs = EJT.convert(map) + + assert structs.type === "Program" + end + + + def json() do + """ + { + "type": "Program", + "start": 0, + "end": 215, + "range": [ + 0, + 215 + ], + "body": [ + { + "type": "FunctionDeclaration", + "start": 0, + "end": 215, + "range": [ + 0, + 215 + ], + "id": { + "type": "Identifier", + "start": 9, + "end": 17, + "range": [ + 9, + 17 + ], + "name": "fizzBuzz" + }, + "generator": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 19, + "end": 215, + "range": [ + 19, + 215 + ], + "body": [ + { + "type": "ForStatement", + "start": 22, + "end": 213, + "range": [ + 22, + 213 + ], + "init": { + "type": "VariableDeclaration", + "start": 26, + "end": 33, + "range": [ + 26, + 33 + ], + "declarations": [ + { + "type": "VariableDeclarator", + "start": 30, + "end": 33, + "range": [ + 30, + 33 + ], + "id": { + "type": "Identifier", + "start": 30, + "end": 31, + "range": [ + 30, + 31 + ], + "name": "i" + }, + "init": { + "type": "Literal", + "start": 32, + "end": 33, + "range": [ + 32, + 33 + ], + "value": 1, + "raw": "1" + } + } + ], + "kind": "var" + }, + "test": { + "type": "BinaryExpression", + "start": 34, + "end": 40, + "range": [ + 34, + 40 + ], + "left": { + "type": "Identifier", + "start": 34, + "end": 35, + "range": [ + 34, + 35 + ], + "name": "i" + }, + "operator": "<=", + "right": { + "type": "Literal", + "start": 37, + "end": 40, + "range": [ + 37, + 40 + ], + "value": 100, + "raw": "100" + } + }, + "update": { + "type": "UpdateExpression", + "start": 41, + "end": 44, + "range": [ + 41, + 44 + ], + "operator": "++", + "prefix": false, + "argument": { + "type": "Identifier", + "start": 41, + "end": 42, + "range": [ + 41, + 42 + ], + "name": "i" + } + }, + "body": { + "type": "BlockStatement", + "start": 45, + "end": 213, + "range": [ + 45, + 213 + ], + "body": [ + { + "type": "IfStatement", + "start": 49, + "end": 210, + "range": [ + 49, + 210 + ], + "test": { + "type": "LogicalExpression", + "start": 52, + "end": 74, + "range": [ + 52, + 74 + ], + "left": { + "type": "BinaryExpression", + "start": 52, + "end": 61, + "range": [ + 52, + 61 + ], + "left": { + "type": "BinaryExpression", + "start": 52, + "end": 55, + "range": [ + 52, + 55 + ], + "left": { + "type": "Identifier", + "start": 52, + "end": 53, + "range": [ + 52, + 53 + ], + "name": "i" + }, + "operator": "%", + "right": { + "type": "Literal", + "start": 54, + "end": 55, + "range": [ + 54, + 55 + ], + "value": 5, + "raw": "5" + } + }, + "operator": "===", + "right": { + "type": "Literal", + "start": 60, + "end": 61, + "range": [ + 60, + 61 + ], + "value": 0, + "raw": "0" + } + }, + "operator": "&&", + "right": { + "type": "BinaryExpression", + "start": 65, + "end": 74, + "range": [ + 65, + 74 + ], + "left": { + "type": "BinaryExpression", + "start": 65, + "end": 68, + "range": [ + 65, + 68 + ], + "left": { + "type": "Identifier", + "start": 65, + "end": 66, + "range": [ + 65, + 66 + ], + "name": "i" + }, + "operator": "%", + "right": { + "type": "Literal", + "start": 67, + "end": 68, + "range": [ + 67, + 68 + ], + "value": 3, + "raw": "3" + } + }, + "operator": "===", + "right": { + "type": "Literal", + "start": 73, + "end": 74, + "range": [ + 73, + 74 + ], + "value": 0, + "raw": "0" + } + } + }, + "consequent": { + "type": "BlockStatement", + "start": 75, + "end": 102, + "range": [ + 75, + 102 + ], + "body": [ + { + "type": "ExpressionStatement", + "start": 80, + "end": 98, + "range": [ + 80, + 98 + ], + "expression": { + "type": "CallExpression", + "start": 80, + "end": 97, + "range": [ + 80, + 97 + ], + "callee": { + "type": "Identifier", + "start": 80, + "end": 85, + "range": [ + 80, + 85 + ], + "name": "print" + }, + "arguments": [ + { + "type": "Literal", + "start": 86, + "end": 96, + "range": [ + 86, + 96 + ], + "value": "FizzBuzz", + "raw": "'FizzBuzz'" + } + ] + } + } + ] + }, + "alternate": { + "type": "IfStatement", + "start": 108, + "end": 210, + "range": [ + 108, + 210 + ], + "test": { + "type": "BinaryExpression", + "start": 111, + "end": 120, + "range": [ + 111, + 120 + ], + "left": { + "type": "BinaryExpression", + "start": 111, + "end": 114, + "range": [ + 111, + 114 + ], + "left": { + "type": "Identifier", + "start": 111, + "end": 112, + "range": [ + 111, + 112 + ], + "name": "i" + }, + "operator": "%", + "right": { + "type": "Literal", + "start": 113, + "end": 114, + "range": [ + 113, + 114 + ], + "value": 3, + "raw": "3" + } + }, + "operator": "===", + "right": { + "type": "Literal", + "start": 119, + "end": 120, + "range": [ + 119, + 120 + ], + "value": 0, + "raw": "0" + } + }, + "consequent": { + "type": "BlockStatement", + "start": 121, + "end": 144, + "range": [ + 121, + 144 + ], + "body": [ + { + "type": "ExpressionStatement", + "start": 126, + "end": 140, + "range": [ + 126, + 140 + ], + "expression": { + "type": "CallExpression", + "start": 126, + "end": 139, + "range": [ + 126, + 139 + ], + "callee": { + "type": "Identifier", + "start": 126, + "end": 131, + "range": [ + 126, + 131 + ], + "name": "print" + }, + "arguments": [ + { + "type": "Literal", + "start": 132, + "end": 138, + "range": [ + 132, + 138 + ], + "value": "Fizz", + "raw": "'Fizz'" + } + ] + } + } + ] + }, + "alternate": { + "type": "IfStatement", + "start": 150, + "end": 210, + "range": [ + 150, + 210 + ], + "test": { + "type": "BinaryExpression", + "start": 153, + "end": 162, + "range": [ + 153, + 162 + ], + "left": { + "type": "BinaryExpression", + "start": 153, + "end": 156, + "range": [ + 153, + 156 + ], + "left": { + "type": "Identifier", + "start": 153, + "end": 154, + "range": [ + 153, + 154 + ], + "name": "i" + }, + "operator": "%", + "right": { + "type": "Literal", + "start": 155, + "end": 156, + "range": [ + 155, + 156 + ], + "value": 5, + "raw": "5" + } + }, + "operator": "===", + "right": { + "type": "Literal", + "start": 161, + "end": 162, + "range": [ + 161, + 162 + ], + "value": 0, + "raw": "0" + } + }, + "consequent": { + "type": "BlockStatement", + "start": 163, + "end": 186, + "range": [ + 163, + 186 + ], + "body": [ + { + "type": "ExpressionStatement", + "start": 168, + "end": 182, + "range": [ + 168, + 182 + ], + "expression": { + "type": "CallExpression", + "start": 168, + "end": 181, + "range": [ + 168, + 181 + ], + "callee": { + "type": "Identifier", + "start": 168, + "end": 173, + "range": [ + 168, + 173 + ], + "name": "print" + }, + "arguments": [ + { + "type": "Literal", + "start": 174, + "end": 180, + "range": [ + 174, + 180 + ], + "value": "Buzz", + "raw": "'Buzz'" + } + ] + } + } + ] + }, + "alternate": { + "type": "BlockStatement", + "start": 192, + "end": 210, + "range": [ + 192, + 210 + ], + "body": [ + { + "type": "ExpressionStatement", + "start": 197, + "end": 206, + "range": [ + 197, + 206 + ], + "expression": { + "type": "CallExpression", + "start": 197, + "end": 205, + "range": [ + 197, + 205 + ], + "callee": { + "type": "Identifier", + "start": 197, + "end": 202, + "range": [ + 197, + 202 + ], + "name": "print" + }, + "arguments": [ + { + "type": "Identifier", + "start": 203, + "end": 204, + "range": [ + 203, + 204 + ], + "name": "i" + } + ] + } + } + ] + } + } + } + } + ] + } + } + ] + } + } + ], + "sourceType": "module" +} + """ + end +end \ No newline at end of file From 6d205c616d35711cf1990d9d1b14720822c1f43f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Apr 2017 18:55:13 -0500 Subject: [PATCH 18/31] Add parenthesis when an await is within an await or call --- lib/es_tree/tools/generator.ex | 11 +++++++- .../tools/generator/await_expression_test.exs | 24 ++++++++++++++++ test/tools/generator/call_expression_test.exs | 28 +++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 test/tools/generator/await_expression_test.exs diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index d59cbfd..16c18df 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -263,6 +263,10 @@ defmodule ESTree.Tools.Generator do # AwaitExpression + defp do_generate(%AwaitExpression{argument: %AwaitExpression{} = argument, all: _all}, opts) do + ["await ", "(", do_generate(argument, opts), ")"] + end + defp do_generate(%AwaitExpression{argument: argument, all: _all}, opts) do ["await ", do_generate(argument, opts)] end @@ -347,7 +351,12 @@ defmodule ESTree.Tools.Generator do end arguments = arguments - |> Enum.map(&do_generate(&1, opts)) + |> Enum.map(fn + %s{} = x when s in [AwaitExpression, YieldExpression] -> + ["("] ++ do_generate(x, opts) ++ [")"] + x -> + do_generate(x, opts) + end) |> Enum.intersperse(opts.comma_sep) [callee, "(", arguments, ")"] diff --git a/test/tools/generator/await_expression_test.exs b/test/tools/generator/await_expression_test.exs new file mode 100644 index 0000000..b91e13e --- /dev/null +++ b/test/tools/generator/await_expression_test.exs @@ -0,0 +1,24 @@ +defmodule ESTree.Tools.Generator.AwaitExpression.Test do + use ShouldI + + alias ESTree.Tools.Builder + import ESTree.Test.Support + + should "convert await expression" do + ast = Builder.await_expression( + Builder.literal(1) + ) + + assert_gen ast, "await 1" + end + + should "convert await expression that contains an await" do + ast = Builder.await_expression( + Builder.await_expression( + Builder.literal(1) + ) + ) + + assert_gen ast, "await (await 1)" + end +end \ No newline at end of file diff --git a/test/tools/generator/call_expression_test.exs b/test/tools/generator/call_expression_test.exs index 57add86..e6bc203 100644 --- a/test/tools/generator/call_expression_test.exs +++ b/test/tools/generator/call_expression_test.exs @@ -91,4 +91,32 @@ defmodule ESTree.Tools.Generator.CallExpression.Test do assert_gen ast, "(a + b).x()" assert_gen ast, "(a+b).x()", beauty: false end + + should "convert call expression with one argument that is an await" do + ast = Builder.call_expression( + Builder.identifier(:x), + [ + Builder.await_expression( + Builder.identifier(:a) + ) + ] + ); + + assert_gen ast, "x((await a))" + assert_gen ast, "x((await a))", beauty: false + end + + should "convert call expression with one argument that is a yield" do + ast = Builder.call_expression( + Builder.identifier(:x), + [ + Builder.yield_expression( + Builder.identifier(:a) + ) + ] + ); + + assert_gen ast, "x((yield a))" + assert_gen ast, "x((yield a))", beauty: false + end end From 28cb3fc0f9efa7b711756e787dc59ba37beaae54 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Apr 2017 19:00:19 -0500 Subject: [PATCH 19/31] Add travis.yml --- .travis.yml | 6 ++++++ README.md | 1 + 2 files changed, 7 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..8149148 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +sudo: false +language: elixir +elixir: + - 1.4.2 +otp_release: + - 19.3 \ No newline at end of file diff --git a/README.md b/README.md index d374cc6..49c3274 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ ## Elixir-ESTree [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/estree/) [![Downloads](https://img.shields.io/hexpm/dt/estree.svg)](https://hex.pm/packages/estree) +[![Build Status](https://travis-ci.org/elixirscript/elixir-estree.svg?branch=master)](https://travis-ci.org/elixirscript/elixir-estree) Defines structs that represent the JavaScript AST nodes from the ESTree spec. From 128ba24b339098fadd1fec8ef9a985aebfd03bfe Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Apr 2017 19:03:29 -0500 Subject: [PATCH 20/31] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 49c3274..634393b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -## Elixir-ESTree [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/estree/) [![Downloads](https://img.shields.io/hexpm/dt/estree.svg)](https://hex.pm/packages/estree) -[![Build Status](https://travis-ci.org/elixirscript/elixir-estree.svg?branch=master)](https://travis-ci.org/elixirscript/elixir-estree) +## Elixir-ESTree [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/estree/) [![Downloads](https://img.shields.io/hexpm/dt/estree.svg)](https://hex.pm/packages/estree) [![Build Status](https://travis-ci.org/elixirscript/elixir-estree.svg?branch=master)](https://travis-ci.org/elixirscript/elixir-estree) + Defines structs that represent the JavaScript AST nodes from the ESTree spec. From bbc921e6721d300c6868259994720d6336d178fc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Apr 2017 19:05:59 -0500 Subject: [PATCH 21/31] Update module doc --- lib/es_tree/tools/estree_json_transformer.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/es_tree/tools/estree_json_transformer.ex b/lib/es_tree/tools/estree_json_transformer.ex index fcf48a4..9ba23da 100644 --- a/lib/es_tree/tools/estree_json_transformer.ex +++ b/lib/es_tree/tools/estree_json_transformer.ex @@ -1,6 +1,6 @@ defmodule ESTree.Tools.ESTreeJSONTransformer do @moduledoc """ - Converts ESTree JSON into the Struct in the ESTree library + Converts ESTree JSON into the structs in the ESTree library """ From 8f9427a29ee0a6ab9e565bae554a8b95af3b675a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Apr 2017 19:12:07 -0500 Subject: [PATCH 22/31] Update changelog --- CHANGELOG.md | 5 +++++ mix.exs | 4 ++-- mix.lock | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da0e36d..1d74d7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v2.6.0 +* Enhancements: + * [Add parenthesis around await expressions in await expressions or in call expressions](https://github.com/elixirscript/elixir-estree/pull/20) + * [Add ESTree.Tools.ESTreeJSONTransformer to translate ESTree JSON data into structs](https://github.com/bryanjos/elixir-estree/pull/21) + # v2.5.1 * Enhancements: * [Correct If statement identation](https://github.com/bryanjos/elixir-estree/pull/18) diff --git a/mix.exs b/mix.exs index ebeef40..143af37 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule ESTree.Mixfile do def project do [app: :estree, - version: "2.5.1", + version: "2.6.0", elixir: "~> 1.0", deps: deps(), description: description(), @@ -17,7 +17,7 @@ defmodule ESTree.Mixfile do defp deps do [ - {:ex_doc, "~> 0.14", only: :dev}, + {:ex_doc, "~> 0.15.1", only: :dev}, {:dialyze, "~> 0.2", only: :dev}, {:shouldi, "~> 0.3.2", only: :test}, {:poison, "~> 3.0", only: :test}, diff --git a/mix.lock b/mix.lock index 8b6f498..5f32066 100644 --- a/mix.lock +++ b/mix.lock @@ -1,5 +1,5 @@ %{"dialyze": {:hex, :dialyze, "0.2.1", "9fb71767f96649020d769db7cbd7290059daff23707d6e851e206b1fdfa92f9d", [:mix], []}, - "earmark": {:hex, :earmark, "1.0.3", "89bdbaf2aca8bbb5c97d8b3b55c5dd0cff517ecc78d417e87f1d0982e514557b", [:mix], []}, - "ex_doc": {:hex, :ex_doc, "0.14.5", "c0433c8117e948404d93ca69411dd575ec6be39b47802e81ca8d91017a0cf83c", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]}, + "earmark": {:hex, :earmark, "1.2.0", "bf1ce17aea43ab62f6943b97bd6e3dc032ce45d4f787504e3adf738e54b42f3a", [:mix], []}, + "ex_doc": {:hex, :ex_doc, "0.15.1", "d5f9d588fd802152516fccfdb96d6073753f77314fcfee892b15b6724ca0d596", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, optional: false]}]}, "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []}, "shouldi": {:hex, :shouldi, "0.3.2", "971f614669b5f37c03507ba643bb8e59aa165ac50ca66d726c9db53be255e440", [:mix], []}} From 96d8d2112b581aab3ad6fe415f55e20189ec91ac Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 30 Jul 2017 17:46:30 -0500 Subject: [PATCH 23/31] Add async option to arrow function expression --- CHANGELOG.md | 4 + lib/es_tree/arrow_function_expression.ex | 16 +- lib/es_tree/tools/builder.ex | 243 +++++++++--------- lib/es_tree/tools/generator.ex | 8 +- mix.exs | 2 +- .../arrow_function_expression_test.exs | 14 + test/tools/generator/call_expression_test.exs | 15 ++ 7 files changed, 170 insertions(+), 132 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d74d7f..01e1de5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v2.6.1 +* Enhancements: + * Add async to arrow function expressions + # v2.6.0 * Enhancements: * [Add parenthesis around await expressions in await expressions or in call expressions](https://github.com/elixirscript/elixir-estree/pull/20) diff --git a/lib/es_tree/arrow_function_expression.ex b/lib/es_tree/arrow_function_expression.ex index a860bb0..0027062 100644 --- a/lib/es_tree/arrow_function_expression.ex +++ b/lib/es_tree/arrow_function_expression.ex @@ -1,20 +1,22 @@ defmodule ESTree.ArrowFunctionExpression do - @type t :: %ESTree.ArrowFunctionExpression{ - type: binary, + @type t :: %ESTree.ArrowFunctionExpression{ + type: binary, loc: ESTree.SourceLocation.t | nil, params: [ESTree.Pattern.t], defaults: [ ESTree.Expression.t ], rest: ESTree.Identifier.t | nil, body: ESTree.BlockStatement.t | ESTree.Expression.t, generator: boolean, - expression: boolean + expression: boolean, + async: boolean } - defstruct type: "ArrowFunctionExpression", - loc: nil, + defstruct type: "ArrowFunctionExpression", + loc: nil, params: [], defaults: [], rest: nil, body: %ESTree.BlockStatement{}, generator: false, - expression: false -end \ No newline at end of file + expression: false, + async: false +end diff --git a/lib/es_tree/tools/builder.ex b/lib/es_tree/tools/builder.ex index 80cd31b..5f69dbe 100644 --- a/lib/es_tree/tools/builder.ex +++ b/lib/es_tree/tools/builder.ex @@ -4,35 +4,36 @@ defmodule ESTree.Tools.Builder do """ @spec array_expression( - [ESTree.Expression.t | nil], + [ESTree.Expression.t | nil], ESTree.SourceLocation.t | nil ) :: ESTree.ArrayExpression.t def array_expression(elements, loc \\ nil) do %ESTree.ArrayExpression{ elements: elements, loc: loc } - end + end @spec array_pattern( - [ESTree.Pattern.t | nil], + [ESTree.Pattern.t | nil], ESTree.SourceLocation.t | nil ) :: ESTree.ArrayPattern.t def array_pattern(elements, loc \\ nil) do %ESTree.ArrayPattern{ elements: elements, loc: loc } - end + end @spec arrow_function_expression( - [ESTree.Pattern.t], - [ESTree.Expression.t], + [ESTree.Pattern.t], + [ESTree.Expression.t], ESTree.BlockStatement.t | ESTree.Expression.t, boolean, boolean, ESTree.SourceLocation.t | nil ) :: ESTree.ArrowFunctionExpression.t - def arrow_function_expression(params, defaults, body, generator \\ false, expression \\ false, loc \\ nil) do + def arrow_function_expression(params, defaults, body, generator \\ false, expression \\ false, async \\ false, loc \\ nil) do %ESTree.ArrowFunctionExpression{ params: params, defaults: defaults, - body: body, generator: generator, expression: expression, loc: loc + body: body, generator: generator, expression: expression, loc: loc, + async: async } - end + end @spec assignment_expression( ESTree.assignment_operator, @@ -58,24 +59,24 @@ defmodule ESTree.Tools.Builder do @spec await_expression( - ESTree.Expression.t | nil, + ESTree.Expression.t | nil, boolean, ESTree.SourceLocation.t | nil ) :: ESTree.AwaitExpression.t def await_expression(argument, all \\ false, loc \\ nil) do - %ESTree.AwaitExpression{ + %ESTree.AwaitExpression{ argument: argument, all: all, loc: loc } end @spec binary_expression( - ESTree.binary_operator, - ESTree.Expression.t, + ESTree.binary_operator, + ESTree.Expression.t, ESTree.Expression.t, ESTree.SourceLocation.t | nil ) :: ESTree.BinaryExpression.t def binary_expression(operator, left, right, loc \\ nil) do - %ESTree.BinaryExpression{ + %ESTree.BinaryExpression{ operator: operator, left: left, right: right, loc: loc } end @@ -85,7 +86,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.BlockStatement.t def block_statement(body, loc \\ nil) do - %ESTree.BlockStatement{ + %ESTree.BlockStatement{ body: body, loc: loc } end @@ -95,10 +96,10 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.BreakStatement.t def break_statement(label \\ nil, loc \\ nil) do - %ESTree.BreakStatement{ + %ESTree.BreakStatement{ label: label, loc: loc } - end + end @spec call_expression( ESTree.Expression.t, @@ -106,10 +107,10 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.CallExpression.t def call_expression(callee, arguments, loc \\ nil) do - %ESTree.CallExpression{ + %ESTree.CallExpression{ callee: callee, arguments: arguments, loc: loc } - end + end @spec catch_clause( ESTree.Pattern.t, @@ -117,20 +118,20 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.CatchClause.t def catch_clause(param, body, loc \\ nil) do - %ESTree.CatchClause{ + %ESTree.CatchClause{ param: param, body: body, loc: loc } - end + end @spec class_body( [ESTree.MethodDefinition.t], ESTree.SourceLocation.t | nil ) :: ESTree.ClassBody.t def class_body(body, loc \\ nil) do - %ESTree.ClassBody{ + %ESTree.ClassBody{ body: body, loc: loc } - end + end @spec class_declaration( ESTree.Identifier.t, @@ -139,10 +140,10 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ClassDeclaration.t def class_declaration(id, body, superClass \\ nil, loc \\ nil) do - %ESTree.ClassDeclaration{ + %ESTree.ClassDeclaration{ id: id, body: body, loc: loc, superClass: superClass } - end + end @spec class_expression( ESTree.ClassBody.t, @@ -150,10 +151,10 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ClassExpression.t def class_expression(body, superClass \\ nil, loc \\ nil) do - %ESTree.ClassExpression{ + %ESTree.ClassExpression{ body: body, loc: loc, superClass: superClass } - end + end @spec conditional_statement( ESTree.Expression.t, @@ -162,7 +163,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ConditionalStatement.t def conditional_statement(test, alternate, consequent, loc \\ nil) do - %ESTree.ConditionalStatement{ + %ESTree.ConditionalStatement{ test: test, alternate: alternate, consequent: consequent, loc: loc } end @@ -172,16 +173,16 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ContinueStatement.t def continue_statement(label, loc \\ nil) do - %ESTree.ContinueStatement{ + %ESTree.ContinueStatement{ label: label, loc: loc } - end + end @spec debugger_statement( ESTree.SourceLocation.t | nil ) :: ESTree.DebuggerStatement.t def debugger_statement(loc \\ nil) do - %ESTree.DebuggerStatement{ + %ESTree.DebuggerStatement{ loc: loc } end @@ -192,7 +193,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.DoWhileStatement.t def do_while_statement(body, test, loc \\ nil) do - %ESTree.DoWhileStatement{ + %ESTree.DoWhileStatement{ body: body, test: test, loc: loc } end @@ -201,36 +202,36 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.EmptyExpression.t def empty_expression(loc \\ nil) do - %ESTree.EmptyExpression{ + %ESTree.EmptyExpression{ loc: loc } - end + end @spec empty_statement( ESTree.SourceLocation.t | nil ) :: ESTree.EmptyStatement.t def empty_statement(loc \\ nil) do - %ESTree.EmptyStatement{ + %ESTree.EmptyStatement{ loc: loc } end @spec export_all_declaration( - ESTree.Identifier.t | nil, + ESTree.Identifier.t | nil, ESTree.SourceLocation.t | nil ) :: ESTree.ExportAllDeclaration.t def export_all_declaration(source \\ nil, loc \\ nil) do - %ESTree.ExportAllDeclaration{ + %ESTree.ExportAllDeclaration{ loc: loc, source: source } end @spec export_default_declaration( - ESTree.Declaration.t | ESTree.Expression.t | nil, + ESTree.Declaration.t | ESTree.Expression.t | nil, ESTree.SourceLocation.t | nil ) :: ESTree.ExportDefaultDeclaration.t def export_default_declaration(declaration \\ nil, loc \\ nil) do - %ESTree.ExportDefaultDeclaration{ + %ESTree.ExportDefaultDeclaration{ loc: loc, declaration: declaration } end @@ -242,7 +243,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ExportNamedDeclaration.t def export_named_declaration(declaration, specifiers \\ [], source \\ nil, loc \\ nil) do - %ESTree.ExportNamedDeclaration{ + %ESTree.ExportNamedDeclaration{ declaration: declaration, specifiers: specifiers, source: source, loc: loc } @@ -250,11 +251,11 @@ defmodule ESTree.Tools.Builder do @spec export_specifier( ESTree.Identifier.t, - ESTree.Identifier.t | nil, + ESTree.Identifier.t | nil, ESTree.SourceLocation.t | nil ) :: ESTree.ExportSpecifier.t def export_specifier(exported, local \\ nil, loc \\ nil) do - %ESTree.ExportSpecifier{ + %ESTree.ExportSpecifier{ local: local, exported: exported, loc: loc } end @@ -264,7 +265,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ExpressionStatement.t def expression_statement(expression, loc \\ nil) do - %ESTree.ExpressionStatement{ + %ESTree.ExpressionStatement{ expression: expression, loc: loc } end @@ -288,7 +289,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ForOfStatement.t def for_of_statement(left, right, body, loc \\ nil) do - %ESTree.ForOfStatement{ + %ESTree.ForOfStatement{ left: left, right: right, body: body, loc: loc } end @@ -301,15 +302,15 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ForStatement.t def for_statement(init, test, update, body, loc \\ nil) do - %ESTree.ForStatement{ + %ESTree.ForStatement{ init: init, test: test, update: update, body: body, loc: loc } end @spec function_declaration( ESTree.Identifier.t, - [ESTree.Pattern.t], - [ESTree.Expression.t], + [ESTree.Pattern.t], + [ESTree.Expression.t], ESTree.BlockStatement.t, boolean, boolean, @@ -317,15 +318,15 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.FunctionDeclaration.t def function_declaration(id, params, defaults, body, generator \\ false, expression \\ false, async \\ false, loc \\ nil) do - %ESTree.FunctionDeclaration{ - id: id, params: params, defaults: defaults, + %ESTree.FunctionDeclaration{ + id: id, params: params, defaults: defaults, body: body, generator: generator, async: async, - expression: expression, loc: loc + expression: expression, loc: loc } - end + end @spec function_expression( - [ESTree.Pattern.t], + [ESTree.Pattern.t], [ ESTree.Expression.t ], ESTree.BlockStatement.t, boolean, @@ -334,19 +335,19 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.FunctionExpression.t def function_expression(params, defaults, body, generator \\ false, expression \\ false, async \\ false, loc \\ nil) do - %ESTree.FunctionExpression{ + %ESTree.FunctionExpression{ params: params, defaults: defaults, body: body, generator: generator, async: async, - expression: expression, loc: loc + expression: expression, loc: loc } - end + end @spec identifier( binary, ESTree.SourceLocation.t | nil ) :: ESTree.Identifier.t def identifier(name, loc \\ nil) do - %ESTree.Identifier{ + %ESTree.Identifier{ name: name, loc: loc } end @@ -358,7 +359,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.IfStatement.t def if_statement(test, consequent, alternate \\ nil, loc \\ nil) do - %ESTree.IfStatement{ + %ESTree.IfStatement{ test: test, consequent: consequent, alternate: alternate, loc: loc } end @@ -369,7 +370,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ImportDeclaration.t def import_declaration(specifiers, source \\ nil, loc \\ nil) do - %ESTree.ImportDeclaration{ + %ESTree.ImportDeclaration{ specifiers: specifiers, source: source, loc: loc } end @@ -379,7 +380,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ImportDefaultSpecifier.t def import_default_specifier(local, loc \\ nil) do - %ESTree.ImportDefaultSpecifier{ + %ESTree.ImportDefaultSpecifier{ local: local, loc: loc } end @@ -389,7 +390,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ImportNamespaceSpecifier.t def import_namespace_specifier(local, loc \\ nil) do - %ESTree.ImportNamespaceSpecifier{ + %ESTree.ImportNamespaceSpecifier{ local: local, loc: loc } end @@ -400,7 +401,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ImportSpecifier.t def import_specifier(imported, local \\ nil, loc \\ nil) do - %ESTree.ImportSpecifier{ + %ESTree.ImportSpecifier{ local: local, imported: imported, loc: loc } end @@ -411,7 +412,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.LabeledStatement.t def labeled_statement(label, body, loc \\ nil) do - %ESTree.LabeledStatement{ + %ESTree.LabeledStatement{ label: label, body: body, loc: loc } end @@ -422,48 +423,48 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.Literal.t def literal(value, regex \\ nil, loc \\ nil) do - %ESTree.Literal{ + %ESTree.Literal{ value: value, regex: regex, loc: loc } end @spec logical_expression( - ESTree.logical_operator, - ESTree.Expression.t, + ESTree.logical_operator, + ESTree.Expression.t, ESTree.Expression.t, ESTree.SourceLocation.t | nil ) :: ESTree.LogicalExpression.t def logical_expression(operator, left, right, loc \\ nil) do - %ESTree.LogicalExpression{ + %ESTree.LogicalExpression{ operator: operator, left: left, right: right, loc: loc } end @spec member_expression( - ESTree.Expression.t | ESTree.Super.t, + ESTree.Expression.t | ESTree.Super.t, ESTree.Identifier.t | ESTree.Expression.t, boolean, ESTree.SourceLocation.t | nil ) :: ESTree.MemberExpression.t def member_expression(object, property, computed \\ false, loc \\ nil) do - %ESTree.MemberExpression{ + %ESTree.MemberExpression{ object: object, property: property, computed: computed, loc: loc } end @spec meta_property( - ESTree.Identifier.t, + ESTree.Identifier.t, ESTree.Identifier.t, ESTree.SourceLocation.t | nil ) :: ESTree.MetaProperty.t def meta_property(meta, property, loc \\ nil) do - %ESTree.MetaProperty{ + %ESTree.MetaProperty{ meta: meta, property: property, loc: loc } end @spec method_definition( - ESTree.Identifier.t, + ESTree.Identifier.t, ESTree.FunctionExpression.t, :constructor | :method | :get | :set, boolean, @@ -471,7 +472,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.MethodDefinition.t def method_definition(key, value, kind \\ :method, computed \\ false, static \\ false, loc \\ nil) do - %ESTree.MethodDefinition{ + %ESTree.MethodDefinition{ key: key, value: value, kind: kind, computed: computed, static: static, loc: loc } end @@ -482,7 +483,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.NewExpression.t def new_expression(callee, arguments, loc \\ nil) do - %ESTree.NewExpression{ + %ESTree.NewExpression{ callee: callee, arguments: arguments, loc: loc } end @@ -492,27 +493,27 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ObjectExpression.t def object_expression(properties, loc \\ nil) do - %ESTree.ObjectExpression{ + %ESTree.ObjectExpression{ properties: properties, loc: loc } - end + end @spec object_pattern( [ESTree.Property.t], ESTree.SourceLocation.t | nil ) :: ESTree.ObjectPattern.t def object_pattern(properties, loc \\ nil) do - %ESTree.ObjectPattern{ + %ESTree.ObjectPattern{ properties: properties, loc: loc } - end + end @spec position( pos_integer, non_neg_integer ) :: ESTree.Position.t def position(line, column) do - %ESTree.Position{ + %ESTree.Position{ line: line, column: column } end @@ -523,13 +524,13 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.Program.t def program(body, sourceType \\ :script, loc \\ nil) do - %ESTree.Program{ + %ESTree.Program{ body: body, loc: loc, sourceType: sourceType } end @spec property( - ESTree.Expression.t, + ESTree.Expression.t, ESTree.Expression.t , :init | :get | :set, boolean, @@ -538,7 +539,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.Property.t def property(key, value, kind \\ :init, shorthand \\ false, method \\ false, computed \\false, loc \\ nil) do - %ESTree.Property{ + %ESTree.Property{ key: key, value: value, kind: kind, shorthand: shorthand, method: method, loc: loc, computed: computed @@ -550,7 +551,7 @@ defmodule ESTree.Tools.Builder do binary ) :: ESTree.Regex.t def regex(pattern, flags) do - %ESTree.Regex{ + %ESTree.Regex{ pattern: pattern, flags: flags } end @@ -560,7 +561,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.RestElement.t def rest_element(argument, loc \\ nil) do - %ESTree.RestElement{ + %ESTree.RestElement{ argument: argument, loc: loc } end @@ -570,7 +571,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ReturnStatement.t def return_statement(argument, loc \\ nil) do - %ESTree.ReturnStatement{ + %ESTree.ReturnStatement{ argument: argument, loc: loc } end @@ -580,7 +581,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.SequenceExpression.t def sequence_expression(expressions, loc \\ nil) do - %ESTree.SequenceExpression{ + %ESTree.SequenceExpression{ expressions: expressions, loc: loc } end @@ -591,7 +592,7 @@ defmodule ESTree.Tools.Builder do ESTree.Position.t ) :: ESTree.SourceLocation.t def source_location(source, start, the_end) do - %ESTree.SourceLocation{ + %ESTree.SourceLocation{ source: source, start: start, end: the_end } end @@ -601,7 +602,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.SpreadElement.t def spread_element(argument, loc \\ nil) do - %ESTree.SpreadElement{ + %ESTree.SpreadElement{ argument: argument, loc: loc } end @@ -610,7 +611,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.Super.t def super(loc \\ nil) do - %ESTree.Super{ + %ESTree.Super{ loc: loc } end @@ -621,7 +622,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.SwitchCase.t def switch_case(test, consequent, loc \\ nil) do - %ESTree.SwitchCase{ + %ESTree.SwitchCase{ test: test, consequent: consequent, loc: loc } end @@ -632,7 +633,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.SwitchStatement.t def switch_statement(discriminant, cases, loc \\ nil) do - %ESTree.SwitchStatement{ + %ESTree.SwitchStatement{ discriminant: discriminant, cases: cases, loc: loc } end @@ -643,7 +644,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.TaggedTemplateExpression.t def tagged_template_expression(tag, quasi, loc \\ nil) do - %ESTree.TaggedTemplateExpression{ + %ESTree.TaggedTemplateExpression{ tag: tag, quasi: quasi, loc: loc } end @@ -655,7 +656,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.TemplateElement.t def template_element(raw, cooked_value, tail, loc \\ nil) do - %ESTree.TemplateElement{ + %ESTree.TemplateElement{ value: %{cooked: cooked_value, raw: raw}, tail: tail, loc: loc } end @@ -666,7 +667,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.TemplateLiteral.t def template_literal(quasis, expressions, loc \\ nil) do - %ESTree.TemplateLiteral{ + %ESTree.TemplateLiteral{ quasis: quasis, expressions: expressions, loc: loc } end @@ -675,7 +676,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ThisExpression.t def this_expression(loc \\ nil) do - %ESTree.ThisExpression{ + %ESTree.ThisExpression{ loc: loc } end @@ -685,7 +686,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.ThrowStatement.t def throw_statement(argument, loc \\ nil) do - %ESTree.ThrowStatement{ + %ESTree.ThrowStatement{ argument: argument, loc: loc } end @@ -697,76 +698,76 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.TryStatement.t def try_statement(block, handler, finalizer \\ nil, loc \\ nil) do - %ESTree.TryStatement{ + %ESTree.TryStatement{ block: block, handler: handler, finalizer: finalizer, loc: loc } end @spec unary_expression( - ESTree.unary_operator, - boolean, + ESTree.unary_operator, + boolean, ESTree.Expression.t, ESTree.SourceLocation.t | nil ) :: ESTree.UnaryExpression.t def unary_expression(operator, prefix, argument, loc \\ nil) do - %ESTree.UnaryExpression{ + %ESTree.UnaryExpression{ operator: operator, prefix: prefix, argument: argument, loc: loc } end @spec update_expression( - ESTree.update_operator, + ESTree.update_operator, ESTree.Expression.t, - boolean, + boolean, ESTree.SourceLocation.t | nil ) :: ESTree.UpdateExpression.t def update_expression(operator, argument, prefix, loc \\ nil) do - %ESTree.UpdateExpression{ + %ESTree.UpdateExpression{ operator: operator, prefix: prefix, argument: argument, loc: loc } end @spec variable_declaration( - [ESTree.VariableDeclarator.t], + [ESTree.VariableDeclarator.t], :var | :let | :const, ESTree.SourceLocation.t | nil ) :: ESTree.VariableDeclaration.t def variable_declaration(declarations, kind \\ :var, loc \\ nil) do - %ESTree.VariableDeclaration{ + %ESTree.VariableDeclaration{ declarations: declarations, kind: kind, loc: loc } end @spec variable_declarator( - ESTree.Pattern.t, + ESTree.Pattern.t, ESTree.Expression.t | nil, ESTree.SourceLocation.t | nil ) :: ESTree.VariableDeclarator.t def variable_declarator(id, init \\ nil, loc \\ nil) do - %ESTree.VariableDeclarator{ + %ESTree.VariableDeclarator{ id: id, init: init, loc: loc } end @spec while_statement( - ESTree.Expression.t, + ESTree.Expression.t, ESTree.Statement.t, ESTree.SourceLocation.t | nil ) :: ESTree.WhileStatement.t def while_statement(test, body, loc \\ nil) do - %ESTree.WhileStatement{ + %ESTree.WhileStatement{ test: test, body: body, loc: loc } end @spec with_statement( - ESTree.Expression.t, + ESTree.Expression.t, ESTree.Statement.t, ESTree.SourceLocation.t | nil ) :: ESTree.WithStatement.t def with_statement(object, body, loc \\ nil) do - %ESTree.WithStatement{ + %ESTree.WithStatement{ object: object, body: body, loc: loc } end @@ -777,7 +778,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.YieldExpression.t def yield_expression(argument \\ nil, delegate \\ false, loc \\ nil) do - %ESTree.YieldExpression{ + %ESTree.YieldExpression{ argument: argument, loc: loc, delegate: delegate } end @@ -788,7 +789,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.JSXIdentifier.t def jsx_identifier(name, loc \\ nil) do - %ESTree.JSXIdentifier{ + %ESTree.JSXIdentifier{ name: name, loc: loc } end @@ -800,7 +801,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.MemberExpression.t def jsx_member_expression(object, property, loc \\ nil) do - %ESTree.JSXMemberExpression{ + %ESTree.JSXMemberExpression{ object: object, property: property, loc: loc } end @@ -811,7 +812,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.JSXNamespacedName.t def jsx_namespaced_name(namespace, name, loc \\ nil) do - %ESTree.JSXNamespacedName{ + %ESTree.JSXNamespacedName{ namespace: namespace, name: name, loc: loc } end @@ -820,7 +821,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.JSXEmptyExpression.t def jsx_empty_expression(loc \\ nil) do - %ESTree.JSXEmptyExpression{ + %ESTree.JSXEmptyExpression{ loc: loc } end @@ -830,7 +831,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.JSXExpressionContainer.t def jsx_expression_container(expression, loc \\ nil) do - %ESTree.JSXExpressionContainer{ + %ESTree.JSXExpressionContainer{ expression: expression, loc: loc } end @@ -843,7 +844,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.JSXOpeningElement.t def jsx_opening_element(name, attributes \\ [], selfClosing \\ false, loc \\ nil) do - %ESTree.JSXOpeningElement{ + %ESTree.JSXOpeningElement{ name: name, attributes: attributes, selfClosing: selfClosing, loc: loc } end @@ -854,7 +855,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.JSXClosingElement.t def jsx_closing_element(name, loc \\ nil) do - %ESTree.JSXClosingElement{ + %ESTree.JSXClosingElement{ name: name, loc: loc } end @@ -866,7 +867,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.JSXAttribute.t def jsx_attribute(name, value \\ nil, loc \\ nil) do - %ESTree.JSXAttribute{ + %ESTree.JSXAttribute{ name: name, value: value, loc: loc } end @@ -876,7 +877,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.SpreadElement.t def jsx_spread_attribute(argument, loc \\ nil) do - %ESTree.JSXSpreadAttribute{ + %ESTree.JSXSpreadAttribute{ argument: argument, loc: loc } end @@ -888,7 +889,7 @@ defmodule ESTree.Tools.Builder do ESTree.SourceLocation.t | nil ) :: ESTree.JSXElement.t def jsx_element(openingElement, children \\ [], closingElement \\ nil, loc \\ nil) do - %ESTree.JSXElement{ + %ESTree.JSXElement{ openingElement: openingElement, children: children, closingElement: closingElement, loc: loc } end diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index 16c18df..a3ad9b5 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -132,6 +132,7 @@ defmodule ESTree.Tools.Generator do ConditionalStatement => 4, AssignmentExpression => 3, YieldExpression => 2, + AwaitExpression => 2, RestElement => 1 } @@ -220,8 +221,9 @@ defmodule ESTree.Tools.Generator do # ArrowFunctionExpression - defp do_generate(%ArrowFunctionExpression{params: params, defaults: defaults, body: body, generator: generator} = ast, %{wh_sep: wh_sep} = opts) do + defp do_generate(%ArrowFunctionExpression{params: params, defaults: defaults, body: body, generator: generator, async: async} = ast, %{wh_sep: wh_sep} = opts) do generator = if generator, do: "*", else: "" + async = if async, do: "async ", else: "" params = params_and_defaults(params, defaults, opts) body = if body.__struct__ == ObjectExpression do ["(", do_generate(body, opts), ")"] @@ -230,9 +232,9 @@ defmodule ESTree.Tools.Generator do end if not opts.beauty and length(ast.params) == 1 do - [params, generator, wh_sep, "=>", wh_sep, body] + [async, params, generator, wh_sep, "=>", wh_sep, body] else - ["(", params, ")", generator, wh_sep, "=>", wh_sep, body] + [async, "(", params, ")", generator, wh_sep, "=>", wh_sep, body] end end diff --git a/mix.exs b/mix.exs index 143af37..1bc69db 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule ESTree.Mixfile do def project do [app: :estree, - version: "2.6.0", + version: "2.6.1", elixir: "~> 1.0", deps: deps(), description: description(), diff --git a/test/tools/generator/arrow_function_expression_test.exs b/test/tools/generator/arrow_function_expression_test.exs index ca71323..b994ca0 100644 --- a/test/tools/generator/arrow_function_expression_test.exs +++ b/test/tools/generator/arrow_function_expression_test.exs @@ -79,4 +79,18 @@ defmodule ESTree.Tools.Generator.ArrowFunctionExpression.Test do assert_gen ast, "(one, two = 1) => {}" assert_gen ast, "(one,two=1)=>{}", beauty: false end + + should "convert basic arrow function expression async" do + ast = Builder.arrow_function_expression( + [], + [], + Builder.block_statement([]), + false, + false, + true + ) + + assert_gen ast, "async () => {}" + assert_gen ast, "async ()=>{}", beauty: false + end end diff --git a/test/tools/generator/call_expression_test.exs b/test/tools/generator/call_expression_test.exs index e6bc203..803e04f 100644 --- a/test/tools/generator/call_expression_test.exs +++ b/test/tools/generator/call_expression_test.exs @@ -119,4 +119,19 @@ defmodule ESTree.Tools.Generator.CallExpression.Test do assert_gen ast, "x((yield a))" assert_gen ast, "x((yield a))", beauty: false end + + should "convert call expression when callee is member expression and is an await" do + ast = Builder.call_expression( + Builder.member_expression( + Builder.await_expression( + Builder.identifier(:x) + ), + Builder.identifier(:y) + ), + [] + ); + + assert_gen ast, "(await x).y()" + assert_gen ast, "(await x).y()", beauty: false + end end From 20621b2051aa8b860b1c583bf56aa86683a80127 Mon Sep 17 00:00:00 2001 From: flames of love Date: Wed, 11 Apr 2018 04:53:35 -0600 Subject: [PATCH 24/31] arrow function expressions w/ object patterns --- lib/es_tree/tools/generator.ex | 2 +- .../generator/arrow_function_expression_test.exs | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index a3ad9b5..68386f5 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -231,7 +231,7 @@ defmodule ESTree.Tools.Generator do do_generate(body, opts) end - if not opts.beauty and length(ast.params) == 1 do + if not opts.beauty and length(ast.params) == 1 and hd(ast.params).__struct__ != ObjectPattern do [async, params, generator, wh_sep, "=>", wh_sep, body] else [async, "(", params, ")", generator, wh_sep, "=>", wh_sep, body] diff --git a/test/tools/generator/arrow_function_expression_test.exs b/test/tools/generator/arrow_function_expression_test.exs index b994ca0..ce4dcea 100644 --- a/test/tools/generator/arrow_function_expression_test.exs +++ b/test/tools/generator/arrow_function_expression_test.exs @@ -30,6 +30,19 @@ defmodule ESTree.Tools.Generator.ArrowFunctionExpression.Test do assert_gen ast, "()=>({})", beauty: false end + should "convert basic arrow function object pattern has parens" do + ast = Builder.arrow_function_expression( + [Builder.object_pattern([Builder.identifier(:one)])], + [], + Builder.block_statement([]), + false, + false + ) + + assert_gen ast, "({one}) => {}" + assert_gen ast, "({one})=>{}", beauty: false + end + should "convert basic arrow function expression generator" do ast = Builder.arrow_function_expression( [], From 7484138d324504c7b52a4892bea9d3b9cb57b9a3 Mon Sep 17 00:00:00 2001 From: flames of love Date: Wed, 11 Apr 2018 04:53:46 -0600 Subject: [PATCH 25/31] editorconfig --- .editorconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..d9e1a52 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = space +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false From 2b905a921625a52fbaf00f3eb4210f9015e5331f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Thu, 21 Mar 2019 14:32:38 +0000 Subject: [PATCH 26/31] Bump ex_doc from 0.15.1 to 0.19.3 Bumps [ex_doc](https://github.com/elixir-lang/ex_doc) from 0.15.1 to 0.19.3. - [Release notes](https://github.com/elixir-lang/ex_doc/releases) - [Changelog](https://github.com/elixir-lang/ex_doc/blob/master/CHANGELOG.md) - [Commits](https://github.com/elixir-lang/ex_doc/compare/v0.15.1...v0.19.3) Signed-off-by: dependabot[bot] --- mix.exs | 2 +- mix.lock | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/mix.exs b/mix.exs index 1bc69db..3a1ef25 100644 --- a/mix.exs +++ b/mix.exs @@ -17,7 +17,7 @@ defmodule ESTree.Mixfile do defp deps do [ - {:ex_doc, "~> 0.15.1", only: :dev}, + {:ex_doc, "~> 0.19.3", only: :dev}, {:dialyze, "~> 0.2", only: :dev}, {:shouldi, "~> 0.3.2", only: :test}, {:poison, "~> 3.0", only: :test}, diff --git a/mix.lock b/mix.lock index 5f32066..b6ce7b4 100644 --- a/mix.lock +++ b/mix.lock @@ -1,5 +1,8 @@ %{"dialyze": {:hex, :dialyze, "0.2.1", "9fb71767f96649020d769db7cbd7290059daff23707d6e851e206b1fdfa92f9d", [:mix], []}, - "earmark": {:hex, :earmark, "1.2.0", "bf1ce17aea43ab62f6943b97bd6e3dc032ce45d4f787504e3adf738e54b42f3a", [:mix], []}, - "ex_doc": {:hex, :ex_doc, "0.15.1", "d5f9d588fd802152516fccfdb96d6073753f77314fcfee892b15b6724ca0d596", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, optional: false]}]}, + "earmark": {:hex, :earmark, "1.3.1", "73812f447f7a42358d3ba79283cfa3075a7580a3a2ed457616d6517ac3738cb9", [:mix], [], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.19.3", "3c7b0f02851f5fc13b040e8e925051452e41248f685e40250d7e40b07b9f8c10", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, + "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, + "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []}, "shouldi": {:hex, :shouldi, "0.3.2", "971f614669b5f37c03507ba643bb8e59aa165ac50ca66d726c9db53be255e440", [:mix], []}} From e69d3a7c9ac7d5e84472f0d9193a09ee9d29634f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 8 Apr 2019 07:05:14 +0000 Subject: [PATCH 27/31] Bump ex_doc from 0.19.3 to 0.20.1 Bumps [ex_doc](https://github.com/elixir-lang/ex_doc) from 0.19.3 to 0.20.1. - [Release notes](https://github.com/elixir-lang/ex_doc/releases) - [Changelog](https://github.com/elixir-lang/ex_doc/blob/master/CHANGELOG.md) - [Commits](https://github.com/elixir-lang/ex_doc/compare/v0.19.3...v0.20.1) Signed-off-by: dependabot[bot] --- mix.exs | 2 +- mix.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mix.exs b/mix.exs index 3a1ef25..495e9cf 100644 --- a/mix.exs +++ b/mix.exs @@ -17,7 +17,7 @@ defmodule ESTree.Mixfile do defp deps do [ - {:ex_doc, "~> 0.19.3", only: :dev}, + {:ex_doc, "~> 0.20.1", only: :dev}, {:dialyze, "~> 0.2", only: :dev}, {:shouldi, "~> 0.3.2", only: :test}, {:poison, "~> 3.0", only: :test}, diff --git a/mix.lock b/mix.lock index b6ce7b4..38ada31 100644 --- a/mix.lock +++ b/mix.lock @@ -1,6 +1,6 @@ %{"dialyze": {:hex, :dialyze, "0.2.1", "9fb71767f96649020d769db7cbd7290059daff23707d6e851e206b1fdfa92f9d", [:mix], []}, - "earmark": {:hex, :earmark, "1.3.1", "73812f447f7a42358d3ba79283cfa3075a7580a3a2ed457616d6517ac3738cb9", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.19.3", "3c7b0f02851f5fc13b040e8e925051452e41248f685e40250d7e40b07b9f8c10", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, + "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.20.1", "88eaa16e67c505664fd6a66f42ddb962d424ad68df586b214b71443c69887123", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, From 748b9571a307fa9af3f108e5f611922407f4d59c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 22 Apr 2019 07:12:48 +0000 Subject: [PATCH 28/31] Bump ex_doc from 0.20.1 to 0.20.2 Bumps [ex_doc](https://github.com/elixir-lang/ex_doc) from 0.20.1 to 0.20.2. - [Release notes](https://github.com/elixir-lang/ex_doc/releases) - [Changelog](https://github.com/elixir-lang/ex_doc/blob/master/CHANGELOG.md) - [Commits](https://github.com/elixir-lang/ex_doc/compare/v0.20.1...v0.20.2) Signed-off-by: dependabot[bot] --- mix.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.lock b/mix.lock index 38ada31..fc73ae9 100644 --- a/mix.lock +++ b/mix.lock @@ -1,6 +1,6 @@ %{"dialyze": {:hex, :dialyze, "0.2.1", "9fb71767f96649020d769db7cbd7290059daff23707d6e851e206b1fdfa92f9d", [:mix], []}, "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.20.1", "88eaa16e67c505664fd6a66f42ddb962d424ad68df586b214b71443c69887123", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, From 5829601198705c1f56328a85d6c4b6562fc80d63 Mon Sep 17 00:00:00 2001 From: Dariusz Czajkowski Date: Thu, 2 May 2019 01:48:10 +0200 Subject: [PATCH 29/31] Allow for options to be customized --- lib/es_tree/tools/generator.ex | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/es_tree/tools/generator.ex b/lib/es_tree/tools/generator.ex index 68386f5..3d44623 100644 --- a/lib/es_tree/tools/generator.ex +++ b/lib/es_tree/tools/generator.ex @@ -145,9 +145,9 @@ defmodule ESTree.Tools.Generator do :">>>=" , :"|=" , :"^=" , :"&=", :++, :-- ] - @spec generate(ESTree.operator | ESTree.Node.t, boolean) :: binary - def generate(value, beauty \\ true) do - opts = if beauty do + @spec generate(ESTree.operator | ESTree.Node.t, boolean | map) :: binary + def generate(value, beauty_or_opts \\ true) do + opts = if beauty_or_opts do %{ beauty: true, wh_sep: " ", @@ -169,6 +169,8 @@ defmodule ESTree.Tools.Generator do no_trailing_semicolon: false } ) + + opts = if is_map(beauty_or_opts), do: Map.merge(opts, beauty_or_opts), else: opts value |> do_generate(opts) From 47639e79f2bc6f3b9d8b4b0ffc3b89b2b1fd1820 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 2 May 2019 11:43:25 -0500 Subject: [PATCH 30/31] Update version for release --- .travis.yml | 4 +-- CHANGELOG.md | 97 ++++++++++++++++++++++++++++++---------------------- mix.exs | 23 +++++++------ mix.lock | 8 +++-- 4 files changed, 76 insertions(+), 56 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8149148..216e7df 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ sudo: false language: elixir elixir: - - 1.4.2 + - 1.8.1 otp_release: - - 19.3 \ No newline at end of file + - 21.3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 01e1de5..063b4da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,80 +1,95 @@ +# v2.7.0 + +- Enhancements: + - [Allow for options to be customized (https://github.com/elixirscript/elixir-estree/pull/27) + # v2.6.1 -* Enhancements: - * Add async to arrow function expressions + +- Enhancements: + - Add async to arrow function expressions # v2.6.0 -* Enhancements: - * [Add parenthesis around await expressions in await expressions or in call expressions](https://github.com/elixirscript/elixir-estree/pull/20) - * [Add ESTree.Tools.ESTreeJSONTransformer to translate ESTree JSON data into structs](https://github.com/bryanjos/elixir-estree/pull/21) + +- Enhancements: + - [Add parenthesis around await expressions in await expressions or in call expressions](https://github.com/elixirscript/elixir-estree/pull/20) + - [Add ESTree.Tools.ESTreeJSONTransformer to translate ESTree JSON data into structs](https://github.com/bryanjos/elixir-estree/pull/21) # v2.5.1 -* Enhancements: - * [Correct If statement identation](https://github.com/bryanjos/elixir-estree/pull/18) + +- Enhancements: + - [Correct If statement identation](https://github.com/bryanjos/elixir-estree/pull/18) # v2.5.0 -* Enhancements: - * [Greatly improved formatting of generated JavaScript](https://github.com/bryanjos/elixir-estree/pull/15) + +- Enhancements: + - [Greatly improved formatting of generated JavaScript](https://github.com/bryanjos/elixir-estree/pull/15) # v2.4.2 -* Fixes - * [Expressions in variable declarations](https://github.com/bryanjos/elixir-estree/pull/13) + +- Fixes + - [Expressions in variable declarations](https://github.com/bryanjos/elixir-estree/pull/13) # v2.4.1 -* Fixes - * Handle edge case when string literal is a JSX child + +- Fixes + - Handle edge case when string literal is a JSX child # v2.4.0 -* Enhancements: - * Added exponential operators from ES2016 + +- Enhancements: + - Added exponential operators from ES2016 # v2.3.0 -* Enhancements: - * Added AssignmentProperty for use with ObjectPattern - * Updated some typespecs to reflect updates in ESTree spec + +- Enhancements: + - Added AssignmentProperty for use with ObjectPattern + - Updated some typespecs to reflect updates in ESTree spec # v2.2.0 -* Enhancements: - * Added structs for JSX AST + +- Enhancements: + - Added structs for JSX AST # v2.1.2 -* Bug fixes - * ESTree.Tools.Generator: updated UnaryExpression to put space in when operator is :typeof +- Bug fixes + - ESTree.Tools.Generator: updated UnaryExpression to put space in when operator is :typeof # v2.1.1 -* Enhancements - * ESTree.Tools.Generator: Updated yield to account for delegate field +- Enhancements + - ESTree.Tools.Generator: Updated yield to account for delegate field # v2.1.0 -* Enhancements - * Added async field to FunctionDeclaration and FunctionExpression - * Added AwaitExpression +- Enhancements + - Added async field to FunctionDeclaration and FunctionExpression + - Added AwaitExpression # v2.0.1 -* Enhancements - * Changed TemplateElement.value.value to TemplateElement.value.raw - * Began adding indentation - * Added empty string for when nil is given to generate +- Enhancements + - Changed TemplateElement.value.value to TemplateElement.value.raw + - Began adding indentation + - Added empty string for when nil is given to generate # v2.0.0 -* Enhancements - * Updated to latest ESTree Spec - * Added ESTree.Tools.Generator to turn JavaScript AST into code +- Enhancements + + - Updated to latest ESTree Spec + - Added ESTree.Tools.Generator to turn JavaScript AST into code -* Breaking - * ESTree.Builder is now ESTree.Tools.Builder +- Breaking + - ESTree.Builder is now ESTree.Tools.Builder # v1.0.1 -* Enhancements - * Add new regex property to literal +- Enhancements + - Add new regex property to literal # v1.0.0 -* Enhancements - * Has the Node definitions from the [ESTree Spec](https://github.com/estree/estree) - * Fills in ES6 Node definitions from [ast-types](https://github.com/benjamn/ast-types) and some from testing with [acorn](https://github.com/marijnh/acorn) +- Enhancements + - Has the Node definitions from the [ESTree Spec](https://github.com/estree/estree) + - Fills in ES6 Node definitions from [ast-types](https://github.com/benjamn/ast-types) and some from testing with [acorn](https://github.com/marijnh/acorn) diff --git a/mix.exs b/mix.exs index 495e9cf..5860834 100644 --- a/mix.exs +++ b/mix.exs @@ -2,13 +2,15 @@ defmodule ESTree.Mixfile do use Mix.Project def project do - [app: :estree, - version: "2.6.1", - elixir: "~> 1.0", - deps: deps(), - description: description(), - package: package(), - source_url: "https://github.com/bryanjos/elixir-estree"] + [ + app: :estree, + version: "2.7.0", + elixir: "~> 1.0", + deps: deps(), + description: description(), + package: package(), + source_url: "https://github.com/bryanjos/elixir-estree" + ] end def application do @@ -20,7 +22,7 @@ defmodule ESTree.Mixfile do {:ex_doc, "~> 0.20.1", only: :dev}, {:dialyze, "~> 0.2", only: :dev}, {:shouldi, "~> 0.3.2", only: :test}, - {:poison, "~> 3.0", only: :test}, + {:poison, "~> 4.0", only: :test} ] end @@ -32,11 +34,12 @@ defmodule ESTree.Mixfile do end defp package do - [ # These are the default files included in the package + # These are the default files included in the package + [ files: ["lib", "mix.exs", "README.md", "CHANGELOG.md"], maintainers: ["Bryan Joseph"], licenses: ["MIT"], - links: %{ "GitHub" => "https://github.com/bryanjos/elixir-estree" } + links: %{"GitHub" => "https://github.com/bryanjos/elixir-estree"} ] end end diff --git a/mix.lock b/mix.lock index fc73ae9..f9e87f4 100644 --- a/mix.lock +++ b/mix.lock @@ -1,8 +1,10 @@ -%{"dialyze": {:hex, :dialyze, "0.2.1", "9fb71767f96649020d769db7cbd7290059daff23707d6e851e206b1fdfa92f9d", [:mix], []}, +%{ + "dialyze": {:hex, :dialyze, "0.2.1", "9fb71767f96649020d769db7cbd7290059daff23707d6e851e206b1fdfa92f9d", [:mix], []}, "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, - "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []}, - "shouldi": {:hex, :shouldi, "0.3.2", "971f614669b5f37c03507ba643bb8e59aa165ac50ca66d726c9db53be255e440", [:mix], []}} + "poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm"}, + "shouldi": {:hex, :shouldi, "0.3.2", "971f614669b5f37c03507ba643bb8e59aa165ac50ca66d726c9db53be255e440", [:mix], []}, +} From 881a275199ab3c453cc8eafcd410e1cfaf3bf9b8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2019 06:40:30 +0000 Subject: [PATCH 31/31] Bump ex_doc from 0.20.2 to 0.21.1 Bumps [ex_doc](https://github.com/elixir-lang/ex_doc) from 0.20.2 to 0.21.1. - [Release notes](https://github.com/elixir-lang/ex_doc/releases) - [Changelog](https://github.com/elixir-lang/ex_doc/blob/master/CHANGELOG.md) - [Commits](https://github.com/elixir-lang/ex_doc/compare/v0.20.2...v0.21.1) Signed-off-by: dependabot-preview[bot] --- mix.exs | 2 +- mix.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mix.exs b/mix.exs index 5860834..9a8190d 100644 --- a/mix.exs +++ b/mix.exs @@ -19,7 +19,7 @@ defmodule ESTree.Mixfile do defp deps do [ - {:ex_doc, "~> 0.20.1", only: :dev}, + {:ex_doc, "~> 0.21.1", only: :dev}, {:dialyze, "~> 0.2", only: :dev}, {:shouldi, "~> 0.3.2", only: :test}, {:poison, "~> 4.0", only: :test} diff --git a/mix.lock b/mix.lock index f9e87f4..8eaf864 100644 --- a/mix.lock +++ b/mix.lock @@ -1,9 +1,9 @@ %{ "dialyze": {:hex, :dialyze, "0.2.1", "9fb71767f96649020d769db7cbd7290059daff23707d6e851e206b1fdfa92f9d", [:mix], []}, "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, - "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.21.1", "5ac36660846967cd869255f4426467a11672fec3d8db602c429425ce5b613b90", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, + "makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, "poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm"}, "shouldi": {:hex, :shouldi, "0.3.2", "971f614669b5f37c03507ba643bb8e59aa165ac50ca66d726c9db53be255e440", [:mix], []},