sord 0.10.0 → 3.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  3. data/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
  4. data/.gitignore +0 -0
  5. data/.parlour +6 -2
  6. data/.rspec +0 -0
  7. data/.travis.yml +0 -0
  8. data/CHANGELOG.md +68 -0
  9. data/CODE_OF_CONDUCT.md +0 -0
  10. data/Gemfile +0 -0
  11. data/LICENSE.txt +0 -0
  12. data/README.md +72 -44
  13. data/Rakefile +26 -7
  14. data/exe/sord +46 -6
  15. data/lib/sord.rb +1 -1
  16. data/lib/sord/generator.rb +592 -0
  17. data/lib/sord/logging.rb +0 -0
  18. data/lib/sord/parlour_plugin.rb +23 -2
  19. data/lib/sord/resolver.rb +0 -0
  20. data/lib/sord/type_converter.rb +71 -63
  21. data/lib/sord/version.rb +1 -1
  22. data/rbi/sord.rbi +211 -30
  23. data/sord.gemspec +3 -3
  24. metadata +11 -30
  25. data/lib/sord/rbi_generator.rb +0 -391
  26. data/sorbet/config +0 -0
  27. data/sorbet/rbi/gems/docile.rbi +0 -31
  28. data/sorbet/rbi/gems/parlour.rbi +0 -214
  29. data/sorbet/rbi/gems/rainbow.rbi +0 -117
  30. data/sorbet/rbi/gems/rake.rbi +0 -643
  31. data/sorbet/rbi/gems/rspec-core.rbi +0 -1658
  32. data/sorbet/rbi/gems/rspec-expectations.rbi +0 -389
  33. data/sorbet/rbi/gems/rspec-mocks.rbi +0 -823
  34. data/sorbet/rbi/gems/rspec-support.rbi +0 -268
  35. data/sorbet/rbi/gems/rspec.rbi +0 -14
  36. data/sorbet/rbi/gems/simplecov-html.rbi +0 -30
  37. data/sorbet/rbi/gems/simplecov.rbi +0 -225
  38. data/sorbet/rbi/gems/sorbet-runtime.rbi +0 -670
  39. data/sorbet/rbi/gems/yard.rbi +0 -310
  40. data/sorbet/rbi/hidden-definitions/errors.txt +0 -9285
  41. data/sorbet/rbi/hidden-definitions/hidden.rbi +0 -26604
  42. data/sorbet/rbi/sorbet-typed/lib/bundler/all/bundler.rbi +0 -8575
  43. data/sorbet/rbi/sorbet-typed/lib/ruby/all/open3.rbi +0 -111
  44. data/sorbet/rbi/sorbet-typed/lib/ruby/all/resolv.rbi +0 -543
@@ -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) }
@@ -24,8 +24,8 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_dependency 'yard'
26
26
  spec.add_dependency 'sorbet-runtime'
27
- spec.add_dependency 'commander', '~> 4.4'
28
- spec.add_dependency 'parlour', '~> 0.8.0'
27
+ spec.add_dependency 'commander', '~> 4.5'
28
+ spec.add_dependency 'parlour', '~> 5.0'
29
29
 
30
30
  spec.add_development_dependency "bundler", "~> 2.0"
31
31
  spec.add_development_dependency "rake", "~> 10.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sord
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Christiansen
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-14 00:00:00.000000000 Z
11
+ date: 2020-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yard
@@ -44,28 +44,28 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '4.4'
47
+ version: '4.5'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '4.4'
54
+ version: '4.5'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: parlour
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.8.0
61
+ version: '5.0'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.8.0
68
+ version: '5.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: bundler
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -136,7 +136,7 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
- description:
139
+ description:
140
140
  email:
141
141
  - aaronc20000@gmail.com
142
142
  executables:
@@ -158,38 +158,19 @@ files:
158
158
  - Rakefile
159
159
  - exe/sord
160
160
  - lib/sord.rb
161
+ - lib/sord/generator.rb
161
162
  - lib/sord/logging.rb
162
163
  - lib/sord/parlour_plugin.rb
163
- - lib/sord/rbi_generator.rb
164
164
  - lib/sord/resolver.rb
165
165
  - lib/sord/type_converter.rb
166
166
  - lib/sord/version.rb
167
167
  - rbi/sord.rbi
168
- - sorbet/config
169
- - sorbet/rbi/gems/docile.rbi
170
- - sorbet/rbi/gems/parlour.rbi
171
- - sorbet/rbi/gems/rainbow.rbi
172
- - sorbet/rbi/gems/rake.rbi
173
- - sorbet/rbi/gems/rspec-core.rbi
174
- - sorbet/rbi/gems/rspec-expectations.rbi
175
- - sorbet/rbi/gems/rspec-mocks.rbi
176
- - sorbet/rbi/gems/rspec-support.rbi
177
- - sorbet/rbi/gems/rspec.rbi
178
- - sorbet/rbi/gems/simplecov-html.rbi
179
- - sorbet/rbi/gems/simplecov.rbi
180
- - sorbet/rbi/gems/sorbet-runtime.rbi
181
- - sorbet/rbi/gems/yard.rbi
182
- - sorbet/rbi/hidden-definitions/errors.txt
183
- - sorbet/rbi/hidden-definitions/hidden.rbi
184
- - sorbet/rbi/sorbet-typed/lib/bundler/all/bundler.rbi
185
- - sorbet/rbi/sorbet-typed/lib/ruby/all/open3.rbi
186
- - sorbet/rbi/sorbet-typed/lib/ruby/all/resolv.rbi
187
168
  - sord.gemspec
188
169
  homepage: https://github.com/AaronC81/sord
189
170
  licenses:
190
171
  - MIT
191
172
  metadata: {}
192
- post_install_message:
173
+ post_install_message:
193
174
  rdoc_options: []
194
175
  require_paths:
195
176
  - lib
@@ -205,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
205
186
  version: '0'
206
187
  requirements: []
207
188
  rubygems_version: 3.0.3
208
- signing_key:
189
+ signing_key:
209
190
  specification_version: 4
210
191
  summary: Generate Sorbet RBI files from YARD documentation
211
192
  test_files: []
@@ -1,391 +0,0 @@
1
- # typed: true
2
- require 'yard'
3
- require 'sord/type_converter'
4
- require 'sord/logging'
5
- require 'parlour'
6
- require 'rainbow'
7
-
8
- module Sord
9
- # Converts the current working directory's YARD registry into an RBI file.
10
- class RbiGenerator
11
- # @return [Integer] The number of objects this generator has processed so
12
- # far.
13
- def object_count
14
- @namespace_count + @method_count
15
- end
16
-
17
- # @return [Array<Array(String, YARD::CodeObjects::Base, Integer)>] The
18
- # errors encountered by by the generator. Each element is of the form
19
- # [message, item, line].
20
- attr_reader :warnings
21
-
22
- # Create a new RBI generator.
23
- # @param [Hash] options
24
- # @option options [Integer] break_params
25
- # @option options [Boolean] replace_errors_with_untyped
26
- # @option options [Boolean] replace_unresolved_with_untyped
27
- # @option options [Boolean] comments
28
- # @option options [Parlour::RbiGenerator] generator
29
- # @option options [Parlour::RbiGenerator::Namespace] root
30
- # @return [void]
31
- def initialize(options)
32
- @parlour = options[:parlour] || Parlour::RbiGenerator.new
33
- @current_object = options[:root] || @parlour.root
34
-
35
- @namespace_count = 0
36
- @method_count = 0
37
- @warnings = []
38
-
39
- @replace_errors_with_untyped = options[:replace_errors_with_untyped]
40
- @replace_unresolved_with_untyped = options[:replace_unresolved_with_untyped]
41
- @keep_original_comments = options[:keep_original_comments]
42
-
43
- # Hook the logger so that messages are added as comments to the RBI file
44
- Logging.add_hook do |type, msg, item|
45
- @current_object.add_comment_to_next_child("sord #{type} - #{msg}")
46
- end if options[:sord_comments]
47
-
48
- # Hook the logger so that warnings are collected
49
- Logging.add_hook do |type, msg, item|
50
- # TODO: is it possible to get line numbers here?
51
- warnings << [msg, item, 0] if type == :warn
52
- end
53
- end
54
-
55
- # Increment the namespace counter.
56
- # @return [void]
57
- def count_namespace
58
- @namespace_count += 1
59
- end
60
-
61
- # Increment the method counter.
62
- # @return [void]
63
- def count_method
64
- @method_count += 1
65
- end
66
-
67
- # Given a YARD CodeObject, add lines defining its mixins (that is, extends
68
- # and includes) to the current RBI file. Returns the number of mixins.
69
- # @param [YARD::CodeObjects::Base] item
70
- # @return [Integer]
71
- def add_mixins(item)
72
- item.instance_mixins.reverse_each do |i|
73
- @current_object.create_include(i.path.to_s)
74
- end
75
- item.class_mixins.reverse_each do |e|
76
- @current_object.create_extend(e.path.to_s)
77
- end
78
-
79
- item.instance_mixins.length + item.class_mixins.length
80
- end
81
-
82
- # Given a YARD NamespaceObject, add lines defining constants.
83
- # @param [YARD::CodeObjects::NamespaceObject] item
84
- # @return [void]
85
- def add_constants(item)
86
- item.constants.each do |constant|
87
- # Take a constant (like "A::B::CONSTANT"), split it on each '::', and
88
- # set the constant name to the last string in the array.
89
- constant_name = constant.to_s.split('::').last
90
-
91
- # Add the constant to the current object being generated.
92
- @current_object.create_constant(constant_name, value: "T.let(#{constant.value}, T.untyped)") do |c|
93
- c.add_comments(constant.docstring.all.split("\n"))
94
- end
95
- end
96
- end
97
-
98
- # Given a YARD NamespaceObject, add lines defining its methods and their
99
- # signatures to the current RBI file.
100
- # @param [YARD::CodeObjects::NamespaceObject] item
101
- # @return [void]
102
- def add_methods(item)
103
- item.meths(inherited: false).each do |meth|
104
- count_method
105
-
106
- # If the method is an alias, skip it so we don't define it as a
107
- # separate method. Sorbet will handle it automatically.
108
- if meth.is_alias?
109
- next
110
- end
111
-
112
- # This is better than iterating over YARD's "@param" tags directly
113
- # because it includes parameters without documentation
114
- # (The gsubs allow for better splat-argument compatibility)
115
- parameter_names_and_defaults_to_tags = meth.parameters.map do |name, default|
116
- [[name, default], meth.tags('param')
117
- .find { |p| p.name&.gsub('*', '')&.gsub(':', '') == name.gsub('*', '').gsub(':', '') }]
118
- end.to_h
119
-
120
- parameter_types = parameter_names_and_defaults_to_tags.map do |name_and_default, tag|
121
- name = name_and_default.first
122
-
123
- if tag
124
- TypeConverter.yard_to_sorbet(tag.types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
125
- elsif name.start_with? '&'
126
- # Find yieldparams and yieldreturn
127
- yieldparams = meth.tags('yieldparam')
128
- yieldreturn = meth.tag('yieldreturn')&.types
129
- yieldreturn = nil if yieldreturn&.length == 1 &&
130
- yieldreturn&.first&.downcase == 'void'
131
-
132
- # Create strings
133
- params_string = yieldparams.map do |param|
134
- "#{param.name.gsub('*', '')}: #{TypeConverter.yard_to_sorbet(param.types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)}" unless param.name.nil?
135
- end.join(', ')
136
- return_string = TypeConverter.yard_to_sorbet(yieldreturn, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
137
-
138
- # Create proc types, if possible
139
- if yieldparams.empty? && yieldreturn.nil?
140
- 'T.untyped'
141
- elsif yieldreturn.nil?
142
- "T.proc#{params_string.empty? ? '' : ".params(#{params_string})"}.void"
143
- else
144
- "T.proc#{params_string.empty? ? '' : ".params(#{params_string})"}.returns(#{return_string})"
145
- end
146
- elsif meth.path.end_with? '='
147
- # Look for the matching getter method
148
- getter_path = meth.path[0...-1]
149
- getter = item.meths.find { |m| m.path == getter_path }
150
-
151
- unless getter
152
- if parameter_names_and_defaults_to_tags.length == 1 \
153
- && meth.tags('param').length == 1 \
154
- && meth.tag('param').types
155
-
156
- Logging.infer("argument name in single @param inferred as #{parameter_names_and_defaults_to_tags.first.first.first.inspect}", meth)
157
- next TypeConverter.yard_to_sorbet(meth.tag('param').types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
158
- else
159
- Logging.omit("no YARD type given for #{name.inspect}, using T.untyped", meth)
160
- next 'T.untyped'
161
- end
162
- end
163
-
164
- return_types = getter.tags('return').flat_map(&:types)
165
- unless return_types.any?
166
- Logging.omit("no YARD type given for #{name.inspect}, using T.untyped", meth)
167
- next 'T.untyped'
168
- end
169
- inferred_type = TypeConverter.yard_to_sorbet(
170
- return_types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
171
-
172
- Logging.infer("inferred type of parameter #{name.inspect} as #{inferred_type} using getter's return type", meth)
173
- inferred_type
174
- else
175
- # Is this the only argument, and was a @param specified without an
176
- # argument name? If so, infer it
177
- if parameter_names_and_defaults_to_tags.length == 1 \
178
- && meth.tags('param').length == 1 \
179
- && meth.tag('param').types
180
-
181
- Logging.infer("argument name in single @param inferred as #{parameter_names_and_defaults_to_tags.first.first.first.inspect}", meth)
182
- TypeConverter.yard_to_sorbet(meth.tag('param').types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
183
- else
184
- Logging.omit("no YARD type given for #{name.inspect}, using T.untyped", meth)
185
- 'T.untyped'
186
- end
187
- end
188
- end
189
-
190
- return_tags = meth.tags('return')
191
- returns = if return_tags.length == 0
192
- Logging.omit("no YARD return type given, using T.untyped", meth)
193
- 'T.untyped'
194
- elsif return_tags.length == 1 && return_tags&.first&.types&.first&.downcase == "void"
195
- nil
196
- else
197
- TypeConverter.yard_to_sorbet(meth.tag('return').types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
198
- end
199
-
200
- parlour_params = parameter_names_and_defaults_to_tags
201
- .zip(parameter_types)
202
- .map do |((name, default), _), type|
203
- # If the default is "nil" but the type is not nilable, then it
204
- # should become nilable
205
- # (T.untyped can include nil, so don't alter that)
206
- type = "T.nilable(#{type})" \
207
- if default == 'nil' && !type.start_with?('T.nilable') && type != 'T.untyped'
208
- Parlour::RbiGenerator::Parameter.new(
209
- name.to_s,
210
- type: type,
211
- default: default
212
- )
213
- end
214
-
215
- @current_object.create_method(
216
- meth.name.to_s,
217
- parameters: parlour_params,
218
- returns: returns,
219
- class_method: meth.scope == :class
220
- ) do |m|
221
- if @keep_original_comments
222
- m.add_comments(meth.docstring.all.split("\n"))
223
- else
224
- parser = YARD::Docstring.parser
225
- parser.parse(meth.docstring.all)
226
-
227
- docs_array = parser.text.split("\n")
228
-
229
- # Add @param tags if there are any with names and descriptions.
230
- params = parser.tags.select { |tag| tag.tag_name == 'param' && tag.is_a?(YARD::Tags::Tag) && !tag.name.nil? }
231
- # Add a blank line if there's anything before the params.
232
- docs_array << '' if docs_array.length.positive? && params.length.positive?
233
- params.each do |param|
234
- docs_array << '' if docs_array.last != '' && docs_array.length.positive?
235
- # Output params in the form of:
236
- # _@param_ `foo` — Lorem ipsum.
237
- # _@param_ `foo`
238
- if param.text.nil?
239
- docs_array << "_@param_ `#{param.name}`"
240
- else
241
- docs_array << "_@param_ `#{param.name}` — #{param.text}"
242
- end
243
- end
244
-
245
- # Add @return tags (there could possibly be more than one, despite this not being supported)
246
- returns = parser.tags.select { |tag| tag.tag_name == 'return' && tag.is_a?(YARD::Tags::Tag) && !tag.text.nil? && tag.text.strip != '' }
247
- # Add a blank line if there's anything before the returns.
248
- docs_array << '' if docs_array.length.positive? && returns.length.positive?
249
- returns.each do |retn|
250
- docs_array << '' if docs_array.last != '' && docs_array.length.positive?
251
- # Output returns in the form of:
252
- # _@return_ — Lorem ipsum.
253
- docs_array << "_@return_ — #{retn.text}"
254
- end
255
-
256
- # Iterate through the @example tags for a given YARD doc and output them in Markdown codeblocks.
257
- examples = parser.tags.select { |tag| tag.tag_name == 'example' && tag.is_a?(YARD::Tags::Tag) }
258
- examples.each do |example|
259
- # Only add a blank line if there's anything before the example.
260
- docs_array << '' if docs_array.length.positive?
261
- # Include the example's 'name' if there is one.
262
- docs_array << example.name unless example.name.nil? || example.name == ""
263
- docs_array << "```ruby"
264
- docs_array.concat(example.text.split("\n"))
265
- docs_array << "```"
266
- end if examples.length.positive?
267
-
268
- # Add @note and @deprecated tags.
269
- notice_tags = parser.tags.select { |tag| ['note', 'deprecated'].include?(tag.tag_name) && tag.is_a?(YARD::Tags::Tag) }
270
- # Add a blank line if there's anything before the params.
271
- docs_array << '' if docs_array.last != '' && docs_array.length.positive? && notice_tags.length.positive?
272
- notice_tags.each do |notice_tag|
273
- docs_array << '' if docs_array.last != ''
274
- # Output note/deprecated/see in the form of:
275
- # _@note_ — Lorem ipsum.
276
- # _@note_
277
- if notice_tag.text.nil?
278
- docs_array << "_@#{notice_tag.tag_name}_"
279
- else
280
- docs_array << "_@#{notice_tag.tag_name}_ — #{notice_tag.text}"
281
- end
282
- end
283
-
284
- # Add @see tags.
285
- see_tags = parser.tags.select { |tag| tag.tag_name == 'see' && tag.is_a?(YARD::Tags::Tag) }
286
- # Add a blank line if there's anything before the params.
287
- docs_array << '' if docs_array.last != '' && docs_array.length.positive? && see_tags.length.positive?
288
- see_tags.each do |see_tag|
289
- docs_array << '' if docs_array.last != ''
290
- # Output note/deprecated/see in the form of:
291
- # _@see_ `B` — Lorem ipsum.
292
- # _@see_ `B`
293
- if see_tag.text.nil?
294
- docs_array << "_@see_ `#{see_tag.name}`"
295
- else
296
- docs_array << "_@see_ `#{see_tag.name}` — #{see_tag.text}"
297
- end
298
- end
299
-
300
- m.add_comments(docs_array)
301
- end
302
- end
303
- end
304
- end
305
-
306
- # Given a YARD NamespaceObject, add lines defining its mixins, methods
307
- # and children to the RBI file.
308
- # @param [YARD::CodeObjects::NamespaceObject] item
309
- # @return [void]
310
- def add_namespace(item)
311
- count_namespace
312
-
313
- superclass = nil
314
- superclass = item.superclass.path.to_s if item.type == :class && item.superclass.to_s != "Object"
315
-
316
- parent = @current_object
317
- @current_object = item.type == :class \
318
- ? parent.create_class(item.name.to_s, superclass: superclass)
319
- : parent.create_module(item.name.to_s)
320
- @current_object.add_comments(item.docstring.all.split("\n"))
321
-
322
- add_mixins(item)
323
- add_methods(item)
324
- add_constants(item)
325
-
326
- item.children.select { |x| [:class, :module].include?(x.type) }
327
- .each { |child| add_namespace(child) }
328
-
329
- @current_object = parent
330
- end
331
-
332
- # Populates the RBI generator with the contents of the YARD registry. You
333
- # must load the YARD registry first!
334
- # @return [void]
335
- def populate
336
- # Generate top-level modules, which recurses to all modules
337
- YARD::Registry.root.children
338
- .select { |x| [:class, :module].include?(x.type) }
339
- .each { |child| add_namespace(child) }
340
- end
341
-
342
- # Populates the RBI generator with the contents of the YARD registry, then
343
- # uses the loaded Parlour::RbiGenerator to generate the RBI file. You must
344
- # load the YARD registry first!
345
- # @return [void]
346
- def generate
347
- populate
348
- @parlour.rbi
349
- end
350
-
351
- # Loads the YARD registry, populates the RBI file, and prints any relevant
352
- # final logs.
353
- # @return [void]
354
- def run
355
- # Get YARD ready
356
- YARD::Registry.load!
357
-
358
- # Populate the RBI
359
- populate
360
-
361
- if object_count.zero?
362
- Logging.warn("No objects processed.")
363
- Logging.warn("Have you definitely generated the YARD documentation for this project?")
364
- Logging.warn("Run `yard` to generate docs.")
365
- end
366
-
367
- Logging.done("Processed #{object_count} objects (#{@namespace_count} namespaces and #{@method_count} methods)")
368
-
369
- Logging.hooks.clear
370
-
371
- unless warnings.empty?
372
- Logging.warn("There were #{warnings.length} important warnings in the RBI file, listed below.")
373
- if @replace_errors_with_untyped
374
- Logging.warn("The types which caused them have been replaced with T.untyped.")
375
- else
376
- Logging.warn("The types which caused them have been replaced with SORD_ERROR_ constants.")
377
- end
378
- Logging.warn("Please edit the file to fix these errors.")
379
- Logging.warn("Alternatively, edit your YARD documentation so that your types are valid and re-run Sord.")
380
- warnings.each do |(msg, item, _)|
381
- puts " (#{Rainbow(item&.path).bold}) #{msg}"
382
- end
383
- end
384
- rescue
385
- Logging.error($!)
386
- $@.each do |line|
387
- puts " #{line}"
388
- end
389
- end
390
- end
391
- end