tapioca 0.5.0 → 0.5.4
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 +1 -1
- data/lib/tapioca/cli.rb +55 -139
- data/lib/tapioca/compilers/dsl/active_model_secure_password.rb +101 -0
- data/lib/tapioca/compilers/dsl/active_record_fixtures.rb +86 -0
- data/lib/tapioca/compilers/dsl/active_support_concern.rb +0 -2
- data/lib/tapioca/compilers/dsl/base.rb +12 -0
- data/lib/tapioca/compilers/dsl/mixed_in_class_attributes.rb +74 -0
- data/lib/tapioca/compilers/dsl/smart_properties.rb +4 -4
- data/lib/tapioca/compilers/dsl_compiler.rb +7 -6
- data/lib/tapioca/compilers/dynamic_mixin_compiler.rb +198 -0
- data/lib/tapioca/compilers/sorbet.rb +0 -1
- data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +84 -153
- data/lib/tapioca/compilers/symbol_table_compiler.rb +5 -11
- data/lib/tapioca/config.rb +1 -0
- data/lib/tapioca/config_builder.rb +1 -0
- data/lib/tapioca/gemfile.rb +11 -5
- data/lib/tapioca/generators/base.rb +61 -0
- data/lib/tapioca/generators/dsl.rb +362 -0
- data/lib/tapioca/generators/gem.rb +345 -0
- data/lib/tapioca/generators/init.rb +79 -0
- data/lib/tapioca/generators/require.rb +52 -0
- data/lib/tapioca/generators/todo.rb +76 -0
- data/lib/tapioca/generators.rb +9 -0
- data/lib/tapioca/internal.rb +1 -2
- data/lib/tapioca/loader.rb +2 -2
- data/lib/tapioca/rbi_ext/model.rb +44 -0
- data/lib/tapioca/reflection.rb +8 -1
- data/lib/tapioca/version.rb +1 -1
- data/lib/tapioca.rb +2 -0
- metadata +16 -6
- data/lib/tapioca/generator.rb +0 -717
@@ -0,0 +1,79 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Tapioca
|
5
|
+
module Generators
|
6
|
+
class Init < Base
|
7
|
+
sig do
|
8
|
+
params(
|
9
|
+
sorbet_config: String,
|
10
|
+
default_postrequire: String,
|
11
|
+
default_command: String,
|
12
|
+
file_writer: Thor::Actions
|
13
|
+
).void
|
14
|
+
end
|
15
|
+
def initialize(sorbet_config:, default_postrequire:, default_command:, file_writer: FileWriter.new)
|
16
|
+
@sorbet_config = sorbet_config
|
17
|
+
@default_postrequire = default_postrequire
|
18
|
+
|
19
|
+
super(default_command: default_command, file_writer: file_writer)
|
20
|
+
|
21
|
+
@installer = T.let(nil, T.nilable(Bundler::Installer))
|
22
|
+
@spec = T.let(nil, T.nilable(Bundler::StubSpecification))
|
23
|
+
end
|
24
|
+
|
25
|
+
sig { override.void }
|
26
|
+
def generate
|
27
|
+
create_config
|
28
|
+
create_post_require
|
29
|
+
if File.exist?(@default_command)
|
30
|
+
generate_binstub!
|
31
|
+
else
|
32
|
+
generate_binstub
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
sig { void }
|
39
|
+
def create_config
|
40
|
+
create_file(@sorbet_config, <<~CONTENT, skip: true, force: false)
|
41
|
+
--dir
|
42
|
+
.
|
43
|
+
CONTENT
|
44
|
+
end
|
45
|
+
|
46
|
+
sig { void }
|
47
|
+
def create_post_require
|
48
|
+
create_file(@default_postrequire, <<~CONTENT, skip: true, force: false)
|
49
|
+
# typed: true
|
50
|
+
# frozen_string_literal: true
|
51
|
+
|
52
|
+
# Add your extra requires here (`#{@default_command} require` can be used to boostrap this list)
|
53
|
+
CONTENT
|
54
|
+
end
|
55
|
+
|
56
|
+
sig { void }
|
57
|
+
def generate_binstub!
|
58
|
+
installer.generate_bundler_executable_stubs(spec, { force: true })
|
59
|
+
say_status(:force, @default_command, :yellow)
|
60
|
+
end
|
61
|
+
|
62
|
+
sig { void }
|
63
|
+
def generate_binstub
|
64
|
+
installer.generate_bundler_executable_stubs(spec)
|
65
|
+
say_status(:create, @default_command, :green)
|
66
|
+
end
|
67
|
+
|
68
|
+
sig { returns(Bundler::Installer) }
|
69
|
+
def installer
|
70
|
+
@installer ||= Bundler::Installer.new(Bundler.root, Bundler.definition)
|
71
|
+
end
|
72
|
+
|
73
|
+
sig { returns(Bundler::StubSpecification) }
|
74
|
+
def spec
|
75
|
+
@spec ||= Bundler.definition.specs.find { |s| s.name == "tapioca" }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Tapioca
|
5
|
+
module Generators
|
6
|
+
class Require < Base
|
7
|
+
sig do
|
8
|
+
params(
|
9
|
+
requires_path: String,
|
10
|
+
sorbet_config_path: String,
|
11
|
+
default_command: String,
|
12
|
+
file_writer: Thor::Actions
|
13
|
+
).void
|
14
|
+
end
|
15
|
+
def initialize(requires_path:, sorbet_config_path:, default_command:, file_writer: FileWriter.new)
|
16
|
+
@requires_path = requires_path
|
17
|
+
@sorbet_config_path = sorbet_config_path
|
18
|
+
|
19
|
+
super(default_command: default_command, file_writer: file_writer)
|
20
|
+
end
|
21
|
+
|
22
|
+
sig { override.void }
|
23
|
+
def generate
|
24
|
+
compiler = Compilers::RequiresCompiler.new(@sorbet_config_path)
|
25
|
+
name = set_color(@requires_path, :yellow, :bold)
|
26
|
+
say("Compiling #{name}, this may take a few seconds... ")
|
27
|
+
|
28
|
+
rb_string = compiler.compile
|
29
|
+
if rb_string.empty?
|
30
|
+
say("Nothing to do", :green)
|
31
|
+
return
|
32
|
+
end
|
33
|
+
|
34
|
+
# Clean all existing requires before regenerating the list so we update
|
35
|
+
# it with the new one found in the client code and remove the old ones.
|
36
|
+
File.delete(@requires_path) if File.exist?(@requires_path)
|
37
|
+
|
38
|
+
content = +"# typed: true\n"
|
39
|
+
content << "# frozen_string_literal: true\n\n"
|
40
|
+
content << rb_string
|
41
|
+
|
42
|
+
create_file(@requires_path, content, verbose: false)
|
43
|
+
|
44
|
+
say("Done", :green)
|
45
|
+
|
46
|
+
say("All requires from this application have been written to #{name}.", [:green, :bold])
|
47
|
+
cmd = set_color("#{@default_command} gem", :yellow, :bold)
|
48
|
+
say("Please review changes and commit them, then run `#{cmd}`.", [:green, :bold])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Tapioca
|
5
|
+
module Generators
|
6
|
+
class Todo < Base
|
7
|
+
sig do
|
8
|
+
params(
|
9
|
+
todos_path: String,
|
10
|
+
file_header: T::Boolean,
|
11
|
+
default_command: String,
|
12
|
+
file_writer: Thor::Actions
|
13
|
+
).void
|
14
|
+
end
|
15
|
+
def initialize(todos_path:, file_header:, default_command:, file_writer: FileWriter.new)
|
16
|
+
@todos_path = todos_path
|
17
|
+
@file_header = file_header
|
18
|
+
|
19
|
+
super(default_command: default_command, file_writer: file_writer)
|
20
|
+
end
|
21
|
+
|
22
|
+
sig { override.void }
|
23
|
+
def generate
|
24
|
+
compiler = Compilers::TodosCompiler.new
|
25
|
+
say("Finding all unresolved constants, this may take a few seconds... ")
|
26
|
+
|
27
|
+
# Clean all existing unresolved constants before regenerating the list
|
28
|
+
# so Sorbet won't grab them as already resolved.
|
29
|
+
File.delete(@todos_path) if File.exist?(@todos_path)
|
30
|
+
|
31
|
+
rbi_string = compiler.compile
|
32
|
+
if rbi_string.empty?
|
33
|
+
say("Nothing to do", :green)
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
content = String.new
|
38
|
+
content << rbi_header(
|
39
|
+
"#{@default_command} todo",
|
40
|
+
reason: "unresolved constants",
|
41
|
+
strictness: "false"
|
42
|
+
)
|
43
|
+
content << rbi_string
|
44
|
+
content << "\n"
|
45
|
+
|
46
|
+
say("Done", :green)
|
47
|
+
create_file(@todos_path, content, verbose: false)
|
48
|
+
|
49
|
+
name = set_color(@todos_path, :yellow, :bold)
|
50
|
+
say("\nAll unresolved constants have been written to #{name}.", [:green, :bold])
|
51
|
+
say("Please review changes and commit them.", [:green, :bold])
|
52
|
+
end
|
53
|
+
|
54
|
+
sig { params(command: String, reason: T.nilable(String), strictness: T.nilable(String)).returns(String) }
|
55
|
+
def rbi_header(command, reason: nil, strictness: nil)
|
56
|
+
statement = <<~HEAD
|
57
|
+
# DO NOT EDIT MANUALLY
|
58
|
+
# This is an autogenerated file for #{reason}.
|
59
|
+
# Please instead update this file by running `#{command}`.
|
60
|
+
HEAD
|
61
|
+
|
62
|
+
sigil = <<~SIGIL if strictness
|
63
|
+
# typed: #{strictness}
|
64
|
+
SIGIL
|
65
|
+
|
66
|
+
if @file_header
|
67
|
+
[statement, sigil].compact.join("\n").strip.concat("\n\n")
|
68
|
+
elsif sigil
|
69
|
+
sigil.strip.concat("\n\n")
|
70
|
+
else
|
71
|
+
""
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "generators/base"
|
5
|
+
require_relative "generators/dsl"
|
6
|
+
require_relative "generators/init"
|
7
|
+
require_relative "generators/gem"
|
8
|
+
require_relative "generators/require"
|
9
|
+
require_relative "generators/todo"
|
data/lib/tapioca/internal.rb
CHANGED
@@ -3,13 +3,12 @@
|
|
3
3
|
|
4
4
|
require "tapioca"
|
5
5
|
require "tapioca/loader"
|
6
|
-
require "tapioca/constant_locator"
|
7
6
|
require "tapioca/sorbet_ext/generic_name_patch"
|
8
7
|
require "tapioca/sorbet_ext/fixed_hash_patch"
|
9
8
|
require "tapioca/generic_type_registry"
|
10
9
|
require "tapioca/config"
|
11
10
|
require "tapioca/config_builder"
|
12
|
-
require "tapioca/
|
11
|
+
require "tapioca/generators"
|
13
12
|
require "tapioca/cli"
|
14
13
|
require "tapioca/gemfile"
|
15
14
|
require "tapioca/compilers/sorbet"
|
data/lib/tapioca/loader.rb
CHANGED
@@ -9,10 +9,10 @@ module Tapioca
|
|
9
9
|
def load_bundle(gemfile, initialize_file, require_file)
|
10
10
|
require_helper(initialize_file)
|
11
11
|
|
12
|
-
gemfile.require_bundle
|
13
|
-
|
14
12
|
load_rails_application
|
15
13
|
|
14
|
+
gemfile.require_bundle
|
15
|
+
|
16
16
|
require_helper(require_file)
|
17
17
|
|
18
18
|
load_rails_engines
|
@@ -4,6 +4,50 @@
|
|
4
4
|
require "rbi"
|
5
5
|
|
6
6
|
module RBI
|
7
|
+
class File
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { returns(String) }
|
11
|
+
def transformed_string
|
12
|
+
transform_rbi!
|
13
|
+
string
|
14
|
+
end
|
15
|
+
|
16
|
+
sig { void }
|
17
|
+
def transform_rbi!
|
18
|
+
root.nest_singleton_methods!
|
19
|
+
root.nest_non_public_methods!
|
20
|
+
root.group_nodes!
|
21
|
+
root.sort_nodes!
|
22
|
+
end
|
23
|
+
|
24
|
+
sig do
|
25
|
+
params(
|
26
|
+
command: String,
|
27
|
+
reason: T.nilable(String),
|
28
|
+
display_heading: T::Boolean
|
29
|
+
).void
|
30
|
+
end
|
31
|
+
def set_file_header(command, reason: nil, display_heading: true)
|
32
|
+
return unless display_heading
|
33
|
+
comments << RBI::Comment.new("DO NOT EDIT MANUALLY")
|
34
|
+
comments << RBI::Comment.new("This is an autogenerated file for #{reason}.") unless reason.nil?
|
35
|
+
comments << RBI::Comment.new("Please instead update this file by running `#{command}`.")
|
36
|
+
end
|
37
|
+
|
38
|
+
sig { void }
|
39
|
+
def set_empty_body_content
|
40
|
+
comments << RBI::EmptyComment.new unless comments.empty?
|
41
|
+
comments << RBI::Comment.new("THIS IS AN EMPTY RBI FILE.")
|
42
|
+
comments << RBI::Comment.new("see https://github.com/Shopify/tapioca/wiki/Manual-Gem-Requires")
|
43
|
+
end
|
44
|
+
|
45
|
+
sig { returns(T::Boolean) }
|
46
|
+
def empty?
|
47
|
+
root.empty?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
7
51
|
class Tree
|
8
52
|
extend T::Sig
|
9
53
|
|
data/lib/tapioca/reflection.rb
CHANGED
@@ -17,6 +17,7 @@ module Tapioca
|
|
17
17
|
PUBLIC_INSTANCE_METHODS_METHOD = T.let(Module.instance_method(:public_instance_methods), UnboundMethod)
|
18
18
|
PROTECTED_INSTANCE_METHODS_METHOD = T.let(Module.instance_method(:protected_instance_methods), UnboundMethod)
|
19
19
|
PRIVATE_INSTANCE_METHODS_METHOD = T.let(Module.instance_method(:private_instance_methods), UnboundMethod)
|
20
|
+
METHOD_METHOD = T.let(Kernel.instance_method(:method), UnboundMethod)
|
20
21
|
|
21
22
|
sig { params(object: BasicObject).returns(Class).checked(:never) }
|
22
23
|
def class_of(object)
|
@@ -30,7 +31,8 @@ module Tapioca
|
|
30
31
|
|
31
32
|
sig { params(constant: Module).returns(T.nilable(String)) }
|
32
33
|
def name_of(constant)
|
33
|
-
NAME_METHOD.bind(constant).call
|
34
|
+
name = NAME_METHOD.bind(constant).call
|
35
|
+
name&.start_with?("#<") ? nil : name
|
34
36
|
end
|
35
37
|
|
36
38
|
sig { params(constant: Module).returns(Class) }
|
@@ -106,6 +108,11 @@ module Tapioca
|
|
106
108
|
type.to_s.gsub(/\bAttachedClass\b/, "T.attached_class")
|
107
109
|
end
|
108
110
|
|
111
|
+
sig { params(constant: Module, method: Symbol).returns(Method) }
|
112
|
+
def method_of(constant, method)
|
113
|
+
METHOD_METHOD.bind(constant).call(method)
|
114
|
+
end
|
115
|
+
|
109
116
|
# Returns an array with all classes that are < than the supplied class.
|
110
117
|
#
|
111
118
|
# class C; end
|
data/lib/tapioca/version.rb
CHANGED
data/lib/tapioca.rb
CHANGED
@@ -18,6 +18,8 @@ module Tapioca
|
|
18
18
|
end
|
19
19
|
|
20
20
|
require "tapioca/reflection"
|
21
|
+
require "tapioca/constant_locator"
|
21
22
|
require "tapioca/compilers/dsl/base"
|
23
|
+
require "tapioca/compilers/dynamic_mixin_compiler"
|
22
24
|
require "tapioca/helpers/active_record_column_type_helper"
|
23
25
|
require "tapioca/version"
|
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.5.
|
4
|
+
version: 0.5.4
|
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-10-26 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -61,14 +61,14 @@ dependencies:
|
|
61
61
|
requirements:
|
62
62
|
- - ">="
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
version: 0.
|
64
|
+
version: 0.5.6200
|
65
65
|
type: :runtime
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
68
68
|
requirements:
|
69
69
|
- - ">="
|
70
70
|
- !ruby/object:Gem::Version
|
71
|
-
version: 0.
|
71
|
+
version: 0.5.6200
|
72
72
|
- !ruby/object:Gem::Dependency
|
73
73
|
name: sorbet-runtime
|
74
74
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,7 +112,7 @@ dependencies:
|
|
112
112
|
- !ruby/object:Gem::Version
|
113
113
|
version: 0.19.2
|
114
114
|
- !ruby/object:Gem::Dependency
|
115
|
-
name:
|
115
|
+
name: yard-sorbet
|
116
116
|
requirement: !ruby/object:Gem::Requirement
|
117
117
|
requirements:
|
118
118
|
- - ">="
|
@@ -144,9 +144,11 @@ files:
|
|
144
144
|
- lib/tapioca/compilers/dsl/action_mailer.rb
|
145
145
|
- lib/tapioca/compilers/dsl/active_job.rb
|
146
146
|
- lib/tapioca/compilers/dsl/active_model_attributes.rb
|
147
|
+
- lib/tapioca/compilers/dsl/active_model_secure_password.rb
|
147
148
|
- lib/tapioca/compilers/dsl/active_record_associations.rb
|
148
149
|
- lib/tapioca/compilers/dsl/active_record_columns.rb
|
149
150
|
- lib/tapioca/compilers/dsl/active_record_enum.rb
|
151
|
+
- lib/tapioca/compilers/dsl/active_record_fixtures.rb
|
150
152
|
- lib/tapioca/compilers/dsl/active_record_scope.rb
|
151
153
|
- lib/tapioca/compilers/dsl/active_record_typed_store.rb
|
152
154
|
- lib/tapioca/compilers/dsl/active_resource.rb
|
@@ -157,12 +159,14 @@ files:
|
|
157
159
|
- lib/tapioca/compilers/dsl/config.rb
|
158
160
|
- lib/tapioca/compilers/dsl/frozen_record.rb
|
159
161
|
- lib/tapioca/compilers/dsl/identity_cache.rb
|
162
|
+
- lib/tapioca/compilers/dsl/mixed_in_class_attributes.rb
|
160
163
|
- lib/tapioca/compilers/dsl/protobuf.rb
|
161
164
|
- lib/tapioca/compilers/dsl/sidekiq_worker.rb
|
162
165
|
- lib/tapioca/compilers/dsl/smart_properties.rb
|
163
166
|
- lib/tapioca/compilers/dsl/state_machines.rb
|
164
167
|
- lib/tapioca/compilers/dsl/url_helpers.rb
|
165
168
|
- lib/tapioca/compilers/dsl_compiler.rb
|
169
|
+
- lib/tapioca/compilers/dynamic_mixin_compiler.rb
|
166
170
|
- lib/tapioca/compilers/requires_compiler.rb
|
167
171
|
- lib/tapioca/compilers/sorbet.rb
|
168
172
|
- lib/tapioca/compilers/symbol_table/symbol_generator.rb
|
@@ -173,7 +177,13 @@ files:
|
|
173
177
|
- lib/tapioca/config_builder.rb
|
174
178
|
- lib/tapioca/constant_locator.rb
|
175
179
|
- lib/tapioca/gemfile.rb
|
176
|
-
- lib/tapioca/
|
180
|
+
- lib/tapioca/generators.rb
|
181
|
+
- lib/tapioca/generators/base.rb
|
182
|
+
- lib/tapioca/generators/dsl.rb
|
183
|
+
- lib/tapioca/generators/gem.rb
|
184
|
+
- lib/tapioca/generators/init.rb
|
185
|
+
- lib/tapioca/generators/require.rb
|
186
|
+
- lib/tapioca/generators/todo.rb
|
177
187
|
- lib/tapioca/generic_type_registry.rb
|
178
188
|
- lib/tapioca/helpers/active_record_column_type_helper.rb
|
179
189
|
- lib/tapioca/internal.rb
|