Skip to content
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

Fix circular require #183

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

davebenvenuti
Copy link
Contributor

@davebenvenuti davebenvenuti commented Jan 30, 2025

Fixes: #173

There's no need for TypeHelper to be namespaced under the CodeGen class if its intent is to be a reusable module. This PR renames the file to match the module name and puts it directly under the ProtoBoeuf module.

@davebenvenuti davebenvenuti marked this pull request as ready for review January 30, 2025 17:38
@davebenvenuti davebenvenuti requested review from rwstauner, nirvdrum and tenderworks and removed request for rwstauner January 30, 2025 17:38
Copy link
Contributor

@rwstauner rwstauner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine.
Worth considering, though: Do we want the require_relative or should we just autoload this like the rest of the constants 🤔

test/gem_test.rb Outdated Show resolved Hide resolved

private

def assert_rb_runs_successfully(ruby, msg = "Ruby returned non-zero exit status")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@davebenvenuti davebenvenuti added the #gsd:43107 Ruby Language: RPC Code Generation for Shopify Internal APIs [GSD 43107] label Jan 30, 2025
@davebenvenuti
Copy link
Contributor Author

davebenvenuti commented Jan 30, 2025

@rwstauner

Do we want the require_relative or should we just autoload this like the rest of the constants 🤔

I know we talked about this offline a bit, but I'm not sure what the convention is here.

One option for autoloading looks like this:

diff --git a/lib/protoboeuf.rb b/lib/protoboeuf.rb
index bd3a0c6..b3c2dcd 100644
--- a/lib/protoboeuf.rb
+++ b/lib/protoboeuf.rb
@@ -3,4 +3,6 @@
 module ProtoBoeuf
   autoload :CodeGen, "protoboeuf/codegen"
   autoload :Google, "protoboeuf/google"
+
+  autoload :TypeHelper, "protoboeuf/type_helper"
 end
diff --git a/lib/protoboeuf/codegen.rb b/lib/protoboeuf/codegen.rb
index b28ebcc..18f6f9b 100644
--- a/lib/protoboeuf/codegen.rb
+++ b/lib/protoboeuf/codegen.rb
@@ -9,7 +9,7 @@ module ProtoBoeuf
     class EnumCompiler
       attr_reader :generate_types
 
-      include TypeHelper
+      include ProtoBoeuf::TypeHelper
 
       class << self
         def result(enum, generate_types:, options: {})
@@ -79,7 +79,7 @@ module ProtoBoeuf
     class MessageCompiler
       attr_reader :generate_types, :requires
 
-      include TypeHelper
+      include ProtoBoeuf::TypeHelper
 
       class << self
         def result(message, toplevel_enums, generate_types:, requires:, syntax:, options: {})

The reason for fully qualifying the module name in the include statements is so the constant can be autoloaded. Otherwise, a bare TypeHelper just looks like an undefined constant.

On the one hand, autoloading the module makes things a little more consistent. On the other, the purpose of autoload is to avoid requiring dependencies that we don't end up using if certain code paths aren't executed. In the case of CodeGen and its nested classes, this is a hard requirement - 100% of code paths require the TypeHelper module. Also, now the dependency of codegen.rb is defined outside of codegen.rb which is a little weird.

Another option is to move the autoload to codegen.rb, like the following:

diff --git a/lib/protoboeuf/codegen.rb b/lib/protoboeuf/codegen.rb
index b28ebcc..43188c3 100644
--- a/lib/protoboeuf/codegen.rb
+++ b/lib/protoboeuf/codegen.rb
@@ -2,9 +2,10 @@
 
 require "erb"
 require "syntax_tree"
-require_relative "type_helper"
 
 module ProtoBoeuf
+  autoload :TypeHelper, "protoboeuf/type_helper"
+
   class CodeGen
     class EnumCompiler
       attr_reader :generate_types

This is a little better, because now the dependency of codegen.rb is defined in the same file, but it feels superfluous because there's no case where codegen.rb would be loaded but not type_helper.rb.

I'm leaning towards keeping is as a require_relative as it is now but I'm open to feedback.

test/gem_test.rb Outdated

::ProtoBoeuf

# The following should autoloaded

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we assert these autoload using Module#autoload??

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change isn't technically related to this PR. The only reason it shows up in this diff is because I moved the Tempfile stuff we were doing here to the private assert_rb_runs_successfully helper method. But yeah that's probably worth verifying.


refute_match(/warning: loading in progress, circular require considered harmful/, stderr)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like being specific, but I'm a bit worried that any change in the warning message could cause this test to pass unexpectedly. These messages aren't really stable across Ruby versions. I'm not sure if JRuby or TruffleRuby even emit them identically.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you suggest refuting a match on a subset of the message, like /circular require/? I suppose that's more likely to be consistent across platforms and versions. Our generated code currently produces other warnings so simply asserting that we don't have any warnings won't work I'm afraid.

@rwstauner
Copy link
Contributor

I think we can just leave it as require_relative since this module is going to use it and there probably isn't anything else that will request it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
#gsd:43107 Ruby Language: RPC Code Generation for Shopify Internal APIs [GSD 43107]
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Circular require
3 participants