Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,30 @@ public fun Relocator.relocatePath(path: String): String {
return relocatePath(RelocatePathContext(path))
}

/**
* Relocates all matching class and package names in the given [text].
*
* Unlike [relocateClass], which operates on a single class name (subject to prefix/format checks in
* [Relocator.canRelocateClass] and single-occurrence replacement), this function performs global
* replacement across arbitrary text content (e.g. `MANIFEST.MF` attributes or ProGuard/R8 rules).
*
* For [SimpleRelocator], it directly replaces all occurrences of [SimpleRelocator.pattern] with
* [SimpleRelocator.shadedPattern]. For generic [Relocator]s, it delegates to [relocateClass] if
* applicable.
*/
internal fun Relocator.relocateText(text: String): String {
if (this is SimpleRelocator) {
return when {
pattern.isEmpty() -> text
else -> text.replace(pattern, shadedPattern)
Comment thread
Goooler marked this conversation as resolved.
}
}
return when {
canRelocateClass(text) -> relocateClass(text)
else -> text
}
}

public fun Iterable<Relocator>.relocateClass(className: String): String {
forEach { relocator ->
if (relocator.canRelocateClass(className)) {
Expand All @@ -29,3 +53,14 @@ public fun Iterable<Relocator>.relocatePath(path: String): String {
}
return path
}

/**
* Sequentially relocates all matching class and package names in the given [text] across all
* relocators in this collection.
*
* Unlike [Iterable.relocateClass] which stops at the first matching relocator, this function passes
* the text through every relocator in a chain-of-responsibility pipeline so that all patterns
* present in the text are relocated.
*/
internal fun Iterable<Relocator>.relocateText(text: String): String =
fold(text) { acc, relocator -> relocator.relocateText(acc) }
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package com.github.jengelman.gradle.plugins.shadow.transformers
import com.github.jengelman.gradle.plugins.shadow.internal.checkDupStrategy
import com.github.jengelman.gradle.plugins.shadow.internal.writeEntry
import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator
import com.github.jengelman.gradle.plugins.shadow.relocation.relocateClass
import com.github.jengelman.gradle.plugins.shadow.relocation.relocatePath
import com.github.jengelman.gradle.plugins.shadow.relocation.relocateText
import org.apache.tools.zip.ZipOutputStream
import org.gradle.api.file.FileTreeElement
import org.gradle.api.tasks.Internal
Expand Down Expand Up @@ -50,20 +50,10 @@ constructor(patternSet: PatternSet = PatternSet().include("META-INF/proguard/**"
}

internal companion object {
/**
* Matches Java class names, fully qualified class names, package wildcards (e.g. `com.foo.**`),
* and inner classes (`com.foo.Bar$Inner`).
*/
private val CLASS_PATTERN =
"""(?<![a-zA-Z0-9_$.])([a-zA-Z_$][a-zA-Z0-9_$]*(?:\.[a-zA-Z0-9_$*?]+)+)""".toRegex()

fun Iterable<Relocator>.relocateRuleLine(line: String): String {
return when {
line.isBlank() || line.trimStart().startsWith("#") -> line
else ->
CLASS_PATTERN.replace(line) { matchResult ->
relocateClass(matchResult.value)
}
else -> relocateText(line)
}
Comment thread
Goooler marked this conversation as resolved.
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,27 @@ class RelocatorsTest {
.isEqualTo("shadow.org.package.Bar")
}

@Test
fun relocateTextChained() {
val relocators =
listOf(
SimpleRelocator("org.foo", "shaded.foo"),
SimpleRelocator("org.bar", "shaded.bar"),
)
assertThat(relocators.relocateText("org.foo.Foo, org.bar.Bar and other.Baz"))
.isEqualTo("shaded.foo.Foo, shaded.bar.Bar and other.Baz")
}

@Test
fun relocateTextOrder() {
val relocators =
listOf(
SimpleRelocator("org.foo", "org.bar"),
SimpleRelocator("org.bar", "org.baz"),
)
assertThat(relocators.relocateText("org.foo.Foo")).isEqualTo("org.baz.Foo")
}

private companion object {
val primitiveTypes = setOf('B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,29 @@ class SimpleRelocatorTest {
assertThat(relocator.relocateClass("org.foo.bar.Class")).isEqualTo("private.stuff.bar.Class")
}

@Test
fun relocateText() {
var relocator = SimpleRelocator("org.foo")
assertThat(
relocator.relocateText("org.foo.bar.Class, hidden.org.foo.bar.Class and org.foo.bar.Class")
)
.isEqualTo(
"hidden.org.foo.bar.Class, hidden.hidden.org.foo.bar.Class and hidden.org.foo.bar.Class"
)

relocator = SimpleRelocator("org.foo", "private.stuff")
assertThat(
relocator.relocateText("org.foo.bar.Class, private.stuff.bar.Class and org.foo.bar.Class")
)
.isEqualTo("private.stuff.bar.Class, private.stuff.bar.Class and private.stuff.bar.Class")

relocator = SimpleRelocator()
assertThat(relocator.relocateText("org.foo.bar.Class")).isEqualTo("org.foo.bar.Class")

relocator = SimpleRelocator("org.foo", "shaded.foo", rawString = true)
assertThat(relocator.relocateText("org.foo.bar.Class")).isEqualTo("org.foo.bar.Class")
}

@Test
fun relocateRawString() {
var relocator = SimpleRelocator("Lorg/foo", "Lhidden/org/foo", rawString = true)
Expand Down