Skip to content

Skip RBS rewriter when file does not contain RBS syntax#917

Open
dejmedus wants to merge 3 commits into
mainfrom
jb-rbs-marker-gaurd
Open

Skip RBS rewriter when file does not contain RBS syntax#917
dejmedus wants to merge 3 commits into
mainfrom
jb-rbs-marker-gaurd

Conversation

@dejmedus
Copy link
Copy Markdown

@dejmedus dejmedus commented May 12, 2026

If a file does not contain typed file markers (ex # typed: true) or RBS syntax we can skip attempting to translate it. If a file has not been rewritten we can exclude it from the count of translated files

@dejmedus dejmedus force-pushed the jb-rbs-marker-gaurd branch from 82e90b7 to 07a9394 Compare May 12, 2026 19:51
RB
end

def test_should_rewrite_returns_true_for_supported_typed_sigils
Copy link
Copy Markdown
Contributor

@amomchilov amomchilov May 12, 2026

Choose a reason for hiding this comment

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

Two more cases to test:

  1. Don't trigger if # typed: true exists later in the file. This is unlikely, but it's a performance improvement to ensure we're not scanning through the whole file

  2. Trigger if there's multiple magic comments, but typed isn't first:

    # frozen_string_literal: true
    # typed: true

Copy link
Copy Markdown
Author

@dejmedus dejmedus May 12, 2026

Choose a reason for hiding this comment

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

Don't trigger if # typed: true exists later in the file

Good call! I updated to only check for the typed marker in the magic comments block

@dejmedus dejmedus force-pushed the jb-rbs-marker-gaurd branch from 07a9394 to 47118ab Compare May 12, 2026 20:57
Comment thread lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb Fixed
Comment thread lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb Fixed
@dejmedus dejmedus force-pushed the jb-rbs-marker-gaurd branch 2 times, most recently from cf00c3f to d3125ac Compare May 12, 2026 21:23
Comment thread lib/spoom/cli/srb/sigs.rb
next if new_contents == contents

File.write(file, new_contents)
transformed_count += 1
Copy link
Copy Markdown
Author

@dejmedus dejmedus May 12, 2026

Choose a reason for hiding this comment

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

This will only count changed files in the Translated signatures in <x> files. message, but I'm happy to drop the commit if we want to leave as is

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.

I like it.

dejmedus and others added 3 commits May 12, 2026 16:24
When a file is not typed or contains no RBS comment
syntax, we can skip running the RBS rewriter on it

Co-authored-by: Matt Kubej <matt.kubej@shopify.com>
@dejmedus dejmedus force-pushed the jb-rbs-marker-gaurd branch from d3125ac to f25aa67 Compare May 12, 2026 22:26
class RBSCommentsToSorbetSigs < Translator
include Spoom::RBS::ExtractRBSComments

magic_comments = /\A(?:\s*#[^\n]*\n)*/
Copy link
Copy Markdown
Author

@dejmedus dejmedus May 12, 2026

Choose a reason for hiding this comment

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

Grabs the magic comments block, considered here as everything up until the first non-comment, non-empty line

@dejmedus dejmedus marked this pull request as ready for review May 12, 2026 22:46
@dejmedus dejmedus requested a review from a team as a code owner May 12, 2026 22:46
@dejmedus dejmedus requested a review from amomchilov May 12, 2026 22:47
Copy link
Copy Markdown
Member

@paracycle paracycle left a comment

Choose a reason for hiding this comment

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

Shouldn't all this logic be encapsulated inside the RBSCommentsToSorbetSigs class, which already stores the ruby_contents as an ivar, and wouldn't need to pass it to a should_rewrite? method. The downside is just an extra object allocation only to return the same contents, but I think that's fine.

#: (String source) -> bool
def should_rewrite?(source)
source.match?(TYPED_FILE_PATTERN) && source.match?(RBS_REWRITE_PATTERN)
end
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.

To what Ufuk was saying, maybe we can add a rewrite class method:

Suggested change
end
end
#: (String ruby_contents, file: String, ?max_line_length: Integer?) -> String
def rewrite(ruby_contents, file:, max_line_length: nil)
# fast path, skip parsing/visiting if there's no RBS syntax at all
return ruby_contents if should_rewrite?(ruby_contents)
new(ruby_contents, file:, max_line_length:).rewrite
end

Copy link
Copy Markdown
Contributor

@amomchilov amomchilov left a comment

Choose a reason for hiding this comment

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

Few small points, but it's shaping up!

"# @overridable",
"# @without_runtime",
].freeze #: Array[String]
RBS_REWRITE_PATTERN = Regexp.union(["#:", "#|"] + RBS_ANNOTATION_MARKERS).freeze #: Regexp
Copy link
Copy Markdown
Contributor

@amomchilov amomchilov May 12, 2026

Choose a reason for hiding this comment

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

tiny opt:

Suggested change
RBS_REWRITE_PATTERN = Regexp.union(["#:", "#|"] + RBS_ANNOTATION_MARKERS).freeze #: Regexp
RBS_REWRITE_PATTERN = Regexp.union(["#:", "#|", *RBS_ANNOTATION_MARKERS]).freeze #: Regexp

Spares one allocation :)

require "bundler/inline"

gemfile do
  source "https://rubygems.org"
  gem "benchmark-memory"
end

a = [3, 4, 5]
Benchmark.memory do |x|
  x.report("    +") { [1, 2] + a }
  x.report("splat") { [1, 2, *a] }
  x.compare!
end

# Calculating -------------
#      +   120.000  memsize
#            2.000  objects
#  splat   208.000  memsize
#            1.000  objects


class << self
#: (String source) -> bool
def should_rewrite?(source)
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.

if this is going to be public API, perhaps contains_rbs_syntax? would be more clear to callers

end
end

def test_calls_new_for_files_with_rbs_syntax
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.

eh, I don't think this is a useful test. it's implied from the other more end-to-endy tests.

#{marker}
class Foo; end
RB
marker,
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.

Suggested change
marker,
"#should_rewrite? should return true for files containing #{marker}",

"# @sealed",
"# @final",
"# @requires_ancestor:",
"# @override",
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.

I think you can just move these here and remove the next test

Suggested change
"# @override",
"# @override",
"# @override(allow_incompatible: true)",
"# @override(allow_incompatible: false)",
"# @override(allow_incompatible: :visibility)",

end
end

def test_should_rewrite_returns_false_for_files_without_rbs_syntax
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.

Can you please reorder these, so related tests are better grouped together?

E.g. the def test_should_rewrite_returns_false_when_the_file_is_not_typed should be in this area, where the other test_should_rewrite_returns_false_for_ tests are

Comment thread rbi/spoom.rbi
end
end

Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs::RBS_ANNOTATION_MARKERS = T.let(T.unsafe(nil), Array)
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.

Let's mark these with private_constant where they're defined, so we don't expose them to the public.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Skip RBS rewriter when a file doesn't contain any RBS syntax

4 participants