Skip to content

feat(gazelle): resolve class-level deps via external CrossResolvers#458

Open
shs96c wants to merge 1 commit into
bazel-contrib:mainfrom
shs96c:shs-gazelle-class-level-cross-resolver
Open

feat(gazelle): resolve class-level deps via external CrossResolvers#458
shs96c wants to merge 1 commit into
bazel-contrib:mainfrom
shs96c:shs-gazelle-class-level-cross-resolver

Conversation

@shs96c

@shs96c shs96c commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

External Gazelle extensions (e.g. a Wire or third-party protobuf generator) can already provide package-level Java resolutions via resolve.CrossResolver. They cannot provide class-level resolutions, so a split package, where some classes of a Java package come from an external extension's target and hand-written sources in the same package are built by a java_library/kt_jvm_library this extension generates, can't be resolved correctly.

The hand-written source registers the package in Gazelle's global index, so package resolution returns a single match. Gazelle only consults CrossResolve on a zero-result index miss, so the external co-provider is never seen and the split goes undetected.

Precedence is preserved: # gazelle:resolve directive > in-repo class > CrossResolver.

External-plugin contract

An external extension contributes class-level resolutions by implementing resolve.CrossResolver and answering dotted fully-qualified class names for lang == "java":

func (e *myExtension) CrossResolve(c *config.Config, ix *resolve.RuleIndex, imp resolve.ImportSpec, lang string) []resolve.FindResult {
    if imp.Lang != "java" {
        return nil
    }
    if target, ok := e.classToTarget[imp.Imp]; ok { // imp.Imp e.g. "com.example.foo.MyMessage"
        return []resolve.FindResult{{Label: target}}
    }
    return nil
}

🤖 Generated with Claude Code

Class import specs are intentionally never registered in Gazelle's global
index, so a class-level FindRulesByImportWithConfig lookup always falls
through to registered CrossResolvers. Use this to let external extensions
(e.g. wire/proto generators) provide class-level Java resolutions, including
split packages where in-repo java/kotlin source coexists with externally
generated classes in the same package.

Precedence is unchanged: gazelle:resolve > in-repo class > CrossResolver.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@shs96c shs96c marked this pull request as ready for review June 26, 2026 11:38
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