class RubyLsp::Listeners::Hover

def generate_gem_hover(node)

def generate_gem_hover(node)
  first_argument = node.arguments&.arguments&.first
  return unless first_argument.is_a?(Prism::StringNode)
  spec = Gem::Specification.find_by_name(first_argument.content)
  return unless spec
  info = T.let(
    [
      spec.description,
      spec.summary,
      "This rubygem does not have a description or summary.",
    ].find { |text| !text.nil? && !text.empty? },
    String,
  )
  # Remove leading whitespace if a heredoc was used for the summary or description
  info = info.gsub(/^ +/, "")
  remote_url = [spec.homepage, spec.metadata["source_code_uri"]].compact.find do |page|
    page.start_with?(*ALLOWED_REMOTE_PROVIDERS)
  end
  @response_builder.push(
    "**#{spec.name}** (#{spec.version}) #{remote_url && " - [open remote](#{remote_url})"}",
    category: :title,
  )
  @response_builder.push(info, category: :documentation)
rescue Gem::MissingSpecError
  # Do nothing if the spec cannot be found
end

def generate_hover(name, location)

def generate_hover(name, location)
  entries = @index.resolve(name, @nesting)
  return unless entries
  # We should only show hover for private constants if the constant is defined in the same namespace as the
  # reference
  first_entry = T.must(entries.first)
  return if first_entry.visibility == :private && first_entry.name != "#{@nesting.join("::")}::#{name}"
  categorized_markdown_from_index_entries(name, entries).each do |category, content|
    @response_builder.push(content, category: category)
  end
end

def initialize(response_builder, uri, nesting, index, dispatcher, typechecker_enabled) # rubocop:disable Metrics/ParameterLists

rubocop:disable Metrics/ParameterLists
def initialize(response_builder, uri, nesting, index, dispatcher, typechecker_enabled) # rubocop:disable Metrics/ParameterLists
  @response_builder = response_builder
  @path = T.let(uri.to_standardized_path, T.nilable(String))
  @nesting = nesting
  @index = index
  @typechecker_enabled = typechecker_enabled
  dispatcher.register(
    self,
    :on_constant_read_node_enter,
    :on_constant_write_node_enter,
    :on_constant_path_node_enter,
    :on_call_node_enter,
  )
end

def on_call_node_enter(node)

def on_call_node_enter(node)
  return unless self_receiver?(node)
  if @path && File.basename(@path) == GEMFILE_NAME && node.name == :gem
    generate_gem_hover(node)
    return
  end
  return if @typechecker_enabled
  message = node.message
  return unless message
  target_method = @index.resolve_method(message, @nesting.join("::"))
  return unless target_method
  categorized_markdown_from_index_entries(message, target_method).each do |category, content|
    @response_builder.push(content, category: category)
  end
end

def on_constant_path_node_enter(node)

def on_constant_path_node_enter(node)
  return if DependencyDetector.instance.typechecker
  generate_hover(node.slice, node.location)
end

def on_constant_read_node_enter(node)

def on_constant_read_node_enter(node)
  return if @typechecker_enabled
  generate_hover(node.slice, node.location)
end

def on_constant_write_node_enter(node)

def on_constant_write_node_enter(node)
  return if DependencyDetector.instance.typechecker
  generate_hover(node.name.to_s, node.name_loc)
end