tapioca 0.4.17 → 0.4.22

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,16 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module T
5
+ module Types
6
+ class Simple
7
+ module NamePatch
8
+ def name
9
+ @name ||= Module.instance_method(:name).bind(@raw_type).call.freeze
10
+ end
11
+ end
12
+
13
+ prepend NamePatch
14
+ end
15
+ end
16
+ end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Tapioca
5
- VERSION = "0.4.17"
5
+ VERSION = "0.4.22"
6
6
  end
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.17
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-03-11 00:00:00.000000000 Z
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.0.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