steep 0.44.0 → 0.47.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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/ruby.yml +3 -2
- data/.gitignore +0 -1
- data/CHANGELOG.md +42 -0
- data/Gemfile +0 -3
- data/Gemfile.lock +75 -0
- data/README.md +2 -1
- data/lib/steep/annotation_parser.rb +1 -1
- data/lib/steep/ast/builtin.rb +7 -1
- data/lib/steep/ast/types/factory.rb +19 -25
- data/lib/steep/cli.rb +7 -1
- data/lib/steep/diagnostic/lsp_formatter.rb +59 -6
- data/lib/steep/diagnostic/ruby.rb +188 -60
- data/lib/steep/diagnostic/signature.rb +38 -15
- data/lib/steep/drivers/check.rb +3 -0
- data/lib/steep/drivers/init.rb +10 -3
- data/lib/steep/drivers/utils/driver_helper.rb +15 -0
- data/lib/steep/drivers/validate.rb +1 -1
- data/lib/steep/drivers/watch.rb +3 -0
- data/lib/steep/equatable.rb +21 -0
- data/lib/steep/interface/function.rb +798 -579
- data/lib/steep/project/dsl.rb +135 -36
- data/lib/steep/project/options.rb +13 -53
- data/lib/steep/project/target.rb +22 -8
- data/lib/steep/server/interaction_worker.rb +245 -26
- data/lib/steep/server/master.rb +2 -2
- data/lib/steep/server/type_check_worker.rb +6 -9
- data/lib/steep/services/file_loader.rb +26 -19
- data/lib/steep/services/goto_service.rb +1 -0
- data/lib/steep/services/hover_content.rb +135 -80
- data/lib/steep/source.rb +12 -11
- data/lib/steep/type_construction.rb +435 -502
- data/lib/steep/type_inference/block_params.rb +3 -6
- data/lib/steep/type_inference/method_params.rb +483 -0
- data/lib/steep/type_inference/send_args.rb +599 -128
- data/lib/steep/typing.rb +46 -21
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +4 -2
- data/sample/Steepfile +10 -3
- data/smoke/alias/Steepfile +2 -1
- data/smoke/and/Steepfile +2 -1
- data/smoke/array/Steepfile +2 -1
- data/smoke/array/test_expectations.yml +3 -3
- data/smoke/block/Steepfile +2 -2
- data/smoke/block/c.rb +0 -1
- data/smoke/case/Steepfile +2 -1
- data/smoke/class/Steepfile +2 -1
- data/smoke/class/test_expectations.yml +12 -15
- data/smoke/const/Steepfile +2 -1
- data/smoke/diagnostics/Steepfile +2 -1
- data/smoke/diagnostics/different_method_parameter_kind.rb +9 -0
- data/smoke/diagnostics/method_arity_mismatch.rb +2 -2
- data/smoke/diagnostics/method_parameter_mismatch.rb +10 -0
- data/smoke/diagnostics/test_expectations.yml +108 -31
- data/smoke/diagnostics-rbs/Steepfile +1 -1
- data/smoke/diagnostics-rbs/mixin-class-error.rbs +6 -0
- data/smoke/diagnostics-rbs/test_expectations.yml +12 -0
- data/smoke/diagnostics-rbs-duplicated/Steepfile +2 -1
- data/smoke/diagnostics-ruby-unsat/Steepfile +2 -1
- data/smoke/dstr/Steepfile +2 -1
- data/smoke/ensure/Steepfile +2 -1
- data/smoke/ensure/test_expectations.yml +3 -3
- data/smoke/enumerator/Steepfile +2 -1
- data/smoke/enumerator/test_expectations.yml +1 -1
- data/smoke/extension/Steepfile +2 -1
- data/smoke/extension/e.rbs +1 -1
- data/smoke/hash/Steepfile +2 -1
- data/smoke/hello/Steepfile +2 -1
- data/smoke/if/Steepfile +2 -1
- data/smoke/implements/Steepfile +2 -1
- data/smoke/initialize/Steepfile +2 -1
- data/smoke/integer/Steepfile +2 -1
- data/smoke/interface/Steepfile +2 -1
- data/smoke/kwbegin/Steepfile +2 -1
- data/smoke/lambda/Steepfile +2 -1
- data/smoke/literal/Steepfile +2 -1
- data/smoke/literal/test_expectations.yml +2 -2
- data/smoke/map/Steepfile +2 -1
- data/smoke/method/Steepfile +2 -1
- data/smoke/method/test_expectations.yml +11 -10
- data/smoke/module/Steepfile +2 -1
- data/smoke/regexp/Steepfile +2 -1
- data/smoke/regression/Steepfile +2 -1
- data/smoke/rescue/Steepfile +2 -1
- data/smoke/rescue/test_expectations.yml +3 -3
- data/smoke/self/Steepfile +2 -1
- data/smoke/skip/Steepfile +2 -1
- data/smoke/stdout/Steepfile +2 -1
- data/smoke/super/Steepfile +2 -1
- data/smoke/toplevel/Steepfile +2 -1
- data/smoke/toplevel/test_expectations.yml +3 -3
- data/smoke/tsort/Steepfile +4 -5
- data/smoke/tsort/test_expectations.yml +2 -2
- data/smoke/type_case/Steepfile +2 -1
- data/smoke/unexpected/Steepfile +2 -1
- data/smoke/yield/Steepfile +2 -1
- data/steep.gemspec +2 -2
- metadata +16 -10
- data/sig/project.rbi +0 -109
@@ -7,6 +7,8 @@ module Steep
|
|
7
7
|
HoverJob = Struct.new(:id, :path, :line, :column, keyword_init: true)
|
8
8
|
CompletionJob = Struct.new(:id, :path, :line, :column, :trigger, keyword_init: true)
|
9
9
|
|
10
|
+
LSP = LanguageServer::Protocol
|
11
|
+
|
10
12
|
attr_reader :service
|
11
13
|
|
12
14
|
def initialize(project:, reader:, writer:, queue: Queue.new)
|
@@ -77,11 +79,12 @@ module Steep
|
|
77
79
|
Steep.logger.info { "path=#{job.path}, line=#{job.line}, column=#{job.column}" }
|
78
80
|
|
79
81
|
hover = Services::HoverContent.new(service: service)
|
80
|
-
content = hover.content_for(path: job.path, line: job.line, column: job.column
|
82
|
+
content = hover.content_for(path: job.path, line: job.line, column: job.column)
|
81
83
|
if content
|
82
84
|
range = content.location.yield_self do |location|
|
83
|
-
|
84
|
-
|
85
|
+
lsp_range = location.as_lsp_range
|
86
|
+
start_position = { line: lsp_range[:start][:line], character: lsp_range[:start][:character] }
|
87
|
+
end_position = { line: lsp_range[:end][:line], character: lsp_range[:end][:character] }
|
85
88
|
{ start: start_position, end: end_position }
|
86
89
|
end
|
87
90
|
|
@@ -99,6 +102,36 @@ module Steep
|
|
99
102
|
|
100
103
|
def format_hover(content)
|
101
104
|
case content
|
105
|
+
when Services::HoverContent::TypeAliasContent
|
106
|
+
comment = content.decl.comment&.string || ''
|
107
|
+
|
108
|
+
<<-MD
|
109
|
+
#{comment}
|
110
|
+
|
111
|
+
```rbs
|
112
|
+
#{retrieve_decl_information(content.decl)}
|
113
|
+
```
|
114
|
+
MD
|
115
|
+
when Services::HoverContent::InterfaceContent
|
116
|
+
comment = content.decl.comment&.string || ''
|
117
|
+
|
118
|
+
<<-MD
|
119
|
+
#{comment}
|
120
|
+
|
121
|
+
```rbs
|
122
|
+
#{retrieve_decl_information(content.decl)}
|
123
|
+
```
|
124
|
+
MD
|
125
|
+
when Services::HoverContent::ClassContent
|
126
|
+
comment = content.decl.comment&.string || ''
|
127
|
+
|
128
|
+
<<-MD
|
129
|
+
#{comment}
|
130
|
+
|
131
|
+
```rbs
|
132
|
+
#{retrieve_decl_information(content.decl)}
|
133
|
+
```
|
134
|
+
MD
|
102
135
|
when Services::HoverContent::VariableContent
|
103
136
|
"`#{content.name}`: `#{content.type.to_s}`"
|
104
137
|
when Services::HoverContent::MethodCallContent
|
@@ -151,32 +184,207 @@ HOVER
|
|
151
184
|
Steep.logger.tagged("#response_to_completion") do
|
152
185
|
Steep.measure "Generating response" do
|
153
186
|
Steep.logger.info "path: #{job.path}, line: #{job.line}, column: #{job.column}, trigger: #{job.trigger}"
|
187
|
+
case
|
188
|
+
when target = project.target_for_source_path(job.path)
|
189
|
+
file = service.source_files[job.path] or return
|
190
|
+
subtyping = service.signature_services[target.name].current_subtyping or return
|
191
|
+
|
192
|
+
provider = Services::CompletionProvider.new(source_text: file.content, path: job.path, subtyping: subtyping)
|
193
|
+
items = begin
|
194
|
+
provider.run(line: job.line, column: job.column)
|
195
|
+
rescue Parser::SyntaxError
|
196
|
+
[]
|
197
|
+
end
|
198
|
+
|
199
|
+
completion_items = items.map do |item|
|
200
|
+
format_completion_item(item)
|
201
|
+
end
|
202
|
+
|
203
|
+
Steep.logger.debug "items = #{completion_items.inspect}"
|
204
|
+
|
205
|
+
LSP::Interface::CompletionList.new(
|
206
|
+
is_incomplete: false,
|
207
|
+
items: completion_items
|
208
|
+
)
|
209
|
+
when (_, targets = project.targets_for_path(job.path))
|
210
|
+
target = targets[0] or return
|
211
|
+
sig_service = service.signature_services[target.name]
|
212
|
+
relative_path = job.path
|
213
|
+
buffer = RBS::Buffer.new(name: relative_path, content: sig_service.files[relative_path].content)
|
214
|
+
pos = buffer.loc_to_pos([job.line, job.column])
|
215
|
+
prefix = buffer.content[0...pos].reverse[/\A[\w\d]*/].reverse
|
216
|
+
|
217
|
+
case sig_service.status
|
218
|
+
when Steep::Services::SignatureService::SyntaxErrorStatus, Steep::Services::SignatureService::AncestorErrorStatus
|
219
|
+
return
|
220
|
+
end
|
221
|
+
|
222
|
+
decls = sig_service.files[relative_path].decls
|
223
|
+
locator = RBS::Locator.new(decls: decls)
|
224
|
+
|
225
|
+
hd, tail = locator.find2(line: job.line, column: job.column)
|
226
|
+
|
227
|
+
namespace = []
|
228
|
+
tail.each do |t|
|
229
|
+
case t
|
230
|
+
when RBS::AST::Declarations::Module, RBS::AST::Declarations::Class
|
231
|
+
namespace << t.name.to_namespace
|
232
|
+
end
|
233
|
+
end
|
234
|
+
context = []
|
235
|
+
|
236
|
+
namespace.each do |ns|
|
237
|
+
context.map! { |n| ns + n }
|
238
|
+
context << ns
|
239
|
+
end
|
240
|
+
|
241
|
+
context.map!(&:absolute!)
|
242
|
+
|
243
|
+
class_items = sig_service.latest_env.class_decls.keys.map { |type_name|
|
244
|
+
format_completion_item_for_rbs(sig_service, type_name, context, job, prefix)
|
245
|
+
}.compact
|
154
246
|
|
155
|
-
|
156
|
-
|
157
|
-
|
247
|
+
alias_items = sig_service.latest_env.alias_decls.keys.map { |type_name|
|
248
|
+
format_completion_item_for_rbs(sig_service, type_name, context, job, prefix)
|
249
|
+
}.compact
|
158
250
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
rescue Parser::SyntaxError
|
163
|
-
[]
|
164
|
-
end
|
251
|
+
interface_items = sig_service.latest_env.interface_decls.keys.map {|type_name|
|
252
|
+
format_completion_item_for_rbs(sig_service, type_name, context, job, prefix)
|
253
|
+
}.compact
|
165
254
|
|
166
|
-
|
167
|
-
|
255
|
+
completion_items = class_items + alias_items + interface_items
|
256
|
+
|
257
|
+
LSP::Interface::CompletionList.new(
|
258
|
+
is_incomplete: false,
|
259
|
+
items: completion_items
|
260
|
+
)
|
168
261
|
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
169
265
|
|
170
|
-
|
266
|
+
def format_completion_item_for_rbs(sig_service, type_name, context, job, prefix)
|
267
|
+
range = LanguageServer::Protocol::Interface::Range.new(
|
268
|
+
start: LanguageServer::Protocol::Interface::Position.new(
|
269
|
+
line: job.line - 1,
|
270
|
+
character: job.column - prefix.size
|
271
|
+
),
|
272
|
+
end: LanguageServer::Protocol::Interface::Position.new(
|
273
|
+
line: job.line - 1,
|
274
|
+
character: job.column - prefix.size
|
275
|
+
)
|
276
|
+
)
|
171
277
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
278
|
+
name = relative_name_in_context(type_name, context).to_s
|
279
|
+
|
280
|
+
return unless name.start_with?(prefix)
|
281
|
+
|
282
|
+
case type_name.kind
|
283
|
+
when :class
|
284
|
+
class_decl = sig_service.latest_env.class_decls[type_name]&.decls[0]&.decl or raise
|
285
|
+
|
286
|
+
LanguageServer::Protocol::Interface::CompletionItem.new(
|
287
|
+
label: "#{name}",
|
288
|
+
documentation: format_comment(class_decl.comment),
|
289
|
+
text_edit: LanguageServer::Protocol::Interface::TextEdit.new(
|
290
|
+
range: range,
|
291
|
+
new_text: name
|
292
|
+
),
|
293
|
+
kind: LSP::Constant::CompletionItemKind::CLASS,
|
294
|
+
insert_text_format: LSP::Constant::InsertTextFormat::SNIPPET
|
295
|
+
|
296
|
+
)
|
297
|
+
when :alias
|
298
|
+
alias_decl = sig_service.latest_env.alias_decls[type_name]&.decl or raise
|
299
|
+
LanguageServer::Protocol::Interface::CompletionItem.new(
|
300
|
+
label: "#{name}",
|
301
|
+
text_edit: LanguageServer::Protocol::Interface::TextEdit.new(
|
302
|
+
range: range,
|
303
|
+
new_text: name
|
304
|
+
),
|
305
|
+
documentation: format_comment(alias_decl.comment),
|
306
|
+
# https://github.com/microsoft/vscode-languageserver-node/blob/6d78fc4d25719b231aba64a721a606f58b9e0a5f/client/src/common/client.ts#L624-L650
|
307
|
+
kind: LSP::Constant::CompletionItemKind::FIELD,
|
308
|
+
insert_text_format: LSP::Constant::InsertTextFormat::SNIPPET
|
309
|
+
)
|
310
|
+
when :interface
|
311
|
+
interface_decl = sig_service.latest_env.interface_decls[type_name]&.decl or raise
|
312
|
+
|
313
|
+
LanguageServer::Protocol::Interface::CompletionItem.new(
|
314
|
+
label: "#{name}",
|
315
|
+
text_edit: LanguageServer::Protocol::Interface::TextEdit.new(
|
316
|
+
range: range,
|
317
|
+
new_text: name
|
318
|
+
),
|
319
|
+
documentation: format_comment(interface_decl.comment),
|
320
|
+
kind: LanguageServer::Protocol::Constant::CompletionItemKind::INTERFACE,
|
321
|
+
insert_text_format: LanguageServer::Protocol::Constant::InsertTextFormat::SNIPPET
|
322
|
+
)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
def format_comment(comment)
|
327
|
+
if comment
|
328
|
+
LSP::Interface::MarkupContent.new(
|
329
|
+
kind: LSP::Constant::MarkupKind::MARKDOWN,
|
330
|
+
value: comment.string
|
331
|
+
)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
def name_and_params(name, params)
|
336
|
+
if params.empty?
|
337
|
+
"#{name}"
|
338
|
+
else
|
339
|
+
ps = params.each.map do |param|
|
340
|
+
s = ""
|
341
|
+
if param.skip_validation
|
342
|
+
s << "unchecked "
|
343
|
+
end
|
344
|
+
case param.variance
|
345
|
+
when :invariant
|
346
|
+
# nop
|
347
|
+
when :covariant
|
348
|
+
s << "out "
|
349
|
+
when :contravariant
|
350
|
+
s << "in "
|
351
|
+
end
|
352
|
+
s + param.name.to_s
|
353
|
+
end
|
354
|
+
|
355
|
+
"#{name}[#{ps.join(", ")}]"
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
def name_and_args(name, args)
|
360
|
+
if name && args
|
361
|
+
if args.empty?
|
362
|
+
"#{name}"
|
363
|
+
else
|
364
|
+
"#{name}[#{args.join(", ")}]"
|
176
365
|
end
|
177
366
|
end
|
178
367
|
end
|
179
368
|
|
369
|
+
def retrieve_decl_information(decl)
|
370
|
+
case decl
|
371
|
+
when RBS::AST::Declarations::Class
|
372
|
+
super_class = if super_class = decl.super_class
|
373
|
+
" < #{name_and_args(super_class.name, super_class.args)}"
|
374
|
+
end
|
375
|
+
"class #{name_and_params(decl.name, decl.type_params)}#{super_class}"
|
376
|
+
when RBS::AST::Declarations::Module
|
377
|
+
self_type = unless decl.self_types.empty?
|
378
|
+
" : #{decl.self_types.join(", ")}"
|
379
|
+
end
|
380
|
+
"module #{name_and_params(decl.name, decl.type_params)}#{self_type}"
|
381
|
+
when RBS::AST::Declarations::Alias
|
382
|
+
"type #{decl.name} = #{decl.type}"
|
383
|
+
when RBS::AST::Declarations::Interface
|
384
|
+
"interface #{name_and_params(decl.name, decl.type_params)}"
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
180
388
|
def format_completion_item(item)
|
181
389
|
range = LanguageServer::Protocol::Interface::Range.new(
|
182
390
|
start: LanguageServer::Protocol::Interface::Position.new(
|
@@ -194,18 +402,18 @@ HOVER
|
|
194
402
|
LanguageServer::Protocol::Interface::CompletionItem.new(
|
195
403
|
label: item.identifier,
|
196
404
|
kind: LanguageServer::Protocol::Constant::CompletionItemKind::VARIABLE,
|
197
|
-
detail:
|
405
|
+
detail: item.type.to_s,
|
198
406
|
text_edit: LanguageServer::Protocol::Interface::TextEdit.new(
|
199
407
|
range: range,
|
200
|
-
new_text:
|
408
|
+
new_text: item.identifier
|
201
409
|
)
|
202
410
|
)
|
203
411
|
when Services::CompletionProvider::MethodNameItem
|
204
|
-
label = "def #{item.identifier}: #{item.method_type}"
|
205
412
|
method_type_snippet = method_type_to_snippet(item.method_type)
|
206
413
|
LanguageServer::Protocol::Interface::CompletionItem.new(
|
207
|
-
label:
|
414
|
+
label: item.identifier,
|
208
415
|
kind: LanguageServer::Protocol::Constant::CompletionItemKind::METHOD,
|
416
|
+
detail: item.method_type.to_s,
|
209
417
|
text_edit: LanguageServer::Protocol::Interface::TextEdit.new(
|
210
418
|
new_text: "#{item.identifier}#{method_type_snippet}",
|
211
419
|
range: range
|
@@ -215,14 +423,14 @@ HOVER
|
|
215
423
|
sort_text: item.inherited? ? 'z' : 'a' # Ensure language server puts non-inherited methods before inherited methods
|
216
424
|
)
|
217
425
|
when Services::CompletionProvider::InstanceVariableItem
|
218
|
-
label = "#{item.identifier}: #{item.type}"
|
219
426
|
LanguageServer::Protocol::Interface::CompletionItem.new(
|
220
|
-
label:
|
427
|
+
label: item.identifier,
|
221
428
|
kind: LanguageServer::Protocol::Constant::CompletionItemKind::FIELD,
|
429
|
+
detail: item.type.to_s,
|
222
430
|
text_edit: LanguageServer::Protocol::Interface::TextEdit.new(
|
223
431
|
range: range,
|
224
432
|
new_text: item.identifier,
|
225
|
-
|
433
|
+
),
|
226
434
|
insert_text_format: LanguageServer::Protocol::Constant::InsertTextFormat::SNIPPET
|
227
435
|
)
|
228
436
|
end
|
@@ -297,6 +505,17 @@ HOVER
|
|
297
505
|
|
298
506
|
params.join(", ")
|
299
507
|
end
|
508
|
+
|
509
|
+
def relative_name_in_context(type_name, context)
|
510
|
+
context.each do |namespace|
|
511
|
+
if (type_name.to_s == namespace.to_type_name.to_s || type_name.namespace.to_s == "::")
|
512
|
+
return RBS::TypeName.new(namespace: RBS::Namespace.empty, name: type_name.name)
|
513
|
+
elsif type_name.to_s.start_with?(namespace.to_s)
|
514
|
+
return TypeName(type_name.to_s.sub(namespace.to_type_name.to_s, '')).relative!
|
515
|
+
end
|
516
|
+
end
|
517
|
+
type_name
|
518
|
+
end
|
300
519
|
end
|
301
520
|
end
|
302
521
|
end
|
data/lib/steep/server/master.rb
CHANGED
@@ -501,9 +501,9 @@ module Steep
|
|
501
501
|
),
|
502
502
|
workspace_symbol_provider: true,
|
503
503
|
definition_provider: true,
|
504
|
-
declaration_provider:
|
504
|
+
declaration_provider: false,
|
505
505
|
implementation_provider: true,
|
506
|
-
type_definition_provider:
|
506
|
+
type_definition_provider: false
|
507
507
|
)
|
508
508
|
)
|
509
509
|
}
|
@@ -144,7 +144,7 @@ module Steep
|
|
144
144
|
if job.guid == current_type_check_guid
|
145
145
|
Steep.logger.info { "Processing ValidateAppSignature for guid=#{job.guid}, path=#{job.path}" }
|
146
146
|
service.validate_signature(path: project.relative_path(job.path)) do |path, diagnostics|
|
147
|
-
formatter = Diagnostic::LSPFormatter.new()
|
147
|
+
formatter = Diagnostic::LSPFormatter.new({})
|
148
148
|
|
149
149
|
writer.write(
|
150
150
|
method: :"textDocument/publishDiagnostics",
|
@@ -162,13 +162,13 @@ module Steep
|
|
162
162
|
if job.guid == current_type_check_guid
|
163
163
|
Steep.logger.info { "Processing ValidateLibrarySignature for guid=#{job.guid}, path=#{job.path}" }
|
164
164
|
service.validate_signature(path: job.path) do |path, diagnostics|
|
165
|
-
formatter = Diagnostic::LSPFormatter.new()
|
165
|
+
formatter = Diagnostic::LSPFormatter.new({})
|
166
166
|
|
167
167
|
writer.write(
|
168
168
|
method: :"textDocument/publishDiagnostics",
|
169
169
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
170
170
|
uri: URI.parse(job.path.to_s).tap {|uri| uri.scheme = "file"},
|
171
|
-
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
|
171
|
+
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
172
172
|
)
|
173
173
|
)
|
174
174
|
end
|
@@ -180,17 +180,14 @@ module Steep
|
|
180
180
|
if job.guid == current_type_check_guid
|
181
181
|
Steep.logger.info { "Processing TypeCheckCodeJob for guid=#{job.guid}, path=#{job.path}" }
|
182
182
|
service.typecheck_source(path: project.relative_path(job.path)) do |path, diagnostics|
|
183
|
-
|
184
|
-
|
185
|
-
end
|
186
|
-
|
187
|
-
formatter = Diagnostic::LSPFormatter.new()
|
183
|
+
target = project.target_for_source_path(path)
|
184
|
+
formatter = Diagnostic::LSPFormatter.new(target&.code_diagnostics_config || {})
|
188
185
|
|
189
186
|
writer.write(
|
190
187
|
method: :"textDocument/publishDiagnostics",
|
191
188
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
192
189
|
uri: URI.parse(job.path.to_s).tap {|uri| uri.scheme = "file"},
|
193
|
-
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
|
190
|
+
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
194
191
|
)
|
195
192
|
)
|
196
193
|
end
|
@@ -8,29 +8,36 @@ module Steep
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def each_path_in_patterns(pattern, commandline_patterns = [])
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
|
@@ -125,6 +125,7 @@ module Steep
|
|
125
125
|
end
|
126
126
|
when :send
|
127
127
|
if test_ast_location(node.location.selector, line: line, column: column)
|
128
|
+
node = parents[0] if parents[0]&.type == :block
|
128
129
|
case call = typing.call_of(node: node)
|
129
130
|
when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
|
130
131
|
call.method_decls.each do |decl|
|