steep 0.40.0 → 0.44.0

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.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/Gemfile +1 -0
  4. data/bin/output_rebaseline.rb +15 -30
  5. data/bin/output_test.rb +23 -57
  6. data/lib/steep.rb +89 -15
  7. data/lib/steep/annotation_parser.rb +10 -2
  8. data/lib/steep/ast/types/class.rb +4 -0
  9. data/lib/steep/cli.rb +31 -6
  10. data/lib/steep/diagnostic/ruby.rb +13 -8
  11. data/lib/steep/diagnostic/signature.rb +152 -2
  12. data/lib/steep/drivers/annotations.rb +18 -36
  13. data/lib/steep/drivers/check.rb +140 -31
  14. data/lib/steep/drivers/diagnostic_printer.rb +20 -11
  15. data/lib/steep/drivers/langserver.rb +4 -8
  16. data/lib/steep/drivers/print_project.rb +10 -9
  17. data/lib/steep/drivers/stats.rb +135 -119
  18. data/lib/steep/drivers/utils/driver_helper.rb +35 -0
  19. data/lib/steep/drivers/utils/jobs_count.rb +9 -0
  20. data/lib/steep/drivers/validate.rb +29 -18
  21. data/lib/steep/drivers/watch.rb +55 -49
  22. data/lib/steep/drivers/worker.rb +11 -8
  23. data/lib/steep/expectations.rb +159 -0
  24. data/lib/steep/index/signature_symbol_provider.rb +23 -1
  25. data/lib/steep/index/source_index.rb +55 -5
  26. data/lib/steep/interface/block.rb +4 -0
  27. data/lib/steep/project.rb +0 -30
  28. data/lib/steep/project/dsl.rb +5 -3
  29. data/lib/steep/project/pattern.rb +56 -0
  30. data/lib/steep/project/target.rb +11 -227
  31. data/lib/steep/server/base_worker.rb +1 -3
  32. data/lib/steep/server/change_buffer.rb +63 -0
  33. data/lib/steep/server/interaction_worker.rb +72 -57
  34. data/lib/steep/server/master.rb +652 -234
  35. data/lib/steep/server/type_check_worker.rb +304 -0
  36. data/lib/steep/server/worker_process.rb +16 -11
  37. data/lib/steep/{project → services}/completion_provider.rb +5 -5
  38. data/lib/steep/services/content_change.rb +61 -0
  39. data/lib/steep/services/file_loader.rb +48 -0
  40. data/lib/steep/services/goto_service.rb +321 -0
  41. data/lib/steep/{project → services}/hover_content.rb +19 -20
  42. data/lib/steep/services/path_assignment.rb +27 -0
  43. data/lib/steep/services/signature_service.rb +403 -0
  44. data/lib/steep/services/stats_calculator.rb +69 -0
  45. data/lib/steep/services/type_check_service.rb +413 -0
  46. data/lib/steep/signature/validator.rb +187 -85
  47. data/lib/steep/source.rb +21 -18
  48. data/lib/steep/subtyping/check.rb +246 -45
  49. data/lib/steep/subtyping/constraints.rb +4 -4
  50. data/lib/steep/type_construction.rb +428 -193
  51. data/lib/steep/type_inference/block_params.rb +1 -1
  52. data/lib/steep/type_inference/context.rb +22 -0
  53. data/lib/steep/type_inference/local_variable_type_env.rb +26 -12
  54. data/lib/steep/type_inference/logic.rb +1 -1
  55. data/lib/steep/type_inference/logic_type_interpreter.rb +4 -4
  56. data/lib/steep/type_inference/type_env.rb +43 -17
  57. data/lib/steep/version.rb +1 -1
  58. data/smoke/alias/test_expectations.yml +96 -0
  59. data/smoke/and/test_expectations.yml +31 -0
  60. data/smoke/array/test_expectations.yml +103 -0
  61. data/smoke/block/test_expectations.yml +125 -0
  62. data/smoke/case/test_expectations.yml +47 -0
  63. data/smoke/class/test_expectations.yml +120 -0
  64. data/smoke/const/test_expectations.yml +129 -0
  65. data/smoke/diagnostics-rbs-duplicated/test_expectations.yml +13 -0
  66. data/smoke/diagnostics-rbs/Steepfile +7 -4
  67. data/smoke/diagnostics-rbs/test_expectations.yml +231 -0
  68. data/smoke/diagnostics-rbs/unknown-type-name-2.rbs +5 -0
  69. data/smoke/{broken → diagnostics-ruby-unsat}/Steepfile +0 -0
  70. data/smoke/diagnostics-ruby-unsat/a.rbs +3 -0
  71. data/smoke/diagnostics-ruby-unsat/test_expectations.yml +27 -0
  72. data/smoke/{diagnostics → diagnostics-ruby-unsat}/unsatisfiable_constraint.rb +0 -1
  73. data/smoke/diagnostics/a.rbs +0 -4
  74. data/smoke/diagnostics/test_expectations.yml +451 -0
  75. data/smoke/dstr/test_expectations.yml +13 -0
  76. data/smoke/ensure/test_expectations.yml +62 -0
  77. data/smoke/enumerator/test_expectations.yml +135 -0
  78. data/smoke/extension/f.rb +2 -0
  79. data/smoke/extension/f.rbs +3 -0
  80. data/smoke/extension/test_expectations.yml +73 -0
  81. data/smoke/hash/test_expectations.yml +81 -0
  82. data/smoke/hello/test_expectations.yml +25 -0
  83. data/smoke/if/test_expectations.yml +34 -0
  84. data/smoke/implements/b.rb +13 -0
  85. data/smoke/implements/b.rbs +12 -0
  86. data/smoke/implements/test_expectations.yml +23 -0
  87. data/smoke/initialize/test_expectations.yml +1 -0
  88. data/smoke/integer/test_expectations.yml +101 -0
  89. data/smoke/interface/test_expectations.yml +23 -0
  90. data/smoke/kwbegin/test_expectations.yml +17 -0
  91. data/smoke/lambda/test_expectations.yml +39 -0
  92. data/smoke/literal/test_expectations.yml +106 -0
  93. data/smoke/map/test_expectations.yml +1 -0
  94. data/smoke/method/test_expectations.yml +90 -0
  95. data/smoke/module/test_expectations.yml +75 -0
  96. data/smoke/regexp/test_expectations.yml +615 -0
  97. data/smoke/regression/issue_328.rb +1 -0
  98. data/smoke/regression/issue_328.rbs +0 -0
  99. data/smoke/regression/issue_332.rb +11 -0
  100. data/smoke/regression/issue_332.rbs +19 -0
  101. data/smoke/regression/issue_372.rb +8 -0
  102. data/smoke/regression/issue_372.rbs +4 -0
  103. data/smoke/regression/masgn.rb +4 -0
  104. data/smoke/regression/test_expectations.yml +60 -0
  105. data/smoke/regression/thread.rb +7 -0
  106. data/smoke/rescue/test_expectations.yml +79 -0
  107. data/smoke/self/test_expectations.yml +23 -0
  108. data/smoke/skip/test_expectations.yml +23 -0
  109. data/smoke/stdout/test_expectations.yml +1 -0
  110. data/smoke/super/test_expectations.yml +69 -0
  111. data/smoke/toplevel/test_expectations.yml +15 -0
  112. data/smoke/tsort/Steepfile +2 -0
  113. data/smoke/tsort/test_expectations.yml +63 -0
  114. data/smoke/type_case/test_expectations.yml +48 -0
  115. data/smoke/unexpected/Steepfile +5 -0
  116. data/smoke/unexpected/test_expectations.yml +25 -0
  117. data/smoke/unexpected/unexpected.rb +1 -0
  118. data/smoke/unexpected/unexpected.rbs +3 -0
  119. data/smoke/yield/test_expectations.yml +68 -0
  120. data/steep.gemspec +4 -3
  121. metadata +127 -80
  122. data/lib/steep/project/file_loader.rb +0 -68
  123. data/lib/steep/project/signature_file.rb +0 -39
  124. data/lib/steep/project/source_file.rb +0 -129
  125. data/lib/steep/project/stats_calculator.rb +0 -80
  126. data/lib/steep/server/code_worker.rb +0 -150
  127. data/lib/steep/server/signature_worker.rb +0 -157
  128. data/lib/steep/server/utils.rb +0 -69
  129. data/smoke/alias/test.yaml +0 -73
  130. data/smoke/and/test.yaml +0 -24
  131. data/smoke/array/test.yaml +0 -80
  132. data/smoke/block/test.yaml +0 -96
  133. data/smoke/broken/broken.rb +0 -0
  134. data/smoke/broken/broken.rbs +0 -0
  135. data/smoke/broken/test.yaml +0 -6
  136. data/smoke/case/test.yaml +0 -36
  137. data/smoke/class/test.yaml +0 -89
  138. data/smoke/const/test.yaml +0 -96
  139. data/smoke/diagnostics-rbs-duplicated/test.yaml +0 -10
  140. data/smoke/diagnostics-rbs/test.yaml +0 -142
  141. data/smoke/diagnostics/test.yaml +0 -333
  142. data/smoke/dstr/test.yaml +0 -10
  143. data/smoke/ensure/test.yaml +0 -47
  144. data/smoke/enumerator/test.yaml +0 -100
  145. data/smoke/extension/test.yaml +0 -50
  146. data/smoke/hash/test.yaml +0 -62
  147. data/smoke/hello/test.yaml +0 -18
  148. data/smoke/if/test.yaml +0 -27
  149. data/smoke/implements/test.yaml +0 -16
  150. data/smoke/initialize/test.yaml +0 -4
  151. data/smoke/integer/test.yaml +0 -66
  152. data/smoke/interface/test.yaml +0 -16
  153. data/smoke/kwbegin/test.yaml +0 -14
  154. data/smoke/lambda/test.yaml +0 -28
  155. data/smoke/literal/test.yaml +0 -79
  156. data/smoke/map/test.yaml +0 -4
  157. data/smoke/method/test.yaml +0 -71
  158. data/smoke/module/test.yaml +0 -51
  159. data/smoke/regexp/test.yaml +0 -372
  160. data/smoke/regression/test.yaml +0 -38
  161. data/smoke/rescue/test.yaml +0 -60
  162. data/smoke/self/test.yaml +0 -16
  163. data/smoke/skip/test.yaml +0 -16
  164. data/smoke/stdout/test.yaml +0 -4
  165. data/smoke/super/test.yaml +0 -52
  166. data/smoke/toplevel/test.yaml +0 -12
  167. data/smoke/tsort/test.yaml +0 -32
  168. data/smoke/type_case/test.yaml +0 -33
  169. data/smoke/yield/test.yaml +0 -49
@@ -0,0 +1,48 @@
1
+ module Steep
2
+ module Services
3
+ class FileLoader
4
+ attr_reader :base_dir
5
+
6
+ def initialize(base_dir:)
7
+ @base_dir = base_dir
8
+ end
9
+
10
+ def each_path_in_patterns(pattern, commandline_patterns = [])
11
+ pats = commandline_patterns.empty? ? pattern.patterns : commandline_patterns
12
+
13
+ pats.each do |path|
14
+ absolute_path = base_dir + path
15
+
16
+ if absolute_path.file?
17
+ yield absolute_path.relative_path_from(base_dir)
18
+ else
19
+ files = if absolute_path.directory?
20
+ Pathname.glob("#{absolute_path}/**/*#{pattern.ext}")
21
+ else
22
+ Pathname.glob(absolute_path)
23
+ end
24
+
25
+ files.sort.each do |source_path|
26
+ if source_path.file?
27
+ relative_path = source_path.relative_path_from(base_dir)
28
+ unless pattern.ignore?(relative_path)
29
+ yield relative_path
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ def load_changes(pattern, command_line_patterns = [], changes:)
38
+ each_path_in_patterns(pattern, command_line_patterns) do |path|
39
+ unless changes.key?(path)
40
+ changes[path] = [ContentChange.string((base_dir + path).read)]
41
+ end
42
+ end
43
+
44
+ changes
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,321 @@
1
+ module Steep
2
+ module Services
3
+ class GotoService
4
+ include ModuleHelper
5
+
6
+ module SourceHelper
7
+ def from_ruby?
8
+ from == :ruby
9
+ end
10
+
11
+ def from_rbs?
12
+ from == :rbs
13
+ end
14
+ end
15
+
16
+ ConstantQuery = Struct.new(:name, :from, keyword_init: true) do
17
+ include SourceHelper
18
+ end
19
+ MethodQuery = Struct.new(:name, :from, keyword_init: true) do
20
+ include SourceHelper
21
+ end
22
+ TypeNameQuery = Struct.new(:name, keyword_init: true)
23
+
24
+ attr_reader :type_check
25
+
26
+ def initialize(type_check:)
27
+ @type_check = type_check
28
+ end
29
+
30
+ def project
31
+ type_check.project
32
+ end
33
+
34
+ def implementation(path:, line:, column:)
35
+ locations = []
36
+
37
+ relative_path = project.relative_path(path)
38
+
39
+ queries = query_at(path: path, line: line, column: column)
40
+ queries.uniq!
41
+
42
+ queries.each do |query|
43
+ case query
44
+ when ConstantQuery
45
+ constant_definition_in_ruby(query.name, locations: locations)
46
+ when MethodQuery
47
+ method_locations(query.name, locations: locations, in_ruby: true, in_rbs: false)
48
+ when TypeNameQuery
49
+ type_name_locations(query.name, locations: locations)
50
+ end
51
+ end
52
+
53
+ locations.uniq
54
+ end
55
+
56
+ def definition(path:, line:, column:)
57
+ locations = []
58
+
59
+ relative_path = project.relative_path(path)
60
+
61
+ queries = query_at(path: path, line: line, column: column)
62
+ queries.uniq!
63
+
64
+ queries.each do |query|
65
+ case query
66
+ when ConstantQuery
67
+ constant_definition_in_rbs(query.name, locations: locations) if query.from_ruby?
68
+ constant_definition_in_ruby(query.name, locations: locations) if query.from_rbs?
69
+ when MethodQuery
70
+ method_locations(
71
+ query.name,
72
+ locations: locations,
73
+ in_ruby: query.from_rbs?,
74
+ in_rbs: query.from_ruby?
75
+ )
76
+ when TypeNameQuery
77
+ type_name_locations(query.name, locations: locations)
78
+ end
79
+ end
80
+
81
+ locations.uniq
82
+ end
83
+
84
+ def test_ast_location(loc, line:, column:)
85
+ return false if line < loc.line
86
+ return false if line == loc.line && column < loc.column
87
+ return false if loc.last_line < line
88
+ return false if line == loc.last_line && loc.last_column < column
89
+ true
90
+ end
91
+
92
+ def query_at(path:, line:, column:)
93
+ queries = []
94
+
95
+ relative_path = project.relative_path(path)
96
+
97
+ case
98
+ when target = type_check.source_file?(relative_path)
99
+ source = type_check.source_files[relative_path]
100
+ typing, signature = type_check_path(target: target, path: relative_path, content: source.content, line: line, column: column)
101
+ if typing
102
+ node, *parents = typing.source.find_nodes(line: line, column: column)
103
+ if node
104
+ case node.type
105
+ when :const, :casgn
106
+ if test_ast_location(node.location.name, line: line, column: column)
107
+ if module_context = typing.context_at(line: line, column: column).module_context
108
+ const_env = module_context.const_env
109
+ const = const_env.lookup_constant(module_name_from_node(node))
110
+ queries << ConstantQuery.new(name: const.name, from: :ruby)
111
+ end
112
+ end
113
+ when :def, :defs
114
+ if test_ast_location(node.location.name, line: line, column: column)
115
+ if method_context = typing.context_at(line: line, column: column).method_context
116
+ type_name = method_context.method.defined_in
117
+ name =
118
+ if method_context.method.defs.any? {|defn| defn.member.singleton? }
119
+ SingletonMethodName.new(type_name: type_name, method_name: method_context.name)
120
+ else
121
+ InstanceMethodName.new(type_name: type_name, method_name: method_context.name)
122
+ end
123
+ queries << MethodQuery.new(name: name, from: :ruby)
124
+ end
125
+ end
126
+ when :send
127
+ if test_ast_location(node.location.selector, line: line, column: column)
128
+ case call = typing.call_of(node: node)
129
+ when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
130
+ call.method_decls.each do |decl|
131
+ queries << MethodQuery.new(name: decl.method_name, from: :ruby)
132
+ end
133
+ when TypeInference::MethodCall::Untyped
134
+ # nop
135
+ when TypeInference::MethodCall::NoMethodError
136
+ # nop
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ when target_names = type_check.signature_file?(path)
143
+ target_names.each do |target_name|
144
+ signature_service = type_check.signature_services[target_name]
145
+ decls = signature_service.latest_env.declarations.select do |decl|
146
+ buffer_path = Pathname(decl.location.buffer.name)
147
+ buffer_path == relative_path || buffer_path == path
148
+ end
149
+
150
+ locator = RBS::Locator.new(decls: decls)
151
+ last, nodes = locator.find2(line: line, column: column)
152
+ case nodes[0]
153
+ when RBS::AST::Declarations::Class, RBS::AST::Declarations::Module
154
+ if last == :name
155
+ queries << ConstantQuery.new(name: nodes[0].name, from: :rbs)
156
+ end
157
+ when RBS::AST::Declarations::Constant
158
+ if last == :name
159
+ queries << ConstantQuery.new(name: nodes[0].name, from: :rbs)
160
+ end
161
+ when RBS::AST::Members::MethodDefinition
162
+ if last == :name
163
+ type_name = nodes[1].name
164
+ method_name = nodes[0].name
165
+ if nodes[0].instance?
166
+ queries << MethodQuery.new(
167
+ name: InstanceMethodName.new(type_name: type_name, method_name: method_name),
168
+ from: :rbs
169
+ )
170
+ end
171
+ if nodes[0].singleton?
172
+ queries << MethodQuery.new(
173
+ name: SingletonMethodName.new(type_name: type_name, method_name: method_name),
174
+ from: :rbs
175
+ )
176
+ end
177
+ end
178
+ when RBS::AST::Members::Include, RBS::AST::Members::Extend, RBS::AST::Members::Prepend
179
+ if last == :name
180
+ queries << TypeNameQuery.new(name: nodes[0].name)
181
+ end
182
+ when RBS::Types::ClassInstance, RBS::Types::ClassSingleton, RBS::Types::Interface, RBS::Types::Alias
183
+ if last == :name
184
+ queries << TypeNameQuery.new(name: nodes[0].name)
185
+ end
186
+ when RBS::AST::Declarations::Class::Super, RBS::AST::Declarations::Module::Self
187
+ if last == :name
188
+ queries << TypeNameQuery.new(name: nodes[0].name)
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ queries
195
+ end
196
+
197
+ def type_check_path(target:, path:, content:, line:, column:)
198
+ signature_service = type_check.signature_services[target.name]
199
+ subtyping = signature_service.current_subtyping or return
200
+ source = Source.parse(content, path: path, factory: subtyping.factory)
201
+ source = source.without_unrelated_defs(line: line, column: column)
202
+ [
203
+ Services::TypeCheckService.type_check(source: source, subtyping: subtyping),
204
+ signature_service
205
+ ]
206
+ rescue
207
+ nil
208
+ end
209
+
210
+ def constant_definition_in_rbs(name, locations:)
211
+ type_check.signature_services.each_value do |signature|
212
+ env = signature.latest_env
213
+
214
+ if entry = env.class_decls[name]
215
+ entry.decls.each do |d|
216
+ locations << d.decl.location[:name]
217
+ end
218
+ end
219
+
220
+ if entry = env.constant_decls[name]
221
+ locations << entry.decl.location[:name]
222
+ end
223
+ end
224
+
225
+ locations
226
+ end
227
+
228
+ def constant_definition_in_ruby(name, locations:)
229
+ type_check.source_files.each do |path, source|
230
+ if typing = source.typing
231
+ entry = typing.source_index.entry(constant: name)
232
+ entry.definitions.each do |node|
233
+ case node.type
234
+ when :class, :module
235
+ locations << node.children[0].location.expression
236
+ when :casgn
237
+ parent = node.children[0]
238
+ location =
239
+ if parent
240
+ parent.location.expression.join(node.location.name)
241
+ else
242
+ node.location.name
243
+ end
244
+ locations << location
245
+ end
246
+ end
247
+ end
248
+ end
249
+
250
+ locations
251
+ end
252
+
253
+ def method_locations(name, in_ruby:, in_rbs:, locations:)
254
+ if in_ruby
255
+ type_check.source_files.each do |path, source|
256
+ if typing = source.typing
257
+ entry = typing.source_index.entry(method: name)
258
+
259
+ if entry.definitions.empty?
260
+ if name.is_a?(SingletonMethodName) && name.method_name == :new
261
+ initialize = InstanceMethodName.new(method_name: :initialize, type_name: name.type_name)
262
+ entry = typing.source_index.entry(method: initialize)
263
+ end
264
+ end
265
+
266
+ entry.definitions.each do |node|
267
+ case node.type
268
+ when :def
269
+ locations << node.location.name
270
+ when :defs
271
+ locations << node.location.name
272
+ end
273
+ end
274
+ end
275
+ end
276
+ end
277
+
278
+ if in_rbs
279
+ type_check.signature_services.each_value do |signature|
280
+ index = signature.latest_rbs_index
281
+
282
+ entry = index.entry(method_name: name)
283
+
284
+ if entry.declarations.empty?
285
+ if name.is_a?(SingletonMethodName) && name.method_name == :new
286
+ initialize = InstanceMethodName.new(method_name: :initialize, type_name: name.type_name)
287
+ entry = index.entry(method_name: initialize)
288
+ end
289
+ end
290
+
291
+ entry.declarations.each do |decl|
292
+ case decl
293
+ when RBS::AST::Members::MethodDefinition
294
+ locations << decl.location[:name]
295
+ when RBS::AST::Members::Alias
296
+ locations << decl.location[:new_name]
297
+ when RBS::AST::Members::AttrAccessor, RBS::AST::Members::AttrReader, RBS::AST::Members::AttrWriter
298
+ locations << decl.location[:name]
299
+ end
300
+ end
301
+ end
302
+ end
303
+
304
+ locations
305
+ end
306
+
307
+ def type_name_locations(name, locations: [])
308
+ type_check.signature_services.each_value do |signature|
309
+ index = signature.latest_rbs_index
310
+
311
+ entry = index.entry(type_name: name)
312
+ entry.declarations.each do |decl|
313
+ locations << decl.location[:name]
314
+ end
315
+ end
316
+
317
+ locations
318
+ end
319
+ end
320
+ end
321
+ end
@@ -1,5 +1,5 @@
1
1
  module Steep
2
- class Project
2
+ module Services
3
3
  class HoverContent
4
4
  TypeContent = Struct.new(:node, :type, :location, keyword_init: true)
5
5
  VariableContent = Struct.new(:node, :name, :type, :location, keyword_init: true)
@@ -15,10 +15,14 @@ module Steep
15
15
  InstanceMethodName = Struct.new(:class_name, :method_name)
16
16
  SingletonMethodName = Struct.new(:class_name, :method_name)
17
17
 
18
- attr_reader :project
18
+ attr_reader :service
19
19
 
20
- def initialize(project:)
21
- @project = project
20
+ def initialize(service:)
21
+ @service = service
22
+ end
23
+
24
+ def project
25
+ service.project
22
26
  end
23
27
 
24
28
  def method_definition_for(factory, type_name, singleton_method: nil, instance_method: nil)
@@ -36,17 +40,11 @@ module Steep
36
40
  end
37
41
  end
38
42
 
39
- def typecheck(target, path:, line:, column:)
40
- target.type_check(target_sources: [], validate_signatures: false)
41
-
42
- case (status = target.status)
43
- when Project::Target::TypeCheckStatus
44
- subtyping = status.subtyping
45
- source = SourceFile
46
- .parse(target.source_files[path].content, path: path, factory: subtyping.factory)
47
- .without_unrelated_defs(line: line, column: column)
48
- SourceFile.type_check(source, subtyping: subtyping)
49
- end
43
+ def typecheck(target, path:, content:, line:, column:)
44
+ subtyping = service.signature_services[target.name].current_subtyping or return
45
+ source = Source.parse(content, path: path, factory: subtyping.factory)
46
+ source = source.without_unrelated_defs(line: line, column: column)
47
+ Services::TypeCheckService.type_check(source: source, subtyping: subtyping)
50
48
  rescue
51
49
  nil
52
50
  end
@@ -55,7 +53,8 @@ module Steep
55
53
  target = project.target_for_source_path(path)
56
54
 
57
55
  if target
58
- typing = typecheck(target, path: path, line: line, column: column) or return
56
+ file = service.source_files[path]
57
+ typing = typecheck(target, path: path, content: file.content, line: line, column: column) or return
59
58
 
60
59
  node, *parents = typing.source.find_nodes(line: line, column: column)
61
60
 
@@ -64,15 +63,15 @@ module Steep
64
63
  when :lvar
65
64
  var_name = node.children[0]
66
65
  context = typing.context_at(line: line, column: column)
67
- var_type = context.lvar_env[var_name.name] || AST::Types::Any.new(location: nil)
66
+ var_type = context.lvar_env[var_name] || AST::Types::Any.new(location: nil)
68
67
 
69
- VariableContent.new(node: node, name: var_name.name, type: var_type, location: node.location.name)
68
+ VariableContent.new(node: node, name: var_name, type: var_type, location: node.location.name)
70
69
  when :lvasgn
71
70
  var_name, rhs = node.children
72
71
  context = typing.context_at(line: line, column: column)
73
- type = context.lvar_env[var_name.name] || typing.type_of(node: rhs)
72
+ type = context.lvar_env[var_name] || typing.type_of(node: rhs)
74
73
 
75
- VariableContent.new(node: node, name: var_name.name, type: type, location: node.location.name)
74
+ VariableContent.new(node: node, name: var_name, type: type, location: node.location.name)
76
75
  when :send
77
76
  receiver, method_name, *_ = node.children
78
77
 
@@ -0,0 +1,27 @@
1
+ module Steep
2
+ module Services
3
+ class PathAssignment
4
+ attr_reader :index, :max_index, :cache
5
+
6
+ def initialize(index:, max_index:)
7
+ @index = index
8
+ @max_index = max_index
9
+ @cache = {}
10
+ end
11
+
12
+ def self.all
13
+ new(index: 0, max_index: 1)
14
+ end
15
+
16
+ def =~(path)
17
+ (cache[path] ||= self.class.index_for(path: path.to_s, max_index: max_index)) == index
18
+ end
19
+
20
+ alias === =~
21
+
22
+ def self.index_for(path:, max_index:)
23
+ Digest::MD5.hexdigest(path).hex % max_index
24
+ end
25
+ end
26
+ end
27
+ end