typeprof 0.2.0 → 0.5.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.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +1 -2
  3. data/.gitignore +1 -0
  4. data/Gemfile +2 -2
  5. data/Gemfile.lock +10 -21
  6. data/LICENSE +21 -0
  7. data/README.md +6 -0
  8. data/doc/demo.md +398 -0
  9. data/doc/doc.ja.md +6 -1
  10. data/doc/doc.md +7 -2
  11. data/exe/typeprof +2 -1
  12. data/lib/typeprof.rb +9 -0
  13. data/lib/typeprof/analyzer.rb +427 -325
  14. data/lib/typeprof/arguments.rb +405 -0
  15. data/lib/typeprof/block.rb +136 -0
  16. data/lib/typeprof/builtin.rb +36 -25
  17. data/lib/typeprof/cli.rb +51 -98
  18. data/lib/typeprof/config.rb +114 -0
  19. data/lib/typeprof/container-type.rb +280 -92
  20. data/lib/typeprof/export.rb +197 -108
  21. data/lib/typeprof/import.rb +134 -80
  22. data/lib/typeprof/iseq.rb +42 -1
  23. data/lib/typeprof/method.rb +178 -82
  24. data/lib/typeprof/type.rb +228 -369
  25. data/lib/typeprof/utils.rb +4 -18
  26. data/lib/typeprof/version.rb +3 -0
  27. data/smoke/arguments2.rb +55 -0
  28. data/smoke/array-each3.rb +1 -4
  29. data/smoke/array12.rb +1 -1
  30. data/smoke/array6.rb +1 -0
  31. data/smoke/block-ambiguous.rb +36 -0
  32. data/smoke/block-args1-rest.rb +62 -0
  33. data/smoke/block-args1.rb +59 -0
  34. data/smoke/block-args2-rest.rb +62 -0
  35. data/smoke/block-args2.rb +59 -0
  36. data/smoke/block-args3-rest.rb +73 -0
  37. data/smoke/block-args3.rb +70 -0
  38. data/smoke/block-blockarg.rb +27 -0
  39. data/smoke/block-kwarg.rb +52 -0
  40. data/smoke/block10.rb +1 -1
  41. data/smoke/block11.rb +1 -1
  42. data/smoke/block14.rb +17 -0
  43. data/smoke/block4.rb +2 -2
  44. data/smoke/block5.rb +1 -0
  45. data/smoke/block6.rb +1 -1
  46. data/smoke/block7.rb +0 -2
  47. data/smoke/block8.rb +2 -2
  48. data/smoke/block9.rb +1 -1
  49. data/smoke/blown.rb +1 -1
  50. data/smoke/class-hierarchy.rb +54 -0
  51. data/smoke/class-hierarchy2.rb +27 -0
  52. data/smoke/constant1.rb +11 -6
  53. data/smoke/constant2.rb +2 -0
  54. data/smoke/cvar.rb +1 -0
  55. data/smoke/demo10.rb +1 -1
  56. data/smoke/demo8.rb +2 -2
  57. data/smoke/demo9.rb +1 -3
  58. data/smoke/flow7.rb +1 -7
  59. data/smoke/flow8.rb +13 -0
  60. data/smoke/hash-fetch.rb +3 -3
  61. data/smoke/hash-merge-bang.rb +11 -0
  62. data/smoke/hash1.rb +1 -1
  63. data/smoke/hash3.rb +1 -1
  64. data/smoke/hash4.rb +1 -1
  65. data/smoke/instance_eval.rb +1 -1
  66. data/smoke/int_times.rb +1 -1
  67. data/smoke/ivar2.rb +1 -1
  68. data/smoke/keyword3.rb +1 -2
  69. data/smoke/keyword4.rb +1 -1
  70. data/smoke/kwsplat1.rb +1 -1
  71. data/smoke/kwsplat2.rb +1 -1
  72. data/smoke/module4.rb +2 -0
  73. data/smoke/multiple-superclass.rb +4 -0
  74. data/smoke/next2.rb +1 -1
  75. data/smoke/optional1.rb +1 -1
  76. data/smoke/optional2.rb +1 -1
  77. data/smoke/optional3.rb +10 -0
  78. data/smoke/pattern-match1.rb +23 -0
  79. data/smoke/pattern-match2.rb +15 -0
  80. data/smoke/proc4.rb +1 -1
  81. data/smoke/rbs-extend.rb +9 -0
  82. data/smoke/rbs-extend.rbs +7 -0
  83. data/smoke/rbs-interface.rb +24 -0
  84. data/smoke/rbs-interface.rbs +12 -0
  85. data/smoke/rbs-proc1.rb +9 -0
  86. data/smoke/rbs-proc1.rbs +3 -0
  87. data/smoke/rbs-proc2.rb +20 -0
  88. data/smoke/rbs-proc2.rbs +3 -0
  89. data/smoke/rbs-proc3.rb +13 -0
  90. data/smoke/rbs-proc3.rbs +4 -0
  91. data/smoke/rbs-record.rb +17 -0
  92. data/smoke/rbs-record.rbs +4 -0
  93. data/smoke/rbs-tyvar.rb +18 -0
  94. data/smoke/rbs-tyvar.rbs +5 -0
  95. data/smoke/rbs-tyvar2.rb +20 -0
  96. data/smoke/rbs-tyvar2.rbs +9 -0
  97. data/smoke/rbs-tyvar3.rb +17 -0
  98. data/smoke/rbs-tyvar3.rbs +5 -0
  99. data/smoke/rbs-tyvar4.rb +36 -0
  100. data/smoke/rbs-tyvar5.rb +12 -0
  101. data/smoke/rbs-tyvar5.rbs +8 -0
  102. data/smoke/rest1.rb +1 -1
  103. data/smoke/rest2.rb +1 -1
  104. data/smoke/rest3.rb +1 -1
  105. data/smoke/rest5.rb +1 -1
  106. data/smoke/rest6.rb +1 -1
  107. data/smoke/retry1.rb +1 -1
  108. data/smoke/return.rb +1 -1
  109. data/smoke/singleton_method.rb +3 -0
  110. data/smoke/step.rb +1 -1
  111. data/smoke/struct.rb +4 -3
  112. data/smoke/struct3.rb +14 -0
  113. data/smoke/symbol-proc.rb +24 -0
  114. data/smoke/uninitialize-var.rb +12 -0
  115. data/smoke/user-demo.rb +15 -0
  116. data/smoke/wrong-extend.rb +1 -0
  117. data/typeprof.gemspec +4 -2
  118. metadata +53 -6
  119. data/run.sh +0 -3
  120. data/smoke/variadic1.rb.notyet +0 -5
@@ -0,0 +1,11 @@
1
+ def foo
2
+ h = { a: 42 }
3
+ h0 = h.merge!({ b: "str" })
4
+ return h0, h
5
+ end
6
+
7
+ __END__
8
+ # Classes
9
+ class Object
10
+ def foo : -> ([{b: Integer | String, a: Integer | String}, {a: Integer}])
11
+ end
@@ -13,6 +13,6 @@ bar
13
13
  __END__
14
14
  # Classes
15
15
  class Object
16
- def foo : -> {:int=>Integer, :str=>String}
16
+ def foo : -> {int: Integer, str: String}
17
17
  def bar : -> ({Integer=>Integer | String, String=>String})
18
18
  end
@@ -9,5 +9,5 @@ foo
9
9
  __END__
10
10
  # Classes
11
11
  class Object
12
- def foo : -> {:int=>Integer, :str=>String}
12
+ def foo : -> {int: Integer, str: String}
13
13
  end
@@ -6,5 +6,5 @@ foo
6
6
  __END__
7
7
  # Classes
8
8
  class Object
9
- def foo : -> Hash
9
+ def foo : -> {}
10
10
  end
@@ -13,6 +13,6 @@ end
13
13
  __END__
14
14
  # Classes
15
15
  class C
16
- def self.foo : -> C
16
+ def self.foo : { (C) -> nil } -> C
17
17
  def log : (Integer) -> nil
18
18
  end
@@ -1,7 +1,7 @@
1
1
  def foo(n)
2
2
  z = "str"
3
3
  n.times {|i| z = i }
4
- # TODO: n.times { z = 42 }
4
+ n.times { z = 42 }
5
5
  z
6
6
  end
7
7
 
@@ -24,7 +24,7 @@ __END__
24
24
  # Classes
25
25
  class Foo
26
26
  attr_reader array : Array[:sym | Integer | String]
27
- attr_reader hash : {:a=>Integer, :b=>String, :c=>:sym}
27
+ attr_reader hash : {a: Integer, b: String, c: :sym}
28
28
  def initialize : -> {}
29
29
  def set : -> :sym
30
30
  end
@@ -1,4 +1,3 @@
1
- # TODO: foo should accept "s: String | [Integer]"?
2
1
  def foo(n: 42, s: [n])
3
2
  [n, s]
4
3
  end
@@ -8,5 +7,5 @@ foo(n: 42, s: "str")
8
7
  __END__
9
8
  # Classes
10
9
  class Object
11
- def foo : (?n: Integer, ?s: String) -> ([Integer, String | [Integer]])
10
+ def foo : (?n: Integer, ?s: String | [Integer]) -> ([Integer, String | [Integer]])
12
11
  end
@@ -7,5 +7,5 @@ foo(n: 42, s: "str")
7
7
  __END__
8
8
  # Classes
9
9
  class Object
10
- def foo : (**{:n=>Integer, :s=>String}) -> nil
10
+ def foo : (**{n: Integer, s: String}) -> {n: Integer, s: String}
11
11
  end
@@ -37,6 +37,6 @@ smoke/kwsplat1.rb:30: [error] undefined method: Object#any
37
37
  class Object
38
38
  def foo : (k: Integer) -> nil
39
39
  def bar : (int: Integer, str: String) -> nil
40
- def baz : (**{:int=>Integer, :str=>String}) -> nil
40
+ def baz : (**{int: Integer, str: String}) -> nil
41
41
  def qux : (**{untyped=>untyped}) -> nil
42
42
  end
@@ -8,5 +8,5 @@ foo(*a, **h)
8
8
  __END__
9
9
  # Classes
10
10
  class Object
11
- def foo : (*Integer | {:k=>Integer}, k: Integer) -> nil
11
+ def foo : (*Integer | {k: Integer}, k: Integer) -> nil
12
12
  end
@@ -25,8 +25,10 @@ module M2
25
25
  end
26
26
 
27
27
  module M1
28
+ extend M2
28
29
  def foo : -> :m1_foo
29
30
  end
30
31
 
31
32
  class C
33
+ extend M1
32
34
  end
@@ -14,6 +14,10 @@ __END__
14
14
  smoke/multiple-superclass.rb:9: [warning] superclass is not a class; Object is used instead
15
15
 
16
16
  # Classes
17
+ class Object
18
+ Base : A.class | B.class
19
+ end
20
+
17
21
  class A
18
22
  end
19
23
 
@@ -12,5 +12,5 @@ end
12
12
  __END__
13
13
  # Classes
14
14
  class Object
15
- def foo : { () -> (Integer | String) } -> (Integer | String)
15
+ def foo : { -> (Integer | String) } -> (Integer | String)
16
16
  end
@@ -9,5 +9,5 @@ foo("A", "B", "C", "Z")
9
9
  __END__
10
10
  # Classes
11
11
  class Object
12
- def foo : (String, ?String, ?String, String) -> ([String, Integer | String, Integer | String, String])
12
+ def foo : (String, ?Integer | String, ?Integer | String, String) -> ([String, Integer | String, Integer | String, String])
13
13
  end
@@ -11,5 +11,5 @@ foo("A", "B", "C", "D", "E", "Z")
11
11
  __END__
12
12
  # Classes
13
13
  class Object
14
- def foo : (String, ?String, ?String, *String, String) -> ([String, Integer | String, Integer | String, Array[String], String])
14
+ def foo : (String, ?Integer | String, ?Integer | String, *String, String) -> ([String, Integer | String, Integer | String, Array[String], String])
15
15
  end
@@ -0,0 +1,10 @@
1
+ def foo(n = 1)
2
+ end
3
+
4
+ foo("str")
5
+
6
+ __END__
7
+ # Classes
8
+ class Object
9
+ def foo : (?Integer | String) -> nil
10
+ end
@@ -0,0 +1,23 @@
1
+ # RUBY_VERSION >= 3.0
2
+
3
+ def foo
4
+ case [:a, :b, :c]
5
+ in [a, b, :c]
6
+ # Due to very subtle detail of bytecode, the variables "a" and "b" could be nil
7
+ return a, b
8
+ end
9
+ end
10
+
11
+ foo
12
+
13
+ __END__
14
+ # Errors
15
+ smoke/pattern-match1.rb:5: [error] undefined method: nil#length
16
+ smoke/pattern-match1.rb:5: [error] undefined method: nil#[]
17
+ smoke/pattern-match1.rb:5: [error] undefined method: nil#[]
18
+ smoke/pattern-match1.rb:5: [error] undefined method: nil#[]
19
+
20
+ # Classes
21
+ class Object
22
+ def foo : -> ([:a | untyped, :b | untyped])
23
+ end
@@ -0,0 +1,15 @@
1
+ # RUBY_VERSION >= 3.0
2
+
3
+ def foo
4
+ case { a: :A, b: :B, c: :C }
5
+ in { a:, b: bb, c: :C }
6
+ return a, bb
7
+ end
8
+ end
9
+
10
+ foo
11
+ __END__
12
+ # Classes
13
+ class Object
14
+ def foo : -> [:A, :B]
15
+ end
@@ -7,5 +7,5 @@ foo(-> x { "str" })
7
7
  __END__
8
8
  # Classes
9
9
  class Object
10
- def foo : (Proc[(Integer) -> String]) -> String
10
+ def foo : (^(Integer) -> String) -> String
11
11
  end
@@ -0,0 +1,9 @@
1
+ def log
2
+ C.foo
3
+ end
4
+
5
+ __END__
6
+ # Classes
7
+ class Object
8
+ def log : -> Integer
9
+ end
@@ -0,0 +1,7 @@
1
+ module M
2
+ def foo: -> Integer
3
+ end
4
+
5
+ class C
6
+ extend M
7
+ end
@@ -0,0 +1,24 @@
1
+ def get_module
2
+ C.new.get_module
3
+ end
4
+
5
+ def get_module_foo
6
+ C.new.get_module.foo
7
+ end
8
+
9
+ def get_interface
10
+ C.new.get_interface
11
+ end
12
+
13
+ def get_interface_foo
14
+ C.new.get_interface.foo
15
+ end
16
+
17
+ __END__
18
+ # Classes
19
+ class Object
20
+ def get_module : -> M
21
+ def get_module_foo : -> Integer
22
+ def get_interface : -> _I
23
+ def get_interface_foo : -> Integer
24
+ end
@@ -0,0 +1,12 @@
1
+ module M
2
+ def foo: -> Integer
3
+ end
4
+
5
+ interface _I
6
+ def foo: -> Integer
7
+ end
8
+
9
+ class C
10
+ def get_module : -> M
11
+ def get_interface : -> _I
12
+ end
@@ -0,0 +1,9 @@
1
+ def log
2
+ Foo.new.foo.call(42)
3
+ end
4
+
5
+ __END__
6
+ # Classes
7
+ class Object
8
+ def log : -> Integer
9
+ end
@@ -0,0 +1,3 @@
1
+ class Foo
2
+ def foo: -> ^(Integer) -> Integer
3
+ end
@@ -0,0 +1,20 @@
1
+ # two issues:
2
+ # (1) TypedProc should call `-> n { log1(n) }` with an Integer, but not implemented yet
3
+ # (2) log1 returns a String, which is inconsistent and should be reported
4
+
5
+ def log1(n)
6
+ n.to_s # XXX: should be reported as "inconsistent with RBS"
7
+ end
8
+
9
+ def log2
10
+ Foo.new.foo(-> n { log1(n) })
11
+ end
12
+
13
+ log2
14
+
15
+ __END__
16
+ # Classes
17
+ class Object
18
+ def log1 : (untyped) -> untyped
19
+ def log2 : -> String
20
+ end
@@ -0,0 +1,3 @@
1
+ class Foo
2
+ def foo: (^(Integer) -> Integer) -> String
3
+ end
@@ -0,0 +1,13 @@
1
+ def log(foo)
2
+ foo.get.call
3
+ end
4
+
5
+ foo = Foo.new
6
+ foo.set(1)
7
+ log(foo)
8
+
9
+ __END__
10
+ # Classes
11
+ class Object
12
+ def log : (Foo[Integer]) -> Integer
13
+ end
@@ -0,0 +1,4 @@
1
+ class Foo[X]
2
+ def set: (X) -> void
3
+ def get: -> ^() -> X
4
+ end
@@ -0,0 +1,17 @@
1
+ def test_foo
2
+ h = C.new.foo
3
+ return h[:aaa], h[:bbb]
4
+ end
5
+
6
+ def test_bar
7
+ h = { }
8
+ h[:a] = 42
9
+ C.new.bar(h)
10
+ end
11
+
12
+ __END__
13
+ # Classes
14
+ class Object
15
+ def test_foo : -> [Integer, String]
16
+ def test_bar : -> Integer
17
+ end
@@ -0,0 +1,4 @@
1
+ class C
2
+ def foo: -> { aaa: Integer, bbb: String }
3
+ def bar: ({ a: Integer }) -> Integer
4
+ end
@@ -0,0 +1,18 @@
1
+ def foo
2
+ cell = Cell.new("str")
3
+ cell.set_elem(42) if rand < 0.5
4
+ cell
5
+ end
6
+
7
+ def bar
8
+ foo.get_elem
9
+ end
10
+
11
+ bar
12
+
13
+ __END__
14
+ # Classes
15
+ class Object
16
+ def foo : -> (Cell[Integer | String])
17
+ def bar : -> (Integer | String)
18
+ end
@@ -0,0 +1,5 @@
1
+ class Cell[T]
2
+ def initialize : (T) -> void
3
+ def set_elem : (T) -> void
4
+ def get_elem : -> T
5
+ end
@@ -0,0 +1,20 @@
1
+ def foo
2
+ cell = Cell.new(:a1, :b1, :c1)
3
+ cell.set_a(:a2)
4
+ cell.set_b(:b2)
5
+ cell.set_c(:c2)
6
+ cell
7
+ end
8
+
9
+ def bar
10
+ foo.get_b
11
+ end
12
+
13
+ bar
14
+
15
+ __END__
16
+ # Classes
17
+ class Object
18
+ def foo : -> (Cell[:a1 | :a2, :b1 | :b2, :c1 | :c2])
19
+ def bar : -> (:b1 | :b2)
20
+ end
@@ -0,0 +1,9 @@
1
+ class Cell[A, B, C]
2
+ def initialize : (A, B, C) -> void
3
+ def set_a : (A) -> void
4
+ def set_b : (B) -> void
5
+ def set_c : (C) -> void
6
+ def get_a : -> A
7
+ def get_b : -> B
8
+ def get_c : -> C
9
+ end
@@ -0,0 +1,17 @@
1
+ def foo
2
+ cell = Cell.new(42)
3
+ cell.map {|s| (s + 1).to_s }
4
+ end
5
+
6
+ def bar
7
+ cell = Cell.new(42)
8
+ cell.map! {|s| (s + 1).to_s }
9
+ cell
10
+ end
11
+
12
+ __END__
13
+ # Classes
14
+ class Object
15
+ def foo : -> Cell[String]
16
+ def bar : -> (Cell[Integer | String])
17
+ end
@@ -0,0 +1,5 @@
1
+ class Cell[T]
2
+ def initialize : (T) -> void
3
+ def map: [A] { (T) -> A } -> Cell[A]
4
+ def map!: { (T) -> T } -> self
5
+ end
@@ -0,0 +1,36 @@
1
+ # This code is created by simplifying matrix.rb.
2
+ # The issue occurs when `Array.new` creates a cell-type container,
3
+ # so this test will be obsolete, but keep it just for case of regression.
4
+ #
5
+ # https://github.com/ruby/typeprof/issues/14
6
+
7
+ class Foo
8
+ def initialize(ivar)
9
+ @ivar = ivar
10
+ end
11
+
12
+ def foo(n)
13
+ @ivar.each_with_index { }
14
+ nil
15
+ end
16
+ end
17
+
18
+ Foo.new([])
19
+
20
+ rows = Array.new(1) do |i|
21
+ Array.new(1) do |j|
22
+ "str"
23
+ end
24
+ end
25
+ obj = Foo.new(rows)
26
+
27
+ obj.foo(:a)
28
+ obj.foo(:b)
29
+
30
+ __END__
31
+ # Classes
32
+ class Foo
33
+ @ivar : Array[Array[String]]
34
+ def initialize : (Array[Array[String]]) -> Array[Array[String]]
35
+ def foo : (:a | :b) -> nil
36
+ end