sord 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,82 @@
1
+ require 'stringio'
2
+
3
+ module Sord
4
+ module Resolver
5
+ # @return [void]
6
+ def self.prepare
7
+ # Construct a hash of class names to full paths
8
+ @@names_to_paths ||= YARD::Registry.all(:class)
9
+ .group_by(&:name)
10
+ .map { |k, v| [k.to_s, v.map(&:path)] }
11
+ .to_h
12
+ .merge(builtin_classes.map { |x| [x, [x]] }.to_h) do |k, a, b|
13
+ a | b
14
+ end
15
+ end
16
+
17
+ # @return [void]
18
+ def self.clear
19
+ @@names_to_paths = nil
20
+ end
21
+
22
+ # @param [String] name
23
+ # @return [Array<String>]
24
+ def self.paths_for(name)
25
+ prepare
26
+ (@@names_to_paths[name.split('::').last] || [])
27
+ .select { |x| x.end_with?(name) }
28
+ end
29
+
30
+ # @param [String] name
31
+ # @return [String, nil]
32
+ def self.path_for(name)
33
+ paths_for(name).one? ? paths_for(name).first : nil
34
+ end
35
+
36
+ # @return [Array<String>]
37
+ def self.builtin_classes
38
+ # This prints some deprecation warnings, so suppress them
39
+ prev_stderr = $stderr
40
+ $stderr = StringIO.new
41
+
42
+ Object.constants
43
+ .select { |x| Object.const_get(x).is_a?(Class) }
44
+ .map(&:to_s)
45
+ ensure
46
+ $stderr = prev_stderr
47
+ end
48
+
49
+ # @param [String] name
50
+ # @param [Object] item
51
+ # @return [Boolean]
52
+ def self.resolvable?(name, item)
53
+ name_parts = name.split('::')
54
+
55
+ current_context = item
56
+ current_context = current_context.parent \
57
+ until current_context.is_a?(YARD::CodeObjects::NamespaceObject)
58
+
59
+ matching_paths = []
60
+
61
+ loop do
62
+ # Try to find that class in this context
63
+ path_followed_context = current_context
64
+ name_parts.each do |name_part|
65
+ path_followed_context = path_followed_context&.child(
66
+ name: name_part, type: [:class, :method, :module]
67
+ )
68
+ end
69
+
70
+ # Return true if we found the constant we're looking for here
71
+ matching_paths |= [path_followed_context.path] if path_followed_context
72
+
73
+ # Move up one context
74
+ break if current_context.root?
75
+ current_context = current_context.parent
76
+ end
77
+
78
+ return (builtin_classes.include?(name) && matching_paths.empty?) ||
79
+ (matching_paths.one? && !builtin_classes.include?(name))
80
+ end
81
+ end
82
+ end
@@ -1,5 +1,6 @@
1
1
  require 'yaml'
2
2
  require 'sord/logging'
3
+ require 'sord/resolver'
3
4
 
4
5
  module Sord
5
6
  # Contains methods to convert YARD types to Sorbet types.
@@ -21,14 +22,22 @@ module Sord
21
22
  # Match duck types which require the object implement one or more methods,
22
23
  # like '#foo', '#foo & #bar', '#foo&#bar&#baz', and '#foo&#bar&#baz&#foo_bar'.
23
24
  DUCK_TYPE_REGEX =
24
- /^\##{SIMPLE_TYPE_REGEX}(?:( ?\& ?\#)*[a-zA-Z_][a-zA-Z_0-9]*)*$/
25
+ /^\#[a-zA-Z_][\w]*(?:[a-zA-Z_][\w=]*)*(?:( ?\& ?\#)*[a-zA-Z_][\w=]*)*$/
25
26
 
26
27
  # A regular expression which matches ordered lists in the format of
27
28
  # either "Array(String, Symbol)" or "(String, Symbol)".
28
29
  ORDERED_LIST_REGEX = /^(?:Array|)\((.*)\s*\)$/
29
30
 
31
+ # A regular expression which matches the shorthand Hash syntax,
32
+ # "{String => Symbol}".
33
+ SHORTHAND_HASH_SYNTAX = /^{\s*(.*)\s*}$/
34
+
35
+ # A regular expression which matches the shorthand Array syntax,
36
+ # "<String>".
37
+ SHORTHAND_ARRAY_SYNTAX = /^<\s*(.*)\s*>$/
38
+
30
39
  # An array of built-in generic types supported by Sorbet.
31
- SORBET_SUPPORTED_GENERIC_TYPES = %w{Array Set Enumerable Enumerator Range Hash}
40
+ SORBET_SUPPORTED_GENERIC_TYPES = %w{Array Set Enumerable Enumerator Range Hash Class}
32
41
  SORBET_SINGLE_ARG_GENERIC_TYPES = %w{Array Set Enumerable Enumerator Range}
33
42
 
34
43
  # Given a string of YARD type parameters (without angle brackets), splits
@@ -85,7 +94,11 @@ module Sord
85
94
  # @param [YARD::CodeObjects::Base] item The CodeObject which the YARD type
86
95
  # is associated with. This is used for logging and can be nil, but this
87
96
  # will lead to less informative log messages.
88
- def self.yard_to_sorbet(yard, item=nil)
97
+ # @param [Integer] indent_level
98
+ # @param [Boolean] replace_errors_with_untyped If true, T.untyped is used
99
+ # 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)
89
102
  case yard
90
103
  when nil # Type not specified
91
104
  "T.untyped"
@@ -98,7 +111,7 @@ module Sord
98
111
  # selection of any of the types
99
112
  types = yard
100
113
  .reject { |x| x == 'nil' }
101
- .map { |x| yard_to_sorbet(x, item) }
114
+ .map { |x| yard_to_sorbet(x, item, indent_level, replace_errors_with_untyped) }
102
115
  .uniq
103
116
  result = types.length == 1 ? types.first : "T.any(#{types.join(', ')})"
104
117
  result = "T.nilable(#{result})" if yard.include?('nil')
@@ -106,11 +119,26 @@ module Sord
106
119
  when /^#{SIMPLE_TYPE_REGEX}$/
107
120
  # If this doesn't begin with an uppercase letter, warn
108
121
  if /^[_a-z]/ === yard
109
- Logging.warn("#{yard} is probably not a type, but using anyway", item)
122
+ Logging.warn("#{yard} is probably not a type, but using anyway", item, indent_level)
123
+ end
124
+
125
+ # Check if whatever has been specified is actually resolvable; if not,
126
+ # do some inference to replace it
127
+ if item && !Resolver.resolvable?(yard, item)
128
+ if Resolver.path_for(yard)
129
+ new_path = Resolver.path_for(yard)
130
+ Logging.infer("#{yard} was resolved to #{new_path}", item, indent_level) \
131
+ unless yard == new_path
132
+ new_path
133
+ else
134
+ Logging.warn("#{yard} wasn't able to be resolved to a constant in this project", item, indent_level)
135
+ yard
136
+ end
137
+ else
138
+ yard
110
139
  end
111
- yard
112
140
  when DUCK_TYPE_REGEX
113
- Logging.duck("#{yard} looks like a duck type, replacing with T.untyped", item)
141
+ Logging.duck("#{yard} looks like a duck type, replacing with T.untyped", item, indent_level)
114
142
  'T.untyped'
115
143
  when /^#{GENERIC_TYPE_REGEX}$/
116
144
  generic_type = $1
@@ -118,31 +146,45 @@ module Sord
118
146
 
119
147
  if SORBET_SUPPORTED_GENERIC_TYPES.include?(generic_type)
120
148
  parameters = split_type_parameters(type_parameters)
121
- .map { |x| yard_to_sorbet(x, item) }
149
+ .map { |x| yard_to_sorbet(x, item, indent_level, replace_errors_with_untyped) }
122
150
  if SORBET_SINGLE_ARG_GENERIC_TYPES.include?(generic_type) && parameters.length > 1
123
151
  "T::#{generic_type}[T.any(#{parameters.join(', ')})]"
152
+ elsif generic_type == 'Class' && parameters.length == 1
153
+ "T.class_of(#{parameters.first})"
124
154
  else
125
155
  "T::#{generic_type}[#{parameters.join(', ')}]"
126
156
  end
127
157
  else
128
- Logging.warn("unsupported generic type #{generic_type.inspect} in #{yard.inspect}", item)
129
- "SORD_ERROR_#{generic_type.gsub(/[^0-9A-Za-z_]/i, '')}"
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, '')}"
130
160
  end
131
161
  # Converts ordered lists like Array(Symbol, String) or (Symbol, String)
132
162
  # into Sorbet Tuples like [Symbol, String].
133
163
  when ORDERED_LIST_REGEX
134
164
  type_parameters = $1
135
165
  parameters = split_type_parameters(type_parameters)
136
- .map { |x| yard_to_sorbet(x, item) }
166
+ .map { |x| yard_to_sorbet(x, item, indent_level, replace_errors_with_untyped) }
137
167
  "[#{parameters.join(', ')}]"
168
+ when SHORTHAND_HASH_SYNTAX
169
+ type_parameters = $1
170
+ 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(', ')}>"
173
+ when SHORTHAND_ARRAY_SYNTAX
174
+ type_parameters = $1
175
+ parameters = split_type_parameters(type_parameters)
176
+ .map { |x| yard_to_sorbet(x, item, indent_level, replace_errors_with_untyped) }
177
+ parameters.one? \
178
+ ? "T::Array<#{parameters.first}>"
179
+ : "T::Array<T.any(#{parameters.join(', ')})>"
138
180
  else
139
181
  # Check for literals
140
182
  from_yaml = YAML.load(yard) rescue nil
141
183
  return from_yaml.class.to_s \
142
184
  if [Symbol, Float, Integer].include?(from_yaml.class)
143
185
 
144
- Logging.warn("#{yard.inspect} does not appear to be a type", item)
145
- "SORD_ERROR_#{yard.gsub(/[^0-9A-Za-z_]/i, '')}"
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, '')}"
146
188
  end
147
189
  end
148
190
  end
@@ -1,4 +1,4 @@
1
1
  # typed: strong
2
2
  module Sord
3
- VERSION = '0.7.1'
3
+ VERSION = '0.8.0'
4
4
  end
@@ -0,0 +1,165 @@
1
+ # typed: strong
2
+ module Sord
3
+ module Logging
4
+ sig { returns(T::Array[Proc]) }
5
+ def self.hooks(); end
6
+
7
+ sig { returns(T::Boolean) }
8
+ def self.silent?(); end
9
+
10
+ sig { params(value: T::Boolean).void }
11
+ def self.silent=(value); end
12
+
13
+ sig { params(value: T::Array[Symbol]).void }
14
+ def self.enabled_types=(value); end
15
+
16
+ sig { returns(T::Array[Symbol]) }
17
+ def self.enabled_types(); end
18
+
19
+ sig { params(value: T::Array[Symbol]).void }
20
+ def self.valid_types?(value); end
21
+
22
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
23
+ sig do
24
+ params(
25
+ kind: Symbol,
26
+ header: String,
27
+ msg: String,
28
+ item: YARD::CodeObjects::Base,
29
+ indent_level: Integer
30
+ ).void
31
+ end
32
+ def self.generic(kind, header, msg, item, indent_level = 0); end
33
+
34
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
35
+ sig { params(msg: String, item: YARD::CodeObjects::Base, indent_level: Integer).void }
36
+ def self.warn(msg, item = nil, indent_level = 0); end
37
+
38
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
39
+ sig { params(msg: String, item: YARD::CodeObjects::Base, indent_level: Integer).void }
40
+ def self.info(msg, item = nil, indent_level = 0); end
41
+
42
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
43
+ sig { params(msg: String, item: YARD::CodeObjects::Base, indent_level: Integer).void }
44
+ def self.duck(msg, item = nil, indent_level = 0); end
45
+
46
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
47
+ sig { params(msg: String, item: YARD::CodeObjects::Base, indent_level: Integer).void }
48
+ def self.error(msg, item = nil, indent_level = 0); end
49
+
50
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
51
+ sig { params(msg: String, item: YARD::CodeObjects::Base, indent_level: Integer).void }
52
+ def self.infer(msg, item = nil, indent_level = 0); end
53
+
54
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
55
+ sig { params(msg: String, item: YARD::CodeObjects::Base, indent_level: Integer).void }
56
+ def self.omit(msg, item = nil, indent_level = 0); end
57
+
58
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
59
+ sig { params(msg: String, item: YARD::CodeObjects::Base, indent_level: Integer).void }
60
+ def self.done(msg, item = nil, indent_level = 0); end
61
+
62
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
63
+ sig do
64
+ params(
65
+ kind: Symbol,
66
+ msg: String,
67
+ item: YARD::CodeObjects::Base,
68
+ indent_level: Integer
69
+ ).void
70
+ end
71
+ def self.invoke_hooks(kind, msg, item, indent_level = 0); end
72
+
73
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
74
+ sig { params(blk: T.proc.params(kind: Symbol, msg: String, item: YARD::CodeObjects::Base, indent_level: Integer).void).void }
75
+ def self.add_hook(&blk); end
76
+ end
77
+
78
+ module Resolver
79
+ sig { void }
80
+ def self.prepare(); end
81
+
82
+ sig { void }
83
+ def self.clear(); end
84
+
85
+ sig { params(name: String).returns(T::Array[String]) }
86
+ def self.paths_for(name); end
87
+
88
+ sig { params(name: String).returns(T.nilable(String)) }
89
+ def self.path_for(name); end
90
+
91
+ sig { returns(T::Array[String]) }
92
+ def self.builtin_classes(); end
93
+
94
+ sig { params(name: String, item: Object).returns(T::Boolean) }
95
+ def self.resolvable?(name, item); end
96
+ end
97
+
98
+ class RbiGenerator
99
+ sig { returns(T::Array[String]) }
100
+ def rbi_contents(); end
101
+
102
+ sig { returns(Integer) }
103
+ def object_count(); end
104
+
105
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
106
+ sig { returns(T::Array[[String, YARD::CodeObjects::Base, Integer]]) }
107
+ def warnings(); end
108
+
109
+ sig { returns(T::Boolean) }
110
+ def next_item_is_first_in_namespace(); end
111
+
112
+ # sord infer - inferred type of parameter "value" as T::Boolean using getter's return type
113
+ sig { params(value: T::Boolean).returns(T::Boolean) }
114
+ def next_item_is_first_in_namespace=(value); end
115
+
116
+ sig { params(options: Hash).void }
117
+ def initialize(options); end
118
+
119
+ sig { void }
120
+ def count_namespace(); end
121
+
122
+ sig { void }
123
+ def count_method(); end
124
+
125
+ sig { void }
126
+ def add_blank(); end
127
+
128
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
129
+ sig { params(item: YARD::CodeObjects::Base, indent_level: Integer).returns(Integer) }
130
+ def add_mixins(item, indent_level); end
131
+
132
+ sig { params(params: T::Array[String], returns: String, indent_level: Integer).void }
133
+ def add_signature(params, returns, indent_level); end
134
+
135
+ # sord warn - YARD::CodeObjects::NamespaceObject wasn't able to be resolved to a constant in this project
136
+ sig { params(item: YARD::CodeObjects::NamespaceObject, indent_level: Integer).void }
137
+ def add_methods(item, indent_level); end
138
+
139
+ # sord warn - YARD::CodeObjects::NamespaceObject wasn't able to be resolved to a constant in this project
140
+ sig { params(item: YARD::CodeObjects::NamespaceObject, indent_level: Integer).void }
141
+ def add_namespace(item, indent_level = 0); end
142
+
143
+ sig { returns(String) }
144
+ def generate(); end
145
+
146
+ sig { params(filename: T.nilable(String)).void }
147
+ def run(filename); end
148
+ end
149
+
150
+ module TypeConverter
151
+ sig { params(params: String).returns(T::Array[String]) }
152
+ def self.split_type_parameters(params); end
153
+
154
+ # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
155
+ sig do
156
+ params(
157
+ yard: T.any(T::Boolean, Array, String),
158
+ item: YARD::CodeObjects::Base,
159
+ indent_level: Integer,
160
+ replace_errors_with_untyped: T::Boolean
161
+ ).returns(String)
162
+ end
163
+ def self.yard_to_sorbet(yard, item = nil, indent_level = 0, replace_errors_with_untyped = false); end
164
+ end
165
+ end
@@ -1,2 +0,0 @@
1
- --dir
2
- .
@@ -0,0 +1,81 @@
1
+ # This file is autogenerated. Do not edit it by hand. Regenerate it with:
2
+ # srb rbi gems
3
+
4
+ # typed: true
5
+ #
6
+ # If you would like to make changes to this file, great! Please create the gem's shim here:
7
+ #
8
+ # https://github.com/sorbet/sorbet-typed/new/master?filename=lib/colorize/all/colorize.rbi
9
+ #
10
+ # colorize-0.8.1
11
+ module Colorize
12
+ end
13
+ module Colorize::ClassMethods
14
+ def color_codes; end
15
+ def color_matrix(_ = nil); end
16
+ def color_methods; end
17
+ def color_samples; end
18
+ def colors; end
19
+ def disable_colorization(value = nil); end
20
+ def disable_colorization=(value); end
21
+ def mode_codes; end
22
+ def modes; end
23
+ def modes_methods; end
24
+ end
25
+ module Colorize::InstanceMethods
26
+ def background_color(color); end
27
+ def color(color); end
28
+ def color_from_symbol(match, symbol); end
29
+ def colorize(params); end
30
+ def colorized?; end
31
+ def colors_from_hash(match, hash); end
32
+ def colors_from_params(match, params); end
33
+ def defaults_colors(match); end
34
+ def mode(mode); end
35
+ def require_windows_libs; end
36
+ def scan_for_colors; end
37
+ def split_colors(match); end
38
+ def uncolorize; end
39
+ end
40
+ class String
41
+ def black; end
42
+ def blink; end
43
+ def blue; end
44
+ def bold; end
45
+ def cyan; end
46
+ def green; end
47
+ def hide; end
48
+ def italic; end
49
+ def light_black; end
50
+ def light_blue; end
51
+ def light_cyan; end
52
+ def light_green; end
53
+ def light_magenta; end
54
+ def light_red; end
55
+ def light_white; end
56
+ def light_yellow; end
57
+ def magenta; end
58
+ def on_black; end
59
+ def on_blue; end
60
+ def on_cyan; end
61
+ def on_green; end
62
+ def on_light_black; end
63
+ def on_light_blue; end
64
+ def on_light_cyan; end
65
+ def on_light_green; end
66
+ def on_light_magenta; end
67
+ def on_light_red; end
68
+ def on_light_white; end
69
+ def on_light_yellow; end
70
+ def on_magenta; end
71
+ def on_red; end
72
+ def on_white; end
73
+ def on_yellow; end
74
+ def red; end
75
+ def swap; end
76
+ def underline; end
77
+ def white; end
78
+ def yellow; end
79
+ extend Colorize::ClassMethods
80
+ include Colorize::InstanceMethods
81
+ end