Class: Ast::Merge::Comment::Region

Inherits:
Object
  • Object
show all
Defined in:
lib/ast/merge/comment/region.rb

Overview

A merge-facing region representing a contiguous span of comment-related content with a specific ownership kind.

Regions are passive data objects. They normalize parser-native or source-augmented comment nodes into a shape that merge gems can attach to structural AST nodes without changing merge behavior on their own.

Constant Summary collapse

KINDS =

Supported normalized comment region kinds.

Returns:

  • (Array<Symbol>)
%i[
  leading
  inline
  trailing
  orphan
  preamble
  postlude
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(kind:, nodes:, metadata: {}, **options) ⇒ Region

Returns a new instance of Region.



27
28
29
30
31
# File 'lib/ast/merge/comment/region.rb', line 27

def initialize(kind:, nodes:, metadata: {}, **options)
  @kind = normalize_kind(kind)
  @nodes = Array(nodes).freeze
  @metadata = .merge(options).freeze
end

Instance Attribute Details

#kindObject (readonly)

Returns the value of attribute kind.



25
26
27
# File 'lib/ast/merge/comment/region.rb', line 25

def kind
  @kind
end

#metadataObject (readonly)

Returns the value of attribute metadata.



25
26
27
# File 'lib/ast/merge/comment/region.rb', line 25

def 
  @metadata
end

#nodesObject (readonly)

Returns the value of attribute nodes.



25
26
27
# File 'lib/ast/merge/comment/region.rb', line 25

def nodes
  @nodes
end

Instance Method Details

#empty?Boolean

Returns:

  • (Boolean)


69
70
71
# File 'lib/ast/merge/comment/region.rb', line 69

def empty?
  nodes.empty?
end

#end_lineInteger?

Return the last line touched by the region.

Returns:

  • (Integer, nil)


83
84
85
# File 'lib/ast/merge/comment/region.rb', line 83

def end_line
  locations.map(&:end_line).compact.max
end

#floating?Boolean

A floating region is gap-separated from its owner node by at least one blank line. Floating comments are positional — they belong to a place in the file rather than to the specific AST node the parser attached them to. This distinction matters for merge deduplication: when two sides attach the same floating comment block to different nodes, only one copy should survive the merge.

The value is set by the Augmenter during region construction.

Returns:

  • (Boolean)


65
66
67
# File 'lib/ast/merge/comment/region.rb', line 65

def floating?
  [:floating] == true
end

#freeze?(freeze_token) ⇒ Boolean

Returns:

  • (Boolean)


138
139
140
# File 'lib/ast/merge/comment/region.rb', line 138

def freeze?(freeze_token)
  freeze_actions(freeze_token).include?(:freeze)
end

#freeze_actions(freeze_token) ⇒ Array<Symbol>

Return all freeze/unfreeze actions exposed by nodes in the region.

Parameters:

  • freeze_token (String)

    token to detect

Returns:

  • (Array<Symbol>)


130
131
132
133
134
135
136
# File 'lib/ast/merge/comment/region.rb', line 130

def freeze_actions(freeze_token)
  nodes.filter_map do |node|
    next unless node.respond_to?(:freeze_action)

    node.freeze_action(freeze_token)
  end
end

#freeze_marker?(freeze_token) ⇒ Boolean

Returns:

  • (Boolean)


146
147
148
# File 'lib/ast/merge/comment/region.rb', line 146

def freeze_marker?(freeze_token)
  freeze?(freeze_token) || unfreeze?(freeze_token)
end

#inline?Boolean

Returns:

  • (Boolean)


37
38
39
# File 'lib/ast/merge/comment/region.rb', line 37

def inline?
  kind == :inline
end

#inspectString

Return a concise debug representation of the region.

Returns:

  • (String)


153
154
155
# File 'lib/ast/merge/comment/region.rb', line 153

def inspect
  "#<#{self.class.name} kind=#{kind} lines=#{start_line}..#{end_line} nodes=#{nodes.size}>"
end

#leading?Boolean

Returns:

  • (Boolean)


33
34
35
# File 'lib/ast/merge/comment/region.rb', line 33

def leading?
  kind == :leading
end

#locationAstNode::Location?

Return a synthetic location spanning the region.

Returns:



90
91
92
93
94
95
96
97
98
99
# File 'lib/ast/merge/comment/region.rb', line 90

def location
  return if empty? || start_line.nil? || end_line.nil?

  AstNode::Location.new(
    start_line: start_line,
    end_line: end_line,
    start_column: 0,
    end_column: 0
  )
end

#normalized_contentString

Return normalized multi-line text used for region comparisons.

Returns:

  • (String)


104
105
106
107
108
# File 'lib/ast/merge/comment/region.rb', line 104

def normalized_content
  nodes
    .map { |node| node.respond_to?(:normalized_content) ? node.normalized_content : node.to_s }
    .join("\n")
end

#orphan?Boolean

Returns:

  • (Boolean)


45
46
47
# File 'lib/ast/merge/comment/region.rb', line 45

def orphan?
  kind == :orphan
end

#postlude?Boolean

Returns:

  • (Boolean)


53
54
55
# File 'lib/ast/merge/comment/region.rb', line 53

def postlude?
  kind == :postlude
end

#preamble?Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/ast/merge/comment/region.rb', line 49

def preamble?
  kind == :preamble
end

#signatureArray

Return a compact signature for matching equivalent regions.

Returns:

  • (Array)


122
123
124
# File 'lib/ast/merge/comment/region.rb', line 122

def signature
  [:comment_region, kind, normalized_content[0..120]]
end

#start_lineInteger?

Return the first line touched by the region.

Returns:

  • (Integer, nil)


76
77
78
# File 'lib/ast/merge/comment/region.rb', line 76

def start_line
  locations.map(&:start_line).compact.min
end

#textString

Return the raw text for all nodes in the region.

Returns:

  • (String)


113
114
115
116
117
# File 'lib/ast/merge/comment/region.rb', line 113

def text
  nodes
    .map { |node| node.respond_to?(:slice) ? node.slice.to_s : node.to_s }
    .join("\n")
end

#trailing?Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/ast/merge/comment/region.rb', line 41

def trailing?
  kind == :trailing
end

#unfreeze?(freeze_token) ⇒ Boolean

Returns:

  • (Boolean)


142
143
144
# File 'lib/ast/merge/comment/region.rb', line 142

def unfreeze?(freeze_token)
  freeze_actions(freeze_token).include?(:unfreeze)
end