Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make DSL generation also autocorrect the gems RBI strictnesses #837

Merged
merged 3 commits into from Mar 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 15 additions & 1 deletion lib/tapioca/commands/dsl.rb
Expand Up @@ -4,6 +4,9 @@
module Tapioca
module Commands
class Dsl < Command
include SorbetHelper
include RBIHelper

sig do
params(
requested_constants: T::Array[String],
Expand All @@ -17,6 +20,8 @@ class Dsl < Command
quiet: T::Boolean,
verbose: T::Boolean,
number_of_workers: T.nilable(Integer),
auto_strictness: T::Boolean,
gem_dir: String,
rbi_formatter: RBIFormatter
).void
end
Expand All @@ -32,6 +37,8 @@ def initialize(
quiet: false,
verbose: false,
number_of_workers: nil,
auto_strictness: true,
gem_dir: DEFAULT_GEM_DIR,
rbi_formatter: DEFAULT_RBI_FORMATTER
)
@requested_constants = requested_constants
Expand All @@ -45,6 +52,8 @@ def initialize(
@quiet = quiet
@verbose = verbose
@number_of_workers = number_of_workers
@auto_strictness = auto_strictness
@gem_dir = gem_dir
@rbi_formatter = rbi_formatter

super()
Expand Down Expand Up @@ -102,9 +111,14 @@ def execute
perform_dsl_verification(outpath)
else
purge_stale_dsl_rbi_files(rbi_files_to_purge)

say("Done", :green)

if @auto_strictness
say("")
update_gem_rbis_strictnesses([], gem_dir: @gem_dir, dsl_dir: @outpath.to_s)
say("")
end

say("All operations performed in working directory.", [:green, :bold])
say("Please review changes and commit them.", [:green, :bold])
end
Expand Down
60 changes: 4 additions & 56 deletions lib/tapioca/commands/gem.rb
Expand Up @@ -5,6 +5,7 @@ module Tapioca
module Commands
class Gem < Command
include SorbetHelper
include RBIHelper

sig do
params(
Expand Down Expand Up @@ -78,7 +79,8 @@ def execute
end

if anything_done
update_strictnesses(gem_queue.map(&:name), gem_dir: @outpath.to_s, dsl_dir: @dsl_dir) if @auto_strictness
gem_names = gem_queue.map(&:name)
update_gem_rbis_strictnesses(gem_names, gem_dir: @outpath.to_s, dsl_dir: @dsl_dir) if @auto_strictness

say("All operations performed in working directory.", [:green, :bold])
say("Please review changes and commit them.", [:green, :bold])
Expand All @@ -102,7 +104,7 @@ def sync(should_verify: false)
].any?

if anything_done
update_strictnesses([], gem_dir: @outpath.to_s, dsl_dir: @dsl_dir) if @auto_strictness
update_gem_rbis_strictnesses([], gem_dir: @outpath.to_s, dsl_dir: @dsl_dir) if @auto_strictness

say("All operations performed in working directory.", [:green, :bold])
say("Please review changes and commit them.", [:green, :bold])
Expand Down Expand Up @@ -379,60 +381,6 @@ def merge_with_exported_rbi(gem, file)
say_error("\n\n RBIs exported by `#{gem.name}` contain errors and can't be used:", :yellow)
say_error("Cause: #{e.message} (#{e.location})")
end

sig { params(gem_names: T::Array[String], gem_dir: String, dsl_dir: String).void }
def update_strictnesses(gem_names, gem_dir: DEFAULT_GEM_DIR, dsl_dir: DEFAULT_DSL_DIR)
return unless File.directory?(dsl_dir)

error_url_base = Spoom::Sorbet::Errors::DEFAULT_ERROR_URL_BASE

say("Typechecking RBI files... ")
res = sorbet(
"--no-config",
"--error-url-base=#{error_url_base}",
"--isolate-error-code 4010",
dsl_dir,
gem_dir
)
say(" Done", :green)

errors = Spoom::Sorbet::Errors::Parser.parse_string(res.err)

if errors.empty?
say("No error found", [:green, :bold])
return
end

files = []

errors.each do |error|
# Collect the file with error
files << error.file
error.more.each do |line|
# Also collect the conflicting definition file paths
next unless line.include?("Previous definition")
files << line.split(":").first&.strip
end
end

files
.uniq
.sort
.select do |file|
name = gem_name_from_rbi_path(file)
file.start_with?(gem_dir) && (gem_names.empty? || gem_names.include?(name))
end.each do |file|
Spoom::Sorbet::Sigils.change_sigil_in_file(file, "false")
say("\n Changed strictness of #{file} to `typed: false` (conflicting with DSL files)", [:yellow, :bold])
end

say("\n")
end

sig { params(path: String).returns(String) }
def gem_name_from_rbi_path(path)
T.must(File.basename(path, ".rbi").split("@").first)
end
end
end
end
2 changes: 1 addition & 1 deletion lib/tapioca/gem/listeners/sorbet_signatures.rb
Expand Up @@ -8,7 +8,7 @@ class SorbetSignatures < Base
extend T::Sig

include Runtime::Reflection
include RBIHelper
include SignaturesHelper

TYPE_PARAMETER_MATCHER = /T\.type_parameter\(:?([[:word:]]+)\)/

Expand Down
2 changes: 1 addition & 1 deletion lib/tapioca/gem/pipeline.rb
Expand Up @@ -8,7 +8,7 @@ module Gem
class Pipeline
extend T::Sig
include Runtime::Reflection
include RBIHelper
include SignaturesHelper

IGNORED_SYMBOLS = T.let(["YAML", "MiniTest", "Mutex"], T::Array[String])

Expand Down
63 changes: 56 additions & 7 deletions lib/tapioca/helpers/rbi_helper.rb
Expand Up @@ -4,14 +4,63 @@
module Tapioca
module RBIHelper
extend T::Sig
extend T::Helpers

sig { params(sig_string: String).returns(String) }
def sanitize_signature_types(sig_string)
sig_string
.gsub(".returns(<VOID>)", ".void")
.gsub("<VOID>", "void")
.gsub("<NOT-TYPED>", "T.untyped")
.gsub(".params()", "")
requires_ancestor { Thor::Shell }
requires_ancestor { SorbetHelper }

sig { params(gem_names: T::Array[String], gem_dir: String, dsl_dir: String).void }
def update_gem_rbis_strictnesses(gem_names, gem_dir: DEFAULT_GEM_DIR, dsl_dir: DEFAULT_DSL_DIR)
return unless File.directory?(dsl_dir)

error_url_base = Spoom::Sorbet::Errors::DEFAULT_ERROR_URL_BASE

say("Typechecking RBI files... ")
res = sorbet(
"--no-config",
"--error-url-base=#{error_url_base}",
"--isolate-error-code 4010",
dsl_dir,
gem_dir
)
say(" Done", :green)

errors = Spoom::Sorbet::Errors::Parser.parse_string(res.err)

if errors.empty?
say("No error found", [:green, :bold])
return
end

files = []

errors.each do |error|
# Collect the file with error
files << error.file
error.more.each do |line|
# Also collect the conflicting definition file paths
next unless line.include?("Previous definition")
files << line.split(":").first&.strip
end
end

files
.uniq
.sort
.select do |file|
name = gem_name_from_rbi_path(file)
file.start_with?(gem_dir) && (gem_names.empty? || gem_names.include?(name))
end.each do |file|
Spoom::Sorbet::Sigils.change_sigil_in_file(file, "false")
say("\n Changed strictness of #{file} to `typed: false` (conflicting with DSL files)", [:yellow, :bold])
end

say("\n")
end

sig { params(path: String).returns(String) }
def gem_name_from_rbi_path(path)
T.must(File.basename(path, ".rbi").split("@").first)
end
end
end
17 changes: 17 additions & 0 deletions lib/tapioca/helpers/signatures_helper.rb
@@ -0,0 +1,17 @@
# typed: strict
# frozen_string_literal: true

module Tapioca
module SignaturesHelper
extend T::Sig

sig { params(sig_string: String).returns(String) }
def sanitize_signature_types(sig_string)
sig_string
.gsub(".returns(<VOID>)", ".void")
.gsub("<VOID>", "void")
.gsub("<NOT-TYPED>", "T.untyped")
.gsub(".params()", "")
end
end
end
1 change: 1 addition & 0 deletions lib/tapioca/internal.rb
Expand Up @@ -11,6 +11,7 @@
require "tapioca/runtime/generic_type_registry"
require "tapioca/helpers/cli_helper"
require "tapioca/helpers/config_helper"
require "tapioca/helpers/signatures_helper"
require "tapioca/helpers/rbi_helper"
require "tapioca/helpers/shims_helper"
require "tapioca/helpers/sorbet_helper"
Expand Down