tapioca icon indicating copy to clipboard operation
tapioca copied to clipboard

Ruby LSP Tapioca addon generates incomplete RBI files

Open olivier-thatch opened this issue 8 months ago • 1 comments

In our codebase, when the Tapioca addon for Ruby LSP regenerates RBI after a routes change, three of the RBI files are missing some definitions.

Specifically:

  • sorbet/rbi/dsl/application_controller.rbi is missing helper methods:
 class ApplicationController
   include GeneratedUrlHelpersModule
   include GeneratedPathHelpersModule
-
-  sig { returns(HelperProxy) }
-  def helpers; end
-
-  module HelperMethods
-    include ::Turbo::DriveHelper
-    # <snip>
-    include ::Pundit::Helper
-
-    sig { returns(T.nilable(::Member)) }
-    def current_member; end
-
-    sig { returns(T.untyped) }
-    def error; end
-
-    sig { params(record: T.untyped).returns(T.untyped) }
-    def policy(record); end
-
-    sig { params(scope: T.untyped).returns(T.untyped) }
-    def pundit_policy_scope(scope); end
-
-    sig { returns(::ApplicationPolicy::UserContext) }
-    def pundit_user; end
-
-    sig { returns(T.untyped) }
-    def success; end
-
-    sig { returns(T.untyped) }
-    def true_user; end
-  end
-
-  class HelperProxy < ::ActionView::Base
-    include HelperMethods
-  end
 end
  • sorbet/rbi/dsl/devise/mailer.rbi is missing mailer methods (this class comes from the Devise gem):
 class Devise::Mailer
   include GeneratedUrlHelpersModule
-
-  class << self
-    sig { params(record: T.untyped, token: T.untyped, opts: T.untyped).returns(::ActionMailer::MessageDelivery) }
-    def confirmation_instructions(record, token, opts = T.unsafe(nil)); end
-
-    sig { params(record: T.untyped, opts: T.untyped).returns(::ActionMailer::MessageDelivery) }
-    def email_changed(record, opts = T.unsafe(nil)); end
-
-    sig { params(record: T.untyped, opts: T.untyped).returns(::ActionMailer::MessageDelivery) }
-    def password_change(record, opts = T.unsafe(nil)); end
-
-    sig { params(record: T.untyped, token: T.untyped, opts: T.untyped).returns(::ActionMailer::MessageDelivery) }
-    def reset_password_instructions(record, token, opts = T.unsafe(nil)); end
-
-    sig { params(record: T.untyped, token: T.untyped, opts: T.untyped).returns(::ActionMailer::MessageDelivery) }
-    def unlock_instructions(record, token, opts = T.unsafe(nil)); end
-  end
 end
  • sorbet/rbi/dsl/rambulance/exceptions_app.rbi is also missing helper methods (this class comes from the Rambulance gem):
 class Rambulance::ExceptionsApp
   include GeneratedUrlHelpersModule
   include GeneratedPathHelpersModule
-
-  sig { returns(HelperProxy) }
-  def helpers; end
-
-  module HelperMethods
-    include ::Turbo::DriveHelper
-    # <snip>
-    include ::DeviseHelper
-
-    sig { returns(T.untyped) }
-    def exception; end
-
-    sig { returns(T.untyped) }
-    def status_in_words; end
-  end
-
-  class HelperProxy < ::ActionView::Base
-    include HelperMethods
-  end
 end

This behavior is annoying enough that we resorted to disabling the Tapioca addon for now, and asking developers to manually run bin/tapioca dsl after updating routes.

On the other hand, the issue is very consistent and easy to reproduce, so let me know if you need more details or need me to do anything to help debug this issue.

olivier-thatch avatar Apr 15 '25 21:04 olivier-thatch

@olivier-thatch Thanks for reporting this! I'll try to repro.

egiurleo avatar Apr 15 '25 21:04 egiurleo

We are experiencing the same issue: Here is some more information for our case

  • Rails 7.0.8.7
  • Ruby 3.3.7

Debugging the Tapioca LSP Addon i see that the ApplicationController is loaded when requesting the "route_dsl" server addon in the rails instance.

The combination of

  1. lib/ruby_lsp/tapioca/server_addon.rb:38. when "route_dsl" that runst Tapioca with only the UrlHelpers compiler
  2. Plus the fact that the ApplicationController is loaded when calling ::Tapioca::Dsl::Compilers::UrlHelpers.gather_constants

Makes the tapioca addon to run something similar to bin/tapioca dsl ApplicationController --only Tapioca::Dsl::Compilers::UrlHelpers ActiveSupportConcern.

And that ends removing some other content generated by the other compilers.

The same happens not only for ApplicationController but for other classes in our project too.

I think that the root cause is that there are constants that are generated by multiple compilers, and recompiling those .rbi with the --only flag makes those rbi get the rbi generated by other compilers pruned.

How to replicate

  1. Load a constant that is affected by Tapioca::Dsl::Compilers::UrlHelpers and another compiler. In this case i replicate with ApplicationController.
# config/routes.rb
Rails.application.routes.draw do
  a = ApplicationController
  get "up" => "rails/health#show", as: :rails_health_check
end
  1. Comment the get to trigger a dsl compiling of routes.
  2. The application_controller.rbi helpers rbi is going to get removed (bug).

I propose that the addon keeps updating the constants gathered by the compiler, but run the tapioca dsl without the --only flag, effectevily keeping the content written by other compilers in those .rbi files.

I will open a PR

domingo2000 avatar Jul 22 '25 01:07 domingo2000

I think this was done because we thought UrlHelpers compiler was distinct enough but I can see that ApplicationController is returned as part of UrlHelpers.gather_constants. We can either not call gather_constants and regenerate generated_path_helpers_module/generated_url_helpers_module or we can remove the --only flag as you have.

Unfortunately I don't think we can do the first option since you could have a constant that no longer should include the helper modules and needs updating. So I think we have to go with removing --only 😕

cc @vinistock

KaanOzkan avatar Jul 23 '25 19:07 KaanOzkan

Yeah, I think we'll need to remove the --only for now. The idea was to get better performance and avoid having other compilers run, but then we would need it to not remove RBIs generated by other compilers.

vinistock avatar Jul 24 '25 14:07 vinistock

@vinistock already done that in this PR if you could review it 👍🏻 .

domingo2000 avatar Jul 24 '25 20:07 domingo2000