[java, java-decompiler] type annotations in class files
Step 1: add top-level field/method/parameter annotations to stubs; include them in decompiled text.
This commit is contained in:
@@ -23,10 +23,7 @@ import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
|
||||
import org.jetbrains.java.decompiler.main.rels.ClassWrapper;
|
||||
import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.exps.AnnotationExprent;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.exps.ConstExprent;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.exps.NewExprent;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.exps.*;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarTypeProcessor;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
|
||||
@@ -43,9 +40,7 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
|
||||
import org.jetbrains.java.decompiler.struct.gen.generics.*;
|
||||
import org.jetbrains.java.decompiler.util.InterpreterUtil;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class ClassWriter {
|
||||
private final PoolInterceptor interceptor;
|
||||
@@ -311,7 +306,7 @@ public class ClassWriter {
|
||||
appendComment(buffer, "synthetic class", indent);
|
||||
}
|
||||
|
||||
appendAnnotations(buffer, cl, indent);
|
||||
appendAnnotations(buffer, indent, cl, -1);
|
||||
|
||||
buffer.appendIndent(indent);
|
||||
|
||||
@@ -407,7 +402,7 @@ public class ClassWriter {
|
||||
appendComment(buffer, "synthetic field", indent);
|
||||
}
|
||||
|
||||
appendAnnotations(buffer, fd, indent);
|
||||
appendAnnotations(buffer, indent, fd, TypeAnnotation.FIELD);
|
||||
|
||||
buffer.appendIndent(indent);
|
||||
|
||||
@@ -630,7 +625,7 @@ public class ClassWriter {
|
||||
appendComment(buffer, "bridge method", indent);
|
||||
}
|
||||
|
||||
appendAnnotations(buffer, mt, indent);
|
||||
appendAnnotations(buffer, indent, mt, TypeAnnotation.METHOD_RETURN_TYPE);
|
||||
|
||||
buffer.appendIndent(indent);
|
||||
|
||||
@@ -816,7 +811,7 @@ public class ClassWriter {
|
||||
StructAnnDefaultAttribute attr = (StructAnnDefaultAttribute)mt.getAttributes().getWithKey("AnnotationDefault");
|
||||
if (attr != null) {
|
||||
buffer.append(" default ");
|
||||
buffer.append(attr.getDefaultValue().toJava(0, new BytecodeMappingTracer())); // dummy tracer
|
||||
buffer.append(attr.getDefaultValue().toJava(0, BytecodeMappingTracer.DUMMY));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -951,26 +946,30 @@ public class ClassWriter {
|
||||
|
||||
private static final String[] ANNOTATION_ATTRIBUTES = {
|
||||
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS};
|
||||
private static final String[] PARAMETER_ANNOTATION_ATTRIBUTES = {
|
||||
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS};
|
||||
private static final String[] TYPE_ANNOTATION_ATTRIBUTES = {
|
||||
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_TYPE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS};
|
||||
|
||||
private static void appendAnnotations(TextBuffer buffer, StructMember mb, int indent) {
|
||||
BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
|
||||
private static void appendAnnotations(TextBuffer buffer, int indent, StructMember mb, int targetType) {
|
||||
Set<String> filter = new HashSet<>();
|
||||
|
||||
for (String name : ANNOTATION_ATTRIBUTES) {
|
||||
StructAnnotationAttribute attribute = (StructAnnotationAttribute)mb.getAttributes().getWithKey(name);
|
||||
if (attribute != null) {
|
||||
for (AnnotationExprent annotation : attribute.getAnnotations()) {
|
||||
buffer.append(annotation.toJava(indent, tracer_dummy)).appendLineSeparator();
|
||||
String text = annotation.toJava(indent, BytecodeMappingTracer.DUMMY).toString();
|
||||
filter.add(text);
|
||||
buffer.append(text).appendLineSeparator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
appendTypeAnnotations(buffer, indent, mb, targetType, -1, filter);
|
||||
}
|
||||
|
||||
private static final String[] PARAMETER_ANNOTATION_ATTRIBUTES = {
|
||||
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS,
|
||||
StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS};
|
||||
|
||||
private static void appendParameterAnnotations(TextBuffer buffer, StructMethod mt, int param) {
|
||||
BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
|
||||
Set<String> filter = new HashSet<>();
|
||||
|
||||
for (String name : PARAMETER_ANNOTATION_ATTRIBUTES) {
|
||||
StructAnnotationParameterAttribute attribute = (StructAnnotationParameterAttribute)mt.getAttributes().getWithKey(name);
|
||||
@@ -978,7 +977,33 @@ public class ClassWriter {
|
||||
List<List<AnnotationExprent>> annotations = attribute.getParamAnnotations();
|
||||
if (param < annotations.size()) {
|
||||
for (AnnotationExprent annotation : annotations.get(param)) {
|
||||
buffer.append(annotation.toJava(0, tracer_dummy)).append(' ');
|
||||
String text = annotation.toJava(-1, BytecodeMappingTracer.DUMMY).toString();
|
||||
filter.add(text);
|
||||
buffer.append(text).append(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
appendTypeAnnotations(buffer, -1, mt, TypeAnnotation.METHOD_PARAMETER, param, filter);
|
||||
}
|
||||
|
||||
private static void appendTypeAnnotations(TextBuffer buffer, int indent, StructMember mb, int targetType, int index, Set<String> filter) {
|
||||
for (String name : TYPE_ANNOTATION_ATTRIBUTES) {
|
||||
StructTypeAnnotationAttribute attribute = (StructTypeAnnotationAttribute)mb.getAttributes().getWithKey(name);
|
||||
if (attribute != null) {
|
||||
for (TypeAnnotation annotation : attribute.getAnnotations()) {
|
||||
if (annotation.isTopLevel() && annotation.getTargetType() == targetType && (index < 0 || annotation.getIndex() == index)) {
|
||||
String text = annotation.getAnnotation().toJava(indent, BytecodeMappingTracer.DUMMY).toString();
|
||||
if (!filter.contains(text)) {
|
||||
buffer.append(text);
|
||||
if (indent < 0) {
|
||||
buffer.append(' ');
|
||||
}
|
||||
else {
|
||||
buffer.appendLineSeparator();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user