-
Notifications
You must be signed in to change notification settings - Fork 215
Support go to definition in the experimental project #812
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
scohen
merged 11 commits into
elixir-lsp:master
from
scottming:support-go-to-definition-in-experimental
Mar 7, 2023
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
2db7a34
Support go to definition in experimental project
scottming 5470d24
Fix the nil bug and add the request->handler to the queue
scottming e398488
Remove a unneed line
scottming 39190a3
Rename the test file and move the duplicated logic to code_mod folder
scottming f0e60f4
Rename location variables
scottming f4a35fc
Apply suggestions from code review
scottming d9b2abe
Apply the remaining suggestions
scottming ac49290
Apply flowing suggestions
scottming e30e11f
Fix typo
scottming 59c101b
Rename an arrange function name
scottming a3ed366
Use setup instead of private_function in the definition test
scottming File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
apps/language_server/lib/language_server/experimental/provider/handlers/goto_definition.ex
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
defmodule ElixirLS.LanguageServer.Experimental.Provider.Handlers.GotoDefinition do | ||
alias ElixirLS.LanguageServer.Experimental.Protocol.Requests.GotoDefinition | ||
alias ElixirLS.LanguageServer.Experimental.Protocol.Responses | ||
alias ElixirLS.LanguageServer.Experimental.SourceFile | ||
alias ElixirLS.LanguageServer.Experimental.SourceFile.Conversions | ||
require Logger | ||
|
||
def handle(%GotoDefinition{} = request, _) do | ||
source_file = request.source_file | ||
pos = request.position | ||
|
||
maybe_location = | ||
source_file |> SourceFile.to_string() |> ElixirSense.definition(pos.line, pos.character + 1) | ||
|
||
case to_response(request.id, maybe_location, source_file) do | ||
{:ok, response} -> | ||
{:reply, response} | ||
|
||
{:error, reason} -> | ||
Logger.error("GotoDefinition conversion failed: #{inspect(reason)}") | ||
{:error, Responses.GotoDefinition.error(request.id, :request_failed, inspect(reason))} | ||
end | ||
end | ||
|
||
defp to_response(request_id, %ElixirSense.Location{} = location, %SourceFile{} = source_file) do | ||
with {:ok, lsp_location} <- Conversions.to_lsp(location, source_file) do | ||
{:ok, Responses.GotoDefinition.new(request_id, lsp_location)} | ||
end | ||
end | ||
|
||
defp to_response(request_id, nil, _source_file) do | ||
{:ok, Responses.GotoDefinition.new(request_id, nil)} | ||
end | ||
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
210 changes: 210 additions & 0 deletions
210
apps/language_server/test/experimental/provider/handlers/goto_definition_test.exs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
defmodule ElixirLS.Experimental.Provider.Handlers.GotoDefinitionTest do | ||
use ExUnit.Case, async: true | ||
|
||
alias ElixirLS.LanguageServer.Experimental.Protocol.Requests.GotoDefinition | ||
alias ElixirLS.LanguageServer.Experimental.Protocol.Responses | ||
alias ElixirLS.LanguageServer.Experimental.Provider.Env | ||
alias ElixirLS.LanguageServer.Experimental.Provider.Handlers | ||
alias ElixirLS.LanguageServer.Experimental.SourceFile | ||
alias ElixirLS.LanguageServer.Experimental.SourceFile.Conversions | ||
|
||
alias ElixirLS.LanguageServer.Fixtures.LspProtocol | ||
alias ElixirLS.LanguageServer.Test.FixtureHelpers | ||
|
||
import LspProtocol | ||
import ElixirLS.Test.TextLoc, only: [annotate_assert: 4] | ||
|
||
setup do | ||
{:ok, _} = start_supervised(SourceFile.Store) | ||
:ok | ||
end | ||
|
||
def request(file_path, line, char) do | ||
uri = Conversions.ensure_uri(file_path) | ||
|
||
params = [ | ||
text_document: [uri: uri], | ||
position: [line: line, character: char] | ||
] | ||
|
||
with {:ok, contents} <- File.read(file_path), | ||
:ok <- SourceFile.Store.open(uri, contents, 1), | ||
{:ok, req} <- build(GotoDefinition, params) do | ||
GotoDefinition.to_elixir(req) | ||
end | ||
end | ||
|
||
def handle(request) do | ||
Handlers.GotoDefinition.handle(request, Env.new()) | ||
end | ||
|
||
def with_referenced_file(_) do | ||
path = FixtureHelpers.get_path("references_referenced.ex") | ||
uri = Conversions.ensure_uri(path) | ||
{:ok, file_uri: uri, file_path: path} | ||
end | ||
|
||
describe "when a file contains references" do | ||
setup [:with_referenced_file] | ||
|
||
test "find definition remote function call", %{file_uri: uri} do | ||
file_path = FixtureHelpers.get_path("references_remote.ex") | ||
{line, char} = {4, 28} | ||
|
||
{:ok, request} = request(file_path, line, char) | ||
|
||
annotate_assert(file_path, line, char, """ | ||
ReferencesReferenced.referenced_fun() | ||
^ | ||
""") | ||
|
||
{:reply, %Responses.GotoDefinition{result: definition}} = handle(request) | ||
|
||
assert definition.uri == uri | ||
assert definition.range.start.line == 1 | ||
assert definition.range.start.character == 6 | ||
assert definition.range.end.line == 1 | ||
assert definition.range.end.character == 6 | ||
end | ||
|
||
test "find definition remote macro call", %{file_uri: uri} do | ||
file_path = FixtureHelpers.get_path("references_remote.ex") | ||
{line, char} = {8, 28} | ||
|
||
{:ok, request} = request(file_path, line, char) | ||
|
||
annotate_assert(file_path, line, char, """ | ||
ReferencesReferenced.referenced_macro a do | ||
^ | ||
""") | ||
|
||
{:reply, %Responses.GotoDefinition{result: definition}} = handle(request) | ||
|
||
assert definition.uri == uri | ||
assert definition.range.start.line == 8 | ||
assert definition.range.start.character == 11 | ||
assert definition.range.end.line == 8 | ||
assert definition.range.end.character == 11 | ||
end | ||
|
||
test "find definition imported function call", %{file_uri: uri} do | ||
file_path = FixtureHelpers.get_path("references_imported.ex") | ||
{line, char} = {4, 5} | ||
|
||
{:ok, request} = request(file_path, line, char) | ||
|
||
annotate_assert(file_path, line, char, """ | ||
referenced_fun() | ||
^ | ||
""") | ||
|
||
{:reply, %Responses.GotoDefinition{result: definition}} = handle(request) | ||
|
||
assert definition.uri == uri | ||
assert definition.range.start.line == 1 | ||
assert definition.range.start.character == 6 | ||
assert definition.range.end.line == 1 | ||
assert definition.range.end.character == 6 | ||
end | ||
|
||
test "find definition imported macro call", %{file_uri: uri} do | ||
file_path = FixtureHelpers.get_path("references_imported.ex") | ||
{line, char} = {8, 5} | ||
|
||
{:ok, request} = request(file_path, line, char) | ||
|
||
annotate_assert(file_path, line, char, """ | ||
referenced_macro a do | ||
^ | ||
""") | ||
|
||
{:reply, %Responses.GotoDefinition{result: definition}} = handle(request) | ||
|
||
assert definition.uri == uri | ||
assert definition.range.start.line == 8 | ||
assert definition.range.start.character == 11 | ||
assert definition.range.end.line == 8 | ||
assert definition.range.end.character == 11 | ||
end | ||
|
||
test "find definition local function call", %{file_uri: uri} do | ||
file_path = FixtureHelpers.get_path("references_referenced.ex") | ||
{line, char} = {15, 5} | ||
|
||
{:ok, request} = request(file_path, line, char) | ||
|
||
annotate_assert(file_path, line, char, """ | ||
referenced_fun() | ||
^ | ||
""") | ||
|
||
{:reply, %Responses.GotoDefinition{result: definition}} = handle(request) | ||
|
||
assert definition.uri == uri | ||
assert definition.range.start.line == 1 | ||
assert definition.range.start.character == 6 | ||
assert definition.range.end.line == 1 | ||
assert definition.range.end.character == 6 | ||
end | ||
|
||
test "find definition local macro call", %{file_uri: uri} do | ||
file_path = FixtureHelpers.get_path("references_referenced.ex") | ||
{line, char} = {19, 5} | ||
|
||
{:ok, request} = request(file_path, line, char) | ||
|
||
annotate_assert(file_path, line, char, """ | ||
referenced_macro a do | ||
^ | ||
""") | ||
|
||
{:reply, %Responses.GotoDefinition{result: definition}} = handle(request) | ||
|
||
assert definition.uri == uri | ||
assert definition.range.start.line == 8 | ||
assert definition.range.start.character == 11 | ||
assert definition.range.end.line == 8 | ||
assert definition.range.end.character == 11 | ||
end | ||
|
||
test "find definition variable", %{file_uri: uri} do | ||
file_path = FixtureHelpers.get_path("references_referenced.ex") | ||
{line, char} = {4, 13} | ||
|
||
{:ok, request} = request(file_path, line, char) | ||
|
||
annotate_assert(file_path, line, char, """ | ||
IO.puts(referenced_variable + 1) | ||
^ | ||
""") | ||
|
||
{:reply, %Responses.GotoDefinition{result: definition}} = handle(request) | ||
|
||
assert definition.uri == uri | ||
assert definition.range.start.line == 2 | ||
assert definition.range.start.character == 4 | ||
assert definition.range.end.line == 2 | ||
assert definition.range.end.character == 4 | ||
end | ||
|
||
test "find definition attribute", %{file_uri: uri} do | ||
file_path = FixtureHelpers.get_path("references_referenced.ex") | ||
{line, char} = {27, 5} | ||
|
||
{:ok, request} = request(file_path, line, char) | ||
|
||
annotate_assert(file_path, line, char, """ | ||
@referenced_attribute | ||
^ | ||
""") | ||
|
||
{:reply, %Responses.GotoDefinition{result: definition}} = handle(request) | ||
|
||
assert definition.uri == uri | ||
assert definition.range.start.line == 24 | ||
assert definition.range.start.character == 2 | ||
assert definition.range.end.line == 24 | ||
assert definition.range.end.character == 2 | ||
end | ||
end | ||
end |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.