diff --git a/README.md b/README.md index 0dc90057..32c13b77 100644 --- a/README.md +++ b/README.md @@ -249,6 +249,8 @@ With visitors, you only define handlers for the nodes that you need. You can fin * call `visit(child)` with each child that you want to visit * call nothing if you're sure you don't want to descend further +There are a couple of visitors that ship with Syntax Tree that can be used as examples. They live in the [lib/syntax_tree/visitor](lib/syntax_tree/visitor) directory. + ### visit_method When you're creating a visitor, it's very easy to accidentally mistype a visit method. Unfortunately, there's no way to tell Ruby to explicitly override a parent method, so it would then be easy to define a method that never gets called. To mitigate this risk, there's `Visitor.visit_method(name)`. This method accepts a symbol that is checked against the list of known visit methods. If it's not in the list, then an error will be raised. It's meant to be used like: diff --git a/lib/syntax_tree.rb b/lib/syntax_tree.rb index dde21f18..f1df71c5 100644 --- a/lib/syntax_tree.rb +++ b/lib/syntax_tree.rb @@ -11,8 +11,8 @@ require_relative "syntax_tree/parser" require_relative "syntax_tree/version" require_relative "syntax_tree/visitor" - -require_relative "syntax_tree/json_visitor" +require_relative "syntax_tree/visitor/json_visitor" +require_relative "syntax_tree/visitor/pretty_print_visitor" # If PrettyPrint::Align isn't defined, then we haven't gotten the updated # version of prettyprint. In that case we'll define our own. This is going to diff --git a/lib/syntax_tree/json_visitor.rb b/lib/syntax_tree/json_visitor.rb deleted file mode 100644 index 89d745cd..00000000 --- a/lib/syntax_tree/json_visitor.rb +++ /dev/null @@ -1,1338 +0,0 @@ -# frozen_string_literal: true - -module SyntaxTree - class JSONVisitor < Visitor - def visit_aref(node) - { - type: :aref, - collection: visit(node.collection), - index: visit(node.index), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_aref_field(node) - { - type: :aref_field, - collection: visit(node.collection), - index: visit(node.index), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_alias(node) - { - type: :alias, - left: visit(node.left), - right: visit(node.right), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_arg_block(node) - { - type: :arg_block, - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_arg_paren(node) - { - type: :arg_paren, - args: visit(node.arguments), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_arg_star(node) - { - type: :arg_star, - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_args(node) - { - type: :args, - parts: visit_all(node.parts), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_args_forward(node) - visit_token(:args_forward, node) - end - - def visit_array(node) - { - type: :array, - cnts: visit(node.contents), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_aryptn(node) - { - type: :aryptn, - constant: visit(node.constant), - reqs: visit_all(node.requireds), - rest: visit(node.rest), - posts: visit_all(node.posts), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_assign(node) - { - type: :assign, - target: visit(node.target), - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_assoc(node) - { - type: :assoc, - key: visit(node.key), - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_assoc_splat(node) - { - type: :assoc_splat, - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_backref(node) - visit_token(:backref, node) - end - - def visit_backtick(node) - visit_token(:backtick, node) - end - - def visit_bare_assoc_hash(node) - { - type: :bare_assoc_hash, - assocs: visit_all(node.assocs), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_BEGIN(node) - { - type: :BEGIN, - lbrace: visit(node.lbrace), - stmts: visit(node.statements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_begin(node) - { - type: :begin, - bodystmt: visit(node.bodystmt), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_binary(node) - { - type: :binary, - left: visit(node.left), - op: node.operator, - right: visit(node.right), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_block_arg(node) - { - type: :blockarg, - name: visit(node.name), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_block_var(node) - { - type: :block_var, - params: visit(node.params), - locals: visit_all(node.locals), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_bodystmt(node) - { - type: :bodystmt, - stmts: visit(node.statements), - rsc: visit(node.rescue_clause), - els: visit(node.else_clause), - ens: visit(node.ensure_clause), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_brace_block(node) - { - type: :brace_block, - lbrace: visit(node.lbrace), - block_var: visit(node.block_var), - stmts: visit(node.statements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_break(node) - { - type: :break, - args: visit(node.arguments), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_call(node) - { - type: :call, - receiver: visit(node.receiver), - op: visit_call_operator(node.operator), - message: node.message == :call ? :call : visit(node.message), - args: visit(node.arguments), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_case(node) - { - type: :case, - value: visit(node.value), - cons: visit(node.consequent), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_CHAR(node) - visit_token(:CHAR, node) - end - - def visit_class(node) - { - type: :class, - constant: visit(node.constant), - superclass: visit(node.superclass), - bodystmt: visit(node.bodystmt), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_comma(node) - visit_token(:comma, node) - end - - def visit_command(node) - { - type: :command, - message: visit(node.message), - args: visit(node.arguments), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_command_call(node) - { - type: :command_call, - receiver: visit(node.receiver), - op: visit_call_operator(node.operator), - message: visit(node.message), - args: visit(node.arguments), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_comment(node) - { - type: :comment, - value: node.value, - inline: node.inline, - loc: visit_location(node.location) - } - end - - def visit_const(node) - visit_token(:const, node) - end - - def visit_const_path_field(node) - { - type: :const_path_field, - parent: visit(node.parent), - constant: visit(node.constant), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_const_path_ref(node) - { - type: :const_path_ref, - parent: visit(node.parent), - constant: visit(node.constant), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_const_ref(node) - { - type: :const_ref, - constant: visit(node.constant), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_cvar(node) - visit_token(:cvar, node) - end - - def visit_def(node) - { - type: :def, - name: visit(node.name), - params: visit(node.params), - bodystmt: visit(node.bodystmt), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_def_endless(node) - { - type: :def_endless, - name: visit(node.name), - paren: visit(node.paren), - stmt: visit(node.statement), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_defined(node) - visit_token(:defined, node) - end - - def visit_defs(node) - { - type: :defs, - target: visit(node.target), - op: visit(node.operator), - name: visit(node.name), - params: visit(node.params), - bodystmt: visit(node.bodystmt), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_do_block(node) - { - type: :do_block, - keyword: visit(node.keyword), - block_var: visit(node.block_var), - bodystmt: visit(node.bodystmt), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_dot2(node) - { - type: :dot2, - left: visit(node.left), - right: visit(node.right), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_dot3(node) - { - type: :dot3, - left: visit(node.left), - right: visit(node.right), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_dyna_symbol(node) - { - type: :dyna_symbol, - parts: visit_all(node.parts), - quote: node.quote, - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_END(node) - { - type: :END, - lbrace: visit(node.lbrace), - stmts: visit(node.statements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_else(node) - { - type: :else, - stmts: visit(node.statements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_elsif(node) - { - type: :elsif, - pred: visit(node.predicate), - stmts: visit(node.statements), - cons: visit(node.consequent), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_embdoc(node) - { - type: :embdoc, - value: node.value, - loc: visit_location(node.location) - } - end - - def visit_embexpr_beg(node) - { - type: :embexpr_beg, - value: node.value, - loc: visit_location(node.location) - } - end - - def visit_embexpr_end(node) - { - type: :embexpr_end, - value: node.value, - loc: visit_location(node.location) - } - end - - def visit_embvar(node) - { - type: :embvar, - value: node.value, - loc: visit_location(node.location) - } - end - - def visit_ensure(node) - { - type: :ensure, - keyword: visit(node.keyword), - stmts: visit(node.statements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_excessed_comma(node) - visit_token(:excessed_comma, node) - end - - def visit_fcall(node) - { - type: :fcall, - value: visit(node.value), - args: visit(node.arguments), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_field(node) - { - type: :field, - parent: visit(node.parent), - op: visit_call_operator(node.operator), - name: visit(node.name), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_float(node) - visit_token(:float, node) - end - - def visit_fndptn(node) - { - type: :fndptn, - constant: visit(node.constant), - left: visit(node.left), - values: visit_all(node.values), - right: visit(node.right), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_for(node) - { - type: :for, - index: visit(node.index), - collection: visit(node.collection), - stmts: visit(node.statements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_gvar(node) - visit_token(:gvar, node) - end - - def visit_hash(node) - { - type: :hash, - assocs: visit_all(node.assocs), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_heredoc(node) - { - type: :heredoc, - beging: visit(node.beginning), - ending: node.ending, - parts: visit_all(node.parts), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_heredoc_beg(node) - visit_token(:heredoc_beg, node) - end - - def visit_hshptn(node) - { - type: :hshptn, - constant: visit(node.constant), - keywords: node.keywords.map { |(name, value)| [visit(name), visit(value)] }, - kwrest: visit(node.keyword_rest), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_ident(node) - visit_token(:ident, node) - end - - def visit_if(node) - { - type: :if, - pred: visit(node.predicate), - stmts: visit(node.statements), - cons: visit(node.consequent), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_if_mod(node) - { - type: :if_mod, - stmt: visit(node.statement), - pred: visit(node.predicate), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_if_op(node) - { - type: :ifop, - pred: visit(node.predicate), - tthy: visit(node.truthy), - flsy: visit(node.falsy), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_imaginary(node) - visit_token(:imaginary, node) - end - - def visit_in(node) - { - type: :in, - pattern: visit(node.pattern), - stmts: visit(node.statements), - cons: visit(node.consequent), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_int(node) - visit_token(:int, node) - end - - def visit_ivar(node) - visit_token(:ivar, node) - end - - def visit_kw(node) - visit_token(:kw, node) - end - - def visit_kwrest_param(node) - { - type: :kwrest_param, - name: visit(node.name), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_label(node) - visit_token(:label, node) - end - - def visit_label_end(node) - visit_token(:label_end, node) - end - - def visit_lambda(node) - { - type: :lambda, - params: visit(node.params), - stmts: visit(node.statements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_lbrace(node) - visit_token(:lbrace, node) - end - - def visit_lbracket(node) - visit_token(:lbracket, node) - end - - def visit_lparen(node) - visit_token(:lparen, node) - end - - def visit_massign(node) - { - type: :massign, - target: visit(node.target), - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_method_add_block(node) - { - type: :method_add_block, - call: visit(node.call), - block: visit(node.block), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_mlhs(node) - { - type: :mlhs, - parts: visit_all(node.parts), - comma: node.comma, - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_mlhs_paren(node) - { - type: :mlhs_paren, - cnts: visit(node.contents), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_module(node) - { - type: :module, - constant: visit(node.constant), - bodystmt: visit(node.bodystmt), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_mrhs(node) - { - type: :mrhs, - parts: visit_all(node.parts), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_next(node) - { - type: :next, - args: visit(node.arguments), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_not(node) - { - type: :not, - value: visit(node.statement), - paren: node.parentheses, - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_op(node) - visit_token(:op, node) - end - - def visit_op_assign(node) - { - type: :opassign, - target: visit(node.target), - op: visit(node.operator), - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_params(node) - { - type: :params, - reqs: visit_all(node.requireds), - opts: node.optionals.map { |(name, value)| [visit(name), visit(value)] }, - rest: visit(node.rest), - posts: visit_all(node.posts), - keywords: node.keywords.map { |(name, value)| [visit(name), visit(value || nil)] }, - kwrest: node.keyword_rest == :nil ? "nil" : visit(node.keyword_rest), - block: visit(node.block), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_paren(node) - { - type: :paren, - lparen: visit(node.lparen), - cnts: visit(node.contents), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_period(node) - visit_token(:period, node) - end - - def visit_pinned_begin(node) - { - type: :pinned_begin, - stmt: visit(node.statement), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_pinned_var_ref(node) - { - type: :pinned_var_ref, - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_program(node) - { - type: :program, - stmts: visit(node.statements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_qsymbols(node) - { - type: :qsymbols, - elems: visit_all(node.elements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_qsymbols_beg(node) - visit_token(:qsymbols_beg, node) - end - - def visit_qwords(node) - { - type: :qwords, - elems: visit_all(node.elements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_qwords_beg(node) - visit_token(:qwords_beg, node) - end - - def visit_rassign(node) - { - type: :rassign, - value: visit(node.value), - op: visit(node.operator), - pattern: visit(node.pattern), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_rational(node) - visit_token(:rational, node) - end - - def visit_rbrace(node) - visit_token(:rbrace, node) - end - - def visit_rbracket(node) - visit_token(:rbracket, node) - end - - def visit_redo(node) - visit_token(:redo, node) - end - - def visit_regexp_beg(node) - visit_token(:regexp_beg, node) - end - - def visit_regexp_content(node) - { - type: :regexp_content, - beging: node.beginning, - parts: visit_all(node.parts), - loc: visit_location(node.location) - } - end - - def visit_regexp_end(node) - visit_token(:regexp_end, node) - end - - def visit_regexp_literal(node) - { - type: :regexp_literal, - beging: node.beginning, - ending: node.ending, - parts: visit_all(node.parts), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_rescue(node) - { - type: :rescue, - extn: visit(node.exception), - stmts: visit(node.statements), - cons: visit(node.consequent), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_rescue_ex(node) - { - type: :rescue_ex, - extns: visit(node.exceptions), - var: visit(node.variable), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_rescue_mod(node) - { - type: :rescue_mod, - stmt: visit(node.statement), - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_rest_param(node) - { - type: :rest_param, - name: visit(node.name), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_retry(node) - visit_token(:retry, node) - end - - def visit_return(node) - { - type: :return, - args: visit(node.arguments), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_return0(node) - visit_token(:return0, node) - end - - def visit_rparen(node) - visit_token(:rparen, node) - end - - def visit_sclass(node) - { - type: :sclass, - target: visit(node.target), - bodystmt: visit(node.bodystmt), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_statements(node) - { - type: :statements, - body: visit_all(node.body), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_string_concat(node) - { - type: :string_concat, - left: visit(node.left), - right: visit(node.right), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_string_content(node) - { - type: :string_content, - parts: visit_all(node.parts), - loc: visit_location(node.location) - } - end - - def visit_string_dvar(node) - { - type: :string_dvar, - var: visit(node.variable), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_string_embexpr(node) - { - type: :string_embexpr, - stmts: visit(node.statements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_string_literal(node) - { - type: :string_literal, - parts: visit_all(node.parts), - quote: node.quote, - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_super(node) - { - type: :super, - args: visit(node.arguments), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_symbeg(node) - visit_token(:symbeg, node) - end - - def visit_symbol_content(node) - { - type: :symbol_content, - value: visit(node.value), - loc: visit_location(node.location) - } - end - - def visit_symbol_literal(node) - { - type: :symbol_literal, - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_symbols(node) - { - type: :symbols, - elems: visit_all(node.elements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_symbols_beg(node) - visit_token(:symbols_beg, node) - end - - def visit_tlambda(node) - visit_token(:tlambda, node) - end - - def visit_tlambeg(node) - visit_token(:tlambeg, node) - end - - def visit_tstring_beg(node) - visit_token(:tstring_beg, node) - end - - def visit_tstring_content(node) - visit_token(:tstring_content, node) - end - - def visit_tstring_end(node) - visit_token(:tstring_end, node) - end - - def visit_top_const_field(node) - { - type: :top_const_field, - constant: visit(node.constant), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_top_const_ref(node) - { - type: :top_const_ref, - constant: visit(node.constant), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_unary(node) - { - type: :unary, - op: node.operator, - value: visit(node.statement), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_undef(node) - { - type: :undef, - syms: visit_all(node.symbols), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_unless(node) - { - type: :unless, - pred: visit(node.predicate), - stmts: visit(node.statements), - cons: visit(node.consequent), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_unless_mod(node) - { - type: :unless_mod, - stmt: visit(node.statement), - pred: visit(node.predicate), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_until(node) - { - type: :until, - pred: visit(node.predicate), - stmts: visit(node.statements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_until_mod(node) - { - type: :until_mod, - stmt: visit(node.statement), - pred: visit(node.predicate), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_var_alias(node) - { - type: :var_alias, - left: visit(node.left), - right: visit(node.right), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_var_field(node) - { - type: :var_field, - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_var_ref(node) - { - type: :var_ref, - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_vcall(node) - { - type: :vcall, - value: visit(node.value), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_void_stmt(node) - { - type: :void_stmt, - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_when(node) - { - type: :when, - args: visit(node.arguments), - stmts: visit(node.statements), - cons: visit(node.consequent), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_while(node) - { - type: :while, - pred: visit(node.predicate), - stmts: visit(node.statements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_while_mod(node) - { - type: :while_mod, - stmt: visit(node.statement), - pred: visit(node.predicate), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_word(node) - { - type: :word, - parts: visit_all(node.parts), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_words(node) - { - type: :words, - elems: visit_all(node.elements), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_words_beg(node) - visit_token(:words_beg, node) - end - - def visit_xstring(node) - { - type: :xstring, - parts: visit_all(node.parts), - loc: visit_location(node.location) - } - end - - def visit_xstring_literal(node) - { - type: :xstring_literal, - parts: visit_all(node.parts), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_yield(node) - { - type: :yield, - args: visit(node.arguments), - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - - def visit_yield0(node) - visit_token(:yield0, node) - end - - def visit_zsuper(node) - visit_token(:zsuper, node) - end - - def visit___end__(node) - visit_token(:__end__, node) - end - - # Explicitly undefine the default aliased method for each of the visitor - # methods so that if there is one that isn't implemented it will raise an - # error. - undef visit_child_nodes - - private - - def visit_call_operator(operator) - operator == :"::" ? :"::" : visit(operator) - end - - def visit_location(location) - [ - location.start_line, - location.start_char, - location.end_line, - location.end_char - ] - end - - def visit_token(type, node) - { - type: type, - value: node.value, - loc: visit_location(node.location), - cmts: visit_all(node.comments) - } - end - end -end diff --git a/lib/syntax_tree/node.rb b/lib/syntax_tree/node.rb index 9081d977..8b8801aa 100644 --- a/lib/syntax_tree/node.rb +++ b/lib/syntax_tree/node.rb @@ -73,11 +73,12 @@ def format(q) end def pretty_print(q) - raise NotImplementedError + visitor = Visitor::PrettyPrintVisitor.new(q) + visitor.visit(self) end def to_json(*opts) - visitor = JSONVisitor.new + visitor = Visitor::JSONVisitor.new visitor.visit(self).to_json(*opts) end end @@ -139,17 +140,6 @@ def format(q) q.text("}") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("BEGIN") - - q.breakable - q.pp(statements) - - q.pp(Comment::List.new(comments)) - end - end end # CHAR irepresents a single codepoint in the script encoding. @@ -194,17 +184,6 @@ def format(q) q.text(q.quote) end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("CHAR") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # ENDBlock represents the use of the +END+ keyword, which hooks into the @@ -264,17 +243,6 @@ def format(q) q.text("}") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("END") - - q.breakable - q.pp(statements) - - q.pp(Comment::List.new(comments)) - end - end end # EndContent represents the use of __END__ syntax, which allows individual @@ -320,17 +288,6 @@ def format(q) separator = -> { q.breakable(indent: false, force: true) } q.seplist(value.split(/\r?\n/, -1), separator) { |line| q.text(line) } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("__end__") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # Alias represents the use of the +alias+ keyword with regular arguments (not @@ -415,20 +372,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("alias") - - q.breakable - q.pp(left) - - q.breakable - q.pp(right) - - q.pp(Comment::List.new(comments)) - end - end end # ARef represents when you're pulling a value out of a collection at a @@ -496,20 +439,6 @@ def format(q) q.text("]") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("aref") - - q.breakable - q.pp(collection) - - q.breakable - q.pp(index) - - q.pp(Comment::List.new(comments)) - end - end end # ARefField represents assigning values into collections at specific indices. @@ -571,20 +500,6 @@ def format(q) q.text("]") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("aref_field") - - q.breakable - q.pp(collection) - - q.breakable - q.pp(index) - - q.pp(Comment::List.new(comments)) - end - end end # ArgParen represents wrapping arguments to a method inside a set of @@ -640,17 +555,6 @@ def format(q) q.breakable("") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("arg_paren") - - q.breakable - q.pp(arguments) - - q.pp(Comment::List.new(comments)) - end - end end # Args represents a list of arguments being passed to a method call or array @@ -688,17 +592,6 @@ def deconstruct_keys(keys) def format(q) q.seplist(parts) { |part| q.format(part) } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("args") - - q.breakable - q.group(2, "(", ")") { q.seplist(parts) { |part| q.pp(part) } } - - q.pp(Comment::List.new(comments)) - end - end end # ArgBlock represents using a block operator on an expression. @@ -736,19 +629,6 @@ def format(q) q.text("&") q.format(value) if value end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("arg_block") - - if value - q.breakable - q.pp(value) - end - - q.pp(Comment::List.new(comments)) - end - end end # Star represents using a splat operator on an expression. @@ -786,17 +666,6 @@ def format(q) q.text("*") q.format(value) if value end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("arg_star") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # ArgsForward represents forwarding all kinds of arguments onto another method @@ -846,17 +715,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("args_forward") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # ArrayLiteral represents an array literal, which can optionally contain @@ -1003,17 +861,6 @@ def format(q) end end - def pretty_print(q) - q.group(2, "(", ")") do - q.text("array") - - q.breakable - q.pp(contents) - - q.pp(Comment::List.new(comments)) - end - end - private def qwords? @@ -1169,36 +1016,6 @@ def format(q) q.group { q.seplist(parts) { |part| q.format(part) } } end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("aryptn") - - if constant - q.breakable - q.pp(constant) - end - - if requireds.any? - q.breakable - q.group(2, "(", ")") do - q.seplist(requireds) { |required| q.pp(required) } - end - end - - if rest - q.breakable - q.pp(rest) - end - - if posts.any? - q.breakable - q.group(2, "(", ")") { q.seplist(posts) { |post| q.pp(post) } } - end - - q.pp(Comment::List.new(comments)) - end - end end # Determins if the following value should be indented or not. @@ -1273,20 +1090,6 @@ def format(q) end end - def pretty_print(q) - q.group(2, "(", ")") do - q.text("assign") - - q.breakable - q.pp(target) - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end - private def skip_indent? @@ -1340,22 +1143,6 @@ def format(q) end end - def pretty_print(q) - q.group(2, "(", ")") do - q.text("assoc") - - q.breakable - q.pp(key) - - if value - q.breakable - q.pp(value) - end - - q.pp(Comment::List.new(comments)) - end - end - private def format_contents(q) @@ -1410,17 +1197,6 @@ def format(q) q.text("**") q.format(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("assoc_splat") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # Backref represents a global variable referencing a matched value. It comes @@ -1458,17 +1234,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("backref") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # Backtick represents the use of the ` operator. It's usually found being used @@ -1504,17 +1269,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("backtick") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # This module is responsible for formatting the assocs contained within a @@ -1620,17 +1374,6 @@ def format(q) def format_key(q, key) (@key_formatter ||= HashKeyFormatter.for(self)).format_key(q, key) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("bare_assoc_hash") - - q.breakable - q.group(2, "(", ")") { q.seplist(assocs) { |assoc| q.pp(assoc) } } - - q.pp(Comment::List.new(comments)) - end - end end # Begin represents a begin..end chain. @@ -1679,17 +1422,6 @@ def format(q) q.breakable(force: true) q.text("end") end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("begin") - - q.breakable - q.pp(bodystmt) - - q.pp(Comment::List.new(comments)) - end - end end # PinnedBegin represents a pinning a nested statement within pattern matching. @@ -1738,17 +1470,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("pinned_begin") - - q.breakable - q.pp(statement) - - q.pp(Comment::List.new(comments)) - end - end end # Binary represents any expression that involves two sub-expressions with an @@ -1825,23 +1546,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("binary") - - q.breakable - q.pp(left) - - q.breakable - q.text(operator) - - q.breakable - q.pp(right) - - q.pp(Comment::List.new(comments)) - end - end end # This module will remove any breakables from the list of contents so that no @@ -1939,22 +1643,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("block_var") - - q.breakable - q.pp(params) - - if locals.any? - q.breakable - q.group(2, "(", ")") { q.seplist(locals) { |local| q.pp(local) } } - end - - q.pp(Comment::List.new(comments)) - end - end end # BlockArg represents declaring a block parameter on a method definition. @@ -1975,7 +1663,7 @@ def initialize(name:, location:, comments: []) end def accept(visitor) - visitor.visit_block_arg(self) + visitor.visit_blockarg(self) end def child_nodes @@ -1992,19 +1680,6 @@ def format(q) q.text("&") q.format(name) if name end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("blockarg") - - if name - q.breakable - q.pp(name) - end - - q.pp(Comment::List.new(comments)) - end - end end # bodystmt can't actually determine its bounds appropriately because it @@ -2130,42 +1805,16 @@ def format(q) end end end + end - def pretty_print(q) - q.group(2, "(", ")") do - q.text("bodystmt") + # Responsible for formatting either a BraceBlock or a DoBlock. + class BlockFormatter + class BlockOpenFormatter + # [String] the actual output that should be printed + attr_reader :text - q.breakable - q.pp(statements) - - if rescue_clause - q.breakable - q.pp(rescue_clause) - end - - if else_clause - q.breakable - q.pp(else_clause) - end - - if ensure_clause - q.breakable - q.pp(ensure_clause) - end - - q.pp(Comment::List.new(comments)) - end - end - end - - # Responsible for formatting either a BraceBlock or a DoBlock. - class BlockFormatter - class BlockOpenFormatter - # [String] the actual output that should be printed - attr_reader :text - - # [LBrace | Keyword] the node that is being represented - attr_reader :node + # [LBrace | Keyword] the node that is being represented + attr_reader :node def initialize(text, node) @text = text @@ -2365,22 +2014,6 @@ def deconstruct_keys(keys) def format(q) BlockFormatter.new(self, lbrace, "}", statements).format(q) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("brace_block") - - if block_var - q.breakable - q.pp(block_var) - end - - q.breakable - q.pp(statements) - - q.pp(Comment::List.new(comments)) - end - end end # Formats either a Break or Next node. @@ -2472,17 +2105,6 @@ def deconstruct_keys(keys) def format(q) FlowControlFormatter.new("break", self).format(q) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("break") - - q.breakable - q.pp(arguments) - - q.pp(Comment::List.new(comments)) - end - end end # Wraps a call operator (which can be a string literal :: or an Op node or a @@ -2597,28 +2219,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("call") - - q.breakable - q.pp(receiver) - - q.breakable - q.pp(operator) - - q.breakable - q.pp(message) - - if arguments - q.breakable - q.pp(arguments) - end - - q.pp(Comment::List.new(comments)) - end - end end # Case represents the beginning of a case chain. @@ -2689,25 +2289,6 @@ def format(q) q.text("end") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("case") - - q.breakable - q.pp(keyword) - - if value - q.breakable - q.pp(value) - end - - q.breakable - q.pp(consequent) - - q.pp(Comment::List.new(comments)) - end - end end # RAssign represents a single-line pattern match. @@ -2770,23 +2351,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("rassign") - - q.breakable - q.pp(value) - - q.breakable - q.pp(operator) - - q.breakable - q.pp(pattern) - - q.pp(Comment::List.new(comments)) - end - end end # Class represents defining a class using the +class+ keyword. @@ -2896,25 +2460,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("class") - - q.breakable - q.pp(constant) - - if superclass - q.breakable - q.pp(superclass) - end - - q.breakable - q.pp(bodystmt) - - q.pp(Comment::List.new(comments)) - end - end end # Comma represents the use of the , operator. @@ -2940,15 +2485,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("comma") - - q.breakable - q.pp(value) - end - end end # Command represents a method call with arguments and no parentheses. Note @@ -3006,20 +2542,6 @@ def format(q) end end - def pretty_print(q) - q.group(2, "(", ")") do - q.text("command") - - q.breakable - q.pp(message) - - q.breakable - q.pp(arguments) - - q.pp(Comment::List.new(comments)) - end - end - private def align?(node) @@ -3108,28 +2630,6 @@ def format(q) end end - def pretty_print(q) - q.group(2, "(", ")") do - q.text("command_call") - - q.breakable - q.pp(receiver) - - q.breakable - q.pp(operator) - - q.breakable - q.pp(message) - - if arguments - q.breakable - q.pp(arguments) - end - - q.pp(Comment::List.new(comments)) - end - end - private # This is a somewhat naive method that is attempting to sum up the width of @@ -3185,22 +2685,6 @@ def argument_alignment(q, doc) # # comment # class Comment < Node - class List - # [Array[ Comment ]] the list of comments this list represents - attr_reader :comments - - def initialize(comments) - @comments = comments - end - - def pretty_print(q) - return if comments.empty? - - q.breakable - q.group(2, "(", ")") { q.seplist(comments) { |comment| q.pp(comment) } } - end - end - # [String] the contents of the comment attr_reader :value @@ -3259,15 +2743,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("comment") - - q.breakable - q.pp(value) - end - end end # Const represents a literal value that _looks_ like a constant. This could @@ -3314,17 +2789,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("const") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # ConstPathField represents the child node of some kind of assignment. It @@ -3374,20 +2838,6 @@ def format(q) q.text("::") q.format(constant) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("const_path_field") - - q.breakable - q.pp(parent) - - q.breakable - q.pp(constant) - - q.pp(Comment::List.new(comments)) - end - end end # ConstPathRef represents referencing a constant by a path. @@ -3435,20 +2885,6 @@ def format(q) q.text("::") q.format(constant) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("const_path_ref") - - q.breakable - q.pp(parent) - - q.breakable - q.pp(constant) - - q.pp(Comment::List.new(comments)) - end - end end # ConstRef represents the name of the constant being used in a class or module @@ -3487,17 +2923,6 @@ def deconstruct_keys(keys) def format(q) q.format(constant) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("const_ref") - - q.breakable - q.pp(constant) - - q.pp(Comment::List.new(comments)) - end - end end # CVar represents the use of a class variable. @@ -3534,17 +2959,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("cvar") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # Def represents defining a regular method on the current self object. @@ -3611,23 +3025,6 @@ def format(q) q.text("end") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("def") - - q.breakable - q.pp(name) - - q.breakable - q.pp(params) - - q.breakable - q.pp(bodystmt) - - q.pp(Comment::List.new(comments)) - end - end end # DefEndless represents defining a single-line method since Ruby 3.0+. @@ -3719,33 +3116,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("def_endless") - - if target - q.breakable - q.pp(target) - - q.breakable - q.pp(operator) - end - - q.breakable - q.pp(name) - - if paren - q.breakable - q.pp(paren) - end - - q.breakable - q.pp(statement) - - q.pp(Comment::List.new(comments)) - end - end end # Defined represents the use of the +defined?+ operator. It can be used with @@ -3789,17 +3159,6 @@ def format(q) q.breakable("") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("defined") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # Defs represents defining a singleton method on an object. @@ -3886,29 +3245,6 @@ def format(q) q.text("end") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("defs") - - q.breakable - q.pp(target) - - q.breakable - q.pp(operator) - - q.breakable - q.pp(name) - - q.breakable - q.pp(params) - - q.breakable - q.pp(bodystmt) - - q.pp(Comment::List.new(comments)) - end - end end # DoBlock represents passing a block to a method call using the +do+ and +end+ @@ -3961,23 +3297,7 @@ def deconstruct_keys(keys) def format(q) BlockFormatter.new(self, keyword, "end", bodystmt).format(q) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("do_block") - - if block_var - q.breakable - q.pp(block_var) - end - - q.breakable - q.pp(bodystmt) - - q.pp(Comment::List.new(comments)) - end - end - end + end # Responsible for formatting Dot2 and Dot3 nodes. class DotFormatter @@ -4051,24 +3371,6 @@ def deconstruct_keys(keys) def format(q) DotFormatter.new("..", self).format(q) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("dot2") - - if left - q.breakable - q.pp(left) - end - - if right - q.breakable - q.pp(right) - end - - q.pp(Comment::List.new(comments)) - end - end end # Dot3 represents using the ... operator between two expressions. Usually this @@ -4117,24 +3419,6 @@ def deconstruct_keys(keys) def format(q) DotFormatter.new("...", self).format(q) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("dot3") - - if left - q.breakable - q.pp(left) - end - - if right - q.breakable - q.pp(right) - end - - q.pp(Comment::List.new(comments)) - end - end end # Responsible for providing information about quotes to be used for strings @@ -4237,17 +3521,6 @@ def format(q) end end - def pretty_print(q) - q.group(2, "(", ")") do - q.text("dyna_symbol") - - q.breakable - q.group(2, "(", ")") { q.seplist(parts) { |part| q.pp(part) } } - - q.pp(Comment::List.new(comments)) - end - end - private # Here we determine the quotes to use for a dynamic symbol. It's bound by a @@ -4342,17 +3615,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("else") - - q.breakable - q.pp(statements) - - q.pp(Comment::List.new(comments)) - end - end end # Elsif represents another clause in an +if+ or +unless+ chain. @@ -4430,25 +3692,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("elsif") - - q.breakable - q.pp(predicate) - - q.breakable - q.pp(statements) - - if consequent - q.breakable - q.pp(consequent) - end - - q.pp(Comment::List.new(comments)) - end - end end # EmbDoc represents a multi-line comment. @@ -4497,15 +3740,6 @@ def format(q) q.trim q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("embdoc") - - q.breakable - q.pp(value) - end - end end # EmbExprBeg represents the beginning token for using interpolation inside of @@ -4536,15 +3770,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("embexpr_beg") - - q.breakable - q.pp(value) - end - end end # EmbExprEnd represents the ending token for using interpolation inside of a @@ -4575,15 +3800,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("embexpr_end") - - q.breakable - q.pp(value) - end - end end # EmbVar represents the use of shorthand interpolation for an instance, class, @@ -4616,15 +3832,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("embvar") - - q.breakable - q.pp(value) - end - end end # Ensure represents the use of the +ensure+ keyword and its subsequent @@ -4680,17 +3887,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("ensure") - - q.breakable - q.pp(statements) - - q.pp(Comment::List.new(comments)) - end - end end # ExcessedComma represents a trailing comma in a list of block parameters. It @@ -4733,17 +3929,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("excessed_comma") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # FCall represents the piece of a method call that comes before any arguments @@ -4793,22 +3978,6 @@ def format(q) q.format(value) q.format(arguments) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("fcall") - - q.breakable - q.pp(value) - - if arguments - q.breakable - q.pp(arguments) - end - - q.pp(Comment::List.new(comments)) - end - end end # Field is always the child of an assignment. It represents assigning to a @@ -4864,23 +4033,6 @@ def format(q) q.format(name) end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("field") - - q.breakable - q.pp(parent) - - q.breakable - q.pp(operator) - - q.breakable - q.pp(name) - - q.pp(Comment::List.new(comments)) - end - end end # FloatLiteral represents a floating point number literal. @@ -4917,17 +4069,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("float") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # FndPtn represents matching against a pattern where you find a pattern in an @@ -4998,28 +4139,6 @@ def format(q) q.format(right) end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("fndptn") - - if constant - q.breakable - q.pp(constant) - end - - q.breakable - q.pp(left) - - q.breakable - q.group(2, "(", ")") { q.seplist(values) { |value| q.pp(value) } } - - q.breakable - q.pp(right) - - q.pp(Comment::List.new(comments)) - end - end end # For represents using a +for+ loop. @@ -5087,23 +4206,6 @@ def format(q) q.text("end") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("for") - - q.breakable - q.pp(index) - - q.breakable - q.pp(collection) - - q.breakable - q.pp(statements) - - q.pp(Comment::List.new(comments)) - end - end end # GVar represents a global variable literal. @@ -5140,17 +4242,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("gvar") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # HashLiteral represents a hash literal. @@ -5200,19 +4291,6 @@ def format_key(q, key) (@key_formatter ||= HashKeyFormatter.for(self)).format_key(q, key) end - def pretty_print(q) - q.group(2, "(", ")") do - q.text("hash") - - if assocs.any? - q.breakable - q.group(2, "(", ")") { q.seplist(assocs) { |assoc| q.pp(assoc) } } - end - - q.pp(Comment::List.new(comments)) - end - end - private def format_contents(q) @@ -5310,17 +4388,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("heredoc") - - q.breakable - q.group(2, "(", ")") { q.seplist(parts) { |part| q.pp(part) } } - - q.pp(Comment::List.new(comments)) - end - end end # HeredocBeg represents the beginning declaration of a heredoc. @@ -5360,17 +4427,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("heredoc_beg") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # HshPtn represents matching against a hash pattern using the Ruby 2.7+ @@ -5488,40 +4544,6 @@ def format(q) contents.call end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("hshptn") - - if constant - q.breakable - q.pp(constant) - end - - if keywords.any? - q.breakable - q.group(2, "(", ")") do - q.seplist(keywords) do |(key, value)| - q.group(2, "(", ")") do - q.pp(key) - - if value - q.breakable - q.pp(value) - end - end - end - end - end - - if keyword_rest - q.breakable - q.pp(keyword_rest) - end - - q.pp(Comment::List.new(comments)) - end - end end # The list of nodes that represent patterns inside of pattern matching so that @@ -5563,17 +4585,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("ident") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # If the predicate of a conditional or loop contains an assignment (in which @@ -5709,25 +4720,6 @@ def deconstruct_keys(keys) def format(q) ConditionalFormatter.new("if", self).format(q) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("if") - - q.breakable - q.pp(predicate) - - q.breakable - q.pp(statements) - - if consequent - q.breakable - q.pp(consequent) - end - - q.pp(Comment::List.new(comments)) - end - end end # IfOp represents a ternary clause. @@ -5791,24 +4783,7 @@ def format(q) q.group { q.if_break { format_break(q) }.if_flat { format_flat(q) } } end - def pretty_print(q) - q.group(2, "(", ")") do - q.text("ifop") - - q.breakable - q.pp(predicate) - - q.breakable - q.pp(truthy) - - q.breakable - q.pp(falsy) - - q.pp(Comment::List.new(comments)) - end - end - - private + private def format_break(q) Parentheses.break(q) do @@ -5932,20 +4907,6 @@ def deconstruct_keys(keys) def format(q) ConditionalModFormatter.new("if", self).format(q) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("if_mod") - - q.breakable - q.pp(statement) - - q.breakable - q.pp(predicate) - - q.pp(Comment::List.new(comments)) - end - end end # Imaginary represents an imaginary number literal. @@ -5982,17 +4943,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("imaginary") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # In represents using the +in+ keyword within the Ruby 2.7+ pattern matching @@ -6063,25 +5013,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("in") - - q.breakable - q.pp(pattern) - - q.breakable - q.pp(statements) - - if consequent - q.breakable - q.pp(consequent) - end - - q.pp(Comment::List.new(comments)) - end - end end # Int represents an integer number literal. @@ -6126,17 +5057,6 @@ def format(q) q.text(value) end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("int") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # IVar represents an instance variable literal. @@ -6173,17 +5093,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("ivar") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # Kw represents the use of a keyword. It can be almost anywhere in the syntax @@ -6229,17 +5138,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("kw") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # KwRestParam represents defining a parameter in a method definition that @@ -6278,17 +5176,6 @@ def format(q) q.text("**") q.format(name) if name end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("kwrest_param") - - q.breakable - q.pp(name) - - q.pp(Comment::List.new(comments)) - end - end end # Label represents the use of an identifier to associate with an object. You @@ -6334,18 +5221,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("label") - - q.breakable - q.text(":") - q.text(value[0...-1]) - - q.pp(Comment::List.new(comments)) - end - end end # LabelEnd represents the end of a dynamic symbol. @@ -6377,15 +5252,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("label_end") - - q.breakable - q.pp(value) - end - end end # Lambda represents using a lambda literal (not the lambda method call). @@ -6462,20 +5328,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("lambda") - - q.breakable - q.pp(params) - - q.breakable - q.pp(statements) - - q.pp(Comment::List.new(comments)) - end - end end # LBrace represents the use of a left brace, i.e., {. @@ -6509,17 +5361,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("lbrace") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # LBracket represents the use of a left bracket, i.e., [. @@ -6553,17 +5394,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("lbracket") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # LParen represents the use of a left parenthesis, i.e., (. @@ -6597,17 +5427,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("lparen") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # MAssign is a parent node of any kind of multiple assignment. This includes @@ -6665,20 +5484,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("massign") - - q.breakable - q.pp(target) - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # MethodAddBlock represents a method call with a block argument. @@ -6720,20 +5525,6 @@ def format(q) q.format(call) q.format(block) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("method_add_block") - - q.breakable - q.pp(call) - - q.breakable - q.pp(block) - - q.pp(Comment::List.new(comments)) - end - end end # MLHS represents a list of values being destructured on the left-hand side @@ -6779,17 +5570,6 @@ def format(q) q.seplist(parts) { |part| q.format(part) } q.text(",") if comma end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("mlhs") - - q.breakable - q.group(2, "(", ")") { q.seplist(parts) { |part| q.pp(part) } } - - q.pp(Comment::List.new(comments)) - end - end end # MLHSParen represents parentheses being used to destruct values in a multiple @@ -6840,17 +5620,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("mlhs_paren") - - q.breakable - q.pp(contents) - - q.pp(Comment::List.new(comments)) - end - end end # ModuleDeclaration represents defining a module using the +module+ keyword. @@ -6922,20 +5691,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("module") - - q.breakable - q.pp(constant) - - q.breakable - q.pp(bodystmt) - - q.pp(Comment::List.new(comments)) - end - end end # MRHS represents the values that are being assigned on the right-hand side of @@ -6973,17 +5728,6 @@ def deconstruct_keys(keys) def format(q) q.seplist(parts) { |part| q.format(part) } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("mrhs") - - q.breakable - q.group(2, "(", ")") { q.seplist(parts) { |part| q.pp(part) } } - - q.pp(Comment::List.new(comments)) - end - end end # Next represents using the +next+ keyword. @@ -7033,17 +5777,6 @@ def deconstruct_keys(keys) def format(q) FlowControlFormatter.new("next", self).format(q) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("next") - - q.breakable - q.pp(arguments) - - q.pp(Comment::List.new(comments)) - end - end end # Op represents an operator literal in the source. @@ -7081,17 +5814,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("op") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # OpAssign represents assigning a value to a variable or constant using an @@ -7122,7 +5844,7 @@ def initialize(target:, operator:, value:, location:, comments: []) end def accept(visitor) - visitor.visit_op_assign(self) + visitor.visit_opassign(self) end def child_nodes @@ -7159,23 +5881,6 @@ def format(q) end end - def pretty_print(q) - q.group(2, "(", ")") do - q.text("opassign") - - q.breakable - q.pp(target) - - q.breakable - q.pp(operator) - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end - private def skip_indent? @@ -7442,70 +6147,6 @@ def format(q) q.nest(0, &contents) end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("params") - - if requireds.any? - q.breakable - q.group(2, "(", ")") { q.seplist(requireds) { |name| q.pp(name) } } - end - - if optionals.any? - q.breakable - q.group(2, "(", ")") do - q.seplist(optionals) do |(name, default)| - q.pp(name) - q.text("=") - q.group(2) do - q.breakable("") - q.pp(default) - end - end - end - end - - if rest - q.breakable - q.pp(rest) - end - - if posts.any? - q.breakable - q.group(2, "(", ")") { q.seplist(posts) { |value| q.pp(value) } } - end - - if keywords.any? - q.breakable - q.group(2, "(", ")") do - q.seplist(keywords) do |(name, default)| - q.pp(name) - - if default - q.text("=") - q.group(2) do - q.breakable("") - q.pp(default) - end - end - end - end - end - - if keyword_rest - q.breakable - q.pp(keyword_rest) - end - - if block - q.breakable - q.pp(block) - end - - q.pp(Comment::List.new(comments)) - end - end end # Paren represents using balanced parentheses in a couple places in a Ruby @@ -7565,17 +6206,6 @@ def format(q) q.text(")") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("paren") - - q.breakable - q.pp(contents) - - q.pp(Comment::List.new(comments)) - end - end end # Period represents the use of the +.+ operator. It is usually found in method @@ -7610,18 +6240,7 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("period") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end - end + end # Program represents the overall syntax tree. class Program < Node @@ -7659,17 +6278,6 @@ def format(q) # replicate the text exactly so we will just let it be. q.breakable(force: true) unless statements.body.last.is_a?(EndContent) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("program") - - q.breakable - q.pp(statements) - - q.pp(Comment::List.new(comments)) - end - end end # QSymbols represents a symbol literal array without interpolation. @@ -7730,17 +6338,6 @@ def format(q) q.breakable("") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("qsymbols") - - q.breakable - q.group(2, "(", ")") { q.seplist(elements) { |element| q.pp(element) } } - - q.pp(Comment::List.new(comments)) - end - end end # QSymbolsBeg represents the beginning of a symbol literal array. @@ -7841,17 +6438,6 @@ def format(q) q.breakable("") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("qwords") - - q.breakable - q.group(2, "(", ")") { q.seplist(elements) { |element| q.pp(element) } } - - q.pp(Comment::List.new(comments)) - end - end end # QWordsBeg represents the beginning of a string literal array. @@ -7883,15 +6469,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("qwords_beg") - - q.breakable - q.pp(value) - end - end end # RationalLiteral represents the use of a rational number literal. @@ -7928,17 +6505,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("rational") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # RBrace represents the use of a right brace, i.e., +++. @@ -7964,15 +6530,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("rbrace") - - q.breakable - q.pp(value) - end - end end # RBracket represents the use of a right bracket, i.e., +]+. @@ -7998,15 +6555,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("rbracket") - - q.breakable - q.pp(value) - end - end end # Redo represents the use of the +redo+ keyword. @@ -8043,17 +6591,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("redo") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # RegexpContent represents the body of a regular expression. @@ -8089,15 +6626,6 @@ def child_nodes def deconstruct_keys(keys) { beginning: beginning, parts: parts, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("regexp_content") - - q.breakable - q.group(2, "(", ")") { q.seplist(parts) { |part| q.pp(part) } } - end - end end # RegexpBeg represents the start of a regular expression literal. @@ -8131,15 +6659,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("regexp_beg") - - q.breakable - q.pp(value) - end - end end # RegexpEnd represents the end of a regular expression literal. @@ -8174,15 +6693,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("regexp_end") - - q.breakable - q.pp(value) - end - end end # RegexpLiteral represents a regular expression literal. @@ -8271,17 +6781,6 @@ def format(q) end end - def pretty_print(q) - q.group(2, "(", ")") do - q.text("regexp_literal") - - q.breakable - q.group(2, "(", ")") { q.seplist(parts) { |part| q.pp(part) } } - - q.pp(Comment::List.new(comments)) - end - end - private def include?(pattern) @@ -8359,20 +6858,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("rescue_ex") - - q.breakable - q.pp(exceptions) - - q.breakable - q.pp(variable) - - q.pp(Comment::List.new(comments)) - end - end end # Rescue represents the use of the rescue keyword inside of a BodyStmt node. @@ -8474,27 +6959,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("rescue") - - if exception - q.breakable - q.pp(exception) - end - - q.breakable - q.pp(statements) - - if consequent - q.breakable - q.pp(consequent) - end - - q.pp(Comment::List.new(comments)) - end - end end # RescueMod represents the use of the modifier form of a +rescue+ clause. @@ -8552,20 +7016,6 @@ def format(q) q.breakable(force: true) end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("rescue_mod") - - q.breakable - q.pp(statement) - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # RestParam represents defining a parameter in a method definition that @@ -8604,17 +7054,6 @@ def format(q) q.text("*") q.format(name) if name end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("rest_param") - - q.breakable - q.pp(name) - - q.pp(Comment::List.new(comments)) - end - end end # Retry represents the use of the +retry+ keyword. @@ -8651,17 +7090,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("retry") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # Return represents using the +return+ keyword with arguments. @@ -8698,17 +7126,6 @@ def deconstruct_keys(keys) def format(q) FlowControlFormatter.new("return", self).format(q) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("return") - - q.breakable - q.pp(arguments) - - q.pp(Comment::List.new(comments)) - end - end end # Return0 represents the bare +return+ keyword with no arguments. @@ -8745,17 +7162,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("return0") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # RParen represents the use of a right parenthesis, i.e., +)+. @@ -8781,15 +7187,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("rparen") - - q.breakable - q.pp(value) - end - end end # SClass represents a block of statements that should be evaluated within the @@ -8845,20 +7242,6 @@ def format(q) q.breakable(force: true) end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("sclass") - - q.breakable - q.pp(target) - - q.breakable - q.pp(bodystmt) - - q.pp(Comment::List.new(comments)) - end - end end # Everything that has a block of code inside of it has a list of statements. @@ -8991,17 +7374,6 @@ def format(q) end end - def pretty_print(q) - q.group(2, "(", ")") do - q.text("statements") - - q.breakable - q.seplist(body) { |statement| q.pp(statement) } - - q.pp(Comment::List.new(comments)) - end - end - private # As efficiently as possible, gather up all of the comments that have been @@ -9064,15 +7436,6 @@ def child_nodes def deconstruct_keys(keys) { parts: parts, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("string_content") - - q.breakable - q.group(2, "(", ")") { q.seplist(parts) { |part| q.pp(part) } } - end - end end # StringConcat represents concatenating two strings together using a backward @@ -9122,20 +7485,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("string_concat") - - q.breakable - q.pp(left) - - q.breakable - q.pp(right) - - q.pp(Comment::List.new(comments)) - end - end end # StringDVar represents shorthand interpolation of a variable into a string. @@ -9176,17 +7525,6 @@ def format(q) q.format(variable) q.text("}") end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("string_dvar") - - q.breakable - q.pp(variable) - - q.pp(Comment::List.new(comments)) - end - end end # StringEmbExpr represents interpolated content. It can be contained within a @@ -9242,17 +7580,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("string_embexpr") - - q.breakable - q.pp(statements) - - q.pp(Comment::List.new(comments)) - end - end end # StringLiteral represents a string literal. @@ -9320,17 +7647,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("string_literal") - - q.breakable - q.group(2, "(", ")") { q.seplist(parts) { |part| q.pp(part) } } - - q.pp(Comment::List.new(comments)) - end - end end # Super represents using the +super+ keyword with arguments. It can optionally @@ -9377,17 +7693,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("super") - - q.breakable - q.pp(arguments) - - q.pp(Comment::List.new(comments)) - end - end end # SymBeg represents the beginning of a symbol literal. @@ -9428,16 +7733,7 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("symbeg") - - q.breakable - q.pp(value) - end - end - end + end # SymbolContent represents symbol contents and is always the child of a # SymbolLiteral node. @@ -9467,15 +7763,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("symbol_content") - - q.breakable - q.pp(value) - end - end end # SymbolLiteral represents a symbol in the system with no interpolation @@ -9515,17 +7802,6 @@ def format(q) q.text(":") q.format(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("symbol_literal") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # Symbols represents a symbol array literal with interpolation. @@ -9586,17 +7862,6 @@ def format(q) q.breakable("") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("symbols") - - q.breakable - q.group(2, "(", ")") { q.seplist(elements) { |element| q.pp(element) } } - - q.pp(Comment::List.new(comments)) - end - end end # SymbolsBeg represents the start of a symbol array literal with @@ -9629,15 +7894,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("symbols_beg") - - q.breakable - q.pp(value) - end - end end # TLambda represents the beginning of a lambda literal. @@ -9667,15 +7923,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("tlambda") - - q.breakable - q.pp(value) - end - end end # TLamBeg represents the beginning of the body of a lambda literal using @@ -9706,15 +7953,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("tlambeg") - - q.breakable - q.pp(value) - end - end end # TopConstField is always the child node of some kind of assignment. It @@ -9754,17 +7992,6 @@ def format(q) q.text("::") q.format(constant) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("top_const_field") - - q.breakable - q.pp(constant) - - q.pp(Comment::List.new(comments)) - end - end end # TopConstRef is very similar to TopConstField except that it is not involved @@ -9803,17 +8030,6 @@ def format(q) q.text("::") q.format(constant) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("top_const_ref") - - q.breakable - q.pp(constant) - - q.pp(Comment::List.new(comments)) - end - end end # TStringBeg represents the beginning of a string literal. @@ -9848,15 +8064,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("tstring_beg") - - q.breakable - q.pp(value) - end - end end # TStringContent represents plain characters inside of an entity that accepts @@ -9901,17 +8108,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("tstring_content") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # TStringEnd represents the end of a string literal. @@ -9946,15 +8142,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("tstring_end") - - q.breakable - q.pp(value) - end - end end # Not represents the unary +not+ method being called on an expression. @@ -10002,17 +8189,6 @@ def format(q) q.format(statement) q.text(")") if parentheses end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("not") - - q.breakable - q.pp(statement) - - q.pp(Comment::List.new(comments)) - end - end end # Unary represents a unary method being called on an expression, as in +!+ or @@ -10060,20 +8236,6 @@ def format(q) q.text(operator) q.format(statement) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("unary") - - q.breakable - q.pp(operator) - - q.breakable - q.pp(statement) - - q.pp(Comment::List.new(comments)) - end - end end # Undef represents the use of the +undef+ keyword. @@ -10139,17 +8301,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("undef") - - q.breakable - q.group(2, "(", ")") { q.seplist(symbols) { |symbol| q.pp(symbol) } } - - q.pp(Comment::List.new(comments)) - end - end end # Unless represents the first clause in an +unless+ chain. @@ -10207,25 +8358,6 @@ def deconstruct_keys(keys) def format(q) ConditionalFormatter.new("unless", self).format(q) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("unless") - - q.breakable - q.pp(predicate) - - q.breakable - q.pp(statements) - - if consequent - q.breakable - q.pp(consequent) - end - - q.pp(Comment::List.new(comments)) - end - end end # UnlessMod represents the modifier form of an +unless+ statement. @@ -10271,20 +8403,6 @@ def deconstruct_keys(keys) def format(q) ConditionalModFormatter.new("unless", self).format(q) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("unless_mod") - - q.breakable - q.pp(statement) - - q.breakable - q.pp(predicate) - - q.pp(Comment::List.new(comments)) - end - end end # Formats an Until, UntilMod, While, or WhileMod node. @@ -10391,20 +8509,6 @@ def format(q) LoopFormatter.new("until", self, statements).format(q) end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("until") - - q.breakable - q.pp(predicate) - - q.breakable - q.pp(statements) - - q.pp(Comment::List.new(comments)) - end - end end # UntilMod represents the modifier form of a +until+ loop. @@ -10470,20 +8574,6 @@ def format(q) LoopFormatter.new("until", self, statement).format(q) end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("until_mod") - - q.breakable - q.pp(statement) - - q.breakable - q.pp(predicate) - - q.pp(Comment::List.new(comments)) - end - end end # VarAlias represents when you're using the +alias+ keyword with global @@ -10530,20 +8620,6 @@ def format(q) q.text(" ") q.format(right) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("var_alias") - - q.breakable - q.pp(left) - - q.breakable - q.pp(right) - - q.pp(Comment::List.new(comments)) - end - end end # VarField represents a variable that is being assigned a value. As such, it @@ -10582,17 +8658,6 @@ def deconstruct_keys(keys) def format(q) q.format(value) if value end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("var_field") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # VarRef represents a variable reference. @@ -10633,17 +8698,6 @@ def deconstruct_keys(keys) def format(q) q.format(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("var_ref") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # PinnedVarRef represents a pinned variable reference within a pattern @@ -10688,17 +8742,6 @@ def format(q) q.format(value) end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("pinned_var_ref") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # VCall represent any plain named object with Ruby that could be either a @@ -10736,17 +8779,6 @@ def deconstruct_keys(keys) def format(q) q.format(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("vcall") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # VoidStmt represents an empty lexical block of code. @@ -10781,13 +8813,6 @@ def deconstruct_keys(keys) def format(q) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("void_stmt") - q.pp(Comment::List.new(comments)) - end - end end # When represents a +when+ clause in a +case+ chain. @@ -10880,25 +8905,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("when") - - q.breakable - q.pp(arguments) - - q.breakable - q.pp(statements) - - if consequent - q.breakable - q.pp(consequent) - end - - q.pp(Comment::List.new(comments)) - end - end end # While represents a +while+ loop. @@ -10956,20 +8962,6 @@ def format(q) LoopFormatter.new("while", self, statements).format(q) end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("while") - - q.breakable - q.pp(predicate) - - q.breakable - q.pp(statements) - - q.pp(Comment::List.new(comments)) - end - end end # WhileMod represents the modifier form of a +while+ loop. @@ -11035,20 +9027,6 @@ def format(q) LoopFormatter.new("while", self, statement).format(q) end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("while_mod") - - q.breakable - q.pp(statement) - - q.breakable - q.pp(predicate) - - q.pp(Comment::List.new(comments)) - end - end end # Word represents an element within a special array literal that accepts @@ -11093,17 +9071,6 @@ def deconstruct_keys(keys) def format(q) q.format_each(parts) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("word") - - q.breakable - q.group(2, "(", ")") { q.seplist(parts) { |part| q.pp(part) } } - - q.pp(Comment::List.new(comments)) - end - end end # Words represents a string literal array with interpolation. @@ -11164,17 +9131,6 @@ def format(q) q.breakable("") end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("words") - - q.breakable - q.group(2, "(", ")") { q.seplist(elements) { |element| q.pp(element) } } - - q.pp(Comment::List.new(comments)) - end - end end # WordsBeg represents the beginning of a string literal array with @@ -11207,15 +9163,6 @@ def child_nodes def deconstruct_keys(keys) { value: value, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("words_beg") - - q.breakable - q.pp(value) - end - end end # XString represents the contents of an XStringLiteral. @@ -11245,15 +9192,6 @@ def child_nodes def deconstruct_keys(keys) { parts: parts, location: location } end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("xstring") - - q.breakable - q.group(2, "(", ")") { q.seplist(parts) { |part| q.pp(part) } } - end - end end # XStringLiteral represents a string that gets executed. @@ -11293,17 +9231,6 @@ def format(q) q.format_each(parts) q.text("`") end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("xstring_literal") - - q.breakable - q.group(2, "(", ")") { q.seplist(parts) { |part| q.pp(part) } } - - q.pp(Comment::List.new(comments)) - end - end end # Yield represents using the +yield+ keyword with arguments. @@ -11354,17 +9281,6 @@ def format(q) end end end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("yield") - - q.breakable - q.pp(arguments) - - q.pp(Comment::List.new(comments)) - end - end end # Yield0 represents the bare +yield+ keyword with no arguments. @@ -11401,17 +9317,6 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("yield0") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end # ZSuper represents the bare +super+ keyword with no arguments. @@ -11448,16 +9353,5 @@ def deconstruct_keys(keys) def format(q) q.text(value) end - - def pretty_print(q) - q.group(2, "(", ")") do - q.text("zsuper") - - q.breakable - q.pp(value) - - q.pp(Comment::List.new(comments)) - end - end end end diff --git a/lib/syntax_tree/visitor.rb b/lib/syntax_tree/visitor.rb index 0ea66fb6..63227d03 100644 --- a/lib/syntax_tree/visitor.rb +++ b/lib/syntax_tree/visitor.rb @@ -123,7 +123,7 @@ def visit_child_nodes(node) alias visit_binary visit_child_nodes # Visit a BlockArg node. - alias visit_block_arg visit_child_nodes + alias visit_blockarg visit_child_nodes # Visit a BlockVar node. alias visit_block_var visit_child_nodes @@ -333,7 +333,7 @@ def visit_child_nodes(node) alias visit_op visit_child_nodes # Visit an OpAssign node. - alias visit_op_assign visit_child_nodes + alias visit_opassign visit_child_nodes # Visit a Params node. alias visit_params visit_child_nodes @@ -461,6 +461,12 @@ def visit_child_nodes(node) # Visit a TLamBeg node. alias visit_tlambeg visit_child_nodes + # Visit a TopConstField node. + alias visit_top_const_field visit_child_nodes + + # Visit a TopConstRef node. + alias visit_top_const_ref visit_child_nodes + # Visit a TStringBeg node. alias visit_tstring_beg visit_child_nodes @@ -470,12 +476,6 @@ def visit_child_nodes(node) # Visit a TStringEnd node. alias visit_tstring_end visit_child_nodes - # Visit a TopConstField node. - alias visit_top_const_field visit_child_nodes - - # Visit a TopConstRef node. - alias visit_top_const_ref visit_child_nodes - # Visit an Unary node. alias visit_unary visit_child_nodes diff --git a/lib/syntax_tree/visitor/json_visitor.rb b/lib/syntax_tree/visitor/json_visitor.rb new file mode 100644 index 00000000..9f0c8f94 --- /dev/null +++ b/lib/syntax_tree/visitor/json_visitor.rb @@ -0,0 +1,1335 @@ + # frozen_string_literal: true + +module SyntaxTree + class Visitor + class JSONVisitor < Visitor + def visit_aref(node) + { + type: :aref, + collection: visit(node.collection), + index: visit(node.index), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_aref_field(node) + { + type: :aref_field, + collection: visit(node.collection), + index: visit(node.index), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_alias(node) + { + type: :alias, + left: visit(node.left), + right: visit(node.right), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_arg_block(node) + { + type: :arg_block, + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_arg_paren(node) + { + type: :arg_paren, + args: visit(node.arguments), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_arg_star(node) + { + type: :arg_star, + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_args(node) + { + type: :args, + parts: visit_all(node.parts), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_args_forward(node) + visit_token(:args_forward, node) + end + + def visit_array(node) + { + type: :array, + cnts: visit(node.contents), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_aryptn(node) + { + type: :aryptn, + constant: visit(node.constant), + reqs: visit_all(node.requireds), + rest: visit(node.rest), + posts: visit_all(node.posts), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_assign(node) + { + type: :assign, + target: visit(node.target), + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_assoc(node) + { + type: :assoc, + key: visit(node.key), + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_assoc_splat(node) + { + type: :assoc_splat, + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_backref(node) + visit_token(:backref, node) + end + + def visit_backtick(node) + visit_token(:backtick, node) + end + + def visit_bare_assoc_hash(node) + { + type: :bare_assoc_hash, + assocs: visit_all(node.assocs), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_BEGIN(node) + { + type: :BEGIN, + lbrace: visit(node.lbrace), + stmts: visit(node.statements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_begin(node) + { + type: :begin, + bodystmt: visit(node.bodystmt), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_binary(node) + { + type: :binary, + left: visit(node.left), + op: node.operator, + right: visit(node.right), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_blockarg(node) + { + type: :blockarg, + name: visit(node.name), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_block_var(node) + { + type: :block_var, + params: visit(node.params), + locals: visit_all(node.locals), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_bodystmt(node) + { + type: :bodystmt, + stmts: visit(node.statements), + rsc: visit(node.rescue_clause), + els: visit(node.else_clause), + ens: visit(node.ensure_clause), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_brace_block(node) + { + type: :brace_block, + lbrace: visit(node.lbrace), + block_var: visit(node.block_var), + stmts: visit(node.statements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_break(node) + { + type: :break, + args: visit(node.arguments), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_call(node) + { + type: :call, + receiver: visit(node.receiver), + op: visit_call_operator(node.operator), + message: node.message == :call ? :call : visit(node.message), + args: visit(node.arguments), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_case(node) + { + type: :case, + value: visit(node.value), + cons: visit(node.consequent), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_CHAR(node) + visit_token(:CHAR, node) + end + + def visit_class(node) + { + type: :class, + constant: visit(node.constant), + superclass: visit(node.superclass), + bodystmt: visit(node.bodystmt), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_comma(node) + visit_token(:comma, node) + end + + def visit_command(node) + { + type: :command, + message: visit(node.message), + args: visit(node.arguments), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_command_call(node) + { + type: :command_call, + receiver: visit(node.receiver), + op: visit_call_operator(node.operator), + message: visit(node.message), + args: visit(node.arguments), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_comment(node) + { + type: :comment, + value: node.value, + inline: node.inline, + loc: visit_location(node.location) + } + end + + def visit_const(node) + visit_token(:const, node) + end + + def visit_const_path_field(node) + { + type: :const_path_field, + parent: visit(node.parent), + constant: visit(node.constant), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_const_path_ref(node) + { + type: :const_path_ref, + parent: visit(node.parent), + constant: visit(node.constant), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_const_ref(node) + { + type: :const_ref, + constant: visit(node.constant), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_cvar(node) + visit_token(:cvar, node) + end + + def visit_def(node) + { + type: :def, + name: visit(node.name), + params: visit(node.params), + bodystmt: visit(node.bodystmt), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_def_endless(node) + { + type: :def_endless, + name: visit(node.name), + paren: visit(node.paren), + stmt: visit(node.statement), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_defined(node) + visit_token(:defined, node) + end + + def visit_defs(node) + { + type: :defs, + target: visit(node.target), + op: visit(node.operator), + name: visit(node.name), + params: visit(node.params), + bodystmt: visit(node.bodystmt), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_do_block(node) + { + type: :do_block, + keyword: visit(node.keyword), + block_var: visit(node.block_var), + bodystmt: visit(node.bodystmt), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_dot2(node) + { + type: :dot2, + left: visit(node.left), + right: visit(node.right), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_dot3(node) + { + type: :dot3, + left: visit(node.left), + right: visit(node.right), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_dyna_symbol(node) + { + type: :dyna_symbol, + parts: visit_all(node.parts), + quote: node.quote, + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_END(node) + { + type: :END, + lbrace: visit(node.lbrace), + stmts: visit(node.statements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_else(node) + { + type: :else, + stmts: visit(node.statements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_elsif(node) + { + type: :elsif, + pred: visit(node.predicate), + stmts: visit(node.statements), + cons: visit(node.consequent), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_embdoc(node) + { + type: :embdoc, + value: node.value, + loc: visit_location(node.location) + } + end + + def visit_embexpr_beg(node) + { + type: :embexpr_beg, + value: node.value, + loc: visit_location(node.location) + } + end + + def visit_embexpr_end(node) + { + type: :embexpr_end, + value: node.value, + loc: visit_location(node.location) + } + end + + def visit_embvar(node) + { + type: :embvar, + value: node.value, + loc: visit_location(node.location) + } + end + + def visit_ensure(node) + { + type: :ensure, + keyword: visit(node.keyword), + stmts: visit(node.statements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_excessed_comma(node) + visit_token(:excessed_comma, node) + end + + def visit_fcall(node) + { + type: :fcall, + value: visit(node.value), + args: visit(node.arguments), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_field(node) + { + type: :field, + parent: visit(node.parent), + op: visit_call_operator(node.operator), + name: visit(node.name), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_float(node) + visit_token(:float, node) + end + + def visit_fndptn(node) + { + type: :fndptn, + constant: visit(node.constant), + left: visit(node.left), + values: visit_all(node.values), + right: visit(node.right), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_for(node) + { + type: :for, + index: visit(node.index), + collection: visit(node.collection), + stmts: visit(node.statements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_gvar(node) + visit_token(:gvar, node) + end + + def visit_hash(node) + { + type: :hash, + assocs: visit_all(node.assocs), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_heredoc(node) + { + type: :heredoc, + beging: visit(node.beginning), + ending: node.ending, + parts: visit_all(node.parts), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_heredoc_beg(node) + visit_token(:heredoc_beg, node) + end + + def visit_hshptn(node) + { + type: :hshptn, + constant: visit(node.constant), + keywords: node.keywords.map { |(name, value)| [visit(name), visit(value)] }, + kwrest: visit(node.keyword_rest), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_ident(node) + visit_token(:ident, node) + end + + def visit_if(node) + { + type: :if, + pred: visit(node.predicate), + stmts: visit(node.statements), + cons: visit(node.consequent), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_if_mod(node) + { + type: :if_mod, + stmt: visit(node.statement), + pred: visit(node.predicate), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_if_op(node) + { + type: :ifop, + pred: visit(node.predicate), + tthy: visit(node.truthy), + flsy: visit(node.falsy), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_imaginary(node) + visit_token(:imaginary, node) + end + + def visit_in(node) + { + type: :in, + pattern: visit(node.pattern), + stmts: visit(node.statements), + cons: visit(node.consequent), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_int(node) + visit_token(:int, node) + end + + def visit_ivar(node) + visit_token(:ivar, node) + end + + def visit_kw(node) + visit_token(:kw, node) + end + + def visit_kwrest_param(node) + { + type: :kwrest_param, + name: visit(node.name), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_label(node) + visit_token(:label, node) + end + + def visit_label_end(node) + visit_token(:label_end, node) + end + + def visit_lambda(node) + { + type: :lambda, + params: visit(node.params), + stmts: visit(node.statements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_lbrace(node) + visit_token(:lbrace, node) + end + + def visit_lbracket(node) + visit_token(:lbracket, node) + end + + def visit_lparen(node) + visit_token(:lparen, node) + end + + def visit_massign(node) + { + type: :massign, + target: visit(node.target), + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_method_add_block(node) + { + type: :method_add_block, + call: visit(node.call), + block: visit(node.block), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_mlhs(node) + { + type: :mlhs, + parts: visit_all(node.parts), + comma: node.comma, + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_mlhs_paren(node) + { + type: :mlhs_paren, + cnts: visit(node.contents), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_module(node) + { + type: :module, + constant: visit(node.constant), + bodystmt: visit(node.bodystmt), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_mrhs(node) + { + type: :mrhs, + parts: visit_all(node.parts), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_next(node) + { + type: :next, + args: visit(node.arguments), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_not(node) + { + type: :not, + value: visit(node.statement), + paren: node.parentheses, + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_op(node) + visit_token(:op, node) + end + + def visit_opassign(node) + { + type: :opassign, + target: visit(node.target), + op: visit(node.operator), + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_params(node) + { + type: :params, + reqs: visit_all(node.requireds), + opts: node.optionals.map { |(name, value)| [visit(name), visit(value)] }, + rest: visit(node.rest), + posts: visit_all(node.posts), + keywords: node.keywords.map { |(name, value)| [visit(name), visit(value || nil)] }, + kwrest: node.keyword_rest == :nil ? "nil" : visit(node.keyword_rest), + block: visit(node.block), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_paren(node) + { + type: :paren, + lparen: visit(node.lparen), + cnts: visit(node.contents), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_period(node) + visit_token(:period, node) + end + + def visit_pinned_begin(node) + { + type: :pinned_begin, + stmt: visit(node.statement), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_pinned_var_ref(node) + { + type: :pinned_var_ref, + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_program(node) + { + type: :program, + stmts: visit(node.statements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_qsymbols(node) + { + type: :qsymbols, + elems: visit_all(node.elements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_qsymbols_beg(node) + visit_token(:qsymbols_beg, node) + end + + def visit_qwords(node) + { + type: :qwords, + elems: visit_all(node.elements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_qwords_beg(node) + visit_token(:qwords_beg, node) + end + + def visit_rassign(node) + { + type: :rassign, + value: visit(node.value), + op: visit(node.operator), + pattern: visit(node.pattern), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_rational(node) + visit_token(:rational, node) + end + + def visit_rbrace(node) + visit_token(:rbrace, node) + end + + def visit_rbracket(node) + visit_token(:rbracket, node) + end + + def visit_redo(node) + visit_token(:redo, node) + end + + def visit_regexp_beg(node) + visit_token(:regexp_beg, node) + end + + def visit_regexp_content(node) + { + type: :regexp_content, + beging: node.beginning, + parts: visit_all(node.parts), + loc: visit_location(node.location) + } + end + + def visit_regexp_end(node) + visit_token(:regexp_end, node) + end + + def visit_regexp_literal(node) + { + type: :regexp_literal, + beging: node.beginning, + ending: node.ending, + parts: visit_all(node.parts), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_rescue(node) + { + type: :rescue, + extn: visit(node.exception), + stmts: visit(node.statements), + cons: visit(node.consequent), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_rescue_ex(node) + { + type: :rescue_ex, + extns: visit(node.exceptions), + var: visit(node.variable), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_rescue_mod(node) + { + type: :rescue_mod, + stmt: visit(node.statement), + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_rest_param(node) + { + type: :rest_param, + name: visit(node.name), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_retry(node) + visit_token(:retry, node) + end + + def visit_return(node) + { + type: :return, + args: visit(node.arguments), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_return0(node) + visit_token(:return0, node) + end + + def visit_rparen(node) + visit_token(:rparen, node) + end + + def visit_sclass(node) + { + type: :sclass, + target: visit(node.target), + bodystmt: visit(node.bodystmt), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_statements(node) + { + type: :statements, + body: visit_all(node.body), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_string_concat(node) + { + type: :string_concat, + left: visit(node.left), + right: visit(node.right), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_string_content(node) + { + type: :string_content, + parts: visit_all(node.parts), + loc: visit_location(node.location) + } + end + + def visit_string_dvar(node) + { + type: :string_dvar, + var: visit(node.variable), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_string_embexpr(node) + { + type: :string_embexpr, + stmts: visit(node.statements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_string_literal(node) + { + type: :string_literal, + parts: visit_all(node.parts), + quote: node.quote, + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_super(node) + { + type: :super, + args: visit(node.arguments), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_symbeg(node) + visit_token(:symbeg, node) + end + + def visit_symbol_content(node) + { + type: :symbol_content, + value: visit(node.value), + loc: visit_location(node.location) + } + end + + def visit_symbol_literal(node) + { + type: :symbol_literal, + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_symbols(node) + { + type: :symbols, + elems: visit_all(node.elements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_symbols_beg(node) + visit_token(:symbols_beg, node) + end + + def visit_tlambda(node) + visit_token(:tlambda, node) + end + + def visit_tlambeg(node) + visit_token(:tlambeg, node) + end + + def visit_top_const_field(node) + { + type: :top_const_field, + constant: visit(node.constant), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_top_const_ref(node) + { + type: :top_const_ref, + constant: visit(node.constant), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_tstring_beg(node) + visit_token(:tstring_beg, node) + end + + def visit_tstring_content(node) + visit_token(:tstring_content, node) + end + + def visit_tstring_end(node) + visit_token(:tstring_end, node) + end + + def visit_unary(node) + { + type: :unary, + op: node.operator, + value: visit(node.statement), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_undef(node) + { + type: :undef, + syms: visit_all(node.symbols), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_unless(node) + { + type: :unless, + pred: visit(node.predicate), + stmts: visit(node.statements), + cons: visit(node.consequent), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_unless_mod(node) + { + type: :unless_mod, + stmt: visit(node.statement), + pred: visit(node.predicate), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_until(node) + { + type: :until, + pred: visit(node.predicate), + stmts: visit(node.statements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_until_mod(node) + { + type: :until_mod, + stmt: visit(node.statement), + pred: visit(node.predicate), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_var_alias(node) + { + type: :var_alias, + left: visit(node.left), + right: visit(node.right), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_var_field(node) + { + type: :var_field, + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_var_ref(node) + { + type: :var_ref, + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_vcall(node) + { + type: :vcall, + value: visit(node.value), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_void_stmt(node) + { + type: :void_stmt, + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_when(node) + { + type: :when, + args: visit(node.arguments), + stmts: visit(node.statements), + cons: visit(node.consequent), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_while(node) + { + type: :while, + pred: visit(node.predicate), + stmts: visit(node.statements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_while_mod(node) + { + type: :while_mod, + stmt: visit(node.statement), + pred: visit(node.predicate), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_word(node) + { + type: :word, + parts: visit_all(node.parts), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_words(node) + { + type: :words, + elems: visit_all(node.elements), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_words_beg(node) + visit_token(:words_beg, node) + end + + def visit_xstring(node) + { + type: :xstring, + parts: visit_all(node.parts), + loc: visit_location(node.location) + } + end + + def visit_xstring_literal(node) + { + type: :xstring_literal, + parts: visit_all(node.parts), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_yield(node) + { + type: :yield, + args: visit(node.arguments), + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + + def visit_yield0(node) + visit_token(:yield0, node) + end + + def visit_zsuper(node) + visit_token(:zsuper, node) + end + + def visit___end__(node) + visit_token(:__end__, node) + end + + private + + def visit_call_operator(operator) + operator == :"::" ? :"::" : visit(operator) + end + + def visit_location(location) + [ + location.start_line, + location.start_char, + location.end_line, + location.end_char + ] + end + + def visit_token(type, node) + { + type: type, + value: node.value, + loc: visit_location(node.location), + cmts: visit_all(node.comments) + } + end + end + end +end diff --git a/lib/syntax_tree/visitor/pretty_print_visitor.rb b/lib/syntax_tree/visitor/pretty_print_visitor.rb new file mode 100644 index 00000000..40420a15 --- /dev/null +++ b/lib/syntax_tree/visitor/pretty_print_visitor.rb @@ -0,0 +1,1213 @@ + # frozen_string_literal: true + +module SyntaxTree + class Visitor + class PrettyPrintVisitor < Visitor + attr_reader :q + + def initialize(q) + @q = q + end + + def visit_aref(node) + node("aref") do + field("collection", node.collection) + field("index", node.index) + comments(node) + end + end + + def visit_aref_field(node) + node("aref_field") do + field("collection", node.collection) + field("index", node.index) + comments(node) + end + end + + def visit_alias(node) + node("alias") do + field("left", node.left) + field("right", node.right) + comments(node) + end + end + + def visit_arg_block(node) + node("arg_block") do + field("value", node.value) if node.value + comments(node) + end + end + + def visit_arg_paren(node) + node("arg_paren") do + field("arguments", node.arguments) + comments(node) + end + end + + def visit_arg_star(node) + node("arg_star") do + field("value", node.value) + comments(node) + end + end + + def visit_args(node) + node("args") do + list("parts", node.parts) + comments(node) + end + end + + def visit_args_forward(node) + visit_token("args_forward", node) + end + + def visit_array(node) + node("array") do + field("contents", node.contents) + comments(node) + end + end + + def visit_aryptn(node) + node("aryptn") do + field("constant", node.constant) if node.constant + list("requireds", node.requireds) if node.requireds.any? + field("rest", node.rest) if node.rest + list("posts", node.posts) if node.posts.any? + comments(node) + end + end + + def visit_assign(node) + node("assign") do + field("target", node.target) + field("value", node.value) + comments(node) + end + end + + def visit_assoc(node) + node("assoc") do + field("key", node.key) + field("value", node.value) if node.value + comments(node) + end + end + + def visit_assoc_splat(node) + node("assoc_splat") do + field("value", node.value) + comments(node) + end + end + + def visit_backref(node) + visit_token("backref", node) + end + + def visit_backtick(node) + visit_token("backtick", node) + end + + def visit_bare_assoc_hash(node) + node("bare_assoc_hash") do + list("assocs", node.assocs) + comments(node) + end + end + + def visit_BEGIN(node) + node("BEGIN") do + field("statements", node.statements) + comments(node) + end + end + + def visit_begin(node) + node("begin") do + field("bodystmt", node.bodystmt) + comments(node) + end + end + + def visit_binary(node) + node("binary") do + field("left", node.left) + text("operator", node.operator) + field("right", node.right) + comments(node) + end + end + + def visit_blockarg(node) + node("blockarg") do + field("name", node.name) if node.name + comments(node) + end + end + + def visit_block_var(node) + node("block_var") do + field("params", node.params) + list("locals", node.locals) if node.locals.any? + comments(node) + end + end + + def visit_bodystmt(node) + node("bodystmt") do + field("statements", node.statements) + field("rescue_clause", node.rescue_clause) if node.rescue_clause + field("else_clause", node.else_clause) if node.else_clause + field("ensure_clause", node.ensure_clause) if node.ensure_clause + comments(node) + end + end + + def visit_brace_block(node) + node("brace_block") do + field("block_var", node.block_var) if node.block_var + field("statements", node.statements) + comments(node) + end + end + + def visit_break(node) + node("break") do + field("arguments", node.arguments) + comments(node) + end + end + + def visit_call(node) + node("call") do + field("receiver", node.receiver) + field("operator", node.operator) + field("message", node.message) + field("arguments", node.arguments) if node.arguments + comments(node) + end + end + + def visit_case(node) + node("case") do + field("keyword", node.keyword) + field("value", node.value) if node.value + field("consequent", node.consequent) + comments(node) + end + end + + def visit_CHAR(node) + visit_token("CHAR", node) + end + + def visit_class(node) + node("class") do + field("constant", node.constant) + field("superclass", node.superclass) if node.superclass + field("bodystmt", node.bodystmt) + comments(node) + end + end + + def visit_comma(node) + node("comma") do + field("value", node) + end + end + + def visit_command(node) + node("command") do + field("message", node.message) + field("arguments", node.arguments) + comments(node) + end + end + + def visit_command_call(node) + node("command_call") do + field("receiver", node.receiver) + field("operator", node.operator) + field("message", node.message) + field("arguments", node.arguments) if node.arguments + comments(node) + end + end + + def visit_comment(node) + node("comment") do + field("value", node.value) + end + end + + def visit_const(node) + visit_token("const", node) + end + + def visit_const_path_field(node) + node("const_path_field") do + field("parent", node.parent) + field("constant", node.constant) + comments(node) + end + end + + def visit_const_path_ref(node) + node("const_path_ref") do + field("parent", node.parent) + field("constant", node.constant) + comments(node) + end + end + + def visit_const_ref(node) + node("const_ref") do + field("constant", node.constant) + comments(node) + end + end + + def visit_cvar(node) + visit_token("cvar", node) + end + + def visit_def(node) + node("def") do + field("name", node.name) + field("params", node.params) + field("bodystmt", node.bodystmt) + comments(node) + end + end + + def visit_def_endless(node) + node("def_endless") do + if node.target + field("target", node.target) + field("operator", node.operator) + end + + field("name", node.name) + field("paren", node.paren) if node.paren + field("statement", node.statement) + comments(node) + end + end + + def visit_defined(node) + node("defined") do + field("value", node.value) + comments(node) + end + end + + def visit_defs(node) + node("defs") do + field("target", node.target) + field("operator", node.operator) + field("name", node.name) + field("params", node.params) + field("bodystmt", node.bodystmt) + comments(node) + end + end + + def visit_do_block(node) + node("do_block") do + field("block_var", node.block_var) if node.block_var + field("bodystmt", node.bodystmt) + comments(node) + end + end + + def visit_dot2(node) + node("dot2") do + field("left", node.left) if node.left + field("right", node.right) if node.right + comments(node) + end + end + + def visit_dot3(node) + node("dot3") do + field("left", node.left) if node.left + field("right", node.right) if node.right + comments(node) + end + end + + def visit_dyna_symbol(node) + node("dyna_symbol") do + list("parts", node.parts) + comments(node) + end + end + + def visit_END(node) + node("END") do + field("statements", node.statements) + comments(node) + end + end + + def visit_else(node) + node("else") do + field("statements", node.statements) + comments(node) + end + end + + def visit_elsif(node) + node("elsif") do + field("predicate", node.predicate) + field("statements", node.statements) + field("consequent", node.consequent) if node.consequent + comments(node) + end + end + + def visit_embdoc(node) + node("embdoc") do + field("value", node.value) + end + end + + def visit_embexpr_beg(node) + node("embexpr_beg") do + field("value", node.value) + end + end + + def visit_embexpr_end(node) + node("embexpr_end") do + field("value", node.value) + end + end + + def visit_embvar(node) + node("embvar") do + field("value", node.value) + end + end + + def visit_ensure(node) + node("ensure") do + field("statements", node.statements) + comments(node) + end + end + + def visit_excessed_comma(node) + visit_token("excessed_comma", node) + end + + def visit_fcall(node) + node("fcall") do + field("value", node.value) + field("arguments", node.arguments) if node.arguments + comments(node) + end + end + + def visit_field(node) + node("field") do + field("parent", node.parent) + field("operator", node.operator) + field("name", node.name) + comments(node) + end + end + + def visit_float(node) + visit_token("float", node) + end + + def visit_fndptn(node) + node("fndptn") do + field("constant", node.constant) if node.constant + field("left", node.left) + list("values", node.values) + field("right", node.right) + comments(node) + end + end + + def visit_for(node) + node("for") do + field("index", node.index) + field("collection", node.collection) + field("statements", node.statements) + comments(node) + end + end + + def visit_gvar(node) + visit_token("gvar", node) + end + + def visit_hash(node) + node("hash") do + list("assocs", node.assocs) if node.assocs.any? + comments(node) + end + end + + def visit_heredoc(node) + node("heredoc") do + list("parts", node.parts) + comments(node) + end + end + + def visit_heredoc_beg(node) + visit_token("heredoc_beg", node) + end + + def visit_hshptn(node) + node("hshptn") do + field("constant", node.constant) if node.constant + + if node.keywords.any? + q.breakable + q.group(2, "(", ")") do + q.seplist(node.keywords) do |(key, value)| + q.group(2, "(", ")") do + key.pretty_print(q) + + if value + q.breakable + value.pretty_print(q) + end + end + end + end + end + + field("keyword_rest", node.keyword_rest) if node.keyword_rest + comments(node) + end + end + + def visit_ident(node) + visit_token("ident", node) + end + + def visit_if(node) + node("if") do + field("predicate", node.predicate) + field("statements", node.statements) + field("consequent", node.consequent) if node.consequent + comments(node) + end + end + + def visit_if_mod(node) + node("if_mod") do + field("statement", node.statement) + field("predicate", node.predicate) + comments(node) + end + end + + def visit_if_op(node) + node("ifop") do + field("predicate", node.predicate) + field("truthy", node.truthy) + field("falsy", node.falsy) + comments(node) + end + end + + def visit_imaginary(node) + visit_token("imaginary", node) + end + + def visit_in(node) + node("in") do + field("pattern", node.pattern) + field("statements", node.statements) + field("consequent", node.consequent) if node.consequent + comments(node) + end + end + + def visit_int(node) + visit_token("int", node) + end + + def visit_ivar(node) + visit_token("ivar", node) + end + + def visit_kw(node) + visit_token("kw", node) + end + + def visit_kwrest_param(node) + node("kwrest_param") do + field("name", node.name) + comments(node) + end + end + + def visit_label(node) + node("label") do + q.breakable + q.text(":") + q.text(node.value[0...-1]) + comments(node) + end + end + + def visit_label_end(node) + node("label_end") do + field("value", node.value) + end + end + + def visit_lambda(node) + node("lambda") do + field("params", node.params) + field("statements", node.statements) + comments(node) + end + end + + def visit_lbrace(node) + visit_token("lbrace", node) + end + + def visit_lbracket(node) + visit_token("lbracket", node) + end + + def visit_lparen(node) + visit_token("lparen", node) + end + + def visit_massign(node) + node("massign") do + field("target", node.target) + field("value", node.value) + comments(node) + end + end + + def visit_method_add_block(node) + node("method_add_block") do + field("call", node.call) + field("block", node.block) + comments(node) + end + end + + def visit_mlhs(node) + node("mlhs") do + list("parts", node.parts) + comments(node) + end + end + + def visit_mlhs_paren(node) + node("mlhs_paren") do + field("contents", node.contents) + comments(node) + end + end + + def visit_module(node) + node("module") do + field("constant", node.constant) + field("bodystmt", node.bodystmt) + comments(node) + end + end + + def visit_mrhs(node) + node("mrhs") do + list("parts", node.parts) + comments(node) + end + end + + def visit_next(node) + node("next") do + field("arguments", node.arguments) + comments(node) + end + end + + def visit_not(node) + node("not") do + field("statement", node.statement) + comments(node) + end + end + + def visit_op(node) + visit_token("op", node) + end + + def visit_opassign(node) + node("opassign") do + field("target", node.target) + field("operator", node.operator) + field("value", node.value) + comments(node) + end + end + + def visit_params(node) + node("params") do + list("requireds", node.requireds) if node.requireds.any? + + if node.optionals.any? + q.breakable + q.group(2, "(", ")") do + q.seplist(node.optionals) do |(name, default)| + name.pretty_print(q) + q.text("=") + q.group(2) do + q.breakable("") + default.pretty_print(q) + end + end + end + end + + field("rest", node.rest) if node.rest + list("posts", node.posts) if node.posts.any? + + if node.keywords.any? + q.breakable + q.group(2, "(", ")") do + q.seplist(node.keywords) do |(name, default)| + name.pretty_print(q) + + if default + q.text("=") + q.group(2) do + q.breakable("") + default.pretty_print(q) + end + end + end + end + end + + field("keyword_rest", node.keyword_rest) if node.keyword_rest + field("block", node.block) if node.block + comments(node) + end + end + + def visit_paren(node) + node("paren") do + field("contents", node.contents) + comments(node) + end + end + + def visit_period(node) + visit_token("period", node) + end + + def visit_pinned_begin(node) + node("pinned_begin") do + field("statement", node.statement) + comments(node) + end + end + + def visit_pinned_var_ref(node) + node("pinned_var_ref") do + field("value", node.value) + comments(node) + end + end + + def visit_program(node) + node("program") do + field("statements", node.statements) + comments(node) + end + end + + def visit_qsymbols(node) + node("qsymbols") do + list("elements", node.elements) + comments(node) + end + end + + def visit_qsymbols_beg(node) + node("qsymbols_beg") do + field("value", node.value) + end + end + + def visit_qwords(node) + node("qwords") do + list("elements", node.elements) + comments(node) + end + end + + def visit_qwords_beg(node) + node("qwords_beg") do + field("value", node.value) + end + end + + def visit_rassign(node) + node("rassign") do + field("value", node.value) + field("operator", node.operator) + field("pattern", node.pattern) + comments(node) + end + end + + def visit_rational(node) + visit_token("rational", node) + end + + def visit_rbrace(node) + node("rbrace") do + field("value", node.value) + end + end + + def visit_rbracket(node) + node("rbracket") do + field("value", node.value) + end + end + + def visit_redo(node) + visit_token("redo", node) + end + + def visit_regexp_beg(node) + node("regexp_beg") do + field("value", node.value) + end + end + + def visit_regexp_content(node) + node("regexp_content") do + list("parts", node.parts) + end + end + + def visit_regexp_end(node) + node("regexp_end") do + field("value", node.value) + end + end + + def visit_regexp_literal(node) + node("regexp_literal") do + list("parts", node.parts) + comments(node) + end + end + + def visit_rescue(node) + node("rescue") do + field("exception", node.exception) if node.exception + field("statements", node.statements) + field("consequent", node.consequent) if node.consequent + comments(node) + end + end + + def visit_rescue_ex(node) + node("rescue_ex") do + field("exceptions", node.exceptions) + field("variable", node.variable) + comments(node) + end + end + + def visit_rescue_mod(node) + node("rescue_mod") do + field("statement", node.statement) + field("value", node.value) + comments(node) + end + end + + def visit_rest_param(node) + node("rest_param") do + field("name", node.name) + comments(node) + end + end + + def visit_retry(node) + visit_token("retry", node) + end + + def visit_return(node) + node("return") do + field("arguments", node.arguments) + comments(node) + end + end + + def visit_return0(node) + visit_token("return0", node) + end + + def visit_rparen(node) + node("rparen") do + field("value", node.value) + end + end + + def visit_sclass(node) + node("sclass") do + field("target", node.target) + field("bodystmt", node.bodystmt) + comments(node) + end + end + + def visit_statements(node) + node("statements") do + list("body", node.body) + comments(node) + end + end + + def visit_string_concat(node) + node("string_concat") do + field("left", node.left) + field("right", node.right) + comments(node) + end + end + + def visit_string_content(node) + node("string_content") do + list("parts", node.parts) + end + end + + def visit_string_dvar(node) + node("string_dvar") do + field("variable", node.variable) + comments(node) + end + end + + def visit_string_embexpr(node) + node("string_embexpr") do + field("statements", node.statements) + comments(node) + end + end + + def visit_string_literal(node) + node("string_literal") do + list("parts", node.parts) + comments(node) + end + end + + def visit_super(node) + node("super") do + field("arguments", node.arguments) + comments(node) + end + end + + def visit_symbeg(node) + node("symbeg") do + field("value", node.value) + end + end + + def visit_symbol_content(node) + node("symbol_content") do + field("value", node.value) + end + end + + def visit_symbol_literal(node) + node("symbol_literal") do + field("value", node.value) + comments(node) + end + end + + def visit_symbols(node) + node("symbols") do + list("elements", node.elements) + comments(node) + end + end + + def visit_symbols_beg(node) + node("symbols_beg") do + field("value", node.value) + end + end + + def visit_tlambda(node) + node("tlambda") do + field("value", node.value) + end + end + + def visit_tlambeg(node) + node("tlambeg") do + field("value", node.value) + end + end + + def visit_top_const_field(node) + node("top_const_field") do + field("constant", node.constant) + comments(node) + end + end + + def visit_top_const_ref(node) + node("top_const_ref") do + field("constant", node.constant) + comments(node) + end + end + + def visit_tstring_beg(node) + node("tstring_beg") do + field("value", node.value) + end + end + + def visit_tstring_content(node) + visit_token("tstring_content", node) + end + + def visit_tstring_end(node) + node("tstring_end") do + field("value", node.value) + end + end + + def visit_unary(node) + node("unary") do + field("operator", node.operator) + field("statement", node.statement) + comments(node) + end + end + + def visit_undef(node) + node("undef") do + list("symbols", node.symbols) + comments(node) + end + end + + def visit_unless(node) + node("unless") do + field("predicate", node.predicate) + field("statements", node.statements) + field("consequent", node.consequent) if node.consequent + comments(node) + end + end + + def visit_unless_mod(node) + node("unless_mod") do + field("statement", node.statement) + field("predicate", node.predicate) + comments(node) + end + end + + def visit_until(node) + node("until") do + field("predicate", node.predicate) + field("statements", node.statements) + comments(node) + end + end + + def visit_until_mod(node) + node("until_mod") do + field("statement", node.statement) + field("predicate", node.predicate) + comments(node) + end + end + + def visit_var_alias(node) + node("var_alias") do + field("left", node.left) + field("right", node.right) + comments(node) + end + end + + def visit_var_field(node) + node("var_field") do + field("value", node.value) + comments(node) + end + end + + def visit_var_ref(node) + node("var_ref") do + field("value", node.value) + comments(node) + end + end + + def visit_vcall(node) + node("vcall") do + field("value", node.value) + comments(node) + end + end + + def visit_void_stmt(node) + node("void_stmt") do + comments(node) + end + end + + def visit_when(node) + node("when") do + field("arguments", node.arguments) + field("statements", node.statements) + field("consequent", node.consequent) if node.consequent + comments(node) + end + end + + def visit_while(node) + node("while") do + field("predicate", node.predicate) + field("statements", node.statements) + comments(node) + end + end + + def visit_while_mod(node) + node("while_mod") do + field("statement", node.statement) + field("predicate", node.predicate) + comments(node) + end + end + + def visit_word(node) + node("word") do + list("parts", node.parts) + comments(node) + end + end + + def visit_words(node) + node("words") do + list("elements", node.elements) + comments(node) + end + end + + def visit_words_beg(node) + node("words_beg") do + field("value", node.value) + end + end + + def visit_xstring(node) + node("xstring") do + list("parts", node.parts) + end + end + + def visit_xstring_literal(node) + node("xstring_literal") do + list("parts", node.parts) + comments(node) + end + end + + def visit_yield(node) + node("yield") do + field("arguments", node.arguments) + comments(node) + end + end + + def visit_yield0(node) + visit_token("yield0", node) + end + + def visit_zsuper(node) + visit_token("zsuper", node) + end + + def visit___end__(node) + visit_token("__end__", node) + end + + private + + def comments(node) + return if node.comments.empty? + + q.breakable + q.group(2, "(", ")") do + q.seplist(node.comments) { |comment| comment.pretty_print(q) } + end + end + + def field(_name, value) + q.breakable + + # I don't entirely know why this is necessary, but in Ruby 2.7 there is + # an issue with calling q.pp on strings that somehow involves inspect + # keys. I'm purposefully avoiding the inspect key stuff here because I + # know the tree does not contain any cycles. + value.is_a?(String) ? q.text(value.inspect) : value.pretty_print(q) + end + + def list(_name, values) + q.breakable + q.group(2, "(", ")") do + q.seplist(values) { |value| value.pretty_print(q) } + end + end + + def node(type) + q.group(2, "(", ")") do + q.text(type) + yield + end + end + + def text(_name, value) + q.breakable + q.text(value) + end + + def visit_token(type, node) + node(type) do + field("value", node.value) + comments(node) + end + end + end + end +end diff --git a/test/pretty_print_visitor_test.rb b/test/pretty_print_visitor_test.rb new file mode 100644 index 00000000..8ca7cdf8 --- /dev/null +++ b/test/pretty_print_visitor_test.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require_relative "test_helper" + +module SyntaxTree + class PrettyPrintVisitorTest < Minitest::Test + Fixtures.each_fixture do |fixture| + define_method(:"test_pretty_print_#{fixture.name}") do + formatter = PP.new([]) + + program = SyntaxTree.parse(fixture.source) + program.pretty_print(formatter) + + formatter.flush + refute_includes(formatter.output.join, "#<") + end + end + end +end