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
2 changes: 2 additions & 0 deletions lib/ruby_indexer/lib/ruby_indexer/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ def constant_name(node)
case node
when Prism::ConstantPathNode, Prism::ConstantReadNode, Prism::ConstantPathTargetNode
node.full_name
when Prism::ConstantWriteNode, Prism::ConstantTargetNode
node.name.to_s
end
rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
Prism::ConstantPathNode::MissingNodesInConstantPathError
Expand Down
6 changes: 6 additions & 0 deletions lib/ruby_indexer/test/index_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2262,6 +2262,12 @@ def test_constant_name
node = Prism.parse("class Foo; end").value.statements.body.first.constant_path
assert_equal("Foo", Index.constant_name(node))

node = Prism.parse("Foo = 1").value.statements.body.first
assert_equal("Foo", Index.constant_name(node))

node = Prism.parse("Foo, Bar = 1, 2").value.statements.body.first.lefts.first
assert_equal("Foo", Index.constant_name(node))

node = Prism.parse(<<~RUBY).value.statements.body.first.constant_path
class class Foo
end
Expand Down
11 changes: 9 additions & 2 deletions lib/ruby_lsp/requests/prepare_rename.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ def perform
node_context = RubyDocument.locate(
@document.ast,
char_position,
node_types: [Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::ConstantPathTargetNode],
node_types: [
Prism::ConstantReadNode,
Prism::ConstantPathNode,
Prism::ConstantPathTargetNode,
Prism::ConstantWriteNode,
Prism::ConstantTargetNode,
],
code_units_cache: @document.code_units_cache,
)
target = node_context.node
Expand All @@ -39,7 +45,8 @@ def perform
)
end

range_from_location(target.location)
location = target.is_a?(Prism::ConstantWriteNode) ? target.name_loc : target.location
range_from_location(location)
end
end
end
Expand Down
10 changes: 8 additions & 2 deletions lib/ruby_lsp/requests/rename.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ def perform
node_context = RubyDocument.locate(
@document.ast,
char_position,
node_types: [Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::ConstantPathTargetNode],
node_types: [
Prism::ConstantReadNode,
Prism::ConstantPathNode,
Prism::ConstantPathTargetNode,
Prism::ConstantWriteNode,
Prism::ConstantTargetNode,
],
code_units_cache: @document.code_units_cache,
)
target = node_context.node
Expand All @@ -51,7 +57,7 @@ def perform
)
end

target = target #: as Prism::ConstantReadNode | Prism::ConstantPathNode | Prism::ConstantPathTargetNode
target = target #: as Prism::ConstantReadNode | Prism::ConstantPathNode | Prism::ConstantPathTargetNode | Prism::ConstantWriteNode | Prism::ConstantTargetNode

name = RubyIndexer::Index.constant_name(target)
return unless name
Expand Down
29 changes: 29 additions & 0 deletions test/requests/prepare_rename_expectations_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,35 @@ def run_expectations(source)
RubyLsp::Requests::PrepareRename.new(document, position).perform
end

def test_constant_definition
source = <<~RUBY
Foo = 1
Bar, Baz = 2, 3
RUBY
uri = URI("file:///fake.rb")
document = RubyLsp::RubyDocument.new(source: source, version: 1, uri: uri, global_state: @global_state)

range = RubyLsp::Requests::PrepareRename.new(
document,
{ line: 0, character: 1 },
).perform #: as !nil

assert_equal(0, range.start.line)
assert_equal(0, range.start.character)
assert_equal(0, range.end.line)
assert_equal(3, range.end.character)

range = RubyLsp::Requests::PrepareRename.new(
document,
{ line: 1, character: 1 },
).perform #: as !nil

assert_equal(1, range.start.line)
assert_equal(0, range.start.character)
assert_equal(1, range.end.line)
assert_equal(3, range.end.character)
end

private

def default_position
Expand Down
57 changes: 57 additions & 0 deletions test/requests/rename_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,65 @@ class RenameMe
assert_equal("NewMe", untitled_change.edits[0].new_text)
end

def test_renaming_from_constant_definition
source = <<~RUBY
Foo = 1
Foo
RUBY
expected = <<~RUBY
Renamed = 1
Renamed
RUBY

assert_equal(expected, rename_source(source, { line: 0, character: 1 }))
end

def test_renaming_from_constant_target
source = <<~RUBY
Foo, Bar = 1, 2
Foo
Bar
RUBY
expected = <<~RUBY
Renamed, Bar = 1, 2
Renamed
Bar
RUBY

assert_equal(expected, rename_source(source, { line: 0, character: 1 }))
end

private

def rename_source(source, position)
source = source.dup
global_state = RubyLsp::GlobalState.new
uri = URI("untitled:constant-definition")
global_state.index.index_single(uri, source)
store = RubyLsp::Store.new(global_state)
document = store.set(
uri: uri,
source: source,
version: 1,
language_id: :ruby,
)

workspace_edit = RubyLsp::Requests::Rename.new(
global_state,
store,
document,
{ position: position, newName: "Renamed" },
).perform #: as !nil

document.push_edits(
workspace_edit.changes.fetch(uri.to_s).map do |edit|
{ range: edit.range.to_hash.transform_values(&:to_hash), text: edit.new_text }
end,
version: 2,
)
document.source
end

def expect_renames(fixture_path, new_fixture_path, expected, position, new_name)
source = File.read(fixture_path)
global_state = RubyLsp::GlobalState.new
Expand Down
Loading