/// <exception cref="System.IO.IOException"/> public virtual void WriteClass(StructClass cl, TextBuffer buffer) { ClassesProcessor.ClassNode root = mapRootClasses.GetOrNull(cl.qualifiedName); if (root.type != ClassesProcessor.ClassNode.Class_Root) { return; } DecompilerContext.GetLogger().StartReadingClass(cl.qualifiedName); try { ImportCollector importCollector = new ImportCollector(root); DecompilerContext.StartClass(importCollector); new LambdaProcessor().ProcessClass(root); // add simple class names to implicit import AddClassnameToImport(root, importCollector); // build wrappers for all nested classes (that's where actual processing takes place) InitWrappers(root); new NestedClassProcessor().ProcessClass(root, root); new NestedMemberAccess().PropagateMemberAccess(root); TextBuffer classBuffer = new TextBuffer(Average_Class_Size); new ClassWriter().ClassToJava(root, classBuffer, 0, null); int index = cl.qualifiedName.LastIndexOf("/"); if (index >= 0) { string packageName = Sharpen.Runtime.Substring(cl.qualifiedName, 0, index).Replace ('/', '.'); buffer.Append("package "); buffer.Append(packageName); buffer.Append(";"); buffer.AppendLineSeparator(); buffer.AppendLineSeparator(); } int import_lines_written = importCollector.WriteImports(buffer); if (import_lines_written > 0) { buffer.AppendLineSeparator(); } int offsetLines = buffer.CountLines(); buffer.Append(classBuffer); if (DecompilerContext.GetOption(IFernflowerPreferences.Bytecode_Source_Mapping)) { BytecodeSourceMapper mapper = DecompilerContext.GetBytecodeSourceMapper(); mapper.AddTotalOffset(offsetLines); if (DecompilerContext.GetOption(IFernflowerPreferences.Dump_Original_Lines)) { buffer.DumpOriginalLineNumbers(mapper.GetOriginalLinesMapping()); } if (DecompilerContext.GetOption(IFernflowerPreferences.Unit_Test_Mode)) { buffer.AppendLineSeparator(); mapper.DumpMapping(buffer, true); } } } finally { DestroyWrappers(root); DecompilerContext.GetLogger().EndReadingClass(); } }
public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buf = new TextBuffer(); bool islabeled = IsLabeled(); buf.Append(ExprProcessor.ListToJava(varDefinitions, indent, tracer)); if (islabeled) { buf.AppendIndent(indent++).Append("label").Append(this.id.ToString()).Append(": {" ).AppendLineSeparator(); tracer.IncrementCurrentSourceLine(); } bool notempty = false; for (int i = 0; i < stats.Count; i++) { Statement st = stats[i]; if (i > 0 && notempty) { buf.AppendLineSeparator(); tracer.IncrementCurrentSourceLine(); } TextBuffer str = ExprProcessor.JmpWrapper(st, indent, false, tracer); buf.Append(str); notempty = !str.ContainsOnlyWhitespaces(); } if (islabeled) { buf.AppendIndent(indent - 1).Append("}").AppendLineSeparator(); tracer.IncrementCurrentSourceLine(); } return(buf); }
public virtual void DumpMapping(TextBuffer buffer, bool offsetsToHex) { if ((mapping.Count == 0) && (linesMapping.Count == 0)) { return; } string lineSeparator = DecompilerContext.GetNewLineSeparator(); foreach (KeyValuePair <string, Dictionary <string, Dictionary <int, int> > > class_entry in mapping) { Dictionary <string, Dictionary <int, int> > class_mapping = class_entry.Value; buffer.Append("class '" + class_entry.Key + "' {" + lineSeparator); bool is_first_method = true; foreach (KeyValuePair <string, Dictionary <int, int> > method_entry in class_mapping) { Dictionary <int, int> method_mapping = method_entry.Value; if (!is_first_method) { buffer.AppendLineSeparator(); } buffer.AppendIndent(1).Append("method '" + method_entry.Key + "' {" + lineSeparator ); List <int> lstBytecodeOffsets = new List <int>(method_mapping.Keys); lstBytecodeOffsets.Sort(); foreach (int offset in lstBytecodeOffsets) { int? line = method_mapping.GetOrNullable(offset); string strOffset = offsetsToHex ? Sharpen.Runtime.ToHexString(offset) : line.ToString(); buffer.AppendIndent(2).Append(strOffset).AppendIndent(2).Append((line.Value + offset_total ) + lineSeparator); } buffer.AppendIndent(1).Append("}").AppendLineSeparator(); is_first_method = false; } buffer.Append("}").AppendLineSeparator().AppendLineSeparator(); } // lines mapping buffer.Append("Lines mapping:").AppendLineSeparator(); IDictionary <int, int> sorted = new SortedDictionary <int, int>(linesMapping); foreach (KeyValuePair <int, int> entry in sorted) { buffer.Append(entry.Key).Append(" <-> ").Append(entry.Value + offset_total + 1).AppendLineSeparator (); } if (!(unmappedLines.Count == 0)) { buffer.Append("Not mapped:").AppendLineSeparator(); foreach (int line in unmappedLines) { if (!linesMapping.ContainsKey(line)) { buffer.Append(line).AppendLineSeparator(); } } } }
public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buf = new TextBuffer(); buf.Append(ExprProcessor.ListToJava(varDefinitions, indent, tracer)); if (IsLabeled()) { buf.AppendIndent(indent).Append("label").Append(this.id.ToString()).Append(":").AppendLineSeparator (); tracer.IncrementCurrentSourceLine(); } buf.AppendIndent(indent).Append("try {").AppendLineSeparator(); tracer.IncrementCurrentSourceLine(); buf.Append(ExprProcessor.JmpWrapper(first, indent + 1, true, tracer)); buf.AppendIndent(indent).Append("}"); for (int i = 1; i < stats.Count; i++) { Statement stat = stats[i]; // map first instruction storing the exception to the catch statement BasicBlock block = stat.GetBasichead().GetBlock(); if (!block.GetSeq().IsEmpty() && block.GetInstruction(0).opcode == ICodeConstants .opc_astore) { int offset = block.GetOldOffset(0); if (offset > -1) { tracer.AddMapping(offset); } } buf.Append(" catch ("); List <string> exception_types = exctstrings[i - 1]; if (exception_types.Count > 1) { // multi-catch, Java 7 style for (int exc_index = 1; exc_index < exception_types.Count; ++exc_index) { VarType exc_type = new VarType(ICodeConstants.Type_Object, 0, exception_types[exc_index ]); string exc_type_name = ExprProcessor.GetCastTypeName(exc_type); buf.Append(exc_type_name).Append(" | "); } } buf.Append(vars[i - 1].ToJava(indent, tracer)); buf.Append(") {").AppendLineSeparator(); tracer.IncrementCurrentSourceLine(); buf.Append(ExprProcessor.JmpWrapper(stat, indent + 1, false, tracer)).AppendIndent (indent).Append("}"); } buf.AppendLineSeparator(); tracer.IncrementCurrentSourceLine(); return(buf); }
public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buffer = new TextBuffer(); buffer.AppendIndent(indent); buffer.Append('@'); buffer.Append(DecompilerContext.GetImportCollector().GetShortName(ExprProcessor.BuildJavaClassName (className))); int type = GetAnnotationType(); if (type != Annotation_Marker) { buffer.Append('('); bool oneLiner = type == Annotation_Single_Element || indent < 0; for (int i = 0; i < parNames.Count; i++) { if (!oneLiner) { buffer.AppendLineSeparator().AppendIndent(indent + 1); } if (type != Annotation_Single_Element) { buffer.Append(parNames[i]); buffer.Append(" = "); } buffer.Append(parValues[i].ToJava(0, tracer)); if (i < parNames.Count - 1) { buffer.Append(','); } } if (!oneLiner) { buffer.AppendLineSeparator().AppendIndent(indent); } buffer.Append(')'); } return(buffer); }
public virtual int WriteImports(TextBuffer buffer) { int importLinesWritten = 0; List <string> imports = PackImports(); foreach (string s in imports) { buffer.Append("import "); buffer.Append(s); buffer.Append(';'); buffer.AppendLineSeparator(); importLinesWritten++; } return(importLinesWritten); }