parlour 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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