├── .editorconfig ├── .github └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── HEADER ├── LICENSE ├── README.md ├── build.gradle ├── checkstyle.xml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main ├── java │ └── net │ │ └── fabricmc │ │ └── tinyremapper │ │ ├── AsmClassRemapper.java │ │ ├── AsmRemapper.java │ │ ├── BridgeHandler.java │ │ ├── ClassInstance.java │ │ ├── ConsoleLogger.java │ │ ├── FileSystemReference.java │ │ ├── IMappingProvider.java │ │ ├── InputTag.java │ │ ├── Main.java │ │ ├── MemberInstance.java │ │ ├── MetaInfFixer.java │ │ ├── MetaInfRemover.java │ │ ├── NonClassCopyMode.java │ │ ├── OutputConsumerPath.java │ │ ├── PackageAccessChecker.java │ │ ├── Propagator.java │ │ ├── TinyRemapper.java │ │ ├── TinyUtils.java │ │ ├── VisitTrackingClassRemapper.java │ │ ├── api │ │ ├── TrClass.java │ │ ├── TrEnvironment.java │ │ ├── TrField.java │ │ ├── TrLogger.java │ │ ├── TrMember.java │ │ ├── TrMethod.java │ │ └── TrRemapper.java │ │ └── extension │ │ └── mixin │ │ ├── MixinExtension.java │ │ ├── common │ │ ├── IMappable.java │ │ ├── MapUtility.java │ │ ├── ResolveUtility.java │ │ ├── StringUtility.java │ │ └── data │ │ │ ├── Annotation.java │ │ │ ├── AnnotationElement.java │ │ │ ├── CommonData.java │ │ │ ├── Constant.java │ │ │ ├── Message.java │ │ │ ├── MxClass.java │ │ │ ├── MxMember.java │ │ │ └── Pair.java │ │ ├── hard │ │ ├── HardTargetMixinClassVisitor.java │ │ ├── HardTargetMixinFieldVisitor.java │ │ ├── HardTargetMixinMethodVisitor.java │ │ ├── annotation │ │ │ ├── ImplementsAnnotationVisitor.java │ │ │ ├── MixinAnnotationVisitor.java │ │ │ ├── OverwriteAnnotationVisitor.java │ │ │ └── ShadowAnnotationVisitor.java │ │ ├── data │ │ │ └── SoftInterface.java │ │ └── util │ │ │ ├── CamelPrefixString.java │ │ │ ├── ConvertibleMappable.java │ │ │ ├── HardTargetMappable.java │ │ │ ├── IConvertibleString.java │ │ │ ├── IdentityString.java │ │ │ └── PrefixString.java │ │ └── soft │ │ ├── SoftTargetMixinClassVisitor.java │ │ ├── SoftTargetMixinMethodVisitor.java │ │ ├── annotation │ │ ├── AccessorAnnotationVisitor.java │ │ ├── InvokerAnnotationVisitor.java │ │ ├── MixinAnnotationVisitor.java │ │ └── injection │ │ │ ├── AtAnnotationVisitor.java │ │ │ ├── AtMemberMappable.java │ │ │ ├── CommonInjectionAnnotationVisitor.java │ │ │ ├── DefinitionAnnotationVisitor.java │ │ │ ├── DefinitionsAnnotationVisitor.java │ │ │ ├── DescAnnotationVisitor.java │ │ │ ├── InjectAnnotationVisitor.java │ │ │ ├── ModifyArgAnnotationVisitor.java │ │ │ ├── ModifyArgsAnnotationVisitor.java │ │ │ ├── ModifyConstantAnnotationVisitor.java │ │ │ ├── ModifyExpressionValueAnnotationVisitor.java │ │ │ ├── ModifyReceiverAnnotationVisitor.java │ │ │ ├── ModifyReturnValueAnnotationVisitor.java │ │ │ ├── ModifyVariableAnnotationVisitor.java │ │ │ ├── RedirectAnnotationVisitor.java │ │ │ ├── SliceAnnotationVisitor.java │ │ │ ├── WrapMethodAnnotationVisitor.java │ │ │ ├── WrapOperationAnnotationVisitor.java │ │ │ ├── WrapWithConditionAnnotationVisitor.java │ │ │ └── WrapWithConditionV2AnnotationVisitor.java │ │ ├── data │ │ └── MemberInfo.java │ │ └── util │ │ └── NamedMappable.java └── resources │ └── META-INF │ └── services │ └── net.fabricmc.tinyremapper.TinyRemapper$CLIExtensionProvider └── test ├── java └── net │ └── fabricmc │ └── tinyremapper │ ├── BulkTest.java │ ├── ClassInstanceTest.java │ ├── IntegrationTest1.java │ ├── IntegrationTest2.java │ ├── IntegrationTest3.java │ ├── TestUtil.java │ ├── TinyRemapperTest.java │ └── extension │ └── mixin │ ├── common │ └── StringUtilityTest.java │ ├── hard │ └── util │ │ └── IConvertibleStringTest.java │ └── soft │ └── data │ └── MemberInfoTest.java └── resources ├── integration ├── access │ └── input.jar ├── annotation │ └── input.jar ├── basic │ └── input.jar ├── bulk │ └── fabric-api-0.35.1+1.17.jar ├── mrj1 │ └── input.jar ├── mrj2 │ └── input.jar └── mrj3 │ └── input.jar └── mapping ├── mapping1.tiny ├── mapping2.tiny ├── mapping3.tiny └── yarn-1.17+build.9-v2.tiny.gz /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | tab_width = 4 8 | 9 | [*.gradle] 10 | indent_style = tab 11 | 12 | [*.java] 13 | indent_style = tab 14 | ij_continuation_indent_size = 8 15 | ij_java_imports_layout = $*,|,java.**,|,javax.**,|,*,|,net.minecraft.**,|,net.fabricmc.** 16 | ij_java_class_count_to_use_import_on_demand = 999 17 | 18 | [.editorconfig] 19 | indent_style = space 20 | indent_size = 4 -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push, pull_request] 3 | jobs: 4 | build: 5 | strategy: 6 | matrix: 7 | java: [11-jdk, 17-jdk, 21-jdk] 8 | runs-on: ubuntu-22.04 9 | container: 10 | image: eclipse-temurin:${{ matrix.java }} 11 | options: --user root 12 | steps: 13 | - uses: actions/checkout@v4 14 | with: 15 | fetch-depth: 0 16 | - uses: gradle/wrapper-validation-action@v1 17 | - run: chmod +x ./gradlew 18 | - run: ./gradlew build test --stacktrace 19 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: [workflow_dispatch] # Manual trigger 3 | jobs: 4 | build: 5 | runs-on: ubuntu-22.04 6 | container: 7 | image: eclipse-temurin:21-jdk 8 | options: --user root 9 | steps: 10 | - uses: actions/checkout@v4 11 | with: 12 | fetch-depth: 0 13 | - uses: gradle/wrapper-validation-action@v1 14 | - run: chmod +x ./gradlew 15 | - run: ./gradlew checkVersion build publish --stacktrace 16 | env: 17 | MAVEN_URL: ${{ secrets.MAVEN_URL }} 18 | MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} 19 | MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /lib/ 3 | /run/ 4 | /build/ 5 | /.settings/ 6 | /.classpath 7 | /.project 8 | /.checkstyle 9 | /.gradle 10 | *.jar 11 | *.tiny 12 | .idea/ 13 | !src/test/resources/** 14 | /tiny-remapper/ 15 | /out/ 16 | -------------------------------------------------------------------------------- /HEADER: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) $YEAR, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tiny-remapper 2 | 3 | A tiny, efficient tool for remapping JAR files using "Tiny"-format mappings. Original code provided by Player. 4 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java-library' 3 | id 'maven-publish' 4 | id 'checkstyle' 5 | id 'com.diffplug.spotless' version '6.22.0' 6 | id 'com.github.johnrengelman.shadow' version '8.1.1' 7 | } 8 | 9 | version = '0.11.1' 10 | 11 | def ENV = System.getenv() 12 | version = version + (ENV.GITHUB_ACTIONS ? "" : "+local") 13 | 14 | group = 'net.fabricmc' 15 | 16 | base { 17 | archivesName = 'tiny-remapper' 18 | } 19 | 20 | repositories { 21 | mavenCentral() 22 | } 23 | 24 | dependencies { 25 | api 'org.ow2.asm:asm:9.7.1' 26 | api 'org.ow2.asm:asm-commons:9.7.1' 27 | implementation 'org.ow2.asm:asm-tree:9.7.1' 28 | implementation 'org.ow2.asm:asm-util:9.7.1' 29 | implementation "net.fabricmc:mapping-io:0.7.1" 30 | 31 | testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2' 32 | } 33 | 34 | java { 35 | withSourcesJar() 36 | sourceCompatibility = JavaVersion.VERSION_1_8 37 | targetCompatibility = JavaVersion.VERSION_1_8 38 | } 39 | 40 | tasks.withType(JavaCompile).configureEach { 41 | it.options.encoding = "UTF-8" 42 | 43 | if (JavaVersion.current().isJava9Compatible()) { 44 | it.options.release = 8 45 | } 46 | } 47 | 48 | shadowJar { 49 | archiveClassifier = 'fat' 50 | } 51 | 52 | test { 53 | useJUnitPlatform() 54 | testLogging { 55 | showStandardStreams = true 56 | exceptionFormat = 'full' 57 | events = ['passed', 'failed', 'skipped'] 58 | } 59 | } 60 | 61 | jar { 62 | manifest { 63 | attributes 'Implementation-Title': 'TinyRemapper', 64 | 'Implementation-Version': archiveVersion, 65 | 'Main-Class': "net.fabricmc.tinyremapper.Main" 66 | } 67 | } 68 | 69 | checkstyle { 70 | configFile = file("checkstyle.xml") 71 | toolVersion = '8.31' 72 | } 73 | 74 | spotless { 75 | java { 76 | licenseHeaderFile(rootProject.file('HEADER')).yearSeparator(', ') 77 | removeUnusedImports() 78 | importOrder('java', 'javax', '', 'net.minecraft', 'net.fabricmc') 79 | indentWithTabs() 80 | trimTrailingWhitespace() 81 | } 82 | } 83 | 84 | publishing { 85 | publications { 86 | mavenJava(MavenPublication) { 87 | from components.java 88 | } 89 | } 90 | 91 | repositories { 92 | if (ENV.MAVEN_URL) { 93 | maven { 94 | url ENV.MAVEN_URL 95 | credentials { 96 | username ENV.MAVEN_USERNAME 97 | password ENV.MAVEN_PASSWORD 98 | } 99 | } 100 | } 101 | } 102 | } 103 | 104 | // A task to ensure that the version being released has not already been released. 105 | task checkVersion { 106 | doFirst { 107 | def xml = new URL("https://maven.fabricmc.net/net/fabricmc/tiny-remapper/maven-metadata.xml").text 108 | def metadata = new XmlSlurper().parseText(xml) 109 | def versions = metadata.versioning.versions.version*.text(); 110 | if (versions.contains(version)) { 111 | throw new RuntimeException("${version} has already been released!") 112 | } 113 | } 114 | } 115 | 116 | publish.mustRunAfter checkVersion 117 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FabricMC/tiny-remapper/d59015fb0b8a656c0a95235a4edb099c3638977a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'tiny-remapper' -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/BridgeHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2020, 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import org.objectweb.asm.ClassVisitor; 22 | import org.objectweb.asm.MethodVisitor; 23 | import org.objectweb.asm.Opcodes; 24 | import org.objectweb.asm.Type; 25 | 26 | import net.fabricmc.tinyremapper.TinyRemapper.MrjState; 27 | 28 | final class BridgeHandler { 29 | public static MemberInstance getTarget(MemberInstance bridgeMethod) { 30 | assert bridgeMethod.isBridge(); 31 | 32 | MemberInstance ret = bridgeMethod.bridgeTarget; 33 | if (ret != null) return ret; 34 | 35 | // try to propagate bridge method mapping to the actual implementation 36 | 37 | String bridgeId = bridgeMethod.getId(); 38 | int descStart = bridgeId.indexOf('('); 39 | 40 | for (MemberInstance m : bridgeMethod.cls.getMembers()) { 41 | if (m != bridgeMethod // same method 42 | && m.isVirtual() // not a method or not relevant 43 | && !m.isBridge() // method is a bridge on its own 44 | && isBridged(bridgeId, m.getId(), descStart, bridgeMethod.getContext())) { 45 | bridgeMethod.bridgeTarget = m; 46 | 47 | return m; 48 | } 49 | } 50 | 51 | return null; 52 | } 53 | 54 | /** 55 | * Determine whether a method is the target of a bridge from the descriptors. 56 | * 57 | *

This requires both methods to have the same name, same parameter count and all args+return value in the 58 | * target method to be assignable to the bridge method's equivalents. The target method specializes the bridge 59 | * method to provide an unchecked parameterized implementation and/or an override with a more specific return type. 60 | */ 61 | private static boolean isBridged(String bridgeId, String targetId, int descStart, MrjState context) { 62 | // check for same method name 63 | if (!bridgeId.regionMatches(0, targetId, 0, descStart + 1)) return false; // comparison includes ( to reject name suffixes 64 | 65 | // check for same or assignable return type 66 | int argsEndBridge = bridgeId.lastIndexOf(')'); 67 | int argsEndTarget = targetId.lastIndexOf(')'); 68 | 69 | if (!ClassInstance.isAssignableFrom(bridgeId, argsEndBridge + 1, targetId, argsEndTarget + 1, context)) { 70 | return false; 71 | } 72 | 73 | // check for same or assignable arg types 74 | int posBridge = descStart + 1; 75 | int posTarget = posBridge; 76 | 77 | for (; posBridge < argsEndBridge && posTarget < argsEndTarget; posBridge++, posTarget++) { // loops one arg at a time 78 | if (!ClassInstance.isAssignableFrom(bridgeId, posBridge, targetId, posTarget, context)) return false; 79 | 80 | // seek to the arg's last character (skip array prefixes and object descriptors).. 81 | // .. for bridgeId 82 | 83 | char type = bridgeId.charAt(posBridge); 84 | 85 | while (type == '[') { 86 | type = bridgeId.charAt(++posBridge); 87 | } 88 | 89 | if (type == 'L') posBridge = bridgeId.indexOf(';', posBridge + 1); 90 | 91 | // .. and for targetId 92 | 93 | type = targetId.charAt(posTarget); 94 | 95 | while (type == '[') { 96 | type = targetId.charAt(++posTarget); 97 | } 98 | 99 | if (type == 'L') posTarget = targetId.indexOf(';', posTarget + 1); 100 | } 101 | 102 | return posBridge == argsEndBridge && posTarget == argsEndTarget; // check for same arg count 103 | } 104 | 105 | public static void generateCompatBridges(ClassInstance cls, AsmRemapper remapper, ClassVisitor out) { 106 | memberLoop: for (MemberInstance m : cls.getMembers()) { 107 | String bridgedName = m.getNewBridgedName(); 108 | String mappedName; 109 | 110 | if (bridgedName == null 111 | || (mappedName = m.getNewMappedName()) == null 112 | || bridgedName.equals(mappedName)) { 113 | continue; 114 | } 115 | 116 | for (MemberInstance o : cls.getMembers()) { 117 | if (o != m 118 | && o.desc.equals(m.desc) 119 | && remapper.mapMethodName(cls.getName(), o.name, o.desc).equals(mappedName)) { 120 | // nameDesc is already in use, skip generating bridge for it 121 | continue memberLoop; 122 | } 123 | } 124 | 125 | String mappedDesc = remapper.mapDesc(m.desc); 126 | int lvSize = 1; 127 | 128 | MethodVisitor mv = out.visitMethod(m.access | Opcodes.ACC_BRIDGE | Opcodes.ACC_SYNTHETIC, mappedName, mappedDesc, null, null); 129 | mv.visitCode(); 130 | mv.visitVarInsn(Opcodes.ALOAD, 0); 131 | 132 | if (!mappedDesc.startsWith("()")) { 133 | for (Type type : Type.getArgumentTypes(mappedDesc)) { 134 | mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), lvSize); 135 | lvSize += type.getSize(); 136 | } 137 | } 138 | 139 | mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, remapper.map(cls.getName()), bridgedName, mappedDesc, cls.isInterface()); 140 | 141 | Type retType = Type.getReturnType(mappedDesc); 142 | mv.visitInsn(retType.getOpcode(Opcodes.IRETURN)); 143 | 144 | mv.visitMaxs(Math.max(lvSize, retType.getSize()), lvSize); 145 | mv.visitEnd(); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/ConsoleLogger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2019, 2022, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import net.fabricmc.tinyremapper.api.TrLogger; 22 | 23 | public final class ConsoleLogger implements TrLogger { 24 | private TrLogger.Level level; 25 | 26 | public ConsoleLogger(TrLogger.Level level) { 27 | this.level = level; 28 | } 29 | 30 | public ConsoleLogger() { 31 | this(TrLogger.Level.INFO); 32 | } 33 | 34 | public void setLevel(TrLogger.Level level) { 35 | this.level = level; 36 | } 37 | 38 | @Override 39 | public void log(Level level, String message) { 40 | if (this.level.compareTo(level) <= 0) { 41 | System.out.println("[" + level + "] " + message); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/FileSystemReference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2019, 2022, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import java.io.Closeable; 22 | import java.io.IOException; 23 | import java.net.URI; 24 | import java.net.URISyntaxException; 25 | import java.nio.file.FileSystem; 26 | import java.nio.file.FileSystemAlreadyExistsException; 27 | import java.nio.file.FileSystemNotFoundException; 28 | import java.nio.file.FileSystems; 29 | import java.nio.file.Path; 30 | import java.util.Collections; 31 | import java.util.IdentityHashMap; 32 | import java.util.Map; 33 | import java.util.Set; 34 | 35 | /** 36 | * Reference counted fs handling. 37 | * 38 | *

The implementation closes file systems opened by itself once they are closed as often as they were opened. This 39 | * allows intersecting open+close actions on e.g. the zip based file systems. The caller has to ensure open and close 40 | * invocations are mirrored. 41 | */ 42 | public final class FileSystemReference implements Closeable { 43 | public static FileSystemReference openJar(Path path) throws IOException { 44 | return openJar(path, false); 45 | } 46 | 47 | public static FileSystemReference openJar(Path path, boolean create) throws IOException { 48 | return open(toJarUri(path), create); 49 | } 50 | 51 | private static URI toJarUri(Path path) { 52 | URI uri = path.toUri(); 53 | 54 | try { 55 | return new URI("jar:" + uri.getScheme(), uri.getHost(), uri.getPath(), uri.getFragment()); 56 | } catch (URISyntaxException e) { 57 | throw new RuntimeException("can't convert path "+path+" to uri", e); 58 | } 59 | } 60 | 61 | public static FileSystemReference open(URI uri) throws IOException { 62 | return open(uri, false); 63 | } 64 | 65 | public static FileSystemReference open(URI uri, boolean create) throws IOException { 66 | synchronized (openFsMap) { 67 | boolean opened = false; 68 | FileSystem fs = null; 69 | 70 | try { 71 | fs = FileSystems.getFileSystem(uri); 72 | } catch (FileSystemNotFoundException e) { 73 | try { 74 | fs = FileSystems.newFileSystem(uri, create ? Collections.singletonMap("create", "true") : Collections.emptyMap()); 75 | opened = true; 76 | } catch (FileSystemAlreadyExistsException f) { 77 | fs = FileSystems.getFileSystem(uri); 78 | } 79 | } 80 | 81 | FileSystemReference ret = new FileSystemReference(fs); 82 | Set refs = openFsMap.get(fs); 83 | 84 | if (refs == null) { 85 | refs = Collections.newSetFromMap(new IdentityHashMap<>()); 86 | openFsMap.put(fs, refs); 87 | if (!opened) refs.add(null); 88 | } else if (opened) { 89 | throw new IllegalStateException("opened but already in refs?"); 90 | } 91 | 92 | refs.add(ret); 93 | 94 | return ret; 95 | } 96 | } 97 | 98 | private FileSystemReference(FileSystem fs) { 99 | this.fileSystem = fs; 100 | } 101 | 102 | public boolean isReadOnly() { 103 | if (closed) throw new IllegalStateException("fs closed"); 104 | 105 | return fileSystem.isReadOnly(); 106 | } 107 | 108 | public Path getPath(String first, String... more) { 109 | if (closed) throw new IllegalStateException("fs closed"); 110 | 111 | return fileSystem.getPath(first, more); 112 | } 113 | 114 | public FileSystem getFs() { 115 | if (closed) throw new IllegalStateException("fs closed"); 116 | 117 | return fileSystem; 118 | } 119 | 120 | @Override 121 | public void close() throws IOException { 122 | synchronized (openFsMap) { 123 | if (closed) return; 124 | closed = true; 125 | 126 | Set refs = openFsMap.get(fileSystem); 127 | if (refs == null || !refs.remove(this)) throw new IllegalStateException("fs "+fileSystem+" was already closed"); 128 | 129 | if (refs.isEmpty()) { 130 | openFsMap.remove(fileSystem); 131 | fileSystem.close(); 132 | } else if (refs.size() == 1 && refs.contains(null)) { // only null -> not opened by us, just abandon 133 | openFsMap.remove(fileSystem); 134 | } 135 | } 136 | } 137 | 138 | @Override 139 | public String toString() { 140 | synchronized (openFsMap) { 141 | Set refs = openFsMap.getOrDefault(fileSystem, Collections.emptySet()); 142 | return String.format("%s=%dx,%s", fileSystem, refs.size(), refs.contains(null) ? "existing" : "new"); 143 | } 144 | } 145 | 146 | private static final Map> openFsMap = new IdentityHashMap<>(); 147 | 148 | private final FileSystem fileSystem; 149 | private volatile boolean closed; 150 | } 151 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/IMappingProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2016, 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | @FunctionalInterface 22 | public interface IMappingProvider { 23 | void load(MappingAcceptor out); 24 | 25 | public interface MappingAcceptor { 26 | void acceptClass(String srcName, String dstName); 27 | void acceptMethod(Member method, String dstName); 28 | void acceptMethodArg(Member method, int lvIndex, String dstName); 29 | void acceptMethodVar(Member method, int lvIndex, int startOpIdx, int asmIndex, String dstName); 30 | void acceptField(Member field, String dstName); 31 | } 32 | 33 | final class Member { 34 | public Member(String owner, String name, String desc) { 35 | this.owner = owner; 36 | this.name = name; 37 | this.desc = desc; 38 | } 39 | 40 | public String owner; 41 | public String name; 42 | public String desc; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/InputTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2020, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | public final class InputTag { 22 | InputTag() { } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/MemberInstance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2019, 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; 22 | 23 | import org.objectweb.asm.Opcodes; 24 | 25 | import net.fabricmc.tinyremapper.TinyRemapper.MrjState; 26 | import net.fabricmc.tinyremapper.api.TrClass; 27 | import net.fabricmc.tinyremapper.api.TrField; 28 | import net.fabricmc.tinyremapper.api.TrMember; 29 | import net.fabricmc.tinyremapper.api.TrMethod; 30 | 31 | public final class MemberInstance implements TrField, TrMethod { 32 | MemberInstance(TrMember.MemberType type, ClassInstance cls, String name, String desc, int access, int index) { 33 | this.type = type; 34 | this.cls = cls; 35 | this.name = name; 36 | this.desc = desc; 37 | this.access = access; 38 | this.index = index; 39 | } 40 | 41 | @Override 42 | public MemberType getType() { 43 | return this.type; 44 | } 45 | 46 | @Override 47 | public TrClass getOwner() { 48 | return this.cls; 49 | } 50 | 51 | @Override 52 | public String getName() { 53 | return this.name; 54 | } 55 | 56 | @Override 57 | public String getDesc() { 58 | return this.desc; 59 | } 60 | 61 | @Override 62 | public int getAccess() { 63 | return this.access; 64 | } 65 | 66 | @Override 67 | public int getIndex() { 68 | return index; 69 | } 70 | 71 | public MrjState getContext() { 72 | return cls.getContext(); 73 | } 74 | 75 | public String getId() { 76 | return getId(type, name, desc, cls.tr.ignoreFieldDesc); 77 | } 78 | 79 | public boolean isPublicOrPrivate() { 80 | return (access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE)) != 0; 81 | } 82 | 83 | @Override 84 | public String getNewName() { 85 | String ret = newBridgedName; 86 | 87 | return ret != null ? ret : newName; 88 | } 89 | 90 | public String getNewMappedName() { 91 | return newName; 92 | } 93 | 94 | public String getNewBridgedName() { 95 | return newBridgedName; 96 | } 97 | 98 | public boolean setNewName(String name, boolean fromBridge) { 99 | if (name == null) throw new NullPointerException("null name"); 100 | 101 | if (fromBridge) { 102 | boolean ret = newBridgedNameUpdater.compareAndSet(this, null, name); 103 | 104 | return ret || name.equals(newBridgedName); 105 | } else { 106 | boolean ret = newNameUpdater.compareAndSet(this, null, name); 107 | 108 | return ret || name.equals(newName); 109 | } 110 | } 111 | 112 | public void forceSetNewName(String name) { 113 | newName = name; 114 | } 115 | 116 | @Override 117 | public String toString() { 118 | return String.format("%s/%s%s", cls.getName(), name, desc); 119 | } 120 | 121 | public static String getId(TrMember.MemberType type, String name, String desc, boolean ignoreFieldDesc) { 122 | return type == TrMember.MemberType.METHOD ? getMethodId(name, desc) : getFieldId(name, desc, ignoreFieldDesc); 123 | } 124 | 125 | public static String getMethodId(String name, String desc) { 126 | return name.concat(desc); 127 | } 128 | 129 | public static String getFieldId(String name, String desc, boolean ignoreDesc) { 130 | return ignoreDesc ? name : name+";;"+desc; 131 | } 132 | 133 | public static String getNameFromId(TrMember.MemberType type, String id, boolean ignoreFieldDesc) { 134 | if (ignoreFieldDesc && type == TrMember.MemberType.FIELD) { 135 | return id; 136 | } else { 137 | String separator = type == TrMember.MemberType.METHOD ? "(" : ";;"; 138 | int pos = id.lastIndexOf(separator); 139 | if (pos < 0) throw new IllegalArgumentException(String.format("invalid %s id: %s", type.name(), id)); 140 | 141 | return id.substring(0, pos); 142 | } 143 | } 144 | 145 | private static final AtomicReferenceFieldUpdater newNameUpdater = AtomicReferenceFieldUpdater.newUpdater(MemberInstance.class, String.class, "newName"); 146 | private static final AtomicReferenceFieldUpdater newBridgedNameUpdater = AtomicReferenceFieldUpdater.newUpdater(MemberInstance.class, String.class, "newBridgedName"); 147 | 148 | final TrMember.MemberType type; 149 | final ClassInstance cls; 150 | final String name; 151 | final String desc; 152 | final int access; 153 | final int index; 154 | private volatile String newName; 155 | private volatile String newBridgedName; 156 | String newNameOriginatingCls; 157 | MemberInstance bridgeTarget; 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/MetaInfFixer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, 2022, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import java.io.BufferedOutputStream; 22 | import java.io.BufferedReader; 23 | import java.io.BufferedWriter; 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.io.InputStreamReader; 27 | import java.io.OutputStream; 28 | import java.nio.file.Files; 29 | import java.nio.file.Path; 30 | import java.nio.file.StandardOpenOption; 31 | import java.util.Iterator; 32 | import java.util.jar.Attributes; 33 | import java.util.jar.Manifest; 34 | 35 | public class MetaInfFixer implements OutputConsumerPath.ResourceRemapper { 36 | public static final MetaInfFixer INSTANCE = new MetaInfFixer(); 37 | 38 | protected MetaInfFixer() { } 39 | 40 | @Override 41 | public boolean canTransform(TinyRemapper remapper, Path relativePath) { 42 | return relativePath.startsWith("META-INF") 43 | && (shouldStripForFixMeta(relativePath) 44 | || relativePath.getFileName().toString().equals("MANIFEST.MF") 45 | || (remapper != null && relativePath.getNameCount() == 3 && relativePath.getName(1).toString().equals("services"))); 46 | } 47 | 48 | @Override 49 | public void transform(Path destinationDirectory, Path relativePath, InputStream input, TinyRemapper remapper) throws IOException { 50 | String fileName = relativePath.getFileName().toString(); 51 | 52 | if (relativePath.getNameCount() == 2 && fileName.equals("MANIFEST.MF")) { 53 | Manifest manifest = new Manifest(input); 54 | fixManifest(manifest, remapper); 55 | 56 | Path outputFile = destinationDirectory.resolve(relativePath.toString()); 57 | Path outputDir = outputFile.getParent(); 58 | if (outputDir != null) Files.createDirectories(outputDir); 59 | 60 | try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(outputFile))) { 61 | manifest.write(os); 62 | } 63 | } else if (remapper != null && relativePath.getNameCount() == 3 && relativePath.getName(1).toString().equals("services")) { 64 | Path outputDir = destinationDirectory.resolve(relativePath.toString()).getParent(); 65 | Files.createDirectories(outputDir); 66 | Path outputFile = outputDir.resolve(mapFullyQualifiedClassName(fileName, remapper)); 67 | 68 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(input)); 69 | BufferedWriter writer = Files.newBufferedWriter(outputFile, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)) { 70 | fixServiceDecl(reader, writer, remapper); 71 | } 72 | } 73 | } 74 | 75 | private static boolean shouldStripForFixMeta(Path file) { 76 | if (file.getNameCount() != 2) return false; // not directly inside META-INF dir 77 | 78 | assert file.getName(0).toString().equals("META-INF"); 79 | 80 | String fileName = file.getFileName().toString(); 81 | 82 | // https://docs.oracle.com/en/java/javase/12/docs/specs/jar/jar.html#signed-jar-file 83 | return fileName.endsWith(".SF") 84 | || fileName.endsWith(".DSA") 85 | || fileName.endsWith(".RSA") 86 | || fileName.endsWith(".EC") 87 | || fileName.startsWith("SIG-"); 88 | } 89 | 90 | private static String mapFullyQualifiedClassName(String name, TinyRemapper tr) { 91 | assert name.indexOf('/') < 0; 92 | 93 | return tr.defaultState.remapper.map(name.replace('.', '/')).replace('/', '.'); 94 | } 95 | 96 | private static void fixManifest(Manifest manifest, TinyRemapper remapper) { 97 | Attributes mainAttrs = manifest.getMainAttributes(); 98 | 99 | if (remapper != null) { 100 | String val = mainAttrs.getValue(Attributes.Name.MAIN_CLASS); 101 | if (val != null) mainAttrs.put(Attributes.Name.MAIN_CLASS, mapFullyQualifiedClassName(val, remapper)); 102 | 103 | val = mainAttrs.getValue("Launcher-Agent-Class"); 104 | if (val != null) mainAttrs.putValue("Launcher-Agent-Class", mapFullyQualifiedClassName(val, remapper)); 105 | } 106 | 107 | mainAttrs.remove(Attributes.Name.SIGNATURE_VERSION); 108 | 109 | for (Iterator it = manifest.getEntries().values().iterator(); it.hasNext(); ) { 110 | Attributes attrs = it.next(); 111 | 112 | for (Iterator it2 = attrs.keySet().iterator(); it2.hasNext(); ) { 113 | Attributes.Name attrName = (Attributes.Name) it2.next(); 114 | String name = attrName.toString(); 115 | 116 | if (name.endsWith("-Digest") || name.contains("-Digest-") || name.equals("Magic")) { 117 | it2.remove(); 118 | } 119 | } 120 | 121 | if (attrs.isEmpty()) it.remove(); 122 | } 123 | } 124 | 125 | private static void fixServiceDecl(BufferedReader reader, BufferedWriter writer, TinyRemapper remapper) throws IOException { 126 | String line; 127 | 128 | while ((line = reader.readLine()) != null) { 129 | int end = line.indexOf('#'); 130 | if (end < 0) end = line.length(); 131 | 132 | // trim start+end to skip ' ' and '\t' 133 | 134 | int start = 0; 135 | char c; 136 | 137 | while (start < end && ((c = line.charAt(start)) == ' ' || c == '\t')) { 138 | start++; 139 | } 140 | 141 | while (end > start && ((c = line.charAt(end - 1)) == ' ' || c == '\t')) { 142 | end--; 143 | } 144 | 145 | if (start == end) { 146 | writer.write(line); 147 | } else { 148 | writer.write(line, 0, start); 149 | writer.write(mapFullyQualifiedClassName(line.substring(start, end), remapper)); 150 | writer.write(line, end, line.length() - end); 151 | } 152 | 153 | writer.newLine(); 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/MetaInfRemover.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import java.io.InputStream; 22 | import java.nio.file.Path; 23 | 24 | public class MetaInfRemover implements OutputConsumerPath.ResourceRemapper { 25 | public static final MetaInfRemover INSTANCE = new MetaInfRemover(); 26 | 27 | protected MetaInfRemover() { } 28 | 29 | @Override 30 | public boolean canTransform(TinyRemapper remapper, Path relativePath) { 31 | return relativePath.startsWith("META-INF") && relativePath.getNameCount() != 2; 32 | } 33 | 34 | @Override 35 | public void transform(Path destinationDirectory, Path relativePath, InputStream input, TinyRemapper remapper) { 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/NonClassCopyMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2019, 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import java.util.Arrays; 22 | import java.util.Collections; 23 | import java.util.List; 24 | 25 | public enum NonClassCopyMode { 26 | UNCHANGED(), 27 | FIX_META_INF(MetaInfFixer.INSTANCE), 28 | SKIP_META_INF(MetaInfRemover.INSTANCE); 29 | 30 | public final List remappers; 31 | 32 | NonClassCopyMode(OutputConsumerPath.ResourceRemapper...remappers) { 33 | this.remappers = Collections.unmodifiableList(Arrays.asList(remappers)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/Propagator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import java.util.Set; 22 | 23 | import org.objectweb.asm.Opcodes; 24 | 25 | import net.fabricmc.tinyremapper.TinyRemapper.Direction; 26 | import net.fabricmc.tinyremapper.TinyRemapper.LinkedMethodPropagation; 27 | import net.fabricmc.tinyremapper.api.TrMember; 28 | 29 | final class Propagator { 30 | static void propagate(MemberInstance member, String memberId, String nameDst, Set visitedUp, Set visitedDown) { 31 | ClassInstance cls = member.cls; 32 | boolean isVirtual = member.isVirtual(); 33 | 34 | visitedUp.add(cls); 35 | visitedDown.add(cls); 36 | cls.propagate(member.type, cls.getName(), memberId, nameDst, 37 | (isVirtual ? Direction.ANY : Direction.DOWN), isVirtual, false, 38 | true, visitedUp, visitedDown); 39 | visitedUp.clear(); 40 | visitedDown.clear(); 41 | 42 | if (cls.tr.propagateRecordComponents != LinkedMethodPropagation.DISABLED 43 | && cls.isRecord() 44 | && member.isField() 45 | && (member.access & (Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL)) == (Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL)) { // not static, but private+final 46 | String getterIdSrc = MemberInstance.getMethodId(member.name, "()".concat(member.desc)); 47 | MemberInstance getter = cls.getMember(TrMember.MemberType.METHOD, getterIdSrc); 48 | 49 | if (getter != null && getter.isVirtual()) { 50 | visitedUp.add(cls); 51 | visitedDown.add(cls); 52 | cls.propagate(TrMember.MemberType.METHOD, cls.getName(), getterIdSrc, nameDst, Direction.ANY, true, true, true, visitedUp, visitedDown); 53 | visitedUp.clear(); 54 | visitedDown.clear(); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/VisitTrackingClassRemapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import org.objectweb.asm.AnnotationVisitor; 22 | import org.objectweb.asm.Attribute; 23 | import org.objectweb.asm.ClassVisitor; 24 | import org.objectweb.asm.FieldVisitor; 25 | import org.objectweb.asm.MethodVisitor; 26 | import org.objectweb.asm.ModuleVisitor; 27 | import org.objectweb.asm.RecordComponentVisitor; 28 | import org.objectweb.asm.TypePath; 29 | import org.objectweb.asm.commons.ClassRemapper; 30 | import org.objectweb.asm.commons.Remapper; 31 | 32 | public abstract class VisitTrackingClassRemapper extends ClassRemapper { 33 | public VisitTrackingClassRemapper(ClassVisitor classVisitor, Remapper remapper) { 34 | super(classVisitor, remapper); 35 | } 36 | 37 | @Override 38 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 39 | onVisit(VisitKind.INITIAL); 40 | super.visit(version, access, name, signature, superName, interfaces); 41 | } 42 | 43 | @Override 44 | public void visitSource(String source, String debug) { 45 | onVisit(VisitKind.SOURCE); 46 | super.visitSource(source, debug); 47 | } 48 | 49 | @Override 50 | public ModuleVisitor visitModule(String name, int access, String version) { 51 | onVisit(VisitKind.MODULE); 52 | return super.visitModule(name, access, version); 53 | } 54 | 55 | @Override 56 | public void visitNestHost(String nestHost) { 57 | onVisit(VisitKind.NEST_HOST); 58 | super.visitNestHost(nestHost); 59 | } 60 | 61 | @Override 62 | public void visitPermittedSubclass(String permittedSubclass) { 63 | onVisit(VisitKind.PERMITTED_SUBCLASS); 64 | super.visitPermittedSubclass(permittedSubclass); 65 | } 66 | 67 | @Override 68 | public void visitOuterClass(String owner, String name, String descriptor) { 69 | onVisit(VisitKind.OUTER_CLASS); 70 | super.visitOuterClass(owner, name, descriptor); 71 | } 72 | 73 | @Override 74 | public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { 75 | onVisit(VisitKind.ANNOTATION); 76 | return super.visitAnnotation(descriptor, visible); 77 | } 78 | 79 | @Override 80 | public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { 81 | onVisit(VisitKind.TYPE_ANNOTATION); 82 | return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible); 83 | } 84 | 85 | @Override 86 | public void visitAttribute(Attribute attribute) { 87 | onVisit(VisitKind.ATTRIBUTE); 88 | super.visitAttribute(attribute); 89 | } 90 | 91 | @Override 92 | public void visitNestMember(String nestMember) { 93 | onVisit(VisitKind.NEST_MEMBER); 94 | super.visitNestMember(nestMember); 95 | } 96 | 97 | @Override 98 | public void visitInnerClass(String name, String outerName, String innerName, int access) { 99 | onVisit(VisitKind.INNER_CLASS); 100 | super.visitInnerClass(name, outerName, innerName, access); 101 | } 102 | 103 | @Override 104 | public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) { 105 | onVisit(VisitKind.RECORD_COMPONENT); 106 | return super.visitRecordComponent(name, descriptor, signature); 107 | } 108 | 109 | @Override 110 | public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { 111 | onVisit(VisitKind.FIELD); 112 | return super.visitField(access, name, descriptor, signature, value); 113 | } 114 | 115 | @Override 116 | public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { 117 | onVisit(VisitKind.METHOD); 118 | return super.visitMethod(access, name, descriptor, signature, exceptions); 119 | } 120 | 121 | @Override 122 | public void visitEnd() { 123 | onVisit(VisitKind.END); 124 | super.visitEnd(); 125 | } 126 | 127 | protected abstract void onVisit(VisitKind kind); 128 | 129 | protected enum VisitKind { 130 | // in visitation order 131 | INITIAL, SOURCE, MODULE, NEST_HOST, PERMITTED_SUBCLASS, OUTER_CLASS, 132 | ANNOTATION, TYPE_ANNOTATION, ATTRIBUTE, 133 | NEST_MEMBER, INNER_CLASS, RECORD_COMPONENT, FIELD, METHOD, 134 | END 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/api/TrClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.api; 20 | 21 | import java.util.Collection; 22 | import java.util.List; 23 | import java.util.function.Predicate; 24 | 25 | import org.objectweb.asm.ClassVisitor; 26 | import org.objectweb.asm.Opcodes; 27 | 28 | public interface TrClass { 29 | TrEnvironment getEnvironment(); 30 | 31 | String getName(); 32 | String getSuperName(); 33 | List getInterfaceNames(); 34 | String getSignature(); 35 | int getAccess(); 36 | 37 | TrClass getSuperClass(); 38 | List getInterfaces(); 39 | 40 | Collection getParents(); 41 | Collection getChildren(); 42 | 43 | TrField getField(String name, String desc); 44 | TrMethod getMethod(String name, String desc); 45 | 46 | Collection getFields(); 47 | Collection getMethods(); 48 | Collection getMembers(); 49 | 50 | Collection getFields(String name, String desc, boolean isDescPrefix, Predicate filter, Collection out); 51 | Collection getMethods(String name, String desc, boolean isDescPrefix, Predicate filter, Collection out); 52 | 53 | TrField resolveField(String name, String desc); 54 | TrMethod resolveMethod(String name, String desc); 55 | 56 | /** 57 | * Get fields in the class, including the one inherited from super-class or super-interfaces, satisfy the search query. 58 | * @param name the name of the field. Nullable. 59 | * @param desc the descriptor (or descriptor prefix) of the field. Nullable. 60 | * @param isDescPrefix is {@code descPrefix} a full qualified descriptor or a prefix. 61 | * @param filter any additional constraint. Nullable. 62 | * @param out if not {@code null}, then reuse this collection instead of allocate a new one. The behaviour 63 | * is undefined is the collection is non-empty. Nullable. 64 | * @return the query result. 65 | */ 66 | Collection resolveFields(String name, String desc, boolean isDescPrefix, Predicate filter, Collection out); 67 | 68 | /** 69 | * Get methods in the class, including the one inherited from super-class or super-interfaces, satisfy the search query. 70 | * @param name the name of the method. Nullable. 71 | * @param desc the descriptor (or descriptor prefix) of the method. Nullable. 72 | * @param isDescPrefix is {@code descPrefix} a full qualified descriptor or a prefix. 73 | * @param filter any additional constraint. Nullable. 74 | * @param out if not {@code null}, then reuse this collection instead of the internal one. The behaviour 75 | * is undefined is the collection is non-empty. Nullable. 76 | * @return the query result. 77 | */ 78 | Collection resolveMethods(String name, String desc, boolean isDescPrefix, Predicate filter, Collection out); 79 | 80 | boolean isAssignableFrom(TrClass cls); 81 | void accept(ClassVisitor cv, int readerFlags); 82 | 83 | /** 84 | * May be accessed from outside its package. 85 | */ 86 | default boolean isPublic() { 87 | return (getAccess() & Opcodes.ACC_PUBLIC) != 0; 88 | } 89 | 90 | /** 91 | * No subclasses allowed. 92 | */ 93 | default boolean isFinal() { 94 | return (getAccess() & Opcodes.ACC_FINAL) != 0; 95 | } 96 | 97 | /** 98 | * Is an interface, not a class. 99 | */ 100 | default boolean isInterface() { 101 | return (getAccess() & Opcodes.ACC_INTERFACE) != 0; 102 | } 103 | 104 | /** 105 | * Declared {@code abstract}; must not be instantiated. 106 | */ 107 | default boolean isAbstract() { 108 | return (getAccess() & Opcodes.ACC_ABSTRACT) != 0; 109 | } 110 | 111 | /** 112 | * Declared {@code synthetic}; not present in the source code. 113 | */ 114 | default boolean isSynthetic() { 115 | return (getAccess() & Opcodes.ACC_SYNTHETIC) != 0; 116 | } 117 | 118 | /** 119 | * Declared as an annotation interface. 120 | */ 121 | default boolean isAnnotation() { 122 | return (getAccess() & Opcodes.ACC_ANNOTATION) != 0; 123 | } 124 | 125 | /** 126 | * Declared as an enum class. 127 | */ 128 | default boolean isEnum() { 129 | return (getAccess() & Opcodes.ACC_ENUM) != 0; 130 | } 131 | 132 | /** 133 | * Declare as a record class. 134 | */ 135 | default boolean isRecord() { 136 | return (getAccess() & Opcodes.ACC_RECORD) != 0; 137 | } 138 | 139 | /** 140 | * Is a module, not a class or interface. 141 | */ 142 | default boolean isModule() { 143 | return (getAccess() & Opcodes.ACC_MODULE) != 0; 144 | } 145 | 146 | /** 147 | * Return true when this class is from an input, and not just on the classpath. 148 | */ 149 | boolean isInput(); 150 | } 151 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/api/TrEnvironment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.api; 20 | 21 | public interface TrEnvironment { 22 | int getMrjVersion(); 23 | TrRemapper getRemapper(); 24 | TrLogger getLogger(); 25 | 26 | /** 27 | * @return the class with the passed name, or null if not found. 28 | */ 29 | TrClass getClass(String internalName); 30 | 31 | default TrField getField(String owner, String name, String desc) { 32 | TrClass cls = getClass(owner); 33 | 34 | return cls != null ? cls.getField(name, desc) : null; 35 | } 36 | 37 | default TrMethod getMethod(String owner, String name, String desc) { 38 | TrClass cls = getClass(owner); 39 | 40 | return cls != null ? cls.getMethod(name, desc) : null; 41 | } 42 | 43 | void propagate(TrMember member, String newName); 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/api/TrField.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.api; 20 | 21 | import org.objectweb.asm.Opcodes; 22 | 23 | public interface TrField extends TrMember { 24 | /** 25 | * Declared volatile; cannot be cached. 26 | */ 27 | default boolean isVolatile() { 28 | return getType().equals(MemberType.FIELD) && (getAccess() & Opcodes.ACC_VOLATILE) != 0; 29 | } 30 | 31 | /** 32 | * Declared as an element of an enum class. 33 | */ 34 | default boolean isEnum() { 35 | return getType().equals(MemberType.FIELD) && (getAccess() & Opcodes.ACC_ENUM) != 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/api/TrLogger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2019, 2022, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.api; 20 | 21 | public interface TrLogger { 22 | void log(Level level, String message); 23 | 24 | default void log(Level level, String message, Object... args) { 25 | log(level, String.format(message, args)); 26 | } 27 | 28 | default void debug(String message) { 29 | log(Level.DEBUG, message); 30 | } 31 | 32 | default void debug(String message, Object... args) { 33 | log(Level.DEBUG, message, args); 34 | } 35 | 36 | default void info(String message) { 37 | log(Level.INFO, message); 38 | } 39 | 40 | default void info(String message, Object... args) { 41 | log(Level.INFO, message, args); 42 | } 43 | 44 | default void warn(String message) { 45 | log(Level.WARN, message); 46 | } 47 | 48 | default void warn(String message, Object... args) { 49 | log(Level.WARN, message, args); 50 | } 51 | 52 | default void error(String message) { 53 | log(Level.ERROR, message); 54 | } 55 | 56 | default void error(String message, Object... args) { 57 | log(Level.ERROR, message, args); 58 | } 59 | 60 | enum Level { 61 | DEBUG, 62 | INFO, 63 | WARN, 64 | ERROR 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/api/TrMember.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.api; 20 | 21 | import org.objectweb.asm.ClassVisitor; 22 | import org.objectweb.asm.Opcodes; 23 | 24 | public interface TrMember { 25 | default boolean isField() { 26 | return getType() == MemberType.FIELD; 27 | } 28 | 29 | default boolean isMethod() { 30 | return getType() == MemberType.METHOD; 31 | } 32 | 33 | MemberType getType(); 34 | 35 | TrClass getOwner(); 36 | 37 | /** 38 | * @see ClassVisitor#visitField(int, String, String, String, Object) 39 | */ 40 | String getName(); 41 | String getNewName(); 42 | 43 | /** 44 | * @see ClassVisitor#visitField(int, String, String, String, Object) 45 | */ 46 | String getDesc(); 47 | 48 | /** 49 | * @see Opcodes 50 | */ 51 | int getAccess(); 52 | 53 | /** 54 | * Position inside the class relative to other members, in occurrence order. 55 | */ 56 | int getIndex(); 57 | 58 | /** 59 | * Declared public; may be accessed from outside its package. 60 | */ 61 | default boolean isPublic() { 62 | return (getAccess() & Opcodes.ACC_PUBLIC) != 0; 63 | } 64 | 65 | /** 66 | * Declared protected; may be accessed within subclasses. 67 | */ 68 | default boolean isProtected() { 69 | return (getAccess() & Opcodes.ACC_PROTECTED) != 0; 70 | } 71 | 72 | /** 73 | * Declared private; accessible only within the defining class and other classes belonging to the same nest (§5.4.4). 74 | */ 75 | default boolean isPrivate() { 76 | return (getAccess() & Opcodes.ACC_PRIVATE) != 0; 77 | } 78 | 79 | /** 80 | * Declared static. 81 | */ 82 | default boolean isStatic() { 83 | return (getAccess() & Opcodes.ACC_STATIC) != 0; 84 | } 85 | 86 | /** 87 | * Declared final; never directly assigned to after object construction / must not be overridden (§5.4.5). 88 | */ 89 | default boolean isFinal() { 90 | return (getAccess() & Opcodes.ACC_FINAL) != 0; 91 | } 92 | 93 | /** 94 | * Declared synthetic; not present in the source code. 95 | */ 96 | default boolean isSynthetic() { 97 | return (getAccess() & Opcodes.ACC_SYNTHETIC) != 0; 98 | } 99 | 100 | enum MemberType { 101 | METHOD, 102 | FIELD 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/api/TrMethod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.api; 20 | 21 | import org.objectweb.asm.Opcodes; 22 | 23 | public interface TrMethod extends TrMember { 24 | /** 25 | * A bridge method, generated by the compiler. 26 | */ 27 | default boolean isBridge() { 28 | return getType().equals(MemberType.METHOD) && (getAccess() & Opcodes.ACC_BRIDGE) != 0; 29 | } 30 | 31 | /** 32 | * Declared native; implemented in a language other than the Java programming language. 33 | */ 34 | default boolean isNative() { 35 | return getType().equals(MemberType.METHOD) && (getAccess() & Opcodes.ACC_NATIVE) != 0; 36 | } 37 | 38 | /** 39 | * Declared abstract; no implementation is provided. 40 | */ 41 | default boolean isAbstract() { 42 | return getType().equals(MemberType.METHOD) && (getAccess() & Opcodes.ACC_ABSTRACT) != 0; 43 | } 44 | 45 | /** 46 | * Non-static and non-private method. 47 | */ 48 | default boolean isVirtual() { 49 | return getType().equals(MemberType.METHOD) && (getAccess() & (Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE)) == 0; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/api/TrRemapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.api; 20 | 21 | import org.objectweb.asm.commons.Remapper; 22 | 23 | public abstract class TrRemapper extends Remapper { 24 | /** 25 | * remaps a method when the full descriptor is unknown. 26 | * @param owner the owner of the method 27 | * @param name the name of the method 28 | * @param descPrefix the part of the descriptor that is known (must be the start) 29 | * @return the mapped name 30 | */ 31 | public abstract String mapMethodNamePrefixDesc(String owner, String name, String descPrefix); 32 | 33 | /** 34 | * remaps a parameter name. 35 | * @param lvIndex the local variable index of the arg 36 | */ 37 | public abstract String mapMethodArg(String methodOwner, String methodName, String methodDesc, int lvIndex, String name); 38 | 39 | public abstract String mapMethodVar(String methodOwner, String methodName, String methodDesc, int lvIndex, int startOpIdx, int asmIndex, String name); 40 | 41 | /** 42 | * @deprecated Please use {@link TrRemapper#mapAnnotationAttributeName(String, String, String)} 43 | */ 44 | @Deprecated 45 | @Override 46 | public String mapAnnotationAttributeName(String descriptor, String name) { 47 | return super.mapAnnotationAttributeName(descriptor, name); 48 | } 49 | 50 | public abstract String mapAnnotationAttributeName(String annotationDesc, String name, String attributeDesc); 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/common/IMappable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.common; 20 | 21 | public interface IMappable { 22 | T result(); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/common/MapUtility.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.common; 20 | 21 | import java.util.Arrays; 22 | import java.util.List; 23 | import java.util.Objects; 24 | 25 | import net.fabricmc.tinyremapper.api.TrClass; 26 | import net.fabricmc.tinyremapper.api.TrLogger; 27 | import net.fabricmc.tinyremapper.api.TrMember; 28 | import net.fabricmc.tinyremapper.api.TrRemapper; 29 | 30 | public final class MapUtility { 31 | private final TrRemapper remapper; 32 | private final TrLogger logger; 33 | 34 | public static final List IGNORED_NAME = Arrays.asList("", ""); 35 | 36 | public MapUtility(TrRemapper remapper, TrLogger logger) { 37 | this.remapper = Objects.requireNonNull(remapper); 38 | this.logger = Objects.requireNonNull(logger); 39 | } 40 | 41 | public String mapName(TrClass _class) { 42 | return remapper.map(_class.getName()); 43 | } 44 | 45 | public String mapName(TrMember member) { 46 | if (member.isField()) { 47 | return remapper.mapFieldName(member.getOwner().getName(), member.getName(), member.getDesc()); 48 | } else { 49 | return remapper.mapMethodName(member.getOwner().getName(), member.getName(), member.getDesc()); 50 | } 51 | } 52 | 53 | public String mapDesc(TrClass _class) { 54 | return StringUtility.classNameToDesc(mapName(_class)); 55 | } 56 | 57 | public String mapDesc(TrMember member) { 58 | if (member.isField()) { 59 | return remapper.mapDesc(member.getDesc()); 60 | } else { 61 | return remapper.mapMethodDesc(member.getDesc()); 62 | } 63 | } 64 | 65 | public String mapOwner(TrMember member) { 66 | return mapName(member.getOwner()); 67 | } 68 | 69 | public TrRemapper asTrRemapper() { 70 | return this.remapper; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/common/ResolveUtility.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.common; 20 | 21 | import java.util.Collection; 22 | import java.util.Comparator; 23 | import java.util.Objects; 24 | import java.util.Optional; 25 | import java.util.function.Supplier; 26 | 27 | import net.fabricmc.tinyremapper.api.TrClass; 28 | import net.fabricmc.tinyremapper.api.TrEnvironment; 29 | import net.fabricmc.tinyremapper.api.TrField; 30 | import net.fabricmc.tinyremapper.api.TrLogger; 31 | import net.fabricmc.tinyremapper.api.TrMember; 32 | import net.fabricmc.tinyremapper.api.TrMember.MemberType; 33 | import net.fabricmc.tinyremapper.api.TrMethod; 34 | 35 | public final class ResolveUtility { 36 | /** 37 | * Raise error if the result is not unique. 38 | */ 39 | public static int FLAG_UNIQUE = 0x1; 40 | /** 41 | * Return first member based on asm ordinal if the result is not unique. 42 | */ 43 | public static int FLAG_FIRST = 0x2; 44 | /** 45 | * Recursively resolve the the member including super-class and super-interface. 46 | */ 47 | public static int FLAG_RECURSIVE = 0x4; 48 | /** 49 | * Prefer non-synthetic member. This has higher priority than {@link ResolveUtility#FLAG_FIRST}; 50 | */ 51 | public static int FLAG_NON_SYN = 0x8; 52 | 53 | private final TrEnvironment environment; 54 | private final TrLogger logger; 55 | 56 | public ResolveUtility(TrEnvironment environment) { 57 | this.environment = Objects.requireNonNull(environment); 58 | this.logger = environment.getLogger(); 59 | } 60 | 61 | public Optional resolveClass(String name) { 62 | TrClass _class = environment.getClass(name); 63 | return Optional.ofNullable(_class); 64 | } 65 | 66 | private Optional resolveMember0(TrClass owner, String name, String desc, int flag, Supplier> get, Supplier> resolve) { 67 | if ((flag & (FLAG_UNIQUE | FLAG_FIRST)) == 0) { 68 | throw new RuntimeException("Unspecified resolution strategy, please use FLAG_UNIQUE or FLAG_FIRST."); 69 | } else if (owner == null) { 70 | return Optional.empty(); 71 | } 72 | 73 | Collection collection; 74 | 75 | if ((flag & FLAG_RECURSIVE) != 0) { 76 | collection = resolve.get(); 77 | } else { 78 | collection = get.get(); 79 | } 80 | 81 | if ((flag & FLAG_UNIQUE) != 0) { 82 | if (collection.size() > 1) { 83 | throw new RuntimeException(String.format("The member %s:%s is ambiguous in class %s for FLAG_UNIQUE. Please use FLAG_FIRST.", name, desc, owner.getName())); 84 | } else { 85 | return collection.stream().findFirst(); 86 | } 87 | } 88 | 89 | Comparator comparator; 90 | 91 | if ((flag & FLAG_NON_SYN) != 0) { 92 | comparator = (x, y) -> Boolean.compare(x.isSynthetic(), y.isSynthetic()) != 0 93 | ? Boolean.compare(x.isSynthetic(), y.isSynthetic()) : Integer.compare(x.getIndex(), y.getIndex()); 94 | } else { 95 | comparator = Comparator.comparingInt(TrMember::getIndex); 96 | } 97 | 98 | return collection.stream().min(comparator); 99 | } 100 | 101 | public Optional resolveField(TrClass owner, String name, String desc, int flag) { 102 | return resolveMember0(owner, name, desc, flag, 103 | () -> owner.getFields(name, desc, false, null, null), 104 | () -> owner.resolveFields(name, desc, false, null, null)); 105 | } 106 | 107 | public Optional resolveField(String owner, String name, String desc, int flag) { 108 | return resolveClass(owner).flatMap(cls -> resolveField(cls, name, desc, flag)); 109 | } 110 | 111 | public Optional resolveMethod(TrClass owner, String name, String desc, int flag) { 112 | return resolveMember0(owner, name, desc, flag, 113 | () -> owner.getMethods(name, desc, false, null, null), 114 | () -> owner.resolveMethods(name, desc, false, null, null)); 115 | } 116 | 117 | public Optional resolveMethod(String owner, String name, String desc, int flag) { 118 | return resolveClass(owner).flatMap(cls -> resolveMethod(cls, name, desc, flag)); 119 | } 120 | 121 | public Optional resolveMember(TrClass owner, String name, String desc, int flag) { 122 | if (desc == null) throw new RuntimeException("desc cannot be null for resolveMember. Please use resolveMethod or resolveField."); 123 | 124 | MemberType type = StringUtility.getTypeByDesc(desc); 125 | 126 | if (type.equals(MemberType.FIELD)) { 127 | return resolveField(owner, name, desc, flag).map(m -> m); 128 | } else if (type.equals(MemberType.METHOD)) { 129 | return resolveMethod(owner, name, desc, flag).map(m -> m); 130 | } else { 131 | throw new RuntimeException(String.format("Unknown member type %s", type.name())); 132 | } 133 | } 134 | 135 | public Optional resolveMember(String owner, String name, String desc, int flag) { 136 | return resolveClass(owner).flatMap(cls -> resolveMember(cls, name, desc, flag)); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/common/StringUtility.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.common; 20 | 21 | import java.util.Locale; 22 | import java.util.regex.Pattern; 23 | 24 | import net.fabricmc.tinyremapper.api.TrMember.MemberType; 25 | 26 | public final class StringUtility { 27 | public static String addPrefix(String prefix, String text) { 28 | return prefix + text; 29 | } 30 | 31 | public static String removePrefix(String prefix, String text) { 32 | if (text.startsWith(prefix)) { 33 | return text.substring(prefix.length()); 34 | } else { 35 | throw new RuntimeException(String.format("%s does not start with %s", text, prefix)); 36 | } 37 | } 38 | 39 | public static String addCamelPrefix(String prefix, String text) { 40 | if (text.isEmpty()) { 41 | return prefix; 42 | } else { 43 | return prefix + text.substring(0, 1).toUpperCase(Locale.ROOT) + text.substring(1); 44 | } 45 | } 46 | 47 | public static String removeCamelPrefix(String prefix, String text) { 48 | text = removePrefix(prefix, text); 49 | 50 | if (text.isEmpty() || text.toUpperCase(Locale.ROOT).equals(text)) { 51 | return text; 52 | } else { 53 | if (Character.isLowerCase(text.charAt(0))) throw new RuntimeException(String.format("%s does not start with camel prefix %s", text, prefix)); 54 | return text.substring(0, 1).toLowerCase(Locale.ROOT) + text.substring(1); 55 | } 56 | } 57 | 58 | private static final Pattern CLASS_NAME_PATTERN = Pattern.compile("([A-Za-z0-9_$]+/)*[A-Za-z0-9_$]+"); 59 | private static final Pattern CLASS_DESC_PATTERN = Pattern.compile("L" + CLASS_NAME_PATTERN + ";"); 60 | 61 | public static boolean isClassName(String text) { 62 | return CLASS_NAME_PATTERN.matcher(text).matches(); 63 | } 64 | 65 | public static boolean isClassDesc(String text) { 66 | return CLASS_DESC_PATTERN.matcher(text).matches(); 67 | } 68 | 69 | private static final Pattern FIELD_DESC_PATTERN = Pattern.compile("\\[*(" + CLASS_DESC_PATTERN +"|[BCDFIJSZ])"); 70 | private static final Pattern METHOD_DESC_PATTERN = Pattern.compile("\\((" + FIELD_DESC_PATTERN + ")*\\)(" + FIELD_DESC_PATTERN + "|V)"); 71 | 72 | public static boolean isFieldDesc(String text) { 73 | return FIELD_DESC_PATTERN.matcher(text).matches(); 74 | } 75 | 76 | public static boolean isMethodDesc(String text) { 77 | return METHOD_DESC_PATTERN.matcher(text).matches(); 78 | } 79 | 80 | public static MemberType getTypeByDesc(String text) { 81 | if (StringUtility.isFieldDesc(text)) { 82 | return MemberType.FIELD; 83 | } else if (StringUtility.isMethodDesc(text)) { 84 | return MemberType.METHOD; 85 | } else { 86 | throw new RuntimeException(String.format("%s is neither field descriptor nor method descriptor.", text)); 87 | } 88 | } 89 | 90 | private static final Pattern INTERNAL_CLASS_PATTERN = Pattern.compile("java/.*"); 91 | 92 | public static boolean isInternalClassName(String className) { 93 | if (!isClassName(className)) throw new RuntimeException(String.format("%s is not a class name.", className)); 94 | 95 | if (INTERNAL_CLASS_PATTERN.matcher(className).matches()) { 96 | return true; 97 | } 98 | 99 | try { 100 | Class.forName(className.replace('/', '.')); 101 | return true; 102 | } catch (Exception e) { 103 | return false; 104 | } 105 | } 106 | 107 | public static String classNameToDesc(String className) { 108 | if (!isClassName(className)) throw new RuntimeException(String.format("%s is not a class name.", className)); 109 | return "L" + className + ";"; 110 | } 111 | 112 | public static String classDescToName(String classDesc) { 113 | if (!isClassDesc(classDesc)) throw new RuntimeException(String.format("%s is not a class descriptor.", classDesc)); 114 | return classDesc.substring(1, classDesc.length() - 1); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/common/data/Annotation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2016, 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.common.data; 20 | 21 | public final class Annotation { 22 | // .* 23 | public static final String DEBUG = "Lorg/spongepowered/asm/mixin/Debug;"; 24 | public static final String DYNAMIC = "Lorg/spongepowered/asm/mixin/Dynamic;"; 25 | public static final String FINAL = "Lorg/spongepowered/asm/mixin/Final;"; 26 | public static final String IMPLEMENTS = "Lorg/spongepowered/asm/mixin/Implements;"; 27 | public static final String INTERFACE = "Lorg/spongepowered/asm/mixin/Interface;"; 28 | public static final String INTRINSIC = "Lorg/spongepowered/asm/mixin/Intrinsic;"; 29 | public static final String MIXIN = "Lorg/spongepowered/asm/mixin/Mixin;"; 30 | public static final String MUTABLE = "Lorg/spongepowered/asm/mixin/Mutable;"; 31 | public static final String OVERWRITE = "Lorg/spongepowered/asm/mixin/Overwrite;"; 32 | public static final String PSEUDO = "Lorg/spongepowered/asm/mixin/Pseudo;"; 33 | public static final String SHADOW = "Lorg/spongepowered/asm/mixin/Shadow;"; 34 | public static final String SOFT_OVERRIDE = "Lorg/spongepowered/asm/mixin/SoftOverride;"; 35 | public static final String UNIQUE = "Lorg/spongepowered/asm/mixin/Unique;"; 36 | // .gen.* 37 | public static final String ACCESSOR = "Lorg/spongepowered/asm/mixin/gen/Accessor;"; 38 | public static final String INVOKER = "Lorg/spongepowered/asm/mixin/gen/Invoker;"; 39 | // .injection.* 40 | public static final String AT = "Lorg/spongepowered/asm/mixin/injection/At;"; 41 | public static final String COERCE = "Lorg/spongepowered/asm/mixin/injection/Coerce;"; 42 | public static final String CONSTANT = "Lorg/spongepowered/asm/mixin/injection/Constant;"; 43 | public static final String DESC = "Lorg/spongepowered/asm/mixin/injection/Desc;"; 44 | public static final String DESCRIPTORS = "Lorg/spongepowered/asm/mixin/injection/Descriptors;"; 45 | public static final String GROUP = "Lorg/spongepowered/asm/mixin/injection/Group;"; 46 | public static final String INJECT = "Lorg/spongepowered/asm/mixin/injection/Inject;"; 47 | public static final String AT_CODE = "Lorg/spongepowered/asm/mixin/injection/InjectionPoint/AtCode;"; 48 | public static final String MODIFY_ARG = "Lorg/spongepowered/asm/mixin/injection/ModifyArg;"; 49 | public static final String MODIFY_ARGS = "Lorg/spongepowered/asm/mixin/injection/ModifyArgs;"; 50 | public static final String MODIFY_CONSTANT = "Lorg/spongepowered/asm/mixin/injection/ModifyConstant;"; 51 | public static final String MODIFY_VARIABLE = "Lorg/spongepowered/asm/mixin/injection/ModifyVariable;"; 52 | public static final String REDIRECT = "Lorg/spongepowered/asm/mixin/injection/Redirect;"; 53 | public static final String SLICE = "Lorg/spongepowered/asm/mixin/injection/Slice;"; 54 | public static final String Surrogate = "Lorg/spongepowered/asm/mixin/injection/Surrogate;"; 55 | // .injection.selectors.* 56 | public static final String SELECTOR_ID = "Lorg/spongepowered/asm/mixin/injection/selectors/ITargetSelectorDynamic/SelectorId;"; 57 | public static final String SELECTOR_ANNOTATION = "Lorg/spongepowered/asm/mixin/injection/selectors/ITargetSelectorDynamic/SelectorAnnotation;"; 58 | // .injection.struct.* 59 | public static final String ANNOTATION_TYPE = "Lorg/spongepowered/asm/mixin/injection/struct/InjectionInfo/AnnotationType;"; 60 | public static final String HANDLER_PREFIX = "Lorg/spongepowered/asm/mixin/injection/struct/InjectionInfo/HandlerPrefix;"; 61 | // .transformer.meta.* 62 | public static final String MIXIN_INNER = "Lorg/spongepowered/asm/mixin/transformer/meta/MixinInner;"; 63 | public static final String MIXIN_MERGED = "Lorg/spongepowered/asm/mixin/transformer/meta/MixinMerged;"; 64 | public static final String MIXIN_PROXY = "Lorg/spongepowered/asm/mixin/transformer/meta/MixinProxy;"; 65 | public static final String MIXIN_RENAMED = "Lorg/spongepowered/asm/mixin/transformer/meta/MixinRenamed;"; 66 | 67 | public static final String MIXIN_EXTRAS_MODIFY_EXPRESSION_VALUE = "Lcom/llamalad7/mixinextras/injector/ModifyExpressionValue;"; 68 | public static final String MIXIN_EXTRAS_MODIFY_RECEIVER = "Lcom/llamalad7/mixinextras/injector/ModifyReceiver;"; 69 | public static final String MIXIN_EXTRAS_MODIFY_RETURN_VALUE = "Lcom/llamalad7/mixinextras/injector/ModifyReturnValue;"; 70 | public static final String MIXIN_EXTRAS_WRAP_METHOD = "Lcom/llamalad7/mixinextras/injector/wrapmethod/WrapMethod;"; 71 | public static final String MIXIN_EXTRAS_WRAP_OPERATION = "Lcom/llamalad7/mixinextras/injector/wrapoperation/WrapOperation;"; 72 | public static final String MIXIN_EXTRAS_WRAP_WITH_CONDITION = "Lcom/llamalad7/mixinextras/injector/WrapWithCondition;"; 73 | public static final String MIXIN_EXTRAS_WRAP_WITH_CONDITION_V2 = "Lcom/llamalad7/mixinextras/injector/v2/WrapWithCondition;"; 74 | public static final String MIXIN_EXTRAS_DEFINITIONS = "Lcom/llamalad7/mixinextras/expression/Definitions;"; 75 | public static final String MIXIN_EXTRAS_DEFINITION = "Lcom/llamalad7/mixinextras/expression/Definition;"; 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/common/data/AnnotationElement.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.common.data; 20 | 21 | public final class AnnotationElement { 22 | public static final String VALUE = "value"; 23 | public static final String REMAP = "remap"; 24 | public static final String TARGET = "target"; 25 | public static final String TARGETS = "targets"; 26 | public static final String PREFIX = "prefix"; 27 | public static final String IFACE = "iface"; 28 | public static final String DESC = "desc"; 29 | public static final String ARGS = "args"; 30 | public static final String OWNER = "owner"; 31 | public static final String RET = "ret"; 32 | public static final String AT = "at"; 33 | public static final String FROM = "from"; 34 | public static final String TO = "to"; 35 | public static final String SLICE = "slice"; 36 | public static final String METHOD = "method"; 37 | public static final String DEFINITION_METHOD = "method"; 38 | public static final String DEFINITION_FIELD = "field"; 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/common/data/CommonData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.common.data; 20 | 21 | import java.util.Objects; 22 | 23 | import net.fabricmc.tinyremapper.api.TrEnvironment; 24 | import net.fabricmc.tinyremapper.api.TrLogger; 25 | import net.fabricmc.tinyremapper.api.TrMember; 26 | import net.fabricmc.tinyremapper.extension.mixin.common.MapUtility; 27 | import net.fabricmc.tinyremapper.extension.mixin.common.ResolveUtility; 28 | 29 | public final class CommonData { 30 | private final TrEnvironment environment; 31 | 32 | public final ResolveUtility resolver; 33 | public final MapUtility mapper; 34 | 35 | public CommonData(TrEnvironment environment) { 36 | this.environment = Objects.requireNonNull(environment); 37 | 38 | this.resolver = new ResolveUtility(environment); 39 | this.mapper = new MapUtility(environment.getRemapper(), environment.getLogger()); 40 | } 41 | 42 | public TrLogger getLogger() { 43 | return this.environment.getLogger(); 44 | } 45 | 46 | public void propagate(TrMember member, String newName) { 47 | this.environment.propagate(member, newName); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/common/data/Constant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.common.data; 20 | 21 | import org.objectweb.asm.Opcodes; 22 | 23 | public final class Constant { 24 | public static final int ASM_VERSION = Opcodes.ASM9; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/common/data/Message.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.common.data; 20 | 21 | public final class Message { 22 | public static final String CANNOT_RESOLVE_CLASS = "Cannot resolve class %s"; 23 | public static final String CONFLICT_MAPPING = "Conflict mapping detected, %s -> %s."; 24 | public static final String MULTIPLE_MAPPING_CHOICES = "Multiple conflicting mapping choices found for %s, which can be remapped to %s or %s. Such issues can be resolved by using fully qualified selectors."; 25 | public static final String NO_MAPPING_NON_RECURSIVE = "Cannot remap %s because it does not exists in any of the targets %s"; 26 | public static final String NO_MAPPING_RECURSIVE = "Cannot remap %s because it does not exists in any of the targets %s or their parents."; 27 | public static final String NOT_FULLY_QUALIFIED = "%s is not fully qualified."; 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/common/data/MxClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.common.data; 20 | 21 | import java.util.Objects; 22 | 23 | import net.fabricmc.tinyremapper.api.TrClass; 24 | import net.fabricmc.tinyremapper.extension.mixin.common.ResolveUtility; 25 | 26 | public class MxClass { 27 | private final String name; 28 | 29 | public MxClass(String name) { 30 | this.name = Objects.requireNonNull(name); 31 | } 32 | 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | public MxMember getField(String name, String desc) { 38 | return new MxMember(this.name, name, desc); 39 | } 40 | 41 | public MxMember getMethod(String name, String desc) { 42 | return new MxMember(this.name, name, desc); 43 | } 44 | 45 | public TrClass asTrClass(ResolveUtility resolver) { 46 | return resolver.resolveClass(name) 47 | .orElseThrow(() -> new RuntimeException(String.format("Cannot convert %s to TrClass.", name))); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/common/data/MxMember.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.common.data; 20 | 21 | import java.util.Objects; 22 | 23 | import net.fabricmc.tinyremapper.api.TrMember; 24 | import net.fabricmc.tinyremapper.api.TrMember.MemberType; 25 | import net.fabricmc.tinyremapper.extension.mixin.common.ResolveUtility; 26 | import net.fabricmc.tinyremapper.extension.mixin.common.StringUtility; 27 | 28 | public class MxMember { 29 | private final String owner; 30 | private final String name; 31 | private final String desc; 32 | 33 | MxMember(String owner, String name, String desc) { 34 | this.owner = Objects.requireNonNull(owner); 35 | this.name = Objects.requireNonNull(name); 36 | this.desc = Objects.requireNonNull(desc); 37 | } 38 | 39 | public String getName() { 40 | return name; 41 | } 42 | 43 | public String getDesc() { 44 | return desc; 45 | } 46 | 47 | public MemberType getType() { 48 | return StringUtility.getTypeByDesc(desc); 49 | } 50 | 51 | public MxClass getOwner() { 52 | return new MxClass(owner); 53 | } 54 | 55 | public TrMember asTrMember(ResolveUtility resolver) { 56 | return resolver.resolveMember(owner, name, desc, ResolveUtility.FLAG_UNIQUE) 57 | .orElseThrow(() -> new RuntimeException(String.format("Cannot convert %s %s %s to TrMember", owner, name, desc))); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/common/data/Pair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.common.data; 20 | 21 | import java.util.Objects; 22 | 23 | public final class Pair { 24 | private final L first; 25 | private final R second; 26 | 27 | private Pair(L first, R second) { 28 | this.first = first; 29 | this.second = second; 30 | } 31 | 32 | public static Pair of(final L first, final R second) { 33 | return new Pair<>(first, second); 34 | } 35 | 36 | public L first() { 37 | return this.first; 38 | } 39 | 40 | public R second() { 41 | return this.second; 42 | } 43 | 44 | @Override 45 | public boolean equals(Object o) { 46 | if (this == o) return true; 47 | if (o == null || getClass() != o.getClass()) return false; 48 | 49 | Pair pair = (Pair) o; 50 | 51 | if (!Objects.equals(first, pair.first)) return false; 52 | return Objects.equals(second, pair.second); 53 | } 54 | 55 | @Override 56 | public int hashCode() { 57 | int result = first != null ? first.hashCode() : 0; 58 | result = 31 * result + (second != null ? second.hashCode() : 0); 59 | return result; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/HardTargetMixinClassVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard; 20 | 21 | import java.util.ArrayList; 22 | import java.util.Collection; 23 | import java.util.Collections; 24 | import java.util.List; 25 | import java.util.Objects; 26 | import java.util.function.Consumer; 27 | 28 | import org.objectweb.asm.AnnotationVisitor; 29 | import org.objectweb.asm.ClassVisitor; 30 | import org.objectweb.asm.FieldVisitor; 31 | import org.objectweb.asm.MethodVisitor; 32 | 33 | import net.fabricmc.tinyremapper.extension.mixin.common.MapUtility; 34 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Annotation; 35 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 36 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 37 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxClass; 38 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; 39 | import net.fabricmc.tinyremapper.extension.mixin.hard.annotation.ImplementsAnnotationVisitor; 40 | import net.fabricmc.tinyremapper.extension.mixin.hard.annotation.MixinAnnotationVisitor; 41 | import net.fabricmc.tinyremapper.extension.mixin.hard.data.SoftInterface; 42 | 43 | public class HardTargetMixinClassVisitor extends ClassVisitor { 44 | private final Collection> tasks; 45 | private MxClass _class; 46 | 47 | // @Mixin 48 | private final List targets = new ArrayList<>(); 49 | 50 | // @Implements 51 | private final List interfaces = new ArrayList<>(); 52 | 53 | public HardTargetMixinClassVisitor(Collection> tasks, ClassVisitor delegate) { 54 | super(Constant.ASM_VERSION, delegate); 55 | this.tasks = Objects.requireNonNull(tasks); 56 | } 57 | 58 | /** 59 | * This is called before visitAnnotation. 60 | */ 61 | @Override 62 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 63 | this._class = new MxClass(name); 64 | super.visit(version, access, name, signature, superName, interfaces); 65 | } 66 | 67 | /** 68 | * This is called before visitMethod & visitField. 69 | */ 70 | @Override 71 | public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { 72 | AnnotationVisitor av = super.visitAnnotation(descriptor, visible); 73 | 74 | if (Annotation.MIXIN.equals(descriptor)) { 75 | av = new MixinAnnotationVisitor(av, targets); 76 | } else if (Annotation.IMPLEMENTS.equals(descriptor)) { 77 | av = new ImplementsAnnotationVisitor(av, interfaces); 78 | } 79 | 80 | return av; 81 | } 82 | 83 | @Override 84 | public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { 85 | FieldVisitor fv = super.visitField(access, name, descriptor, signature, value); 86 | MxMember field = _class.getField(name, descriptor); 87 | 88 | if (targets.isEmpty()) { 89 | return fv; 90 | } else { 91 | return new HardTargetMixinFieldVisitor(tasks, fv, field, Collections.unmodifiableList(targets)); 92 | } 93 | } 94 | 95 | @Override 96 | public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { 97 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); 98 | MxMember method = _class.getMethod(name, descriptor); 99 | 100 | if (!interfaces.isEmpty() && !MapUtility.IGNORED_NAME.contains(name)) { 101 | ImplementsAnnotationVisitor.visitMethod(tasks, method, interfaces); 102 | } 103 | 104 | if (targets.isEmpty()) { 105 | return mv; 106 | } else { 107 | return new HardTargetMixinMethodVisitor(tasks, mv, method, Collections.unmodifiableList(targets)); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/HardTargetMixinFieldVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard; 20 | 21 | import java.util.Collection; 22 | import java.util.List; 23 | import java.util.Objects; 24 | import java.util.function.Consumer; 25 | 26 | import org.objectweb.asm.AnnotationVisitor; 27 | import org.objectweb.asm.FieldVisitor; 28 | 29 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Annotation; 30 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 31 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 32 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; 33 | import net.fabricmc.tinyremapper.extension.mixin.hard.annotation.ShadowAnnotationVisitor; 34 | 35 | class HardTargetMixinFieldVisitor extends FieldVisitor { 36 | private final Collection> tasks; 37 | private final MxMember field; 38 | 39 | private final List targets; 40 | 41 | HardTargetMixinFieldVisitor(Collection> tasks, FieldVisitor delegate, MxMember field, 42 | List targets) { 43 | super(Constant.ASM_VERSION, delegate); 44 | this.tasks = Objects.requireNonNull(tasks); 45 | this.field = Objects.requireNonNull(field); 46 | 47 | this.targets = Objects.requireNonNull(targets); 48 | } 49 | 50 | @Override 51 | public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { 52 | AnnotationVisitor av = super.visitAnnotation(descriptor, visible); 53 | 54 | if (Annotation.SHADOW.equals(descriptor)) { 55 | av = new ShadowAnnotationVisitor(tasks, av, field, targets); 56 | } 57 | 58 | return av; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/HardTargetMixinMethodVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard; 20 | 21 | import java.util.Collection; 22 | import java.util.List; 23 | import java.util.Objects; 24 | import java.util.function.Consumer; 25 | 26 | import org.objectweb.asm.AnnotationVisitor; 27 | import org.objectweb.asm.MethodVisitor; 28 | 29 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Annotation; 30 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 31 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 32 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; 33 | import net.fabricmc.tinyremapper.extension.mixin.hard.annotation.OverwriteAnnotationVisitor; 34 | import net.fabricmc.tinyremapper.extension.mixin.hard.annotation.ShadowAnnotationVisitor; 35 | 36 | class HardTargetMixinMethodVisitor extends MethodVisitor { 37 | private final Collection> data; 38 | private final MxMember method; 39 | 40 | private final List targets; 41 | 42 | HardTargetMixinMethodVisitor(Collection> data, MethodVisitor delegate, MxMember method, List targets) { 43 | super(Constant.ASM_VERSION, delegate); 44 | this.data = Objects.requireNonNull(data); 45 | this.method = Objects.requireNonNull(method); 46 | 47 | this.targets = Objects.requireNonNull(targets); 48 | } 49 | 50 | @Override 51 | public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { 52 | AnnotationVisitor av = super.visitAnnotation(descriptor, visible); 53 | 54 | if (Annotation.SHADOW.equals(descriptor)) { 55 | av = new ShadowAnnotationVisitor(data, av, method, targets); 56 | } else if (Annotation.OVERWRITE.equals(descriptor)) { 57 | av = new OverwriteAnnotationVisitor(data, av, method, targets); 58 | } 59 | 60 | return av; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/annotation/MixinAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard.annotation; 20 | 21 | import java.util.List; 22 | import java.util.Objects; 23 | 24 | import org.objectweb.asm.AnnotationVisitor; 25 | import org.objectweb.asm.Type; 26 | 27 | import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; 28 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 29 | 30 | /** 31 | * Only collect information for other hard-target. 32 | */ 33 | public class MixinAnnotationVisitor extends AnnotationVisitor { 34 | private final List targets; 35 | 36 | public MixinAnnotationVisitor(AnnotationVisitor delegate, List targetsOut) { 37 | super(Constant.ASM_VERSION, delegate); 38 | 39 | this.targets = Objects.requireNonNull(targetsOut); 40 | } 41 | 42 | @Override 43 | public AnnotationVisitor visitArray(String name) { 44 | AnnotationVisitor visitor = super.visitArray(name); 45 | 46 | if (name.equals(AnnotationElement.TARGETS)) { 47 | return new AnnotationVisitor(Constant.ASM_VERSION, visitor) { 48 | @Override 49 | public void visit(String name, Object value) { 50 | String srcName = ((String) value).replaceAll("\\s", "").replace('.', '/'); 51 | String dstName = srcName; 52 | 53 | MixinAnnotationVisitor.this.targets.add(srcName); 54 | 55 | value = dstName; 56 | super.visit(name, value); 57 | } 58 | }; 59 | } else if (name.equals(AnnotationElement.VALUE)) { 60 | return new AnnotationVisitor(Constant.ASM_VERSION, visitor) { 61 | @Override 62 | public void visit(String name, Object value) { 63 | Type srcType = Objects.requireNonNull((Type) value); 64 | 65 | MixinAnnotationVisitor.this.targets.add(srcType.getInternalName()); 66 | 67 | super.visit(name, value); 68 | } 69 | }; 70 | } else { 71 | return visitor; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/annotation/OverwriteAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard.annotation; 20 | 21 | import java.util.Collection; 22 | import java.util.List; 23 | import java.util.Objects; 24 | import java.util.function.Consumer; 25 | 26 | import org.objectweb.asm.AnnotationVisitor; 27 | 28 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 29 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 30 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; 31 | import net.fabricmc.tinyremapper.extension.mixin.hard.util.ConvertibleMappable; 32 | import net.fabricmc.tinyremapper.extension.mixin.hard.util.IConvertibleString; 33 | import net.fabricmc.tinyremapper.extension.mixin.hard.util.IdentityString; 34 | 35 | /** 36 | * In case of multi-target, if a remap conflict is detected, 37 | * an error message will show up and the behaviour is undefined. 38 | */ 39 | public class OverwriteAnnotationVisitor extends AnnotationVisitor { 40 | private final Collection> tasks; 41 | private final MxMember method; 42 | private final List targets; 43 | 44 | public OverwriteAnnotationVisitor(Collection> tasks, AnnotationVisitor delegate, MxMember method, List targets) { 45 | super(Constant.ASM_VERSION, delegate); 46 | 47 | this.tasks = Objects.requireNonNull(tasks); 48 | this.method = Objects.requireNonNull(method); 49 | this.targets = Objects.requireNonNull(targets); 50 | } 51 | 52 | @Override 53 | public void visitEnd() { 54 | tasks.add(data -> new OverwriteMappable(data, method, targets).result()); 55 | 56 | super.visitEnd(); 57 | } 58 | 59 | private static class OverwriteMappable extends ConvertibleMappable { 60 | OverwriteMappable(CommonData data, MxMember self, Collection targets) { 61 | super(data, self, targets); 62 | } 63 | 64 | @Override 65 | protected IConvertibleString getName() { 66 | return new IdentityString(self.getName()); 67 | } 68 | 69 | @Override 70 | protected String getDesc() { 71 | return self.getDesc(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/annotation/ShadowAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard.annotation; 20 | 21 | import java.util.Collection; 22 | import java.util.List; 23 | import java.util.Objects; 24 | import java.util.function.Consumer; 25 | 26 | import org.objectweb.asm.AnnotationVisitor; 27 | 28 | import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; 29 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 30 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 31 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; 32 | import net.fabricmc.tinyremapper.extension.mixin.hard.util.ConvertibleMappable; 33 | import net.fabricmc.tinyremapper.extension.mixin.hard.util.IConvertibleString; 34 | import net.fabricmc.tinyremapper.extension.mixin.hard.util.IdentityString; 35 | import net.fabricmc.tinyremapper.extension.mixin.hard.util.PrefixString; 36 | 37 | /** 38 | * In case of multi-target, if a remap conflict is detected, 39 | * an error message will show up and the behaviour is undefined. 40 | * If a prefix is detected, will only attempt to match the prefix-stripped name. 41 | */ 42 | public class ShadowAnnotationVisitor extends AnnotationVisitor { 43 | private final Collection> tasks; 44 | private final MxMember member; 45 | private final List targets; 46 | 47 | private String prefix; 48 | 49 | public ShadowAnnotationVisitor(Collection> tasks, AnnotationVisitor delegate, MxMember member, List targets) { 50 | super(Constant.ASM_VERSION, delegate); 51 | this.tasks = Objects.requireNonNull(tasks); 52 | this.member = Objects.requireNonNull(member); 53 | 54 | this.targets = Objects.requireNonNull(targets); 55 | this.prefix = "shadow$"; 56 | } 57 | 58 | @Override 59 | public void visit(String name, Object value) { 60 | if (name.equals(AnnotationElement.PREFIX)) { 61 | prefix = Objects.requireNonNull((String) value); 62 | } 63 | 64 | super.visit(name, value); 65 | } 66 | 67 | @Override 68 | public void visitEnd() { 69 | tasks.add(data -> new ShadowPrefixMappable(data, member, targets, prefix).result()); 70 | 71 | super.visitEnd(); 72 | } 73 | 74 | private static class ShadowPrefixMappable extends ConvertibleMappable { 75 | private final String prefix; 76 | 77 | ShadowPrefixMappable(CommonData data, MxMember self, Collection targets, String prefix) { 78 | super(data, self, targets); 79 | Objects.requireNonNull(prefix); 80 | 81 | this.prefix = self.getName().startsWith(prefix) ? prefix : ""; 82 | } 83 | 84 | @Override 85 | protected IConvertibleString getName() { 86 | if (prefix.isEmpty()) { 87 | return new IdentityString(self.getName()); 88 | } else { 89 | return new PrefixString(prefix, self.getName()); 90 | } 91 | } 92 | 93 | @Override 94 | protected String getDesc() { 95 | return self.getDesc(); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/data/SoftInterface.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard.data; 20 | 21 | public final class SoftInterface { 22 | public enum Remap { 23 | NONE, ONLY_PREFIX, ALL, FORCE 24 | } 25 | 26 | private String target; 27 | private String prefix; 28 | private Remap remap; 29 | 30 | public String getTarget() { 31 | return target; 32 | } 33 | 34 | public String getPrefix() { 35 | return prefix; 36 | } 37 | 38 | public Remap getRemap() { 39 | return remap; 40 | } 41 | 42 | public void setTarget(String target) { 43 | this.target = target; 44 | } 45 | 46 | public void setPrefix(String prefix) { 47 | this.prefix = prefix; 48 | } 49 | 50 | public void setRemap(Remap remap) { 51 | this.remap = remap; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return "Interface{" 57 | + "target='" + target + '\'' 58 | + ", prefix='" + prefix + '\'' 59 | + ", remap=" + remap 60 | + '}'; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/util/CamelPrefixString.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard.util; 20 | 21 | import java.util.Objects; 22 | 23 | import net.fabricmc.tinyremapper.extension.mixin.common.StringUtility; 24 | 25 | public class CamelPrefixString implements IConvertibleString { 26 | private final String prefix; 27 | private final String text; 28 | 29 | public CamelPrefixString(String prefix, String text) { 30 | this.prefix = Objects.requireNonNull(prefix); 31 | this.text = StringUtility.removeCamelPrefix(prefix, text); 32 | } 33 | 34 | @Override 35 | public String getOriginal() { 36 | return StringUtility.addCamelPrefix(prefix, text); 37 | } 38 | 39 | @Override 40 | public String getConverted() { 41 | return text; 42 | } 43 | 44 | @Override 45 | public String getReverted(String newText) { 46 | return StringUtility.addCamelPrefix(prefix, newText); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/util/ConvertibleMappable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard.util; 20 | 21 | import java.util.Collection; 22 | import java.util.List; 23 | import java.util.Objects; 24 | import java.util.Optional; 25 | import java.util.stream.Collectors; 26 | import java.util.stream.Stream; 27 | 28 | import net.fabricmc.tinyremapper.api.TrClass; 29 | import net.fabricmc.tinyremapper.extension.mixin.common.ResolveUtility; 30 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 31 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Message; 32 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; 33 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Pair; 34 | 35 | public abstract class ConvertibleMappable extends HardTargetMappable { 36 | private final Collection targets; 37 | 38 | public ConvertibleMappable(CommonData data, MxMember self, Collection targets) { 39 | super(data, self); 40 | 41 | this.targets = Objects.requireNonNull(targets).stream() 42 | .map(data.resolver::resolveClass) 43 | .filter(Optional::isPresent) 44 | .map(Optional::get) 45 | .collect(Collectors.toList()); 46 | } 47 | 48 | protected abstract IConvertibleString getName(); 49 | protected abstract String getDesc(); 50 | 51 | protected Stream mapMultiTarget(IConvertibleString name, String desc) { 52 | return targets.stream() 53 | .map(target -> Pair.of(name, data.resolver.resolveMember(target, name.getConverted(), desc, ResolveUtility.FLAG_UNIQUE | ResolveUtility.FLAG_RECURSIVE))) 54 | .filter(x -> x.second().isPresent()) 55 | .map(x -> Pair.of(x.first(), data.mapper.mapName(x.second().get()))) 56 | .map(x -> x.first().getReverted(x.second())); 57 | } 58 | 59 | @Override 60 | protected Optional getMappedName() { 61 | if (targets.isEmpty()) { 62 | return Optional.empty(); 63 | } 64 | 65 | List collection = mapMultiTarget(getName(), getDesc()) 66 | .collect(Collectors.toList()); 67 | 68 | if (collection.size() > 1) { 69 | data.getLogger().error(Message.CONFLICT_MAPPING, self.getName(), collection); 70 | } else if (collection.isEmpty()) { 71 | data.getLogger().warn(Message.NO_MAPPING_RECURSIVE, self.getName(), targets); 72 | } 73 | 74 | return collection.stream().findFirst(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/util/HardTargetMappable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard.util; 20 | 21 | import java.util.Objects; 22 | import java.util.Optional; 23 | 24 | import net.fabricmc.tinyremapper.extension.mixin.common.IMappable; 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; 27 | 28 | public abstract class HardTargetMappable implements IMappable { 29 | protected CommonData data; 30 | protected MxMember self; 31 | 32 | public HardTargetMappable(CommonData data, MxMember self) { 33 | this.data = Objects.requireNonNull(data); 34 | this.self = Objects.requireNonNull(self); 35 | } 36 | 37 | protected abstract Optional getMappedName(); 38 | 39 | @Override 40 | public Void result() { 41 | getMappedName().ifPresent(x -> data.propagate(self.asTrMember(data.resolver), x)); 42 | return null; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/util/IConvertibleString.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard.util; 20 | 21 | public interface IConvertibleString { 22 | String getOriginal(); 23 | String getConverted(); 24 | String getReverted(String newText); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/util/IdentityString.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard.util; 20 | 21 | import java.util.Objects; 22 | 23 | public class IdentityString implements IConvertibleString { 24 | private final String text; 25 | 26 | public IdentityString(String text) { 27 | this.text = Objects.requireNonNull(text); 28 | } 29 | 30 | @Override 31 | public String getOriginal() { 32 | return text; 33 | } 34 | 35 | @Override 36 | public String getConverted() { 37 | return text; 38 | } 39 | 40 | @Override 41 | public String getReverted(String newText) { 42 | return newText; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/util/PrefixString.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard.util; 20 | 21 | import java.util.Objects; 22 | 23 | import net.fabricmc.tinyremapper.extension.mixin.common.StringUtility; 24 | 25 | public class PrefixString implements IConvertibleString { 26 | private final String prefix; 27 | private final String text; 28 | 29 | public PrefixString(String prefix, String text) { 30 | this.prefix = Objects.requireNonNull(prefix); 31 | this.text = StringUtility.removePrefix(prefix, text); 32 | } 33 | 34 | @Override 35 | public String getOriginal() { 36 | return StringUtility.addPrefix(prefix, text); 37 | } 38 | 39 | @Override 40 | public String getConverted() { 41 | return text; 42 | } 43 | 44 | @Override 45 | public String getReverted(String newText) { 46 | return StringUtility.addPrefix(prefix, newText); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/SoftTargetMixinClassVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft; 20 | 21 | import java.util.ArrayList; 22 | import java.util.Collections; 23 | import java.util.List; 24 | import java.util.Objects; 25 | 26 | import org.objectweb.asm.AnnotationVisitor; 27 | import org.objectweb.asm.ClassVisitor; 28 | import org.objectweb.asm.MethodVisitor; 29 | 30 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Annotation; 31 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 32 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 33 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxClass; 34 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; 35 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.MixinAnnotationVisitor; 36 | 37 | public class SoftTargetMixinClassVisitor extends ClassVisitor { 38 | private final CommonData data; 39 | private MxClass _class; 40 | 41 | // @Mixin 42 | private final List targets = new ArrayList<>(); 43 | 44 | public SoftTargetMixinClassVisitor(CommonData data, ClassVisitor delegate) { 45 | super(Constant.ASM_VERSION, delegate); 46 | this.data = Objects.requireNonNull(data); 47 | } 48 | 49 | /** 50 | * This is called before visitAnnotation. 51 | */ 52 | @Override 53 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 54 | this._class = new MxClass(name); 55 | super.visit(version, access, name, signature, superName, interfaces); 56 | } 57 | 58 | /** 59 | * This is called before visitMethod & visitField. 60 | */ 61 | @Override 62 | public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { 63 | AnnotationVisitor av = super.visitAnnotation(descriptor, visible); 64 | 65 | if (Annotation.MIXIN.equals(descriptor)) { 66 | av = new MixinAnnotationVisitor(data, av, targets); 67 | } 68 | 69 | return av; 70 | } 71 | 72 | @Override 73 | public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { 74 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); 75 | MxMember method = _class.getMethod(name, descriptor); 76 | 77 | if (targets.isEmpty()) { 78 | return mv; 79 | } else { 80 | return new SoftTargetMixinMethodVisitor(data, mv, method, Collections.unmodifiableList(targets)); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/SoftTargetMixinMethodVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft; 20 | 21 | import java.util.List; 22 | import java.util.Objects; 23 | 24 | import org.objectweb.asm.AnnotationVisitor; 25 | import org.objectweb.asm.MethodVisitor; 26 | 27 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Annotation; 28 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 29 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 30 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; 31 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.AccessorAnnotationVisitor; 32 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.InvokerAnnotationVisitor; 33 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.DefinitionAnnotationVisitor; 34 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.DefinitionsAnnotationVisitor; 35 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.InjectAnnotationVisitor; 36 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.ModifyArgAnnotationVisitor; 37 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.ModifyArgsAnnotationVisitor; 38 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.ModifyConstantAnnotationVisitor; 39 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.ModifyExpressionValueAnnotationVisitor; 40 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.ModifyReceiverAnnotationVisitor; 41 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.ModifyReturnValueAnnotationVisitor; 42 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.ModifyVariableAnnotationVisitor; 43 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.RedirectAnnotationVisitor; 44 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.WrapMethodAnnotationVisitor; 45 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.WrapOperationAnnotationVisitor; 46 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.WrapWithConditionAnnotationVisitor; 47 | import net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection.WrapWithConditionV2AnnotationVisitor; 48 | 49 | class SoftTargetMixinMethodVisitor extends MethodVisitor { 50 | private final CommonData data; 51 | private final MxMember method; 52 | 53 | private final List targets; 54 | 55 | SoftTargetMixinMethodVisitor(CommonData data, MethodVisitor delegate, MxMember method, List targets) { 56 | super(Constant.ASM_VERSION, delegate); 57 | this.data = Objects.requireNonNull(data); 58 | this.method = Objects.requireNonNull(method); 59 | 60 | this.targets = Objects.requireNonNull(targets); 61 | } 62 | 63 | @Override 64 | public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { 65 | AnnotationVisitor av = super.visitAnnotation(descriptor, visible); 66 | 67 | switch (descriptor) { 68 | case Annotation.ACCESSOR: 69 | return new AccessorAnnotationVisitor(data, av, method, targets); 70 | case Annotation.INVOKER: 71 | return new InvokerAnnotationVisitor(data, av, method, targets); 72 | case Annotation.INJECT: 73 | return new InjectAnnotationVisitor(data, av, targets); 74 | case Annotation.MODIFY_ARG: 75 | return new ModifyArgAnnotationVisitor(data, av, targets); 76 | case Annotation.MODIFY_ARGS: 77 | return new ModifyArgsAnnotationVisitor(data, av, targets); 78 | case Annotation.MODIFY_CONSTANT: 79 | return new ModifyConstantAnnotationVisitor(data, av, targets); 80 | case Annotation.MODIFY_VARIABLE: 81 | return new ModifyVariableAnnotationVisitor(data, av, targets); 82 | case Annotation.REDIRECT: 83 | return new RedirectAnnotationVisitor(data, av, targets); 84 | case Annotation.MIXIN_EXTRAS_MODIFY_EXPRESSION_VALUE: 85 | return new ModifyExpressionValueAnnotationVisitor(data, av, targets); 86 | case Annotation.MIXIN_EXTRAS_MODIFY_RECEIVER: 87 | return new ModifyReceiverAnnotationVisitor(data, av, targets); 88 | case Annotation.MIXIN_EXTRAS_MODIFY_RETURN_VALUE: 89 | return new ModifyReturnValueAnnotationVisitor(data, av, targets); 90 | case Annotation.MIXIN_EXTRAS_WRAP_METHOD: 91 | return new WrapMethodAnnotationVisitor(data, av, targets); 92 | case Annotation.MIXIN_EXTRAS_WRAP_OPERATION: 93 | return new WrapOperationAnnotationVisitor(data, av, targets); 94 | case Annotation.MIXIN_EXTRAS_WRAP_WITH_CONDITION: 95 | return new WrapWithConditionAnnotationVisitor(data, av, targets); 96 | case Annotation.MIXIN_EXTRAS_WRAP_WITH_CONDITION_V2: 97 | return new WrapWithConditionV2AnnotationVisitor(data, av, targets); 98 | case Annotation.MIXIN_EXTRAS_DEFINITIONS: 99 | return new DefinitionsAnnotationVisitor(data, av); 100 | case Annotation.MIXIN_EXTRAS_DEFINITION: 101 | return new DefinitionAnnotationVisitor(data, av); 102 | } 103 | 104 | return av; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/AccessorAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation; 20 | 21 | import java.util.List; 22 | import java.util.Objects; 23 | import java.util.regex.Matcher; 24 | import java.util.regex.Pattern; 25 | 26 | import org.objectweb.asm.AnnotationVisitor; 27 | 28 | import net.fabricmc.tinyremapper.extension.mixin.common.StringUtility; 29 | import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; 30 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 31 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 32 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; 33 | import net.fabricmc.tinyremapper.extension.mixin.soft.util.NamedMappable; 34 | 35 | /** 36 | * In case of multi-target, if a remap conflict is detected, 37 | * an error message will show up and the behaviour is undefined. 38 | */ 39 | public class AccessorAnnotationVisitor extends AnnotationVisitor { 40 | private final CommonData data; 41 | 42 | private final MxMember method; 43 | private final List targets; 44 | private final String fieldDesc; 45 | 46 | private boolean isSoftTarget; 47 | 48 | private static final Pattern GETTER_PATTERN = Pattern.compile("(?<=\\(\\)).*"); 49 | private static final Pattern SETTER_PATTERN = Pattern.compile("(?<=\\().*(?=\\)V)"); 50 | 51 | public AccessorAnnotationVisitor(CommonData data, AnnotationVisitor delegate, MxMember method, List targets) { 52 | super(Constant.ASM_VERSION, Objects.requireNonNull(delegate)); 53 | 54 | this.data = Objects.requireNonNull(data); 55 | Objects.requireNonNull(method); 56 | 57 | this.method = method; 58 | this.targets = Objects.requireNonNull(targets); 59 | 60 | Matcher getterMatcher = GETTER_PATTERN.matcher(method.getDesc()); 61 | Matcher setterMatcher = SETTER_PATTERN.matcher(method.getDesc()); 62 | 63 | if (getterMatcher.find()) { 64 | this.fieldDesc = getterMatcher.group(); 65 | } else if (setterMatcher.find()) { 66 | this.fieldDesc = setterMatcher.group(); 67 | } else { 68 | throw new RuntimeException(method.getDesc() + " is not getter or setter"); 69 | } 70 | } 71 | 72 | @Override 73 | public void visit(String name, Object value) { 74 | if (name.equals(AnnotationElement.VALUE)) { 75 | isSoftTarget = true; 76 | String fieldName = Objects.requireNonNull((String) value); 77 | setAnnotationValue(fieldName); 78 | return; 79 | } 80 | 81 | super.visit(name, value); 82 | } 83 | 84 | @Override 85 | public void visitEnd() { 86 | if (!isSoftTarget) { 87 | setAnnotationValue(inferFieldName()); 88 | } 89 | 90 | super.visitEnd(); 91 | } 92 | 93 | private void setAnnotationValue(String fieldName) { 94 | super.visit(AnnotationElement.VALUE, new NamedMappable(data, fieldName, fieldDesc, targets).result()); 95 | } 96 | 97 | private String inferFieldName() { 98 | String prefix; 99 | 100 | if (method.getName().startsWith("get")) { 101 | prefix = "get"; 102 | } else if (method.getName().startsWith("set")) { 103 | prefix = "set"; 104 | } else if (method.getName().startsWith("is")) { 105 | prefix = "is"; 106 | } else { 107 | throw new RuntimeException(String.format("%s does not start with get, set or is.", method.getName())); 108 | } 109 | 110 | return StringUtility.removeCamelPrefix(prefix, method.getName()); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/InvokerAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation; 20 | 21 | import java.util.List; 22 | import java.util.Objects; 23 | 24 | import org.objectweb.asm.AnnotationVisitor; 25 | 26 | import net.fabricmc.tinyremapper.extension.mixin.common.StringUtility; 27 | import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; 28 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 29 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 30 | import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; 31 | import net.fabricmc.tinyremapper.extension.mixin.soft.util.NamedMappable; 32 | 33 | /** 34 | * In case of multi-target, if a remap conflict is detected, 35 | * an error message will show up and the behaviour is undefined. 36 | */ 37 | public class InvokerAnnotationVisitor extends AnnotationVisitor { 38 | private final CommonData data; 39 | private final MxMember method; 40 | 41 | private final List targets; 42 | 43 | private boolean isSoftTarget; 44 | 45 | public InvokerAnnotationVisitor(CommonData data, AnnotationVisitor delegate, MxMember method, List targets) { 46 | super(Constant.ASM_VERSION, Objects.requireNonNull(delegate)); 47 | 48 | this.data = Objects.requireNonNull(data); 49 | this.method = Objects.requireNonNull(method); 50 | 51 | this.targets = Objects.requireNonNull(targets); 52 | } 53 | 54 | @Override 55 | public void visit(String name, Object value) { 56 | if (name.equals(AnnotationElement.VALUE)) { 57 | isSoftTarget = true; 58 | String methodName = Objects.requireNonNull((String) value); 59 | 60 | setAnnotationValue(methodName); 61 | return; 62 | } 63 | 64 | super.visit(name, value); 65 | } 66 | 67 | @Override 68 | public void visitEnd() { 69 | if (!isSoftTarget) { 70 | String inferredName = inferMethodName(); 71 | 72 | if (inferredName != null) { 73 | setAnnotationValue(inferredName); 74 | } 75 | } 76 | 77 | super.visitEnd(); 78 | } 79 | 80 | private void setAnnotationValue(String methodName) { 81 | super.visit(AnnotationElement.VALUE, new NamedMappable(data, methodName, method.getDesc(), targets).result()); 82 | } 83 | 84 | private String inferMethodName() { 85 | if (method.getName().startsWith("new") || method.getName().startsWith("create")) { 86 | // The rest of the name isn't important, leave it as-is 87 | return null; 88 | } 89 | 90 | String prefix; 91 | 92 | if (method.getName().startsWith("call")) { 93 | prefix = "call"; 94 | } else if (method.getName().startsWith("invoke")) { 95 | prefix = "invoke"; 96 | } else { 97 | throw new RuntimeException(String.format("%s does not start with call or invoke.", method.getName())); 98 | } 99 | 100 | return StringUtility.removeCamelPrefix(prefix, method.getName()); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/MixinAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation; 20 | 21 | import java.util.List; 22 | import java.util.Objects; 23 | 24 | import org.objectweb.asm.AnnotationVisitor; 25 | import org.objectweb.asm.Type; 26 | 27 | import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; 28 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 29 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 30 | 31 | public class MixinAnnotationVisitor extends AnnotationVisitor { 32 | private final CommonData data; 33 | private final List targets; 34 | 35 | public MixinAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targetsOut) { 36 | super(Constant.ASM_VERSION, Objects.requireNonNull(delegate)); 37 | this.data = Objects.requireNonNull(data); 38 | this.targets = Objects.requireNonNull(targetsOut); 39 | } 40 | 41 | @Override 42 | public AnnotationVisitor visitArray(String name) { 43 | AnnotationVisitor visitor = super.visitArray(name); 44 | 45 | if (name.equals(AnnotationElement.TARGETS)) { 46 | return new AnnotationVisitor(Constant.ASM_VERSION, visitor) { 47 | @Override 48 | public void visit(String name, Object value) { 49 | String srcName = ((String) value).replaceAll("\\s", "").replace('.', '/'); 50 | 51 | MixinAnnotationVisitor.this.targets.add(srcName); 52 | 53 | value = data.mapper.asTrRemapper().map(srcName); 54 | super.visit(name, value); 55 | } 56 | }; 57 | } else if (name.equals(AnnotationElement.VALUE)) { 58 | return new AnnotationVisitor(Constant.ASM_VERSION, visitor) { 59 | @Override 60 | public void visit(String name, Object value) { 61 | Type srcType = Objects.requireNonNull((Type) value); 62 | 63 | MixinAnnotationVisitor.this.targets.add(srcType.getInternalName()); 64 | 65 | super.visit(name, value); 66 | } 67 | }; 68 | } else { 69 | return visitor; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/AtAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.Objects; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | import org.objectweb.asm.tree.AnnotationNode; 25 | 26 | import net.fabricmc.tinyremapper.extension.mixin.common.IMappable; 27 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Annotation; 28 | import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; 29 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 30 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 31 | import net.fabricmc.tinyremapper.extension.mixin.soft.data.MemberInfo; 32 | 33 | /** 34 | * {@code @At} require fully-qualified {@link net.fabricmc.tinyremapper.extension.mixin.soft.data.MemberInfo} unless 35 | * {@code value = NEW}, in which case a special set of rule applies. 36 | */ 37 | class AtAnnotationVisitor extends AnnotationNode { 38 | private final CommonData data; 39 | private final AnnotationVisitor delegate; 40 | 41 | private String value; 42 | 43 | AtAnnotationVisitor(CommonData data, AnnotationVisitor delegate) { 44 | super(Constant.ASM_VERSION, Annotation.AT); 45 | 46 | this.data = Objects.requireNonNull(data); 47 | this.delegate = Objects.requireNonNull(delegate); 48 | } 49 | 50 | @Override 51 | public void visit(String name, Object value) { 52 | if (name.equals(AnnotationElement.VALUE)) { 53 | this.value = Objects.requireNonNull((String) value); 54 | } 55 | 56 | super.visit(name, value); 57 | } 58 | 59 | @Override 60 | public void visitEnd() { 61 | accept(new AtSecondPassAnnotationVisitor(data, delegate, value)); 62 | 63 | super.visitEnd(); 64 | } 65 | 66 | private static class AtSecondPassAnnotationVisitor extends AnnotationVisitor { 67 | private final CommonData data; 68 | private final String value; 69 | 70 | AtSecondPassAnnotationVisitor(CommonData data, AnnotationVisitor delegate, String value) { 71 | super(Constant.ASM_VERSION, delegate); 72 | 73 | this.data = Objects.requireNonNull(data); 74 | this.value = Objects.requireNonNull(value); 75 | } 76 | 77 | @Override 78 | public void visit(String name, Object value) { 79 | if (name.equals(AnnotationElement.TARGET)) { 80 | MemberInfo info = MemberInfo.parse(Objects.requireNonNull((String) value).replaceAll("\\s", "")); 81 | 82 | if (info != null) { 83 | if (this.value.equals("NEW")) { 84 | value = new AtConstructorMappable(data, info).result().toString(); 85 | } else { 86 | value = new AtMemberMappable(data, info).result().toString(); 87 | } 88 | } 89 | } 90 | 91 | super.visit(name, value); 92 | } 93 | 94 | @Override 95 | public AnnotationVisitor visitArray(String name) { 96 | AnnotationVisitor av = super.visitArray(name); 97 | 98 | if (name.equals(AnnotationElement.ARGS) && this.value.equals("NEW")) { 99 | final String prefix = "class="; 100 | 101 | av = new AnnotationVisitor(Constant.ASM_VERSION, av) { 102 | @Override 103 | public void visit(String name, Object value) { 104 | String argument = Objects.requireNonNull((String) value); 105 | MemberInfo info; 106 | 107 | if (argument.startsWith(prefix) 108 | && (info = MemberInfo.parse(argument.substring(prefix.length()).replaceAll("\\s", ""))) != null) { 109 | value = prefix + new AtConstructorMappable(data, info).result().toString(); 110 | } 111 | 112 | super.visit(name, value); 113 | } 114 | }; 115 | } 116 | 117 | return av; 118 | } 119 | } 120 | 121 | private static class AtConstructorMappable implements IMappable { 122 | private final CommonData data; 123 | private final MemberInfo info; 124 | 125 | AtConstructorMappable(CommonData data, MemberInfo info) { 126 | this.data = Objects.requireNonNull(data); 127 | this.info = Objects.requireNonNull(info); 128 | } 129 | 130 | @Override 131 | public MemberInfo result() { 132 | if (info.getDesc().isEmpty()) { 133 | // remap owner only 134 | return new MemberInfo(data.mapper.asTrRemapper().map(info.getOwner()), info.getName(), info.getQuantifier(), ""); 135 | } else if (info.getDesc().endsWith(")V")) { 136 | // remap owner and desc 137 | return new MemberInfo(data.mapper.asTrRemapper().map(info.getOwner()), info.getName(), info.getQuantifier(), data.mapper.asTrRemapper().mapMethodDesc(info.getDesc())); 138 | } else { 139 | // remap desc only 140 | return new MemberInfo(info.getOwner(), info.getName(), info.getQuantifier(), data.mapper.asTrRemapper().mapMethodDesc(info.getDesc())); 141 | } 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/AtMemberMappable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2025, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.Objects; 22 | import java.util.Optional; 23 | 24 | import net.fabricmc.tinyremapper.api.TrMember; 25 | import net.fabricmc.tinyremapper.extension.mixin.common.IMappable; 26 | import net.fabricmc.tinyremapper.extension.mixin.common.ResolveUtility; 27 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 28 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Message; 29 | import net.fabricmc.tinyremapper.extension.mixin.soft.data.MemberInfo; 30 | 31 | class AtMemberMappable implements IMappable { 32 | private final CommonData data; 33 | private final MemberInfo info; 34 | 35 | AtMemberMappable(CommonData data, MemberInfo info) { 36 | this.data = Objects.requireNonNull(data); 37 | this.info = Objects.requireNonNull(info); 38 | } 39 | 40 | @Override 41 | public MemberInfo result() { 42 | if (!info.isFullyQualified()) { 43 | data.getLogger().warn(Message.NOT_FULLY_QUALIFIED, info); 44 | return info; 45 | } 46 | 47 | Optional resolved = data.resolver.resolveMember(info.getOwner(), info.getName(), info.getDesc(), ResolveUtility.FLAG_UNIQUE | ResolveUtility.FLAG_RECURSIVE); 48 | 49 | if (resolved.isPresent()) { 50 | String newOwner = data.mapper.asTrRemapper().map(info.getOwner()); 51 | String newName = data.mapper.mapName(resolved.get()); 52 | String newDesc = data.mapper.mapDesc(resolved.get()); 53 | 54 | return new MemberInfo(newOwner, newName, info.getQuantifier(), newDesc); 55 | } else { 56 | return info; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/DefinitionAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2025, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.Objects; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; 26 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 27 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 28 | import net.fabricmc.tinyremapper.extension.mixin.soft.data.MemberInfo; 29 | 30 | public class DefinitionAnnotationVisitor extends AnnotationVisitor { 31 | private final CommonData data; 32 | 33 | public DefinitionAnnotationVisitor(CommonData data, AnnotationVisitor delegate) { 34 | super(Constant.ASM_VERSION, Objects.requireNonNull(delegate)); 35 | 36 | this.data = Objects.requireNonNull(data); 37 | } 38 | 39 | @Override 40 | public AnnotationVisitor visitArray(String name) { 41 | AnnotationVisitor av = super.visitArray(name); 42 | switch (name) { 43 | case AnnotationElement.DEFINITION_METHOD: 44 | case AnnotationElement.DEFINITION_FIELD: 45 | return new MemberRemappingVisitor(data, av); 46 | } 47 | 48 | return av; 49 | } 50 | 51 | private static class MemberRemappingVisitor extends AnnotationVisitor { 52 | private final CommonData data; 53 | 54 | MemberRemappingVisitor(CommonData data, AnnotationVisitor delegate) { 55 | super(Constant.ASM_VERSION, Objects.requireNonNull(delegate)); 56 | 57 | this.data = Objects.requireNonNull(data); 58 | } 59 | 60 | @Override 61 | public void visit(String name, Object value) { 62 | MemberInfo info = MemberInfo.parse(Objects.requireNonNull((String) value)); 63 | 64 | if (info != null) { 65 | value = new AtMemberMappable(data, info).result().toString(); 66 | } 67 | 68 | super.visit(name, value); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/DefinitionsAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2025, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.Objects; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; 26 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 27 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 28 | 29 | public class DefinitionsAnnotationVisitor extends AnnotationVisitor { 30 | private final CommonData data; 31 | 32 | public DefinitionsAnnotationVisitor(CommonData data, AnnotationVisitor delegate) { 33 | super(Constant.ASM_VERSION, Objects.requireNonNull(delegate)); 34 | 35 | this.data = Objects.requireNonNull(data); 36 | } 37 | 38 | @Override 39 | public AnnotationVisitor visitArray(String name) { 40 | AnnotationVisitor av = super.visitArray(name); 41 | 42 | if (name.equals(AnnotationElement.VALUE)) { 43 | return new DefinitionRemappingVisitor(data, av); 44 | } 45 | 46 | return av; 47 | } 48 | 49 | private static class DefinitionRemappingVisitor extends AnnotationVisitor { 50 | private final CommonData data; 51 | 52 | DefinitionRemappingVisitor(CommonData data, AnnotationVisitor delegate) { 53 | super(Constant.ASM_VERSION, Objects.requireNonNull(delegate)); 54 | 55 | this.data = Objects.requireNonNull(data); 56 | } 57 | 58 | @Override 59 | public AnnotationVisitor visitAnnotation(String name, String descriptor) { 60 | return new DefinitionAnnotationVisitor(data, super.visitAnnotation(name, descriptor)); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/InjectAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class InjectAnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public InjectAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/ModifyArgAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class ModifyArgAnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public ModifyArgAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/ModifyArgsAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class ModifyArgsAnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public ModifyArgsAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/ModifyConstantAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class ModifyConstantAnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public ModifyConstantAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/ModifyExpressionValueAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class ModifyExpressionValueAnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public ModifyExpressionValueAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/ModifyReceiverAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class ModifyReceiverAnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public ModifyReceiverAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/ModifyReturnValueAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class ModifyReturnValueAnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public ModifyReturnValueAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/ModifyVariableAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class ModifyVariableAnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public ModifyVariableAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/RedirectAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class RedirectAnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public RedirectAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/SliceAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.Objects; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Annotation; 26 | import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; 27 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 28 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; 29 | 30 | public class SliceAnnotationVisitor extends AnnotationVisitor { 31 | private final CommonData data; 32 | 33 | public SliceAnnotationVisitor(CommonData data, AnnotationVisitor delegate) { 34 | super(Constant.ASM_VERSION, delegate); 35 | this.data = Objects.requireNonNull(data); 36 | } 37 | 38 | @Override 39 | public AnnotationVisitor visitAnnotation(String name, String descriptor) { 40 | AnnotationVisitor av = super.visitAnnotation(name, descriptor); 41 | 42 | if (name.equals(AnnotationElement.FROM) || name.equals(AnnotationElement.TO)) { 43 | if (!descriptor.equals(Annotation.AT)) { 44 | throw new RuntimeException("Unexpected annotation " + descriptor); 45 | } 46 | 47 | av = new AtAnnotationVisitor(data, av); 48 | } 49 | 50 | return av; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/WrapMethodAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class WrapMethodAnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public WrapMethodAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/WrapOperationAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class WrapOperationAnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public WrapOperationAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/WrapWithConditionAnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class WrapWithConditionAnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public WrapWithConditionAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/WrapWithConditionV2AnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2023, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; 20 | 21 | import java.util.List; 22 | 23 | import org.objectweb.asm.AnnotationVisitor; 24 | 25 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 26 | 27 | public class WrapWithConditionV2AnnotationVisitor extends CommonInjectionAnnotationVisitor { 28 | public WrapWithConditionV2AnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { 29 | super(data, delegate, targets); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/data/MemberInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.data; 20 | 21 | import java.util.Objects; 22 | 23 | import net.fabricmc.tinyremapper.api.TrMember.MemberType; 24 | import net.fabricmc.tinyremapper.extension.mixin.common.StringUtility; 25 | 26 | public final class MemberInfo { 27 | private final String owner; // desc 28 | private final String name; // name 29 | private final String quantifier; 30 | private final String desc; // desc 31 | 32 | public MemberInfo(String owner, String name, String quantifier, String desc) { 33 | this.owner = Objects.requireNonNull(owner); 34 | this.name = Objects.requireNonNull(name); 35 | this.quantifier = Objects.requireNonNull(quantifier); 36 | this.desc = Objects.requireNonNull(desc); 37 | } 38 | 39 | public String getOwner() { 40 | return owner; 41 | } 42 | 43 | public String getName() { 44 | return name; 45 | } 46 | 47 | public String getQuantifier() { 48 | return quantifier; 49 | } 50 | 51 | public String getDesc() { 52 | return desc; 53 | } 54 | 55 | public MemberType getType() { 56 | if (desc.isEmpty()) { 57 | return null; 58 | } 59 | 60 | return StringUtility.isMethodDesc(desc) ? MemberType.METHOD : MemberType.FIELD; 61 | } 62 | 63 | public boolean isFullyQualified() { 64 | return !(owner.isEmpty() || name.isEmpty() || desc.isEmpty()); 65 | } 66 | 67 | public static boolean isRegex(String str) { 68 | return str.endsWith("/"); 69 | } 70 | 71 | public static boolean isDynamic(String str) { 72 | return str.startsWith("@"); 73 | } 74 | 75 | public static MemberInfo parse(String str) { 76 | if (isRegex(str) || isDynamic(str)) { 77 | return null; 78 | } 79 | 80 | str = str.replaceAll("\\s", ""); 81 | 82 | // str = owner | name | quantifier | descriptor 83 | 84 | int sep; 85 | String owner, name, quantifier, descriptor; 86 | owner = name = quantifier = descriptor = ""; 87 | 88 | if ((sep = str.indexOf('(')) >= 0) { 89 | descriptor = str.substring(sep); 90 | str = str.substring(0, sep); 91 | } else if ((sep = str.indexOf(":")) >= 0) { 92 | descriptor = str.substring(sep + 1); 93 | str = str.substring(0, sep); 94 | } 95 | 96 | // str = owner | name | quantifier 97 | 98 | if ((sep = str.indexOf('*')) >= 0) { 99 | quantifier = str.substring(sep); 100 | str = str.substring(0, sep); 101 | } else if ((sep = str.indexOf('+')) >= 0) { 102 | quantifier = str.substring(sep); 103 | str = str.substring(0, sep); 104 | } else if ((sep = str.indexOf('{')) >= 0) { 105 | quantifier = str.substring(sep); 106 | str = str.substring(0, sep); 107 | } 108 | 109 | // str = owner | name 110 | 111 | if ((sep = str.indexOf(';')) >= 0) { 112 | owner = StringUtility.classDescToName(str.substring(0, sep + 1)); 113 | str = str.substring(sep + 1); 114 | } else if ((sep = str.lastIndexOf('.')) >= 0) { 115 | owner = str.substring(0, sep).replace('.', '/'); 116 | str = str.substring(sep + 1); 117 | } 118 | 119 | // str = owner or name 120 | if (str.contains("/") || str.contains(".")) { 121 | owner = str.replace('.', '/'); 122 | } else { 123 | name = str; 124 | } 125 | 126 | return new MemberInfo(owner, name, quantifier, descriptor); 127 | } 128 | 129 | @Override 130 | public String toString() { 131 | String owner = getOwner().isEmpty() ? "" : StringUtility.classNameToDesc(getOwner()); 132 | 133 | return owner + name + quantifier + formattedDesc(); 134 | } 135 | 136 | private String formattedDesc() { 137 | final String desc = getDesc(); 138 | 139 | if (desc.isEmpty()) { 140 | return ""; 141 | } 142 | 143 | if (Objects.equals(getType(), MemberType.FIELD)) { 144 | return ":" + desc; 145 | } 146 | 147 | // Wildcards match regardless of descriptor 148 | if (getQuantifier().equals("*")) { 149 | return ""; 150 | } 151 | 152 | return desc; 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/util/NamedMappable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.util; 20 | 21 | import java.util.Collection; 22 | import java.util.Objects; 23 | import java.util.Optional; 24 | import java.util.stream.Collectors; 25 | 26 | import net.fabricmc.tinyremapper.api.TrClass; 27 | import net.fabricmc.tinyremapper.extension.mixin.common.IMappable; 28 | import net.fabricmc.tinyremapper.extension.mixin.common.MapUtility; 29 | import net.fabricmc.tinyremapper.extension.mixin.common.ResolveUtility; 30 | import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; 31 | import net.fabricmc.tinyremapper.extension.mixin.common.data.Message; 32 | 33 | public class NamedMappable implements IMappable { 34 | private final CommonData data; 35 | private final String name; 36 | private final String desc; 37 | private final Collection targets; 38 | 39 | public NamedMappable(CommonData data, String name, String desc, Collection targets) { 40 | this.data = Objects.requireNonNull(data); 41 | this.name = Objects.requireNonNull(name); 42 | this.desc = Objects.requireNonNull(desc); 43 | this.targets = Objects.requireNonNull(targets).stream() 44 | .map(data.resolver::resolveClass) 45 | .filter(Optional::isPresent) 46 | .map(Optional::get) 47 | .collect(Collectors.toList()); 48 | } 49 | 50 | @Override 51 | public String result() { 52 | if (MapUtility.IGNORED_NAME.contains(name)) { 53 | return name; 54 | } 55 | 56 | Collection collection = targets.stream() 57 | .map(target -> data.resolver.resolveMember(target, name, desc, ResolveUtility.FLAG_UNIQUE | ResolveUtility.FLAG_RECURSIVE)) 58 | .filter(Optional::isPresent) 59 | .map(Optional::get) 60 | .map(data.mapper::mapName) 61 | .distinct().collect(Collectors.toList()); 62 | 63 | if (collection.size() > 1) { 64 | data.getLogger().error(Message.CONFLICT_MAPPING, this.name, collection); 65 | } else if (collection.isEmpty()) { 66 | data.getLogger().warn(Message.NO_MAPPING_RECURSIVE, this.name, targets); 67 | } 68 | 69 | return collection.stream().findFirst().orElse(name); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/net.fabricmc.tinyremapper.TinyRemapper$CLIExtensionProvider: -------------------------------------------------------------------------------- 1 | net.fabricmc.tinyremapper.extension.mixin.MixinExtension$CLIProvider 2 | -------------------------------------------------------------------------------- /src/test/java/net/fabricmc/tinyremapper/BulkTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import java.io.BufferedReader; 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | import java.io.InputStreamReader; 25 | import java.nio.charset.StandardCharsets; 26 | import java.nio.file.Files; 27 | import java.nio.file.Path; 28 | import java.util.HashMap; 29 | import java.util.Map; 30 | import java.util.zip.GZIPInputStream; 31 | import java.util.zip.ZipEntry; 32 | import java.util.zip.ZipInputStream; 33 | 34 | import org.junit.jupiter.api.Test; 35 | import org.junit.jupiter.api.io.TempDir; 36 | 37 | public class BulkTest { 38 | @Test 39 | public void fabricApi() throws IOException { 40 | TinyRemapper remapper; 41 | 42 | try (BufferedReader reader = getMappingReader()) { 43 | remapper = TinyRemapper.newRemapper() 44 | .withMappings(TinyUtils.createTinyMappingProvider(reader, "intermediary", "named")) 45 | .build(); 46 | 47 | Map files = new HashMap<>(); 48 | 49 | try (ZipInputStream zis = new ZipInputStream(getInputStream("integration/bulk/fabric-api-0.35.1+1.17.jar"))) { 50 | ZipEntry entry; 51 | 52 | while ((entry = zis.getNextEntry()) != null) { 53 | if (!entry.isDirectory() && entry.getName().endsWith(".jar")) { 54 | String name = entry.getName(); 55 | name = name.substring(name.lastIndexOf('/') + 1); 56 | 57 | Path file = tmpDir.resolve(name); 58 | Files.copy(zis, file); 59 | files.put(file, remapper.createInputTag()); 60 | } 61 | } 62 | } 63 | 64 | for (Map.Entry entry : files.entrySet()) { 65 | remapper.readInputsAsync(entry.getValue(), entry.getKey()); 66 | } 67 | 68 | //remapper.readClassPathAsync(Paths.get("/home/m/.gradle/caches/fabric-loom/minecraft-1.17-intermediary-net.fabricmc.yarn-1.17+build.6-v2.jar")); 69 | 70 | for (Map.Entry entry : files.entrySet()) { 71 | Path file = entry.getKey(); 72 | 73 | try (OutputConsumerPath consumer = new OutputConsumerPath.Builder(tmpDir.resolve(file.getFileName().toString().replace(".jar", "-out.jar"))).build()) { 74 | remapper.apply(consumer, entry.getValue()); 75 | } 76 | } 77 | } 78 | } 79 | 80 | private static BufferedReader getMappingReader() throws IOException { 81 | InputStream is = getInputStream("mapping/yarn-1.17+build.9-v2.tiny.gz"); 82 | 83 | return new BufferedReader(new InputStreamReader(new GZIPInputStream(is), StandardCharsets.UTF_8)); 84 | } 85 | 86 | private static InputStream getInputStream(String file) { 87 | return BulkTest.class.getClassLoader().getResourceAsStream(file); 88 | } 89 | 90 | @TempDir 91 | static Path tmpDir; 92 | } 93 | -------------------------------------------------------------------------------- /src/test/java/net/fabricmc/tinyremapper/ClassInstanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import static org.junit.jupiter.api.Assertions.assertEquals; 22 | import static org.junit.jupiter.api.Assertions.fail; 23 | 24 | import org.junit.jupiter.api.Test; 25 | 26 | public class ClassInstanceTest { 27 | @Test 28 | void addInputTags() { 29 | InputTag tag1 = new InputTag(); 30 | InputTag tag2 = new InputTag(); 31 | 32 | ClassInstance classInstance = new ClassInstance(null, false, new InputTag[]{}, null, new byte[]{}); 33 | assertEquals(0, classInstance.getInputTags().length); 34 | 35 | classInstance.addInputTags(new InputTag[]{tag1}); 36 | assertEquals(1, classInstance.getInputTags().length); 37 | assertContains(tag1, classInstance.getInputTags()); 38 | 39 | classInstance.addInputTags(new InputTag[]{tag1}); 40 | assertEquals(1, classInstance.getInputTags().length); 41 | assertContains(tag1, classInstance.getInputTags()); 42 | 43 | classInstance.addInputTags(new InputTag[]{tag2}); 44 | assertEquals(2, classInstance.getInputTags().length); 45 | assertContains(tag1, classInstance.getInputTags()); 46 | assertContains(tag2, classInstance.getInputTags()); 47 | } 48 | 49 | private static void assertContains(T value, T[] array) { 50 | for (T t : array) { 51 | if (t == value) { 52 | return; 53 | } 54 | } 55 | 56 | fail("Array does not contain value: " + value); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/net/fabricmc/tinyremapper/IntegrationTest3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import java.io.File; 22 | import java.io.IOException; 23 | import java.nio.file.Path; 24 | import java.util.Collections; 25 | import java.util.Set; 26 | import java.util.jar.JarFile; 27 | 28 | import org.junit.jupiter.api.AfterAll; 29 | import org.junit.jupiter.api.BeforeAll; 30 | import org.junit.jupiter.api.Test; 31 | import org.junit.jupiter.api.io.TempDir; 32 | 33 | public class IntegrationTest3 { 34 | private static final String MAPPING3_PATH = "/mapping/mapping3.tiny"; 35 | private static final String ANNOTATION_INPUT_PATH = "/integration/annotation/input.jar"; 36 | 37 | @TempDir 38 | static Path folder; 39 | 40 | @BeforeAll 41 | public static void setup() throws IOException { 42 | TestUtil.folder = folder; 43 | 44 | TestUtil.copyFile(IntegrationTest3.class, MAPPING3_PATH); 45 | 46 | TestUtil.copyFile(IntegrationTest3.class, ANNOTATION_INPUT_PATH); 47 | } 48 | 49 | private TinyRemapper setupRemapper() { 50 | // copy from Main.java 51 | final boolean ignoreFieldDesc = false; 52 | final boolean propagatePrivate = false; 53 | final boolean removeFrames = false; 54 | final Set forcePropagation = Collections.emptySet(); 55 | final File forcePropagationFile = null; 56 | final boolean ignoreConflicts = false; 57 | final boolean checkPackageAccess = true; 58 | final boolean fixPackageAccess = true; 59 | final boolean resolveMissing = false; 60 | final boolean rebuildSourceFilenames = false; 61 | final boolean skipLocalVariableMapping = false; 62 | final boolean renameInvalidLocals = false; 63 | final int threads = -1; 64 | 65 | final String from = "a"; 66 | final String to = "b"; 67 | 68 | Path mappings = TestUtil.getFile(IntegrationTest3.MAPPING3_PATH).toPath(); 69 | 70 | return TinyRemapper.newRemapper() 71 | .withMappings(TinyUtils.createTinyMappingProvider(mappings, from, to)) 72 | .ignoreFieldDesc(ignoreFieldDesc) 73 | .withForcedPropagation(forcePropagation) 74 | .propagatePrivate(propagatePrivate) 75 | .removeFrames(removeFrames) 76 | .ignoreConflicts(ignoreConflicts) 77 | .checkPackageAccess(checkPackageAccess) 78 | .fixPackageAccess(fixPackageAccess) 79 | .resolveMissing(resolveMissing) 80 | .rebuildSourceFilenames(rebuildSourceFilenames) 81 | .skipLocalVariableMapping(skipLocalVariableMapping) 82 | .renameInvalidLocals(renameInvalidLocals) 83 | .threads(threads) 84 | .build(); 85 | } 86 | 87 | /** 88 | * This is a test for annotation remapping. 89 | */ 90 | @Test 91 | public void annotation() throws IOException { 92 | final TinyRemapper remapper = setupRemapper(); 93 | final NonClassCopyMode ncCopyMode = NonClassCopyMode.FIX_META_INF; 94 | final Path[] classpath = new Path[]{}; 95 | 96 | Path output = TestUtil.output(ANNOTATION_INPUT_PATH); 97 | Path input = TestUtil.input(ANNOTATION_INPUT_PATH); 98 | 99 | try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) { 100 | outputConsumer.addNonClassFiles(input, ncCopyMode, remapper); 101 | 102 | remapper.readInputs(input); 103 | remapper.readClassPath(classpath); 104 | 105 | remapper.apply(outputConsumer); 106 | } catch (IOException e) { 107 | throw new RuntimeException(e); 108 | } finally { 109 | remapper.finish(); 110 | } 111 | 112 | JarFile result = new JarFile(output.toFile()); 113 | 114 | result.close(); 115 | } 116 | 117 | @AfterAll 118 | public static void cleanup() throws IOException { 119 | TestUtil.folder = null; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/test/java/net/fabricmc/tinyremapper/TestUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import java.io.File; 22 | import java.io.FileOutputStream; 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.io.OutputStream; 26 | import java.nio.file.Files; 27 | import java.nio.file.Path; 28 | 29 | public class TestUtil { 30 | public static Path folder = null; 31 | 32 | public static void copyFile(Class cls, String path) 33 | throws IOException { 34 | if (folder == null) throw new RuntimeException("the temporary folder is not created"); 35 | 36 | try (InputStream input = cls.getResourceAsStream(path)) { 37 | if (input == null) throw new IOException("input is null"); 38 | 39 | byte[] buffer = new byte[input.available()]; 40 | //noinspection ResultOfMethodCallIgnored 41 | input.read(buffer); 42 | 43 | Path target = folder.resolve(path.substring(1)); 44 | Files.createDirectories(target.getParent()); 45 | Files.createFile(target); 46 | 47 | try (OutputStream output = new FileOutputStream(target.toFile())) { 48 | output.write(buffer); 49 | } 50 | } 51 | } 52 | 53 | public static File getFile(String path) { 54 | return folder.resolve(path.substring(1)).toFile(); 55 | } 56 | 57 | public static Path input(String path) { 58 | return getFile(path).toPath(); 59 | } 60 | 61 | public static Path output(String path) { 62 | return folder.resolve(path.replace("input", "output").substring(1)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/net/fabricmc/tinyremapper/TinyRemapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper; 20 | 21 | import static org.junit.jupiter.api.Assertions.assertEquals; 22 | 23 | import java.lang.reflect.Method; 24 | import java.nio.file.Path; 25 | import java.nio.file.Paths; 26 | 27 | import org.junit.jupiter.api.Test; 28 | 29 | class TinyRemapperTest { 30 | @Test 31 | public void analyzeMrjVersion() throws ReflectiveOperationException { 32 | String input; 33 | String name; 34 | int result; 35 | 36 | name = "com/github/logicf/App"; 37 | 38 | input = "/path/to/bin/META-INF/versions/16/com/github/logicf/App.class"; 39 | result = getMrjVersionFromPath(input, name); 40 | assertEquals(16, result); 41 | 42 | input = "/META-INF/versions/9/com/github/logicf/App.class"; 43 | result = getMrjVersionFromPath(input, name); 44 | assertEquals(9, result); 45 | 46 | input = "path/to/bin/META-INF/versions/16/com/github/logicf/App.class"; 47 | result = getMrjVersionFromPath(input, name); 48 | assertEquals(16, result); 49 | 50 | input = "META-INF/versions/9/com/github/logicf/App.class"; 51 | result = getMrjVersionFromPath(input, name); 52 | assertEquals(9, result); 53 | 54 | input = "/path/to/bin/com/github/logicf/App.class"; 55 | result = getMrjVersionFromPath(input, name); 56 | assertEquals(ClassInstance.MRJ_DEFAULT, result); 57 | 58 | input = "/path/to/bin/META-INF/versions/16/abc/com/github/logicf/App.class"; 59 | result = getMrjVersionFromPath(input, name); 60 | assertEquals(ClassInstance.MRJ_DEFAULT, result); 61 | 62 | input = "/path/to/bin/versions/16/com/github/logicf/App.class"; 63 | result = getMrjVersionFromPath(input, name); 64 | assertEquals(ClassInstance.MRJ_DEFAULT, result); 65 | 66 | input = "/META-INF/versions/9aa/com/github/logicf/App.class"; 67 | result = getMrjVersionFromPath(input, name); 68 | assertEquals(ClassInstance.MRJ_DEFAULT, result); 69 | 70 | input = "/bin/App.class"; 71 | result = getMrjVersionFromPath(input, name); 72 | assertEquals(ClassInstance.MRJ_DEFAULT, result); 73 | 74 | input = "App.class"; 75 | result = getMrjVersionFromPath(input, name); 76 | assertEquals(ClassInstance.MRJ_DEFAULT, result); 77 | } 78 | 79 | private static int getMrjVersionFromPath(String file, String name) throws ReflectiveOperationException { 80 | return (int) getMrjVersionFromPathMethod.invoke(null, Paths.get(file), name); 81 | } 82 | 83 | private static final Method getMrjVersionFromPathMethod; 84 | 85 | static { 86 | try { 87 | getMrjVersionFromPathMethod = TinyRemapper.class.getDeclaredMethod("analyzeMrjVersion", Path.class, String.class); 88 | getMrjVersionFromPathMethod.setAccessible(true); 89 | } catch (ReflectiveOperationException e) { 90 | throw new RuntimeException(e); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/test/java/net/fabricmc/tinyremapper/extension/mixin/hard/util/IConvertibleStringTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.hard.util; 20 | 21 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 22 | import static org.junit.jupiter.api.Assertions.assertEquals; 23 | import static org.junit.jupiter.api.Assertions.assertThrows; 24 | 25 | import org.junit.jupiter.api.Test; 26 | 27 | class IConvertibleStringTest { 28 | @Test 29 | void IdentityString() { 30 | IConvertibleString str; 31 | 32 | str = new IdentityString("bla"); 33 | assertEquals("bla", str.getOriginal()); 34 | assertEquals("bla", str.getConverted()); 35 | assertEquals("abc", str.getReverted("abc")); 36 | } 37 | 38 | @Test 39 | void PrefixString() { 40 | IConvertibleString str; 41 | 42 | str = new PrefixString("abc", "abcde"); 43 | assertEquals("abcde", str.getOriginal()); 44 | assertEquals("de", str.getConverted()); 45 | assertEquals("abcbla", str.getReverted("bla")); 46 | 47 | assertThrows(RuntimeException.class, () -> new PrefixString("abc", "blade")); 48 | } 49 | 50 | @Test 51 | void CamelPrefixString() { 52 | IConvertibleString str; 53 | 54 | str = new CamelPrefixString("abc", "abcDe"); 55 | assertEquals("abcDe", str.getOriginal()); 56 | assertEquals("de", str.getConverted()); 57 | assertEquals("abcAbc", str.getReverted("abc")); 58 | 59 | assertThrows(RuntimeException.class, () -> new CamelPrefixString("abc", "abcde")); 60 | assertThrows(RuntimeException.class, () -> new CamelPrefixString("abc", "def")); 61 | assertDoesNotThrow(() -> new CamelPrefixString("abc", "abc123")); 62 | 63 | str = new CamelPrefixString("get", "getBIOME"); 64 | assertEquals("getBIOME", str.getOriginal()); 65 | assertEquals("BIOME", str.getConverted()); 66 | assertEquals("getField_1234", str.getReverted("field_1234")); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/net/fabricmc/tinyremapper/extension/mixin/soft/data/MemberInfoTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, 2018, Player, asie 3 | * Copyright (c) 2021, FabricMC 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package net.fabricmc.tinyremapper.extension.mixin.soft.data; 20 | 21 | import static org.junit.jupiter.api.Assertions.assertEquals; 22 | import static org.junit.jupiter.api.Assertions.assertFalse; 23 | import static org.junit.jupiter.api.Assertions.assertNotNull; 24 | import static org.junit.jupiter.api.Assertions.assertNull; 25 | import static org.junit.jupiter.api.Assertions.assertTrue; 26 | 27 | import org.junit.jupiter.api.Test; 28 | 29 | import net.fabricmc.tinyremapper.api.TrMember.MemberType; 30 | 31 | class MemberInfoTest { 32 | @Test 33 | void isRegex() { 34 | assertTrue(MemberInfo.isRegex("/^foo/")); 35 | assertTrue(MemberInfo.isRegex("/bar$/ desc=/^\\(I\\)/")); 36 | assertTrue(MemberInfo.isRegex("name=/bar$/ desc=/^\\(I\\)/")); 37 | assertTrue(MemberInfo.isRegex("/Entity/")); 38 | assertTrue(MemberInfo.isRegex("owner=/\\/google\\//")); 39 | assertFalse(MemberInfo.isRegex("func_1234_a")); 40 | assertFalse(MemberInfo.isRegex("field_5678_z:Ljava/lang/String;")); 41 | assertFalse(MemberInfo.isRegex("Lfoo/bar/Baz;func_1234_a(DDD)V")); 42 | } 43 | 44 | @Test 45 | void parse() { 46 | MemberInfo info; 47 | 48 | info = MemberInfo.parse("{2}(Z)V"); 49 | assertNotNull(info); 50 | assertEquals(info.getType(), MemberType.METHOD); 51 | assertEquals(info.getOwner(), ""); 52 | assertEquals(info.getName(), ""); 53 | assertEquals(info.getQuantifier(), "{2}"); 54 | assertEquals(info.getDesc(), "(Z)V"); 55 | assertEquals(info.toString(), "{2}(Z)V"); 56 | 57 | info = MemberInfo.parse("field_5678_z:Ljava/lang/String;"); 58 | assertNotNull(info); 59 | assertEquals(info.getType(), MemberType.FIELD); 60 | assertEquals(info.getOwner(), ""); 61 | assertEquals(info.getName(), "field_5678_z"); 62 | assertEquals(info.getQuantifier(), ""); 63 | assertEquals(info.getDesc(), "Ljava/lang/String;"); 64 | assertEquals(info.toString(), "field_5678_z:Ljava/lang/String;"); 65 | 66 | info = MemberInfo.parse("Lfoo/bar/Baz;func_1234_a(DDD)V"); 67 | assertNotNull(info); 68 | assertEquals(info.getType(), MemberType.METHOD); 69 | assertEquals(info.getOwner(), "foo/bar/Baz"); 70 | assertEquals(info.getName(), "func_1234_a"); 71 | assertEquals(info.getQuantifier(), ""); 72 | assertEquals(info.getDesc(), "(DDD)V"); 73 | assertEquals(info.toString(), "Lfoo/bar/Baz;func_1234_a(DDD)V"); 74 | 75 | info = MemberInfo.parse("foo.bar.Baz.func_1234_a(DDD)V"); 76 | assertNotNull(info); 77 | assertEquals(info.getType(), MemberType.METHOD); 78 | assertEquals(info.getOwner(), "foo/bar/Baz"); 79 | assertEquals(info.getName(), "func_1234_a"); 80 | assertEquals(info.getQuantifier(), ""); 81 | assertEquals(info.getDesc(), "(DDD)V"); 82 | assertEquals(info.toString(), "Lfoo/bar/Baz;func_1234_a(DDD)V"); 83 | 84 | info = MemberInfo.parse("java/lang/String"); 85 | assertNotNull(info); 86 | assertNull(info.getType()); 87 | assertEquals(info.getOwner(), "java/lang/String"); 88 | assertEquals(info.getName(), ""); 89 | assertEquals(info.getQuantifier(), ""); 90 | assertEquals(info.getDesc(), ""); 91 | assertEquals(info.toString(), "Ljava/lang/String;"); 92 | 93 | info = MemberInfo.parse("([C)Ljava/lang/String;"); 94 | assertNotNull(info); 95 | assertEquals(info.getType(), MemberType.METHOD); 96 | assertEquals(info.getOwner(), ""); 97 | assertEquals(info.getName(), ""); 98 | assertEquals(info.getQuantifier(), ""); 99 | assertEquals(info.getDesc(), "([C)Ljava/lang/String;"); 100 | assertEquals(info.toString(), "([C)Ljava/lang/String;"); 101 | 102 | info = MemberInfo.parse("*"); 103 | assertNotNull(info); 104 | assertNull(info.getType()); 105 | assertEquals(info.getOwner(), ""); 106 | assertEquals(info.getName(), ""); 107 | assertEquals(info.getQuantifier(), "*"); 108 | assertEquals(info.getDesc(), ""); 109 | assertEquals(info.toString(), "*"); 110 | 111 | info = new MemberInfo("", "", "*", "()V"); 112 | assertNotNull(info); 113 | assertEquals(info.getType(), MemberType.METHOD); 114 | assertEquals(info.getOwner(), ""); 115 | assertEquals(info.getName(), ""); 116 | assertEquals(info.getQuantifier(), "*"); 117 | assertEquals(info.getDesc(), "()V"); 118 | assertEquals(info.toString(), "*"); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/test/resources/integration/access/input.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FabricMC/tiny-remapper/d59015fb0b8a656c0a95235a4edb099c3638977a/src/test/resources/integration/access/input.jar -------------------------------------------------------------------------------- /src/test/resources/integration/annotation/input.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FabricMC/tiny-remapper/d59015fb0b8a656c0a95235a4edb099c3638977a/src/test/resources/integration/annotation/input.jar -------------------------------------------------------------------------------- /src/test/resources/integration/basic/input.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FabricMC/tiny-remapper/d59015fb0b8a656c0a95235a4edb099c3638977a/src/test/resources/integration/basic/input.jar -------------------------------------------------------------------------------- /src/test/resources/integration/bulk/fabric-api-0.35.1+1.17.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FabricMC/tiny-remapper/d59015fb0b8a656c0a95235a4edb099c3638977a/src/test/resources/integration/bulk/fabric-api-0.35.1+1.17.jar -------------------------------------------------------------------------------- /src/test/resources/integration/mrj1/input.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FabricMC/tiny-remapper/d59015fb0b8a656c0a95235a4edb099c3638977a/src/test/resources/integration/mrj1/input.jar -------------------------------------------------------------------------------- /src/test/resources/integration/mrj2/input.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FabricMC/tiny-remapper/d59015fb0b8a656c0a95235a4edb099c3638977a/src/test/resources/integration/mrj2/input.jar -------------------------------------------------------------------------------- /src/test/resources/integration/mrj3/input.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FabricMC/tiny-remapper/d59015fb0b8a656c0a95235a4edb099c3638977a/src/test/resources/integration/mrj3/input.jar -------------------------------------------------------------------------------- /src/test/resources/mapping/mapping1.tiny: -------------------------------------------------------------------------------- 1 | tiny 2 0 a b 2 | c com/github/logicf/App com/github/logicf/Main 3 | c com/github/logicf/C1 com/github/logicf/D1 4 | c com/github/logicf/C2 com/github/logicf/D2 5 | c com/github/logicf/C3 com/github/logicf/D3 6 | c com/github/logicf/C4 com/github/logicf/D4 7 | c com/github/logicf/C5 com/github/logicf/D5 8 | -------------------------------------------------------------------------------- /src/test/resources/mapping/mapping2.tiny: -------------------------------------------------------------------------------- 1 | tiny 2 0 a b 2 | c com/github/logicf/App com/github/logicf/Main 3 | c com/github/logicf/C1 com/github/logicf/pkg1/D1 4 | c com/github/logicf/C3 com/github/logicf/pkg2/D3 5 | -------------------------------------------------------------------------------- /src/test/resources/mapping/mapping3.tiny: -------------------------------------------------------------------------------- 1 | tiny 2 0 a b 2 | c test/Test pkg/c_test 3 | m (ILjava/lang/String;DZ)V someAbstractMethod some_abstract_method 4 | p 1 someArg1 some_arg_1 5 | p 2 someArg2 some_arg_2 6 | p 3 someArg3 some_arg_3 7 | p 5 someArg4 some_arg_4 8 | m (ILjava/lang/String;DZ)V someStaticMethod some_static_method 9 | p 0 someArg1 some_arg_1 10 | p 1 someArg2 some_arg_2 11 | p 2 someArg3 some_arg_3 12 | p 4 someArg4 some_arg_4 13 | c test/TestAnnotation pkg/c_test_annotation 14 | m ()Ljava/lang/String; strVal m_str_val 15 | m ()[Ljava/lang/String; strArrayVal m_str_array_val 16 | m ()[Ljava/lang/String; strArrayVal2 m_str_array_val_2 17 | m ()I intVal m_int_val 18 | m ()[I intArrayVal m_int_array_val 19 | m ()[I intArrayVal2 m_int_array_val_2 20 | m ()Ltest/TestEnum; enumVal m_enum_val 21 | m ()[Ltest/TestEnum; enumArrayVal m_enum_array_val 22 | m ()[Ltest/TestEnum; enumArrayVal2 m_enum_array_val_2 23 | m ()Ltest/TestAnnotation1; annVal m_ann_val 24 | m ()[Ltest/TestAnnotation1; annArrayVal m_ann_array_val 25 | c test/TestAnnotation1 pkg/c_test_annotation_1 26 | m ()Ljava/lang/String; strVal m_str_val 27 | c test/TestEnum pkg/c_test_enum 28 | f Ltest/TestEnum; Test1 f_test1 29 | f Ltest/TestEnum; Test2 f_test2 30 | f Ltest/TestEnum; Test3 f_test3 -------------------------------------------------------------------------------- /src/test/resources/mapping/yarn-1.17+build.9-v2.tiny.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FabricMC/tiny-remapper/d59015fb0b8a656c0a95235a4edb099c3638977a/src/test/resources/mapping/yarn-1.17+build.9-v2.tiny.gz --------------------------------------------------------------------------------