parlour 3.0.0 → 5.0.0.beta.3
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/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
- data/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
- data/.gitignore +1 -1
- data/.parlour +5 -0
- data/.rspec +0 -0
- data/.travis.yml +0 -0
- data/CHANGELOG.md +57 -0
- data/CODE_OF_CONDUCT.md +0 -0
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +233 -19
- data/Rakefile +0 -0
- data/exe/parlour +109 -4
- data/lib/parlour.rb +27 -1
- data/lib/parlour/conflict_resolver.rb +31 -9
- data/lib/parlour/conversion/converter.rb +34 -0
- data/lib/parlour/conversion/rbi_to_rbs.rb +223 -0
- data/lib/parlour/debugging.rb +0 -0
- data/lib/parlour/detached_rbi_generator.rb +1 -6
- data/lib/parlour/detached_rbs_generator.rb +25 -0
- data/lib/parlour/generator.rb +34 -0
- data/lib/parlour/kernel_hack.rb +0 -0
- data/lib/parlour/options.rb +71 -0
- data/lib/parlour/parse_error.rb +0 -0
- data/lib/parlour/plugin.rb +1 -1
- data/lib/parlour/rbi_generator.rb +24 -37
- data/lib/parlour/rbi_generator/arbitrary.rb +5 -2
- data/lib/parlour/rbi_generator/attribute.rb +14 -5
- data/lib/parlour/rbi_generator/class_namespace.rb +8 -3
- data/lib/parlour/rbi_generator/constant.rb +28 -8
- data/lib/parlour/rbi_generator/enum_class_namespace.rb +8 -3
- data/lib/parlour/rbi_generator/extend.rb +5 -2
- data/lib/parlour/rbi_generator/include.rb +5 -2
- data/lib/parlour/rbi_generator/method.rb +15 -10
- data/lib/parlour/rbi_generator/module_namespace.rb +7 -2
- data/lib/parlour/rbi_generator/namespace.rb +68 -18
- data/lib/parlour/rbi_generator/parameter.rb +13 -7
- data/lib/parlour/rbi_generator/rbi_object.rb +19 -78
- data/lib/parlour/rbi_generator/struct_class_namespace.rb +9 -2
- data/lib/parlour/rbi_generator/struct_prop.rb +12 -9
- data/lib/parlour/rbi_generator/type_alias.rb +101 -0
- data/lib/parlour/rbs_generator.rb +24 -0
- data/lib/parlour/rbs_generator/arbitrary.rb +92 -0
- data/lib/parlour/rbs_generator/attribute.rb +82 -0
- data/lib/parlour/rbs_generator/block.rb +49 -0
- data/lib/parlour/rbs_generator/class_namespace.rb +106 -0
- data/lib/parlour/rbs_generator/constant.rb +95 -0
- data/lib/parlour/rbs_generator/extend.rb +92 -0
- data/lib/parlour/rbs_generator/include.rb +92 -0
- data/lib/parlour/rbs_generator/interface_namespace.rb +34 -0
- data/lib/parlour/rbs_generator/method.rb +146 -0
- data/lib/parlour/rbs_generator/method_signature.rb +104 -0
- data/lib/parlour/rbs_generator/module_namespace.rb +35 -0
- data/lib/parlour/rbs_generator/namespace.rb +627 -0
- data/lib/parlour/rbs_generator/parameter.rb +146 -0
- data/lib/parlour/rbs_generator/rbs_object.rb +78 -0
- data/lib/parlour/rbs_generator/type_alias.rb +96 -0
- data/lib/parlour/type_loader.rb +25 -12
- data/lib/parlour/type_parser.rb +174 -17
- data/lib/parlour/typed_object.rb +87 -0
- data/lib/parlour/types.rb +539 -0
- data/lib/parlour/version.rb +1 -1
- data/parlour.gemspec +1 -1
- data/plugin_examples/foobar_plugin.rb +0 -0
- data/rbi/parlour.rbi +1856 -0
- metadata +35 -10
- data/lib/parlour/rbi_generator/options.rb +0 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c9fa581e9b41195e54a4716df7926d1beb225c47871ff39d2f08fb0fa462aeb
|
4
|
+
data.tar.gz: 1aa333b0896df783baefa79d87fdbda732dea8676b85e89b7d76de607716658c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30486957baea0d7b30f827483ca69fbf589bd55039bedbcee6ea4f6258c0601612d191818a547569b32fe2e805dd29e34f27a46005eb3d5586dd7cb3462f7fb2
|
7
|
+
data.tar.gz: ed021b13ea01c171852be2d4892ba1042bc7dbf747e3413881e7d9c674553dea82337172c986dfec8ec78bfbed2be5519b6a091e2f3cd19f142797f54e35689e
|
File without changes
|
File without changes
|
data/.gitignore
CHANGED
data/.parlour
ADDED
data/.rspec
CHANGED
File without changes
|
data/.travis.yml
CHANGED
File without changes
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,63 @@ All notable changes to this project will be documented in this file.
|
|
3
3
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
5
5
|
|
6
|
+
## [5.0.0.beta.3] - 2020-09-15
|
7
|
+
### Changed
|
8
|
+
- Changed the RBS keyword warning to come from "RBS generation" rather than
|
9
|
+
"Type generalization"
|
10
|
+
- Added many more of RBS' keywords which are detected and prefixed with an
|
11
|
+
underscore to avoid syntax errors
|
12
|
+
|
13
|
+
## [5.0.0.beta.2] - 2020-09-14
|
14
|
+
### Added
|
15
|
+
- Added `Types::Type#describe` for simple text descriptions of types
|
16
|
+
- Added `Types::Self` for RBI's `T.self_type` or RBS' `self`
|
17
|
+
|
18
|
+
### Fixed
|
19
|
+
- Fixed `RbiGenerator::Namespace#create_method`'s `returns:` kwarg only
|
20
|
+
accepting String types
|
21
|
+
- Fixed lack of spacing between argument lists and blocks in RBS
|
22
|
+
- Fixed RBS attributes not having comments
|
23
|
+
|
24
|
+
## [5.0.0.beta.1] - 2020-09-13
|
25
|
+
### Added
|
26
|
+
- Added RBS generation support! This includes:
|
27
|
+
- The new `RbsGenerator` class
|
28
|
+
- `RbsObject` and a set of subclasses representing different RBS components
|
29
|
+
- Added the `Types` module, which is used to describe types agnostic of the
|
30
|
+
underlying type system
|
31
|
+
- Added `RbiGenerator::Namespace#generalize_from_rbi!` to convert RBI string
|
32
|
+
types into `Types` types
|
33
|
+
- **Specifying types as strings is still currently supported, but may be
|
34
|
+
phased out in future, and should be avoided in new projects**.
|
35
|
+
- Added conversion from RBI to RBS type trees
|
36
|
+
- Added a couple of classes to deduplicate functionality between type systems:
|
37
|
+
- `TypedObject`, which `RbiObject` and `RbsObject` both inherit from
|
38
|
+
- `Generator`, which `RbiGenerator` and `RbsGenerator` both inherit from
|
39
|
+
- Added RBI type aliases
|
40
|
+
|
41
|
+
### Changed
|
42
|
+
- `Parlour::RbiGenerator::Options` is now `Parlour::Options`. An alias exists
|
43
|
+
for now, but **`Parlour::RbiGenerator::Options` is deprecated** and could be
|
44
|
+
removed in future versions.
|
45
|
+
- Updated README and gem metadata to refer to Parlour as a type information
|
46
|
+
generator, rather than just an RBI generator
|
47
|
+
|
48
|
+
## [4.0.1] - 2020-08-05
|
49
|
+
### Fixed
|
50
|
+
- Fixed duplicate includes and extends.
|
51
|
+
- Fixed the block return type for `#resolve_conflicts` not being nilable.
|
52
|
+
|
53
|
+
## [4.0.0] - 2020-05-23
|
54
|
+
### Added
|
55
|
+
- Parlour now defaults to loading the current project when running its command
|
56
|
+
line tool, allowing it to be used as a "`sig` extractor" when run without
|
57
|
+
plugins! **Breaking if you invoke Parlour from its command line tool** - to
|
58
|
+
revert to the old behaviour of having nothing loaded into the root namespace
|
59
|
+
initially, add `parser: false` to your `.parlour` file.
|
60
|
+
- Generating constants in an eigenclass context (`class << self`) is now
|
61
|
+
supported.
|
62
|
+
|
6
63
|
## [3.0.0] - 2020-05-15
|
7
64
|
### Added
|
8
65
|
- `T::Struct` classes can now be generated and parsed.
|
data/CODE_OF_CONDUCT.md
CHANGED
File without changes
|
data/Gemfile
CHANGED
File without changes
|
data/LICENSE.txt
CHANGED
File without changes
|
data/README.md
CHANGED
@@ -3,39 +3,77 @@
|
|
3
3
|
[](https://travis-ci.org/AaronC81/parlour)
|
4
4
|

|
5
5
|
|
6
|
-
Parlour is
|
7
|
-
key parts:
|
6
|
+
Parlour is a Ruby type information generator, merger and parser, supporting both
|
7
|
+
**Sorbet RBI files and Ruby 3/Steep RBS files**. It consists of three key parts:
|
8
8
|
|
9
|
-
- The generator, which outputs beautifully formatted RBI files, created
|
10
|
-
an intuitive DSL.
|
9
|
+
- The generator, which outputs beautifully formatted RBI/RBS files, created
|
10
|
+
using an intuitive DSL.
|
11
11
|
|
12
12
|
- The plugin/build system, which allows multiple Parlour plugins to generate
|
13
13
|
RBIs for the same codebase. These are combined automatically as much as
|
14
14
|
possible, but any other conflicts can be resolved manually through prompts.
|
15
15
|
|
16
|
-
- The parser, which can read an RBI and convert it back
|
17
|
-
generator objects.
|
16
|
+
- The parser (currently RBI-only), which can read an RBI and convert it back
|
17
|
+
into a tree of generator objects.
|
18
18
|
|
19
19
|
## Why should I use this?
|
20
20
|
|
21
|
-
- Parlour enables **much easier creation of RBI generators**, as
|
22
|
-
is all handled for you, and you don't need to write your own CLI.
|
21
|
+
- Parlour enables **much easier creation of RBI/RBS generators**, as
|
22
|
+
formatting is all handled for you, and you don't need to write your own CLI.
|
23
23
|
|
24
24
|
- You can **use many plugins together seamlessly**, running them all with a
|
25
25
|
single command and consolidating all of their definitions into a single
|
26
|
-
|
26
|
+
output file.
|
27
27
|
|
28
28
|
- You can **effortlessly build tools which need to access types within an RBI**;
|
29
|
-
no need to write your own parser!
|
29
|
+
no need to write your own parser!
|
30
|
+
|
31
|
+
- You can **generate RBI/RBS to ship with your gem** for consuming projects to
|
32
|
+
use ([see "RBIs within gems" in Sorbet's
|
33
|
+
docs](https://sorbet.org/docs/rbi#rbis-within-gems)).
|
30
34
|
|
31
35
|
Please [**read the wiki**](https://github.com/AaronC81/parlour/wiki) to get
|
32
36
|
started!
|
33
37
|
|
34
|
-
##
|
38
|
+
## Feature Support
|
39
|
+
|
40
|
+
| Feature | RBI | RBS |
|
41
|
+
|---------|-----|-----|
|
42
|
+
| **GENERATION** | | |
|
43
|
+
| Classes | ✅ | ⚠️ (missing `extension`) |
|
44
|
+
| Modules | ✅ | ⚠️ (missing `extension`) |
|
45
|
+
| Interfaces | ✅ | ✅ |
|
46
|
+
| Attributes | ✅ | ✅ |
|
47
|
+
| Methods | ✅ | ✅ |
|
48
|
+
| Overloaded methods | ❌* | ✅ |
|
49
|
+
| Structs | ✅ | ✅† |
|
50
|
+
| Enums | ✅ | ✅† |
|
51
|
+
| Generation with plugins | ✅ | ❌ |
|
52
|
+
| **MANIPULATION** | | |
|
53
|
+
| Parsing | ✅ | ❌ |
|
54
|
+
| Merging | ✅ | ❌ |
|
55
|
+
|
56
|
+
- ✅ - Well supported
|
57
|
+
- ⚠️ - Some missing features
|
58
|
+
- ❌ - Not currently supported
|
59
|
+
|
60
|
+
- \* Only supported in stdlib types anyway
|
61
|
+
- † Not natively supported; available as a one-way conversion from RBI
|
62
|
+
|
63
|
+
## Creating Type Information
|
35
64
|
|
36
|
-
|
65
|
+
Each file format has its own type information generator class, so there are two
|
66
|
+
different generators you can use: `RbiGenerator` and `RbsGenerator`. Both
|
67
|
+
generators are similar to use, however they provide different object types and
|
68
|
+
parameters to match the functionality of their underlying type systems.
|
37
69
|
|
38
|
-
|
70
|
+
You can also convert your type information between formats; see
|
71
|
+
[converting between formats](#converting-between-formats).
|
72
|
+
|
73
|
+
### Using Just the Generator
|
74
|
+
|
75
|
+
Here's a quick example of how you can generate some type information. Here
|
76
|
+
we'll generate an RBI using the `RbiGenerator` classes:
|
39
77
|
|
40
78
|
```ruby
|
41
79
|
require 'parlour'
|
@@ -69,11 +107,50 @@ module A
|
|
69
107
|
end
|
70
108
|
```
|
71
109
|
|
72
|
-
|
110
|
+
Using the RBS generator looks similar, but has an intermediary
|
111
|
+
`MethodSignature` class to support RBS' method overloading:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
require 'parlour'
|
115
|
+
|
116
|
+
generator = Parlour::RbsGenerator.new
|
117
|
+
generator.root.create_module('A') do |a|
|
118
|
+
a.create_class('Foo') do |foo|
|
119
|
+
foo.create_method('add_two_integers', [
|
120
|
+
Parlour::RbsGenerator::MethodSignature.new(
|
121
|
+
[
|
122
|
+
Parlour::RbsGenerator::Parameter.new('a', type: 'Integer'),
|
123
|
+
Parlour::RbsGenerator::Parameter.new('b', type: 'Integer')
|
124
|
+
],
|
125
|
+
'Integer'
|
126
|
+
)
|
127
|
+
])
|
128
|
+
end
|
129
|
+
|
130
|
+
a.create_class('Bar', superclass: 'Foo')
|
131
|
+
end
|
132
|
+
|
133
|
+
generator.rbs # => Our RBS as a string
|
134
|
+
```
|
135
|
+
|
136
|
+
This generates an equivalent RBS file:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
module A
|
140
|
+
class Foo
|
141
|
+
def add_two_integers: (Integer a, Integer b) -> Integer
|
142
|
+
end
|
143
|
+
|
144
|
+
class Bar < Foo
|
145
|
+
end
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
### Writing a Plugin
|
73
150
|
Plugins are better than using the generator alone, as your plugin can be
|
74
|
-
combined with others to produce larger
|
151
|
+
combined with others to produce larger files without conflicts.
|
75
152
|
|
76
|
-
We could write the above example as
|
153
|
+
We could write the above example as an RBI plugin like this:
|
77
154
|
|
78
155
|
```ruby
|
79
156
|
require 'parlour'
|
@@ -104,7 +181,8 @@ called `plugin.rb`, then using this `.parlour` file and then running `parlour`
|
|
104
181
|
would save the RBI into `output.rbi`:
|
105
182
|
|
106
183
|
```yaml
|
107
|
-
output_file:
|
184
|
+
output_file:
|
185
|
+
rbi: output.rbi
|
108
186
|
|
109
187
|
relative_requires:
|
110
188
|
- plugin.rb
|
@@ -128,7 +206,8 @@ You can also use plugins from gems. If that plugin was published as a gem called
|
|
128
206
|
`parlour-gem`:
|
129
207
|
|
130
208
|
```yaml
|
131
|
-
output_file:
|
209
|
+
output_file:
|
210
|
+
rbi: output.rbi
|
132
211
|
|
133
212
|
requires:
|
134
213
|
- parlour-gem
|
@@ -140,7 +219,8 @@ plugins:
|
|
140
219
|
The real power of this is the ability to use many plugins at once:
|
141
220
|
|
142
221
|
```yaml
|
143
|
-
output_file:
|
222
|
+
output_file:
|
223
|
+
rbi: output.rbi
|
144
224
|
|
145
225
|
requires:
|
146
226
|
- gem1
|
@@ -153,6 +233,92 @@ plugins:
|
|
153
233
|
Gem3::Plugin: {}
|
154
234
|
```
|
155
235
|
|
236
|
+
Currently, only plugins which generate RBI files are supported. However, you can
|
237
|
+
use [Parlour's type conversion](#converting-between-formats) to convert the RBI
|
238
|
+
types into RBS types:
|
239
|
+
|
240
|
+
```yaml
|
241
|
+
output_file:
|
242
|
+
rbi: output.rbi
|
243
|
+
rbs: output.rbs
|
244
|
+
```
|
245
|
+
|
246
|
+
## Using Types
|
247
|
+
|
248
|
+
The most important part of your type information is the types themselves, which
|
249
|
+
you'll be specifying for method parameters, method returns, and attributes.
|
250
|
+
These include simple types like `String`, up to more complex types like
|
251
|
+
"an array of elements which are one of `Integer`, `String`, or nil".
|
252
|
+
|
253
|
+
There are two ways to represent these types in Parlour:
|
254
|
+
|
255
|
+
1. As **generalized types**; that is, instances of classes in the
|
256
|
+
`Parlour::Types` namespace. This is the **recommended way**, as it is
|
257
|
+
format-agnostic and can be compiled to RBI or RBS. For more information
|
258
|
+
about these types and how to use them, see
|
259
|
+
[this wiki page](https://github.com/AaronC81/parlour/wiki/The-Types-namespace).
|
260
|
+
|
261
|
+
2. As **strings of code** written in the format that your type system expects.
|
262
|
+
The given strings are directly inserted into the final type file. These types
|
263
|
+
are **not portable across formats**, and as such are
|
264
|
+
**not recommended and may be phased out** in the future.
|
265
|
+
|
266
|
+
Currently most type values within Parlour are typed as `Types::TypeLike`,
|
267
|
+
which accepts a `String` or a `Types::Type` subclass.
|
268
|
+
|
269
|
+
```ruby
|
270
|
+
include Parlour
|
271
|
+
|
272
|
+
# Two ways to express an attribute called 'example', which is:
|
273
|
+
# an array of nilable strings or integers
|
274
|
+
|
275
|
+
# 1. With generalised types - type is agnostic to the underlying type system
|
276
|
+
root.create_attr_accessor('example', type:
|
277
|
+
Types::Array.new(
|
278
|
+
Types::Nilable.new(
|
279
|
+
Types::Union.new(['String', 'Integer'])
|
280
|
+
)
|
281
|
+
)
|
282
|
+
)
|
283
|
+
|
284
|
+
# 2. With string types - format depends on type system
|
285
|
+
# If using RBI...
|
286
|
+
root.create_attr_accessor('example', type:
|
287
|
+
'T::Array[T.nilable(T.any(String, Integer))]'
|
288
|
+
)
|
289
|
+
# If using RBS...
|
290
|
+
root.create_attr_accessor('example', type:
|
291
|
+
'Array[?(String | Integer)]'
|
292
|
+
)
|
293
|
+
```
|
294
|
+
|
295
|
+
### Generalizing String Types
|
296
|
+
|
297
|
+
If you have loaded an RBI project or created a structure of nodes on an
|
298
|
+
`RbiGenerator`, you can use `#generalize_from_rbi!` on your root namespace
|
299
|
+
to attempt to permanently convert the RBI string types into generalized types:
|
300
|
+
|
301
|
+
```ruby
|
302
|
+
# Build up an RBI tree with string types
|
303
|
+
root.create_attr_accessor('example', type:
|
304
|
+
'T::Array[T.nilable(T.any(String, Integer))]'
|
305
|
+
)
|
306
|
+
|
307
|
+
# Generalize it
|
308
|
+
root.generalize_from_rbi!
|
309
|
+
|
310
|
+
# Take a look at our generalized type!
|
311
|
+
pp root.children.first.type
|
312
|
+
# => #<Parlour::Types::Array:0x0000557cdcebfdf8
|
313
|
+
# @element=
|
314
|
+
# #<Parlour::Types::Nilable:0x0000557cdcef8c70
|
315
|
+
# @type=
|
316
|
+
# #<Parlour::Types::Union:0x0000557cdcea0a70
|
317
|
+
# @types=
|
318
|
+
# [#<Parlour::Types::Raw:0x0000557cdcea1920 @str="String">,
|
319
|
+
# #<Parlour::Types::Raw:0x0000557cdcea0ae8 @str="Integer">]>>>
|
320
|
+
```
|
321
|
+
|
156
322
|
## Parsing RBIs
|
157
323
|
|
158
324
|
You can either parse individual RBI files, or point Parlour to the root of a
|
@@ -174,6 +340,54 @@ Parlour::TypeLoader.load_project('root/of/the/project')
|
|
174
340
|
The structure of the returned object trees is identical to those you would
|
175
341
|
create when generating an RBI, built of instances of `RbiObject` subclasses.
|
176
342
|
|
343
|
+
## Generating RBI for a Gem
|
344
|
+
|
345
|
+
Include `parlour` as a development_dependency in your `.gemspec`:
|
346
|
+
|
347
|
+
```ruby
|
348
|
+
spec.add_development_dependency 'parlour'
|
349
|
+
```
|
350
|
+
|
351
|
+
Run Parlour from the command line:
|
352
|
+
|
353
|
+
```ruby
|
354
|
+
bundle exec parlour
|
355
|
+
```
|
356
|
+
|
357
|
+
Parlour is configured to use sane defaults assuming a standard gem structure
|
358
|
+
to generate an RBI that Sorbet will automatically find when your gem is included
|
359
|
+
as a dependency. If you require more advanced configuration you can add a
|
360
|
+
`.parlour` YAML file in the root of your project (see this project's `.parlour`
|
361
|
+
file as an example).
|
362
|
+
|
363
|
+
To disable the parsing step entire and just run plugins you can set `parser: false`
|
364
|
+
in your `.parlour` file.
|
365
|
+
|
366
|
+
## Converting Between Formats
|
367
|
+
|
368
|
+
_For more information, see the [wiki page](https://github.com/AaronC81/parlour/wiki/Converting-between-RBI-and-RBS)._
|
369
|
+
|
370
|
+
Currently, only RBI to RBS conversion is supported, and if you've used string
|
371
|
+
types (or are using a freshly-loaded project) you
|
372
|
+
**must [generalize them](#generalizing-string-types) first**.
|
373
|
+
|
374
|
+
Then, all you need to do is create an `RbsGenerator` (which the converter will
|
375
|
+
add your converted types to) and a `Conversion::RbiToRbs` instance (which
|
376
|
+
performs the conversion). Then you can convert each object at your
|
377
|
+
`RbiGenerator`'s root namespace:
|
378
|
+
|
379
|
+
```ruby
|
380
|
+
rbi_gen = Parlour::RbiGenerator.new
|
381
|
+
# Then, after populating the RbiGenerator with types...
|
382
|
+
|
383
|
+
# Create an RbsGenerator and a converter
|
384
|
+
rbs_gen = Parlour::RbsGenerator.new
|
385
|
+
converter = Parlour::Conversion::RbiToRbs.new(rbs_gen)
|
386
|
+
|
387
|
+
# Convert each item at the root of the RbiGenerator and it to the root of the RbsGenerator
|
388
|
+
converter.convert_all(rbi_gen.root, rbs_gen.root)
|
389
|
+
```
|
390
|
+
|
177
391
|
## Parlour Plugins
|
178
392
|
|
179
393
|
_Have you written an awesome Parlour plugin? Please submit a PR to add it to this list!_
|
data/Rakefile
CHANGED
File without changes
|
data/exe/parlour
CHANGED
@@ -16,15 +16,67 @@ command :run do |c|
|
|
16
16
|
c.description = 'Generates an RBI file from your .parlour file'
|
17
17
|
|
18
18
|
c.action do |args, options|
|
19
|
-
|
19
|
+
working_dir = Dir.pwd
|
20
|
+
config_filename = File.join(working_dir, '.parlour')
|
20
21
|
|
21
|
-
|
22
|
+
if File.exists?(config_filename)
|
23
|
+
configuration = keys_to_symbols(YAML.load_file(config_filename))
|
24
|
+
else
|
25
|
+
configuration = {}
|
26
|
+
end
|
27
|
+
|
28
|
+
# Output file
|
29
|
+
if configuration[:output_file].is_a?(String)
|
30
|
+
assumed_format = \
|
31
|
+
if configuration[:output_file].end_with?('.rbi')
|
32
|
+
:rbi
|
33
|
+
elsif configuration[:output_file].end_with?('.rbs')
|
34
|
+
:rbs
|
35
|
+
else
|
36
|
+
raise 'invalid output file; please specify an RBI or RBS file'
|
37
|
+
end
|
38
|
+
|
39
|
+
unless $VERBOSE.nil?
|
40
|
+
print Rainbow("Parlour warning: ").yellow.dark.bold
|
41
|
+
print Rainbow("CLI: ").magenta.bright.bold
|
42
|
+
puts "Specifying output_file in .parlour as a string is deprecated."
|
43
|
+
puts "For now, generating an #{assumed_format.to_s.upcase} file based on the file extension."
|
44
|
+
puts "Please update your .parlour to use the new form:"
|
45
|
+
puts " output_file:"
|
46
|
+
puts " #{assumed_format}: #{configuration[:output_file]}"
|
47
|
+
end
|
48
|
+
configuration[:output_file] = {
|
49
|
+
assumed_format => configuration[:output_file]
|
50
|
+
}
|
51
|
+
end
|
52
|
+
configuration[:output_file] ||= {
|
53
|
+
rbi: "rbi/#{File.basename(working_dir)}.rbi"
|
54
|
+
}
|
22
55
|
|
23
56
|
# Style defaults
|
24
57
|
configuration[:style] ||= {}
|
25
58
|
configuration[:style][:tab_size] ||= 2
|
26
59
|
configuration[:style][:break_params] ||= 4
|
27
60
|
|
61
|
+
# Parser defaults, set explicitly to false to not run parser
|
62
|
+
if configuration[:parser] != false
|
63
|
+
configuration[:parser] ||= {}
|
64
|
+
|
65
|
+
# Input/Output defaults
|
66
|
+
configuration[:parser][:root] ||= '.'
|
67
|
+
|
68
|
+
# Included/Excluded path defaults
|
69
|
+
configuration[:parser][:included_paths] ||= ['lib']
|
70
|
+
configuration[:parser][:excluded_paths] ||= ['sorbet', 'spec']
|
71
|
+
|
72
|
+
# Defaults can be overridden but we always want to exclude the output file
|
73
|
+
configuration[:parser][:excluded_paths] << configuration[:output_file][:rbi]
|
74
|
+
end
|
75
|
+
|
76
|
+
# Included/Excluded module defaults
|
77
|
+
configuration[:included_modules] ||= []
|
78
|
+
configuration[:excluded_modules] ||= []
|
79
|
+
|
28
80
|
# Require defaults
|
29
81
|
configuration[:requires] ||= []
|
30
82
|
configuration[:relative_requires] ||= []
|
@@ -53,6 +105,15 @@ command :run do |c|
|
|
53
105
|
break_params: configuration[:style][:break_params],
|
54
106
|
tab_size: configuration[:style][:tab_size]
|
55
107
|
)
|
108
|
+
|
109
|
+
if configuration[:parser]
|
110
|
+
Parlour::TypeLoader.load_project(
|
111
|
+
configuration[:parser][:root],
|
112
|
+
inclusions: configuration[:parser][:included_paths],
|
113
|
+
exclusions: configuration[:parser][:excluded_paths],
|
114
|
+
generator: gen,
|
115
|
+
)
|
116
|
+
end
|
56
117
|
Parlour::Plugin.run_plugins(plugin_instances, gen)
|
57
118
|
|
58
119
|
# Run a pass of the conflict resolver
|
@@ -74,6 +135,14 @@ command :run do |c|
|
|
74
135
|
choice == 0 ? nil : candidates[choice - 1]
|
75
136
|
end
|
76
137
|
|
138
|
+
if !configuration[:included_modules].empty? || !configuration[:excluded_modules].empty?
|
139
|
+
remove_unwanted_modules(
|
140
|
+
gen.root,
|
141
|
+
included_modules: configuration[:included_modules],
|
142
|
+
excluded_modules: configuration[:excluded_modules],
|
143
|
+
)
|
144
|
+
end
|
145
|
+
|
77
146
|
# Figure out strictness levels
|
78
147
|
requested_strictness_levels = plugin_instances.map do |plugin|
|
79
148
|
s = plugin.strictness&.to_s
|
@@ -97,8 +166,23 @@ command :run do |c|
|
|
97
166
|
end
|
98
167
|
end
|
99
168
|
|
100
|
-
# Write the final
|
101
|
-
|
169
|
+
# Write the final files
|
170
|
+
if configuration[:output_file][:rbi]
|
171
|
+
FileUtils.mkdir_p(File.dirname(configuration[:output_file][:rbi]))
|
172
|
+
File.write(configuration[:output_file][:rbi], gen.rbi(strictness))
|
173
|
+
end
|
174
|
+
if configuration[:output_file][:rbs]
|
175
|
+
gen.root.generalize_from_rbi!
|
176
|
+
rbs_gen = Parlour::RbsGenerator.new
|
177
|
+
|
178
|
+
converter = Parlour::Conversion::RbiToRbs.new(rbs_gen)
|
179
|
+
gen.root.children.each do |child|
|
180
|
+
converter.convert_object(child, rbs_gen.root)
|
181
|
+
end
|
182
|
+
|
183
|
+
FileUtils.mkdir_p(File.dirname(configuration[:output_file][:rbs]))
|
184
|
+
File.write(configuration[:output_file][:rbs], rbs_gen.rbs)
|
185
|
+
end
|
102
186
|
end
|
103
187
|
end
|
104
188
|
|
@@ -122,3 +206,24 @@ def keys_to_symbols(hash)
|
|
122
206
|
]
|
123
207
|
end.to_h
|
124
208
|
end
|
209
|
+
|
210
|
+
def remove_unwanted_modules(root, included_modules:, excluded_modules:, prefix: nil)
|
211
|
+
root.children.select! do |child|
|
212
|
+
module_name = "#{prefix}#{child.name}"
|
213
|
+
|
214
|
+
if child.respond_to?(:children)
|
215
|
+
remove_unwanted_modules(
|
216
|
+
child,
|
217
|
+
included_modules: included_modules,
|
218
|
+
excluded_modules: excluded_modules,
|
219
|
+
prefix: "#{module_name}::",
|
220
|
+
)
|
221
|
+
has_included_children = !child.children.empty?
|
222
|
+
end
|
223
|
+
|
224
|
+
included = included_modules.empty? ? true : included_modules.any? { |m| module_name.start_with?(m) }
|
225
|
+
excluded = excluded_modules.empty? ? false : excluded_modules.any? { |m| module_name.start_with?(m) }
|
226
|
+
|
227
|
+
(included || has_included_children) && !excluded
|
228
|
+
end
|
229
|
+
end
|