diff --git a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java index 0ab37d31677..0e4c2779951 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java @@ -421,18 +421,19 @@ public void addField(ICodeWriter code, FieldNode f) { if (f.contains(AFlag.DONT_GENERATE)) { return; } + if (f.contains(JadxAttrType.ANNOTATION_LIST) || f.contains(AType.JADX_COMMENTS) || f.getFieldInfo().hasAlias()) { + code.newLine(); + } if (Consts.DEBUG_USAGE) { addFieldUsageInfo(code, f); } + if (f.getFieldInfo().hasAlias()) { + CodeGenUtils.addRenamedComment(code, f, f.getName()); + } CodeGenUtils.addComments(code, f); annotationGen.addForField(code, f); - boolean addInfoComments = f.checkCommentsLevel(CommentsLevel.INFO); - if (f.getFieldInfo().hasAlias() && addInfoComments) { - code.newLine(); - CodeGenUtils.addRenamedComment(code, f, f.getName()); - } - code.startLine(f.getAccessFlags().makeString(addInfoComments)); + code.startLine(f.getAccessFlags().makeString(f.checkCommentsLevel(CommentsLevel.INFO))); useType(code, f.getType()); code.add(' '); code.attachDefinition(f); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/rename/UserRenames.java b/jadx-core/src/main/java/jadx/core/dex/visitors/rename/UserRenames.java index e5f60b1292a..fe31f00bdfe 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/rename/UserRenames.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/rename/UserRenames.java @@ -18,6 +18,7 @@ import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.PackageNode; import jadx.core.dex.nodes.RootNode; +import jadx.core.utils.StringUtils; public class UserRenames { private static final Logger LOG = LoggerFactory.getLogger(UserRenames.class); @@ -57,7 +58,12 @@ private static void applyRename(ClassNode cls, ICodeRename rename) { case FIELD: FieldNode fieldNode = cls.searchFieldByShortId(nodeRef.getShortId()); if (fieldNode == null) { - LOG.warn("Field reference not found: {}", nodeRef); + String fieldName = StringUtils.getPrefix(nodeRef.getShortId(), ":"); + String fieldSign = cls.getFields().stream() + .filter(f -> f.getFieldInfo().getName().equals(fieldName)) + .map(f -> f.getFieldInfo().getShortId()) + .collect(Collectors.joining()); + LOG.warn("Field reference not found: {}. Fields with same name: {}", nodeRef, fieldSign); } else { fieldNode.rename(rename.getNewName()); } diff --git a/jadx-core/src/main/java/jadx/core/utils/CodeGenUtils.java b/jadx-core/src/main/java/jadx/core/utils/CodeGenUtils.java index 294bdbba2cb..9a386ccfdac 100644 --- a/jadx-core/src/main/java/jadx/core/utils/CodeGenUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/CodeGenUtils.java @@ -124,8 +124,7 @@ public static void addRenamedComment(ICodeWriter code, NotificationAttrNode node code.startLine("/* renamed from: ").add(origName); RenameReasonAttr renameReasonAttr = node.get(AType.RENAME_REASON); if (renameReasonAttr != null) { - code.add(" reason: "); - code.add(renameReasonAttr.getDescription()); + code.add(", reason: ").add(renameReasonAttr.getDescription()); } code.add(" */"); } diff --git a/jadx-core/src/main/java/jadx/core/utils/StringUtils.java b/jadx-core/src/main/java/jadx/core/utils/StringUtils.java index 62e969cc736..28fbbebbce6 100644 --- a/jadx-core/src/main/java/jadx/core/utils/StringUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/StringUtils.java @@ -374,6 +374,14 @@ public static String removeSuffix(String str, String suffix) { return str; } + public static @Nullable String getPrefix(String str, String delim) { + int idx = str.indexOf(delim); + if (idx != -1) { + return str.substring(0, idx); + } + return null; + } + public static String getDateText() { return new SimpleDateFormat("HH:mm:ss").format(new Date()); } diff --git a/jadx-core/src/test/java/jadx/tests/integration/rename/TestFieldRenameFormat.java b/jadx-core/src/test/java/jadx/tests/integration/rename/TestFieldRenameFormat.java new file mode 100644 index 00000000000..ec62ae019f5 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/rename/TestFieldRenameFormat.java @@ -0,0 +1,66 @@ +package jadx.tests.integration.rename; + +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.google.gson.annotations.SerializedName; + +import jadx.api.data.ICodeRename; +import jadx.api.data.IJavaNodeRef.RefType; +import jadx.api.data.impl.JadxCodeData; +import jadx.api.data.impl.JadxCodeRename; +import jadx.api.data.impl.JadxNodeRef; +import jadx.tests.api.IntegrationTest; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestFieldRenameFormat extends IntegrationTest { + + @SuppressWarnings({ "unused", "NonSerializableClassWithSerialVersionUID" }) + public static class TestCls { + private static final long serialVersionUID = -2619335455376089892L; + @SerializedName("id") + private int b; + @SerializedName("title") + private String c; + @SerializedName("images") + private List d; + @SerializedName("authors") + private List e; + @SerializedName("description") + private String f; + } + + @Test + public void test() { + noDebugInfo(); + + String baseClsId = TestCls.class.getName(); + List renames = Arrays.asList( + fieldRename(baseClsId, "b:I", "id"), + fieldRename(baseClsId, "c:Ljava/lang/String;", "title"), + fieldRename(baseClsId, "e:Ljava/util/List;", "authors")); + + JadxCodeData codeData = new JadxCodeData(); + codeData.setRenames(renames); + getArgs().setCodeData(codeData); + getArgs().setDeobfuscationOn(false); + + assertThat(getClassNode(TestCls.class)) + .code() + .containsOne("private int id;") + .containsOne("private List authors;") + .containsLines(1, + "", + "/* renamed from: c */", + "@SerializedName(\"title\")", + "private String title;", + ""); + } + + private static JadxCodeRename fieldRename(String baseClsId, String shortId, String id) { + return new JadxCodeRename(new JadxNodeRef(RefType.FIELD, baseClsId, shortId), id); + } +}