-
Notifications
You must be signed in to change notification settings - Fork 30
Integrate document symbol for callbacks #280
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,63 @@ class DocumentSymbol | |
include Requests::Support::Common | ||
include ActiveSupportTestCaseHelper | ||
|
||
MODEL_CALLBACKS = T.let( | ||
[ | ||
"before_validation", | ||
"after_validation", | ||
"before_save", | ||
"around_save", | ||
"after_save", | ||
"before_create", | ||
"around_create", | ||
"after_create", | ||
"after_commit", | ||
"after_rollback", | ||
"before_update", | ||
"around_update", | ||
"after_update", | ||
"before_destroy", | ||
"around_destroy", | ||
"after_destroy", | ||
"after_initialize", | ||
"after_find", | ||
"after_touch", | ||
].freeze, | ||
T::Array[String], | ||
) | ||
|
||
CONTROLLER_CALLBACKS = T.let( | ||
[ | ||
"after_action", | ||
"append_after_action", | ||
"append_around_action", | ||
"append_before_action", | ||
"around_action", | ||
"before_action", | ||
"prepend_after_action", | ||
"prepend_around_action", | ||
"prepend_before_action", | ||
"skip_after_action", | ||
"skip_around_action", | ||
"skip_before_action", | ||
].freeze, | ||
T::Array[String], | ||
) | ||
|
||
JOB_CALLBACKS = T.let( | ||
[ | ||
"after_enqueue", | ||
"after_perform", | ||
"around_enqueue", | ||
"around_perform", | ||
"before_enqueue", | ||
"before_perform", | ||
].freeze, | ||
T::Array[String], | ||
) | ||
|
||
CALLBACKS = T.let((MODEL_CALLBACKS + CONTROLLER_CALLBACKS + JOB_CALLBACKS).freeze, T::Array[String]) | ||
|
||
sig do | ||
params( | ||
response_builder: ResponseBuilders::DocumentSymbol, | ||
|
@@ -28,13 +85,115 @@ def initialize(response_builder, dispatcher) | |
def on_call_node_enter(node) | ||
content = extract_test_case_name(node) | ||
|
||
return unless content | ||
if content | ||
append_document_symbol( | ||
name: content, | ||
selection_range: range_from_node(node), | ||
range: range_from_node(node), | ||
) | ||
end | ||
|
||
extract_callbacks(node) | ||
end | ||
|
||
private | ||
|
||
sig { params(node: Prism::CallNode).void } | ||
def extract_callbacks(node) | ||
receiver = node.receiver | ||
return if receiver && !receiver.is_a?(Prism::SelfNode) | ||
|
||
message_value = node.message | ||
|
||
return unless CALLBACKS.include?(message_value) | ||
|
||
block = node.block | ||
|
||
if block | ||
append_document_symbol( | ||
name: "#{message_value}(<anonymous>)", | ||
range: range_from_location(node.location), | ||
selection_range: range_from_location(block.location), | ||
) | ||
return | ||
end | ||
|
||
arguments = node.arguments&.arguments | ||
return unless arguments&.any? | ||
|
||
arguments.each do |argument| | ||
case argument | ||
when Prism::SymbolNode | ||
name = argument.value | ||
next unless name | ||
|
||
append_document_symbol( | ||
name: "#{message_value}(#{name})", | ||
range: range_from_location(argument.location), | ||
selection_range: range_from_location(T.must(argument.value_loc)), | ||
) | ||
when Prism::StringNode | ||
name = argument.content | ||
next if name.empty? | ||
|
||
append_document_symbol( | ||
name: "#{message_value}(#{name})", | ||
range: range_from_location(argument.location), | ||
selection_range: range_from_location(argument.content_loc), | ||
) | ||
when Prism::LambdaNode | ||
append_document_symbol( | ||
name: "#{message_value}(<anonymous>)", | ||
range: range_from_location(node.location), | ||
selection_range: range_from_location(argument.location), | ||
) | ||
when Prism::CallNode | ||
arg_receiver = argument.receiver | ||
|
||
name = arg_receiver.name if arg_receiver.is_a?(Prism::ConstantReadNode) | ||
name = arg_receiver.full_name if arg_receiver.is_a?(Prism::ConstantPathNode) | ||
next unless name | ||
|
||
append_document_symbol( | ||
name: "#{message_value}(#{name})", | ||
range: range_from_location(argument.location), | ||
selection_range: range_from_location(argument.location), | ||
) | ||
when Prism::ConstantReadNode | ||
name = argument.name | ||
next if name.empty? | ||
|
||
append_document_symbol( | ||
name: "#{message_value}(#{name})", | ||
range: range_from_location(argument.location), | ||
selection_range: range_from_location(argument.location), | ||
) | ||
when Prism::ConstantPathNode | ||
name = argument.full_name | ||
next if name.empty? | ||
|
||
append_document_symbol( | ||
name: "#{message_value}(#{name})", | ||
range: range_from_location(argument.location), | ||
selection_range: range_from_location(argument.location), | ||
) | ||
end | ||
end | ||
end | ||
|
||
sig do | ||
params( | ||
name: String, | ||
range: RubyLsp::Interface::Range, | ||
selection_range: RubyLsp::Interface::Range, | ||
).void | ||
end | ||
def append_document_symbol(name:, range:, selection_range:) | ||
@response_builder.last.children << RubyLsp::Interface::DocumentSymbol.new( | ||
name: content, | ||
kind: LanguageServer::Protocol::Constant::SymbolKind::METHOD, | ||
selection_range: range_from_node(node), | ||
range: range_from_node(node), | ||
name: name, | ||
kind: RubyLsp::Constant::SymbolKind::METHOD, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This affects the icon of the symbol. I chose the same approach as the base Ruby LSP. The options are listed in this link — I don't think it's optimal to use any other config. |
||
range: range, | ||
selection_range: selection_range, | ||
) | ||
end | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,8 +11,6 @@ def extract_test_case_name(node) | |
message_value = node.message | ||
return unless message_value == "test" || message_value == "it" | ||
|
||
return unless node.arguments | ||
|
||
Comment on lines
-14
to
-15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not in the direct scope of this PR, but I've kept it to a separate commit; it is used by the |
||
arguments = node.arguments&.arguments | ||
return unless arguments&.any? | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,5 @@ | |
# frozen_string_literal: true | ||
|
||
class User < ApplicationRecord | ||
before_create :foo_arg, -> () {} | ||
end |
Uh oh!
There was an error while loading. Please reload this page.