Skip to content
Open
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
5 changes: 4 additions & 1 deletion .github/workflows/plugins.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,12 @@ jobs:
- name: clone https://github.com/lekemula/solargraph-rspec/
run: |
cd ..
git clone https://github.com/lekemula/solargraph-rspec.git
# git clone https://github.com/lekemula/solargraph-rspec.git

# pending https://github.com/lekemula/solargraph-rspec/pull/31
git clone https://github.com/apiology/solargraph-rspec.git
cd solargraph-rspec
git checkout test_solargraph_prereleases
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ coverage
/Makefile
/.pryrc
/.rspec-local
vendor/cache
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
## 0.58.2 - January 19, 2026
- Avoid rbs pollution (#1146)
- Fix 'solargraph pin --references ClassName' private method call (#1150)
- Improve memory efficiency of Position class (#1054)
- Raise InvalidOffsetError for offsets > text (#1155)

## 0.58.1 - January 2, 2026
- Normalize line endings to LF (#1142)
- Normalize line endings to LF (#1142)

## 0.58.0 - January 1, 2026
- Faster constant resolution (#1083)
Expand Down
40 changes: 29 additions & 11 deletions lib/solargraph/position.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,24 @@ def inspect
# @return [Integer]
def self.to_offset text, position
return 0 if text.empty?
text.lines[0...position.line].sum(&:length) + position.character

newline_index = -1
line = -1
last_line_index = 0

# @sg-ignore flow sensitive typing should be able to handle redefinition
while (newline_index = text.index("\n", newline_index + 1)) && line <= position.line
line += 1
break if line == position.line

# @sg-ignore oflow sensitive typing should be able to handle redefinition
line_length = newline_index - last_line_index
last_line_index = newline_index
end

last_line_index += 1 if position.line > 0
# @sg-ignore flow sensitive typing should be able to handle redefinition
last_line_index + position.character
end

# Get a numeric offset for the specified text and a position identified
Expand All @@ -73,23 +90,24 @@ def self.line_char_to_offset text, line, character

# Get a position for the specified text and offset.
#
# @raise [InvalidOffsetError] if the offset is outside the text range
#
# @param text [String]
# @param offset [Integer]
# @return [Position]
def self.from_offset text, offset
raise InvalidOffsetError if offset > text.length

cursor = 0
line = 0
# @type [Integer, nil]
character = nil
text.lines.each do |l|
line_length = l.length
char_length = l.chomp.length
if cursor + char_length >= offset
character = offset - cursor
break
end
cursor += line_length
character = offset
newline_index = -1

# @sg-ignore flow sensitive typing should be able to handle redefinition
while (newline_index = text.index("\n", newline_index + 1)) && newline_index < offset
line += 1
# @sg-ignore flow sensitive typing should be able to handle redefinition
character = offset - newline_index - 1
end
character = 0 if character.nil? and (cursor - offset).between?(0, 1)
raise InvalidOffsetError if character.nil?
Expand Down
2 changes: 1 addition & 1 deletion lib/solargraph/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Solargraph
VERSION = ENV.fetch('SOLARGRAPH_FORCE_VERSION', '0.59.0.dev.1')
VERSION = ENV.fetch('SOLARGRAPH_FORCE_VERSION', '0.59.0.dev.2')
end
29 changes: 29 additions & 0 deletions spec/position_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,38 @@
expect(orig).to be(norm)
end

it 'finds offset from position' do
text = "\n class Foo\n def bar baz, boo = 'boo'\n end\n end\n "
expect(Solargraph::Position.to_offset(text, Solargraph::Position.new(0, 0))).to eq(0)
expect(Solargraph::Position.to_offset(text, Solargraph::Position.new(0, 4))).to eq(4)
expect(Solargraph::Position.to_offset(text, Solargraph::Position.new(2, 12))).to eq(29)
expect(Solargraph::Position.to_offset(text, Solargraph::Position.new(2, 27))).to eq(44)
expect(Solargraph::Position.to_offset(text, Solargraph::Position.new(3, 8))).to eq(58)
end

it 'constructs position from offset' do
text = "\n class Foo\n def bar baz, boo = 'boo'\n end\n end\n "
expect(Solargraph::Position.from_offset(text, 0)).to eq(Solargraph::Position.new(0, 0))
expect(Solargraph::Position.from_offset(text, 4)).to eq(Solargraph::Position.new(1, 3))
expect(Solargraph::Position.from_offset(text, 29)).to eq(Solargraph::Position.new(2, 12))
expect(Solargraph::Position.from_offset(text, 44)).to eq(Solargraph::Position.new(2, 27))
end

it "raises an error for objects that cannot be normalized" do
expect {
Solargraph::Position.normalize('0, 1')
}.to raise_error(ArgumentError)
end

it 'avoids fencepost errors' do
text = " class Foo\n def bar baz, boo = 'boo'\n end\n end\n "
offset = Solargraph::Position.to_offset(text, Solargraph::Position.new(3, 6))
expect(offset).to eq(67)
end

it 'avoids fencepost errors with multiple blank lines' do
text = " class Foo\n def bar baz, boo = 'boo'\n\n end\n end\n "
offset = Solargraph::Position.to_offset(text, Solargraph::Position.new(4, 6))
expect(offset).to eq(68)
end
end
Loading