Skip to content

Commit

Permalink
Merge SimpleRelocatorNew into SimpleRelocator
Browse files Browse the repository at this point in the history
  • Loading branch information
Goooler committed Dec 7, 2024
1 parent e3da94e commit 5adaeaf
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 279 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public open class SimpleRelocator @JvmOverloads constructor(
private val pathPattern: String
private val shadedPattern: String
private val shadedPathPattern: String
private val sourcePackageExcludes = mutableSetOf<String>()
private val sourcePathExcludes = mutableSetOf<String>()

@get:Input
public val includes: SetProperty<String> = objectFactory.setProperty(String::class.java)
Expand All @@ -47,16 +49,42 @@ public open class SimpleRelocator @JvmOverloads constructor(
this.pattern = pattern.replace('/', '.')
this.pathPattern = pattern.replace('.', '/')
}
if (shadedPattern == null) {
this.shadedPattern = "hidden.${this.pattern}"
this.shadedPathPattern = "hidden/${this.pathPattern}"
} else {
if (shadedPattern != null) {
this.shadedPattern = shadedPattern.replace('/', '.')
this.shadedPathPattern = shadedPattern.replace('.', '/')
} else {
this.shadedPattern = "hidden.${this.pattern}"
this.shadedPathPattern = "hidden/${this.pathPattern}"
}
}
this.includes.addAll(normalizePatterns(includes))
this.excludes.addAll(normalizePatterns(excludes))

// Don't replace all dots to slashes, otherwise /META-INF/maven/${groupId} can't be matched.
if (!includes.isNullOrEmpty()) {
this.includes.addAll(includes)
}
if (!excludes.isNullOrEmpty()) {
this.excludes.addAll(excludes)
}

if (!rawString) {
// Create exclude pattern sets for sources
for (exclude in this.excludes.get()) {
// Excludes should be subpackages of the global pattern
if (exclude.startsWith(this.pattern)) {
sourcePackageExcludes.add(
exclude.substring(this.pattern.length).replaceFirst("[.][*]$".toRegex(), ""),
)
}
// Excludes should be subpackages of the global pattern
if (exclude.startsWith(pathPattern)) {
sourcePathExcludes.add(
exclude.substring(pathPattern.length).replaceFirst("/[*]$".toRegex(), ""),
)
}
}
}
}

public open fun include(pattern: String): SimpleRelocator = apply {
Expand All @@ -78,10 +106,10 @@ public open class SimpleRelocator @JvmOverloads constructor(
} else {
path
}
// Allow for annoying option of an extra / on the front of a path. See MSHADE-119 comes from getClass().getResource("/a/b/c.properties").
// Allow for annoying option of an extra / on the front of a path. See MSHADE-119;
// comes from getClass().getResource("/a/b/c.properties").
val startIndex = if (adjustedPath.startsWith("/")) 1 else 0
val pathStartsWithPattern = adjustedPath.startsWith(pathPattern, startIndex)
return pathStartsWithPattern && isIncluded(adjustedPath) && !isExcluded(adjustedPath)
return isIncluded(adjustedPath) && !isExcluded(adjustedPath) && adjustedPath.startsWith(pathPattern, startIndex)
}

override fun canRelocateClass(className: String): Boolean {
Expand All @@ -94,21 +122,20 @@ public open class SimpleRelocator @JvmOverloads constructor(
return if (rawString) {
path.replace(pathPattern.toRegex(), shadedPathPattern)
} else {
path.replaceFirst(pathPattern, shadedPathPattern)
path.replaceFirst(pathPattern.toRegex(), shadedPathPattern)
}
}

override fun relocateClass(context: RelocateClassContext): String {
context.stats.relocate(pathPattern, shadedPathPattern)
return context.className.replaceFirst(pattern, shadedPattern)
val clazz = context.className
return if (rawString) clazz else clazz.replaceFirst(pattern.toRegex(), shadedPattern)
}

override fun applyToSourceContent(sourceContent: String): String {
return if (rawString) {
sourceContent
} else {
sourceContent.replace("\\b$pattern".toRegex(), shadedPattern)
}
if (rawString) return sourceContent
val content = shadeSourceWithExcludes(sourceContent, pattern, shadedPattern, sourcePackageExcludes)
return shadeSourceWithExcludes(content, pathPattern, shadedPathPattern, sourcePathExcludes)
}

private fun isIncluded(path: String): Boolean {
Expand All @@ -120,6 +147,28 @@ public open class SimpleRelocator @JvmOverloads constructor(
}

private companion object {
/**
* Match dot, slash or space at end of string
*/
val RX_ENDS_WITH_DOT_SLASH_SPACE: Pattern = Pattern.compile("[./ ]$")

/**
* Match
* - certain Java keywords + space
* - beginning of Javadoc link + optional line breaks and continuations with '*'
* - (opening curly brace / opening parenthesis / comma / equals / semicolon) + space
* - (closing curly brace / closing multi-line comment) + space
*
* at end of string
*/
val RX_ENDS_WITH_JAVA_KEYWORD: Pattern = Pattern.compile(
"\\b(import|package|public|protected|private|static|final|synchronized|abstract|volatile|extends|implements|throws) $" +
"|" +
"\\{@link( \\*)* $" +
"|" +
"([{}(=;,]|\\*/) $",
)

fun normalizePatterns(patterns: Collection<String>?) = buildSet {
patterns ?: return@buildSet
for (pattern in patterns) {
Expand All @@ -138,5 +187,46 @@ public open class SimpleRelocator @JvmOverloads constructor(
}
}
}

fun shadeSourceWithExcludes(
sourceContent: String,
patternFrom: String,
patternTo: String?,
excludedPatterns: Set<String>,
): String {
// Usually shading makes package names a bit longer, so make buffer 10% bigger than original source
val shadedSourceContent = StringBuilder(sourceContent.length * 11 / 10)
var isFirstSnippet = true
// Make sure that search pattern starts at word boundary and that we look for literal ".", not regex jokers
val snippets = sourceContent.split(("\\b" + patternFrom.replace(".", "[.]") + "\\b").toRegex())
.dropLastWhile { it.isEmpty() }.toTypedArray()
var i = 0
val snippetsLength = snippets.size
while (i < snippetsLength) {
val snippet = snippets[i]
val previousSnippet = if (isFirstSnippet) "" else snippets[i - 1]
var doExclude = false
for (excludedPattern in excludedPatterns) {
if (snippet.startsWith(excludedPattern)) {
doExclude = true
break
}
}
if (isFirstSnippet) {
shadedSourceContent.append(snippet)
isFirstSnippet = false
} else {
val previousSnippetOneLine = previousSnippet.replace("\\s+".toRegex(), " ")
val afterDotSlashSpace = RX_ENDS_WITH_DOT_SLASH_SPACE.matcher(previousSnippetOneLine).find()
val afterJavaKeyWord = RX_ENDS_WITH_JAVA_KEYWORD.matcher(previousSnippetOneLine).find()
val shouldExclude = doExclude || afterDotSlashSpace && !afterJavaKeyWord
shadedSourceContent
.append(if (shouldExclude) patternFrom else patternTo)
.append(snippet)
}
i++
}
return shadedSourceContent.toString()
}
}
}
Loading

0 comments on commit 5adaeaf

Please sign in to comment.