Skip to content

Blocks cannot be formatted when they're top-level nodes #163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kkuchta opened this issue Sep 29, 2022 · 1 comment
Closed

Blocks cannot be formatted when they're top-level nodes #163

kkuchta opened this issue Sep 29, 2022 · 1 comment

Comments

@kkuchta
Copy link

kkuchta commented Sep 29, 2022

If you parse a string like foo = bar { |x| x + 1 }, then traverse it down to the block node ({ |x| x + 1 }), trying to format that node throws an error. Here's a repro case:

require 'syntax_tree'

# Create a node visitor that walks the syntax tree looking for blocks.
class BlockFinder < SyntaxTree::Visitor
  attr_reader :first_block
  visit_method def visit_do_block(node)
    puts "found a brace block node!"
    @first_block ||= node
    # Don't traverse further
  end
  visit_method def visit_brace_block(node)
    puts "found a brace block node!"
    @first_block ||= node
    # Don't traverse further
  end
end

input_string = "foo = bar() { |x| x + 1}"
root = SyntaxTree.parse(input_string)

# use that visitor to find the first, outermost block
visitor = BlockFinder.new
visitor.visit(root)
block_node = visitor.first_block

formatter = SyntaxTree::Formatter.new(input_string, [], 80)

# !!! This throws an error:
# /Users/kevin/.rvm/gems/ruby-3.0.0/gems/syntax_tree-3.6.0/lib/syntax_tree/node.rb:1990:in `forced_do_end_bounds?': undefined method `call' for nil:NilClass
formatter.format(block_node)

# But if I comment that line out and then fake that this block node is nested
# within a parent node, it works:
formatter.instance_variable_set(:@stack, [proc {SyntaxTree::Program.new(statements: [], location: nil)}])
formatter.format(block_node)

formatter.flush
output_string = formatter.output.join
puts output_string # Prints  { |x| x + 1 }

The issue seems to be that forced_do_end_bounds in BlockFormatter inspects the parent node and doesn't handle when it doesn't exist.

PS: thanks for the great tool and, honestly, the very readable source!

@kddnewton
Copy link
Member

Fixed by #166

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants