parlour 0.6.1 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f14e75030cacb5f17788f44b4433f99061f6cf2d33ad809f54e15eeffa345e75
4
- data.tar.gz: b68177fc5b69ac579adcc12b06d231fa650beef042f627534f22ebb8effeb0b8
3
+ metadata.gz: e525051c1791bc175f8cbd109497f058e8708a60820683390e76c0f055ffca32
4
+ data.tar.gz: 68ff90fd52d6c2b252460b62402556ddee28ac246e7d16f16681e7dcd5e07337
5
5
  SHA512:
6
- metadata.gz: 69df3cca5b4420140ba5a45c563f51d26ed3043a67ea2128ef75775e8abc510fb5981d7282a0a437aa7ddcf36031950e1d32342ebf56e5ffca136480db319521
7
- data.tar.gz: 252dd6eabe1bd8deadc1ecea1e20e60793ee180eb2e5211ac622919a24bacb0597e6ef4599d7b2b77a446d1c31f5c0c182ccb8221812a2e3ec17e8ed48e34540
6
+ metadata.gz: f677a46f79678ae034348c85e52fbe80ee231eadb9ab08544fef93970f7a3615d0edc79aabeaa6b0be47072394054896d8f09e4b93a11c69e8caa13f6e7a25d2
7
+ data.tar.gz: fa81cba64780ff57a8b147b6aeb5b6501f3fbc6bfbf877480f017ca4a0f8cd989992067416f5afc326293d2f83a4e1652957576a0425298d60a26ecea934660d
data/.travis.yml CHANGED
@@ -12,13 +12,16 @@ rvm:
12
12
  matrix:
13
13
  allow_failures:
14
14
  - rvm: ruby-head
15
- after_success:
16
- - yard
17
- deploy:
18
- provider: pages
19
- local_dir: doc
20
- skip_cleanup: true
21
- github_token: $GITHUB_TOKEN
22
- keep_history: true
23
- on:
24
- branch: master
15
+
16
+ jobs:
17
+ include:
18
+ - stage: deploy documentation
19
+ script: yard
20
+ deploy:
21
+ provider: pages
22
+ local_dir: doc
23
+ skip_cleanup: true
24
+ github_token: $GITHUB_TOKEN
25
+ keep_history: true
26
+ on:
27
+ branch: master
data/CHANGELOG.md CHANGED
@@ -3,6 +3,29 @@ 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
+ ## [0.7.0] - 2019-09-11
7
+ ### Added
8
+ - The strictness level can now be specified when generating an RBI, using an
9
+ optional positional argument to `RBIGenerator#generate`. The default strictness
10
+ is `strong`.
11
+ - Plugins can specify a strictness level they would prefer by setting
12
+ `Plugin#strictness` for themselves. If multiple plugins set conflicting
13
+ strictnesses, the least strict will be used.
14
+ - Attributes can now specified as class attributes by setting
15
+ `Attribute#class_attribute` to `true`. This will wrap them in a `class << self`
16
+ block.
17
+
18
+ ### Changed
19
+ - The `sorbet` directory is no longer included in the built gem.
20
+ - Generated files now end with a new line (`\n`).
21
+
22
+ ### Fixed
23
+ - An instance method and a class method with the same name are no longer
24
+ considered conflicting.
25
+ - The signature for the constructor of `Attribute` previously typed the optional
26
+ initializer block as taking a `Method`. This has been corrected to taking an
27
+ `Attribute`.
28
+
6
29
  ## [0.6.1] - 2019-07-29
7
30
  ### Changed
8
31
  - Various areas of the codebase have been made compatible with older Ruby
data/README.md CHANGED
@@ -158,6 +158,13 @@ _Have you written an awesome Parlour plugin? Please submit a PR to add it to thi
158
158
 
159
159
  Bug reports and pull requests are welcome on GitHub at https://github.com/AaronC81/parlour. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
160
160
 
161
+ After making changes, you may wish to regenerate the RBI definitions in the `sorbet` folder by running these `srb rbi` commands:
162
+
163
+ ```
164
+ srb rbi gems
165
+ srb rbi sorbet-typed
166
+ ```
167
+
161
168
  ## License
162
169
 
163
170
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/exe/parlour CHANGED
@@ -71,9 +71,32 @@ command :run do |c|
71
71
  choice = ask("? ", Integer) { |q| q.in = 0..candidates.length }
72
72
  choice == 0 ? nil : candidates[choice - 1]
73
73
  end
74
+
75
+ # Figure out strictness levels
76
+ requested_strictness_levels = plugin_instances.map do |plugin|
77
+ s = plugin.strictness&.to_s
78
+ puts "WARNING: Plugin #{plugin.class.name} requested an invalid strictness #{s}" \
79
+ unless s && %w[ignore false true strict strong].include?(s)
80
+ s
81
+ end.compact
82
+ unique_strictness_levels = requested_strictness_levels.uniq
83
+ if unique_strictness_levels.empty?
84
+ # If no requests were made, just use the default
85
+ strictness = 'strong'
86
+ else
87
+ # Sort the strictnesses into "strictness order" and pick the weakest
88
+ strictness = unique_strictness_levels.min_by do |level|
89
+ %w[ignore false true strict strong].index(level) || Float::INFINITY
90
+ end
91
+ if unique_strictness_levels.one?
92
+ puts Rainbow('Note: ').yellow.bold + "All plugins specified the same strictness level, using it (#{strictness})"
93
+ else
94
+ puts Rainbow('Note: ').yellow.bold + "Plugins specified multiple strictness levels, chose the weakest (#{strictness})"
95
+ end
96
+ end
74
97
 
75
98
  # Write the final RBI
76
- File.write(configuration[:output_file], gen.rbi)
99
+ File.write(configuration[:output_file], gen.rbi(strictness))
77
100
  end
78
101
  end
79
102
 
@@ -44,6 +44,18 @@ module Parlour
44
44
 
45
45
  grouped_by_name_children.each do |name, children|
46
46
  if children.length > 1
47
+ # Special case: do we have two methods, one of which is a class method
48
+ # and the other isn't? If so, do nothing - this is fine
49
+ next if children.length == 2 &&
50
+ children.all? { |c| c.is_a?(RbiGenerator::Method) } &&
51
+ children.count { |c| T.cast(c, RbiGenerator::Method).class_method } == 1
52
+
53
+ # Special case: do we have two attributes, one of which is a class
54
+ # attribute and the other isn't? If so, do nothing - this is fine
55
+ next if children.length == 2 &&
56
+ children.all? { |c| c.is_a?(RbiGenerator::Attribute) } &&
57
+ children.count { |c| T.cast(c, RbiGenerator::Attribute).class_attribute } == 1
58
+
47
59
  # We found a conflict!
48
60
  # Start by removing all the conflicting items
49
61
  children.each do |c|
@@ -60,5 +60,12 @@ module Parlour
60
60
  # @param root [RbiGenerator::Namespace] The root {RbiGenerator::Namespace}.
61
61
  # @return [void]
62
62
  def generate(root); end
63
+
64
+ sig { returns(T.nilable(String)) }
65
+ # The strictness level which this plugin would prefer the generated RBI
66
+ # uses. If other plugins request different strictness levels, then the
67
+ # lowest strictness will be used, meaning there is no guarantee that this
68
+ # level will be used.
69
+ attr_accessor :strictness
63
70
  end
64
71
  end
@@ -38,12 +38,12 @@ module Parlour
38
38
  # @return [Plugin, nil]
39
39
  attr_accessor :current_plugin
40
40
 
41
- sig { returns(String) }
41
+ sig { params(strictness: String).returns(String) }
42
42
  # Returns the complete contents of the generated RBI file as a string.
43
43
  #
44
44
  # @return [String] The generated RBI file
45
- def rbi
46
- "# typed: strong\n" + root.generate_rbi(0, options).join("\n")
45
+ def rbi(strictness = 'strong')
46
+ "# typed: #{strictness}\n" + root.generate_rbi(0, options).join("\n") + "\n"
47
47
  end
48
48
  end
49
49
  end
@@ -9,7 +9,8 @@ module Parlour
9
9
  name: String,
10
10
  kind: Symbol,
11
11
  type: String,
12
- block: T.nilable(T.proc.params(x: Method).void)
12
+ class_attribute: T::Boolean,
13
+ block: T.nilable(T.proc.params(x: Attribute).void)
13
14
  ).void
14
15
  end
15
16
  # Creates a new attribute.
@@ -21,15 +22,18 @@ module Parlour
21
22
  # :accessor.
22
23
  # @param type [String] A Sorbet string of this attribute's type, such as
23
24
  # +"String"+ or +"T.untyped"+.
25
+ # @param class_attribute [Boolean] Whether this attribute belongs to the
26
+ # singleton class.
24
27
  # @param block A block which the new instance yields itself to.
25
28
  # @return [void]
26
- def initialize(generator, name, kind, type, &block)
29
+ def initialize(generator, name, kind, type, class_attribute: false, &block)
27
30
  # According to this source:
28
31
  # https://github.com/sorbet/sorbet/blob/2275752e51604acfb79b30a0a96debc996c089d9/test/testdata/dsl/attr_multi.rb
29
32
  # attr_accessor and attr_reader should have: sig { returns(X) }
30
33
  # attr_writer :foo should have: sig { params(foo: X).returns(X) }
31
34
 
32
35
  @kind = kind
36
+ @class_attribute = class_attribute
33
37
  case kind
34
38
  when :accessor, :reader
35
39
  super(generator, name, [], type, &block)
@@ -47,6 +51,24 @@ module Parlour
47
51
  # @return [Symbol]
48
52
  attr_reader :kind
49
53
 
54
+ sig { returns(T::Boolean) }
55
+ # Whether this attribute belongs to the singleton class.
56
+ attr_reader :class_attribute
57
+
58
+ sig { override.params(other: Object).returns(T::Boolean) }
59
+ # Returns true if this instance is equal to another attribute.
60
+ #
61
+ # @param other [Object] The other instance. If this is not a {Attribute}
62
+ # (or a subclass of it), this will always return false.
63
+ # @return [Boolean]
64
+ def ==(other)
65
+ T.must(
66
+ super(other) && Attribute === other &&
67
+ kind == other.kind &&
68
+ class_attribute == other.class_attribute
69
+ )
70
+ end
71
+
50
72
  private
51
73
 
52
74
  sig do
@@ -51,7 +51,7 @@ module Parlour
51
51
  yield_self(&block) if block
52
52
  end
53
53
 
54
- sig { params(other: Object).returns(T::Boolean) }
54
+ sig { overridable.params(other: Object).returns(T::Boolean) }
55
55
  # Returns true if this instance is equal to another method.
56
56
  #
57
57
  # @param other [Object] The other instance. If this is not a {Method} (or a
@@ -242,36 +242,55 @@ module Parlour
242
242
  new_method
243
243
  end
244
244
 
245
+ sig do
246
+ params(
247
+ name: String,
248
+ kind: Symbol,
249
+ type: String,
250
+ class_attribute: T::Boolean,
251
+ block: T.nilable(T.proc.params(x: Attribute).void)
252
+ ).returns(Attribute)
253
+ end
245
254
  # Creates a new attribute.
246
255
  #
247
256
  # @example Create an +attr_reader+.
248
- # module.create_attribute('readable', :reader, 'String')
257
+ # module.create_attribute('readable', kind: :reader, type: 'String')
249
258
  # # #=> sig { returns(String) }
250
259
  # # attr_reader :readable
251
260
  #
252
261
  # @example Create an +attr_writer+.
253
- # module.create_attribute('writable', :writer, 'Integer')
262
+ # module.create_attribute('writable', kind: :writer, type: 'Integer')
254
263
  # # #=> sig { params(writable: Integer).returns(Integer) }
255
264
  # # attr_writer :writable
256
265
  #
257
266
  # @example Create an +attr_accessor+.
258
- # module.create_attribute('accessible', :accessor, 'T::Boolean')
267
+ # module.create_attribute('accessible', kind: :accessor, type: 'T::Boolean')
259
268
  # # #=> sig { returns(T::Boolean) }
260
269
  # # attr_accessor :accessible
261
270
  #
271
+ # @example Create an +attr_accessor+ on the singleton class.
272
+ # module.create_attribute('singleton_attr', kind: :accessor, type: 'T::Boolean')
273
+ # # #=> class << self
274
+ # # sig { returns(T::Boolean) }
275
+ # # attr_accessor :singleton_attr
276
+ # # end
277
+ #
262
278
  # @param name [String] The name of this attribute.
263
279
  # @param kind [Symbol] The kind of attribute this is; one of +:writer+, +:reader+, or
264
280
  # +:accessor+.
265
281
  # @param type [String] A Sorbet string of this attribute's type, such as
266
282
  # +"String"+ or +"T.untyped"+.
283
+ # @param class_attribute [Boolean] Whether this attribute belongs to the
284
+ # singleton class.
267
285
  # @param block A block which the new instance yields itself to.
268
286
  # @return [RbiGenerator::Attribute]
269
- def create_attribute(name, kind:, type:, &block)
287
+ def create_attribute(name, kind:, type:, class_attribute: false, &block)
270
288
  new_attribute = RbiGenerator::Attribute.new(
271
289
  generator,
272
290
  name,
273
291
  kind,
274
292
  type,
293
+ class_attribute: class_attribute,
275
294
  &block
276
295
  )
277
296
  move_next_comments(new_attribute)
@@ -280,37 +299,67 @@ module Parlour
280
299
  end
281
300
  alias_method :create_attr, :create_attribute
282
301
 
302
+ sig do
303
+ params(
304
+ name: String,
305
+ type: String,
306
+ class_attribute: T::Boolean,
307
+ block: T.nilable(T.proc.params(x: Attribute).void)
308
+ ).returns(Attribute)
309
+ end
283
310
  # Creates a new read-only attribute (+attr_reader+).
284
311
  #
285
312
  # @param name [String] The name of this attribute.
286
313
  # @param type [String] A Sorbet string of this attribute's type, such as
287
314
  # +"String"+ or +"T.untyped"+.
315
+ # @param class_attribute [Boolean] Whether this attribute belongs to the
316
+ # singleton class.
288
317
  # @param block A block which the new instance yields itself to.
289
318
  # @return [RbiGenerator::Attribute]
290
- def create_attr_reader(name, type:, &block)
291
- create_attribute(name, kind: :reader, type: type, &block)
319
+ def create_attr_reader(name, type:, class_attribute: false, &block)
320
+ create_attribute(name, kind: :reader, type: type, class_attribute: class_attribute, &block)
292
321
  end
293
322
 
323
+ sig do
324
+ params(
325
+ name: String,
326
+ type: String,
327
+ class_attribute: T::Boolean,
328
+ block: T.nilable(T.proc.params(x: Attribute).void)
329
+ ).returns(Attribute)
330
+ end
294
331
  # Creates a new write-only attribute (+attr_writer+).
295
332
  #
296
333
  # @param name [String] The name of this attribute.
297
334
  # @param type [String] A Sorbet string of this attribute's type, such as
298
335
  # +"String"+ or +"T.untyped"+.
336
+ # @param class_attribute [Boolean] Whether this attribute belongs to the
337
+ # singleton class.
299
338
  # @param block A block which the new instance yields itself to.
300
339
  # @return [RbiGenerator::Attribute]
301
- def create_attr_writer(name, type:, &block)
302
- create_attribute(name, kind: :writer, type: type, &block)
340
+ def create_attr_writer(name, type:, class_attribute: false, &block)
341
+ create_attribute(name, kind: :writer, type: type, class_attribute: class_attribute, &block)
303
342
  end
304
343
 
344
+ sig do
345
+ params(
346
+ name: String,
347
+ type: String,
348
+ class_attribute: T::Boolean,
349
+ block: T.nilable(T.proc.params(x: Attribute).void)
350
+ ).returns(Attribute)
351
+ end
305
352
  # Creates a new read and write attribute (+attr_accessor+).
306
353
  #
307
354
  # @param name [String] The name of this attribute.
308
355
  # @param type [String] A Sorbet string of this attribute's type, such as
309
356
  # +"String"+ or +"T.untyped"+.
357
+ # @param class_attribute [Boolean] Whether this attribute belongs to the
358
+ # singleton class.
310
359
  # @param block A block which the new instance yields itself to.
311
360
  # @return [RbiGenerator::Attribute]
312
- def create_attr_accessor(name, type:, &block)
313
- create_attribute(name, kind: :accessor, type: type, &block)
361
+ def create_attr_accessor(name, type:, class_attribute: false, &block)
362
+ create_attribute(name, kind: :accessor, type: type, class_attribute: class_attribute, &block)
314
363
  end
315
364
 
316
365
  # Creates a new arbitrary code section.
@@ -501,13 +550,29 @@ module Parlour
501
550
  result << ""
502
551
  end
503
552
 
504
- first, *rest = children.reject do |child|
553
+ # Process singleton class attributes
554
+ class_attributes, remaining_children = children.partition do |child|
555
+ child.is_a?(Attribute) && child.class_attribute
556
+ end
557
+ if class_attributes.any?
558
+ result << options.indented(indent_level, 'class << self')
559
+
560
+ first, *rest = class_attributes
561
+ result += T.must(first).generate_rbi(indent_level + 1, options) + T.must(rest)
562
+ .map { |obj| obj.generate_rbi(indent_level + 1, options) }
563
+ .map { |lines| [""] + lines }
564
+ .flatten
565
+ result << options.indented(indent_level, 'end')
566
+ result << ''
567
+ end
568
+
569
+ first, *rest = remaining_children.reject do |child|
505
570
  # We already processed these kinds of children
506
571
  child.is_a?(Include) || child.is_a?(Extend) || child.is_a?(Constant)
507
572
  end
508
573
  unless first
509
- # Remove any trailing whitespace due to includes
510
- result.pop if result.last == ''
574
+ # Remove any trailing whitespace due to includes or class attributes
575
+ result.pop while result.last == ''
511
576
  return result
512
577
  end
513
578
 
@@ -1,5 +1,5 @@
1
1
  # typed: strong
2
2
  module Parlour
3
3
  # The library version.
4
- VERSION = '0.6.1'
4
+ VERSION = '0.7.0'
5
5
  end
data/parlour.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  # Specify which files should be added to the gem when it is released.
17
17
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
18
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|sorbet)/}) }
20
20
  end
21
21
  spec.bindir = "exe"
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parlour
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Christiansen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-29 00:00:00.000000000 Z
11
+ date: 2019-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sorbet-runtime
@@ -148,16 +148,6 @@ files:
148
148
  - lib/parlour/version.rb
149
149
  - parlour.gemspec
150
150
  - plugin_examples/foobar_plugin.rb
151
- - sorbet/config
152
- - sorbet/rbi/gems/rake.rbi
153
- - sorbet/rbi/gems/rspec-core.rbi
154
- - sorbet/rbi/gems/rspec-support.rbi
155
- - sorbet/rbi/gems/rspec.rbi
156
- - sorbet/rbi/hidden-definitions/errors.txt
157
- - sorbet/rbi/hidden-definitions/hidden.rbi
158
- - sorbet/rbi/sorbet-typed/lib/bundler/all/bundler.rbi
159
- - sorbet/rbi/sorbet-typed/lib/ruby/all/open3.rbi
160
- - sorbet/rbi/sorbet-typed/lib/ruby/all/resolv.rbi
161
151
  homepage: https://github.com/AaronC81/parlour
162
152
  licenses:
163
153
  - MIT
@@ -177,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
177
167
  - !ruby/object:Gem::Version
178
168
  version: '0'
179
169
  requirements: []
180
- rubygems_version: 3.0.2
170
+ rubygems_version: 3.0.3
181
171
  signing_key:
182
172
  specification_version: 4
183
173
  summary: An RBI generator