Skip to content

Commit

Permalink
feat: add support for 'package-info' (skylot#1967)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Aug 7, 2023
1 parent f213082 commit c602b3d
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,6 @@ public Map<Integer, ICodeAnnotation> getRawAnnotations() {

@Override
public String getCodeStr() {
removeFirstEmptyLine();
return buf.toString();
}

Expand Down
28 changes: 25 additions & 3 deletions jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,29 @@ public ClassNode getClassNode() {
}

public ICodeInfo makeClass() throws CodegenException {
if (cls.contains(AFlag.PACKAGE_INFO)) {
return makePackageInfo();
}
ICodeWriter clsBody = cls.root().makeCodeWriter();
addClassCode(clsBody);

ICodeWriter clsCode = cls.root().makeCodeWriter();
addPackage(clsCode);
clsCode.newLine();
addImports(clsCode);
clsCode.add(clsBody);
return clsCode.finish();
}

private void addPackage(ICodeWriter clsCode) {
if (cls.getPackage().isEmpty()) {
clsCode.add("// default package");
} else {
clsCode.add("package ").add(cls.getPackage()).add(';');
}
clsCode.newLine();
}

private void addImports(ICodeWriter clsCode) {
int importsCount = imports.size();
if (importsCount != 0) {
List<ClassInfo> sortedImports = new ArrayList<>(imports);
Expand All @@ -122,8 +135,17 @@ public ICodeInfo makeClass() throws CodegenException {
clsCode.newLine();
imports.clear();
}
clsCode.add(clsBody);
return clsCode.finish();
}

private ICodeInfo makePackageInfo() {
ICodeWriter code = cls.root().makeCodeWriter();
annotationGen.addForClass(code);
code.newLine();
code.attachDefinition(cls);
addPackage(code);
code.newLine();
addImports(code);
return code.finish();
}

public void addClassCode(ICodeWriter code) throws CodegenException {
Expand Down
2 changes: 2 additions & 0 deletions jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public enum AFlag {
THIS,
SUPER,

PACKAGE_INFO,

/**
* Mark Android resources class
*/
Expand Down
10 changes: 10 additions & 0 deletions jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ private void load(IClassData cls, boolean reloading) {
}
initStaticValues(fields);
processAttributes(this);
processSpecialClasses(this);
buildCache();

// TODO: implement module attribute parsing
Expand Down Expand Up @@ -167,6 +168,15 @@ public void updateGenericClsData(List<ArgType> generics, ArgType superClass, Lis
this.interfaces = interfaces;
}

private static void processSpecialClasses(ClassNode cls) {
AccessInfo flags = cls.getAccessFlags();
if (flags.isSynthetic() && flags.isInterface() && flags.isAbstract()
&& cls.getName().equals("package-info")) {
cls.add(AFlag.PACKAGE_INFO);
cls.add(AFlag.DONT_RENAME);
}
}

private static void processAttributes(ClassNode cls) {
// move AnnotationDefault from cls to methods (dex specific)
AnnotationDefaultClassAttr defAttr = cls.get(JadxAttrType.ANNOTATION_DEFAULT_CLASS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public class ClassModifier extends AbstractVisitor {

@Override
public boolean visit(ClassNode cls) throws JadxException {
if (cls.contains(AFlag.PACKAGE_INFO)) {
return false;
}
for (ClassNode inner : cls.getInnerClasses()) {
visit(inner);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ private static void checkNames(RootNode root) {
}

private static void checkClassName(IAliasProvider aliasProvider, ClassNode cls, JadxArgs args) {
if (cls.contains(AFlag.DONT_RENAME)) {
return;
}
ClassInfo classInfo = cls.getClassInfo();
String clsName = classInfo.getAliasShortName();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.jetbrains.annotations.NotNull;

import jadx.api.impl.SimpleCodeWriter;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.utils.files.FileUtils;
import jadx.tests.api.IntegrationTest;
Expand Down Expand Up @@ -80,12 +81,16 @@ private void compile(List<JavaFileObject> jfObjects) {
arguments.add(javaVerStr);
arguments.addAll(options.getArguments());

DiagnosticListener<? super JavaFileObject> diagnostic =
diagObj -> System.out.println("Compiler diagnostic: " + diagObj);
SimpleCodeWriter output = new SimpleCodeWriter();
DiagnosticListener<JavaFileObject> diagnostic = diagObj -> {
String msg = "Compiler diagnostic: " + diagObj;
output.startLine(msg);
System.out.println(msg);
};
Writer out = new PrintWriter(System.out);
CompilationTask compilerTask = compiler.getTask(out, fileManager, diagnostic, arguments, null, jfObjects);
if (Boolean.FALSE.equals(compilerTask.call())) {
throw new RuntimeException("Compilation failed");
throw new RuntimeException("Compilation failed: " + output);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ public void check() {
@Test
public void test() {
noDebugInfo();
getArgs().setRawCFGOutput(true);
assertThat(getClassNode(TestCls.class))
.code()
.containsOne("i++");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package jadx.tests.integration.special;

import java.util.List;

import org.junit.jupiter.api.Test;

import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;

import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;

public class TestPackageInfoSupport extends SmaliTest {

@Test
public void test() {
disableCompilation();
List<ClassNode> classes = loadFromSmaliFiles();
assertThat(searchCls(classes, "special.pkg1.package-info"))
.satisfies(cls -> assertThat(cls.getAlias()).isEqualTo("package-info")) // shouldn't be renamed
.code()
.containsLines(
"@Deprecated",
"package special.pkg1;");
assertThat(searchCls(classes, "special.pkg2.package-info"))
.code()
.containsLines(
"@ApiStatus.Internal",
"package special.pkg2;",
"",
"import org.jetbrains.annotations.ApiStatus;");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.class interface abstract synthetic Lspecial/pkg1/package-info;
.super Ljava/lang/Object;
.source "package-info.java"

.annotation runtime Ljava/lang/Deprecated;
.end annotation
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.class interface abstract synthetic Lspecial/pkg2/package-info;
.super Ljava/lang/Object;

.annotation runtime Lorg/jetbrains/annotations/ApiStatus$Internal;
.end annotation

0 comments on commit c602b3d

Please sign in to comment.