Skip to content
This repository has been archived by the owner on Jun 10, 2018. It is now read-only.

Commit

Permalink
Add mapping binary search
Browse files Browse the repository at this point in the history
  • Loading branch information
josh committed May 6, 2012
1 parent 6d9edc1 commit b67d74e
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 4 deletions.
42 changes: 41 additions & 1 deletion lib/sprockets/source_map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
module Sprockets
class SourceMap
class Offset
include Comparable

def initialize(line, column)
@line, @column = line, column
end
Expand All @@ -17,7 +19,17 @@ def +(other)
when Integer
Offset.new(self.line + other, self.column)
else
raise ArgumentError, "can't convert #{other} into Offset"
raise ArgumentError, "can't convert #{other} into #{self.class}"
end
end

def <=>(other)
case other
when Offset
diff = self.line - other.line
diff.zero? ? self.column - other.column : diff
else
raise ArgumentError, "can't convert #{other.class} into #{self.class}"
end
end

Expand All @@ -31,13 +43,26 @@ def inspect
end

class Mapping
include Comparable

def initialize(source, generated, original, name = nil)
@source, @generated, @original = source, generated, original
@name = name
end

attr_reader :generated, :original, :source, :name

def <=>(other)
case other
when Mapping
self.generated <=> other.generated
when Offset
self.generated <=> other
else
raise ArgumentError, "can't convert #{other.class} into #{self.class}"
end
end

def inspect
"#<#{self.class} generated=#{generated}, original=#{original}, source=#{source}, name=#{name}>"
end
Expand Down Expand Up @@ -73,6 +98,9 @@ def self.from_vlq(str, sources = [], names = [])

source = sources[source_id]
original = Offset.new(original_line, original_column)
else
# TODO: Research this case
next
end

if segment[4]
Expand Down Expand Up @@ -141,6 +169,18 @@ def +(other)
self.class.new(mappings)
end

def bsearch(offset, low = 0, high = size - 1)
return self[low-1] if low > high
mid = (low + high) / 2
return self[mid] if self[mid] == offset
if self[mid] > offset
high = mid - 1
else
low = mid + 1
end
bsearch(offset, low, high)
end

protected
def build_vlq_string
source_id = 0
Expand Down
50 changes: 47 additions & 3 deletions test/test_source_map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ class TestMappings < Test::Unit::TestCase
def setup
@mappings = Mappings.new([
Mapping.new('a.js', Offset.new(0, 0), Offset.new(0, 0)),
Mapping.new('b.js', Offset.new(1, 0), Offset.new(0, 0)),
Mapping.new('c.js', Offset.new(2, 0), Offset.new(0, 0))
Mapping.new('b.js', Offset.new(1, 0), Offset.new(20, 0)),
Mapping.new('c.js', Offset.new(2, 0), Offset.new(30, 0))
])
end

Expand All @@ -126,7 +126,7 @@ def test_line_count
end

def test_to_s
assert_equal "ACAA;ACAA;", @mappings.to_s
assert_equal "ACoBA;ACUA;", @mappings.to_s
end

def test_sources
Expand All @@ -147,6 +147,14 @@ def test_add
assert_equal 2, mappings3[2].generated.line
assert_equal 3, mappings3[3].generated.line
end

def test_bsearch
assert_equal Offset.new(0, 0), @mappings.bsearch(Offset.new(0, 0)).original
assert_equal Offset.new(0, 0), @mappings.bsearch(Offset.new(0, 5)).original
assert_equal Offset.new(20, 0), @mappings.bsearch(Offset.new(1, 0)).original
assert_equal Offset.new(20, 0), @mappings.bsearch(Offset.new(1, 0)).original
assert_equal Offset.new(30, 0), @mappings.bsearch(Offset.new(2, 0)).original
end
end

class TestMapping < Test::Unit::TestCase
Expand Down Expand Up @@ -175,6 +183,34 @@ def test_name
assert_equal 'hello', @mapping.name
end

def test_compare
assert @mapping == @mapping
assert @mapping <= @mapping
assert @mapping >= @mapping

other = Mapping.new('script.js', Offset.new(2, 0), Offset.new(3, 0), 'goodbye')
assert @mapping < other
assert other > @mapping

other = Mapping.new('script.js', Offset.new(1, 9), Offset.new(3, 0), 'goodbye')
assert @mapping < other
assert other > @mapping
end

def test_compare_offset
other = Offset.new(1, 8)

assert @mapping == other
assert @mapping <= other
assert @mapping >= other

other = Offset.new(2, 0)
assert @mapping < other

other = Offset.new(1, 9)
assert @mapping < other
end

def test_inspect
assert_equal "#<Sprockets::SourceMap::Mapping generated=1:8, original=2:9, source=script.js, name=hello>", @mapping.inspect
end
Expand Down Expand Up @@ -214,4 +250,12 @@ def test_add_line
assert_equal 6, offset.line
assert_equal 5, offset.column
end

def test_compare
assert @offset < Offset.new(2, 0)
assert @offset < Offset.new(1, 6)
assert @offset > Offset.new(1, 4)
assert @offset >= Offset.new(1, 5)
assert @offset <= Offset.new(1, 5)
end
end

0 comments on commit b67d74e

Please sign in to comment.