Skip to content

Commit b290733

Browse files
committed
Implement MatchData#byteoffset for 3.2 compatibility
1 parent 7f6bbb3 commit b290733

File tree

4 files changed

+37
-27
lines changed

4 files changed

+37
-27
lines changed
Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1 @@
1-
fails:MatchData#byteoffset returns beginning and ending byte-based offset of whole matched substring for 0 element
2-
fails:MatchData#byteoffset returns beginning and ending byte-based offset of n-th match, all the subsequent elements are capturing groups
3-
fails:MatchData#byteoffset accepts String as a reference to a named capture
4-
fails:MatchData#byteoffset accepts Symbol as a reference to a named capture
5-
fails:MatchData#byteoffset returns [nil, nil] if a capturing group is optional and doesn't match
6-
fails:MatchData#byteoffset returns correct beginning and ending byte-based offset for multi-byte strings
7-
fails:MatchData#byteoffset returns [nil, nil] if a capturing group is optional and doesn't match for multi-byte string
8-
fails:MatchData#byteoffset converts argument into integer if is not String nor Symbol
9-
fails:MatchData#byteoffset raises IndexError if there is no group with provided name
10-
fails:MatchData#byteoffset raises IndexError if index is out of matches
111
fails:MatchData#byteoffset raises TypeError if can't convert argument into Integer

src/main/java/org/truffleruby/core/regexp/MatchDataNodes.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,14 @@ Object byteBegin(RubyMatchData matchData, int index,
627627
}
628628
}
629629

630+
@TruffleBoundary
631+
@Specialization(guards = "!inBounds(matchData, index)")
632+
Object byteBeginError(RubyMatchData matchData, int index) {
633+
throw new RaiseException(
634+
getContext(),
635+
coreExceptions().indexError(StringUtils.format("index %d out of matches", index), this));
636+
}
637+
630638
protected boolean inBounds(RubyMatchData matchData, int index) {
631639
return index >= 0 && index < matchData.region.numRegs;
632640
}
@@ -649,6 +657,14 @@ Object byteEnd(RubyMatchData matchData, int index,
649657
}
650658
}
651659

660+
@TruffleBoundary
661+
@Specialization(guards = "!inBounds(matchData, index)")
662+
Object byteEndError(RubyMatchData matchData, int index) {
663+
throw new RaiseException(
664+
getContext(),
665+
coreExceptions().indexError(StringUtils.format("index %d out of matches", index), this));
666+
}
667+
652668
protected boolean inBounds(RubyMatchData matchData, int index) {
653669
return index >= 0 && index < matchData.region.numRegs;
654670
}

src/main/ruby/truffleruby/core/match_data.rb

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ class << self
4040
undef_method :allocate
4141
end
4242

43+
def byteoffset(idx)
44+
backref = backref_from_arg(idx)
45+
[Primitive.match_data_byte_begin(self, backref), Primitive.match_data_byte_end(self, backref)]
46+
end
47+
4348
def offset(idx)
4449
[self.begin(idx), self.end(idx)]
4550
end
@@ -71,26 +76,12 @@ def named_captures
7176
end
7277

7378
def begin(index)
74-
backref = if Primitive.is_a?(index, String) || Primitive.is_a?(index, Symbol)
75-
names_to_backref = Hash[Primitive.regexp_names(self.regexp)]
76-
names_to_backref[index.to_sym].last
77-
else
78-
Truffle::Type.coerce_to(index, Integer, :to_int)
79-
end
80-
81-
79+
backref = backref_from_arg(index)
8280
Primitive.match_data_begin(self, backref)
8381
end
8482

8583
def end(index)
86-
backref = if Primitive.is_a?(index, String) || Primitive.is_a?(index, Symbol)
87-
names_to_backref = Hash[Primitive.regexp_names(self.regexp)]
88-
names_to_backref[index.to_sym].last
89-
else
90-
Truffle::Type.coerce_to(index, Integer, :to_int)
91-
end
92-
93-
84+
backref = backref_from_arg(index)
9485
Primitive.match_data_end(self, backref)
9586
end
9687

@@ -153,6 +144,20 @@ def match_length(n)
153144
def to_s
154145
self[0]
155146
end
147+
148+
private
149+
150+
def backref_from_arg(index)
151+
if Primitive.is_a?(index, String) || Primitive.is_a?(index, Symbol)
152+
names_to_backref = Hash[Primitive.regexp_names(self.regexp)]
153+
unless names_to_backref.key?(index.to_sym)
154+
raise IndexError, "undefined group name reference: #{index}"
155+
end
156+
names_to_backref[index.to_sym].last
157+
else
158+
Truffle::Type.coerce_to(index, Integer, :to_int)
159+
end
160+
end
156161
end
157162

158163
Truffle::KernelOperations.define_hooked_variable(

test/mri/excludes/TestRegexp.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
exclude :test_match_control_meta_escape, "<0> expected but was"
4040
exclude :test_initialize_option, "<//m> expected but was"
4141
exclude :test_initialize_bool_warning, "expected: /expected true or false as ignorecase/"
42-
exclude :test_match_byteoffset_begin_end, "NoMethodError: undefined method `byteoffset' for #<MatchData \"bar\" x:\"bar\">"
4342
exclude :test_match_data_deconstruct, "NoMethodError: undefined method `deconstruct' for #<MatchData \"foobarbaz\">"
4443
exclude :test_linear_time_p, "NoMethodError: undefined method `linear_time?' for Regexp:Class"
4544
exclude :test_match_data_deconstruct_keys, "NoMethodError: undefined method `deconstruct_keys' for #<MatchData \"foobarbaz\">"

0 commit comments

Comments
 (0)