tapioca 0.8.3 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -2
  3. data/README.md +188 -36
  4. data/lib/tapioca/cli.rb +130 -66
  5. data/lib/tapioca/commands/annotations.rb +167 -34
  6. data/lib/tapioca/commands/check_shims.rb +101 -0
  7. data/lib/tapioca/commands/{init.rb → configure.rb} +1 -1
  8. data/lib/tapioca/commands/dsl.rb +1 -1
  9. data/lib/tapioca/commands/gem.rb +15 -10
  10. data/lib/tapioca/commands.rb +2 -1
  11. data/lib/tapioca/dsl/compiler.rb +1 -13
  12. data/lib/tapioca/dsl/compilers/active_model_attributes.rb +1 -1
  13. data/lib/tapioca/dsl/compilers/active_record_relations.rb +17 -0
  14. data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +5 -4
  15. data/lib/tapioca/dsl/compilers/frozen_record.rb +2 -2
  16. data/lib/tapioca/dsl/compilers/protobuf.rb +6 -0
  17. data/lib/tapioca/dsl/compilers.rb +0 -4
  18. data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +21 -3
  19. data/lib/tapioca/dsl/pipeline.rb +0 -2
  20. data/lib/tapioca/dsl.rb +8 -0
  21. data/lib/tapioca/executor.rb +0 -3
  22. data/lib/tapioca/gem/events.rb +22 -3
  23. data/lib/tapioca/gem/listeners/base.rb +11 -0
  24. data/lib/tapioca/gem/listeners/dynamic_mixins.rb +5 -0
  25. data/lib/tapioca/gem/listeners/foreign_constants.rb +65 -0
  26. data/lib/tapioca/gem/listeners/methods.rb +7 -18
  27. data/lib/tapioca/gem/listeners/mixins.rb +31 -10
  28. data/lib/tapioca/gem/listeners/remove_empty_payload_scopes.rb +5 -0
  29. data/lib/tapioca/gem/listeners/sorbet_enums.rb +5 -0
  30. data/lib/tapioca/gem/listeners/sorbet_helpers.rb +5 -0
  31. data/lib/tapioca/gem/listeners/sorbet_props.rb +5 -0
  32. data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +5 -0
  33. data/lib/tapioca/gem/listeners/sorbet_signatures.rb +6 -1
  34. data/lib/tapioca/gem/listeners/sorbet_type_variables.rb +5 -0
  35. data/lib/tapioca/gem/listeners/source_location.rb +67 -0
  36. data/lib/tapioca/gem/listeners/subconstants.rb +5 -0
  37. data/lib/tapioca/gem/listeners/yard_doc.rb +5 -0
  38. data/lib/tapioca/gem/listeners.rb +2 -0
  39. data/lib/tapioca/gem/pipeline.rb +64 -19
  40. data/lib/tapioca/gem.rb +6 -0
  41. data/lib/tapioca/gemfile.rb +7 -6
  42. data/lib/tapioca/helpers/cli_helper.rb +8 -2
  43. data/lib/tapioca/helpers/config_helper.rb +0 -2
  44. data/lib/tapioca/helpers/env_helper.rb +16 -0
  45. data/lib/tapioca/helpers/rbi_files_helper.rb +255 -0
  46. data/lib/tapioca/helpers/rbi_helper.rb +98 -94
  47. data/lib/tapioca/helpers/sorbet_helper.rb +2 -3
  48. data/lib/tapioca/helpers/test/content.rb +0 -2
  49. data/lib/tapioca/helpers/test/template.rb +0 -2
  50. data/lib/tapioca/internal.rb +36 -12
  51. data/lib/tapioca/rbi_ext/model.rb +2 -15
  52. data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +18 -16
  53. data/lib/tapioca/runtime/reflection.rb +26 -0
  54. data/lib/tapioca/runtime/trackers/constant_definition.rb +44 -16
  55. data/lib/tapioca/runtime/trackers/mixin.rb +49 -14
  56. data/lib/tapioca/sorbet_ext/generic_name_patch.rb +1 -4
  57. data/lib/tapioca/sorbet_ext/name_patch.rb +15 -5
  58. data/lib/tapioca/sorbet_ext/proc_bind_patch.rb +40 -0
  59. data/lib/tapioca/static/requires_compiler.rb +0 -2
  60. data/lib/tapioca/static/symbol_loader.rb +26 -30
  61. data/lib/tapioca/static/symbol_table_parser.rb +0 -3
  62. data/lib/tapioca/version.rb +1 -1
  63. data/lib/tapioca.rb +3 -0
  64. metadata +24 -7
  65. data/lib/tapioca/dsl/helpers/param_helper.rb +0 -55
  66. data/lib/tapioca/helpers/shims_helper.rb +0 -115
  67. data/lib/tapioca/helpers/signatures_helper.rb +0 -17
  68. data/lib/tapioca/helpers/type_variable_helper.rb +0 -43
@@ -1,18 +1,28 @@
1
1
  # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
- # We need sorbet to compile the signature for `qualified_name_of` before applying
5
- # the patch to avoid an infinite loop.
6
- T::Utils.signature_for_method(::Tapioca::Runtime::Reflection.method(:qualified_name_of))
7
-
8
4
  module T
9
5
  module Types
10
6
  class Simple
11
7
  module NamePatch
8
+ NAME_METHOD = T.let(Module.instance_method(:name), UnboundMethod)
9
+
12
10
  def name
13
11
  # Sorbet memoizes this method into the `@name` instance variable but
14
12
  # doing so means that types get memoized before this patch is applied
15
- ::Tapioca::Runtime::Reflection.qualified_name_of(@raw_type)
13
+ qualified_name_of(@raw_type)
14
+ end
15
+
16
+ def qualified_name_of(constant)
17
+ name = NAME_METHOD.bind_call(constant)
18
+ name = nil if name&.start_with?("#<")
19
+ return if name.nil?
20
+
21
+ if name.start_with?("::")
22
+ name
23
+ else
24
+ "::#{name}"
25
+ end
16
26
  end
17
27
  end
18
28
 
@@ -0,0 +1,40 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module T
5
+ module Types
6
+ module ProcBindPatch
7
+ def initialize(arg_types, returns, bind = T::Private::Methods::ARG_NOT_PROVIDED)
8
+ super(arg_types, returns)
9
+
10
+ unless bind == T::Private::Methods::ARG_NOT_PROVIDED
11
+ @bind = T.let(T::Utils.coerce(bind), T::Types::Base)
12
+ end
13
+ end
14
+
15
+ def name
16
+ name = super
17
+ name = name.sub("T.proc", "T.proc.bind(#{@bind})") unless @bind.nil?
18
+ name
19
+ end
20
+ end
21
+
22
+ Proc.prepend(ProcBindPatch)
23
+ end
24
+ end
25
+
26
+ module T
27
+ module Private
28
+ module Methods
29
+ module ProcBindPatch
30
+ def finalize_proc(decl)
31
+ super
32
+
33
+ T.unsafe(T::Types::Proc).new(decl.params, decl.returns, decl.bind)
34
+ end
35
+ end
36
+
37
+ singleton_class.prepend(ProcBindPatch)
38
+ end
39
+ end
40
+ end
@@ -1,8 +1,6 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "spoom"
5
-
6
4
  module Tapioca
7
5
  module Static
8
6
  class RequiresCompiler
@@ -1,9 +1,6 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "json"
5
- require "tempfile"
6
-
7
4
  module Tapioca
8
5
  module Static
9
6
  module SymbolLoader
@@ -22,12 +19,21 @@ module Tapioca
22
19
  T.must(@payload_symbols)
23
20
  end
24
21
 
25
- sig { returns(T::Set[String]) }
26
- def engine_symbols
27
- unless @engine_symbols
28
- @engine_symbols = T.let(load_engine_symbols, T.nilable(T::Set[String]))
22
+ sig { params(gem: Gemfile::GemSpec).returns(T::Set[String]) }
23
+ def engine_symbols(gem)
24
+ gem_engine = engines.find do |engine|
25
+ gem.contains_path?(engine.config.root.to_s)
26
+ end
27
+
28
+ return Set.new unless gem_engine
29
+
30
+ paths = gem_engine.config.eager_load_paths.flat_map do |load_path|
31
+ Pathname.glob("#{load_path}/**/*.rb")
29
32
  end
30
- T.must(@engine_symbols)
33
+
34
+ symbols_from_paths(paths)
35
+ rescue
36
+ Set.new
31
37
  end
32
38
 
33
39
  sig { params(gem: Gemfile::GemSpec).returns(T::Set[String]) }
@@ -37,31 +43,21 @@ module Tapioca
37
43
 
38
44
  private
39
45
 
40
- sig { params(input: String, table_type: String).returns(String) }
41
- def symbol_table_json_from(input, table_type: "symbol-table-json")
42
- sorbet("--no-config", "--quiet", "--print=#{table_type}", input).out
43
- end
44
-
45
- sig { returns(T::Set[String]) }
46
- def load_engine_symbols
47
- return Set.new unless Object.const_defined?("Rails::Engine")
48
-
49
- engine = descendants_of(Object.const_get("Rails::Engine"))
50
- .reject(&:abstract_railtie?)
51
- .find do |klass|
52
- name = name_of(klass)
53
- !name.nil? && payload_symbols.include?(name)
54
- end
46
+ sig { returns(T::Array[T.class_of(Rails::Engine)]) }
47
+ def engines
48
+ @engines = T.let(@engines, T.nilable(T::Array[T.class_of(Rails::Engine)]))
55
49
 
56
- return Set.new unless engine
57
-
58
- paths = engine.config.eager_load_paths.flat_map do |load_path|
59
- Pathname.glob("#{load_path}/**/*.rb")
50
+ @engines ||= if Object.const_defined?("Rails::Engine")
51
+ descendants_of(Object.const_get("Rails::Engine"))
52
+ .reject(&:abstract_railtie?)
53
+ else
54
+ []
60
55
  end
56
+ end
61
57
 
62
- symbols_from_paths(paths)
63
- rescue
64
- Set.new
58
+ sig { params(input: String, table_type: String).returns(String) }
59
+ def symbol_table_json_from(input, table_type: "symbol-table-json")
60
+ sorbet("--no-config", "--quiet", "--print=#{table_type}", input).out
65
61
  end
66
62
 
67
63
  sig { params(paths: T::Array[Pathname]).returns(T::Set[String]) }
@@ -1,9 +1,6 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "json"
5
- require "tempfile"
6
-
7
4
  module Tapioca
8
5
  module Static
9
6
  class SymbolTableParser
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Tapioca
5
- VERSION = "0.8.3"
5
+ VERSION = "0.9.2"
6
6
  end
data/lib/tapioca.rb CHANGED
@@ -43,6 +43,9 @@ module Tapioca
43
43
  "activesupport" => "false",
44
44
  }.freeze, T::Hash[String, String])
45
45
 
46
+ DEFAULT_RBI_MAX_LINE_LENGTH = 120
47
+ DEFAULT_ENVIRONMENT = "development"
48
+
46
49
  CENTRAL_REPO_ROOT_URI = "https://raw.githubusercontent.com/Shopify/rbi-central/main"
47
50
  CENTRAL_REPO_INDEX_PATH = "index.json"
48
51
  CENTRAL_REPO_ANNOTATIONS_DIR = "rbi/annotations"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tapioca
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.3
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ufuk Kayserilioglu
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2022-06-28 00:00:00.000000000 Z
14
+ date: 2022-07-19 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -27,6 +27,20 @@ dependencies:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
29
  version: 1.17.3
30
+ - !ruby/object:Gem::Dependency
31
+ name: netrc
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 0.11.0
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 0.11.0
30
44
  - !ruby/object:Gem::Dependency
31
45
  name: parallel
32
46
  requirement: !ruby/object:Gem::Requirement
@@ -153,10 +167,11 @@ files:
153
167
  - lib/tapioca/cli.rb
154
168
  - lib/tapioca/commands.rb
155
169
  - lib/tapioca/commands/annotations.rb
170
+ - lib/tapioca/commands/check_shims.rb
156
171
  - lib/tapioca/commands/command.rb
172
+ - lib/tapioca/commands/configure.rb
157
173
  - lib/tapioca/commands/dsl.rb
158
174
  - lib/tapioca/commands/gem.rb
159
- - lib/tapioca/commands/init.rb
160
175
  - lib/tapioca/commands/require.rb
161
176
  - lib/tapioca/commands/todo.rb
162
177
  - lib/tapioca/dsl.rb
@@ -192,13 +207,14 @@ files:
192
207
  - lib/tapioca/dsl/extensions/frozen_record.rb
193
208
  - lib/tapioca/dsl/helpers/active_record_column_type_helper.rb
194
209
  - lib/tapioca/dsl/helpers/active_record_constants_helper.rb
195
- - lib/tapioca/dsl/helpers/param_helper.rb
196
210
  - lib/tapioca/dsl/pipeline.rb
197
211
  - lib/tapioca/executor.rb
212
+ - lib/tapioca/gem.rb
198
213
  - lib/tapioca/gem/events.rb
199
214
  - lib/tapioca/gem/listeners.rb
200
215
  - lib/tapioca/gem/listeners/base.rb
201
216
  - lib/tapioca/gem/listeners/dynamic_mixins.rb
217
+ - lib/tapioca/gem/listeners/foreign_constants.rb
202
218
  - lib/tapioca/gem/listeners/methods.rb
203
219
  - lib/tapioca/gem/listeners/mixins.rb
204
220
  - lib/tapioca/gem/listeners/remove_empty_payload_scopes.rb
@@ -208,22 +224,22 @@ files:
208
224
  - lib/tapioca/gem/listeners/sorbet_required_ancestors.rb
209
225
  - lib/tapioca/gem/listeners/sorbet_signatures.rb
210
226
  - lib/tapioca/gem/listeners/sorbet_type_variables.rb
227
+ - lib/tapioca/gem/listeners/source_location.rb
211
228
  - lib/tapioca/gem/listeners/subconstants.rb
212
229
  - lib/tapioca/gem/listeners/yard_doc.rb
213
230
  - lib/tapioca/gem/pipeline.rb
214
231
  - lib/tapioca/gemfile.rb
215
232
  - lib/tapioca/helpers/cli_helper.rb
216
233
  - lib/tapioca/helpers/config_helper.rb
234
+ - lib/tapioca/helpers/env_helper.rb
217
235
  - lib/tapioca/helpers/gem_helper.rb
236
+ - lib/tapioca/helpers/rbi_files_helper.rb
218
237
  - lib/tapioca/helpers/rbi_helper.rb
219
- - lib/tapioca/helpers/shims_helper.rb
220
- - lib/tapioca/helpers/signatures_helper.rb
221
238
  - lib/tapioca/helpers/sorbet_helper.rb
222
239
  - lib/tapioca/helpers/test/content.rb
223
240
  - lib/tapioca/helpers/test/dsl_compiler.rb
224
241
  - lib/tapioca/helpers/test/isolation.rb
225
242
  - lib/tapioca/helpers/test/template.rb
226
- - lib/tapioca/helpers/type_variable_helper.rb
227
243
  - lib/tapioca/internal.rb
228
244
  - lib/tapioca/rbi_ext/model.rb
229
245
  - lib/tapioca/rbi_formatter.rb
@@ -240,6 +256,7 @@ files:
240
256
  - lib/tapioca/sorbet_ext/fixed_hash_patch.rb
241
257
  - lib/tapioca/sorbet_ext/generic_name_patch.rb
242
258
  - lib/tapioca/sorbet_ext/name_patch.rb
259
+ - lib/tapioca/sorbet_ext/proc_bind_patch.rb
243
260
  - lib/tapioca/static/requires_compiler.rb
244
261
  - lib/tapioca/static/symbol_loader.rb
245
262
  - lib/tapioca/static/symbol_table_parser.rb
@@ -1,55 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require "tapioca/helpers/signatures_helper"
5
-
6
- module Tapioca
7
- module Dsl
8
- module Helpers
9
- module ParamHelper
10
- extend T::Sig
11
- include SignaturesHelper
12
-
13
- sig { params(name: String, type: String).returns(RBI::TypedParam) }
14
- def create_param(name, type:)
15
- create_typed_param(RBI::Param.new(name), type)
16
- end
17
-
18
- sig { params(name: String, type: String, default: String).returns(RBI::TypedParam) }
19
- def create_opt_param(name, type:, default:)
20
- create_typed_param(RBI::OptParam.new(name, default), type)
21
- end
22
-
23
- sig { params(name: String, type: String).returns(RBI::TypedParam) }
24
- def create_rest_param(name, type:)
25
- create_typed_param(RBI::RestParam.new(name), type)
26
- end
27
-
28
- sig { params(name: String, type: String).returns(RBI::TypedParam) }
29
- def create_kw_param(name, type:)
30
- create_typed_param(RBI::KwParam.new(name), type)
31
- end
32
-
33
- sig { params(name: String, type: String, default: String).returns(RBI::TypedParam) }
34
- def create_kw_opt_param(name, type:, default:)
35
- create_typed_param(RBI::KwOptParam.new(name, default), type)
36
- end
37
-
38
- sig { params(name: String, type: String).returns(RBI::TypedParam) }
39
- def create_kw_rest_param(name, type:)
40
- create_typed_param(RBI::KwRestParam.new(name), type)
41
- end
42
-
43
- sig { params(name: String, type: String).returns(RBI::TypedParam) }
44
- def create_block_param(name, type:)
45
- create_typed_param(RBI::BlockParam.new(name), type)
46
- end
47
-
48
- sig { params(param: RBI::Param, type: String).returns(RBI::TypedParam) }
49
- def create_typed_param(param, type)
50
- RBI::TypedParam.new(param: param, type: sanitize_signature_types(type))
51
- end
52
- end
53
- end
54
- end
55
- end
@@ -1,115 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module Tapioca
5
- module ShimsHelper
6
- extend T::Sig
7
- extend T::Helpers
8
-
9
- requires_ancestor { Thor::Shell }
10
-
11
- SORBET_PAYLOAD_URL = "https://github.com/sorbet/sorbet/tree/master/rbi"
12
-
13
- sig { params(index: RBI::Index, dir: String).void }
14
- def index_payload(index, dir)
15
- return unless Dir.exist?(dir)
16
-
17
- say("Loading Sorbet payload... ")
18
- files = Dir.glob("#{dir}/**/*.rbi").sort
19
- parse_and_index_files(index, files)
20
- say(" Done", :green)
21
- end
22
-
23
- sig { params(index: RBI::Index, kind: String, dir: String).void }
24
- def index_rbis(index, kind, dir)
25
- return unless Dir.exist?(dir) && !Dir.empty?(dir)
26
-
27
- say("Loading #{kind} RBIs from #{dir}... ")
28
- files = Dir.glob("#{dir}/**/*.rbi").sort
29
- parse_and_index_files(index, files)
30
- say(" Done", :green)
31
- end
32
-
33
- sig { params(index: RBI::Index, shim_rbi_dir: String).returns(T::Hash[String, T::Array[RBI::Node]]) }
34
- def duplicated_nodes_from_index(index, shim_rbi_dir)
35
- duplicates = {}
36
- say("Looking for duplicates... ")
37
- index.keys.each do |key|
38
- nodes = index[key]
39
- next unless shims_have_duplicates?(nodes, shim_rbi_dir)
40
-
41
- duplicates[key] = nodes
42
- end
43
- say(" Done", :green)
44
- duplicates
45
- end
46
-
47
- sig { params(loc: RBI::Loc, path_prefix: T.nilable(String)).returns(String) }
48
- def location_to_payload_url(loc, path_prefix:)
49
- return loc.to_s unless path_prefix
50
-
51
- url = loc.file || ""
52
- return loc.to_s unless url.start_with?(path_prefix)
53
-
54
- url = url.sub(path_prefix, SORBET_PAYLOAD_URL)
55
- url = "#{url}#L#{loc.begin_line}"
56
- url
57
- end
58
-
59
- private
60
-
61
- sig { params(index: RBI::Index, files: T::Array[String]).void }
62
- def parse_and_index_files(index, files)
63
- trees = files.map do |file|
64
- RBI::Parser.parse_file(file)
65
- rescue RBI::ParseError => e
66
- say_error("\nWarning: #{e} (#{e.location})", :yellow)
67
- end.compact
68
- index.visit_all(trees)
69
- end
70
-
71
- sig { params(nodes: T::Array[RBI::Node], shim_rbi_dir: String).returns(T::Boolean) }
72
- def shims_have_duplicates?(nodes, shim_rbi_dir)
73
- return false if nodes.size == 1
74
-
75
- shims = extract_shims(nodes, shim_rbi_dir)
76
- return false if shims.empty?
77
-
78
- props = extract_methods_and_attrs(shims)
79
- return false if props.empty?
80
-
81
- shims_with_sigs = extract_nodes_with_sigs(props)
82
- shims_with_sigs.each do |shim|
83
- shim_sigs = shim.sigs
84
-
85
- extract_methods_and_attrs(nodes).each do |node|
86
- next if node == shim
87
- return true if shim_sigs.all? { |sig| node.sigs.include?(sig) }
88
- end
89
-
90
- return false
91
- end
92
-
93
- true
94
- end
95
-
96
- sig { params(nodes: T::Array[RBI::Node], shim_rbi_dir: String).returns(T::Array[RBI::Node]) }
97
- def extract_shims(nodes, shim_rbi_dir)
98
- nodes.select do |node|
99
- node.loc&.file&.start_with?(shim_rbi_dir)
100
- end
101
- end
102
-
103
- sig { params(nodes: T::Array[RBI::Node]).returns(T::Array[T.any(RBI::Method, RBI::Attr)]) }
104
- def extract_methods_and_attrs(nodes)
105
- T.cast(nodes.select do |node|
106
- node.is_a?(RBI::Method) || node.is_a?(RBI::Attr)
107
- end, T::Array[T.any(RBI::Method, RBI::Attr)])
108
- end
109
-
110
- sig { params(nodes: T::Array[T.any(RBI::Method, RBI::Attr)]).returns(T::Array[T.any(RBI::Method, RBI::Attr)]) }
111
- def extract_nodes_with_sigs(nodes)
112
- nodes.reject { |node| node.sigs.empty? }
113
- end
114
- end
115
- end
@@ -1,17 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module Tapioca
5
- module SignaturesHelper
6
- extend T::Sig
7
-
8
- sig { params(sig_string: String).returns(String) }
9
- def sanitize_signature_types(sig_string)
10
- sig_string
11
- .gsub(".returns(<VOID>)", ".void")
12
- .gsub("<VOID>", "void")
13
- .gsub("<NOT-TYPED>", "T.untyped")
14
- .gsub(".params()", "")
15
- end
16
- end
17
- end
@@ -1,43 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module Tapioca
5
- module TypeVariableHelper
6
- extend T::Sig
7
- extend SorbetHelper
8
-
9
- sig do
10
- params(
11
- type: String,
12
- variance: Symbol,
13
- fixed: T.nilable(String),
14
- upper: T.nilable(String),
15
- lower: T.nilable(String)
16
- ).returns(String)
17
- end
18
- def self.serialize_type_variable(type, variance, fixed, upper, lower)
19
- variance = nil if variance == :invariant
20
-
21
- bounds = []
22
- bounds << "fixed: #{fixed}" if fixed
23
- bounds << "lower: #{lower}" if lower
24
- bounds << "upper: #{upper}" if upper
25
-
26
- parameters = []
27
- block = []
28
-
29
- parameters << ":#{variance}" if variance
30
-
31
- if sorbet_supports?(:type_variable_block_syntax)
32
- block = bounds
33
- else
34
- parameters.concat(bounds)
35
- end
36
-
37
- serialized = type.dup
38
- serialized << "(#{parameters.join(", ")})" unless parameters.empty?
39
- serialized << " { { #{block.join(", ")} } }" unless block.empty?
40
- serialized
41
- end
42
- end
43
- end