|
|
@ -142,8 +142,7 @@ public class ClassWriter { |
|
|
|
buffer.append(") ->"); |
|
|
|
buffer.append(") ->"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
buffer.append(" {"); |
|
|
|
buffer.append(" {").appendLineSeparator(); |
|
|
|
buffer.append(DecompilerContext.getNewLineSeparator()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
methodLambdaToJava(node, classNode, mt, buffer, indent + 1, !lambdaToAnonymous, tracer); |
|
|
|
methodLambdaToJava(node, classNode, mt, buffer, indent + 1, !lambdaToAnonymous, tracer); |
|
|
|
|
|
|
|
|
|
|
@ -193,8 +192,7 @@ public class ClassWriter { |
|
|
|
boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); |
|
|
|
boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); |
|
|
|
if (isEnum) { |
|
|
|
if (isEnum) { |
|
|
|
if (enumFields) { |
|
|
|
if (enumFields) { |
|
|
|
buffer.append(','); |
|
|
|
buffer.append(',').appendLineSeparator(); |
|
|
|
buffer.appendLineSeparator(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
enumFields = true; |
|
|
|
enumFields = true; |
|
|
|
} |
|
|
|
} |
|
|
@ -211,8 +209,7 @@ public class ClassWriter { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (enumFields) { |
|
|
|
if (enumFields) { |
|
|
|
buffer.append(';'); |
|
|
|
buffer.append(';').appendLineSeparator(); |
|
|
|
buffer.appendLineSeparator(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// FIXME: fields don't matter at the moment
|
|
|
|
// FIXME: fields don't matter at the moment
|
|
|
@ -226,6 +223,7 @@ public class ClassWriter { |
|
|
|
if (hide) continue; |
|
|
|
if (hide) continue; |
|
|
|
|
|
|
|
|
|
|
|
int position = buffer.length(); |
|
|
|
int position = buffer.length(); |
|
|
|
|
|
|
|
int storedLine = startLine; |
|
|
|
if (hasContent) { |
|
|
|
if (hasContent) { |
|
|
|
buffer.appendLineSeparator(); |
|
|
|
buffer.appendLineSeparator(); |
|
|
|
startLine++; |
|
|
|
startLine++; |
|
|
@ -236,10 +234,11 @@ public class ClassWriter { |
|
|
|
hasContent = true; |
|
|
|
hasContent = true; |
|
|
|
DecompilerContext.getBytecodeSourceMapper().addTracer(cl.qualifiedName, |
|
|
|
DecompilerContext.getBytecodeSourceMapper().addTracer(cl.qualifiedName, |
|
|
|
InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()), method_tracer); |
|
|
|
InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()), method_tracer); |
|
|
|
startLine = method_tracer.getCurrentSourceLine()+1; // zero-based line index
|
|
|
|
startLine = method_tracer.getCurrentSourceLine(); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
buffer.setLength(position); |
|
|
|
buffer.setLength(position); |
|
|
|
|
|
|
|
startLine = storedLine; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -278,11 +277,8 @@ public class ClassWriter { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) { |
|
|
|
private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) { |
|
|
|
String lineSeparator = DecompilerContext.getNewLineSeparator(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (node.type == ClassNode.CLASS_ANONYMOUS) { |
|
|
|
if (node.type == ClassNode.CLASS_ANONYMOUS) { |
|
|
|
buffer.append(" {"); |
|
|
|
buffer.append(" {").appendLineSeparator(); |
|
|
|
buffer.append(lineSeparator); |
|
|
|
|
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -297,19 +293,19 @@ public class ClassWriter { |
|
|
|
boolean isAnnotation = (flags & CodeConstants.ACC_ANNOTATION) != 0; |
|
|
|
boolean isAnnotation = (flags & CodeConstants.ACC_ANNOTATION) != 0; |
|
|
|
|
|
|
|
|
|
|
|
if (isDeprecated) { |
|
|
|
if (isDeprecated) { |
|
|
|
appendDeprecation(buffer, indent, lineSeparator); |
|
|
|
appendDeprecation(buffer, indent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (interceptor != null) { |
|
|
|
if (interceptor != null) { |
|
|
|
String oldName = interceptor.getOldName(cl.qualifiedName); |
|
|
|
String oldName = interceptor.getOldName(cl.qualifiedName); |
|
|
|
appendRenameComment(buffer, oldName, MType.CLASS, indent, lineSeparator); |
|
|
|
appendRenameComment(buffer, oldName, MType.CLASS, indent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (isSynthetic) { |
|
|
|
if (isSynthetic) { |
|
|
|
appendComment(buffer, "synthetic class", indent, lineSeparator); |
|
|
|
appendComment(buffer, "synthetic class", indent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
appendAnnotations(buffer, cl, indent, lineSeparator); |
|
|
|
appendAnnotations(buffer, cl, indent); |
|
|
|
|
|
|
|
|
|
|
|
buffer.appendIndent(indent); |
|
|
|
buffer.appendIndent(indent); |
|
|
|
|
|
|
|
|
|
|
@ -383,31 +379,28 @@ public class ClassWriter { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
buffer.append('{'); |
|
|
|
buffer.append('{').appendLineSeparator(); |
|
|
|
buffer.append(lineSeparator); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) { |
|
|
|
private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) { |
|
|
|
String lineSeparator = DecompilerContext.getNewLineSeparator(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE); |
|
|
|
boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE); |
|
|
|
boolean isDeprecated = fd.getAttributes().containsKey("Deprecated"); |
|
|
|
boolean isDeprecated = fd.getAttributes().containsKey("Deprecated"); |
|
|
|
boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); |
|
|
|
boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); |
|
|
|
|
|
|
|
|
|
|
|
if (isDeprecated) { |
|
|
|
if (isDeprecated) { |
|
|
|
appendDeprecation(buffer, indent, lineSeparator); |
|
|
|
appendDeprecation(buffer, indent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (interceptor != null) { |
|
|
|
if (interceptor != null) { |
|
|
|
String oldName = interceptor.getOldName(cl.qualifiedName + " " + fd.getName() + " " + fd.getDescriptor()); |
|
|
|
String oldName = interceptor.getOldName(cl.qualifiedName + " " + fd.getName() + " " + fd.getDescriptor()); |
|
|
|
appendRenameComment(buffer, oldName, MType.FIELD, indent, lineSeparator); |
|
|
|
appendRenameComment(buffer, oldName, MType.FIELD, indent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (fd.isSynthetic()) { |
|
|
|
if (fd.isSynthetic()) { |
|
|
|
appendComment(buffer, "synthetic field", indent, lineSeparator); |
|
|
|
appendComment(buffer, "synthetic field", indent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
appendAnnotations(buffer, fd, indent, lineSeparator); |
|
|
|
appendAnnotations(buffer, fd, indent); |
|
|
|
|
|
|
|
|
|
|
|
buffer.appendIndent(indent); |
|
|
|
buffer.appendIndent(indent); |
|
|
|
|
|
|
|
|
|
|
@ -467,8 +460,7 @@ public class ClassWriter { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!isEnum) { |
|
|
|
if (!isEnum) { |
|
|
|
buffer.append(";"); |
|
|
|
buffer.append(";").appendLineSeparator(); |
|
|
|
buffer.append(lineSeparator); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -523,8 +515,7 @@ public class ClassWriter { |
|
|
|
index += md_content.params[i].stack_size; |
|
|
|
index += md_content.params[i].stack_size; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
buffer.append(") {"); |
|
|
|
buffer.append(") {").appendLineSeparator(); |
|
|
|
buffer.append(DecompilerContext.getNewLineSeparator()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
indent += 1; |
|
|
|
indent += 1; |
|
|
|
} |
|
|
|
} |
|
|
@ -545,7 +536,7 @@ public class ClassWriter { |
|
|
|
if (methodWrapper.decompiledWithErrors) { |
|
|
|
if (methodWrapper.decompiledWithErrors) { |
|
|
|
buffer.appendIndent(indent); |
|
|
|
buffer.appendIndent(indent); |
|
|
|
buffer.append("// $FF: Couldn't be decompiled"); |
|
|
|
buffer.append("// $FF: Couldn't be decompiled"); |
|
|
|
buffer.append(DecompilerContext.getNewLineSeparator()); |
|
|
|
buffer.appendLineSeparator(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!codeOnly) { |
|
|
|
if (!codeOnly) { |
|
|
@ -553,7 +544,7 @@ public class ClassWriter { |
|
|
|
|
|
|
|
|
|
|
|
buffer.appendIndent(indent); |
|
|
|
buffer.appendIndent(indent); |
|
|
|
buffer.append('}'); |
|
|
|
buffer.append('}'); |
|
|
|
buffer.append(DecompilerContext.getNewLineSeparator()); |
|
|
|
buffer.appendLineSeparator(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
finally { |
|
|
|
finally { |
|
|
@ -569,8 +560,6 @@ public class ClassWriter { |
|
|
|
boolean hideMethod = false; |
|
|
|
boolean hideMethod = false; |
|
|
|
int start_index_method = buffer.length(); |
|
|
|
int start_index_method = buffer.length(); |
|
|
|
|
|
|
|
|
|
|
|
String lineSeparator = DecompilerContext.getNewLineSeparator(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MethodWrapper outerWrapper = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER); |
|
|
|
MethodWrapper outerWrapper = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER); |
|
|
|
DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_WRAPPER, methodWrapper); |
|
|
|
DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_WRAPPER, methodWrapper); |
|
|
|
|
|
|
|
|
|
|
@ -596,24 +585,24 @@ public class ClassWriter { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (isDeprecated) { |
|
|
|
if (isDeprecated) { |
|
|
|
appendDeprecation(buffer, indent, lineSeparator); |
|
|
|
appendDeprecation(buffer, indent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (interceptor != null) { |
|
|
|
if (interceptor != null) { |
|
|
|
String oldName = interceptor.getOldName(cl.qualifiedName + " " + mt.getName() + " " + mt.getDescriptor()); |
|
|
|
String oldName = interceptor.getOldName(cl.qualifiedName + " " + mt.getName() + " " + mt.getDescriptor()); |
|
|
|
appendRenameComment(buffer, oldName, MType.METHOD, indent, lineSeparator); |
|
|
|
appendRenameComment(buffer, oldName, MType.METHOD, indent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || mt.getAttributes().containsKey("Synthetic"); |
|
|
|
boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || mt.getAttributes().containsKey("Synthetic"); |
|
|
|
boolean isBridge = (flags & CodeConstants.ACC_BRIDGE) != 0; |
|
|
|
boolean isBridge = (flags & CodeConstants.ACC_BRIDGE) != 0; |
|
|
|
if (isSynthetic) { |
|
|
|
if (isSynthetic) { |
|
|
|
appendComment(buffer, "synthetic method", indent, lineSeparator); |
|
|
|
appendComment(buffer, "synthetic method", indent); |
|
|
|
} |
|
|
|
} |
|
|
|
if (isBridge) { |
|
|
|
if (isBridge) { |
|
|
|
appendComment(buffer, "bridge method", indent, lineSeparator); |
|
|
|
appendComment(buffer, "bridge method", indent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
appendAnnotations(buffer, mt, indent, lineSeparator); |
|
|
|
appendAnnotations(buffer, mt, indent); |
|
|
|
|
|
|
|
|
|
|
|
buffer.appendIndent(indent); |
|
|
|
buffer.appendIndent(indent); |
|
|
|
|
|
|
|
|
|
|
@ -831,10 +820,12 @@ public class ClassWriter { |
|
|
|
if (methodWrapper.decompiledWithErrors) { |
|
|
|
if (methodWrapper.decompiledWithErrors) { |
|
|
|
buffer.appendIndent(indent + 1); |
|
|
|
buffer.appendIndent(indent + 1); |
|
|
|
buffer.append("// $FF: Couldn't be decompiled"); |
|
|
|
buffer.append("// $FF: Couldn't be decompiled"); |
|
|
|
buffer.append(lineSeparator); |
|
|
|
buffer.appendLineSeparator(); |
|
|
|
|
|
|
|
tracer.incrementCurrentSourceLine(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
buffer.appendIndent(indent).append('}').appendLineSeparator(); |
|
|
|
buffer.appendIndent(indent).append('}').appendLineSeparator(); |
|
|
|
|
|
|
|
tracer.incrementCurrentSourceLine(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
finally { |
|
|
|
finally { |
|
|
@ -897,13 +888,13 @@ public class ClassWriter { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static void appendDeprecation(TextBuffer buffer, int indent, String lineSeparator) { |
|
|
|
private static void appendDeprecation(TextBuffer buffer, int indent) { |
|
|
|
buffer.appendIndent(indent).append("/** @deprecated */").append(lineSeparator); |
|
|
|
buffer.appendIndent(indent).append("/** @deprecated */").appendLineSeparator(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private enum MType {CLASS, FIELD, METHOD} |
|
|
|
private enum MType {CLASS, FIELD, METHOD} |
|
|
|
|
|
|
|
|
|
|
|
private static void appendRenameComment(TextBuffer buffer, String oldName, MType type, int indent, String lineSeparator) { |
|
|
|
private static void appendRenameComment(TextBuffer buffer, String oldName, MType type, int indent) { |
|
|
|
if (oldName == null) return; |
|
|
|
if (oldName == null) return; |
|
|
|
|
|
|
|
|
|
|
|
buffer.appendIndent(indent); |
|
|
|
buffer.appendIndent(indent); |
|
|
@ -939,7 +930,7 @@ public class ClassWriter { |
|
|
|
buffer.append(getTypePrintOut(md.ret)); |
|
|
|
buffer.append(getTypePrintOut(md.ret)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
buffer.append(lineSeparator); |
|
|
|
buffer.appendLineSeparator(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static String getTypePrintOut(VarType type) { |
|
|
|
private static String getTypePrintOut(VarType type) { |
|
|
@ -951,14 +942,14 @@ public class ClassWriter { |
|
|
|
return typeText; |
|
|
|
return typeText; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static void appendComment(TextBuffer buffer, String comment, int indent, String lineSeparator) { |
|
|
|
private static void appendComment(TextBuffer buffer, String comment, int indent) { |
|
|
|
buffer.appendIndent(indent).append("// $FF: ").append(comment).append(lineSeparator); |
|
|
|
buffer.appendIndent(indent).append("// $FF: ").append(comment).appendLineSeparator(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static final String[] ANNOTATION_ATTRIBUTES = { |
|
|
|
private static final String[] ANNOTATION_ATTRIBUTES = { |
|
|
|
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS}; |
|
|
|
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS}; |
|
|
|
|
|
|
|
|
|
|
|
private static void appendAnnotations(TextBuffer buffer, StructMember mb, int indent, String lineSeparator) { |
|
|
|
private static void appendAnnotations(TextBuffer buffer, StructMember mb, int indent) { |
|
|
|
|
|
|
|
|
|
|
|
BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
|
|
|
|
BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
|
|
|
|
|
|
|
|
|
|
|
@ -966,7 +957,7 @@ public class ClassWriter { |
|
|
|
StructAnnotationAttribute attribute = (StructAnnotationAttribute)mb.getAttributes().getWithKey(name); |
|
|
|
StructAnnotationAttribute attribute = (StructAnnotationAttribute)mb.getAttributes().getWithKey(name); |
|
|
|
if (attribute != null) { |
|
|
|
if (attribute != null) { |
|
|
|
for (AnnotationExprent annotation : attribute.getAnnotations()) { |
|
|
|
for (AnnotationExprent annotation : attribute.getAnnotations()) { |
|
|
|
buffer.append(annotation.toJava(indent, tracer_dummy)).append(lineSeparator); |
|
|
|
buffer.append(annotation.toJava(indent, tracer_dummy)).appendLineSeparator(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|