Skip to content

Commit

Permalink
Introduce skip_constants flag to dsl
Browse files Browse the repository at this point in the history
There might be need for an escape hatch that will prevent tapioca from
generation DSL RBIs for specific constants.
  • Loading branch information
KaanOzkan committed Apr 23, 2024
1 parent e13dd7c commit c532150
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -500,6 +500,7 @@ Options:
# Default: .
[--halt-upon-load-error], [--no-halt-upon-load-error], [--skip-halt-upon-load-error] # Halt upon a load error while loading the Rails application
# Default: true
[--skip-constant=constant [constant ...]] # Skip the given application constant(s) when generating RBIs
-c, [--config=<config file path>] # Path to the Tapioca configuration file
# Default: sorbet/tapioca/config.yml
-V, [--verbose], [--no-verbose], [--skip-verbose] # Verbose output for debugging purposes
Expand Down Expand Up @@ -933,6 +934,7 @@ dsl:
list_compilers: false
app_root: "."
halt_upon_load_error: true
skip_constant: []
gem:
outdir: sorbet/rbi/gems
file_header: true
Expand Down
6 changes: 6 additions & 0 deletions lib/tapioca/cli.rb
Expand Up @@ -135,6 +135,11 @@ def todo
type: :boolean,
desc: "Halt upon a load error while loading the Rails application",
default: true
option :skip_constant,
type: :array,
banner: "constant [constant ...]",
desc: "Skip the given application constant(s) when generating RBIs",
default: []
def dsl(*constant_or_paths)
set_environment(options)

Expand All @@ -149,6 +154,7 @@ def dsl(*constant_or_paths)
exclude: options[:exclude],
file_header: options[:file_header],
tapioca_path: TAPIOCA_DIR,
skip_constant: options[:skip_constant],
quiet: options[:quiet],
verbose: options[:verbose],
number_of_workers: options[:workers],
Expand Down
4 changes: 4 additions & 0 deletions lib/tapioca/commands/abstract_dsl.rb
Expand Up @@ -18,6 +18,7 @@ class AbstractDsl < CommandWithoutTracker
exclude: T::Array[String],
file_header: T::Boolean,
tapioca_path: String,
skip_constant: T::Array[String],
quiet: T::Boolean,
verbose: T::Boolean,
number_of_workers: T.nilable(Integer),
Expand All @@ -36,6 +37,7 @@ def initialize(
exclude:,
file_header:,
tapioca_path:,
skip_constant:,
quiet: false,
verbose: false,
number_of_workers: nil,
Expand All @@ -60,6 +62,7 @@ def initialize(
@rbi_formatter = rbi_formatter
@app_root = app_root
@halt_upon_load_error = halt_upon_load_error
@skip_constant = skip_constant

super()
end
Expand Down Expand Up @@ -124,6 +127,7 @@ def create_pipeline
error_handler: ->(error) {
say_error(error, :bold, :red)
},
skipped_constants: constantize(@skip_constant),
number_of_workers: @number_of_workers,
)
end
Expand Down
19 changes: 16 additions & 3 deletions lib/tapioca/dsl/pipeline.rb
Expand Up @@ -15,6 +15,9 @@ class Pipeline
sig { returns(T::Array[Pathname]) }
attr_reader :requested_paths

sig { returns(T::Array[Module]) }
attr_reader :skipped_constants

sig { returns(T.proc.params(error: String).void) }
attr_reader :error_handler

Expand All @@ -28,6 +31,7 @@ class Pipeline
requested_compilers: T::Array[T.class_of(Compiler)],
excluded_compilers: T::Array[T.class_of(Compiler)],
error_handler: T.proc.params(error: String).void,
skipped_constants: T::Array[Module],
number_of_workers: T.nilable(Integer),
).void
end
Expand All @@ -37,6 +41,7 @@ def initialize(
requested_compilers: [],
excluded_compilers: [],
error_handler: $stderr.method(:puts).to_proc,
skipped_constants: [],
number_of_workers: nil
)
@active_compilers = T.let(
Expand All @@ -46,6 +51,7 @@ def initialize(
@requested_constants = requested_constants
@requested_paths = requested_paths
@error_handler = error_handler
@skipped_constants = skipped_constants
@number_of_workers = number_of_workers
@errors = T.let([], T::Array[String])
end
Expand All @@ -56,7 +62,7 @@ def initialize(
).returns(T::Array[T.type_parameter(:T)])
end
def run(&blk)
constants_to_process = gather_constants(requested_constants, requested_paths)
constants_to_process = gather_constants(requested_constants, requested_paths, skipped_constants)
.select { |c| Module === c } # Filter value constants out
.sort_by! { |c| T.must(Runtime::Reflection.name_of(c)) }

Expand Down Expand Up @@ -128,13 +134,20 @@ def gather_active_compilers(requested_compilers, excluded_compilers)
active_compilers
end

sig { params(requested_constants: T::Array[Module], requested_paths: T::Array[Pathname]).returns(T::Set[Module]) }
def gather_constants(requested_constants, requested_paths)
sig do
params(
requested_constants: T::Array[Module],
requested_paths: T::Array[Pathname],
skipped_constants: T::Array[Module],
).returns(T::Set[Module])
end
def gather_constants(requested_constants, requested_paths, skipped_constants)
constants = Set.new.compare_by_identity
active_compilers.each do |compiler|
constants.merge(compiler.processable_constants)
end
constants = filter_anonymous_and_reloaded_constants(constants)
constants -= skipped_constants

constants &= requested_constants unless requested_constants.empty? && requested_paths.empty?
constants
Expand Down
61 changes: 61 additions & 0 deletions spec/tapioca/cli/dsl_spec.rb
Expand Up @@ -1371,6 +1371,67 @@ def body=(body); end
RBI
end

it "must respect `skip_constant` option" do
@project.write!("lib/post.rb", <<~RB)
class Post; end
RB

@project.write!("lib/job.rb", <<~RB)
class Job; end
RB

@project.write!("lib/compilers/foo/compiler.rb", <<~RB)
require "job"
require "post"
module Foo
class Compiler < Tapioca::Dsl::Compiler
extend T::Sig
ConstantType = type_member { { fixed: Module } }
sig { override.void }
def decorate
root.create_path(constant) do |job|
job.create_module("FooModule")
end
end
sig { override.returns(T::Enumerable[Module]) }
def self.gather_constants
[Post, Job]
end
end
end
RB

result = @project.tapioca("dsl --skip-constant Job")

assert_stdout_equals(<<~OUT, result)
Loading DSL extension classes... Done
Loading Rails application... Done
Loading DSL compiler classes... Done
Compiling DSL RBI files...
create sorbet/rbi/dsl/post.rbi
Done
Checking generated RBI files... Done
No errors found
All operations performed in working directory.
Please review changes and commit them.
OUT

assert_empty_stderr(result)

refute_project_file_exist("sorbet/rbi/dsl/job.rbi")
assert_project_file_exist("sorbet/rbi/dsl/post.rbi")

assert_success_status(result)
end

describe "pending migrations" do
before do
@project.write!("db/migrate/202001010000_create_articles.rb", <<~RB)
Expand Down

0 comments on commit c532150

Please sign in to comment.