Skip to content

Commit 3f6014d

Browse files
eregonkddnewton
authored andcommitted
Ensure Source#offsets is set correctly in all cases
* See #3861
1 parent b5f70d7 commit 3f6014d

6 files changed

Lines changed: 36 additions & 8 deletions

File tree

lib/prism/parse_result.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ class Source
2626
# source is a subset of a larger source or if this is an eval. offsets is an
2727
# array of byte offsets for the start of each line in the source code, which
2828
# can be calculated by iterating through the source code and recording the
29-
# byte offset whenever a newline character is encountered.
29+
# byte offset whenever a newline character is encountered. The first
30+
# element is always 0 to mark the first line.
3031
#--
3132
#: (String source, Integer start_line, Array[Integer] offsets) -> Source
3233
def self.for(source, start_line, offsets)

rbi/generated/prism/dsl.rbi

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rbi/generated/prism/parse_result.rbi

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sig/generated/prism/dsl.rbs

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sig/generated/prism/parse_result.rbs

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

templates/lib/prism/dsl.rb.erb

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Prism
55
# The DSL module provides a set of methods that can be used to create prism
66
# nodes in a more concise manner. For example, instead of writing:
77
#
8-
# source = Prism::Source.for("[1]", 1, [])
8+
# source = Prism::Source.for("[1]", 1, [0])
99
#
1010
# Prism::ArrayNode.new(
1111
# source,
@@ -62,7 +62,7 @@ module Prism
6262
#--
6363
#: (String string) -> Source
6464
def source(string)
65-
Source.for(string, 1, [])
65+
Source.for(string, 1, build_offsets(string))
6666
end
6767

6868
# Create a new Location object.
@@ -136,7 +136,7 @@ module Prism
136136
#--
137137
#: () -> Source
138138
def default_source
139-
Source.for("", 1, [])
139+
Source.for("", 1, [0])
140140
end
141141

142142
# The default location object that gets attached to nodes if no location is
@@ -154,5 +154,19 @@ module Prism
154154
def default_node(source, location)
155155
MissingNode.new(source, -1, location, 0)
156156
end
157+
158+
private
159+
160+
# Build the newline byte offset array for the given source string.
161+
#--
162+
#: (String source) -> Array[Integer]
163+
def build_offsets(source)
164+
offsets = [0]
165+
start = 0
166+
while (index = source.byteindex("\n", start))
167+
offsets << (start = index + 1)
168+
end
169+
offsets
170+
end
157171
end
158172
end

0 commit comments

Comments
 (0)