Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions lib/spoom/sorbet/sigils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,21 @@ def contains_valid_sigil?(content)
!!strictness && valid_strictness?(strictness)
end

# returns true if the passed content contains a valid sigil at or above the passed strictness
# internal sigils do not satisfy a minimum strictness
#: (String content, String strictness) -> bool
def satisfies_minimum_strictness?(content, strictness)
return false unless contains_valid_sigil?(content)

current_strictness = strictness_in_content(content)
strictness = strictness.strip
return false if current_strictness == STRICTNESS_INTERNAL || strictness == STRICTNESS_INTERNAL

strictness_index = VALID_STRICTNESS.index(current_strictness)
minimum_index = VALID_STRICTNESS.index(strictness)
!!strictness_index && !!minimum_index && strictness_index >= minimum_index
end

# returns a string which is the passed content but with the sigil updated to a new strictness
#: (String content, String new_strictness) -> String
def update_sigil(content, new_strictness)
Expand Down
37 changes: 23 additions & 14 deletions lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,29 @@ module Spoom
module Sorbet
module Translate
module RBSCommentsToSorbetSigs
RBS_ANNOTATION_MARKERS = [
"# @abstract",
"# @interface",
"# @sealed",
"# @final",
"# @requires_ancestor:",
"# @override",
"# @overridable",
"# @without_runtime",
].freeze #: Array[String]
RBS_REWRITE_PATTERN = Regexp.union(["#:", "#|", *RBS_ANNOTATION_MARKERS]).freeze #: Regexp
private_constant :RBS_ANNOTATION_MARKERS

class << self
RBS_REWRITE_PATTERN = Regexp.union([
"#:",
"#|",
"# @abstract",
"# @interface",
"# @sealed",
"# @final",
"# @requires_ancestor:",
"# @override",
"# @overridable",
"# @without_runtime",
]).freeze #: Regexp
private_constant :RBS_REWRITE_PATTERN

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you undoing #1030?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I didn't cut a release for it and this PR adopts @amomchilov's suggestion to create API methods instead.


# Detects RBS comment markers (`#:`, `#|`, and supported `# @...` annotations).
# Use this check to skip parsing files without those markers.
# It does not validate RBS syntax or check the `typed:` sigil.
#: (String ruby_contents) -> bool
def contains_rbs_syntax?(ruby_contents)
ruby_contents.match?(RBS_REWRITE_PATTERN)
end

#: (
#| String ruby_contents,
#| file: String,
Expand All @@ -34,7 +43,7 @@ def rewrite_if_needed(
erase_generic_types: false,
force: false
)
return ruby_contents unless ruby_contents.match?(RBS_REWRITE_PATTERN) &&
return ruby_contents unless contains_rbs_syntax?(ruby_contents) &&
(force || Sigils.contains_valid_sigil?(ruby_contents))

options = Options.new(
Expand Down
8 changes: 6 additions & 2 deletions rbi/spoom.rbi
Original file line number Diff line number Diff line change
Expand Up @@ -3247,6 +3247,9 @@ module Spoom::Sorbet::Sigils
sig { params(path: T.any(::Pathname, ::String)).returns(T.nilable(::String)) }
def file_strictness(path); end

sig { params(content: ::String, strictness: ::String).returns(T::Boolean) }
def satisfies_minimum_strictness?(content, strictness); end

sig { params(strictness: ::String).returns(::String) }
def sigil_string(strictness); end

Expand Down Expand Up @@ -3353,6 +3356,9 @@ end

module Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs
class << self
sig { params(ruby_contents: ::String).returns(T::Boolean) }
def contains_rbs_syntax?(ruby_contents); end

sig do
params(
ruby_contents: ::String,
Expand Down Expand Up @@ -3611,8 +3617,6 @@ class Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs::Options
end

Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs::Options::ALLOWED_OVERLOAD_STRATEGIES = T.let(T.unsafe(nil), Array)
Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs::RBS_ANNOTATION_MARKERS = T.let(T.unsafe(nil), Array)
Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs::RBS_REWRITE_PATTERN = T.let(T.unsafe(nil), Regexp)

class Spoom::Sorbet::Translate::SorbetAssertionsToRBSComments < ::Spoom::Sorbet::Translate::Translator
sig do
Expand Down
23 changes: 23 additions & 0 deletions test/spoom/sorbet/sigils_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,33 @@ class A; end

def test_contains_valid_sigil
assert(Sigils.contains_valid_sigil?("# typed: true\nclass A; end\n"))
assert(Sigils.contains_valid_sigil?("# typed: __STDLIB_INTERNAL\n"))
refute(Sigils.contains_valid_sigil?("class A; end\n"))
refute(Sigils.contains_valid_sigil?("# typed: foo\nclass A; end\n"))
end

def test_satisfies_minimum_strictness
["true", "strict", "strong"].each do |strictness|
assert(Sigils.satisfies_minimum_strictness?("# typed: #{strictness}\n", "true"))
end

["ignore", "false", "foo", "__STDLIB_INTERNAL", "true#"].each do |strictness|
refute(Sigils.satisfies_minimum_strictness?("# typed: #{strictness}\n", "true"))
end

refute(Sigils.satisfies_minimum_strictness?("class A; end\n", "true"))
refute(Sigils.satisfies_minimum_strictness?("# typed: false\n# typed: strict\n", "true"))
refute(Sigils.satisfies_minimum_strictness?("# typed: true\n", "strict"))
assert(Sigils.satisfies_minimum_strictness?("# typed: strict\n", "strict"))
assert(Sigils.satisfies_minimum_strictness?("# typed: strong\n", "strict"))
end

def test_satisfies_minimum_strictness_with_invalid_minimum
["", "foo", "__STDLIB_INTERNAL"].each do |minimum_strictness|
refute(Sigils.satisfies_minimum_strictness?("# typed: strong\n", minimum_strictness))
end
end

def test_update_sigil_to_use_valid_strictness
content = <<~STR
# typed: ignore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ module Spoom
module Sorbet
module Translate
class RBSCommentsToSorbetSigsTest < Minitest::Test
def test_contains_rbs_syntax
assert(RBSCommentsToSorbetSigs.contains_rbs_syntax?("#: -> void\ndef foo; end\n"))
assert(RBSCommentsToSorbetSigs.contains_rbs_syntax?("#| String\n"))
assert(RBSCommentsToSorbetSigs.contains_rbs_syntax?("# @abstract\nclass A; end\n"))
assert(RBSCommentsToSorbetSigs.contains_rbs_syntax?("# typed: false\n#: -> void\ndef foo; end\n"))
refute(RBSCommentsToSorbetSigs.contains_rbs_syntax?("# typed: true\ndef foo; end\n"))
end

def test_translate_to_rbi_empty
contents = ""
assert_rewrites_rbs(
Expand Down
Loading