Class: Kotoshu::Documents::SourceRange

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Comparable
Defined in:
lib/kotoshu/documents/source_range.rb

Overview

Immutable value object: a span in the original source. The start position is inclusive; the end position is exclusive (matches Ruby's range convention and editor selection APIs).

SourceRange is the canonical "where" that an error report carries. The checker resolves it from the Document before constructing an error so callers (plugins, editors, the CLI) never have to know about flattened vs source offsets.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(start_pos:, end_pos:) ⇒ SourceRange

Returns a new instance of SourceRange.

Parameters:

Raises:

  • (TypeError)


25
26
27
28
29
30
31
32
33
# File 'lib/kotoshu/documents/source_range.rb', line 25

def initialize(start_pos:, end_pos:)
  raise TypeError, "start must be a SourcePosition" unless start_pos.is_a?(SourcePosition)
  raise TypeError, "end must be a SourcePosition" unless end_pos.is_a?(SourcePosition)
  raise ArgumentError, "end must be >= start" if end_pos < start_pos

  @start = start_pos
  @end = end_pos
  freeze
end

Instance Attribute Details

#endObject (readonly)

Returns the value of attribute end.



19
20
21
# File 'lib/kotoshu/documents/source_range.rb', line 19

def end
  @end
end

#startObject (readonly)

Returns the value of attribute start.



19
20
21
# File 'lib/kotoshu/documents/source_range.rb', line 19

def start
  @start
end

Instance Method Details

#<=>(other) ⇒ Object

Order by start position; ties broken by end position.



36
37
38
39
40
41
# File 'lib/kotoshu/documents/source_range.rb', line 36

def <=>(other)
  return nil unless other.is_a?(SourceRange)

  cmp = @start <=> other.start
  cmp.zero? ? (@end <=> other.end) : cmp
end

#contains?(pos) ⇒ Boolean

True if pos falls inside this range. End is exclusive.

Returns:

  • (Boolean)


44
45
46
# File 'lib/kotoshu/documents/source_range.rb', line 44

def contains?(pos)
  pos.is_a?(SourcePosition) && pos >= @start && pos < @end
end

#empty?Boolean

True when this range covers zero characters (start == end).

Returns:

  • (Boolean)


56
57
58
# File 'lib/kotoshu/documents/source_range.rb', line 56

def empty?
  @start == @end
end

#lengthObject

Length in characters of the source span. Uses the offset difference, which is the editor-friendly interpretation: a range from offset 7 to offset 15 covers 8 characters.



51
52
53
# File 'lib/kotoshu/documents/source_range.rb', line 51

def length
  @end.offset - @start.offset
end

#to_sObject



71
72
73
# File 'lib/kotoshu/documents/source_range.rb', line 71

def to_s
  "#{@start}..#{@end}"
end

#union(other) ⇒ SourceRange

Combine other with self into a range that spans both.

Parameters:

Returns:

Raises:

  • (TypeError)


63
64
65
66
67
68
69
# File 'lib/kotoshu/documents/source_range.rb', line 63

def union(other)
  raise TypeError, "other must be a SourceRange" unless other.is_a?(SourceRange)

  min_start = [@start, other.start].min
  max_end = [@end, other.end].max
  self.class.new(start_pos: min_start, end_pos: max_end)
end