Skip to content

Exclude generated files from relocations#6627

Draft
ikhoon wants to merge 2 commits intoline:mainfrom
ikhoon:shade-exclude-gen-files
Draft

Exclude generated files from relocations#6627
ikhoon wants to merge 2 commits intoline:mainfrom
ikhoon:shade-exclude-gen-files

Conversation

@ikhoon
Copy link
Contributor

@ikhoon ikhoon commented Feb 12, 2026

Motivation:

Explain why you're making this change and what problem you're trying to solve.

Modifications:

  • List the modifications you've made in detail.

Result:

  • Closes #. (If this resolves the issue.)
  • Describe the consequences that a user will face after this PR is merged.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 12, 2026

📝 Walkthrough

Walkthrough

This PR modifies the Gradle build configuration to improve handling of Thrift-generated Java sources. Changes include registering a dedicated "javaThrift" directory for generated sources in the Spring build utilities, updating the Thrift compilation output path, and implementing logic to exclude generated Thrift/gRPC/Proto classes from the shading process with debug logging.

Changes

Cohort / File(s) Summary
Spring Build Utilities
buildSrc/src/main/java/com/linecorp/armeria/conventions/spring/SpringBuildUtil.java
Adds "gen-src/test/javaThrift" and "gen-src/main/javaThrift" to the additionalSourceDirs arrays for TEST and MAIN source sets respectively.
Thrift Compilation Configuration
gradle/scripts/lib/java-rpc-thrift.gradle
Updates Java output directory path from ${scope}/java to ${scope}/javaThrift and adds guard condition to register javaOutputDir as a sourceDir when not already included in the source set.
Shading Configuration
gradle/scripts/lib/java-shade.gradle
Introduces isGenerated(project, path, isMain) helper function to detect generated sources; enhances relocation shading loop with exclusion logic for generated classes and debug logging for each relocation.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 With files renamed to javaThrift's way,
Generated sources have their place to stay,
Shading now knows to leave them be,
From thrift and proto, forever free! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description contains only the template placeholder text without substantive content describing the motivation, modifications, or results of the changes. Fill in the PR description template with actual content explaining why generated files need to be excluded, what modifications were made, and the resulting behavior.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: excluding generated files from relocations during the shading process.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@gradle/scripts/lib/java-shade.gradle`:
- Around line 374-381: The relocate block currently uses a closure-based exclude
(task.relocate(...) { exclude { ... } }) which ShadowJar does not support;
remove the closure-based exclude and instead implement the generated-source
check via a custom Relocator and register it with task.relocate, or convert to
string/regex excludes if generated classes follow a predictable package/path.
Specifically, remove the exclude closure from the task.relocate call and create
a class implementing Shadow's Relocator interface (override canRelocatePath or
canRelocateClass to call isGenerated(project, path, isMain)), then add that
Relocator instance to task.relocate so generated files are skipped during
relocation.
🧹 Nitpick comments (1)
gradle/scripts/lib/java-shade.gradle (1)

418-421: Edge case: classes with $ in the package path.

Line 421 splits on $ to extract the top-level class name, which correctly handles inner classes like com/foo/Outer$Inner. However, if any generated code produces file paths containing $ in directory names (rare, but possible with some code generators), this could incorrectly truncate the path. This is an unlikely edge case given standard Java conventions, just noting it.

Comment on lines +374 to 381
logger.debug("[${project.name}] Relocating ${props['name']} from ${props['from']} to ${props['to']} " +
"in ${isMain ? 'main' : 'test'}")
task.relocate(props['from'], props['to']) {
exclude {
return isGenerated(project, it.path, isMain)
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Find Shadow plugin version
rg "com.gradleup.shadow|com.github.jengelman.gradle.plugins.shadow" --type=gradle,toml -C2

Repository: line/armeria

Length of output: 91


🏁 Script executed:

# Check how relocate is used elsewhere in the codebase
rg "\.relocate\(" --type=groovy -C5

Repository: line/armeria

Length of output: 859


🌐 Web query:

Shadow Gradle plugin relocate exclude closure predicate API

💡 Result:

In the ShadowJar relocate(from, to) { … } block, exclude/include are path-pattern filters, not predicate closures. You pass Ant-style path match patterns (and optionally %regex[...] patterns), e.g.:

tasks.shadowJar {
  relocate('junit.textui', 'a') {
    exclude 'junit.textui.TestRunner'   // Ant-path style
  }
  relocate('org.foo', 'a') {
    include '%regex[org/foo/.*Factory[0-9].*]'  // regex form
  }
}

[1]

If what you want is a closure/predicate-style exclude, that API exists for dependency filtering (i.e., which dependencies get merged), via tasks.shadowJar { dependencies { exclude { dep -> … } } }, e.g.:

tasks.shadowJar {
  dependencies {
    exclude { it.moduleGroup == 'org.apache.logging.log4j' }
  }
}

[2]


Remove the closure-based exclude from relocate — Shadow plugin does not support predicate closures in relocate blocks.

The exclude/include methods in ShadowJar's relocate configuration accept only Ant-style path patterns or regex patterns (e.g., exclude 'com/foo/Bar'), not closure-based predicates. The code at lines 376–379 will be silently ignored or cause a runtime error.

To exclude generated sources during relocation, either:

  1. Use string patterns if all generated sources follow a predictable path pattern, or
  2. Implement a custom Relocator that performs the generated-source check in canRelocatePath or canRelocateClass methods.

The isGenerated function (lines 411–437) is correctly implemented but needs to be applied via the correct API.

🤖 Prompt for AI Agents
In `@gradle/scripts/lib/java-shade.gradle` around lines 374 - 381, The relocate
block currently uses a closure-based exclude (task.relocate(...) { exclude { ...
} }) which ShadowJar does not support; remove the closure-based exclude and
instead implement the generated-source check via a custom Relocator and register
it with task.relocate, or convert to string/regex excludes if generated classes
follow a predictable package/path. Specifically, remove the exclude closure from
the task.relocate call and create a class implementing Shadow's Relocator
interface (override canRelocatePath or canRelocateClass to call
isGenerated(project, path, isMain)), then add that Relocator instance to
task.relocate so generated files are skipped during relocation.

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.

2 participants