steep 1.9.0.dev.1 → 1.9.0.dev.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Steepfile +35 -12
- data/bin/rbs-inline +19 -0
- data/lib/steep/cli.rb +1 -10
- data/lib/steep/diagnostic/ruby.rb +10 -0
- data/lib/steep/drivers/check.rb +5 -9
- data/lib/steep/drivers/utils/driver_helper.rb +34 -3
- data/lib/steep/project/pattern.rb +4 -0
- data/lib/steep/server/custom_methods.rb +16 -0
- data/lib/steep/server/master.rb +36 -1
- data/lib/steep/server/type_check_controller.rb +44 -0
- data/lib/steep/type_construction.rb +11 -2
- data/lib/steep/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89c207623c288c2142cdcf7d7de7f404da4d160b5bc40c84210116a721ec4029
|
4
|
+
data.tar.gz: dfd95e726115676f4d293d312bd1f06afa6ea89336911e9887c8e4b5ee1167ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9800ef17d4108ff391642510701e12a0ec4e63035c74765ed1203fa9b62d964be10441d60890ab3c643dc8d0295dd2a68be5285126307f3cb401f517eaa799f
|
7
|
+
data.tar.gz: 3ef2c5d7bac4dd2d492df8e5c60322de6c06d9c33cec21e2a97e4608f235e41729f0383e0817cfd324213853cad4c34308b14f5a582eedda71d36828545d6840
|
data/Steepfile
CHANGED
@@ -1,28 +1,51 @@
|
|
1
1
|
D = Steep::Diagnostic
|
2
2
|
|
3
|
+
FileUtils.mkpath("tmp")
|
4
|
+
tmp_rbs_dir = Pathname("tmp/rbs-sig")
|
5
|
+
|
6
|
+
definition = Bundler::Definition.build(Pathname("Gemfile"), Pathname("Gemfile.lock"), nil)
|
7
|
+
rbs_dep = definition.dependencies.find {|dep| dep.name == "rbs" }
|
8
|
+
if (source = rbs_dep&.source).is_a?(Bundler::Source::Path)
|
9
|
+
unless tmp_rbs_dir.directory?
|
10
|
+
FileUtils.ln_s(Pathname.pwd + source.path + "sig", tmp_rbs_dir.to_s, force: true)
|
11
|
+
end
|
12
|
+
else
|
13
|
+
FileUtils.rm_f(tmp_rbs_dir)
|
14
|
+
library "rbs"
|
15
|
+
end
|
16
|
+
|
3
17
|
target :app do
|
18
|
+
collection_config "rbs_collection.steep.yaml"
|
19
|
+
|
4
20
|
check "lib"
|
5
21
|
ignore "lib/steep/shims"
|
6
22
|
|
7
23
|
signature "sig"
|
8
|
-
|
9
|
-
collection_config "rbs_collection.steep.yaml"
|
24
|
+
ignore_signature "sig/test"
|
10
25
|
|
11
26
|
configure_code_diagnostics(D::Ruby.strict) do |hash|
|
12
27
|
end
|
13
28
|
|
14
|
-
|
15
|
-
|
29
|
+
if tmp_rbs_dir.directory?
|
30
|
+
signature tmp_rbs_dir.to_s
|
31
|
+
else
|
32
|
+
library "rbs"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
target :test do
|
37
|
+
collection_config "rbs_collection.steep.yaml"
|
38
|
+
|
39
|
+
unreferenced!
|
40
|
+
|
41
|
+
check "test"
|
42
|
+
signature "sig/test"
|
43
|
+
|
44
|
+
configure_code_diagnostics(D::Ruby.lenient)
|
16
45
|
|
17
|
-
|
18
|
-
|
19
|
-
if (source = rbs_dep&.source).is_a?(Bundler::Source::Path)
|
20
|
-
unless Pathname(tmp_rbs_dir).exist?
|
21
|
-
FileUtils.ln_s(Pathname.pwd + source.path + "sig", tmp_rbs_dir, force: true)
|
22
|
-
end
|
23
|
-
signature tmp_rbs_dir
|
46
|
+
if tmp_rbs_dir.directory?
|
47
|
+
signature tmp_rbs_dir.to_s
|
24
48
|
else
|
25
|
-
FileUtils.rm_f(tmp_rbs_dir)
|
26
49
|
library "rbs"
|
27
50
|
end
|
28
51
|
end
|
data/bin/rbs-inline
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
BINSTUB_DIR=$(cd $(dirname $0); pwd)
|
4
|
+
GEMFILE=$(readlink -f ${BINSTUB_DIR}/../gemfile_steep/Gemfile)
|
5
|
+
ROOT_DIR=$(readlink -f ${BINSTUB_DIR}/..)
|
6
|
+
|
7
|
+
RBSINLINE="bundle exec --gemfile=${GEMFILE} rbs-inline"
|
8
|
+
|
9
|
+
if type "rbenv" > /dev/null 2>&1; then
|
10
|
+
RBSINLINE="rbenv exec ${RBSINLINE}"
|
11
|
+
else
|
12
|
+
if type "rvm" > /dev/null 2>&1; then
|
13
|
+
if [ -e ${ROOT_DIR}/.ruby-version ]; then
|
14
|
+
RBS="rvm ${ROOT_DIR} do ${RBSINLINE}"
|
15
|
+
fi
|
16
|
+
fi
|
17
|
+
fi
|
18
|
+
|
19
|
+
exec $RBSINLINE $@
|
data/lib/steep/cli.rb
CHANGED
@@ -138,31 +138,22 @@ module Steep
|
|
138
138
|
command.type_check_code = v ? true : false
|
139
139
|
end
|
140
140
|
|
141
|
-
opts.on("--validate=OPTION", ["skip", "group", "
|
141
|
+
opts.on("--validate=OPTION", ["skip", "group", "project", "library"], "Validation levels of signatures (default: group, options: skip,group,project,library)") do |level|
|
142
142
|
case level
|
143
143
|
when "skip"
|
144
144
|
command.validate_group_signatures = false
|
145
|
-
command.validate_target_signatures = false
|
146
145
|
command.validate_project_signatures = false
|
147
146
|
command.validate_library_signatures = false
|
148
147
|
when "group"
|
149
148
|
command.validate_group_signatures = true
|
150
|
-
command.validate_target_signatures = false
|
151
|
-
command.validate_project_signatures = false
|
152
|
-
command.validate_library_signatures = false
|
153
|
-
when "target"
|
154
|
-
command.validate_group_signatures = true
|
155
|
-
command.validate_target_signatures = true
|
156
149
|
command.validate_project_signatures = false
|
157
150
|
command.validate_library_signatures = false
|
158
151
|
when "project"
|
159
152
|
command.validate_group_signatures = true
|
160
|
-
command.validate_target_signatures = true
|
161
153
|
command.validate_project_signatures = true
|
162
154
|
command.validate_library_signatures = false
|
163
155
|
when "library"
|
164
156
|
command.validate_group_signatures = true
|
165
|
-
command.validate_target_signatures = true
|
166
157
|
command.validate_project_signatures = true
|
167
158
|
command.validate_library_signatures = true
|
168
159
|
end
|
@@ -917,6 +917,13 @@ module Steep
|
|
917
917
|
end
|
918
918
|
end
|
919
919
|
|
920
|
+
class UnannotatedEmptyCollection < Base
|
921
|
+
def header_line
|
922
|
+
node or raise
|
923
|
+
"Empty #{node.type} doesn't have type annotation"
|
924
|
+
end
|
925
|
+
end
|
926
|
+
|
920
927
|
ALL = ObjectSpace.each_object(Class).with_object([]) do |klass, array|
|
921
928
|
if klass < Base
|
922
929
|
array << klass
|
@@ -963,6 +970,7 @@ module Steep
|
|
963
970
|
SetterReturnTypeMismatch => :information,
|
964
971
|
SyntaxError => :hint,
|
965
972
|
TypeArgumentMismatchError => :hint,
|
973
|
+
UnannotatedEmptyCollection => :warning,
|
966
974
|
UnexpectedBlockGiven => :warning,
|
967
975
|
UnexpectedDynamicMethod => :hint,
|
968
976
|
UnexpectedError => :hint,
|
@@ -1019,6 +1027,7 @@ module Steep
|
|
1019
1027
|
SetterReturnTypeMismatch => :error,
|
1020
1028
|
SyntaxError => :hint,
|
1021
1029
|
TypeArgumentMismatchError => :error,
|
1030
|
+
UnannotatedEmptyCollection => :error,
|
1022
1031
|
UnexpectedBlockGiven => :error,
|
1023
1032
|
UnexpectedDynamicMethod => :information,
|
1024
1033
|
UnexpectedError => :information,
|
@@ -1075,6 +1084,7 @@ module Steep
|
|
1075
1084
|
SetterReturnTypeMismatch => nil,
|
1076
1085
|
SyntaxError => :hint,
|
1077
1086
|
TypeArgumentMismatchError => nil,
|
1087
|
+
UnannotatedEmptyCollection => :hint,
|
1078
1088
|
UnexpectedBlockGiven => :hint,
|
1079
1089
|
UnexpectedDynamicMethod => nil,
|
1080
1090
|
UnexpectedError => :hint,
|
data/lib/steep/drivers/check.rb
CHANGED
@@ -14,7 +14,6 @@ module Steep
|
|
14
14
|
attr_reader :active_group_names
|
15
15
|
attr_accessor :type_check_code
|
16
16
|
attr_accessor :validate_group_signatures
|
17
|
-
attr_accessor :validate_target_signatures
|
18
17
|
attr_accessor :validate_project_signatures
|
19
18
|
attr_accessor :validate_library_signatures
|
20
19
|
|
@@ -29,7 +28,6 @@ module Steep
|
|
29
28
|
@active_group_names = []
|
30
29
|
@type_check_code = true
|
31
30
|
@validate_group_signatures = true
|
32
|
-
@validate_target_signatures = false
|
33
31
|
@validate_project_signatures = false
|
34
32
|
@validate_library_signatures = false
|
35
33
|
end
|
@@ -217,19 +215,17 @@ module Steep
|
|
217
215
|
params[:signature_paths] << [target.name.to_s, target.project.absolute_path(path).to_s]
|
218
216
|
end
|
219
217
|
end
|
220
|
-
if validate_target_signatures
|
221
|
-
if group.is_a?(Project::Group)
|
222
|
-
files.each_target_signature_path(target, group) do |path|
|
223
|
-
params[:signature_paths] << [target.name.to_s, target.project.absolute_path(path).to_s]
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
218
|
if validate_project_signatures
|
228
219
|
files.each_project_signature_path(target) do |path|
|
229
220
|
if path_target = files.signature_path_target(path)
|
230
221
|
params[:signature_paths] << [path_target.name.to_s, target.project.absolute_path(path).to_s]
|
231
222
|
end
|
232
223
|
end
|
224
|
+
if group.is_a?(Project::Group)
|
225
|
+
files.each_target_signature_path(target, group) do |path|
|
226
|
+
params[:signature_paths] << [target.name.to_s, target.project.absolute_path(path).to_s]
|
227
|
+
end
|
228
|
+
end
|
233
229
|
end
|
234
230
|
if validate_library_signatures
|
235
231
|
files.each_library_path(target) do |path|
|
@@ -3,6 +3,7 @@ module Steep
|
|
3
3
|
module Utils
|
4
4
|
module DriverHelper
|
5
5
|
attr_accessor :steepfile
|
6
|
+
attr_accessor :disable_install_collection
|
6
7
|
|
7
8
|
def load_config(path: steepfile || Pathname("Steepfile"))
|
8
9
|
if path.file?
|
@@ -25,17 +26,47 @@ module Steep
|
|
25
26
|
case result = target.options.load_collection_lock
|
26
27
|
when nil, RBS::Collection::Config::Lockfile
|
27
28
|
# ok
|
28
|
-
|
29
|
+
when Pathname
|
30
|
+
# File is missing
|
29
31
|
if result == target.options.collection_config_path
|
30
|
-
|
32
|
+
# Config file is missing
|
33
|
+
Steep.ui_logger.error { "rbs-collection configuration is missing: `#{result}`" }
|
31
34
|
else
|
32
|
-
|
35
|
+
# Lockfile is missing
|
36
|
+
Steep.ui_logger.error { "Run `rbs collection install` to generate missing lockfile: `#{result}`" }
|
37
|
+
end
|
38
|
+
when YAML::SyntaxError
|
39
|
+
# File is broken
|
40
|
+
Steep.ui_logger.error { "rbs-collection setup is broken:\nsyntax error #{result.inspect}" }
|
41
|
+
when RBS::Collection::Config::CollectionNotAvailable
|
42
|
+
unless disable_install_collection
|
43
|
+
install_collection(target, target.options.collection_config_path || raise)
|
44
|
+
else
|
45
|
+
Steep.ui_logger.error { "Run `rbs collection install` to set up RBS files for gems" }
|
33
46
|
end
|
34
47
|
end
|
35
48
|
end
|
36
49
|
end
|
37
50
|
end
|
38
51
|
|
52
|
+
def install_collection(target, config_path)
|
53
|
+
Steep.ui_logger.info { "Installing RBS files for collection: #{config_path}" }
|
54
|
+
lockfile_path = RBS::Collection::Config.to_lockfile_path(config_path)
|
55
|
+
io = StringIO.new
|
56
|
+
begin
|
57
|
+
RBS::Collection::Installer.new(lockfile_path: lockfile_path, stdout: io).install_from_lockfile()
|
58
|
+
target.options.load_collection_lock(force: true)
|
59
|
+
Steep.ui_logger.debug { "Finished setting up RBS collection: " + io.string }
|
60
|
+
|
61
|
+
result = target.options.load_collection_lock(force: true)
|
62
|
+
unless result.is_a?(RBS::Collection::Config::Lockfile)
|
63
|
+
raise "Failed to set up RBS collection: #{result.inspect}"
|
64
|
+
end
|
65
|
+
rescue => exn
|
66
|
+
Steep.ui_logger.error { "Failed to set up RBS collection: #{exn.inspect}" }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
39
70
|
def request_id
|
40
71
|
SecureRandom.alphanumeric(10)
|
41
72
|
end
|
@@ -29,6 +29,14 @@ module Steep
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
module TypeCheckGroups
|
33
|
+
METHOD = "$/steep/typecheck/groups"
|
34
|
+
|
35
|
+
def self.notification(params)
|
36
|
+
{ method: METHOD, params: params }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
32
40
|
module TypeCheck__Start
|
33
41
|
METHOD = "$/steep/typecheck/start"
|
34
42
|
|
@@ -56,6 +64,14 @@ module Steep
|
|
56
64
|
{ id: id, result: result }
|
57
65
|
end
|
58
66
|
end
|
67
|
+
|
68
|
+
module Groups
|
69
|
+
METHOD = "$/steep/groups"
|
70
|
+
|
71
|
+
def self.response(id, result)
|
72
|
+
{ id: id, result: result }
|
73
|
+
end
|
74
|
+
end
|
59
75
|
end
|
60
76
|
end
|
61
77
|
end
|
data/lib/steep/server/master.rb
CHANGED
@@ -382,7 +382,11 @@ module Steep
|
|
382
382
|
declaration_provider: false,
|
383
383
|
implementation_provider: true,
|
384
384
|
type_definition_provider: true
|
385
|
-
)
|
385
|
+
),
|
386
|
+
server_info: {
|
387
|
+
name: "steep",
|
388
|
+
version: VERSION
|
389
|
+
}
|
386
390
|
)
|
387
391
|
}
|
388
392
|
)
|
@@ -657,6 +661,18 @@ module Steep
|
|
657
661
|
|
658
662
|
start_type_check(request: request, last_request: nil)
|
659
663
|
|
664
|
+
when CustomMethods::TypeCheckGroups::METHOD
|
665
|
+
params = message[:params] #: CustomMethods::TypeCheckGroups::params
|
666
|
+
|
667
|
+
groups = params.fetch(:groups)
|
668
|
+
|
669
|
+
progress = work_done_progress(SecureRandom.uuid)
|
670
|
+
progress.begin("Type checking #{groups.empty? ? "project" : groups.join(", ")}", request_id: fresh_request_id)
|
671
|
+
|
672
|
+
request = controller.make_group_request(groups, progress: progress)
|
673
|
+
request.needs_response = false
|
674
|
+
start_type_check(request: request, last_request: current_type_check_request, report_progress_threshold: 0)
|
675
|
+
|
660
676
|
when "$/ping"
|
661
677
|
enqueue_write_job SendMessageJob.to_client(
|
662
678
|
message: {
|
@@ -665,6 +681,25 @@ module Steep
|
|
665
681
|
}
|
666
682
|
)
|
667
683
|
|
684
|
+
when CustomMethods::Groups::METHOD
|
685
|
+
groups = [] #: Array[String]
|
686
|
+
|
687
|
+
project.targets.each do |target|
|
688
|
+
unless target.source_pattern.empty? && target.signature_pattern.empty?
|
689
|
+
groups << target.name.to_s
|
690
|
+
end
|
691
|
+
|
692
|
+
target.groups.each do |group|
|
693
|
+
unless group.source_pattern.empty? && group.signature_pattern.empty?
|
694
|
+
groups << "#{target.name}.#{group.name}"
|
695
|
+
end
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
699
|
+
enqueue_write_job(SendMessageJob.to_client(
|
700
|
+
message: CustomMethods::Groups.response(message[:id], groups)
|
701
|
+
))
|
702
|
+
|
668
703
|
when "shutdown"
|
669
704
|
start_type_checking_queue.cancel
|
670
705
|
|
@@ -254,6 +254,50 @@ module Steep
|
|
254
254
|
end
|
255
255
|
end
|
256
256
|
|
257
|
+
def make_group_request(groups, progress:)
|
258
|
+
TypeCheckController::Request.new(guid: progress.guid, progress: progress).tap do |request|
|
259
|
+
if groups.empty?
|
260
|
+
files.signature_paths.each do |path, target_group|
|
261
|
+
target_group = target_group.target if target_group.is_a?(Project::Group)
|
262
|
+
request.signature_paths << [target_group.name, path]
|
263
|
+
end
|
264
|
+
files.source_paths.each do |path, target_group|
|
265
|
+
target_group = target_group.target if target_group.is_a?(Project::Group)
|
266
|
+
request.code_paths << [target_group.name, path]
|
267
|
+
end
|
268
|
+
else
|
269
|
+
group_set = groups.map do |group_name|
|
270
|
+
target_name, group_name = group_name.split(".", 2)
|
271
|
+
target_name or raise
|
272
|
+
|
273
|
+
target_name = target_name.to_sym
|
274
|
+
group_name = group_name.to_sym if group_name
|
275
|
+
|
276
|
+
if group_name
|
277
|
+
if target = project.targets.find {|target| target.name == target_name }
|
278
|
+
target.groups.find {|group| group.name == group_name }
|
279
|
+
end
|
280
|
+
else
|
281
|
+
project.targets.find {|target| target.name == target_name }
|
282
|
+
end
|
283
|
+
end.compact.to_set
|
284
|
+
|
285
|
+
files.signature_paths.each do |path, target_group|
|
286
|
+
if group_set.include?(target_group)
|
287
|
+
target_group = target_group.target if target_group.is_a?(Project::Group)
|
288
|
+
request.signature_paths << [target_group.name, path]
|
289
|
+
end
|
290
|
+
end
|
291
|
+
files.source_paths.each do |path, target_group|
|
292
|
+
if group_set.include?(target_group)
|
293
|
+
target_group = target_group.target if target_group.is_a?(Project::Group)
|
294
|
+
request.code_paths << [target_group.name, path]
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
257
301
|
def make_request(guid: SecureRandom.uuid, include_unchanged: false, progress:)
|
258
302
|
TypeCheckController::Request.new(guid: guid, progress: progress).tap do |request|
|
259
303
|
if include_unchanged
|
@@ -1436,7 +1436,7 @@ module Steep
|
|
1436
1436
|
# ok
|
1437
1437
|
else
|
1438
1438
|
unless hint == pair.type
|
1439
|
-
pair.constr.typing.add_error Diagnostic::Ruby::
|
1439
|
+
pair.constr.typing.add_error Diagnostic::Ruby::UnannotatedEmptyCollection.new(node: node)
|
1440
1440
|
end
|
1441
1441
|
end
|
1442
1442
|
end
|
@@ -1704,7 +1704,7 @@ module Steep
|
|
1704
1704
|
add_typing node, type: array
|
1705
1705
|
end
|
1706
1706
|
else
|
1707
|
-
typing.add_error Diagnostic::Ruby::
|
1707
|
+
typing.add_error Diagnostic::Ruby::UnannotatedEmptyCollection.new(node: node)
|
1708
1708
|
add_typing node, type: AST::Builtin::Array.instance_type(AST::Builtin.any_type)
|
1709
1709
|
end
|
1710
1710
|
else
|
@@ -4763,6 +4763,15 @@ module Steep
|
|
4763
4763
|
|
4764
4764
|
def try_tuple_type!(node, hint: nil)
|
4765
4765
|
if node.type == :array
|
4766
|
+
if node.children.size == 1 && node.children[0]&.type == :splat
|
4767
|
+
# Skip the array construct
|
4768
|
+
splat_node = node.children[0] or raise
|
4769
|
+
splat_value = splat_node.children[0] or raise
|
4770
|
+
|
4771
|
+
type, constr = try_tuple_type!(splat_value, hint: hint)
|
4772
|
+
_, constr = constr.add_typing(splat_node, type: AST::Types::Any.instance)
|
4773
|
+
return constr.add_typing(node, type: type)
|
4774
|
+
end
|
4766
4775
|
if hint.nil? || hint.is_a?(AST::Types::Tuple)
|
4767
4776
|
typing.new_child() do |child_typing|
|
4768
4777
|
if pair = with_new_typing(child_typing).try_tuple_type(node, hint)
|
data/lib/steep/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: steep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.9.0.dev.
|
4
|
+
version: 1.9.0.dev.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Soutaro Matsumoto
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -245,6 +245,7 @@ files:
|
|
245
245
|
- bin/output_rebaseline.rb
|
246
246
|
- bin/output_test.rb
|
247
247
|
- bin/rbs
|
248
|
+
- bin/rbs-inline
|
248
249
|
- bin/setup
|
249
250
|
- bin/stackprof_test.rb
|
250
251
|
- bin/steep
|
@@ -412,7 +413,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
412
413
|
- !ruby/object:Gem::Version
|
413
414
|
version: '0'
|
414
415
|
requirements: []
|
415
|
-
rubygems_version: 3.5.
|
416
|
+
rubygems_version: 3.5.11
|
416
417
|
signing_key:
|
417
418
|
specification_version: 4
|
418
419
|
summary: Gradual Typing for Ruby
|