tapioca 0.16.9 → 0.17.7
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/README.md +21 -0
- data/exe/tapioca +6 -1
- data/lib/ruby_lsp/tapioca/addon.rb +73 -43
- data/lib/ruby_lsp/tapioca/run_gem_rbi_check.rb +43 -43
- data/lib/ruby_lsp/tapioca/server_addon.rb +13 -10
- data/lib/tapioca/bundler_ext/auto_require_hook.rb +6 -14
- data/lib/tapioca/cli.rb +16 -8
- data/lib/tapioca/commands/abstract_dsl.rb +39 -66
- data/lib/tapioca/commands/abstract_gem.rb +25 -46
- data/lib/tapioca/commands/annotations.rb +28 -34
- data/lib/tapioca/commands/check_shims.rb +6 -15
- data/lib/tapioca/commands/command.rb +12 -26
- data/lib/tapioca/commands/command_without_tracker.rb +2 -5
- data/lib/tapioca/commands/configure.rb +11 -16
- data/lib/tapioca/commands/dsl_compiler_list.rb +2 -1
- data/lib/tapioca/commands/dsl_generate.rb +2 -1
- data/lib/tapioca/commands/dsl_verify.rb +2 -1
- data/lib/tapioca/commands/gem_generate.rb +5 -9
- data/lib/tapioca/commands/gem_sync.rb +2 -1
- data/lib/tapioca/commands/gem_verify.rb +3 -2
- data/lib/tapioca/commands/require.rb +3 -7
- data/lib/tapioca/commands/todo.rb +6 -10
- data/lib/tapioca/dsl/compiler.rb +36 -63
- data/lib/tapioca/dsl/compilers/aasm.rb +33 -44
- data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +8 -7
- data/lib/tapioca/dsl/compilers/action_mailer.rb +6 -5
- data/lib/tapioca/dsl/compilers/action_text.rb +6 -5
- data/lib/tapioca/dsl/compilers/active_job.rb +6 -10
- data/lib/tapioca/dsl/compilers/active_model_attributes.rb +10 -11
- data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +5 -6
- data/lib/tapioca/dsl/compilers/active_model_validations_confirmation.rb +5 -12
- data/lib/tapioca/dsl/compilers/active_record_associations.rb +17 -44
- data/lib/tapioca/dsl/compilers/active_record_columns.rb +20 -26
- data/lib/tapioca/dsl/compilers/active_record_delegated_types.rb +9 -8
- data/lib/tapioca/dsl/compilers/active_record_enum.rb +7 -6
- data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +54 -62
- data/lib/tapioca/dsl/compilers/active_record_relations.rb +148 -209
- data/lib/tapioca/dsl/compilers/active_record_scope.rb +8 -13
- data/lib/tapioca/dsl/compilers/active_record_secure_token.rb +5 -4
- data/lib/tapioca/dsl/compilers/active_record_store.rb +5 -4
- data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +19 -28
- data/lib/tapioca/dsl/compilers/active_resource.rb +19 -21
- data/lib/tapioca/dsl/compilers/active_storage.rb +6 -14
- data/lib/tapioca/dsl/compilers/active_support_concern.rb +9 -8
- data/lib/tapioca/dsl/compilers/active_support_current_attributes.rb +8 -7
- data/lib/tapioca/dsl/compilers/active_support_time_ext.rb +5 -4
- data/lib/tapioca/dsl/compilers/config.rb +5 -4
- data/lib/tapioca/dsl/compilers/frozen_record.rb +7 -11
- data/lib/tapioca/dsl/compilers/graphql_input_object.rb +9 -10
- data/lib/tapioca/dsl/compilers/graphql_mutation.rb +6 -10
- data/lib/tapioca/dsl/compilers/identity_cache.rb +11 -39
- data/lib/tapioca/dsl/compilers/json_api_client_resource.rb +9 -18
- data/lib/tapioca/dsl/compilers/kredis.rb +7 -8
- data/lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb +5 -4
- data/lib/tapioca/dsl/compilers/protobuf.rb +13 -26
- data/lib/tapioca/dsl/compilers/rails_generators.rb +9 -11
- data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +23 -13
- data/lib/tapioca/dsl/compilers/smart_properties.rb +32 -38
- data/lib/tapioca/dsl/compilers/state_machines.rb +15 -26
- data/lib/tapioca/dsl/compilers/url_helpers.rb +10 -9
- data/lib/tapioca/dsl/compilers.rb +4 -7
- data/lib/tapioca/dsl/helpers/active_model_type_helper.rb +13 -16
- data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +13 -28
- data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +19 -15
- data/lib/tapioca/dsl/helpers/graphql_type_helper.rb +5 -24
- data/lib/tapioca/dsl/pipeline.rb +30 -58
- data/lib/tapioca/executor.rb +6 -12
- data/lib/tapioca/gem/events.rb +24 -34
- data/lib/tapioca/gem/listeners/base.rb +7 -10
- data/lib/tapioca/gem/listeners/dynamic_mixins.rb +4 -2
- data/lib/tapioca/gem/listeners/foreign_constants.rb +5 -7
- data/lib/tapioca/gem/listeners/methods.rb +36 -47
- data/lib/tapioca/gem/listeners/mixins.rb +6 -18
- data/lib/tapioca/gem/listeners/remove_empty_payload_scopes.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_enums.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_helpers.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_props.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_signatures.rb +7 -5
- data/lib/tapioca/gem/listeners/sorbet_type_variables.rb +6 -4
- data/lib/tapioca/gem/listeners/source_location.rb +15 -8
- data/lib/tapioca/gem/listeners/subconstants.rb +5 -4
- data/lib/tapioca/gem/listeners/yard_doc.rb +30 -23
- data/lib/tapioca/gem/pipeline.rb +107 -91
- data/lib/tapioca/gem_info.rb +1 -1
- data/lib/tapioca/gemfile.rb +64 -73
- data/lib/tapioca/helpers/cli_helper.rb +4 -7
- data/lib/tapioca/helpers/config_helper.rb +17 -29
- data/lib/tapioca/helpers/env_helper.rb +2 -5
- data/lib/tapioca/helpers/gem_helper.rb +5 -5
- data/lib/tapioca/helpers/git_attributes.rb +3 -3
- data/lib/tapioca/helpers/rbi_files_helper.rb +76 -73
- data/lib/tapioca/helpers/rbi_helper.rb +14 -22
- data/lib/tapioca/helpers/sorbet_helper.rb +9 -18
- data/lib/tapioca/helpers/source_uri.rb +15 -25
- data/lib/tapioca/helpers/test/content.rb +7 -10
- data/lib/tapioca/helpers/test/dsl_compiler.rb +20 -33
- data/lib/tapioca/helpers/test/isolation.rb +10 -14
- data/lib/tapioca/helpers/test/template.rb +6 -11
- data/lib/tapioca/internal.rb +18 -8
- data/lib/tapioca/loaders/dsl.rb +11 -19
- data/lib/tapioca/loaders/gem.rb +6 -21
- data/lib/tapioca/loaders/loader.rb +21 -39
- data/lib/tapioca/rbi_ext/model.rb +12 -37
- data/lib/tapioca/rbi_formatter.rb +10 -19
- data/lib/tapioca/rbs/rewriter.rb +55 -0
- data/lib/tapioca/repo_index.rb +7 -9
- data/lib/tapioca/runtime/attached_class_of_32.rb +1 -1
- data/lib/tapioca/runtime/attached_class_of_legacy.rb +2 -5
- data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +23 -23
- data/lib/tapioca/runtime/generic_type_registry.rb +13 -23
- data/lib/tapioca/runtime/reflection.rb +81 -60
- data/lib/tapioca/runtime/source_location.rb +44 -0
- data/lib/tapioca/runtime/trackers/autoload.rb +7 -9
- data/lib/tapioca/runtime/trackers/constant_definition.rb +18 -14
- data/lib/tapioca/runtime/trackers/method_definition.rb +65 -0
- data/lib/tapioca/runtime/trackers/mixin.rb +8 -11
- data/lib/tapioca/runtime/trackers/required_ancestor.rb +3 -3
- data/lib/tapioca/runtime/trackers/tracker.rb +3 -6
- data/lib/tapioca/runtime/trackers.rb +5 -8
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +9 -15
- data/lib/tapioca/sorbet_ext/name_patch.rb +2 -2
- data/lib/tapioca/sorbet_ext/proc_bind_patch.rb +1 -1
- data/lib/tapioca/static/requires_compiler.rb +6 -6
- data/lib/tapioca/static/symbol_loader.rb +14 -16
- data/lib/tapioca/static/symbol_table_parser.rb +8 -8
- data/lib/tapioca/version.rb +1 -1
- data/lib/tapioca.rb +22 -29
- metadata +27 -10
|
@@ -10,12 +10,12 @@ module Tapioca
|
|
|
10
10
|
|
|
11
11
|
NOOP_METHOD = ->(*_args, **_kwargs, &_block) {}
|
|
12
12
|
|
|
13
|
-
@constant_names_registered_for_autoload =
|
|
13
|
+
@constant_names_registered_for_autoload = [] #: Array[String]
|
|
14
14
|
|
|
15
15
|
class << self
|
|
16
16
|
extend T::Sig
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
#: -> void
|
|
19
19
|
def eager_load_all!
|
|
20
20
|
with_disabled_exits do
|
|
21
21
|
until @constant_names_registered_for_autoload.empty?
|
|
@@ -27,18 +27,14 @@ module Tapioca
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
#: (String constant_name) -> void
|
|
31
31
|
def register(constant_name)
|
|
32
32
|
return unless enabled?
|
|
33
33
|
|
|
34
34
|
@constant_names_registered_for_autoload << constant_name
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
type_parameters(:Result)
|
|
39
|
-
.params(block: T.proc.returns(T.type_parameter(:Result)))
|
|
40
|
-
.returns(T.type_parameter(:Result))
|
|
41
|
-
end
|
|
37
|
+
#: [Result] { -> Result } -> Result
|
|
42
38
|
def with_disabled_exits(&block)
|
|
43
39
|
original_abort = Kernel.instance_method(:abort)
|
|
44
40
|
original_exit = Kernel.instance_method(:exit)
|
|
@@ -47,7 +43,9 @@ module Tapioca
|
|
|
47
43
|
Kernel.define_method(:abort, NOOP_METHOD)
|
|
48
44
|
Kernel.define_method(:exit, NOOP_METHOD)
|
|
49
45
|
|
|
50
|
-
|
|
46
|
+
Tapioca.silence_warnings do
|
|
47
|
+
block.call
|
|
48
|
+
end
|
|
51
49
|
ensure
|
|
52
50
|
Kernel.define_method(:exit, original_exit)
|
|
53
51
|
Kernel.define_method(:abort, original_abort)
|
|
@@ -13,12 +13,7 @@ module Tapioca
|
|
|
13
13
|
extend Reflection
|
|
14
14
|
extend T::Sig
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
const :lineno, Integer
|
|
18
|
-
const :path, String
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
@class_files = {}.compare_by_identity
|
|
16
|
+
@class_files = {}.compare_by_identity #: Hash[Module, Set[SourceLocation]]
|
|
22
17
|
|
|
23
18
|
# Immediately activated upon load. Observes class/module definition.
|
|
24
19
|
@class_tracepoint = TracePoint.trace(:class) do |tp|
|
|
@@ -28,14 +23,17 @@ module Tapioca
|
|
|
28
23
|
|
|
29
24
|
path = tp.path
|
|
30
25
|
if File.exist?(path)
|
|
31
|
-
loc =
|
|
26
|
+
loc = build_source_location(tp, caller_locations)
|
|
32
27
|
else
|
|
33
28
|
caller_location = T.must(caller_locations)
|
|
34
29
|
.find { |loc| loc.path && File.exist?(loc.path) }
|
|
35
30
|
|
|
36
31
|
next unless caller_location
|
|
37
32
|
|
|
38
|
-
loc =
|
|
33
|
+
loc = SourceLocation.from_loc([
|
|
34
|
+
caller_location.absolute_path || "",
|
|
35
|
+
caller_location.lineno,
|
|
36
|
+
])
|
|
39
37
|
end
|
|
40
38
|
|
|
41
39
|
(@class_files[key] ||= Set.new) << loc
|
|
@@ -47,31 +45,37 @@ module Tapioca
|
|
|
47
45
|
key = tp.return_value
|
|
48
46
|
next unless Module === key
|
|
49
47
|
|
|
50
|
-
loc =
|
|
48
|
+
loc = build_source_location(tp, caller_locations)
|
|
51
49
|
(@class_files[key] ||= Set.new) << loc
|
|
52
50
|
end
|
|
53
51
|
|
|
54
52
|
class << self
|
|
53
|
+
extend T::Sig
|
|
54
|
+
|
|
55
55
|
def disable!
|
|
56
56
|
@class_tracepoint.disable
|
|
57
57
|
@creturn_tracepoint.disable
|
|
58
58
|
super
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
def
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
def build_source_location(tp, locations)
|
|
62
|
+
loc = resolve_loc(locations)
|
|
63
|
+
file = loc&.file
|
|
64
|
+
line = loc&.line
|
|
65
|
+
lineno = file && File.identical?(file, tp.path) ? tp.lineno : (line || 0)
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
SourceLocation.from_loc([file || "", lineno])
|
|
66
68
|
end
|
|
67
69
|
|
|
68
70
|
# Returns the files in which this class or module was opened. Doesn't know
|
|
69
71
|
# about situations where the class was opened prior to +require+ing,
|
|
70
72
|
# or where metaprogramming was used via +eval+, etc.
|
|
73
|
+
#: (Module klass) -> Set[String]
|
|
71
74
|
def files_for(klass)
|
|
72
|
-
locations_for(klass).map(&:
|
|
75
|
+
locations_for(klass).map(&:file).to_set
|
|
73
76
|
end
|
|
74
77
|
|
|
78
|
+
#: (Module klass) -> Set[SourceLocation]
|
|
75
79
|
def locations_for(klass)
|
|
76
80
|
@class_files.fetch(klass, Set.new)
|
|
77
81
|
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Tapioca
|
|
5
|
+
module Runtime
|
|
6
|
+
module Trackers
|
|
7
|
+
module MethodDefinition
|
|
8
|
+
extend Tracker
|
|
9
|
+
extend T::Sig
|
|
10
|
+
|
|
11
|
+
@method_definitions = {}.compare_by_identity #: Hash[Module, Hash[Symbol, Array[SourceLocation]]]
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
#: (Symbol method_name, Module owner, Array[Thread::Backtrace::Location] locations) -> void
|
|
15
|
+
def register(method_name, owner, locations)
|
|
16
|
+
return unless enabled?
|
|
17
|
+
# If Sorbet runtime is redefining a method, it sets this to true.
|
|
18
|
+
# In those cases, we should skip the registration, as the method's original
|
|
19
|
+
# definition should already be registered.
|
|
20
|
+
return if T::Private::DeclState.current.skip_on_method_added
|
|
21
|
+
|
|
22
|
+
loc = Reflection.resolve_loc(locations)
|
|
23
|
+
return unless loc
|
|
24
|
+
|
|
25
|
+
registrations_for(method_name, owner) << loc
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
#: (Symbol method_name, Module owner) -> Array[SourceLocation]
|
|
29
|
+
def method_definitions_for(method_name, owner)
|
|
30
|
+
definitions = registrations_for(method_name, owner)
|
|
31
|
+
|
|
32
|
+
if definitions.empty?
|
|
33
|
+
source_loc = owner.instance_method(method_name).source_location
|
|
34
|
+
definitions = [SourceLocation.from_loc(source_loc)].compact
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
definitions
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
#: (Symbol method_name, Module owner) -> Array[SourceLocation]
|
|
43
|
+
def registrations_for(method_name, owner)
|
|
44
|
+
owner_lookup = (@method_definitions[owner] ||= {})
|
|
45
|
+
owner_lookup[method_name] ||= []
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class Module
|
|
54
|
+
prepend(Module.new do
|
|
55
|
+
def singleton_method_added(method_name)
|
|
56
|
+
Tapioca::Runtime::Trackers::MethodDefinition.register(method_name, singleton_class, Kernel.caller_locations)
|
|
57
|
+
super
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def method_added(method_name)
|
|
61
|
+
Tapioca::Runtime::Trackers::MethodDefinition.register(method_name, self, Kernel.caller_locations)
|
|
62
|
+
super
|
|
63
|
+
end
|
|
64
|
+
end)
|
|
65
|
+
end
|
|
@@ -22,22 +22,19 @@ module Tapioca
|
|
|
22
22
|
class << self
|
|
23
23
|
extend T::Sig
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
type_parameters(:Result)
|
|
27
|
-
.params(block: T.proc.returns(T.type_parameter(:Result)))
|
|
28
|
-
.returns(T.type_parameter(:Result))
|
|
29
|
-
end
|
|
25
|
+
#: [Result] { -> Result } -> Result
|
|
30
26
|
def with_disabled_registration(&block)
|
|
31
27
|
with_disabled_tracker(&block)
|
|
32
28
|
end
|
|
33
29
|
|
|
34
|
-
|
|
30
|
+
#: (Module constant, Module mixin, Type mixin_type) -> void
|
|
35
31
|
def register(constant, mixin, mixin_type)
|
|
36
32
|
return unless enabled?
|
|
37
33
|
|
|
38
34
|
location = Reflection.resolve_loc(caller_locations)
|
|
35
|
+
return unless location
|
|
39
36
|
|
|
40
|
-
register_with_location(constant, mixin, mixin_type, location)
|
|
37
|
+
register_with_location(constant, mixin, mixin_type, location.file)
|
|
41
38
|
end
|
|
42
39
|
|
|
43
40
|
def resolve_to_attached_class(constant, mixin, mixin_type)
|
|
@@ -52,19 +49,19 @@ module Tapioca
|
|
|
52
49
|
attached_class
|
|
53
50
|
end
|
|
54
51
|
|
|
55
|
-
|
|
52
|
+
#: (Module mixin) -> Hash[Type, Hash[Module, String]]
|
|
56
53
|
def constants_with_mixin(mixin)
|
|
57
54
|
find_or_initialize_mixin_lookup(mixin)
|
|
58
55
|
end
|
|
59
56
|
|
|
60
|
-
|
|
57
|
+
#: (Module mixin, Type mixin_type, Module constant) -> String?
|
|
61
58
|
def mixin_location(mixin, mixin_type, constant)
|
|
62
59
|
find_or_initialize_mixin_lookup(mixin).dig(mixin_type, constant)
|
|
63
60
|
end
|
|
64
61
|
|
|
65
62
|
private
|
|
66
63
|
|
|
67
|
-
|
|
64
|
+
#: (Module constant, Module mixin, Type mixin_type, String location) -> void
|
|
68
65
|
def register_with_location(constant, mixin, mixin_type, location)
|
|
69
66
|
return unless @enabled
|
|
70
67
|
|
|
@@ -72,7 +69,7 @@ module Tapioca
|
|
|
72
69
|
constants.fetch(mixin_type).store(constant, location)
|
|
73
70
|
end
|
|
74
71
|
|
|
75
|
-
|
|
72
|
+
#: (Module mixin) -> Hash[Type, Hash[Module, String]]
|
|
76
73
|
def find_or_initialize_mixin_lookup(mixin)
|
|
77
74
|
@mixins_to_constants[mixin] ||= {
|
|
78
75
|
Type::Prepend => {}.compare_by_identity,
|
|
@@ -11,7 +11,7 @@ module Tapioca
|
|
|
11
11
|
class << self
|
|
12
12
|
extend T::Sig
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
#: (T::Helpers requiring, ^-> void block) -> void
|
|
15
15
|
def register(requiring, block)
|
|
16
16
|
return unless enabled?
|
|
17
17
|
|
|
@@ -19,12 +19,12 @@ module Tapioca
|
|
|
19
19
|
ancestors << block
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
#: (Module mod) -> Array[^-> void]
|
|
23
23
|
def required_ancestors_blocks_by(mod)
|
|
24
24
|
@required_ancestors_map[mod] || []
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
#: (Module mod) -> Array[untyped]
|
|
28
28
|
def required_ancestors_by(mod)
|
|
29
29
|
blocks = required_ancestors_blocks_by(mod)
|
|
30
30
|
blocks.map do |block|
|
|
@@ -4,16 +4,13 @@
|
|
|
4
4
|
module Tapioca
|
|
5
5
|
module Runtime
|
|
6
6
|
module Trackers
|
|
7
|
+
# @abstract
|
|
7
8
|
module Tracker
|
|
8
9
|
extend T::Sig
|
|
9
|
-
extend T::Helpers
|
|
10
|
-
|
|
11
|
-
abstract!
|
|
12
|
-
|
|
13
10
|
class << self
|
|
14
11
|
extend T::Sig
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
#: ((Tracker & Module) base) -> void
|
|
17
14
|
def extended(base)
|
|
18
15
|
Trackers.register_tracker(base)
|
|
19
16
|
base.instance_exec do
|
|
@@ -22,7 +19,7 @@ module Tapioca
|
|
|
22
19
|
end
|
|
23
20
|
end
|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
#: -> void
|
|
26
23
|
def disable!
|
|
27
24
|
@enabled = false
|
|
28
25
|
end
|
|
@@ -8,16 +8,12 @@ module Tapioca
|
|
|
8
8
|
module Trackers
|
|
9
9
|
extend T::Sig
|
|
10
10
|
|
|
11
|
-
@trackers =
|
|
11
|
+
@trackers = [] #: Array[Tracker]
|
|
12
12
|
|
|
13
13
|
class << self
|
|
14
14
|
extend T::Sig
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
type_parameters(:Return)
|
|
18
|
-
.params(blk: T.proc.returns(T.type_parameter(:Return)))
|
|
19
|
-
.returns(T.type_parameter(:Return))
|
|
20
|
-
end
|
|
16
|
+
#: [Return] { -> Return } -> Return
|
|
21
17
|
def with_trackers_enabled(&blk)
|
|
22
18
|
# Currently this is a dirty hack to ensure disabling trackers
|
|
23
19
|
# doesn't work while in the block passed to this method.
|
|
@@ -30,12 +26,12 @@ module Tapioca
|
|
|
30
26
|
end
|
|
31
27
|
end
|
|
32
28
|
|
|
33
|
-
|
|
29
|
+
#: -> void
|
|
34
30
|
def disable_all!
|
|
35
31
|
@trackers.each(&:disable!)
|
|
36
32
|
end
|
|
37
33
|
|
|
38
|
-
|
|
34
|
+
#: (Tracker tracker) -> void
|
|
39
35
|
def register_tracker(tracker)
|
|
40
36
|
@trackers << tracker
|
|
41
37
|
end
|
|
@@ -56,3 +52,4 @@ require "tapioca/runtime/trackers/mixin"
|
|
|
56
52
|
require "tapioca/runtime/trackers/constant_definition"
|
|
57
53
|
require "tapioca/runtime/trackers/autoload"
|
|
58
54
|
require "tapioca/runtime/trackers/required_ancestor"
|
|
55
|
+
require "tapioca/runtime/trackers/method_definition"
|
|
@@ -130,19 +130,12 @@ module Tapioca
|
|
|
130
130
|
end
|
|
131
131
|
end
|
|
132
132
|
|
|
133
|
-
DEFAULT_BOUNDS_PROC =
|
|
133
|
+
DEFAULT_BOUNDS_PROC = -> { {} } #: ^-> Hash[Symbol, untyped]
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
#: Type
|
|
136
136
|
attr_reader :type
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
params(
|
|
140
|
-
context: Module,
|
|
141
|
-
type: Type,
|
|
142
|
-
variance: Symbol,
|
|
143
|
-
bounds_proc: T.nilable(T.proc.returns(T::Hash[Symbol, T.untyped])),
|
|
144
|
-
).void
|
|
145
|
-
end
|
|
138
|
+
#: (Module context, Type type, Symbol variance, (^-> Hash[Symbol, untyped])? bounds_proc) -> void
|
|
146
139
|
def initialize(context, type, variance, bounds_proc)
|
|
147
140
|
@context = context
|
|
148
141
|
@type = type
|
|
@@ -151,18 +144,19 @@ module Tapioca
|
|
|
151
144
|
|
|
152
145
|
super()
|
|
153
146
|
end
|
|
154
|
-
|
|
147
|
+
|
|
148
|
+
#: -> String?
|
|
155
149
|
def name
|
|
156
150
|
constant_name = super
|
|
157
151
|
constant_name&.split("::")&.last
|
|
158
152
|
end
|
|
159
153
|
|
|
160
|
-
|
|
154
|
+
#: -> bool
|
|
161
155
|
def fixed?
|
|
162
156
|
bounds.key?(:fixed)
|
|
163
157
|
end
|
|
164
158
|
|
|
165
|
-
|
|
159
|
+
#: -> String
|
|
166
160
|
def serialize
|
|
167
161
|
fixed = bounds[:fixed].to_s if fixed?
|
|
168
162
|
lower = bounds[:lower].to_s if bounds.key?(:lower)
|
|
@@ -177,14 +171,14 @@ module Tapioca
|
|
|
177
171
|
)
|
|
178
172
|
end
|
|
179
173
|
|
|
180
|
-
|
|
174
|
+
#: -> Tapioca::TypeVariable
|
|
181
175
|
def coerce_to_type_variable
|
|
182
176
|
TypeVariable.new(name, @variance)
|
|
183
177
|
end
|
|
184
178
|
|
|
185
179
|
private
|
|
186
180
|
|
|
187
|
-
|
|
181
|
+
#: -> Hash[Symbol, untyped]
|
|
188
182
|
def bounds
|
|
189
183
|
@bounds ||= @bounds_proc.call
|
|
190
184
|
end
|
|
@@ -5,7 +5,7 @@ module T
|
|
|
5
5
|
module Types
|
|
6
6
|
class Simple
|
|
7
7
|
module NamePatch
|
|
8
|
-
NAME_METHOD =
|
|
8
|
+
NAME_METHOD = Module.instance_method(:name) #: UnboundMethod
|
|
9
9
|
|
|
10
10
|
def name
|
|
11
11
|
# Sorbet memoizes this method into the `@name` instance variable but
|
|
@@ -16,7 +16,7 @@ module T
|
|
|
16
16
|
def qualified_name_of(constant)
|
|
17
17
|
name = NAME_METHOD.bind_call(constant)
|
|
18
18
|
name = nil if name&.start_with?("#<")
|
|
19
|
-
return if name.nil?
|
|
19
|
+
return "::T.untyped" if name.nil?
|
|
20
20
|
|
|
21
21
|
if name.start_with?("::")
|
|
22
22
|
name
|
|
@@ -6,12 +6,12 @@ module Tapioca
|
|
|
6
6
|
class RequiresCompiler
|
|
7
7
|
extend T::Sig
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
#: (String sorbet_path) -> void
|
|
10
10
|
def initialize(sorbet_path)
|
|
11
11
|
@sorbet_path = sorbet_path
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
#: -> String
|
|
15
15
|
def compile
|
|
16
16
|
config = Spoom::Sorbet::Config.parse_file(@sorbet_path)
|
|
17
17
|
files = collect_files(config)
|
|
@@ -25,7 +25,7 @@ module Tapioca
|
|
|
25
25
|
|
|
26
26
|
private
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
#: (Spoom::Sorbet::Config config) -> Array[String]
|
|
29
29
|
def collect_files(config)
|
|
30
30
|
config.paths.flat_map do |path|
|
|
31
31
|
path = (Pathname.new(@sorbet_path) / "../.." / path).cleanpath
|
|
@@ -40,14 +40,14 @@ module Tapioca
|
|
|
40
40
|
end.sort.uniq
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
#: (String file_path) -> T::Enumerable[String]
|
|
44
44
|
def collect_requires(file_path)
|
|
45
45
|
File.binread(file_path).lines.filter_map do |line|
|
|
46
46
|
/^\s*require\s*(\(\s*)?['"](?<name>[^'"]+)['"](\s*\))?/.match(line) { |m| m["name"] }
|
|
47
47
|
end.reject { |require| require.include?('#{') } # ignore interpolation
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
#: (Spoom::Sorbet::Config config, Pathname file_path) -> bool
|
|
51
51
|
def file_ignored_by_sorbet?(config, file_path)
|
|
52
52
|
file_path_parts = path_parts(file_path)
|
|
53
53
|
|
|
@@ -76,7 +76,7 @@ module Tapioca
|
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
#: (Pathname path) -> Array[String]
|
|
80
80
|
def path_parts(path)
|
|
81
81
|
T.unsafe(path).descend.map { |part| part.basename.to_s }
|
|
82
82
|
end
|
|
@@ -9,17 +9,17 @@ module Tapioca
|
|
|
9
9
|
include SorbetHelper
|
|
10
10
|
include Runtime::Reflection
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
#: -> Set[String]
|
|
13
13
|
def payload_symbols
|
|
14
14
|
unless @payload_symbols
|
|
15
15
|
output = symbol_table_json_from("-e ''", table_type: "symbol-table-full-json")
|
|
16
|
-
@payload_symbols =
|
|
16
|
+
@payload_symbols = SymbolTableParser.parse_json(output) #: Set[String]?
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
T.must(@payload_symbols)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
#: (Gemfile::GemSpec gem) -> Set[String]
|
|
23
23
|
def engine_symbols(gem)
|
|
24
24
|
gem_engine = engines.find do |engine|
|
|
25
25
|
gem.full_gem_path == engine.config.root.to_s
|
|
@@ -44,12 +44,12 @@ module Tapioca
|
|
|
44
44
|
Set.new
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
#: (Gemfile::GemSpec gem) -> Set[String]
|
|
48
48
|
def gem_symbols(gem)
|
|
49
49
|
symbols_from_paths(gem.files)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
#: (Array[Pathname] paths) -> Set[String]
|
|
53
53
|
def symbols_from_paths(paths)
|
|
54
54
|
return Set.new if paths.empty?
|
|
55
55
|
|
|
@@ -67,20 +67,18 @@ module Tapioca
|
|
|
67
67
|
|
|
68
68
|
private
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
# @without_runtime
|
|
71
|
+
#: -> Array[singleton(Rails::Engine)]
|
|
71
72
|
def engines
|
|
72
|
-
@engines ||=
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
end,
|
|
79
|
-
T.nilable(T::Array[T.class_of(Rails::Engine)]),
|
|
80
|
-
)
|
|
73
|
+
@engines ||= if Object.const_defined?("Rails::Engine")
|
|
74
|
+
descendants_of(Object.const_get("Rails::Engine"))
|
|
75
|
+
.reject(&:abstract_railtie?)
|
|
76
|
+
else
|
|
77
|
+
[]
|
|
78
|
+
end #: Array[singleton(Rails::Engine)]?
|
|
81
79
|
end
|
|
82
80
|
|
|
83
|
-
|
|
81
|
+
#: (String input, ?table_type: String) -> String
|
|
84
82
|
def symbol_table_json_from(input, table_type: "symbol-table-json")
|
|
85
83
|
sorbet("--no-config", "--quiet", "--print=#{table_type}", input).out
|
|
86
84
|
end
|
|
@@ -6,12 +6,12 @@ module Tapioca
|
|
|
6
6
|
class SymbolTableParser
|
|
7
7
|
extend T::Sig
|
|
8
8
|
|
|
9
|
-
SKIP_PARSE_KINDS =
|
|
9
|
+
SKIP_PARSE_KINDS = ["CLASS_OR_MODULE", "STATIC_FIELD"].freeze #: Array[String]
|
|
10
10
|
|
|
11
11
|
class << self
|
|
12
12
|
extend T::Sig
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
#: (String json_string) -> Set[String]
|
|
15
15
|
def parse_json(json_string)
|
|
16
16
|
obj = JSON.parse(json_string)
|
|
17
17
|
|
|
@@ -23,16 +23,16 @@ module Tapioca
|
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
#: Set[String]
|
|
27
27
|
attr_reader :symbols
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
#: -> void
|
|
30
30
|
def initialize
|
|
31
|
-
@symbols =
|
|
32
|
-
@parents =
|
|
31
|
+
@symbols = Set.new #: Set[String]
|
|
32
|
+
@parents = [] #: Array[String]
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
#: (Hash[String, untyped] object) -> void
|
|
36
36
|
def parse_object(object)
|
|
37
37
|
children = object.fetch("children", [])
|
|
38
38
|
|
|
@@ -61,7 +61,7 @@ module Tapioca
|
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
#: (String name) -> String
|
|
65
65
|
def fully_qualified_name(name)
|
|
66
66
|
[*@parents, name].join("::")
|
|
67
67
|
end
|
data/lib/tapioca/version.rb
CHANGED