steep-relaxed 1.9.3.3 → 1.10.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +60 -0
- data/Rakefile +23 -0
- data/Steepfile +5 -2
- data/lib/steep/annotations_helper.rb +43 -0
- data/lib/steep/ast/ignore.rb +3 -4
- data/lib/steep/cli.rb +102 -23
- data/lib/steep/diagnostic/lsp_formatter.rb +17 -3
- data/lib/steep/diagnostic/ruby.rb +33 -0
- data/lib/steep/diagnostic/signature.rb +48 -0
- data/lib/steep/drivers/check.rb +3 -1
- data/lib/steep/drivers/diagnostic_printer/base_formatter.rb +19 -0
- data/lib/steep/drivers/diagnostic_printer/code_formatter.rb +95 -0
- data/lib/steep/drivers/diagnostic_printer/github_actions_formatter.rb +44 -0
- data/lib/steep/drivers/diagnostic_printer.rb +9 -86
- data/lib/steep/drivers/langserver.rb +4 -1
- data/lib/steep/drivers/worker.rb +2 -0
- data/lib/steep/interface/builder.rb +2 -2
- data/lib/steep/server/custom_methods.rb +12 -0
- data/lib/steep/server/interaction_worker.rb +33 -6
- data/lib/steep/server/master.rb +103 -7
- data/lib/steep/server/type_check_worker.rb +48 -2
- data/lib/steep/server/worker_process.rb +31 -20
- data/lib/steep/services/completion_provider.rb +12 -2
- data/lib/steep/services/signature_service.rb +2 -2
- data/lib/steep/signature/validator.rb +56 -4
- data/lib/steep/source.rb +2 -2
- data/lib/steep/subtyping/check.rb +5 -6
- data/lib/steep/type_construction.rb +171 -38
- data/lib/steep/type_inference/context.rb +4 -0
- data/lib/steep/type_inference/logic_type_interpreter.rb +77 -15
- data/lib/steep/type_inference/method_call.rb +5 -3
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +10 -0
- data/manual/ruby-diagnostics.md +46 -0
- data/sample/Steepfile +0 -2
- data/sample/lib/deprecated.rb +7 -0
- data/sample/sig/deprecated.rbs +16 -0
- data/steep-relaxed.gemspec +5 -3
- metadata +16 -13
@@ -1494,6 +1494,10 @@ module Steep
|
|
1494
1494
|
Diagnostic::Ruby::UnknownConstant.new(node: name_node, name: name_node.children[1]).class!
|
1495
1495
|
)
|
1496
1496
|
end
|
1497
|
+
|
1498
|
+
if class_name
|
1499
|
+
check_deprecation_constant(class_name, name_node, name_node.location.expression)
|
1500
|
+
end
|
1497
1501
|
else
|
1498
1502
|
_, constr = synthesize(name_node)
|
1499
1503
|
end
|
@@ -1549,6 +1553,10 @@ module Steep
|
|
1549
1553
|
_, constr, module_name = synthesize_constant_decl(name_node, name_node.children[0], name_node.children[1]) do
|
1550
1554
|
typing.add_error Diagnostic::Ruby::UnknownConstant.new(node: name_node, name: name_node.children[1]).module!
|
1551
1555
|
end
|
1556
|
+
|
1557
|
+
if module_name
|
1558
|
+
check_deprecation_constant(module_name, name_node, name_node.location.expression)
|
1559
|
+
end
|
1552
1560
|
else
|
1553
1561
|
_, constr = synthesize(name_node)
|
1554
1562
|
end
|
@@ -1619,6 +1627,7 @@ module Steep
|
|
1619
1627
|
|
1620
1628
|
if name
|
1621
1629
|
typing.source_index.add_reference(constant: name, ref: node)
|
1630
|
+
constr.check_deprecation_constant(name, node, node.location.expression)
|
1622
1631
|
end
|
1623
1632
|
|
1624
1633
|
Pair.new(type: type, constr: constr)
|
@@ -1637,6 +1646,8 @@ module Steep
|
|
1637
1646
|
|
1638
1647
|
if constant_name
|
1639
1648
|
typing.source_index.add_definition(constant: constant_name, definition: node)
|
1649
|
+
location = node.location #: Parser::Source::Map & Parser::AST::_Variable
|
1650
|
+
constr.check_deprecation_constant(constant_name, node, location.name)
|
1640
1651
|
end
|
1641
1652
|
|
1642
1653
|
value_type, constr = constr.synthesize(node.children.last, hint: constant_type)
|
@@ -2400,6 +2411,9 @@ module Steep
|
|
2400
2411
|
lhs_type = context.type_env[name]
|
2401
2412
|
rhs_type, constr = synthesize(rhs, hint: lhs_type).to_ary
|
2402
2413
|
|
2414
|
+
location = node.location #: Parser::Source::Map & Parser::AST::_Variable
|
2415
|
+
constr.check_deprecation_global(name, node, location.name)
|
2416
|
+
|
2403
2417
|
type, constr = constr.gvasgn(node, rhs_type)
|
2404
2418
|
|
2405
2419
|
constr.add_typing(node, type: type)
|
@@ -2408,6 +2422,9 @@ module Steep
|
|
2408
2422
|
when :gvar
|
2409
2423
|
yield_self do
|
2410
2424
|
name = node.children.first
|
2425
|
+
|
2426
|
+
check_deprecation_global(name, node, node.location.expression)
|
2427
|
+
|
2411
2428
|
if type = context.type_env[name]
|
2412
2429
|
add_typing(node, type: type)
|
2413
2430
|
else
|
@@ -2956,7 +2973,7 @@ module Steep
|
|
2956
2973
|
nil
|
2957
2974
|
]
|
2958
2975
|
else
|
2959
|
-
# No
|
2976
|
+
# No nesting
|
2960
2977
|
synthesize_constant(node, nil, constant_name, &block)
|
2961
2978
|
end
|
2962
2979
|
end
|
@@ -3091,7 +3108,7 @@ module Steep
|
|
3091
3108
|
body_node,
|
3092
3109
|
block_params: params,
|
3093
3110
|
block_param_hint: params_hint,
|
3094
|
-
|
3111
|
+
block_next_type: return_hint,
|
3095
3112
|
block_block_hint: block_hint,
|
3096
3113
|
block_annotations: block_annotations,
|
3097
3114
|
block_self_hint: self_hint,
|
@@ -3220,6 +3237,18 @@ module Steep
|
|
3220
3237
|
end
|
3221
3238
|
end
|
3222
3239
|
|
3240
|
+
def deprecated_send?(call)
|
3241
|
+
return unless call.node.type == :send || call.node.type == :csend
|
3242
|
+
|
3243
|
+
call.method_decls.each do |decl|
|
3244
|
+
if pair = AnnotationsHelper.deprecated_annotation?(decl.method_def.each_annotation.to_a)
|
3245
|
+
return pair
|
3246
|
+
end
|
3247
|
+
end
|
3248
|
+
|
3249
|
+
nil
|
3250
|
+
end
|
3251
|
+
|
3223
3252
|
def type_send_interface(node, interface:, receiver:, receiver_type:, method_name:, arguments:, block_params:, block_body:, tapp:, hint:)
|
3224
3253
|
method = interface.methods[method_name]
|
3225
3254
|
|
@@ -3273,6 +3302,20 @@ module Steep
|
|
3273
3302
|
end
|
3274
3303
|
end
|
3275
3304
|
end
|
3305
|
+
|
3306
|
+
if (_, message = deprecated_send?(call))
|
3307
|
+
send_node, _ = deconstruct_sendish_and_block_nodes(node)
|
3308
|
+
send_node or raise
|
3309
|
+
_, _, _, loc = deconstruct_send_node!(send_node)
|
3310
|
+
|
3311
|
+
constr.typing.add_error(
|
3312
|
+
Diagnostic::Ruby::DeprecatedReference.new(
|
3313
|
+
node: node,
|
3314
|
+
location: loc.selector,
|
3315
|
+
message: message
|
3316
|
+
)
|
3317
|
+
)
|
3318
|
+
end
|
3276
3319
|
end
|
3277
3320
|
|
3278
3321
|
if node.type == :csend || ((node.type == :block || node.type == :numblock) && node.children[0].type == :csend)
|
@@ -3415,7 +3458,7 @@ module Steep
|
|
3415
3458
|
block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
|
3416
3459
|
block_params or raise
|
3417
3460
|
|
3418
|
-
constr = constr.synthesize_children(node.children[0])
|
3461
|
+
constr = constr.synthesize_children(node.children[0], skips: [receiver])
|
3419
3462
|
|
3420
3463
|
constr.type_block_without_hint(
|
3421
3464
|
node: node,
|
@@ -3821,26 +3864,40 @@ module Steep
|
|
3821
3864
|
if forwarded_args
|
3822
3865
|
method_name or raise "method_name cannot be nil if `forwarded_args` is given, because proc/block doesn't support `...` arg"
|
3823
3866
|
|
3824
|
-
|
3867
|
+
method_context = context.method_context or raise
|
3868
|
+
forward_arg_type = method_context.forward_arg_type
|
3825
3869
|
|
3826
|
-
|
3827
|
-
|
3828
|
-
|
3829
|
-
|
3830
|
-
|
3831
|
-
|
3870
|
+
case forward_arg_type
|
3871
|
+
when nil
|
3872
|
+
if context.method_context.method_type
|
3873
|
+
raise "Method context must have `forwarded_arg_type` if `...` node appears in it"
|
3874
|
+
else
|
3875
|
+
# Skips type checking forwarded argument because the method type is not given
|
3876
|
+
end
|
3877
|
+
when true
|
3878
|
+
# Skip type checking forwarded argument because the method is untyped function
|
3879
|
+
else
|
3880
|
+
params, _block = forward_arg_type
|
3881
|
+
|
3882
|
+
checker.with_context(self_type: self_type, instance_type: context.module_context.instance_type, class_type: context.module_context.module_type, constraints: constraints) do
|
3883
|
+
result = checker.check_method_params(
|
3884
|
+
:"... (argument forwarding)",
|
3885
|
+
Subtyping::Relation.new(
|
3886
|
+
sub_type: forwarded_args.params,
|
3887
|
+
super_type: params
|
3888
|
+
)
|
3832
3889
|
)
|
3833
|
-
)
|
3834
3890
|
|
3835
|
-
|
3836
|
-
|
3837
|
-
|
3838
|
-
|
3839
|
-
|
3840
|
-
|
3841
|
-
|
3891
|
+
if result.failure?
|
3892
|
+
errors.push(
|
3893
|
+
Diagnostic::Ruby::IncompatibleArgumentForwarding.new(
|
3894
|
+
method_name: method_name,
|
3895
|
+
node: forwarded_args.node,
|
3896
|
+
params_pair: [params, forwarded_args.params],
|
3897
|
+
result: result
|
3898
|
+
)
|
3842
3899
|
)
|
3843
|
-
|
3900
|
+
end
|
3844
3901
|
end
|
3845
3902
|
end
|
3846
3903
|
end
|
@@ -4007,7 +4064,7 @@ module Steep
|
|
4007
4064
|
block_body,
|
4008
4065
|
block_params: block_params_,
|
4009
4066
|
block_param_hint: method_type.block.type.params,
|
4010
|
-
|
4067
|
+
block_next_type: method_type.block.type.return_type,
|
4011
4068
|
block_block_hint: nil,
|
4012
4069
|
block_annotations: block_annotations,
|
4013
4070
|
block_self_hint: method_type.block.self_type,
|
@@ -4062,6 +4119,15 @@ module Steep
|
|
4062
4119
|
|
4063
4120
|
fvs_.merge(method_type.type.params.free_variables) if method_type.type.params
|
4064
4121
|
fvs_.merge(method_type.block.type.params.free_variables) if method_type.block.type.params
|
4122
|
+
(method_type.type.return_type.free_variables + method_type.block.type.return_type.free_variables).each do |var|
|
4123
|
+
if var.is_a?(Symbol)
|
4124
|
+
if constraints.unknown?(var)
|
4125
|
+
unless constraints.has_constraint?(var)
|
4126
|
+
fvs_.delete(var)
|
4127
|
+
end
|
4128
|
+
end
|
4129
|
+
end
|
4130
|
+
end
|
4065
4131
|
|
4066
4132
|
constraints.solution(checker, variables: fvs_, context: ccontext)
|
4067
4133
|
}
|
@@ -4073,7 +4139,7 @@ module Steep
|
|
4073
4139
|
block_constr = block_constr.update_type_env {|env| env.subst(s) }
|
4074
4140
|
block_constr = block_constr.update_context {|context|
|
4075
4141
|
context.with(
|
4076
|
-
self_type:
|
4142
|
+
self_type: context.self_type.subst(s),
|
4077
4143
|
type_env: context.type_env.subst(s),
|
4078
4144
|
block_context: context.block_context&.subst(s),
|
4079
4145
|
break_context: context.break_context&.subst(s)
|
@@ -4194,18 +4260,29 @@ module Steep
|
|
4194
4260
|
|
4195
4261
|
case
|
4196
4262
|
when forwarded_args_node = args.forwarded_args_node
|
4197
|
-
|
4263
|
+
case forward_arg_type = method_context!.forward_arg_type
|
4264
|
+
when nil
|
4265
|
+
if method_context!.method_type
|
4266
|
+
raise "Method context must have `forwarded_arg_type` if `...` node appears in it"
|
4267
|
+
else
|
4268
|
+
# Skips type checking forwarded argument because the method type is not given
|
4269
|
+
end
|
4270
|
+
when true
|
4271
|
+
# Skip type checking because it's untyped function
|
4272
|
+
else
|
4273
|
+
_, block = forward_arg_type
|
4198
4274
|
|
4199
|
-
|
4200
|
-
|
4275
|
+
method_block_type = method_type.block&.to_proc_type || AST::Builtin.nil_type
|
4276
|
+
forwarded_block_type = block&.to_proc_type || AST::Builtin.nil_type
|
4201
4277
|
|
4202
|
-
|
4203
|
-
|
4204
|
-
|
4205
|
-
|
4206
|
-
|
4207
|
-
|
4208
|
-
|
4278
|
+
if result = constr.no_subtyping?(sub_type: forwarded_block_type, super_type: method_block_type)
|
4279
|
+
errors << Diagnostic::Ruby::IncompatibleArgumentForwarding.new(
|
4280
|
+
method_name: method_name,
|
4281
|
+
node: forwarded_args_node,
|
4282
|
+
block_pair: [block, method_type.block],
|
4283
|
+
result: result
|
4284
|
+
)
|
4285
|
+
end
|
4209
4286
|
end
|
4210
4287
|
|
4211
4288
|
when arg.compatible?
|
@@ -4358,7 +4435,7 @@ module Steep
|
|
4358
4435
|
block_body,
|
4359
4436
|
block_params: block_params,
|
4360
4437
|
block_param_hint: nil,
|
4361
|
-
|
4438
|
+
block_next_type: nil,
|
4362
4439
|
block_block_hint: nil,
|
4363
4440
|
block_annotations: block_annotations,
|
4364
4441
|
block_self_hint: nil,
|
@@ -4411,7 +4488,7 @@ module Steep
|
|
4411
4488
|
end
|
4412
4489
|
end
|
4413
4490
|
|
4414
|
-
def for_block(body_node, block_params:, block_param_hint:,
|
4491
|
+
def for_block(body_node, block_params:, block_param_hint:, block_next_type:, block_block_hint:, block_annotations:, node_type_hint:, block_self_hint:)
|
4415
4492
|
block_param_pairs = block_param_hint && block_params.zip(block_param_hint, block_block_hint, factory: checker.factory)
|
4416
4493
|
|
4417
4494
|
# @type var param_types_hash: Hash[Symbol?, AST::Types::t]
|
@@ -4453,7 +4530,7 @@ module Steep
|
|
4453
4530
|
|
4454
4531
|
param_types = param_types_hash.each.with_object({}) do |pair, hash| #$ Hash[Symbol, [AST::Types::t, AST::Types::t?]]
|
4455
4532
|
name, type = pair
|
4456
|
-
# skip
|
4533
|
+
# skip unnamed arguments `*`, `**` and `&`
|
4457
4534
|
next if name.nil?
|
4458
4535
|
hash[name] = [type, nil]
|
4459
4536
|
end
|
@@ -4500,19 +4577,18 @@ module Steep
|
|
4500
4577
|
end
|
4501
4578
|
|
4502
4579
|
block_context = TypeInference::Context::BlockContext.new(
|
4503
|
-
body_type: block_annotations.block_type
|
4580
|
+
body_type: block_annotations.block_type
|
4504
4581
|
)
|
4505
4582
|
break_context = TypeInference::Context::BreakContext.new(
|
4506
4583
|
break_type: break_type || AST::Builtin.any_type,
|
4507
|
-
next_type:
|
4584
|
+
next_type: block_next_type || AST::Builtin.any_type
|
4508
4585
|
)
|
4509
4586
|
|
4510
|
-
self_type =
|
4587
|
+
self_type = block_self_hint || self.self_type
|
4511
4588
|
module_context = self.module_context
|
4512
4589
|
|
4513
4590
|
if implements = block_annotations.implement_module_annotation
|
4514
4591
|
module_context = default_module_context(implements.name, nesting: nesting)
|
4515
|
-
|
4516
4592
|
self_type = module_context.module_type
|
4517
4593
|
end
|
4518
4594
|
|
@@ -4520,6 +4596,11 @@ module Steep
|
|
4520
4596
|
self_type = annotation_self_type
|
4521
4597
|
end
|
4522
4598
|
|
4599
|
+
# self_type here means the top-level `self` type because of the `Interface::Builder` implementation
|
4600
|
+
if self_type
|
4601
|
+
self_type = expand_self(self_type)
|
4602
|
+
end
|
4603
|
+
|
4523
4604
|
self.class.new(
|
4524
4605
|
checker: checker,
|
4525
4606
|
source: source,
|
@@ -4542,6 +4623,20 @@ module Steep
|
|
4542
4623
|
if block_body
|
4543
4624
|
body_type, _, context = synthesize(block_body, hint: block_context&.body_type || block_type_hint)
|
4544
4625
|
|
4626
|
+
if annotated_body_type = block_context&.body_type
|
4627
|
+
if result = no_subtyping?(sub_type: body_type, super_type: annotated_body_type)
|
4628
|
+
typing.add_error(
|
4629
|
+
Diagnostic::Ruby::BlockBodyTypeMismatch.new(
|
4630
|
+
node: node,
|
4631
|
+
expected: annotated_body_type,
|
4632
|
+
actual: body_type,
|
4633
|
+
result: result
|
4634
|
+
)
|
4635
|
+
)
|
4636
|
+
end
|
4637
|
+
body_type = annotated_body_type
|
4638
|
+
end
|
4639
|
+
|
4545
4640
|
range = block_body.loc.expression.end_pos..node.loc.end.begin_pos
|
4546
4641
|
typing.cursor_context.set(range, context)
|
4547
4642
|
|
@@ -5179,5 +5274,43 @@ module Steep
|
|
5179
5274
|
end
|
5180
5275
|
end
|
5181
5276
|
end
|
5277
|
+
|
5278
|
+
def check_deprecation_global(name, node, location)
|
5279
|
+
if global_entry = checker.factory.env.global_decls[name]
|
5280
|
+
if (_, message = AnnotationsHelper.deprecated_annotation?(global_entry.decl.annotations))
|
5281
|
+
typing.add_error(
|
5282
|
+
Diagnostic::Ruby::DeprecatedReference.new(
|
5283
|
+
node: node,
|
5284
|
+
location: location,
|
5285
|
+
message: message
|
5286
|
+
)
|
5287
|
+
)
|
5288
|
+
end
|
5289
|
+
end
|
5290
|
+
end
|
5291
|
+
|
5292
|
+
def check_deprecation_constant(name, node, location)
|
5293
|
+
entry = checker.builder.factory.env.constant_entry(name)
|
5294
|
+
|
5295
|
+
annotations =
|
5296
|
+
case entry
|
5297
|
+
when RBS::Environment::ModuleEntry, RBS::Environment::ClassEntry
|
5298
|
+
entry.decls.flat_map { _1.decl.annotations }
|
5299
|
+
when RBS::Environment::ConstantEntry, RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
|
5300
|
+
entry.decl.annotations
|
5301
|
+
end
|
5302
|
+
|
5303
|
+
if annotations
|
5304
|
+
if (_, message = AnnotationsHelper.deprecated_annotation?(annotations))
|
5305
|
+
typing.add_error(
|
5306
|
+
Diagnostic::Ruby::DeprecatedReference.new(
|
5307
|
+
node: node,
|
5308
|
+
location: location,
|
5309
|
+
message: message
|
5310
|
+
)
|
5311
|
+
)
|
5312
|
+
end
|
5313
|
+
end
|
5314
|
+
end
|
5182
5315
|
end
|
5183
5316
|
end
|
@@ -155,6 +155,10 @@ module Steep
|
|
155
155
|
@type_env = type_env
|
156
156
|
@call_context = call_context
|
157
157
|
@variable_context = variable_context
|
158
|
+
|
159
|
+
if self_type.free_variables.include?(AST::Types::Self.instance)
|
160
|
+
raise "Context#self_type cannot contain `self`"
|
161
|
+
end
|
158
162
|
end
|
159
163
|
|
160
164
|
def with(method_context: self.method_context,
|
@@ -169,25 +169,45 @@ module Steep
|
|
169
169
|
return [truthy_result, falsy_result]
|
170
170
|
end
|
171
171
|
else
|
172
|
-
|
173
|
-
|
172
|
+
receiver, *_ = node.children
|
173
|
+
receiver_type = typing.type_of(node: receiver) if receiver
|
174
|
+
|
175
|
+
if env[receiver] && receiver_type.is_a?(AST::Types::Union)
|
176
|
+
result = evaluate_union_method_call(node: node, type: type, env: env, receiver: receiver, receiver_type: receiver_type)
|
177
|
+
if result
|
178
|
+
truthy_result = result[0] unless result[0].unreachable
|
179
|
+
falsy_result = result[1] unless result[1].unreachable
|
180
|
+
end
|
181
|
+
end
|
174
182
|
|
175
|
-
|
176
|
-
|
177
|
-
Result.new(type: truthy_type, env: env.refine_types(pure_call_types: { node => truthy_type }), unreachable: false)
|
178
|
-
else
|
179
|
-
Result.new(type: type, env: env, unreachable: true)
|
180
|
-
end
|
183
|
+
truthy_result ||= Result.new(type: type, env: env, unreachable: false)
|
184
|
+
falsy_result ||= Result.new(type: type, env: env, unreachable: false)
|
181
185
|
|
182
|
-
|
183
|
-
if falsy_type
|
184
|
-
Result.new(type: falsy_type, env: env.refine_types(pure_call_types: { node => falsy_type }), unreachable: false)
|
185
|
-
else
|
186
|
-
Result.new(type: type, env: env, unreachable: true)
|
187
|
-
end
|
186
|
+
truthy_type, falsy_type = factory.partition_union(type)
|
188
187
|
|
189
|
-
|
188
|
+
if truthy_type
|
189
|
+
truthy_result = truthy_result.update_type { truthy_type }
|
190
|
+
else
|
191
|
+
truthy_result = truthy_result.update_type { BOT }.unreachable!
|
190
192
|
end
|
193
|
+
|
194
|
+
if falsy_type
|
195
|
+
falsy_result = falsy_result.update_type { falsy_type }
|
196
|
+
else
|
197
|
+
falsy_result = falsy_result.update_type { BOT }.unreachable!
|
198
|
+
end
|
199
|
+
|
200
|
+
if truthy_result.env[node] && falsy_result.env[node]
|
201
|
+
if truthy_type
|
202
|
+
truthy_result = Result.new(type: truthy_type, env: truthy_result.env.refine_types(pure_call_types: { node => truthy_type }), unreachable: false)
|
203
|
+
end
|
204
|
+
|
205
|
+
if falsy_type
|
206
|
+
falsy_result = Result.new(type: falsy_type, env: falsy_result.env.refine_types(pure_call_types: { node => falsy_type }), unreachable: false)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
return [truthy_result, falsy_result]
|
191
211
|
end
|
192
212
|
end
|
193
213
|
|
@@ -408,6 +428,48 @@ module Steep
|
|
408
428
|
end
|
409
429
|
end
|
410
430
|
|
431
|
+
def evaluate_union_method_call(node:, type:, env:, receiver:, receiver_type:)
|
432
|
+
call_type = typing.call_of(node: node) rescue nil
|
433
|
+
return unless call_type.is_a?(Steep::TypeInference::MethodCall::Typed)
|
434
|
+
|
435
|
+
truthy_types = [] #: Array[AST::Types::t]
|
436
|
+
falsy_types = [] #: Array[AST::Types::t]
|
437
|
+
|
438
|
+
receiver_type.types.each do |type|
|
439
|
+
if shape = subtyping.builder.shape(type, config)
|
440
|
+
method = shape.methods[call_type.method_name] or raise
|
441
|
+
method_type = method.method_types.find do |method_type|
|
442
|
+
call_type.method_decls.any? {|decl| factory.method_type(decl.method_type) == method_type }
|
443
|
+
end
|
444
|
+
if method_type
|
445
|
+
return_type = method_type.type.return_type
|
446
|
+
truthy, falsy = factory.partition_union(return_type)
|
447
|
+
truthy_types << type if truthy
|
448
|
+
falsy_types << type if falsy
|
449
|
+
next
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
truthy_types << type
|
454
|
+
falsy_types << type
|
455
|
+
end
|
456
|
+
|
457
|
+
truthy_type = truthy_types.empty? ? BOT : AST::Types::Union.build(types: truthy_types)
|
458
|
+
falsy_type = falsy_types.empty? ? BOT : AST::Types::Union.build(types: falsy_types)
|
459
|
+
|
460
|
+
truthy_env, falsy_env = refine_node_type(
|
461
|
+
env: env,
|
462
|
+
node: receiver,
|
463
|
+
truthy_type: truthy_type,
|
464
|
+
falsy_type: falsy_type
|
465
|
+
)
|
466
|
+
|
467
|
+
return [
|
468
|
+
Result.new(type: type, env: truthy_env, unreachable: truthy_type.nil?),
|
469
|
+
Result.new(type: type, env: falsy_env, unreachable: falsy_type.nil?)
|
470
|
+
]
|
471
|
+
end
|
472
|
+
|
411
473
|
def decompose_value(node)
|
412
474
|
case node.type
|
413
475
|
when :lvar
|
@@ -124,12 +124,14 @@ module Steep
|
|
124
124
|
|
125
125
|
def pure?
|
126
126
|
method_decls.all? do |method_decl|
|
127
|
-
case
|
128
|
-
when RBS::AST::Members::MethodDefinition
|
129
|
-
member.annotations.any? {|annotation| annotation.string == "pure" }
|
127
|
+
case method_decl.method_def.member
|
130
128
|
when RBS::AST::Members::Attribute
|
131
129
|
# The attribute writer is not pure
|
132
130
|
!method_decl.method_name.method_name.end_with?("=")
|
131
|
+
else
|
132
|
+
method_decl.method_def.each_annotation.any? do |annotation|
|
133
|
+
annotation.string == "pure"
|
134
|
+
end
|
133
135
|
end
|
134
136
|
end
|
135
137
|
end
|
data/lib/steep/version.rb
CHANGED
data/lib/steep.rb
CHANGED
@@ -17,6 +17,7 @@ require "yaml"
|
|
17
17
|
require "securerandom"
|
18
18
|
require "base64"
|
19
19
|
require "time"
|
20
|
+
require 'socket'
|
20
21
|
|
21
22
|
require "concurrent/utility/processor_counter"
|
22
23
|
require "terminal-table"
|
@@ -150,6 +151,11 @@ require "steep/drivers/init"
|
|
150
151
|
require "steep/drivers/vendor"
|
151
152
|
require "steep/drivers/worker"
|
152
153
|
require "steep/drivers/diagnostic_printer"
|
154
|
+
require "steep/drivers/diagnostic_printer/base_formatter"
|
155
|
+
require "steep/drivers/diagnostic_printer/code_formatter"
|
156
|
+
require "steep/drivers/diagnostic_printer/github_actions_formatter"
|
157
|
+
|
158
|
+
require "steep/annotations_helper"
|
153
159
|
|
154
160
|
if ENV["NO_COLOR"]
|
155
161
|
Rainbow.enabled = false
|
@@ -226,6 +232,10 @@ module Steep
|
|
226
232
|
end
|
227
233
|
end
|
228
234
|
|
235
|
+
def self.can_fork?
|
236
|
+
defined?(fork)
|
237
|
+
end
|
238
|
+
|
229
239
|
class Sampler
|
230
240
|
def initialize()
|
231
241
|
@samples = []
|
data/manual/ruby-diagnostics.md
CHANGED
@@ -237,6 +237,52 @@ test.rb:4:6: [error] ::Kernel is declared as a module in RBS
|
|
237
237
|
| - | - | - | - | - |
|
238
238
|
| error | error | error | - | - |
|
239
239
|
|
240
|
+
<a name='Ruby::DeprecatedReference'></a>
|
241
|
+
## Ruby::DeprecatedReference
|
242
|
+
|
243
|
+
Method call or constant reference is deprecated.
|
244
|
+
|
245
|
+
### RBS
|
246
|
+
|
247
|
+
```rbs
|
248
|
+
%a{deprecated} class Foo end
|
249
|
+
|
250
|
+
class Bar
|
251
|
+
%a{deprecated: since v0.9} def self.bar: () -> void
|
252
|
+
end
|
253
|
+
```
|
254
|
+
|
255
|
+
### Ruby code
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
Foo
|
259
|
+
|
260
|
+
Bar.bar()
|
261
|
+
```
|
262
|
+
|
263
|
+
### Diagnostic
|
264
|
+
|
265
|
+
```
|
266
|
+
lib/deprecated.rb:1:0: [warning] The constant is deprecated
|
267
|
+
│ Diagnostic ID: Ruby::DeprecatedReference
|
268
|
+
│
|
269
|
+
└ Foo
|
270
|
+
~~~
|
271
|
+
|
272
|
+
lib/deprecated.rb:3:4: [warning] The method is deprecated: since v0.9
|
273
|
+
│ Diagnostic ID: Ruby::DeprecatedReference
|
274
|
+
│
|
275
|
+
└ Bar.bar()
|
276
|
+
~~~
|
277
|
+
```
|
278
|
+
|
279
|
+
|
280
|
+
### Severity
|
281
|
+
|
282
|
+
| all_error | strict | default | lenient | silent |
|
283
|
+
| - | - | - | - | - |
|
284
|
+
| error | warning | warning | warning | - |
|
285
|
+
|
240
286
|
<a name='Ruby::DifferentMethodParameterKind'></a>
|
241
287
|
## Ruby::DifferentMethodParameterKind
|
242
288
|
|
data/sample/Steepfile
CHANGED
@@ -5,8 +5,6 @@ target :lib do
|
|
5
5
|
|
6
6
|
check "lib" # Directory name
|
7
7
|
|
8
|
-
library "rbs"
|
9
|
-
|
10
8
|
# configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
|
11
9
|
# configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
|
12
10
|
# configure_code_diagnostics(D::Ruby.silent) # `silent` diagnostics setting
|
@@ -0,0 +1,16 @@
|
|
1
|
+
%a{deprecated: Use Bar instead} class Foo end
|
2
|
+
|
3
|
+
class Bar
|
4
|
+
# Original bar
|
5
|
+
def self.bar: %a{deprecated: since v0.9} () -> void
|
6
|
+
|
7
|
+
# Overloading bar
|
8
|
+
def self.bar: (String) -> String | ...
|
9
|
+
|
10
|
+
def hogehoge: (String) -> void
|
11
|
+
| %a{deprecated: Pass an positional argument} (string: String) -> void
|
12
|
+
end
|
13
|
+
|
14
|
+
type t = Foo
|
15
|
+
|
16
|
+
%a{deprecated} $test: untyped
|
data/steep-relaxed.gemspec
CHANGED
@@ -41,10 +41,10 @@ Gem::Specification.new do |spec|
|
|
41
41
|
spec.add_runtime_dependency "activesupport", ">= 4.2"
|
42
42
|
spec.add_runtime_dependency "rainbow", ">= 2.2.2", "< 4.0"
|
43
43
|
spec.add_runtime_dependency "listen", "~> 3.0"
|
44
|
-
spec.add_runtime_dependency "language_server-protocol", ">= 3.
|
45
|
-
spec.add_runtime_dependency "rbs", "~> 3.
|
44
|
+
spec.add_runtime_dependency "language_server-protocol", ">= 3.17.0.4", "< 4.0"
|
45
|
+
spec.add_runtime_dependency "rbs-relaxed", "~> 3.9"
|
46
46
|
spec.add_runtime_dependency "concurrent-ruby", ">= 1.1.10"
|
47
|
-
spec.add_runtime_dependency "terminal-table", ">= 2", "<
|
47
|
+
spec.add_runtime_dependency "terminal-table", ">= 2", "< 5"
|
48
48
|
|
49
49
|
# Stdgem dependencies omitted for compatibility with legacy environments
|
50
50
|
# spec.add_runtime_dependency "securerandom", ">= 0.1"
|
@@ -53,4 +53,6 @@ Gem::Specification.new do |spec|
|
|
53
53
|
# spec.add_runtime_dependency "fileutils", ">= 1.1.0"
|
54
54
|
# spec.add_runtime_dependency "strscan", ">= 1.0.0"
|
55
55
|
# spec.add_runtime_dependency "csv", ">= 3.0.9"
|
56
|
+
# spec.add_runtime_dependency "uri", ">= 0.12.0"
|
57
|
+
# spec.add_runtime_dependency "mutex_m", ">= 0.3.0"
|
56
58
|
end
|