Skip to content

Commit

Permalink
Merge pull request #837 from Shopify/at-typed-override
Browse files Browse the repository at this point in the history
Make DSL generation also autocorrect the gems RBI strictnesses
  • Loading branch information
Morriar committed Mar 1, 2022
2 parents 473258e + 820f7b7 commit 4754fc1
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 66 deletions.
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

0 comments on commit 4754fc1

Please sign in to comment.