Skip to content

Commit

Permalink
Merge pull request #275 from Shopify/uk-print-full-dsl-command-for-ve…
Browse files Browse the repository at this point in the history
…rify

Print full command line for `tapioca dsl` in verify
  • Loading branch information
paracycle authored Apr 1, 2021
2 parents 7257f87 + e359514 commit c750b97
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 30 deletions.
66 changes: 40 additions & 26 deletions lib/tapioca/generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def build_dsl(requested_constants, should_verify: false, quiet: false)
end
say("")

outpath = should_verify ? Dir.mktmpdir : config.outpath
outpath = should_verify ? Pathname.new(Dir.mktmpdir) : config.outpath
rbi_files_to_purge = existing_rbi_filenames(requested_constants)

compiler = Compilers::DslCompiler.new(
Expand All @@ -145,19 +145,27 @@ def build_dsl(requested_constants, should_verify: false, quiet: false)
}
)

constant_lookup = {}

compiler.run do |constant, contents|
constant_name = Module.instance_method(:name).bind(constant).call

filename = compile_dsl_rbi(
constant,
constant_name,
contents,
outpath: Pathname.new(outpath),
outpath: outpath,
quiet: should_verify || quiet
)
rbi_files_to_purge.delete(filename) if filename

if filename
rbi_files_to_purge.delete(filename)
constant_lookup[filename.relative_path_from(outpath)] = constant_name
end
end
say("")

if should_verify
perform_dsl_verification(outpath)
perform_dsl_verification(outpath, constant_lookup)
else
purge_stale_dsl_rbi_files(rbi_files_to_purge)

Expand Down Expand Up @@ -513,20 +521,19 @@ def compile_gem_rbi(gem)
end

sig do
params(constant: Module, contents: String, outpath: Pathname, quiet: T::Boolean)
params(constant_name: String, contents: String, outpath: Pathname, quiet: T::Boolean)
.returns(T.nilable(Pathname))
end
def compile_dsl_rbi(constant, contents, outpath: config.outpath, quiet: false)
def compile_dsl_rbi(constant_name, contents, outpath: config.outpath, quiet: false)
return if contents.nil?

constant_name = Module.instance_method(:name).bind(constant).call
rbi_name = constant_name.underscore + ".rbi"
filename = outpath / rbi_name

out = String.new
out << rbi_header(
"#{Config::DEFAULT_COMMAND} dsl #{constant_name}",
reason: "dynamic methods in `#{constant.name}`"
reason: "dynamic methods in `#{constant_name}`"
)
out << contents

Expand All @@ -541,23 +548,23 @@ def compile_dsl_rbi(constant, contents, outpath: config.outpath, quiet: false)
filename
end

sig { params(tmp_dir: Pathname).returns(T::Array[String]) }
sig { params(tmp_dir: Pathname).returns(T::Hash[String, Symbol]) }
def verify_dsl_rbi(tmp_dir:)
errors = []
diff = {}

existing_rbis = rbi_files_in(config.outpath)
new_rbis = rbi_files_in(tmp_dir)

added_files = (new_rbis - existing_rbis)

unless added_files.empty?
errors << build_error_for_files(:added, added_files)
added_files.each do |file|
diff[file] = :added
end

removed_files = (existing_rbis - new_rbis)

unless removed_files.empty?
errors << build_error_for_files(:removed, removed_files)
removed_files.each do |file|
diff[file] = :removed
end

common_files = (existing_rbis & new_rbis)
Expand All @@ -566,14 +573,14 @@ def verify_dsl_rbi(tmp_dir:)
filename unless FileUtils.identical?(config.outpath / filename, tmp_dir / filename)
end.compact

unless changed_files.empty?
errors << build_error_for_files(:changed, changed_files)
changed_files.each do |file|
diff[file] = :changed
end

errors
diff
end

sig { params(cause: Symbol, files: T::Array[Pathname]).returns(String) }
sig { params(cause: Symbol, files: T::Array[String]).returns(String) }
def build_error_for_files(cause, files)
filenames = files.map do |file|
config.outpath / file
Expand All @@ -589,18 +596,25 @@ def rbi_files_in(path)
end.sort
end

sig { params(dir: String).void }
def perform_dsl_verification(dir)
errors = verify_dsl_rbi(tmp_dir: Pathname.new(dir))
sig { params(dir: Pathname, constant_lookup: T::Hash[String, String]).void }
def perform_dsl_verification(dir, constant_lookup)
diff = verify_dsl_rbi(tmp_dir: dir)

if errors.empty?
if diff.empty?
say("Nothing to do, all RBIs are up-to-date.")
else
say("RBI files are out-of-date, please run `#{Config::DEFAULT_COMMAND} dsl` to update.")
constants = T.unsafe(constant_lookup).values_at(*diff.keys).join(" ")

say("RBI files are out-of-date, please run:")
say(" `#{Config::DEFAULT_COMMAND} dsl #{constants}`")

say("")

say("Reason:", [:red])
errors.each do |error|
say(error)
diff.group_by(&:last).sort.each do |cause, diff_for_cause|
say(build_error_for_files(cause, diff_for_cause.map(&:first)))
end

exit(1)
end
ensure
Expand Down
22 changes: 18 additions & 4 deletions spec/tapioca/cli_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -637,8 +637,15 @@ class Image
it 'advises of new file(s) and returns exit_status 1' do
output = execute("dsl", "--verify")

assert_includes(output, <<~OUTPUT)
RBI files are out-of-date, please run `bin/tapioca dsl` to update.
assert_equal(output, <<~OUTPUT)
Loading Rails application... Done
Loading DSL generator classes... Done
Checking for out-of-date RBIs...
RBI files are out-of-date, please run:
`bin/tapioca dsl Image`
Reason:
File(s) added:
- #{outdir}/image.rbi
Expand Down Expand Up @@ -680,8 +687,15 @@ class Image
it 'advises of modified file(s) and returns exit status 1' do
output = execute("dsl", "--verify")

assert_includes(output, <<~OUTPUT)
RBI files are out-of-date, please run `bin/tapioca dsl` to update.
assert_equal(output, <<~OUTPUT)
Loading Rails application... Done
Loading DSL generator classes... Done
Checking for out-of-date RBIs...
RBI files are out-of-date, please run:
`bin/tapioca dsl Image`
Reason:
File(s) changed:
- #{outdir}/image.rbi
Expand Down

0 comments on commit c750b97

Please sign in to comment.