steep 0.50.0 → 0.52.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +13 -6
- data/.github/workflows/ruby.yml +3 -1
- data/CHANGELOG.md +20 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +9 -6
- data/lib/steep/ast/annotation/collection.rb +10 -8
- data/lib/steep/ast/types/factory.rb +7 -6
- data/lib/steep/cli.rb +87 -1
- data/lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb +28 -0
- data/lib/steep/diagnostic/ruby.rb +21 -15
- data/lib/steep/index/source_index.rb +18 -1
- data/lib/steep/module_helper.rb +4 -7
- data/lib/steep/server/interaction_worker.rb +32 -135
- data/lib/steep/server/lsp_formatter.rb +234 -0
- data/lib/steep/server/master.rb +1 -1
- data/lib/steep/services/completion_provider.rb +109 -1
- data/lib/steep/services/goto_service.rb +4 -6
- data/lib/steep/services/hover_provider/rbs.rb +63 -0
- data/lib/steep/services/hover_provider/ruby.rb +168 -0
- data/lib/steep/services/hover_provider/singleton_methods.rb +21 -0
- data/lib/steep/services/type_check_service.rb +6 -3
- data/lib/steep/source.rb +71 -18
- data/lib/steep/subtyping/check.rb +2 -2
- data/lib/steep/type_construction.rb +183 -148
- data/lib/steep/type_inference/constant_env.rb +33 -15
- data/lib/steep/type_inference/context.rb +10 -7
- data/lib/steep/type_inference/type_env.rb +16 -54
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +11 -8
- data/smoke/const/test_expectations.yml +24 -19
- data/smoke/diagnostics/test_expectations.yml +77 -17
- data/smoke/integer/test_expectations.yml +24 -4
- data/smoke/method/test_expectations.yml +30 -0
- data/smoke/regression/test_expectations.yml +24 -0
- data/smoke/yield/test_expectations.yml +20 -0
- data/steep.gemspec +1 -1
- metadata +9 -5
- data/lib/steep/services/hover_content.rb +0 -206
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c373c6a4366397b2b014850a8993ce6d8a0c27bcdd8bc8c5135bb64b4132b162
|
4
|
+
data.tar.gz: '097245d5e3745ceb634a2f2bcd007cca0c549449c835b644feb62c23c3c6e3ed'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eadc49c7c81bce14e4e4c5f9adbcb0411669cd1f78eb290029953e26ea3997d15a65db53329124812e841f3fbe486d30f25bbf89d7bce74d528692176250c795
|
7
|
+
data.tar.gz: 3257fa14e2888e68afd6266e1c1d28dc95b8ef7e1ec499393994f35cb715abfc133f005d0ce79962fc6642f7fdeb0b28c35fa0d3bb5687972ea1b31d0a9d6c38
|
data/.github/dependabot.yml
CHANGED
@@ -1,8 +1,15 @@
|
|
1
1
|
version: 2
|
2
|
+
|
2
3
|
updates:
|
3
|
-
- package-ecosystem: bundler
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
- package-ecosystem: bundler
|
5
|
+
directory: "/"
|
6
|
+
schedule:
|
7
|
+
interval: daily
|
8
|
+
time: "20:00"
|
9
|
+
open-pull-requests-limit: 10
|
10
|
+
|
11
|
+
- package-ecosystem: "github-actions"
|
12
|
+
directory: "/"
|
13
|
+
schedule:
|
14
|
+
# Check for updates to GitHub Actions every weekday
|
15
|
+
interval: "daily"
|
data/.github/workflows/ruby.yml
CHANGED
@@ -14,6 +14,7 @@ jobs:
|
|
14
14
|
container_tag:
|
15
15
|
- "2.7"
|
16
16
|
- "3.0"
|
17
|
+
- "3.1"
|
17
18
|
- "master-nightly-focal"
|
18
19
|
task:
|
19
20
|
- test
|
@@ -22,9 +23,10 @@ jobs:
|
|
22
23
|
container:
|
23
24
|
image: rubylang/ruby:${{ matrix.container_tag }}
|
24
25
|
steps:
|
25
|
-
- uses: actions/checkout@
|
26
|
+
- uses: actions/checkout@v3
|
26
27
|
- name: Run test
|
27
28
|
run: |
|
29
|
+
git config --global --add safe.directory /__w/steep/steep
|
28
30
|
ruby -v
|
29
31
|
gem install bundler
|
30
32
|
bundle install --jobs 4 --retry 3
|
data/CHANGELOG.md
CHANGED
@@ -2,7 +2,26 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
-
|
5
|
+
## 0.52.1 (2022-04-25)
|
6
|
+
|
7
|
+
* Better union type inference (it type checks `Array#filter_map` now!) ([\#531](https://github.com/soutaro/steep/pull/531))
|
8
|
+
* Improve method call hover message ([\#537](https://github.com/soutaro/steep/pull/537), [\#538](https://github.com/soutaro/steep/pull/538))
|
9
|
+
* Make `NilClass#!` a special method to improve flow-sensitive typing ([\#539](https://github.com/soutaro/steep/pull/539))
|
10
|
+
* Fix `steep binstub` ([\#540](https://github.com/soutaro/steep/pull/540), [\#541](https://github.com/soutaro/steep/pull/541))
|
11
|
+
|
12
|
+
## 0.52.0 (2022-04-05)
|
13
|
+
|
14
|
+
* Add `steep binstub` command ([\#527](https://github.com/soutaro/steep/pull/527))
|
15
|
+
* Let hover and completion work in heredoc ([\#528](https://github.com/soutaro/steep/pull/528))
|
16
|
+
* Better constant typing ([\#529](https://github.com/soutaro/steep/pull/529))
|
17
|
+
|
18
|
+
## 0.51.0 (2022-04-01)
|
19
|
+
|
20
|
+
* Completion for constant ([\#524](https://github.com/soutaro/steep/pull/524))
|
21
|
+
* Better hover/completion message ([\#525](https://github.com/soutaro/steep/pull/525))
|
22
|
+
* Show available commands when using `--help` ([\#523](https://github.com/soutaro/steep/pull/523))
|
23
|
+
|
24
|
+
## 0.50.0 (2022-03-22)
|
6
25
|
|
7
26
|
* CLI option for override steep command at spawn worker ([\#511](https://github.com/soutaro/steep/pull/511))
|
8
27
|
* LSP related improvements for Sublime LSP ([\#513](https://github.com/soutaro/steep/pull/513))
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
steep (0.
|
4
|
+
steep (0.52.1)
|
5
5
|
activesupport (>= 5.1)
|
6
6
|
language_server-protocol (>= 3.15, < 4.0)
|
7
7
|
listen (~> 3.0)
|
8
8
|
parallel (>= 1.0.0)
|
9
9
|
parser (>= 3.0)
|
10
10
|
rainbow (>= 2.2.2, < 4.0)
|
11
|
-
rbs (>= 2.2
|
11
|
+
rbs (>= 2.3.2)
|
12
12
|
terminal-table (>= 2, < 4)
|
13
13
|
|
14
14
|
PATH
|
@@ -30,7 +30,7 @@ GEM
|
|
30
30
|
minitest (>= 5.1)
|
31
31
|
tzinfo (~> 2.0)
|
32
32
|
ast (2.4.2)
|
33
|
-
concurrent-ruby (1.1.
|
33
|
+
concurrent-ruby (1.1.10)
|
34
34
|
ffi (1.15.5)
|
35
35
|
i18n (1.10.0)
|
36
36
|
concurrent-ruby (~> 1.0)
|
@@ -41,15 +41,17 @@ GEM
|
|
41
41
|
minitest (5.15.0)
|
42
42
|
minitest-hooks (1.5.0)
|
43
43
|
minitest (> 5.3)
|
44
|
-
|
45
|
-
|
44
|
+
minitest-slow_test (0.2.0)
|
45
|
+
minitest (>= 5.0)
|
46
|
+
parallel (1.22.1)
|
47
|
+
parser (3.1.2.0)
|
46
48
|
ast (~> 2.4.1)
|
47
49
|
rainbow (3.1.1)
|
48
50
|
rake (13.0.6)
|
49
51
|
rb-fsevent (0.11.1)
|
50
52
|
rb-inotify (0.10.1)
|
51
53
|
ffi (~> 1.0)
|
52
|
-
rbs (2.
|
54
|
+
rbs (2.3.2)
|
53
55
|
stackprof (0.2.19)
|
54
56
|
terminal-table (3.0.2)
|
55
57
|
unicode-display_width (>= 1.1.1, < 3)
|
@@ -63,6 +65,7 @@ PLATFORMS
|
|
63
65
|
DEPENDENCIES
|
64
66
|
minitest (~> 5.15)
|
65
67
|
minitest-hooks
|
68
|
+
minitest-slow_test
|
66
69
|
rake
|
67
70
|
stackprof
|
68
71
|
steep!
|
@@ -4,7 +4,7 @@ module Steep
|
|
4
4
|
class Collection
|
5
5
|
attr_reader :annotations
|
6
6
|
attr_reader :factory
|
7
|
-
attr_reader :
|
7
|
+
attr_reader :context
|
8
8
|
|
9
9
|
attr_reader :var_type_annotations
|
10
10
|
attr_reader :const_type_annotations
|
@@ -19,10 +19,10 @@ module Steep
|
|
19
19
|
attr_reader :dynamic_annotations
|
20
20
|
attr_reader :break_type_annotation
|
21
21
|
|
22
|
-
def initialize(annotations:, factory:,
|
22
|
+
def initialize(annotations:, factory:, context:)
|
23
23
|
@annotations = annotations
|
24
24
|
@factory = factory
|
25
|
-
@
|
25
|
+
@context = context
|
26
26
|
|
27
27
|
@var_type_annotations = {}
|
28
28
|
@method_type_annotations = {}
|
@@ -64,7 +64,7 @@ module Steep
|
|
64
64
|
|
65
65
|
def absolute_type(type)
|
66
66
|
if type
|
67
|
-
factory.absolute_type(type,
|
67
|
+
factory.absolute_type(type, context: context)
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
@@ -140,7 +140,7 @@ module Steep
|
|
140
140
|
end
|
141
141
|
|
142
142
|
def merge_block_annotations(annotations)
|
143
|
-
if annotations.
|
143
|
+
if annotations.context != context || annotations.factory != factory
|
144
144
|
raise "Cannot merge another annotation: self=#{self}, other=#{annotations}"
|
145
145
|
end
|
146
146
|
|
@@ -148,9 +148,11 @@ module Steep
|
|
148
148
|
annotation.is_a?(BlockType) || annotation.is_a?(BreakType)
|
149
149
|
end
|
150
150
|
|
151
|
-
self.class.new(
|
152
|
-
|
153
|
-
|
151
|
+
self.class.new(
|
152
|
+
annotations: retained_annotations + annotations.annotations,
|
153
|
+
factory: factory,
|
154
|
+
context: context
|
155
|
+
)
|
154
156
|
end
|
155
157
|
|
156
158
|
def any?(&block)
|
@@ -18,7 +18,7 @@ module Steep
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def type_name_resolver
|
21
|
-
@type_name_resolver ||= RBS::TypeNameResolver.
|
21
|
+
@type_name_resolver ||= RBS::Resolver::TypeNameResolver.new(definition_builder.env)
|
22
22
|
end
|
23
23
|
|
24
24
|
def type_opt(type)
|
@@ -431,7 +431,8 @@ module Steep
|
|
431
431
|
case defined_in
|
432
432
|
when RBS::BuiltinNames::BasicObject.name,
|
433
433
|
RBS::BuiltinNames::TrueClass.name,
|
434
|
-
RBS::BuiltinNames::FalseClass.name
|
434
|
+
RBS::BuiltinNames::FalseClass.name,
|
435
|
+
AST::Builtin::NilClass.module_name
|
435
436
|
return method_type.with(
|
436
437
|
type: method_type.type.with(
|
437
438
|
return_type: AST::Types::Logic::Not.new(location: method_type.type.return_type.location)
|
@@ -810,15 +811,15 @@ module Steep
|
|
810
811
|
@env ||= definition_builder.env
|
811
812
|
end
|
812
813
|
|
813
|
-
def absolute_type(type,
|
814
|
+
def absolute_type(type, context:)
|
814
815
|
absolute_type = type_1(type).map_type_name do |name|
|
815
|
-
absolute_type_name(name,
|
816
|
+
absolute_type_name(name, context: context) || name.absolute!
|
816
817
|
end
|
817
818
|
type(absolute_type)
|
818
819
|
end
|
819
820
|
|
820
|
-
def absolute_type_name(type_name,
|
821
|
-
type_name_resolver.resolve(type_name, context:
|
821
|
+
def absolute_type_name(type_name, context:)
|
822
|
+
type_name_resolver.resolve(type_name, context: context)
|
822
823
|
end
|
823
824
|
|
824
825
|
def instance_type(type_name, args: nil, location: nil)
|
data/lib/steep/cli.rb
CHANGED
@@ -18,11 +18,19 @@ module Steep
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.available_commands
|
21
|
-
[:init, :check, :validate, :annotations, :version, :project, :watch, :langserver, :stats]
|
21
|
+
[:init, :check, :validate, :annotations, :version, :project, :watch, :langserver, :stats, :binstub]
|
22
22
|
end
|
23
23
|
|
24
24
|
def process_global_options
|
25
25
|
OptionParser.new do |opts|
|
26
|
+
opts.banner = <<~USAGE
|
27
|
+
Usage: steep [options]
|
28
|
+
|
29
|
+
available commands: #{CLI.available_commands.join(', ')}
|
30
|
+
|
31
|
+
Options:
|
32
|
+
USAGE
|
33
|
+
|
26
34
|
opts.on("--version") do
|
27
35
|
process_version
|
28
36
|
exit 0
|
@@ -200,6 +208,84 @@ module Steep
|
|
200
208
|
end.run
|
201
209
|
end
|
202
210
|
|
211
|
+
def process_binstub
|
212
|
+
path = Pathname("bin/steep")
|
213
|
+
root_path = Pathname.pwd
|
214
|
+
force = false
|
215
|
+
|
216
|
+
OptionParser.new do |opts|
|
217
|
+
opts.banner = <<BANNER
|
218
|
+
Usage: steep binstub [options]
|
219
|
+
|
220
|
+
Generate a binstub to execute Steep with setting up Bundler and rbenv/rvm.
|
221
|
+
Use the executable for LSP integration setup.
|
222
|
+
|
223
|
+
Options:
|
224
|
+
BANNER
|
225
|
+
handle_logging_options opts
|
226
|
+
|
227
|
+
opts.on("-o PATH", "--output=PATH", "The path of the executable file (defaults to `bin/steep`)") do |v|
|
228
|
+
path = Pathname(v)
|
229
|
+
end
|
230
|
+
|
231
|
+
opts.on("--root=PATH", "The repository root path (defaults to `.`)") do |v|
|
232
|
+
root_path = (Pathname.pwd + v).cleanpath
|
233
|
+
end
|
234
|
+
|
235
|
+
opts.on("--[no-]force", "Overwrite file (defaults to false)") do
|
236
|
+
force = true
|
237
|
+
end
|
238
|
+
end.parse!(argv)
|
239
|
+
|
240
|
+
binstub_path = (Pathname.pwd + path).cleanpath
|
241
|
+
bindir_path = binstub_path.parent
|
242
|
+
|
243
|
+
bindir_path.mkpath
|
244
|
+
|
245
|
+
gemfile_path =
|
246
|
+
if defined?(Bundler)
|
247
|
+
Bundler.default_gemfile.relative_path_from(bindir_path)
|
248
|
+
else
|
249
|
+
Pathname("../Gemfile")
|
250
|
+
end
|
251
|
+
|
252
|
+
if binstub_path.file?
|
253
|
+
if force
|
254
|
+
stdout.puts Rainbow("#{path} already exists. Overwriting...").yellow
|
255
|
+
else
|
256
|
+
stdout.puts Rainbow(''"⚠️ #{path} already exists. Bye! 👋").red
|
257
|
+
return 0
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
template = <<TEMPLATE
|
262
|
+
#!/usr/bin/env bash
|
263
|
+
|
264
|
+
BINSTUB_DIR=$(cd $(dirname $0); pwd)
|
265
|
+
GEMFILE=$(readlink -f ${BINSTUB_DIR}/#{gemfile_path})
|
266
|
+
ROOT_DIR=$(readlink -f ${BINSTUB_DIR}/#{root_path.relative_path_from(bindir_path)})
|
267
|
+
|
268
|
+
STEEP="bundle exec --gemfile=${GEMFILE} steep"
|
269
|
+
|
270
|
+
if type "rbenv" > /dev/null 2>&1; then
|
271
|
+
STEEP="rbenv exec ${STEEP}"
|
272
|
+
else
|
273
|
+
if type "rvm" > /dev/null 2>&1; then
|
274
|
+
STEEP="rvm ${ROOT_DIR} do ${STEEP}"
|
275
|
+
fi
|
276
|
+
fi
|
277
|
+
|
278
|
+
exec $STEEP $@
|
279
|
+
TEMPLATE
|
280
|
+
|
281
|
+
binstub_path.write(template)
|
282
|
+
binstub_path.chmod(0755)
|
283
|
+
|
284
|
+
stdout.puts Rainbow("Successfully generated executable #{path} 🎉").blue
|
285
|
+
|
286
|
+
0
|
287
|
+
end
|
288
|
+
|
203
289
|
def process_version
|
204
290
|
stdout.puts Steep::VERSION
|
205
291
|
0
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Steep.logger.error "Diagnostic `Ruby::UnknownConstantAssigned` is deprecated. Use `Ruby::UnknownConstant` instead."
|
2
|
+
|
3
|
+
module Steep
|
4
|
+
module Diagnostic
|
5
|
+
module Ruby
|
6
|
+
class UnknownConstantAssigned < Base
|
7
|
+
attr_reader :context
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
def initialize(node:, context:, name:)
|
11
|
+
const = node.children[0]
|
12
|
+
loc = if const
|
13
|
+
const.loc.expression.join(node.loc.name)
|
14
|
+
else
|
15
|
+
node.loc.name
|
16
|
+
end
|
17
|
+
super(node: node, location: loc)
|
18
|
+
@context = context
|
19
|
+
@name = name
|
20
|
+
end
|
21
|
+
|
22
|
+
def header_line
|
23
|
+
"Cannot find the declaration of constant `#{name}`"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -551,27 +551,33 @@ module Steep
|
|
551
551
|
end
|
552
552
|
end
|
553
553
|
|
554
|
-
class
|
555
|
-
attr_reader :context
|
554
|
+
class UnknownConstant < Base
|
556
555
|
attr_reader :name
|
556
|
+
attr_reader :kind
|
557
557
|
|
558
|
-
def initialize(node:,
|
559
|
-
|
560
|
-
loc = if const
|
561
|
-
const.loc.expression.join(node.loc.name)
|
562
|
-
else
|
563
|
-
node.loc.name
|
564
|
-
end
|
565
|
-
super(node: node, location: loc)
|
566
|
-
@context = context
|
558
|
+
def initialize(node:, name:)
|
559
|
+
super(node: node, location: node.loc.name)
|
567
560
|
@name = name
|
561
|
+
@kind = :constant
|
562
|
+
end
|
563
|
+
|
564
|
+
def class!
|
565
|
+
@kind = :class
|
566
|
+
self
|
567
|
+
end
|
568
|
+
|
569
|
+
def module!
|
570
|
+
@kind = :module
|
571
|
+
self
|
568
572
|
end
|
569
573
|
|
570
574
|
def header_line
|
571
|
-
"Cannot find the declaration of
|
575
|
+
"Cannot find the declaration of #{kind}: `#{name}`"
|
572
576
|
end
|
573
577
|
end
|
574
578
|
|
579
|
+
autoload :UnknownConstantAssigned, "steep/diagnostic/deprecated/unknown_constant_assigned"
|
580
|
+
|
575
581
|
class FallbackAny < Base
|
576
582
|
def initialize(node:)
|
577
583
|
super(node: node)
|
@@ -744,7 +750,7 @@ module Steep
|
|
744
750
|
ImplicitBreakValueMismatch => :warning,
|
745
751
|
FallbackAny => :information,
|
746
752
|
ElseOnExhaustiveCase => :warning,
|
747
|
-
|
753
|
+
UnknownConstant => :warning,
|
748
754
|
MethodDefinitionMissing => :information
|
749
755
|
}
|
750
756
|
).freeze
|
@@ -757,7 +763,7 @@ module Steep
|
|
757
763
|
ImplicitBreakValueMismatch => nil,
|
758
764
|
FallbackAny => nil,
|
759
765
|
ElseOnExhaustiveCase => nil,
|
760
|
-
|
766
|
+
UnknownConstant => nil,
|
761
767
|
MethodDefinitionMissing => nil
|
762
768
|
}
|
763
769
|
).freeze
|
@@ -770,7 +776,7 @@ module Steep
|
|
770
776
|
ImplicitBreakValueMismatch => nil,
|
771
777
|
FallbackAny => nil,
|
772
778
|
ElseOnExhaustiveCase => nil,
|
773
|
-
|
779
|
+
UnknownConstant => nil,
|
774
780
|
MethodDefinitionMissing => nil,
|
775
781
|
UnexpectedJump => nil
|
776
782
|
}
|
@@ -16,7 +16,7 @@ module Steep
|
|
16
16
|
|
17
17
|
def add_definition(node)
|
18
18
|
case node.type
|
19
|
-
when :casgn, :
|
19
|
+
when :casgn, :const
|
20
20
|
@definitions << node
|
21
21
|
else
|
22
22
|
raise "Unexpected constant definition: #{node.type}"
|
@@ -145,6 +145,23 @@ module Steep
|
|
145
145
|
raise
|
146
146
|
end
|
147
147
|
end
|
148
|
+
|
149
|
+
def reference(constant_node: nil)
|
150
|
+
case
|
151
|
+
when constant_node
|
152
|
+
constant_index.each do |name, entry|
|
153
|
+
if entry.references.include?(constant_node)
|
154
|
+
return name
|
155
|
+
end
|
156
|
+
|
157
|
+
if entry.definitions.include?(constant_node)
|
158
|
+
return name
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
nil
|
163
|
+
end
|
164
|
+
end
|
148
165
|
end
|
149
166
|
end
|
150
167
|
end
|
data/lib/steep/module_helper.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
1
|
module Steep
|
2
2
|
module ModuleHelper
|
3
|
-
def module_name_from_node(
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
name = node.children[1]
|
8
|
-
RBS::TypeName.new(name: name, namespace: namespace)
|
9
|
-
end
|
3
|
+
def module_name_from_node(parent_node, constant_name)
|
4
|
+
namespace = namespace_from_node(parent_node) or return
|
5
|
+
name = constant_name
|
6
|
+
RBS::TypeName.new(name: name, namespace: namespace)
|
10
7
|
end
|
11
8
|
|
12
9
|
def namespace_from_node(node)
|