Search code examples
sorbet

How do I use `srb rbi suggest-typed` without downgrading sigils?


The Sorbet typechecker for Ruby has a utility, srb rbi suggest-typed, which will automatically update the # typed: sigils on each file. However, as the Sorbet docs explain, “currently, the suggestion process is fallible, and may suggest downgrading when it's not necessary.” I have a Sorbet-typed codebase that I’d like to try upgrading the types on (to “ratchet” any files that have been fully typed without having their sigil changed), but because it’s a very large codebase I don’t want to have to manually audit every file that’s changed. Is there a way to get Sorbet to only apply a change to the sigil if it’s an upgrade?


Solution

  • There doesn’t seem to be any way to get Sorbet to do this itself. Instead, as a workaround, here are some instructions for using Git to only commit the changes that upgrade the sigil, and discard any changes that would be a downgrade.

    1. Start with a clean working directory (make sure git status doesn’t show any changed files).
    2. Run srb rbi suggest-typed. This will change a lot of sigils, both upgrading and downgrading them.
    3. Produce a summary of the different kinds of changes that have been made:
      git diff --word-diff -U0 | grep '# typed: ' | sort | uniq -c
      
        36 # typed: [-false-]{+ignore+}
         8 # typed: [-false-]{+strict+}
        27 # typed: [-false-]{+true+}
        36 # typed: [-strict-]{+false+}
       150 # typed: [-true-]{+strict+}
        80 {+# typed: false+}
      
    4. Use grepdiff to find each of the changes you don’t want, and pipe the result to git checkout to drop those changes (modify the below commands as needed for the changes you have gotten):
      git diff | grepdiff --output-matching=hunk --only-match=rem 'typed: false'  | grepdiff --only-match=add 'typed: ignore' --strip=1 | xargs git checkout --
      git diff | grepdiff --output-matching=hunk --only-match=rem 'typed: strict' | grepdiff --only-match=add 'typed: false'  --strip=1 | xargs git checkout --
      git diff | grepdiff --only-match=add 'typed: false' --strip=1 | xargs git checkout --
      
    5. Rerun the summary command from step 3 to make sure the results include only what you want.
    6. Commit.