Module: Sord::TypeConverter
- Defined in:
- lib/sord/type_converter.rb
Overview
Contains methods to convert YARD types to Sorbet types.
Constant Summary collapse
- SIMPLE_TYPE_REGEX =
A regular expression which matches Ruby namespaces and identifiers. “Foo”, “Foo::Bar”, and “::Foo::Bar” are all matches, whereas “Foo.Bar” or “Foo#bar” are not.
/(?:\:\:)?[a-zA-Z_][a-zA-Z_0-9]*(?:\:\:[a-zA-Z_][a-zA-Z_0-9]*)*/
- GENERIC_TYPE_REGEX =
A regular expression which matches a Ruby namespace immediately followed by another Ruby namespace in angle brackets. This is the format usually used in YARD to model generic types, such as “Array<String>”.
/(#{SIMPLE_TYPE_REGEX})\s*<\s*(.*)\s*>/
- SORBET_SUPPORTED_GENERIC_TYPES =
An array of built-in generic types supported by Sorbet.
%w{Array Set Enumerable Enumerator Range Hash}
Class Method Summary collapse
-
.split_type_parameters(params) ⇒ Array<String>
Given a string of YARD type parameters (without angle brackets), splits the string into an array of each type parameter.
-
.yard_to_sorbet(yard, item = nil) ⇒ Object
Converts a YARD type into a Sorbet type.
Class Method Details
.split_type_parameters(params) ⇒ Array<String>
Given a string of YARD type parameters (without angle brackets), splits the string into an array of each type parameter.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/sord/type_converter.rb', line 25 def self.split_type_parameters(params) result = [] buffer = "" current_bracketing_level = 0 character_pointer = 0 while character_pointer < params.length should_buffer = true current_bracketing_level += 1 if params[character_pointer] == ?< current_bracketing_level -= 1 if params[character_pointer] == ?> if params[character_pointer] == ?, if current_bracketing_level == 0 result << buffer.strip buffer = "" should_buffer = false end end buffer += params[character_pointer] if should_buffer character_pointer += 1 end result << buffer.strip result end |
.yard_to_sorbet(yard, item = nil) ⇒ Object
Converts a YARD type into a Sorbet type.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/sord/type_converter.rb', line 59 def self.yard_to_sorbet(yard, item=nil) case yard when nil # Type not specified "T.untyped" when "bool", "Bool", "boolean", "Boolean", "true", "false" "T::Boolean" when 'self' item.parent.path when Array # If there's only one element, unwrap it, otherwise allow for a # selection of any of the types types = yard .reject { |x| x == 'nil' } .map { |x| yard_to_sorbet(x, item) } .uniq result = types.length == 1 ? types.first : "T.any(#{types.join(', ')})" result = "T.nilable(#{result})" if yard.include?('nil') result when /^#{SIMPLE_TYPE_REGEX}$/ # If this doesn't begin with an uppercase letter, warn if /^[_a-z]/ === yard Logging.warn("#{yard} is probably not a type, but using anyway", item) end yard when /^#{GENERIC_TYPE_REGEX}$/ generic_type = $1 type_parameters = $2 if SORBET_SUPPORTED_GENERIC_TYPES.include?(generic_type) "T::#{generic_type}[#{ split_type_parameters(type_parameters).map { |x| yard_to_sorbet(x, item) }.join(', ')}]" else Logging.warn("unsupported generic type #{generic_type.inspect} in #{yard.inspect}", item) "SORD_ERROR_#{generic_type.gsub(/[^0-9A-Za-z_]/i, '')}" end else Logging.warn("#{yard.inspect} does not appear to be a type", item) "SORD_ERROR_#{yard.gsub(/[^0-9A-Za-z_]/i, '')}" end end |