Class: Steep::Project::HoverContent

Inherits:
Object
  • Object
show all
Defined in:
lib/steep/project/hover_content.rb

Defined Under Namespace

Classes: DefinitionContent, InstanceMethodName, MethodCallContent, SingletonMethodName, TypeContent, VariableContent

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project:) ⇒ HoverContent

Returns a new instance of HoverContent.



14
15
16
# File 'lib/steep/project/hover_content.rb', line 14

def initialize(project:)
  @project = project
end

Instance Attribute Details

#projectObject (readonly)

Returns the value of attribute project.



12
13
14
# File 'lib/steep/project/hover_content.rb', line 12

def project
  @project
end

Instance Method Details

#content_for(path:, line:, column:) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/steep/project/hover_content.rb', line 35

def content_for(path:, line:, column:)
  source_file = project.targets.map {|target| target.source_files[path] }.compact[0]

  if source_file
    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, :lvasgn
          var_name = node.children[0]
          context = status.typing.context_of(node: node)
          var_type = context.type_env.get(lvar: var_name.name)

          VariableContent.new(node: node, name: var_name.name, type: var_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_of(node: result_node)

          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_of(node: node)
          method_context = context.method_context

          if method_context
            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

#method_definition_for(factory, module_name, singleton_method: nil, instance_method: nil) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/steep/project/hover_content.rb', line 18

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