steep 0.51.0 → 0.52.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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