tapioca 0.9.4 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +21 -0
  3. data/README.md +48 -22
  4. data/lib/tapioca/cli.rb +17 -23
  5. data/lib/tapioca/commands/annotations.rb +2 -2
  6. data/lib/tapioca/commands/dsl.rb +43 -65
  7. data/lib/tapioca/commands/gem.rb +18 -50
  8. data/lib/tapioca/commands/todo.rb +1 -2
  9. data/lib/tapioca/dsl/compiler.rb +34 -37
  10. data/lib/tapioca/dsl/compilers/aasm.rb +7 -3
  11. data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +7 -3
  12. data/lib/tapioca/dsl/compilers/action_mailer.rb +7 -3
  13. data/lib/tapioca/dsl/compilers/active_job.rb +7 -3
  14. data/lib/tapioca/dsl/compilers/active_model_attributes.rb +9 -5
  15. data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +11 -7
  16. data/lib/tapioca/dsl/compilers/active_record_associations.rb +7 -3
  17. data/lib/tapioca/dsl/compilers/active_record_columns.rb +7 -3
  18. data/lib/tapioca/dsl/compilers/active_record_enum.rb +7 -3
  19. data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +8 -4
  20. data/lib/tapioca/dsl/compilers/active_record_relations.rb +7 -3
  21. data/lib/tapioca/dsl/compilers/active_record_scope.rb +5 -3
  22. data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +8 -4
  23. data/lib/tapioca/dsl/compilers/active_resource.rb +7 -3
  24. data/lib/tapioca/dsl/compilers/active_storage.rb +9 -5
  25. data/lib/tapioca/dsl/compilers/active_support_concern.rb +21 -18
  26. data/lib/tapioca/dsl/compilers/active_support_current_attributes.rb +7 -3
  27. data/lib/tapioca/dsl/compilers/config.rb +12 -8
  28. data/lib/tapioca/dsl/compilers/frozen_record.rb +7 -3
  29. data/lib/tapioca/dsl/compilers/graphql_input_object.rb +71 -0
  30. data/lib/tapioca/dsl/compilers/graphql_mutation.rb +81 -0
  31. data/lib/tapioca/dsl/compilers/identity_cache.rb +8 -4
  32. data/lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb +9 -5
  33. data/lib/tapioca/dsl/compilers/protobuf.rb +69 -25
  34. data/lib/tapioca/dsl/compilers/rails_generators.rb +12 -8
  35. data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +7 -3
  36. data/lib/tapioca/dsl/compilers/smart_properties.rb +10 -6
  37. data/lib/tapioca/dsl/compilers/state_machines.rb +7 -3
  38. data/lib/tapioca/dsl/compilers/url_helpers.rb +29 -26
  39. data/lib/tapioca/dsl/compilers.rb +0 -5
  40. data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +1 -9
  41. data/lib/tapioca/dsl/helpers/graphql_type_helper.rb +62 -0
  42. data/lib/tapioca/dsl/pipeline.rb +19 -11
  43. data/lib/tapioca/gem/listeners/source_location.rb +16 -9
  44. data/lib/tapioca/gemfile.rb +30 -0
  45. data/lib/tapioca/helpers/config_helper.rb +2 -2
  46. data/lib/tapioca/helpers/rbi_helper.rb +43 -30
  47. data/lib/tapioca/helpers/source_uri.rb +77 -0
  48. data/lib/tapioca/helpers/test/dsl_compiler.rb +1 -1
  49. data/lib/tapioca/helpers/test/isolation.rb +7 -3
  50. data/lib/tapioca/internal.rb +5 -1
  51. data/lib/tapioca/loaders/dsl.rb +84 -0
  52. data/lib/tapioca/loaders/gem.rb +85 -0
  53. data/lib/tapioca/{runtime → loaders}/loader.rb +39 -31
  54. data/lib/tapioca/repo_index.rb +12 -8
  55. data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +2 -2
  56. data/lib/tapioca/runtime/trackers/constant_definition.rb +15 -13
  57. data/lib/tapioca/runtime/trackers/mixin.rb +35 -31
  58. data/lib/tapioca/runtime/trackers/required_ancestor.rb +21 -19
  59. data/lib/tapioca/static/requires_compiler.rb +2 -3
  60. data/lib/tapioca/static/symbol_table_parser.rb +19 -17
  61. data/lib/tapioca/version.rb +1 -1
  62. data/lib/tapioca.rb +24 -20
  63. metadata +10 -5
  64. data/Gemfile +0 -53
  65. data/Rakefile +0 -18
@@ -136,6 +136,22 @@ module Tapioca
136
136
  extend(T::Sig)
137
137
  include GemHelper
138
138
 
139
+ class << self
140
+ extend T::Sig
141
+
142
+ sig { returns(T::Hash[String, Gemfile::GemSpec]) }
143
+ def spec_lookup_by_file_path
144
+ @lookup ||= T.let(
145
+ [*::Gem::Specification.default_stubs, *::Gem::Specification.stubs]
146
+ .map! { |spec| new(spec.to_spec) }
147
+ .flat_map do |spec|
148
+ spec.files.filter_map { |file| [file.realpath.to_s, spec] if file.exist? }
149
+ end.to_h,
150
+ T.nilable(T::Hash[String, Gemfile::GemSpec])
151
+ )
152
+ end
153
+ end
154
+
139
155
  IGNORED_GEMS = T.let(
140
156
  [
141
157
  "sorbet", "sorbet-static", "sorbet-runtime", "sorbet-static-and-runtime",
@@ -160,6 +176,11 @@ module Tapioca
160
176
  @files = T.let(collect_files, T::Array[Pathname])
161
177
  end
162
178
 
179
+ sig { params(other: BasicObject).returns(T::Boolean) }
180
+ def ==(other)
181
+ GemSpec === other && other.name == name && other.version == version
182
+ end
183
+
163
184
  sig { params(gemfile_dir: String).returns(T::Boolean) }
164
185
  def ignore?(gemfile_dir)
165
186
  gem_ignored? || gem_in_app_dir?(gemfile_dir, full_gem_path)
@@ -211,6 +232,15 @@ module Tapioca
211
232
  rewriter.tree
212
233
  end
213
234
 
235
+ sig { params(file: Pathname).returns(Pathname) }
236
+ def relative_path_for(file)
237
+ if default_gem?
238
+ file.realpath.relative_path_from(RbConfig::CONFIG["rubylibdir"])
239
+ else
240
+ file.realpath.relative_path_from(full_gem_path)
241
+ end
242
+ end
243
+
214
244
  private
215
245
 
216
246
  sig { returns(T::Array[Pathname]) }
@@ -100,7 +100,7 @@ module Tapioca
100
100
  ).returns(T::Array[ConfigError])
101
101
  end
102
102
  def validate_config_options(command_options, config_key, config_options)
103
- config_options.map do |config_option_key, config_option_value|
103
+ config_options.filter_map do |config_option_key, config_option_value|
104
104
  command_option = command_options[config_option_key.to_sym]
105
105
  error_msg = "unknown option `#{config_option_key}` for key `#{config_key}`"
106
106
  next build_error(error_msg) unless command_option
@@ -135,7 +135,7 @@ module Tapioca
135
135
  all_strings = (config_option_value.keys + config_option_value.values).all? { |v| v.is_a?(String) }
136
136
  next build_error(error_msg) unless all_strings
137
137
  end
138
- end.compact
138
+ end
139
139
  end
140
140
 
141
141
  class ConfigErrorMessagePart < T::Struct
@@ -8,6 +8,44 @@ module Tapioca
8
8
  extend SorbetHelper
9
9
  extend self
10
10
 
11
+ class << self
12
+ extend T::Sig
13
+
14
+ sig do
15
+ params(
16
+ type: String,
17
+ variance: Symbol,
18
+ fixed: T.nilable(String),
19
+ upper: T.nilable(String),
20
+ lower: T.nilable(String)
21
+ ).returns(String)
22
+ end
23
+ def serialize_type_variable(type, variance, fixed, upper, lower)
24
+ variance = nil if variance == :invariant
25
+
26
+ bounds = []
27
+ bounds << "fixed: #{fixed}" if fixed
28
+ bounds << "lower: #{lower}" if lower
29
+ bounds << "upper: #{upper}" if upper
30
+
31
+ parameters = []
32
+ block = []
33
+
34
+ parameters << ":#{variance}" if variance
35
+
36
+ if sorbet_supports?(:type_variable_block_syntax)
37
+ block = bounds
38
+ else
39
+ parameters.concat(bounds)
40
+ end
41
+
42
+ serialized = type.dup
43
+ serialized << "(#{parameters.join(", ")})" unless parameters.empty?
44
+ serialized << " { { #{block.join(", ")} } }" unless block.empty?
45
+ serialized
46
+ end
47
+ end
48
+
11
49
  sig { params(name: String, type: String).returns(RBI::TypedParam) }
12
50
  def create_param(name, type:)
13
51
  create_typed_param(RBI::Param.new(name), type)
@@ -57,38 +95,13 @@ module Tapioca
57
95
  .gsub(".params()", "")
58
96
  end
59
97
 
60
- sig do
61
- params(
62
- type: String,
63
- variance: Symbol,
64
- fixed: T.nilable(String),
65
- upper: T.nilable(String),
66
- lower: T.nilable(String)
67
- ).returns(String)
68
- end
69
- def self.serialize_type_variable(type, variance, fixed, upper, lower)
70
- variance = nil if variance == :invariant
71
-
72
- bounds = []
73
- bounds << "fixed: #{fixed}" if fixed
74
- bounds << "lower: #{lower}" if lower
75
- bounds << "upper: #{upper}" if upper
76
-
77
- parameters = []
78
- block = []
79
-
80
- parameters << ":#{variance}" if variance
81
-
82
- if sorbet_supports?(:type_variable_block_syntax)
83
- block = bounds
98
+ sig { params(type: String).returns(String) }
99
+ def as_nilable_type(type)
100
+ if type.start_with?("T.nilable(", "::T.nilable(") || type == "T.untyped" || type == "::T.untyped"
101
+ type
84
102
  else
85
- parameters.concat(bounds)
103
+ "T.nilable(#{type})"
86
104
  end
87
-
88
- serialized = type.dup
89
- serialized << "(#{parameters.join(", ")})" unless parameters.empty?
90
- serialized << " { { #{block.join(", ")} } }" unless block.empty?
91
- serialized
92
105
  end
93
106
 
94
107
  sig { params(name: String).returns(T::Boolean) }
@@ -0,0 +1,77 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require "uri/file"
5
+
6
+ module URI
7
+ class Source < URI::File
8
+ extend T::Sig
9
+
10
+ COMPONENT = T.let([
11
+ :scheme,
12
+ :gem_name,
13
+ :gem_version,
14
+ :path,
15
+ :line_number,
16
+ ].freeze, T::Array[Symbol])
17
+
18
+ alias_method(:gem_name, :host)
19
+ alias_method(:line_number, :fragment)
20
+
21
+ sig { returns(T.nilable(String)) }
22
+ attr_reader :gem_version
23
+
24
+ class << self
25
+ extend T::Sig
26
+
27
+ sig do
28
+ params(
29
+ gem_name: String,
30
+ gem_version: T.nilable(String),
31
+ path: String,
32
+ line_number: T.nilable(String)
33
+ ).returns(URI::Source)
34
+ end
35
+ def build(gem_name:, gem_version:, path:, line_number:)
36
+ super(
37
+ {
38
+ scheme: "source",
39
+ host: gem_name,
40
+ path: DEFAULT_PARSER.escape("/#{gem_version}/#{path}"),
41
+ fragment: line_number,
42
+ }
43
+ )
44
+ end
45
+ end
46
+
47
+ sig { params(v: T.nilable(String)).void }
48
+ def set_path(v) # rubocop:disable Naming/AccessorMethodName
49
+ return if v.nil?
50
+
51
+ @gem_version, @path = v.split("/", 2)
52
+ end
53
+
54
+ sig { params(v: T.nilable(String)).returns(T::Boolean) }
55
+ def check_host(v)
56
+ return true unless v
57
+
58
+ if /[A-Za-z][A-Za-z0-9\-_]*/ !~ v
59
+ raise InvalidComponentError,
60
+ "bad component(expected gem name): #{v}"
61
+ end
62
+
63
+ true
64
+ end
65
+
66
+ sig { returns(String) }
67
+ def to_s
68
+ "source://#{gem_name}/#{gem_version}#{path}##{line_number}"
69
+ end
70
+
71
+ if URI.respond_to?(:register_scheme)
72
+ URI.register_scheme("SOURCE", self)
73
+ else
74
+ @@schemes["SOURCE"] = self
75
+ end
76
+ end
77
+ end
@@ -79,7 +79,7 @@ module Tapioca
79
79
 
80
80
  sig { returns(T::Array[String]) }
81
81
  def gathered_constants
82
- compiler_class.processable_constants.map(&:name).compact.sort
82
+ compiler_class.processable_constants.filter_map(&:name).sort
83
83
  end
84
84
 
85
85
  sig { params(constant_name: T.any(Symbol, String)).returns(String) }
@@ -10,9 +10,13 @@ module Tapioca
10
10
  extend T::Sig
11
11
  require "thread"
12
12
 
13
- sig { returns(T::Boolean) }
14
- def self.forking_env?
15
- !ENV["NO_FORK"] && Process.respond_to?(:fork)
13
+ class << self
14
+ extend T::Sig
15
+
16
+ sig { returns(T::Boolean) }
17
+ def forking_env?
18
+ !ENV["NO_FORK"] && Process.respond_to?(:fork)
19
+ end
16
20
  end
17
21
 
18
22
  def run
@@ -27,7 +27,6 @@ require "yard-sorbet"
27
27
 
28
28
  require "tapioca/runtime/dynamic_mixin_compiler"
29
29
  require "tapioca/helpers/gem_helper"
30
- require "tapioca/runtime/loader"
31
30
 
32
31
  require "tapioca/helpers/sorbet_helper"
33
32
  require "tapioca/helpers/rbi_helper"
@@ -37,6 +36,7 @@ require "tapioca/sorbet_ext/generic_name_patch"
37
36
  require "tapioca/sorbet_ext/proc_bind_patch"
38
37
  require "tapioca/runtime/generic_type_registry"
39
38
 
39
+ require "tapioca/helpers/source_uri"
40
40
  require "tapioca/helpers/cli_helper"
41
41
  require "tapioca/helpers/config_helper"
42
42
  require "tapioca/helpers/rbi_files_helper"
@@ -50,6 +50,10 @@ require "tapioca/static/symbol_table_parser"
50
50
  require "tapioca/static/symbol_loader"
51
51
  require "tapioca/static/requires_compiler"
52
52
 
53
+ require "tapioca/loaders/loader"
54
+ require "tapioca/loaders/gem"
55
+ require "tapioca/loaders/dsl"
56
+
53
57
  require "tapioca/gem"
54
58
  require "tapioca/dsl"
55
59
  require "tapioca/commands"
@@ -0,0 +1,84 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Tapioca
5
+ module Loaders
6
+ class Dsl < Loader
7
+ extend T::Sig
8
+
9
+ class << self
10
+ extend T::Sig
11
+
12
+ sig { params(tapioca_path: String, eager_load: T::Boolean).void }
13
+ def load_application(tapioca_path:, eager_load: true)
14
+ loader = new(tapioca_path: tapioca_path)
15
+ loader.load
16
+ end
17
+ end
18
+
19
+ sig { override.void }
20
+ def load
21
+ load_dsl_extensions
22
+ load_application
23
+ abort_if_pending_migrations!
24
+ load_dsl_compilers
25
+ end
26
+
27
+ protected
28
+
29
+ sig { params(tapioca_path: String, eager_load: T::Boolean).void }
30
+ def initialize(tapioca_path:, eager_load: true)
31
+ super()
32
+
33
+ @tapioca_path = tapioca_path
34
+ @eager_load = eager_load
35
+ end
36
+
37
+ sig { void }
38
+ def load_dsl_extensions
39
+ Dir["#{__dir__}/../dsl/extensions/*.rb"].sort.each { |f| require(f) }
40
+ end
41
+
42
+ sig { void }
43
+ def load_dsl_compilers
44
+ say("Loading DSL compiler classes... ")
45
+
46
+ Dir.glob([
47
+ "#{@tapioca_path}/generators/**/*.rb", # TODO: Here for backcompat, remove later
48
+ "#{@tapioca_path}/compilers/**/*.rb",
49
+ ]).each do |compiler|
50
+ require File.expand_path(compiler)
51
+ end
52
+
53
+ ::Gem.find_files("tapioca/dsl/compilers/*.rb").each do |compiler|
54
+ require File.expand_path(compiler)
55
+ end
56
+
57
+ say("Done", :green)
58
+ end
59
+
60
+ sig { void }
61
+ def load_application
62
+ say("Loading Rails application... ")
63
+
64
+ load_rails_application(
65
+ environment_load: true,
66
+ eager_load: @eager_load
67
+ )
68
+
69
+ say("Done", :green)
70
+ end
71
+
72
+ sig { void }
73
+ def abort_if_pending_migrations!
74
+ return unless File.exist?("config/application.rb")
75
+ return unless defined?(::Rake)
76
+
77
+ Rails.application.load_tasks
78
+ if Rake::Task.task_defined?("db:abort_if_pending_migrations")
79
+ Rake::Task["db:abort_if_pending_migrations"].invoke
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,85 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Tapioca
5
+ module Loaders
6
+ class Gem < Loader
7
+ extend T::Sig
8
+
9
+ class << self
10
+ extend T::Sig
11
+
12
+ sig do
13
+ params(
14
+ bundle: Gemfile,
15
+ prerequire: T.nilable(String),
16
+ postrequire: String,
17
+ default_command: String
18
+ ).void
19
+ end
20
+ def load_application(bundle:, prerequire:, postrequire:, default_command:)
21
+ loader = new(bundle: bundle,
22
+ prerequire: prerequire,
23
+ postrequire: postrequire,
24
+ default_command: default_command)
25
+ loader.load
26
+ end
27
+ end
28
+
29
+ sig { override.void }
30
+ def load
31
+ require_gem_file
32
+ end
33
+
34
+ protected
35
+
36
+ sig do
37
+ params(
38
+ bundle: Gemfile,
39
+ prerequire: T.nilable(String),
40
+ postrequire: String,
41
+ default_command: String
42
+ ).void
43
+ end
44
+ def initialize(bundle:, prerequire:, postrequire:, default_command:)
45
+ super()
46
+
47
+ @bundle = bundle
48
+ @prerequire = prerequire
49
+ @postrequire = postrequire
50
+ @default_command = default_command
51
+ end
52
+
53
+ sig { void }
54
+ def require_gem_file
55
+ say("Requiring all gems to prepare for compiling... ")
56
+ begin
57
+ load_bundle(@bundle, @prerequire, @postrequire)
58
+ rescue LoadError => e
59
+ explain_failed_require(@postrequire, e)
60
+ exit(1)
61
+ end
62
+
63
+ Runtime::Trackers::Autoload.eager_load_all!
64
+
65
+ say(" Done", :green)
66
+ unless @bundle.missing_specs.empty?
67
+ say(" completed with missing specs: ")
68
+ say(@bundle.missing_specs.join(", "), :yellow)
69
+ end
70
+ puts
71
+ end
72
+
73
+ sig { params(file: String, error: LoadError).void }
74
+ def explain_failed_require(file, error)
75
+ say_error("\n\nLoadError: #{error}", :bold, :red)
76
+ say_error("\nTapioca could not load all the gems required by your application.", :yellow)
77
+ say_error("If you populated ", :yellow)
78
+ say_error("#{file} ", :bold, :blue)
79
+ say_error("with ", :yellow)
80
+ say_error("`#{@default_command}`", :bold, :blue)
81
+ say_error("you should probably review it and remove the faulty line.", :yellow)
82
+ end
83
+ end
84
+ end
85
+ end
@@ -1,12 +1,22 @@
1
- # typed: strict
1
+ # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Tapioca
5
- module Runtime
5
+ module Loaders
6
6
  class Loader
7
- extend(T::Sig)
8
- include Tapioca::GemHelper
7
+ extend T::Sig
8
+ extend T::Helpers
9
+
9
10
  include Thor::Base
11
+ include CliHelper
12
+ include Tapioca::GemHelper
13
+
14
+ abstract!
15
+
16
+ sig { abstract.void }
17
+ def load; end
18
+
19
+ private
10
20
 
11
21
  sig do
12
22
  params(gemfile: Tapioca::Gemfile, initialize_file: T.nilable(String), require_file: T.nilable(String)).void
@@ -43,16 +53,27 @@ module Tapioca
43
53
  say("Continuing RBI generation without loading the Rails application.")
44
54
  end
45
55
 
46
- private
47
-
48
- sig { params(file: T.nilable(String)).void }
49
- def require_helper(file)
50
- return unless file
56
+ sig { void }
57
+ def load_rails_engines
58
+ rails_engines.each do |engine|
59
+ errored_files = []
51
60
 
52
- file = File.absolute_path(file)
53
- return unless File.exist?(file)
61
+ engine.config.eager_load_paths.each do |load_path|
62
+ Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
63
+ require(file)
64
+ rescue LoadError, StandardError
65
+ errored_files << file
66
+ end
67
+ end
54
68
 
55
- require(file)
69
+ # Try files that have errored one more time
70
+ # It might have been a load order problem
71
+ errored_files.each do |file|
72
+ require(file)
73
+ rescue LoadError, StandardError
74
+ nil
75
+ end
76
+ end
56
77
  end
57
78
 
58
79
  sig { returns(T::Array[T.untyped]) }
@@ -110,27 +131,14 @@ module Tapioca
110
131
  end
111
132
  end
112
133
 
113
- sig { void }
114
- def load_rails_engines
115
- rails_engines.each do |engine|
116
- errored_files = []
134
+ sig { params(file: T.nilable(String)).void }
135
+ def require_helper(file)
136
+ return unless file
117
137
 
118
- engine.config.eager_load_paths.each do |load_path|
119
- Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
120
- require(file)
121
- rescue LoadError, StandardError
122
- errored_files << file
123
- end
124
- end
138
+ file = File.absolute_path(file)
139
+ return unless File.exist?(file)
125
140
 
126
- # Try files that have errored one more time
127
- # It might have been a load order problem
128
- errored_files.each do |file|
129
- require(file)
130
- rescue LoadError, StandardError
131
- nil
132
- end
133
- end
141
+ require(file)
134
142
  end
135
143
  end
136
144
  end
@@ -6,15 +6,19 @@ module Tapioca
6
6
  extend T::Sig
7
7
  extend T::Generic
8
8
 
9
- sig { params(json: String).returns(RepoIndex) }
10
- def self.from_json(json)
11
- RepoIndex.from_hash(JSON.parse(json))
12
- end
9
+ class << self
10
+ extend T::Sig
11
+
12
+ sig { params(json: String).returns(RepoIndex) }
13
+ def from_json(json)
14
+ RepoIndex.from_hash(JSON.parse(json))
15
+ end
13
16
 
14
- sig { params(hash: T::Hash[String, T::Hash[T.untyped, T.untyped]]).returns(RepoIndex) }
15
- def self.from_hash(hash)
16
- hash.each_with_object(RepoIndex.new) do |(name, _), index|
17
- index << name
17
+ sig { params(hash: T::Hash[String, T::Hash[T.untyped, T.untyped]]).returns(RepoIndex) }
18
+ def from_hash(hash)
19
+ hash.each_with_object(RepoIndex.new) do |(name, _), index|
20
+ index << name
21
+ end
18
22
  end
19
23
  end
20
24
 
@@ -178,7 +178,7 @@ module Tapioca
178
178
 
179
179
  sig { params(tree: RBI::Tree).returns([T::Array[Module], T::Array[Module]]) }
180
180
  def compile_mixes_in_class_methods(tree)
181
- includes = dynamic_includes.map do |mod|
181
+ includes = dynamic_includes.filter_map do |mod|
182
182
  qname = qualified_name_of(mod)
183
183
 
184
184
  next if qname.nil? || qname.empty?
@@ -187,7 +187,7 @@ module Tapioca
187
187
  tree << RBI::Include.new(qname)
188
188
 
189
189
  mod
190
- end.compact
190
+ end
191
191
 
192
192
  # If we can generate multiple mixes_in_class_methods, then we want to use all dynamic extends that are not the
193
193
  # constant itself
@@ -49,22 +49,24 @@ module Tapioca
49
49
  (@class_files[key] ||= Set.new) << loc
50
50
  end
51
51
 
52
- def self.build_constant_location(tp, locations)
53
- file = resolve_loc(caller_locations)
54
- lineno = file == File.realpath(tp.path) ? tp.lineno : 0
52
+ class << self
53
+ def build_constant_location(tp, locations)
54
+ file = resolve_loc(caller_locations)
55
+ lineno = file == File.realpath(tp.path) ? tp.lineno : 0
55
56
 
56
- ConstantLocation.new(path: file, lineno: lineno)
57
- end
57
+ ConstantLocation.new(path: file, lineno: lineno)
58
+ end
58
59
 
59
- # Returns the files in which this class or module was opened. Doesn't know
60
- # about situations where the class was opened prior to +require+ing,
61
- # or where metaprogramming was used via +eval+, etc.
62
- def self.files_for(klass)
63
- locations_for(klass).map(&:path).to_set
64
- end
60
+ # Returns the files in which this class or module was opened. Doesn't know
61
+ # about situations where the class was opened prior to +require+ing,
62
+ # or where metaprogramming was used via +eval+, etc.
63
+ def files_for(klass)
64
+ locations_for(klass).map(&:path).to_set
65
+ end
65
66
 
66
- def self.locations_for(klass)
67
- @class_files.fetch(klass, Set.new)
67
+ def locations_for(klass)
68
+ @class_files.fetch(klass, Set.new)
69
+ end
68
70
  end
69
71
  end
70
72
  end