sord 0.8.0 → 3.0.0.beta.1

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 (43) 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 +11 -0
  6. data/.rspec +0 -0
  7. data/.travis.yml +6 -0
  8. data/CHANGELOG.md +99 -0
  9. data/CODE_OF_CONDUCT.md +0 -0
  10. data/Gemfile +0 -0
  11. data/LICENSE.txt +0 -0
  12. data/README.md +17 -11
  13. data/Rakefile +87 -12
  14. data/exe/sord +50 -33
  15. data/lib/sord.rb +2 -1
  16. data/lib/sord/generator.rb +592 -0
  17. data/lib/sord/logging.rb +21 -30
  18. data/lib/sord/parlour_plugin.rb +84 -0
  19. data/lib/sord/resolver.rb +9 -2
  20. data/lib/sord/type_converter.rb +88 -42
  21. data/lib/sord/version.rb +1 -1
  22. data/rbi/sord.rbi +279 -68
  23. data/sord.gemspec +3 -3
  24. metadata +23 -38
  25. data/lib/sord/rbi_generator.rb +0 -334
  26. data/sorbet/config +0 -0
  27. data/sorbet/rbi/gems/colorize.rbi +0 -81
  28. data/sorbet/rbi/gems/docile.rbi +0 -31
  29. data/sorbet/rbi/gems/rake.rbi +0 -643
  30. data/sorbet/rbi/gems/rspec-core.rbi +0 -1658
  31. data/sorbet/rbi/gems/rspec-expectations.rbi +0 -389
  32. data/sorbet/rbi/gems/rspec-mocks.rbi +0 -823
  33. data/sorbet/rbi/gems/rspec-support.rbi +0 -268
  34. data/sorbet/rbi/gems/rspec.rbi +0 -14
  35. data/sorbet/rbi/gems/simplecov-html.rbi +0 -30
  36. data/sorbet/rbi/gems/simplecov.rbi +0 -223
  37. data/sorbet/rbi/gems/sorbet-runtime.rbi +0 -647
  38. data/sorbet/rbi/gems/yard.rbi +0 -310
  39. data/sorbet/rbi/hidden-definitions/errors.txt +0 -9353
  40. data/sorbet/rbi/hidden-definitions/hidden.rbi +0 -16640
  41. data/sorbet/rbi/sorbet-typed/lib/bundler/all/bundler.rbi +0 -8547
  42. data/sorbet/rbi/sorbet-typed/lib/ruby/all/open3.rbi +0 -111
  43. data/sorbet/rbi/sorbet-typed/lib/ruby/all/resolv.rbi +0 -543
@@ -1,4 +1,5 @@
1
- require 'colorize'
1
+ # typed: true
2
+ require 'rainbow'
2
3
 
3
4
  module Sord
4
5
  # Handles writing logs to stdout and any other classes which request them.
@@ -68,18 +69,17 @@ module Sord
68
69
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
69
70
  # is associated with, if any. This is shown before the log message if it is
70
71
  # specified.
71
- # @param [Integer] indent_level The level at which to indent the code.
72
72
  # @return [void]
73
- def self.generic(kind, header, msg, item, indent_level = 0)
73
+ def self.generic(kind, header, msg, item)
74
74
  return unless enabled_types.include?(kind)
75
75
 
76
76
  if item
77
- puts "#{header} (#{item.path.bold}) #{msg}" unless silent?
77
+ puts "#{header} (#{Rainbow(item.path).bold}) #{msg}" unless silent?
78
78
  else
79
79
  puts "#{header} #{msg}" unless silent?
80
80
  end
81
81
 
82
- invoke_hooks(kind, msg, item, indent_level)
82
+ invoke_hooks(kind, msg, item)
83
83
  end
84
84
 
85
85
  # Print a warning message. This should be used for things which require the
@@ -88,10 +88,9 @@ module Sord
88
88
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
89
89
  # is associated with, if any. This is shown before the log message if it is
90
90
  # specified.
91
- # @param [Integer] indent_level The level at which to indent the code.
92
91
  # @return [void]
93
- def self.warn(msg, item = nil, indent_level = 0)
94
- generic(:warn, '[WARN ]'.yellow, msg, item, indent_level)
92
+ def self.warn(msg, item = nil)
93
+ generic(:warn, Rainbow('[WARN ]').yellow, msg, item)
95
94
  end
96
95
 
97
96
  # Print an info message. This should be used for generic informational
@@ -100,10 +99,9 @@ module Sord
100
99
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
101
100
  # is associated with, if any. This is shown before the log message if it is
102
101
  # specified.
103
- # @param [Integer] indent_level The level at which to indent the code.
104
102
  # @return [void]
105
- def self.info(msg, item = nil, indent_level = 0)
106
- generic(:info, '[INFO ]', msg, item, indent_level)
103
+ def self.info(msg, item = nil)
104
+ generic(:info, '[INFO ]', msg, item)
107
105
  end
108
106
 
109
107
  # Print a duck-typing message. This should be used when the YARD
@@ -113,10 +111,9 @@ module Sord
113
111
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
114
112
  # is associated with, if any. This is shown before the log message if it is
115
113
  # specified.
116
- # @param [Integer] indent_level The level at which to indent the code.
117
114
  # @return [void]
118
- def self.duck(msg, item = nil, indent_level = 0)
119
- generic(:duck, '[DUCK ]'.cyan, msg, item, indent_level)
115
+ def self.duck(msg, item = nil)
116
+ generic(:duck, Rainbow('[DUCK ]').cyan, msg, item)
120
117
  end
121
118
 
122
119
  # Print an error message. This should be used for things which require the
@@ -125,10 +122,9 @@ module Sord
125
122
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
126
123
  # is associated with, if any. This is shown before the log message if it is
127
124
  # specified.
128
- # @param [Integer] indent_level The level at which to indent the code.
129
125
  # @return [void]
130
- def self.error(msg, item = nil, indent_level = 0)
131
- generic(:error, '[ERROR]'.red, msg, item, indent_level)
126
+ def self.error(msg, item = nil)
127
+ generic(:error, Rainbow('[ERROR]').red, msg, item)
132
128
  end
133
129
 
134
130
  # Print an infer message. This should be used when the user should be told
@@ -138,10 +134,9 @@ module Sord
138
134
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
139
135
  # is associated with, if any. This is shown before the log message if it is
140
136
  # specified.
141
- # @param [Integer] indent_level The level at which to indent the code.
142
137
  # @return [void]
143
- def self.infer(msg, item = nil, indent_level = 0)
144
- generic(:infer, '[INFER]'.light_blue, msg, item, indent_level)
138
+ def self.infer(msg, item = nil)
139
+ generic(:infer, Rainbow('[INFER]').blue, msg, item)
145
140
  end
146
141
 
147
142
  # Print an omit message. This should be used as a special type of warning
@@ -151,10 +146,9 @@ module Sord
151
146
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
152
147
  # is associated with, if any. This is shown before the log message if it is
153
148
  # specified.
154
- # @param [Integer] indent_level The level at which to indent the code.
155
149
  # @return [void]
156
- def self.omit(msg, item = nil, indent_level = 0)
157
- generic(:omit, '[OMIT ]'.magenta, msg, item, indent_level)
150
+ def self.omit(msg, item = nil)
151
+ generic(:omit, Rainbow('[OMIT ]').magenta, msg, item)
158
152
  end
159
153
 
160
154
  # Print a done message. This should be used when a process completes
@@ -163,10 +157,9 @@ module Sord
163
157
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
164
158
  # is associated with, if any. This is shown before the log message if it is
165
159
  # specified.
166
- # @param [Integer] indent_level The level at which to indent the code.
167
160
  # @return [void]
168
- def self.done(msg, item = nil, indent_level = 0)
169
- generic(:done, '[DONE ]'.green, msg, item)
161
+ def self.done(msg, item = nil)
162
+ generic(:done, Rainbow('[DONE ]').green, msg, item)
170
163
  end
171
164
 
172
165
  # Invokes all registered hooks on the logger.
@@ -175,11 +168,10 @@ module Sord
175
168
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
176
169
  # is associated with, if any. This is shown before the log message if it is
177
170
  # specified.
178
- # @param [Integer] indent_level The level at which to indent the code.
179
171
  # @return [void]
180
- def self.invoke_hooks(kind, msg, item, indent_level = 0)
172
+ def self.invoke_hooks(kind, msg, item)
181
173
  @@hooks.each do |hook|
182
- hook.(kind, msg, item, indent_level) rescue nil
174
+ hook.(kind, msg, item) rescue nil
183
175
  end
184
176
  end
185
177
 
@@ -189,7 +181,6 @@ module Sord
189
181
  # @yieldparam [YARD::CodeObjects::Base] item The CodeObject which this log
190
182
  # is associated with, if any. This is shown before the log message if it is
191
183
  # specified.
192
- # @yieldparam [Integer] indent_level The level at which to indent the code.
193
184
  # @yieldreturn [void]
194
185
  # @return [void]
195
186
  def self.add_hook(&blk)
@@ -0,0 +1,84 @@
1
+ # typed: true
2
+ require 'parlour'
3
+
4
+ module Sord
5
+ class ParlourPlugin < Parlour::Plugin
6
+ attr_reader :options
7
+ attr_accessor :parlour
8
+
9
+ def initialize(options)
10
+ @parlour = nil
11
+ @options = options
12
+
13
+ options[:sord_comments] = true if options[:sord_comments].nil?
14
+ options[:regenerate] = true if options[:regenerate].nil?
15
+ options[:replace_errors_with_untyped] ||= false
16
+ options[:replace_unresolved_with_untyped] ||= false
17
+ end
18
+
19
+ def generate(root)
20
+ if options[:include_messages] && options[:exclude_messages]
21
+ Sord::Logging.error('Please specify only one of --include-messages and --exclude-messages.')
22
+ return false
23
+ elsif options[:include_messages]
24
+ whitelist = options[:include_messages].map { |x| x.downcase.to_sym }
25
+ unless Sord::Logging.valid_types?(whitelist)
26
+ Sord::Logging.error('Not all types on your --include-messages list are valid.')
27
+ Sord::Logging.error("Valid options are: #{Sord::Logging::AVAILABLE_TYPES.map(&:to_s).join(', ')}")
28
+ return false
29
+ end
30
+ Sord::Logging.enabled_types = whitelist | [:done]
31
+ elsif options[:exclude_messages]
32
+ blacklist = options[:exclude_messages].map { |x| x.downcase.to_sym }
33
+ unless Sord::Logging.valid_types?(blacklist)
34
+ Sord::Logging.error('Not all types on your --include-messages list are valid.')
35
+ Sord::Logging.error("Valid options are: #{Sord::Logging::AVAILABLE_TYPES.map(&:to_s).join(', ')}")
36
+ return false
37
+ end
38
+ Sord::Logging.enabled_types = Sord::Logging::AVAILABLE_TYPES - blacklist
39
+ end
40
+
41
+ if !(options[:rbi] || options[:rbs])
42
+ Sord::Logging.error('No output format given; please specify --rbi or --rbs')
43
+ exit 1
44
+ end
45
+
46
+ if (options[:rbi] && options[:rbs])
47
+ Sord::Logging.error('You cannot specify both --rbi and --rbs; please use only one')
48
+ exit 1
49
+ end
50
+
51
+ if options[:regenerate]
52
+ begin
53
+ Sord::Logging.info('Running YARD...')
54
+ Sord::ParlourPlugin.with_clean_env do
55
+ system('bundle exec yard')
56
+ end
57
+ rescue Errno::ENOENT
58
+ Sord::Logging.error('The YARD tool could not be found on your PATH.')
59
+ Sord::Logging.error('You may need to run \'gem install yard\'.')
60
+ Sord::Logging.error('If documentation has already been generated, pass --no-regenerate to Sord.')
61
+ return false
62
+ end
63
+ end
64
+
65
+ options[:mode] = \
66
+ if options[:rbi] then :rbi elsif options[:rbs] then :rbs end
67
+ options[:parlour] = @parlour
68
+ options[:root] = root
69
+
70
+ Sord::Generator.new(options).run
71
+
72
+ true
73
+ end
74
+
75
+ def self.with_clean_env &block
76
+ meth = if Bundler.respond_to?(:with_unbundled_env)
77
+ :with_unbundled_env
78
+ else
79
+ :with_clean_env
80
+ end
81
+ Bundler.send meth, &block
82
+ end
83
+ end
84
+ end
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  require 'stringio'
2
3
 
3
4
  module Sord
@@ -50,12 +51,18 @@ module Sord
50
51
  # @param [Object] item
51
52
  # @return [Boolean]
52
53
  def self.resolvable?(name, item)
53
- name_parts = name.split('::')
54
-
55
54
  current_context = item
56
55
  current_context = current_context.parent \
57
56
  until current_context.is_a?(YARD::CodeObjects::NamespaceObject)
58
57
 
58
+ # If there is any matching object directly in the heirarchy, this is
59
+ # always true. Ruby can do the resolution.
60
+ unless name.include?('::')
61
+ return true if current_context.path.split('::').include?(name)
62
+ end
63
+
64
+ name_parts = name.split('::')
65
+
59
66
  matching_paths = []
60
67
 
61
68
  loop do
@@ -1,9 +1,11 @@
1
+ # typed: true
1
2
  require 'yaml'
2
3
  require 'sord/logging'
3
4
  require 'sord/resolver'
5
+ require 'parlour'
4
6
 
5
7
  module Sord
6
- # Contains methods to convert YARD types to Sorbet types.
8
+ # Contains methods to convert YARD types to Parlour types.
7
9
  module TypeConverter
8
10
  # A regular expression which matches Ruby namespaces and identifiers.
9
11
  # "Foo", "Foo::Bar", and "::Foo::Bar" are all matches, whereas "Foo.Bar"
@@ -36,9 +38,9 @@ module Sord
36
38
  # "<String>".
37
39
  SHORTHAND_ARRAY_SYNTAX = /^<\s*(.*)\s*>$/
38
40
 
39
- # An array of built-in generic types supported by Sorbet.
40
- SORBET_SUPPORTED_GENERIC_TYPES = %w{Array Set Enumerable Enumerator Range Hash Class}
41
- SORBET_SINGLE_ARG_GENERIC_TYPES = %w{Array Set Enumerable Enumerator Range}
41
+ # An array of built-in types supported by Parlour.
42
+ SUPPORTED_GENERIC_TYPES = %w{Array Set Enumerable Enumerator Range Hash Class}
43
+ SINGLE_ARG_GENERIC_TYPES = %w{Array Set Enumerable Enumerator Range}
42
44
 
43
45
  # Given a string of YARD type parameters (without angle brackets), splits
44
46
  # the string into an array of each type parameter.
@@ -89,37 +91,47 @@ module Sord
89
91
  result
90
92
  end
91
93
 
92
- # Converts a YARD type into a Sorbet type.
94
+ # Converts a YARD type into a Parlour type.
93
95
  # @param [Boolean, Array, String] yard The YARD type.
94
96
  # @param [YARD::CodeObjects::Base] item The CodeObject which the YARD type
95
97
  # is associated with. This is used for logging and can be nil, but this
96
98
  # will lead to less informative log messages.
97
- # @param [Integer] indent_level
98
99
  # @param [Boolean] replace_errors_with_untyped If true, T.untyped is used
99
100
  # instead of SORD_ERROR_ constants for unknown types.
100
- # @return [String]
101
- def self.yard_to_sorbet(yard, item = nil, indent_level = 0, replace_errors_with_untyped = false)
101
+ # @param [Boolean] replace_unresolved_with_untyped If true, T.untyped is used
102
+ # when Sord is unable to resolve a constant.
103
+ # @return [Parlour::Types::Type]
104
+ def self.yard_to_parlour(yard, item = nil, replace_errors_with_untyped = false, replace_unresolved_with_untyped = false)
102
105
  case yard
103
106
  when nil # Type not specified
104
- "T.untyped"
107
+ Parlour::Types::Untyped.new
105
108
  when "bool", "Bool", "boolean", "Boolean", "true", "false"
106
- "T::Boolean"
109
+ Parlour::Types::Boolean.new
107
110
  when 'self'
108
- item.parent.path
111
+ Parlour::Types::Self.new
109
112
  when Array
110
113
  # If there's only one element, unwrap it, otherwise allow for a
111
114
  # selection of any of the types
112
115
  types = yard
113
116
  .reject { |x| x == 'nil' }
114
- .map { |x| yard_to_sorbet(x, item, indent_level, replace_errors_with_untyped) }
115
- .uniq
116
- result = types.length == 1 ? types.first : "T.any(#{types.join(', ')})"
117
- result = "T.nilable(#{result})" if yard.include?('nil')
117
+ .map { |x| yard_to_parlour(x, item, replace_errors_with_untyped, replace_unresolved_with_untyped) }
118
+ .uniq(&:hash)
119
+ result = types.length == 1 \
120
+ ? types.first
121
+ : Parlour::Types::Union.new(types)
122
+ result = Parlour::Types::Nilable.new(result) if yard.include?('nil')
118
123
  result
119
124
  when /^#{SIMPLE_TYPE_REGEX}$/
125
+ if SINGLE_ARG_GENERIC_TYPES.include?(yard)
126
+ return Parlour::Types.const_get(yard).new(Parlour::Types::Untyped.new)
127
+ elsif yard == "Hash"
128
+ return Parlour::Types::Hash.new(
129
+ Parlour::Types::Untyped.new, Parlour::Types::Untyped.new
130
+ )
131
+ end
120
132
  # If this doesn't begin with an uppercase letter, warn
121
133
  if /^[_a-z]/ === yard
122
- Logging.warn("#{yard} is probably not a type, but using anyway", item, indent_level)
134
+ Logging.warn("#{yard} is probably not a type, but using anyway", item)
123
135
  end
124
136
 
125
137
  # Check if whatever has been specified is actually resolvable; if not,
@@ -127,65 +139,99 @@ module Sord
127
139
  if item && !Resolver.resolvable?(yard, item)
128
140
  if Resolver.path_for(yard)
129
141
  new_path = Resolver.path_for(yard)
130
- Logging.infer("#{yard} was resolved to #{new_path}", item, indent_level) \
142
+ Logging.infer("#{yard} was resolved to #{new_path}", item) \
131
143
  unless yard == new_path
132
- new_path
144
+ Parlour::Types::Raw.new(new_path)
133
145
  else
134
- Logging.warn("#{yard} wasn't able to be resolved to a constant in this project", item, indent_level)
135
- yard
146
+ if replace_unresolved_with_untyped
147
+ Logging.warn("#{yard} wasn't able to be resolved to a constant in this project, replaced with untyped", item)
148
+ Parlour::Types::Untyped.new
149
+ else
150
+ Logging.warn("#{yard} wasn't able to be resolved to a constant in this project", item)
151
+ Parlour::Types::Raw.new(yard)
152
+ end
136
153
  end
137
154
  else
138
- yard
155
+ Parlour::Types::Raw.new(yard)
139
156
  end
140
157
  when DUCK_TYPE_REGEX
141
- Logging.duck("#{yard} looks like a duck type, replacing with T.untyped", item, indent_level)
142
- 'T.untyped'
158
+ Logging.duck("#{yard} looks like a duck type, replacing with untyped", item)
159
+ Parlour::Types::Untyped.new
143
160
  when /^#{GENERIC_TYPE_REGEX}$/
144
161
  generic_type = $1
145
162
  type_parameters = $2
146
163
 
147
- if SORBET_SUPPORTED_GENERIC_TYPES.include?(generic_type)
164
+ if SUPPORTED_GENERIC_TYPES.include?(generic_type)
148
165
  parameters = split_type_parameters(type_parameters)
149
- .map { |x| yard_to_sorbet(x, item, indent_level, replace_errors_with_untyped) }
150
- if SORBET_SINGLE_ARG_GENERIC_TYPES.include?(generic_type) && parameters.length > 1
151
- "T::#{generic_type}[T.any(#{parameters.join(', ')})]"
166
+ .map { |x| yard_to_parlour(x, item, replace_errors_with_untyped, replace_unresolved_with_untyped) }
167
+ if SINGLE_ARG_GENERIC_TYPES.include?(generic_type) && parameters.length > 1
168
+ Parlour::Types.const_get(generic_type).new(Parlour::Types::Union.new(parameters))
152
169
  elsif generic_type == 'Class' && parameters.length == 1
153
- "T.class_of(#{parameters.first})"
170
+ Parlour::Types::Class.new(parameters.first)
171
+ elsif generic_type == 'Hash'
172
+ if parameters.length == 2
173
+ Parlour::Types::Hash.new(*parameters)
174
+ else
175
+ handle_sord_error(parameters.map(&:describe).join, "Invalid hash, must have exactly two types: #{yard.inspect}.", item, replace_errors_with_untyped)
176
+ end
154
177
  else
155
- "T::#{generic_type}[#{parameters.join(', ')}]"
178
+ Parlour::Types.const_get(generic_type).new(*parameters)
156
179
  end
157
180
  else
158
- Logging.warn("unsupported generic type #{generic_type.inspect} in #{yard.inspect}", item, indent_level)
159
- replace_errors_with_untyped ? "T.untyped" : "SORD_ERROR_#{generic_type.gsub(/[^0-9A-Za-z_]/i, '')}"
181
+ return handle_sord_error(
182
+ generic_type,
183
+ "unsupported generic type #{generic_type.inspect} in #{yard.inspect}",
184
+ item,
185
+ replace_errors_with_untyped
186
+ )
160
187
  end
161
188
  # Converts ordered lists like Array(Symbol, String) or (Symbol, String)
162
- # into Sorbet Tuples like [Symbol, String].
189
+ # into tuples.
163
190
  when ORDERED_LIST_REGEX
164
191
  type_parameters = $1
165
192
  parameters = split_type_parameters(type_parameters)
166
- .map { |x| yard_to_sorbet(x, item, indent_level, replace_errors_with_untyped) }
167
- "[#{parameters.join(', ')}]"
193
+ .map { |x| yard_to_parlour(x, item, replace_errors_with_untyped, replace_unresolved_with_untyped) }
194
+ Parlour::Types::Tuple.new(parameters)
168
195
  when SHORTHAND_HASH_SYNTAX
169
196
  type_parameters = $1
170
197
  parameters = split_type_parameters(type_parameters)
171
- .map { |x| yard_to_sorbet(x, item, indent_level, replace_errors_with_untyped) }
172
- "T::Hash<#{parameters.join(', ')}>"
198
+ .map { |x| yard_to_parlour(x, item, replace_errors_with_untyped, replace_unresolved_with_untyped) }
199
+ # Return a warning about an invalid hash when it has more or less than two elements.
200
+ if parameters.length == 2
201
+ Parlour::Types::Hash.new(*parameters)
202
+ else
203
+ handle_sord_error(parameters.map(&:describe).join, "Invalid hash, must have exactly two types: #{yard.inspect}.", item, replace_errors_with_untyped)
204
+ end
173
205
  when SHORTHAND_ARRAY_SYNTAX
174
206
  type_parameters = $1
175
207
  parameters = split_type_parameters(type_parameters)
176
- .map { |x| yard_to_sorbet(x, item, indent_level, replace_errors_with_untyped) }
208
+ .map { |x| yard_to_parlour(x, item, replace_errors_with_untyped, replace_unresolved_with_untyped) }
177
209
  parameters.one? \
178
- ? "T::Array<#{parameters.first}>"
179
- : "T::Array<T.any(#{parameters.join(', ')})>"
210
+ ? Parlour::Types::Array.new(parameters.first)
211
+ : Parlour::Types::Array.new(Parlour::Types::Union.new(parameters))
180
212
  else
181
213
  # Check for literals
182
214
  from_yaml = YAML.load(yard) rescue nil
183
- return from_yaml.class.to_s \
215
+ return Parlour::Types::Raw.new(from_yaml.class.to_s) \
184
216
  if [Symbol, Float, Integer].include?(from_yaml.class)
185
217
 
186
- Logging.warn("#{yard.inspect} does not appear to be a type", item, indent_level)
187
- replace_errors_with_untyped ? "T.untyped" : "SORD_ERROR_#{yard.gsub(/[^0-9A-Za-z_]/i, '')}"
218
+ return handle_sord_error(yard.to_s, "#{yard.inspect} does not appear to be a type", item, replace_errors_with_untyped)
188
219
  end
189
220
  end
221
+
222
+ # Handles SORD_ERRORs.
223
+ #
224
+ # @param [String, Parlour::Types::Type] name
225
+ # @param [String] log_warning
226
+ # @param [YARD::CodeObjects::Base] item
227
+ # @param [Boolean] replace_errors_with_untyped
228
+ # @return [Parlour::Types::Type]
229
+ def self.handle_sord_error(name, log_warning, item, replace_errors_with_untyped)
230
+ Logging.warn(log_warning, item)
231
+ str = name.is_a?(Parlour::Types::Type) ? name.describe : name
232
+ return replace_errors_with_untyped \
233
+ ? Parlour::Types::Untyped.new
234
+ : Parlour::Types::Raw.new("SORD_ERROR_#{name.gsub(/[^0-9A-Za-z_]/i, '')}")
235
+ end
190
236
  end
191
237
  end