Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 108 additions & 108 deletions ext/rbs_extension/ast_translation.c

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions ext/rbs_extension/legacy_location.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,16 @@ VALUE rbs_new_location(VALUE buffer, rbs_range_t rg) {
rbs_loc *loc;
VALUE obj = TypedData_Make_Struct(RBS_Location, rbs_loc, &location_type, loc);

rbs_loc_init(loc, buffer, (rbs_loc_range) { rg.start.char_pos, rg.end.char_pos });
rbs_loc_init(loc, buffer, (rbs_loc_range) { rg.start.byte_pos, rg.end.byte_pos });

return obj;
}

VALUE rbs_new_location2(VALUE buffer, int start_char, int end_char) {
VALUE rbs_new_location2(VALUE buffer, int start_byte, int end_byte) {
rbs_loc *loc;
VALUE obj = TypedData_Make_Struct(RBS_Location, rbs_loc, &location_type, loc);

rbs_loc_init(loc, buffer, (rbs_loc_range) { .start = start_char, .end = end_char });
rbs_loc_init(loc, buffer, (rbs_loc_range) { start_byte, end_byte });

return obj;
}
Expand Down
4 changes: 2 additions & 2 deletions ext/rbs_extension/legacy_location.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ SUPPRESS_RUBY_HEADER_DIAGNOSTICS_END
extern VALUE RBS_Location;

/**
* Range of character index for `rbs_loc` locations.
* Range of byte index for `rbs_loc` locations.
*/
typedef struct {
int start;
Expand Down Expand Up @@ -57,7 +57,7 @@ typedef struct {
* */
VALUE rbs_new_location(VALUE buffer, rbs_range_t rg);

VALUE rbs_new_location2(VALUE buffer, int start_char, int end_char);
VALUE rbs_new_location2(VALUE buffer, int start_byte, int end_byte);

/**
* Return rbs_loc associated with the RBS::Location object.
Expand Down
10 changes: 5 additions & 5 deletions lib/rbs/ast/ruby/comment_block.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ def initialize(source_buffer, comments)

offsets << tuple

start_char = comment.location.start_character_offset + tuple[1]
end_char = comment.location.end_character_offset
ranges << (start_char ... end_char)
start_byte = comment.location.start_offset + tuple[1]
end_byte = comment.location.end_offset
ranges << (start_byte ... end_byte)
end

@comment_buffer = source_buffer.sub_buffer(lines: ranges)
Expand All @@ -53,7 +53,7 @@ def end_line

def line_starts
offsets.map do |comment, prefix_size|
comment.location.start_character_offset + prefix_size
comment.location.start_offset + prefix_size
end
end

Expand Down Expand Up @@ -168,7 +168,7 @@ def yield_annotation(start_line, end_line, current_line, variables, &block)

def text(comment_index)
range = comment_buffer.ranges[comment_index]
comment_buffer.content[range] or raise
comment_buffer.content.byteslice(range) or raise
end

def line_location(start_line, end_line)
Expand Down
4 changes: 2 additions & 2 deletions lib/rbs/ast/ruby/declarations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ def location
if type_annotation
Location.new(
type_name_location.buffer,
type_name_location.start_pos,
type_annotation.location.end_pos
type_name_location.start_byte,
type_annotation.location.end_byte
)
else
type_name_location
Expand Down
2 changes: 1 addition & 1 deletion lib/rbs/ast/ruby/helpers/location_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module Ruby
module Helpers
module LocationHelper
def rbs_location(location)
Location.new(buffer, location.start_character_offset, location.end_character_offset)
Location.new(buffer, location.start_offset, location.end_offset)
end
end
end
Expand Down
13 changes: 6 additions & 7 deletions lib/rbs/buffer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def initialize(name: nil, content:, parent: nil)
end

def lines
ranges.map { self.content[_1] || raise } #$ String
ranges.map { content.byteslice(_1) || raise } #$ String
end

def line_count
Expand All @@ -31,7 +31,6 @@ def ranges
@ranges ||= begin
if content.empty?
ranges = [0...0] #: Array[Range[Integer]]
lines = [""]
else
lines = content.lines
lines << "" if content.end_with?("\n")
Expand All @@ -40,9 +39,9 @@ def ranges
offset = 0

lines.each do |line|
size0 = line.size
size0 = line.bytesize
line = line.chomp
range = offset...(offset+line.size)
range = offset...(offset+line.bytesize)
ranges << range

offset += size0
Expand Down Expand Up @@ -89,9 +88,9 @@ def inspect

def rbs_location(location, loc2=nil)
if loc2
Location.new(self.top_buffer, location.start_character_offset, loc2.end_character_offset)
Location.new(self.top_buffer, location.start_offset, loc2.end_offset)
else
Location.new(self.top_buffer, location.start_character_offset, location.end_character_offset)
Location.new(self.top_buffer, location.start_offset, location.end_offset)
end
end

Expand All @@ -100,7 +99,7 @@ def sub_buffer(lines:)
lines.each_with_index do |range, index|
start_pos = range.begin
end_pos = range.end
slice = content[start_pos...end_pos] or raise
slice = content.byteslice(start_pos, end_pos - start_pos) or raise
if slice.include?("\n")
raise "Line #{index + 1} cannot contain newline character."
end
Expand Down
4 changes: 2 additions & 2 deletions lib/rbs/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ def detailed_message(highlight: false, **)
# Support only one line
return msg unless location.start_line == location.end_line

indent = " " * location.start_column
marker = "^" * ([location.end_column - location.start_column, 1].max or raise)
indent = " " * location.start_byte_column
marker = "^" * ([location.end_byte_column - location.start_byte_column, 1].max or raise)

io = StringIO.new
io.puts msg
Expand Down
76 changes: 62 additions & 14 deletions lib/rbs/location_aux.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def inspect
else
source.each_line.first&.chomp&.inspect
end
"#<#{self.class}:#{self.__id__} buffer=#{buffer.name}, start=#{start_line}:#{start_column}, pos=#{start_pos}...#{end_pos}, children=#{(rks + ops).join(",")} source=#{src}>"
"#<#{self.class}:#{self.__id__} buffer=#{buffer.name}, start=#{start_line}:#{start_byte_column}, pos=#{start_byte}...#{end_byte}, children=#{(rks + ops).join(",")} source=#{src}>"
end

def self.new(buffer_ = nil, start_pos_ = nil, end_pos_ = nil, buffer: nil, start_pos: nil, end_pos: nil)
Expand All @@ -28,14 +28,36 @@ def self.new(buffer_ = nil, start_pos_ = nil, end_pos_ = nil, buffer: nil, start

WithChildren = self

def start_pos
def start_byte
buffer.absolute_position(_start_pos) || raise
end

def end_pos
def end_byte
buffer.absolute_position(_end_pos) || raise
end

def start_char
top = buffer.top_buffer
top.content.byteslice(0, start_byte)&.length || 0
end

def end_char
top = buffer.top_buffer
top.content.byteslice(0, end_byte)&.length || 0
end

# @deprecated Use `start_char` or `start_byte` instead.
def start_pos
RBS.print_warning { "`RBS::Location#start_pos` is deprecated. Use `start_char` or `start_byte` instead." }
start_char
end

# @deprecated Use `end_char` or `end_byte` instead.
def end_pos
RBS.print_warning { "`RBS::Location#end_pos` is deprecated. Use `end_char` or `end_byte` instead." }
end_char
end

def name
buffer.name
end
Expand All @@ -44,54 +66,80 @@ def start_line
start_loc[0]
end

def start_column
def start_byte_column
start_loc[1]
end

def start_char_column
top = buffer.top_buffer
line, byte_col = top.pos_to_loc(start_byte)
line_range = top.ranges[line - 1] or return 0
top.content.byteslice(line_range.begin, byte_col)&.length || 0
end

def end_byte_column
end_loc[1]
end

def end_char_column
top = buffer.top_buffer
line, byte_col = top.pos_to_loc(end_byte)
line_range = top.ranges[line - 1] or return 0
top.content.byteslice(line_range.begin, byte_col)&.length || 0
end

# @deprecated Use `start_byte_column` or `start_char_column` instead.
def start_column
RBS.print_warning { "`RBS::Location#start_column` is deprecated. Use `start_byte_column` or `start_char_column` instead." }
start_byte_column
end

def end_line
end_loc[0]
end

# @deprecated Use `end_byte_column` or `end_char_column` instead.
def end_column
end_loc[1]
RBS.print_warning { "`RBS::Location#end_column` is deprecated. Use `end_byte_column` or `end_char_column` instead." }
end_byte_column
end

def start_loc
@start_loc ||= buffer.top_buffer.pos_to_loc(start_pos)
@start_loc ||= buffer.top_buffer.pos_to_loc(start_byte)
end

def end_loc
@end_loc ||= buffer.top_buffer.pos_to_loc(end_pos)
@end_loc ||= buffer.top_buffer.pos_to_loc(end_byte)
end

def range
@range ||= start_pos...end_pos
@range ||= start_byte...end_byte
end

def source
@source ||= (buffer.top_buffer.content[range] || raise)
@source ||= (buffer.top_buffer.content.byteslice(start_byte, end_byte - start_byte) || raise)
end

def to_s
"#{name || "-"}:#{start_line}:#{start_column}...#{end_line}:#{end_column}"
"#{name || "-"}:#{start_line}:#{start_byte_column}...#{end_line}:#{end_byte_column}"
end

def ==(other)
other.is_a?(Location) &&
other.buffer == buffer &&
other.start_pos == start_pos &&
other.end_pos == end_pos
other.start_byte == start_byte &&
other.end_byte == end_byte
end

def to_json(state = nil)
{
start: {
line: start_line,
column: start_column
column: start_byte_column
},
end: {
line: end_line,
column: end_column
column: end_byte_column
},
buffer: {
name: name&.to_s
Expand Down
47 changes: 42 additions & 5 deletions lib/rbs/locator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,16 @@ def initialize(buffer:, dirs:, decls:)
@decls = decls
end

def find(line:, column:)
pos = buffer.loc_to_pos([line, column])
# Find RBS elements at the given position.
#
# Returns a list of components, inner component comes first.
#
# @param line [Integer] Line number (1-origin)
# @param byte_column [Integer] Byte offset within the line (0-origin)
# @param char_column [Integer] Character offset within the line (0-origin). Converted to byte offset internally.
# @param column [Integer] Deprecated. Treated as char column for backwards compatibility.
def find(line:, column: nil, byte_column: nil, char_column: nil)
pos = resolve_position(line: line, column: column, byte_column: byte_column, char_column: char_column)

dirs.each do |dir|
array = [] #: Array[component]
Expand All @@ -26,8 +34,14 @@ def find(line:, column:)
[]
end

def find2(line:, column:)
path = find(line: line, column: column)
# Find RBS elements at the given position, returning the inner most symbol and outer components.
#
# @param line [Integer] Line number (1-origin)
# @param byte_column [Integer] Byte offset within the line (0-origin)
# @param char_column [Integer] Character offset within the line (0-origin). Converted to byte offset internally.
# @param column [Integer] Deprecated. Treated as char column for backwards compatibility.
def find2(line:, column: nil, byte_column: nil, char_column: nil)
path = find(line: line, column: column, byte_column: byte_column, char_column: char_column)

return if path.empty?

Expand Down Expand Up @@ -238,10 +252,33 @@ def find_in_loc(pos, location:, array:)

def test_loc(pos, location:)
if location
location.start_pos <= pos && pos <= location.end_pos
location.start_byte <= pos && pos <= location.end_byte
else
false
end
end

private

# Converts char column to byte column within a line.
def char_column_to_byte_column(line, char_column) #: Integer
line_range = buffer.ranges[line - 1] or return 0
line_content = buffer.content.byteslice(line_range) or return 0
prefix = line_content.encode(Encoding::UTF_8).chars.first(char_column).join
prefix.bytesize
end

def resolve_position(line:, column:, byte_column:, char_column:) #: Integer
if byte_column
buffer.loc_to_pos([line, byte_column])
elsif char_column
buffer.loc_to_pos([line, char_column_to_byte_column(line, char_column)])
elsif column
RBS.print_warning { "`column` keyword argument of RBS::Locator#find is deprecated. Use `char_column` or `byte_column` instead." }
buffer.loc_to_pos([line, char_column_to_byte_column(line, column)])
else
raise ArgumentError, "One of `byte_column`, `char_column`, or `column` must be specified"
end
end
end
end
2 changes: 1 addition & 1 deletion lib/rbs/parser_aux.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def self.parse_signature(source)
resolved = magic_comment(buf)
start_pos =
if resolved
(resolved.location || raise).end_pos
(resolved.location || raise).end_byte
else
0
end
Expand Down
Loading
Loading