steep 0.15.0 → 0.17.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/.gitmodules +0 -3
- data/CHANGELOG.md +25 -0
- data/Rakefile +0 -13
- data/bin/setup +0 -2
- data/bin/smoke_runner.rb +0 -1
- data/exe/steep +0 -1
- data/lib/steep.rb +12 -1
- data/lib/steep/cli.rb +16 -1
- data/lib/steep/drivers/annotations.rb +1 -1
- data/lib/steep/drivers/check.rb +1 -12
- data/lib/steep/drivers/langserver.rb +13 -462
- data/lib/steep/drivers/utils/driver_helper.rb +1 -1
- data/lib/steep/drivers/watch.rb +97 -85
- data/lib/steep/drivers/worker.rb +51 -0
- data/lib/steep/project.rb +9 -5
- data/lib/steep/project/completion_provider.rb +4 -2
- data/lib/steep/project/file.rb +2 -1
- data/lib/steep/project/hover_content.rb +6 -3
- data/lib/steep/project/options.rb +15 -0
- data/lib/steep/project/target.rb +30 -20
- data/lib/steep/server/base_worker.rb +56 -0
- data/lib/steep/server/code_worker.rb +151 -0
- data/lib/steep/server/interaction_worker.rb +281 -0
- data/lib/steep/server/master.rb +196 -0
- data/lib/steep/server/signature_worker.rb +148 -0
- data/lib/steep/server/utils.rb +36 -0
- data/lib/steep/server/worker_process.rb +62 -0
- data/lib/steep/signature/validator.rb +5 -5
- data/lib/steep/type_construction.rb +13 -19
- data/lib/steep/type_inference/constant_env.rb +2 -10
- data/lib/steep/type_inference/context.rb +1 -0
- data/lib/steep/version.rb +1 -1
- data/steep.gemspec +7 -8
- metadata +22 -142
- data/exe/rbs +0 -3
- data/vendor/ruby-signature/.github/workflows/ruby.yml +0 -27
- data/vendor/ruby-signature/.gitignore +0 -12
- data/vendor/ruby-signature/.rubocop.yml +0 -15
- data/vendor/ruby-signature/BSDL +0 -22
- data/vendor/ruby-signature/COPYING +0 -56
- data/vendor/ruby-signature/Gemfile +0 -6
- data/vendor/ruby-signature/README.md +0 -93
- data/vendor/ruby-signature/Rakefile +0 -67
- data/vendor/ruby-signature/bin/annotate-with-rdoc +0 -157
- data/vendor/ruby-signature/bin/console +0 -14
- data/vendor/ruby-signature/bin/query-rdoc +0 -103
- data/vendor/ruby-signature/bin/setup +0 -10
- data/vendor/ruby-signature/bin/sort +0 -89
- data/vendor/ruby-signature/bin/test_runner.rb +0 -16
- data/vendor/ruby-signature/docs/CONTRIBUTING.md +0 -97
- data/vendor/ruby-signature/docs/sigs.md +0 -148
- data/vendor/ruby-signature/docs/stdlib.md +0 -152
- data/vendor/ruby-signature/docs/syntax.md +0 -528
- data/vendor/ruby-signature/exe/rbs +0 -7
- data/vendor/ruby-signature/lib/rbs.rb +0 -64
- data/vendor/ruby-signature/lib/rbs/ast/annotation.rb +0 -27
- data/vendor/ruby-signature/lib/rbs/ast/comment.rb +0 -27
- data/vendor/ruby-signature/lib/rbs/ast/declarations.rb +0 -395
- data/vendor/ruby-signature/lib/rbs/ast/members.rb +0 -362
- data/vendor/ruby-signature/lib/rbs/buffer.rb +0 -50
- data/vendor/ruby-signature/lib/rbs/builtin_names.rb +0 -55
- data/vendor/ruby-signature/lib/rbs/cli.rb +0 -558
- data/vendor/ruby-signature/lib/rbs/constant.rb +0 -26
- data/vendor/ruby-signature/lib/rbs/constant_table.rb +0 -150
- data/vendor/ruby-signature/lib/rbs/definition.rb +0 -170
- data/vendor/ruby-signature/lib/rbs/definition_builder.rb +0 -919
- data/vendor/ruby-signature/lib/rbs/environment.rb +0 -281
- data/vendor/ruby-signature/lib/rbs/environment_loader.rb +0 -136
- data/vendor/ruby-signature/lib/rbs/environment_walker.rb +0 -124
- data/vendor/ruby-signature/lib/rbs/errors.rb +0 -187
- data/vendor/ruby-signature/lib/rbs/location.rb +0 -102
- data/vendor/ruby-signature/lib/rbs/method_type.rb +0 -123
- data/vendor/ruby-signature/lib/rbs/namespace.rb +0 -91
- data/vendor/ruby-signature/lib/rbs/parser.y +0 -1344
- data/vendor/ruby-signature/lib/rbs/prototype/rb.rb +0 -553
- data/vendor/ruby-signature/lib/rbs/prototype/rbi.rb +0 -587
- data/vendor/ruby-signature/lib/rbs/prototype/runtime.rb +0 -381
- data/vendor/ruby-signature/lib/rbs/substitution.rb +0 -46
- data/vendor/ruby-signature/lib/rbs/test.rb +0 -26
- data/vendor/ruby-signature/lib/rbs/test/errors.rb +0 -61
- data/vendor/ruby-signature/lib/rbs/test/hook.rb +0 -294
- data/vendor/ruby-signature/lib/rbs/test/setup.rb +0 -58
- data/vendor/ruby-signature/lib/rbs/test/spy.rb +0 -325
- data/vendor/ruby-signature/lib/rbs/test/test_helper.rb +0 -183
- data/vendor/ruby-signature/lib/rbs/test/type_check.rb +0 -254
- data/vendor/ruby-signature/lib/rbs/type_name.rb +0 -70
- data/vendor/ruby-signature/lib/rbs/types.rb +0 -936
- data/vendor/ruby-signature/lib/rbs/variance_calculator.rb +0 -138
- data/vendor/ruby-signature/lib/rbs/vendorer.rb +0 -47
- data/vendor/ruby-signature/lib/rbs/version.rb +0 -3
- data/vendor/ruby-signature/lib/rbs/writer.rb +0 -269
- data/vendor/ruby-signature/lib/ruby/signature.rb +0 -7
- data/vendor/ruby-signature/rbs.gemspec +0 -45
- data/vendor/ruby-signature/stdlib/abbrev/abbrev.rbs +0 -60
- data/vendor/ruby-signature/stdlib/base64/base64.rbs +0 -71
- data/vendor/ruby-signature/stdlib/benchmark/benchmark.rbs +0 -372
- data/vendor/ruby-signature/stdlib/builtin/array.rbs +0 -1997
- data/vendor/ruby-signature/stdlib/builtin/basic_object.rbs +0 -280
- data/vendor/ruby-signature/stdlib/builtin/binding.rbs +0 -177
- data/vendor/ruby-signature/stdlib/builtin/builtin.rbs +0 -44
- data/vendor/ruby-signature/stdlib/builtin/class.rbs +0 -145
- data/vendor/ruby-signature/stdlib/builtin/comparable.rbs +0 -116
- data/vendor/ruby-signature/stdlib/builtin/complex.rbs +0 -400
- data/vendor/ruby-signature/stdlib/builtin/constants.rbs +0 -37
- data/vendor/ruby-signature/stdlib/builtin/data.rbs +0 -5
- data/vendor/ruby-signature/stdlib/builtin/deprecated.rbs +0 -2
- data/vendor/ruby-signature/stdlib/builtin/dir.rbs +0 -413
- data/vendor/ruby-signature/stdlib/builtin/encoding.rbs +0 -607
- data/vendor/ruby-signature/stdlib/builtin/enumerable.rbs +0 -404
- data/vendor/ruby-signature/stdlib/builtin/enumerator.rbs +0 -260
- data/vendor/ruby-signature/stdlib/builtin/errno.rbs +0 -781
- data/vendor/ruby-signature/stdlib/builtin/errors.rbs +0 -582
- data/vendor/ruby-signature/stdlib/builtin/exception.rbs +0 -194
- data/vendor/ruby-signature/stdlib/builtin/false_class.rbs +0 -40
- data/vendor/ruby-signature/stdlib/builtin/fiber.rbs +0 -68
- data/vendor/ruby-signature/stdlib/builtin/fiber_error.rbs +0 -12
- data/vendor/ruby-signature/stdlib/builtin/file.rbs +0 -1076
- data/vendor/ruby-signature/stdlib/builtin/file_test.rbs +0 -59
- data/vendor/ruby-signature/stdlib/builtin/float.rbs +0 -696
- data/vendor/ruby-signature/stdlib/builtin/gc.rbs +0 -243
- data/vendor/ruby-signature/stdlib/builtin/hash.rbs +0 -1029
- data/vendor/ruby-signature/stdlib/builtin/integer.rbs +0 -707
- data/vendor/ruby-signature/stdlib/builtin/io.rbs +0 -683
- data/vendor/ruby-signature/stdlib/builtin/kernel.rbs +0 -576
- data/vendor/ruby-signature/stdlib/builtin/marshal.rbs +0 -161
- data/vendor/ruby-signature/stdlib/builtin/match_data.rbs +0 -271
- data/vendor/ruby-signature/stdlib/builtin/math.rbs +0 -369
- data/vendor/ruby-signature/stdlib/builtin/method.rbs +0 -185
- data/vendor/ruby-signature/stdlib/builtin/module.rbs +0 -1104
- data/vendor/ruby-signature/stdlib/builtin/nil_class.rbs +0 -82
- data/vendor/ruby-signature/stdlib/builtin/numeric.rbs +0 -409
- data/vendor/ruby-signature/stdlib/builtin/object.rbs +0 -824
- data/vendor/ruby-signature/stdlib/builtin/proc.rbs +0 -429
- data/vendor/ruby-signature/stdlib/builtin/process.rbs +0 -1227
- data/vendor/ruby-signature/stdlib/builtin/random.rbs +0 -267
- data/vendor/ruby-signature/stdlib/builtin/range.rbs +0 -226
- data/vendor/ruby-signature/stdlib/builtin/rational.rbs +0 -424
- data/vendor/ruby-signature/stdlib/builtin/rb_config.rbs +0 -57
- data/vendor/ruby-signature/stdlib/builtin/regexp.rbs +0 -1083
- data/vendor/ruby-signature/stdlib/builtin/ruby_vm.rbs +0 -14
- data/vendor/ruby-signature/stdlib/builtin/signal.rbs +0 -55
- data/vendor/ruby-signature/stdlib/builtin/string.rbs +0 -1901
- data/vendor/ruby-signature/stdlib/builtin/string_io.rbs +0 -284
- data/vendor/ruby-signature/stdlib/builtin/struct.rbs +0 -40
- data/vendor/ruby-signature/stdlib/builtin/symbol.rbs +0 -228
- data/vendor/ruby-signature/stdlib/builtin/thread.rbs +0 -1108
- data/vendor/ruby-signature/stdlib/builtin/thread_group.rbs +0 -23
- data/vendor/ruby-signature/stdlib/builtin/time.rbs +0 -1047
- data/vendor/ruby-signature/stdlib/builtin/trace_point.rbs +0 -290
- data/vendor/ruby-signature/stdlib/builtin/true_class.rbs +0 -46
- data/vendor/ruby-signature/stdlib/builtin/unbound_method.rbs +0 -153
- data/vendor/ruby-signature/stdlib/builtin/warning.rbs +0 -17
- data/vendor/ruby-signature/stdlib/coverage/coverage.rbs +0 -62
- data/vendor/ruby-signature/stdlib/csv/csv.rbs +0 -773
- data/vendor/ruby-signature/stdlib/erb/erb.rbs +0 -392
- data/vendor/ruby-signature/stdlib/find/find.rbs +0 -40
- data/vendor/ruby-signature/stdlib/ipaddr/ipaddr.rbs +0 -247
- data/vendor/ruby-signature/stdlib/pathname/pathname.rbs +0 -1093
- data/vendor/ruby-signature/stdlib/prime/integer-extension.rbs +0 -23
- data/vendor/ruby-signature/stdlib/prime/prime.rbs +0 -188
- data/vendor/ruby-signature/stdlib/securerandom/securerandom.rbs +0 -9
- data/vendor/ruby-signature/stdlib/set/set.rbs +0 -301
- data/vendor/ruby-signature/stdlib/tmpdir/tmpdir.rbs +0 -53
@@ -1,152 +0,0 @@
|
|
1
|
-
# Stdlib Signatures Guide
|
2
|
-
|
3
|
-
This is a guide for contributing to `ruby-signature` by writing/revising stdlib signatures.
|
4
|
-
|
5
|
-
The typical steps of writing signatures will be like the following:
|
6
|
-
|
7
|
-
1. Generate a prototype
|
8
|
-
2. Import RDoc document
|
9
|
-
3. Give correct types to the prototype
|
10
|
-
4. Add tests
|
11
|
-
|
12
|
-
## Signatures
|
13
|
-
|
14
|
-
Signatures for standard libraries are located in `stdlib` directory. `stdlib/builtin` is for builtin libraries. Other libraries have directories like `stdlib/set` or `stdlib/pathname`.
|
15
|
-
|
16
|
-
To write signatures see [syntax guide](syntax.md).
|
17
|
-
|
18
|
-
## Generating prototypes
|
19
|
-
|
20
|
-
`ruby-signature` provides a tool to generate a prototype of signatures, `rbs prototype`.
|
21
|
-
It provides several options, `rbi` from Sorbet RBI files, `rb` from Ruby code, and `runtime` from runtime API.
|
22
|
-
`runtime` should be the best option for standard libraries because they may be implemented in C, no Ruby source code.
|
23
|
-
|
24
|
-
The tool `require`s all of the libraries specified with `-r` option, and then use introspection APIs like `instance_methods` to know the structure of the class.
|
25
|
-
The commandline receives the name of classes you want to prototype, exact class name (like `Pathname`) or pattern with `*` (like `IO::*`).
|
26
|
-
|
27
|
-
```
|
28
|
-
$ bundle exec rbs prototype runtime --require pathname Pathname
|
29
|
-
class Pathname
|
30
|
-
def self.getwd: () -> untyped
|
31
|
-
|
32
|
-
def self.glob: (*untyped) -> untyped
|
33
|
-
|
34
|
-
def self.pwd: () -> untyped
|
35
|
-
|
36
|
-
def +: (untyped other) -> untyped
|
37
|
-
|
38
|
-
alias / +
|
39
|
-
|
40
|
-
def <=>: (untyped) -> untyped
|
41
|
-
|
42
|
-
# snip
|
43
|
-
end
|
44
|
-
|
45
|
-
# snip
|
46
|
-
```
|
47
|
-
|
48
|
-
The prototype includes:
|
49
|
-
|
50
|
-
* Instance method definitions,
|
51
|
-
* Singleton method definitions,
|
52
|
-
* Includes, and
|
53
|
-
* Constants
|
54
|
-
|
55
|
-
It generate a simple prototype in the sense that all of the types included are `untyped`.
|
56
|
-
But it will help you to have an overview of the signatures you are trying to write.
|
57
|
-
|
58
|
-
### What to do with existing RBS files
|
59
|
-
|
60
|
-
Generating prototypes will override everything, so the problem is if there is a RBS files already.
|
61
|
-
You can try to find missing parts, or you can start from the scratch.
|
62
|
-
|
63
|
-
One non-trivial but absolutely better solution is to make a tool:
|
64
|
-
|
65
|
-
1. To load type definitions from existing RBS file, and
|
66
|
-
2. Generate prototypes only for missing methods.
|
67
|
-
|
68
|
-
## Import RDoc document
|
69
|
-
|
70
|
-
The next step should be importing RDoc documents.
|
71
|
-
|
72
|
-
```
|
73
|
-
$ bin/annotate-with-rdoc stdlib/pathname/pathname.rbs
|
74
|
-
Loading store from /Users/soutaro/.rbenv/versions/2.7.0-dev/share/ri/2.7.0/system...
|
75
|
-
Loading store from /Users/soutaro/.rbenv/versions/2.7.0-dev/share/ri/2.7.0/site...
|
76
|
-
Opening stdlib/pathname/pathname.rbs...
|
77
|
-
Importing documentation for Pathname...
|
78
|
-
Processing glob...
|
79
|
-
Processing +...
|
80
|
-
# snip
|
81
|
-
Writing stdlib/pathname/pathname.rbs...
|
82
|
-
```
|
83
|
-
|
84
|
-
The `annotate-with-rdoc` command adds annotations to RBS files.
|
85
|
-
|
86
|
-
1. Query RDoc documents to annotate classes, modules, methods, and constants,
|
87
|
-
2. Put annotations on RBS AST, and
|
88
|
-
3. Update the given .RBS files
|
89
|
-
|
90
|
-
We recommend using the command to annotate the RBS files.
|
91
|
-
|
92
|
-
## Writing types
|
93
|
-
|
94
|
-
The next step is to replace `untyped` types in the prototype.
|
95
|
-
See [syntax guide](syntax.md) for the detail of the syntax.
|
96
|
-
|
97
|
-
We can show some of the guides for writing types.
|
98
|
-
|
99
|
-
1. Use `bool` for truth values, truthy or falsey. More specific types like `TrueClass | FalseClass` may be too strict.
|
100
|
-
2. Use `void` if the return value is useless.
|
101
|
-
3. Use `nil` instead of `NilClass`.
|
102
|
-
4. The most strict types may not be the best types. Use `untyped` if you cannot find the best one.
|
103
|
-
|
104
|
-
## Add Tests
|
105
|
-
|
106
|
-
We support writing tests for stdlib signatures.
|
107
|
-
|
108
|
-
### Writing tests
|
109
|
-
|
110
|
-
First, execute `generate:stdlib_test` rake task with a class name that you want to test.
|
111
|
-
|
112
|
-
```bash
|
113
|
-
$ bundle exec rake 'generate:stdlib_test[String]'
|
114
|
-
Created: test/stdlib/String_test.rb
|
115
|
-
```
|
116
|
-
|
117
|
-
It generates `test/stdlib/[class_name]_test.rb`.
|
118
|
-
The test scripts would look like the following:
|
119
|
-
|
120
|
-
```rb
|
121
|
-
class StringTest < StdlibTest
|
122
|
-
target String
|
123
|
-
using hook.refinement
|
124
|
-
|
125
|
-
def test_gsub
|
126
|
-
s = "string"
|
127
|
-
s.gsub(/./, "")
|
128
|
-
s.gsub("a", "b")
|
129
|
-
s.gsub(/./) {|x| "" }
|
130
|
-
s.gsub(/./, {"foo" => "bar"})
|
131
|
-
s.gsub(/./)
|
132
|
-
s.gsub("")
|
133
|
-
end
|
134
|
-
end
|
135
|
-
```
|
136
|
-
|
137
|
-
You need two method calls, `target` and `using`.
|
138
|
-
`target` method call tells which class is the subject of the class.
|
139
|
-
`using hook.refinement` installs a special instrumentation for stdlib, based on refinements.
|
140
|
-
And you write the sample programs which calls all of the patterns of overloads.
|
141
|
-
|
142
|
-
Note that the instrumentation is based on refinements and you need to write all method calls in the unit class definitions.
|
143
|
-
If the execution of the program escape from the class definition, the instrumentation is disabled and no check will be done.
|
144
|
-
|
145
|
-
### Running tests
|
146
|
-
|
147
|
-
You can run the test with:
|
148
|
-
|
149
|
-
```
|
150
|
-
$ bundle exec ruby bin/test_runner.rb # Run all tests
|
151
|
-
$ bundle exec ruby test/stdlib/String_test.rb # Run specific tests
|
152
|
-
```
|
@@ -1,528 +0,0 @@
|
|
1
|
-
# Syntax
|
2
|
-
|
3
|
-
## Types
|
4
|
-
|
5
|
-
```markdown
|
6
|
-
_type_ ::= _class-name_ _type-arguments_ (Class instance type)
|
7
|
-
| _interface-name_ _type-arguments_ (Interface type)
|
8
|
-
| `singleton(` _class-name_ `)` (Class singleton type)
|
9
|
-
| _alias-name_ (Alias type)
|
10
|
-
| _literal_ (Literal type)
|
11
|
-
| _type_ `|` _type_ (Union type)
|
12
|
-
| _type_ `&` _type_ (Intersection type)
|
13
|
-
| _type_ `?` (Optional type)
|
14
|
-
| `{` _record-name_ `:` _type_ `,` ... `}` (Record type)
|
15
|
-
| `[]` | `[` _type_ `,` ... `]` (Tuples)
|
16
|
-
| _type-variable_ (Type variables)
|
17
|
-
| `^(` _parameters_ `) ->` _type_ (Proc type)
|
18
|
-
| `self`
|
19
|
-
| `instance`
|
20
|
-
| `class`
|
21
|
-
| `bool`
|
22
|
-
| `untyped`
|
23
|
-
| `nil`
|
24
|
-
| `top`
|
25
|
-
| `bot`
|
26
|
-
| `void`
|
27
|
-
|
28
|
-
_class-name_ ::= _namespace_ /[A-Z]\w*/
|
29
|
-
_interface-name_ ::= _namespace_ /_[A-Z]\w*/
|
30
|
-
_alias-name_ ::= _namespace_ /[a-z]\w*/
|
31
|
-
|
32
|
-
_type-variable_ ::= /[A-Z]\w*/
|
33
|
-
|
34
|
-
_namespace_ ::= (Empty namespace)
|
35
|
-
| `::` (Root)
|
36
|
-
| _namespace_ /[A-Z]\w*/ `::` (Namespace)
|
37
|
-
|
38
|
-
_type-arguments_ ::= (No application)
|
39
|
-
| `[` _type_ `,` ... `]` (Type application)
|
40
|
-
|
41
|
-
_literal_ ::= _string-literal_
|
42
|
-
| _symbol-literal_
|
43
|
-
| _integer-literal_
|
44
|
-
| `true`
|
45
|
-
| `false`
|
46
|
-
```
|
47
|
-
|
48
|
-
### Class instance type
|
49
|
-
|
50
|
-
Class instance type denotes _an instance of a class_.
|
51
|
-
|
52
|
-
```
|
53
|
-
Integer # Instance of Integer class
|
54
|
-
::Integer # Instance of ::Integer class
|
55
|
-
Hash[Symbol, String] # Instance of Hash class with type application of Symbol and String
|
56
|
-
```
|
57
|
-
|
58
|
-
### Interface type
|
59
|
-
|
60
|
-
Interface type denotes _type of a value which can be a subtype of the interface_.
|
61
|
-
|
62
|
-
```
|
63
|
-
_ToS # _ToS interface
|
64
|
-
::MyApp::_Each[String] # Interface name with namespace and type application
|
65
|
-
```
|
66
|
-
|
67
|
-
### Class singleton type
|
68
|
-
|
69
|
-
Class singleton type denotes _the type of a singleton object of a class_.
|
70
|
-
|
71
|
-
```
|
72
|
-
singleton(String)
|
73
|
-
singleton(::Hash) # Class singleton type cannot be parametrized.
|
74
|
-
```
|
75
|
-
|
76
|
-
### Alias type
|
77
|
-
|
78
|
-
Alias type denotes an alias declared with _alias declaration_.
|
79
|
-
|
80
|
-
The name of type aliases starts with lowercase `[a-z]`.
|
81
|
-
|
82
|
-
|
83
|
-
```
|
84
|
-
name
|
85
|
-
::JSON::t # Alias name with namespace
|
86
|
-
```
|
87
|
-
|
88
|
-
### Literal type
|
89
|
-
|
90
|
-
Literal type denotes _a type with only one value of the literal_.
|
91
|
-
|
92
|
-
```
|
93
|
-
123 # Integer
|
94
|
-
"hello world" # A string
|
95
|
-
:to_s # A symbol
|
96
|
-
true # true or false
|
97
|
-
```
|
98
|
-
|
99
|
-
### Union type
|
100
|
-
|
101
|
-
Union type denotes _a type of one of the given types_.
|
102
|
-
|
103
|
-
```
|
104
|
-
Integer | String # Integer or String
|
105
|
-
Array[Integer | String] # Array of Integer or String
|
106
|
-
```
|
107
|
-
|
108
|
-
### Intersection type
|
109
|
-
|
110
|
-
Intersection type denotes _a type of all of the given types_.
|
111
|
-
|
112
|
-
```
|
113
|
-
Integer & String # Integer and String
|
114
|
-
```
|
115
|
-
|
116
|
-
Note that `&` has higher precedence than `|` that `Integer & String | Symbol` is `(Integer & String) | Symbol`.
|
117
|
-
|
118
|
-
### Optional type
|
119
|
-
|
120
|
-
Optional type denotes _a type of value or nil_.
|
121
|
-
|
122
|
-
```
|
123
|
-
Integer?
|
124
|
-
Array[Integer?]
|
125
|
-
```
|
126
|
-
|
127
|
-
### Record type
|
128
|
-
|
129
|
-
Records are `Hash` objects, fixed set of keys, and heterogeneous.
|
130
|
-
|
131
|
-
```
|
132
|
-
{ id: Integer, name: String } # Hash object like `{ id: 31, name: String }`
|
133
|
-
```
|
134
|
-
|
135
|
-
### Tuple type
|
136
|
-
|
137
|
-
Tuples are `Array` objects, fixed size and heterogeneous.
|
138
|
-
|
139
|
-
```
|
140
|
-
[ ] # Empty like `[]`
|
141
|
-
[String] # Single string like `["hi"]`
|
142
|
-
[Integer, Integer] # Pair of integers like `[1, 2]`
|
143
|
-
[Symbol, Integer, Integer] # Tuple of Symbol, Integer, and Integer like `[:pair, 30, 22]`
|
144
|
-
```
|
145
|
-
|
146
|
-
*Empty tuple* or *1-tuple* sound strange, but RBS allows these types.
|
147
|
-
|
148
|
-
### Type variable
|
149
|
-
|
150
|
-
```
|
151
|
-
U
|
152
|
-
T
|
153
|
-
S
|
154
|
-
Elem
|
155
|
-
```
|
156
|
-
|
157
|
-
Type variables cannot be distinguished from _class instance types_.
|
158
|
-
They are scoped in _class/module/interface declaration_ or _generic method types_.
|
159
|
-
|
160
|
-
```
|
161
|
-
class Ref[T] # Object is scoped in the class declaration.
|
162
|
-
@value: T # Type variable `T`
|
163
|
-
def map: [X] { (T) -> X } -> Ref[X] # X is a type variable scoped in the method type.
|
164
|
-
end
|
165
|
-
```
|
166
|
-
|
167
|
-
### Proc type
|
168
|
-
|
169
|
-
Proc type denots type of procedures, `Proc` instances.
|
170
|
-
|
171
|
-
```
|
172
|
-
^(Integer) -> String # A procedure with an `Integer` parameter and returns `String`
|
173
|
-
^(?String, size: Integer) -> bool # A procedure with `String` optional parameter, `size` keyword of `Integer`, and returns `bool`
|
174
|
-
```
|
175
|
-
|
176
|
-
### Base types
|
177
|
-
|
178
|
-
`self` denotes the type of receiver. The type is used to model the open recursion via `self`.
|
179
|
-
|
180
|
-
`instance` denotes the type of instance of the class. `class` is the singleton of the class.
|
181
|
-
|
182
|
-
`bool` is an abstract type for truth value.
|
183
|
-
|
184
|
-
`untyped` is for _a type without type checking_. It is `?` in gradual typing, _dynamic_ in some languages like C#, and _any_ in TypeScript. It is both subtype _and_ supertype of all of the types. (The type was `any` but renamed to `untyped`.)
|
185
|
-
|
186
|
-
`nil` is for _nil_.
|
187
|
-
|
188
|
-
`top` is a supertype of all of the types. `bot` is a subtype of all of the types.
|
189
|
-
|
190
|
-
`void` is a supertype of all of the types.
|
191
|
-
|
192
|
-
#### `nil` or `NilClass`?
|
193
|
-
|
194
|
-
We recommend using `nil`.
|
195
|
-
|
196
|
-
#### `bool` or `TrueClass | FalseClass`
|
197
|
-
|
198
|
-
We recommend using `bool` because it is more close to Ruby's semantics. If the type of a parameter of a method is `bool`, we usually pass `true` and `false`, and also `nil` or any other values. `TrueClass | FalseClass` rejects other values than `true` and `false`.
|
199
|
-
|
200
|
-
#### `void`, `bool`, or `top`?
|
201
|
-
|
202
|
-
They are all equivalent for the type system; they are all _top type_.
|
203
|
-
|
204
|
-
`void` tells developers a hint that _the value should not be used_. `bool` implies the value is used as a truth value. `top` is anything else.
|
205
|
-
|
206
|
-
## Method Types
|
207
|
-
|
208
|
-
```markdown
|
209
|
-
_method-type_ ::= `(` _parameters_ `) ->` _type_ # Method without block
|
210
|
-
| `(` _parameters_ `) { (` _parameters_ `) -> ` _type_ `} ->` _type_ # Method with required block
|
211
|
-
| `(` _parameters_ `) ?{ (` _parameters_ `) -> ` _type_ `} ->` _type_ # Method with optional block
|
212
|
-
|
213
|
-
_parameters_ ::= _required-positionals_ _optional-positionals_ _rest-positional_ _trailing-positionals_ _keywords_
|
214
|
-
|
215
|
-
_paramater_ ::= _type_ _var-name_ # Parameter with var name
|
216
|
-
| _type_ # Parameter without var name
|
217
|
-
_required-positionals_ ::= _parameter_ `,` ...
|
218
|
-
_optional-positionals_ ::= `?` _parameter_ `,` ...
|
219
|
-
_rest-positional_ ::= # Empty
|
220
|
-
| `*` _parameter_
|
221
|
-
_trailing-positionals_ ::= _parameter_ `,` ...
|
222
|
-
_keywords_ ::= # Empty
|
223
|
-
| `**` _parameter_ # Rest keyword
|
224
|
-
| _keyword_ `:` _parameter_ `,` _keywords_ # Required keyword
|
225
|
-
| `?` _keyword_ `:` _parameter_ `,` _keywords_ # Optional keyword
|
226
|
-
|
227
|
-
_var-name_ ::= /[a-z]\w*/
|
228
|
-
```
|
229
|
-
|
230
|
-
### Parameters
|
231
|
-
|
232
|
-
A parameter can be a type or a pair of type and variable name.
|
233
|
-
Variable name can be used for documentation.
|
234
|
-
|
235
|
-
### Examples
|
236
|
-
|
237
|
-
```
|
238
|
-
# Two required positional `Integer` parameters, and returns `String`
|
239
|
-
(Integer, Integer) -> String
|
240
|
-
|
241
|
-
# Two optional parameters `size` and `name`.
|
242
|
-
# `name` is a optional parameter with optional type so that developer can omit, pass a string, or pass `nil`.
|
243
|
-
(?Integer size, ?String? name) -> String
|
244
|
-
|
245
|
-
# Method type with a rest parameter
|
246
|
-
(*Integer, Integer) -> void
|
247
|
-
|
248
|
-
# `size` is a required keyword, with variable name of `sz`.
|
249
|
-
# `name` is a optional keyword.
|
250
|
-
# `created_at` is a optional keyword, and the value can be `nil`.
|
251
|
-
(size: Integer sz, ?name: String, ?created_at: Time?) -> void
|
252
|
-
```
|
253
|
-
|
254
|
-
## Members
|
255
|
-
|
256
|
-
```markdown
|
257
|
-
_member_ ::= _ivar-member_ # Ivar definition
|
258
|
-
| _method-member_ # Method definition
|
259
|
-
| _attribute-member_ # Attribute definition
|
260
|
-
| _include-member_ # Mixin (include)
|
261
|
-
| _extend-member_ # Mixin (extend)
|
262
|
-
| _prepend-member_ # Mixin (prepend)
|
263
|
-
| _alias-member_ # Alias
|
264
|
-
| `public` # Public
|
265
|
-
| `private` # Private
|
266
|
-
|
267
|
-
_ivar-member_ ::= _ivar-name_ `:` _type_
|
268
|
-
|
269
|
-
_method-member_ ::= `def` _method-name_ `:` _method-types_ # Instance method
|
270
|
-
| `def self.` _method-name_ `:` _method-types_ # Singleton method
|
271
|
-
| `def self?.` _method-name_ `:` _method-types_ # Singleton and instance method
|
272
|
-
|
273
|
-
_method-types_ ::= # Empty
|
274
|
-
| `super` # `super` overloading
|
275
|
-
| _type-parameters_ _method-type_ `|` _method-types_ # Overloading types
|
276
|
-
|
277
|
-
_type-parameters_ ::= # Empty
|
278
|
-
| `[` _type-variable_ `,` ... `]`
|
279
|
-
|
280
|
-
_attribute-member_ ::= _attribute-type_ _method-name_ `:` _type_ # Attribute
|
281
|
-
| _attribute-type_ _method-name_ `(` _ivar-name_ `) :` _type_ # Attribute with variable name specification
|
282
|
-
| _attribute-type_ _method-name_ `() :` _type_ # Attribute without variable
|
283
|
-
|
284
|
-
_attribute-type_ ::= `attr_reader` | `attr_writer` | `attr_accessor`
|
285
|
-
|
286
|
-
_include-member_ ::= `include` _class-name_ _type-arguments_
|
287
|
-
| `include` _interface-name_ _type-arguments_
|
288
|
-
_extend-member_ ::= `extend` _class-name_ _type-arguments_
|
289
|
-
| `extend` _interface-name_ _type-arguments_
|
290
|
-
_prepend-member_ ::= `prepend` _class-name_ _type-arguments_
|
291
|
-
|
292
|
-
_alias-member_ ::= `alias` _method-name_ _method-name_
|
293
|
-
| `alias self.` _method-name_ `self.` _method-name_
|
294
|
-
|
295
|
-
_ivar-name_ ::= /@\w+/
|
296
|
-
_method-name_ ::= ...
|
297
|
-
| /`[^`]+`/
|
298
|
-
```
|
299
|
-
|
300
|
-
### Ivar definition
|
301
|
-
|
302
|
-
An instance variable definition consists of the name of an instance variable and its type.
|
303
|
-
|
304
|
-
```
|
305
|
-
@name: String
|
306
|
-
@value: Hash[Symbol, Key]
|
307
|
-
```
|
308
|
-
|
309
|
-
### Method definition
|
310
|
-
|
311
|
-
Method definition has several syntax variations.
|
312
|
-
|
313
|
-
You can write `self.` or `self?.` before the name of the method to specify the kind of method: instance, singleton, or both instance and singleton.
|
314
|
-
|
315
|
-
```
|
316
|
-
def to_s: () -> String # Defines a instance method
|
317
|
-
def self.new: () -> AnObject # Defines singleton method
|
318
|
-
def self?.sqrt: (Numeric) -> Numeric # self? is for `module_function`s
|
319
|
-
```
|
320
|
-
|
321
|
-
The method type can be connected with `|`s to define an overloaded method.
|
322
|
-
|
323
|
-
```
|
324
|
-
def +: (Float) -> Float
|
325
|
-
| (Integer) -> Integer
|
326
|
-
| (Numeric) -> Numeric
|
327
|
-
```
|
328
|
-
|
329
|
-
You need extra parentheses on return type to avoid ambiguity.
|
330
|
-
|
331
|
-
```
|
332
|
-
def +: (Float | Integer) -> (Float | Integer)
|
333
|
-
| (Numeric) -> Numeric
|
334
|
-
```
|
335
|
-
|
336
|
-
Method types can end with `super` which means the methods from existing definitions.
|
337
|
-
This is useful to define an _extension_, which adds a new variation to the existing method preserving the original behavior.
|
338
|
-
|
339
|
-
### Attribute definition
|
340
|
-
|
341
|
-
Attribute definitions help to define methods and instance variables based on the convention of `attr_reader`, `attr_writer` and `attr_accessor` methods in Ruby.
|
342
|
-
|
343
|
-
You can specify the name of instance variable using `(@some_name)` syntax and also omit the instance variable definition by specifying `()`.
|
344
|
-
|
345
|
-
```
|
346
|
-
# Defines `id` method and `@id` instance variable.
|
347
|
-
attr_reader id: Integer
|
348
|
-
# @id: Integer
|
349
|
-
# def id: () -> Integer
|
350
|
-
|
351
|
-
# Defines `name=` method and `raw_name` instance variable.
|
352
|
-
attr_writer name (@raw_name) : String
|
353
|
-
# @raw_name: String
|
354
|
-
# def name=: (String) -> String
|
355
|
-
|
356
|
-
# Defines `people` and `people=` methods, but no instance variable.
|
357
|
-
attr_accessor people (): Array[Person]
|
358
|
-
# def people: () -> Array[Person]
|
359
|
-
# def people=: (Array[Person]) -> Array[Person]
|
360
|
-
```
|
361
|
-
|
362
|
-
### Mixin (include), Mixin (extend), Mixin (prepend)
|
363
|
-
|
364
|
-
You can define mixins between class and modules.
|
365
|
-
|
366
|
-
```
|
367
|
-
include Kernel
|
368
|
-
include Enumerable[String, void]
|
369
|
-
extend ActiveSupport::Concern
|
370
|
-
```
|
371
|
-
|
372
|
-
You can also `include` or `extend` an interface.
|
373
|
-
|
374
|
-
```
|
375
|
-
include _Hashing
|
376
|
-
extend _LikeString
|
377
|
-
```
|
378
|
-
|
379
|
-
This allows importing `def`s from the interface to help developer implementing a set of methods.
|
380
|
-
|
381
|
-
### Alias
|
382
|
-
|
383
|
-
You can define an alias between methods.
|
384
|
-
|
385
|
-
```
|
386
|
-
def map: [X] () { (String) -> X } -> Array[X]
|
387
|
-
alias collect map # `#collect` has the same type with `map`
|
388
|
-
```
|
389
|
-
|
390
|
-
### `public`, `private`
|
391
|
-
|
392
|
-
`public` and `private` allows specifying the visibility of methods.
|
393
|
-
|
394
|
-
These work only as _statements_, not per-method specifier.
|
395
|
-
|
396
|
-
## Declarations
|
397
|
-
|
398
|
-
```markdown
|
399
|
-
_decl_ ::= _class-decl_ # Class declaration
|
400
|
-
| _module-decl_ # Module declaration
|
401
|
-
| _interface-decl_ # Interface declaration
|
402
|
-
| _extension-decl_ # Extension declaration
|
403
|
-
| _type-alias-decl_ # Type alias declaration
|
404
|
-
| _const-decl_ # Constant declaration
|
405
|
-
| _global-decl_ # Global declaration
|
406
|
-
|
407
|
-
_class-decl_ ::= `class` _class-name_ _module-type-parameters_ _members_ `end`
|
408
|
-
| `class` _class-name_ _module-type-parameters_ `<` _class-name_ _type-arguments_ _members_ `end`
|
409
|
-
|
410
|
-
_module-decl_ ::= `module` _module-name_ _module-type-parameters_ _members_ `end`
|
411
|
-
| `module` _module-name_ _module-type-parameters_ `:` _class-name_ _type-arguments_ _members_ `end`
|
412
|
-
|
413
|
-
_interface-decl_ ::= `interface` _interface-name_ _module-type-parameters_ _interface-members_ `end`
|
414
|
-
|
415
|
-
_interface-members_ ::= _method-member_ # Method
|
416
|
-
| _include-member_ # Mixin (include)
|
417
|
-
| _alias-member_ # Alias
|
418
|
-
|
419
|
-
_extension-decl_ ::= `extension` _class-name_ _type-parameters_ `(` _extension-name_ `)` _members_ `end`
|
420
|
-
|
421
|
-
_type-alias-decl_ ::= `type` _alias-name_ `=` _type_
|
422
|
-
|
423
|
-
_const-decl_ ::= _const-name_ `:` _type_
|
424
|
-
|
425
|
-
_global-decl_ ::= _global-name_ `:` _type_
|
426
|
-
|
427
|
-
_const-name_ ::= _namespace_ /[A-Z]\w*/
|
428
|
-
_global-name_ ::= /$[a-zA-Z]\w+/ | ...
|
429
|
-
|
430
|
-
_module-type-parameters_ ::= # Empty
|
431
|
-
| `[` _module-type-parameter_ `,` ... `]`
|
432
|
-
|
433
|
-
_module-type-parameter_ ::= _variance_ _type-variable_
|
434
|
-
_variance_ ::= `out` | `in`
|
435
|
-
```
|
436
|
-
|
437
|
-
### Class declaration
|
438
|
-
|
439
|
-
Class declaration can have type parameters and superclass. When you omit superclass, `::Object` is assumed.
|
440
|
-
|
441
|
-
```
|
442
|
-
class Ref[A] < Object
|
443
|
-
attr_reader value: A
|
444
|
-
def initialize: (value: A) -> void
|
445
|
-
end
|
446
|
-
```
|
447
|
-
|
448
|
-
### Module declaration
|
449
|
-
|
450
|
-
Module declaration takes optional _self type_ parameter, which defines a constraint about a class when the module is mixed.
|
451
|
-
|
452
|
-
```
|
453
|
-
interface _Each[A, B]
|
454
|
-
def each: { (A) -> void } -> B
|
455
|
-
end
|
456
|
-
|
457
|
-
module Enumerable[A, B] : _Each[A, B]
|
458
|
-
def count: () -> Integer
|
459
|
-
end
|
460
|
-
```
|
461
|
-
|
462
|
-
The `Enumerable` module above requires `each` method for enumerating objects.
|
463
|
-
|
464
|
-
### Interface declaration
|
465
|
-
|
466
|
-
Interface declaration can have parameters but allows only a few of the members.
|
467
|
-
|
468
|
-
```
|
469
|
-
interface _Hashing
|
470
|
-
def hash: () -> Integer
|
471
|
-
def eql?: (any) -> bool
|
472
|
-
end
|
473
|
-
```
|
474
|
-
|
475
|
-
There are several limitations which are not described in the grammar.
|
476
|
-
|
477
|
-
1. Interface cannot `include` modules
|
478
|
-
2. Interface cannot have singleton method definitions
|
479
|
-
|
480
|
-
```
|
481
|
-
interface _Foo
|
482
|
-
include Bar # Error: cannot include modules
|
483
|
-
def self.new: () -> Foo # Error: cannot include singleton method definitions
|
484
|
-
end
|
485
|
-
```
|
486
|
-
|
487
|
-
### Extension declaration
|
488
|
-
|
489
|
-
Extension is to model _open class_.
|
490
|
-
|
491
|
-
```
|
492
|
-
extension Kernel (Pathname)
|
493
|
-
def Pathname: (String) -> Pathname
|
494
|
-
end
|
495
|
-
|
496
|
-
extension Array[A] (ActiveSupport)
|
497
|
-
def to: (Integer) -> Array[A]
|
498
|
-
def from: (Integer) -> Array[A]
|
499
|
-
def second: () -> A?
|
500
|
-
def third: () -> A?
|
501
|
-
end
|
502
|
-
```
|
503
|
-
|
504
|
-
### Type alias declaration
|
505
|
-
|
506
|
-
You can declare an alias of types.
|
507
|
-
|
508
|
-
```
|
509
|
-
type subject = Attendee | Speaker
|
510
|
-
type JSON::t = Integer | TrueClass | FalseClass | String | Hash[Symbol, t] | Array[t]
|
511
|
-
```
|
512
|
-
|
513
|
-
### Constant type declaration
|
514
|
-
|
515
|
-
You can declare a constant.
|
516
|
-
|
517
|
-
```
|
518
|
-
Person::DefaultEmailAddress: String
|
519
|
-
```
|
520
|
-
|
521
|
-
### Global type declaration
|
522
|
-
|
523
|
-
You can declare a global variable.
|
524
|
-
|
525
|
-
```
|
526
|
-
$LOAD_PATH: Array[String]
|
527
|
-
```
|
528
|
-
|