Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
0
        private static Exprent IsSimpleConstructorInvocation(Exprent exprent)
        {
            List <Exprent> lst = exprent.GetAllExprents();

            foreach (Exprent expr in lst)
            {
                Exprent ret = IsSimpleConstructorInvocation(expr);
                if (ret != null)
                {
                    exprent.ReplaceExprent(expr, ret);
                }
            }
            if (exprent.type == Exprent.Exprent_Invocation)
            {
                InvocationExprent @in = (InvocationExprent)exprent;
                if (@in.GetFunctype() == InvocationExprent.Typ_Init && @in.GetInstance().type ==
                    Exprent.Exprent_New)
                {
                    NewExprent newExpr = (NewExprent)@in.GetInstance();
                    newExpr.SetConstructor(@in);
                    @in.SetInstance(null);
                    return(newExpr);
                }
            }
            return(null);
        }
Ejemplo n.º 3
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);
 }
Ejemplo n.º 4
0
 private static bool AddArrayInitializer(Exprent first, Exprent second)
 {
     if (first.type == Exprent.Exprent_Assignment)
     {
         AssignmentExprent @as = (AssignmentExprent)first;
         if (@as.GetRight().type == Exprent.Exprent_New && @as.GetLeft().type == Exprent.Exprent_Var)
         {
             NewExprent newExpr = (NewExprent)@as.GetRight();
             if (!(newExpr.GetLstArrayElements().Count == 0))
             {
                 VarExprent arrVar = (VarExprent)@as.GetLeft();
                 if (second.type == Exprent.Exprent_Assignment)
                 {
                     AssignmentExprent aas = (AssignmentExprent)second;
                     if (aas.GetLeft().type == Exprent.Exprent_Array)
                     {
                         ArrayExprent arrExpr = (ArrayExprent)aas.GetLeft();
                         if (arrExpr.GetArray().type == Exprent.Exprent_Var && arrVar.Equals(arrExpr.GetArray
                                                                                                 ()) && arrExpr.GetIndex().type == Exprent.Exprent_Const)
                         {
                             int constValue = ((ConstExprent)arrExpr.GetIndex()).GetIntValue();
                             if (constValue < newExpr.GetLstArrayElements().Count)
                             {
                                 Exprent init = newExpr.GetLstArrayElements()[constValue];
                                 if (init.type == Exprent.Exprent_Const)
                                 {
                                     ConstExprent cinit      = (ConstExprent)init;
                                     VarType      arrType    = newExpr.GetNewType().DecreaseArrayDim();
                                     ConstExprent defaultVal = ExprProcessor.GetDefaultArrayValue(arrType);
                                     if (cinit.Equals(defaultVal))
                                     {
                                         Exprent tempExpr = aas.GetRight();
                                         if (!tempExpr.ContainsExprent(arrVar))
                                         {
                                             newExpr.GetLstArrayElements()[constValue] = tempExpr;
                                             if (tempExpr.type == Exprent.Exprent_New)
                                             {
                                                 NewExprent tempNewExpr = (NewExprent)tempExpr;
                                                 int        dims        = newExpr.GetNewType().arrayDim;
                                                 if (dims > 1 && !(tempNewExpr.GetLstArrayElements().Count == 0))
                                                 {
                                                     tempNewExpr.SetDirectArrayInit(true);
                                                 }
                                             }
                                             return(true);
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     return(false);
 }
Ejemplo n.º 5
0
 private static bool IsNewConcat(NewExprent expr, VarType cltype)
 {
     if (expr.GetNewType().Equals(cltype))
     {
         VarType[] @params = expr.GetConstructor().GetDescriptor().@params;
         return(@params.Length == 0 || @params.Length == 1 && @params[0].Equals(VarType.Vartype_String
                                                                                ));
     }
     return(false);
 }
Ejemplo n.º 6
0
        // propagate (var = new X) forward to the <init> invocation
        private static bool IsConstructorInvocationRemote(List <Exprent> list, int index)
        {
            Exprent current = list[index];

            if (current.type == Exprent.Exprent_Assignment)
            {
                AssignmentExprent @as = (AssignmentExprent)current;
                if (@as.GetLeft().type == Exprent.Exprent_Var && @as.GetRight().type == Exprent.Exprent_New)
                {
                    NewExprent     newExpr  = (NewExprent)@as.GetRight();
                    VarType        newType  = newExpr.GetNewType();
                    VarVersionPair leftPair = new VarVersionPair((VarExprent)@as.GetLeft());
                    if (newType.type == ICodeConstants.Type_Object && newType.arrayDim == 0 && newExpr
                        .GetConstructor() == null)
                    {
                        for (int i = index + 1; i < list.Count; i++)
                        {
                            Exprent remote = list[i];
                            // <init> invocation
                            if (remote.type == Exprent.Exprent_Invocation)
                            {
                                InvocationExprent @in = (InvocationExprent)remote;
                                if (@in.GetFunctype() == InvocationExprent.Typ_Init && @in.GetInstance().type ==
                                    Exprent.Exprent_Var && @as.GetLeft().Equals(@in.GetInstance()))
                                {
                                    newExpr.SetConstructor(@in);
                                    @in.SetInstance(null);
                                    list[i] = @as.Copy();
                                    return(true);
                                }
                            }
                            // check for variable in use
                            HashSet <VarVersionPair> setVars = remote.GetAllVariables();
                            if (setVars.Contains(leftPair))
                            {
                                // variable used somewhere in between -> exit, need a better reduced code
                                return(false);
                            }
                        }
                    }
                }
            }
            return(false);
        }
        static ClassReference14Processor()
        {
            InvocationExprent invFor = new InvocationExprent();

            invFor.SetName("forName");
            invFor.SetClassname("java/lang/Class");
            invFor.SetStringDescriptor("(Ljava/lang/String;)Ljava/lang/Class;");
            invFor.SetDescriptor(MethodDescriptor.ParseDescriptor("(Ljava/lang/String;)Ljava/lang/Class;"
                                                                  ));
            invFor.SetStatic(true);
            invFor.SetLstParameters(new [] { new VarExprent(0, VarType
                                                            .Vartype_String, null) }.Cast <Exprent>().ToList());
            Body_Expr = new ExitExprent(ExitExprent.Exit_Return, invFor, VarType.Vartype_Class
                                        , null);
            InvocationExprent ctor = new InvocationExprent();

            ctor.SetName(ICodeConstants.Init_Name);
            ctor.SetClassname("java/lang/NoClassDefFoundError");
            ctor.SetStringDescriptor("()V");
            ctor.SetFunctype(InvocationExprent.Typ_Init);
            ctor.SetDescriptor(MethodDescriptor.ParseDescriptor("()V"));
            NewExprent newExpr = new NewExprent(new VarType(ICodeConstants.Type_Object, 0, "java/lang/NoClassDefFoundError"
                                                            ), new List <Exprent>(), null);

            newExpr.SetConstructor(ctor);
            InvocationExprent invCause = new InvocationExprent();

            invCause.SetName("initCause");
            invCause.SetClassname("java/lang/NoClassDefFoundError");
            invCause.SetStringDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
            invCause.SetDescriptor(MethodDescriptor.ParseDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;"
                                                                    ));
            invCause.SetInstance(newExpr);
            invCause.SetLstParameters(new List <Exprent>(new [] { new VarExprent(2,
                                                                                 new VarType(ICodeConstants.Type_Object, 0, "java/lang/ClassNotFoundException"),
                                                                                 null) }.ToList()));
            Handler_Expr = new ExitExprent(ExitExprent.Exit_Throw, invCause, null, null);
        }
Ejemplo n.º 8
0
        private static InvocationExprent IsAssertionError(Statement stat)
        {
            if (stat == null || stat.GetExprents() == null || stat.GetExprents().Count != 1)
            {
                return(null);
            }
            Exprent expr = stat.GetExprents()[0];

            if (expr.type == Exprent.Exprent_Exit)
            {
                ExitExprent exexpr = (ExitExprent)expr;
                if (exexpr.GetExitType() == ExitExprent.Exit_Throw && exexpr.GetValue().type == Exprent
                    .Exprent_New)
                {
                    NewExprent nexpr = (NewExprent)exexpr.GetValue();
                    if (Class_Assertion_Error.Equals(nexpr.GetNewType()) && nexpr.GetConstructor() !=
                        null)
                    {
                        return(nexpr.GetConstructor());
                    }
                }
            }
            return(null);
        }
Ejemplo n.º 9
0
        private int[] IterateExprent(List <Exprent> lstExprents, int index, Exprent next,
                                     Dictionary <VarVersionPair, Exprent> mapVarValues, SSAUConstructorSparseEx ssau)
        {
            Exprent exprent = lstExprents[index];
            int     changed = 0;

            foreach (Exprent expr in exprent.GetAllExprents())
            {
                var oldExpr = expr;
                while (true)
                {
                    object[] arr     = IterateChildExprent(oldExpr, exprent, next, mapVarValues, ssau);
                    Exprent  retexpr = (Exprent)arr[0];
                    changed |= (bool)arr[1] ? 1 : 0;
                    bool isReplaceable = (bool)arr[2];
                    if (retexpr != null)
                    {
                        if (isReplaceable)
                        {
                            ReplaceSingleVar(exprent, (VarExprent)oldExpr, retexpr, ssau);
                            oldExpr = retexpr;
                        }
                        else
                        {
                            exprent.ReplaceExprent(oldExpr, retexpr);
                        }
                        changed = 1;
                    }
                    if (!isReplaceable)
                    {
                        break;
                    }
                }
            }
            // no var on the highest level, so no replacing
            VarExprent left  = null;
            Exprent    right = null;

            if (exprent.type == Exprent.Exprent_Assignment)
            {
                AssignmentExprent @as = (AssignmentExprent)exprent;
                if (@as.GetLeft().type == Exprent.Exprent_Var)
                {
                    left  = (VarExprent)@as.GetLeft();
                    right = @as.GetRight();
                }
            }
            if (left == null)
            {
                return(new int[] { -1, changed });
            }
            VarVersionPair        leftpaar = new VarVersionPair(left);
            List <VarVersionNode> usedVers = new List <VarVersionNode>();
            bool notdom = GetUsedVersions(ssau, leftpaar, usedVers);

            if (!notdom && (usedVers.Count == 0))
            {
                if (left.IsStack() && (right.type == Exprent.Exprent_Invocation || right.type ==
                                       Exprent.Exprent_Assignment || right.type == Exprent.Exprent_New))
                {
                    if (right.type == Exprent.Exprent_New)
                    {
                        // new Object(); permitted
                        NewExprent nexpr = (NewExprent)right;
                        if (nexpr.IsAnonymous() || nexpr.GetNewType().arrayDim > 0 || nexpr.GetNewType().
                            type != ICodeConstants.Type_Object)
                        {
                            return(new int[] { -1, changed });
                        }
                    }
                    lstExprents[index] = right;
                    return(new int[] { index + 1, 1 });
                }
                else if (right.type == Exprent.Exprent_Var)
                {
                    lstExprents.RemoveAtReturningValue(index);
                    return(new int[] { index, 1 });
                }
                else
                {
                    return(new int[] { -1, changed });
                }
            }
            int useflags = right.GetExprentUse();

            // stack variables only
            if (!left.IsStack() && (right.type != Exprent.Exprent_Var || ((VarExprent)right).
                                    IsStack()))
            {
                // special case catch(... ex)
                return(new int[] { -1, changed });
            }
            if ((useflags & Exprent.Multiple_Uses) == 0 && (notdom || usedVers.Count > 1))
            {
                return(new int[] { -1, changed });
            }
            Dictionary <int, HashSet <VarVersionPair> > mapVars = GetAllVarVersions(leftpaar, right
                                                                                    , ssau);
            bool isSelfReference = mapVars.ContainsKey(leftpaar.var);

            if (isSelfReference && notdom)
            {
                return(new int[] { -1, changed });
            }
            HashSet <VarVersionPair> setNextVars = next == null ? null : GetAllVersions(next);

            // FIXME: fix the entire method!
            if (right.type != Exprent.Exprent_Const && right.type != Exprent.Exprent_Var && setNextVars
                != null && mapVars.ContainsKey(leftpaar.var))
            {
                foreach (VarVersionNode usedvar in usedVers)
                {
                    if (!setNextVars.Contains(new VarVersionPair(usedvar.var, usedvar.version)))
                    {
                        return(new int[] { -1, changed });
                    }
                }
            }
            Sharpen.Collections.Remove(mapVars, leftpaar.var);
            bool vernotreplaced = false;
            bool verreplaced    = false;
            HashSet <VarVersionPair> setTempUsedVers = new HashSet <VarVersionPair>();

            foreach (VarVersionNode usedvar in usedVers)
            {
                VarVersionPair usedver = new VarVersionPair(usedvar.var, usedvar.version);
                if (IsVersionToBeReplaced(usedver, mapVars, ssau, leftpaar) && (right.type == Exprent
                                                                                .Exprent_Const || right.type == Exprent.Exprent_Var || right.type == Exprent.Exprent_Field ||
                                                                                setNextVars == null || setNextVars.Contains(usedver)))
                {
                    setTempUsedVers.Add(usedver);
                    verreplaced = true;
                }
                else
                {
                    vernotreplaced = true;
                }
            }
            if (isSelfReference && vernotreplaced)
            {
                return(new int[] { -1, changed });
            }
            else
            {
                foreach (VarVersionPair usedver in setTempUsedVers)
                {
                    Exprent copy = right.Copy();
                    if (right.type == Exprent.Exprent_Field && ssau.GetMapFieldVars().ContainsKey(right
                                                                                                  .id))
                    {
                        Sharpen.Collections.Put(ssau.GetMapFieldVars(), copy.id, ssau.GetMapFieldVars().GetOrNullable
                                                    (right.id));
                    }
                    Sharpen.Collections.Put(mapVarValues, usedver, copy);
                }
            }
            if (!notdom && !vernotreplaced)
            {
                // remove assignment
                lstExprents.RemoveAtReturningValue(index);
                return(new int[] { index, 1 });
            }
            else if (verreplaced)
            {
                return(new int[] { index + 1, changed });
            }
            else
            {
                return(new int[] { -1, changed });
            }
        }
Ejemplo n.º 10
0
        private static int IsArrayInitializer(List <Exprent> list, int index)
        {
            Exprent current = list[index];

            if (current.type == Exprent.Exprent_Assignment)
            {
                AssignmentExprent @as = (AssignmentExprent)current;
                if (@as.GetRight().type == Exprent.Exprent_New && @as.GetLeft().type == Exprent.Exprent_Var)
                {
                    NewExprent newExpr = (NewExprent)@as.GetRight();
                    if (newExpr.GetExprType().arrayDim > 0 && newExpr.GetLstDims().Count == 1 && (newExpr
                                                                                                  .GetLstArrayElements().Count == 0) && newExpr.GetLstDims()[0].type == Exprent.Exprent_Const)
                    {
                        int size = (int)((ConstExprent)newExpr.GetLstDims()[0]).GetValue();
                        if (size == 0)
                        {
                            return(0);
                        }
                        VarExprent arrVar = (VarExprent)@as.GetLeft();
                        Dictionary <int, Exprent> mapInit = new Dictionary <int, Exprent>();
                        int i = 1;
                        while (index + i < list.Count && i <= size)
                        {
                            bool    found = false;
                            Exprent expr  = list[index + i];
                            if (expr.type == Exprent.Exprent_Assignment)
                            {
                                AssignmentExprent aas = (AssignmentExprent)expr;
                                if (aas.GetLeft().type == Exprent.Exprent_Array)
                                {
                                    ArrayExprent arrExpr = (ArrayExprent)aas.GetLeft();
                                    if (arrExpr.GetArray().type == Exprent.Exprent_Var && arrVar.Equals(arrExpr.GetArray
                                                                                                            ()) && arrExpr.GetIndex().type == Exprent.Exprent_Const)
                                    {
                                        // TODO: check for a number type. Failure extremely improbable, but nevertheless...
                                        int constValue = ((ConstExprent)arrExpr.GetIndex()).GetIntValue();
                                        if (constValue < size && !mapInit.ContainsKey(constValue))
                                        {
                                            if (!aas.GetRight().ContainsExprent(arrVar))
                                            {
                                                Sharpen.Collections.Put(mapInit, constValue, aas.GetRight());
                                                found = true;
                                            }
                                        }
                                    }
                                }
                            }
                            if (!found)
                            {
                                break;
                            }
                            i++;
                        }
                        double fraction = ((double)mapInit.Count) / size;
                        if ((arrVar.IsStack() && fraction > 0) || (size <= 7 && fraction >= 0.3) || (size
                                                                                                     > 7 && fraction >= 0.7))
                        {
                            List <Exprent> lstRet     = new List <Exprent>();
                            VarType        arrayType  = newExpr.GetNewType().DecreaseArrayDim();
                            ConstExprent   defaultVal = ExprProcessor.GetDefaultArrayValue(arrayType);
                            for (int j = 0; j < size; j++)
                            {
                                lstRet.Add(defaultVal.Copy());
                            }
                            int dims = newExpr.GetNewType().arrayDim;
                            foreach (KeyValuePair <int, Exprent> ent in mapInit)
                            {
                                Exprent tempExpr = ent.Value;
                                lstRet[ent.Key] = tempExpr;
                                if (tempExpr.type == Exprent.Exprent_New)
                                {
                                    NewExprent tempNewExpr = (NewExprent)tempExpr;
                                    if (dims > 1 && !(tempNewExpr.GetLstArrayElements().Count == 0))
                                    {
                                        tempNewExpr.SetDirectArrayInit(true);
                                    }
                                }
                            }
                            newExpr.SetLstArrayElements(lstRet);
                            return(mapInit.Count);
                        }
                    }
                }
            }
            return(0);
        }
        /// <exception cref="IOException"/>
        public static Exprent ParseAnnotationElement(DataInputStream data, ConstantPool pool
                                                     )
        {
            int tag = data.ReadUnsignedByte();

            switch (tag)
            {
            case 'e':
            {
                // enum constant
                string className = pool.GetPrimitiveConstant(data.ReadUnsignedShort()).GetString(
                    );
                string constName = pool.GetPrimitiveConstant(data.ReadUnsignedShort()).GetString(
                    );
                FieldDescriptor descr = FieldDescriptor.ParseDescriptor(className);
                return(new FieldExprent(constName, descr.type.value, true, null, descr, null));
            }

            case 'c':
            {
                // class
                string descriptor = pool.GetPrimitiveConstant(data.ReadUnsignedShort()).GetString
                                        ();
                VarType type = FieldDescriptor.ParseDescriptor(descriptor).type;
                string  value;
                switch (type.type)
                {
                case ICodeConstants.Type_Object:
                {
                    value = type.value;
                    break;
                }

                case ICodeConstants.Type_Byte:
                {
                    value = typeof(byte).FullName;
                    break;
                }

                case ICodeConstants.Type_Char:
                {
                    value = typeof(char).FullName;
                    break;
                }

                case ICodeConstants.Type_Double:
                {
                    value = typeof(double).FullName;
                    break;
                }

                case ICodeConstants.Type_Float:
                {
                    value = typeof(float).FullName;
                    break;
                }

                case ICodeConstants.Type_Int:
                {
                    value = typeof(int).FullName;
                    break;
                }

                case ICodeConstants.Type_Long:
                {
                    value = typeof(long).FullName;
                    break;
                }

                case ICodeConstants.Type_Short:
                {
                    value = typeof(short).FullName;
                    break;
                }

                case ICodeConstants.Type_Boolean:
                {
                    value = typeof(bool).FullName;
                    break;
                }

                case ICodeConstants.Type_Void:
                {
                    value = typeof(void).FullName;
                    break;
                }

                default:
                {
                    throw new Exception("invalid class type: " + type.type);
                }
                }
                return(new ConstExprent(VarType.Vartype_Class, value, null));
            }

            case '[':
            {
                // array
                List <Exprent> elements = new System.Collections.Generic.List <Exprent>();
                int            len      = data.ReadUnsignedShort();
                if (len > 0)
                {
                    elements = new List <Exprent>(len);
                    for (int i = 0; i < len; i++)
                    {
                        elements.Add(ParseAnnotationElement(data, pool));
                    }
                }
                VarType newType;
                if ((elements.Count == 0))
                {
                    newType = new VarType(ICodeConstants.Type_Object, 1, "java/lang/Object");
                }
                else
                {
                    VarType elementType = elements[0].GetExprType();
                    newType = new VarType(elementType.type, 1, elementType.value);
                }
                NewExprent newExpr = new NewExprent(newType, new System.Collections.Generic.List <
                                                        Exprent>(), null);
                newExpr.SetDirectArrayInit(true);
                newExpr.SetLstArrayElements(elements);
                return(newExpr);
            }

            case '@':
            {
                // annotation
                return(ParseAnnotation(data, pool));
            }

            default:
            {
                PrimitiveConstant cn = pool.GetPrimitiveConstant(data.ReadUnsignedShort());
                switch (tag)
                {
                case 'B':
                {
                    return(new ConstExprent(VarType.Vartype_Byte, cn.value, null));
                }

                case 'C':
                {
                    return(new ConstExprent(VarType.Vartype_Char, cn.value, null));
                }

                case 'D':
                {
                    return(new ConstExprent(VarType.Vartype_Double, cn.value, null));
                }

                case 'F':
                {
                    return(new ConstExprent(VarType.Vartype_Float, cn.value, null));
                }

                case 'I':
                {
                    return(new ConstExprent(VarType.Vartype_Int, cn.value, null));
                }

                case 'J':
                {
                    return(new ConstExprent(VarType.Vartype_Long, cn.value, null));
                }

                case 'S':
                {
                    return(new ConstExprent(VarType.Vartype_Short, cn.value, null));
                }

                case 'Z':
                {
                    return(new ConstExprent(VarType.Vartype_Boolean, cn.value, null));
                }

                case 's':
                {
                    return(new ConstExprent(VarType.Vartype_String, cn.value, null));
                }

                default:
                {
                    throw new Exception("invalid element type!");
                }
                }
                break;
            }
            }
        }
Ejemplo n.º 12
0
        public static Exprent ContractStringConcat(Exprent expr)
        {
            Exprent exprTmp = null;
            VarType cltype  = null;

            // first quick test
            if (expr.type == Exprent.Exprent_Invocation)
            {
                InvocationExprent iex = (InvocationExprent)expr;
                if ("toString".Equals(iex.GetName()))
                {
                    if (builderClass.Equals(iex.GetClassname()))
                    {
                        cltype = builderType;
                    }
                    else if (bufferClass.Equals(iex.GetClassname()))
                    {
                        cltype = bufferType;
                    }
                    if (cltype != null)
                    {
                        exprTmp = iex.GetInstance();
                    }
                }
                else if ("makeConcatWithConstants".Equals(iex.GetName()))
                {
                    // java 9 style
                    List <Exprent> parameters = ExtractParameters(iex.GetBootstrapArguments(), iex);
                    if (parameters.Count >= 2)
                    {
                        return(CreateConcatExprent(parameters, expr.bytecode));
                    }
                }
            }
            if (exprTmp == null)
            {
                return(expr);
            }
            // iterate in depth, collecting possible operands
            List <Exprent> lstOperands = new List <Exprent>();

            while (true)
            {
                int found = 0;
                switch (exprTmp.type)
                {
                case Exprent.Exprent_Invocation:
                {
                    InvocationExprent iex = (InvocationExprent)exprTmp;
                    if (IsAppendConcat(iex, cltype))
                    {
                        lstOperands.Add(0, iex.GetLstParameters()[0]);
                        exprTmp = iex.GetInstance();
                        found   = 1;
                    }
                    break;
                }

                case Exprent.Exprent_New:
                {
                    NewExprent nex = (NewExprent)exprTmp;
                    if (IsNewConcat(nex, cltype))
                    {
                        VarType[] @params = nex.GetConstructor().GetDescriptor().@params;
                        if (@params.Length == 1)
                        {
                            lstOperands.Add(0, nex.GetConstructor().GetLstParameters()[0]);
                        }
                        found = 2;
                    }
                    break;
                }
                }
                if (found == 0)
                {
                    return(expr);
                }
                else if (found == 2)
                {
                    break;
                }
            }
            int first2str = 0;
            int index     = 0;

            while (index < lstOperands.Count && index < 2)
            {
                if (lstOperands[index].GetExprType().Equals(VarType.Vartype_String))
                {
                    first2str |= (index + 1);
                }
                index++;
            }
            if (first2str == 0)
            {
                lstOperands.Add(0, new ConstExprent(VarType.Vartype_String, string.Empty, expr.bytecode
                                                    ));
            }
            // remove redundant String.valueOf
            for (int i = 0; i < lstOperands.Count; i++)
            {
                Exprent rep = RemoveStringValueOf(lstOperands[i]);
                bool    ok  = (i > 1);
                if (!ok)
                {
                    bool isstr = rep.GetExprType().Equals(VarType.Vartype_String);
                    ok = isstr || first2str != i + 1;
                    if (i == 0)
                    {
                        first2str &= 2;
                    }
                }
                if (ok)
                {
                    lstOperands[i] = rep;
                }
            }
            return(CreateConcatExprent(lstOperands, expr.bytecode));
        }