steep 0.33.0 → 0.34.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e93086efe3704ac8b59a1450fda301b7ab91f409c13c53a679a2ed3b3419ca84
4
- data.tar.gz: b00e2030a9ea2171b6f967c78f469204c903cb937d421e5dcab896021fce2919
3
+ metadata.gz: 0ec77465913e4b2146e068c58f63b7ae8b5c51fd2391f6eb2776dba8372a81c2
4
+ data.tar.gz: 7528dbaf4873d9eb77728521837ecb0fe43a2010036572be2c3dc017c5b903cc
5
5
  SHA512:
6
- metadata.gz: 06023d31b509f58efdea8c8f0e13c49b38f3a4936debbe3a0d88bfd84b356e7a761506a8f105c035bd454a4b2f39ae6af13d16b84d29e6d0050d9d58d7062e82
7
- data.tar.gz: '0601459d31ad8ca758c95c29215eb237b5bc50490b5133e574057ec1836396d9189c3dd22628244c1d8d432e0f945a746c280ae96ca20b768c063fbae0c696af'
6
+ metadata.gz: b0426373f8fb9e48ccec48d0676d70d5a674a389a83624df78dc3deacaba23840b02cc94becba92304de35f98c8d8bb3af12ef185161e4e6a6c37600cb61a82d
7
+ data.tar.gz: 5f3a32240541f116b6299c354fada0c8de398b6139b9d5e275e7b05490ccc401aa1b4f70978af5561e2ce9c6c7bb2587c1c8e43801276c0875000496ed332a5b
@@ -2,6 +2,13 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.34.0 (2020-10-27)
6
+
7
+ * Add `steep stats` command to show method call typing stats ([#246](https://github.com/soutaro/steep/pull/246))
8
+ * Fix attribute assignment typing ([#243](https://github.com/soutaro/steep/pull/243))
9
+ * Let `Range[T]` be covariant ([#242](https://github.com/soutaro/steep/pull/242))
10
+ * Fix constant typing ([#247](https://github.com/soutaro/steep/pull/247), [#248](https://github.com/soutaro/steep/pull/248))
11
+
5
12
  ## 0.33.0 (2020-10-13)
6
13
 
7
14
  * Make `!` typing flow sensitive ([#240](https://github.com/soutaro/steep/pull/240))
@@ -16,6 +16,7 @@ require 'uri'
16
16
 
17
17
  require "rbs"
18
18
 
19
+ require "steep/method_name"
19
20
  require "steep/ast/types/helper"
20
21
  require "steep/ast/types/any"
21
22
  require "steep/ast/types/instance"
@@ -70,6 +71,7 @@ require "steep/type_inference/type_env"
70
71
  require "steep/type_inference/local_variable_type_env"
71
72
  require "steep/type_inference/logic"
72
73
  require "steep/type_inference/logic_type_interpreter"
74
+ require "steep/type_inference/method_call"
73
75
  require "steep/ast/types"
74
76
 
75
77
  require "steep/server/utils"
@@ -91,6 +93,7 @@ require "steep/project/hover_content"
91
93
  require "steep/project/completion_provider"
92
94
  require "steep/drivers/utils/driver_helper"
93
95
  require "steep/drivers/check"
96
+ require "steep/drivers/stats"
94
97
  require "steep/drivers/validate"
95
98
  require "steep/drivers/annotations"
96
99
  require "steep/drivers/watch"
@@ -68,7 +68,7 @@ module Steep
68
68
  name = match[:name]
69
69
  type = match[:type]
70
70
 
71
- method_type = factory.method_type(RBS::Parser.parse_method_type(type), self_type: AST::Types::Self.new)
71
+ method_type = factory.method_type(RBS::Parser.parse_method_type(type), self_type: AST::Types::Self.new, method_decls: Set[])
72
72
 
73
73
  AST::Annotation::MethodType.new(name: name.to_sym,
74
74
  type: method_type,
@@ -149,6 +149,8 @@ module Steep
149
149
  type: function_1(type.params, type.return_type),
150
150
  location: nil
151
151
  )
152
+ when Logic::Base
153
+ RBS::Types::Bases::Bool.new(location: nil)
152
154
  else
153
155
  raise "Unexpected type given: #{type} (#{type.class})"
154
156
  end
@@ -178,7 +180,7 @@ module Steep
178
180
  )
179
181
  end
180
182
 
181
- def method_type(method_type, self_type:, subst2: nil, method_def: nil)
183
+ def method_type(method_type, self_type:, subst2: nil, method_decls:)
182
184
  fvs = self_type.free_variables()
183
185
 
184
186
  type_params = []
@@ -209,8 +211,7 @@ module Steep
209
211
  return_type: type(block.type.return_type).subst(subst), location: nil)
210
212
  )
211
213
  end,
212
- method_def: method_def,
213
- location: method_def&.member&.location
214
+ method_decls: method_decls
214
215
  )
215
216
 
216
217
  if block_given?
@@ -344,46 +345,44 @@ module Steep
344
345
 
345
346
  NilClassName = TypeName("::NilClass")
346
347
 
347
- def setup_primitives(method_name, method_type)
348
- if method_def = method_type.method_def
349
- defined_in = method_def.defined_in
350
- member = method_def.member
351
-
352
- if member.is_a?(RBS::AST::Members::MethodDefinition)
353
- case method_name
354
- when :is_a?, :kind_of?, :instance_of?
355
- if defined_in == RBS::BuiltinNames::Object.name && member.instance?
356
- return method_type.with(
357
- return_type: AST::Types::Logic::ReceiverIsArg.new(location: method_type.return_type.location)
358
- )
359
- end
348
+ def setup_primitives(method_name, method_def, method_type)
349
+ defined_in = method_def.defined_in
350
+ member = method_def.member
360
351
 
361
- when :nil?
362
- case defined_in
363
- when RBS::BuiltinNames::Object.name,
364
- NilClassName
365
- return method_type.with(
366
- return_type: AST::Types::Logic::ReceiverIsNil.new(location: method_type.return_type.location)
367
- )
368
- end
352
+ if member.is_a?(RBS::AST::Members::MethodDefinition)
353
+ case method_name
354
+ when :is_a?, :kind_of?, :instance_of?
355
+ if defined_in == RBS::BuiltinNames::Object.name && member.instance?
356
+ return method_type.with(
357
+ return_type: AST::Types::Logic::ReceiverIsArg.new(location: method_type.return_type.location)
358
+ )
359
+ end
369
360
 
370
- when :!
371
- case defined_in
372
- when RBS::BuiltinNames::BasicObject.name,
373
- RBS::BuiltinNames::TrueClass.name,
374
- RBS::BuiltinNames::FalseClass.name
375
- return method_type.with(
376
- return_type: AST::Types::Logic::Not.new(location: method_type.return_type.location)
377
- )
378
- end
361
+ when :nil?
362
+ case defined_in
363
+ when RBS::BuiltinNames::Object.name,
364
+ NilClassName
365
+ return method_type.with(
366
+ return_type: AST::Types::Logic::ReceiverIsNil.new(location: method_type.return_type.location)
367
+ )
368
+ end
379
369
 
380
- when :===
381
- case defined_in
382
- when RBS::BuiltinNames::Module.name
383
- return method_type.with(
384
- return_type: AST::Types::Logic::ArgIsReceiver.new(location: method_type.return_type.location)
385
- )
386
- end
370
+ when :!
371
+ case defined_in
372
+ when RBS::BuiltinNames::BasicObject.name,
373
+ RBS::BuiltinNames::TrueClass.name,
374
+ RBS::BuiltinNames::FalseClass.name
375
+ return method_type.with(
376
+ return_type: AST::Types::Logic::Not.new(location: method_type.return_type.location)
377
+ )
378
+ end
379
+
380
+ when :===
381
+ case defined_in
382
+ when RBS::BuiltinNames::Module.name
383
+ return method_type.with(
384
+ return_type: AST::Types::Logic::ArgIsReceiver.new(location: method_type.return_type.location)
385
+ )
387
386
  end
388
387
  end
389
388
  end
@@ -433,10 +432,13 @@ module Steep
433
432
 
434
433
  interface.methods[name] = Interface::Interface::Entry.new(
435
434
  method_types: method.defs.map do |type_def|
435
+ method_name = InstanceMethodName.new(type_name: type_def.implemented_in || type_def.defined_in, method_name: name)
436
+ decl = TypeInference::MethodCall::MethodDecl.new(method_name: method_name, method_def: type_def)
436
437
  setup_primitives(
437
438
  name,
439
+ type_def,
438
440
  method_type(type_def.type,
439
- method_def: type_def,
441
+ method_decls: Set[decl],
440
442
  self_type: self_type,
441
443
  subst2: subst)
442
444
  )
@@ -460,7 +462,11 @@ module Steep
460
462
  definition.methods.each do |name, method|
461
463
  interface.methods[name] = Interface::Interface::Entry.new(
462
464
  method_types: method.defs.map do |type_def|
463
- method_type(type_def.type, method_def: type_def, self_type: self_type, subst2: subst)
465
+ decls = Set[TypeInference::MethodCall::MethodDecl.new(
466
+ method_name: InstanceMethodName.new(type_name: type_def.implemented_in || type_def.defined_in, method_name: name),
467
+ method_def: type_def
468
+ )]
469
+ method_type(type_def.type, method_decls: decls, self_type: self_type, subst2: subst)
464
470
  end
465
471
  )
466
472
  end
@@ -485,10 +491,16 @@ module Steep
485
491
 
486
492
  interface.methods[name] = Interface::Interface::Entry.new(
487
493
  method_types: method.defs.map do |type_def|
494
+ decl = TypeInference::MethodCall::MethodDecl.new(
495
+ method_name: SingletonMethodName.new(type_name: type_def.implemented_in || type_def.defined_in,
496
+ method_name: name),
497
+ method_def: type_def
498
+ )
488
499
  setup_primitives(
489
500
  name,
501
+ type_def,
490
502
  method_type(type_def.type,
491
- method_def: type_def,
503
+ method_decls: Set[decl],
492
504
  self_type: self_type,
493
505
  subst2: subst)
494
506
  )
@@ -568,8 +580,7 @@ module Steep
568
580
  rest_keywords: nil),
569
581
  block: nil,
570
582
  return_type: elem_type,
571
- method_def: nil,
572
- location: nil
583
+ method_decls: Set[]
573
584
  )
574
585
  } + aref.method_types
575
586
  )
@@ -588,8 +599,7 @@ module Steep
588
599
  rest_keywords: nil),
589
600
  block: nil,
590
601
  return_type: elem_type,
591
- method_def: nil,
592
- location: nil
602
+ method_decls: Set[]
593
603
  )
594
604
  } + update.method_types
595
605
  )
@@ -603,8 +613,7 @@ module Steep
603
613
  params: Interface::Params.empty,
604
614
  block: nil,
605
615
  return_type: type.types[0] || AST::Builtin.nil_type,
606
- method_def: nil,
607
- location: nil
616
+ method_decls: Set[]
608
617
  )
609
618
  ]
610
619
  )
@@ -618,8 +627,7 @@ module Steep
618
627
  params: Interface::Params.empty,
619
628
  block: nil,
620
629
  return_type: type.types.last || AST::Builtin.nil_type,
621
- method_def: nil,
622
- location: nil
630
+ method_decls: Set[]
623
631
  )
624
632
  ]
625
633
  )
@@ -640,6 +648,7 @@ module Steep
640
648
  Interface::Interface::Entry.new(
641
649
  method_types: type.elements.map {|key_value, value_type|
642
650
  key_type = Literal.new(value: key_value, location: nil)
651
+
643
652
  Interface::MethodType.new(
644
653
  type_params: [],
645
654
  params: Interface::Params.new(required: [key_type],
@@ -650,8 +659,7 @@ module Steep
650
659
  rest_keywords: nil),
651
660
  block: nil,
652
661
  return_type: value_type,
653
- method_def: nil,
654
- location: nil
662
+ method_decls: Set[]
655
663
  )
656
664
  } + ref.method_types
657
665
  )
@@ -671,8 +679,7 @@ module Steep
671
679
  rest_keywords: nil),
672
680
  block: nil,
673
681
  return_type: value_type,
674
- method_def: nil,
675
- location: nil
682
+ method_decls: Set[]
676
683
  )
677
684
  } + update.method_types
678
685
  )
@@ -687,8 +694,7 @@ module Steep
687
694
  params: type.params,
688
695
  return_type: type.return_type,
689
696
  block: nil,
690
- method_def: nil,
691
- location: nil
697
+ method_decls: Set[]
692
698
  )
693
699
 
694
700
  interface.methods[:[]] = Interface::Interface::Entry.new(method_types: [method_type])
@@ -16,7 +16,7 @@ module Steep
16
16
  end
17
17
 
18
18
  def self.available_commands
19
- [:init, :check, :validate, :annotations, :version, :project, :watch, :langserver, :vendor]
19
+ [:init, :check, :validate, :annotations, :version, :project, :watch, :langserver, :vendor, :stats]
20
20
  end
21
21
 
22
22
  def process_global_options
@@ -91,6 +91,19 @@ module Steep
91
91
  end.run
92
92
  end
93
93
 
94
+ def process_stats
95
+ Drivers::Stats.new(stdout: stdout, stderr: stderr).tap do |check|
96
+ OptionParser.new do |opts|
97
+ opts.banner = "Usage: steep stats [options] [sources]"
98
+
99
+ opts.on("--steepfile=PATH") {|path| check.steepfile = Pathname(path) }
100
+ handle_logging_options opts
101
+ end.parse!(argv)
102
+
103
+ check.command_line_patterns.push *argv
104
+ end.run
105
+ end
106
+
94
107
  def process_validate
95
108
  Drivers::Validate.new(stdout: stdout, stderr: stderr).tap do |command|
96
109
  OptionParser.new do |opts|
@@ -0,0 +1,85 @@
1
+ require "csv"
2
+
3
+ module Steep
4
+ module Drivers
5
+ class Stats
6
+ attr_reader :stdout
7
+ attr_reader :stderr
8
+ attr_reader :command_line_patterns
9
+
10
+ include Utils::DriverHelper
11
+
12
+ def initialize(stdout:, stderr:)
13
+ @stdout = stdout
14
+ @stderr = stderr
15
+ @command_line_patterns = []
16
+ end
17
+
18
+ def run
19
+ project = load_config()
20
+
21
+ loader = Project::FileLoader.new(project: project)
22
+ loader.load_sources(command_line_patterns)
23
+ loader.load_signatures()
24
+
25
+ type_check(project)
26
+
27
+ stdout.puts(
28
+ CSV.generate do |csv|
29
+ csv << ["Target", "File", "Status", "Typed calls", "Untyped calls", "All calls", "Typed %"]
30
+
31
+ project.targets.each do |target|
32
+ case (status = target.status)
33
+ when Project::Target::TypeCheckStatus
34
+ status.type_check_sources.each do |source_file|
35
+ case source_file.status
36
+ when Project::SourceFile::TypeCheckStatus
37
+ typing = source_file.status.typing
38
+
39
+ typed = 0
40
+ untyped = 0
41
+ total = 0
42
+ typing.method_calls.each_value do |call|
43
+ case call
44
+ when TypeInference::MethodCall::Typed
45
+ typed += 1
46
+ when TypeInference::MethodCall::Untyped
47
+ untyped += 1
48
+ end
49
+
50
+ total += 1
51
+ end
52
+
53
+ csv << format_stats(target, source_file.path, "success", typed, untyped, total)
54
+ when Project::SourceFile::TypeCheckErrorStatus
55
+ csv << format_stats(target, source_file.path, "error", 0, 0, 0)
56
+ else
57
+ csv << format_stats(target, source_file.path, "unknown (#{source_file.status.class.to_s.split(/::/).last})", 0, 0, 0)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ )
64
+
65
+ 0
66
+ end
67
+
68
+ def format_stats(target, path, status, typed, untyped, total)
69
+ [
70
+ target.name,
71
+ path.to_s,
72
+ status,
73
+ typed,
74
+ untyped,
75
+ total,
76
+ if total.nonzero?
77
+ format("%.2f", (typed.to_f/total)*100)
78
+ else
79
+ 0
80
+ end
81
+ ]
82
+ end
83
+ end
84
+ end
85
+ end
@@ -101,20 +101,6 @@ module Steep
101
101
  end
102
102
  end
103
103
 
104
- class IncompatibleBlockParameters < Base
105
- attr_reader :node
106
- attr_reader :method_type
107
-
108
- def initialize(node:, method_type:)
109
- super(node: node)
110
- @method_type = method_type
111
- end
112
-
113
- def to_s
114
- "#{location_to_str}: IncompatibleBlockParameters: method_type=#{method_type}"
115
- end
116
- end
117
-
118
104
  class BlockParameterTypeMismatch < Base
119
105
  attr_reader :expected
120
106
  attr_reader :actual
@@ -186,7 +172,7 @@ module Steep
186
172
  end
187
173
 
188
174
  def to_s
189
- "#{location_to_str}: RequiredBlockMissing: method_type=#{method_type.location&.source}"
175
+ "#{location_to_str}: RequiredBlockMissing: method_type=#{method_type.to_s}"
190
176
  end
191
177
  end
192
178
 
@@ -557,5 +543,23 @@ module Steep
557
543
  "#{location_to_str}: UnsupportedSyntax: #{msg}"
558
544
  end
559
545
  end
546
+
547
+ class UnexpectedError < Base
548
+ attr_reader :message
549
+ attr_reader :error
550
+
551
+ def initialize(node:, error:)
552
+ super(node: node)
553
+ @error = error
554
+ @message = error.message
555
+ end
556
+
557
+ def to_s
558
+ <<-MESSAGE
559
+ #{location_to_str}: UnexpectedError: #{error.class}
560
+ >> #{message}
561
+ MESSAGE
562
+ end
563
+ end
560
564
  end
561
565
  end