sord 3.0.1 → 5.0.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/.github/workflows/ruby.yml +22 -0
- data/CHANGELOG.md +43 -0
- data/README.md +6 -0
- data/exe/sord +10 -4
- data/lib/sord/generator.rb +146 -37
- data/lib/sord/logging.rb +22 -21
- data/lib/sord/parlour_plugin.rb +21 -5
- data/lib/sord/resolver.rb +69 -8
- data/lib/sord/type_converter.rb +102 -24
- data/lib/sord/version.rb +1 -1
- data/rbi/sord.rbi +147 -40
- data/sord.gemspec +1 -0
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 12567f3b935a14271aedb28b62acfcfef3cb1e3bfb80fd294732947490dfb765
|
4
|
+
data.tar.gz: c40c2790500508fd2e575ab01e471cf7fe0e90f0c6d255285c7474433b65952c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85435a86928840302557121d0deeafde94a0b70905da93403c642a303ec773f5f4503b316beed31709052839a597e671df9ac554410d4c169843e859aebf361d
|
7
|
+
data.tar.gz: 77795ca64b509b9c7e7da210fac12d2b27bb8fe9e952ab61dc1d87c92189a1d0e457a4546bce2cebac4230a643f96072559c39bd477fc7e345819c98dd0b3bdd
|
@@ -0,0 +1,22 @@
|
|
1
|
+
name: Run tests
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
strategy:
|
8
|
+
matrix:
|
9
|
+
ruby: [2.7, 3.0, 3.1]
|
10
|
+
continue-on-error: false
|
11
|
+
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@v2
|
15
|
+
- name: Set up Ruby
|
16
|
+
uses: ruby/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: ${{ matrix.ruby }}
|
19
|
+
- name: Install dependencies
|
20
|
+
run: bundle install
|
21
|
+
- name: Run tests
|
22
|
+
run: bundle exec rake
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,49 @@ 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] - 2022-10-06
|
7
|
+
### Added
|
8
|
+
- If a derived class does not provide tags for a method, but it is overridden from a base class
|
9
|
+
which does, then the base class' documentation will be used to generate types for the derived
|
10
|
+
method.
|
11
|
+
- When generating RBS, if a duck type matches one of RBS' built-in interfaces, this type will be
|
12
|
+
generated instead. (For example, `#to_s` will generate the type `_ToS`.)
|
13
|
+
- Added the `--hide-private` flag, which will omit outputting items with private visibility.
|
14
|
+
- To improve resolution, types for gems are now loaded from the RBS collection.
|
15
|
+
- If you are using custom YARD tags, Sord can now be made aware of these by passing the `--tags`
|
16
|
+
option.
|
17
|
+
|
18
|
+
### Changed
|
19
|
+
- **Breaking change**: Support for versions of Ruby prior to 2.7 has been dropped.
|
20
|
+
- When Sord runs YARD automatically, it no longer generates HTML documentation, since this isn't
|
21
|
+
necessary for Sord's analysis. If you were relying on this as part of your workflow, then this
|
22
|
+
could be a **breaking change**.
|
23
|
+
|
24
|
+
### Fixed
|
25
|
+
- Duck-typed methods ending with `?` or `!`, and operator methods like `#[]=`, are now correctly
|
26
|
+
recognised as duck types.
|
27
|
+
- Fixed an exception when referring to built-in types with root namespace (`::Array<Foo>`) syntax.
|
28
|
+
- `@yieldparams` without a parameter name no longer cause an exception, and instead use default
|
29
|
+
names of the pattern: `arg0`, `arg1`, ...
|
30
|
+
|
31
|
+
## [4.0.0] - 2022-07-19
|
32
|
+
### Added
|
33
|
+
- Constants are now assigned types when generating RBS, using `@return`.
|
34
|
+
- Class-level `attr_accessor`s are converted to methods when generating RBS.
|
35
|
+
- Added the `--exclude-untyped` flag, which skips generating type signatures for methods with
|
36
|
+
`untyped` return values.
|
37
|
+
|
38
|
+
### Changed
|
39
|
+
- If YARD tags are present for a block, but there is no block param (such as when using `yield`),
|
40
|
+
the type signature now includes the documented block. This could be a **breaking change** leading
|
41
|
+
to type errors in existing code where such methods are called.
|
42
|
+
|
43
|
+
### Fixed
|
44
|
+
- Added workaround for YARD syntax error when a default parameter value begins with a unary minus
|
45
|
+
- Name resolutions from the root (e.g. `::X`) now behave correctly; previously they may have
|
46
|
+
selected a class named `X` nested within another namespace. This may be a **breaking change** if
|
47
|
+
any part of your generated type signatures was relying on the old, buggy behaviour.
|
48
|
+
|
6
49
|
## [3.0.1] - 2020-12-28
|
7
50
|
### Fixed
|
8
51
|
- Fixed `SortedSet` crash on Ruby 3
|
data/README.md
CHANGED
@@ -12,6 +12,8 @@ type signatures you need!
|
|
12
12
|
Sord is the perfect way to jump-start the adoption of types in your project,
|
13
13
|
whether you plan to use Sorbet's RBI format or Ruby 3/Steep's RBS format.
|
14
14
|
|
15
|
+
**Try Sord online at: [sord.aaronc.cc](https://sord.aaronc.cc)**
|
16
|
+
|
15
17
|
Sord has the following features:
|
16
18
|
- Automatically generates signatures for modules, classes and methods
|
17
19
|
- Support for multiple parameter or return types (`T.any`/`|`)
|
@@ -81,6 +83,10 @@ Sord also takes some flags to alter the generated file:
|
|
81
83
|
take a comma-separated list of logging kinds, for example `omit,infer`.
|
82
84
|
When using `--include-messages`, the `done` kind is included by default.
|
83
85
|
(You cannot specify both `--include-messages` and `--exclude-messages`.)
|
86
|
+
- `--exclude-untyped`: Exclude methods and attributes with untyped return
|
87
|
+
values.
|
88
|
+
- `--tags TAGS`: Provide a list of comma-separated tags as understood by the
|
89
|
+
`yard` command. E.g. `--tags 'mytag:My Description,mytag2:My New Description'
|
84
90
|
|
85
91
|
## Example
|
86
92
|
|
data/exe/sord
CHANGED
@@ -22,7 +22,10 @@ command :gen do |c|
|
|
22
22
|
c.option '--include-messages STRING', String, 'Whitelists a comma-separated string of log message types'
|
23
23
|
c.option '--keep-original-comments', 'Retains original YARD comments rather than converting them to Markdown'
|
24
24
|
c.option '--skip-constants', 'Excludes constants from generated file'
|
25
|
+
c.option '--hide-private', 'Exclude any object marked with @!visibility private'
|
25
26
|
c.option '--use-original-initialize-return', 'Uses the specified return type for #initialize rather than void'
|
27
|
+
c.option '--exclude-untyped', 'Exclude methods and attributes with untyped return values'
|
28
|
+
c.option '--tags TAGS', Array, 'Tag parameters for the YARD command'
|
26
29
|
|
27
30
|
c.action do |args, options|
|
28
31
|
options.default(
|
@@ -33,21 +36,24 @@ command :gen do |c|
|
|
33
36
|
break_params: 4,
|
34
37
|
replace_errors_with_untyped: false,
|
35
38
|
replace_unresolved_with_untyped: false,
|
39
|
+
hide_private: false,
|
36
40
|
exclude_messages: nil,
|
37
41
|
include_messages: nil,
|
38
42
|
keep_original_comments: false,
|
39
43
|
skip_constants: false,
|
40
44
|
use_original_initialize_return: false,
|
45
|
+
exclude_untyped: false,
|
46
|
+
tags: [],
|
41
47
|
)
|
42
48
|
|
43
49
|
if args.length != 1
|
44
50
|
Sord::Logging.error('Must specify filename')
|
45
51
|
exit 1
|
46
52
|
end
|
47
|
-
|
53
|
+
|
48
54
|
plugin_options = options.__hash__
|
49
|
-
plugin_options[:
|
50
|
-
plugin_options[:
|
55
|
+
plugin_options[:exclude_messages] = plugin_options[:exclude_messages]&.split(',')
|
56
|
+
plugin_options[:include_messages] = plugin_options[:include_messages]&.split(',')
|
51
57
|
|
52
58
|
if !(plugin_options[:rbi] || plugin_options[:rbs])
|
53
59
|
if args.first
|
@@ -84,7 +90,7 @@ command :gen do |c|
|
|
84
90
|
|
85
91
|
plugin.parlour = klass.new(break_params: plugin_options[:break_params])
|
86
92
|
plugin.generate(plugin.parlour.root)
|
87
|
-
|
93
|
+
|
88
94
|
File.write(args.first, plugin.parlour.send(generator_method))
|
89
95
|
end
|
90
96
|
end
|
data/lib/sord/generator.rb
CHANGED
@@ -8,16 +8,16 @@ require 'rainbow'
|
|
8
8
|
module Sord
|
9
9
|
# Converts the current working directory's YARD registry into an type
|
10
10
|
# signature file.
|
11
|
-
class Generator
|
11
|
+
class Generator
|
12
12
|
VALID_MODES = [:rbi, :rbs]
|
13
13
|
|
14
|
-
# @return [Integer] The number of objects this generator has processed so
|
14
|
+
# @return [Integer] The number of objects this generator has processed so
|
15
15
|
# far.
|
16
16
|
def object_count
|
17
17
|
@namespace_count + @method_count
|
18
18
|
end
|
19
19
|
|
20
|
-
# @return [Array<Array(String, YARD::CodeObjects::Base, Integer)>] The
|
20
|
+
# @return [Array<Array(String, YARD::CodeObjects::Base, Integer)>] The
|
21
21
|
# errors encountered by by the generator. Each element is of the form
|
22
22
|
# [message, item, line].
|
23
23
|
attr_reader :warnings
|
@@ -28,6 +28,7 @@ module Sord
|
|
28
28
|
# @option options [Integer] break_params
|
29
29
|
# @option options [Boolean] replace_errors_with_untyped
|
30
30
|
# @option options [Boolean] replace_unresolved_with_untyped
|
31
|
+
# @option options [Boolean] hide_private
|
31
32
|
# @option options [Boolean] comments
|
32
33
|
# @option options [Parlour::Generator] generator
|
33
34
|
# @option options [Parlour::TypedObject] root
|
@@ -53,12 +54,28 @@ module Sord
|
|
53
54
|
@replace_errors_with_untyped = options[:replace_errors_with_untyped]
|
54
55
|
@replace_unresolved_with_untyped = options[:replace_unresolved_with_untyped]
|
55
56
|
@keep_original_comments = options[:keep_original_comments]
|
57
|
+
@hide_private = options[:hide_private]
|
56
58
|
@skip_constants = options[:skip_constants]
|
57
59
|
@use_original_initialize_return = options[:use_original_initialize_return]
|
60
|
+
@exclude_untyped = options[:exclude_untyped]
|
61
|
+
|
62
|
+
@type_converter_config = TypeConverter::Configuration.new(
|
63
|
+
output_language: @mode,
|
64
|
+
replace_errors_with_untyped: @replace_errors_with_untyped,
|
65
|
+
replace_unresolved_with_untyped: @replace_unresolved_with_untyped,
|
66
|
+
)
|
58
67
|
|
59
68
|
# Hook the logger so that messages are added as comments
|
60
|
-
Logging.add_hook do |type, msg, item|
|
61
|
-
|
69
|
+
Logging.add_hook do |type, msg, item, **opts|
|
70
|
+
# Hack: the "exclude untyped" log message needs to print somewhere, but
|
71
|
+
# if there's no future object for that comment to associate with, it'll
|
72
|
+
# never be printed!
|
73
|
+
# Instead, add an arbitrary containing the comment
|
74
|
+
if opts[:immediate]
|
75
|
+
@current_object.create_arbitrary(code: "# sord #{type} - #{msg}")
|
76
|
+
else
|
77
|
+
@current_object.add_comment_to_next_child("sord #{type} - #{msg}")
|
78
|
+
end
|
62
79
|
end if options[:sord_comments]
|
63
80
|
|
64
81
|
# Hook the logger so that warnings are collected
|
@@ -110,7 +127,8 @@ module Sord
|
|
110
127
|
def add_constants(item)
|
111
128
|
inserted_constant_names = Set.new
|
112
129
|
|
113
|
-
item.constants(included: false).each do |constant|
|
130
|
+
item.constants(included: false).each do |constant|
|
131
|
+
next if @hide_private && constant.visibility == :private
|
114
132
|
# Take a constant (like "A::B::CONSTANT"), split it on each '::', and
|
115
133
|
# set the constant name to the last string in the array.
|
116
134
|
constant_name = constant.to_s.split('::').last
|
@@ -119,7 +137,7 @@ module Sord
|
|
119
137
|
next
|
120
138
|
end
|
121
139
|
inserted_constant_names << constant_name
|
122
|
-
|
140
|
+
|
123
141
|
# Add the constant to the current object being generated.
|
124
142
|
case @mode
|
125
143
|
when :rbi
|
@@ -127,7 +145,18 @@ module Sord
|
|
127
145
|
c.add_comments(constant.docstring.all.split("\n"))
|
128
146
|
end
|
129
147
|
when :rbs
|
130
|
-
|
148
|
+
return_tags = constant.tags('return')
|
149
|
+
returns = if return_tags.empty?
|
150
|
+
Logging.omit("no YARD return type given, using untyped", constant)
|
151
|
+
Parlour::Types::Untyped.new
|
152
|
+
else
|
153
|
+
TypeConverter.yard_to_parlour(
|
154
|
+
return_tags.map(&:types).flatten,
|
155
|
+
constant,
|
156
|
+
@type_converter_config,
|
157
|
+
)
|
158
|
+
end
|
159
|
+
@current_object.create_constant(constant_name, type: returns) do |c|
|
131
160
|
c.add_comments(constant.docstring.all.split("\n"))
|
132
161
|
end
|
133
162
|
end
|
@@ -225,12 +254,33 @@ module Sord
|
|
225
254
|
end
|
226
255
|
end
|
227
256
|
|
257
|
+
# @param method [YARD::CodeObjects::MethodObject]
|
258
|
+
# @param tag_name [String]
|
259
|
+
# @return [Array<YARD::Tags::Tag>]
|
260
|
+
def method_tags(method, tag_name)
|
261
|
+
tags = method.tags(tag_name)
|
262
|
+
return tags if tags.any? || method.overridden_method.nil?
|
263
|
+
|
264
|
+
method.overridden_method.tags(tag_name)
|
265
|
+
end
|
266
|
+
|
267
|
+
# @param method [YARD::CodeObjects::MethodObject]
|
268
|
+
# @param tag_name [String]
|
269
|
+
# @return [YARD::Tags::Tag, nil]
|
270
|
+
def method_tag(method, tag_name)
|
271
|
+
tag = method.tag(tag_name)
|
272
|
+
return tag if tag || method.overridden_method.nil?
|
273
|
+
|
274
|
+
method.overridden_method.tag(tag_name)
|
275
|
+
end
|
276
|
+
|
228
277
|
# Given a YARD NamespaceObject, add lines defining its methods and their
|
229
278
|
# signatures to the current file.
|
230
279
|
# @param [YARD::CodeObjects::NamespaceObject] item
|
231
280
|
# @return [void]
|
232
281
|
def add_methods(item)
|
233
282
|
item.meths(inherited: false).each do |meth|
|
283
|
+
next if @hide_private && meth.visibility == :private
|
234
284
|
count_method
|
235
285
|
|
236
286
|
# If the method is an alias, skip it so we don't define it as a
|
@@ -243,37 +293,44 @@ module Sord
|
|
243
293
|
if meth.is_attribute?
|
244
294
|
next
|
245
295
|
end
|
246
|
-
|
296
|
+
|
247
297
|
# Sort parameters
|
248
298
|
meth.parameters.reverse.sort! { |pair1, pair2| sort_params(pair1, pair2) }
|
249
|
-
|
299
|
+
|
300
|
+
# This is better than iterating over YARD's "@param" tags directly
|
250
301
|
# because it includes parameters without documentation
|
251
302
|
# (The gsubs allow for better splat-argument compatibility)
|
252
303
|
parameter_names_and_defaults_to_tags = meth.parameters.map do |name, default|
|
253
|
-
[[name, default], meth
|
304
|
+
[[name, fix_default_if_unary_minus(default)], method_tags(meth, 'param')
|
254
305
|
.find { |p| p.name&.gsub('*', '')&.gsub(':', '') == name.gsub('*', '').gsub(':', '') }]
|
255
306
|
end.to_h
|
256
307
|
|
308
|
+
# Add block param if there is no named param but YARD tags are present
|
309
|
+
if !parameter_names_and_defaults_to_tags.any? { |((name, _), _)| name.start_with? '&' } \
|
310
|
+
&& (method_tags(meth, 'yieldparam').any? || method_tag(meth, 'yieldreturn'))
|
311
|
+
parameter_names_and_defaults_to_tags[['&blk']] = nil
|
312
|
+
end
|
313
|
+
|
257
314
|
parameter_types = parameter_names_and_defaults_to_tags.map do |name_and_default, tag|
|
258
315
|
name = name_and_default.first
|
259
316
|
|
260
317
|
if tag
|
261
|
-
TypeConverter.yard_to_parlour(tag.types, meth, @
|
318
|
+
TypeConverter.yard_to_parlour(tag.types, meth, @type_converter_config)
|
262
319
|
elsif name.start_with? '&'
|
263
320
|
# Find yieldparams and yieldreturn
|
264
|
-
yieldparams = meth
|
265
|
-
yieldreturn = meth
|
321
|
+
yieldparams = method_tags(meth, 'yieldparam')
|
322
|
+
yieldreturn = method_tag(meth, 'yieldreturn')&.types
|
266
323
|
yieldreturn = nil if yieldreturn&.length == 1 &&
|
267
324
|
yieldreturn&.first&.downcase == 'void'
|
268
325
|
|
269
326
|
# Create strings
|
270
|
-
params = yieldparams.map do |param|
|
327
|
+
params = yieldparams.map.with_index do |param, i|
|
271
328
|
Parlour::Types::Proc::Parameter.new(
|
272
|
-
param.name
|
273
|
-
TypeConverter.yard_to_parlour(param.types, meth, @
|
329
|
+
param.name&.gsub('*', '') || "arg#{i}",
|
330
|
+
TypeConverter.yard_to_parlour(param.types, meth, @type_converter_config)
|
274
331
|
)
|
275
332
|
end
|
276
|
-
returns = TypeConverter.yard_to_parlour(yieldreturn, meth, @
|
333
|
+
returns = TypeConverter.yard_to_parlour(yieldreturn, meth, @type_converter_config)
|
277
334
|
|
278
335
|
# Create proc types, if possible
|
279
336
|
if yieldparams.empty? && yieldreturn.nil?
|
@@ -288,36 +345,36 @@ module Sord
|
|
288
345
|
|
289
346
|
unless getter
|
290
347
|
if parameter_names_and_defaults_to_tags.length == 1 \
|
291
|
-
&& meth
|
292
|
-
&& meth
|
293
|
-
|
348
|
+
&& method_tags(meth, 'param').length == 1 \
|
349
|
+
&& method_tag(meth, 'param').types
|
350
|
+
|
294
351
|
Logging.infer("argument name in single @param inferred as #{parameter_names_and_defaults_to_tags.first.first.first.inspect}", meth)
|
295
|
-
next TypeConverter.yard_to_parlour(meth
|
296
|
-
else
|
352
|
+
next TypeConverter.yard_to_parlour(method_tag(meth, 'param').types, meth, @type_converter_config)
|
353
|
+
else
|
297
354
|
Logging.omit("no YARD type given for #{name.inspect}, using untyped", meth)
|
298
355
|
next Parlour::Types::Untyped.new
|
299
356
|
end
|
300
357
|
end
|
301
358
|
|
302
|
-
return_types = getter
|
359
|
+
return_types = method_tags(getter, 'return').flat_map(&:types)
|
303
360
|
unless return_types.any?
|
304
361
|
Logging.omit("no YARD type given for #{name.inspect}, using untyped", meth)
|
305
362
|
next Parlour::Types::Untyped.new
|
306
363
|
end
|
307
364
|
inferred_type = TypeConverter.yard_to_parlour(
|
308
|
-
return_types, meth, @
|
309
|
-
|
365
|
+
return_types, meth, @type_converter_config)
|
366
|
+
|
310
367
|
Logging.infer("inferred type of parameter #{name.inspect} as #{inferred_type.describe} using getter's return type", meth)
|
311
368
|
inferred_type
|
312
369
|
else
|
313
370
|
# Is this the only argument, and was a @param specified without an
|
314
371
|
# argument name? If so, infer it
|
315
372
|
if parameter_names_and_defaults_to_tags.length == 1 \
|
316
|
-
&& meth
|
317
|
-
&& meth
|
373
|
+
&& method_tags(meth, 'param').length == 1 \
|
374
|
+
&& method_tag(meth, 'param').types
|
318
375
|
|
319
376
|
Logging.infer("argument name in single @param inferred as #{parameter_names_and_defaults_to_tags.first.first.first.inspect}", meth)
|
320
|
-
TypeConverter.yard_to_parlour(meth
|
377
|
+
TypeConverter.yard_to_parlour(method_tag(meth, 'param').types, meth, @type_converter_config)
|
321
378
|
else
|
322
379
|
Logging.omit("no YARD type given for #{name.inspect}, using untyped", meth)
|
323
380
|
Parlour::Types::Untyped.new
|
@@ -325,7 +382,7 @@ module Sord
|
|
325
382
|
end
|
326
383
|
end
|
327
384
|
|
328
|
-
return_tags = meth
|
385
|
+
return_tags = method_tags(meth, 'return')
|
329
386
|
returns = if meth.name == :initialize && !@use_original_initialize_return
|
330
387
|
nil
|
331
388
|
elsif return_tags.length == 0
|
@@ -334,14 +391,14 @@ module Sord
|
|
334
391
|
elsif return_tags.length == 1 && %w{void nil}.include?(return_tags&.first&.types&.first&.downcase)
|
335
392
|
nil
|
336
393
|
else
|
337
|
-
TypeConverter.yard_to_parlour(meth
|
394
|
+
TypeConverter.yard_to_parlour(method_tag(meth, 'return').types, meth, @type_converter_config)
|
338
395
|
end
|
339
396
|
|
340
397
|
rbs_block = nil
|
341
398
|
parlour_params = parameter_names_and_defaults_to_tags
|
342
399
|
.zip(parameter_types)
|
343
400
|
.map do |((name, default), _), type|
|
344
|
-
# If the default is "nil" but the type is not nilable, then it
|
401
|
+
# If the default is "nil" but the type is not nilable, then it
|
345
402
|
# should become nilable
|
346
403
|
# (T.untyped can include nil, so don't alter that)
|
347
404
|
type = Parlour::Types::Nilable.new(type) \
|
@@ -369,10 +426,15 @@ module Sord
|
|
369
426
|
end
|
370
427
|
.compact
|
371
428
|
|
429
|
+
if @exclude_untyped && parlour_params.all? { |p| p.type.is_a?(Parlour::Types::Untyped) } && returns.is_a?(Parlour::Types::Untyped)
|
430
|
+
Logging.omit("excluding untyped", meth, immediate: true)
|
431
|
+
next
|
432
|
+
end
|
433
|
+
|
372
434
|
case @mode
|
373
435
|
when :rbi
|
374
436
|
@current_object.create_method(
|
375
|
-
meth.name.to_s,
|
437
|
+
meth.name.to_s,
|
376
438
|
parameters: parlour_params,
|
377
439
|
returns: returns,
|
378
440
|
class_method: meth.scope == :class
|
@@ -391,7 +453,7 @@ module Sord
|
|
391
453
|
) do |m|
|
392
454
|
add_comments(meth, m)
|
393
455
|
end
|
394
|
-
end
|
456
|
+
end
|
395
457
|
end
|
396
458
|
end
|
397
459
|
|
@@ -415,10 +477,12 @@ module Sord
|
|
415
477
|
# Get all given types
|
416
478
|
yard_types = []
|
417
479
|
if reader
|
480
|
+
next if @hide_private && reader.visibility == :private
|
418
481
|
yard_types += reader.tags('return').flat_map(&:types).compact.reject { |x| x.downcase == 'void' } +
|
419
482
|
reader.tags('param').flat_map(&:types)
|
420
483
|
end
|
421
484
|
if writer
|
485
|
+
next if @hide_private && writer.visibility == :private
|
422
486
|
yard_types += writer.tags('return').flat_map(&:types).compact.reject { |x| x.downcase == 'void' } +
|
423
487
|
writer.tags('param').flat_map(&:types)
|
424
488
|
end
|
@@ -433,7 +497,7 @@ module Sord
|
|
433
497
|
parlour_type = Parlour::Types::Untyped.new
|
434
498
|
else
|
435
499
|
parlour_type = TypeConverter.yard_to_parlour(
|
436
|
-
yard_types, reader || writer, @
|
500
|
+
yard_types, reader || writer, @type_converter_config)
|
437
501
|
end
|
438
502
|
|
439
503
|
# Generate attribute
|
@@ -445,6 +509,11 @@ module Sord
|
|
445
509
|
kind = :writer
|
446
510
|
end
|
447
511
|
|
512
|
+
if @exclude_untyped && parlour_type.is_a?(Parlour::Types::Untyped)
|
513
|
+
Logging.omit("excluding untyped attribute", reader || writer, immediate: true)
|
514
|
+
next
|
515
|
+
end
|
516
|
+
|
448
517
|
case @mode
|
449
518
|
when :rbi
|
450
519
|
@current_object.create_attribute(
|
@@ -457,7 +526,31 @@ module Sord
|
|
457
526
|
end
|
458
527
|
when :rbs
|
459
528
|
if attr_loc == :class
|
460
|
-
|
529
|
+
# RBS doesn't support class attr_accessors so create individual methods
|
530
|
+
|
531
|
+
if reader
|
532
|
+
@current_object.create_method(
|
533
|
+
name.to_s,
|
534
|
+
[Parlour::RbsGenerator::MethodSignature.new([], parlour_type)],
|
535
|
+
class_method: true
|
536
|
+
) do |m|
|
537
|
+
add_comments(reader, m)
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
if writer
|
542
|
+
@current_object.create_method(
|
543
|
+
"#{name}=",
|
544
|
+
[Parlour::RbsGenerator::MethodSignature.new([Parlour::RbsGenerator::Parameter.new(
|
545
|
+
"value",
|
546
|
+
type: parlour_type,
|
547
|
+
required: true
|
548
|
+
)], parlour_type)],
|
549
|
+
class_method: true
|
550
|
+
) do |m|
|
551
|
+
add_comments(writer, m)
|
552
|
+
end
|
553
|
+
end
|
461
554
|
else
|
462
555
|
@current_object.create_attribute(
|
463
556
|
name.to_s,
|
@@ -477,6 +570,7 @@ module Sord
|
|
477
570
|
# @param [YARD::CodeObjects::NamespaceObject] item
|
478
571
|
# @return [void]
|
479
572
|
def add_namespace(item)
|
573
|
+
return if @hide_private && item.visibility == :private
|
480
574
|
count_namespace
|
481
575
|
|
482
576
|
superclass = nil
|
@@ -499,7 +593,7 @@ module Sord
|
|
499
593
|
@current_object = parent
|
500
594
|
end
|
501
595
|
|
502
|
-
# Populates the generator with the contents of the YARD registry. You
|
596
|
+
# Populates the generator with the contents of the YARD registry. You
|
503
597
|
# must load the YARD registry first!
|
504
598
|
# @return [void]
|
505
599
|
def populate
|
@@ -597,5 +691,20 @@ module Sord
|
|
597
691
|
|
598
692
|
return pair_type_order[pair1_type] <=> pair_type_order[pair2_type]
|
599
693
|
end
|
694
|
+
|
695
|
+
# Removes the last character of a default parameter value if it begins with
|
696
|
+
# '-', working around a bug in YARD. (See lsegal/yard #894)
|
697
|
+
#
|
698
|
+
# @param [String] default
|
699
|
+
# @return [String, nil]
|
700
|
+
def fix_default_if_unary_minus(default)
|
701
|
+
if default.nil?
|
702
|
+
nil
|
703
|
+
elsif default[0] == '-' && !default.start_with?('->')
|
704
|
+
default[0..-2]
|
705
|
+
else
|
706
|
+
default
|
707
|
+
end
|
708
|
+
end
|
600
709
|
end
|
601
710
|
end
|
data/lib/sord/logging.rb
CHANGED
@@ -70,16 +70,17 @@ module Sord
|
|
70
70
|
# is associated with, if any. This is shown before the log message if it is
|
71
71
|
# specified.
|
72
72
|
# @return [void]
|
73
|
-
def self.generic(kind, header, msg, item)
|
73
|
+
def self.generic(kind, header, msg, item, **opts)
|
74
74
|
return unless enabled_types.include?(kind)
|
75
75
|
|
76
|
-
if item
|
77
|
-
|
76
|
+
message = if item
|
77
|
+
"#{header} (#{Rainbow(item.path).bold}) #{msg}"
|
78
78
|
else
|
79
|
-
|
79
|
+
"#{header} #{msg}"
|
80
80
|
end
|
81
|
+
puts message unless silent?
|
81
82
|
|
82
|
-
invoke_hooks(kind, msg, item)
|
83
|
+
invoke_hooks(kind, msg, item, **opts)
|
83
84
|
end
|
84
85
|
|
85
86
|
# Print a warning message. This should be used for things which require the
|
@@ -89,8 +90,8 @@ module Sord
|
|
89
90
|
# is associated with, if any. This is shown before the log message if it is
|
90
91
|
# specified.
|
91
92
|
# @return [void]
|
92
|
-
def self.warn(msg, item = nil)
|
93
|
-
generic(:warn, Rainbow('[WARN ]').yellow, msg, item)
|
93
|
+
def self.warn(msg, item = nil, **opts)
|
94
|
+
generic(:warn, Rainbow('[WARN ]').yellow, msg, item, **opts)
|
94
95
|
end
|
95
96
|
|
96
97
|
# Print an info message. This should be used for generic informational
|
@@ -100,8 +101,8 @@ module Sord
|
|
100
101
|
# is associated with, if any. This is shown before the log message if it is
|
101
102
|
# specified.
|
102
103
|
# @return [void]
|
103
|
-
def self.info(msg, item = nil)
|
104
|
-
generic(:info, '[INFO ]', msg, item)
|
104
|
+
def self.info(msg, item = nil, **opts)
|
105
|
+
generic(:info, '[INFO ]', msg, item, **opts)
|
105
106
|
end
|
106
107
|
|
107
108
|
# Print a duck-typing message. This should be used when the YARD
|
@@ -112,8 +113,8 @@ module Sord
|
|
112
113
|
# is associated with, if any. This is shown before the log message if it is
|
113
114
|
# specified.
|
114
115
|
# @return [void]
|
115
|
-
def self.duck(msg, item = nil)
|
116
|
-
generic(:duck, Rainbow('[DUCK ]').cyan, msg, item)
|
116
|
+
def self.duck(msg, item = nil, **opts)
|
117
|
+
generic(:duck, Rainbow('[DUCK ]').cyan, msg, item, **opts)
|
117
118
|
end
|
118
119
|
|
119
120
|
# Print an error message. This should be used for things which require the
|
@@ -123,8 +124,8 @@ module Sord
|
|
123
124
|
# is associated with, if any. This is shown before the log message if it is
|
124
125
|
# specified.
|
125
126
|
# @return [void]
|
126
|
-
def self.error(msg, item = nil)
|
127
|
-
generic(:error, Rainbow('[ERROR]').red, msg, item)
|
127
|
+
def self.error(msg, item = nil, **opts)
|
128
|
+
generic(:error, Rainbow('[ERROR]').red, msg, item, **opts)
|
128
129
|
end
|
129
130
|
|
130
131
|
# Print an infer message. This should be used when the user should be told
|
@@ -135,8 +136,8 @@ module Sord
|
|
135
136
|
# is associated with, if any. This is shown before the log message if it is
|
136
137
|
# specified.
|
137
138
|
# @return [void]
|
138
|
-
def self.infer(msg, item = nil)
|
139
|
-
generic(:infer, Rainbow('[INFER]').blue, msg, item)
|
139
|
+
def self.infer(msg, item = nil, **opts)
|
140
|
+
generic(:infer, Rainbow('[INFER]').blue, msg, item, **opts)
|
140
141
|
end
|
141
142
|
|
142
143
|
# Print an omit message. This should be used as a special type of warning
|
@@ -147,8 +148,8 @@ module Sord
|
|
147
148
|
# is associated with, if any. This is shown before the log message if it is
|
148
149
|
# specified.
|
149
150
|
# @return [void]
|
150
|
-
def self.omit(msg, item = nil)
|
151
|
-
generic(:omit, Rainbow('[OMIT ]').magenta, msg, item)
|
151
|
+
def self.omit(msg, item = nil, **opts)
|
152
|
+
generic(:omit, Rainbow('[OMIT ]').magenta, msg, item, **opts)
|
152
153
|
end
|
153
154
|
|
154
155
|
# Print a done message. This should be used when a process completes
|
@@ -158,8 +159,8 @@ module Sord
|
|
158
159
|
# is associated with, if any. This is shown before the log message if it is
|
159
160
|
# specified.
|
160
161
|
# @return [void]
|
161
|
-
def self.done(msg, item = nil)
|
162
|
-
generic(:done, Rainbow('[DONE ]').green, msg, item)
|
162
|
+
def self.done(msg, item = nil, **opts)
|
163
|
+
generic(:done, Rainbow('[DONE ]').green, msg, item, **opts)
|
163
164
|
end
|
164
165
|
|
165
166
|
# Invokes all registered hooks on the logger.
|
@@ -169,9 +170,9 @@ module Sord
|
|
169
170
|
# is associated with, if any. This is shown before the log message if it is
|
170
171
|
# specified.
|
171
172
|
# @return [void]
|
172
|
-
def self.invoke_hooks(kind, msg, item)
|
173
|
+
def self.invoke_hooks(kind, msg, item, **opts)
|
173
174
|
@@hooks.each do |hook|
|
174
|
-
hook.(kind, msg, item)
|
175
|
+
hook.(kind, msg, item, **opts)
|
175
176
|
end
|
176
177
|
end
|
177
178
|
|