Skip to content

Commit

Permalink
Introduce CLI command to translate RBI sigs to RBS
Browse files Browse the repository at this point in the history
Signed-off-by: Alexandre Terrasa <[email protected]>
  • Loading branch information
Morriar committed Oct 3, 2024
1 parent 365a285 commit bfa30c7
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 0 deletions.
4 changes: 4 additions & 0 deletions lib/spoom/cli/srb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require_relative "srb/bump"
require_relative "srb/coverage"
require_relative "srb/lsp"
require_relative "srb/sigs"
require_relative "srb/tc"

module Spoom
Expand All @@ -19,6 +20,9 @@ class Main < Thor
desc "bump", "Change Sorbet sigils from one strictness to another when no errors"
subcommand "bump", Spoom::Cli::Srb::Bump

desc "sigs", "Translate signatures from/to RBI and RBS"
subcommand "sigs", Spoom::Cli::Srb::Sigs

desc "tc", "Run typechecking with advanced options"
subcommand "tc", Spoom::Cli::Srb::Tc
end
Expand Down
49 changes: 49 additions & 0 deletions lib/spoom/cli/srb/sigs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# typed: true
# frozen_string_literal: true

require "spoom/sorbet/translate_sigs"

module Spoom
module Cli
module Srb
class Sigs < Thor
include Helper

desc "translate", "Translate signatures from/to RBI and RBS"
option :from, type: :string, aliases: :f, desc: "From format", enum: ["rbi"], default: "rbi"
option :to, type: :string, aliases: :t, desc: "To format", enum: ["rbs"], default: "rbs"
def translate(*paths)
from = options[:from]
to = options[:to]
paths << "." if paths.empty?

files = paths.flat_map do |path|
if File.file?(path)
[path]
else
Dir.glob("#{path}/**/*.rb")
end
end

if files.empty?
say_error("No files to translate")
exit(1)
end

say("Translating signatures from `#{from}` to `#{to}` in `#{files.size}` files...\n\n")

files.each do |file|
contents = File.read(file)
contents = Spoom::Sorbet::TranslateSigs.rbi_to_rbs(contents)
File.write(file, contents)
rescue RBI::ParseError => error
say_warning("Can't parse #{file}: #{error.message}")
next
end

say("Translated signatures in `#{files.size}` files.")
end
end
end
end
end
85 changes: 85 additions & 0 deletions test/spoom/cli/srb/sigs_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# typed: true
# frozen_string_literal: true

require "test_with_project"

module Spoom
module Cli
module Srb
class SigsTest < TestWithProject
def setup
@project.bundle_install!
end

def test_only_supports_translation_from_rbi
result = @project.spoom("srb sigs translate --from rbs")

assert_equal(<<~ERR, result.err)
Expected '--from' to be one of rbi; got rbs
ERR
refute(result.status)
end

def test_only_supports_translation_to_rbs
result = @project.spoom("srb sigs translate --to rbi")

assert_equal(<<~ERR, result.err)
Expected '--to' to be one of rbs; got rbi
ERR
refute(result.status)
end

def test_no_files
result = @project.spoom("srb sigs translate --no-color")

assert_equal(<<~OUT, result.err)
Error: No files to translate
OUT
refute(result.status)
end

def test_only_selected_files
@project.write!("a/file1.rb", <<~RB)
sig { void }
def foo; end
RB

@project.write!("a/file2.rb", <<~RB)
sig { void }
def foo; end
RB

@project.write!("b/file1.rb", <<~RB)
sig { void }
def foo; end
RB

result = @project.spoom("srb sigs translate --no-color a/file1.rb b/")

assert_empty(result.err)
assert_equal(<<~OUT, result.out)
Translating signatures from `rbi` to `rbs` in `2` files...
Translated signatures in `2` files.
OUT
assert(result.status)

assert_equal(<<~RB, @project.read("a/file1.rb"))
#: -> void
def foo; end
RB

assert_equal(<<~RB, @project.read("a/file2.rb"))
sig { void }
def foo; end
RB

assert_equal(<<~RB, @project.read("b/file1.rb"))
#: -> void
def foo; end
RB
end
end
end
end
end

0 comments on commit bfa30c7

Please sign in to comment.