-
-
Notifications
You must be signed in to change notification settings - Fork 638
Add RBS type signatures for improved type safety #1945
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
ec29344
Add RBS type signatures for React on Rails gem
justin808 2bd6a40
Fix RBS type signatures based on feedback
justin808 8d83c38
Improve RBS signatures based on code review feedback
justin808 16c9604
Fix RBS type accuracy and improve error handling
justin808 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| # rubocop:disable Metrics/BlockLength | ||
| namespace :rbs do | ||
| desc "Validate RBS type signatures" | ||
| task :validate do | ||
| require "rbs" | ||
| require "rbs/cli" | ||
|
|
||
| puts "Validating RBS type signatures..." | ||
|
|
||
| # Run RBS validate | ||
| result = system("bundle exec rbs -I sig validate") | ||
|
|
||
| case result | ||
| when true | ||
| puts "✓ RBS validation passed" | ||
| when false | ||
| puts "✗ RBS validation failed" | ||
| exit 1 | ||
| when nil | ||
| puts "✗ RBS command not found or could not be executed" | ||
| exit 1 | ||
| end | ||
| end | ||
|
|
||
| desc "Check RBS type signatures (alias for validate)" | ||
| task check: :validate | ||
|
|
||
| desc "List all RBS files" | ||
| task :list do | ||
| sig_files = Dir.glob("sig/**/*.rbs") | ||
| puts "RBS type signature files:" | ||
| sig_files.each { |f| puts " #{f}" } | ||
| puts "\nTotal: #{sig_files.count} files" | ||
| end | ||
| end | ||
| # rubocop:enable Metrics/BlockLength |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| # RBS Type Signatures | ||
|
|
||
| This directory contains RBS (Ruby Signature) type definitions for the React on Rails gem. | ||
|
|
||
| ## What is RBS? | ||
|
|
||
| RBS is Ruby's official type signature language. It provides type information for Ruby code, enabling: | ||
|
|
||
| - Better IDE support and autocomplete | ||
| - Static type checking with tools like Steep | ||
| - Improved documentation | ||
| - Early detection of type-related bugs | ||
|
|
||
| ## Structure | ||
|
|
||
| The signatures are organized to mirror the `lib/` directory structure: | ||
|
|
||
| - `react_on_rails.rbs` - Main module and core classes | ||
| - `react_on_rails/configuration.rbs` - Configuration class types | ||
| - `react_on_rails/helper.rbs` - View helper method signatures | ||
| - `react_on_rails/server_rendering_pool.rbs` - Server rendering types | ||
| - `react_on_rails/utils.rbs` - Utility method signatures | ||
| - And more... | ||
|
|
||
| ## Validation | ||
|
|
||
| To validate the RBS signatures: | ||
|
|
||
| ```bash | ||
| bundle exec rake rbs:validate | ||
| ``` | ||
|
|
||
| Or directly: | ||
|
|
||
| ```bash | ||
| bundle exec rbs -I sig validate | ||
| ``` | ||
|
|
||
| To list all RBS files: | ||
|
|
||
| ```bash | ||
| bundle exec rake rbs:list | ||
| ``` | ||
|
|
||
| ## Development | ||
|
|
||
| When adding new public methods or classes to the gem, please also add corresponding RBS signatures. | ||
|
|
||
| For more information about RBS: | ||
|
|
||
| - [RBS Documentation](https://github.com/ruby/rbs) | ||
| - [RBS Syntax Guide](https://github.com/ruby/rbs/blob/master/docs/syntax.md) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # Type signatures for ReactOnRails gem | ||
|
|
||
| module ReactOnRails | ||
| VERSION: String | ||
|
|
||
| DEFAULT_GENERATED_ASSETS_DIR: String | ||
| DEFAULT_COMPONENT_REGISTRY_TIMEOUT: Integer | ||
|
|
||
| def self.configure: () { (Configuration) -> void } -> void | ||
| def self.configuration: () -> Configuration | ||
|
|
||
| class Error < StandardError | ||
| end | ||
|
|
||
| class PrerenderError < Error | ||
| attr_reader component_name: String? | ||
| attr_reader js_code: String? | ||
| attr_reader err: Hash[Symbol, untyped]? | ||
| attr_reader props: (Hash[Symbol, untyped] | String)? | ||
| attr_reader console_messages: Array[String]? | ||
|
|
||
| def initialize: ( | ||
| ?component_name: String?, | ||
| ?js_code: String?, | ||
| ?err: Hash[Symbol, untyped]?, | ||
| ?props: (Hash[Symbol, untyped] | String)?, | ||
| ?console_messages: Array[String]? | ||
| ) -> void | ||
|
|
||
| def to_honeybadger_context: () -> Hash[Symbol, untyped] | ||
| def raven_context: () -> Hash[Symbol, untyped] | ||
| def to_error_context: () -> Hash[Symbol, untyped] | ||
| end | ||
|
|
||
| class JsonParseError < Error | ||
| def initialize: (Hash[Symbol, untyped] err) -> void | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| module ReactOnRails | ||
| class Configuration | ||
| attr_accessor node_modules_location: String? | ||
| attr_accessor server_bundle_js_file: String | ||
| attr_accessor prerender: bool | ||
| attr_accessor replay_console: bool | ||
| attr_accessor trace: bool | ||
| attr_accessor development_mode: bool | ||
| attr_accessor logging_on_server: bool | ||
| attr_accessor server_renderer_pool_size: Integer | ||
| attr_accessor server_renderer_timeout: Integer | ||
| attr_accessor skip_display_none: bool? | ||
| attr_accessor raise_on_prerender_error: bool | ||
| attr_accessor generated_assets_dirs: Array[String]? | ||
| attr_accessor generated_assets_dir: String | ||
| attr_accessor components_subdirectory: String? | ||
| attr_accessor webpack_generated_files: Array[String] | ||
| attr_accessor rendering_extension: String? | ||
| attr_accessor build_test_command: String | ||
| attr_accessor build_production_command: String | ||
| attr_accessor i18n_dir: String? | ||
| attr_accessor i18n_yml_dir: String? | ||
| attr_accessor i18n_output_format: Symbol? | ||
| attr_accessor i18n_yml_safe_load_options: Hash[Symbol, untyped]? | ||
| attr_accessor defer_generated_component_packs: bool | ||
| attr_accessor server_render_method: String? | ||
| attr_accessor random_dom_id: bool | ||
| attr_accessor auto_load_bundle: bool | ||
| attr_accessor same_bundle_for_client_and_server: bool | ||
| attr_accessor rendering_props_extension: String? | ||
| attr_accessor make_generated_server_bundle_the_entrypoint: bool | ||
| attr_accessor generated_component_packs_loading_strategy: Symbol? | ||
| attr_accessor immediate_hydration: bool | ||
| attr_accessor component_registry_timeout: Integer | ||
| attr_accessor server_bundle_output_path: String? | ||
| attr_accessor enforce_private_server_bundles: bool | ||
|
|
||
| def initialize: ( | ||
| ?node_modules_location: String?, | ||
| ?server_bundle_js_file: String?, | ||
| ?prerender: bool?, | ||
| ?replay_console: bool?, | ||
| ?make_generated_server_bundle_the_entrypoint: bool?, | ||
| ?trace: bool?, | ||
| ?development_mode: bool?, | ||
| ?defer_generated_component_packs: bool?, | ||
| ?logging_on_server: bool?, | ||
| ?server_renderer_pool_size: Integer?, | ||
| ?server_renderer_timeout: Integer?, | ||
| ?raise_on_prerender_error: bool?, | ||
| ?skip_display_none: bool?, | ||
| ?generated_assets_dirs: Array[String]?, | ||
| ?generated_assets_dir: String?, | ||
| ?webpack_generated_files: Array[String]?, | ||
| ?rendering_extension: String?, | ||
| ?build_test_command: String?, | ||
| ?build_production_command: String?, | ||
| ?generated_component_packs_loading_strategy: Symbol?, | ||
| ?same_bundle_for_client_and_server: bool?, | ||
| ?i18n_dir: String?, | ||
| ?i18n_yml_dir: String?, | ||
| ?i18n_output_format: Symbol?, | ||
| ?i18n_yml_safe_load_options: Hash[Symbol, untyped]?, | ||
| ?random_dom_id: bool?, | ||
| ?server_render_method: String?, | ||
| ?rendering_props_extension: String?, | ||
| ?components_subdirectory: String?, | ||
| ?auto_load_bundle: bool?, | ||
| ?immediate_hydration: bool?, | ||
| ?component_registry_timeout: Integer?, | ||
| ?server_bundle_output_path: String?, | ||
| ?enforce_private_server_bundles: bool? | ||
| ) -> void | ||
|
|
||
| def setup_config_values: () -> void | ||
|
|
||
| private | ||
|
|
||
| def check_component_registry_timeout: () -> void | ||
| def validate_generated_component_packs_loading_strategy: () -> void | ||
| def validate_enforce_private_server_bundles: () -> void | ||
| def check_minimum_shakapacker_version: () -> void | ||
| def check_autobundling_requirements: () -> void | ||
| def adjust_precompile_task: () -> void | ||
| def error_if_using_packer_and_generated_assets_dir_not_match_public_output_path: () -> void | ||
| def check_server_render_method_is_only_execjs: () -> void | ||
| def configure_generated_assets_dirs_deprecation: () -> void | ||
| def ensure_webpack_generated_files_exists: () -> void | ||
| def configure_skip_display_none_deprecation: () -> void | ||
| def raise_missing_components_subdirectory: () -> void | ||
| def compile_command_conflict_message: () -> String | ||
| def rsc_bundle_js_file: () -> String? | ||
| def react_client_manifest_file: () -> String? | ||
| def react_server_client_manifest_file: () -> String? | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| module ReactOnRails | ||
| module Controller | ||
| # Type alias for ActiveSupport::SafeBuffer (html_safe strings) | ||
| type safe_buffer = String | ||
|
|
||
| def redux_store: ( | ||
| String store_name, | ||
| ?props: untyped, | ||
| ?immediate_hydration: bool | ||
| ) -> void | ||
|
|
||
| # Returns html_safe string (ActiveSupport::SafeBuffer) | ||
| def redux_store_hydration_data: () -> safe_buffer | ||
| end | ||
| end | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| module ReactOnRails | ||
| module GitUtils | ||
| def self.uncommitted_changes?: (String path) -> bool | ||
| def self.git_installed?: () -> bool | ||
| def self.current_branch: () -> String? | ||
| def self.rspec_fixture_branches: () -> Array[String] | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| module ReactOnRails | ||
| module Helper | ||
| # Type alias for ActiveSupport::SafeBuffer (html_safe strings) | ||
| type safe_buffer = String | ||
|
|
||
| COMPONENT_HTML_KEY: String | ||
|
|
||
| # Main helper methods | ||
| # Returns html_safe string (ActiveSupport::SafeBuffer) | ||
| def react_component: ( | ||
| String component_name, | ||
| ?Hash[Symbol, untyped] options | ||
| ) ?{ () -> untyped } -> safe_buffer | ||
|
|
||
| # Returns hash with html_safe strings (ActiveSupport::SafeBuffer) | ||
| def react_component_hash: ( | ||
| String component_name, | ||
| ?Hash[Symbol, untyped] options | ||
| ) ?{ () -> untyped } -> Hash[String, safe_buffer] | ||
|
|
||
| # Returns html_safe string (ActiveSupport::SafeBuffer) | ||
| def redux_store: ( | ||
| String store_name, | ||
| ?Hash[Symbol, untyped] props | ||
| ) -> safe_buffer | ||
|
|
||
| # Returns html_safe string (ActiveSupport::SafeBuffer) | ||
| def redux_store_hydration_data: () -> safe_buffer | ||
|
|
||
| # Returns html_safe string (ActiveSupport::SafeBuffer) | ||
| def server_render_js: ( | ||
| String js_expression, | ||
| ?Hash[Symbol, untyped] options | ||
| ) -> safe_buffer | ||
|
|
||
| def sanitized_props_string: (untyped props) -> String | ||
|
|
||
| def rails_context: ( | ||
| ?server_side: bool | ||
| ) -> Hash[Symbol, untyped] | ||
|
|
||
| private | ||
|
|
||
| def internal_react_component: ( | ||
| String component_name, | ||
| Hash[Symbol, untyped] options | ||
| ) ?{ () -> untyped } -> Hash[Symbol, untyped] | ||
|
|
||
| def build_react_component_result_for_server_rendered_string: ( | ||
| server_rendered_html: String, | ||
| component_specification_tag: String, | ||
| console_script: String, | ||
| render_options: Hash[Symbol, untyped] | ||
| ) -> safe_buffer | ||
|
|
||
| def build_react_component_result_for_server_rendered_hash: ( | ||
| server_rendered_html: Hash[String, untyped], | ||
| component_specification_tag: String, | ||
| console_script: String, | ||
| render_options: Hash[Symbol, untyped] | ||
| ) -> Hash[String, safe_buffer] | ||
|
|
||
| def prepend_render_rails_context: (String result) -> safe_buffer | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| module ReactOnRails | ||
| module PackerUtils | ||
| def self.supports_autobundling?: () -> bool | ||
| def self.supports_basic_pack_generation?: () -> bool | ||
| def self.supports_async_loading?: () -> bool | ||
| def self.nested_entries?: () -> bool | ||
| def self.packer_public_output_path: () -> String | ||
| def self.precompile?: () -> bool | ||
| def self.shakapacker_precompile_hook_configured?: () -> bool | ||
| def self.shakapacker_precompile_hook_value: () -> String | ||
| def self.raise_shakapacker_version_incompatible_for_autobundling: () -> void | ||
| def self.raise_shakapacker_version_incompatible_for_basic_pack_generation: () -> void | ||
| def self.raise_nested_entries_disabled: () -> void | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| module ReactOnRails | ||
| module ServerRenderingPool | ||
| def self.pool: () -> untyped | ||
|
|
||
| def self.reset_pool_if_server_bundle_was_modified: () -> void | ||
| def self.reset_pool: () -> void | ||
| def self.server_render_js_with_console_logging: ( | ||
| String js_code, | ||
| Hash[Symbol, untyped] render_options | ||
| ) -> Hash[String, untyped] | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| module ReactOnRails | ||
| module TestHelper | ||
| def self.configure_rspec_to_compile_assets: (untyped config) -> void | ||
| def self.ensure_assets_compiled: (?force_compile: bool) -> void | ||
| def self.webpack_assets_compiled?: () -> bool | ||
|
|
||
| module EnsureAssetsCompiled | ||
| def self.has_been_run?: () -> bool | ||
| end | ||
| end | ||
| end |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Past issue resolved; verify props type consistency with Helper.
The
immediate_hydrationparameter is now correctly typed asbool(matching the past review recommendation). However, thepropsparameter is typed asuntypedhere, while the correspondingredux_storemethod insig/react_on_rails/helper.rbs(lines 16-19) types it asHash[Symbol, untyped]. Consider using the same type in both signatures to maintain consistency across the API surface.🏁 Script executed:
Length of output: 814
I need to verify the actual Helper RBS signature that the review mentions. Let me search for it in the codebase.
I need to verify the actual RBS signatures in the repository since I can't do more web searches. Let me check the codebase directly.
🏁 Script executed:
Length of output: 1834
🏁 Script executed:
Length of output: 217
Correct props type in Controller RBS to match Helper and implementation.
The
immediate_hydrationparameter is correctly typed asbool. However, thepropsparameter in Controller RBS is typed asuntyped, while both the Helper RBS (lines 12-14) and the actual Controller implementation (which defaultspropsto{}) indicate it should beHash[Symbol, untyped]. Updatesig/react_on_rails/controller.rbsline 5 to use?props: Hash[Symbol, untyped]for consistency.🤖 Prompt for AI Agents