steep 0.43.1 → 0.46.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +8 -0
  3. data/.github/workflows/ruby.yml +4 -2
  4. data/.gitignore +0 -1
  5. data/CHANGELOG.md +41 -0
  6. data/Gemfile +0 -1
  7. data/Gemfile.lock +77 -0
  8. data/bin/output_test.rb +8 -2
  9. data/lib/steep/ast/builtin.rb +7 -1
  10. data/lib/steep/ast/types/factory.rb +19 -25
  11. data/lib/steep/cli.rb +7 -1
  12. data/lib/steep/diagnostic/lsp_formatter.rb +59 -6
  13. data/lib/steep/diagnostic/ruby.rb +188 -60
  14. data/lib/steep/diagnostic/signature.rb +34 -0
  15. data/lib/steep/drivers/check.rb +3 -0
  16. data/lib/steep/drivers/init.rb +10 -3
  17. data/lib/steep/drivers/utils/driver_helper.rb +15 -0
  18. data/lib/steep/drivers/validate.rb +1 -1
  19. data/lib/steep/drivers/watch.rb +3 -0
  20. data/lib/steep/equatable.rb +21 -0
  21. data/lib/steep/index/source_index.rb +55 -5
  22. data/lib/steep/interface/block.rb +4 -0
  23. data/lib/steep/interface/function.rb +798 -579
  24. data/lib/steep/project/dsl.rb +105 -33
  25. data/lib/steep/project/options.rb +12 -53
  26. data/lib/steep/project/target.rb +21 -8
  27. data/lib/steep/server/interaction_worker.rb +239 -20
  28. data/lib/steep/server/master.rb +22 -1
  29. data/lib/steep/server/type_check_worker.rb +74 -9
  30. data/lib/steep/services/file_loader.rb +26 -19
  31. data/lib/steep/services/goto_service.rb +322 -0
  32. data/lib/steep/services/hover_content.rb +132 -80
  33. data/lib/steep/services/type_check_service.rb +25 -0
  34. data/lib/steep/source.rb +7 -10
  35. data/lib/steep/type_construction.rb +496 -518
  36. data/lib/steep/type_inference/block_params.rb +2 -5
  37. data/lib/steep/type_inference/method_params.rb +483 -0
  38. data/lib/steep/type_inference/send_args.rb +610 -128
  39. data/lib/steep/typing.rb +46 -21
  40. data/lib/steep/version.rb +1 -1
  41. data/lib/steep.rb +4 -1
  42. data/sample/Steepfile +10 -3
  43. data/sig/steep/type_inference/send_args.rbs +42 -0
  44. data/smoke/alias/Steepfile +2 -1
  45. data/smoke/and/Steepfile +2 -1
  46. data/smoke/array/Steepfile +2 -1
  47. data/smoke/array/test_expectations.yml +3 -3
  48. data/smoke/block/Steepfile +2 -2
  49. data/smoke/block/c.rb +0 -1
  50. data/smoke/case/Steepfile +2 -1
  51. data/smoke/class/Steepfile +2 -1
  52. data/smoke/class/test_expectations.yml +12 -15
  53. data/smoke/const/Steepfile +2 -1
  54. data/smoke/const/test_expectations.yml +0 -10
  55. data/smoke/diagnostics/Steepfile +2 -1
  56. data/smoke/diagnostics/a.rbs +0 -4
  57. data/smoke/diagnostics/different_method_parameter_kind.rb +9 -0
  58. data/smoke/diagnostics/method_arity_mismatch.rb +2 -2
  59. data/smoke/diagnostics/method_parameter_mismatch.rb +10 -0
  60. data/smoke/diagnostics/test_expectations.yml +108 -57
  61. data/smoke/diagnostics-rbs/Steepfile +1 -1
  62. data/smoke/diagnostics-rbs/mixin-class-error.rbs +6 -0
  63. data/smoke/diagnostics-rbs/test_expectations.yml +12 -0
  64. data/smoke/diagnostics-rbs-duplicated/Steepfile +2 -1
  65. data/smoke/diagnostics-ruby-unsat/Steepfile +6 -0
  66. data/smoke/diagnostics-ruby-unsat/a.rbs +3 -0
  67. data/smoke/diagnostics-ruby-unsat/test_expectations.yml +27 -0
  68. data/smoke/{diagnostics → diagnostics-ruby-unsat}/unsatisfiable_constraint.rb +0 -1
  69. data/smoke/dstr/Steepfile +2 -1
  70. data/smoke/ensure/Steepfile +2 -1
  71. data/smoke/ensure/test_expectations.yml +3 -3
  72. data/smoke/enumerator/Steepfile +2 -1
  73. data/smoke/enumerator/test_expectations.yml +1 -1
  74. data/smoke/extension/Steepfile +2 -1
  75. data/smoke/hash/Steepfile +2 -1
  76. data/smoke/hello/Steepfile +2 -1
  77. data/smoke/if/Steepfile +2 -1
  78. data/smoke/implements/Steepfile +2 -1
  79. data/smoke/initialize/Steepfile +2 -1
  80. data/smoke/integer/Steepfile +2 -1
  81. data/smoke/interface/Steepfile +2 -1
  82. data/smoke/kwbegin/Steepfile +2 -1
  83. data/smoke/lambda/Steepfile +2 -1
  84. data/smoke/literal/Steepfile +2 -1
  85. data/smoke/literal/test_expectations.yml +2 -2
  86. data/smoke/map/Steepfile +2 -1
  87. data/smoke/method/Steepfile +2 -1
  88. data/smoke/method/test_expectations.yml +11 -10
  89. data/smoke/module/Steepfile +2 -1
  90. data/smoke/regexp/Steepfile +2 -1
  91. data/smoke/regression/Steepfile +2 -1
  92. data/smoke/regression/issue_372.rb +8 -0
  93. data/smoke/regression/issue_372.rbs +4 -0
  94. data/smoke/regression/test_expectations.yml +0 -12
  95. data/smoke/rescue/Steepfile +2 -1
  96. data/smoke/rescue/test_expectations.yml +3 -3
  97. data/smoke/self/Steepfile +2 -1
  98. data/smoke/skip/Steepfile +2 -1
  99. data/smoke/stdout/Steepfile +2 -1
  100. data/smoke/super/Steepfile +2 -1
  101. data/smoke/toplevel/Steepfile +2 -1
  102. data/smoke/toplevel/test_expectations.yml +3 -3
  103. data/smoke/tsort/Steepfile +4 -5
  104. data/smoke/tsort/test_expectations.yml +2 -2
  105. data/smoke/type_case/Steepfile +2 -1
  106. data/smoke/unexpected/Steepfile +2 -1
  107. data/smoke/yield/Steepfile +2 -1
  108. data/steep.gemspec +2 -2
  109. metadata +24 -10
@@ -499,7 +499,11 @@ module Steep
499
499
  trigger_characters: [".", "@"],
500
500
  work_done_progress: true
501
501
  ),
502
- workspace_symbol_provider: true
502
+ workspace_symbol_provider: true,
503
+ definition_provider: true,
504
+ declaration_provider: false,
505
+ implementation_provider: true,
506
+ type_definition_provider: false
503
507
  )
504
508
  )
505
509
  }
@@ -584,6 +588,23 @@ module Steep
584
588
  end
585
589
  end
586
590
 
591
+ when "textDocument/definition", "textDocument/implementation"
592
+ result_controller << group_request do |group|
593
+ typecheck_workers.each do |worker|
594
+ group << send_request(method: message[:method], params: message[:params], worker: worker)
595
+ end
596
+
597
+ group.on_completion do |handlers|
598
+ links = handlers.flat_map(&:result)
599
+ job_queue << SendMessageJob.to_client(
600
+ message: {
601
+ id: message[:id],
602
+ result: links
603
+ }
604
+ )
605
+ end
606
+ end
607
+
587
608
  when "$/typecheck"
588
609
  request = controller.make_request(
589
610
  guid: message[:params][:guid],
@@ -11,6 +11,31 @@ module Steep
11
11
  TypeCheckCodeJob = Struct.new(:guid, :path, keyword_init: true)
12
12
  ValidateAppSignatureJob = Struct.new(:guid, :path, keyword_init: true)
13
13
  ValidateLibrarySignatureJob = Struct.new(:guid, :path, keyword_init: true)
14
+ GotoJob = Struct.new(:id, :kind, :params, keyword_init: true) do
15
+ def self.implementation(id:, params:)
16
+ new(
17
+ kind: :implementation,
18
+ id: id,
19
+ params: params
20
+ )
21
+ end
22
+
23
+ def self.definition(id:, params:)
24
+ new(
25
+ kind: :definition,
26
+ id: id,
27
+ params: params
28
+ )
29
+ end
30
+
31
+ def implementation?
32
+ kind == :implementation
33
+ end
34
+
35
+ def definition?
36
+ kind == :definition
37
+ end
38
+ end
14
39
 
15
40
  include ChangeBuffer
16
41
 
@@ -44,6 +69,10 @@ module Steep
44
69
  when "$/typecheck/start"
45
70
  params = request[:params]
46
71
  enqueue_typecheck_jobs(params)
72
+ when "textDocument/definition"
73
+ queue << GotoJob.definition(id: request[:id], params: request[:params])
74
+ when "textDocument/implementation"
75
+ queue << GotoJob.implementation(id: request[:id], params: request[:params])
47
76
  end
48
77
  end
49
78
 
@@ -115,7 +144,7 @@ module Steep
115
144
  if job.guid == current_type_check_guid
116
145
  Steep.logger.info { "Processing ValidateAppSignature for guid=#{job.guid}, path=#{job.path}" }
117
146
  service.validate_signature(path: project.relative_path(job.path)) do |path, diagnostics|
118
- formatter = Diagnostic::LSPFormatter.new()
147
+ formatter = Diagnostic::LSPFormatter.new({})
119
148
 
120
149
  writer.write(
121
150
  method: :"textDocument/publishDiagnostics",
@@ -133,13 +162,13 @@ module Steep
133
162
  if job.guid == current_type_check_guid
134
163
  Steep.logger.info { "Processing ValidateLibrarySignature for guid=#{job.guid}, path=#{job.path}" }
135
164
  service.validate_signature(path: job.path) do |path, diagnostics|
136
- formatter = Diagnostic::LSPFormatter.new()
165
+ formatter = Diagnostic::LSPFormatter.new({})
137
166
 
138
167
  writer.write(
139
168
  method: :"textDocument/publishDiagnostics",
140
169
  params: LSP::Interface::PublishDiagnosticsParams.new(
141
170
  uri: URI.parse(job.path.to_s).tap {|uri| uri.scheme = "file"},
142
- diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
171
+ diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
143
172
  )
144
173
  )
145
174
  end
@@ -151,17 +180,14 @@ module Steep
151
180
  if job.guid == current_type_check_guid
152
181
  Steep.logger.info { "Processing TypeCheckCodeJob for guid=#{job.guid}, path=#{job.path}" }
153
182
  service.typecheck_source(path: project.relative_path(job.path)) do |path, diagnostics|
154
- if target = project.target_for_source_path(path)
155
- diagnostics = diagnostics.select {|diagnostic| target.options.error_to_report?(diagnostic) }
156
- end
157
-
158
- formatter = Diagnostic::LSPFormatter.new()
183
+ target = project.target_for_source_path(path)
184
+ formatter = Diagnostic::LSPFormatter.new(target&.code_diagnostics_config || {})
159
185
 
160
186
  writer.write(
161
187
  method: :"textDocument/publishDiagnostics",
162
188
  params: LSP::Interface::PublishDiagnosticsParams.new(
163
189
  uri: URI.parse(job.path.to_s).tap {|uri| uri.scheme = "file"},
164
- diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
190
+ diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
165
191
  )
166
192
  )
167
193
  end
@@ -179,6 +205,11 @@ module Steep
179
205
  id: job.id,
180
206
  result: stats_result().map(&:as_json)
181
207
  )
208
+ when GotoJob
209
+ writer.write(
210
+ id: job.id,
211
+ result: goto(job)
212
+ )
182
213
  end
183
214
  end
184
215
 
@@ -231,6 +262,40 @@ module Steep
231
262
  end
232
263
  end
233
264
  end
265
+
266
+ def goto(job)
267
+ path = Pathname(URI.parse(job.params[:textDocument][:uri]).path)
268
+ line = job.params[:position][:line] + 1
269
+ column = job.params[:position][:character]
270
+
271
+ goto_service = Services::GotoService.new(type_check: service)
272
+ locations =
273
+ case
274
+ when job.definition?
275
+ goto_service.definition(path: path, line: line, column: column)
276
+ when job.implementation?
277
+ goto_service.implementation(path: path, line: line, column: column)
278
+ else
279
+ raise
280
+ end
281
+
282
+ locations.map do |loc|
283
+ path =
284
+ case loc
285
+ when RBS::Location
286
+ Pathname(loc.buffer.name)
287
+ else
288
+ Pathname(loc.source_buffer.name)
289
+ end
290
+
291
+ path = project.absolute_path(path)
292
+
293
+ {
294
+ uri: URI.parse(path.to_s).tap {|uri| uri.scheme = "file" }.to_s,
295
+ range: loc.as_lsp_range
296
+ }
297
+ end
298
+ end
234
299
  end
235
300
  end
236
301
  end
@@ -8,29 +8,36 @@ module Steep
8
8
  end
9
9
 
10
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
11
+ if block_given?
12
+ pats = commandline_patterns.empty? ? pattern.patterns : commandline_patterns
13
+
14
+ pats.each do |path|
15
+ absolute_path = base_dir + path
16
+
17
+ if absolute_path.file?
18
+ if pattern =~ path
19
+ yield absolute_path.relative_path_from(base_dir)
20
+ end
21
+ else
22
+ files = if absolute_path.directory?
23
+ Pathname.glob("#{absolute_path}/**/*#{pattern.ext}")
24
+ else
25
+ Pathname.glob(absolute_path)
26
+ end
27
+
28
+ files.sort.each do |source_path|
29
+ if source_path.file?
30
+ relative_path = source_path.relative_path_from(base_dir)
31
+ unless pattern.ignore?(relative_path)
32
+ yield relative_path
33
+ end
30
34
  end
31
35
  end
32
36
  end
37
+
33
38
  end
39
+ else
40
+ enum_for :each_path_in_patterns, pattern, commandline_patterns
34
41
  end
35
42
  end
36
43
 
@@ -0,0 +1,322 @@
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
+ node = parents[0] if parents[0]&.type == :block
129
+ case call = typing.call_of(node: node)
130
+ when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
131
+ call.method_decls.each do |decl|
132
+ queries << MethodQuery.new(name: decl.method_name, from: :ruby)
133
+ end
134
+ when TypeInference::MethodCall::Untyped
135
+ # nop
136
+ when TypeInference::MethodCall::NoMethodError
137
+ # nop
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ when target_names = type_check.signature_file?(path)
144
+ target_names.each do |target_name|
145
+ signature_service = type_check.signature_services[target_name]
146
+ decls = signature_service.latest_env.declarations.select do |decl|
147
+ buffer_path = Pathname(decl.location.buffer.name)
148
+ buffer_path == relative_path || buffer_path == path
149
+ end
150
+
151
+ locator = RBS::Locator.new(decls: decls)
152
+ last, nodes = locator.find2(line: line, column: column)
153
+ case nodes[0]
154
+ when RBS::AST::Declarations::Class, RBS::AST::Declarations::Module
155
+ if last == :name
156
+ queries << ConstantQuery.new(name: nodes[0].name, from: :rbs)
157
+ end
158
+ when RBS::AST::Declarations::Constant
159
+ if last == :name
160
+ queries << ConstantQuery.new(name: nodes[0].name, from: :rbs)
161
+ end
162
+ when RBS::AST::Members::MethodDefinition
163
+ if last == :name
164
+ type_name = nodes[1].name
165
+ method_name = nodes[0].name
166
+ if nodes[0].instance?
167
+ queries << MethodQuery.new(
168
+ name: InstanceMethodName.new(type_name: type_name, method_name: method_name),
169
+ from: :rbs
170
+ )
171
+ end
172
+ if nodes[0].singleton?
173
+ queries << MethodQuery.new(
174
+ name: SingletonMethodName.new(type_name: type_name, method_name: method_name),
175
+ from: :rbs
176
+ )
177
+ end
178
+ end
179
+ when RBS::AST::Members::Include, RBS::AST::Members::Extend, RBS::AST::Members::Prepend
180
+ if last == :name
181
+ queries << TypeNameQuery.new(name: nodes[0].name)
182
+ end
183
+ when RBS::Types::ClassInstance, RBS::Types::ClassSingleton, RBS::Types::Interface, RBS::Types::Alias
184
+ if last == :name
185
+ queries << TypeNameQuery.new(name: nodes[0].name)
186
+ end
187
+ when RBS::AST::Declarations::Class::Super, RBS::AST::Declarations::Module::Self
188
+ if last == :name
189
+ queries << TypeNameQuery.new(name: nodes[0].name)
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ queries
196
+ end
197
+
198
+ def type_check_path(target:, path:, content:, line:, column:)
199
+ signature_service = type_check.signature_services[target.name]
200
+ subtyping = signature_service.current_subtyping or return
201
+ source = Source.parse(content, path: path, factory: subtyping.factory)
202
+ source = source.without_unrelated_defs(line: line, column: column)
203
+ [
204
+ Services::TypeCheckService.type_check(source: source, subtyping: subtyping),
205
+ signature_service
206
+ ]
207
+ rescue
208
+ nil
209
+ end
210
+
211
+ def constant_definition_in_rbs(name, locations:)
212
+ type_check.signature_services.each_value do |signature|
213
+ env = signature.latest_env
214
+
215
+ if entry = env.class_decls[name]
216
+ entry.decls.each do |d|
217
+ locations << d.decl.location[:name]
218
+ end
219
+ end
220
+
221
+ if entry = env.constant_decls[name]
222
+ locations << entry.decl.location[:name]
223
+ end
224
+ end
225
+
226
+ locations
227
+ end
228
+
229
+ def constant_definition_in_ruby(name, locations:)
230
+ type_check.source_files.each do |path, source|
231
+ if typing = source.typing
232
+ entry = typing.source_index.entry(constant: name)
233
+ entry.definitions.each do |node|
234
+ case node.type
235
+ when :class, :module
236
+ locations << node.children[0].location.expression
237
+ when :casgn
238
+ parent = node.children[0]
239
+ location =
240
+ if parent
241
+ parent.location.expression.join(node.location.name)
242
+ else
243
+ node.location.name
244
+ end
245
+ locations << location
246
+ end
247
+ end
248
+ end
249
+ end
250
+
251
+ locations
252
+ end
253
+
254
+ def method_locations(name, in_ruby:, in_rbs:, locations:)
255
+ if in_ruby
256
+ type_check.source_files.each do |path, source|
257
+ if typing = source.typing
258
+ entry = typing.source_index.entry(method: name)
259
+
260
+ if entry.definitions.empty?
261
+ if name.is_a?(SingletonMethodName) && name.method_name == :new
262
+ initialize = InstanceMethodName.new(method_name: :initialize, type_name: name.type_name)
263
+ entry = typing.source_index.entry(method: initialize)
264
+ end
265
+ end
266
+
267
+ entry.definitions.each do |node|
268
+ case node.type
269
+ when :def
270
+ locations << node.location.name
271
+ when :defs
272
+ locations << node.location.name
273
+ end
274
+ end
275
+ end
276
+ end
277
+ end
278
+
279
+ if in_rbs
280
+ type_check.signature_services.each_value do |signature|
281
+ index = signature.latest_rbs_index
282
+
283
+ entry = index.entry(method_name: name)
284
+
285
+ if entry.declarations.empty?
286
+ if name.is_a?(SingletonMethodName) && name.method_name == :new
287
+ initialize = InstanceMethodName.new(method_name: :initialize, type_name: name.type_name)
288
+ entry = index.entry(method_name: initialize)
289
+ end
290
+ end
291
+
292
+ entry.declarations.each do |decl|
293
+ case decl
294
+ when RBS::AST::Members::MethodDefinition
295
+ locations << decl.location[:name]
296
+ when RBS::AST::Members::Alias
297
+ locations << decl.location[:new_name]
298
+ when RBS::AST::Members::AttrAccessor, RBS::AST::Members::AttrReader, RBS::AST::Members::AttrWriter
299
+ locations << decl.location[:name]
300
+ end
301
+ end
302
+ end
303
+ end
304
+
305
+ locations
306
+ end
307
+
308
+ def type_name_locations(name, locations: [])
309
+ type_check.signature_services.each_value do |signature|
310
+ index = signature.latest_rbs_index
311
+
312
+ entry = index.entry(type_name: name)
313
+ entry.declarations.each do |decl|
314
+ locations << decl.location[:name]
315
+ end
316
+ end
317
+
318
+ locations
319
+ end
320
+ end
321
+ end
322
+ end