steep 1.9.4 → 1.10.0.pre.1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -3
  3. data/Steepfile +5 -2
  4. data/lib/steep/annotations_helper.rb +43 -0
  5. data/lib/steep/ast/ignore.rb +3 -4
  6. data/lib/steep/cli.rb +102 -23
  7. data/lib/steep/diagnostic/lsp_formatter.rb +17 -3
  8. data/lib/steep/diagnostic/ruby.rb +75 -0
  9. data/lib/steep/diagnostic/signature.rb +20 -0
  10. data/lib/steep/drivers/check.rb +3 -1
  11. data/lib/steep/drivers/diagnostic_printer/base_formatter.rb +19 -0
  12. data/lib/steep/drivers/diagnostic_printer/code_formatter.rb +95 -0
  13. data/lib/steep/drivers/diagnostic_printer/github_actions_formatter.rb +44 -0
  14. data/lib/steep/drivers/diagnostic_printer.rb +9 -86
  15. data/lib/steep/drivers/langserver.rb +4 -1
  16. data/lib/steep/drivers/worker.rb +2 -0
  17. data/lib/steep/interface/builder.rb +2 -2
  18. data/lib/steep/server/custom_methods.rb +12 -0
  19. data/lib/steep/server/interaction_worker.rb +33 -6
  20. data/lib/steep/server/master.rb +103 -7
  21. data/lib/steep/server/type_check_worker.rb +48 -2
  22. data/lib/steep/server/worker_process.rb +31 -20
  23. data/lib/steep/services/completion_provider.rb +12 -2
  24. data/lib/steep/services/signature_service.rb +2 -2
  25. data/lib/steep/services/type_check_service.rb +22 -7
  26. data/lib/steep/signature/validator.rb +56 -4
  27. data/lib/steep/source.rb +3 -1
  28. data/lib/steep/subtyping/check.rb +22 -16
  29. data/lib/steep/type_construction.rb +153 -34
  30. data/lib/steep/type_inference/case_when.rb +2 -0
  31. data/lib/steep/type_inference/logic_type_interpreter.rb +77 -15
  32. data/lib/steep/type_inference/method_call.rb +5 -3
  33. data/lib/steep/version.rb +1 -1
  34. data/lib/steep.rb +10 -0
  35. data/manual/ruby-diagnostics.md +114 -1
  36. data/sample/Steepfile +0 -2
  37. data/sample/lib/conference.rb +14 -0
  38. data/sample/lib/deprecated.rb +7 -0
  39. data/sample/sig/deprecated.rbs +16 -0
  40. data/steep.gemspec +4 -3
  41. metadata +28 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b23b392399196d67221acd72708ebe27ee3b7bbb7b54e4b5922e8ecbb6ceb5e3
4
- data.tar.gz: a315e09c38f8736bc66aad3a57275f8546c28c75845fa33a9de375387cc63a13
3
+ metadata.gz: 2233f51ac985ee697a7f3617582dc034f32b1cd3b0732a87b8184210f2c1d7b0
4
+ data.tar.gz: 1298685cafa59f5074afa950df4c1f14cff9a8b6be9b99b914902b37e537aad3
5
5
  SHA512:
6
- metadata.gz: 1fe50cd4df36c00affa8868857d55deeea0e58c36372260209d95fabec69eb9f005d37581c5184c0b44e3a5fb1d42bd5bb25a5630c5dfafa4552b08a8fb87377
7
- data.tar.gz: bc41b2386db2d9a97dabf2c81ff2079c6fac875decc01ba223d1475473048945d81ba43cc17f0db24f6ba2da285954dff83e10910b5f3831716781698b458d9e
6
+ metadata.gz: 1cb518e2f5743330e58b0c6032ed99d22f29254b91d9c8e33e3bafc3cb1a9f46247f181ee5b9b078dba13768f675f03b1c2e8fb24b53609902d6534092625282
7
+ data.tar.gz: e26fde370f8d793b13138d71dc6295ffde59e781ed2d0a39cf73e639c8440517d7fa13586d871c9eab6880ae8864c31a711beb45c49280152416d0111935f3da
data/CHANGELOG.md CHANGED
@@ -1,14 +1,45 @@
1
1
  # CHANGELOG
2
2
 
3
- ## 1.9.4 (2025-02-04)
3
+ ## 1.10.0.pre.1 (2025-03-11)
4
+
5
+ ### Type checker core
6
+
7
+ * Skip type checking forwarded argument if the method is undeclared ([#1519](https://github.com/soutaro/steep/pull/1519))
8
+ * Dedup error message on ancestors check ([#1515](https://github.com/soutaro/steep/pull/1515))
9
+ * Add deprecation validation on RBS ([#1518](https://github.com/soutaro/steep/pull/1518))
10
+ * Fix union self type refinement based on method call ([#1517](https://github.com/soutaro/steep/pull/1517))
11
+ * Check deprecations in Ruby code ([#1513](https://github.com/soutaro/steep/pull/1513))
12
+ * Support `InvalidTypeApplication` on `#update_env` ([#1507](https://github.com/soutaro/steep/pull/1507))
13
+ * Fix Source.parse crashes with selector-less sendish node ([#1433](https://github.com/soutaro/steep/pull/1433))
14
+ * Fix steep:ignore does not work with CR/LF ([#1406](https://github.com/soutaro/steep/pull/1406))
15
+ * Fix self union type checking ([#1467](https://github.com/soutaro/steep/pull/1467))
16
+ * Type narrowing union types via return type of method call ([#1497](https://github.com/soutaro/steep/pull/1497))
17
+ * Fix `else` clause of `case-when` syntax typing ([#1475](https://github.com/soutaro/steep/pull/1475))
18
+ * Strict record and tuple subtyping ([#1460](https://github.com/soutaro/steep/pull/1460))
19
+ * Allow to annotate "self" on toplevel ([#1455](https://github.com/soutaro/steep/pull/1455))
20
+ * Let annotations in `when` clause without `cond` expression work ([#1459](https://github.com/soutaro/steep/pull/1459))
21
+ * Fix `RuntimeError` on `when` clause with assertion ([#1458](https://github.com/soutaro/steep/pull/1458))
22
+ * Add diagnostic for method definition without types ([#1457](https://github.com/soutaro/steep/pull/1457))
23
+
24
+ ### Commandline tool
25
+
26
+ * Implement GitHub formatter ([#1516](https://github.com/soutaro/steep/pull/1516))
27
+ * Refine `--help` messages ([#1463](https://github.com/soutaro/steep/pull/1463))
4
28
 
5
29
  ### Language server
6
30
 
7
- * Set up file watcher for groups ([#1485](https://github.com/soutaro/steep/pull/1485), Backported)
31
+ * Reforking steep ([#1492](https://github.com/soutaro/steep/pull/1492))
32
+ * Set up file watcher for groups ([#1485](https://github.com/soutaro/steep/pull/1485))
8
33
 
9
34
  ### Miscellaneous
10
35
 
11
- * Fix CI ([#1486](https://github.com/soutaro/steep/pull/1486), Backported)
36
+ * Fix a runtime warning for ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator ([#1438](https://github.com/soutaro/steep/pull/1438))
37
+ * Fix a runtime warning for ambiguous `*` has been interpreted as an argument prefix ([#1439](https://github.com/soutaro/steep/pull/1439))
38
+ * Fix a runtime warning for key :cursor is duplicated and overwritten on line 99 ([#1440](https://github.com/soutaro/steep/pull/1440))
39
+ * Use release version of RBS ([#1511](https://github.com/soutaro/steep/pull/1511))
40
+ * Prepare for rbs-3.9 ([#1510](https://github.com/soutaro/steep/pull/1510))
41
+ * Fix typos ([#1506](https://github.com/soutaro/steep/pull/1506))
42
+ * Fix CI ([#1486](https://github.com/soutaro/steep/pull/1486))
12
43
 
13
44
  ## 1.9.3 (2024-12-26)
14
45
 
data/Steepfile CHANGED
@@ -13,7 +13,6 @@ if (source = rbs_dep&.source).is_a?(Bundler::Source::Path)
13
13
  end
14
14
  else
15
15
  FileUtils.rm_f(tmp_rbs_dir)
16
- library "rbs"
17
16
  end
18
17
 
19
18
  target :app do
@@ -64,5 +63,9 @@ target :bin do
64
63
  check "bin/generate-diagnostics-docs.rb"
65
64
  signature "tmp/rbs-inline/bin"
66
65
 
67
- library "rbs"
66
+ if tmp_rbs_dir.directory?
67
+ signature tmp_rbs_dir.to_s
68
+ else
69
+ library "rbs"
70
+ end
68
71
  end
@@ -0,0 +1,43 @@
1
+ module Steep
2
+ module AnnotationsHelper
3
+ module_function
4
+
5
+ def deprecated_annotation?(annotations)
6
+ annotations.reverse_each do |annotation|
7
+ if match = annotation.string.match(/deprecated(:\s*(?<message>.+))?/)
8
+ return [annotation, match[:message]]
9
+ end
10
+ if match = annotation.string.match(/steep:deprecated(:\s*(?<message>.+))?/)
11
+ return [annotation, match[:message]]
12
+ end
13
+ end
14
+
15
+ nil
16
+ end
17
+
18
+ def deprecated_type_name?(type_name, env)
19
+ annotations =
20
+ case
21
+ when type_name.class?
22
+ case
23
+ when decl = env.class_decls.fetch(type_name, nil)
24
+ decl.decls.flat_map { _1.decl.annotations }
25
+ when decl = env.class_alias_decls.fetch(type_name, nil)
26
+ decl.decl.annotations
27
+ end
28
+ when type_name.interface?
29
+ if decl = env.interface_decls.fetch(type_name, nil)
30
+ decl.decl.annotations
31
+ end
32
+ when type_name.alias?
33
+ if decl = env.type_alias_decls.fetch(type_name, nil)
34
+ decl.decl.annotations
35
+ end
36
+ end
37
+
38
+ if annotations
39
+ deprecated_annotation?(annotations)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -93,15 +93,14 @@ module Steep
93
93
  def self.parse(comment, buffer)
94
94
  return unless comment.inline?
95
95
 
96
- comment_location = RBS::Location.new(buffer, comment.loc.expression.begin_pos, comment.loc.expression.end_pos)
96
+ begin_pos = buffer.loc_to_pos([comment.loc.line, comment.loc.column])
97
+ end_pos = buffer.loc_to_pos([comment.loc.last_line, comment.loc.last_column])
98
+ comment_location = RBS::Location.new(buffer, begin_pos, end_pos)
97
99
  scanner = BufferScanner.new(comment_location)
98
100
 
99
101
  scanner.scan(/#/)
100
102
  scanner.skip(/\s*/)
101
103
 
102
- begin_pos = comment.location.expression.begin_pos
103
- end_pos = comment.location.expression.end_pos
104
-
105
104
  case
106
105
  when loc = scanner.scan(/steep:ignore:start\b/)
107
106
  scanner.skip(/\s*/)
data/lib/steep/cli.rb CHANGED
@@ -24,12 +24,13 @@ module Steep
24
24
  opts.banner = <<~USAGE
25
25
  Usage: steep [options]
26
26
 
27
- available commands: #{CLI.available_commands.join(', ')}
27
+ Available commands:
28
+ #{CLI.available_commands.join(', ')}
28
29
 
29
30
  Options:
30
31
  USAGE
31
32
 
32
- opts.on("--version") do
33
+ opts.on("--version", "Print Steep version") do
33
34
  process_version
34
35
  exit 0
35
36
  end
@@ -60,6 +61,10 @@ module Steep
60
61
  __send__(:"process_#{command}")
61
62
  end
62
63
 
64
+ def handle_steepfile_option(opts, command)
65
+ opts.on("--steepfile=PATH", "Specify path to Steepfile") {|path| command.steepfile = Pathname(path) }
66
+ end
67
+
63
68
  def handle_logging_options(opts)
64
69
  opts.on("--log-level=LEVEL", "Specify log level: debug, info, warn, error, fatal") do |level|
65
70
  Steep.logger.level = level
@@ -101,10 +106,16 @@ module Steep
101
106
  def process_init
102
107
  Drivers::Init.new(stdout: stdout, stderr: stderr).tap do |command|
103
108
  OptionParser.new do |opts|
104
- opts.banner = "Usage: steep init [options]"
109
+ opts.banner = <<BANNER
110
+ Usage: steep init [options]
111
+
112
+ Description:
113
+ Generates a Steepfile at specified path.
105
114
 
106
- opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
107
- opts.on("--force") { command.force_write = true }
115
+ Options:
116
+ BANNER
117
+ handle_steepfile_option(opts, command)
118
+ opts.on("--force", "Overwrite the Steepfile if it already exists") { command.force_write = true }
108
119
 
109
120
  handle_logging_options opts
110
121
  end.parse!(argv)
@@ -114,9 +125,19 @@ module Steep
114
125
  def process_check
115
126
  Drivers::Check.new(stdout: stdout, stderr: stderr).tap do |command|
116
127
  OptionParser.new do |opts|
117
- opts.banner = "Usage: steep check [options] [sources]"
128
+ opts.banner = <<BANNER
129
+ Usage: steep check [options] [paths]
130
+
131
+ Description:
132
+ Type check the program.
118
133
 
119
- opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
134
+ If paths are specified, it type checks and validates the files at the given path.
135
+ Otherwise, it type checks and validates all files in the project or the groups if specified.
136
+
137
+ Options:
138
+ BANNER
139
+
140
+ handle_steepfile_option(opts, command)
120
141
  opts.on("--with-expectations[=PATH]", "Type check with expectations saved in PATH (or steep_expectations.yml)") do |path|
121
142
  command.with_expectations_path = Pathname(path || "steep_expectations.yml")
122
143
  end
@@ -166,22 +187,33 @@ module Steep
166
187
  end
167
188
  end
168
189
 
190
+ opts.on("--format=FORMATTER", ["code", "github"], "Output formatters (default: code, options: code,github)") do |formatter|
191
+ command.formatter = formatter
192
+ end
193
+
169
194
  handle_jobs_option command.jobs_option, opts
170
195
  handle_logging_options opts
171
196
  end.parse!(argv)
172
197
 
173
198
  setup_jobs_for_ci(command.jobs_option)
174
199
 
175
- command.command_line_patterns.push *argv
200
+ command.command_line_patterns.push(*argv)
176
201
  end.run
177
202
  end
178
203
 
179
204
  def process_checkfile
180
205
  Drivers::Checkfile.new(stdout: stdout, stderr: stderr).tap do |command|
181
206
  OptionParser.new do |opts|
182
- opts.banner = "Usage: steep checkfile [options] [files]"
207
+ opts.banner = <<BANNER
208
+ Usage: steep checkfile [options] [files]
209
+
210
+ Description:
211
+ Deprecated: Use `steep check` instead.
212
+
213
+ Options:
214
+ BANNER
183
215
 
184
- opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
216
+ handle_steepfile_option(opts, command)
185
217
  opts.on("--all-rbs", "Type check all RBS files") { command.all_rbs = true }
186
218
  opts.on("--all-ruby", "Type check all Ruby files") { command.all_ruby = true }
187
219
  opts.on("--stdin", "Read files to type check from stdin") do
@@ -197,16 +229,23 @@ module Steep
197
229
 
198
230
  setup_jobs_for_ci(command.jobs_option)
199
231
 
200
- command.command_line_args.push *argv
232
+ command.command_line_args.push(*argv)
201
233
  end.run
202
234
  end
203
235
 
204
236
  def process_stats
205
237
  Drivers::Stats.new(stdout: stdout, stderr: stderr).tap do |command|
206
238
  OptionParser.new do |opts|
207
- opts.banner = "Usage: steep stats [options] [sources]"
239
+ opts.banner = <<BANNER
240
+ Usage: steep stats [options] [sources]
208
241
 
209
- opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
242
+ Description:
243
+ Displays statistics about the typing of method calls.
244
+
245
+ Options:
246
+ BANNER
247
+
248
+ handle_steepfile_option(opts, command)
210
249
  opts.on("--format=FORMAT", "Specify output format: csv, table") {|format| command.format = format }
211
250
  handle_jobs_option command.jobs_option, opts
212
251
  handle_logging_options opts
@@ -214,7 +253,7 @@ module Steep
214
253
 
215
254
  setup_jobs_for_ci(command.jobs_option)
216
255
 
217
- command.command_line_patterns.push *argv
256
+ command.command_line_patterns.push(*argv)
218
257
  end.run
219
258
  end
220
259
 
@@ -226,19 +265,33 @@ module Steep
226
265
  def process_annotations
227
266
  Drivers::Annotations.new(stdout: stdout, stderr: stderr).tap do |command|
228
267
  OptionParser.new do |opts|
229
- opts.banner = "Usage: steep annotations [options] [sources]"
268
+ opts.banner = <<BANNER
269
+ Usage: steep annotations [options] [sources]
270
+
271
+ Description:
272
+ Prints the type annotations in the Ruby code.
273
+
274
+ Options:
275
+ BANNER
230
276
  handle_logging_options opts
231
277
  end.parse!(argv)
232
278
 
233
- command.command_line_patterns.push *argv
279
+ command.command_line_patterns.push(*argv)
234
280
  end.run
235
281
  end
236
282
 
237
283
  def process_project
238
284
  Drivers::PrintProject.new(stdout: stdout, stderr: stderr).tap do |command|
239
285
  OptionParser.new do |opts|
240
- opts.banner = "Usage: steep project [options]"
241
- opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
286
+ opts.banner = <<BANNER
287
+ Usage: steep project [options]
288
+
289
+ Description:
290
+ Prints the project configuration.
291
+
292
+ Options:
293
+ BANNER
294
+ handle_steepfile_option(opts, command)
242
295
  opts.on("--[no-]print-files", "Print files") {|v|
243
296
  command.print_files = v ? true : false
244
297
  }
@@ -250,7 +303,15 @@ module Steep
250
303
  def process_watch
251
304
  Drivers::Watch.new(stdout: stdout, stderr: stderr).tap do |command|
252
305
  OptionParser.new do |opts|
253
- opts.banner = "Usage: steep watch [options] [dirs]"
306
+ opts.banner = <<BANNER
307
+ Usage: steep watch [options] [dirs]
308
+
309
+ Description:
310
+ Monitors file changes and automatically type checks updated files.
311
+ Using LSP is recommended for better performance and more features.
312
+
313
+ Options:
314
+ BANNER
254
315
  opts.on("--severity-level=LEVEL", /^error|warning|information|hint$/, "Specify the minimum diagnostic severity to be recognized as an error (defaults: warning): error, warning, information, or hint") do |level|
255
316
  # @type var level: String
256
317
  command.severity_level = _ = level.to_sym
@@ -269,7 +330,16 @@ module Steep
269
330
  def process_langserver
270
331
  Drivers::Langserver.new(stdout: stdout, stderr: stderr, stdin: stdin).tap do |command|
271
332
  OptionParser.new do |opts|
272
- opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
333
+ opts.banner = <<BANNER
334
+ Usage: steep langserver [options]
335
+
336
+ Description:
337
+ Starts language server, which is assumed to be invoked from language client.
338
+
339
+ Options:
340
+ BANNER
341
+ handle_steepfile_option(opts, command)
342
+ opts.on("--refork") { command.refork = true }
273
343
  handle_jobs_option command.jobs_option, opts
274
344
  handle_logging_options opts
275
345
  end.parse!(argv)
@@ -300,8 +370,8 @@ module Steep
300
370
  opts.banner = <<BANNER
301
371
  Usage: steep binstub [options]
302
372
 
303
- Generate a binstub to execute Steep with setting up Bundler and rbenv/rvm.
304
- Use the executable for LSP integration setup.
373
+ Description:
374
+ Generate a binstub which set up ruby executables and bundlers.
305
375
 
306
376
  Options:
307
377
  BANNER
@@ -372,6 +442,15 @@ TEMPLATE
372
442
  end
373
443
 
374
444
  def process_version
445
+ OptionParser.new do |opts|
446
+ opts.banner = <<BANNER
447
+ Usage: steep version [options]
448
+
449
+ Description:
450
+ Prints Steep version.
451
+ BANNER
452
+ end.parse!(argv)
453
+
375
454
  stdout.puts Steep::VERSION
376
455
  0
377
456
  end
@@ -384,7 +463,7 @@ TEMPLATE
384
463
 
385
464
  opts.on("--interaction") { command.worker_type = :interaction }
386
465
  opts.on("--typecheck") { command.worker_type = :typecheck }
387
- opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
466
+ handle_steepfile_option(opts, command)
388
467
  opts.on("--name=NAME") {|name| command.worker_name = name }
389
468
  opts.on("--delay-shutdown") { command.delay_shutdown = true }
390
469
  opts.on("--max-index=COUNT") {|count| command.max_index = Integer(count) }
@@ -49,13 +49,27 @@ module Steep
49
49
  } #: LSP::Interface::CodeDescription::json
50
50
  end
51
51
 
52
- {
52
+ tags = [] #: Array[LSP::Constant::DiagnosticTag::t]
53
+
54
+ case diagnostic
55
+ when Ruby::DeprecatedReference
56
+ tags << LSP::Constant::DiagnosticTag::DEPRECATED
57
+ when Signature::DeprecatedTypeName
58
+ tags << LSP::Constant::DiagnosticTag::DEPRECATED
59
+ severity = LSP::Constant::DiagnosticSeverity::WARNING
60
+ end
61
+
62
+ json = {
53
63
  message: diagnostic.full_message,
54
64
  code: diagnostic.diagnostic_code,
55
65
  severity: severity,
56
66
  range: range,
57
- codeDescription: description
58
- }
67
+ codeDescription: description,
68
+ } #: LSP::Interface::Diagnostic::json
69
+
70
+ json[:tags] = tags unless tags.empty?
71
+
72
+ json
59
73
  end
60
74
  end
61
75
 
@@ -977,6 +977,72 @@ module Steep
977
977
  end
978
978
  end
979
979
 
980
+ class UndeclaredMethodDefinition < Base
981
+ attr_reader :method_name, :type_name
982
+
983
+ def initialize(method_name:, type_name:, node:)
984
+ @method_name = method_name
985
+ @type_name = type_name
986
+ super(node: node, location: (_ = node.loc).name)
987
+ end
988
+
989
+ def header_line
990
+ name =
991
+ case node.type
992
+ when :def
993
+ "#{type_name}##{method_name}"
994
+ when :defs
995
+ "#{type_name}.#{method_name}"
996
+ else
997
+ raise
998
+ end
999
+ "Method `#{name}` is not declared in RBS"
1000
+ end
1001
+ end
1002
+
1003
+ class MethodDefinitionInUndeclaredModule < Base
1004
+ attr_reader :method_name
1005
+
1006
+ def initialize(method_name:, node:)
1007
+ @method_name = method_name
1008
+ super(node: node, location: (_ = node.loc).name)
1009
+ end
1010
+
1011
+ def header_line
1012
+ "Method `#{method_name}` is defined in undeclared module"
1013
+ end
1014
+ end
1015
+
1016
+ class DeprecatedReference < Base
1017
+ attr_reader :message
1018
+
1019
+ def initialize(node:, location:, message:)
1020
+ super(node: node, location: location)
1021
+ @message = message
1022
+ end
1023
+
1024
+ def header_line
1025
+ header =
1026
+ case node&.type
1027
+ when :send, :csend, :block, :numblock
1028
+ "The method is deprecated"
1029
+ when :const, :casgn
1030
+ "The constant is deprecated"
1031
+ when :gvar, :gvasgn
1032
+ "The global variable is deprecated"
1033
+ else
1034
+ raise "Unexpected node: #{node}"
1035
+ end
1036
+
1037
+ if message
1038
+ header = +header
1039
+ header.concat(": ", message)
1040
+ end
1041
+
1042
+ header
1043
+ end
1044
+ end
1045
+
980
1046
  ALL = ObjectSpace.each_object(Class).with_object([]) do |klass, array|
981
1047
  if klass < Base
982
1048
  array << klass
@@ -997,6 +1063,7 @@ module Steep
997
1063
  BlockBodyTypeMismatch => :warning,
998
1064
  BlockTypeMismatch => :warning,
999
1065
  BreakTypeMismatch => :hint,
1066
+ DeprecatedReference => :warning,
1000
1067
  DifferentMethodParameterKind => :hint,
1001
1068
  FallbackAny => :hint,
1002
1069
  FalseAssertion => :hint,
@@ -1010,6 +1077,7 @@ module Steep
1010
1077
  InvalidIgnoreComment => :warning,
1011
1078
  MethodArityMismatch => :error,
1012
1079
  MethodBodyTypeMismatch => :error,
1080
+ MethodDefinitionInUndeclaredModule => :information,
1013
1081
  MethodDefinitionMissing => nil,
1014
1082
  MethodParameterMismatch => :error,
1015
1083
  MethodReturnTypeAnnotationMismatch => :hint,
@@ -1026,6 +1094,7 @@ module Steep
1026
1094
  SyntaxError => :information,
1027
1095
  TypeArgumentMismatchError => :hint,
1028
1096
  UnannotatedEmptyCollection => :warning,
1097
+ UndeclaredMethodDefinition => :warning,
1029
1098
  UnexpectedBlockGiven => :warning,
1030
1099
  UnexpectedDynamicMethod => :hint,
1031
1100
  UnexpectedError => :hint,
@@ -1057,6 +1126,7 @@ module Steep
1057
1126
  BlockBodyTypeMismatch => :error,
1058
1127
  BlockTypeMismatch => :error,
1059
1128
  BreakTypeMismatch => :error,
1129
+ DeprecatedReference => :warning,
1060
1130
  DifferentMethodParameterKind => :error,
1061
1131
  FallbackAny => :warning,
1062
1132
  FalseAssertion => :error,
@@ -1070,6 +1140,7 @@ module Steep
1070
1140
  InvalidIgnoreComment => :warning,
1071
1141
  MethodArityMismatch => :error,
1072
1142
  MethodBodyTypeMismatch => :error,
1143
+ MethodDefinitionInUndeclaredModule => :warning,
1073
1144
  MethodDefinitionMissing => :hint,
1074
1145
  MethodParameterMismatch => :error,
1075
1146
  MethodReturnTypeAnnotationMismatch => :error,
@@ -1086,6 +1157,7 @@ module Steep
1086
1157
  SyntaxError => :information,
1087
1158
  TypeArgumentMismatchError => :error,
1088
1159
  UnannotatedEmptyCollection => :error,
1160
+ UndeclaredMethodDefinition => :warning,
1089
1161
  UnexpectedBlockGiven => :error,
1090
1162
  UnexpectedDynamicMethod => :information,
1091
1163
  UnexpectedError => :information,
@@ -1117,6 +1189,7 @@ module Steep
1117
1189
  BlockBodyTypeMismatch => :information,
1118
1190
  BlockTypeMismatch => :information,
1119
1191
  BreakTypeMismatch => :hint,
1192
+ DeprecatedReference => :warning,
1120
1193
  DifferentMethodParameterKind => nil,
1121
1194
  FallbackAny => nil,
1122
1195
  FalseAssertion => nil,
@@ -1130,6 +1203,7 @@ module Steep
1130
1203
  InvalidIgnoreComment => :warning,
1131
1204
  MethodArityMismatch => :information,
1132
1205
  MethodBodyTypeMismatch => :warning,
1206
+ MethodDefinitionInUndeclaredModule => :hint,
1133
1207
  MethodDefinitionMissing => nil,
1134
1208
  MethodParameterMismatch => :warning,
1135
1209
  MethodReturnTypeAnnotationMismatch => nil,
@@ -1146,6 +1220,7 @@ module Steep
1146
1220
  SyntaxError => :information,
1147
1221
  TypeArgumentMismatchError => nil,
1148
1222
  UnannotatedEmptyCollection => :hint,
1223
+ UndeclaredMethodDefinition => :information,
1149
1224
  UnexpectedBlockGiven => :hint,
1150
1225
  UnexpectedDynamicMethod => nil,
1151
1226
  UnexpectedError => :hint,
@@ -460,6 +460,26 @@ module Steep
460
460
  end
461
461
  end
462
462
 
463
+ class DeprecatedTypeName < Base
464
+ attr_reader :type_name
465
+ attr_reader :message
466
+
467
+ def initialize(type_name, message, location:)
468
+ super(location: location)
469
+ @type_name = type_name
470
+ @message = message
471
+ end
472
+
473
+ def header_line
474
+ buffer = "Type `#{type_name}` is deprecated"
475
+ if message
476
+ buffer = +buffer
477
+ buffer << ": " << message
478
+ end
479
+ buffer
480
+ end
481
+ end
482
+
463
483
 
464
484
  def self.from_rbs_error(error, factory:)
465
485
  case error
@@ -16,6 +16,7 @@ module Steep
16
16
  attr_accessor :validate_group_signatures
17
17
  attr_accessor :validate_project_signatures
18
18
  attr_accessor :validate_library_signatures
19
+ attr_accessor :formatter
19
20
 
20
21
  include Utils::DriverHelper
21
22
 
@@ -30,6 +31,7 @@ module Steep
30
31
  @validate_group_signatures = true
31
32
  @validate_project_signatures = false
32
33
  @validate_library_signatures = false
34
+ @formatter = 'code'
33
35
  end
34
36
 
35
37
  def active_group?(group)
@@ -322,7 +324,7 @@ module Steep
322
324
  errors.each do |notification|
323
325
  path = Steep::PathHelper.to_pathname(notification[:uri]) or raise
324
326
  buffer = RBS::Buffer.new(name: project.relative_path(path), content: path.read)
325
- printer = DiagnosticPrinter.new(buffer: buffer, stdout: stdout)
327
+ printer = DiagnosticPrinter.new(buffer: buffer, stdout: stdout, formatter: formatter)
326
328
 
327
329
  notification[:diagnostics].each do |diag|
328
330
  printer.print(diag)
@@ -0,0 +1,19 @@
1
+ module Steep
2
+ module Drivers
3
+ class DiagnosticPrinter
4
+ class BaseFormatter
5
+ attr_reader :stdout
6
+ attr_reader :buffer
7
+
8
+ def initialize(stdout:, buffer:)
9
+ @stdout = stdout
10
+ @buffer = buffer
11
+ end
12
+
13
+ def path
14
+ Pathname(buffer.name)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end