Skip to content

Add --inline option to load inline RBS declarations from Ruby files - #3204

Draft
ksss wants to merge 1 commit into
ruby:masterfrom
ksss:inline-loader-option
Draft

ksss wants to merge 1 commit into
ruby:masterfrom
ksss:inline-loader-option

Conversation

@ksss

@ksss ksss commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation

rbs validate only checks RBS files. With inline RBS declarations, part of the signatures now live in Ruby files, and the rbs command has no way to load them. So inline declarations are never validated, and each tool that consumes them (type checkers, etc.) has to validate them by itself.

If rbs validate can check inline declarations, tools can rely on "the signatures pass rbs validate" as a precondition, regardless of the language they are implemented in.

What this PR does

Adds --inline DIR as a library option, next to -I DIR.

$ rbs -I sig --inline lib validate
  • The rbs command doesn't guess which Ruby files to load. Users give them explicitly, as they do with -I.
  • It follows the same rules as -I: a directory loads all .rb files under it (recursively, sorted), and a file is loaded regardless of its extension. FileFinder.each_file gets an extension: keyword so that both options share the implementation.
  • EnvironmentLoader#add(inline:) collects the paths, and EnvironmentLoader#load parses the files with InlineParser and adds Source::Ruby to the environment.
  • Since it is a library option, it works with every command that loads the environment (validate, method, methods, ancestors, ...). rbs paths shows the paths as lib (dir, inline).
  • Commands that rewrite RBS files directly (parse, annotate, subtract, bin/sort) don't use the loader, and they are not affected.

rbs validate

  • CLI::Validate assumed RBS AST and crashed on Ruby declarations (Location#aref(:type_params), super_class.args, member.name of mixins). It now handles both.
  • Validator#validate_class_alias uses the whole location for Ruby alias declarations, which don't have the old_name child location.
  • InlineParser diagnostics are reported as warnings, and they don't make the command fail.
ERROR -- rbs: lib/calc.rb:2:31...2:37: Could not find Intger (RBS::NoTypeFoundError)

    # @rbs (Integer, Integer) -> Intger
                                 ^^^^^^
WARN -- rbs: lib/calc.rb:16:4...16:12: Top-level method definition is not supported (RBS::InlineParser::Diagnostic::TopLevelMethodDefinition)

Error message snippet fix

DetailedMessageable#detailed_message printed the source line from location.buffer. Inline annotations are parsed in sub-buffers, and Location#start_line is in the top buffer's coordinates, so the printed line was empty (or wrong). It now uses location.buffer.top_buffer. This only happens with inline declarations, so it is included here.

Open questions

  • Diagnostics severity. They are warnings because they are reported for ordinary Ruby code without any annotations, which a project adopting inline RBS still has. For example, class Foo < Struct.new(...) gives NonConstantSuperClassName, and RDoc's #:nodoc: gives AnnotationSyntaxError. These patterns are common in real code: running the parser over some installed gems found 12 Struct.new superclasses in steep and 3 #:nodoc: comments in rake. With errors, such a project couldn't pass rbs validate without rewriting unrelated code. But this means a broken annotation like # @rbs ( is only a warning. Should AnnotationSyntaxError, or some others, be errors?
  • Option name. --inline matches InlineParser and the "inline RBS" term in the docs. There is no short form.

Not changed

  • The same type error can be reported more than once (an attr_reader type is checked as both the method and the instance variable, and an error in an ancestor is reported for each class). .rbs files behave the same way.

🤖 Generated with Claude Code

`rbs` commands only loaded RBS files, so `rbs validate` could not check
inline RBS declarations written in Ruby files.

This adds `--inline DIR` as a library option alongside `-I DIR`. It loads
all `.rb` files under the directory (or the given file) through
`InlineParser`, using the same file finding rules as `-I`.

`rbs validate` now validates the inline declarations too, and reports the
inline parser diagnostics as warnings. This also fixes the error message
snippet for locations in sub-buffers, which inline annotations use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant