class Steep::Project::HoverContent

def content_for(path:, line:, column:)

def content_for(path:, line:, column:)
  target = project.targets.find {|target| target.source_file?(path) }
  if target
    source_file = target.source_files[path]
    target.type_check(target_sources: [source_file], validate_signatures: false)
    case (status = source_file.status)
    when SourceFile::TypeCheckStatus
      node, *parents = status.source.find_nodes(line: line, column: column)
      if node
        case node.type
        when :lvar
          var_name = node.children[0]
          context = status.typing.context_at(line: line, column: column)
          var_type = context.lvar_env[var_name.name] || AST::Types::Any.new(location: nil)
          VariableContent.new(node: node, name: var_name.name, type: var_type, location: node.location.name)
        when :lvasgn
          var_name, rhs = node.children
          context = status.typing.context_at(line: line, column: column)
          type = context.lvar_env[var_name.name] || status.typing.type_of(node: rhs)
          VariableContent.new(node: node, name: var_name.name, type: type, location: node.location.name)
        when :send
          receiver, method_name, *_ = node.children
          result_node = if parents[0]&.type == :block
                          parents[0]
                        else
                          node
                        end
          context = status.typing.context_at(line: line, column: column)
          receiver_type = if receiver
                            status.typing.type_of(node: receiver)
                          else
                            context.self_type
                          end
          factory = context.type_env.subtyping.factory
          method_name, definition = case receiver_type
                                    when AST::Types::Name::Instance
                                      method_definition = method_definition_for(factory, receiver_type.name, instance_method: method_name)
                                      if method_definition&.defined_in
                                        owner_name = factory.type_name(method_definition.defined_in.name.absolute!)
                                        [
                                          InstanceMethodName.new(owner_name, method_name),
                                          method_definition
                                        ]
                                      end
                                    when AST::Types::Name::Class
                                      method_definition = method_definition_for(factory, receiver_type.name, singleton_method: method_name)
                                      if method_definition&.defined_in
                                        owner_name = factory.type_name(method_definition.defined_in.name.absolute!)
                                        [
                                          SingletonMethodName.new(owner_name, method_name),
                                          method_definition
                                        ]
                                      end
                                    else
                                      nil
                                    end
          MethodCallContent.new(
            node: node,
            method_name: method_name,
            type: status.typing.type_of(node: result_node),
            definition: definition,
            location: result_node.location.expression
          )
        when :def, :defs
          context = status.typing.context_at(line: line, column: column)
          method_context = context.method_context
          if method_context && method_context.method
            DefinitionContent.new(
              node: node,
              method_name: method_context.name,
              method_type: method_context.method_type,
              definition: method_context.method,
              location: node.loc.expression
            )
          end
        else
          type = status.typing.type_of(node: node)
          TypeContent.new(
            node: node,
            type: type,
            location: node.location.expression
          )
        end
      end
    end
  end
end

def initialize(project:)

def initialize(project:)
  @project = project
end

def method_definition_for(factory, module_name, singleton_method: nil, instance_method: nil)

def method_definition_for(factory, module_name, singleton_method: nil, instance_method: nil)
  type_name = factory.type_name_1(module_name)
  case
  when instance_method
    factory.definition_builder.build_instance(type_name).methods[instance_method]
  when singleton_method
    methods = factory.definition_builder.build_singleton(type_name).methods
    if singleton_method == :new
      methods[:new] || methods[:initialize]
    else
      methods[singleton_method]
    end
  end
end