Class: Yoga::Location

Inherits:
Object
  • Object
show all
Defined in:
lib/yoga/location.rb

Overview

A location in a file. This can be used for debugging purposes.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file, line, column) ⇒ Location

Initialize the location with the given information.


48
49
50
51
52
53
54
# File 'lib/yoga/location.rb', line 48

def initialize(file, line, column)
  @file = file.freeze
  @line = ensure_range(line).freeze
  @column = ensure_range(column).freeze
  @hash = [@file, @line, @column].hash
  freeze
end

Instance Attribute Details

#column::Range (readonly)

The column the location on. This can be a range of columns, or a single column.


24
25
26
# File 'lib/yoga/location.rb', line 24

def column
  @column
end

#file::String (readonly)

The file the location is positioned in. This should just be a string that uniquely identifies the file from all possible values of the location.


12
13
14
# File 'lib/yoga/location.rb', line 12

def file
  @file
end

#hash::Numeric (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

A "hash" of the location. This is a number that is meant to roughly represent the value of this location. Used primarily for the Hash class.


32
33
34
# File 'lib/yoga/location.rb', line 32

def hash
  @hash
end

#line::Range (readonly)

The line the location is on. This can be a range of lines, or a single line.


18
19
20
# File 'lib/yoga/location.rb', line 18

def line
  @line
end

Class Method Details

.default(file = "<unknown>") ⇒ Location

Creates a "default" location. This is a location that can be given if the location is unknown.


39
40
41
# File 'lib/yoga/location.rb', line 39

def self.default(file = "<unknown>")
  new(file, 0..0, 0..0)
end

Instance Method Details

#==(other) ⇒ Boolean

Determines if the other object is equal to the current instance. This checks equal? first to determine if they are strict equals; otherwise, it checks if the other is a Yoga::Location. If it is, it checks that the properties are equal.

Examples:

a # => #<Location file="a" line=1..1 column=5..20>
a == a # => true
a # => #<Location file="a" line=1..1 column=5..20>
b # => #<Location file="a" line=1..1 column=5..20>
a == b # => true
a # => #<Location file="a" line=1..1 column=5..20>
b # => #<Location file="b" line=1..1 column=6..20>
a == b # => false

89
90
91
92
# File 'lib/yoga/location.rb', line 89

def ==(other)
  equal?(other) || other.is_a?(Location) && @file == other.file &&
    @line == other.line && @column == other.column
end

#construct_range(from) ⇒ ::Range<::Numeric> (private)

Creates a range from a list of ranges. This takes the lowest starting value, and the greatest ending value, and creates a new range from that.


143
144
145
146
147
148
# File 'lib/yoga/location.rb', line 143

def construct_range(from)
  first = from.map(&:first).min
  last = from.map(&:last).max

  first..last
end

#ensure_range(value) ⇒ ::Range (private)

Ensures that the given value is a range. If it's numeric, it's turned into a range with the same starting and ending values. If it's a range, it's returned. Otherwise, it fails.


156
157
158
159
160
161
162
163
164
165
# File 'lib/yoga/location.rb', line 156

def ensure_range(value)
  case value
  when ::Numeric
    value..value
  when ::Range
    value
  else
    fail ArgumentError, "Unexpected #{value.class}, expected Range"
  end
end

#inspect::String

Pretty inspect.


66
67
68
# File 'lib/yoga/location.rb', line 66

def inspect
  "#<#{self.class} #{self}>"
end

#range(value) ⇒ ::String (private)

Returns a string version of the range. If there is no distance between the starting and ending for the given range, it returns a string of the value. Otherwise, it returns <starting>-<ending>.


173
174
175
176
# File 'lib/yoga/location.rb', line 173

def range(value)
  return value.first.to_s unless value.first != value.last
  "#{value.first}-#{value.last}"
end

#to_s::String

Creates a string representing this location in a file.


59
60
61
# File 'lib/yoga/location.rb', line 59

def to_s
  "#{file}:#{range(line)}.#{range(column)}"
end

#union(*others) ⇒ Location Also known as: |

Unions this location with another location. This creates a new location, with the two locations combined. A conflict in the file name causes an error to be raised.

Examples:

a = Location.new("a", 1..1, 5..10)
a.union(a) # => #<Location file="a" line=1..1 column=5..10>
a.union(a) == a # => true
a.union(a).equal?(a) # => false
a = Location.new("a", 1..1, 5..10)
b = Location.new("a", 1..1, 6..20)
a.union(b) # => #<Location file="a" line=1..1 column=5..20>
a = Location.new("a", 1..5, 3..10)
b = Location.new("b", 1..3, 2..20)
a.union(b) # => #<Location file="a" line=1..5 column=2..20>
a # => #<Location ...>
b # => #<Location ...>
a.union(b) == b.union(a)

Raises:

  • (::ArgumentError)

    if other isn't a Yoga::Location.

  • (::ArgumentError)

    if other's file isn't the receiver's file.


120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/yoga/location.rb', line 120

def union(*others)
  others.each do |other|
    fail ArgumentError, "Expected #{self.class}, got #{other.class}" \
      unless other.is_a?(Location)
    fail ArgumentError, "Expected other to have the same file" unless
      file == other.file
  end

  line = construct_range([@line, *others.map(&:line)])
  column = construct_range([@column, *others.map(&:column)])

  Location.new(@file, line, column)
end