Skip to content

Commit

Permalink
Support DocumentLink request
Browse files Browse the repository at this point in the history
This request uses the gem source comments generated by Tapioca to
let users quickly jump to the actual source of the definition.
  • Loading branch information
st0012 committed Jul 26, 2022
1 parent fb31d48 commit 777097a
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/ruby_lsp/requests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module RubyLsp
# Supported features
#
# - {RubyLsp::Requests::DocumentSymbol}
# - {RubyLsp::Requests::DocumentLink}
# - {RubyLsp::Requests::FoldingRanges}
# - {RubyLsp::Requests::SelectionRanges}
# - {RubyLsp::Requests::SemanticHighlighting}
Expand All @@ -15,6 +16,7 @@ module RubyLsp
module Requests
autoload :BaseRequest, "ruby_lsp/requests/base_request"
autoload :DocumentSymbol, "ruby_lsp/requests/document_symbol"
autoload :DocumentLink, "ruby_lsp/requests/document_link"
autoload :FoldingRanges, "ruby_lsp/requests/folding_ranges"
autoload :SelectionRanges, "ruby_lsp/requests/selection_ranges"
autoload :SemanticHighlighting, "ruby_lsp/requests/semantic_highlighting"
Expand Down
40 changes: 40 additions & 0 deletions lib/ruby_lsp/requests/document_link.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# typed: strict
# frozen_string_literal: true

module RubyLsp
module Requests
class DocumentLink < BaseRequest
extend T::Sig

sig { params(document: Document).void }
def initialize(document)
super

@links = T.let([], T::Array[LanguageServer::Protocol::Interface::DocumentLink])
end

sig { override.returns(T.all(T::Array[LanguageServer::Protocol::Interface::DocumentLink], Object)) }
def run
visit(@document.tree)
@links
end

sig { params(node: SyntaxTree::Comment).void }
def visit_comment(node)
match = node.value.match(%r{source://(?<path>.*):(?<line>\d+)$})
return unless match

file_path = File.join(Bundler.bundle_path, "gems", match[:path])
return unless File.exist?(file_path)

target = "file://#{file_path}##{match[:line]}"

@links << LanguageServer::Protocol::Interface::DocumentLink.new(
range: range_from_syntax_tree_node(node),
target: target,
tooltip: "Jump to the source"
)
end
end
end
end
11 changes: 11 additions & 0 deletions lib/ruby_lsp/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ module RubyLsp
)
end

document_link_provider = if enabled_features.include?("documentLink")
Interface::DocumentLinkOptions.new(resolve_provider: false)
end

folding_ranges_provider = if enabled_features.include?("foldingRanges")
Interface::FoldingRangeClientCapabilities.new(line_folding_only: true)
end
Expand All @@ -45,6 +49,7 @@ module RubyLsp
),
selection_range_provider: enabled_features.include?("selectionRanges"),
document_symbol_provider: document_symbol_provider,
document_link_provider: document_link_provider,
folding_range_provider: folding_ranges_provider,
semantic_tokens_provider: semantic_tokens_provider,
document_formatting_provider: enabled_features.include?("formatting"),
Expand Down Expand Up @@ -85,6 +90,12 @@ module RubyLsp
end
end

on("testDocument/documentLink") do |request|
store.cache_fetch(request.dig(:params, :textDocument, :uri), :document_link) do |document|
RubyLsp::Requests::DocumentLink.new(document).run
end
end

on("textDocument/foldingRange") do |request|
store.cache_fetch(request.dig(:params, :textDocument, :uri), :folding_ranges) do |document|
Requests::FoldingRanges.new(document).run
Expand Down
9 changes: 9 additions & 0 deletions test/expectations/document_link/gem_source_comment.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"result": [
{
"range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 50}},
"target": "file://BUNDLER_PATH/gems/syntax_tree-3.0.0/lib/syntax_tree.rb#39",
"tooltip": "Jump to the source"
}
]
}
3 changes: 3 additions & 0 deletions test/fixtures/gem_source_comment.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# source://syntax_tree-3.0.0/lib/syntax_tree.rb:39
def foo
end
20 changes: 20 additions & 0 deletions test/requests/document_link_expectations_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# typed: true
# frozen_string_literal: true

require "test_helper"
require "expectations/expectations_test_runner"

class DocumentLinkExpectationsTest < ExpectationsTestRunner
expectations_tests RubyLsp::Requests::DocumentLink, "document_link"

def assert_expectations(source, expected)
actual = run_expectations(source)
assert_equal(map_expectations(json_expectations(expected)), JSON.parse(actual.to_json))
end

def map_expectations(expectations)
expectations.each do |expectation|
expectation["target"] = expectation["target"].sub("BUNDLER_PATH", Bundler.bundle_path.to_s)
end
end
end

0 comments on commit 777097a

Please sign in to comment.