Module: Jade::AST::Node

Defined in:
lib/jade/ast/node.rb

Constant Summary collapse

BOILERPLATE_FIELDS =

Boilerplate added by Nodes.define alongside the AST-specific fields. Excluded from child traversal so we don't iterate the range Range as integers or descend into comment metadata.

%i[
  range symbol id
  leading_comments trailing_comments dangling_comments
  trailing_comma
].freeze
@@_next_id =
0

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.next_idObject



15
16
17
# File 'lib/jade/ast/node.rb', line 15

def self.next_id
  @@_next_id += 1
end

Instance Method Details

#doc(source) ⇒ Object

The comment block touching this node. A blank line above it means a section banner, which documents the region and not this node.



21
22
23
24
25
26
# File 'lib/jade/ast/node.rb', line 21

def doc(source)
  leading_comment_groups(source)
    .last
    &.then { follows_directly?(it.last, self, source) ? it : nil }
    &.then { it.map(&:value).join("\n") }
end

#find_at(offset) ⇒ Object

Deepest descendant whose range covers offset, or self if no child matches. Returns nil if this node's range is missing or doesn't cover the offset.



38
39
40
# File 'lib/jade/ast/node.rb', line 38

def find_at(offset)
  find_at_path(offset).last
end

#find_at_path(offset) ⇒ Object

Path of nested nodes from self down to the deepest descendant covering offset. Empty if self doesn't cover. Use this when you need to consult ancestors — e.g. hover on String inside String.length(...) needs the surrounding QualifiedAccess, not the raw ConstructorReference.



47
48
49
50
51
52
53
54
55
56
57
# File 'lib/jade/ast/node.rb', line 47

def find_at_path(offset)
  return [] unless range&.cover?(offset)

  (members - BOILERPLATE_FIELDS)
    .flat_map { public_send(it) }
    .flat_map { it.is_a?(Array) ? it : [it] }
    .filter_map { it.is_a?(Node) ? it.find_at_path(offset) : nil }
    .reject(&:empty?)
    .first
    .then { [self] + (it || []) }
end

#leading_comment_groups(source) ⇒ Object

Split wherever a blank line separates one block from the next.



29
30
31
32
33
# File 'lib/jade/ast/node.rb', line 29

def leading_comment_groups(source)
  leading_comments
    .slice_when { |a, b| !follows_directly?(a, b, source) }
    .to_a
end