tapioca 0.4.10 → 0.4.15
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 +3 -2
- data/lib/tapioca/compilers/dsl/action_controller_helpers.rb +38 -39
- data/lib/tapioca/compilers/dsl/action_mailer.rb +4 -4
- data/lib/tapioca/compilers/dsl/active_record_associations.rb +80 -48
- data/lib/tapioca/compilers/dsl/active_record_columns.rb +60 -65
- data/lib/tapioca/compilers/dsl/active_record_enum.rb +27 -23
- data/lib/tapioca/compilers/dsl/active_record_scope.rb +18 -17
- data/lib/tapioca/compilers/dsl/active_record_typed_store.rb +8 -7
- data/lib/tapioca/compilers/dsl/active_resource.rb +5 -4
- data/lib/tapioca/compilers/dsl/active_support_current_attributes.rb +6 -7
- data/lib/tapioca/compilers/dsl/base.rb +1 -1
- data/lib/tapioca/compilers/dsl/frozen_record.rb +25 -25
- data/lib/tapioca/compilers/dsl/{active_record_identity_cache.rb → identity_cache.rb} +11 -10
- data/lib/tapioca/compilers/dsl/protobuf.rb +1 -1
- data/lib/tapioca/compilers/dsl/sidekiq_worker.rb +83 -0
- data/lib/tapioca/compilers/dsl/smart_properties.rb +1 -1
- data/lib/tapioca/compilers/dsl/state_machines.rb +75 -73
- data/lib/tapioca/compilers/dsl/url_helpers.rb +9 -5
- data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +69 -40
- data/lib/tapioca/gemfile.rb +30 -22
- data/lib/tapioca/generator.rb +4 -0
- data/lib/tapioca/version.rb +1 -1
- metadata +18 -3
@@ -15,7 +15,7 @@ module Tapioca
|
|
15
15
|
module Compilers
|
16
16
|
module Dsl
|
17
17
|
# `Tapioca::Compilers::Dsl::SmartProperties` generates RBI files for classes that include
|
18
|
-
# `SmartProperties`
|
18
|
+
# [`SmartProperties`](https://github.com/t6d/smart_properties).
|
19
19
|
#
|
20
20
|
# For example, with the following class that includes `SmartProperties`:
|
21
21
|
#
|
@@ -15,10 +15,12 @@ end
|
|
15
15
|
module Tapioca
|
16
16
|
module Compilers
|
17
17
|
module Dsl
|
18
|
-
# `
|
19
|
-
# (
|
20
|
-
# methods generated by
|
21
|
-
#
|
18
|
+
# `Tapioca::Compilers::Dsl::StateMachines` generates RBI files for classes that setup a
|
19
|
+
# [`state_machine`](https://github.com/state-machines/state_machines). The generator also
|
20
|
+
# processes the extra methods generated by
|
21
|
+
# [StateMachines Active Record](https://github.com/state-machines/state_machines-activerecord)
|
22
|
+
# and [StateMachines Active Model](https://github.com/state-machines/state_machines-activemodel)
|
23
|
+
# integrations.
|
22
24
|
#
|
23
25
|
# For example, with the following `Vehicle` class:
|
24
26
|
#
|
@@ -45,75 +47,75 @@ module Tapioca
|
|
45
47
|
# # vehicle.rbi
|
46
48
|
# # typed: true
|
47
49
|
# class Vehicle
|
48
|
-
# include
|
49
|
-
# extend
|
50
|
-
# end
|
50
|
+
# include StateMachineInstanceHelperModule
|
51
|
+
# extend StateMachineClassHelperModule
|
51
52
|
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
53
|
+
# module StateMachineClassHelperModule
|
54
|
+
# sig { params(event: T.any(String, Symbol)).returns(String) }
|
55
|
+
# def human_alarm_state_event_name(event); end
|
55
56
|
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
57
|
+
# sig { params(state: T.any(String, Symbol)).returns(String) }
|
58
|
+
# def human_alarm_state_name(state); end
|
59
|
+
# end
|
59
60
|
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
61
|
+
# module StateMachineInstanceHelperModule
|
62
|
+
# sig { returns(T::Boolean) }
|
63
|
+
# def alarm_active?; end
|
63
64
|
#
|
64
|
-
#
|
65
|
-
#
|
65
|
+
# sig { returns(T::Boolean) }
|
66
|
+
# def alarm_off?; end
|
66
67
|
#
|
67
|
-
#
|
68
|
-
#
|
68
|
+
# sig { returns(Integer) }
|
69
|
+
# def alarm_state; end
|
69
70
|
#
|
70
|
-
#
|
71
|
-
#
|
71
|
+
# sig { params(value: Integer).returns(Integer) }
|
72
|
+
# def alarm_state=(value); end
|
72
73
|
#
|
73
|
-
#
|
74
|
-
#
|
74
|
+
# sig { params(state: T.any(String, Symbol)).returns(T::Boolean) }
|
75
|
+
# def alarm_state?(state); end
|
75
76
|
#
|
76
|
-
#
|
77
|
-
#
|
77
|
+
# sig { params(args: T.untyped).returns(T::Array[T.any(String, Symbol)]) }
|
78
|
+
# def alarm_state_events(*args); end
|
78
79
|
#
|
79
|
-
#
|
80
|
-
#
|
80
|
+
# sig { returns(T.any(String, Symbol)) }
|
81
|
+
# def alarm_state_name; end
|
81
82
|
#
|
82
|
-
#
|
83
|
-
#
|
83
|
+
# sig { params(args: T.untyped).returns(T::Array[::StateMachines::Transition]) }
|
84
|
+
# def alarm_state_paths(*args); end
|
84
85
|
#
|
85
|
-
#
|
86
|
-
#
|
86
|
+
# sig { params(args: T.untyped).returns(T::Array[::StateMachines::Transition]) }
|
87
|
+
# def alarm_state_transitions(*args); end
|
87
88
|
#
|
88
|
-
#
|
89
|
-
#
|
89
|
+
# sig { returns(T::Boolean) }
|
90
|
+
# def can_disable_alarm?; end
|
90
91
|
#
|
91
|
-
#
|
92
|
-
#
|
92
|
+
# sig { returns(T::Boolean) }
|
93
|
+
# def can_enable_alarm?; end
|
93
94
|
#
|
94
|
-
#
|
95
|
-
#
|
95
|
+
# sig { params(args: T.untyped).returns(T::Boolean) }
|
96
|
+
# def disable_alarm(*args); end
|
96
97
|
#
|
97
|
-
#
|
98
|
-
#
|
98
|
+
# sig { params(args: T.untyped).returns(T::Boolean) }
|
99
|
+
# def disable_alarm!(*args); end
|
99
100
|
#
|
100
|
-
#
|
101
|
-
#
|
101
|
+
# sig { params(args: T.untyped).returns(T.nilable(::StateMachines::Transition)) }
|
102
|
+
# def disable_alarm_transition(*args); end
|
102
103
|
#
|
103
|
-
#
|
104
|
-
#
|
104
|
+
# sig { params(args: T.untyped).returns(T::Boolean) }
|
105
|
+
# def enable_alarm(*args); end
|
105
106
|
#
|
106
|
-
#
|
107
|
-
#
|
107
|
+
# sig { params(args: T.untyped).returns(T::Boolean) }
|
108
|
+
# def enable_alarm!(*args); end
|
108
109
|
#
|
109
|
-
#
|
110
|
-
#
|
110
|
+
# sig { params(args: T.untyped).returns(T.nilable(::StateMachines::Transition)) }
|
111
|
+
# def enable_alarm_transition(*args); end
|
111
112
|
#
|
112
|
-
#
|
113
|
-
#
|
113
|
+
# sig { params(event: T.any(String, Symbol), args: T.untyped).returns(T::Boolean) }
|
114
|
+
# def fire_alarm_state_event(event, *args); end
|
114
115
|
#
|
115
|
-
#
|
116
|
-
#
|
116
|
+
# sig { returns(String) }
|
117
|
+
# def human_alarm_state_name; end
|
118
|
+
# end
|
117
119
|
# end
|
118
120
|
# ~~~
|
119
121
|
class StateMachines < Base
|
@@ -123,34 +125,34 @@ module Tapioca
|
|
123
125
|
def decorate(root, constant)
|
124
126
|
return if constant.state_machines.empty?
|
125
127
|
|
126
|
-
|
127
|
-
|
128
|
+
root.path(constant) do |klass|
|
129
|
+
instance_module_name = "StateMachineInstanceHelperModule"
|
130
|
+
class_module_name = "StateMachineClassHelperModule"
|
128
131
|
|
129
|
-
|
130
|
-
|
132
|
+
instance_module = klass.create_module(instance_module_name)
|
133
|
+
class_module = klass.create_module(class_module_name)
|
131
134
|
|
132
|
-
|
133
|
-
|
135
|
+
constant.state_machines.each_value do |machine|
|
136
|
+
state_type = state_type_for(machine)
|
134
137
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
define_state_accessor(instance_module, machine, state_type)
|
139
|
+
define_state_predicate(instance_module, machine)
|
140
|
+
define_event_helpers(instance_module, machine)
|
141
|
+
define_path_helpers(instance_module, machine)
|
142
|
+
define_name_helpers(instance_module, class_module, machine)
|
143
|
+
define_scopes(class_module, machine)
|
141
144
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
+
define_state_methods(instance_module, machine)
|
146
|
+
define_event_methods(instance_module, machine)
|
147
|
+
end
|
145
148
|
|
146
|
-
|
149
|
+
matching_integration_name = ::StateMachines::Integrations.match(constant)&.integration_name
|
147
150
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
151
|
+
case matching_integration_name
|
152
|
+
when :active_record
|
153
|
+
define_activerecord_methods(instance_module)
|
154
|
+
end
|
152
155
|
|
153
|
-
root.path(constant) do |klass|
|
154
156
|
klass.create_include(instance_module_name)
|
155
157
|
klass.create_extend(class_module_name)
|
156
158
|
end
|
@@ -15,8 +15,7 @@ module Tapioca
|
|
15
15
|
module Compilers
|
16
16
|
module Dsl
|
17
17
|
# `Tapioca::Compilers::Dsl::UrlHelpers` generates RBI files for classes that include or extend
|
18
|
-
# `Rails.application.routes.url_helpers`
|
19
|
-
# (see https://api.rubyonrails.org/v5.1.7/classes/ActionDispatch/Routing/UrlFor.html#module-ActionDispatch::Routing::UrlFor-label-URL+generation+for+named+routes).
|
18
|
+
# [`Rails.application.routes.url_helpers`](https://api.rubyonrails.org/v5.1.7/classes/ActionDispatch/Routing/UrlFor.html#module-ActionDispatch::Routing::UrlFor-label-URL+generation+for+named+routes).
|
20
19
|
#
|
21
20
|
# For example, with the following setup:
|
22
21
|
#
|
@@ -32,7 +31,12 @@ module Tapioca
|
|
32
31
|
# ~~~rb
|
33
32
|
# app/models/post.rb
|
34
33
|
# class Post
|
35
|
-
#
|
34
|
+
# # Use `T.unsafe` so that Sorbet does not complain about a dynamic
|
35
|
+
# # module being included. This allows the `include` to happen properly
|
36
|
+
# # at runtime but Sorbet won't see the include. However, since this
|
37
|
+
# # generator will generate the proper RBI files for the include,
|
38
|
+
# # static type checking will work as expected.
|
39
|
+
# T.unsafe(self).include Rails.application.routes.url_helpers
|
36
40
|
# end
|
37
41
|
# ~~~
|
38
42
|
#
|
@@ -126,8 +130,8 @@ module Tapioca
|
|
126
130
|
sig { params(root: Parlour::RbiGenerator::Namespace, constant: T.class_of(Module)).void }
|
127
131
|
def generate_module_for(root, constant)
|
128
132
|
root.create_module(T.must(constant.name)) do |mod|
|
129
|
-
mod.create_include("ActionDispatch::Routing::UrlFor")
|
130
|
-
mod.create_include("ActionDispatch::Routing::PolymorphicRoutes")
|
133
|
+
mod.create_include("::ActionDispatch::Routing::UrlFor")
|
134
|
+
mod.create_include("::ActionDispatch::Routing::PolymorphicRoutes")
|
131
135
|
|
132
136
|
constant.instance_methods(false).each do |method|
|
133
137
|
mod.create_method(
|
@@ -74,9 +74,9 @@ module Tapioca
|
|
74
74
|
compile(symbol, constant)
|
75
75
|
end
|
76
76
|
|
77
|
-
sig { params(symbol: String).returns(BasicObject).checked(:never) }
|
78
|
-
def resolve_constant(symbol)
|
79
|
-
Object.const_get(symbol,
|
77
|
+
sig { params(symbol: String, inherit: T::Boolean).returns(BasicObject).checked(:never) }
|
78
|
+
def resolve_constant(symbol, inherit: false)
|
79
|
+
Object.const_get(symbol, inherit)
|
80
80
|
rescue NameError, LoadError, RuntimeError, ArgumentError, TypeError
|
81
81
|
nil
|
82
82
|
end
|
@@ -122,12 +122,15 @@ module Tapioca
|
|
122
122
|
def compile_alias(name, constant)
|
123
123
|
return if symbol_ignored?(name)
|
124
124
|
|
125
|
-
|
125
|
+
target = name_of(constant)
|
126
|
+
# If target has no name, let's make it an anonymous class or module with `Class.new` or `Module.new`
|
127
|
+
target = "#{constant.class}.new" unless target
|
128
|
+
|
126
129
|
add_to_alias_namespace(name)
|
127
130
|
|
128
131
|
return if IGNORED_SYMBOLS.include?(name)
|
129
132
|
|
130
|
-
indented("#{name} = #{
|
133
|
+
indented("#{name} = #{target}")
|
131
134
|
end
|
132
135
|
|
133
136
|
sig do
|
@@ -189,15 +192,12 @@ module Tapioca
|
|
189
192
|
def compile_module_helpers(constant)
|
190
193
|
abstract_type = T::Private::Abstract::Data.get(constant, :abstract_type)
|
191
194
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
else
|
199
|
-
""
|
200
|
-
end
|
195
|
+
helpers = []
|
196
|
+
helpers << indented("#{abstract_type}!") if abstract_type
|
197
|
+
helpers << indented("final!") if T::Private::Final.final_module?(constant)
|
198
|
+
helpers << indented("sealed!") if T::Private::Sealed.sealed_module?(constant)
|
199
|
+
|
200
|
+
helpers.join("\n")
|
201
201
|
end
|
202
202
|
|
203
203
|
sig { params(constant: Module).returns(String) }
|
@@ -207,7 +207,7 @@ module Tapioca
|
|
207
207
|
constant.props.map do |name, prop|
|
208
208
|
method = "prop"
|
209
209
|
method = "const" if prop.fetch(:immutable, false)
|
210
|
-
type = prop.fetch(:type_object, "T.untyped")
|
210
|
+
type = prop.fetch(:type_object, "T.untyped").to_s.gsub(".returns(<VOID>)", ".void")
|
211
211
|
|
212
212
|
if prop.key?(:default)
|
213
213
|
indented("#{method} :#{name}, #{type}, default: T.unsafe(nil)")
|
@@ -292,33 +292,16 @@ module Tapioca
|
|
292
292
|
|
293
293
|
sig { params(constant: Module).returns(String) }
|
294
294
|
def compile_mixins(constant)
|
295
|
-
|
296
|
-
if constant.is_a?(Class)
|
297
|
-
ancestors = constant.superclass&.ancestors || Object.ancestors
|
298
|
-
Set.new(ancestors)
|
299
|
-
else
|
300
|
-
Module.ancestors
|
301
|
-
end
|
295
|
+
singleton_class = singleton_class_of(constant)
|
302
296
|
|
303
|
-
|
304
|
-
|
305
|
-
Set.new(singleton_class_of(constant.superclass).ancestors)
|
306
|
-
else
|
307
|
-
Module.ancestors
|
308
|
-
end
|
309
|
-
|
310
|
-
interesting_ancestors =
|
311
|
-
constant.ancestors.reject { |mod| ignorable_ancestors.include?(mod) }
|
297
|
+
interesting_ancestors = interesting_ancestors_of(constant)
|
298
|
+
interesting_singleton_class_ancestors = interesting_ancestors_of(singleton_class)
|
312
299
|
|
313
300
|
prepend = interesting_ancestors.take_while { |c| !are_equal?(constant, c) }
|
314
301
|
include = interesting_ancestors.drop(prepend.size + 1)
|
315
|
-
extend =
|
316
|
-
|
317
|
-
|
318
|
-
inherited_singleton_class_ancestors.include?(mod) ||
|
319
|
-
!public_module?(mod) ||
|
320
|
-
Module != class_of(mod)
|
321
|
-
end
|
302
|
+
extend = interesting_singleton_class_ancestors.reject do |mod|
|
303
|
+
!public_module?(mod) || Module != class_of(mod) || are_equal?(mod, singleton_class)
|
304
|
+
end
|
322
305
|
|
323
306
|
prepends = prepend
|
324
307
|
.reverse
|
@@ -757,18 +740,59 @@ module Tapioca
|
|
757
740
|
Module.instance_method(:name).bind(constant).call
|
758
741
|
end
|
759
742
|
|
760
|
-
sig { params(constant:
|
743
|
+
sig { params(constant: Module).returns(Class) }
|
761
744
|
def singleton_class_of(constant)
|
762
745
|
Object.instance_method(:singleton_class).bind(constant).call
|
763
746
|
end
|
764
747
|
|
748
|
+
sig { params(constant: Module).returns(T::Array[Module]) }
|
749
|
+
def ancestors_of(constant)
|
750
|
+
Module.instance_method(:ancestors).bind(constant).call
|
751
|
+
end
|
752
|
+
|
753
|
+
sig { params(constant: Module).returns(T::Array[Module]) }
|
754
|
+
def inherited_ancestors_of(constant)
|
755
|
+
if Class === constant
|
756
|
+
ancestors_of(superclass_of(constant) || Object)
|
757
|
+
else
|
758
|
+
Module.ancestors
|
759
|
+
end
|
760
|
+
end
|
761
|
+
|
762
|
+
sig { params(constant: Module).returns(T::Array[Module]) }
|
763
|
+
def interesting_ancestors_of(constant)
|
764
|
+
inherited_ancestors_ids = Set.new(
|
765
|
+
inherited_ancestors_of(constant).map { |mod| object_id_of(mod) }
|
766
|
+
)
|
767
|
+
# TODO: There is actually a bug here where this will drop modules that
|
768
|
+
# may be included twice. For example:
|
769
|
+
#
|
770
|
+
# ```ruby
|
771
|
+
# class Foo
|
772
|
+
# prepend Kernel
|
773
|
+
# end
|
774
|
+
# ````
|
775
|
+
# would give:
|
776
|
+
# ```ruby
|
777
|
+
# Foo.ancestors #=> [Kernel, Foo, Object, Kernel, BasicObject]
|
778
|
+
# ````
|
779
|
+
# but since we drop `Kernel` whenever we match it, we would miss
|
780
|
+
# the `prepend Kernel` in the output.
|
781
|
+
#
|
782
|
+
# Instead, we should only drop the tail matches of the ancestors and
|
783
|
+
# inherited ancestors, past the location of the constant itself.
|
784
|
+
constant.ancestors.reject do |mod|
|
785
|
+
inherited_ancestors_ids.include?(object_id_of(mod))
|
786
|
+
end
|
787
|
+
end
|
788
|
+
|
765
789
|
sig { params(constant: Module).returns(T.nilable(String)) }
|
766
790
|
def name_of(constant)
|
767
791
|
name = name_of_proxy_target(constant)
|
768
792
|
return name if name
|
769
793
|
name = raw_name_of(constant)
|
770
794
|
return if name.nil?
|
771
|
-
return unless are_equal?(constant, resolve_constant(name))
|
795
|
+
return unless are_equal?(constant, resolve_constant(name, inherit: true))
|
772
796
|
name = "Struct" if name =~ /^(::)?Struct::[^:]+$/
|
773
797
|
name
|
774
798
|
end
|
@@ -817,6 +841,11 @@ module Tapioca
|
|
817
841
|
constant.to_s.gsub(/\bAttachedClass\b/, "T.attached_class")
|
818
842
|
end
|
819
843
|
|
844
|
+
sig { params(object: Object).returns(T::Boolean).checked(:never) }
|
845
|
+
def object_id_of(object)
|
846
|
+
Object.instance_method(:object_id).bind(object).call
|
847
|
+
end
|
848
|
+
|
820
849
|
sig { params(constant: Module, other: BasicObject).returns(T::Boolean).checked(:never) }
|
821
850
|
def are_equal?(constant, other)
|
822
851
|
BasicObject.instance_method(:equal?).bind(constant).call(other)
|
data/lib/tapioca/gemfile.rb
CHANGED
@@ -17,27 +17,23 @@ module Tapioca
|
|
17
17
|
)
|
18
18
|
end
|
19
19
|
|
20
|
+
sig { returns(Bundler::Definition) }
|
21
|
+
attr_reader(:definition)
|
22
|
+
|
23
|
+
sig { returns(T::Array[Gem]) }
|
24
|
+
attr_reader(:dependencies)
|
25
|
+
|
26
|
+
sig { returns(T::Array[String]) }
|
27
|
+
attr_reader(:missing_specs)
|
28
|
+
|
20
29
|
sig { void }
|
21
30
|
def initialize
|
22
31
|
@gemfile = T.let(File.new(Bundler.default_gemfile), File)
|
23
32
|
@lockfile = T.let(File.new(Bundler.default_lockfile), File)
|
24
|
-
@
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
sig { returns(T::Array[Gem]) }
|
29
|
-
def dependencies
|
30
|
-
@dependencies ||= begin
|
31
|
-
specs = definition.locked_gems.specs.to_a
|
32
|
-
|
33
|
-
definition
|
34
|
-
.resolve
|
35
|
-
.materialize(specs)
|
36
|
-
.map { |spec| Gem.new(spec) }
|
37
|
-
.reject { |gem| gem.ignore?(dir) }
|
38
|
-
.uniq(&:rbi_file_name)
|
39
|
-
.sort_by(&:rbi_file_name)
|
40
|
-
end
|
33
|
+
@definition = T.let(Bundler::Dsl.evaluate(gemfile, lockfile, {}), Bundler::Definition)
|
34
|
+
dependencies, missing_specs = load_dependencies
|
35
|
+
@dependencies = T.let(dependencies, T::Array[Gem])
|
36
|
+
@missing_specs = T.let(missing_specs, T::Array[String])
|
41
37
|
end
|
42
38
|
|
43
39
|
sig { params(gem_name: String).returns(T.nilable(Gem)) }
|
@@ -55,6 +51,23 @@ module Tapioca
|
|
55
51
|
sig { returns(File) }
|
56
52
|
attr_reader(:gemfile, :lockfile)
|
57
53
|
|
54
|
+
sig { returns([T::Array[Gem], T::Array[String]]) }
|
55
|
+
def load_dependencies
|
56
|
+
deps = definition.locked_gems.dependencies.values
|
57
|
+
|
58
|
+
missing_specs = T::Array[String].new
|
59
|
+
|
60
|
+
dependencies = definition
|
61
|
+
.resolve
|
62
|
+
.materialize(deps, missing_specs)
|
63
|
+
.map { |spec| Gem.new(spec) }
|
64
|
+
.reject { |gem| gem.ignore?(dir) }
|
65
|
+
.uniq(&:rbi_file_name)
|
66
|
+
.sort_by(&:rbi_file_name)
|
67
|
+
|
68
|
+
[dependencies, missing_specs]
|
69
|
+
end
|
70
|
+
|
58
71
|
sig { returns(Bundler::Runtime) }
|
59
72
|
def runtime
|
60
73
|
Bundler::Runtime.new(File.dirname(gemfile.path), definition)
|
@@ -65,11 +78,6 @@ module Tapioca
|
|
65
78
|
definition.groups
|
66
79
|
end
|
67
80
|
|
68
|
-
sig { returns(Bundler::Definition) }
|
69
|
-
def definition
|
70
|
-
@definition ||= Bundler::Dsl.evaluate(gemfile, lockfile, {})
|
71
|
-
end
|
72
|
-
|
73
81
|
sig { returns(String) }
|
74
82
|
def dir
|
75
83
|
File.expand_path(gemfile.path + "/..")
|