├── .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 extends TrClass> getInterfaces();
39 |
40 | Collection extends TrClass> getParents();
41 | Collection extends TrClass> getChildren();
42 |
43 | TrField getField(String name, String desc);
44 | TrMethod getMethod(String name, String desc);
45 |
46 | Collection extends TrField> getFields();
47 | Collection extends TrMethod> getMethods();
48 | Collection extends TrMember> 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
--------------------------------------------------------------------------------