steep 1.7.0.dev.3 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -0
  3. data/README.md +18 -0
  4. data/doc/narrowing.md +1 -1
  5. data/doc/shape.md +176 -0
  6. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +7 -24
  7. data/lib/steep/ast/types/factory.rb +27 -18
  8. data/lib/steep/ast/types/proc.rb +14 -9
  9. data/lib/steep/interface/block.rb +1 -1
  10. data/lib/steep/interface/builder.rb +1 -0
  11. data/lib/steep/interface/function.rb +14 -6
  12. data/lib/steep/interface/method_type.rb +15 -7
  13. data/lib/steep/project/pattern.rb +1 -2
  14. data/lib/steep/rake_task.rb +132 -0
  15. data/lib/steep/server/interaction_worker.rb +6 -0
  16. data/lib/steep/server/lsp_formatter.rb +2 -0
  17. data/lib/steep/services/completion_provider.rb +1 -1
  18. data/lib/steep/services/file_loader.rb +15 -20
  19. data/lib/steep/services/signature_help_provider.rb +11 -9
  20. data/lib/steep/signature/validator.rb +1 -1
  21. data/lib/steep/subtyping/check.rb +15 -6
  22. data/lib/steep/subtyping/variable_variance.rb +3 -3
  23. data/lib/steep/type_construction.rb +186 -149
  24. data/lib/steep/type_inference/block_params.rb +1 -1
  25. data/lib/steep/type_inference/logic_type_interpreter.rb +2 -1
  26. data/lib/steep/type_inference/method_params.rb +16 -0
  27. data/lib/steep/type_inference/send_args.rb +5 -2
  28. data/lib/steep/version.rb +1 -1
  29. data/steep.gemspec +5 -2
  30. metadata +7 -145
  31. data/.github/dependabot.yml +0 -28
  32. data/.github/workflows/ruby-windows.yml +0 -35
  33. data/.github/workflows/ruby.yml +0 -32
  34. data/.vscode/steep-shared.code-snippets +0 -41
  35. data/Gemfile +0 -14
  36. data/Gemfile.lock +0 -104
  37. data/Gemfile.steep +0 -0
  38. data/gemfile_steep/Gemfile +0 -3
  39. data/gemfile_steep/Gemfile.lock +0 -77
  40. data/rbs_collection.steep.lock.yaml +0 -108
  41. data/rbs_collection.steep.yaml +0 -23
  42. data/sig/shims/bundler.rbs +0 -3
  43. data/sig/shims/concurrent-ruby.rbs +0 -39
  44. data/sig/shims/exception.rbs +0 -4
  45. data/sig/shims/language-server_protocol.rbs +0 -450
  46. data/sig/shims/parser/comment.rbs +0 -33
  47. data/sig/shims/parser/nodes.rbs +0 -252
  48. data/sig/shims/parser/source/map.rbs +0 -146
  49. data/sig/shims/parser/source/range.rbs +0 -237
  50. data/sig/shims/parser.rbs +0 -69
  51. data/sig/shims/string.rbs +0 -4
  52. data/sig/shims/tagged_logging.rbs +0 -6
  53. data/sig/shims/yaml.rbs +0 -4
  54. data/sig/steep/annotation_parser.rbs +0 -60
  55. data/sig/steep/ast/annotation/collection.rbs +0 -78
  56. data/sig/steep/ast/annotation.rbs +0 -121
  57. data/sig/steep/ast/builtin.rbs +0 -69
  58. data/sig/steep/ast/ignore.rbs +0 -66
  59. data/sig/steep/ast/node/type_application.rbs +0 -31
  60. data/sig/steep/ast/node/type_assertion.rbs +0 -32
  61. data/sig/steep/ast/types/any.rbs +0 -29
  62. data/sig/steep/ast/types/boolean.rbs +0 -31
  63. data/sig/steep/ast/types/bot.rbs +0 -29
  64. data/sig/steep/ast/types/class.rbs +0 -33
  65. data/sig/steep/ast/types/factory.rbs +0 -110
  66. data/sig/steep/ast/types/helper.rbs +0 -24
  67. data/sig/steep/ast/types/instance.rbs +0 -33
  68. data/sig/steep/ast/types/intersection.rbs +0 -40
  69. data/sig/steep/ast/types/literal.rbs +0 -35
  70. data/sig/steep/ast/types/logic.rbs +0 -83
  71. data/sig/steep/ast/types/name.rbs +0 -84
  72. data/sig/steep/ast/types/nil.rbs +0 -31
  73. data/sig/steep/ast/types/proc.rbs +0 -53
  74. data/sig/steep/ast/types/record.rbs +0 -39
  75. data/sig/steep/ast/types/self.rbs +0 -33
  76. data/sig/steep/ast/types/top.rbs +0 -29
  77. data/sig/steep/ast/types/tuple.rbs +0 -37
  78. data/sig/steep/ast/types/union.rbs +0 -40
  79. data/sig/steep/ast/types/var.rbs +0 -42
  80. data/sig/steep/ast/types/void.rbs +0 -29
  81. data/sig/steep/ast/types.rbs +0 -16
  82. data/sig/steep/cli.rbs +0 -55
  83. data/sig/steep/diagnostic/deprecated/else_on_exhaustive_case.rbs +0 -13
  84. data/sig/steep/diagnostic/deprecated/unknown_constant_assigned.rbs +0 -15
  85. data/sig/steep/diagnostic/helper.rbs +0 -15
  86. data/sig/steep/diagnostic/lsp_formatter.rbs +0 -36
  87. data/sig/steep/diagnostic/ruby.rbs +0 -703
  88. data/sig/steep/diagnostic/signature.rbs +0 -252
  89. data/sig/steep/drivers/annotations.rbs +0 -17
  90. data/sig/steep/drivers/check.rbs +0 -33
  91. data/sig/steep/drivers/checkfile.rbs +0 -27
  92. data/sig/steep/drivers/diagnostic_printer.rbs +0 -25
  93. data/sig/steep/drivers/init.rbs +0 -19
  94. data/sig/steep/drivers/langserver.rbs +0 -36
  95. data/sig/steep/drivers/print_project.rbs +0 -15
  96. data/sig/steep/drivers/stats.rbs +0 -47
  97. data/sig/steep/drivers/utils/driver_helper.rbs +0 -25
  98. data/sig/steep/drivers/utils/jobs_option.rbs +0 -19
  99. data/sig/steep/drivers/validate.rbs +0 -15
  100. data/sig/steep/drivers/vendor.rbs +0 -19
  101. data/sig/steep/drivers/watch.rbs +0 -27
  102. data/sig/steep/drivers/worker.rbs +0 -29
  103. data/sig/steep/equatable.rbs +0 -11
  104. data/sig/steep/expectations.rbs +0 -72
  105. data/sig/steep/index/rbs_index.rbs +0 -141
  106. data/sig/steep/index/signature_symbol_provider.rbs +0 -41
  107. data/sig/steep/index/source_index.rbs +0 -63
  108. data/sig/steep/interface/block.rbs +0 -41
  109. data/sig/steep/interface/builder.rbs +0 -152
  110. data/sig/steep/interface/function.rbs +0 -270
  111. data/sig/steep/interface/method_type.rbs +0 -105
  112. data/sig/steep/interface/shape.rbs +0 -80
  113. data/sig/steep/interface/substitution.rbs +0 -51
  114. data/sig/steep/interface/type_param.rbs +0 -43
  115. data/sig/steep/method_name.rbs +0 -30
  116. data/sig/steep/module_helper.rbs +0 -16
  117. data/sig/steep/node_helper.rbs +0 -91
  118. data/sig/steep/path_helper.rbs +0 -15
  119. data/sig/steep/project/dsl.rbs +0 -108
  120. data/sig/steep/project/options.rbs +0 -47
  121. data/sig/steep/project/pattern.rbs +0 -47
  122. data/sig/steep/project/target.rbs +0 -25
  123. data/sig/steep/project.rbs +0 -26
  124. data/sig/steep/range_extension.rbs +0 -7
  125. data/sig/steep/server/base_worker.rbs +0 -49
  126. data/sig/steep/server/change_buffer.rbs +0 -38
  127. data/sig/steep/server/delay_queue.rbs +0 -37
  128. data/sig/steep/server/interaction_worker.rbs +0 -90
  129. data/sig/steep/server/lsp_formatter.rbs +0 -63
  130. data/sig/steep/server/master.rbs +0 -299
  131. data/sig/steep/server/type_check_worker.rbs +0 -141
  132. data/sig/steep/server/worker_process.rbs +0 -97
  133. data/sig/steep/services/completion_provider.rbs +0 -264
  134. data/sig/steep/services/content_change.rbs +0 -37
  135. data/sig/steep/services/file_loader.rbs +0 -21
  136. data/sig/steep/services/goto_service.rbs +0 -106
  137. data/sig/steep/services/hover_provider/rbs.rbs +0 -47
  138. data/sig/steep/services/hover_provider/ruby.rbs +0 -127
  139. data/sig/steep/services/hover_provider/singleton_methods.rbs +0 -11
  140. data/sig/steep/services/path_assignment.rbs +0 -21
  141. data/sig/steep/services/signature_help_provider.rbs +0 -51
  142. data/sig/steep/services/signature_service.rbs +0 -156
  143. data/sig/steep/services/stats_calculator.rbs +0 -41
  144. data/sig/steep/services/type_check_service.rbs +0 -112
  145. data/sig/steep/services/type_name_completion.rbs +0 -135
  146. data/sig/steep/signature/validator.rbs +0 -85
  147. data/sig/steep/source/ignore_ranges.rbs +0 -38
  148. data/sig/steep/source.rbs +0 -105
  149. data/sig/steep/subtyping/cache.rbs +0 -17
  150. data/sig/steep/subtyping/check.rbs +0 -131
  151. data/sig/steep/subtyping/constraints.rbs +0 -111
  152. data/sig/steep/subtyping/relation.rbs +0 -63
  153. data/sig/steep/subtyping/result.rbs +0 -179
  154. data/sig/steep/subtyping/variable_variance.rbs +0 -25
  155. data/sig/steep/thread_waiter.rbs +0 -13
  156. data/sig/steep/type_construction.rbs +0 -542
  157. data/sig/steep/type_inference/block_params.rbs +0 -170
  158. data/sig/steep/type_inference/case_when.rbs +0 -130
  159. data/sig/steep/type_inference/constant_env.rbs +0 -29
  160. data/sig/steep/type_inference/context.rbs +0 -216
  161. data/sig/steep/type_inference/context_array.rbs +0 -38
  162. data/sig/steep/type_inference/logic_type_interpreter.rbs +0 -108
  163. data/sig/steep/type_inference/method_call.rbs +0 -124
  164. data/sig/steep/type_inference/method_params.rbs +0 -127
  165. data/sig/steep/type_inference/multiple_assignment.rbs +0 -76
  166. data/sig/steep/type_inference/send_args.rbs +0 -243
  167. data/sig/steep/type_inference/type_env.rbs +0 -160
  168. data/sig/steep/type_inference/type_env_builder.rbs +0 -81
  169. data/sig/steep/typing.rbs +0 -75
  170. data/sig/steep.rbs +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c30f769d118a31c069ae146f976dc3df96b71acfa50659e6f03b00bdc1624da7
4
- data.tar.gz: '064953d68e749654f069f2ea215746366a58506406ec5977826f5cf73552f779'
3
+ metadata.gz: ee680022ab2333d1fcfeff84ee0513c389ccfb6cf52fbc04f3f53edace112931
4
+ data.tar.gz: 400fd763d24b8154fea38900c988cf651c6a0e646485a1aa4d4e6c5ba285a453
5
5
  SHA512:
6
- metadata.gz: 4ce31d8368b84b72284eb331606a6f1c15b3843a2c13a01770bcac35c4f9fa35ab5a62617a4d13c913c482b1775fc043265a8fbdb5a58e7598e9ad92a2246fda
7
- data.tar.gz: 206491dcd015533b092afe61277f48e28e288693c9ffadaa85aa855b0616ab9f64ba7001b297a7387432fec3492aed55f16ac5ebba3b379cb7bf79575249700c
6
+ metadata.gz: 6836114d1f2e78eea1b2d19528a480ca234cc02f1339d8c70543e20a6c7b969d59b11a9434290e0fa2a4116ffe8f2b646bb0a9c642a0978102e5752be06ae808
7
+ data.tar.gz: 0476bc765f54bba0442aafdd08a64c2985a0d16fe25efaac69f9c3ddad8cca44628d78d1fb62e2c5e0727627cdcddd1a7cdc5987e3de6ef4cdc1e1a5761bcb99
data/CHANGELOG.md CHANGED
@@ -1,5 +1,48 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.7.0 (2024-06-07)
4
+
5
+ ### Type checker core
6
+
7
+ * Implement untyped function params ([#1101](https://github.com/soutaro/steep/pull/1101))
8
+ * Fix method call type narrowing with`||` operator ([#1085](https://github.com/soutaro/steep/pull/1085))
9
+ * Refactor `Interface::Builder` ([#1081](https://github.com/soutaro/steep/pull/1081))
10
+ * Fix UnexpectedError with unnamed arguments ([#1041](https://github.com/soutaro/steep/pull/1041))
11
+ * Abort if subtyping fails to (possible) infinite loop ([#1055](https://github.com/soutaro/steep/pull/1055))
12
+ * Ignore diagnostics by `steep:ignore` comment ([#1034](https://github.com/soutaro/steep/pull/1034))
13
+ * Make defined? accept any type ([#1031](https://github.com/soutaro/steep/pull/1031))
14
+ * Refactor case-when syntax ([#999](https://github.com/soutaro/steep/pull/999))
15
+ * Update `Steep::Subtyping::Check#check` types ([#972](https://github.com/soutaro/steep/pull/972))
16
+
17
+ ### Commandline tool
18
+
19
+ * Improve wildcard handling in pattern matching for directory paths ([#1121](https://github.com/soutaro/steep/pull/1121))
20
+ * Fix issue with wildcard expansion in FileLoader ([#1113](https://github.com/soutaro/steep/pull/1113))
21
+ * Avoid unnecessary calling `RBS::Location#to_s` on debug log ([#1092](https://github.com/soutaro/steep/pull/1092))
22
+ * Better recovery from collection problems ([#987](https://github.com/soutaro/steep/pull/987))
23
+ * Handle absolute path ([#975](https://github.com/soutaro/steep/pull/975))
24
+ * Default to check the entire current directory when there is no `Steepfile` ([#968](https://github.com/soutaro/steep/pull/968))
25
+
26
+ ### Language server
27
+
28
+ * Fix variable untyped hover issue in rescue clause ([#1147](https://github.com/soutaro/steep/pull/1147))
29
+ * Handle `$/file/reset` request in interaction worker ([#1122](https://github.com/soutaro/steep/pull/1122))
30
+ * Skip pending UI jobs ([#1035](https://github.com/soutaro/steep/pull/1035))
31
+ * Fix no method error ([#1040](https://github.com/soutaro/steep/pull/1040))
32
+ * Implement completion for comments ([#1039](https://github.com/soutaro/steep/pull/1039))
33
+ * Fix signature help ([#1038](https://github.com/soutaro/steep/pull/1038))
34
+
35
+ ### Miscellaneous
36
+
37
+ * Revise rake tasks ([#1156](https://github.com/soutaro/steep/pull/1156))
38
+ * Update `steep.gemspec` ([#1155](https://github.com/soutaro/steep/pull/1155))
39
+ * Add `Steep::RakeTask` ([#995](https://github.com/soutaro/steep/pull/995))
40
+ * Stop to distribute sig dir ([#1144](https://github.com/soutaro/steep/pull/1144))
41
+ * Update gem-rbs-collection.md ([#1127](https://github.com/soutaro/steep/pull/1127))
42
+ * Add shape docs ([#1089](https://github.com/soutaro/steep/pull/1089))
43
+ * Ignore smoke tests when packaging gem ([#962](https://github.com/soutaro/steep/pull/962))
44
+ * Fix setup for Ruby 3.3 ([#1000](https://github.com/soutaro/steep/pull/1000))
45
+
3
46
  ## master
4
47
 
5
48
  ## 1.6.0 (2023-11-09)
data/README.md CHANGED
@@ -219,6 +219,24 @@ Steep implements some of the Language Server Protocol features.
219
219
 
220
220
  Other LSP supporting tools may work with Steep where it starts the server as `steep langserver`.
221
221
 
222
+ ## Rake Tasks
223
+
224
+ Steep comes with a set of configurable Rake tasks.
225
+
226
+ ```ruby
227
+ # Rakefile
228
+
229
+ require "steep/rake_task"
230
+ Steep::RakeTask.new do |t|
231
+ t.check.severity_level = :error
232
+ t.watch.verbose
233
+ end
234
+
235
+ task default: [:steep]
236
+ ```
237
+
238
+ Use `bundle exec rake -T` to see all available tasks.
239
+
222
240
  ## Development
223
241
 
224
242
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/doc/narrowing.md CHANGED
@@ -65,7 +65,7 @@ It immediately type checks the left hand side, but with *conditional mode*. Cond
65
65
  x && y
66
66
  ```
67
67
 
68
- Going down again, it gets a typing `x: String?` and `y: String?. It runs a type narrowing, to obtain a result both of `x` and `y` are `String` for truthy result, both of `x` and `y` are `String?` for falsy result. The two environments should be propagated to the upper node, because the parent node is also `&&` which is a subject of type narrowing. So, it returns an `ENV` type, `String?` for original type, `{ x: String, y: String }` for truthy result, and `{ x: String?, y: String? }` for falsy result.
68
+ Going down again, it gets a typing `x: String?` and `y: String?`. It runs a type narrowing, to obtain a result both of `x` and `y` are `String` for truthy result, both of `x` and `y` are `String?` for falsy result. The two environments should be propagated to the upper node, because the parent node is also `&&` which is a subject of type narrowing. So, it returns an `ENV` type, `String?` for original type, `{ x: String, y: String }` for truthy result, and `{ x: String?, y: String? }` for falsy result.
69
69
 
70
70
  Going up to the outer `&&` expression. The left hand side has `ENV` type, and then the right hand side is type checked based on the truthy environment (because of the semantics of `&&` expression.) Both `x` and `y` are `String` and it type checks. The type of the whole expression union of `String` and the falsy part of the original type -- `nil`.
71
71
  ## Union type partition
data/doc/shape.md ADDED
@@ -0,0 +1,176 @@
1
+ # Shapes
2
+
3
+ A *shape* is a data structure, which contains the set of available methods and their types, which is associated with a type. Steep uses shapes to type check method calls -- it calculates the shape of the type of the receiver, checks if the called method is defined on the shape and the arguments are compatible with the method, and calculates the return type.
4
+
5
+ Assume an interface `_Foo` is defined as follows:
6
+
7
+ ```rbs
8
+ interface _Foo
9
+ def foo: () -> String
10
+
11
+ def bar: () -> self
12
+ end
13
+ ```
14
+
15
+ The shape of `_Foo` will be the following:
16
+
17
+ ```
18
+ Shape (_Foo) {
19
+ foo: () -> String,
20
+ bar: () -> _Foo
21
+ }
22
+ ```
23
+
24
+ Note that the `self` type in the example is resolved to `_Foo` during shape calculation.
25
+
26
+ The shape calculation of an object is straightforward. Calculate a `RBS::Definition` of a class singleton/instance, or an interface, and translate the data structure to a `Shape` object. But there are a few things to consider.
27
+ ## Tuple, record, and proc types
28
+ The shape of tuple, record, or proc types are based on their base types -- Array, Hash, or Proc classes --, but with specialized method types.
29
+
30
+ ```
31
+ Shape ([Integer, String]) {
32
+ []: (0) -> Integer
33
+ | (1) -> String
34
+ | (Integer) -> (Integer | String)
35
+ ...
36
+ }
37
+ ```
38
+
39
+ The specialization is implemented as a part of shape calculation.
40
+ ## Special methods
41
+ Steep recognizes some special methods for type narrowing, including `#is_a?`, `#===`, `#nil?`, ... These methods are defined with normal RBS syntax, but the method types in shapes are transformed to types using logic types.
42
+
43
+ The shape calculation inserts the specialized methods with these special methods.
44
+ ## `self` types
45
+ There are two cases of `self` types to consider during shape calculation.
46
+
47
+ 1. `self` types included in the shape of a type
48
+ 2. `self` types included in given types
49
+ ### 1. `self` types included in the shape of a type
50
+ `self` types may be included in a class or interface definition.
51
+
52
+ ```rbs
53
+ interface _Foo
54
+ def itself: () -> self
55
+ end
56
+ ```
57
+
58
+ The `self` types included in the shape of `_Foo` type should be resolved to `_Foo` type.
59
+
60
+ ```
61
+ Shape (_Foo) {
62
+ itself: () -> _Foo
63
+ }
64
+ ```
65
+ ### 2. `self` types included in given types
66
+ Unlike `self` types included in definitions, `self` types in given types should be preserved.
67
+
68
+ ```rbs
69
+ interface _Foo[A]
70
+ def get: () -> A
71
+ end
72
+ ```
73
+
74
+ The shape of `_Foo[self]` has `self` type as its type argument, and we want the `self` type preserved after the shape calculation.
75
+
76
+ ```
77
+ Shape (_Foo[self]) {
78
+ get: () -> self
79
+ }
80
+ ```
81
+
82
+ We often use `self` types as the return type of a method.
83
+
84
+ ```rbs
85
+ class Foo
86
+ def foo: () -> self
87
+ end
88
+ ```
89
+
90
+ So, the implementation of `foo` might use `self` node to return `self` type.
91
+
92
+ ```rb
93
+ class Foo
94
+ def foo
95
+ # @type var foo: _Foo[self]
96
+ foo = ...
97
+ foo.get
98
+ end
99
+ end
100
+ ```
101
+
102
+ We want the type of `foo.get` to be `self`, not `Foo`, to avoid a type error being detected.
103
+ ## Shape of `self` types
104
+ We also want `self` type if `self` is the type of the shape.
105
+
106
+ ```rb
107
+ class Foo
108
+ def foo
109
+ self.itself
110
+ end
111
+ end
112
+ ```
113
+
114
+ This is a straightforward case, because the type of `self` is `self` itself. Calculate the shape of it, but keep the `self` types in the shape.
115
+
116
+ ```
117
+ Shape (self) {
118
+ itself: () -> self
119
+ }
120
+ ```
121
+
122
+ If `self` is a union type, or something built with a type constructor, the shape calculation gets complicated.
123
+
124
+ ```rbs
125
+ class Foo
126
+ def foo: () -> Integer
127
+ end
128
+
129
+ class Bar
130
+ def foo: () -> self
131
+ end
132
+ ```
133
+
134
+ What is the expected shape of `self` where the type of `self` is `Foo | Bar`?
135
+
136
+ The shape of a union type is straightforward. It calculates the shape of each type, and then it calculates a union of the shape.
137
+
138
+ We do the same for the case with `self` types, but it results in slightly incorrect shapes.
139
+
140
+ ```
141
+ Shape (Foo) {
142
+ foo: () -> Integer
143
+ }
144
+
145
+ Shape (Bar) {
146
+ foo: () -> self # self is preserved, because the shape of `self` is being calculated
147
+ }
148
+
149
+ Shape (Foo | Bar) {
150
+ foo: () -> (Integer | self)
151
+ }
152
+ ```
153
+
154
+ So, the resulting type of `self.foo` where the type of `self` is `Foo | Bar`, would be `Integer | Foo | Bar`. But, actually, it won't be `Foo` because the `self` comes from `Bar`.
155
+
156
+ This is an incorrect result, but Steep is doing this right now.
157
+ ## `class` and `instance` types
158
+ The shape calculation provides limited support for `class` and `instance` types.
159
+
160
+ 1. `class`/`instance` types from the definition are resolved
161
+ 2. `class`/`instance` types in generics type arguments of interfaces/instances are preserved
162
+ 3. Shape of `class`/`instance` types are resolved to configuration's `class_type` and `instance_type`, and the translated types are used to calculate the shape
163
+
164
+ It's different from `self` types except case #2. The relationship between `self`/`class`/`instance` is not trivial in Ruby. All of them might be resolved to any type, which means calculating one from another of them is simply impossible.
165
+ ## Public methods, private methods
166
+ `Shape` objects have a flag of if the shape is for *public* method calls or *private* method calls. Private method call is a form of `foo()` or `self.foo()` -- when the receiver is omitted or `self`. Public method calls are anything else.
167
+
168
+ The shape calculation starts with *private methods*, and the `Shape#public_shape` method returns another shape that only has *public* methods.
169
+
170
+ > Note that the private shape calculation is required even on public method calls. This means a possible chance of future optimizations.
171
+ ## Lazy method type calculation
172
+ We rarely need all of the methods available for an object. If we want to type check a method call, we only need the method type of that method. All other methods can be just ignored.
173
+
174
+ *Lazy method type calculation* is introduced for that case. Instead of calculating the types of all of the methods, it registers a block that computes the method type.
175
+
176
+ It is implemented in `Steep::Interface::Shape::Entry` and used to make the shape calculation of a union type faster.
@@ -12,30 +12,13 @@ Run rbs-collection-init to start setup.
12
12
  $ rbs collection init
13
13
  ```
14
14
 
15
- You have to edit the generated `rbs_collection.yaml` file. Add a few lines under gems section.
16
-
17
- ```yaml
18
- # Download sources
19
- sources:
20
- - name: ruby/gem_rbs_collection
21
- remote: https://github.com/ruby/gem_rbs_collection.git
22
- revision: main
23
- repo_dir: gems
24
-
25
- # A directory to install the downloaded RBSs
26
- path: .gem_rbs_collection
27
-
28
- gems:
29
- # Skip loading rbs gem's RBS.
30
- # It's unnecessary if you don't use rbs as a library.
31
- - name: rbs
32
- ignore: true
33
- - name: steep
34
- ignore: true
35
- - name: rbs_rails # Add these lines if you use rbs_rails
36
- ignore: true
37
- - name: rbs_protobuf # Add these lines if you use rbs_protobuf
38
- ignore: true
15
+ You have to edit your `Gemfile`. Specify `require: false` for gems for which you do not want type definitions.
16
+
17
+ ```ruby
18
+ gem 'rbs', require: false
19
+ gem 'steep, require: false
20
+ gem 'rbs_rails', require: false
21
+ gem 'rbs_protobuf', require: false
39
22
  ```
40
23
 
41
24
  Once you save the file, run the install command.
@@ -212,27 +212,36 @@ module Steep
212
212
  params = func.params
213
213
  return_type = func.return_type
214
214
 
215
- RBS::Types::Function.new(
216
- required_positionals: params.required.map {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
217
- optional_positionals: params.optional.map {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
218
- rest_positionals: params.rest&.yield_self {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
219
- trailing_positionals: [],
220
- required_keywords: params.required_keywords.transform_values {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
221
- optional_keywords: params.optional_keywords.transform_values {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
222
- rest_keywords: params.rest_keywords&.yield_self {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
223
- return_type: type_1(return_type)
224
- )
215
+ if params
216
+ RBS::Types::Function.new(
217
+ required_positionals: params.required.map {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
218
+ optional_positionals: params.optional.map {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
219
+ rest_positionals: params.rest&.yield_self {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
220
+ trailing_positionals: [],
221
+ required_keywords: params.required_keywords.transform_values {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
222
+ optional_keywords: params.optional_keywords.transform_values {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
223
+ rest_keywords: params.rest_keywords&.yield_self {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
224
+ return_type: type_1(return_type)
225
+ )
226
+ else
227
+ RBS::Types::UntypedFunction.new(return_type: type_1(return_type))
228
+ end
225
229
  end
226
230
 
227
231
  def params(type)
228
- Interface::Function::Params.build(
229
- required: type.required_positionals.map {|param| type(param.type) },
230
- optional: type.optional_positionals.map {|param| type(param.type) },
231
- rest: type.rest_positionals&.yield_self {|param| type(param.type) },
232
- required_keywords: type.required_keywords.transform_values {|param| type(param.type) },
233
- optional_keywords: type.optional_keywords.transform_values {|param| type(param.type) },
234
- rest_keywords: type.rest_keywords&.yield_self {|param| type(param.type) }
235
- )
232
+ case type
233
+ when RBS::Types::Function
234
+ Interface::Function::Params.build(
235
+ required: type.required_positionals.map {|param| type(param.type) },
236
+ optional: type.optional_positionals.map {|param| type(param.type) },
237
+ rest: type.rest_positionals&.yield_self {|param| type(param.type) },
238
+ required_keywords: type.required_keywords.transform_values {|param| type(param.type) },
239
+ optional_keywords: type.optional_keywords.transform_values {|param| type(param.type) },
240
+ rest_keywords: type.rest_keywords&.yield_self {|param| type(param.type) }
241
+ )
242
+ when RBS::Types::UntypedFunction
243
+ nil
244
+ end
236
245
  end
237
246
 
238
247
  def type_param(type_param)
@@ -57,9 +57,11 @@ module Steep
57
57
  include Helper::ChildrenLevel
58
58
 
59
59
  def level
60
- children = type.params.each_type.to_a + [type.return_type]
60
+ children = type.params&.each_type.to_a + [type.return_type]
61
61
  if block
62
- children.push(*block.type.params.each_type.to_a)
62
+ if block.type.params
63
+ children.push(*block.type.params.each_type.to_a)
64
+ end
63
65
  children.push(block.type.return_type)
64
66
  end
65
67
  if self_type
@@ -83,13 +85,16 @@ module Steep
83
85
 
84
86
  def one_arg?
85
87
  params = type.params
86
-
87
- params.required.size == 1 &&
88
- params.optional.empty? &&
89
- !params.rest &&
90
- params.required_keywords.empty? &&
91
- params.optional_keywords.empty? &&
92
- !params.rest_keywords
88
+ if params
89
+ params.required.size == 1 &&
90
+ params.optional.empty? &&
91
+ !params.rest &&
92
+ params.required_keywords.empty? &&
93
+ params.optional_keywords.empty? &&
94
+ !params.rest_keywords
95
+ else
96
+ true
97
+ end
93
98
  end
94
99
 
95
100
  def back_type
@@ -82,7 +82,7 @@ module Steep
82
82
  def +(other)
83
83
  optional = self.optional? || other.optional?
84
84
  type = Function.new(
85
- params: self.type.params + other.type.params,
85
+ params: self.type.params && other.type.params ? self.type.params + other.type.params : nil,
86
86
  return_type: AST::Types::Union.build(types: [self.type.return_type, other.type.return_type]),
87
87
  location: nil
88
88
  )
@@ -62,6 +62,7 @@ module Steep
62
62
  def shape(type, config)
63
63
  Steep.logger.tagged "shape(#{type})" do
64
64
  if shape = raw_shape(type, config)
65
+ # Optimization that skips unnecesary substittuion
65
66
  if type.free_variables.include?(AST::Types::Self.instance)
66
67
  shape
67
68
  else
@@ -1008,7 +1008,7 @@ module Steep
1008
1008
  def free_variables
1009
1009
  @fvs ||= Set[].tap do |fvs|
1010
1010
  # @type var fvs: Set[AST::Types::variable]
1011
- fvs.merge(params.free_variables)
1011
+ fvs.merge(params.free_variables) if params
1012
1012
  fvs.merge(return_type.free_variables)
1013
1013
  end
1014
1014
  end
@@ -1016,7 +1016,7 @@ module Steep
1016
1016
  def subst(s)
1017
1017
  return self if s.empty?
1018
1018
 
1019
- ps = params.subst(s)
1019
+ ps = params.subst(s) if params
1020
1020
  ret = return_type.subst(s)
1021
1021
 
1022
1022
  if ps == params && ret == return_type
@@ -1032,7 +1032,7 @@ module Steep
1032
1032
 
1033
1033
  def each_type(&block)
1034
1034
  if block
1035
- params.each_type(&block)
1035
+ params&.each_type(&block)
1036
1036
  yield return_type
1037
1037
  else
1038
1038
  enum_for :each_type
@@ -1043,7 +1043,7 @@ module Steep
1043
1043
 
1044
1044
  def map_type(&block)
1045
1045
  Function.new(
1046
- params: params.map_type(&block),
1046
+ params: params&.map_type(&block),
1047
1047
  return_type: yield(return_type),
1048
1048
  location: location
1049
1049
  )
@@ -1058,11 +1058,19 @@ module Steep
1058
1058
  end
1059
1059
 
1060
1060
  def to_s
1061
- "#{params} -> #{return_type}"
1061
+ if params
1062
+ "#{params} -> #{return_type}"
1063
+ else
1064
+ "(?) -> #{return_type}"
1065
+ end
1062
1066
  end
1063
1067
 
1064
1068
  def closed?
1065
- params.closed? && return_type.free_variables.empty?
1069
+ if params
1070
+ params.closed? && return_type.free_variables.empty?
1071
+ else
1072
+ return_type.free_variables.empty?
1073
+ end
1066
1074
  end
1067
1075
  end
1068
1076
  end
@@ -61,7 +61,7 @@ module Steep
61
61
  type.each_type(&block)
62
62
  if block()
63
63
  yield(block().self_type) if block().self_type
64
- block().type.params.each_type(&block)
64
+ block().type.params&.each_type(&block)
65
65
  yield(block().type.return_type)
66
66
  end
67
67
  else
@@ -119,7 +119,7 @@ module Steep
119
119
  self.class.new(
120
120
  type_params: type_params,
121
121
  type: Function.new(
122
- params: type.params.subst(s1) + other.type.params.subst(s2),
122
+ params: type.params && other.type.params ? type.params.subst(s1) + other.type.params.subst(s2) : nil,
123
123
  return_type: AST::Types::Union.build(
124
124
  types: [type.return_type.subst(s1), other.type.return_type.subst(s2)]
125
125
  ),
@@ -250,10 +250,13 @@ module Steep
250
250
  nil
251
251
  end
252
252
 
253
- # Return when the two block parameters are imcompatible.
254
- return unless b.type.params & ob.type.params
255
-
256
- block_params = b.type.params | ob.type.params or return
253
+ if b.type.params && ob.type.params
254
+ # Return when the two block parameters are imcompatible.
255
+ return unless b.type.params & ob.type.params
256
+ block_params = b.type.params | ob.type.params or return
257
+ else
258
+ block_params = b.type.params || ob.type.params
259
+ end
257
260
 
258
261
  block_return_type = AST::Types::Intersection.build(types: [b.type.return_type, ob.type.return_type])
259
262
  block_type = Function.new(params: block_params, return_type: block_return_type, location: nil)
@@ -285,7 +288,12 @@ module Steep
285
288
  def &(other)
286
289
  return self if self == other
287
290
 
288
- params = self.type.params | other.type.params or return
291
+ if self.type.params && other.type.params
292
+ params = self.type.params | other.type.params or return
293
+ else
294
+ params = self.type.params || other.type.params
295
+ end
296
+
289
297
  block =
290
298
  case
291
299
  when (b = self.block) && (ob = other.block)
@@ -46,10 +46,9 @@ module Steep
46
46
 
47
47
  def test_string(path, patterns, prefixes)
48
48
  string = path.to_s
49
- extension = path.extname
50
49
 
51
50
  patterns.any? {|pat| File.fnmatch(pat, string, File::FNM_PATHNAME) } ||
52
- prefixes.any? {|prefix| string.start_with?(prefix) && extension == ext }
51
+ prefixes.any? {|prefix| File.fnmatch("#{prefix}**/*#{ext}", string, File::FNM_PATHNAME) }
53
52
  end
54
53
  end
55
54
  end