private bool ReplaceInvocations(ClassesProcessor.ClassNode caller, MethodWrapper
                                        meth, Exprent exprent)
        {
            bool res = false;

            foreach (Exprent expr in exprent.GetAllExprents())
            {
                res |= ReplaceInvocations(caller, meth, expr);
            }
            while (true)
            {
                bool found = false;
                foreach (Exprent expr in exprent.GetAllExprents())
                {
                    if (expr.type == Exprent.Exprent_Invocation)
                    {
                        Exprent newexpr = ReplaceAccessExprent(caller, meth, (InvocationExprent)expr);
                        if (newexpr != null)
                        {
                            exprent.ReplaceExprent(expr, newexpr);
                            found = true;
                            res   = true;
                            break;
                        }
                    }
                }
                if (!found)
                {
                    break;
                }
            }
            return(res);
        }
Beispiel #2
0
 private static bool IsQualifiedNewGetClass(Exprent first, Exprent second)
 {
     if (first.type == Exprent.Exprent_Invocation)
     {
         InvocationExprent invocation = (InvocationExprent)first;
         if (!invocation.IsStatic() && invocation.GetInstance().type == Exprent.Exprent_Var &&
             invocation.GetName().Equals("getClass") && invocation.GetStringDescriptor().
             Equals("()Ljava/lang/Class;"))
         {
             List <Exprent> lstExprents = second.GetAllExprents();
             lstExprents.Add(second);
             foreach (Exprent expr in lstExprents)
             {
                 if (expr.type == Exprent.Exprent_New)
                 {
                     NewExprent newExpr = (NewExprent)expr;
                     if (newExpr.GetConstructor() != null && !(newExpr.GetConstructor().GetLstParameters
                                                                   ().Count == 0) && newExpr.GetConstructor().GetLstParameters()[0].Equals(invocation
                                                                                                                                           .GetInstance()))
                     {
                         string classname = newExpr.GetNewType().value;
                         ClassesProcessor.ClassNode node = DecompilerContext.GetClassProcessor().GetMapRootClasses
                                                               ().GetOrNull(classname);
                         if (node != null && node.type != ClassesProcessor.ClassNode.Class_Root)
                         {
                             return(true);
                         }
                     }
                 }
             }
         }
     }
     return(false);
 }
Beispiel #3
0
        public static List <VarVersionPair> GetSyntheticParametersMask(ClassesProcessor.ClassNode
                                                                       node, string descriptor, int parameters)
        {
            List <VarVersionPair> mask    = null;
            ClassWrapper          wrapper = node.GetWrapper();

            if (wrapper != null)
            {
                // own class
                MethodWrapper methodWrapper = wrapper.GetMethodWrapper(ICodeConstants.Init_Name,
                                                                       descriptor);
                if (methodWrapper == null)
                {
                    if (DecompilerContext.GetOption(IFernflowerPreferences.Ignore_Invalid_Bytecode))
                    {
                        return(null);
                    }
                    throw new Exception("Constructor " + node.classStruct.qualifiedName + "." + ICodeConstants
                                        .Init_Name + descriptor + " not found");
                }
                mask = methodWrapper.synthParameters;
            }
            else if (parameters > 0 && node.type == ClassesProcessor.ClassNode.Class_Member &&
                     (node.access & ICodeConstants.Acc_Static) == 0)
            {
                // non-static member class
                mask    = new List <VarVersionPair>(Enumerable.Repeat <VarVersionPair>(null, parameters));
                mask[0] = new VarVersionPair(-1, 0);
            }
            return(mask);
        }
Beispiel #4
0
        private static Exprent IsLambda(Exprent exprent, StructClass cl)
        {
            List <Exprent> lst = exprent.GetAllExprents();

            foreach (Exprent expr in lst)
            {
                Exprent ret = IsLambda(expr, cl);
                if (ret != null)
                {
                    exprent.ReplaceExprent(expr, ret);
                }
            }
            if (exprent.type == Exprent.Exprent_Invocation)
            {
                InvocationExprent @in = (InvocationExprent)exprent;
                if (@in.GetInvocationTyp() == InvocationExprent.Invoke_Dynamic)
                {
                    string lambda_class_name = cl.qualifiedName + @in.GetInvokeDynamicClassSuffix();
                    ClassesProcessor.ClassNode lambda_class = DecompilerContext.GetClassProcessor().GetMapRootClasses
                                                                  ().GetOrNull(lambda_class_name);
                    if (lambda_class != null)
                    {
                        // real lambda class found, replace invocation with an anonymous class
                        NewExprent newExpr = new NewExprent(new VarType(lambda_class_name, true), null, 0
                                                            , @in.bytecode);
                        newExpr.SetConstructor(@in);
                        // note: we don't set the instance to null with in.setInstance(null) like it is done for a common constructor invocation
                        // lambda can also be a reference to a virtual method (e.g. String x; ...(x::toString);)
                        // in this case instance will hold the corresponding object
                        return(newExpr);
                    }
                }
            }
            return(null);
        }
Beispiel #5
0
        public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer)
        {
            TextBuffer buffer = new TextBuffer();

            tracer.AddMapping(bytecode);
            if (classDef)
            {
                ClassesProcessor.ClassNode child = DecompilerContext.GetClassProcessor().GetMapRootClasses
                                                       ().GetOrNull(varType.value);
                new ClassWriter().ClassToJava(child, buffer, indent, tracer);
                tracer.IncrementCurrentSourceLine(buffer.CountLines());
            }
            else
            {
                VarVersionPair varVersion = GetVarVersionPair();
                string         name       = null;
                if (processor != null)
                {
                    name = processor.GetVarName(varVersion);
                }
                if (definition)
                {
                    if (processor != null && processor.GetVarFinal(varVersion) == VarTypeProcessor.Var_Explicit_Final)
                    {
                        buffer.Append("final ");
                    }
                    AppendDefinitionType(buffer);
                    buffer.Append(" ");
                }
                buffer.Append(name == null ? ("var" + index + (this.version == 0 ? string.Empty :
                                                               "_" + this.version)) : name);
            }
            return(buffer);
        }
Beispiel #6
0
 public static List <VarVersionPair> GetSyntheticParametersMask(string className,
                                                                string descriptor, int parameters)
 {
     ClassesProcessor.ClassNode node = DecompilerContext.GetClassProcessor().GetMapRootClasses
                                           ().GetOrNull(className);
     return(node != null?GetSyntheticParametersMask(node, descriptor, parameters) :
                null);
 }
Beispiel #7
0
        public ImportCollector(ClassesProcessor.ClassNode root)
        {
            // set of field names in this class and all its predecessors.
            string clName = root.classStruct.qualifiedName;
            int    index  = clName.LastIndexOf('/');

            if (index >= 0)
            {
                string packageName = Sharpen.Runtime.Substring(clName, 0, index);
                currentPackageSlash = packageName + '/';
                currentPackagePoint = packageName.Replace('/', '.');
            }
            else
            {
                currentPackageSlash = string.Empty;
                currentPackagePoint = string.Empty;
            }
            Dictionary <string, StructClass> classes = DecompilerContext.GetStructContext().GetClasses
                                                           ();
            LinkedList <string> queue        = new LinkedList <string>();
            StructClass         currentClass = root.classStruct;

            while (currentClass != null)
            {
                if (currentClass.superClass != null)
                {
                    queue.AddLast(currentClass.superClass.GetString());
                }
                Sharpen.Collections.AddAll(queue, currentClass.GetInterfaceNames());
                // all field names for the current class ..
                foreach (StructField f in currentClass.GetFields())
                {
                    setFieldNames.Add(f.GetName());
                }
                // .. all inner classes for the current class ..
                StructInnerClassesAttribute attribute = currentClass.GetAttribute(StructGeneralAttribute
                                                                                  .Attribute_Inner_Classes);
                if (attribute != null)
                {
                    foreach (StructInnerClassesAttribute.Entry entry in attribute.GetEntries())
                    {
                        if (entry.enclosingName != null && entry.enclosingName.Equals(currentClass.qualifiedName
                                                                                      ))
                        {
                            setInnerClassNames.Add(entry.simpleName);
                        }
                    }
                }
                // .. and traverse through parent.
                currentClass = !(queue.Count == 0) ? classes.GetOrNull(Sharpen.Collections.RemoveFirst
                                                                           (queue)) : null;
                while (currentClass == null && !(queue.Count == 0))
                {
                    currentClass = classes.GetOrNull(Sharpen.Collections.RemoveFirst(queue));
                }
            }
        }
 public virtual void PropagateMemberAccess(ClassesProcessor.ClassNode root)
 {
     if ((root.nested.Count == 0))
     {
         return;
     }
     noSynthFlag = DecompilerContext.GetOption(IFernflowerPreferences.Synthetic_Not_Set
                                               );
     ComputeMethodTypes(root);
     EliminateStaticAccess(root);
 }
Beispiel #9
0
 public static void WriteQualifiedSuper(TextBuffer buf, string qualifier)
 {
     ClassesProcessor.ClassNode classNode = (ClassesProcessor.ClassNode)DecompilerContext
                                            .GetProperty(DecompilerContext.Current_Class_Node);
     if (!qualifier.Equals(classNode.classStruct.qualifiedName))
     {
         buf.Append(DecompilerContext.GetImportCollector().GetShortName(ExprProcessor.BuildJavaClassName
                                                                            (qualifier))).Append('.');
     }
     buf.Append("super");
 }
Beispiel #10
0
 public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer)
 {
     tracer.AddMapping(bytecode);
     if (exitType == Exit_Return)
     {
         TextBuffer buffer = new TextBuffer("return");
         if (retType.type != ICodeConstants.Type_Void)
         {
             buffer.Append(' ');
             ExprProcessor.GetCastedExprent(value, retType, buffer, indent, false, tracer);
         }
         return(buffer);
     }
     else
     {
         MethodWrapper method = (MethodWrapper)DecompilerContext.GetProperty(DecompilerContext
                                                                             .Current_Method_Wrapper);
         ClassesProcessor.ClassNode node = ((ClassesProcessor.ClassNode)DecompilerContext.
                                            GetProperty(DecompilerContext.Current_Class_Node));
         if (method != null && node != null)
         {
             StructExceptionsAttribute attr = method.methodStruct.GetAttribute(StructGeneralAttribute
                                                                               .Attribute_Exceptions);
             if (attr != null)
             {
                 string classname = null;
                 for (int i = 0; i < attr.GetThrowsExceptions().Count; i++)
                 {
                     string exClassName = attr.GetExcClassname(i, node.classStruct.GetPool());
                     if ("java/lang/Throwable".Equals(exClassName))
                     {
                         classname = exClassName;
                         break;
                     }
                     else if ("java/lang/Exception".Equals(exClassName))
                     {
                         classname = exClassName;
                     }
                 }
                 if (classname != null)
                 {
                     VarType    exType = new VarType(classname, true);
                     TextBuffer buffer = new TextBuffer("throw ");
                     ExprProcessor.GetCastedExprent(value, exType, buffer, indent, false, tracer);
                     return(buffer);
                 }
             }
         }
         return(value.ToJava(indent, tracer).Prepend("throw "));
     }
 }
 private void EliminateStaticAccess(ClassesProcessor.ClassNode node)
 {
     if (node.type == ClassesProcessor.ClassNode.Class_Lambda)
     {
         return;
     }
     foreach (MethodWrapper meth in node.GetWrapper().GetMethods())
     {
         if (meth.root != null)
         {
             bool                    replaced   = false;
             DirectGraph             graph      = meth.GetOrBuildGraph();
             HashSet <DirectNode>    setVisited = new HashSet <DirectNode>();
             LinkedList <DirectNode> stack      = new LinkedList <DirectNode>();
             stack.AddLast(graph.first);
             while (!(stack.Count == 0))
             {
                 // TODO: replace with interface iterator?
                 DirectNode nd = Sharpen.Collections.RemoveFirst(stack);
                 if (setVisited.Contains(nd))
                 {
                     continue;
                 }
                 setVisited.Add(nd);
                 for (int i = 0; i < nd.exprents.Count; i++)
                 {
                     Exprent exprent = nd.exprents[i];
                     replaced |= ReplaceInvocations(node, meth, exprent);
                     if (exprent.type == Exprent.Exprent_Invocation)
                     {
                         Exprent ret = ReplaceAccessExprent(node, meth, (InvocationExprent)exprent);
                         if (ret != null)
                         {
                             nd.exprents[i] = ret;
                             replaced       = true;
                         }
                     }
                 }
                 Sharpen.Collections.AddAll(stack, nd.succs);
             }
             if (replaced)
             {
                 ComputeMethodType(node, meth);
             }
         }
     }
     foreach (ClassesProcessor.ClassNode child in node.nested)
     {
         EliminateStaticAccess(child);
     }
 }
 private void ComputeMethodTypes(ClassesProcessor.ClassNode node)
 {
     if (node.type == ClassesProcessor.ClassNode.Class_Lambda)
     {
         return;
     }
     foreach (ClassesProcessor.ClassNode nd in node.nested)
     {
         ComputeMethodTypes(nd);
     }
     foreach (MethodWrapper method in node.GetWrapper().GetMethods())
     {
         ComputeMethodType(node, method);
     }
 }
 private static bool SameTree(ClassesProcessor.ClassNode caller, ClassesProcessor.ClassNode
                              callee)
 {
     if (caller.classStruct.qualifiedName.Equals(callee.classStruct.qualifiedName))
     {
         return(false);
     }
     while (caller.parent != null)
     {
         caller = caller.parent;
     }
     while (callee.parent != null)
     {
         callee = callee.parent;
     }
     return(caller == callee);
 }
Beispiel #14
0
 private static string GetQualifiedNewInstance(string classname, List <Exprent> lstParams
                                               , int indent, BytecodeMappingTracer tracer)
 {
     ClassesProcessor.ClassNode node = DecompilerContext.GetClassProcessor().GetMapRootClasses
                                           ().GetOrNull(classname);
     if (node != null && node.type != ClassesProcessor.ClassNode.Class_Root && node.type
         != ClassesProcessor.ClassNode.Class_Local && (node.access & ICodeConstants.Acc_Static
                                                       ) == 0)
     {
         if (!(lstParams.Count == 0))
         {
             Exprent enclosing      = lstParams[0];
             bool    isQualifiedNew = false;
             if (enclosing.type == Exprent.Exprent_Var)
             {
                 VarExprent  varEnclosing  = (VarExprent)enclosing;
                 StructClass current_class = ((ClassesProcessor.ClassNode)DecompilerContext.GetProperty
                                                  (DecompilerContext.Current_Class_Node)).classStruct;
                 string this_classname = varEnclosing.GetProcessor().GetThisVars().GetOrNull(new VarVersionPair
                                                                                                 (varEnclosing));
                 if (!current_class.qualifiedName.Equals(this_classname))
                 {
                     isQualifiedNew = true;
                 }
             }
             else
             {
                 isQualifiedNew = true;
             }
             if (isQualifiedNew)
             {
                 return(enclosing.ToJava(indent, tracer).ToString());
             }
         }
     }
     return(null);
 }
Beispiel #15
0
 public NewExprent(VarType newType, List <Exprent> lstDims, HashSet <int> bytecodeOffsets
                   )
     : base(Exprent_New)
 {
     this.newType = newType;
     this.lstDims = lstDims;
     anonymous    = false;
     lambda       = false;
     if (newType.type == ICodeConstants.Type_Object && newType.arrayDim == 0)
     {
         ClassesProcessor.ClassNode node = DecompilerContext.GetClassProcessor().GetMapRootClasses
                                               ().GetOrNull(newType.value);
         if (node != null && (node.type == ClassesProcessor.ClassNode.Class_Anonymous || node
                              .type == ClassesProcessor.ClassNode.Class_Lambda))
         {
             anonymous = true;
             if (node.type == ClassesProcessor.ClassNode.Class_Lambda)
             {
                 lambda = true;
             }
         }
     }
     AddBytecodeOffsets(bytecodeOffsets);
 }
Beispiel #16
0
        /// <exception cref="IOException"/>
        public virtual void ProcessClass(ClassesProcessor.ClassNode node)
        {
            foreach (ClassesProcessor.ClassNode child in node.nested)
            {
                ProcessClass(child);
            }
            ClassesProcessor clProcessor = DecompilerContext.GetClassProcessor();
            StructClass      cl          = node.classStruct;

            if (cl.GetBytecodeVersion() < ICodeConstants.Bytecode_Java_8)
            {
                // lambda beginning with Java 8
                return;
            }
            StructBootstrapMethodsAttribute bootstrap = cl.GetAttribute(StructGeneralAttribute
                                                                        .Attribute_Bootstrap_Methods);

            if (bootstrap == null || bootstrap.GetMethodsNumber() == 0)
            {
                return;
            }
            // no bootstrap constants in pool
            BitSet lambda_methods = new BitSet();

            // find lambda bootstrap constants
            for (int i = 0; i < bootstrap.GetMethodsNumber(); ++i)
            {
                LinkConstant method_ref = bootstrap.GetMethodReference(i);
                // method handle
                // FIXME: extend for Eclipse etc. at some point
                if (Javac_Lambda_Class.Equals(method_ref.classname) && (Javac_Lambda_Method.Equals
                                                                            (method_ref.elementname) || Javac_Lambda_Alt_Method.Equals(method_ref.elementname
                                                                                                                                       )))
                {
                    lambda_methods.Set(i);
                }
            }
            if (lambda_methods.IsEmpty())
            {
                return;
            }
            // no lambda bootstrap constant found
            Dictionary <string, string> mapMethodsLambda = new Dictionary <string, string>();

            // iterate over code and find invocations of bootstrap methods. Replace them with anonymous classes.
            foreach (StructMethod mt in cl.GetMethods())
            {
                mt.ExpandData();
                InstructionSequence seq = mt.GetInstructionSequence();
                if (seq != null && seq.Length() > 0)
                {
                    int len = seq.Length();
                    for (int i = 0; i < len; ++i)
                    {
                        Instruction instr = seq.GetInstr(i);
                        if (instr.opcode == ICodeConstants.opc_invokedynamic)
                        {
                            LinkConstant invoke_dynamic = cl.GetPool().GetLinkConstant(instr.Operand(0));
                            if (lambda_methods.Get(invoke_dynamic.index1))
                            {
                                // lambda invocation found
                                List <PooledConstant> bootstrap_arguments = bootstrap.GetMethodArguments(invoke_dynamic
                                                                                                         .index1);
                                MethodDescriptor md = MethodDescriptor.ParseDescriptor(invoke_dynamic.descriptor);
                                string           lambda_class_name        = md.ret.value;
                                string           lambda_method_name       = invoke_dynamic.elementname;
                                string           lambda_method_descriptor = ((PrimitiveConstant)bootstrap_arguments[2]).GetString
                                                                                ();
                                // method type
                                LinkConstant content_method_handle     = (LinkConstant)bootstrap_arguments[1];
                                ClassesProcessor.ClassNode node_lambda = new ClassesProcessor.ClassNode(content_method_handle
                                                                                                        .classname, content_method_handle.elementname, content_method_handle.descriptor,
                                                                                                        content_method_handle.index1, lambda_class_name, lambda_method_name, lambda_method_descriptor
                                                                                                        , cl);
                                node_lambda.simpleName = cl.qualifiedName + "##Lambda_" + invoke_dynamic.index1 +
                                                         "_" + invoke_dynamic.index2;
                                node_lambda.enclosingMethod = InterpreterUtil.MakeUniqueKey(mt.GetName(), mt.GetDescriptor
                                                                                                ());
                                node.nested.Add(node_lambda);
                                node_lambda.parent = node;
                                Sharpen.Collections.Put(clProcessor.GetMapRootClasses(), node_lambda.simpleName,
                                                        node_lambda);
                                if (!node_lambda.lambdaInformation.is_method_reference)
                                {
                                    Sharpen.Collections.Put(mapMethodsLambda, node_lambda.lambdaInformation.content_method_key
                                                            , node_lambda.simpleName);
                                }
                            }
                        }
                    }
                }
                mt.ReleaseResources();
            }
            // build class hierarchy on lambda
            foreach (ClassesProcessor.ClassNode nd in node.nested)
            {
                if (nd.type == ClassesProcessor.ClassNode.Class_Lambda)
                {
                    string parent_class_name = mapMethodsLambda.GetOrNull(nd.enclosingMethod);
                    if (parent_class_name != null)
                    {
                        ClassesProcessor.ClassNode parent_class = clProcessor.GetMapRootClasses().GetOrNull
                                                                      (parent_class_name);
                        parent_class.nested.Add(nd);
                        nd.parent = parent_class;
                    }
                }
            }
        }
Beispiel #17
0
 private static bool ProbablySyntheticParameter(string className)
 {
     ClassesProcessor.ClassNode node = DecompilerContext.GetClassProcessor().GetMapRootClasses
                                           ().GetOrNull(className);
     return(node != null && node.type == ClassesProcessor.ClassNode.Class_Anonymous);
 }
Beispiel #18
0
        public static void Simplify(SwitchStatement switchStatement)
        {
            SwitchExprent switchExprent = (SwitchExprent)switchStatement.GetHeadexprent();
            Exprent       value         = switchExprent.GetValue();

            if (IsEnumArray(value))
            {
                List <List <Exprent> >        caseValues = switchStatement.GetCaseValues();
                Dictionary <Exprent, Exprent> mapping    = new Dictionary <Exprent, Exprent>(caseValues
                                                                                             .Count);
                ArrayExprent array      = (ArrayExprent)value;
                FieldExprent arrayField = (FieldExprent)array.GetArray();
                ClassesProcessor.ClassNode classNode = DecompilerContext.GetClassProcessor().GetMapRootClasses
                                                           ().GetOrNull(arrayField.GetClassname());
                if (classNode != null)
                {
                    MethodWrapper wrapper = classNode.GetWrapper().GetMethodWrapper(ICodeConstants.Clinit_Name
                                                                                    , "()V");
                    if (wrapper != null && wrapper.root != null)
                    {
                        wrapper.GetOrBuildGraph().IterateExprents((Exprent exprent) => {
                            if (exprent is AssignmentExprent)
                            {
                                AssignmentExprent assignment = (AssignmentExprent)exprent;
                                Exprent left = assignment.GetLeft();
                                if (left.type == Exprent.Exprent_Array && ((ArrayExprent)left).GetArray().Equals(
                                        arrayField))
                                {
                                    Sharpen.Collections.Put(mapping, assignment.GetRight(), ((InvocationExprent)((ArrayExprent
                                                                                                                  )left).GetIndex()).GetInstance());
                                }
                            }
                            return(0);
                        }
                                                                  );
                    }
                }
                List <List <Exprent> > realCaseValues = new List <List <Exprent> >(caseValues.Count);
                foreach (List <Exprent> caseValue in caseValues)
                {
                    List <Exprent> values = new List <Exprent>(caseValue.Count);
                    realCaseValues.Add(values);
                    foreach (Exprent exprent in caseValue)
                    {
                        if (exprent == null)
                        {
                            values.Add(null);
                        }
                        else
                        {
                            Exprent realConst = mapping.GetOrNull(exprent);
                            if (realConst == null)
                            {
                                DecompilerContext.GetLogger().WriteMessage("Unable to simplify switch on enum: "
                                                                           + exprent + " not found, available: " + mapping, IFernflowerLogger.Severity.Error
                                                                           );
                                return;
                            }
                            values.Add(realConst.Copy());
                        }
                    }
                }
                caseValues.Clear();
                Sharpen.Collections.AddAll(caseValues, realCaseValues);
                switchExprent.ReplaceExprent(value, ((InvocationExprent)array.GetIndex()).GetInstance
                                                 ().Copy());
            }
        }
Beispiel #19
0
        public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer)
        {
            TextBuffer buf = new TextBuffer();

            if (isStatic__)
            {
                ClassesProcessor.ClassNode node = (ClassesProcessor.ClassNode)DecompilerContext.GetProperty
                                                      (DecompilerContext.Current_Class_Node);
                if (node == null || !classname.Equals(node.classStruct.qualifiedName) || IsAmbiguous
                        ())
                {
                    buf.Append(DecompilerContext.GetImportCollector().GetShortNameInClassContext(ExprProcessor
                                                                                                 .BuildJavaClassName(classname)));
                    buf.Append(".");
                }
            }
            else
            {
                string super_qualifier = null;
                if (instance != null && instance.type == Exprent.Exprent_Var)
                {
                    VarExprent     instVar       = (VarExprent)instance;
                    VarVersionPair pair          = new VarVersionPair(instVar);
                    MethodWrapper  currentMethod = (MethodWrapper)DecompilerContext.GetProperty(DecompilerContext
                                                                                                .Current_Method_Wrapper);
                    if (currentMethod != null)
                    {
                        // FIXME: remove
                        string this_classname = currentMethod.varproc.GetThisVars().GetOrNull(pair);
                        if (this_classname != null)
                        {
                            if (!classname.Equals(this_classname))
                            {
                                // TODO: direct comparison to the super class?
                                super_qualifier = this_classname;
                            }
                        }
                    }
                }
                if (super_qualifier != null)
                {
                    TextUtil.WriteQualifiedSuper(buf, super_qualifier);
                }
                else
                {
                    TextBuffer buff   = new TextBuffer();
                    bool       casted = ExprProcessor.GetCastedExprent(instance, new VarType(ICodeConstants
                                                                                             .Type_Object, 0, classname), buff, indent, true, tracer);
                    string res = buff.ToString();
                    if (casted || instance.GetPrecedence() > GetPrecedence())
                    {
                        res = "(" + res + ")";
                    }
                    buf.Append(res);
                }
                if (buf.ToString().Equals(VarExprent.Var_Nameless_Enclosure))
                {
                    // FIXME: workaround for field access of an anonymous enclosing class. Find a better way.
                    buf.SetLength(0);
                }
                else
                {
                    buf.Append(".");
                }
            }
            buf.Append(name);
            tracer.AddMapping(bytecode);
            return(buf);
        }
        private void ComputeMethodType(ClassesProcessor.ClassNode node, MethodWrapper method
                                       )
        {
            NestedMemberAccess.MethodAccess type = NestedMemberAccess.MethodAccess.Normal;
            if (method.root != null)
            {
                DirectGraph  graph = method.GetOrBuildGraph();
                StructMethod mt    = method.methodStruct;
                if ((noSynthFlag || mt.IsSynthetic()) && mt.HasModifier(ICodeConstants.Acc_Static
                                                                        ))
                {
                    if (graph.nodes.Count == 2)
                    {
                        // incl. dummy exit node
                        if (graph.first.exprents.Count == 1)
                        {
                            Exprent          exprent = graph.first.exprents[0];
                            MethodDescriptor mtdesc  = MethodDescriptor.ParseDescriptor(mt.GetDescriptor());
                            int     parcount         = [email protected];
                            Exprent exprCore         = exprent;
                            if (exprent.type == Exprent.Exprent_Exit)
                            {
                                ExitExprent exexpr = (ExitExprent)exprent;
                                if (exexpr.GetExitType() == ExitExprent.Exit_Return && exexpr.GetValue() != null)
                                {
                                    exprCore = exexpr.GetValue();
                                }
                            }
                            switch (exprCore.type)
                            {
                            case Exprent.Exprent_Field:
                            {
                                FieldExprent fexpr = (FieldExprent)exprCore;
                                if ((parcount == 1 && !fexpr.IsStatic()) || (parcount == 0 && fexpr.IsStatic()))
                                {
                                    if (fexpr.GetClassname().Equals(node.classStruct.qualifiedName))
                                    {
                                        // FIXME: check for private flag of the field
                                        if (fexpr.IsStatic() || (fexpr.GetInstance().type == Exprent.Exprent_Var && ((VarExprent
                                                                                                                      )fexpr.GetInstance()).GetIndex() == 0))
                                        {
                                            type = NestedMemberAccess.MethodAccess.Field_Get;
                                        }
                                    }
                                }
                                break;
                            }

                            case Exprent.Exprent_Var:
                            {
                                // qualified this
                                if (parcount == 1)
                                {
                                    // this or final variable
                                    if (((VarExprent)exprCore).GetIndex() != 0)
                                    {
                                        type = NestedMemberAccess.MethodAccess.Field_Get;
                                    }
                                }
                                break;
                            }

                            case Exprent.Exprent_Function:
                            {
                                // for now detect only increment/decrement
                                FunctionExprent functionExprent = (FunctionExprent)exprCore;
                                if (functionExprent.GetFuncType() >= FunctionExprent.Function_Imm && functionExprent
                                    .GetFuncType() <= FunctionExprent.Function_Ppi)
                                {
                                    if (functionExprent.GetLstOperands()[0].type == Exprent.Exprent_Field)
                                    {
                                        type = NestedMemberAccess.MethodAccess.Function;
                                    }
                                }
                                break;
                            }

                            case Exprent.Exprent_Invocation:
                            {
                                type = NestedMemberAccess.MethodAccess.Method;
                                break;
                            }

                            case Exprent.Exprent_Assignment:
                            {
                                AssignmentExprent asexpr = (AssignmentExprent)exprCore;
                                if (asexpr.GetLeft().type == Exprent.Exprent_Field && asexpr.GetRight().type == Exprent
                                    .Exprent_Var)
                                {
                                    FieldExprent fexpras = (FieldExprent)asexpr.GetLeft();
                                    if ((parcount == 2 && !fexpras.IsStatic()) || (parcount == 1 && fexpras.IsStatic(
                                                                                       )))
                                    {
                                        if (fexpras.GetClassname().Equals(node.classStruct.qualifiedName))
                                        {
                                            // FIXME: check for private flag of the field
                                            if (fexpras.IsStatic() || (fexpras.GetInstance().type == Exprent.Exprent_Var && (
                                                                           (VarExprent)fexpras.GetInstance()).GetIndex() == 0))
                                            {
                                                if (((VarExprent)asexpr.GetRight()).GetIndex() == parcount - 1)
                                                {
                                                    type = NestedMemberAccess.MethodAccess.Field_Set;
                                                }
                                            }
                                        }
                                    }
                                }
                                break;
                            }
                            }
                            if (type == NestedMemberAccess.MethodAccess.Method)
                            {
                                // FIXME: check for private flag of the method
                                type = NestedMemberAccess.MethodAccess.Normal;
                                InvocationExprent invexpr = (InvocationExprent)exprCore;
                                bool isStatic             = invexpr.IsStatic();
                                if ((isStatic && invexpr.GetLstParameters().Count == parcount) || (!isStatic && invexpr
                                                                                                   .GetInstance().type == Exprent.Exprent_Var && ((VarExprent)invexpr.GetInstance()
                                                                                                                                                  ).GetIndex() == 0 && invexpr.GetLstParameters().Count == parcount - 1))
                                {
                                    bool equalpars = true;
                                    int  index     = isStatic ? 0 : 1;
                                    for (int i = 0; i < invexpr.GetLstParameters().Count; i++)
                                    {
                                        Exprent parexpr = invexpr.GetLstParameters()[i];
                                        if (parexpr.type != Exprent.Exprent_Var || ((VarExprent)parexpr).GetIndex() != index)
                                        {
                                            equalpars = false;
                                            break;
                                        }
                                        index += mtdesc.@params[i + (isStatic ? 0 : 1)].stackSize;
                                    }
                                    if (equalpars)
                                    {
                                        type = NestedMemberAccess.MethodAccess.Method;
                                    }
                                }
                            }
                        }
                        else if (graph.first.exprents.Count == 2)
                        {
                            Exprent exprentFirst  = graph.first.exprents[0];
                            Exprent exprentSecond = graph.first.exprents[1];
                            if (exprentFirst.type == Exprent.Exprent_Assignment && exprentSecond.type == Exprent
                                .Exprent_Exit)
                            {
                                MethodDescriptor mtdesc  = MethodDescriptor.ParseDescriptor(mt.GetDescriptor());
                                int parcount             = [email protected];
                                AssignmentExprent asexpr = (AssignmentExprent)exprentFirst;
                                if (asexpr.GetLeft().type == Exprent.Exprent_Field && asexpr.GetRight().type == Exprent
                                    .Exprent_Var)
                                {
                                    FieldExprent fexpras = (FieldExprent)asexpr.GetLeft();
                                    if ((parcount == 2 && !fexpras.IsStatic()) || (parcount == 1 && fexpras.IsStatic(
                                                                                       )))
                                    {
                                        if (fexpras.GetClassname().Equals(node.classStruct.qualifiedName))
                                        {
                                            // FIXME: check for private flag of the field
                                            if (fexpras.IsStatic() || (fexpras.GetInstance().type == Exprent.Exprent_Var && (
                                                                           (VarExprent)fexpras.GetInstance()).GetIndex() == 0))
                                            {
                                                if (((VarExprent)asexpr.GetRight()).GetIndex() == parcount - 1)
                                                {
                                                    ExitExprent exexpr = (ExitExprent)exprentSecond;
                                                    if (exexpr.GetExitType() == ExitExprent.Exit_Return && exexpr.GetValue() != null)
                                                    {
                                                        if (exexpr.GetValue().type == Exprent.Exprent_Var && ((VarExprent)asexpr.GetRight
                                                                                                                  ()).GetIndex() == parcount - 1)
                                                        {
                                                            type = NestedMemberAccess.MethodAccess.Field_Set;
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (type != NestedMemberAccess.MethodAccess.Normal)
            {
                Sharpen.Collections.Put(mapMethodType, method, type);
            }
            else
            {
                Sharpen.Collections.Remove(mapMethodType, method);
            }
        }
        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);
        }
        private Exprent ReplaceAccessExprent(ClassesProcessor.ClassNode caller, MethodWrapper
                                             methdest, InvocationExprent invexpr)
        {
            ClassesProcessor.ClassNode node = DecompilerContext.GetClassProcessor().GetMapRootClasses
                                                  ().GetOrNull(invexpr.GetClassname());
            MethodWrapper methsource = null;

            if (node != null && node.GetWrapper() != null)
            {
                methsource = node.GetWrapper().GetMethodWrapper(invexpr.GetName(), invexpr.GetStringDescriptor
                                                                    ());
            }
            if (methsource == null || !mapMethodType.ContainsKey(methsource))
            {
                return(null);
            }
            // if same method, return
            if (node.classStruct.qualifiedName.Equals(caller.classStruct.qualifiedName) && methsource
                .methodStruct.GetName().Equals(methdest.methodStruct.GetName()) && methsource.methodStruct
                .GetDescriptor().Equals(methdest.methodStruct.GetDescriptor()))
            {
                // no recursive invocations permitted!
                return(null);
            }
            NestedMemberAccess.MethodAccess type = mapMethodType.GetOrNull(methsource);
            //		// FIXME: impossible case. MethodAccess.NORMAL is not saved in the map
            //		if(type == MethodAccess.NORMAL) {
            //			return null;
            //		}
            if (!SameTree(caller, node))
            {
                return(null);
            }
            DirectGraph graph      = methsource.GetOrBuildGraph();
            Exprent     source     = graph.first.exprents[0];
            Exprent     retexprent = null;

            switch (type.ordinal())
            {
            case 1:
            {
                ExitExprent exsource = (ExitExprent)source;
                if (exsource.GetValue().type == Exprent.Exprent_Var)
                {
                    // qualified this
                    VarExprent var     = (VarExprent)exsource.GetValue();
                    string     varname = methsource.varproc.GetVarName(new VarVersionPair(var));
                    if (!methdest.setOuterVarNames.Contains(varname))
                    {
                        VarNamesCollector vnc = new VarNamesCollector();
                        vnc.AddName(varname);
                        methdest.varproc.RefreshVarNames(vnc);
                        methdest.setOuterVarNames.Add(varname);
                    }
                    int        index = methdest.counter.GetCounterAndIncrement(CounterContainer.Var_Counter);
                    VarExprent ret   = new VarExprent(index, var.GetVarType(), methdest.varproc);
                    methdest.varproc.SetVarName(new VarVersionPair(index, 0), varname);
                    retexprent = ret;
                }
                else
                {
                    // field
                    FieldExprent ret = (FieldExprent)exsource.GetValue().Copy();
                    if (!ret.IsStatic())
                    {
                        ret.ReplaceExprent(ret.GetInstance(), invexpr.GetLstParameters()[0]);
                    }
                    retexprent = ret;
                }
                break;
            }

            case 2:
            {
                AssignmentExprent ret_1;
                if (source.type == Exprent.Exprent_Exit)
                {
                    ExitExprent extex = (ExitExprent)source;
                    ret_1 = (AssignmentExprent)extex.GetValue().Copy();
                }
                else
                {
                    ret_1 = (AssignmentExprent)source.Copy();
                }
                FieldExprent fexpr = (FieldExprent)ret_1.GetLeft();
                if (fexpr.IsStatic())
                {
                    ret_1.ReplaceExprent(ret_1.GetRight(), invexpr.GetLstParameters()[0]);
                }
                else
                {
                    ret_1.ReplaceExprent(ret_1.GetRight(), invexpr.GetLstParameters()[1]);
                    fexpr.ReplaceExprent(fexpr.GetInstance(), invexpr.GetLstParameters()[0]);
                }
                // do not use copied bytecodes
                ret_1.GetLeft().bytecode  = null;
                ret_1.GetRight().bytecode = null;
                retexprent = ret_1;
                break;
            }

            case 4:
            {
                retexprent = ReplaceFunction(invexpr, source);
                break;
            }

            case 3:
            {
                if (source.type == Exprent.Exprent_Exit)
                {
                    source = ((ExitExprent)source).GetValue();
                }
                InvocationExprent invret = (InvocationExprent)source.Copy();
                int index_1 = 0;
                if (!invret.IsStatic())
                {
                    invret.ReplaceExprent(invret.GetInstance(), invexpr.GetLstParameters()[0]);
                    index_1 = 1;
                }
                for (int i = 0; i < invret.GetLstParameters().Count; i++)
                {
                    invret.ReplaceExprent(invret.GetLstParameters()[i], invexpr.GetLstParameters()[i
                                                                                                   + index_1]);
                }
                retexprent = invret;
                break;
            }
            }
            if (retexprent != null)
            {
                // preserve original bytecodes
                retexprent.bytecode = null;
                retexprent.AddBytecodeOffsets(invexpr.bytecode);
                // hide synthetic access method
                bool hide = true;
                if (node.type == ClassesProcessor.ClassNode.Class_Root || (node.access & ICodeConstants
                                                                           .Acc_Static) != 0)
                {
                    StructMethod mt = methsource.methodStruct;
                    if (!mt.IsSynthetic())
                    {
                        hide = false;
                    }
                }
                if (hide)
                {
                    node.GetWrapper().GetHiddenMembers().Add(InterpreterUtil.MakeUniqueKey(invexpr.GetName
                                                                                               (), invexpr.GetStringDescriptor()));
                }
            }
            return(retexprent);
        }
        public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer)
        {
            VarType leftType         = left.GetExprType();
            VarType rightType        = right.GetExprType();
            bool    fieldInClassInit = false;
            bool    hiddenField      = false;

            if (left.type == Exprent.Exprent_Field)
            {
                // first assignment to a final field. Field name without "this" in front of it
                FieldExprent field = (FieldExprent)left;
                ClassesProcessor.ClassNode node = ((ClassesProcessor.ClassNode)DecompilerContext.
                                                   GetProperty(DecompilerContext.Current_Class_Node));
                if (node != null)
                {
                    StructField fd = node.classStruct.GetField(field.GetName(), field.GetDescriptor()
                                                               .descriptorString);
                    if (fd != null)
                    {
                        if (field.IsStatic() && fd.HasModifier(ICodeConstants.Acc_Final))
                        {
                            fieldInClassInit = true;
                        }
                        if (node.GetWrapper() != null && node.GetWrapper().GetHiddenMembers().Contains(InterpreterUtil
                                                                                                       .MakeUniqueKey(fd.GetName(), fd.GetDescriptor())))
                        {
                            hiddenField = true;
                        }
                    }
                }
            }
            if (hiddenField)
            {
                return(new TextBuffer());
            }
            TextBuffer buffer = new TextBuffer();

            if (fieldInClassInit)
            {
                buffer.Append(((FieldExprent)left).GetName());
            }
            else
            {
                buffer.Append(left.ToJava(indent, tracer));
            }
            if (right.type == Exprent_Const)
            {
                ((ConstExprent)right).AdjustConstType(leftType);
            }
            TextBuffer res = right.ToJava(indent, tracer);

            if (condType == Condition_None && !leftType.IsSuperset(rightType) && (rightType.Equals
                                                                                      (VarType.Vartype_Object) || leftType.type != ICodeConstants.Type_Object))
            {
                if (right.GetPrecedence() >= FunctionExprent.GetPrecedence(FunctionExprent.Function_Cast
                                                                           ))
                {
                    res.Enclose("(", ")");
                }
                res.Prepend("(" + ExprProcessor.GetCastTypeName(leftType) + ")");
            }
            buffer.Append(condType == Condition_None ? " = " : Operators[condType]).Append(res
                                                                                           );
            tracer.AddMapping(bytecode);
            return(buffer);
        }
Beispiel #24
0
        // precedence of new
        public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer)
        {
            TextBuffer buf = new TextBuffer();

            if (anonymous)
            {
                ClassesProcessor.ClassNode child = DecompilerContext.GetClassProcessor().GetMapRootClasses
                                                       ().GetOrNull(newType.value);
                // IDEA-204310 - avoid backtracking later on for lambdas (causes spurious imports)
                if (!enumConst && (!lambda || DecompilerContext.GetOption(IFernflowerPreferences
                                                                          .Lambda_To_Anonymous_Class)))
                {
                    string enclosing = null;
                    if (!lambda && constructor != null)
                    {
                        enclosing = GetQualifiedNewInstance(child.anonymousClassType.value, constructor.GetLstParameters
                                                                (), indent, tracer);
                        if (enclosing != null)
                        {
                            buf.Append(enclosing).Append('.');
                        }
                    }
                    buf.Append("new ");
                    string typename = ExprProcessor.GetCastTypeName(child.anonymousClassType);
                    if (enclosing != null)
                    {
                        ClassesProcessor.ClassNode anonymousNode = DecompilerContext.GetClassProcessor().
                                                                   GetMapRootClasses().GetOrNull(child.anonymousClassType.value);
                        if (anonymousNode != null)
                        {
                            typename = anonymousNode.simpleName;
                        }
                        else
                        {
                            typename = Sharpen.Runtime.Substring(typename, typename.LastIndexOf('.') + 1);
                        }
                    }
                    GenericClassDescriptor descriptor = ClassWriter.GetGenericClassDescriptor(child.classStruct
                                                                                              );
                    if (descriptor != null)
                    {
                        if ((descriptor.superinterfaces.Count == 0))
                        {
                            buf.Append(GenericMain.GetGenericCastTypeName(descriptor.superclass));
                        }
                        else
                        {
                            if (descriptor.superinterfaces.Count > 1 && !lambda)
                            {
                                DecompilerContext.GetLogger().WriteMessage("Inconsistent anonymous class signature: "
                                                                           + child.classStruct.qualifiedName, IFernflowerLogger.Severity.Warn);
                            }
                            buf.Append(GenericMain.GetGenericCastTypeName(descriptor.superinterfaces[0]));
                        }
                    }
                    else
                    {
                        buf.Append(typename);
                    }
                }
                buf.Append('(');
                if (!lambda && constructor != null)
                {
                    List <Exprent>        parameters = constructor.GetLstParameters();
                    List <VarVersionPair> mask       = child.GetWrapper().GetMethodWrapper(ICodeConstants.Init_Name
                                                                                           , constructor.GetStringDescriptor()).synthParameters;
                    if (mask == null)
                    {
                        InvocationExprent superCall = child.superInvocation;
                        mask = ExprUtil.GetSyntheticParametersMask(superCall.GetClassname(), superCall.GetStringDescriptor
                                                                       (), parameters.Count);
                    }
                    int  start      = enumConst ? 2 : 0;
                    bool firstParam = true;
                    for (int i = start; i < parameters.Count; i++)
                    {
                        if (mask == null || mask[i] == null)
                        {
                            if (!firstParam)
                            {
                                buf.Append(", ");
                            }
                            ExprProcessor.GetCastedExprent(parameters[i], constructor.GetDescriptor().@params
                                                           [i], buf, indent, true, tracer);
                            firstParam = false;
                        }
                    }
                }
                buf.Append(')');
                if (enumConst && buf.Length() == 2)
                {
                    buf.SetLength(0);
                }
                if (lambda)
                {
                    if (!DecompilerContext.GetOption(IFernflowerPreferences.Lambda_To_Anonymous_Class
                                                     ))
                    {
                        buf.SetLength(0);
                    }
                    // remove the usual 'new <class>()', it will be replaced with lambda style '() ->'
                    Exprent    methodObject = constructor == null ? null : constructor.GetInstance();
                    TextBuffer clsBuf       = new TextBuffer();
                    new ClassWriter().ClassLambdaToJava(child, clsBuf, methodObject, indent, tracer);
                    buf.Append(clsBuf);
                    tracer.IncrementCurrentSourceLine(clsBuf.CountLines());
                }
                else
                {
                    TextBuffer clsBuf = new TextBuffer();
                    new ClassWriter().ClassToJava(child, clsBuf, indent, tracer);
                    buf.Append(clsBuf);
                    tracer.IncrementCurrentSourceLine(clsBuf.CountLines());
                }
            }
            else if (directArrayInit)
            {
                VarType leftType = newType.DecreaseArrayDim();
                buf.Append('{');
                for (int i = 0; i < lstArrayElements.Count; i++)
                {
                    if (i > 0)
                    {
                        buf.Append(", ");
                    }
                    ExprProcessor.GetCastedExprent(lstArrayElements[i], leftType, buf, indent, false,
                                                   tracer);
                }
                buf.Append('}');
            }
            else if (newType.arrayDim == 0)
            {
                if (!enumConst)
                {
                    string enclosing = null;
                    if (constructor != null)
                    {
                        enclosing = GetQualifiedNewInstance(newType.value, constructor.GetLstParameters()
                                                            , indent, tracer);
                        if (enclosing != null)
                        {
                            buf.Append(enclosing).Append('.');
                        }
                    }
                    buf.Append("new ");
                    string typename = ExprProcessor.GetTypeName(newType);
                    if (enclosing != null)
                    {
                        ClassesProcessor.ClassNode newNode = DecompilerContext.GetClassProcessor().GetMapRootClasses
                                                                 ().GetOrNull(newType.value);
                        if (newNode != null)
                        {
                            typename = newNode.simpleName;
                        }
                        else
                        {
                            typename = Sharpen.Runtime.Substring(typename, typename.LastIndexOf('.') + 1);
                        }
                    }
                    buf.Append(typename);
                }
                if (constructor != null)
                {
                    List <Exprent>        parameters = constructor.GetLstParameters();
                    List <VarVersionPair> mask       = ExprUtil.GetSyntheticParametersMask(constructor.GetClassname
                                                                                               (), constructor.GetStringDescriptor(), parameters.Count);
                    int start = enumConst ? 2 : 0;
                    if (!enumConst || start < parameters.Count)
                    {
                        buf.Append('(');
                        bool firstParam = true;
                        for (int i = start; i < parameters.Count; i++)
                        {
                            if (mask == null || mask[i] == null)
                            {
                                Exprent expr     = parameters[i];
                                VarType leftType = constructor.GetDescriptor().@params[i];
                                if (i == parameters.Count - 1 && expr.GetExprType() == VarType.Vartype_Null && ProbablySyntheticParameter
                                        (leftType.value))
                                {
                                    break;
                                }
                                // skip last parameter of synthetic constructor call
                                if (!firstParam)
                                {
                                    buf.Append(", ");
                                }
                                ExprProcessor.GetCastedExprent(expr, leftType, buf, indent, true, false, true, true
                                                               , tracer);
                                firstParam = false;
                            }
                        }
                        buf.Append(')');
                    }
                }
            }
            else if (isVarArgParam)
            {
                // just print the array elements
                VarType leftType = newType.DecreaseArrayDim();
                for (int i = 0; i < lstArrayElements.Count; i++)
                {
                    if (i > 0)
                    {
                        buf.Append(", ");
                    }
                    // new String[][]{{"abc"}, {"DEF"}} => new String[]{"abc"}, new String[]{"DEF"}
                    Exprent element = lstArrayElements[i];
                    if (element.type == Exprent_New)
                    {
                        ((NewExprent)element).SetDirectArrayInit(false);
                    }
                    ExprProcessor.GetCastedExprent(element, leftType, buf, indent, false, tracer);
                }
                // if there is just one element of Object[] type it needs to be casted to resolve ambiguity
                if (lstArrayElements.Count == 1)
                {
                    VarType elementType = lstArrayElements[0].GetExprType();
                    if (elementType.type == ICodeConstants.Type_Object && elementType.value.Equals("java/lang/Object"
                                                                                                   ) && elementType.arrayDim >= 1)
                    {
                        buf.Prepend("(Object)");
                    }
                }
            }
            else
            {
                buf.Append("new ").Append(ExprProcessor.GetTypeName(newType));
                if ((lstArrayElements.Count == 0))
                {
                    for (int i = 0; i < newType.arrayDim; i++)
                    {
                        buf.Append('[');
                        if (i < lstDims.Count)
                        {
                            buf.Append(lstDims[i].ToJava(indent, tracer));
                        }
                        buf.Append(']');
                    }
                }
                else
                {
                    for (int i = 0; i < newType.arrayDim; i++)
                    {
                        buf.Append("[]");
                    }
                    VarType leftType = newType.DecreaseArrayDim();
                    buf.Append('{');
                    for (int i = 0; i < lstArrayElements.Count; i++)
                    {
                        if (i > 0)
                        {
                            buf.Append(", ");
                        }
                        ExprProcessor.GetCastedExprent(lstArrayElements[i], leftType, buf, indent, false,
                                                       tracer);
                    }
                    buf.Append('}');
                }
            }
            return(buf);
        }
Beispiel #25
0
        public virtual string GetShortName(string fullName, bool imported)
        {
            ClassesProcessor.ClassNode node = DecompilerContext.GetClassProcessor().GetMapRootClasses
                                                  ().GetOrNull(fullName.Replace('.', '/'));
            //todo[r.sh] anonymous classes?
            string result = null;

            if (node != null && node.classStruct.IsOwn())
            {
                result = node.simpleName;
                while (node.parent != null && node.type == ClassesProcessor.ClassNode.Class_Member
                       )
                {
                    //noinspection StringConcatenationInLoop
                    result = node.parent.simpleName + '.' + result;
                    node   = node.parent;
                }
                if (node.type == ClassesProcessor.ClassNode.Class_Root)
                {
                    fullName = node.classStruct.qualifiedName;
                    fullName = fullName.Replace('/', '.');
                }
                else
                {
                    return(result);
                }
            }
            else
            {
                fullName = fullName.Replace('$', '.');
            }
            string shortName   = fullName;
            string packageName = string.Empty;
            int    lastDot     = fullName.LastIndexOf('.');

            if (lastDot >= 0)
            {
                shortName   = Sharpen.Runtime.Substring(fullName, lastDot + 1);
                packageName = Sharpen.Runtime.Substring(fullName, 0, lastDot);
            }
            StructContext context = DecompilerContext.GetStructContext();
            // check for another class which could 'shadow' this one. Three cases:
            // 1) class with the same short name in the current package
            // 2) class with the same short name in the default package
            // 3) inner class with the same short name in the current class, a super class, or an implemented interface
            bool existsDefaultClass = (context.GetClass(currentPackageSlash + shortName) != null &&
                                       !packageName.Equals(currentPackagePoint)) || (context.GetClass(shortName) !=
                                                                                     null && !(currentPackagePoint.Length == 0)) || setInnerClassNames.Contains(shortName
                                                                                                                                                                );

            // current package
            // default package
            // inner class
            if (existsDefaultClass || (mapSimpleNames.ContainsKey(shortName) && !packageName.
                                       Equals(mapSimpleNames.GetOrNull(shortName))))
            {
                //  don't return full name because if the class is a inner class, full name refers to the parent full name, not the child full name
                return(result == null ? fullName : (packageName + "." + result));
            }
            else if (!mapSimpleNames.ContainsKey(shortName))
            {
                Sharpen.Collections.Put(mapSimpleNames, shortName, packageName);
                if (!imported)
                {
                    setNotImportedNames.Add(shortName);
                }
            }
            return(result == null ? shortName : result);
        }