Class: Ast::Merge::Layout::Gap

Inherits:
Object
  • Object
show all
Defined in:
lib/ast/merge/layout/gap.rb

Overview

Passive representation of a contiguous blank-line run.

A gap may be adjacent to both a preceding and a following owner. Both owners can reference the same shared gap object, but only one side is the active controller for output at any moment.

Constant Summary collapse

KINDS =

Supported gap kinds.

Returns:

  • (Array<Symbol>)
%i[preamble interstitial postlude].freeze
SIDES =

Supported owner-reference sides.

Returns:

  • (Array<Symbol>)
%i[before after].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(kind:, start_line:, end_line:, lines:, before_owner: nil, after_owner: nil, controller_side: nil, metadata: {}, **options) ⇒ Gap

Returns a new instance of Gap.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/ast/merge/layout/gap.rb', line 23

def initialize(kind:, start_line:, end_line:, lines:, before_owner: nil, after_owner: nil,
               controller_side: nil, metadata: {}, **options)
  @kind = normalize_kind(kind)
  @start_line = Integer(start_line)
  @end_line = Integer(end_line)
  @lines = Array(lines).freeze
  @before_owner = before_owner
  @after_owner = after_owner
  @controller_side = normalize_controller_side(controller_side || default_controller_side)
  @metadata = .merge(options).freeze

  validate_range!
  validate_adjacency!
  validate_controller_side!
end

Instance Attribute Details

#after_ownerObject (readonly)

Returns the value of attribute after_owner.



21
22
23
# File 'lib/ast/merge/layout/gap.rb', line 21

def after_owner
  @after_owner
end

#before_ownerObject (readonly)

Returns the value of attribute before_owner.



21
22
23
# File 'lib/ast/merge/layout/gap.rb', line 21

def before_owner
  @before_owner
end

#controller_sideObject (readonly)

Returns the value of attribute controller_side.



21
22
23
# File 'lib/ast/merge/layout/gap.rb', line 21

def controller_side
  @controller_side
end

#end_lineObject (readonly)

Returns the value of attribute end_line.



21
22
23
# File 'lib/ast/merge/layout/gap.rb', line 21

def end_line
  @end_line
end

#kindObject (readonly)

Returns the value of attribute kind.



21
22
23
# File 'lib/ast/merge/layout/gap.rb', line 21

def kind
  @kind
end

#linesObject (readonly)

Returns the value of attribute lines.



21
22
23
# File 'lib/ast/merge/layout/gap.rb', line 21

def lines
  @lines
end

#metadataObject (readonly)

Returns the value of attribute metadata.



21
22
23
# File 'lib/ast/merge/layout/gap.rb', line 21

def 
  @metadata
end

#start_lineObject (readonly)

Returns the value of attribute start_line.



21
22
23
# File 'lib/ast/merge/layout/gap.rb', line 21

def start_line
  @start_line
end

Instance Method Details

#adjacent_side_for(owner) ⇒ Object



107
108
109
110
111
112
# File 'lib/ast/merge/layout/gap.rb', line 107

def adjacent_side_for(owner)
  return :before if trailing_for?(owner)
  return :after if leading_for?(owner)

  nil
end

#blank_line_countInteger

Return the number of blank lines contained in the gap.

Returns:

  • (Integer)


61
62
63
# File 'lib/ast/merge/layout/gap.rb', line 61

def blank_line_count
  lines.count { |line| line.to_s.strip.empty? }
end

#controllerObject?

Return the owner currently controlling output for this gap.

Returns:

  • (Object, nil)


68
69
70
# File 'lib/ast/merge/layout/gap.rb', line 68

def controller
  owner_for(controller_side)
end

#controls_output_for?(owner, retained_owners: nil, removed_owners: nil) ⇒ Boolean

Returns:

  • (Boolean)


149
150
151
# File 'lib/ast/merge/layout/gap.rb', line 149

def controls_output_for?(owner, retained_owners: nil, removed_owners: nil)
  effective_controller(retained_owners: retained_owners, removed_owners: removed_owners).equal?(owner)
end

#effective_controller(retained_owners: nil, removed_owners: nil) ⇒ Object?

Return the owner that should control output after owner removal/retention filtering.

Parameters:

  • retained_owners (Array<Object>, nil) (defaults to: nil)

    explicitly retained owners

  • removed_owners (Array<Object>, nil) (defaults to: nil)

    explicitly removed owners

Returns:

  • (Object, nil)


130
131
132
133
# File 'lib/ast/merge/layout/gap.rb', line 130

def effective_controller(retained_owners: nil, removed_owners: nil)
  effective_side = effective_controller_side(retained_owners: retained_owners, removed_owners: removed_owners)
  effective_side ? owner_for(effective_side) : nil
end

#effective_controller_side(retained_owners: nil, removed_owners: nil) ⇒ Symbol?

Return the side that should control output after owner filtering.

Parameters:

  • retained_owners (Array<Object>, nil) (defaults to: nil)

    explicitly retained owners

  • removed_owners (Array<Object>, nil) (defaults to: nil)

    explicitly removed owners

Returns:

  • (Symbol, nil)


140
141
142
143
144
145
146
147
# File 'lib/ast/merge/layout/gap.rb', line 140

def effective_controller_side(retained_owners: nil, removed_owners: nil)
  return controller_side if owner_available?(controller, retained_owners: retained_owners,
                                                         removed_owners: removed_owners)
  return fallback_side if owner_available?(fallback_controller, retained_owners: retained_owners,
                                                                removed_owners: removed_owners)

  nil
end

#fallback_controllerObject?

Return the owner on the fallback controller side.

Returns:

  • (Object, nil)


84
85
86
# File 'lib/ast/merge/layout/gap.rb', line 84

def fallback_controller
  owner_for(fallback_side)
end

#fallback_sideSymbol?

Return the opposite controller side, if any.

Returns:

  • (Symbol, nil)


75
76
77
78
79
# File 'lib/ast/merge/layout/gap.rb', line 75

def fallback_side
  return unless controller_side

  controller_side == :before ? :after : :before
end

#inspectString

Return a concise debug representation of the gap.

Returns:

  • (String)


156
157
158
# File 'lib/ast/merge/layout/gap.rb', line 156

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

#interstitial?Boolean

Returns:

  • (Boolean)


43
44
45
# File 'lib/ast/merge/layout/gap.rb', line 43

def interstitial?
  kind == :interstitial
end

#leading_for?(owner) ⇒ Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/ast/merge/layout/gap.rb', line 99

def leading_for?(owner)
  after_owner.equal?(owner)
end

#line_countInteger

Return the number of source lines spanned by the gap.

Returns:

  • (Integer)


54
55
56
# File 'lib/ast/merge/layout/gap.rb', line 54

def line_count
  end_line - start_line + 1
end

#owned_by?(owner) ⇒ Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/ast/merge/layout/gap.rb', line 121

def owned_by?(owner)
  leading_for?(owner) || trailing_for?(owner)
end

#owner_for(side) ⇒ Object?

Resolve an owner by side.

Parameters:

  • side (Symbol, String, nil)

Returns:

  • (Object, nil)


92
93
94
95
96
97
# File 'lib/ast/merge/layout/gap.rb', line 92

def owner_for(side)
  case normalize_controller_side(side)
  when :before then before_owner
  when :after then after_owner
  end
end

#postlude?Boolean

Returns:

  • (Boolean)


47
48
49
# File 'lib/ast/merge/layout/gap.rb', line 47

def postlude?
  kind == :postlude
end

#preamble?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/ast/merge/layout/gap.rb', line 39

def preamble?
  kind == :preamble
end

#role_for(owner) ⇒ Object



114
115
116
117
118
119
# File 'lib/ast/merge/layout/gap.rb', line 114

def role_for(owner)
  case adjacent_side_for(owner)
  when :before then :trailing
  when :after then :leading
  end
end

#trailing_for?(owner) ⇒ Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/ast/merge/layout/gap.rb', line 103

def trailing_for?(owner)
  before_owner.equal?(owner)
end