steep 1.2.1 → 1.3.0.pre.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -0
- data/Gemfile.lock +4 -4
- data/Gemfile.steep +1 -1
- data/Gemfile.steep.lock +13 -3
- data/Steepfile +0 -1
- data/bin/steep-prof +1 -1
- data/lib/steep/annotation_parser.rb +34 -28
- data/lib/steep/ast/annotation.rb +16 -5
- data/lib/steep/ast/node/type_application.rb +74 -0
- data/lib/steep/ast/node/type_assertion.rb +56 -0
- data/lib/steep/ast/types/factory.rb +5 -1
- data/lib/steep/ast/types/helper.rb +4 -3
- data/lib/steep/ast/types/logic.rb +4 -0
- data/lib/steep/diagnostic/helper.rb +2 -1
- data/lib/steep/diagnostic/lsp_formatter.rb +3 -1
- data/lib/steep/diagnostic/ruby.rb +70 -5
- data/lib/steep/diagnostic/signature.rb +21 -8
- data/lib/steep/drivers/check.rb +2 -2
- data/lib/steep/drivers/checkfile.rb +2 -2
- data/lib/steep/drivers/langserver.rb +2 -2
- data/lib/steep/drivers/stats.rb +2 -2
- data/lib/steep/drivers/utils/jobs_option.rb +0 -4
- data/lib/steep/drivers/watch.rb +1 -1
- data/lib/steep/drivers/worker.rb +0 -1
- data/lib/steep/server/lsp_formatter.rb +13 -3
- data/lib/steep/server/master.rb +4 -1
- data/lib/steep/server/worker_process.rb +91 -14
- data/lib/steep/services/completion_provider.rb +2 -1
- data/lib/steep/services/goto_service.rb +2 -1
- data/lib/steep/services/hover_provider/rbs.rb +7 -7
- data/lib/steep/services/hover_provider/ruby.rb +21 -5
- data/lib/steep/services/signature_service.rb +23 -4
- data/lib/steep/services/type_check_service.rb +4 -4
- data/lib/steep/signature/validator.rb +36 -13
- data/lib/steep/source.rb +189 -71
- data/lib/steep/type_construction.rb +246 -135
- data/lib/steep/type_inference/logic_type_interpreter.rb +3 -1
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +2 -0
- data/rbs_collection.steep.lock.yaml +27 -10
- data/rbs_collection.steep.yaml +0 -1
- data/sig/shims/exception.rbs +4 -0
- data/sig/shims/parser/comment.rbs +33 -0
- data/sig/shims/parser.rbs +30 -2
- data/sig/steep/annotation_parser.rbs +59 -0
- data/sig/steep/ast/annotation.rbs +21 -26
- data/sig/steep/ast/node/type_application.rbs +31 -0
- data/sig/steep/ast/node/type_assertion.rbs +26 -0
- data/sig/steep/ast/types/any.rbs +1 -1
- data/sig/steep/ast/types/boolean.rbs +1 -1
- data/sig/steep/ast/types/bot.rbs +1 -1
- data/sig/steep/ast/types/class.rbs +1 -1
- data/sig/steep/ast/types/factory.rbs +0 -2
- data/sig/steep/ast/types/helper.rbs +6 -3
- data/sig/steep/ast/types/instance.rbs +1 -1
- data/sig/steep/ast/types/intersection.rbs +1 -1
- data/sig/steep/ast/types/logic.rbs +2 -0
- data/sig/steep/ast/types/name.rbs +2 -2
- data/sig/steep/ast/types/nil.rbs +1 -1
- data/sig/steep/ast/types/record.rbs +1 -1
- data/sig/steep/ast/types/self.rbs +1 -1
- data/sig/steep/ast/types/top.rbs +2 -2
- data/sig/steep/ast/types/tuple.rbs +1 -1
- data/sig/steep/ast/types/union.rbs +1 -1
- data/sig/steep/ast/types/var.rbs +2 -2
- data/sig/steep/ast/types/void.rbs +1 -1
- data/sig/steep/diagnostic/helper.rbs +9 -3
- data/sig/steep/diagnostic/lsp_formatter.rbs +12 -8
- data/sig/steep/diagnostic/ruby.rbs +62 -8
- data/sig/steep/diagnostic/signature.rbs +118 -85
- data/sig/steep/drivers/utils/jobs_option.rbs +0 -2
- data/sig/steep/drivers/worker.rbs +11 -13
- data/sig/steep/range_extension.rbs +7 -0
- data/sig/steep/server/lsp_formatter.rbs +14 -7
- data/sig/steep/server/worker_process.rbs +74 -12
- data/sig/steep/services/hover_provider/rbs.rbs +27 -7
- data/sig/steep/services/hover_provider/ruby.rbs +18 -4
- data/sig/steep/services/hover_provider/singleton_methods.rbs +1 -1
- data/sig/steep/services/signature_service.rbs +14 -0
- data/sig/steep/services/type_check_service.rbs +2 -2
- data/sig/steep/signature/validator.rbs +76 -0
- data/sig/steep/source.rbs +54 -30
- data/sig/steep/type_construction.rbs +85 -27
- data/sig/steep/type_inference/method_call.rbs +1 -1
- data/sig/steep.rbs +2 -0
- data/smoke/diagnostics-rbs/inherit-module.rbs +2 -0
- data/smoke/diagnostics-rbs/test_expectations.yml +12 -0
- data/steep.gemspec +1 -1
- metadata +16 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 639a97319d661c777702365209eaf5a6ea2632723a509331a03f6f1ef3926148
|
4
|
+
data.tar.gz: fb6061b52a09fb97c907abff4f69d6c9267eef1c9a3af52fa87fffda9de5d1f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 232ec5b779c018aa9824318e003cd60e3ec3691297903337bb414fff87e757daaacfda2d94fb0c751538dcad194763ad6cb5b072156686bd450d5292d490a2e6
|
7
|
+
data.tar.gz: b322f5568a1fe5cbc0693a01a7be50d9860e056a9f69325e6c55a9322f2d32f7d1d0889d19e45576ca6f3f9afde9649747d9d02a0e251702f94cd27bf5fae27c
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,34 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 1.3.0.pre.2 (2022-11-23)
|
6
|
+
|
7
|
+
### Type checker core
|
8
|
+
|
9
|
+
* Add missing `#level` method ([\#671](https://github.com/soutaro/steep/pull/671))
|
10
|
+
* Cache `constant_resolver` among files in a target([\#673](https://github.com/soutaro/steep/pull/673))
|
11
|
+
* Early return from type checking overloads ([\#674](https://github.com/soutaro/steep/pull/674))
|
12
|
+
|
13
|
+
### Commandline tool
|
14
|
+
|
15
|
+
* Spawn worker processes if `--steep-command` is specified ([\#672](https://github.com/soutaro/steep/pull/672))
|
16
|
+
|
17
|
+
## 1.3.0.pre.1 (2022-11-22)
|
18
|
+
|
19
|
+
### Type checker core
|
20
|
+
|
21
|
+
* Add type assertion syntax ([#665](https://github.com/soutaro/steep/pull/665))
|
22
|
+
* Add type application syntax ([#670](https://github.com/soutaro/steep/pull/670))
|
23
|
+
|
24
|
+
### Commandline tool
|
25
|
+
|
26
|
+
* Fork when available for quicker startup ([#664](https://github.com/soutaro/steep/pull/664))
|
27
|
+
|
28
|
+
### Miscellaneous
|
29
|
+
|
30
|
+
* Fixes for some RBS errors within steep gem ([#668](https://github.com/soutaro/steep/pull/668))
|
31
|
+
* Upgrade to RBS 2.8 (pre) ([#669](https://github.com/soutaro/steep/pull/669))
|
32
|
+
|
5
33
|
## 1.2.1 (2022-10-22)
|
6
34
|
|
7
35
|
### Type checker core
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
steep (1.2
|
4
|
+
steep (1.3.0.pre.2)
|
5
5
|
activesupport (>= 5.1)
|
6
6
|
csv (>= 3.0.9)
|
7
7
|
fileutils (>= 1.1.0)
|
@@ -12,7 +12,7 @@ PATH
|
|
12
12
|
parallel (>= 1.0.0)
|
13
13
|
parser (>= 3.1)
|
14
14
|
rainbow (>= 2.2.2, < 4.0)
|
15
|
-
rbs (>= 2.
|
15
|
+
rbs (>= 2.8.0.pre)
|
16
16
|
securerandom (>= 0.1)
|
17
17
|
strscan (>= 1.0.0)
|
18
18
|
terminal-table (>= 2, < 4)
|
@@ -54,11 +54,11 @@ GEM
|
|
54
54
|
rb-fsevent (0.11.2)
|
55
55
|
rb-inotify (0.10.1)
|
56
56
|
ffi (~> 1.0)
|
57
|
-
rbs (2.
|
57
|
+
rbs (2.8.0.pre.1)
|
58
58
|
ruby-debug-ide (0.7.3)
|
59
59
|
rake (>= 0.8.1)
|
60
60
|
securerandom (0.2.0)
|
61
|
-
stackprof (0.2.
|
61
|
+
stackprof (0.2.22)
|
62
62
|
strscan (3.0.4)
|
63
63
|
terminal-table (3.0.2)
|
64
64
|
unicode-display_width (>= 1.1.1, < 3)
|
data/Gemfile.steep
CHANGED
data/Gemfile.steep.lock
CHANGED
@@ -8,13 +8,17 @@ GEM
|
|
8
8
|
tzinfo (~> 2.0)
|
9
9
|
ast (2.4.2)
|
10
10
|
concurrent-ruby (1.1.10)
|
11
|
+
csv (3.2.5)
|
11
12
|
ffi (1.15.5)
|
13
|
+
fileutils (1.6.0)
|
12
14
|
i18n (1.12.0)
|
13
15
|
concurrent-ruby (~> 1.0)
|
16
|
+
json (2.6.2)
|
14
17
|
language_server-protocol (3.17.0.1)
|
15
18
|
listen (3.7.1)
|
16
19
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
17
20
|
rb-inotify (~> 0.9, >= 0.9.10)
|
21
|
+
logger (1.5.1)
|
18
22
|
minitest (5.16.3)
|
19
23
|
parallel (1.22.1)
|
20
24
|
parser (3.1.2.1)
|
@@ -23,18 +27,24 @@ GEM
|
|
23
27
|
rb-fsevent (0.11.2)
|
24
28
|
rb-inotify (0.10.1)
|
25
29
|
ffi (~> 1.0)
|
26
|
-
rbs (2.
|
30
|
+
rbs (2.8.0.pre.1)
|
27
31
|
securerandom (0.2.0)
|
28
|
-
steep (1.2.
|
32
|
+
steep (1.2.1)
|
29
33
|
activesupport (>= 5.1)
|
34
|
+
csv (>= 3.0.9)
|
35
|
+
fileutils (>= 1.1.0)
|
36
|
+
json (>= 2.1.0)
|
30
37
|
language_server-protocol (>= 3.15, < 4.0)
|
31
38
|
listen (~> 3.0)
|
39
|
+
logger (>= 1.3.0)
|
32
40
|
parallel (>= 1.0.0)
|
33
41
|
parser (>= 3.1)
|
34
42
|
rainbow (>= 2.2.2, < 4.0)
|
35
43
|
rbs (>= 2.7.0)
|
36
44
|
securerandom (>= 0.1)
|
45
|
+
strscan (>= 1.0.0)
|
37
46
|
terminal-table (>= 2, < 4)
|
47
|
+
strscan (3.0.4)
|
38
48
|
terminal-table (3.0.2)
|
39
49
|
unicode-display_width (>= 1.1.1, < 3)
|
40
50
|
tzinfo (2.0.5)
|
@@ -45,7 +55,7 @@ PLATFORMS
|
|
45
55
|
arm64-darwin-21
|
46
56
|
|
47
57
|
DEPENDENCIES
|
48
|
-
rbs
|
58
|
+
rbs (~> 2.8.0.pre)
|
49
59
|
steep (~> 1.2.0)
|
50
60
|
|
51
61
|
BUNDLED WITH
|
data/Steepfile
CHANGED
data/bin/steep-prof
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require "stackprof"
|
4
4
|
|
5
|
-
mode = (ENV["STEEP_STACKPROF_MODE"] || :
|
5
|
+
mode = (ENV["STEEP_STACKPROF_MODE"] || :cpu).to_sym
|
6
6
|
out = ENV["STEEP_STACKPROF_OUT"] || "tmp/stackprof-#{mode}-steep.dump"
|
7
7
|
interval = ENV["STEEP_STACKPROF_INTERVAL"]&.to_i || 1000
|
8
8
|
|
@@ -27,7 +27,7 @@ module Steep
|
|
27
27
|
message = case exn
|
28
28
|
when RBS::ParsingError
|
29
29
|
Diagnostic::Signature::SyntaxError.parser_syntax_error_message(exn)
|
30
|
-
|
30
|
+
when Exception
|
31
31
|
exn.message
|
32
32
|
end
|
33
33
|
|
@@ -45,16 +45,10 @@ module Steep
|
|
45
45
|
factory.type(RBS::Parser.parse_type(string))
|
46
46
|
end
|
47
47
|
|
48
|
-
# @type ${keyword} ${name}: ${type}
|
49
|
-
# Example: @type const Foo::Bar: String
|
50
|
-
# @type var xyzzy: Array[String]
|
51
48
|
def keyword_subject_type(keyword, name)
|
52
49
|
/@type\s+#{keyword}\s+(?<name>#{name})#{COLON}#{TYPE}/
|
53
50
|
end
|
54
51
|
|
55
|
-
# @type ${keyword}: ${type}
|
56
|
-
# Example: @type break: String
|
57
|
-
# @type self: Foo
|
58
52
|
def keyword_and_type(keyword)
|
59
53
|
/@type\s+#{keyword}#{COLON}#{TYPE}/
|
60
54
|
end
|
@@ -63,8 +57,9 @@ module Steep
|
|
63
57
|
case src
|
64
58
|
when keyword_subject_type("var", VAR_NAME)
|
65
59
|
Regexp.last_match.yield_self do |match|
|
66
|
-
|
67
|
-
|
60
|
+
match or raise
|
61
|
+
name = match[:name] or raise
|
62
|
+
type = match[:type] or raise
|
68
63
|
|
69
64
|
AST::Annotation::VarType.new(name: name.to_sym,
|
70
65
|
type: parse_type(type),
|
@@ -73,8 +68,9 @@ module Steep
|
|
73
68
|
|
74
69
|
when keyword_subject_type("method", METHOD_NAME)
|
75
70
|
Regexp.last_match.yield_self do |match|
|
76
|
-
|
77
|
-
|
71
|
+
match or raise
|
72
|
+
name = match[:name] or raise
|
73
|
+
type = match[:type] or raise
|
78
74
|
|
79
75
|
method_type = factory.method_type(RBS::Parser.parse_method_type(type), method_decls: Set[])
|
80
76
|
|
@@ -85,16 +81,18 @@ module Steep
|
|
85
81
|
|
86
82
|
when keyword_subject_type("const", CONST_NAME)
|
87
83
|
Regexp.last_match.yield_self do |match|
|
88
|
-
|
89
|
-
|
84
|
+
match or raise
|
85
|
+
name = match[:name] or raise
|
86
|
+
type = parse_type(match[:type] || raise)
|
90
87
|
|
91
88
|
AST::Annotation::ConstType.new(name: TypeName(name), type: type, location: location)
|
92
89
|
end
|
93
90
|
|
94
91
|
when keyword_subject_type("ivar", IVAR_NAME)
|
95
92
|
Regexp.last_match.yield_self do |match|
|
96
|
-
|
97
|
-
|
93
|
+
match or raise
|
94
|
+
name = match[:name] or raise
|
95
|
+
type = parse_type(match[:type] || raise)
|
98
96
|
|
99
97
|
AST::Annotation::IvarType.new(name: name.to_sym,
|
100
98
|
type: type,
|
@@ -103,51 +101,58 @@ module Steep
|
|
103
101
|
|
104
102
|
when keyword_and_type("return")
|
105
103
|
Regexp.last_match.yield_self do |match|
|
106
|
-
|
104
|
+
match or raise
|
105
|
+
type = parse_type(match[:type] || raise)
|
107
106
|
AST::Annotation::ReturnType.new(type: type, location: location)
|
108
107
|
end
|
109
108
|
|
110
109
|
when keyword_and_type("block")
|
111
110
|
Regexp.last_match.yield_self do |match|
|
112
|
-
|
111
|
+
match or raise
|
112
|
+
type = parse_type(match[:type] || raise)
|
113
113
|
AST::Annotation::BlockType.new(type: type, location: location)
|
114
114
|
end
|
115
115
|
|
116
116
|
when keyword_and_type("self")
|
117
117
|
Regexp.last_match.yield_self do |match|
|
118
|
-
|
118
|
+
match or raise
|
119
|
+
type = parse_type(match[:type] || raise)
|
119
120
|
AST::Annotation::SelfType.new(type: type, location: location)
|
120
121
|
end
|
121
122
|
|
122
123
|
when keyword_and_type("instance")
|
123
124
|
Regexp.last_match.yield_self do |match|
|
124
|
-
|
125
|
+
match or raise
|
126
|
+
type = parse_type(match[:type] || raise)
|
125
127
|
AST::Annotation::InstanceType.new(type: type, location: location)
|
126
128
|
end
|
127
129
|
|
128
130
|
when keyword_and_type("module")
|
129
131
|
Regexp.last_match.yield_self do |match|
|
130
|
-
|
132
|
+
match or raise
|
133
|
+
type = parse_type(match[:type] || raise)
|
131
134
|
AST::Annotation::ModuleType.new(type: type, location: location)
|
132
135
|
end
|
133
136
|
|
134
137
|
when keyword_and_type("break")
|
135
138
|
Regexp.last_match.yield_self do |match|
|
136
|
-
|
139
|
+
match or raise
|
140
|
+
type = parse_type(match[:type] || raise)
|
137
141
|
AST::Annotation::BreakType.new(type: type, location: location)
|
138
142
|
end
|
139
143
|
|
140
144
|
when /@dynamic\s+(?<names>(#{DYNAMIC_NAME}\s*,\s*)*#{DYNAMIC_NAME})/
|
141
145
|
Regexp.last_match.yield_self do |match|
|
142
|
-
|
146
|
+
match or raise
|
147
|
+
names = (match[:names] || raise).split(/\s*,\s*/)
|
143
148
|
|
144
149
|
AST::Annotation::Dynamic.new(
|
145
150
|
names: names.map {|name|
|
146
|
-
case
|
147
|
-
when
|
148
|
-
AST::Annotation::Dynamic::Name.new(name: name
|
149
|
-
when
|
150
|
-
AST::Annotation::Dynamic::Name.new(name: name
|
151
|
+
case
|
152
|
+
when name.delete_prefix!("self.")
|
153
|
+
AST::Annotation::Dynamic::Name.new(name: name.to_sym, kind: :module)
|
154
|
+
when name.delete_prefix!("self?.")
|
155
|
+
AST::Annotation::Dynamic::Name.new(name: name.to_sym, kind: :module_instance)
|
151
156
|
else
|
152
157
|
AST::Annotation::Dynamic::Name.new(name: name.to_sym, kind: :instance)
|
153
158
|
end
|
@@ -158,7 +163,8 @@ module Steep
|
|
158
163
|
|
159
164
|
when /@implements\s+(?<name>#{CONST_NAME})#{TYPE_PARAMS}$/
|
160
165
|
Regexp.last_match.yield_self do |match|
|
161
|
-
|
166
|
+
match or raise
|
167
|
+
type_name = TypeName(match[:name] || raise)
|
162
168
|
params = match[:params]&.yield_self {|params| params.split(/,/).map {|param| param.strip.to_sym } } || []
|
163
169
|
|
164
170
|
name = AST::Annotation::Implements::Module.new(name: type_name, args: params)
|
data/lib/steep/ast/annotation.rb
CHANGED
@@ -1,10 +1,19 @@
|
|
1
1
|
module Steep
|
2
2
|
module AST
|
3
3
|
module Annotation
|
4
|
+
module Located
|
5
|
+
attr_reader :location
|
6
|
+
|
7
|
+
def line
|
8
|
+
location&.start_line
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
4
12
|
class Named
|
13
|
+
include Located
|
14
|
+
|
5
15
|
attr_reader :name
|
6
16
|
attr_reader :type
|
7
|
-
attr_reader :location
|
8
17
|
|
9
18
|
def initialize(name:, type:, location: nil)
|
10
19
|
@name = name
|
@@ -20,9 +29,9 @@ module Steep
|
|
20
29
|
end
|
21
30
|
|
22
31
|
class Typed
|
32
|
+
include Located
|
33
|
+
|
23
34
|
attr_reader :type
|
24
|
-
attr_reader :annotation
|
25
|
-
attr_reader :location
|
26
35
|
|
27
36
|
def initialize(type:, location: nil)
|
28
37
|
@type = type
|
@@ -68,7 +77,8 @@ module Steep
|
|
68
77
|
end
|
69
78
|
end
|
70
79
|
|
71
|
-
|
80
|
+
include Located
|
81
|
+
|
72
82
|
attr_reader :name
|
73
83
|
|
74
84
|
def initialize(name:, location: nil)
|
@@ -108,7 +118,8 @@ module Steep
|
|
108
118
|
end
|
109
119
|
end
|
110
120
|
|
111
|
-
|
121
|
+
include Located
|
122
|
+
|
112
123
|
attr_reader :names
|
113
124
|
|
114
125
|
def initialize(names:, location: nil)
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Node
|
4
|
+
class TypeApplication
|
5
|
+
attr_reader :location
|
6
|
+
|
7
|
+
def initialize(location)
|
8
|
+
@location = location
|
9
|
+
end
|
10
|
+
|
11
|
+
def node
|
12
|
+
@node || raise
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_node(node)
|
16
|
+
@node = node
|
17
|
+
end
|
18
|
+
|
19
|
+
def line
|
20
|
+
location.start_line
|
21
|
+
end
|
22
|
+
|
23
|
+
def source
|
24
|
+
location.source
|
25
|
+
end
|
26
|
+
|
27
|
+
def types(context, factory, type_vars)
|
28
|
+
# @type var types: Array[Types::t]
|
29
|
+
types = []
|
30
|
+
|
31
|
+
loc = type_location
|
32
|
+
|
33
|
+
while true
|
34
|
+
ty = RBS::Parser.parse_type(loc.buffer, range: loc.range, variables: type_vars) or break
|
35
|
+
ty = factory.type(ty)
|
36
|
+
types << factory.absolute_type(ty, context: context)
|
37
|
+
|
38
|
+
match = RBS::Location.new(loc.buffer, ty.location.end_pos, type_location.end_pos).source.match(/\A\s*,\s*/) or break
|
39
|
+
offset = match.length
|
40
|
+
loc = RBS::Location.new(loc.buffer, ty.location.end_pos + offset, type_location.end_pos)
|
41
|
+
end
|
42
|
+
|
43
|
+
types
|
44
|
+
rescue ::RBS::ParsingError => exn
|
45
|
+
exn
|
46
|
+
end
|
47
|
+
|
48
|
+
def types?(context, factory, type_vars)
|
49
|
+
case types = types(context, factory, type_vars)
|
50
|
+
when RBS::ParsingError
|
51
|
+
nil
|
52
|
+
else
|
53
|
+
types
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def type_str
|
58
|
+
@type_str ||= source.delete_prefix("$").lstrip
|
59
|
+
end
|
60
|
+
|
61
|
+
def type_location
|
62
|
+
offset = source.size - type_str.size
|
63
|
+
RBS::Location.new(location.buffer, location.start_pos + offset, location.end_pos)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.parse(location)
|
67
|
+
if location.source =~/\A\$\s*(.+)/
|
68
|
+
TypeApplication.new(location)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Node
|
4
|
+
class TypeAssertion
|
5
|
+
attr_reader :location
|
6
|
+
|
7
|
+
def initialize(location)
|
8
|
+
@location = location
|
9
|
+
end
|
10
|
+
|
11
|
+
def source
|
12
|
+
location.source
|
13
|
+
end
|
14
|
+
|
15
|
+
def line
|
16
|
+
location.start_line
|
17
|
+
end
|
18
|
+
|
19
|
+
def type(context, factory, type_vars)
|
20
|
+
if ty = RBS::Parser.parse_type(type_location.buffer, range: type_location.range, variables: type_vars)
|
21
|
+
ty = factory.type(ty)
|
22
|
+
factory.absolute_type(ty, context: context)
|
23
|
+
else
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
rescue ::RBS::ParsingError => exn
|
27
|
+
exn
|
28
|
+
end
|
29
|
+
|
30
|
+
def type?(context, factory, type_vars)
|
31
|
+
case type = type(context, factory, type_vars)
|
32
|
+
when RBS::ParsingError
|
33
|
+
nil
|
34
|
+
else
|
35
|
+
type
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def type_str
|
40
|
+
@type_str ||= source.delete_prefix(":").lstrip
|
41
|
+
end
|
42
|
+
|
43
|
+
def type_location
|
44
|
+
offset = source.size - type_str.size
|
45
|
+
RBS::Location.new(location.buffer, location.start_pos + offset, location.end_pos)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.parse(location)
|
49
|
+
if location.source =~/\A:\s*(.+)/
|
50
|
+
TypeAssertion.new(location)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -4,12 +4,13 @@ module Steep
|
|
4
4
|
module Helper
|
5
5
|
module ChildrenLevel
|
6
6
|
def level_of_children(children)
|
7
|
-
children.map(&:level)
|
8
|
-
|
7
|
+
levels = children.map(&:level)
|
8
|
+
children.map(&:level).sort {|a, b| (b.size <=> a.size) || 0 }.inject() do |a, b|
|
9
|
+
a.zip(b).map do |x, y|
|
9
10
|
if x && y
|
10
11
|
x + y
|
11
12
|
else
|
12
|
-
x || y
|
13
|
+
x || y || raise
|
13
14
|
end
|
14
15
|
end
|
15
16
|
end || []
|
@@ -41,11 +41,13 @@ module Steep
|
|
41
41
|
severity = severity_for(diagnostic)
|
42
42
|
|
43
43
|
if severity
|
44
|
+
range = diagnostic.location&.as_lsp_range or raise
|
45
|
+
|
44
46
|
LSP::Interface::Diagnostic.new(
|
45
47
|
message: diagnostic.full_message,
|
46
48
|
code: diagnostic.diagnostic_code,
|
47
49
|
severity: severity,
|
48
|
-
range:
|
50
|
+
range: range
|
49
51
|
).to_hash
|
50
52
|
end
|
51
53
|
end
|
@@ -773,6 +773,65 @@ module Steep
|
|
773
773
|
end
|
774
774
|
end
|
775
775
|
|
776
|
+
class FalseAssertion < Base
|
777
|
+
attr_reader :node, :assertion_type, :node_type
|
778
|
+
|
779
|
+
def initialize(node:, assertion_type:, node_type:)
|
780
|
+
super(node: node)
|
781
|
+
@assertion_type = assertion_type
|
782
|
+
@node_type = node_type
|
783
|
+
end
|
784
|
+
|
785
|
+
def header_line
|
786
|
+
"Assertion cannot hold: no relationship between infered type (`#{node_type.to_s}`) and asserted type (`#{assertion_type.to_s}`)"
|
787
|
+
end
|
788
|
+
end
|
789
|
+
|
790
|
+
class UnexpectedTypeArgument < Base
|
791
|
+
attr_reader :type_arg, :method_type
|
792
|
+
|
793
|
+
def initialize(type_arg:, method_type:)
|
794
|
+
super(node: nil, location: type_arg.location)
|
795
|
+
@type_arg = type_arg
|
796
|
+
@method_type = method_type
|
797
|
+
end
|
798
|
+
|
799
|
+
def header_line
|
800
|
+
"Unexpected type arg is given to method type `#{method_type.to_s}`"
|
801
|
+
end
|
802
|
+
end
|
803
|
+
|
804
|
+
class InsufficientTypeArgument < Base
|
805
|
+
attr_reader :type_args, :method_type
|
806
|
+
|
807
|
+
def initialize(node:, type_args:, method_type:)
|
808
|
+
super(node: node)
|
809
|
+
@type_args = type_args
|
810
|
+
@method_type = method_type
|
811
|
+
end
|
812
|
+
|
813
|
+
def header_line
|
814
|
+
"Requires #{method_type.type_params.size} types, but #{type_args.size} given: `#{method_type.to_s}`"
|
815
|
+
end
|
816
|
+
end
|
817
|
+
|
818
|
+
class TypeArgumentMismatchError < Base
|
819
|
+
attr_reader :type_argument, :type_parameter, :result
|
820
|
+
|
821
|
+
def initialize(type_arg:, type_param:, result:)
|
822
|
+
super(node: nil, location: type_arg.location)
|
823
|
+
@type_argument = type_arg
|
824
|
+
@type_parameter = type_param
|
825
|
+
@result = result
|
826
|
+
end
|
827
|
+
|
828
|
+
include ResultPrinter
|
829
|
+
|
830
|
+
def header_line
|
831
|
+
"Cannot pass a type `#{type_argument}` as a type parameter `#{type_parameter.to_s}`"
|
832
|
+
end
|
833
|
+
end
|
834
|
+
|
776
835
|
ALL = ObjectSpace.each_object(Class).with_object([]) do |klass, array|
|
777
836
|
if klass < Base
|
778
837
|
array << klass
|
@@ -781,24 +840,29 @@ module Steep
|
|
781
840
|
|
782
841
|
def self.all_error
|
783
842
|
@all_error ||= ALL.each.with_object({}) do |klass, hash|
|
843
|
+
# @type var hash: Hash[singleton(Base), LSPFormatter::severity]
|
784
844
|
hash[klass] = LSPFormatter::ERROR
|
785
845
|
end.freeze
|
786
846
|
end
|
787
847
|
|
788
848
|
def self.default
|
789
|
-
@default ||= all_error.merge(
|
849
|
+
@default ||= _ = all_error.merge(
|
790
850
|
{
|
791
851
|
ImplicitBreakValueMismatch => :warning,
|
792
852
|
FallbackAny => :information,
|
793
853
|
ElseOnExhaustiveCase => :warning,
|
794
854
|
UnknownConstant => :warning,
|
795
|
-
MethodDefinitionMissing => :information
|
855
|
+
MethodDefinitionMissing => :information,
|
856
|
+
FalseAssertion => :information,
|
857
|
+
UnexpectedTypeArgument => :information,
|
858
|
+
InsufficientTypeArgument => :information,
|
859
|
+
UnexpectedTypeArgument => :information
|
796
860
|
}
|
797
861
|
).freeze
|
798
862
|
end
|
799
863
|
|
800
864
|
def self.strict
|
801
|
-
@strict ||= all_error.merge(
|
865
|
+
@strict ||= _ = all_error.merge(
|
802
866
|
{
|
803
867
|
NoMethod => nil,
|
804
868
|
ImplicitBreakValueMismatch => nil,
|
@@ -811,7 +875,7 @@ module Steep
|
|
811
875
|
end
|
812
876
|
|
813
877
|
def self.lenient
|
814
|
-
@lenient ||= all_error.merge(
|
878
|
+
@lenient ||= _ = all_error.merge(
|
815
879
|
{
|
816
880
|
NoMethod => nil,
|
817
881
|
ImplicitBreakValueMismatch => nil,
|
@@ -819,7 +883,8 @@ module Steep
|
|
819
883
|
ElseOnExhaustiveCase => nil,
|
820
884
|
UnknownConstant => nil,
|
821
885
|
MethodDefinitionMissing => nil,
|
822
|
-
UnexpectedJump => nil
|
886
|
+
UnexpectedJump => nil,
|
887
|
+
FalseAssertion => :hint
|
823
888
|
}
|
824
889
|
).freeze
|
825
890
|
end
|