tapioca 0.4.17 → 0.4.22
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.
- checksums.yaml +4 -4
- data/Gemfile +13 -14
- data/README.md +4 -2
- data/exe/tapioca +17 -2
- data/lib/tapioca.rb +1 -27
- data/lib/tapioca/cli.rb +1 -108
- data/lib/tapioca/cli/main.rb +146 -0
- data/lib/tapioca/compilers/dsl/active_job.rb +71 -0
- data/lib/tapioca/compilers/dsl/active_record_columns.rb +4 -4
- data/lib/tapioca/compilers/dsl/active_record_scope.rb +1 -1
- data/lib/tapioca/compilers/dsl/base.rb +1 -1
- data/lib/tapioca/compilers/dsl/protobuf.rb +132 -16
- data/lib/tapioca/compilers/dsl/url_helpers.rb +3 -3
- data/lib/tapioca/compilers/requires_compiler.rb +1 -1
- data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +264 -301
- data/lib/tapioca/config.rb +1 -1
- data/lib/tapioca/config_builder.rb +7 -12
- data/lib/tapioca/core_ext/string.rb +18 -0
- data/lib/tapioca/gemfile.rb +1 -1
- data/lib/tapioca/generator.rb +144 -37
- data/lib/tapioca/generic_type_registry.rb +222 -0
- data/lib/tapioca/internal.rb +28 -0
- data/lib/tapioca/rbi/model.rb +405 -0
- data/lib/tapioca/rbi/printer.rb +410 -0
- data/lib/tapioca/rbi/rewriters/group_nodes.rb +106 -0
- data/lib/tapioca/rbi/rewriters/nest_non_public_methods.rb +65 -0
- data/lib/tapioca/rbi/rewriters/nest_singleton_methods.rb +42 -0
- data/lib/tapioca/rbi/rewriters/sort_nodes.rb +82 -0
- data/lib/tapioca/rbi/visitor.rb +21 -0
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +66 -0
- data/lib/tapioca/sorbet_ext/name_patch.rb +16 -0
- data/lib/tapioca/version.rb +1 -1
- metadata +17 -3
@@ -0,0 +1,106 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Tapioca
|
5
|
+
module RBI
|
6
|
+
module Rewriters
|
7
|
+
class GroupNodes < Visitor
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { override.params(node: T.nilable(Node)).void }
|
11
|
+
def visit(node)
|
12
|
+
return unless node
|
13
|
+
|
14
|
+
case node
|
15
|
+
when Tree
|
16
|
+
kinds = node.nodes.map(&:group_kind)
|
17
|
+
kinds.compact!
|
18
|
+
kinds.uniq!
|
19
|
+
|
20
|
+
groups = {}
|
21
|
+
kinds.each { |kind| groups[kind] = Group.new(kind) }
|
22
|
+
|
23
|
+
node.nodes.dup.each do |child|
|
24
|
+
visit(child)
|
25
|
+
child.detach
|
26
|
+
groups[child.group_kind] << child
|
27
|
+
end
|
28
|
+
|
29
|
+
groups.each { |_, group| node << group }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Tree
|
36
|
+
extend T::Sig
|
37
|
+
|
38
|
+
sig { void }
|
39
|
+
def group_nodes!
|
40
|
+
visitor = Rewriters::GroupNodes.new
|
41
|
+
visitor.visit(self)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Node
|
46
|
+
extend T::Sig
|
47
|
+
|
48
|
+
sig { returns(Group::Kind) }
|
49
|
+
def group_kind
|
50
|
+
case self
|
51
|
+
when Include, Extend
|
52
|
+
Group::Kind::Mixins
|
53
|
+
when Helper
|
54
|
+
Group::Kind::Helpers
|
55
|
+
when TypeMember
|
56
|
+
Group::Kind::TypeMembers
|
57
|
+
when MixesInClassMethods
|
58
|
+
Group::Kind::MixesInClassMethods
|
59
|
+
when TStructField
|
60
|
+
Group::Kind::TStructFields
|
61
|
+
when TEnumBlock
|
62
|
+
Group::Kind::TEnums
|
63
|
+
when VisibilityGroup
|
64
|
+
Group::Kind::Methods
|
65
|
+
when Method
|
66
|
+
if name == "initialize"
|
67
|
+
Group::Kind::Inits
|
68
|
+
else
|
69
|
+
Group::Kind::Methods
|
70
|
+
end
|
71
|
+
when Scope, Const
|
72
|
+
Group::Kind::Consts
|
73
|
+
else
|
74
|
+
raise "Unknown group for #{self}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class Group < Tree
|
80
|
+
extend T::Sig
|
81
|
+
|
82
|
+
sig { returns(Kind) }
|
83
|
+
attr_reader :kind
|
84
|
+
|
85
|
+
sig { params(kind: Kind).void }
|
86
|
+
def initialize(kind)
|
87
|
+
super()
|
88
|
+
@kind = kind
|
89
|
+
end
|
90
|
+
|
91
|
+
class Kind < T::Enum
|
92
|
+
enums do
|
93
|
+
Mixins = new
|
94
|
+
Helpers = new
|
95
|
+
TypeMembers = new
|
96
|
+
MixesInClassMethods = new
|
97
|
+
TStructFields = new
|
98
|
+
TEnums = new
|
99
|
+
Inits = new
|
100
|
+
Methods = new
|
101
|
+
Consts = new
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Tapioca
|
5
|
+
module RBI
|
6
|
+
module Rewriters
|
7
|
+
class NestNonPublicMethods < Visitor
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { override.params(node: T.nilable(Node)).void }
|
11
|
+
def visit(node)
|
12
|
+
return unless node
|
13
|
+
|
14
|
+
case node
|
15
|
+
when Tree
|
16
|
+
public_group = VisibilityGroup.new(Visibility::Public)
|
17
|
+
protected_group = VisibilityGroup.new(Visibility::Protected)
|
18
|
+
private_group = VisibilityGroup.new(Visibility::Private)
|
19
|
+
|
20
|
+
node.nodes.dup.each do |child|
|
21
|
+
visit(child)
|
22
|
+
next unless child.is_a?(Method)
|
23
|
+
child.detach
|
24
|
+
case child.visibility
|
25
|
+
when Visibility::Protected
|
26
|
+
protected_group << child
|
27
|
+
when Visibility::Private
|
28
|
+
private_group << child
|
29
|
+
else
|
30
|
+
public_group << child
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
node << public_group unless public_group.empty?
|
35
|
+
node << protected_group unless protected_group.empty?
|
36
|
+
node << private_group unless private_group.empty?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Tree
|
43
|
+
extend T::Sig
|
44
|
+
|
45
|
+
sig { void }
|
46
|
+
def nest_non_public_methods!
|
47
|
+
visitor = Rewriters::NestNonPublicMethods.new
|
48
|
+
visitor.visit(self)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class VisibilityGroup < Tree
|
53
|
+
extend T::Sig
|
54
|
+
|
55
|
+
sig { returns(Visibility) }
|
56
|
+
attr_reader :visibility
|
57
|
+
|
58
|
+
sig { params(visibility: Visibility).void }
|
59
|
+
def initialize(visibility)
|
60
|
+
super()
|
61
|
+
@visibility = visibility
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Tapioca
|
5
|
+
module RBI
|
6
|
+
module Rewriters
|
7
|
+
class NestSingletonMethods < Visitor
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { override.params(node: T.nilable(Node)).void }
|
11
|
+
def visit(node)
|
12
|
+
return unless node
|
13
|
+
|
14
|
+
case node
|
15
|
+
when Tree
|
16
|
+
singleton_class = SingletonClass.new
|
17
|
+
|
18
|
+
node.nodes.dup.each do |child|
|
19
|
+
visit(child)
|
20
|
+
next unless child.is_a?(Method) && child.is_singleton
|
21
|
+
child.detach
|
22
|
+
child.is_singleton = false
|
23
|
+
singleton_class << child
|
24
|
+
end
|
25
|
+
|
26
|
+
node << singleton_class unless singleton_class.empty?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Tree
|
33
|
+
extend T::Sig
|
34
|
+
|
35
|
+
sig { void }
|
36
|
+
def nest_singleton_methods!
|
37
|
+
visitor = Rewriters::NestSingletonMethods.new
|
38
|
+
visitor.visit(self)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Tapioca
|
5
|
+
module RBI
|
6
|
+
module Rewriters
|
7
|
+
class SortNodes < Visitor
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { override.params(node: T.nilable(Node)).void }
|
11
|
+
def visit(node)
|
12
|
+
return unless node.is_a?(Tree)
|
13
|
+
visit_all(node.nodes)
|
14
|
+
node.nodes.sort! do |a, b|
|
15
|
+
res = node_rank(a) <=> node_rank(b)
|
16
|
+
res = node_name(a) <=> node_name(b) if res == 0
|
17
|
+
res || 0
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
sig { params(node: Node).returns(Integer) }
|
24
|
+
def node_rank(node)
|
25
|
+
case node
|
26
|
+
when Group then kind_rank(node.kind)
|
27
|
+
when Include, Extend then 0
|
28
|
+
when Helper then 1
|
29
|
+
when TypeMember then 2
|
30
|
+
when MixesInClassMethods then 3
|
31
|
+
when TStructField then 4
|
32
|
+
when TEnumBlock then 5
|
33
|
+
when Method
|
34
|
+
if node.name == "initialize"
|
35
|
+
7
|
36
|
+
else
|
37
|
+
8
|
38
|
+
end
|
39
|
+
when Scope, Const then 9
|
40
|
+
else
|
41
|
+
10
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
sig { params(kind: Group::Kind).returns(Integer) }
|
46
|
+
def kind_rank(kind)
|
47
|
+
case kind
|
48
|
+
when Group::Kind::Mixins then 0
|
49
|
+
when Group::Kind::Helpers then 1
|
50
|
+
when Group::Kind::TypeMembers then 2
|
51
|
+
when Group::Kind::MixesInClassMethods then 3
|
52
|
+
when Group::Kind::TStructFields then 4
|
53
|
+
when Group::Kind::TEnums then 5
|
54
|
+
when Group::Kind::Inits then 6
|
55
|
+
when Group::Kind::Methods then 7
|
56
|
+
when Group::Kind::Consts then 8
|
57
|
+
else
|
58
|
+
T.absurd(kind)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
sig { params(node: Node).returns(T.nilable(String)) }
|
63
|
+
def node_name(node)
|
64
|
+
case node
|
65
|
+
when Module, Class, Const, Method, Helper, TStructField
|
66
|
+
node.name
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class Tree
|
73
|
+
extend T::Sig
|
74
|
+
|
75
|
+
sig { void }
|
76
|
+
def sort_nodes!
|
77
|
+
visitor = Rewriters::SortNodes.new
|
78
|
+
visitor.visit(self)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Tapioca
|
5
|
+
module RBI
|
6
|
+
class Visitor
|
7
|
+
extend T::Helpers
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
abstract!
|
11
|
+
|
12
|
+
sig { abstract.params(node: T.nilable(Node)).void }
|
13
|
+
def visit(node); end
|
14
|
+
|
15
|
+
sig { params(nodes: T::Array[Node]).void }
|
16
|
+
def visit_all(nodes)
|
17
|
+
nodes.each { |node| visit(node) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "tapioca/sorbet_ext/name_patch"
|
5
|
+
|
6
|
+
module T
|
7
|
+
module Generic
|
8
|
+
# This module intercepts calls to generic type instantiations and type variable definitions.
|
9
|
+
# Tapioca stores the data from those calls in a `GenericTypeRegistry` which can then be used
|
10
|
+
# to look up the original call details when we are trying to do code generation.
|
11
|
+
#
|
12
|
+
# We are interested in the data of the `[]`, `type_member` and `type_template` calls which
|
13
|
+
# are all needed to generate good generic information at runtime.
|
14
|
+
module TypeStoragePatch
|
15
|
+
def [](*types)
|
16
|
+
# `T::Generic#[]` just returns `self`, so let's call and store it.
|
17
|
+
constant = super
|
18
|
+
# `register_type` method builds and returns an instantiated clone of the generic type
|
19
|
+
# so, we just return that from this method as well.
|
20
|
+
Tapioca::GenericTypeRegistry.register_type(constant, types)
|
21
|
+
end
|
22
|
+
|
23
|
+
def type_member(variance = :invariant, fixed: nil, lower: T.untyped, upper: BasicObject)
|
24
|
+
# `T::Generic#type_member` just instantiates a `T::Type::TypeMember` instance and returns it.
|
25
|
+
# We use that when registering the type member and then later return it from this method.
|
26
|
+
type_member = super
|
27
|
+
Tapioca::GenericTypeRegistry.register_type_member(self, type_member, fixed, lower, upper)
|
28
|
+
type_member
|
29
|
+
end
|
30
|
+
|
31
|
+
def type_template(variance = :invariant, fixed: nil, lower: T.untyped, upper: BasicObject)
|
32
|
+
# `T::Generic#type_template` just instantiates a `T::Type::TypeTemplate` instance and returns it.
|
33
|
+
# We use that when registering the type template and then later return it from this method.
|
34
|
+
type_template = super
|
35
|
+
Tapioca::GenericTypeRegistry.register_type_template(self, type_template, fixed, lower, upper)
|
36
|
+
type_template
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
prepend TypeStoragePatch
|
41
|
+
end
|
42
|
+
|
43
|
+
module Types
|
44
|
+
class Simple
|
45
|
+
# This module intercepts calls to the `name` method for
|
46
|
+
# simple types, so that it can ask the name to the type if
|
47
|
+
# the type is generic, since, by this point, we've created
|
48
|
+
# a clone of that type with the `name` method returning the
|
49
|
+
# appropriate name for that specific concrete type.
|
50
|
+
module GenericNamePatch
|
51
|
+
def name
|
52
|
+
if T::Generic === @raw_type
|
53
|
+
# for types that are generic, use the name
|
54
|
+
# returned by the "name" method of this instance
|
55
|
+
@name ||= T.unsafe(@raw_type).name.freeze
|
56
|
+
else
|
57
|
+
# otherwise, fallback to the normal name lookup
|
58
|
+
super
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
prepend GenericNamePatch
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/tapioca/version.rb
CHANGED
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.4.
|
4
|
+
version: 0.4.22
|
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: 2021-
|
14
|
+
date: 2021-05-19 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -125,8 +125,10 @@ files:
|
|
125
125
|
- exe/tapioca
|
126
126
|
- lib/tapioca.rb
|
127
127
|
- lib/tapioca/cli.rb
|
128
|
+
- lib/tapioca/cli/main.rb
|
128
129
|
- lib/tapioca/compilers/dsl/action_controller_helpers.rb
|
129
130
|
- lib/tapioca/compilers/dsl/action_mailer.rb
|
131
|
+
- lib/tapioca/compilers/dsl/active_job.rb
|
130
132
|
- lib/tapioca/compilers/dsl/active_record_associations.rb
|
131
133
|
- lib/tapioca/compilers/dsl/active_record_columns.rb
|
132
134
|
- lib/tapioca/compilers/dsl/active_record_enum.rb
|
@@ -153,9 +155,21 @@ files:
|
|
153
155
|
- lib/tapioca/config_builder.rb
|
154
156
|
- lib/tapioca/constant_locator.rb
|
155
157
|
- lib/tapioca/core_ext/class.rb
|
158
|
+
- lib/tapioca/core_ext/string.rb
|
156
159
|
- lib/tapioca/gemfile.rb
|
157
160
|
- lib/tapioca/generator.rb
|
161
|
+
- lib/tapioca/generic_type_registry.rb
|
162
|
+
- lib/tapioca/internal.rb
|
158
163
|
- lib/tapioca/loader.rb
|
164
|
+
- lib/tapioca/rbi/model.rb
|
165
|
+
- lib/tapioca/rbi/printer.rb
|
166
|
+
- lib/tapioca/rbi/rewriters/group_nodes.rb
|
167
|
+
- lib/tapioca/rbi/rewriters/nest_non_public_methods.rb
|
168
|
+
- lib/tapioca/rbi/rewriters/nest_singleton_methods.rb
|
169
|
+
- lib/tapioca/rbi/rewriters/sort_nodes.rb
|
170
|
+
- lib/tapioca/rbi/visitor.rb
|
171
|
+
- lib/tapioca/sorbet_ext/generic_name_patch.rb
|
172
|
+
- lib/tapioca/sorbet_ext/name_patch.rb
|
159
173
|
- lib/tapioca/version.rb
|
160
174
|
homepage: https://github.com/Shopify/tapioca
|
161
175
|
licenses:
|
@@ -177,7 +191,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
177
191
|
- !ruby/object:Gem::Version
|
178
192
|
version: '0'
|
179
193
|
requirements: []
|
180
|
-
rubygems_version: 3.
|
194
|
+
rubygems_version: 3.2.17
|
181
195
|
signing_key:
|
182
196
|
specification_version: 4
|
183
197
|
summary: A Ruby Interface file generator for gems, core types and the Ruby standard
|