Skip to content

Add concern class methods for classes defined in gems - #448

Closed
apiology wants to merge 4 commits into
masterfrom
extend-concern-class-methods-from-gem-includes
Closed

apiology wants to merge 4 commits into
masterfrom
extend-concern-class-methods-from-gem-includes

Conversation

@apiology

@apiology apiology commented Oct 30, 2026 •

Copy link
Copy Markdown
Owner

Claude: This PR was written by Claude Code on behalf of @apiology.

Problem:

A class defined in a gem loses the ClassMethods of the concerns it includes:

# Gem source (activesupport in the Gemfile):
module Support
  module Callbacks
    extend ActiveSupport::Concern
    module ClassMethods
      def set_callback; end
    end
  end
end

module Job
  module Callbacks
    extend ActiveSupport::Concern
    include Support::Callbacks
    module ClassMethods
      def before_perform; end
    end
  end

  class Base
    include Callbacks
  end
end

# Workspace: Unresolved call to before_perform
Job::Base.before_perform
# Unresolved call to set_callback (in workspace source too)
Job::Base.set_callback

Since castwide#1469 removed Convention::ActiveSupportConcern, ActiveJob::Base (.set_callback, .rescue_from), Rails::Application and ActionController::Base (.config, .view_context_class) lose class methods from the concerns they include.

Solution:

Give Plugin::Panel the gem and stdlib pins (loading requires before plugins run) and have Plugin::ActiveSupport treat each included module and its nested includes as ActiveSupport::Concern does: extend the includer with their ClassMethods, and for concerns also copy their own class methods and extends (from class_methods and included blocks) onto the includer.

apiology and others added 3 commits October 29, 2026 23:43
Plugin::ActiveSupport added an extend of ClassMethods only for
includes in workspace source maps. Since Convention::ActiveSupportConcern
was removed, classes defined in gems (ActiveJob::Base,
ActionController::Base, Rails::Application) lost class methods that
come from concerns they include, e.g. ActiveSupport::Callbacks
.define_callbacks.

Load external requires before running plugins and pass the external
pins to the plugin panel, so the plugin also sees includes from gems
and stdlib.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhUSLUimEYJyCZv8NdQGKb
ActiveSupport::Concern extends an includer with the ClassMethods of
the concern's own dependencies too: ActiveJob::Base includes
ActiveJob::Callbacks, which includes ActiveSupport::Callbacks, so
ActiveJob::Base gets set_callback. Plugin::ActiveSupport only extended
the ClassMethods of the directly included module.

Resolve each included module lexically and also extend the includer
with the ClassMethods of the modules it includes, at any depth.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhUSLUimEYJyCZv8NdQGKb
ActiveSupport::Concern runs a concern's included block and
class_methods block in the includer, so the includer gets the
concern's class methods and extends (e.g., ActiveRecord::Core's
self.configurations, ActiveSupport::Callbacks' DescendantsTracker).
Copy those pins onto the includer for each concern it includes,
directly or as a dependency.

Extend only ClassMethods defined in the included module itself:
for an include of an undefined module, the old X::ClassMethods
reference resolved lexically to an enclosing namespace's
ClassMethods, e.g. ActiveRecord::Base::ClassMethods with its
generics unbound.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhUSLUimEYJyCZv8NdQGKb
@apiology
apiology marked this pull request as ready for review October 30, 2026 08:28
Strong typecheck inferred Array, Array<Array> for the recursive
flat_map in nested_include_paths; push into a typed result array
instead.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhUSLUimEYJyCZv8NdQGKb
apiology added a commit to iftheshoefritz/solargraph-rails that referenced this pull request Oct 30, 2026
0.62.0 ships castwide/solargraph#1469, which stopped extending
classes defined in gems with their concerns ClassMethods, so the
Devise and ActiveStorage completion specs fail on it.
apiology/solargraph#448 restores that. Skip on exactly 0.62.0, like
rails_spec broken_versions, so a later broken release still fails.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhUSLUimEYJyCZv8NdQGKb
@apiology

Copy link
Copy Markdown
Owner Author

Claude: Moved upstream to castwide#1476 (same branch).

@apiology apiology closed this Oct 30, 2026
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