steep 1.9.0.dev.2 → 1.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +82 -0
- data/README.md +9 -4
- data/Rakefile +1 -0
- data/Steepfile +11 -0
- data/bin/generate-diagnostics-docs.rb +112 -0
- data/lib/steep/ast/builtin.rb +1 -0
- data/lib/steep/ast/ignore.rb +1 -1
- data/lib/steep/ast/types/factory.rb +2 -0
- data/lib/steep/cli.rb +9 -2
- data/lib/steep/diagnostic/lsp_formatter.rb +8 -1
- data/lib/steep/diagnostic/ruby.rb +65 -3
- data/lib/steep/diagnostic/signature.rb +4 -4
- data/lib/steep/drivers/annotations.rb +1 -1
- data/lib/steep/drivers/check.rb +3 -3
- data/lib/steep/drivers/diagnostic_printer.rb +1 -1
- data/lib/steep/drivers/init.rb +6 -3
- data/lib/steep/expectations.rb +1 -1
- data/lib/steep/interface/builder.rb +7 -5
- data/lib/steep/interface/function.rb +13 -0
- data/lib/steep/interface/method_type.rb +5 -0
- data/lib/steep/interface/shape.rb +1 -1
- data/lib/steep/project/dsl.rb +11 -1
- data/lib/steep/project/target.rb +3 -1
- data/lib/steep/server/change_buffer.rb +1 -1
- data/lib/steep/server/interaction_worker.rb +5 -5
- data/lib/steep/server/master.rb +2 -17
- data/lib/steep/server/type_check_controller.rb +3 -3
- data/lib/steep/server/type_check_worker.rb +1 -1
- data/lib/steep/services/completion_provider.rb +4 -4
- data/lib/steep/services/goto_service.rb +3 -3
- data/lib/steep/services/hover_provider/rbs.rb +1 -1
- data/lib/steep/services/hover_provider/ruby.rb +6 -6
- data/lib/steep/services/signature_help_provider.rb +8 -8
- data/lib/steep/services/signature_service.rb +12 -8
- data/lib/steep/services/type_check_service.rb +9 -9
- data/lib/steep/signature/validator.rb +3 -3
- data/lib/steep/source.rb +4 -4
- data/lib/steep/subtyping/check.rb +3 -3
- data/lib/steep/subtyping/constraints.rb +4 -4
- data/lib/steep/type_construction.rb +84 -45
- data/lib/steep/type_inference/block_params.rb +3 -3
- data/lib/steep/type_inference/context.rb +1 -1
- data/lib/steep/type_inference/method_params.rb +1 -1
- data/lib/steep/type_inference/type_env.rb +3 -3
- data/lib/steep/version.rb +1 -1
- data/manual/annotations.md +37 -0
- data/manual/ignore.md +20 -0
- data/manual/ruby-diagnostics.md +1812 -0
- data/steep.gemspec +1 -1
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 522d134347810d1fbb030d139f616077fcc197aabe079bf14453305c9c9562bd
|
4
|
+
data.tar.gz: bd6a1a97a815c02ba20160d6bc1bd2166c1a02cdee3901c2a84fca2fe1b22d0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 254fb6ef3b682ea7866e2892755e183bcd8ed797f4209faf999f40cdcb140a67083c73684ba80273cbf2e563650a2213114c474a2e0d3e50cc6d0cdc5d05caf0
|
7
|
+
data.tar.gz: b5daeab25121a44e5e9ad4a353de77115f7f626c0f5ac9342c1fe0ac061eabf75cbf3fef26a3b651d0b4849a0c05d5c1eafe9027f72294af0974f7b051f9eb71
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,87 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 1.9.1 (2024-12-09)
|
4
|
+
|
5
|
+
### Type checker core
|
6
|
+
|
7
|
+
* Make `implicitly-returns-nil` opt-in ([#1396](https://github.com/soutaro/steep/pull/1396))
|
8
|
+
|
9
|
+
## 1.9.0 (2024-12-06)
|
10
|
+
|
11
|
+
### Type checker core
|
12
|
+
|
13
|
+
* Report diagnostic on unknown record key ([#1385](https://github.com/soutaro/steep/pull/1385))
|
14
|
+
* Report annotation syntax error ([#1384](https://github.com/soutaro/steep/pull/1384))
|
15
|
+
* emit UnreachableBranch to the "void" condition ([#1356](https://github.com/soutaro/steep/pull/1356))
|
16
|
+
* Support &method(:name) call for block_pass ([#1276](https://github.com/soutaro/steep/pull/1276))
|
17
|
+
* Emit SingletonTypeMismatch when class/module mismatch ([#1274](https://github.com/soutaro/steep/pull/1274))
|
18
|
+
* refactor: Use Array#fetch instead of Array#[] to resolve type errors ([#1287](https://github.com/soutaro/steep/pull/1287))
|
19
|
+
* refactor: Use Hash#fetch instead of Hash#[] to resolve type errors ([#1286](https://github.com/soutaro/steep/pull/1286))
|
20
|
+
* Expand `array(splat(expr` node ([#1347](https://github.com/soutaro/steep/pull/1347))
|
21
|
+
* Add `UnannotatedEmptyCollection` diagnostic ([#1338](https://github.com/soutaro/steep/pull/1338))
|
22
|
+
* Update type checking strategy ([#1308](https://github.com/soutaro/steep/pull/1308))
|
23
|
+
* Fix untyped hash typing ([#1299](https://github.com/soutaro/steep/pull/1299))
|
24
|
+
* Support `implicitly-returns-nil` ([#1258](https://github.com/soutaro/steep/pull/1258))
|
25
|
+
* Fix record shape ([#1265](https://github.com/soutaro/steep/pull/1265))
|
26
|
+
* Remove unused rules ([#1238](https://github.com/soutaro/steep/pull/1238))
|
27
|
+
|
28
|
+
### Commandline tool
|
29
|
+
|
30
|
+
* Introduces a new `target.*` syntax for everything in the target ([#1387](https://github.com/soutaro/steep/pull/1387))
|
31
|
+
* Symbolize target/group names ([#1364](https://github.com/soutaro/steep/pull/1364))
|
32
|
+
* Update Steepfile template ([#1355](https://github.com/soutaro/steep/pull/1355))
|
33
|
+
* Delete `target` from `--validate` option ([#1346](https://github.com/soutaro/steep/pull/1346))
|
34
|
+
* Install rbs collection automatically ([#1345](https://github.com/soutaro/steep/pull/1345))
|
35
|
+
|
36
|
+
### Language server
|
37
|
+
|
38
|
+
* Add link to diagnostic manual ([#1388](https://github.com/soutaro/steep/pull/1388))
|
39
|
+
* Stop accumulating diagnostics ([#1367](https://github.com/soutaro/steep/pull/1367))
|
40
|
+
* Send server version to client ([#1341](https://github.com/soutaro/steep/pull/1341))
|
41
|
+
* Add custom methods to trigger type check manually ([#1340](https://github.com/soutaro/steep/pull/1340))
|
42
|
+
* Type check thread helpers ([#1335](https://github.com/soutaro/steep/pull/1335))
|
43
|
+
* Use `URI::RFC2396_Parser` ([#1329](https://github.com/soutaro/steep/pull/1329))
|
44
|
+
* Handle file deletion notification ([#1300](https://github.com/soutaro/steep/pull/1300))
|
45
|
+
* Refactor communication between master and type check worker ([#1285](https://github.com/soutaro/steep/pull/1285))
|
46
|
+
* Skip sending response to `$/steep/typecheck` request from `steep langserver` ([#1267](https://github.com/soutaro/steep/pull/1267))
|
47
|
+
|
48
|
+
### Miscellaneous
|
49
|
+
|
50
|
+
* Use rbs-3.7 ([#1383](https://github.com/soutaro/steep/pull/1383))
|
51
|
+
* Move diagnostic docs ([#1370](https://github.com/soutaro/steep/pull/1370))
|
52
|
+
* Add anchor ([#1359](https://github.com/soutaro/steep/pull/1359))
|
53
|
+
* Update example to not use `^` as a hash function ([#1360](https://github.com/soutaro/steep/pull/1360))
|
54
|
+
* doc: Add diagnostics for Ruby page ([#1249](https://github.com/soutaro/steep/pull/1249))
|
55
|
+
* Update filename example in initial Steepfile ([#1230](https://github.com/soutaro/steep/pull/1230))
|
56
|
+
* docs: Add document for steep:ignore comment ([#1353](https://github.com/soutaro/steep/pull/1353))
|
57
|
+
* docs: Add document for type assertion and type application ([#1235](https://github.com/soutaro/steep/pull/1235))
|
58
|
+
* Print test names in CI for investigation ([#1354](https://github.com/soutaro/steep/pull/1354))
|
59
|
+
* Fix typo ([#1352](https://github.com/soutaro/steep/pull/1352))
|
60
|
+
* Set up type checking tests ([#1339](https://github.com/soutaro/steep/pull/1339))
|
61
|
+
* Fix typo ([#1248](https://github.com/soutaro/steep/pull/1248))
|
62
|
+
|
63
|
+
## 1.8.3 (2024-10-29)
|
64
|
+
|
65
|
+
### Type checker core
|
66
|
+
|
67
|
+
* Fix untyped hash typing ([#1299](https://github.com/soutaro/steep/pull/1299), Backport in [#1301](https://github.com/soutaro/steep/pull/1301))
|
68
|
+
|
69
|
+
### Language server
|
70
|
+
|
71
|
+
* Handle file deletion notification ([#1300](https://github.com/soutaro/steep/pull/1300), Backport in [#1301](https://github.com/soutaro/steep/pull/1301))
|
72
|
+
|
73
|
+
## 1.8.2 (2024-10-24)
|
74
|
+
|
75
|
+
### Language server
|
76
|
+
|
77
|
+
* Ignore `didChangeWatchedFiles notification` for open files ([#1290](https://github.com/soutaro/steep/pull/1290))
|
78
|
+
|
79
|
+
## 1.8.1 (2024-10-08)
|
80
|
+
|
81
|
+
### Language server
|
82
|
+
|
83
|
+
* 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))
|
84
|
+
|
3
85
|
## 1.8.0 (2024-09-30)
|
4
86
|
|
5
87
|
### 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
|
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
|
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
|
-
##
|
204
|
+
## Docs
|
205
205
|
|
206
|
-
There are some
|
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
data/Steepfile
CHANGED
@@ -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
|
data/lib/steep/ast/builtin.rb
CHANGED
data/lib/steep/ast/ignore.rb
CHANGED
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
|
131
|
+
# @type var arg: String
|
132
132
|
target, group = arg.split(".")
|
133
133
|
target or raise
|
134
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
521
|
+
location: error.defs.fetch(0).original&.location
|
522
522
|
)
|
523
523
|
when RBS::RecursiveAncestorError
|
524
524
|
Diagnostic::Signature::RecursiveAncestor.new(
|
@@ -21,7 +21,7 @@ module Steep
|
|
21
21
|
|
22
22
|
project.targets.each do |target|
|
23
23
|
Steep.logger.tagged "target=#{target.name}" do
|
24
|
-
service = Services::SignatureService.load_from(target.new_env_loader())
|
24
|
+
service = Services::SignatureService.load_from(target.new_env_loader(), implicitly_returns_nil: target.implicitly_returns_nil)
|
25
25
|
|
26
26
|
sigs = loader.load_changes(target.signature_pattern, changes: {})
|
27
27
|
service.update(sigs)
|
data/lib/steep/drivers/check.rb
CHANGED
@@ -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
|
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
|
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]
|
data/lib/steep/drivers/init.rb
CHANGED
@@ -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 "
|
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
|
-
#
|
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
|
-
#
|
39
|
+
# configure_code_diagnostics(D::Ruby.lenient) # Weak type checking for test code
|
37
40
|
#
|
38
41
|
# # library "pathname" # Standard libraries
|
39
42
|
# end
|
data/lib/steep/expectations.rb
CHANGED
@@ -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
|
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)
|
@@ -54,19 +54,20 @@ module Steep
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
attr_reader :factory, :object_shape_cache, :union_shape_cache, :singleton_shape_cache
|
57
|
+
attr_reader :factory, :object_shape_cache, :union_shape_cache, :singleton_shape_cache, :implicitly_returns_nil
|
58
58
|
|
59
|
-
def initialize(factory)
|
59
|
+
def initialize(factory, implicitly_returns_nil:)
|
60
60
|
@factory = factory
|
61
61
|
@object_shape_cache = {}
|
62
62
|
@union_shape_cache = {}
|
63
63
|
@singleton_shape_cache = {}
|
64
|
+
@implicitly_returns_nil = implicitly_returns_nil
|
64
65
|
end
|
65
66
|
|
66
67
|
def shape(type, config)
|
67
68
|
Steep.logger.tagged "shape(#{type})" do
|
68
69
|
if shape = raw_shape(type, config)
|
69
|
-
# Optimization that skips
|
70
|
+
# Optimization that skips unnecessary substitution
|
70
71
|
if type.free_variables.include?(AST::Types::Self.instance)
|
71
72
|
shape
|
72
73
|
else
|
@@ -172,7 +173,7 @@ module Steep
|
|
172
173
|
if bound = config.upper_bound(type.name)
|
173
174
|
new_config = Config.new(self_type: bound, variable_bounds: config.variable_bounds)
|
174
175
|
sub = Substitution.build([], self_type: type)
|
175
|
-
# We have to use `self_shape`
|
176
|
+
# We have to use `self_shape` instead of `raw_shape` here.
|
176
177
|
# Keep the `self` types included in the `bound`'s shape, and replace it to the type variable.
|
177
178
|
self_shape(bound, new_config)&.subst(sub, type: type)
|
178
179
|
end
|
@@ -826,6 +827,8 @@ module Steep
|
|
826
827
|
end
|
827
828
|
|
828
829
|
def add_implicitly_returns_nil(annotations, method_type)
|
830
|
+
return method_type unless implicitly_returns_nil
|
831
|
+
|
829
832
|
if annotations.find { _1.string == "implicitly-returns-nil" }
|
830
833
|
return_type = method_type.type.return_type
|
831
834
|
method_type = method_type.with(
|
@@ -838,4 +841,3 @@ module Steep
|
|
838
841
|
end
|
839
842
|
end
|
840
843
|
end
|
841
|
-
|