private static void ExtractStaticInitializers(ClassWrapper wrapper, MethodWrapper method) { RootStatement root = method.root; StructClass cl = wrapper.GetClassStruct(); Statement firstData = Statements.FindFirstData(root); if (firstData != null) { bool inlineInitializers = cl.HasModifier(ICodeConstants.Acc_Interface) || cl.HasModifier (ICodeConstants.Acc_Enum); while (!(firstData.GetExprents().Count == 0)) { Exprent exprent = firstData.GetExprents()[0]; bool found = false; if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent assignExpr = (AssignmentExprent)exprent; if (assignExpr.GetLeft().type == Exprent.Exprent_Field) { FieldExprent fExpr = (FieldExprent)assignExpr.GetLeft(); if (fExpr.IsStatic() && fExpr.GetClassname().Equals(cl.qualifiedName) && cl.HasField (fExpr.GetName(), fExpr.GetDescriptor().descriptorString)) { // interfaces fields should always be initialized inline if (inlineInitializers || IsExprentIndependent(assignExpr.GetRight(), method)) { string keyField = InterpreterUtil.MakeUniqueKey(fExpr.GetName(), fExpr.GetDescriptor ().descriptorString); if (!wrapper.GetStaticFieldInitializers().ContainsKey(keyField)) { wrapper.GetStaticFieldInitializers().AddWithKey(assignExpr.GetRight(), keyField); firstData.GetExprents().RemoveAtReturningValue(0); found = true; } } } } } if (!found) { break; } } } }
private void BuildInheritanceTree() { Dictionary <string, ClassWrapperNode> nodes = new Dictionary <string, ClassWrapperNode >(); Dictionary <string, StructClass> classes = context.GetClasses(); List <ClassWrapperNode> rootClasses = new List <ClassWrapperNode>(); List <ClassWrapperNode> rootInterfaces = new List <ClassWrapperNode>(); foreach (StructClass cl in classes.Values) { if (!cl.IsOwn()) { continue; } LinkedList <StructClass> stack = new LinkedList <StructClass>(); LinkedList <ClassWrapperNode> stackSubNodes = new LinkedList <ClassWrapperNode>(); stack.AddLast(cl); stackSubNodes.AddLast((ClassWrapperNode)null); while (!(stack.Count == 0)) { StructClass clStr = Sharpen.Collections.RemoveFirst(stack); ClassWrapperNode child = Sharpen.Collections.RemoveFirst(stackSubNodes); ClassWrapperNode node = nodes.GetOrNull(clStr.qualifiedName); bool isNewNode = (node == null); if (isNewNode) { Sharpen.Collections.Put(nodes, clStr.qualifiedName, node = new ClassWrapperNode(clStr )); } if (child != null) { node.AddSubclass(child); } if (!isNewNode) { break; } else { bool isInterface = clStr.HasModifier(ICodeConstants.Acc_Interface); bool found_parent = false; if (isInterface) { foreach (string ifName in clStr.GetInterfaceNames()) { StructClass clParent = classes.GetOrNull(ifName); if (clParent != null) { stack.AddLast(clParent); stackSubNodes.AddLast(node); found_parent = true; } } } else if (clStr.superClass != null) { // null iff java/lang/Object StructClass clParent = classes.GetOrNull(clStr.superClass.GetString()); if (clParent != null) { stack.AddLast(clParent); stackSubNodes.AddLast(node); found_parent = true; } } if (!found_parent) { // no super class or interface (isInterface ? rootInterfaces : rootClasses).Add(node); } } } } this.rootClasses = rootClasses; this.rootInterfaces = rootInterfaces; }
public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buf = new TextBuffer(); string super_qualifier = null; bool isInstanceThis = false; tracer.AddMapping(bytecode); if (instance is InvocationExprent) { ((InvocationExprent)instance).MarkUsingBoxingResult(); } if (isStatic__) { if (IsBoxingCall() && canIgnoreBoxing) { // process general "boxing" calls, e.g. 'Object[] data = { true }' or 'Byte b = 123' // here 'byte' and 'short' values do not need an explicit narrowing type cast ExprProcessor.GetCastedExprent(lstParameters[0], descriptor.@params[0], buf, indent , false, false, false, false, tracer); return(buf); } ClassesProcessor.ClassNode node = (ClassesProcessor.ClassNode)DecompilerContext.GetProperty (DecompilerContext.Current_Class_Node); if (node == null || !classname.Equals(node.classStruct.qualifiedName)) { buf.Append(DecompilerContext.GetImportCollector().GetShortNameInClassContext(ExprProcessor .BuildJavaClassName(classname))); } } else { if (instance != null && instance.type == Exprent.Exprent_Var) { VarExprent instVar = (VarExprent)instance; VarVersionPair varPair = new VarVersionPair(instVar); VarProcessor varProc = instVar.GetProcessor(); if (varProc == null) { MethodWrapper currentMethod = (MethodWrapper)DecompilerContext.GetProperty(DecompilerContext .Current_Method_Wrapper); if (currentMethod != null) { varProc = currentMethod.varproc; } } string this_classname = null; if (varProc != null) { this_classname = varProc.GetThisVars().GetOrNull(varPair); } if (this_classname != null) { isInstanceThis = true; if (invocationTyp == Invoke_Special) { if (!classname.Equals(this_classname)) { // TODO: direct comparison to the super class? StructClass cl = DecompilerContext.GetStructContext().GetClass(classname); bool isInterface = cl != null && cl.HasModifier(ICodeConstants.Acc_Interface); super_qualifier = !isInterface ? this_classname : classname; } } } } if (functype == Typ_General) { if (super_qualifier != null) { TextUtil.WriteQualifiedSuper(buf, super_qualifier); } else if (instance != null) { TextBuffer res = instance.ToJava(indent, tracer); if (IsUnboxingCall()) { // we don't print the unboxing call - no need to bother with the instance wrapping / casting buf.Append(res); return(buf); } VarType rightType = instance.GetExprType(); VarType leftType = new VarType(ICodeConstants.Type_Object, 0, classname); if (rightType.Equals(VarType.Vartype_Object) && !leftType.Equals(rightType)) { buf.Append("((").Append(ExprProcessor.GetCastTypeName(leftType)).Append(")"); if (instance.GetPrecedence() >= FunctionExprent.GetPrecedence(FunctionExprent.Function_Cast )) { res.Enclose("(", ")"); } buf.Append(res).Append(")"); } else if (instance.GetPrecedence() > GetPrecedence()) { buf.Append("(").Append(res).Append(")"); } else { buf.Append(res); } } } } switch (functype) { case Typ_General: { if (VarExprent.Var_Nameless_Enclosure.Equals(buf.ToString())) { buf = new TextBuffer(); } if (buf.Length() > 0) { buf.Append("."); } buf.Append(name); if (invocationTyp == Invoke_Dynamic) { buf.Append("<invokedynamic>"); } buf.Append("("); break; } case Typ_Clinit: { throw new Exception("Explicit invocation of " + ICodeConstants.Clinit_Name); } case Typ_Init: { if (super_qualifier != null) { buf.Append("super("); } else if (isInstanceThis) { buf.Append("this("); } else if (instance != null) { buf.Append(instance.ToJava(indent, tracer)).Append(".<init>("); } else { throw new Exception("Unrecognized invocation of " + ICodeConstants.Init_Name); } break; } } List <VarVersionPair> mask = null; bool isEnum = false; if (functype == Typ_Init) { ClassesProcessor.ClassNode newNode = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(classname); if (newNode != null) { mask = ExprUtil.GetSyntheticParametersMask(newNode, stringDescriptor, lstParameters .Count); isEnum = newNode.classStruct.HasModifier(ICodeConstants.Acc_Enum) && DecompilerContext .GetOption(IFernflowerPreferences.Decompile_Enum); } } BitSet setAmbiguousParameters = GetAmbiguousParameters(); // omit 'new Type[] {}' for the last parameter of a vararg method call if (lstParameters.Count == [email protected] && IsVarArgCall()) { Exprent lastParam = lstParameters[lstParameters.Count - 1]; if (lastParam.type == Exprent_New && lastParam.GetExprType().arrayDim >= 1) { ((NewExprent)lastParam).SetVarArgParam(true); } } bool firstParameter = true; int start = isEnum ? 2 : 0; for (int i = start; i < lstParameters.Count; i++) { if (mask == null || mask[i] == null) { TextBuffer buff = new TextBuffer(); bool ambiguous = setAmbiguousParameters.Get(i); // 'byte' and 'short' literals need an explicit narrowing type cast when used as a parameter ExprProcessor.GetCastedExprent(lstParameters[i], descriptor.@params[i], buff, indent , true, ambiguous, true, true, tracer); // the last "new Object[0]" in the vararg call is not printed if (buff.Length() > 0) { if (!firstParameter) { buf.Append(", "); } buf.Append(buff); } firstParameter = false; } } buf.Append(')'); return(buf); }