class RubyLsp::Listeners::DocumentSymbol
def create_document_symbol(name:, kind:, range_location:, selection_range_location:)
def create_document_symbol(name:, kind:, range_location:, selection_range_location:) name = "<blank>" if name.empty? symbol = Interface::DocumentSymbol.new( name: name, kind: kind, range: range_from_location(range_location), selection_range: range_from_location(selection_range_location), children: [], ) @response_builder.last.children << symbol symbol end
def handle_alias_method(node)
def handle_alias_method(node) receiver = node.receiver return if receiver && !receiver.is_a?(Prism::SelfNode) arguments = node.arguments return unless arguments new_name_argument = arguments.arguments.first if new_name_argument.is_a?(Prism::SymbolNode) name = new_name_argument.value return unless name create_document_symbol( name: name, kind: Constant::SymbolKind::METHOD, range_location: new_name_argument.location, selection_range_location: T.must(new_name_argument.value_loc), ) elsif new_name_argument.is_a?(Prism::StringNode) name = new_name_argument.content return if name.empty? create_document_symbol( name: name, kind: Constant::SymbolKind::METHOD, range_location: new_name_argument.location, selection_range_location: new_name_argument.content_loc, ) end end
def handle_attr_accessor(node)
def handle_attr_accessor(node) receiver = node.receiver return if receiver && !receiver.is_a?(Prism::SelfNode) arguments = node.arguments return unless arguments arguments.arguments.each do |argument| if argument.is_a?(Prism::SymbolNode) name = argument.value next unless name create_document_symbol( name: name, kind: Constant::SymbolKind::FIELD, range_location: argument.location, selection_range_location: T.must(argument.value_loc), ) elsif argument.is_a?(Prism::StringNode) name = argument.content next if name.empty? create_document_symbol( name: name, kind: Constant::SymbolKind::FIELD, range_location: argument.location, selection_range_location: argument.content_loc, ) end end end
def handle_rake_namespace(node)
def handle_rake_namespace(node) return unless rake? return if node.receiver arguments = node.arguments return unless arguments name_argument = arguments.arguments.first return unless name_argument name = case name_argument when Prism::StringNode then name_argument.content when Prism::SymbolNode then name_argument.value end return if name.nil? || name.empty? @response_builder << create_document_symbol( name: name, kind: Constant::SymbolKind::MODULE, range_location: name_argument.location, selection_range_location: name_argument.location, ) end
def handle_rake_task(node)
def handle_rake_task(node) return unless rake? return if node.receiver arguments = node.arguments return unless arguments name_argument = arguments.arguments.first return unless name_argument name = case name_argument when Prism::StringNode then name_argument.content when Prism::SymbolNode then name_argument.value when Prism::KeywordHashNode first_element = name_argument.elements.first if first_element.is_a?(Prism::AssocNode) key = first_element.key case key when Prism::StringNode then key.content when Prism::SymbolNode then key.value end end end return if name.nil? || name.empty? create_document_symbol( name: name, kind: Constant::SymbolKind::METHOD, range_location: name_argument.location, selection_range_location: name_argument.location, ) end
def initialize(response_builder, uri, dispatcher)
def initialize(response_builder, uri, dispatcher) @response_builder = response_builder @uri = uri dispatcher.register( self, :on_class_node_enter, :on_class_node_leave, :on_call_node_enter, :on_call_node_leave, :on_constant_path_write_node_enter, :on_constant_write_node_enter, :on_constant_path_or_write_node_enter, :on_constant_path_operator_write_node_enter, :on_constant_path_and_write_node_enter, :on_constant_or_write_node_enter, :on_constant_operator_write_node_enter, :on_constant_and_write_node_enter, :on_constant_target_node_enter, :on_constant_path_target_node_enter, :on_def_node_enter, :on_def_node_leave, :on_module_node_enter, :on_module_node_leave, :on_instance_variable_write_node_enter, :on_class_variable_write_node_enter, :on_singleton_class_node_enter, :on_singleton_class_node_leave, :on_alias_method_node_enter, ) end
def on_alias_method_node_enter(node)
def on_alias_method_node_enter(node) new_name_node = node.new_name return unless new_name_node.is_a?(Prism::SymbolNode) name = new_name_node.value return unless name create_document_symbol( name: name, kind: Constant::SymbolKind::METHOD, range_location: new_name_node.location, selection_range_location: T.must(new_name_node.value_loc), ) end
def on_call_node_enter(node)
def on_call_node_enter(node) node_name = node.name if ATTR_ACCESSORS.include?(node_name) handle_attr_accessor(node) elsif node_name == :alias_method handle_alias_method(node) elsif node_name == :namespace handle_rake_namespace(node) elsif node_name == :task handle_rake_task(node) end end
def on_call_node_leave(node)
def on_call_node_leave(node) return unless rake? if node.name == :namespace && !node.receiver @response_builder.pop end end
def on_class_node_enter(node)
def on_class_node_enter(node) @response_builder << create_document_symbol( name: node.constant_path.location.slice, kind: Constant::SymbolKind::CLASS, range_location: node.location, selection_range_location: node.constant_path.location, ) end
def on_class_node_leave(node)
def on_class_node_leave(node) @response_builder.pop end
def on_class_variable_write_node_enter(node)
def on_class_variable_write_node_enter(node) create_document_symbol( name: node.name.to_s, kind: Constant::SymbolKind::VARIABLE, range_location: node.name_loc, selection_range_location: node.name_loc, ) end
def on_constant_and_write_node_enter(node)
def on_constant_and_write_node_enter(node) create_document_symbol( name: node.name.to_s, kind: Constant::SymbolKind::CONSTANT, range_location: node.location, selection_range_location: node.name_loc, ) end
def on_constant_operator_write_node_enter(node)
def on_constant_operator_write_node_enter(node) create_document_symbol( name: node.name.to_s, kind: Constant::SymbolKind::CONSTANT, range_location: node.location, selection_range_location: node.name_loc, ) end
def on_constant_or_write_node_enter(node)
def on_constant_or_write_node_enter(node) create_document_symbol( name: node.name.to_s, kind: Constant::SymbolKind::CONSTANT, range_location: node.location, selection_range_location: node.name_loc, ) end
def on_constant_path_and_write_node_enter(node)
def on_constant_path_and_write_node_enter(node) create_document_symbol( name: node.target.location.slice, kind: Constant::SymbolKind::CONSTANT, range_location: node.location, selection_range_location: node.target.location, ) end
def on_constant_path_operator_write_node_enter(node)
def on_constant_path_operator_write_node_enter(node) create_document_symbol( name: node.target.location.slice, kind: Constant::SymbolKind::CONSTANT, range_location: node.location, selection_range_location: node.target.location, ) end
def on_constant_path_or_write_node_enter(node)
def on_constant_path_or_write_node_enter(node) create_document_symbol( name: node.target.location.slice, kind: Constant::SymbolKind::CONSTANT, range_location: node.location, selection_range_location: node.target.location, ) end
def on_constant_path_target_node_enter(node)
def on_constant_path_target_node_enter(node) create_document_symbol( name: node.slice, kind: Constant::SymbolKind::CONSTANT, range_location: node.location, selection_range_location: node.location, ) end
def on_constant_path_write_node_enter(node)
def on_constant_path_write_node_enter(node) create_document_symbol( name: node.target.location.slice, kind: Constant::SymbolKind::CONSTANT, range_location: node.location, selection_range_location: node.target.location, ) end
def on_constant_target_node_enter(node)
def on_constant_target_node_enter(node) create_document_symbol( name: node.name.to_s, kind: Constant::SymbolKind::CONSTANT, range_location: node.location, selection_range_location: node.location, ) end
def on_constant_write_node_enter(node)
def on_constant_write_node_enter(node) create_document_symbol( name: node.name.to_s, kind: Constant::SymbolKind::CONSTANT, range_location: node.location, selection_range_location: node.name_loc, ) end
def on_def_node_enter(node)
def on_def_node_enter(node) receiver = node.receiver previous_symbol = @response_builder.last if receiver.is_a?(Prism::SelfNode) name = "self.#{node.name}" kind = Constant::SymbolKind::FUNCTION elsif previous_symbol.is_a?(Interface::DocumentSymbol) && previous_symbol.name.start_with?("<<") name = node.name.to_s kind = Constant::SymbolKind::FUNCTION else name = node.name.to_s kind = name == "initialize" ? Constant::SymbolKind::CONSTRUCTOR : Constant::SymbolKind::METHOD end symbol = create_document_symbol( name: name, kind: kind, range_location: node.location, selection_range_location: node.name_loc, ) @response_builder << symbol end
def on_def_node_leave(node)
def on_def_node_leave(node) @response_builder.pop end
def on_instance_variable_write_node_enter(node)
def on_instance_variable_write_node_enter(node) create_document_symbol( name: node.name.to_s, kind: Constant::SymbolKind::VARIABLE, range_location: node.name_loc, selection_range_location: node.name_loc, ) end
def on_module_node_enter(node)
def on_module_node_enter(node) @response_builder << create_document_symbol( name: node.constant_path.location.slice, kind: Constant::SymbolKind::MODULE, range_location: node.location, selection_range_location: node.constant_path.location, ) end
def on_module_node_leave(node)
def on_module_node_leave(node) @response_builder.pop end
def on_singleton_class_node_enter(node)
def on_singleton_class_node_enter(node) expression = node.expression @response_builder << create_document_symbol( name: "<< #{expression.slice}", kind: Constant::SymbolKind::NAMESPACE, range_location: node.location, selection_range_location: expression.location, ) end
def on_singleton_class_node_leave(node)
def on_singleton_class_node_leave(node) @response_builder.pop end
def rake?
def rake? if (path = @uri.to_standardized_path) path.match?(/(Rakefile|\.rake)$/) else false end end