steep 1.9.0.dev.2 → 1.9.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -0
  3. data/README.md +9 -4
  4. data/Rakefile +1 -0
  5. data/Steepfile +11 -0
  6. data/bin/generate-diagnostics-docs.rb +112 -0
  7. data/lib/steep/ast/builtin.rb +1 -0
  8. data/lib/steep/ast/ignore.rb +1 -1
  9. data/lib/steep/ast/types/factory.rb +2 -0
  10. data/lib/steep/cli.rb +9 -2
  11. data/lib/steep/diagnostic/lsp_formatter.rb +8 -1
  12. data/lib/steep/diagnostic/ruby.rb +65 -3
  13. data/lib/steep/diagnostic/signature.rb +4 -4
  14. data/lib/steep/drivers/check.rb +3 -3
  15. data/lib/steep/drivers/diagnostic_printer.rb +1 -1
  16. data/lib/steep/drivers/init.rb +6 -3
  17. data/lib/steep/expectations.rb +1 -1
  18. data/lib/steep/interface/builder.rb +2 -3
  19. data/lib/steep/interface/function.rb +13 -0
  20. data/lib/steep/interface/method_type.rb +5 -0
  21. data/lib/steep/interface/shape.rb +1 -1
  22. data/lib/steep/project/dsl.rb +2 -0
  23. data/lib/steep/server/change_buffer.rb +1 -1
  24. data/lib/steep/server/interaction_worker.rb +5 -5
  25. data/lib/steep/server/master.rb +2 -17
  26. data/lib/steep/server/type_check_controller.rb +2 -2
  27. data/lib/steep/server/type_check_worker.rb +1 -1
  28. data/lib/steep/services/completion_provider.rb +4 -4
  29. data/lib/steep/services/goto_service.rb +3 -3
  30. data/lib/steep/services/hover_provider/rbs.rb +1 -1
  31. data/lib/steep/services/hover_provider/ruby.rb +6 -6
  32. data/lib/steep/services/signature_help_provider.rb +8 -8
  33. data/lib/steep/services/type_check_service.rb +8 -8
  34. data/lib/steep/signature/validator.rb +3 -3
  35. data/lib/steep/source.rb +4 -4
  36. data/lib/steep/subtyping/check.rb +3 -3
  37. data/lib/steep/subtyping/constraints.rb +4 -4
  38. data/lib/steep/type_construction.rb +84 -45
  39. data/lib/steep/type_inference/block_params.rb +3 -3
  40. data/lib/steep/type_inference/context.rb +1 -1
  41. data/lib/steep/type_inference/method_params.rb +1 -1
  42. data/lib/steep/type_inference/type_env.rb +3 -3
  43. data/lib/steep/version.rb +1 -1
  44. data/manual/annotations.md +37 -0
  45. data/manual/ignore.md +20 -0
  46. data/manual/ruby-diagnostics.md +1812 -0
  47. data/steep.gemspec +1 -1
  48. metadata +8 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89c207623c288c2142cdcf7d7de7f404da4d160b5bc40c84210116a721ec4029
4
- data.tar.gz: dfd95e726115676f4d293d312bd1f06afa6ea89336911e9887c8e4b5ee1167ff
3
+ metadata.gz: 7f7a4597973dff6192b6977a32875ed18b7da16a70d34bf5e811cb8a719b18d5
4
+ data.tar.gz: 8b9ec7e28728c0f6e35e962fed6dd8a43828d41763ae2ffce831b787a501b200
5
5
  SHA512:
6
- metadata.gz: c9800ef17d4108ff391642510701e12a0ec4e63035c74765ed1203fa9b62d964be10441d60890ab3c643dc8d0295dd2a68be5285126307f3cb401f517eaa799f
7
- data.tar.gz: 3ef2c5d7bac4dd2d492df8e5c60322de6c06d9c33cec21e2a97e4608f235e41729f0383e0817cfd324213853cad4c34308b14f5a582eedda71d36828545d6840
6
+ metadata.gz: f11cb6ec05bc38e2e8130b7e6860409c63a9d1ba3ef93ca14dcc3781800c00d97e59506343e8191c97741865a1fa1895dfd9ff69928b574df423e32983a315b5
7
+ data.tar.gz: d6b544a988c8f0adae6705a5b7085907bb7148dde0eeb857a3aae7b9c44b2787f47ea40aa1c0b54b5d5da650f07e4f94e0a754ead23baca844cb2f21ae6c7eaa
data/CHANGELOG.md CHANGED
@@ -1,5 +1,81 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.9.0 (2024-12-06)
4
+
5
+ ### Type checker core
6
+
7
+ * Report diagnostic on unknown record key ([#1385](https://github.com/soutaro/steep/pull/1385))
8
+ * Report annotation syntax error ([#1384](https://github.com/soutaro/steep/pull/1384))
9
+ * emit UnreachableBranch to the "void" condition ([#1356](https://github.com/soutaro/steep/pull/1356))
10
+ * Support &method(:name) call for block_pass ([#1276](https://github.com/soutaro/steep/pull/1276))
11
+ * Emit SingletonTypeMismatch when class/module mismatch ([#1274](https://github.com/soutaro/steep/pull/1274))
12
+ * refactor: Use Array#fetch instead of Array#[] to resolve type errors ([#1287](https://github.com/soutaro/steep/pull/1287))
13
+ * refactor: Use Hash#fetch instead of Hash#[] to resolve type errors ([#1286](https://github.com/soutaro/steep/pull/1286))
14
+ * Expand `array(splat(expr` node ([#1347](https://github.com/soutaro/steep/pull/1347))
15
+ * Add `UnannotatedEmptyCollection` diagnostic ([#1338](https://github.com/soutaro/steep/pull/1338))
16
+ * Update type checking strategy ([#1308](https://github.com/soutaro/steep/pull/1308))
17
+ * Fix untyped hash typing ([#1299](https://github.com/soutaro/steep/pull/1299))
18
+ * Support `implicitly-returns-nil` ([#1258](https://github.com/soutaro/steep/pull/1258))
19
+ * Fix record shape ([#1265](https://github.com/soutaro/steep/pull/1265))
20
+ * Remove unused rules ([#1238](https://github.com/soutaro/steep/pull/1238))
21
+
22
+ ### Commandline tool
23
+
24
+ * Introduces a new `target.*` syntax for everything in the target ([#1387](https://github.com/soutaro/steep/pull/1387))
25
+ * Symbolize target/group names ([#1364](https://github.com/soutaro/steep/pull/1364))
26
+ * Update Steepfile template ([#1355](https://github.com/soutaro/steep/pull/1355))
27
+ * Delete `target` from `--validate` option ([#1346](https://github.com/soutaro/steep/pull/1346))
28
+ * Install rbs collection automatically ([#1345](https://github.com/soutaro/steep/pull/1345))
29
+
30
+ ### Language server
31
+
32
+ * Add link to diagnostic manual ([#1388](https://github.com/soutaro/steep/pull/1388))
33
+ * Stop accumulating diagnostics ([#1367](https://github.com/soutaro/steep/pull/1367))
34
+ * Send server version to client ([#1341](https://github.com/soutaro/steep/pull/1341))
35
+ * Add custom methods to trigger type check manually ([#1340](https://github.com/soutaro/steep/pull/1340))
36
+ * Type check thread helpers ([#1335](https://github.com/soutaro/steep/pull/1335))
37
+ * Use `URI::RFC2396_Parser` ([#1329](https://github.com/soutaro/steep/pull/1329))
38
+ * Handle file deletion notification ([#1300](https://github.com/soutaro/steep/pull/1300))
39
+ * Refactor communication between master and type check worker ([#1285](https://github.com/soutaro/steep/pull/1285))
40
+ * Skip sending response to `$/steep/typecheck` request from `steep langserver` ([#1267](https://github.com/soutaro/steep/pull/1267))
41
+
42
+ ### Miscellaneous
43
+
44
+ * Use rbs-3.7 ([#1383](https://github.com/soutaro/steep/pull/1383))
45
+ * Move diagnostic docs ([#1370](https://github.com/soutaro/steep/pull/1370))
46
+ * Add anchor ([#1359](https://github.com/soutaro/steep/pull/1359))
47
+ * Update example to not use `^` as a hash function ([#1360](https://github.com/soutaro/steep/pull/1360))
48
+ * doc: Add diagnostics for Ruby page ([#1249](https://github.com/soutaro/steep/pull/1249))
49
+ * Update filename example in initial Steepfile ([#1230](https://github.com/soutaro/steep/pull/1230))
50
+ * docs: Add document for steep:ignore comment ([#1353](https://github.com/soutaro/steep/pull/1353))
51
+ * docs: Add document for type assertion and type application ([#1235](https://github.com/soutaro/steep/pull/1235))
52
+ * Print test names in CI for investigation ([#1354](https://github.com/soutaro/steep/pull/1354))
53
+ * Fix typo ([#1352](https://github.com/soutaro/steep/pull/1352))
54
+ * Set up type checking tests ([#1339](https://github.com/soutaro/steep/pull/1339))
55
+ * Fix typo ([#1248](https://github.com/soutaro/steep/pull/1248))
56
+
57
+ ## 1.8.3 (2024-10-29)
58
+
59
+ ### Type checker core
60
+
61
+ * Fix untyped hash typing ([#1299](https://github.com/soutaro/steep/pull/1299), Backport in [#1301](https://github.com/soutaro/steep/pull/1301))
62
+
63
+ ### Language server
64
+
65
+ * Handle file deletion notification ([#1300](https://github.com/soutaro/steep/pull/1300), Backport in [#1301](https://github.com/soutaro/steep/pull/1301))
66
+
67
+ ## 1.8.2 (2024-10-24)
68
+
69
+ ### Language server
70
+
71
+ * Ignore `didChangeWatchedFiles notification` for open files ([#1290](https://github.com/soutaro/steep/pull/1290))
72
+
73
+ ## 1.8.1 (2024-10-08)
74
+
75
+ ### Language server
76
+
77
+ * Skip sending response to `$/steep/typecheck` request from `steep langserver` ([#1268](https://github.com/soutaro/steep/pull/1268), backport [#1267](https://github.com/soutaro/steep/pull/1267))
78
+
3
79
  ## 1.8.0 (2024-09-30)
4
80
 
5
81
  ### Type checker core
data/README.md CHANGED
@@ -120,7 +120,7 @@ class Email
120
120
  end
121
121
 
122
122
  def hash
123
- self.class.hash ^ address.hash
123
+ [self.class, address].hash
124
124
  end
125
125
  end
126
126
 
@@ -144,7 +144,7 @@ class Phone
144
144
  end
145
145
 
146
146
  def hash
147
- self.class.hash ^ country.hash ^ number.hash
147
+ [self.class, country, number].hash
148
148
  end
149
149
  end
150
150
  ```
@@ -201,11 +201,16 @@ Generally, these are by our design.
201
201
 
202
202
  `rbs prototype` offers options: `rbi` to generate prototype from Sorbet RBI and `runtime` to generate from runtime API.
203
203
 
204
- ## Guides
204
+ ## Docs
205
205
 
206
- There are some guides in the `guide` directory. I know we need more comprehensive set of documentations. Just started writing docs.
206
+ There are some documents in the `manul` and `guide` directories.
207
207
 
208
208
  * [Guides](guides)
209
+ * [Manual](manual)
210
+
211
+ The `doc` directory contains a few internal design docs.
212
+
213
+ * [Internal docs](doc)
209
214
 
210
215
  ## Examples
211
216
 
data/Rakefile CHANGED
@@ -48,6 +48,7 @@ task :changelog do
48
48
  "list",
49
49
  "--json",
50
50
  "url,title,number",
51
+ "--limit=100",
51
52
  "--search" ,
52
53
  "milestone:\"#{milestone}\" is:merged sort:updated-desc -label:Released"
53
54
  ]
data/Steepfile CHANGED
@@ -49,3 +49,14 @@ target :test do
49
49
  library "rbs"
50
50
  end
51
51
  end
52
+
53
+ target :bin do
54
+ unreferenced!
55
+
56
+ collection_config "rbs_collection.steep.yaml"
57
+
58
+ check "bin/generate-diagnostics-docs.rb"
59
+ signature "tmp/rbs-inline/bin"
60
+
61
+ library "rbs"
62
+ end
@@ -0,0 +1,112 @@
1
+ # rbs_inline: enabled
2
+
3
+ require "rbs"
4
+ require "steep"
5
+
6
+ class RubyDiagnosticsVisitor < RBS::AST::Visitor
7
+ attr_reader :classes #: Hash[String, String]
8
+ attr_reader :templates #: Hash[Symbol, String]
9
+
10
+ def initialize #: void
11
+ @classes = {}
12
+ @templates = {}
13
+ end
14
+
15
+ # @rbs ...
16
+ def visit_declaration_class(node)
17
+ unless node.annotations.find { _1.string == "diagnostics--skip" }
18
+ if node.comment
19
+ name = node.name.to_s
20
+ classes[name] = node.comment.string
21
+ end
22
+ end
23
+
24
+ super
25
+ end
26
+
27
+ # @rbs ...
28
+ def visit_member_method_definition(node)
29
+ if node.annotations.find { _1.string == "diagnostics--template" }
30
+ if node.comment
31
+ templates[node.name] = node.comment.string
32
+ end
33
+ end
34
+ end
35
+
36
+ # @rbs (IO) -> void
37
+ def format_templates(io)
38
+ io.puts "## Configuration Templates"
39
+
40
+ io.puts <<~MD
41
+ Steep provides several templates to configure diagnostics for Ruby code.
42
+ You can use these templates or customize them to suit your needs via `#configure_code_diagnostics` method in `Steepfile`.
43
+
44
+ The following templates are available:
45
+
46
+ MD
47
+
48
+ io.puts "<dl>"
49
+ templates.keys.sort.each do |key|
50
+ body = templates.fetch(key)
51
+
52
+ io.puts "<dt><code>Ruby.#{key}</code></dt>"
53
+ io.puts "<dd>#{body}</dd>"
54
+ end
55
+ io.puts "</dl>"
56
+ io.puts
57
+ end
58
+
59
+ # @rbs (IO) -> void
60
+ def format_class(io)
61
+ classes.keys.sort.each do |key|
62
+ content = classes[key]
63
+
64
+ # io.puts "<h2 id='Ruby::#{key}'>Ruby::#{key}</h2>"
65
+ io.puts "<a name='Ruby::#{key}'></a>"
66
+ io.puts "## Ruby::#{key}"
67
+ io.puts
68
+ io.puts content
69
+ io.puts
70
+
71
+ configs = templates.keys
72
+
73
+ io.puts "### Severity"
74
+ io.puts
75
+ io.puts "| #{configs.map { "#{_1}" }.join(" | ")} |"
76
+ io.puts "| #{configs.map{"-"}.join(" | ")} |"
77
+
78
+ line = configs.map {|config|
79
+ hash = Steep::Diagnostic::Ruby.__send__(config) #: Hash[Class, untyped]
80
+ const =Steep::Diagnostic::Ruby.const_get(key.to_sym)
81
+ "#{hash[const] || "-"}"
82
+ }
83
+ io.puts "| #{line.join(" | ")} |"
84
+ io.puts
85
+ end
86
+ end
87
+
88
+ # @rbs (Pathname) { (instance) -> void } -> void
89
+ def self.visit_file(path, &block)
90
+ STDERR.puts "Reading #{path}..."
91
+ buffer = RBS::Buffer.new(name: path, content: path.read)
92
+ _, _dirs, decls = RBS::Parser.parse_signature(buffer)
93
+
94
+ visitor = new()
95
+ visitor.visit_all(decls)
96
+
97
+ yield visitor
98
+ end
99
+ end
100
+
101
+ diagnostic_dir = Pathname(__dir__ || raise) + "../sig/steep/diagnostic"
102
+ output_dir = Pathname(__dir__ || raise) + "../manual"
103
+
104
+ RubyDiagnosticsVisitor.visit_file(diagnostic_dir + "ruby.rbs") do |visitor|
105
+ STDERR.puts ">> Writing #{output_dir + "ruby-diagnostics.md"}..."
106
+ (output_dir + "ruby-diagnostics.md").open("w") do |io|
107
+ io.puts "# Ruby Code Diagnostics"
108
+ io.puts
109
+ visitor.format_templates(io)
110
+ visitor.format_class(io)
111
+ end
112
+ end
@@ -66,6 +66,7 @@ module Steep
66
66
  NilClass = Type.new("::NilClass")
67
67
  Proc = Type.new("::Proc")
68
68
  Kernel = Type.new("::Kernel")
69
+ Method = Type.new("::Method")
69
70
 
70
71
  def self.nil_type
71
72
  AST::Types::Nil.instance
@@ -79,7 +79,7 @@ module Steep
79
79
  return :all
80
80
  end
81
81
 
82
- if raw_diagnostics.size == 1 && raw_diagnostics[0].source == "all"
82
+ if raw_diagnostics.size == 1 && raw_diagnostics.fetch(0).source == "all"
83
83
  return :all
84
84
  end
85
85
 
@@ -409,6 +409,8 @@ module Steep
409
409
  ]
410
410
  when AST::Types::Any, AST::Types::Boolean, AST::Types::Top, AST::Types::Logic::Base
411
411
  [type, type]
412
+ when AST::Types::Bot, AST::Types::Void
413
+ [nil, nil]
412
414
  when AST::Types::Nil
413
415
  [nil, type]
414
416
  when AST::Types::Literal
data/lib/steep/cli.rb CHANGED
@@ -128,10 +128,17 @@ module Steep
128
128
  end
129
129
 
130
130
  opts.on("--group=GROUP", "Specify target/group name to type check") do |arg|
131
- # @type var group: String
131
+ # @type var arg: String
132
132
  target, group = arg.split(".")
133
133
  target or raise
134
- command.active_group_names << [target.to_sym, group&.to_sym]
134
+ case group
135
+ when "*"
136
+ command.active_group_names << [target.to_sym, true]
137
+ when nil
138
+ command.active_group_names << [target.to_sym, nil]
139
+ else
140
+ command.active_group_names << [target.to_sym, group.to_sym]
141
+ end
135
142
  end
136
143
 
137
144
  opts.on("--[no-]type-check", "Type check Ruby code") do |v|
@@ -43,11 +43,18 @@ module Steep
43
43
  if severity
44
44
  range = diagnostic.location&.as_lsp_range || raise("#{diagnostic.class} object (#{diagnostic.full_message}) instance must have `#location`")
45
45
 
46
+ if diagnostic.is_a?(Ruby::Base)
47
+ description = {
48
+ href: "https://github.com/soutaro/steep/tree/v#{VERSION}/manual/ruby-diagnostics.md##{URI.encode_uri_component(diagnostic.diagnostic_code)}"
49
+ } #: LSP::Interface::CodeDescription::json
50
+ end
51
+
46
52
  {
47
53
  message: diagnostic.full_message,
48
54
  code: diagnostic.diagnostic_code,
49
55
  severity: severity,
50
- range: range
56
+ range: range,
57
+ codeDescription: description
51
58
  }
52
59
  end
53
60
  end
@@ -409,6 +409,33 @@ module Steep
409
409
  end
410
410
  end
411
411
 
412
+ class ClassModuleMismatch < Base
413
+ attr_reader :name
414
+
415
+ def initialize(node:, name:)
416
+ case node.type
417
+ when :module, :class
418
+ location = node.loc.name # steep:ignore NoMethod
419
+ else
420
+ raise "Unexpected node: #{node.type}"
421
+ end
422
+ super(node: node, location: location) # steep:ignore NoMethod
423
+
424
+ @name = name
425
+ end
426
+
427
+ def header_line
428
+ case node&.type
429
+ when :module
430
+ "#{name} is declared as a class in RBS"
431
+ when :class
432
+ "#{name} is declared as a module in RBS"
433
+ else
434
+ raise
435
+ end
436
+ end
437
+ end
438
+
412
439
  class MethodArityMismatch < Base
413
440
  attr_reader :method_type
414
441
 
@@ -794,6 +821,19 @@ module Steep
794
821
  end
795
822
  end
796
823
 
824
+ class AnnotationSyntaxError < Base
825
+ attr_reader :message
826
+
827
+ def initialize(message: ,location:)
828
+ super(node: nil, location: location)
829
+ @message = message
830
+ end
831
+
832
+ def header_line
833
+ "Type annotation has a syntax error: #{message}"
834
+ end
835
+ end
836
+
797
837
  class FalseAssertion < Base
798
838
  attr_reader :node, :assertion_type, :node_type
799
839
 
@@ -924,6 +964,19 @@ module Steep
924
964
  end
925
965
  end
926
966
 
967
+ class UnknownRecordKey < Base
968
+ attr_reader :key
969
+
970
+ def initialize(key:, node:)
971
+ super(node: node)
972
+ @key = key
973
+ end
974
+
975
+ def header_line
976
+ "Unknown key `#{key.inspect}` is given to a record type"
977
+ end
978
+ end
979
+
927
980
  ALL = ObjectSpace.each_object(Class).with_object([]) do |klass, array|
928
981
  if klass < Base
929
982
  array << klass
@@ -939,6 +992,7 @@ module Steep
939
992
  def self.default
940
993
  @default ||= _ = all_error.merge(
941
994
  {
995
+ AnnotationSyntaxError => :error,
942
996
  ArgumentTypeMismatch => :error,
943
997
  BlockBodyTypeMismatch => :warning,
944
998
  BlockTypeMismatch => :warning,
@@ -968,7 +1022,8 @@ module Steep
968
1022
  ReturnTypeMismatch => :error,
969
1023
  SetterBodyTypeMismatch => :information,
970
1024
  SetterReturnTypeMismatch => :information,
971
- SyntaxError => :hint,
1025
+ ClassModuleMismatch => :error,
1026
+ SyntaxError => :information,
972
1027
  TypeArgumentMismatchError => :hint,
973
1028
  UnannotatedEmptyCollection => :warning,
974
1029
  UnexpectedBlockGiven => :warning,
@@ -983,6 +1038,7 @@ module Steep
983
1038
  UnexpectedYield => :warning,
984
1039
  UnknownConstant => :warning,
985
1040
  UnknownGlobalVariable => :warning,
1041
+ UnknownRecordKey => :information,
986
1042
  UnknownInstanceVariable => :information,
987
1043
  UnreachableBranch => :hint,
988
1044
  UnreachableValueBranch => :hint,
@@ -996,6 +1052,7 @@ module Steep
996
1052
  def self.strict
997
1053
  @strict ||= _ = all_error.merge(
998
1054
  {
1055
+ AnnotationSyntaxError => :error,
999
1056
  ArgumentTypeMismatch => :error,
1000
1057
  BlockBodyTypeMismatch => :error,
1001
1058
  BlockTypeMismatch => :error,
@@ -1025,7 +1082,8 @@ module Steep
1025
1082
  ReturnTypeMismatch => :error,
1026
1083
  SetterBodyTypeMismatch => :error,
1027
1084
  SetterReturnTypeMismatch => :error,
1028
- SyntaxError => :hint,
1085
+ ClassModuleMismatch => :error,
1086
+ SyntaxError => :information,
1029
1087
  TypeArgumentMismatchError => :error,
1030
1088
  UnannotatedEmptyCollection => :error,
1031
1089
  UnexpectedBlockGiven => :error,
@@ -1040,6 +1098,7 @@ module Steep
1040
1098
  UnexpectedYield => :error,
1041
1099
  UnknownConstant => :error,
1042
1100
  UnknownGlobalVariable => :error,
1101
+ UnknownRecordKey => :warning,
1043
1102
  UnknownInstanceVariable => :error,
1044
1103
  UnreachableBranch => :information,
1045
1104
  UnreachableValueBranch => :warning,
@@ -1053,6 +1112,7 @@ module Steep
1053
1112
  def self.lenient
1054
1113
  @lenient ||= _ = all_error.merge(
1055
1114
  {
1115
+ AnnotationSyntaxError => :error,
1056
1116
  ArgumentTypeMismatch => :information,
1057
1117
  BlockBodyTypeMismatch => :information,
1058
1118
  BlockTypeMismatch => :information,
@@ -1082,7 +1142,8 @@ module Steep
1082
1142
  ReturnTypeMismatch => :warning,
1083
1143
  SetterBodyTypeMismatch => nil,
1084
1144
  SetterReturnTypeMismatch => nil,
1085
- SyntaxError => :hint,
1145
+ ClassModuleMismatch => nil,
1146
+ SyntaxError => :information,
1086
1147
  TypeArgumentMismatchError => nil,
1087
1148
  UnannotatedEmptyCollection => :hint,
1088
1149
  UnexpectedBlockGiven => :hint,
@@ -1097,6 +1158,7 @@ module Steep
1097
1158
  UnexpectedYield => :information,
1098
1159
  UnknownConstant => :hint,
1099
1160
  UnknownGlobalVariable => :hint,
1161
+ UnknownRecordKey => :hint,
1100
1162
  UnknownInstanceVariable => :hint,
1101
1163
  UnreachableBranch => :hint,
1102
1164
  UnreachableValueBranch => :hint,
@@ -456,7 +456,7 @@ module Steep
456
456
  end
457
457
 
458
458
  def header_line
459
- "The default type of `#{param_name}` doesn't satisfy upper bound constarint: #{relation}"
459
+ "The default type of `#{param_name}` doesn't satisfy upper bound constraint: #{relation}"
460
460
  end
461
461
  end
462
462
 
@@ -468,7 +468,7 @@ module Steep
468
468
  when RBS::DuplicatedDeclarationError
469
469
  Diagnostic::Signature::DuplicatedDeclaration.new(
470
470
  type_name: error.name,
471
- location: error.decls[0].location
471
+ location: error.decls.fetch(0).location
472
472
  )
473
473
  when RBS::GenericParameterMismatchError
474
474
  Diagnostic::Signature::GenericParameterMismatch.new(
@@ -494,7 +494,7 @@ module Steep
494
494
  Diagnostic::Signature::InvalidMethodOverload.new(
495
495
  class_name: error.type_name,
496
496
  method_name: error.method_name,
497
- location: error.members[0].location
497
+ location: error.members.fetch(0).location
498
498
  )
499
499
  when RBS::DuplicatedMethodDefinitionError
500
500
  Diagnostic::Signature::DuplicatedMethodDefinition.new(
@@ -518,7 +518,7 @@ module Steep
518
518
  Diagnostic::Signature::RecursiveAlias.new(
519
519
  class_name: error.type.name,
520
520
  names: error.defs.map(&:name),
521
- location: error.defs[0].original&.location
521
+ location: error.defs.fetch(0).original&.location
522
522
  )
523
523
  when RBS::RecursiveAncestorError
524
524
  Diagnostic::Signature::RecursiveAncestor.new(
@@ -38,12 +38,12 @@ module Steep
38
38
  case group
39
39
  when Project::Target
40
40
  active_group_names.any? {|target_name, group_name|
41
- target_name == group.name && group_name == nil
41
+ target_name == group.name && (group_name == nil || group_name == true)
42
42
  }
43
43
  when Project::Group
44
44
  active_group_names.any? {|target_name, group_name|
45
45
  target_name == group.target.name &&
46
- (group_name == group.name || group_name.nil?)
46
+ (group_name == group.name || group_name == true)
47
47
  }
48
48
  end
49
49
  end
@@ -206,7 +206,7 @@ module Steep
206
206
 
207
207
  def load_files(files, target, group, params:)
208
208
  if type_check_code
209
- files.each_group_source_path(group) do |path|
209
+ files.each_group_source_path(group, true) do |path|
210
210
  params[:code_paths] << [target.name.to_s, target.project.absolute_path(path).to_s]
211
211
  end
212
212
  end
@@ -82,7 +82,7 @@ module Steep
82
82
  start_pos = diagnostic[:range][:start]
83
83
  end_pos = diagnostic[:range][:end]
84
84
 
85
- line = buffer.lines[start_pos[:line]]
85
+ line = buffer.lines.fetch(start_pos[:line])
86
86
 
87
87
  leading = line[0...start_pos[:character]] || ""
88
88
  if start_pos[:line] == end_pos[:line]
@@ -12,9 +12,10 @@ module Steep
12
12
  #
13
13
  # target :lib do
14
14
  # signature "sig"
15
+ # ignore_signature "sig/test"
15
16
  #
16
17
  # check "lib" # Directory name
17
- # check "Gemfile" # File name
18
+ # check "path/to/source.rb" # File name
18
19
  # check "app/models/**/*.rb" # Glob
19
20
  # # ignore "lib/templates/*.rb"
20
21
  #
@@ -31,9 +32,11 @@ module Steep
31
32
  # end
32
33
 
33
34
  # target :test do
34
- # signature "sig", "sig-private"
35
+ # unreferenced! # Skip type checking the `lib` code when types in `test` target is changed
36
+ # signature "sig/test" # Put RBS files for tests under `sig/test`
37
+ # check "test" # Type check Ruby scripts under `test`
35
38
  #
36
- # check "test"
39
+ # configure_code_diagnostics(D::Ruby.lenient) # Weak type checking for test code
37
40
  #
38
41
  # # library "pathname" # Standard libraries
39
42
  # end
@@ -203,7 +203,7 @@ module Steep
203
203
  array = [] #: Array[{ "file" => String, "diagnostics" => Array[untyped] }]
204
204
 
205
205
  diagnostics.each_key.sort.each do |key|
206
- ds = diagnostics[key]
206
+ ds = diagnostics.fetch(key)
207
207
  array << {
208
208
  "file" => key.to_s,
209
209
  'diagnostics' => ds.sort_by(&:sort_key).map(&:to_hash)
@@ -66,7 +66,7 @@ module Steep
66
66
  def shape(type, config)
67
67
  Steep.logger.tagged "shape(#{type})" do
68
68
  if shape = raw_shape(type, config)
69
- # Optimization that skips unnecesary substittuion
69
+ # Optimization that skips unnecessary substitution
70
70
  if type.free_variables.include?(AST::Types::Self.instance)
71
71
  shape
72
72
  else
@@ -172,7 +172,7 @@ module Steep
172
172
  if bound = config.upper_bound(type.name)
173
173
  new_config = Config.new(self_type: bound, variable_bounds: config.variable_bounds)
174
174
  sub = Substitution.build([], self_type: type)
175
- # We have to use `self_shape` insead of `raw_shape` here.
175
+ # We have to use `self_shape` instead of `raw_shape` here.
176
176
  # Keep the `self` types included in the `bound`'s shape, and replace it to the type variable.
177
177
  self_shape(bound, new_config)&.subst(sub, type: type)
178
178
  end
@@ -838,4 +838,3 @@ module Steep
838
838
  end
839
839
  end
840
840
  end
841
-
@@ -1057,6 +1057,19 @@ module Steep
1057
1057
  )
1058
1058
  end
1059
1059
 
1060
+ def accept_one_arg?
1061
+ return false unless params
1062
+ return false unless params.keyword_params.requireds.empty?
1063
+ head = params.positional_params or return false
1064
+
1065
+ case head.head
1066
+ when Params::PositionalParams::Required
1067
+ !head.tail.is_a?(Params::PositionalParams::Required)
1068
+ else
1069
+ true
1070
+ end
1071
+ end
1072
+
1060
1073
  def to_s
1061
1074
  if params
1062
1075
  "#{params} -> #{return_type}"
@@ -320,6 +320,11 @@ module Steep
320
320
  block: block
321
321
  )
322
322
  end
323
+
324
+ def accept_one_arg?
325
+ return false if block && block.required?
326
+ type.accept_one_arg?
327
+ end
323
328
  end
324
329
  end
325
330
  end
@@ -125,7 +125,7 @@ module Steep
125
125
  return nil unless key?(name)
126
126
 
127
127
  resolved_methods[name] ||= begin
128
- entry = methods[name]
128
+ entry = methods.fetch(name)
129
129
  Entry.new(
130
130
  method_name: name,
131
131
  overloads: entry.overloads.map do |overload|