Shopify/tapioca

Suppress "WARNING: Multiple constants with the same name" in LSP mode

amomchilov opened this issue · 0 comments

When running the Tapioca DSLGenerate from the Ruby LSP, we're seeing these warnings:

WARNING: Multiple constants with the same name: ...

$stderr.puts("WARNING: Multiple constants with the same name: #{reloaded_constant_names}")
$stderr.puts("Make sure some object is not holding onto these constants during an app reload.")

This didn't used to happen before, because each run was invoked by a separate bin/tapioca dsl ... command, in a fresh process, with an independent copy of the Rails server. When running in the LSP, and the Rails server is reused, with multiple DSLGenerate calls happening within the lifetime of that single process.

This interacts poorly with Zeitwerk reloading. Each reload of example.rb would create a new instance of Class called Example. Surprisingly, the old copy of Class does not go away. When Tapicoa uses ObjectSpace.each_object(Module), it'll find both the old Example class, and the new one.

There would have been a risk that Tapioca would non-deterministically render RBIs for a stale version of the constant, but luckily that doesn't happen because it can find the newest one with this constantize:

.map { |name| T.cast(Runtime::Reflection.constantize(name), Module) }

I.e. whichever Module/Class is currently bound to that constant name, is the newer one.

So because this isn't an issue, perhaps this warning should be suppressed when it happens on the second run of a pipeline? I.e. it'll trigger up to once in the LSP mode, but then never again. For CLI runs, it'll continue to trigger on every run.