try to remap patches
This commit is contained in:
parent
a1acc70992
commit
cecca9d248
3 changed files with 474 additions and 2 deletions
|
@ -83,8 +83,8 @@ open class PatchRemapTasks(
|
||||||
|
|
||||||
val patchCraftBukkit by tasks.registering<ApplyCraftBukkitPatches> {
|
val patchCraftBukkit by tasks.registering<ApplyCraftBukkitPatches> {
|
||||||
// TODO temp to speed stuff up
|
// TODO temp to speed stuff up
|
||||||
//sourceJar.set(spigotDecompileJar.flatMap { it.outputJar })
|
sourceJar.set(spigotDecompileJar.flatMap { it.outputJar })
|
||||||
sourceJar.set(cache.resolve("paperweight/taskCache/spigotDecompileJar.jar"))
|
//sourceJar.set(cache.resolve("paperweight/taskCache/spigotDecompileJar.jar"))
|
||||||
cleanDirPath.set("net/minecraft")
|
cleanDirPath.set("net/minecraft")
|
||||||
patchDir.set(extension.patchRemap.patchDir)
|
patchDir.set(extension.patchRemap.patchDir)
|
||||||
craftBukkitDir.set(extension.patchRemap.craftBukkitDir)
|
craftBukkitDir.set(extension.patchRemap.craftBukkitDir)
|
||||||
|
@ -92,4 +92,35 @@ open class PatchRemapTasks(
|
||||||
|
|
||||||
//dependsOn(cloneForPatchRemap)
|
//dependsOn(cloneForPatchRemap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//val filterSpigotMojMapExcludes by tasks.registering<FilterSpigotExcludes> {
|
||||||
|
// inputZip.set(spigotMojMapRemapJar.flatMap { it.outputJar })
|
||||||
|
// excludesFile.set(extension.patchRemap.excludesFile)
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//val spigotDecompileMojMapJar by tasks.registering<SpigotDecompileJar> {
|
||||||
|
// inputJar.set(filterSpigotMojMapExcludes.flatMap { it.outputZip })
|
||||||
|
// fernFlowerJar.set(extension.patchRemap.fernFlowerJar)
|
||||||
|
// decompileCommand.set(buildDataInfo.map { it.decompileCommand })
|
||||||
|
//}
|
||||||
|
|
||||||
|
val remapCraftBukkitSources by tasks.registering<RemapSources> {
|
||||||
|
vanillaJar.set(allTasks.extractFromBundler.flatMap { it.serverJar })
|
||||||
|
//mojangMappedVanillaJar.set(fixJar.flatMap { it.outputJar })
|
||||||
|
//vanillaRemappedSpigotJar.set(filterSpigotExcludes.flatMap { it.outputZip })
|
||||||
|
//mappings.set(generateSpigotMappings.flatMap { it.outputMappings })
|
||||||
|
mappings.set(cache.resolve(SPIGOT_MOJANG_YARN_MAPPINGS))
|
||||||
|
//sources.set(patchCraftBukkit.flatMap { it.outputDir }) // todo temp to speed stuff up
|
||||||
|
sources.set(extension.patchRemap.patchedCraftBukkitDir);
|
||||||
|
//spigotDeps.from(downloadSpigotDependencies.map { it.outputDir.asFileTree })
|
||||||
|
//additionalAts.set(mergePaperAts.flatMap { it.outputFile })
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo first try diffing against remapped mcp config source
|
||||||
|
// if that fails, we have to diff against spigot decompiled mojmap+yarn mapped vanilla jar
|
||||||
|
val diffCraftBukkitAgainstVanilla by tasks.registering<DiffCraftBukkitAgainstVanilla> {
|
||||||
|
craftBukkit.set(remapCraftBukkitSources.flatMap { it.sourcesOutputZip })
|
||||||
|
//vanilla.set(allTasks.prepareBase.flatMap { it.output })
|
||||||
|
vanilla.set(cache.resolve(BASE_PROJECT))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
package io.papermc.paperweight.tasks.patchremap
|
||||||
|
|
||||||
|
import codechicken.diffpatch.cli.DiffOperation
|
||||||
|
import io.papermc.paperweight.tasks.BaseTask
|
||||||
|
import io.papermc.paperweight.util.defaultOutput
|
||||||
|
import io.papermc.paperweight.util.filesMatchingRecursive
|
||||||
|
import io.papermc.paperweight.util.path
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.tasks.InputDirectory
|
||||||
|
import org.gradle.api.tasks.InputFile
|
||||||
|
import org.gradle.api.tasks.OutputDirectory
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import java.nio.file.Files
|
||||||
|
|
||||||
|
abstract class DiffCraftBukkitAgainstVanilla: BaseTask() {
|
||||||
|
|
||||||
|
@get:InputFile
|
||||||
|
abstract val craftBukkit: RegularFileProperty
|
||||||
|
|
||||||
|
@get:InputDirectory
|
||||||
|
abstract val vanilla: DirectoryProperty
|
||||||
|
|
||||||
|
@get:OutputDirectory
|
||||||
|
abstract val patches: RegularFileProperty
|
||||||
|
|
||||||
|
override fun init() {
|
||||||
|
patches.convention(defaultOutput())
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
open fun run() {
|
||||||
|
val diffOp = DiffOperation.builder()
|
||||||
|
.logTo(System.out)
|
||||||
|
.aPath(vanilla.path.resolve("src/vanilla"))
|
||||||
|
.bPath(craftBukkit.path)
|
||||||
|
.outputPath(patches.path.resolve("dum"))
|
||||||
|
.verbose(false)
|
||||||
|
.summary(true)
|
||||||
|
.lineEnding("\n")
|
||||||
|
//.ignorePattern(ignorePattern.get())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
diffOp.operate()
|
||||||
|
|
||||||
|
patches.path.resolve("dum").filesMatchingRecursive("*.patch").forEach { p ->
|
||||||
|
if (Files.readAllLines(p)[1].contains("+++ /dev/null")) {
|
||||||
|
Files.delete(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Files.walk(patches.path.resolve("dum"))
|
||||||
|
.filter { Files.isDirectory(it) }
|
||||||
|
.filter { it.toFile().listFiles()?.isEmpty() ?: false }
|
||||||
|
.forEach { Files.delete(it) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,385 @@
|
||||||
|
/*
|
||||||
|
* paperweight is a Gradle plugin for the PaperMC project.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Kyle Wood (DenWav)
|
||||||
|
* Contributors
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation;
|
||||||
|
* version 2.1 only, no later versions.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.papermc.paperweight.tasks.patchremap
|
||||||
|
|
||||||
|
import io.papermc.paperweight.tasks.JavaLauncherTask
|
||||||
|
import io.papermc.paperweight.util.*
|
||||||
|
import io.papermc.paperweight.util.constants.*
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlin.io.path.*
|
||||||
|
import kotlin.streams.asSequence
|
||||||
|
import org.cadixdev.at.AccessTransformSet
|
||||||
|
import org.cadixdev.at.io.AccessTransformFormats
|
||||||
|
import org.cadixdev.mercury.Mercury
|
||||||
|
import org.cadixdev.mercury.RewriteContext
|
||||||
|
import org.cadixdev.mercury.SourceProcessor
|
||||||
|
import org.cadixdev.mercury.SourceRewriter
|
||||||
|
import org.cadixdev.mercury.at.AccessTransformerRewriter
|
||||||
|
import org.cadixdev.mercury.extra.AccessAnalyzerProcessor
|
||||||
|
import org.cadixdev.mercury.remapper.MercuryRemapper
|
||||||
|
import org.eclipse.jdt.core.JavaCore
|
||||||
|
import org.eclipse.jdt.core.dom.*
|
||||||
|
import org.gradle.api.file.ConfigurableFileCollection
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.ListProperty
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
import org.gradle.kotlin.dsl.*
|
||||||
|
import org.gradle.workers.WorkAction
|
||||||
|
import org.gradle.workers.WorkParameters
|
||||||
|
import org.gradle.workers.WorkerExecutor
|
||||||
|
|
||||||
|
@CacheableTask
|
||||||
|
abstract class RemapSources : JavaLauncherTask() {
|
||||||
|
|
||||||
|
@get:CompileClasspath
|
||||||
|
abstract val vanillaJar: RegularFileProperty
|
||||||
|
|
||||||
|
//@get:CompileClasspath
|
||||||
|
//abstract val mojangMappedVanillaJar: RegularFileProperty
|
||||||
|
|
||||||
|
//@get:CompileClasspath
|
||||||
|
//abstract val vanillaRemappedSpigotJar: RegularFileProperty
|
||||||
|
|
||||||
|
@get:InputFile
|
||||||
|
@get:PathSensitive(PathSensitivity.NONE)
|
||||||
|
abstract val mappings: RegularFileProperty
|
||||||
|
|
||||||
|
//@get:CompileClasspath
|
||||||
|
//abstract val spigotDeps: ConfigurableFileCollection
|
||||||
|
|
||||||
|
@get:InputDirectory
|
||||||
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
|
abstract val sources: DirectoryProperty
|
||||||
|
|
||||||
|
//@get:Optional
|
||||||
|
//@get:InputFile
|
||||||
|
//@get:PathSensitive(PathSensitivity.NONE)
|
||||||
|
//abstract val additionalAts: RegularFileProperty
|
||||||
|
|
||||||
|
@get:OutputFile
|
||||||
|
abstract val generatedAt: RegularFileProperty
|
||||||
|
|
||||||
|
@get:OutputFile
|
||||||
|
abstract val sourcesOutputZip: RegularFileProperty
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
abstract val jvmargs: ListProperty<String>
|
||||||
|
|
||||||
|
@get:Inject
|
||||||
|
abstract val workerExecutor: WorkerExecutor
|
||||||
|
|
||||||
|
@get:OutputFile
|
||||||
|
abstract val spigotRecompiledClasses: RegularFileProperty
|
||||||
|
|
||||||
|
override fun init() {
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
jvmargs.convention(listOf("-Xmx2G"))
|
||||||
|
sourcesOutputZip.convention(defaultOutput("$name-sources", "jar"))
|
||||||
|
generatedAt.convention(defaultOutput("at"))
|
||||||
|
spigotRecompiledClasses.convention(defaultOutput("spigotRecompiledClasses", "txt"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun run() {
|
||||||
|
val srcOut = findOutputDir(sourcesOutputZip.path).apply { createDirectories() }
|
||||||
|
|
||||||
|
try {
|
||||||
|
val queue = workerExecutor.processIsolation {
|
||||||
|
forkOptions.jvmArgs(jvmargs.get())
|
||||||
|
forkOptions.executable(launcher.get().executablePath.path.absolutePathString())
|
||||||
|
}
|
||||||
|
|
||||||
|
val srcDir = sources.path.resolve("src/main/java")
|
||||||
|
|
||||||
|
// Remap sources
|
||||||
|
queue.submit(RemapAction::class) {
|
||||||
|
//classpath.from(vanillaRemappedSpigotJar.path)
|
||||||
|
//classpath.from(mojangMappedVanillaJar.path)
|
||||||
|
classpath.from(vanillaJar.path)
|
||||||
|
//classpath.from(spigotApiDir.dir("src/main/java").path)
|
||||||
|
//classpath.from(spigotDeps.files.filter { it.toPath().isLibraryJar })
|
||||||
|
//additionalAts.set(this@RemapSources.additionalAts.pathOrNull)
|
||||||
|
|
||||||
|
mappings.set(this@RemapSources.mappings.path)
|
||||||
|
inputDir.set(srcDir)
|
||||||
|
|
||||||
|
cacheDir.set(this@RemapSources.layout.cache)
|
||||||
|
|
||||||
|
outputDir.set(srcOut)
|
||||||
|
generatedAtOutput.set(generatedAt.path)
|
||||||
|
}
|
||||||
|
queue.await()
|
||||||
|
|
||||||
|
zip(srcOut, sourcesOutputZip)
|
||||||
|
|
||||||
|
writeSpigotRecompiledFiles(srcOut)
|
||||||
|
} finally {
|
||||||
|
srcOut.deleteRecursively()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun writeSpigotRecompiledFiles(srcOut: Path) {
|
||||||
|
// Write list of java files spigot recompiles
|
||||||
|
val spigotRecompiled = Files.walk(srcOut).use { stream ->
|
||||||
|
stream.asSequence().mapNotNull {
|
||||||
|
if (!it.isRegularFile()) {
|
||||||
|
return@mapNotNull null
|
||||||
|
}
|
||||||
|
if (!it.fileName.pathString.endsWith(".java")) {
|
||||||
|
return@mapNotNull null
|
||||||
|
}
|
||||||
|
val path = srcOut.relativize(it).pathString
|
||||||
|
if (!path.startsWith("net/minecraft")) {
|
||||||
|
return@mapNotNull null
|
||||||
|
}
|
||||||
|
path.replace(".java", "")
|
||||||
|
}.sorted().joinToString("\n")
|
||||||
|
}
|
||||||
|
spigotRecompiledClasses.path.parent.createDirectories()
|
||||||
|
spigotRecompiledClasses.path.writeText(spigotRecompiled)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class RemapAction : WorkAction<RemapParams> {
|
||||||
|
override fun execute() {
|
||||||
|
val mappingSet = MappingFormats.TINY.read(
|
||||||
|
parameters.mappings.path,
|
||||||
|
SPIGOT_NAMESPACE,
|
||||||
|
DEOBF_NAMESPACE
|
||||||
|
)
|
||||||
|
|
||||||
|
val additionalAt = parameters.additionalAts.pathOrNull?.let { AccessTransformFormats.FML.read(it) }
|
||||||
|
|
||||||
|
val processAt = AccessTransformSet.create()
|
||||||
|
val generatedAtOutPath = parameters.generatedAtOutput.pathOrNull
|
||||||
|
|
||||||
|
// Remap any references Spigot maps to mojmap+yarn
|
||||||
|
Mercury().let { merc ->
|
||||||
|
merc.sourceCompatibility = JavaCore.VERSION_17
|
||||||
|
merc.isGracefulClasspathChecks = true
|
||||||
|
merc.classPath.addAll(parameters.classpath.map { it.toPath() })
|
||||||
|
|
||||||
|
if (generatedAtOutPath != null) {
|
||||||
|
merc.processors += AccessAnalyzerProcessor.create(processAt, mappingSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
merc.process(parameters.inputDir.path)
|
||||||
|
|
||||||
|
val tempOut = Files.createTempDirectory(parameters.cacheDir.path, "remap")
|
||||||
|
try {
|
||||||
|
merc.processors.clear()
|
||||||
|
merc.processors.addAll(
|
||||||
|
listOf(
|
||||||
|
ExplicitThisAdder,
|
||||||
|
OverrideRemover, // TODO meh
|
||||||
|
MercuryRemapper.create(mappingSet),
|
||||||
|
AccessTransformerRewriter.create(processAt)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (generatedAtOutPath != null) {
|
||||||
|
merc.processors.add(AccessTransformerRewriter.create(processAt))
|
||||||
|
}
|
||||||
|
|
||||||
|
merc.rewrite(parameters.inputDir.path, tempOut)
|
||||||
|
|
||||||
|
if (additionalAt != null) {
|
||||||
|
merc.processors.clear()
|
||||||
|
merc.processors += AccessTransformerRewriter.create(additionalAt)
|
||||||
|
|
||||||
|
merc.rewrite(tempOut, parameters.outputDir.path)
|
||||||
|
} else {
|
||||||
|
tempOut.copyRecursivelyTo(parameters.outputDir.path)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
tempOut.deleteRecursively()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generatedAtOutPath != null) {
|
||||||
|
AccessTransformFormats.FML.write(generatedAtOutPath, processAt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RemapParams : WorkParameters {
|
||||||
|
val classpath: ConfigurableFileCollection
|
||||||
|
val mappings: RegularFileProperty
|
||||||
|
val inputDir: RegularFileProperty
|
||||||
|
val additionalAts: RegularFileProperty
|
||||||
|
|
||||||
|
val cacheDir: RegularFileProperty
|
||||||
|
val generatedAtOutput: RegularFileProperty
|
||||||
|
val outputDir: RegularFileProperty
|
||||||
|
}
|
||||||
|
|
||||||
|
object OverrideRemover : SourceRewriter {
|
||||||
|
|
||||||
|
override fun getFlags(): Int = SourceProcessor.FLAG_RESOLVE_BINDINGS
|
||||||
|
|
||||||
|
override fun rewrite(context: RewriteContext) {
|
||||||
|
context.compilationUnit.accept(OverrideRemoverVisitor(context))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OverrideRemoverVisitor(private val context: RewriteContext) : ASTVisitor() {
|
||||||
|
|
||||||
|
override fun visit(node: MarkerAnnotation): Boolean {
|
||||||
|
if (node.typeName.fullyQualifiedName == "Override") {
|
||||||
|
context.createASTRewrite().remove(node, null)
|
||||||
|
}
|
||||||
|
return super.visit(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ExplicitThisAdder : SourceRewriter {
|
||||||
|
|
||||||
|
override fun getFlags(): Int = SourceProcessor.FLAG_RESOLVE_BINDINGS
|
||||||
|
|
||||||
|
override fun rewrite(context: RewriteContext) {
|
||||||
|
context.compilationUnit.accept(ExplicitThisAdderVisitor(context))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExplicitThisAdderVisitor(private val context: RewriteContext) : ASTVisitor() {
|
||||||
|
|
||||||
|
override fun visit(node: SimpleName): Boolean {
|
||||||
|
val binding = node.resolveBinding() ?: return false
|
||||||
|
|
||||||
|
val name = when (val declaringNode = context.compilationUnit.findDeclaringNode(binding)) {
|
||||||
|
is VariableDeclarationFragment -> declaringNode.name
|
||||||
|
is MethodDeclaration -> declaringNode.name
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
if (name === node) {
|
||||||
|
// this is the actual declaration
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
visit(node, binding)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visit(node: SimpleName, binding: IBinding) {
|
||||||
|
if (binding.kind != IBinding.VARIABLE && binding.kind != IBinding.METHOD) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val referringClass = when (binding) {
|
||||||
|
is IVariableBinding -> {
|
||||||
|
if (!binding.isField || binding.isEnumConstant) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
binding.declaringClass
|
||||||
|
}
|
||||||
|
is IMethodBinding -> {
|
||||||
|
if (binding.isConstructor || binding.isSynthetic) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
binding.declaringClass
|
||||||
|
}
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
val modifiers = when (binding) {
|
||||||
|
is IVariableBinding -> binding.modifiers
|
||||||
|
is IMethodBinding -> binding.modifiers
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
|
||||||
|
when (val p = node.parent) {
|
||||||
|
is FieldAccess, is SuperFieldAccess, is QualifiedName, is ThisExpression, is MethodReference, is SuperMethodInvocation -> return
|
||||||
|
is MethodInvocation -> {
|
||||||
|
if (p.expression != null && p.expression !== node) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// find declaring method
|
||||||
|
var parentNode: ASTNode? = node
|
||||||
|
loop@ while (parentNode != null) {
|
||||||
|
when (parentNode) {
|
||||||
|
is MethodDeclaration, is AnonymousClassDeclaration, is LambdaExpression, is Initializer -> break@loop
|
||||||
|
}
|
||||||
|
parentNode = parentNode.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
val rewrite = context.createASTRewrite()
|
||||||
|
val fieldAccess = rewrite.ast.newFieldAccess()
|
||||||
|
|
||||||
|
val expr: Expression = if (!Modifier.isStatic(modifiers)) {
|
||||||
|
rewrite.ast.newThisExpression().also { thisExpr ->
|
||||||
|
if (parentNode is LambdaExpression) {
|
||||||
|
return@also
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parentNode is AnonymousClassDeclaration && referringClass.erasure != parentNode.resolveBinding().erasure) {
|
||||||
|
val name = getNameNode(referringClass) ?: return
|
||||||
|
thisExpr.qualifier = rewrite.createCopyTarget(name) as Name
|
||||||
|
return@also
|
||||||
|
}
|
||||||
|
|
||||||
|
val methodDec = parentNode as? MethodDeclaration ?: return@also
|
||||||
|
|
||||||
|
var methodClass = methodDec.resolveBinding()?.declaringClass ?: return // silently return if binding does not resolve
|
||||||
|
if (methodClass.isAnonymous) {
|
||||||
|
val name = getNameNode(referringClass) ?: return
|
||||||
|
thisExpr.qualifier = rewrite.createCopyTarget(name) as Name
|
||||||
|
return@also
|
||||||
|
}
|
||||||
|
|
||||||
|
if (referringClass.erasure != methodClass.erasure && methodClass.isNested && !Modifier.isStatic(methodClass.modifiers)) {
|
||||||
|
while (true) {
|
||||||
|
methodClass = methodClass.declaringClass ?: break
|
||||||
|
}
|
||||||
|
// Looks like the method is accessing an outer class's fields
|
||||||
|
if (referringClass.erasure == methodClass.erasure) {
|
||||||
|
val name = getNameNode(referringClass) ?: return
|
||||||
|
thisExpr.qualifier = rewrite.createCopyTarget(name) as Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (parentNode is Initializer && Modifier.isStatic(parentNode.modifiers)) {
|
||||||
|
// Can't provide explicit static receiver here
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val name = getNameNode(referringClass) ?: return
|
||||||
|
rewrite.createCopyTarget(name) as Name
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldAccess.expression = expr
|
||||||
|
fieldAccess.name = rewrite.createMoveTarget(node) as SimpleName
|
||||||
|
|
||||||
|
rewrite.replace(node, fieldAccess, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getNameNode(dec: ITypeBinding): Name? {
|
||||||
|
val typeDec = context.compilationUnit.findDeclaringNode(dec) as? TypeDeclaration ?: return null
|
||||||
|
return typeDec.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue