steep 0.51.0 → 0.52.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,254 +0,0 @@
1
- module Steep
2
- module Services
3
- class HoverContent
4
- TypeContent = Struct.new(:node, :type, :location, keyword_init: true)
5
- VariableContent = Struct.new(:node, :name, :type, :location, keyword_init: true)
6
- MethodCallContent = Struct.new(:node, :method_name, :type, :definition, :location, keyword_init: true)
7
- DefinitionContent = Struct.new(:node, :method_name, :method_type, :definition, :location, keyword_init: true) do
8
- def comment_string
9
- if comments = definition&.comments
10
- comments.map {|c| c.string.chomp }.uniq.join("\n----\n")
11
- end
12
- end
13
- end
14
- ConstantContent = Struct.new(:location, :full_name, :type, :decl, keyword_init: true) do
15
- def comment_string
16
- if class_or_module?
17
- comments = decl.decls.filter_map {|d| d.decl.comment&.string }
18
- unless comments.empty?
19
- return comments.join("\n----\n")
20
- end
21
- end
22
-
23
- if constant?
24
- if comment = decl.decl.comment
25
- return comment.string
26
- end
27
- end
28
-
29
- nil
30
- end
31
-
32
- def constant?
33
- decl.is_a?(RBS::Environment::SingleEntry)
34
- end
35
-
36
- def class_or_module?
37
- decl.is_a?(RBS::Environment::MultiEntry)
38
- end
39
- end
40
-
41
- TypeAliasContent = Struct.new(:location, :decl, keyword_init: true)
42
- ClassContent = Struct.new(:location, :decl, keyword_init: true)
43
- InterfaceContent = Struct.new(:location, :decl, keyword_init: true)
44
-
45
- InstanceMethodName = Struct.new(:class_name, :method_name)
46
- SingletonMethodName = Struct.new(:class_name, :method_name)
47
-
48
- attr_reader :service
49
-
50
- def initialize(service:)
51
- @service = service
52
- end
53
-
54
- def project
55
- service.project
56
- end
57
-
58
- def method_definition_for(factory, type_name, singleton_method: nil, instance_method: nil)
59
- case
60
- when instance_method
61
- factory.definition_builder.build_instance(type_name).methods[instance_method]
62
- when singleton_method
63
- methods = factory.definition_builder.build_singleton(type_name).methods
64
-
65
- if singleton_method == :new
66
- methods[:new] || methods[:initialize]
67
- else
68
- methods[singleton_method]
69
- end
70
- end
71
- end
72
-
73
- def typecheck(target, path:, content:, line:, column:)
74
- subtyping = service.signature_services[target.name].current_subtyping or return
75
- source = Source.parse(content, path: path, factory: subtyping.factory)
76
- source = source.without_unrelated_defs(line: line, column: column)
77
- Services::TypeCheckService.type_check(source: source, subtyping: subtyping)
78
- rescue
79
- nil
80
- end
81
-
82
- def content_for(path:, line:, column:)
83
- target_for_code, targets_for_sigs = project.targets_for_path(path)
84
-
85
- case
86
- when target = target_for_code
87
- Steep.logger.info "target #{target}"
88
-
89
- hover_for_source(column, line, path, target)
90
-
91
- when target = targets_for_sigs[0]
92
- service = self.service.signature_services[target.name]
93
-
94
- _buffer, decls = service.latest_env.buffers_decls.find do |buffer, _|
95
- Pathname(buffer.name) == path
96
- end
97
-
98
- return if decls.nil?
99
-
100
- locator = RBS::Locator.new(decls: decls)
101
- hd, tail = locator.find2(line: line, column: column)
102
-
103
- # Maybe hover on comment
104
- return if tail.nil?
105
-
106
- case type = tail[0]
107
- when RBS::Types::Alias
108
- alias_decl = service.latest_env.alias_decls[type.name]&.decl or raise
109
-
110
- location = tail[0].location
111
- TypeAliasContent.new(
112
- location: location,
113
- decl: alias_decl
114
- )
115
- when RBS::Types::ClassInstance, RBS::Types::ClassSingleton
116
- if hd == :name
117
- env = service.latest_env
118
- class_decl = env.class_decls[type.name]&.decls[0]&.decl or raise
119
- location = tail[0].location[:name]
120
- ClassContent.new(
121
- location: location,
122
- decl: class_decl
123
- )
124
- end
125
- when RBS::Types::Interface
126
- env = service.latest_env
127
- interface_decl = env.interface_decls[type.name]&.decl or raise
128
- location = type.location[:name]
129
-
130
- InterfaceContent.new(
131
- location: location,
132
- decl: interface_decl
133
- )
134
- end
135
- end
136
- end
137
-
138
- def hover_for_source(column, line, path, target)
139
- file = service.source_files[path]
140
- typing = typecheck(target, path: path, content: file.content, line: line, column: column) or return
141
- node, *parents = typing.source.find_nodes(line: line, column: column)
142
-
143
- if node
144
- case node.type
145
- when :lvar
146
- var_name = node.children[0]
147
- context = typing.context_at(line: line, column: column)
148
- var_type = context.lvar_env[var_name] || AST::Types::Any.new(location: nil)
149
-
150
- VariableContent.new(node: node, name: var_name, type: var_type, location: node.location.name)
151
- when :lvasgn
152
- var_name, rhs = node.children
153
- context = typing.context_at(line: line, column: column)
154
- type = context.lvar_env[var_name] || typing.type_of(node: rhs)
155
-
156
- VariableContent.new(node: node, name: var_name, type: type, location: node.location.name)
157
- when :send
158
- receiver, method_name, *_ = node.children
159
-
160
- result_node = case parents[0]&.type
161
- when :block, :numblock
162
- parents[0]
163
- else
164
- node
165
- end
166
-
167
- context = typing.context_at(line: line, column: column)
168
-
169
- receiver_type = if receiver
170
- typing.type_of(node: receiver)
171
- else
172
- context.self_type
173
- end
174
-
175
- factory = context.type_env.subtyping.factory
176
- method_name, definition = case receiver_type
177
- when AST::Types::Name::Instance
178
- method_definition = method_definition_for(factory, receiver_type.name, instance_method: method_name)
179
- if method_definition&.defined_in
180
- owner_name = method_definition.defined_in
181
- [
182
- InstanceMethodName.new(owner_name, method_name),
183
- method_definition
184
- ]
185
- end
186
- when AST::Types::Name::Singleton
187
- method_definition = method_definition_for(factory, receiver_type.name, singleton_method: method_name)
188
- if method_definition&.defined_in
189
- owner_name = method_definition.defined_in
190
- [
191
- SingletonMethodName.new(owner_name, method_name),
192
- method_definition
193
- ]
194
- end
195
- else
196
- nil
197
- end
198
-
199
- MethodCallContent.new(
200
- node: node,
201
- method_name: method_name,
202
- type: typing.type_of(node: result_node),
203
- definition: definition,
204
- location: result_node.location.expression
205
- )
206
- when :def, :defs
207
- context = typing.context_at(line: line, column: column)
208
- method_context = context.method_context
209
-
210
- if method_context && method_context.method
211
- DefinitionContent.new(
212
- node: node,
213
- method_name: method_context.name,
214
- method_type: method_context.method_type,
215
- definition: method_context.method,
216
- location: node.loc.expression
217
- )
218
- end
219
- when :const, :casgn
220
- context = typing.context_at(line: line, column: column)
221
-
222
- type = typing.type_of(node: node)
223
- const_name = typing.source_index.reference(constant_node: node)
224
-
225
- if const_name
226
- decl = context.env.class_decls[const_name] || context.env.constant_decls[const_name]
227
-
228
- ConstantContent.new(
229
- location: node.location.name,
230
- full_name: const_name,
231
- type: type,
232
- decl: decl
233
- )
234
- else
235
- TypeContent.new(
236
- node: node,
237
- type: type,
238
- location: node.location.expression
239
- )
240
- end
241
- else
242
- type = typing.type_of(node: node)
243
-
244
- TypeContent.new(
245
- node: node,
246
- type: type,
247
- location: node.location.expression
248
- )
249
- end
250
- end
251
- end
252
- end
253
- end
254
- end