Class: SyntaxTree::Statements

Inherits:
Node
  • Object
show all
Defined in:
lib/syntax_tree/node.rb

Overview

Everything that has a block of code inside of it has a list of statements. Normally we would just track those as a node that has an array body, but we have some special handling in order to handle empty statement lists. They need to have the right location information, so all of the parent node of stmts nodes will report back down the location information. We then propagate that onto void_stmt nodes inside the stmts in order to make sure all comments get printed appropriately.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parser, body:, location:, comments: []) ⇒ Statements

Returns a new instance of Statements.



9363
9364
9365
9366
9367
9368
# File 'lib/syntax_tree/node.rb', line 9363

def initialize(parser, body:, location:, comments: [])
  @parser = parser
  @body = body
  @location = location
  @comments = comments
end

Instance Attribute Details

#bodyObject (readonly)

Array[ untyped ]

the list of expressions contained within this node



9355
9356
9357
# File 'lib/syntax_tree/node.rb', line 9355

def body
  @body
end

#commentsObject (readonly)

Array[ Comment | EmbDoc ]

the comments attached to this node



9361
9362
9363
# File 'lib/syntax_tree/node.rb', line 9361

def comments
  @comments
end

#locationObject (readonly)

Location

the location of this node



9358
9359
9360
# File 'lib/syntax_tree/node.rb', line 9358

def location
  @location
end

#parserObject (readonly)

SyntaxTree

the parser that is generating this node



9352
9353
9354
# File 'lib/syntax_tree/node.rb', line 9352

def parser
  @parser
end

Instance Method Details

#bind(start_char, end_char) ⇒ Object



9370
9371
9372
9373
9374
9375
9376
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386
9387
9388
9389
9390
9391
9392
9393
# File 'lib/syntax_tree/node.rb', line 9370

def bind(start_char, end_char)
  @location =
    Location.new(
      start_line: location.start_line,
      start_char: start_char,
      end_line: location.end_line,
      end_char: end_char
    )

  if body[0].is_a?(VoidStmt)
    location = body[0].location
    location =
      Location.new(
        start_line: location.start_line,
        start_char: start_char,
        end_line: location.end_line,
        end_char: start_char
      )

    body[0] = VoidStmt.new(location: location)
  end

  attach_comments(start_char, end_char)
end

#bind_end(end_char) ⇒ Object



9395
9396
9397
9398
9399
9400
9401
9402
9403
# File 'lib/syntax_tree/node.rb', line 9395

def bind_end(end_char)
  @location =
    Location.new(
      start_line: location.start_line,
      start_char: location.start_char,
      end_line: location.end_line,
      end_char: end_char
    )
end

#child_nodesObject Also known as: deconstruct



9411
9412
9413
# File 'lib/syntax_tree/node.rb', line 9411

def child_nodes
  body
end

#deconstruct_keys(keys) ⇒ Object



9417
9418
9419
# File 'lib/syntax_tree/node.rb', line 9417

def deconstruct_keys(keys)
  { parser: parser, body: body, location: location, comments: comments }
end

#empty?Boolean

Returns:

  • (Boolean)


9405
9406
9407
9408
9409
# File 'lib/syntax_tree/node.rb', line 9405

def empty?
  body.all? do |statement|
    statement.is_a?(VoidStmt) && statement.comments.empty?
  end
end

#format(q) ⇒ Object



9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
9468
9469
9470
# File 'lib/syntax_tree/node.rb', line 9421

def format(q)
  line = nil

  # This handles a special case where you've got a block of statements where
  # the only value is a comment. In that case a lot of nodes like
  # brace_block will attempt to format as a single line, but since that
  # wouldn't work with a comment, we intentionally break the parent group.
  if body.length == 2
    void_stmt, comment = body

    if void_stmt.is_a?(VoidStmt) && comment.is_a?(Comment)
      q.format(comment)
      q.break_parent
      return
    end
  end

  access_controls =
    Hash.new do |hash, node|
      hash[node] = node.is_a?(VCall) &&
        %w[private protected public].include?(node.value.value)
    end

  body.each_with_index do |statement, index|
    next if statement.is_a?(VoidStmt)

    if line.nil?
      q.format(statement)
    elsif (statement.location.start_line - line) > 1
      q.breakable(force: true)
      q.breakable(force: true)
      q.format(statement)
    elsif access_controls[statement] || access_controls[body[index - 1]]
      q.breakable(force: true)
      q.breakable(force: true)
      q.format(statement)
    elsif statement.location.start_line != line
      q.breakable(force: true)
      q.format(statement)
    elsif !q.parent.is_a?(StringEmbExpr)
      q.breakable(force: true)
      q.format(statement)
    else
      q.text("; ")
      q.format(statement)
    end

    line = statement.location.end_line
  end
end

#pretty_print(q) ⇒ Object



9472
9473
9474
9475
9476
9477
9478
9479
9480
9481
# File 'lib/syntax_tree/node.rb', line 9472

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

#to_json(*opts) ⇒ Object



9483
9484
9485
9486
9487
# File 'lib/syntax_tree/node.rb', line 9483

def to_json(*opts)
  { type: :statements, body: body, loc: location, cmts: comments }.to_json(
    *opts
  )
end