├── .gitignore ├── test ├── test_helper.exs ├── support.ex └── tools │ ├── generator │ ├── export_declaration_test.exs │ ├── assignment_test.exs │ ├── throw_statement_test.exs │ ├── identifier_test.exs │ ├── for_in_statement_test.exs │ ├── for_of_statement_test.exs │ ├── await_expression_test.exs │ ├── while_statement_test.exs │ ├── array_expression_test.exs │ ├── array_pattern_test.exs │ ├── conditional_statement_test.exs │ ├── for_statement_test.exs │ ├── block_statement_test.exs │ ├── switch_statement_test.exs │ ├── try_statement_test.exs │ ├── object_pattern_test.exs │ ├── class_expression_test.exs │ ├── expression_statement_test.exs │ ├── variable_declaration_test.exs │ ├── class_declaration_test.exs │ ├── literal_test.exs │ ├── if_statement_test.exs │ ├── unary_expression_test.exs │ ├── import_declaration_test.exs │ ├── new_expression_test.exs │ ├── arrow_function_expression_test.exs │ ├── binary_expression_test.exs │ ├── template_literal_test.exs │ ├── call_expression_test.exs │ ├── export_default_declaration_test.exs │ ├── export_named_declaration_test.exs │ ├── object_expression_test.exs │ ├── function_test.exs │ ├── class_body_test.exs │ ├── jsx_test.exs │ └── formatting_test.exs │ └── estree_json_transformer_test.exs ├── .travis.yml ├── lib ├── es_tree │ ├── class.ex │ ├── position.ex │ ├── regex.ex │ ├── function.ex │ ├── super.ex │ ├── empty_expression.ex │ ├── empty_statement.ex │ ├── this_expression.ex │ ├── debugger_statement.ex │ ├── jsx_empty_expression.ex │ ├── identifier.ex │ ├── pattern.ex │ ├── block_statement.ex │ ├── jsx_identifier.ex │ ├── declaration.ex │ ├── class_body.ex │ ├── sequence_expression.ex │ ├── array_pattern.ex │ ├── program.ex │ ├── assignment_property.ex │ ├── break_statement.ex │ ├── expression_statement.ex │ ├── rest_element.ex │ ├── continue_statement.ex │ ├── object_expression.ex │ ├── object_pattern.ex │ ├── return_statement.ex │ ├── source_location.ex │ ├── jsx_spread_attribute.ex │ ├── spread_element.ex │ ├── throw_statement.ex │ ├── export_all_declaration.ex │ ├── jsx_closing_element.ex │ ├── array_expression.ex │ ├── literal.ex │ ├── import_default_specifier.ex │ ├── export_default_declaration.ex │ ├── import_namespace_specifier.ex │ ├── jsx_expression_container.ex │ ├── switch_case.ex │ ├── assignment_pattern.ex │ ├── await_expression.ex │ ├── jsx_namespaced_name.ex │ ├── yield_expression.ex │ ├── template_element.ex │ ├── template_literal.ex │ ├── catch_clause.ex │ ├── jsx_attribute.ex │ ├── meta_property.ex │ ├── variable_declarator.ex │ ├── class_expression.ex │ ├── switch_statement.ex │ ├── variable_declaration.ex │ ├── while_statement.ex │ ├── with_statement.ex │ ├── do_while_statement.ex │ ├── labeled_statement.ex │ ├── new_expression.ex │ ├── export_specifier.ex │ ├── import_specifier.ex │ ├── jsx_member_expression.ex │ ├── tagged_template_expression.ex │ ├── call_expression.ex │ ├── export_named_declaration.ex │ ├── jsx_element.ex │ ├── unary_expression.ex │ ├── import_declaration.ex │ ├── update_expression.ex │ ├── try_statement.ex │ ├── class_declaration.ex │ ├── if_statement.ex │ ├── jsx_opening_element.ex │ ├── binary_expression.ex │ ├── assignment_expression.ex │ ├── logical_expression.ex │ ├── for_in_statement.ex │ ├── for_of_statement.ex │ ├── conditional_statement.ex │ ├── member_expression.ex │ ├── for_statement.ex │ ├── export_declaration.ex │ ├── method_definition.ex │ ├── property.ex │ ├── function_expression.ex │ ├── arrow_function_expression.ex │ ├── function_declaration.ex │ ├── statement.ex │ ├── node.ex │ ├── expression.ex │ └── tools │ │ ├── estree_json_transformer.ex │ │ └── builder.ex └── es_tree.ex ├── .editorconfig ├── config └── config.exs ├── mix.exs ├── README.md ├── mix.lock └── CHANGELOG.md /.gitignore: -------------------------------------------------------------------------------- 1 | /_build 2 | /deps 3 | erl_crash.dump 4 | *.ez 5 | /doc 6 | /docs 7 | -------------------------------------------------------------------------------- /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | 3 | Code.require_file "support.ex", __DIR__ 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: elixir 3 | elixir: 4 | - 1.8.1 5 | otp_release: 6 | - 21.3 7 | -------------------------------------------------------------------------------- /lib/es_tree/class.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Class do 2 | @type t :: ESTree.ClassDeclaration.t | ESTree.ClassExpression.t 3 | end -------------------------------------------------------------------------------- /lib/es_tree/position.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Position do 2 | @type t :: %ESTree.Position{ line: pos_integer, column: non_neg_integer } 3 | defstruct line: 1, column: 0 4 | end -------------------------------------------------------------------------------- /lib/es_tree/regex.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Regex do 2 | @type t :: %ESTree.Regex{ 3 | pattern: binary, 4 | flags: binary 5 | } 6 | defstruct pattern: "", flags: "" 7 | end -------------------------------------------------------------------------------- /lib/es_tree/function.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Function do 2 | @type t :: ESTree.FunctionDeclaration.t | 3 | ESTree.FunctionExpression.t | 4 | ESTree.ArrowFunctionExpression.t 5 | end -------------------------------------------------------------------------------- /lib/es_tree/super.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Super do 2 | @type t :: %ESTree.Super{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | } 6 | defstruct type: "Super", loc: nil 7 | end 8 | -------------------------------------------------------------------------------- /lib/es_tree/empty_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.EmptyExpression do 2 | @type t :: %ESTree.EmptyExpression{ type: binary, loc: ESTree.SourceLocation.t | nil } 3 | defstruct type: "EmptyExpression", loc: nil 4 | end -------------------------------------------------------------------------------- /lib/es_tree/empty_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.EmptyStatement do 2 | @type t :: %ESTree.EmptyStatement{ type: binary, loc: ESTree.SourceLocation.t | nil } 3 | defstruct type: "EmptyStatement", loc: nil 4 | end -------------------------------------------------------------------------------- /lib/es_tree/this_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ThisExpression do 2 | @type t :: %ESTree.ThisExpression{ type: binary, loc: ESTree.SourceLocation.t | nil } 3 | defstruct type: "ThisExpression", loc: nil 4 | end -------------------------------------------------------------------------------- /lib/es_tree/debugger_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.DebuggerStatement do 2 | @type t :: %ESTree.DebuggerStatement{ type: binary, loc: ESTree.SourceLocation.t | nil } 3 | defstruct type: "DebuggerStatement", loc: nil 4 | end -------------------------------------------------------------------------------- /lib/es_tree/jsx_empty_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.JSXEmptyExpression do 2 | @type t :: %ESTree.JSXEmptyExpression{ type: binary, loc: ESTree.SourceLocation.t | nil } 3 | defstruct type: "JSXEmptyExpression", loc: nil 4 | end 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /lib/es_tree/identifier.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Identifier do 2 | @type t :: %ESTree.Identifier{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | name: binary 6 | } 7 | defstruct type: "Identifier", loc: nil, name: nil 8 | end -------------------------------------------------------------------------------- /lib/es_tree/pattern.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Pattern do 2 | @type t :: ESTree.Expression.t | 3 | ESTree.ObjectPattern.t | 4 | ESTree.ArrayPattern.t | 5 | ESTree.Identifier.t | 6 | ESTree.AssignmentPattern.t 7 | end 8 | -------------------------------------------------------------------------------- /lib/es_tree/block_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.BlockStatement do 2 | @type t :: %ESTree.BlockStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | body: [ESTree.Statement.t] 6 | } 7 | defstruct type: "BlockStatement", loc: nil, body: [] 8 | end -------------------------------------------------------------------------------- /lib/es_tree/jsx_identifier.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.JSXIdentifier do 2 | @type t :: %ESTree.JSXIdentifier{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | name: binary 6 | } 7 | 8 | defstruct type: "JSXIdentifier", loc: nil, name: nil 9 | end 10 | -------------------------------------------------------------------------------- /lib/es_tree/declaration.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Declaration do 2 | @type t :: ESTree.FunctionDeclaration.t | 3 | ESTree.VariableDeclaration.t | 4 | ESTree.ClassDeclaration.t | 5 | ESTree.ImportDeclaration.t | 6 | ESTree.ExportDeclaration.t 7 | end -------------------------------------------------------------------------------- /lib/es_tree/class_body.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ClassBody do 2 | @type t :: %ESTree.ClassBody{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | body: [ESTree.MethodDefinition.t] 6 | } 7 | defstruct type: "ClassBody", 8 | loc: nil, 9 | body: [] 10 | end -------------------------------------------------------------------------------- /lib/es_tree/sequence_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.SequenceExpression do 2 | @type t :: %ESTree.SequenceExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | expressions: [ESTree.Expression.t ] 6 | } 7 | defstruct type: "SequenceExpression", loc: nil, expressions: [] 8 | end -------------------------------------------------------------------------------- /lib/es_tree/array_pattern.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ArrayPattern do 2 | @type t :: %ESTree.ArrayPattern{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | elements: [ESTree.Pattern.t | nil] 6 | } 7 | defstruct type: "ArrayPattern", 8 | loc: nil, 9 | elements: [] 10 | end -------------------------------------------------------------------------------- /lib/es_tree/program.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Program do 2 | @type t :: %ESTree.Program{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | body: [ESTree.Statement.t ], 6 | sourceType: :script | :module 7 | } 8 | defstruct type: "Program", loc: nil, body: [], sourceType: :module 9 | end 10 | -------------------------------------------------------------------------------- /lib/es_tree/assignment_property.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.AssignmentProperty do 2 | @type t :: %ESTree.AssignmentProperty{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | value: ESTree.Pattern.t 6 | } 7 | defstruct type: "Property", 8 | loc: nil, 9 | value: %ESTree.EmptyExpression{} 10 | end 11 | -------------------------------------------------------------------------------- /lib/es_tree/break_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.BreakStatement do 2 | @type t :: %ESTree.BreakStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | label: ESTree.Identifier.t | nil 6 | } 7 | defstruct type: "BreakStatement", 8 | loc: nil, 9 | label: nil 10 | end -------------------------------------------------------------------------------- /lib/es_tree/expression_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ExpressionStatement do 2 | @type t :: %ESTree.ExpressionStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | expression: ESTree.Expression.t 6 | } 7 | defstruct type: "ExpressionStatement", loc: nil, expression: %ESTree.EmptyExpression{} 8 | end -------------------------------------------------------------------------------- /lib/es_tree/rest_element.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.RestElement do 2 | @type t :: %ESTree.RestElement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | argument: ESTree.Pattern.t 6 | } 7 | defstruct type: "RestElement", 8 | loc: nil, 9 | argument: %ESTree.Identifier{} 10 | end 11 | -------------------------------------------------------------------------------- /lib/es_tree/continue_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ContinueStatement do 2 | @type t :: %ESTree.ContinueStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | label: ESTree.Identifier.t | nil 6 | } 7 | defstruct type: "ContinueStatement", 8 | loc: nil, 9 | label: nil 10 | end -------------------------------------------------------------------------------- /lib/es_tree/object_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ObjectExpression do 2 | @type t :: %ESTree.ObjectExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | properties: [ESTree.Property.t] 6 | } 7 | defstruct type: "ObjectExpression", 8 | loc: nil, 9 | properties: [] 10 | end -------------------------------------------------------------------------------- /lib/es_tree/object_pattern.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ObjectPattern do 2 | @type t :: %ESTree.ObjectPattern{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | properties: [ESTree.AssignmentProperty.t] 6 | } 7 | defstruct type: "ObjectPattern", 8 | loc: nil, 9 | properties: [] 10 | end 11 | -------------------------------------------------------------------------------- /lib/es_tree/return_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ReturnStatement do 2 | @type t :: %ESTree.ReturnStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | argument: ESTree.Expression.t | nil 6 | } 7 | defstruct type: "ReturnStatement", 8 | loc: nil, 9 | argument: nil 10 | end -------------------------------------------------------------------------------- /lib/es_tree/source_location.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.SourceLocation do 2 | @type t :: %ESTree.SourceLocation{ 3 | source: binary | nil, 4 | start: ESTree.Position.t, 5 | end: ESTree.Position.t 6 | } 7 | defstruct source: nil, 8 | start: %ESTree.Position{}, 9 | end: %ESTree.Position{} 10 | end -------------------------------------------------------------------------------- /lib/es_tree/jsx_spread_attribute.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.JSXSpreadAttribute do 2 | @type t :: %ESTree.JSXSpreadAttribute{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | argument: ESTree.Expression.t 6 | } 7 | defstruct type: "JSXSpreadAttribute", 8 | loc: nil, 9 | argument: %ESTree.EmptyExpression{} 10 | end 11 | -------------------------------------------------------------------------------- /lib/es_tree/spread_element.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.SpreadElement do 2 | @type t :: %ESTree.SpreadElement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | argument: ESTree.Expression.t 6 | } 7 | defstruct type: "SpreadElement", 8 | loc: nil, 9 | argument: %ESTree.EmptyExpression{} 10 | end 11 | -------------------------------------------------------------------------------- /lib/es_tree/throw_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ThrowStatement do 2 | @type t :: %ESTree.ThrowStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | argument: ESTree.Expression.t 6 | } 7 | defstruct type: "ThrowStatement", 8 | loc: nil, 9 | argument: %ESTree.EmptyExpression{} 10 | end -------------------------------------------------------------------------------- /lib/es_tree/export_all_declaration.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ExportAllDeclaration do 2 | @type t :: %ESTree.ExportAllDeclaration{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | source: ESTree.Identifier.t | nil 6 | } 7 | defstruct type: "ExportAllDeclaration", 8 | loc: nil, 9 | source: nil 10 | end 11 | -------------------------------------------------------------------------------- /lib/es_tree/jsx_closing_element.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.JSXClosingElement do 2 | @type t :: %ESTree.JSXClosingElement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | name: ESTree.JSXIdentifier.t | ESTree.JSXMemberExpression.t | ESTree.JSXNamespacedName.t 6 | } 7 | defstruct type: "JSXClosingElement", loc: nil, name: nil 8 | end 9 | -------------------------------------------------------------------------------- /lib/es_tree/array_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ArrayExpression do 2 | @type t :: %ESTree.ArrayExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | elements: [ESTree.Expression.t | ESTree.SpreadElement.t | nil] 6 | } 7 | defstruct type: "ArrayExpression", 8 | loc: nil, 9 | elements: [] 10 | end 11 | -------------------------------------------------------------------------------- /lib/es_tree/literal.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Literal do 2 | @type t :: %ESTree.Literal{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | value: binary | boolean | number | nil, 6 | regex: ESTree.Regex.t | nil 7 | } 8 | defstruct type: "Literal", 9 | loc: nil, 10 | value: nil, 11 | regex: nil 12 | end -------------------------------------------------------------------------------- /lib/es_tree/import_default_specifier.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ImportDefaultSpecifier do 2 | @type t :: %ESTree.ImportDefaultSpecifier{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | local: ESTree.Identifier.t 6 | } 7 | defstruct type: "ImportDefaultSpecifier", 8 | loc: nil, 9 | local: %ESTree.Identifier{} 10 | end 11 | -------------------------------------------------------------------------------- /lib/es_tree/export_default_declaration.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ExportDefaultDeclaration do 2 | @type t :: %ESTree.ExportDefaultDeclaration{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | declaration: ESTree.Declaration.t | ESTree.Expression.t 6 | } 7 | defstruct type: "ExportDefaultDeclaration", 8 | loc: nil, 9 | declaration: nil 10 | end 11 | -------------------------------------------------------------------------------- /lib/es_tree/import_namespace_specifier.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ImportNamespaceSpecifier do 2 | @type t :: %ESTree.ImportNamespaceSpecifier{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | local: ESTree.Identifier.t 6 | } 7 | defstruct type: "ImportNamespaceSpecifier", 8 | loc: nil, 9 | local: %ESTree.Identifier{} 10 | end 11 | -------------------------------------------------------------------------------- /lib/es_tree/jsx_expression_container.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.JSXExpressionContainer do 2 | @type t :: %ESTree.JSXExpressionContainer{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | expression: ESTree.Expression.t | JSXEmptyExpression.t 6 | } 7 | 8 | defstruct type: "JSXExpressionContainer", loc: nil, expression: %ESTree.JSXEmptyExpression{} 9 | end 10 | -------------------------------------------------------------------------------- /lib/es_tree/switch_case.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.SwitchCase do 2 | @type t :: %ESTree.SwitchCase{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | test: ESTree.Expression.t | nil, 6 | consequent: [ESTree.Statement.t] 7 | } 8 | defstruct type: "SwitchCase", 9 | loc: nil, 10 | test: nil, 11 | consequent: [] 12 | end -------------------------------------------------------------------------------- /lib/es_tree/assignment_pattern.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.AssignmentPattern do 2 | @type t :: %ESTree.AssignmentPattern{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | left: ESTree.Pattern.t, 6 | right: ESTree.Expression.t 7 | } 8 | defstruct type: "AssignmentPattern", 9 | loc: nil, 10 | left: nil, 11 | right: nil 12 | end 13 | -------------------------------------------------------------------------------- /lib/es_tree/await_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.AwaitExpression do 2 | @type t :: %ESTree.AwaitExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | argument: ESTree.Expression.t | nil, 6 | all: boolean 7 | } 8 | defstruct type: "AwaitExpression", 9 | loc: nil, 10 | argument: nil, 11 | all: false 12 | end -------------------------------------------------------------------------------- /lib/es_tree/jsx_namespaced_name.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.JSXNamespacedName do 2 | @type t :: %ESTree.JSXNamespacedName{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | namespace: ESTree.JSXIdentifier.t, 6 | name: ESTree.JSXIdentifier.t 7 | } 8 | 9 | defstruct type: "JSXNamespacedName", 10 | loc: nil, 11 | namespace: nil, 12 | name: nil 13 | 14 | end 15 | -------------------------------------------------------------------------------- /test/support.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Test.Support do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Generator 5 | 6 | defmacro assert_gen(ast, str, opts \\ []) do 7 | opts = Keyword.merge([beauty: true], opts) 8 | beauty = Keyword.get(opts, :beauty) 9 | 10 | quote do 11 | assert Generator.generate(unquote(ast), unquote(beauty)) == unquote(str) 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/es_tree/yield_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.YieldExpression do 2 | @type t :: %ESTree.YieldExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | argument: ESTree.Expression.t | nil, 6 | delegate: boolean 7 | } 8 | defstruct type: "YieldExpression", 9 | loc: nil, 10 | argument: nil, 11 | delegate: false 12 | end 13 | -------------------------------------------------------------------------------- /lib/es_tree/template_element.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.TemplateElement do 2 | @type t :: %ESTree.TemplateElement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | value: %{cooked: binary, raw: binary}, 6 | tail: boolean 7 | } 8 | defstruct type: "TemplateElement", 9 | loc: nil, 10 | value: %{cooked: "", raw: ""}, 11 | tail: false 12 | end 13 | -------------------------------------------------------------------------------- /lib/es_tree/template_literal.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.TemplateLiteral do 2 | @type t :: %ESTree.TemplateLiteral{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | quasis: [ESTree.TemplateElement.t], 6 | expressions: [ESTree.Expression.t] 7 | } 8 | defstruct type: "TemplateLiteral", 9 | loc: nil, 10 | quasis: [], 11 | expressions: [] 12 | end -------------------------------------------------------------------------------- /lib/es_tree/catch_clause.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.CatchClause do 2 | @type t :: %ESTree.CatchClause{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | param: ESTree.Pattern.t, 6 | body: ESTree.BlockStatement.t 7 | } 8 | defstruct type: "CatchClause", 9 | loc: nil, 10 | param: %ESTree.EmptyExpression{}, 11 | body: %ESTree.BlockStatement{} 12 | end -------------------------------------------------------------------------------- /lib/es_tree/jsx_attribute.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.JSXAttribute do 2 | @type t :: %ESTree.JSXAttribute{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | name: ESTree.JSXIdentifier.t | ESTree.JSXNamespacedName.t, 6 | value: ESTree.Literal.t | ESTree.JSXExpressionContainer.t | ESTree.JSXElement.t | nil 7 | } 8 | defstruct type: "JSXAttribute", loc: nil, name: nil, value: nil 9 | end 10 | -------------------------------------------------------------------------------- /lib/es_tree/meta_property.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.MetaProperty do 2 | @type t :: %ESTree.MetaProperty{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | meta: ESTree.Identifier.t, 6 | property: ESTree.Identifier.t 7 | } 8 | defstruct type: "MetaProperty", 9 | loc: nil, 10 | meta: %ESTree.Identifier{}, 11 | property: %ESTree.Identifier{} 12 | end 13 | -------------------------------------------------------------------------------- /lib/es_tree/variable_declarator.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.VariableDeclarator do 2 | @type t :: %ESTree.VariableDeclarator{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | id: ESTree.Pattern.t , 6 | init: ESTree.Expression.t | nil 7 | } 8 | defstruct type: "VariableDeclarator", 9 | loc: nil, 10 | id: %ESTree.EmptyExpression{}, 11 | init: nil 12 | end -------------------------------------------------------------------------------- /lib/es_tree/class_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ClassExpression do 2 | @type t :: %ESTree.ClassExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | body: ESTree.ClassBody.t, 6 | superClass: ESTree.Expression.t | nil 7 | } 8 | defstruct type: "ClassExpression", 9 | loc: nil, 10 | body: %ESTree.ClassBody{}, 11 | superClass: nil 12 | end 13 | -------------------------------------------------------------------------------- /lib/es_tree/switch_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.SwitchStatement do 2 | @type t :: %ESTree.SwitchStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | discriminant: ESTree.Expression.t , 6 | cases: [ESTree.SwitchCase.t] 7 | } 8 | defstruct type: "SwitchStatement", 9 | loc: nil, 10 | discriminant: %ESTree.EmptyExpression{}, 11 | cases: [] 12 | end -------------------------------------------------------------------------------- /lib/es_tree/variable_declaration.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.VariableDeclaration do 2 | @type t :: %ESTree.VariableDeclaration{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | declarations: [ESTree.VariableDeclarator.t], 6 | kind: :var | :let | :const 7 | } 8 | defstruct type: "VariableDeclaration", 9 | loc: nil, 10 | declarations: [], 11 | kind: :var 12 | end -------------------------------------------------------------------------------- /lib/es_tree/while_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.WhileStatement do 2 | @type t :: %ESTree.WhileStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | test: ESTree.Expression.t , 6 | body: ESTree.Statement.t 7 | } 8 | defstruct type: "WhileStatement", 9 | loc: nil, 10 | test: %ESTree.EmptyExpression{}, 11 | body: %ESTree.EmptyStatement{} 12 | end -------------------------------------------------------------------------------- /lib/es_tree/with_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.WithStatement do 2 | @type t :: %ESTree.WithStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | object: ESTree.Expression.t , 6 | body: ESTree.Statement.t 7 | } 8 | defstruct type: "WithStatement", 9 | loc: nil, 10 | object: %ESTree.EmptyExpression{}, 11 | body: %ESTree.EmptyStatement{} 12 | end -------------------------------------------------------------------------------- /lib/es_tree/do_while_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.DoWhileStatement do 2 | @type t :: %ESTree.DoWhileStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | body: ESTree.Statement.t, 6 | test: ESTree.Expression.t 7 | } 8 | defstruct type: "DoWhileStatement", 9 | loc: nil, 10 | body: %ESTree.EmptyStatement{}, 11 | test: %ESTree.EmptyExpression{} 12 | end -------------------------------------------------------------------------------- /lib/es_tree/labeled_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.LabeledStatement do 2 | @type t :: %ESTree.LabeledStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | label: ESTree.Identifier.t, 6 | body: ESTree.Statement.t 7 | } 8 | defstruct type: "LabeledStatement", 9 | loc: nil, 10 | label: %ESTree.Identifier{}, 11 | body: %ESTree.EmptyStatement{} 12 | end -------------------------------------------------------------------------------- /lib/es_tree/new_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.NewExpression do 2 | @type t :: %ESTree.NewExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | callee: ESTree.Expression.t , 6 | arguments: [ESTree.Expression.t ] 7 | } 8 | defstruct type: "NewExpression", 9 | loc: nil, 10 | callee: %ESTree.EmptyExpression{}, 11 | arguments: [] 12 | end -------------------------------------------------------------------------------- /lib/es_tree/export_specifier.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ExportSpecifier do 2 | @type t :: %ESTree.ExportSpecifier{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | local: ESTree.Identifier.t, 6 | exported: ESTree.Identifier.t 7 | } 8 | defstruct type: "ExportSpecifier", 9 | loc: nil, 10 | local: %ESTree.Identifier{}, 11 | exported: %ESTree.Identifier{} 12 | end 13 | -------------------------------------------------------------------------------- /lib/es_tree/import_specifier.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ImportSpecifier do 2 | @type t :: %ESTree.ImportSpecifier{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | local: ESTree.Identifier.t, 6 | imported: ESTree.Identifier.t 7 | } 8 | defstruct type: "ImportSpecifier", 9 | loc: nil, 10 | local: %ESTree.Identifier{}, 11 | imported: %ESTree.Identifier{} 12 | end 13 | -------------------------------------------------------------------------------- /lib/es_tree/jsx_member_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.JSXMemberExpression do 2 | @type t :: %ESTree.JSXMemberExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | object: ESTree.JSXMemberExpression.t | ESTree.JSXIdentifier.t, 6 | property: ESTree.JSXIdentifier.t 7 | } 8 | 9 | defstruct type: "JSXMemberExpression", 10 | loc: nil, 11 | object: nil, 12 | property: nil 13 | 14 | end 15 | -------------------------------------------------------------------------------- /test/tools/generator/export_declaration_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ExportDeclaration.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert export all declaration" do 8 | ast = Builder.export_all_declaration(Builder.literal(:test)) 9 | 10 | assert_gen ast, "export * from 'test';" 11 | assert_gen ast, "export*from'test';", beauty: false 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/es_tree/tagged_template_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.TaggedTemplateExpression do 2 | @type t :: %ESTree.TaggedTemplateExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | tag: ESTree.Expression.t, 6 | quasi: ESTree.TemplateLiteral.t 7 | } 8 | defstruct type: "TaggedTemplateExpression", 9 | loc: nil, 10 | tag: %ESTree.EmptyExpression{}, 11 | quasi: %ESTree.TemplateLiteral{} 12 | end -------------------------------------------------------------------------------- /lib/es_tree/call_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.CallExpression do 2 | @type t :: %ESTree.CallExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | callee: ESTree.Expression.t | ESTree.Super.t, 6 | arguments: [ESTree.Expression.t | ESTree.SpreadElement.t] 7 | } 8 | defstruct type: "CallExpression", 9 | loc: nil, 10 | callee: %ESTree.EmptyExpression{}, 11 | arguments: [] 12 | end 13 | -------------------------------------------------------------------------------- /test/tools/generator/assignment_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.Assignment.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert assignment expression" do 8 | ast = Builder.assignment_expression( 9 | :=, 10 | Builder.identifier(:a), 11 | Builder.literal(0) 12 | ) 13 | 14 | assert_gen ast, "a = 0" 15 | assert_gen ast, "a=0", beauty: false 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/es_tree/export_named_declaration.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ExportNamedDeclaration do 2 | @type t :: %ESTree.ExportNamedDeclaration{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | declaration: ESTree.Declaration.t | nil, 6 | specifiers: [ESTree.ExportSpecifier], 7 | source: ESTree.Literal.t | nil 8 | } 9 | defstruct type: "ExportNamedDeclaration", 10 | loc: nil, 11 | declaration: nil, 12 | specifiers: [], 13 | source: nil 14 | end 15 | -------------------------------------------------------------------------------- /lib/es_tree/jsx_element.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.JSXElement do 2 | @type t :: %ESTree.JSXElement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | openingElement: ESTree.JSXOpeningElement.t, 6 | children: [ESTree.Literal.t | ESTree.JSXExpressionContainer.t | ESTree.JSXElement.t], 7 | closingElement: ESTree.JSXClosingElement.t | nil 8 | } 9 | defstruct type: "JSXElement", loc: nil, openingElement: nil, children: [], closingElement: nil 10 | end 11 | -------------------------------------------------------------------------------- /lib/es_tree/unary_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.UnaryExpression do 2 | @type t :: %ESTree.UnaryExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | operator: ESTree.unary_operator, 6 | prefix: boolean, 7 | argument: ESTree.Expression.t 8 | } 9 | defstruct type: "UnaryExpression", 10 | loc: nil, 11 | operator: nil, 12 | prefix: false, 13 | argument: %ESTree.EmptyExpression{} 14 | end -------------------------------------------------------------------------------- /lib/es_tree/import_declaration.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ImportDeclaration do 2 | @type t :: %ESTree.ImportDeclaration{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | specifiers: [ESTree.ImportSpecifier.t | ESTree.ImportNamespaceSpecifier.t | ESTree.ImportDefaultSpecifier.t], 6 | source: ESTree.Identifier.t | nil 7 | } 8 | defstruct type: "ImportDeclaration", 9 | loc: nil, 10 | specifiers: [], 11 | source: nil 12 | end -------------------------------------------------------------------------------- /lib/es_tree/update_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.UpdateExpression do 2 | @type t :: %ESTree.UpdateExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | operator: ESTree.update_operator, 6 | argument: ESTree.Expression.t , 7 | prefix: boolean 8 | } 9 | defstruct type: "UpdateExpression", 10 | loc: nil, 11 | operator: nil, 12 | argument: %ESTree.EmptyExpression{}, 13 | prefix: false 14 | end -------------------------------------------------------------------------------- /lib/es_tree/try_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.TryStatement do 2 | @type t :: %ESTree.TryStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | block: ESTree.BlockStatement.t, 6 | handler: ESTree.CaseClause.t | nil, 7 | finalizer: ESTree.BlockStatement.t | nil 8 | } 9 | defstruct type: "TryStatement", 10 | loc: nil, 11 | block: %ESTree.BlockStatement{}, 12 | handler: nil, 13 | finalizer: nil 14 | end -------------------------------------------------------------------------------- /lib/es_tree/class_declaration.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ClassDeclaration do 2 | @type t :: %ESTree.ClassDeclaration{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | id: ESTree.Identifier.t, 6 | body: ESTree.ClassBody.t, 7 | superClass: ESTree.Expression.t | nil 8 | } 9 | defstruct type: "ClassDeclaration", 10 | loc: nil, 11 | id: %ESTree.Identifier{}, 12 | body: %ESTree.ClassBody{}, 13 | superClass: nil 14 | end -------------------------------------------------------------------------------- /lib/es_tree/if_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.IfStatement do 2 | @type t :: %ESTree.IfStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | test: ESTree.Expression.t , 6 | consequent: ESTree.Statement.t , 7 | alternate: ESTree.Statement.t | nil 8 | } 9 | defstruct type: "IfStatement", 10 | loc: nil, 11 | test: %ESTree.EmptyExpression{}, 12 | consequent: %ESTree.EmptyStatement{}, 13 | alternate: nil 14 | end -------------------------------------------------------------------------------- /lib/es_tree/jsx_opening_element.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.JSXOpeningElement do 2 | @type t :: %ESTree.JSXOpeningElement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | name: ESTree.JSXIdentifier.t | ESTree.JSXMemberExpression.t | ESTree.JSXNamespacedName.t, 6 | attributes: [ ESTree.JSXAttribute.t | ESTree.JSXSpreadAttribute.t ], 7 | selfClosing: boolean 8 | } 9 | defstruct type: "JSXOpeningElement", loc: nil, name: nil, attributes: [], selfClosing: false 10 | end 11 | -------------------------------------------------------------------------------- /lib/es_tree/binary_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.BinaryExpression do 2 | @type t :: %ESTree.BinaryExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | operator: ESTree.binary_operator, 6 | left: ESTree.Expression.t, 7 | right: ESTree.Expression.t 8 | } 9 | defstruct type: "BinaryExpression", 10 | loc: nil, 11 | operator: nil, 12 | left: %ESTree.EmptyExpression{}, 13 | right: %ESTree.EmptyExpression{} 14 | end -------------------------------------------------------------------------------- /lib/es_tree/assignment_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.AssignmentExpression do 2 | @type t :: %ESTree.AssignmentExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | operator: ESTree.assignment_operator, 6 | left: ESTree.Pattern.t, 7 | right: ESTree.Expression.t 8 | } 9 | defstruct type: "AssignmentExpression", 10 | loc: nil, 11 | operator: nil, 12 | left: %ESTree.EmptyExpression{}, 13 | right: %ESTree.EmptyExpression{} 14 | end 15 | -------------------------------------------------------------------------------- /lib/es_tree/logical_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.LogicalExpression do 2 | @type t :: %ESTree.LogicalExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | operator: ESTree.logical_operator, 6 | left: ESTree.Expression.t , 7 | right: ESTree.Expression.t 8 | } 9 | defstruct type: "LogicalExpression", 10 | loc: nil, 11 | operator: nil, 12 | left: %ESTree.EmptyExpression{}, 13 | right: %ESTree.EmptyExpression{} 14 | end -------------------------------------------------------------------------------- /lib/es_tree/for_in_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ForInStatement do 2 | @type t :: %ESTree.ForInStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | left: ESTree.VariableDeclaration.t | ESTree.Pattern.t , 6 | right: ESTree.Expression.t , 7 | body: ESTree.Statement.t 8 | } 9 | defstruct type: "ForInStatement", 10 | loc: nil, 11 | left: %ESTree.EmptyExpression{}, 12 | right: %ESTree.EmptyExpression{}, 13 | body: %ESTree.EmptyStatement{} 14 | end 15 | -------------------------------------------------------------------------------- /lib/es_tree/for_of_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ForOfStatement do 2 | @type t :: %ESTree.ForOfStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | left: ESTree.VariableDeclaration.t | ESTree.Pattern.t , 6 | right: ESTree.Expression.t , 7 | body: ESTree.Statement.t 8 | } 9 | defstruct type: "ForOfStatement", 10 | loc: nil, 11 | left: %ESTree.EmptyExpression{}, 12 | right: %ESTree.EmptyExpression{}, 13 | body: %ESTree.EmptyStatement{} 14 | end 15 | -------------------------------------------------------------------------------- /lib/es_tree/conditional_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ConditionalStatement do 2 | @type t :: %ESTree.ConditionalStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | test: ESTree.Expression.t, 6 | alternate: ESTree.Expression.t, 7 | consequent: ESTree.Expression.t 8 | } 9 | defstruct type: "ConditionalStatement", 10 | loc: nil, 11 | test: %ESTree.EmptyExpression{}, 12 | alternate: %ESTree.EmptyExpression{}, 13 | consequent: %ESTree.EmptyExpression{} 14 | end -------------------------------------------------------------------------------- /lib/es_tree/member_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.MemberExpression do 2 | @type t :: %ESTree.MemberExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | object: ESTree.Expression.t | ESTree.Super.t, 6 | property: ESTree.Identifier.t | ESTree.Expression.t , 7 | computed: boolean 8 | } 9 | defstruct type: "MemberExpression", 10 | loc: nil, 11 | object: %ESTree.EmptyExpression{}, 12 | property: %ESTree.EmptyExpression{}, 13 | computed: false 14 | end 15 | -------------------------------------------------------------------------------- /test/tools/generator/throw_statement_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ThrowStatement.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert throw statement" do 8 | ast = Builder.throw_statement( 9 | Builder.new_expression( 10 | Builder.identifier(:Error), 11 | [Builder.literal("error")] 12 | ) 13 | ) 14 | 15 | assert_gen ast, "throw new Error('error');" 16 | assert_gen ast, "throw new Error('error');", beauty: false 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /test/tools/generator/identifier_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.Identifier.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert identifiers (binary)" do 8 | ast = Builder.identifier("hello") 9 | 10 | assert_gen ast, "hello" 11 | assert_gen ast, "hello", beauty: false 12 | end 13 | 14 | should "convert identifiers (atom)" do 15 | ast = Builder.identifier(:hello) 16 | 17 | assert_gen ast, "hello" 18 | assert_gen ast, "hello", beauty: false 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/es_tree/for_statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ForStatement do 2 | @type t :: %ESTree.ForStatement{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | init: ESTree.VariableDeclaration.t | ESTree.Expression.t | nil, 6 | test: ESTree.Expression.t | nil, 7 | update: ESTree.Expression.t | nil, 8 | body: ESTree.Statement.t 9 | } 10 | defstruct type: "ForStatement", 11 | loc: nil, 12 | init: nil, 13 | test: nil, 14 | update: nil, 15 | body: %ESTree.EmptyStatement{} 16 | end -------------------------------------------------------------------------------- /lib/es_tree/export_declaration.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ExportDeclaration do 2 | @type t :: %ESTree.ExportDeclaration{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | declaration: ESTree.Declaration.t, 6 | specifiers: [ESTree.ExportSpecifier.t], 7 | default: boolean, 8 | source: ESTree.Identifier.t | nil 9 | } 10 | defstruct type: "ExportDeclaration", 11 | loc: nil, 12 | declaration: %ESTree.EmptyStatement{}, 13 | specifiers: nil, 14 | default: false, 15 | source: nil 16 | end 17 | -------------------------------------------------------------------------------- /test/tools/generator/for_in_statement_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ForInStatement.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert for in statement" do 8 | ast = Builder.for_in_statement( 9 | Builder.variable_declaration([ 10 | Builder.variable_declarator(Builder.identifier(:a)) 11 | ]), 12 | Builder.identifier(:b), 13 | Builder.block_statement([]) 14 | ) 15 | 16 | assert_gen ast, "for (var a in b) {}" 17 | assert_gen ast, "for(var a in b){}", beauty: false 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /test/tools/generator/for_of_statement_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ForOfStatement.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert for of statement" do 8 | ast = Builder.for_of_statement( 9 | Builder.variable_declaration([ 10 | Builder.variable_declarator(Builder.identifier(:a)) 11 | ]), 12 | Builder.identifier(:b), 13 | Builder.block_statement([]) 14 | ) 15 | 16 | assert_gen ast, "for (var a of b) {}" 17 | assert_gen ast, "for(var a of b){}", beauty: false 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/es_tree/method_definition.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.MethodDefinition do 2 | @type t :: %ESTree.MethodDefinition{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | key: ESTree.Identifier.t, 6 | value: ESTree.FunctionExpression.t, 7 | kind: :contructor | :method | :get | :set, 8 | computed: boolean, 9 | static: boolean 10 | } 11 | defstruct type: "MethodDefinition", 12 | loc: nil, 13 | key: %ESTree.Identifier{}, 14 | value: %ESTree.FunctionExpression{}, 15 | kind: :"", 16 | computed: false, 17 | static: false 18 | end 19 | -------------------------------------------------------------------------------- /lib/es_tree/property.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Property do 2 | @type t :: %ESTree.Property{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | key: ESTree.Expression.t, 6 | value: ESTree.Expression.t, 7 | kind: :init | :get | :set, 8 | method: boolean, 9 | shorthand: boolean, 10 | computed: boolean 11 | } 12 | defstruct type: "Property", 13 | loc: nil, 14 | key: %ESTree.Literal{}, 15 | value: %ESTree.EmptyExpression{}, 16 | kind: :init, 17 | method: false, 18 | shorthand: false, 19 | computed: false 20 | end 21 | -------------------------------------------------------------------------------- /test/tools/generator/await_expression_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.AwaitExpression.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert await expression" do 8 | ast = Builder.await_expression( 9 | Builder.literal(1) 10 | ) 11 | 12 | assert_gen ast, "await 1" 13 | end 14 | 15 | should "convert await expression that contains an await" do 16 | ast = Builder.await_expression( 17 | Builder.await_expression( 18 | Builder.literal(1) 19 | ) 20 | ) 21 | 22 | assert_gen ast, "await (await 1)" 23 | end 24 | end -------------------------------------------------------------------------------- /lib/es_tree/function_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.FunctionExpression do 2 | @type t :: %ESTree.FunctionExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | params: [ESTree.Pattern.t], 6 | defaults: [ ESTree.Expression.t ], 7 | body: ESTree.BlockStatement.t, 8 | generator: boolean, 9 | expression: boolean, 10 | async: boolean 11 | } 12 | defstruct type: "FunctionExpression", 13 | loc: nil, 14 | params: [], 15 | defaults: [], 16 | body: %ESTree.BlockStatement{}, 17 | generator: false, 18 | expression: false, 19 | async: false 20 | end 21 | -------------------------------------------------------------------------------- /test/tools/generator/while_statement_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.WhileStatement.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert while" do 8 | ast = Builder.while_statement( 9 | Builder.identifier(:test), 10 | Builder.block_statement([]) 11 | ) 12 | 13 | assert_gen ast, "while (test) {}" 14 | assert_gen ast, "while(test){}", beauty: false 15 | end 16 | 17 | should "convert do while" do 18 | ast = Builder.do_while_statement( 19 | Builder.block_statement([]), 20 | Builder.identifier(:test) 21 | ) 22 | 23 | assert_gen ast, "do {} while (test);" 24 | assert_gen ast, "do{}while(test);", beauty: false 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/es_tree/arrow_function_expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.ArrowFunctionExpression do 2 | @type t :: %ESTree.ArrowFunctionExpression{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | params: [ESTree.Pattern.t], 6 | defaults: [ ESTree.Expression.t ], 7 | rest: ESTree.Identifier.t | nil, 8 | body: ESTree.BlockStatement.t | ESTree.Expression.t, 9 | generator: boolean, 10 | expression: boolean, 11 | async: boolean 12 | } 13 | defstruct type: "ArrowFunctionExpression", 14 | loc: nil, 15 | params: [], 16 | defaults: [], 17 | rest: nil, 18 | body: %ESTree.BlockStatement{}, 19 | generator: false, 20 | expression: false, 21 | async: false 22 | end 23 | -------------------------------------------------------------------------------- /lib/es_tree/function_declaration.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.FunctionDeclaration do 2 | @type t :: %ESTree.FunctionDeclaration{ 3 | type: binary, 4 | loc: ESTree.SourceLocation.t | nil, 5 | id: ESTree.Identifier.t, 6 | params: [ESTree.Pattern.t ], 7 | defaults: [ ESTree.Expression.t ], 8 | body: ESTree.BlockStatement.t | ESTree.Expression.t, 9 | generator: boolean, 10 | expression: boolean, 11 | async: boolean 12 | } 13 | defstruct type: "FunctionDeclaration", 14 | loc: nil, 15 | id: %ESTree.Identifier{}, 16 | params: [], 17 | defaults: [], 18 | body: %ESTree.BlockStatement{}, 19 | generator: false, 20 | expression: false, 21 | async: false 22 | end 23 | -------------------------------------------------------------------------------- /lib/es_tree/statement.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Statement do 2 | @type t :: ESTree.EmptyStatement.t | 3 | ESTree.BlockStatement.t | 4 | ESTree.ExpressionStatement.t | 5 | ESTree.IfStatement.t | 6 | ESTree.LabeledStatement.t | 7 | ESTree.BreakStatement.t | 8 | ESTree.ContinueStatement.t | 9 | ESTree.WithStatement.t | 10 | ESTree.SwitchStatement.t | 11 | ESTree.ReturnStatement.t | 12 | ESTree.ThrowStatement.t | 13 | ESTree.TryStatement.t | 14 | ESTree.WhileStatement.t | 15 | ESTree.DoWhileStatement.t | 16 | ESTree.ForStatement.t | 17 | ESTree.ForInStatement.t | 18 | ESTree.ForOfStatement.t | 19 | ESTree.DebuggerStatement.t | 20 | ESTree.ConditionalStatement.t | 21 | ESTree.Declaration.t 22 | end -------------------------------------------------------------------------------- /test/tools/generator/array_expression_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ArrayExpression.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert array when elements is nil" do 8 | assert_gen Builder.array_expression(nil), "[]" 9 | end 10 | 11 | should "convert array when elements is empty" do 12 | assert_gen Builder.array_expression([]), "[]" 13 | end 14 | 15 | should "convert array when elements contains one element" do 16 | assert_gen Builder.array_expression([ 17 | Builder.literal(1) 18 | ]), "[1]" 19 | end 20 | 21 | should "convert array when elements contains multiple elements" do 22 | ast = Builder.array_expression([ 23 | Builder.literal(1), 24 | Builder.identifier(:a), 25 | Builder.spread_element(Builder.identifier(:b)) 26 | ]) 27 | 28 | assert_gen ast, "[1, a, ...b]" 29 | assert_gen ast, "[1,a,...b]", beauty: false 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /test/tools/generator/array_pattern_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ArrayPattern.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert array pattern when elements is nil" do 8 | assert_gen Builder.array_pattern(nil), "[]" 9 | end 10 | 11 | should "convert array pattern when elements is empty" do 12 | assert_gen Builder.array_pattern([]), "[]" 13 | end 14 | 15 | should "convert array pattern when elements contains one element" do 16 | assert_gen Builder.array_pattern([ 17 | Builder.identifier(:a) 18 | ]), "[a]" 19 | end 20 | 21 | should "convert array pattern when elements contains multiple elements" do 22 | ast = Builder.array_pattern([ 23 | Builder.identifier(:a), 24 | Builder.identifier(:b), 25 | Builder.spread_element(Builder.identifier(:c)) 26 | ]) 27 | 28 | assert_gen ast, "[a, b, ...c]" 29 | assert_gen ast, "[a,b,...c]", beauty: false 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/es_tree/node.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Node do 2 | @type t :: ESTree.Program.t | 3 | ESTree.Function.t | 4 | ESTree.Statement.t | 5 | ESTree.VariableDeclarator.t | 6 | ESTree.Expression.t | 7 | ESTree.Property.t | 8 | ESTree.Pattern.t | 9 | ESTree.SwitchCase.t | 10 | ESTree.CatchClause.t | 11 | ESTree.MethodDefinition.t | 12 | ESTree.Class.t | 13 | ESTree.ClassBody.t | 14 | ESTree.ImportDeclaration.t | 15 | ESTree.ImportSpecifier.t | 16 | ESTree.ImportDefaultSpecifier.t | 17 | ESTree.ImportNamespaceSpecifier.t | 18 | ESTree.ExportNamedDeclaration.t | 19 | ESTree.ExportSpecifier.t | 20 | ESTree.ExportDefaultDeclaration.t | 21 | ESTree.ExportAllDeclaration.t | 22 | ESTree.TemplateElement.t | 23 | ESTree.Super.t 24 | end 25 | -------------------------------------------------------------------------------- /lib/es_tree/expression.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Expression do 2 | @type t :: ESTree.ThisExpression.t | 3 | ESTree.ArrayExpression.t | 4 | ESTree.ObjectExpression.t | 5 | ESTree.FunctionExpression.t | 6 | ESTree.ArrowFunctionExpression.t | 7 | ESTree.SequenceExpression.t | 8 | ESTree.UnaryExpression.t | 9 | ESTree.BinaryExpression.t | 10 | ESTree.AssignmentExpression.t | 11 | ESTree.UpdateExpression.t | 12 | ESTree.LogicalExpression.t | 13 | ESTree.NewExpression.t | 14 | ESTree.CallExpression.t | 15 | ESTree.MemberExpression.t | 16 | ESTree.YieldExpression.t | 17 | ESTree.Identifier.t | 18 | ESTree.Literal.t | 19 | ESTree.ClassExpression.t | 20 | ESTree.TemplateLiteral.t | 21 | ESTree.TaggedTemplateExpression.t | 22 | ESTree.AwaitExpression.t 23 | end -------------------------------------------------------------------------------- /test/tools/generator/conditional_statement_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ConditionalStatement.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert conditional statement" do 8 | ast = Builder.conditional_statement( 9 | Builder.identifier(:test), 10 | Builder.identifier(:alternate), 11 | Builder.identifier(:consequent) 12 | ) 13 | 14 | assert_gen ast, "test ? consequent : alternate" 15 | assert_gen ast, "test?consequent:alternate", beauty: false 16 | end 17 | 18 | should "convert conditional statement precedence" do 19 | ast = Builder.conditional_statement( 20 | Builder.assignment_expression( 21 | :=, 22 | Builder.identifier(:test), 23 | Builder.literal(1) 24 | ), 25 | Builder.identifier(:alternate), 26 | Builder.identifier(:consequent) 27 | ) 28 | 29 | assert_gen ast, "(test = 1) ? consequent : alternate" 30 | assert_gen ast, "(test=1)?consequent:alternate", beauty: false 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /config/config.exs: -------------------------------------------------------------------------------- 1 | # This file is responsible for configuring your application 2 | # and its dependencies with the aid of the Mix.Config module. 3 | use Mix.Config 4 | 5 | # This configuration is loaded before any dependency and is restricted 6 | # to this project. If another project depends on this project, this 7 | # file won't be loaded nor affect the parent project. For this reason, 8 | # if you want to provide default values for your application for third- 9 | # party users, it should be done in your mix.exs file. 10 | 11 | # Sample configuration: 12 | # 13 | # config :logger, :console, 14 | # level: :info, 15 | # format: "$date $time [$level] $metadata$message\n", 16 | # metadata: [:user_id] 17 | 18 | # It is also possible to import configuration files, relative to this 19 | # directory. For example, you can emulate configuration per environment 20 | # by uncommenting the line below and defining dev.exs, test.exs and such. 21 | # Configuration from the imported file will override the ones defined 22 | # here (which is why it is important to import them last). 23 | # 24 | # import_config "#{Mix.env}.exs" 25 | -------------------------------------------------------------------------------- /test/tools/generator/for_statement_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ForStatement.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert for statement empty" do 8 | ast = Builder.for_statement( 9 | nil, 10 | nil, 11 | nil, 12 | Builder.block_statement([]) 13 | ) 14 | 15 | assert_gen ast, "for (; ; ) {}" 16 | assert_gen ast, "for(;;){}", beauty: false 17 | end 18 | 19 | should "convert for statement" do 20 | ast = Builder.for_statement( 21 | Builder.variable_declaration([ 22 | Builder.variable_declarator(Builder.identifier(:i), Builder.literal(0)) 23 | ]), 24 | Builder.binary_expression( 25 | :<, 26 | Builder.identifier(:i), 27 | Builder.identifier(:length) 28 | ), 29 | Builder.unary_expression( 30 | :++, 31 | false, 32 | Builder.identifier(:i) 33 | ), 34 | Builder.block_statement([]) 35 | ) 36 | 37 | assert_gen ast, "for (var i = 0; i < length; i++) {}" 38 | assert_gen ast, "for(var i=0;i 1.0", 9 | deps: deps(), 10 | description: description(), 11 | package: package(), 12 | source_url: "https://github.com/bryanjos/elixir-estree" 13 | ] 14 | end 15 | 16 | def application do 17 | [extra_applications: [:logger]] 18 | end 19 | 20 | defp deps do 21 | [ 22 | {:ex_doc, "~> 0.21.1", only: :dev}, 23 | {:dialyze, "~> 0.2", only: :dev}, 24 | {:shouldi, "~> 0.3.2", only: :test}, 25 | {:poison, "~> 4.0", only: :test} 26 | ] 27 | end 28 | 29 | defp description do 30 | """ 31 | Represents the JavaScript AST from the ESTree spec. 32 | Includes tools for building an AST and generating code from it. 33 | """ 34 | end 35 | 36 | defp package do 37 | # These are the default files included in the package 38 | [ 39 | files: ["lib", "mix.exs", "README.md", "CHANGELOG.md"], 40 | maintainers: ["Bryan Joseph"], 41 | licenses: ["MIT"], 42 | links: %{"GitHub" => "https://github.com/bryanjos/elixir-estree"} 43 | ] 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /test/tools/generator/switch_statement_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.SwitchStatement.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert switch statement" do 8 | ast = Builder.switch_statement( 9 | Builder.identifier(:test), 10 | [ 11 | Builder.switch_case( 12 | Builder.identifier(:b), 13 | [Builder.break_statement()] 14 | ), 15 | Builder.switch_case( 16 | Builder.literal("c"), 17 | [Builder.break_statement()] 18 | ), 19 | Builder.switch_case( 20 | Builder.literal(1), 21 | [Builder.break_statement()] 22 | ), 23 | Builder.switch_case( 24 | nil, 25 | [Builder.break_statement()] 26 | ) 27 | ] 28 | ) 29 | 30 | str = """ 31 | switch (test) { 32 | case b: 33 | break; 34 | 35 | case 'c': 36 | break; 37 | 38 | case 1: 39 | break; 40 | 41 | default: 42 | break; 43 | } 44 | """ 45 | 46 | assert_gen ast, String.trim(str) 47 | assert_gen ast, "switch(test){case b:break;case 'c':break;case 1:break;default:break;}", beauty: false 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 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) 2 | 3 | 4 | Defines structs that represent the JavaScript AST nodes from the ESTree spec. 5 | 6 | [ESTree Spec](https://github.com/estree/estree) 7 | 8 | [JSX AST Spec](https://github.com/facebook/jsx) 9 | 10 | Also includes a JavaScript AST to JavaScript code generator. 11 | 12 | ```elixir 13 | alias ESTree.Tools.Builder 14 | alias ESTree.Tools.Generator 15 | 16 | ast = Builder.array_expression([ 17 | Builder.literal(1), 18 | Builder.identifier(:a) 19 | ]) 20 | 21 | Generator.generate(ast) 22 | # "[1, a]" 23 | 24 | #jsx ast and generation 25 | ast = Builder.jsx_element( 26 | Builder.jsx_opening_element( 27 | Builder.jsx_identifier( 28 | "Test" 29 | ) 30 | ), 31 | [], 32 | Builder.jsx_closing_element( 33 | Builder.jsx_identifier( 34 | "Test" 35 | ) 36 | ) 37 | ) 38 | 39 | Generator.generate(ast) 40 | # "" 41 | ``` 42 | -------------------------------------------------------------------------------- /test/tools/generator/try_statement_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.TryStatement.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert try with catch" do 8 | ast = Builder.try_statement( 9 | Builder.block_statement([]), 10 | Builder.catch_clause( 11 | Builder.identifier(:e), 12 | Builder.block_statement([]) 13 | ) 14 | ) 15 | 16 | assert_gen ast, "try {} catch (e) {}" 17 | assert_gen ast, "try{}catch(e){}", beauty: false 18 | end 19 | 20 | should "convert try with finally" do 21 | ast = Builder.try_statement( 22 | Builder.block_statement([]), 23 | nil, 24 | Builder.block_statement([]) 25 | ) 26 | 27 | assert_gen ast, "try {} finally {}" 28 | assert_gen ast, "try{}finally{}", beauty: false 29 | end 30 | 31 | should "convert try catch finally" do 32 | ast = Builder.try_statement( 33 | Builder.block_statement([]), 34 | Builder.catch_clause( 35 | Builder.identifier(:e), 36 | Builder.block_statement([]) 37 | ), 38 | Builder.block_statement([]) 39 | ) 40 | 41 | assert_gen ast, "try {} catch (e) {} finally {}" 42 | assert_gen ast, "try{}catch(e){}finally{}", beauty: false 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/es_tree.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree do 2 | @moduledoc """ 3 | Defines structs that represent the JavaScript AST nodes from the ESTree spec. 4 | 5 | [ESTree Spec](https://github.com/estree/estree) 6 | 7 | Also includes a JavaScript AST to JavaScript code generator. 8 | 9 | alias ESTree.Tools.Builder 10 | alias ESTree.Tools.Generator 11 | 12 | ast = Builder.array_expression([ 13 | Builder.literal(1), 14 | Builder.identifier(:a) 15 | ]) 16 | 17 | Generator.generate(ast) 18 | #"[1, a]" 19 | """ 20 | 21 | @type unary_operator :: :- | :+ | :! | :"~" | :typeof | :void | :delete 22 | 23 | @type binary_operator :: :== | :!= | :=== | :!== | :< | :<= | :> | :>= | 24 | :"<<" | :">>" | :>>> | :+ | :- | :* | :/ | :% | :| | 25 | :^ | :& | :in | :instanceof | :"**" 26 | 27 | @type logical_operator :: :|| | :&& 28 | 29 | @type assignment_operator :: := | :"+=" | :"-=" | :"*=" | :"/=" | :"%=" | 30 | :"<<=" | :">>=" | :">>>=" | 31 | :"|=" | :"^=" | :"&=" | :"**=" 32 | 33 | @type update_operator :: :++ | :-- 34 | 35 | @type operator :: unary_operator | binary_operator | logical_operator | assignment_operator | update_operator 36 | end 37 | -------------------------------------------------------------------------------- /mix.lock: -------------------------------------------------------------------------------- 1 | %{ 2 | "dialyze": {:hex, :dialyze, "0.2.1", "9fb71767f96649020d769db7cbd7290059daff23707d6e851e206b1fdfa92f9d", [:mix], []}, 3 | "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, 4 | "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"}, 5 | "makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, 6 | "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, 7 | "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, 8 | "poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm"}, 9 | "shouldi": {:hex, :shouldi, "0.3.2", "971f614669b5f37c03507ba643bb8e59aa165ac50ca66d726c9db53be255e440", [:mix], []}, 10 | } 11 | -------------------------------------------------------------------------------- /test/tools/generator/object_pattern_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Generator.ObjectPattern.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert object pattern" do 8 | ast = Builder.object_pattern([ 9 | Builder.property( 10 | Builder.identifier(:i), 11 | nil, 12 | :init, 13 | true 14 | ), 15 | Builder.property( 16 | Builder.identifier(:j), 17 | Builder.identifier(:k) 18 | ) 19 | ]) 20 | 21 | assert_gen ast, "{i, j: k}" 22 | assert_gen ast, "{i,j:k}", beauty: false 23 | 24 | ast = Builder.object_pattern([ 25 | Builder.property( 26 | Builder.identifier(:a), 27 | Builder.array_pattern([ 28 | Builder.identifier(:b), 29 | Builder.object_pattern([ 30 | Builder.property( 31 | Builder.identifier(:c), 32 | nil, 33 | :init, 34 | true 35 | ) 36 | ]) 37 | ]) 38 | ) 39 | ]) 40 | 41 | assert_gen ast, "{a: [b, {c}]}" 42 | assert_gen ast, "{a:[b,{c}]}", beauty: false 43 | 44 | ast = Builder.object_pattern([ 45 | Builder.property( 46 | Builder.identifier(:g), 47 | Builder.assignment_expression( 48 | :=, 49 | Builder.identifier(:h), 50 | Builder.literal(1) 51 | ) 52 | ) 53 | ]) 54 | 55 | assert_gen ast, "{g: h = 1}" 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /test/tools/generator/class_expression_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ClassExpression.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert class expression" do 8 | ast = Builder.class_expression( 9 | Builder.class_body([]) 10 | ) 11 | 12 | assert_gen ast, "class {}" 13 | assert_gen ast, "class{}", beauty: false 14 | end 15 | 16 | should "convert class expression when it extends identifier" do 17 | ast = Builder.class_expression( 18 | Builder.class_body([]), 19 | Builder.identifier(:Y) 20 | ) 21 | 22 | assert_gen ast, "class extends Y {}" 23 | assert_gen ast, "class extends Y{}", beauty: false 24 | end 25 | 26 | should "convert class expression when it extends class declaration" do 27 | ast = Builder.class_expression( 28 | Builder.class_body([]), 29 | Builder.class_declaration( 30 | Builder.identifier(:Y), 31 | Builder.class_body([]) 32 | ) 33 | ) 34 | 35 | assert_gen ast, "class extends class Y {} {}" 36 | assert_gen ast, "class extends class Y{}{}", beauty: false 37 | end 38 | 39 | should "convert class expression when it extends class expression" do 40 | ast = Builder.class_expression( 41 | Builder.class_body([]), 42 | Builder.class_expression( 43 | Builder.class_body([]) 44 | ) 45 | ) 46 | 47 | assert_gen ast, "class extends class {} {}" 48 | assert_gen ast, "class extends class{}{}", beauty: false 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /test/tools/generator/expression_statement_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ExpressionStatement.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert expression statement with class expression" do 8 | ast = Builder.expression_statement( 9 | Builder.class_expression( 10 | Builder.class_body([]) 11 | ) 12 | ) 13 | 14 | assert_gen ast, "(class {});" 15 | assert_gen ast, "(class{});", beauty: false 16 | end 17 | 18 | should "convert expression statement with function expression" do 19 | ast = Builder.expression_statement( 20 | Builder.function_expression( 21 | [], 22 | [], 23 | Builder.block_statement([]) 24 | ) 25 | ) 26 | 27 | assert_gen ast, "(function() {});" 28 | assert_gen ast, "(function(){});", beauty: false 29 | end 30 | 31 | should "convert expression statement with object expression" do 32 | ast = Builder.expression_statement( 33 | Builder.object_expression( 34 | [] 35 | ) 36 | ) 37 | 38 | assert_gen ast, "({});" 39 | assert_gen ast, "({});", beauty: false 40 | end 41 | 42 | should "convert expression statement with assignment expression" do 43 | ast = Builder.expression_statement( 44 | Builder.assignment_expression( 45 | :=, 46 | Builder.object_pattern([]), 47 | Builder.identifier(:a) 48 | ) 49 | ) 50 | 51 | assert_gen ast, "({} = a);" 52 | assert_gen ast, "({}=a);", beauty: false 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /test/tools/generator/variable_declaration_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.VariableDeclaration.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "emit var declaration" do 8 | ast = Builder.variable_declaration([]) 9 | 10 | assert_gen ast, "var ;" 11 | assert_gen ast, "var ;", beauty: false 12 | end 13 | 14 | should "emit let declaration" do 15 | ast = Builder.variable_declaration([], :let) 16 | 17 | assert_gen ast, "let ;" 18 | assert_gen ast, "let ;", beauty: false 19 | end 20 | 21 | should "emit const declaration" do 22 | ast = Builder.variable_declaration([], :const) 23 | 24 | assert_gen ast, "const ;" 25 | assert_gen ast, "const ;", beauty: false 26 | end 27 | 28 | should "add variable declarator" do 29 | ast = Builder.variable_declaration([ 30 | Builder.variable_declarator(Builder.identifier(:a)) 31 | ]) 32 | 33 | assert_gen ast, "var a;" 34 | assert_gen ast, "var a;", beauty: false 35 | end 36 | 37 | should "add variable declarators with corresponding inits" do 38 | ast = Builder.variable_declaration([ 39 | Builder.variable_declarator(Builder.identifier(:a), Builder.literal(1)), 40 | Builder.variable_declarator(Builder.identifier(:b)), 41 | Builder.variable_declarator( 42 | Builder.identifier(:c), 43 | Builder.binary_expression( 44 | :+, 45 | Builder.identifier(:a), 46 | Builder.literal(2) 47 | ) 48 | ) 49 | ]) 50 | 51 | assert_gen ast, "var a = 1,\n b,\n c = a + 2;" 52 | assert_gen ast, "var a=1,b,c=a+2;", beauty: false 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /test/tools/generator/class_declaration_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ClassDeclaration.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert class declaration" do 8 | ast = Builder.class_declaration( 9 | Builder.identifier(:X), 10 | Builder.class_body([]) 11 | ) 12 | 13 | assert_gen ast, "class X {}" 14 | assert_gen ast, "class X{}", beauty: false 15 | end 16 | 17 | should "convert class declaration when it extends identifier" do 18 | ast = Builder.class_declaration( 19 | Builder.identifier(:X), 20 | Builder.class_body([]), 21 | Builder.identifier(:Y) 22 | ) 23 | 24 | assert_gen ast, "class X extends Y {}" 25 | assert_gen ast, "class X extends Y{}", beauty: false 26 | end 27 | 28 | should "convert class declaration when it extends class declaration" do 29 | ast = Builder.class_declaration( 30 | Builder.identifier(:X), 31 | Builder.class_body([]), 32 | Builder.class_declaration( 33 | Builder.identifier(:Y), 34 | Builder.class_body([]) 35 | ) 36 | ) 37 | 38 | assert_gen ast, "class X extends class Y {} {}" 39 | assert_gen ast, "class X extends class Y{}{}", beauty: false 40 | end 41 | 42 | should "convert class declaration when it extends class expression" do 43 | ast = Builder.class_declaration( 44 | Builder.identifier(:X), 45 | Builder.class_body([]), 46 | Builder.class_expression( 47 | Builder.class_body([]) 48 | ) 49 | ) 50 | 51 | assert_gen ast, "class X extends class {} {}" 52 | assert_gen ast, "class X extends class{}{}", beauty: false 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /test/tools/generator/literal_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Generator.Literal.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert numbers" do 8 | assert_gen Builder.literal(1), "1" 9 | assert_gen Builder.literal(10), "10" 10 | assert_gen Builder.literal(1.012), "1.012" 11 | end 12 | 13 | should "convert booleans" do 14 | assert_gen Builder.literal(true), "true" 15 | assert_gen Builder.literal(false), "false" 16 | end 17 | 18 | should "convert string" do 19 | assert_gen Builder.literal("hello"), "'hello'" 20 | assert_gen Builder.literal("goodbye"), "'goodbye'" 21 | assert_gen Builder.literal(:hello), "'hello'" 22 | assert_gen Builder.literal(:goodbye), "'goodbye'" 23 | end 24 | 25 | should "convert string escape" do 26 | assert_gen Builder.literal("\\"), "'\\\\'" 27 | assert_gen Builder.literal("\n"), "'\\n'" 28 | assert_gen Builder.literal("\r"), "'\\r'" 29 | assert_gen Builder.literal("\t"), "'\\t'" 30 | assert_gen Builder.literal("\b"), "'\\b'" 31 | assert_gen Builder.literal("\f"), "'\\f'" 32 | assert_gen Builder.literal("\v"), "'\\v'" 33 | assert_gen Builder.literal("\u2028"), "'\\u2028'" 34 | assert_gen Builder.literal("\u2029"), "'\\u2029'" 35 | assert_gen Builder.literal("\ufeff"), "'\\ufeff'" 36 | assert_gen Builder.literal("'"), "'\\''" 37 | end 38 | 39 | should "convert null" do 40 | assert_gen Builder.literal(nil), "null" 41 | end 42 | 43 | should "convert regex" do 44 | assert_gen Builder.literal(%{}, Builder.regex("^abc$", "i")), "/^abc$/i" 45 | assert_gen Builder.literal(%{}, Builder.regex("^abc$", "")), "/^abc$/" 46 | assert_gen Builder.literal(%{}, Builder.regex("", "")), "//" 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /test/tools/generator/if_statement_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.IfStatement.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert if without else" do 8 | ast = Builder.if_statement( 9 | Builder.identifier(:test), 10 | Builder.block_statement([]) 11 | ) 12 | 13 | assert_gen ast, "if (test) {}" 14 | assert_gen ast, "if(test){}", beauty: false 15 | end 16 | 17 | should "convert if with else" do 18 | ast = Builder.if_statement( 19 | Builder.identifier(:test), 20 | Builder.block_statement([]), 21 | Builder.block_statement([]) 22 | ) 23 | 24 | assert_gen ast, "if (test) {} else {}" 25 | assert_gen ast, "if(test){}else{}", beauty: false 26 | end 27 | 28 | should "convert if with else if" do 29 | ast = Builder.if_statement( 30 | Builder.identifier(:test), 31 | Builder.block_statement([]), 32 | Builder.if_statement( 33 | Builder.identifier(:test), 34 | Builder.block_statement([]), 35 | Builder.block_statement([]) 36 | ) 37 | ) 38 | 39 | assert_gen ast, "if (test) {} else if (test) {} else {}" 40 | assert_gen ast, "if(test){}else if(test){}else{}", beauty: false 41 | end 42 | 43 | should "convert if statement with short syntax" do 44 | ast = Builder.if_statement( 45 | Builder.identifier(:test), 46 | Builder.return_statement(Builder.literal(1)), 47 | Builder.if_statement( 48 | Builder.identifier(:test2), 49 | Builder.return_statement(Builder.literal(2)), 50 | Builder.return_statement(Builder.literal(3)) 51 | ) 52 | ) 53 | 54 | assert_gen ast, "if (test)\n return 1;\nelse if (test2)\n return 2;\nelse\n return 3;" 55 | assert_gen ast, "if(test)return 1;else if(test2)return 2;else return 3;", beauty: false 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /test/tools/generator/unary_expression_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Generator.UnaryExpression.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert unary expression !true" do 8 | ast = Builder.unary_expression( 9 | :!, 10 | true, 11 | Builder.literal(true) 12 | ) 13 | 14 | assert_gen ast, "!true" 15 | assert_gen ast, "!true", beauty: false 16 | end 17 | 18 | should "convert unary expression !false" do 19 | ast = Builder.unary_expression( 20 | :!, 21 | true, 22 | Builder.literal(false) 23 | ) 24 | 25 | assert_gen ast, "!false" 26 | assert_gen ast, "!false", beauty: false 27 | end 28 | 29 | should "convert unary expression !typeof" do 30 | ast = Builder.unary_expression( 31 | :!, 32 | true, 33 | Builder.unary_expression( 34 | :typeof, 35 | true, 36 | Builder.identifier(:x) 37 | ) 38 | ) 39 | 40 | assert_gen ast, "!typeof x" 41 | assert_gen ast, "!typeof x", beauty: false 42 | end 43 | 44 | should "convert unary expression ! and typeof with binary expression" do 45 | ast = Builder.unary_expression( 46 | :!, 47 | true, 48 | Builder.binary_expression( 49 | :===, 50 | Builder.unary_expression( 51 | :typeof, 52 | true, 53 | Builder.identifier(:x) 54 | ), 55 | Builder.literal("boolean") 56 | ) 57 | ) 58 | 59 | assert_gen ast, "!(typeof x === 'boolean')" 60 | assert_gen ast, "!(typeof x==='boolean')", beauty: false 61 | end 62 | 63 | should "convert unary expression delete" do 64 | ast = Builder.unary_expression( 65 | :delete, 66 | true, 67 | Builder.identifier(:a) 68 | ) 69 | 70 | assert_gen ast, "delete a" 71 | assert_gen ast, "delete a", beauty: false 72 | end 73 | 74 | should "convert unary expression void" do 75 | ast = Builder.unary_expression( 76 | :void, 77 | true, 78 | Builder.identifier(:a) 79 | ) 80 | 81 | assert_gen ast, "void a" 82 | assert_gen ast, "void a", beauty: false 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /test/tools/generator/import_declaration_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ImportDeclaration.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert import declaration with one specifier" do 8 | ast = Builder.import_declaration([ 9 | Builder.import_specifier( 10 | Builder.identifier(:test), 11 | Builder.identifier(:test) 12 | )], 13 | Builder.literal(:test) 14 | ) 15 | 16 | assert_gen ast, "import { test } from 'test';" 17 | assert_gen ast, "import{test}from'test';", beauty: false 18 | end 19 | 20 | should "convert import declaration with one specifier with an alias" do 21 | ast = Builder.import_declaration([ 22 | Builder.import_specifier( 23 | Builder.identifier(:test), 24 | Builder.identifier(:test1) 25 | )], 26 | Builder.literal(:test) 27 | ) 28 | 29 | assert_gen ast, "import { test as test1 } from 'test';" 30 | assert_gen ast, "import{test as test1}from'test';", beauty: false 31 | end 32 | 33 | should "convert import declaration with more than one specifier" do 34 | ast = Builder.import_declaration( 35 | [ 36 | Builder.import_specifier( 37 | Builder.identifier(:top), 38 | Builder.identifier(:top) 39 | ), 40 | Builder.import_specifier( 41 | Builder.identifier(:test), 42 | Builder.identifier(:test1) 43 | ) 44 | ], 45 | Builder.literal(:test) 46 | ) 47 | 48 | assert_gen ast, "import { top, test as test1 } from 'test';" 49 | assert_gen ast, "import{top,test as test1}from'test';", beauty: false 50 | end 51 | 52 | 53 | should "convert import declaration with one default specifier" do 54 | ast = Builder.import_declaration([ 55 | Builder.import_default_specifier( 56 | Builder.identifier(:test), 57 | Builder.identifier(:test) 58 | )], 59 | Builder.literal(:test) 60 | ) 61 | 62 | assert_gen ast, "import test from 'test';" 63 | assert_gen ast, "import test from'test';", beauty: false 64 | end 65 | 66 | should "convert import declaration with a namespace specifier" do 67 | ast = Builder.import_declaration([ 68 | Builder.import_namespace_specifier( 69 | Builder.identifier(:test) 70 | )], 71 | Builder.literal(:test) 72 | ) 73 | 74 | assert_gen ast, "import * as test from 'test';" 75 | assert_gen ast, "import*as test from'test';", beauty: false 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # v2.7.0 2 | 3 | - Enhancements: 4 | - [Allow for options to be customized (https://github.com/elixirscript/elixir-estree/pull/27) 5 | 6 | # v2.6.1 7 | 8 | - Enhancements: 9 | - Add async to arrow function expressions 10 | 11 | # v2.6.0 12 | 13 | - Enhancements: 14 | - [Add parenthesis around await expressions in await expressions or in call expressions](https://github.com/elixirscript/elixir-estree/pull/20) 15 | - [Add ESTree.Tools.ESTreeJSONTransformer to translate ESTree JSON data into structs](https://github.com/bryanjos/elixir-estree/pull/21) 16 | 17 | # v2.5.1 18 | 19 | - Enhancements: 20 | - [Correct If statement identation](https://github.com/bryanjos/elixir-estree/pull/18) 21 | 22 | # v2.5.0 23 | 24 | - Enhancements: 25 | - [Greatly improved formatting of generated JavaScript](https://github.com/bryanjos/elixir-estree/pull/15) 26 | 27 | # v2.4.2 28 | 29 | - Fixes 30 | - [Expressions in variable declarations](https://github.com/bryanjos/elixir-estree/pull/13) 31 | 32 | # v2.4.1 33 | 34 | - Fixes 35 | - Handle edge case when string literal is a JSX child 36 | 37 | # v2.4.0 38 | 39 | - Enhancements: 40 | - Added exponential operators from ES2016 41 | 42 | # v2.3.0 43 | 44 | - Enhancements: 45 | - Added AssignmentProperty for use with ObjectPattern 46 | - Updated some typespecs to reflect updates in ESTree spec 47 | 48 | # v2.2.0 49 | 50 | - Enhancements: 51 | - Added structs for JSX AST 52 | 53 | # v2.1.2 54 | 55 | - Bug fixes 56 | - ESTree.Tools.Generator: updated UnaryExpression to put space in when operator is :typeof 57 | 58 | # v2.1.1 59 | 60 | - Enhancements 61 | - ESTree.Tools.Generator: Updated yield to account for delegate field 62 | 63 | # v2.1.0 64 | 65 | - Enhancements 66 | - Added async field to FunctionDeclaration and FunctionExpression 67 | - Added AwaitExpression 68 | 69 | # v2.0.1 70 | 71 | - Enhancements 72 | - Changed TemplateElement.value.value to TemplateElement.value.raw 73 | - Began adding indentation 74 | - Added empty string for when nil is given to generate 75 | 76 | # v2.0.0 77 | 78 | - Enhancements 79 | 80 | - Updated to latest ESTree Spec 81 | - Added ESTree.Tools.Generator to turn JavaScript AST into code 82 | 83 | - Breaking 84 | - ESTree.Builder is now ESTree.Tools.Builder 85 | 86 | # v1.0.1 87 | 88 | - Enhancements 89 | - Add new regex property to literal 90 | 91 | # v1.0.0 92 | 93 | - Enhancements 94 | - Has the Node definitions from the [ESTree Spec](https://github.com/estree/estree) 95 | - 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) 96 | -------------------------------------------------------------------------------- /test/tools/generator/new_expression_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.NewExpression.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert new expression when arguments are empty" do 8 | ast = Builder.new_expression( 9 | Builder.identifier(:X), 10 | [] 11 | ) 12 | 13 | assert_gen ast, "new X()" 14 | assert_gen ast, "new X()", beauty: false 15 | end 16 | 17 | should "convert new expression when argument" do 18 | ast = Builder.new_expression( 19 | Builder.identifier(:X), 20 | [Builder.identifier(:a)] 21 | ) 22 | 23 | assert_gen ast, "new X(a)" 24 | assert_gen ast, "new X(a)", beauty: false 25 | end 26 | 27 | should "convert new expression when callee is member expression" do 28 | ast = Builder.new_expression( 29 | Builder.member_expression( 30 | Builder.identifier(:x), 31 | Builder.identifier(:Y) 32 | ), 33 | [] 34 | ) 35 | 36 | assert_gen ast, "new x.Y()" 37 | assert_gen ast, "new x.Y()", beauty: false 38 | end 39 | 40 | should "convert new expression when callee is call expression" do 41 | ast = Builder.new_expression( 42 | Builder.member_expression( 43 | Builder.call_expression( 44 | Builder.identifier(:x), 45 | [] 46 | ), 47 | Builder.identifier(:Y) 48 | ), 49 | [] 50 | ) 51 | 52 | assert_gen ast, "new (x().Y)()" 53 | assert_gen ast, "new (x().Y)()", beauty: false 54 | end 55 | 56 | should "convert new expression when callee is new expression" do 57 | ast = Builder.new_expression( 58 | Builder.new_expression( 59 | Builder.identifier(:X), 60 | [] 61 | ), 62 | [] 63 | ) 64 | 65 | assert_gen ast, "new new X()()" 66 | assert_gen ast, "new new X()()", beauty: false 67 | end 68 | 69 | should "convert new expression when callee is sequence expression" do 70 | ast = Builder.new_expression( 71 | Builder.sequence_expression([ 72 | Builder.identifier(:X), 73 | Builder.identifier(:Y) 74 | ]), 75 | [] 76 | ) 77 | 78 | assert_gen ast, "new (X, Y)()" 79 | assert_gen ast, "new (X,Y)()", beauty: false 80 | end 81 | 82 | should "convert new expression when callee is conditional statement" do 83 | ast = Builder.new_expression( 84 | Builder.conditional_statement( 85 | Builder.literal(true), 86 | Builder.identifier(:Y), 87 | Builder.identifier(:X) 88 | ), 89 | [] 90 | ) 91 | 92 | assert_gen ast, "new (true ? X : Y)()" 93 | assert_gen ast, "new (true?X:Y)()", beauty: false 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /test/tools/generator/arrow_function_expression_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ArrowFunctionExpression.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert basic arrow function" do 8 | ast = Builder.arrow_function_expression( 9 | [], 10 | [], 11 | Builder.block_statement([]), 12 | false, 13 | false 14 | ) 15 | 16 | assert_gen ast, "() => {}" 17 | assert_gen ast, "()=>{}", beauty: false 18 | end 19 | 20 | should "convert basic arrow function returns object" do 21 | ast = Builder.arrow_function_expression( 22 | [], 23 | [], 24 | Builder.object_expression([]), 25 | false, 26 | false 27 | ) 28 | 29 | assert_gen ast, "() => ({})" 30 | assert_gen ast, "()=>({})", beauty: false 31 | end 32 | 33 | should "convert basic arrow function object pattern has parens" do 34 | ast = Builder.arrow_function_expression( 35 | [Builder.object_pattern([Builder.identifier(:one)])], 36 | [], 37 | Builder.block_statement([]), 38 | false, 39 | false 40 | ) 41 | 42 | assert_gen ast, "({one}) => {}" 43 | assert_gen ast, "({one})=>{}", beauty: false 44 | end 45 | 46 | should "convert basic arrow function expression generator" do 47 | ast = Builder.arrow_function_expression( 48 | [], 49 | [], 50 | Builder.block_statement([]), 51 | true, 52 | false 53 | ) 54 | 55 | assert_gen ast, "()* => {}" 56 | assert_gen ast, "()*=>{}", beauty: false 57 | end 58 | 59 | should "convert arrow function with params" do 60 | ast = Builder.arrow_function_expression( 61 | [Builder.identifier(:one)], 62 | [], 63 | Builder.block_statement([]), 64 | false, 65 | false 66 | ) 67 | 68 | assert_gen ast, "(one) => {}" 69 | assert_gen ast, "one=>{}", beauty: false 70 | 71 | ast = Builder.arrow_function_expression( 72 | [Builder.identifier(:one), Builder.identifier(:two)], 73 | [], 74 | Builder.block_statement([]), 75 | false, 76 | false 77 | ) 78 | 79 | assert_gen ast, "(one, two) => {}" 80 | assert_gen ast, "(one,two)=>{}", beauty: false 81 | end 82 | 83 | should "convert arrow function with default values" do 84 | ast = Builder.arrow_function_expression( 85 | [Builder.identifier(:one), Builder.identifier(:two)], 86 | [nil, Builder.literal(1)], 87 | Builder.block_statement([]), 88 | false, 89 | false 90 | ) 91 | 92 | assert_gen ast, "(one, two = 1) => {}" 93 | assert_gen ast, "(one,two=1)=>{}", beauty: false 94 | end 95 | 96 | should "convert basic arrow function expression async" do 97 | ast = Builder.arrow_function_expression( 98 | [], 99 | [], 100 | Builder.block_statement([]), 101 | false, 102 | false, 103 | true 104 | ) 105 | 106 | assert_gen ast, "async () => {}" 107 | assert_gen ast, "async ()=>{}", beauty: false 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /test/tools/generator/binary_expression_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Generator.BinaryExpression.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert binary expression with correct precedence" do 8 | ast = Builder.binary_expression( 9 | :+, 10 | Builder.literal(1), 11 | Builder.binary_expression( 12 | :/, 13 | Builder.binary_expression( 14 | :*, 15 | Builder.literal(2), 16 | Builder.literal(3) 17 | ), 18 | Builder.literal(4) 19 | ) 20 | ) 21 | 22 | assert_gen ast, "1 + 2 * 3 / 4" 23 | assert_gen ast, "1+2*3/4", beauty: false 24 | 25 | ast = Builder.binary_expression( 26 | :+, 27 | Builder.literal(1), 28 | Builder.binary_expression( 29 | :*, 30 | Builder.literal(2), 31 | Builder.binary_expression( 32 | :/, 33 | Builder.literal(3), 34 | Builder.literal(4) 35 | ) 36 | ) 37 | ) 38 | 39 | assert_gen ast, "1 + 2 * (3 / 4)" 40 | assert_gen ast, "1+2*(3/4)", beauty: false 41 | 42 | ast = Builder.binary_expression( 43 | :/, 44 | Builder.binary_expression( 45 | :*, 46 | Builder.binary_expression( 47 | :+, 48 | Builder.literal(1), 49 | Builder.literal(2) 50 | ), 51 | Builder.literal(3) 52 | ), 53 | Builder.literal(4) 54 | ) 55 | 56 | assert_gen ast, "(1 + 2) * 3 / 4" 57 | assert_gen ast, "(1+2)*3/4", beauty: false 58 | 59 | ast = Builder.binary_expression( 60 | :*, 61 | Builder.binary_expression( 62 | :+, 63 | Builder.literal(1), 64 | Builder.literal(2) 65 | ), 66 | Builder.binary_expression( 67 | :/, 68 | Builder.literal(3), 69 | Builder.literal(4) 70 | ) 71 | ) 72 | 73 | assert_gen ast, "(1 + 2) * (3 / 4)" 74 | assert_gen ast, "(1+2)*(3/4)", beauty: false 75 | end 76 | 77 | should "convert binary expression in" do 78 | ast = Builder.binary_expression( 79 | :in, 80 | Builder.identifier(:a), 81 | Builder.identifier(:b) 82 | ) 83 | 84 | assert_gen ast, "(a in b)" 85 | assert_gen ast, "(a in b)", beauty: false 86 | end 87 | 88 | should "convert binary expression instanceof" do 89 | ast = Builder.binary_expression( 90 | :instanceof, 91 | Builder.unary_expression( 92 | :!, 93 | true, 94 | Builder.identifier(:x) 95 | ), 96 | Builder.identifier(:Number) 97 | ) 98 | 99 | assert_gen ast, "!x instanceof Number" 100 | assert_gen ast, "!x instanceof Number", beauty: false 101 | 102 | ast = Builder.unary_expression( 103 | :!, 104 | true, 105 | Builder.binary_expression( 106 | :instanceof, 107 | Builder.identifier(:x), 108 | Builder.identifier(:Number) 109 | ) 110 | ) 111 | 112 | assert_gen ast, "!(x instanceof Number)" 113 | assert_gen ast, "!(x instanceof Number)", beauty: false 114 | end 115 | end 116 | -------------------------------------------------------------------------------- /test/tools/generator/template_literal_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.TemplateLiteral.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert empty template literal" do 8 | ast = Builder.template_literal([],[]) 9 | 10 | assert_gen ast, "``" 11 | assert_gen ast, "``", beauty: false 12 | end 13 | 14 | should "convert template literal with no expressions" do 15 | ast = Builder.template_literal([ 16 | Builder.template_element("hello ", "hello ", false, 17 | Builder.source_location( 18 | nil, 19 | Builder.position(0, 1), 20 | Builder.position(0, 5) 21 | ) 22 | ), 23 | Builder.template_element("there", "there", true, 24 | Builder.source_location( 25 | nil, 26 | Builder.position(0, 5), 27 | Builder.position(0, 10) 28 | ) 29 | ) 30 | ], []) 31 | 32 | assert_gen ast, "`hello there`" 33 | assert_gen ast, "`hello there`", beauty: false 34 | end 35 | 36 | should "convert template literal with no quasis" do 37 | ast = Builder.template_literal( 38 | [], 39 | [ 40 | Builder.identifier(:a, 41 | Builder.source_location( 42 | nil, 43 | Builder.position(0, 1), 44 | Builder.position(0, 2) 45 | ) 46 | ) 47 | ] 48 | ) 49 | 50 | assert_gen ast, "`${a}`" 51 | assert_gen ast, "`${a}`", beauty: false 52 | end 53 | 54 | 55 | should "convert template literal with interlaping quasis and expressions" do 56 | ast = Builder.template_literal([ 57 | Builder.template_element("hello ", "hello ", false, 58 | Builder.source_location( 59 | nil, 60 | Builder.position(0, 1), 61 | Builder.position(0, 5) 62 | ) 63 | ), 64 | Builder.template_element(" there", " there", true, 65 | Builder.source_location( 66 | nil, 67 | Builder.position(0, 6), 68 | Builder.position(0, 12) 69 | ) 70 | ) 71 | ], [ 72 | Builder.identifier(:a, 73 | Builder.source_location( 74 | nil, 75 | Builder.position(0, 5), 76 | Builder.position(0, 6) 77 | ) 78 | ) 79 | ]) 80 | 81 | assert_gen ast, "`hello ${a} there`" 82 | assert_gen ast, "`hello ${a} there`", beauty: false 83 | end 84 | 85 | should "convert tagged template expressions" do 86 | ast = Builder.tagged_template_expression( 87 | Builder.identifier(:tag), 88 | Builder.template_literal([ 89 | Builder.template_element("hello ", "hello ", false, 90 | Builder.source_location( 91 | nil, 92 | Builder.position(0, 1), 93 | Builder.position(0, 5) 94 | ) 95 | ), 96 | Builder.template_element(" there", " there", true, 97 | Builder.source_location( 98 | nil, 99 | Builder.position(0, 6), 100 | Builder.position(0, 12) 101 | ) 102 | ) 103 | ],[ 104 | Builder.identifier(:a, 105 | Builder.source_location( 106 | nil, 107 | Builder.position(0, 5), 108 | Builder.position(0, 6) 109 | ) 110 | ) 111 | ]) 112 | ) 113 | 114 | assert_gen ast, "tag `hello ${a} there`" 115 | assert_gen ast, "tag `hello ${a} there`", beauty: false 116 | end 117 | end 118 | -------------------------------------------------------------------------------- /test/tools/generator/call_expression_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.CallExpression.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert call expression when arguments is empty" do 8 | ast = Builder.call_expression(Builder.identifier(:x), []); 9 | 10 | assert_gen ast, "x()" 11 | assert_gen ast, "x()", beauty: false 12 | end 13 | 14 | should "convert call expression with one argument" do 15 | ast = Builder.call_expression( 16 | Builder.identifier(:x), 17 | [ 18 | Builder.identifier(:a) 19 | ] 20 | ); 21 | 22 | assert_gen ast, "x(a)" 23 | assert_gen ast, "x(a)", beauty: false 24 | end 25 | 26 | should "convert call expression with spread" do 27 | ast = Builder.call_expression( 28 | Builder.identifier(:x), 29 | [ 30 | Builder.spread_element(Builder.identifier(:a)) 31 | ] 32 | ); 33 | 34 | assert_gen ast, "x(...a)" 35 | assert_gen ast, "x(...a)", beauty: false 36 | end 37 | 38 | should "convert call expression with arguments" do 39 | ast = Builder.call_expression( 40 | Builder.identifier(:x), 41 | [ 42 | Builder.identifier(:a), 43 | Builder.identifier(:b) 44 | ] 45 | ); 46 | 47 | assert_gen ast, "x(a, b)" 48 | assert_gen ast, "x(a,b)", beauty: false 49 | end 50 | 51 | should "convert call expression with arguments and spread" do 52 | ast = Builder.call_expression( 53 | Builder.identifier(:x), 54 | [ 55 | Builder.identifier(:a), 56 | Builder.identifier(:b), 57 | Builder.spread_element(Builder.identifier(:c)) 58 | ] 59 | ); 60 | 61 | assert_gen ast, "x(a, b, ...c)" 62 | assert_gen ast, "x(a,b,...c)", beauty: false 63 | end 64 | 65 | should "convert call expression when callee is member expression" do 66 | ast = Builder.call_expression( 67 | Builder.member_expression( 68 | Builder.identifier(:x), 69 | Builder.identifier(:y) 70 | ), 71 | [] 72 | ); 73 | 74 | assert_gen ast, "x.y()" 75 | assert_gen ast, "x.y()", beauty: false 76 | end 77 | 78 | should "convert call expression when callee is binary expression" do 79 | ast = Builder.call_expression( 80 | Builder.member_expression( 81 | Builder.binary_expression( 82 | :+, 83 | Builder.identifier(:a), 84 | Builder.identifier(:b) 85 | ), 86 | Builder.identifier(:x) 87 | ), 88 | [] 89 | ); 90 | 91 | assert_gen ast, "(a + b).x()" 92 | assert_gen ast, "(a+b).x()", beauty: false 93 | end 94 | 95 | should "convert call expression with one argument that is an await" do 96 | ast = Builder.call_expression( 97 | Builder.identifier(:x), 98 | [ 99 | Builder.await_expression( 100 | Builder.identifier(:a) 101 | ) 102 | ] 103 | ); 104 | 105 | assert_gen ast, "x((await a))" 106 | assert_gen ast, "x((await a))", beauty: false 107 | end 108 | 109 | should "convert call expression with one argument that is a yield" do 110 | ast = Builder.call_expression( 111 | Builder.identifier(:x), 112 | [ 113 | Builder.yield_expression( 114 | Builder.identifier(:a) 115 | ) 116 | ] 117 | ); 118 | 119 | assert_gen ast, "x((yield a))" 120 | assert_gen ast, "x((yield a))", beauty: false 121 | end 122 | 123 | should "convert call expression when callee is member expression and is an await" do 124 | ast = Builder.call_expression( 125 | Builder.member_expression( 126 | Builder.await_expression( 127 | Builder.identifier(:x) 128 | ), 129 | Builder.identifier(:y) 130 | ), 131 | [] 132 | ); 133 | 134 | assert_gen ast, "(await x).y()" 135 | assert_gen ast, "(await x).y()", beauty: false 136 | end 137 | end 138 | -------------------------------------------------------------------------------- /test/tools/generator/export_default_declaration_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ExportDefaultDeclaration.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert export default declaration with function declaration" do 8 | ast = Builder.export_default_declaration( 9 | Builder.function_declaration( 10 | Builder.identifier(:x), 11 | [], 12 | [], 13 | Builder.block_statement([]) 14 | ) 15 | ) 16 | 17 | assert_gen ast, "export default function x() {}" 18 | assert_gen ast, "export default function x(){}", beauty: false 19 | end 20 | 21 | should "convert export default declaration with function expression" do 22 | ast = Builder.export_default_declaration( 23 | Builder.function_expression( 24 | [], 25 | [], 26 | Builder.block_statement([]) 27 | ) 28 | ) 29 | 30 | assert_gen ast, "export default function() {};" 31 | assert_gen ast, "export default function(){};", beauty: false 32 | end 33 | 34 | should "convert export default declaration with function declaration generator" do 35 | ast = Builder.export_default_declaration( 36 | Builder.function_declaration( 37 | Builder.identifier(:x), 38 | [], 39 | [], 40 | Builder.block_statement([]), 41 | true 42 | ) 43 | ) 44 | 45 | assert_gen ast, "export default function* x() {}" 46 | assert_gen ast, "export default function*x(){}", beauty: false 47 | end 48 | 49 | should "convert export default declaration with function expression generator" do 50 | ast = Builder.export_default_declaration( 51 | Builder.function_expression( 52 | [], 53 | [], 54 | Builder.block_statement([]), 55 | true 56 | ) 57 | ) 58 | 59 | assert_gen ast, "export default function*() {};" 60 | assert_gen ast, "export default function*(){};", beauty: false 61 | end 62 | 63 | should "convert export default declaration with class declaration" do 64 | ast = Builder.export_default_declaration( 65 | Builder.class_declaration( 66 | Builder.identifier(:y), 67 | Builder.class_body([]) 68 | ) 69 | ) 70 | 71 | assert_gen ast, "export default class y {}" 72 | assert_gen ast, "export default class y{}", beauty: false 73 | end 74 | 75 | should "convert export default declaration with class declaration extends" do 76 | ast = Builder.export_default_declaration( 77 | Builder.class_declaration( 78 | Builder.identifier(:y), 79 | Builder.class_body([]), 80 | Builder.identifier(:z) 81 | ) 82 | ) 83 | 84 | assert_gen ast, "export default class y extends z {}" 85 | assert_gen ast, "export default class y extends z{}", beauty: false 86 | end 87 | 88 | should "convert export default declaration with class expression" do 89 | ast = Builder.export_default_declaration( 90 | Builder.class_expression( 91 | Builder.class_body([]) 92 | ) 93 | ) 94 | 95 | assert_gen ast, "export default class {};" 96 | assert_gen ast, "export default class{};", beauty: false 97 | end 98 | 99 | should "convert export default declaration with assignment expression" do 100 | ast = Builder.export_default_declaration( 101 | Builder.assignment_expression( 102 | :=, 103 | Builder.identifier(:x), 104 | Builder.literal(0) 105 | ) 106 | ) 107 | 108 | assert_gen ast, "export default x = 0;" 109 | assert_gen ast, "export default x=0;", beauty: false 110 | end 111 | 112 | should "convert export default declaration with literal" do 113 | ast = Builder.export_default_declaration( 114 | Builder.literal(0) 115 | ) 116 | 117 | assert_gen ast, "export default 0;" 118 | assert_gen ast, "export default 0;", beauty: false 119 | end 120 | 121 | should "convert export default declaration with sequence expression" do 122 | ast = Builder.export_default_declaration( 123 | Builder.sequence_expression([ 124 | Builder.literal(0), 125 | Builder.literal(1) 126 | ]) 127 | ) 128 | 129 | assert_gen ast, "export default (0, 1);" 130 | assert_gen ast, "export default (0,1);", beauty: false 131 | end 132 | end 133 | -------------------------------------------------------------------------------- /test/tools/generator/export_named_declaration_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ExportNamedDeclaration.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert export named declaration with one specifier" do 8 | ast = Builder.export_named_declaration(nil, [ 9 | Builder.export_specifier( 10 | Builder.identifier(:test), 11 | Builder.identifier(:test) 12 | )] 13 | ) 14 | 15 | assert_gen ast, "export { test };" 16 | assert_gen ast, "export{test};", beauty: false 17 | end 18 | 19 | should "convert export named declaration with one specifier with an alias" do 20 | ast = Builder.export_named_declaration(nil, [ 21 | Builder.export_specifier( 22 | Builder.identifier(:test), 23 | Builder.identifier(:test1) 24 | )] 25 | ) 26 | 27 | assert_gen ast, "export { test as test1 };" 28 | assert_gen ast, "export{test as test1};", beauty: false 29 | end 30 | 31 | should "convert export named declaration with more than one specifier" do 32 | ast = Builder.export_named_declaration(nil, 33 | [ 34 | Builder.export_specifier( 35 | Builder.identifier(:top), 36 | Builder.identifier(:top) 37 | ), 38 | Builder.export_specifier( 39 | Builder.identifier(:test), 40 | Builder.identifier(:test1) 41 | ) 42 | ], 43 | Builder.literal(:test) 44 | ) 45 | 46 | assert_gen ast, "export { top, test as test1 } from 'test';" 47 | assert_gen ast, "export{top,test as test1}from'test';", beauty: false 48 | end 49 | 50 | should "convert export named declaration with variable declaration" do 51 | ast = Builder.export_named_declaration( 52 | Builder.variable_declaration([ 53 | Builder.variable_declarator(Builder.identifier(:a)), 54 | Builder.variable_declarator(Builder.identifier(:b), Builder.literal(0)) 55 | ]) 56 | ) 57 | 58 | assert_gen ast, "export var a,\n b = 0;" 59 | assert_gen ast, "export var a,b=0;", beauty: false 60 | end 61 | 62 | should "convert export named declaration with let variable declaration" do 63 | ast = Builder.export_named_declaration( 64 | Builder.variable_declaration([ 65 | Builder.variable_declarator(Builder.identifier(:a)), 66 | Builder.variable_declarator(Builder.identifier(:b), Builder.literal(0)) 67 | ], 68 | :let) 69 | ) 70 | 71 | assert_gen ast, "export let a,\n b = 0;" 72 | assert_gen ast, "export let a,b=0;", beauty: false 73 | end 74 | 75 | should "convert export named declaration with const variable declaration" do 76 | ast = Builder.export_named_declaration( 77 | Builder.variable_declaration([ 78 | Builder.variable_declarator(Builder.identifier(:a)), 79 | Builder.variable_declarator(Builder.identifier(:b), Builder.literal(0)) 80 | ], 81 | :const) 82 | ) 83 | 84 | assert_gen ast, "export const a,\n b = 0;" 85 | assert_gen ast, "export const a,b=0;", beauty: false 86 | end 87 | 88 | should "convert export named declaration with function declaration" do 89 | ast = Builder.export_named_declaration( 90 | Builder.function_declaration( 91 | Builder.identifier(:x), 92 | [], 93 | [], 94 | Builder.block_statement([]) 95 | ) 96 | ) 97 | 98 | assert_gen ast, "export function x() {}" 99 | assert_gen ast, "export function x(){}", beauty: false 100 | end 101 | 102 | should "convert export named declaration with function declaration generator" do 103 | ast = Builder.export_named_declaration( 104 | Builder.function_declaration( 105 | Builder.identifier(:x), 106 | [], 107 | [], 108 | Builder.block_statement([]), 109 | true 110 | ) 111 | ) 112 | 113 | assert_gen ast, "export function* x() {}" 114 | assert_gen ast, "export function*x(){}", beauty: false 115 | end 116 | 117 | should "convert export named declaration with class declaration" do 118 | ast = Builder.export_named_declaration( 119 | Builder.class_declaration( 120 | Builder.identifier(:y), 121 | Builder.class_body([]) 122 | ) 123 | ) 124 | 125 | assert_gen ast, "export class y {}" 126 | assert_gen ast, "export class y{}", beauty: false 127 | end 128 | 129 | should "convert export named declaration with class declaration extends" do 130 | ast = Builder.export_named_declaration( 131 | Builder.class_declaration( 132 | Builder.identifier(:y), 133 | Builder.class_body([]), 134 | Builder.identifier(:z) 135 | ) 136 | ) 137 | 138 | assert_gen ast, "export class y extends z {}" 139 | assert_gen ast, "export class y extends z{}", beauty: false 140 | end 141 | end 142 | -------------------------------------------------------------------------------- /test/tools/generator/object_expression_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ObjectExpression.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert object when properties is nil" do 8 | ast = Builder.object_expression(nil) 9 | 10 | assert_gen ast, "{}" 11 | assert_gen ast, "{}", beauty: false 12 | end 13 | 14 | should "convert object when properties is empty" do 15 | ast = Builder.object_expression([]) 16 | 17 | assert_gen ast, "{}" 18 | assert_gen ast, "{}", beauty: false 19 | end 20 | 21 | should "convert object when properties contains one property" do 22 | ast = Builder.object_expression([ 23 | Builder.property( 24 | Builder.identifier(:key), 25 | Builder.identifier(:value) 26 | ) 27 | ]) 28 | 29 | assert_gen ast, "{\n key: value\n}" 30 | assert_gen ast, "{key:value}", beauty: false 31 | end 32 | 33 | should "convert object when properties contains one property string" do 34 | ast = Builder.object_expression([ 35 | Builder.property( 36 | Builder.literal(:key), 37 | Builder.identifier(:value) 38 | ) 39 | ]) 40 | 41 | assert_gen ast, "{\n 'key': value\n}" 42 | assert_gen ast, "{'key':value}", beauty: false 43 | end 44 | 45 | should "convert object when properties contains computed properties" do 46 | ast = Builder.object_expression([ 47 | Builder.property( 48 | Builder.identifier(:key), 49 | Builder.identifier(:value), 50 | :init, 51 | false, 52 | false, 53 | true 54 | ), 55 | Builder.property( 56 | Builder.literal(:key), 57 | Builder.identifier(:value), 58 | :init, 59 | false, 60 | false, 61 | true 62 | ) 63 | ]) 64 | 65 | assert_gen ast, "{\n [key]: value,\n ['key']: value\n}" 66 | assert_gen ast, "{[key]:value,['key']:value}", beauty: false 67 | end 68 | 69 | should "convert object when properties contains multiple properties" do 70 | ast = Builder.object_expression([ 71 | Builder.property( 72 | Builder.identifier(:key), 73 | Builder.identifier(:value) 74 | ), 75 | Builder.property( 76 | Builder.identifier(:key1), 77 | Builder.identifier(:value1) 78 | ) 79 | ]) 80 | 81 | assert_gen ast, "{\n key: value,\n key1: value1\n}" 82 | assert_gen ast, "{key:value,key1:value1}", beauty: false 83 | end 84 | 85 | 86 | should "convert object when properties contains getters and setters" do 87 | ast = Builder.object_expression([ 88 | Builder.property( 89 | Builder.identifier(:key), 90 | Builder.function_expression([],[], Builder.block_statement([])), 91 | :get 92 | ), 93 | Builder.property( 94 | Builder.identifier(:key), 95 | Builder.function_expression([Builder.identifier(:p)],[], Builder.block_statement([])), 96 | :set 97 | ), 98 | ]) 99 | 100 | assert_gen ast, "{\n get key() {},\n set key(p) {}\n}" 101 | assert_gen ast, "{get key(){},set key(p){}}", beauty: false 102 | end 103 | 104 | should "convert object when properties contains getter and setter methods" do 105 | ast = Builder.object_expression([ 106 | Builder.property( 107 | Builder.identifier(:key), 108 | Builder.function_expression([],[], Builder.block_statement([])), 109 | :get, 110 | false, 111 | true 112 | ), 113 | Builder.property( 114 | Builder.identifier(:key), 115 | Builder.function_expression([Builder.identifier(:p)],[], Builder.block_statement([])), 116 | :set, 117 | false, 118 | true 119 | ), 120 | ]) 121 | 122 | assert_gen ast, "{\n key() {},\n key(p) {}\n}" 123 | assert_gen ast, "{key(){},key(p){}}", beauty: false 124 | end 125 | 126 | should "convert object when properties are methods computed" do 127 | ast = Builder.object_expression([ 128 | Builder.property( 129 | Builder.identifier(:key), 130 | Builder.function_expression([], [], Builder.block_statement([])), 131 | :init, 132 | false, 133 | true, 134 | true 135 | ), 136 | Builder.property( 137 | Builder.literal(:key), 138 | Builder.function_expression([], [], Builder.block_statement([])), 139 | :init, 140 | false, 141 | true, 142 | true 143 | ), 144 | ]) 145 | 146 | assert_gen ast, "{\n [key]() {},\n ['key']() {}\n}" 147 | assert_gen ast, "{[key](){},['key'](){}}", beauty: false 148 | end 149 | 150 | should "convert object when properties contains shorthand properties" do 151 | ast = Builder.object_expression([ 152 | Builder.property( 153 | Builder.identifier(:key), 154 | Builder.identifier(:key), 155 | :init, 156 | true) 157 | ]) 158 | 159 | assert_gen ast, "{\n key\n}" 160 | assert_gen ast, "{key}", beauty: false 161 | end 162 | end 163 | -------------------------------------------------------------------------------- /test/tools/generator/function_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.Function.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert basic function declaration" do 8 | ast = Builder.function_declaration( 9 | Builder.identifier(:hello), 10 | [], 11 | [], 12 | Builder.block_statement([]), 13 | false, 14 | false 15 | ) 16 | 17 | assert_gen ast, "function hello() {}" 18 | assert_gen ast, "function hello(){}", beauty: false 19 | end 20 | 21 | should "convert basic function declaration generator" do 22 | ast = Builder.function_declaration( 23 | Builder.identifier(:hello), 24 | [], 25 | [], 26 | Builder.block_statement([ 27 | Builder.return_statement( 28 | Builder.yield_expression( 29 | Builder.call_expression( 30 | Builder.identifier(:x), 31 | [] 32 | ) 33 | ) 34 | ) 35 | ]), 36 | true, 37 | false 38 | ) 39 | 40 | assert_gen ast, "function* hello() {\n return yield x();\n}" 41 | assert_gen ast, "function*hello(){return yield x();}", beauty: false 42 | end 43 | 44 | should "convert basic async function declaration" do 45 | ast = Builder.function_declaration( 46 | Builder.identifier(:hello), 47 | [], 48 | [], 49 | Builder.block_statement([ 50 | Builder.return_statement( 51 | Builder.await_expression( 52 | Builder.call_expression( 53 | Builder.identifier(:x), 54 | [] 55 | ) 56 | ) 57 | ) 58 | ]), 59 | false, 60 | false, 61 | true 62 | ) 63 | 64 | assert_gen ast, "async function hello() {\n return await x();\n}" 65 | assert_gen ast, "async function hello(){return await x();}", beauty: false 66 | end 67 | 68 | should "convert function declaration with params" do 69 | ast = Builder.function_declaration( 70 | Builder.identifier(:hello), 71 | [Builder.identifier(:one)], 72 | [], 73 | Builder.block_statement([]), 74 | false, 75 | false 76 | ) 77 | 78 | assert_gen ast, "function hello(one) {}" 79 | assert_gen ast, "function hello(one){}", beauty: false 80 | 81 | ast = Builder.function_declaration( 82 | Builder.identifier(:hello), 83 | [Builder.identifier(:one), Builder.identifier(:two)], 84 | [], 85 | Builder.block_statement([]), 86 | false, 87 | false 88 | ) 89 | 90 | assert_gen ast, "function hello(one, two) {}" 91 | assert_gen ast, "function hello(one,two){}", beauty: false 92 | end 93 | 94 | should "convert function declaration with default values" do 95 | ast = Builder.function_declaration( 96 | Builder.identifier(:hello), 97 | [Builder.identifier(:one), Builder.identifier(:two)], 98 | [nil, Builder.literal(1)], 99 | Builder.block_statement([]), 100 | false, 101 | false 102 | ) 103 | 104 | assert_gen ast, "function hello(one, two = 1) {}" 105 | assert_gen ast, "function hello(one,two=1){}", beauty: false 106 | end 107 | 108 | should "convert basic function expression" do 109 | ast = Builder.function_expression( 110 | [], 111 | [], 112 | Builder.block_statement([]), 113 | false, 114 | false 115 | ) 116 | 117 | assert_gen ast, "function() {}" 118 | assert_gen ast, "function(){}", beauty: false 119 | end 120 | 121 | should "convert basic function expression generator" do 122 | ast = Builder.function_expression( 123 | [], 124 | [], 125 | Builder.block_statement([]), 126 | true, 127 | false 128 | ) 129 | 130 | assert_gen ast, "function*() {}" 131 | assert_gen ast, "function*(){}", beauty: false 132 | end 133 | 134 | should "convert basic async function expression" do 135 | ast = Builder.function_expression( 136 | [], 137 | [], 138 | Builder.block_statement([ 139 | Builder.return_statement( 140 | Builder.await_expression( 141 | Builder.call_expression( 142 | Builder.identifier(:x), 143 | [] 144 | ) 145 | ) 146 | ) 147 | ]), 148 | false, 149 | false, 150 | true 151 | ) 152 | 153 | assert_gen ast, "async function() {\n return await x();\n}" 154 | assert_gen ast, "async function(){return await x();}", beauty: false 155 | end 156 | 157 | should "convert function expression with params" do 158 | ast = Builder.function_expression( 159 | [Builder.identifier(:one)], 160 | [], 161 | Builder.block_statement([]), 162 | false, 163 | false 164 | ) 165 | 166 | assert_gen ast, "function(one) {}" 167 | assert_gen ast, "function(one){}", beauty: false 168 | 169 | ast = Builder.function_expression( 170 | [Builder.identifier(:one), Builder.identifier(:two)], 171 | [], 172 | Builder.block_statement([]), 173 | false, 174 | false 175 | ) 176 | 177 | assert_gen ast, "function(one, two) {}" 178 | assert_gen ast, "function(one,two){}", beauty: false 179 | end 180 | 181 | should "convert function expression with default values" do 182 | ast = Builder.function_expression( 183 | [Builder.identifier(:one), Builder.identifier(:two)], 184 | [nil, Builder.literal(1)], 185 | Builder.block_statement([]), 186 | false, 187 | false 188 | ) 189 | 190 | assert_gen ast, "function(one, two = 1) {}" 191 | assert_gen ast, "function(one,two=1){}", beauty: false 192 | end 193 | end 194 | -------------------------------------------------------------------------------- /test/tools/generator/class_body_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.ClassBody.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "convert class body with method definition constructor" do 8 | ast = Builder.class_body([ 9 | Builder.method_definition( 10 | nil, 11 | Builder.function_expression( 12 | [], 13 | [], 14 | Builder.block_statement([ 15 | Builder.expression_statement( 16 | Builder.call_expression( 17 | Builder.super(), 18 | [] 19 | ) 20 | ) 21 | ]) 22 | ), 23 | :constructor 24 | ) 25 | ]) 26 | 27 | assert_gen ast, "{\n constructor() {\n super();\n }\n}" 28 | assert_gen ast, "{constructor(){super();}}", beauty: false 29 | end 30 | 31 | should "convert class body with method definition" do 32 | ast = Builder.class_body([ 33 | Builder.method_definition( 34 | Builder.identifier(:method), 35 | Builder.function_expression( 36 | [], 37 | [], 38 | Builder.block_statement([]) 39 | ) 40 | ) 41 | ]) 42 | 43 | assert_gen ast, "{\n method() {}\n}" 44 | assert_gen ast, "{method(){}}", beauty: false 45 | end 46 | 47 | should "convert class body with method definition getter" do 48 | ast = Builder.class_body([ 49 | Builder.method_definition( 50 | Builder.identifier(:property), 51 | Builder.function_expression( 52 | [], 53 | [], 54 | Builder.block_statement([]) 55 | ), 56 | :get 57 | ) 58 | ]) 59 | 60 | assert_gen ast, "{\n get property() {}\n}" 61 | assert_gen ast, "{get property(){}}", beauty: false 62 | end 63 | 64 | should "convert class body with method definition setter" do 65 | ast = Builder.class_body([ 66 | Builder.method_definition( 67 | Builder.identifier(:property), 68 | Builder.function_expression( 69 | [Builder.identifier(:value)], 70 | [], 71 | Builder.block_statement([]) 72 | ), 73 | :set 74 | ) 75 | ]) 76 | 77 | assert_gen ast, "{\n set property(value) {}\n}" 78 | assert_gen ast, "{set property(value){}}", beauty: false 79 | end 80 | 81 | should "convert class body with method definition computed" do 82 | ast = Builder.class_body([ 83 | Builder.method_definition( 84 | Builder.member_expression(Builder.identifier(:Symbol), Builder.identifier(:iterator)), 85 | Builder.function_expression( 86 | [], 87 | [], 88 | Builder.block_statement([]) 89 | ), 90 | :method, 91 | true 92 | ) 93 | ]) 94 | 95 | assert_gen ast, "{\n [Symbol.iterator]() {}\n}" 96 | assert_gen ast, "{[Symbol.iterator](){}}", beauty: false 97 | end 98 | 99 | should "convert class body with method definition computed literal" do 100 | ast = Builder.class_body([ 101 | Builder.method_definition( 102 | Builder.literal(:method), 103 | Builder.function_expression( 104 | [], 105 | [], 106 | Builder.block_statement([]) 107 | ), 108 | :method, 109 | true 110 | ) 111 | ]) 112 | 113 | assert_gen ast, "{\n ['method']() {}\n}" 114 | assert_gen ast, "{['method'](){}}", beauty: false 115 | end 116 | 117 | should "convert class body with method definition static" do 118 | ast = Builder.class_body([ 119 | Builder.method_definition( 120 | Builder.identifier("classMethod"), 121 | Builder.function_expression( 122 | [], 123 | [], 124 | Builder.block_statement([]) 125 | ), 126 | :method, 127 | false, 128 | true 129 | ) 130 | ]) 131 | 132 | assert_gen ast, "{\n static classMethod() {}\n}" 133 | assert_gen ast, "{static classMethod(){}}", beauty: false 134 | end 135 | 136 | should "convert class body with method definition static getter" do 137 | ast = Builder.class_body([ 138 | Builder.method_definition( 139 | Builder.identifier(:property), 140 | Builder.function_expression( 141 | [], 142 | [], 143 | Builder.block_statement([]) 144 | ), 145 | :get, 146 | false, 147 | true 148 | ) 149 | ]) 150 | 151 | assert_gen ast, "{\n static get property() {}\n}" 152 | assert_gen ast, "{static get property(){}}", beauty: false 153 | end 154 | 155 | should "convert class body with method definition static setter" do 156 | ast = Builder.class_body([ 157 | Builder.method_definition( 158 | Builder.identifier(:property), 159 | Builder.function_expression( 160 | [Builder.identifier(:value)], 161 | [], 162 | Builder.block_statement([]) 163 | ), 164 | :set, 165 | false, 166 | true 167 | ) 168 | ]) 169 | 170 | assert_gen ast, "{\n static set property(value) {}\n}" 171 | assert_gen ast, "{static set property(value){}}", beauty: false 172 | end 173 | 174 | should "convert class body with method definition static computed" do 175 | ast = Builder.class_body([ 176 | Builder.method_definition( 177 | Builder.member_expression(Builder.identifier(:Symbol), Builder.identifier(:iterator)), 178 | Builder.function_expression( 179 | [], 180 | [], 181 | Builder.block_statement([]) 182 | ), 183 | :method, 184 | true, 185 | true 186 | ) 187 | ]) 188 | 189 | assert_gen ast, "{\n static [Symbol.iterator]() {}\n}" 190 | assert_gen ast, "{static [Symbol.iterator](){}}", beauty: false 191 | end 192 | 193 | should "convert class body with method definition static computed literal" do 194 | ast = Builder.class_body([ 195 | Builder.method_definition( 196 | Builder.literal(:method), 197 | Builder.function_expression( 198 | [], 199 | [], 200 | Builder.block_statement([]) 201 | ), 202 | :method, 203 | true, 204 | true 205 | ) 206 | ]) 207 | 208 | assert_gen ast, "{\n static ['method']() {}\n}" 209 | assert_gen ast, "{static ['method'](){}}", beauty: false 210 | end 211 | end 212 | -------------------------------------------------------------------------------- /test/tools/generator/jsx_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.JSX.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "handle atom and binary as identifier name" do 8 | assert_gen Builder.jsx_identifier("Test"), "Test" 9 | assert_gen Builder.jsx_identifier(:Test), "Test" 10 | end 11 | 12 | should "handle no closing tag" do 13 | ast = Builder.jsx_element( 14 | Builder.jsx_opening_element( 15 | Builder.jsx_identifier( 16 | "Test" 17 | ), 18 | [], 19 | true 20 | ) 21 | ) 22 | 23 | assert_gen ast, "" 24 | assert_gen ast, "", beauty: false 25 | end 26 | 27 | should "handle closing tag" do 28 | ast = Builder.jsx_element( 29 | Builder.jsx_opening_element( 30 | Builder.jsx_identifier( 31 | "Test" 32 | ) 33 | ), 34 | [], 35 | Builder.jsx_closing_element( 36 | Builder.jsx_identifier( 37 | "Test" 38 | ) 39 | ) 40 | ) 41 | 42 | assert_gen ast, "" 43 | assert_gen ast, "", beauty: false 44 | end 45 | 46 | 47 | should "handle element with attributes" do 48 | ast = Builder.jsx_element( 49 | Builder.jsx_opening_element( 50 | Builder.jsx_identifier("Test"), 51 | [ 52 | Builder.jsx_attribute( 53 | Builder.jsx_identifier("className"), 54 | Builder.literal("test") 55 | ), 56 | Builder.jsx_attribute( 57 | Builder.jsx_identifier("name"), 58 | Builder.jsx_expression_container( 59 | Builder.array_expression([ 60 | Builder.literal(1) 61 | ]) 62 | ) 63 | ), 64 | Builder.jsx_spread_attribute( 65 | Builder.array_expression([ 66 | Builder.literal(1) 67 | ]) 68 | ) 69 | ] 70 | ), 71 | [], 72 | Builder.jsx_closing_element( 73 | Builder.jsx_identifier( 74 | "Test" 75 | ) 76 | ) 77 | ) 78 | 79 | assert_gen ast, "" 80 | assert_gen ast, "", beauty: false 81 | end 82 | 83 | should "handle escaped attributes value" do 84 | ast = fn x -> 85 | Builder.jsx_element( 86 | Builder.jsx_opening_element( 87 | Builder.jsx_identifier("Test"), 88 | [ 89 | Builder.jsx_attribute( 90 | Builder.jsx_identifier("className"), 91 | x 92 | ) 93 | ] 94 | ), 95 | [], 96 | Builder.jsx_closing_element( 97 | Builder.jsx_identifier( 98 | "Test" 99 | ) 100 | ) 101 | ) 102 | end 103 | 104 | assert_gen ast.(Builder.literal("\\")), "" 105 | assert_gen ast.(Builder.literal("\n")), "" 106 | assert_gen ast.(Builder.literal("\r")), "" 107 | assert_gen ast.(Builder.literal("\t")), "" 108 | assert_gen ast.(Builder.literal("\b")), "" 109 | assert_gen ast.(Builder.literal("\f")), "" 110 | assert_gen ast.(Builder.literal("\v")), "" 111 | assert_gen ast.(Builder.literal("\u2028")), "" 112 | assert_gen ast.(Builder.literal("\u2029")), "" 113 | assert_gen ast.(Builder.literal("\ufeff")), "" 114 | assert_gen ast.(Builder.literal("'")), "" 115 | end 116 | 117 | should "handle element with elements inside" do 118 | ast = Builder.jsx_element( 119 | Builder.jsx_opening_element( 120 | Builder.jsx_identifier("Test") 121 | ), 122 | [ 123 | Builder.jsx_element( 124 | Builder.jsx_opening_element( 125 | Builder.jsx_identifier("div"), [], true 126 | ) 127 | ) 128 | ], 129 | Builder.jsx_closing_element( 130 | Builder.jsx_identifier( 131 | "Test" 132 | ) 133 | ) 134 | ) 135 | 136 | assert_gen ast, "
" 137 | assert_gen ast, "
", beauty: false 138 | end 139 | 140 | should "handle namespaced names" do 141 | ast = Builder.jsx_element( 142 | Builder.jsx_opening_element( 143 | Builder.jsx_namespaced_name( 144 | Builder.jsx_identifier("Test"), 145 | Builder.jsx_identifier("xml") 146 | ) 147 | ), 148 | [ 149 | Builder.jsx_element( 150 | Builder.jsx_opening_element( 151 | Builder.jsx_identifier("div"), [], true 152 | ) 153 | ) 154 | ], 155 | Builder.jsx_closing_element( 156 | Builder.jsx_namespaced_name( 157 | Builder.jsx_identifier("Test"), 158 | Builder.jsx_identifier("xml") 159 | ) 160 | ) 161 | ) 162 | 163 | assert_gen ast, "
" 164 | assert_gen ast, "
", beauty: false 165 | end 166 | 167 | should "handle member names" do 168 | ast = Builder.jsx_element( 169 | Builder.jsx_opening_element( 170 | Builder.jsx_member_expression( 171 | Builder.jsx_identifier("Test"), 172 | Builder.jsx_identifier("xml") 173 | ) 174 | ), 175 | [ 176 | Builder.jsx_element( 177 | Builder.jsx_opening_element( 178 | Builder.jsx_identifier("div"), [], true 179 | ) 180 | ) 181 | ], 182 | Builder.jsx_closing_element( 183 | Builder.jsx_member_expression( 184 | Builder.jsx_identifier("Test"), 185 | Builder.jsx_identifier("xml") 186 | ) 187 | ) 188 | ) 189 | 190 | assert_gen ast, "
" 191 | assert_gen ast, "
", beauty: false 192 | end 193 | 194 | should "handle inner text" do 195 | ast = Builder.jsx_element( 196 | Builder.jsx_opening_element( 197 | Builder.jsx_identifier( 198 | "Test" 199 | ) 200 | ), 201 | [ 202 | Builder.literal("counter: "), 203 | Builder.jsx_expression_container( 204 | Builder.identifier(:count) 205 | ), 206 | Builder.literal("."), 207 | ], 208 | Builder.jsx_closing_element( 209 | Builder.jsx_identifier( 210 | "Test" 211 | ) 212 | ) 213 | ) 214 | 215 | assert_gen ast, "counter: {count}." 216 | assert_gen ast, "counter: {count}.", beauty: false 217 | end 218 | 219 | should "handle inner text escape" do 220 | ast = fn x -> 221 | Builder.jsx_element( 222 | Builder.jsx_opening_element( 223 | Builder.jsx_identifier( 224 | "Test" 225 | ) 226 | ), 227 | [x], 228 | Builder.jsx_closing_element( 229 | Builder.jsx_identifier( 230 | "Test" 231 | ) 232 | ) 233 | ) 234 | end 235 | 236 | assert_gen ast.(Builder.literal("{")), "{" 237 | assert_gen ast.(Builder.literal("}")), "}" 238 | assert_gen ast.(Builder.literal("<")), "<" 239 | assert_gen ast.(Builder.literal(">")), ">" 240 | end 241 | end 242 | -------------------------------------------------------------------------------- /test/tools/generator/formatting_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Generator.Formatting.Test do 2 | use ShouldI 3 | 4 | alias ESTree.Tools.Builder 5 | import ESTree.Test.Support 6 | 7 | should "format objects" do 8 | ast = Builder.program([ 9 | Builder.function_declaration( 10 | Builder.identifier(:test), 11 | [], 12 | [], 13 | Builder.block_statement([ 14 | Builder.variable_declaration([ 15 | Builder.variable_declarator(Builder.identifier(:a)), 16 | Builder.variable_declarator(Builder.identifier(:b)), 17 | Builder.variable_declarator( 18 | Builder.identifier(:c), 19 | Builder.function_expression( 20 | [], 21 | [], 22 | Builder.block_statement([ 23 | Builder.return_statement(Builder.literal(1)) 24 | ]) 25 | ) 26 | ) 27 | ]), 28 | Builder.if_statement( 29 | Builder.literal(true), 30 | Builder.block_statement([ 31 | Builder.expression_statement( 32 | Builder.assignment_expression( 33 | :=, 34 | Builder.identifier(:a), 35 | Builder.literal(-1) 36 | ) 37 | ) 38 | ]), 39 | Builder.if_statement( 40 | Builder.literal(false), 41 | Builder.block_statement([ 42 | Builder.expression_statement( 43 | Builder.assignment_expression( 44 | :=, 45 | Builder.identifier(:a), 46 | Builder.literal(-2) 47 | ) 48 | ) 49 | ]), 50 | Builder.block_statement([ 51 | Builder.expression_statement( 52 | Builder.assignment_expression( 53 | :=, 54 | Builder.identifier(:a), 55 | Builder.literal(-3) 56 | ) 57 | ) 58 | ]) 59 | ) 60 | ), 61 | Builder.if_statement( 62 | Builder.literal(false), 63 | Builder.return_statement( 64 | Builder.literal(-1) 65 | ), 66 | Builder.if_statement( 67 | Builder.literal(false), 68 | Builder.return_statement( 69 | Builder.literal(-2) 70 | ), 71 | Builder.return_statement( 72 | Builder.literal(-3) 73 | ) 74 | ) 75 | ), 76 | Builder.switch_statement( 77 | Builder.literal(false), 78 | [ 79 | Builder.switch_case( 80 | nil, 81 | [ 82 | Builder.expression_statement( 83 | Builder.assignment_expression( 84 | :=, 85 | Builder.identifier(:b), 86 | Builder.literal(0) 87 | ) 88 | ), 89 | Builder.break_statement() 90 | ] 91 | ) 92 | ] 93 | ), 94 | Builder.return_statement( 95 | Builder.object_expression([ 96 | Builder.property( 97 | Builder.identifier(:a), 98 | Builder.binary_expression( 99 | :+, 100 | Builder.identifier(:a), 101 | Builder.literal(1) 102 | ) 103 | ), 104 | Builder.property( 105 | Builder.identifier(:b), 106 | Builder.binary_expression( 107 | :+, 108 | Builder.identifier(:b), 109 | Builder.literal(2) 110 | ) 111 | ), 112 | Builder.property( 113 | Builder.identifier(:c), 114 | Builder.binary_expression( 115 | :+, 116 | Builder.identifier(:c), 117 | Builder.literal(3) 118 | ) 119 | ) 120 | ]) 121 | ) 122 | ]) 123 | ), 124 | Builder.expression_statement( 125 | Builder.call_expression( 126 | Builder.identifier(:test), 127 | [] 128 | ) 129 | ) 130 | ]) 131 | 132 | str = """ 133 | function test() { 134 | var a, 135 | b, 136 | c = function() { 137 | return 1; 138 | }; 139 | 140 | if (true) { 141 | a = -1; 142 | } else if (false) { 143 | a = -2; 144 | } else { 145 | a = -3; 146 | } 147 | 148 | if (false) 149 | return -1; 150 | else if (false) 151 | return -2; 152 | else 153 | return -3; 154 | 155 | switch (false) { 156 | default: 157 | b = 0; 158 | break; 159 | } 160 | 161 | return { 162 | a: a + 1, 163 | b: b + 2, 164 | c: c + 3 165 | }; 166 | } 167 | 168 | test(); 169 | """ 170 | 171 | assert_gen ast, String.trim(str) 172 | 173 | 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();" 174 | 175 | assert_gen ast, str, beauty: false 176 | end 177 | 178 | should "format if statements correct" do 179 | ast = Builder.program([ 180 | Builder.function_declaration( 181 | Builder.identifier(:test), 182 | [], 183 | [], 184 | Builder.block_statement([ 185 | Builder.if_statement( 186 | Builder.literal(true), 187 | Builder.block_statement([ 188 | Builder.return_statement(Builder.literal(1)) 189 | ]) 190 | ), 191 | Builder.if_statement( 192 | Builder.literal(true), 193 | Builder.return_statement(Builder.literal(1)) 194 | ), 195 | Builder.if_statement( 196 | Builder.literal(true), 197 | Builder.block_statement([ 198 | Builder.return_statement(Builder.literal(1)) 199 | ]), 200 | Builder.return_statement(Builder.literal(2)) 201 | ), 202 | Builder.if_statement( 203 | Builder.literal(true), 204 | Builder.return_statement(Builder.literal(1)), 205 | Builder.block_statement([ 206 | Builder.return_statement(Builder.literal(2)) 207 | ]) 208 | ), 209 | Builder.if_statement( 210 | Builder.literal(true), 211 | Builder.block_statement([ 212 | Builder.return_statement(Builder.literal(1)) 213 | ]), 214 | Builder.if_statement( 215 | Builder.literal(false), 216 | Builder.return_statement(Builder.literal(2)) 217 | ) 218 | ), 219 | Builder.if_statement( 220 | Builder.literal(true), 221 | Builder.return_statement(Builder.literal(1)), 222 | Builder.if_statement( 223 | Builder.literal(false), 224 | Builder.block_statement([ 225 | Builder.return_statement(Builder.literal(2)) 226 | ]) 227 | ) 228 | ) 229 | ]) 230 | ) 231 | ]) 232 | 233 | str = """ 234 | function test() { 235 | if (true) { 236 | return 1; 237 | } 238 | 239 | if (true) 240 | return 1; 241 | 242 | if (true) { 243 | return 1; 244 | } else 245 | return 2; 246 | 247 | if (true) 248 | return 1; 249 | else { 250 | return 2; 251 | } 252 | 253 | if (true) { 254 | return 1; 255 | } else if (false) 256 | return 2; 257 | 258 | if (true) 259 | return 1; 260 | else if (false) { 261 | return 2; 262 | } 263 | } 264 | """ 265 | 266 | assert_gen ast, String.trim(str) 267 | 268 | 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;}}" 269 | 270 | assert_gen ast, str, beauty: false 271 | end 272 | end 273 | -------------------------------------------------------------------------------- /lib/es_tree/tools/estree_json_transformer.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.ESTreeJSONTransformer do 2 | @moduledoc """ 3 | Converts ESTree JSON into the structs in the ESTree library 4 | """ 5 | 6 | 7 | @spec convert(%{}) :: ESTree.Node.t 8 | def convert(json) 9 | 10 | def convert(%{"type" => "ArrayExpression"} = json) do 11 | %ESTree.ArrayExpression{ 12 | elements: convert_property(json, "elements", []) 13 | } 14 | end 15 | 16 | def convert(%{"type" => "ArrayPattern"} = json) do 17 | %ESTree.ArrayPattern{ 18 | elements: convert_property(json, "elements", []) 19 | } 20 | end 21 | 22 | def convert(%{"type" => "ArrowFunctionExpression"} = json) do 23 | %ESTree.ArrowFunctionExpression{ 24 | generator: convert_property(json, "generator", false), 25 | expression: convert_property(json, "expression", false), 26 | params: convert_property(json, "params", []), 27 | body: convert_property(json, "body", []) 28 | } 29 | end 30 | 31 | def convert(%{"type" => "AssignmentExpression"} = json) do 32 | %ESTree.AssignmentExpression{ 33 | operator: convert_property_to_atom(json, "operator", "="), 34 | left: convert_property(json, "left"), 35 | right: convert_property(json, "right") 36 | } 37 | end 38 | 39 | def convert(%{"type" => "AssignmentPattern"} = json) do 40 | %ESTree.AssignmentPattern{ 41 | left: convert_property(json, "left"), 42 | right: convert_property(json, "right") 43 | } 44 | end 45 | 46 | def convert(%{"type" => "AwaitExpression"} = json) do 47 | %ESTree.AwaitExpression{ 48 | argument: convert_property(json, "argument") 49 | } 50 | end 51 | 52 | def convert(%{"type" => "BinaryExpression"} = json) do 53 | %ESTree.BinaryExpression{ 54 | operator: convert_property_to_atom(json, "operator", "="), 55 | left: convert_property(json, "left"), 56 | right: convert_property(json, "right") 57 | } 58 | end 59 | 60 | def convert(%{"type" => "BlockStatement"} = json) do 61 | %ESTree.BlockStatement{ 62 | body: convert_property(json, "body", []) 63 | } 64 | end 65 | 66 | def convert(%{"type" => "BreakStatement"} = json) do 67 | %ESTree.BreakStatement{ 68 | label: convert_property(json, "label") 69 | } 70 | end 71 | 72 | def convert(%{"type" => "CallExpression"} = json) do 73 | %ESTree.CallExpression{ 74 | callee: convert_property(json, "callee", false), 75 | arguments: convert_property(json, "arguments", []) 76 | } 77 | end 78 | 79 | def convert(%{"type" => "CatchClause"} = json) do 80 | %ESTree.CatchClause{ 81 | param: convert_property(json, "param"), 82 | body: convert_property(json, "body") 83 | } 84 | end 85 | 86 | def convert(%{"type" => "ClassBody"} = json) do 87 | %ESTree.ClassBody{ 88 | body: convert_property(json, "body", []) 89 | } 90 | end 91 | 92 | def convert(%{"type" => "ClassDeclaration"} = json) do 93 | %ESTree.ClassDeclaration{ 94 | id: convert_property(json, "id"), 95 | body: convert_property(json, "body"), 96 | superClass: convert_property(json, "superClass") 97 | } 98 | end 99 | 100 | def convert(%{"type" => "ClassExpression"} = json) do 101 | %ESTree.ClassExpression{ 102 | body: convert_property(json, "body"), 103 | superClass: convert_property(json, "superClass") 104 | } 105 | end 106 | 107 | def convert(%{"type" => "ConditionalStatement"} = json) do 108 | %ESTree.ConditionalStatement{ 109 | test: convert_property(json, "test"), 110 | alternate: convert_property(json, "alternate"), 111 | consequent: convert_property(json, "consequent") 112 | } 113 | end 114 | 115 | def convert(%{"type" => "ContinueStatement"} = json) do 116 | %ESTree.ContinueStatement{ 117 | label: convert_property(json, "label") 118 | } 119 | end 120 | 121 | def convert(%{"type" => "DebuggerStatement"}) do 122 | %ESTree.DebuggerStatement{} 123 | end 124 | 125 | def convert(%{"type" => "DoWhileStatement"} = json) do 126 | %ESTree.DoWhileStatement{ 127 | test: convert_property(json, "test"), 128 | body: convert_property(json, "body") 129 | } 130 | end 131 | 132 | def convert(%{"type" => "EmptyExpression"}) do 133 | %ESTree.EmptyExpression{} 134 | end 135 | 136 | def convert(%{"type" => "EmptyStatement"}) do 137 | %ESTree.EmptyStatement{} 138 | end 139 | 140 | def convert(%{"type" => "ExportAllDeclaration"} = json) do 141 | %ESTree.ExportAllDeclaration{ 142 | source: convert_property(json, "source") 143 | } 144 | end 145 | 146 | def convert(%{"type" => "ExportDefaultDeclaration"} = json) do 147 | %ESTree.ExportDefaultDeclaration{ 148 | declaration: convert_property(json, "declaration") 149 | } 150 | end 151 | 152 | def convert(%{"type" => "ExportNamedDeclaration"} = json) do 153 | %ESTree.ExportNamedDeclaration{ 154 | declaration: convert_property(json, "declaration"), 155 | specifiers: convert_property(json, "specifiers", []), 156 | source: convert_property(json, "source") 157 | } 158 | end 159 | 160 | def convert(%{"type" => "ExportSpecifier"} = json) do 161 | %ESTree.ExportSpecifier{ 162 | local: convert_property(json, "local"), 163 | exported: convert_property(json, "exported") 164 | } 165 | end 166 | 167 | def convert(%{"type" => "ExpressionStatement"} = json) do 168 | %ESTree.ExpressionStatement{ 169 | expression: convert_property(json, "expression") 170 | } 171 | end 172 | 173 | def convert(%{"type" => "ForInStatement"} = json) do 174 | %ESTree.ForInStatement{ 175 | left: convert_property(json, "left"), 176 | right: convert_property(json, "right"), 177 | body: convert_property(json, "body") 178 | } 179 | end 180 | 181 | def convert(%{"type" => "ForOfStatement"} = json) do 182 | %ESTree.ForOfStatement{ 183 | left: convert_property(json, "left"), 184 | right: convert_property(json, "right"), 185 | body: convert_property(json, "body") 186 | } 187 | end 188 | 189 | def convert(%{"type" => "ForStatement"} = json) do 190 | %ESTree.ForStatement{ 191 | init: convert_property(json, "init"), 192 | test: convert_property(json, "test"), 193 | update: convert_property(json, "update"), 194 | body: convert_property(json, "body") 195 | } 196 | end 197 | 198 | def convert(%{"type" => "FunctionDeclaration"} = json) do 199 | %ESTree.FunctionDeclaration{ 200 | id: convert_property(json, "id"), 201 | params: convert_property(json, "params", []), 202 | defaults: convert_property(json, "defaults", []), 203 | body: convert_property(json, "body"), 204 | generator: convert_property(json, "generator", false), 205 | expression: convert_property(json, "expression", false), 206 | async: convert_property(json, "async", false) 207 | } 208 | end 209 | 210 | def convert(%{"type" => "FunctionExpression"} = json) do 211 | %ESTree.FunctionExpression{ 212 | params: convert_property(json, "params", []), 213 | defaults: convert_property(json, "defaults", []), 214 | body: convert_property(json, "body"), 215 | generator: convert_property(json, "generator", false), 216 | expression: convert_property(json, "expression", false), 217 | async: convert_property(json, "async", false) 218 | } 219 | end 220 | 221 | def convert(%{"type" => "Identifier"} = json) do 222 | %ESTree.Identifier{ 223 | name: convert_property(json, "name") 224 | } 225 | end 226 | 227 | def convert(%{"type" => "IfStatement"} = json) do 228 | %ESTree.IfStatement{ 229 | test: convert_property(json, "test"), 230 | consequent: convert_property(json, "consequent"), 231 | alternate: convert_property(json, "alternate") 232 | } 233 | end 234 | 235 | def convert(%{"type" => "ImportDeclaration"} = json) do 236 | %ESTree.ImportDeclaration{ 237 | specifiers: convert_property(json, "specifiers", []), 238 | source: convert_property(json, "source") 239 | } 240 | end 241 | 242 | def convert(%{"type" => "ImportDefaultSpecifier"} = json) do 243 | %ESTree.ImportDefaultSpecifier{ 244 | local: convert_property(json, "local") 245 | } 246 | end 247 | 248 | def convert(%{"type" => "ImportNamespaceSpecifier"} = json) do 249 | %ESTree.ImportNamespaceSpecifier{ 250 | local: convert_property(json, "local") 251 | } 252 | end 253 | 254 | def convert(%{"type" => "ImportSpecifier"} = json) do 255 | %ESTree.ImportSpecifier{ 256 | local: convert_property(json, "local"), 257 | imported: convert_property(json, "imported") 258 | } 259 | end 260 | 261 | def convert(%{"type" => "JSXAttribute"} = json) do 262 | %ESTree.JSXAttribute{ 263 | name: convert_property(json, "name"), 264 | value: convert_property(json, "value") 265 | } 266 | end 267 | 268 | def convert(%{"type" => "JSXClosingElement"} = json) do 269 | %ESTree.JSXClosingElement{ 270 | name: convert_property(json, "name") 271 | } 272 | end 273 | 274 | def convert(%{"type" => "JSXElement"} = json) do 275 | %ESTree.JSXElement{ 276 | openingElement: convert_property(json, "openingElement"), 277 | children: convert_property(json, "children", []), 278 | closingElement: convert_property(json, "closingElement") 279 | } 280 | end 281 | 282 | def convert(%{"type" => "JSXEmptyExpression"}) do 283 | %ESTree.JSXEmptyExpression{} 284 | end 285 | 286 | def convert(%{"type" => "JSXExpressionContainer"} = json) do 287 | %ESTree.JSXExpressionContainer{ 288 | expression: convert_property(json, "expression") 289 | } 290 | end 291 | 292 | def convert(%{"type" => "JSXIdentifier"} = json) do 293 | %ESTree.JSXIdentifier{ 294 | name: convert_property(json, "name") 295 | } 296 | end 297 | 298 | def convert(%{"type" => "JSXMemberExpression"} = json) do 299 | %ESTree.JSXMemberExpression{ 300 | object: convert_property(json, "object"), 301 | property: convert_property(json, "property") 302 | } 303 | end 304 | 305 | def convert(%{"type" => "JSXNamespacedName"} = json) do 306 | %ESTree.JSXNamespacedName{ 307 | namespace: convert_property(json, "namespace"), 308 | name: convert_property(json, "name") 309 | } 310 | end 311 | 312 | def convert(%{"type" => "JSXOpeningElement"} = json) do 313 | %ESTree.JSXOpeningElement{ 314 | name: convert_property(json, "name"), 315 | attributes: convert_property(json, "attributes", []), 316 | selfClosing: convert_property(json, "selfClosing", false) 317 | } 318 | end 319 | 320 | def convert(%{"type" => "JSXSpreadAttribute"} = json) do 321 | %ESTree.JSXSpreadAttribute{ 322 | argument: convert_property(json, "argument") 323 | } 324 | end 325 | 326 | def convert(%{"type" => "LabeledStatement"} = json) do 327 | %ESTree.LabeledStatement{ 328 | label: convert_property(json, "label"), 329 | body: convert_property(json, "body") 330 | } 331 | end 332 | 333 | def convert(%{"type" => "Literal"} = json) do 334 | %ESTree.Literal{ 335 | value: convert_property(json, "value") 336 | } 337 | end 338 | 339 | def convert(%{"type" => "LogicalExpression"} = json) do 340 | %ESTree.LogicalExpression{ 341 | operator: convert_property_to_atom(json, "operator", ""), 342 | left: convert_property(json, "left"), 343 | right: convert_property(json, "right") 344 | } 345 | end 346 | 347 | def convert(%{"type" => "MemberExpression"} = json) do 348 | %ESTree.MemberExpression{ 349 | object: convert_property(json, "object"), 350 | property: convert_property(json, "property"), 351 | computed: convert_property(json, "computed", false) 352 | } 353 | end 354 | 355 | def convert(%{"type" => "MetaProperty"} = json) do 356 | %ESTree.MetaProperty{ 357 | meta: convert_property(json, "meta"), 358 | property: convert_property(json, "property") 359 | } 360 | end 361 | 362 | def convert(%{"type" => "MethodDefinition"} = json) do 363 | %ESTree.MethodDefinition{ 364 | key: convert_property(json, "key"), 365 | value: convert_property(json, "value"), 366 | kind: convert_property_to_atom(json, "kind", ""), 367 | computed: convert_property(json, "computed", false), 368 | static: convert_property(json, "static", false) 369 | } 370 | end 371 | 372 | def convert(%{"type" => "NewExpression"} = json) do 373 | %ESTree.NewExpression{ 374 | callee: convert_property(json, "callee", false), 375 | arguments: convert_property(json, "arguments", []) 376 | } 377 | end 378 | 379 | def convert(%{"type" => "ObjectExpression"} = json) do 380 | %ESTree.ObjectExpression{ 381 | properties: convert_property(json, "properties", []) 382 | } 383 | end 384 | 385 | def convert(%{"type" => "ObjectPattern"} = json) do 386 | %ESTree.ObjectPattern{ 387 | properties: convert_property(json, "properties", []) 388 | } 389 | end 390 | 391 | def convert(%{"type" => "Program"} = json) do 392 | %ESTree.Program{ 393 | body: convert_property(json, "body", []), 394 | sourceType: convert_property(json, "sourceType", "module") 395 | } 396 | end 397 | 398 | def convert(%{"type" => "Property"} = json) do 399 | %ESTree.Property{ 400 | key: convert_property(json, "key"), 401 | value: convert_property(json, "value"), 402 | kind: convert_property_to_atom(json, "kind", ""), 403 | method: convert_property(json, "method", false), 404 | shorthand: convert_property(json, "shorthand", false), 405 | computed: convert_property(json, "computed", false) 406 | } 407 | end 408 | 409 | def convert(%{"type" => "RestElement"} = json) do 410 | %ESTree.RestElement{ 411 | argument: convert_property(json, "argument") 412 | } 413 | end 414 | 415 | def convert(%{"type" => "ReturnStatement"} = json) do 416 | %ESTree.ReturnStatement{ 417 | argument: convert_property(json, "argument") 418 | } 419 | end 420 | 421 | def convert(%{"type" => "SequenceExpression"} = json) do 422 | %ESTree.SequenceExpression{ 423 | expressions: convert_property(json, "expressions", []) 424 | } 425 | end 426 | 427 | def convert(%{"type" => "SpreadElement"} = json) do 428 | %ESTree.SpreadElement{ 429 | argument: convert_property(json, "argument") 430 | } 431 | end 432 | 433 | def convert(%{"type" => "Super"}) do 434 | %ESTree.Super{} 435 | end 436 | 437 | def convert(%{"type" => "SwitchCase"} = json) do 438 | %ESTree.SwitchCase{ 439 | test: convert_property(json, "test"), 440 | consequent: convert_property(json, "consequent") 441 | } 442 | end 443 | 444 | def convert(%{"type" => "SwitchStatement"} = json) do 445 | %ESTree.SwitchStatement{ 446 | discriminant: convert_property(json, "discriminant"), 447 | cases: convert_property(json, "cases", []) 448 | } 449 | end 450 | 451 | def convert(%{"type" => "TaggedTemplateExpression"} = json) do 452 | %ESTree.TaggedTemplateExpression{ 453 | tag: convert_property(json, "tag"), 454 | quasi: convert_property(json, "quasi") 455 | } 456 | end 457 | 458 | def convert(%{"type" => "TemplateElement"} = json) do 459 | value = case Map.get(json, "value") do 460 | map when is_map(map) -> 461 | %{ 462 | cooked: convert_property(map, "cooked"), 463 | raw: convert_property(map, "raw") 464 | } 465 | other -> 466 | other 467 | end 468 | 469 | %ESTree.TemplateElement{ 470 | value: value, 471 | tail: convert_property(json, "tail", false) 472 | } 473 | end 474 | 475 | def convert(%{"type" => "TemplateLiteral"} = json) do 476 | %ESTree.TemplateLiteral{ 477 | quasis: convert_property(json, "quasis", []), 478 | expressions: convert_property(json, "expressions", []) 479 | } 480 | end 481 | 482 | def convert(%{"type" => "ThisExpression"}) do 483 | %ESTree.ThisExpression{} 484 | end 485 | 486 | def convert(%{"type" => "ThrowStatement"} = json) do 487 | %ESTree.ThrowStatement{ 488 | argument: convert_property(json, "argument") 489 | } 490 | end 491 | 492 | def convert(%{"type" => "TryStatement"} = json) do 493 | %ESTree.TryStatement{ 494 | block: convert_property(json, "block"), 495 | handler: convert_property(json, "handler"), 496 | finalizer: convert_property(json, "finalizer") 497 | } 498 | end 499 | 500 | def convert(%{"type" => "UnaryExpression"} = json) do 501 | %ESTree.UnaryExpression{ 502 | operator: convert_property_to_atom(json, "operator", ""), 503 | prefix: convert_property(json, "prefix", false), 504 | argument: convert_property(json, "argument") 505 | } 506 | end 507 | 508 | def convert(%{"type" => "UpdateExpression"} = json) do 509 | %ESTree.UpdateExpression{ 510 | operator: convert_property_to_atom(json, "operator", ""), 511 | prefix: convert_property(json, "prefix", false), 512 | argument: convert_property(json, "argument") 513 | } 514 | end 515 | 516 | def convert(%{"type" => "VariableDeclaration"} = json) do 517 | %ESTree.VariableDeclaration{ 518 | kind: convert_property_to_atom(json, "kind", "var"), 519 | declarations: convert_property(json, "declarations", []) 520 | } 521 | end 522 | 523 | def convert(%{"type" => "VariableDeclarator"} = json) do 524 | %ESTree.VariableDeclarator{ 525 | id: convert_property(json, "id"), 526 | init: convert_property(json, "init") 527 | } 528 | end 529 | 530 | def convert(%{"type" => "WhileStatement"} = json) do 531 | %ESTree.WhileStatement{ 532 | test: convert_property(json, "test"), 533 | body: convert_property(json, "body") 534 | } 535 | end 536 | 537 | def convert(%{"type" => "WithStatement"} = json) do 538 | %ESTree.WithStatement{ 539 | object: convert_property(json, "object"), 540 | body: convert_property(json, "body") 541 | } 542 | end 543 | 544 | def convert(%{"type" => "YieldExpression"} = json) do 545 | %ESTree.YieldExpression{ 546 | argument: convert_property(json, "argument"), 547 | delegate: convert_property(json, "delegate", false) 548 | } 549 | end 550 | 551 | defp convert_property_to_atom(json, property, default) do 552 | json 553 | |> Map.get(property, default) 554 | |> String.to_atom() 555 | end 556 | 557 | defp convert_property(json, property, default \\ nil) do 558 | case Map.get(json, property, default) do 559 | nil -> 560 | nil 561 | list when is_list(list) -> 562 | Enum.map(list, &convert/1) 563 | map when is_map(map) -> 564 | convert(map) 565 | val -> 566 | val 567 | end 568 | end 569 | end -------------------------------------------------------------------------------- /test/tools/estree_json_transformer_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.ESTreeJSONTransformer.Test do 2 | use ExUnit.Case, async: true 3 | 4 | alias ESTree.Tools.ESTreeJSONTransformer, as: EJT 5 | 6 | 7 | test "convert json to structs" do 8 | map = json() |> Poison.decode! 9 | structs = EJT.convert(map) 10 | 11 | assert structs.type === "Program" 12 | end 13 | 14 | 15 | def json() do 16 | """ 17 | { 18 | "type": "Program", 19 | "start": 0, 20 | "end": 215, 21 | "range": [ 22 | 0, 23 | 215 24 | ], 25 | "body": [ 26 | { 27 | "type": "FunctionDeclaration", 28 | "start": 0, 29 | "end": 215, 30 | "range": [ 31 | 0, 32 | 215 33 | ], 34 | "id": { 35 | "type": "Identifier", 36 | "start": 9, 37 | "end": 17, 38 | "range": [ 39 | 9, 40 | 17 41 | ], 42 | "name": "fizzBuzz" 43 | }, 44 | "generator": false, 45 | "expression": false, 46 | "params": [], 47 | "body": { 48 | "type": "BlockStatement", 49 | "start": 19, 50 | "end": 215, 51 | "range": [ 52 | 19, 53 | 215 54 | ], 55 | "body": [ 56 | { 57 | "type": "ForStatement", 58 | "start": 22, 59 | "end": 213, 60 | "range": [ 61 | 22, 62 | 213 63 | ], 64 | "init": { 65 | "type": "VariableDeclaration", 66 | "start": 26, 67 | "end": 33, 68 | "range": [ 69 | 26, 70 | 33 71 | ], 72 | "declarations": [ 73 | { 74 | "type": "VariableDeclarator", 75 | "start": 30, 76 | "end": 33, 77 | "range": [ 78 | 30, 79 | 33 80 | ], 81 | "id": { 82 | "type": "Identifier", 83 | "start": 30, 84 | "end": 31, 85 | "range": [ 86 | 30, 87 | 31 88 | ], 89 | "name": "i" 90 | }, 91 | "init": { 92 | "type": "Literal", 93 | "start": 32, 94 | "end": 33, 95 | "range": [ 96 | 32, 97 | 33 98 | ], 99 | "value": 1, 100 | "raw": "1" 101 | } 102 | } 103 | ], 104 | "kind": "var" 105 | }, 106 | "test": { 107 | "type": "BinaryExpression", 108 | "start": 34, 109 | "end": 40, 110 | "range": [ 111 | 34, 112 | 40 113 | ], 114 | "left": { 115 | "type": "Identifier", 116 | "start": 34, 117 | "end": 35, 118 | "range": [ 119 | 34, 120 | 35 121 | ], 122 | "name": "i" 123 | }, 124 | "operator": "<=", 125 | "right": { 126 | "type": "Literal", 127 | "start": 37, 128 | "end": 40, 129 | "range": [ 130 | 37, 131 | 40 132 | ], 133 | "value": 100, 134 | "raw": "100" 135 | } 136 | }, 137 | "update": { 138 | "type": "UpdateExpression", 139 | "start": 41, 140 | "end": 44, 141 | "range": [ 142 | 41, 143 | 44 144 | ], 145 | "operator": "++", 146 | "prefix": false, 147 | "argument": { 148 | "type": "Identifier", 149 | "start": 41, 150 | "end": 42, 151 | "range": [ 152 | 41, 153 | 42 154 | ], 155 | "name": "i" 156 | } 157 | }, 158 | "body": { 159 | "type": "BlockStatement", 160 | "start": 45, 161 | "end": 213, 162 | "range": [ 163 | 45, 164 | 213 165 | ], 166 | "body": [ 167 | { 168 | "type": "IfStatement", 169 | "start": 49, 170 | "end": 210, 171 | "range": [ 172 | 49, 173 | 210 174 | ], 175 | "test": { 176 | "type": "LogicalExpression", 177 | "start": 52, 178 | "end": 74, 179 | "range": [ 180 | 52, 181 | 74 182 | ], 183 | "left": { 184 | "type": "BinaryExpression", 185 | "start": 52, 186 | "end": 61, 187 | "range": [ 188 | 52, 189 | 61 190 | ], 191 | "left": { 192 | "type": "BinaryExpression", 193 | "start": 52, 194 | "end": 55, 195 | "range": [ 196 | 52, 197 | 55 198 | ], 199 | "left": { 200 | "type": "Identifier", 201 | "start": 52, 202 | "end": 53, 203 | "range": [ 204 | 52, 205 | 53 206 | ], 207 | "name": "i" 208 | }, 209 | "operator": "%", 210 | "right": { 211 | "type": "Literal", 212 | "start": 54, 213 | "end": 55, 214 | "range": [ 215 | 54, 216 | 55 217 | ], 218 | "value": 5, 219 | "raw": "5" 220 | } 221 | }, 222 | "operator": "===", 223 | "right": { 224 | "type": "Literal", 225 | "start": 60, 226 | "end": 61, 227 | "range": [ 228 | 60, 229 | 61 230 | ], 231 | "value": 0, 232 | "raw": "0" 233 | } 234 | }, 235 | "operator": "&&", 236 | "right": { 237 | "type": "BinaryExpression", 238 | "start": 65, 239 | "end": 74, 240 | "range": [ 241 | 65, 242 | 74 243 | ], 244 | "left": { 245 | "type": "BinaryExpression", 246 | "start": 65, 247 | "end": 68, 248 | "range": [ 249 | 65, 250 | 68 251 | ], 252 | "left": { 253 | "type": "Identifier", 254 | "start": 65, 255 | "end": 66, 256 | "range": [ 257 | 65, 258 | 66 259 | ], 260 | "name": "i" 261 | }, 262 | "operator": "%", 263 | "right": { 264 | "type": "Literal", 265 | "start": 67, 266 | "end": 68, 267 | "range": [ 268 | 67, 269 | 68 270 | ], 271 | "value": 3, 272 | "raw": "3" 273 | } 274 | }, 275 | "operator": "===", 276 | "right": { 277 | "type": "Literal", 278 | "start": 73, 279 | "end": 74, 280 | "range": [ 281 | 73, 282 | 74 283 | ], 284 | "value": 0, 285 | "raw": "0" 286 | } 287 | } 288 | }, 289 | "consequent": { 290 | "type": "BlockStatement", 291 | "start": 75, 292 | "end": 102, 293 | "range": [ 294 | 75, 295 | 102 296 | ], 297 | "body": [ 298 | { 299 | "type": "ExpressionStatement", 300 | "start": 80, 301 | "end": 98, 302 | "range": [ 303 | 80, 304 | 98 305 | ], 306 | "expression": { 307 | "type": "CallExpression", 308 | "start": 80, 309 | "end": 97, 310 | "range": [ 311 | 80, 312 | 97 313 | ], 314 | "callee": { 315 | "type": "Identifier", 316 | "start": 80, 317 | "end": 85, 318 | "range": [ 319 | 80, 320 | 85 321 | ], 322 | "name": "print" 323 | }, 324 | "arguments": [ 325 | { 326 | "type": "Literal", 327 | "start": 86, 328 | "end": 96, 329 | "range": [ 330 | 86, 331 | 96 332 | ], 333 | "value": "FizzBuzz", 334 | "raw": "'FizzBuzz'" 335 | } 336 | ] 337 | } 338 | } 339 | ] 340 | }, 341 | "alternate": { 342 | "type": "IfStatement", 343 | "start": 108, 344 | "end": 210, 345 | "range": [ 346 | 108, 347 | 210 348 | ], 349 | "test": { 350 | "type": "BinaryExpression", 351 | "start": 111, 352 | "end": 120, 353 | "range": [ 354 | 111, 355 | 120 356 | ], 357 | "left": { 358 | "type": "BinaryExpression", 359 | "start": 111, 360 | "end": 114, 361 | "range": [ 362 | 111, 363 | 114 364 | ], 365 | "left": { 366 | "type": "Identifier", 367 | "start": 111, 368 | "end": 112, 369 | "range": [ 370 | 111, 371 | 112 372 | ], 373 | "name": "i" 374 | }, 375 | "operator": "%", 376 | "right": { 377 | "type": "Literal", 378 | "start": 113, 379 | "end": 114, 380 | "range": [ 381 | 113, 382 | 114 383 | ], 384 | "value": 3, 385 | "raw": "3" 386 | } 387 | }, 388 | "operator": "===", 389 | "right": { 390 | "type": "Literal", 391 | "start": 119, 392 | "end": 120, 393 | "range": [ 394 | 119, 395 | 120 396 | ], 397 | "value": 0, 398 | "raw": "0" 399 | } 400 | }, 401 | "consequent": { 402 | "type": "BlockStatement", 403 | "start": 121, 404 | "end": 144, 405 | "range": [ 406 | 121, 407 | 144 408 | ], 409 | "body": [ 410 | { 411 | "type": "ExpressionStatement", 412 | "start": 126, 413 | "end": 140, 414 | "range": [ 415 | 126, 416 | 140 417 | ], 418 | "expression": { 419 | "type": "CallExpression", 420 | "start": 126, 421 | "end": 139, 422 | "range": [ 423 | 126, 424 | 139 425 | ], 426 | "callee": { 427 | "type": "Identifier", 428 | "start": 126, 429 | "end": 131, 430 | "range": [ 431 | 126, 432 | 131 433 | ], 434 | "name": "print" 435 | }, 436 | "arguments": [ 437 | { 438 | "type": "Literal", 439 | "start": 132, 440 | "end": 138, 441 | "range": [ 442 | 132, 443 | 138 444 | ], 445 | "value": "Fizz", 446 | "raw": "'Fizz'" 447 | } 448 | ] 449 | } 450 | } 451 | ] 452 | }, 453 | "alternate": { 454 | "type": "IfStatement", 455 | "start": 150, 456 | "end": 210, 457 | "range": [ 458 | 150, 459 | 210 460 | ], 461 | "test": { 462 | "type": "BinaryExpression", 463 | "start": 153, 464 | "end": 162, 465 | "range": [ 466 | 153, 467 | 162 468 | ], 469 | "left": { 470 | "type": "BinaryExpression", 471 | "start": 153, 472 | "end": 156, 473 | "range": [ 474 | 153, 475 | 156 476 | ], 477 | "left": { 478 | "type": "Identifier", 479 | "start": 153, 480 | "end": 154, 481 | "range": [ 482 | 153, 483 | 154 484 | ], 485 | "name": "i" 486 | }, 487 | "operator": "%", 488 | "right": { 489 | "type": "Literal", 490 | "start": 155, 491 | "end": 156, 492 | "range": [ 493 | 155, 494 | 156 495 | ], 496 | "value": 5, 497 | "raw": "5" 498 | } 499 | }, 500 | "operator": "===", 501 | "right": { 502 | "type": "Literal", 503 | "start": 161, 504 | "end": 162, 505 | "range": [ 506 | 161, 507 | 162 508 | ], 509 | "value": 0, 510 | "raw": "0" 511 | } 512 | }, 513 | "consequent": { 514 | "type": "BlockStatement", 515 | "start": 163, 516 | "end": 186, 517 | "range": [ 518 | 163, 519 | 186 520 | ], 521 | "body": [ 522 | { 523 | "type": "ExpressionStatement", 524 | "start": 168, 525 | "end": 182, 526 | "range": [ 527 | 168, 528 | 182 529 | ], 530 | "expression": { 531 | "type": "CallExpression", 532 | "start": 168, 533 | "end": 181, 534 | "range": [ 535 | 168, 536 | 181 537 | ], 538 | "callee": { 539 | "type": "Identifier", 540 | "start": 168, 541 | "end": 173, 542 | "range": [ 543 | 168, 544 | 173 545 | ], 546 | "name": "print" 547 | }, 548 | "arguments": [ 549 | { 550 | "type": "Literal", 551 | "start": 174, 552 | "end": 180, 553 | "range": [ 554 | 174, 555 | 180 556 | ], 557 | "value": "Buzz", 558 | "raw": "'Buzz'" 559 | } 560 | ] 561 | } 562 | } 563 | ] 564 | }, 565 | "alternate": { 566 | "type": "BlockStatement", 567 | "start": 192, 568 | "end": 210, 569 | "range": [ 570 | 192, 571 | 210 572 | ], 573 | "body": [ 574 | { 575 | "type": "ExpressionStatement", 576 | "start": 197, 577 | "end": 206, 578 | "range": [ 579 | 197, 580 | 206 581 | ], 582 | "expression": { 583 | "type": "CallExpression", 584 | "start": 197, 585 | "end": 205, 586 | "range": [ 587 | 197, 588 | 205 589 | ], 590 | "callee": { 591 | "type": "Identifier", 592 | "start": 197, 593 | "end": 202, 594 | "range": [ 595 | 197, 596 | 202 597 | ], 598 | "name": "print" 599 | }, 600 | "arguments": [ 601 | { 602 | "type": "Identifier", 603 | "start": 203, 604 | "end": 204, 605 | "range": [ 606 | 203, 607 | 204 608 | ], 609 | "name": "i" 610 | } 611 | ] 612 | } 613 | } 614 | ] 615 | } 616 | } 617 | } 618 | } 619 | ] 620 | } 621 | } 622 | ] 623 | } 624 | } 625 | ], 626 | "sourceType": "module" 627 | } 628 | """ 629 | end 630 | end -------------------------------------------------------------------------------- /lib/es_tree/tools/builder.ex: -------------------------------------------------------------------------------- 1 | defmodule ESTree.Tools.Builder do 2 | @moduledoc """ 3 | Functions to make building the Nodes easier 4 | """ 5 | 6 | @spec array_expression( 7 | [ESTree.Expression.t | nil], 8 | ESTree.SourceLocation.t | nil 9 | ) :: ESTree.ArrayExpression.t 10 | def array_expression(elements, loc \\ nil) do 11 | %ESTree.ArrayExpression{ elements: elements, loc: loc } 12 | end 13 | 14 | @spec array_pattern( 15 | [ESTree.Pattern.t | nil], 16 | ESTree.SourceLocation.t | nil 17 | ) :: ESTree.ArrayPattern.t 18 | def array_pattern(elements, loc \\ nil) do 19 | %ESTree.ArrayPattern{ elements: elements, loc: loc } 20 | end 21 | 22 | @spec arrow_function_expression( 23 | [ESTree.Pattern.t], 24 | [ESTree.Expression.t], 25 | ESTree.BlockStatement.t | ESTree.Expression.t, 26 | boolean, 27 | boolean, 28 | ESTree.SourceLocation.t | nil 29 | ) :: ESTree.ArrowFunctionExpression.t 30 | def arrow_function_expression(params, defaults, body, generator \\ false, expression \\ false, async \\ false, loc \\ nil) do 31 | %ESTree.ArrowFunctionExpression{ 32 | params: params, defaults: defaults, 33 | body: body, generator: generator, expression: expression, loc: loc, 34 | async: async 35 | } 36 | end 37 | 38 | @spec assignment_expression( 39 | ESTree.assignment_operator, 40 | ESTree.Pattern.t, 41 | ESTree.Expression.t, 42 | ESTree.SourceLocation.t | nil 43 | ) :: ESTree.AssignmentExpression.t 44 | def assignment_expression(operator, left, right, loc \\ nil) do 45 | %ESTree.AssignmentExpression{ 46 | operator: operator, left: left, right: right, loc: loc 47 | } 48 | end 49 | 50 | @spec assignment_property( 51 | ESTree.Pattern.t, 52 | ESTree.SourceLocation.t | nil 53 | ) :: ESTree.AssignmentProperty.t 54 | def assignment_property(value, loc \\ nil) do 55 | %ESTree.AssignmentProperty{ 56 | value: value, loc: loc 57 | } 58 | end 59 | 60 | 61 | @spec await_expression( 62 | ESTree.Expression.t | nil, 63 | boolean, 64 | ESTree.SourceLocation.t | nil 65 | ) :: ESTree.AwaitExpression.t 66 | def await_expression(argument, all \\ false, loc \\ nil) do 67 | %ESTree.AwaitExpression{ 68 | argument: argument, all: all, loc: loc 69 | } 70 | end 71 | 72 | @spec binary_expression( 73 | ESTree.binary_operator, 74 | ESTree.Expression.t, 75 | ESTree.Expression.t, 76 | ESTree.SourceLocation.t | nil 77 | ) :: ESTree.BinaryExpression.t 78 | def binary_expression(operator, left, right, loc \\ nil) do 79 | %ESTree.BinaryExpression{ 80 | operator: operator, left: left, right: right, loc: loc 81 | } 82 | end 83 | 84 | @spec block_statement( 85 | [ESTree.Statement.t], 86 | ESTree.SourceLocation.t | nil 87 | ) :: ESTree.BlockStatement.t 88 | def block_statement(body, loc \\ nil) do 89 | %ESTree.BlockStatement{ 90 | body: body, loc: loc 91 | } 92 | end 93 | 94 | @spec break_statement( 95 | ESTree.Identifier.t | nil, 96 | ESTree.SourceLocation.t | nil 97 | ) :: ESTree.BreakStatement.t 98 | def break_statement(label \\ nil, loc \\ nil) do 99 | %ESTree.BreakStatement{ 100 | label: label, loc: loc 101 | } 102 | end 103 | 104 | @spec call_expression( 105 | ESTree.Expression.t, 106 | [ESTree.Expression.t], 107 | ESTree.SourceLocation.t | nil 108 | ) :: ESTree.CallExpression.t 109 | def call_expression(callee, arguments, loc \\ nil) do 110 | %ESTree.CallExpression{ 111 | callee: callee, arguments: arguments, loc: loc 112 | } 113 | end 114 | 115 | @spec catch_clause( 116 | ESTree.Pattern.t, 117 | ESTree.BlockStatement.t, 118 | ESTree.SourceLocation.t | nil 119 | ) :: ESTree.CatchClause.t 120 | def catch_clause(param, body, loc \\ nil) do 121 | %ESTree.CatchClause{ 122 | param: param, body: body, loc: loc 123 | } 124 | end 125 | 126 | @spec class_body( 127 | [ESTree.MethodDefinition.t], 128 | ESTree.SourceLocation.t | nil 129 | ) :: ESTree.ClassBody.t 130 | def class_body(body, loc \\ nil) do 131 | %ESTree.ClassBody{ 132 | body: body, loc: loc 133 | } 134 | end 135 | 136 | @spec class_declaration( 137 | ESTree.Identifier.t, 138 | ESTree.ClassBody.t, 139 | ESTree.Expression.t | nil, 140 | ESTree.SourceLocation.t | nil 141 | ) :: ESTree.ClassDeclaration.t 142 | def class_declaration(id, body, superClass \\ nil, loc \\ nil) do 143 | %ESTree.ClassDeclaration{ 144 | id: id, body: body, loc: loc, superClass: superClass 145 | } 146 | end 147 | 148 | @spec class_expression( 149 | ESTree.ClassBody.t, 150 | ESTree.Expression.t | nil, 151 | ESTree.SourceLocation.t | nil 152 | ) :: ESTree.ClassExpression.t 153 | def class_expression(body, superClass \\ nil, loc \\ nil) do 154 | %ESTree.ClassExpression{ 155 | body: body, loc: loc, superClass: superClass 156 | } 157 | end 158 | 159 | @spec conditional_statement( 160 | ESTree.Expression.t, 161 | ESTree.Expression.t, 162 | ESTree.Expression.t, 163 | ESTree.SourceLocation.t | nil 164 | ) :: ESTree.ConditionalStatement.t 165 | def conditional_statement(test, alternate, consequent, loc \\ nil) do 166 | %ESTree.ConditionalStatement{ 167 | test: test, alternate: alternate, consequent: consequent, loc: loc 168 | } 169 | end 170 | 171 | @spec continue_statement( 172 | ESTree.Identifier.t, 173 | ESTree.SourceLocation.t | nil 174 | ) :: ESTree.ContinueStatement.t 175 | def continue_statement(label, loc \\ nil) do 176 | %ESTree.ContinueStatement{ 177 | label: label, loc: loc 178 | } 179 | end 180 | 181 | @spec debugger_statement( 182 | ESTree.SourceLocation.t | nil 183 | ) :: ESTree.DebuggerStatement.t 184 | def debugger_statement(loc \\ nil) do 185 | %ESTree.DebuggerStatement{ 186 | loc: loc 187 | } 188 | end 189 | 190 | @spec do_while_statement( 191 | ESTree.Statement.t, 192 | ESTree.Expression.t, 193 | ESTree.SourceLocation.t | nil 194 | ) :: ESTree.DoWhileStatement.t 195 | def do_while_statement(body, test, loc \\ nil) do 196 | %ESTree.DoWhileStatement{ 197 | body: body, test: test, loc: loc 198 | } 199 | end 200 | 201 | @spec empty_expression( 202 | ESTree.SourceLocation.t | nil 203 | ) :: ESTree.EmptyExpression.t 204 | def empty_expression(loc \\ nil) do 205 | %ESTree.EmptyExpression{ 206 | loc: loc 207 | } 208 | end 209 | 210 | @spec empty_statement( 211 | ESTree.SourceLocation.t | nil 212 | ) :: ESTree.EmptyStatement.t 213 | def empty_statement(loc \\ nil) do 214 | %ESTree.EmptyStatement{ 215 | loc: loc 216 | } 217 | end 218 | 219 | @spec export_all_declaration( 220 | ESTree.Identifier.t | nil, 221 | ESTree.SourceLocation.t | nil 222 | ) :: ESTree.ExportAllDeclaration.t 223 | def export_all_declaration(source \\ nil, loc \\ nil) do 224 | %ESTree.ExportAllDeclaration{ 225 | loc: loc, source: source 226 | } 227 | end 228 | 229 | @spec export_default_declaration( 230 | ESTree.Declaration.t | ESTree.Expression.t | nil, 231 | ESTree.SourceLocation.t | nil 232 | ) :: ESTree.ExportDefaultDeclaration.t 233 | def export_default_declaration(declaration \\ nil, loc \\ nil) do 234 | %ESTree.ExportDefaultDeclaration{ 235 | loc: loc, declaration: declaration 236 | } 237 | end 238 | 239 | @spec export_named_declaration( 240 | ESTree.Declaration.t | nil, 241 | [ESTree.ExportSpecifier], 242 | ESTree.Literal.t | nil, 243 | ESTree.SourceLocation.t | nil 244 | ) :: ESTree.ExportNamedDeclaration.t 245 | def export_named_declaration(declaration, specifiers \\ [], source \\ nil, loc \\ nil) do 246 | %ESTree.ExportNamedDeclaration{ 247 | declaration: declaration, specifiers: specifiers, 248 | source: source, loc: loc 249 | } 250 | end 251 | 252 | @spec export_specifier( 253 | ESTree.Identifier.t, 254 | ESTree.Identifier.t | nil, 255 | ESTree.SourceLocation.t | nil 256 | ) :: ESTree.ExportSpecifier.t 257 | def export_specifier(exported, local \\ nil, loc \\ nil) do 258 | %ESTree.ExportSpecifier{ 259 | local: local, exported: exported, loc: loc 260 | } 261 | end 262 | 263 | @spec expression_statement( 264 | ESTree.Expression.t, 265 | ESTree.SourceLocation.t | nil 266 | ) :: ESTree.ExpressionStatement.t 267 | def expression_statement(expression, loc \\ nil) do 268 | %ESTree.ExpressionStatement{ 269 | expression: expression, loc: loc 270 | } 271 | end 272 | 273 | @spec for_in_statement( 274 | ESTree.VariableDeclaration.t | ESTree.Pattern.t, 275 | ESTree.Expression.t, 276 | ESTree.Statement.t, 277 | ESTree.SourceLocation.t | nil 278 | ) :: ESTree.ForInStatement.t 279 | def for_in_statement(left, right, body, loc \\ nil) do 280 | %ESTree.ForInStatement{ 281 | left: left, right: right, body: body, loc: loc 282 | } 283 | end 284 | 285 | @spec for_of_statement( 286 | ESTree.VariableDeclaration.t | ESTree.Pattern.t, 287 | ESTree.Expression.t, 288 | ESTree.Statement.t, 289 | ESTree.SourceLocation.t | nil 290 | ) :: ESTree.ForOfStatement.t 291 | def for_of_statement(left, right, body, loc \\ nil) do 292 | %ESTree.ForOfStatement{ 293 | left: left, right: right, body: body, loc: loc 294 | } 295 | end 296 | 297 | @spec for_statement( 298 | ESTree.VariableDeclaration.t | ESTree.Expression.t, 299 | ESTree.Expression.t | nil, 300 | ESTree.Expression.t | nil, 301 | ESTree.Statement.t, 302 | ESTree.SourceLocation.t | nil 303 | ) :: ESTree.ForStatement.t 304 | def for_statement(init, test, update, body, loc \\ nil) do 305 | %ESTree.ForStatement{ 306 | init: init, test: test, update: update, body: body, loc: loc 307 | } 308 | end 309 | 310 | @spec function_declaration( 311 | ESTree.Identifier.t, 312 | [ESTree.Pattern.t], 313 | [ESTree.Expression.t], 314 | ESTree.BlockStatement.t, 315 | boolean, 316 | boolean, 317 | boolean, 318 | ESTree.SourceLocation.t | nil 319 | ) :: ESTree.FunctionDeclaration.t 320 | def function_declaration(id, params, defaults, body, generator \\ false, expression \\ false, async \\ false, loc \\ nil) do 321 | %ESTree.FunctionDeclaration{ 322 | id: id, params: params, defaults: defaults, 323 | body: body, generator: generator, async: async, 324 | expression: expression, loc: loc 325 | } 326 | end 327 | 328 | @spec function_expression( 329 | [ESTree.Pattern.t], 330 | [ ESTree.Expression.t ], 331 | ESTree.BlockStatement.t, 332 | boolean, 333 | boolean, 334 | boolean, 335 | ESTree.SourceLocation.t | nil 336 | ) :: ESTree.FunctionExpression.t 337 | def function_expression(params, defaults, body, generator \\ false, expression \\ false, async \\ false, loc \\ nil) do 338 | %ESTree.FunctionExpression{ 339 | params: params, defaults: defaults, 340 | body: body, generator: generator, async: async, 341 | expression: expression, loc: loc 342 | } 343 | end 344 | 345 | @spec identifier( 346 | binary, 347 | ESTree.SourceLocation.t | nil 348 | ) :: ESTree.Identifier.t 349 | def identifier(name, loc \\ nil) do 350 | %ESTree.Identifier{ 351 | name: name, loc: loc 352 | } 353 | end 354 | 355 | @spec if_statement( 356 | ESTree.Expression.t, 357 | ESTree.Statement.t, 358 | ESTree.Statement.t | nil, 359 | ESTree.SourceLocation.t | nil 360 | ) :: ESTree.IfStatement.t 361 | def if_statement(test, consequent, alternate \\ nil, loc \\ nil) do 362 | %ESTree.IfStatement{ 363 | test: test, consequent: consequent, alternate: alternate, loc: loc 364 | } 365 | end 366 | 367 | @spec import_declaration( 368 | [ESTree.ImportSpecifier.t | ESTree.ImportNamespaceSpecifier.t | ESTree.ImportDefaultSpecifier.t], 369 | ESTree.Identifier.t | nil, 370 | ESTree.SourceLocation.t | nil 371 | ) :: ESTree.ImportDeclaration.t 372 | def import_declaration(specifiers, source \\ nil, loc \\ nil) do 373 | %ESTree.ImportDeclaration{ 374 | specifiers: specifiers, source: source, loc: loc 375 | } 376 | end 377 | 378 | @spec import_default_specifier( 379 | ESTree.Identifier.t, 380 | ESTree.SourceLocation.t | nil 381 | ) :: ESTree.ImportDefaultSpecifier.t 382 | def import_default_specifier(local, loc \\ nil) do 383 | %ESTree.ImportDefaultSpecifier{ 384 | local: local, loc: loc 385 | } 386 | end 387 | 388 | @spec import_namespace_specifier( 389 | ESTree.Identifier.t, 390 | ESTree.SourceLocation.t | nil 391 | ) :: ESTree.ImportNamespaceSpecifier.t 392 | def import_namespace_specifier(local, loc \\ nil) do 393 | %ESTree.ImportNamespaceSpecifier{ 394 | local: local, loc: loc 395 | } 396 | end 397 | 398 | @spec import_specifier( 399 | ESTree.Identifier.t, 400 | ESTree.Identifier.t | nil, 401 | ESTree.SourceLocation.t | nil 402 | ) :: ESTree.ImportSpecifier.t 403 | def import_specifier(imported, local \\ nil, loc \\ nil) do 404 | %ESTree.ImportSpecifier{ 405 | local: local, imported: imported, loc: loc 406 | } 407 | end 408 | 409 | @spec labeled_statement( 410 | ESTree.Identifier.t, 411 | ESTree.Statement.t, 412 | ESTree.SourceLocation.t | nil 413 | ) :: ESTree.LabeledStatement.t 414 | def labeled_statement(label, body, loc \\ nil) do 415 | %ESTree.LabeledStatement{ 416 | label: label, body: body, loc: loc 417 | } 418 | end 419 | 420 | @spec literal( 421 | binary | boolean | number | nil, 422 | ESTree.Regex.t | nil, 423 | ESTree.SourceLocation.t | nil 424 | ) :: ESTree.Literal.t 425 | def literal(value, regex \\ nil, loc \\ nil) do 426 | %ESTree.Literal{ 427 | value: value, regex: regex, loc: loc 428 | } 429 | end 430 | 431 | @spec logical_expression( 432 | ESTree.logical_operator, 433 | ESTree.Expression.t, 434 | ESTree.Expression.t, 435 | ESTree.SourceLocation.t | nil 436 | ) :: ESTree.LogicalExpression.t 437 | def logical_expression(operator, left, right, loc \\ nil) do 438 | %ESTree.LogicalExpression{ 439 | operator: operator, left: left, right: right, loc: loc 440 | } 441 | end 442 | 443 | @spec member_expression( 444 | ESTree.Expression.t | ESTree.Super.t, 445 | ESTree.Identifier.t | ESTree.Expression.t, 446 | boolean, 447 | ESTree.SourceLocation.t | nil 448 | ) :: ESTree.MemberExpression.t 449 | def member_expression(object, property, computed \\ false, loc \\ nil) do 450 | %ESTree.MemberExpression{ 451 | object: object, property: property, computed: computed, loc: loc 452 | } 453 | end 454 | 455 | @spec meta_property( 456 | ESTree.Identifier.t, 457 | ESTree.Identifier.t, 458 | ESTree.SourceLocation.t | nil 459 | ) :: ESTree.MetaProperty.t 460 | def meta_property(meta, property, loc \\ nil) do 461 | %ESTree.MetaProperty{ 462 | meta: meta, property: property, loc: loc 463 | } 464 | end 465 | 466 | @spec method_definition( 467 | ESTree.Identifier.t, 468 | ESTree.FunctionExpression.t, 469 | :constructor | :method | :get | :set, 470 | boolean, 471 | boolean, 472 | ESTree.SourceLocation.t | nil 473 | ) :: ESTree.MethodDefinition.t 474 | def method_definition(key, value, kind \\ :method, computed \\ false, static \\ false, loc \\ nil) do 475 | %ESTree.MethodDefinition{ 476 | key: key, value: value, kind: kind, computed: computed, static: static, loc: loc 477 | } 478 | end 479 | 480 | @spec new_expression( 481 | ESTree.Expression.t, 482 | [ESTree.Expression.t], 483 | ESTree.SourceLocation.t | nil 484 | ) :: ESTree.NewExpression.t 485 | def new_expression(callee, arguments, loc \\ nil) do 486 | %ESTree.NewExpression{ 487 | callee: callee, arguments: arguments, loc: loc 488 | } 489 | end 490 | 491 | @spec object_expression( 492 | [ESTree.Property.t], 493 | ESTree.SourceLocation.t | nil 494 | ) :: ESTree.ObjectExpression.t 495 | def object_expression(properties, loc \\ nil) do 496 | %ESTree.ObjectExpression{ 497 | properties: properties, loc: loc 498 | } 499 | end 500 | 501 | @spec object_pattern( 502 | [ESTree.Property.t], 503 | ESTree.SourceLocation.t | nil 504 | ) :: ESTree.ObjectPattern.t 505 | def object_pattern(properties, loc \\ nil) do 506 | %ESTree.ObjectPattern{ 507 | properties: properties, loc: loc 508 | } 509 | end 510 | 511 | @spec position( 512 | pos_integer, 513 | non_neg_integer 514 | ) :: ESTree.Position.t 515 | def position(line, column) do 516 | %ESTree.Position{ 517 | line: line, column: column 518 | } 519 | end 520 | 521 | @spec program( 522 | [ESTree.Statement.t], 523 | :script | :module, 524 | ESTree.SourceLocation.t | nil 525 | ) :: ESTree.Program.t 526 | def program(body, sourceType \\ :script, loc \\ nil) do 527 | %ESTree.Program{ 528 | body: body, loc: loc, sourceType: sourceType 529 | } 530 | end 531 | 532 | @spec property( 533 | ESTree.Expression.t, 534 | ESTree.Expression.t , 535 | :init | :get | :set, 536 | boolean, 537 | boolean, 538 | boolean, 539 | ESTree.SourceLocation.t | nil 540 | ) :: ESTree.Property.t 541 | def property(key, value, kind \\ :init, shorthand \\ false, method \\ false, computed \\false, loc \\ nil) do 542 | %ESTree.Property{ 543 | key: key, value: value, 544 | kind: kind, shorthand: shorthand, method: method, 545 | loc: loc, computed: computed 546 | } 547 | end 548 | 549 | @spec regex( 550 | binary, 551 | binary 552 | ) :: ESTree.Regex.t 553 | def regex(pattern, flags) do 554 | %ESTree.Regex{ 555 | pattern: pattern, flags: flags 556 | } 557 | end 558 | 559 | @spec rest_element( 560 | ESTree.Expression.t | nil, 561 | ESTree.SourceLocation.t | nil 562 | ) :: ESTree.RestElement.t 563 | def rest_element(argument, loc \\ nil) do 564 | %ESTree.RestElement{ 565 | argument: argument, loc: loc 566 | } 567 | end 568 | 569 | @spec return_statement( 570 | ESTree.Expression.t | nil, 571 | ESTree.SourceLocation.t | nil 572 | ) :: ESTree.ReturnStatement.t 573 | def return_statement(argument, loc \\ nil) do 574 | %ESTree.ReturnStatement{ 575 | argument: argument, loc: loc 576 | } 577 | end 578 | 579 | @spec sequence_expression( 580 | [ESTree.Expression.t], 581 | ESTree.SourceLocation.t | nil 582 | ) :: ESTree.SequenceExpression.t 583 | def sequence_expression(expressions, loc \\ nil) do 584 | %ESTree.SequenceExpression{ 585 | expressions: expressions, loc: loc 586 | } 587 | end 588 | 589 | @spec source_location( 590 | binary | nil, 591 | ESTree.Position.t, 592 | ESTree.Position.t 593 | ) :: ESTree.SourceLocation.t 594 | def source_location(source, start, the_end) do 595 | %ESTree.SourceLocation{ 596 | source: source, start: start, end: the_end 597 | } 598 | end 599 | 600 | @spec spread_element( 601 | ESTree.Expression.t | nil, 602 | ESTree.SourceLocation.t | nil 603 | ) :: ESTree.SpreadElement.t 604 | def spread_element(argument, loc \\ nil) do 605 | %ESTree.SpreadElement{ 606 | argument: argument, loc: loc 607 | } 608 | end 609 | 610 | @spec super( 611 | ESTree.SourceLocation.t | nil 612 | ) :: ESTree.Super.t 613 | def super(loc \\ nil) do 614 | %ESTree.Super{ 615 | loc: loc 616 | } 617 | end 618 | 619 | @spec switch_case( 620 | ESTree.Expression.t | nil, 621 | [ESTree.Statement.t], 622 | ESTree.SourceLocation.t | nil 623 | ) :: ESTree.SwitchCase.t 624 | def switch_case(test, consequent, loc \\ nil) do 625 | %ESTree.SwitchCase{ 626 | test: test, consequent: consequent, loc: loc 627 | } 628 | end 629 | 630 | @spec switch_statement( 631 | ESTree.Expression.t, 632 | [ESTree.SwitchCase.t], 633 | ESTree.SourceLocation.t | nil 634 | ) :: ESTree.SwitchStatement.t 635 | def switch_statement(discriminant, cases, loc \\ nil) do 636 | %ESTree.SwitchStatement{ 637 | discriminant: discriminant, cases: cases, loc: loc 638 | } 639 | end 640 | 641 | @spec tagged_template_expression( 642 | ESTree.Expression.t, 643 | ESTree.TemplateLiteral.t, 644 | ESTree.SourceLocation.t | nil 645 | ) :: ESTree.TaggedTemplateExpression.t 646 | def tagged_template_expression(tag, quasi, loc \\ nil) do 647 | %ESTree.TaggedTemplateExpression{ 648 | tag: tag, quasi: quasi, loc: loc 649 | } 650 | end 651 | 652 | @spec template_element( 653 | binary, 654 | binary, 655 | boolean, 656 | ESTree.SourceLocation.t | nil 657 | ) :: ESTree.TemplateElement.t 658 | def template_element(raw, cooked_value, tail, loc \\ nil) do 659 | %ESTree.TemplateElement{ 660 | value: %{cooked: cooked_value, raw: raw}, tail: tail, loc: loc 661 | } 662 | end 663 | 664 | @spec template_literal( 665 | [ESTree.TemplateElement.t], 666 | [ESTree.Expression.t], 667 | ESTree.SourceLocation.t | nil 668 | ) :: ESTree.TemplateLiteral.t 669 | def template_literal(quasis, expressions, loc \\ nil) do 670 | %ESTree.TemplateLiteral{ 671 | quasis: quasis, expressions: expressions, loc: loc 672 | } 673 | end 674 | 675 | @spec this_expression( 676 | ESTree.SourceLocation.t | nil 677 | ) :: ESTree.ThisExpression.t 678 | def this_expression(loc \\ nil) do 679 | %ESTree.ThisExpression{ 680 | loc: loc 681 | } 682 | end 683 | 684 | @spec throw_statement( 685 | ESTree.Expression.t, 686 | ESTree.SourceLocation.t | nil 687 | ) :: ESTree.ThrowStatement.t 688 | def throw_statement(argument, loc \\ nil) do 689 | %ESTree.ThrowStatement{ 690 | argument: argument, loc: loc 691 | } 692 | end 693 | 694 | @spec try_statement( 695 | ESTree.BlockStatement.t, 696 | ESTree.CatchClause.t | nil, 697 | ESTree.BlockStatement.t | nil, 698 | ESTree.SourceLocation.t | nil 699 | ) :: ESTree.TryStatement.t 700 | def try_statement(block, handler, finalizer \\ nil, loc \\ nil) do 701 | %ESTree.TryStatement{ 702 | block: block, handler: handler, finalizer: finalizer, loc: loc 703 | } 704 | end 705 | 706 | @spec unary_expression( 707 | ESTree.unary_operator, 708 | boolean, 709 | ESTree.Expression.t, 710 | ESTree.SourceLocation.t | nil 711 | ) :: ESTree.UnaryExpression.t 712 | def unary_expression(operator, prefix, argument, loc \\ nil) do 713 | %ESTree.UnaryExpression{ 714 | operator: operator, prefix: prefix, argument: argument, loc: loc 715 | } 716 | end 717 | 718 | @spec update_expression( 719 | ESTree.update_operator, 720 | ESTree.Expression.t, 721 | boolean, 722 | ESTree.SourceLocation.t | nil 723 | ) :: ESTree.UpdateExpression.t 724 | def update_expression(operator, argument, prefix, loc \\ nil) do 725 | %ESTree.UpdateExpression{ 726 | operator: operator, prefix: prefix, argument: argument, loc: loc 727 | } 728 | end 729 | 730 | 731 | @spec variable_declaration( 732 | [ESTree.VariableDeclarator.t], 733 | :var | :let | :const, 734 | ESTree.SourceLocation.t | nil 735 | ) :: ESTree.VariableDeclaration.t 736 | def variable_declaration(declarations, kind \\ :var, loc \\ nil) do 737 | %ESTree.VariableDeclaration{ 738 | declarations: declarations, kind: kind, loc: loc 739 | } 740 | end 741 | 742 | @spec variable_declarator( 743 | ESTree.Pattern.t, 744 | ESTree.Expression.t | nil, 745 | ESTree.SourceLocation.t | nil 746 | ) :: ESTree.VariableDeclarator.t 747 | def variable_declarator(id, init \\ nil, loc \\ nil) do 748 | %ESTree.VariableDeclarator{ 749 | id: id, init: init, loc: loc 750 | } 751 | end 752 | 753 | @spec while_statement( 754 | ESTree.Expression.t, 755 | ESTree.Statement.t, 756 | ESTree.SourceLocation.t | nil 757 | ) :: ESTree.WhileStatement.t 758 | def while_statement(test, body, loc \\ nil) do 759 | %ESTree.WhileStatement{ 760 | test: test, body: body, loc: loc 761 | } 762 | end 763 | 764 | @spec with_statement( 765 | ESTree.Expression.t, 766 | ESTree.Statement.t, 767 | ESTree.SourceLocation.t | nil 768 | ) :: ESTree.WithStatement.t 769 | def with_statement(object, body, loc \\ nil) do 770 | %ESTree.WithStatement{ 771 | object: object, body: body, loc: loc 772 | } 773 | end 774 | 775 | @spec yield_expression( 776 | ESTree.Expression.t | nil, 777 | boolean, 778 | ESTree.SourceLocation.t | nil 779 | ) :: ESTree.YieldExpression.t 780 | def yield_expression(argument \\ nil, delegate \\ false, loc \\ nil) do 781 | %ESTree.YieldExpression{ 782 | argument: argument, loc: loc, delegate: delegate 783 | } 784 | end 785 | 786 | 787 | @spec jsx_identifier( 788 | binary, 789 | ESTree.SourceLocation.t | nil 790 | ) :: ESTree.JSXIdentifier.t 791 | def jsx_identifier(name, loc \\ nil) do 792 | %ESTree.JSXIdentifier{ 793 | name: name, loc: loc 794 | } 795 | end 796 | 797 | 798 | @spec jsx_member_expression( 799 | ESTree.JSXMemberExpression.t | ESTree.JSXIdentifier.t, 800 | ESTree.JSXIdentifier.t, 801 | ESTree.SourceLocation.t | nil 802 | ) :: ESTree.MemberExpression.t 803 | def jsx_member_expression(object, property, loc \\ nil) do 804 | %ESTree.JSXMemberExpression{ 805 | object: object, property: property, loc: loc 806 | } 807 | end 808 | 809 | @spec jsx_namespaced_name( 810 | ESTree.JSXIdentifier.t, 811 | ESTree.JSXIdentifier.t, 812 | ESTree.SourceLocation.t | nil 813 | ) :: ESTree.JSXNamespacedName.t 814 | def jsx_namespaced_name(namespace, name, loc \\ nil) do 815 | %ESTree.JSXNamespacedName{ 816 | namespace: namespace, name: name, loc: loc 817 | } 818 | end 819 | 820 | @spec jsx_empty_expression( 821 | ESTree.SourceLocation.t | nil 822 | ) :: ESTree.JSXEmptyExpression.t 823 | def jsx_empty_expression(loc \\ nil) do 824 | %ESTree.JSXEmptyExpression{ 825 | loc: loc 826 | } 827 | end 828 | 829 | @spec jsx_expression_container( 830 | ESTree.Expression.t | ESTree.JSXEmptyExpression.t, 831 | ESTree.SourceLocation.t | nil 832 | ) :: ESTree.JSXExpressionContainer.t 833 | def jsx_expression_container(expression, loc \\ nil) do 834 | %ESTree.JSXExpressionContainer{ 835 | expression: expression, loc: loc 836 | } 837 | end 838 | 839 | 840 | @spec jsx_opening_element( 841 | ESTree.JSXIdentifier.t | ESTree.JSXMemberExpression.t | ESTree.JSXNamespacedName.t, 842 | [ ESTree.JSXAttribute.t | ESTree.JSXSpreadAttribute.t ], 843 | boolean, 844 | ESTree.SourceLocation.t | nil 845 | ) :: ESTree.JSXOpeningElement.t 846 | def jsx_opening_element(name, attributes \\ [], selfClosing \\ false, loc \\ nil) do 847 | %ESTree.JSXOpeningElement{ 848 | name: name, attributes: attributes, selfClosing: selfClosing, loc: loc 849 | } 850 | end 851 | 852 | 853 | @spec jsx_closing_element( 854 | ESTree.JSXIdentifier.t | ESTree.JSXMemberExpression.t | ESTree.JSXNamespacedName.t, 855 | ESTree.SourceLocation.t | nil 856 | ) :: ESTree.JSXClosingElement.t 857 | def jsx_closing_element(name, loc \\ nil) do 858 | %ESTree.JSXClosingElement{ 859 | name: name, loc: loc 860 | } 861 | end 862 | 863 | 864 | @spec jsx_attribute( 865 | ESTree.JSXIdentifier.t | ESTree.JSXNamespacedName.t, 866 | ESTree.Literal.t | ESTree.JSXExpressionContainer.t | ESTree.JSXElement.t | nil, 867 | ESTree.SourceLocation.t | nil 868 | ) :: ESTree.JSXAttribute.t 869 | def jsx_attribute(name, value \\ nil, loc \\ nil) do 870 | %ESTree.JSXAttribute{ 871 | name: name, value: value, loc: loc 872 | } 873 | end 874 | 875 | @spec jsx_spread_attribute( 876 | ESTree.Expression.t | nil, 877 | ESTree.SourceLocation.t | nil 878 | ) :: ESTree.SpreadElement.t 879 | def jsx_spread_attribute(argument, loc \\ nil) do 880 | %ESTree.JSXSpreadAttribute{ 881 | argument: argument, loc: loc 882 | } 883 | end 884 | 885 | @spec jsx_element( 886 | ESTree.JSXOpeningElement.t, 887 | [ESTree.Literal.t | ESTree.JSXExpressionContainer.t | ESTree.JSXElement.t], 888 | ESTree.JSXClosingElement.t | nil, 889 | ESTree.SourceLocation.t | nil 890 | ) :: ESTree.JSXElement.t 891 | def jsx_element(openingElement, children \\ [], closingElement \\ nil, loc \\ nil) do 892 | %ESTree.JSXElement{ 893 | openingElement: openingElement, children: children, closingElement: closingElement, loc: loc 894 | } 895 | end 896 | end 897 | --------------------------------------------------------------------------------