public override void ValidateSemantics(SemanticsValidator validator)
        {
            foreach (var parameter in Parameters)
            {
                parameter.ValidateSemantics(validator);
            }

            this.StructClass = validator.Container.TryGetClass(CtorName);

            if (StructClass == null)
            {
                validator.AddError("Unknown struct type " + CtorName, ParsingContext);
            }
            if (StructClass.Type != ContainerType.@struct)
            {
                validator.AddError("Constructors can only be called on struct", ParsingContext);
            }

            this.StructClass = validator.Container[CtorName];

            this.StructCtor = StructClass.GetCtor();

            if (StructCtor == null)
            {
                validator.AddError("Unknown struct ctor \"" + StructClass.ClassName + "\"", ParsingContext);
            }
            else if (Parameters.Count != StructCtor.Parameters.Count)
            {
                validator.AddError("Invalid parameters count for Ctor \"" + StructClass.ClassName + "\"", ParsingContext);
            }
        }
            public ClassNode(string content_class_name, string content_method_name, string content_method_descriptor
                             , int content_method_invocation_type, string lambda_class_name, string lambda_method_name
                             , string lambda_method_descriptor, StructClass classStruct)
            {
                // lambda class constructor
                this.type        = Class_Lambda;
                this.classStruct = classStruct;
                // 'parent' class containing the static function
                lambdaInformation                                = new ClassesProcessor.ClassNode.LambdaInformation();
                lambdaInformation.method_name                    = lambda_method_name;
                lambdaInformation.method_descriptor              = lambda_method_descriptor;
                lambdaInformation.content_class_name             = content_class_name;
                lambdaInformation.content_method_name            = content_method_name;
                lambdaInformation.content_method_descriptor      = content_method_descriptor;
                lambdaInformation.content_method_invocation_type = content_method_invocation_type;
                lambdaInformation.content_method_key             = InterpreterUtil.MakeUniqueKey(lambdaInformation
                                                                                                 .content_method_name, lambdaInformation.content_method_descriptor);
                anonymousClassType = new VarType(lambda_class_name, true);
                bool is_method_reference = (content_class_name != classStruct.qualifiedName);

                if (!is_method_reference)
                {
                    // content method in the same class, check synthetic flag
                    StructMethod mt = classStruct.GetMethod(content_method_name, content_method_descriptor
                                                            );
                    is_method_reference = !mt.IsSynthetic();
                }
                // if not synthetic -> method reference
                lambdaInformation.is_method_reference      = is_method_reference;
                lambdaInformation.is_content_method_static = (lambdaInformation.content_method_invocation_type
                                                              == ICodeConstants.CONSTANT_MethodHandle_REF_invokeStatic);
            }
Exemple #3
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);
        }
Exemple #4
0
        public void TestObjectWithStruct()
        {
            var nodeContainer = new NodeContainer();
            var instance      = new StructClass {
                Member1 = 3, Member2 = new Struct()
            };
            var rootNode = nodeContainer.GetOrCreateNode(instance);
            var visitor  = new TestVisitor();

            visitor.Visit(rootNode);
            var expectedNodes = new IContentNode[]
            {
                rootNode,
                rootNode[nameof(StructClass.Member1)],
                rootNode[nameof(StructClass.Member2)],
                rootNode[nameof(StructClass.Member2)].Target,
                rootNode[nameof(StructClass.Member2)].Target[nameof(Struct.Member1)],
                rootNode[nameof(StructClass.Member2)].Target[nameof(Struct.Member2)],
            };
            var expectedPaths = new[]
            {
                new GraphNodePath(rootNode),
                new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member1)),
                new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)),
                new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)).PushTarget(),
                new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)).PushTarget().PushMember(nameof(Struct.Member1)),
                new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)).PushTarget().PushMember(nameof(Struct.Member2)),
            };

            VerifyNodesAndPath(expectedNodes, expectedPaths, visitor);
        }
 /// <exception cref="System.IO.IOException"/>
 public virtual void WriteClass(StructClass cl, TextBuffer buffer)
 {
     ClassesProcessor.ClassNode root = mapRootClasses.GetOrNull(cl.qualifiedName);
     if (root.type != ClassesProcessor.ClassNode.Class_Root)
     {
         return;
     }
     DecompilerContext.GetLogger().StartReadingClass(cl.qualifiedName);
     try
     {
         ImportCollector importCollector = new ImportCollector(root);
         DecompilerContext.StartClass(importCollector);
         new LambdaProcessor().ProcessClass(root);
         // add simple class names to implicit import
         AddClassnameToImport(root, importCollector);
         // build wrappers for all nested classes (that's where actual processing takes place)
         InitWrappers(root);
         new NestedClassProcessor().ProcessClass(root, root);
         new NestedMemberAccess().PropagateMemberAccess(root);
         TextBuffer classBuffer = new TextBuffer(Average_Class_Size);
         new ClassWriter().ClassToJava(root, classBuffer, 0, null);
         int index = cl.qualifiedName.LastIndexOf("/");
         if (index >= 0)
         {
             string packageName = Sharpen.Runtime.Substring(cl.qualifiedName, 0, index).Replace
                                      ('/', '.');
             buffer.Append("package ");
             buffer.Append(packageName);
             buffer.Append(";");
             buffer.AppendLineSeparator();
             buffer.AppendLineSeparator();
         }
         int import_lines_written = importCollector.WriteImports(buffer);
         if (import_lines_written > 0)
         {
             buffer.AppendLineSeparator();
         }
         int offsetLines = buffer.CountLines();
         buffer.Append(classBuffer);
         if (DecompilerContext.GetOption(IFernflowerPreferences.Bytecode_Source_Mapping))
         {
             BytecodeSourceMapper mapper = DecompilerContext.GetBytecodeSourceMapper();
             mapper.AddTotalOffset(offsetLines);
             if (DecompilerContext.GetOption(IFernflowerPreferences.Dump_Original_Lines))
             {
                 buffer.DumpOriginalLineNumbers(mapper.GetOriginalLinesMapping());
             }
             if (DecompilerContext.GetOption(IFernflowerPreferences.Unit_Test_Mode))
             {
                 buffer.AppendLineSeparator();
                 mapper.DumpMapping(buffer, true);
             }
         }
     }
     finally
     {
         DestroyWrappers(root);
         DecompilerContext.GetLogger().EndReadingClass();
     }
 }
        public void TestObjectWithStruct()
        {
            var nodeContainer = new NodeContainer();
            var instance      = new StructClass {
                Member1 = 3, Member2 = new Struct()
            };
            var rootNode = nodeContainer.GetOrCreateNode(instance);
            var visitor  = new TestVisitor();

            visitor.Visit(rootNode);
            var expectedNodes = new IGraphNode[]
            {
                rootNode,
                rootNode[nameof(StructClass.Member1)],
                rootNode[nameof(StructClass.Member2)],
                rootNode[nameof(StructClass.Member2)].Target,
                rootNode[nameof(StructClass.Member2)].Target[nameof(Struct.Member1)],
                rootNode[nameof(StructClass.Member2)].Target[nameof(Struct.Member2)],
            };
            var expectedPaths = new GraphNodePath[6];

            expectedPaths[0] = new GraphNodePath(rootNode);
            expectedPaths[1] = expectedPaths[0].Clone();
            expectedPaths[1].PushMember(nameof(StructClass.Member1));
            expectedPaths[2] = expectedPaths[0].Clone();
            expectedPaths[2].PushMember(nameof(StructClass.Member2));
            expectedPaths[3] = expectedPaths[2].Clone();
            expectedPaths[3].PushTarget();
            expectedPaths[4] = expectedPaths[3].Clone();
            expectedPaths[4].PushMember(nameof(Struct.Member1));
            expectedPaths[5] = expectedPaths[3].Clone();
            expectedPaths[5].PushMember(nameof(Struct.Member2));
            VerifyNodesAndPath(expectedNodes, expectedPaths, visitor);
        }
Exemple #7
0
        public void TestObjectWithStruct()
        {
            var nodeContainer = new NodeContainer();
            var instance1     = new StructClass {
                Member1 = 3, Member2 = new Struct {
                    Member2 = new SimpleClass()
                }
            };
            var instance2 = new StructClass {
                Member1 = 3, Member2 = new Struct {
                    Member2 = new SimpleClass()
                }
            };
            var source = nodeContainer.GetOrCreateNode(instance1);
            var target = nodeContainer.GetOrCreateNode(instance2);
            var linker = new TestLinker();

            linker.LinkGraph(source, target);
            var expectedLinks = new Dictionary <IGraphNode, IGraphNode>
            {
                { source, target },
                { source.GetChild(nameof(StructClass.Member1)), target.GetChild(nameof(StructClass.Member1)) },
                { source.GetChild(nameof(StructClass.Member2)), target.GetChild(nameof(StructClass.Member2)) },
                { source.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member1)), target.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member1)) },
                { source.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)), target.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)) },
                { source.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)).GetTarget(), target.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)).GetTarget() },
                { source.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)).GetTarget().GetChild(nameof(SimpleClass.Member1)), target.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)).GetTarget().GetChild(nameof(SimpleClass.Member1)) },
                { source.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)).GetTarget().GetChild(nameof(SimpleClass.Member2)), target.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)).GetTarget().GetChild(nameof(SimpleClass.Member2)) },
            };

            VerifyLinks(expectedLinks, linker);
        }
Exemple #8
0
        private void RenameInterfaces()
        {
            List <ClassWrapperNode> lstInterfaces = GetReversePostOrderListIterative(rootInterfaces
                                                                                     );
            Dictionary <string, Dictionary <string, string> > interfaceNameMaps = new Dictionary
                                                                                  <string, Dictionary <string, string> >();

            // rename methods and fields
            foreach (ClassWrapperNode node in lstInterfaces)
            {
                StructClass cl = node.GetClassStruct();
                Dictionary <string, string> names = new Dictionary <string, string>();
                // merge information on super interfaces
                foreach (string ifName in cl.GetInterfaceNames())
                {
                    Dictionary <string, string> mapInt = interfaceNameMaps.GetOrNull(ifName);
                    if (mapInt != null)
                    {
                        Sharpen.Collections.PutAll(names, mapInt);
                    }
                }
                RenameClassIdentifiers(cl, names);
                Sharpen.Collections.Put(interfaceNameMaps, cl.qualifiedName, names);
            }
            this.interfaceNameMaps = interfaceNameMaps;
        }
 public ClassNode(int type, StructClass classStruct)
 {
     // FIXME: redundant?
     this.type        = type;
     this.classStruct = classStruct;
     simpleName       = Sharpen.Runtime.Substring(classStruct.qualifiedName, classStruct.qualifiedName
                                                  .LastIndexOf('/') + 1);
 }
Exemple #10
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));
                }
            }
        }
Exemple #11
0
        public static void ClearEnum(ClassWrapper wrapper)
        {
            StructClass cl = wrapper.GetClassStruct();

            // hide values/valueOf methods and super() invocations
            foreach (MethodWrapper method in wrapper.GetMethods())
            {
                StructMethod mt         = method.methodStruct;
                string       name       = mt.GetName();
                string       descriptor = mt.GetDescriptor();
                if ("values".Equals(name))
                {
                    if (descriptor.Equals("()[L" + cl.qualifiedName + ";"))
                    {
                        wrapper.GetHiddenMembers().Add(InterpreterUtil.MakeUniqueKey(name, descriptor));
                    }
                }
                else if ("valueOf".Equals(name))
                {
                    if (descriptor.Equals("(Ljava/lang/String;)L" + cl.qualifiedName + ";"))
                    {
                        wrapper.GetHiddenMembers().Add(InterpreterUtil.MakeUniqueKey(name, descriptor));
                    }
                }
                else if (ICodeConstants.Init_Name.Equals(name))
                {
                    Statement firstData = Statements.FindFirstData(method.root);
                    if (firstData != null && !(firstData.GetExprents().Count == 0))
                    {
                        Exprent exprent = firstData.GetExprents()[0];
                        if (exprent.type == Exprent.Exprent_Invocation)
                        {
                            InvocationExprent invExpr = (InvocationExprent)exprent;
                            if (Statements.IsInvocationInitConstructor(invExpr, method, wrapper, false))
                            {
                                firstData.GetExprents().RemoveAtReturningValue(0);
                            }
                        }
                    }
                }
            }
            // hide synthetic fields of enum and it's constants
            foreach (StructField fd in cl.GetFields())
            {
                string descriptor = fd.GetDescriptor();
                if (fd.IsSynthetic() && descriptor.Equals("[L" + cl.qualifiedName + ";"))
                {
                    wrapper.GetHiddenMembers().Add(InterpreterUtil.MakeUniqueKey(fd.GetName(), descriptor
                                                                                 ));
                }
            }
        }
        private void SetInitVars(RootStatement root)
        {
            bool             thisVar = !method.HasModifier(ICodeConstants.Acc_Static);
            MethodDescriptor md      = methodDescriptor;

            if (thisVar)
            {
                StructClass cl = (StructClass)DecompilerContext.GetProperty(DecompilerContext.Current_Class
                                                                            );
                VarType clType = new VarType(ICodeConstants.Type_Object, 0, cl.qualifiedName);
                Sharpen.Collections.Put(mapExprentMinTypes, new VarVersionPair(0, 1), clType);
                Sharpen.Collections.Put(mapExprentMaxTypes, new VarVersionPair(0, 1), clType);
            }
            int varIndex = 0;

            for (int i = 0; i < [email protected]; i++)
            {
                Sharpen.Collections.Put(mapExprentMinTypes, new VarVersionPair(varIndex + (thisVar
                                         ? 1 : 0), 1), md.@params[i]);
                Sharpen.Collections.Put(mapExprentMaxTypes, new VarVersionPair(varIndex + (thisVar
                                         ? 1 : 0), 1), md.@params[i]);
                varIndex += md.@params[i].stackSize;
            }
            // catch variables
            LinkedList <Statement> stack = new LinkedList <Statement>();

            stack.AddLast(root);
            while (!(stack.Count == 0))
            {
                Statement         stat    = Sharpen.Collections.RemoveFirst(stack);
                List <VarExprent> lstVars = null;
                if (stat.type == Statement.Type_Catchall)
                {
                    lstVars = ((CatchAllStatement)stat).GetVars();
                }
                else if (stat.type == Statement.Type_Trycatch)
                {
                    lstVars = ((CatchStatement)stat).GetVars();
                }
                if (lstVars != null)
                {
                    foreach (VarExprent var in lstVars)
                    {
                        Sharpen.Collections.Put(mapExprentMinTypes, new VarVersionPair(var.GetIndex(), 1)
                                                , var.GetVarType());
                        Sharpen.Collections.Put(mapExprentMaxTypes, new VarVersionPair(var.GetIndex(), 1)
                                                , var.GetVarType());
                    }
                }
                Sharpen.Collections.AddAll(stack, stat.GetStats());
            }
        }
Exemple #13
0
        private static void ExtractStaticInitializers(ClassWrapper wrapper, MethodWrapper
                                                      method)
        {
            RootStatement root      = method.root;
            StructClass   cl        = wrapper.GetClassStruct();
            Statement     firstData = Statements.FindFirstData(root);

            if (firstData != null)
            {
                bool inlineInitializers = cl.HasModifier(ICodeConstants.Acc_Interface) || cl.HasModifier
                                              (ICodeConstants.Acc_Enum);
                while (!(firstData.GetExprents().Count == 0))
                {
                    Exprent exprent = firstData.GetExprents()[0];
                    bool    found   = false;
                    if (exprent.type == Exprent.Exprent_Assignment)
                    {
                        AssignmentExprent assignExpr = (AssignmentExprent)exprent;
                        if (assignExpr.GetLeft().type == Exprent.Exprent_Field)
                        {
                            FieldExprent fExpr = (FieldExprent)assignExpr.GetLeft();
                            if (fExpr.IsStatic() && fExpr.GetClassname().Equals(cl.qualifiedName) && cl.HasField
                                    (fExpr.GetName(), fExpr.GetDescriptor().descriptorString))
                            {
                                // interfaces fields should always be initialized inline
                                if (inlineInitializers || IsExprentIndependent(assignExpr.GetRight(), method))
                                {
                                    string keyField = InterpreterUtil.MakeUniqueKey(fExpr.GetName(), fExpr.GetDescriptor
                                                                                        ().descriptorString);
                                    if (!wrapper.GetStaticFieldInitializers().ContainsKey(keyField))
                                    {
                                        wrapper.GetStaticFieldInitializers().AddWithKey(assignExpr.GetRight(), keyField);
                                        firstData.GetExprents().RemoveAtReturningValue(0);
                                        found = true;
                                    }
                                }
                            }
                        }
                    }
                    if (!found)
                    {
                        break;
                    }
                }
            }
        }
Exemple #14
0
 public virtual string GetClassContent(StructClass cl)
 {
     try
     {
         TextBuffer buffer = new TextBuffer(ClassesProcessor.Average_Class_Size);
         buffer.Append(DecompilerContext.GetProperty(IFernflowerPreferences.Banner).ToString
                           ());
         classProcessor.WriteClass(cl, buffer);
         return(buffer.ToString());
     }
     catch (Exception t)
     {
         DecompilerContext.GetLogger().WriteMessage("Class " + cl.qualifiedName + " couldn't be fully decompiled."
                                                    , t);
         return(null);
     }
 }
Exemple #15
0
    public static void Main()
    {
        MyStruct struct1 = new MyStruct {
            MyParam1 = 0
        };
        MyStruct struct2 = struct1;

        struct1.MyParam1 = 20;
        Console.WriteLine($"{struct1.GetHashCode()} != {struct2.GetHashCode()}");
        Console.WriteLine($"{struct1.MyParam1} == 20");
        Console.WriteLine($"{struct2.MyParam1} == 0");

        var class1 = new StructClass();
        var class2 = class1;

        Console.WriteLine($"{class1.GetHashCode()} == {class2.GetHashCode()}");
    }
Exemple #16
0
        private void RenameClasses()
        {
            List <ClassWrapperNode> lstClasses = GetReversePostOrderListIterative(rootClasses
                                                                                  );
            Dictionary <string, Dictionary <string, string> > classNameMaps = new Dictionary <string
                                                                                              , Dictionary <string, string> >();

            foreach (ClassWrapperNode node in lstClasses)
            {
                StructClass cl = node.GetClassStruct();
                Dictionary <string, string> names = new Dictionary <string, string>();
                // merge information on super class
                if (cl.superClass != null)
                {
                    Dictionary <string, string> mapClass = classNameMaps.GetOrNull(cl.superClass.GetString
                                                                                       ());
                    if (mapClass != null)
                    {
                        Sharpen.Collections.PutAll(names, mapClass);
                    }
                }
                // merge information on interfaces
                foreach (string ifName in cl.GetInterfaceNames())
                {
                    Dictionary <string, string> mapInt = interfaceNameMaps.GetOrNull(ifName);
                    if (mapInt != null)
                    {
                        Sharpen.Collections.PutAll(names, mapInt);
                    }
                    else
                    {
                        StructClass clintr = context.GetClass(ifName);
                        if (clintr != null)
                        {
                            Sharpen.Collections.PutAll(names, ProcessExternalInterface(clintr));
                        }
                    }
                }
                RenameClassIdentifiers(cl, names);
                if (!(node.GetSubclasses().Count == 0))
                {
                    Sharpen.Collections.Put(classNameMaps, cl.qualifiedName, names);
                }
            }
        }
Exemple #17
0
 public virtual string GetClassEntryName(StructClass cl, string entryName)
 {
     ClassesProcessor.ClassNode node = classProcessor.GetMapRootClasses().GetOrNull(cl
                                                                                    .qualifiedName);
     if (node.type != ClassesProcessor.ClassNode.Class_Root)
     {
         return(null);
     }
     else if (converter != null)
     {
         string simpleClassName = Sharpen.Runtime.Substring(cl.qualifiedName, cl.qualifiedName
                                                            .LastIndexOf('/') + 1);
         return(Sharpen.Runtime.Substring(entryName, 0, entryName.LastIndexOf('/') + 1) +
                simpleClassName + ".java");
     }
     else
     {
         return(Sharpen.Runtime.Substring(entryName, 0, entryName.LastIndexOf(".class")) +
                ".java");
     }
 }
Exemple #18
0
        public virtual bool SimplifyStackVarsStatement(Statement stat, HashSet <int> setReorderedIfs
                                                       , SSAConstructorSparseEx ssa, StructClass cl)
        {
            bool           res         = false;
            List <Exprent> expressions = stat.GetExprents();

            if (expressions == null)
            {
                bool processClass14 = DecompilerContext.GetOption(IFernflowerPreferences.Decompile_Class_1_4
                                                                  );
                while (true)
                {
                    bool changed = false;
                    foreach (Statement st in stat.GetStats())
                    {
                        res    |= SimplifyStackVarsStatement(st, setReorderedIfs, ssa, cl);
                        changed = IfHelper.MergeIfs(st, setReorderedIfs) || BuildIff(st, ssa) || processClass14 &&
                                  CollapseInlinedClass14(st);
                        // collapse composed if's
                        // collapse iff ?: statement
                        // collapse inlined .class property in version 1.4 and before
                        if (changed)
                        {
                            break;
                        }
                    }
                    res |= changed;
                    if (!changed)
                    {
                        break;
                    }
                }
            }
            else
            {
                res = SimplifyStackVarsExprents(expressions, cl);
            }
            return(res);
        }
Exemple #19
0
        private Dictionary <string, string> ProcessExternalInterface(StructClass cl)
        {
            Dictionary <string, string> names = new Dictionary <string, string>();

            foreach (string ifName in cl.GetInterfaceNames())
            {
                Dictionary <string, string> mapInt = interfaceNameMaps.GetOrNull(ifName);
                if (mapInt != null)
                {
                    Sharpen.Collections.PutAll(names, mapInt);
                }
                else
                {
                    StructClass clintr = context.GetClass(ifName);
                    if (clintr != null)
                    {
                        Sharpen.Collections.PutAll(names, ProcessExternalInterface(clintr));
                    }
                }
            }
            RenameClassIdentifiers(cl, names);
            return(names);
        }
        private bool IsVarArgCall()
        {
            StructClass cl = DecompilerContext.GetStructContext().GetClass(classname);

            if (cl != null)
            {
                StructMethod mt = cl.GetMethod(InterpreterUtil.MakeUniqueKey(name, stringDescriptor
                                                                             ));
                if (mt != null)
                {
                    return(mt.HasModifier(ICodeConstants.Acc_Varargs));
                }
            }
            else
            {
                // TODO: tap into IDEA indices to access libraries methods details
                // try to check the class on the classpath
                MethodInfo mtd = ClasspathHelper.FindMethod(classname, name, descriptor);
                return(mtd != null && mtd.GetParameters()
                       .Any(param => Attribute.IsDefined(param, typeof(ParamArrayAttribute))));
            }
            return(false);
        }
Exemple #21
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);
 }
Exemple #22
0
        private void RenameClass(StructClass cl)
        {
            if (!cl.IsOwn())
            {
                return;
            }
            string classOldFullName = cl.qualifiedName;
            // TODO: rename packages
            string clSimpleName = ConverterHelper.GetSimpleClassName(classOldFullName);

            if (helper.ToBeRenamed(IIdentifierRenamer.Type.Element_Class, clSimpleName, null,
                                   null))
            {
                string classNewFullName;
                do
                {
                    string classname = helper.GetNextClassName(classOldFullName, ConverterHelper.GetSimpleClassName
                                                                   (classOldFullName));
                    classNewFullName = ConverterHelper.ReplaceSimpleClassName(classOldFullName, classname
                                                                              );
                }while (context.GetClasses().ContainsKey(classNewFullName));
                interceptor.AddName(classOldFullName, classNewFullName);
            }
        }
Exemple #23
0
        public virtual void SimplifyStackVars(RootStatement root, StructMethod mt, StructClass
                                              cl)
        {
            HashSet <int>           setReorderedIfs = new HashSet <int>();
            SSAUConstructorSparseEx ssau            = null;

            while (true)
            {
                bool found = false;
                SSAConstructorSparseEx ssa = new SSAConstructorSparseEx();
                ssa.SplitVariables(root, mt);
                SimplifyExprentsHelper sehelper = new SimplifyExprentsHelper(ssau == null);
                while (sehelper.SimplifyStackVarsStatement(root, setReorderedIfs, ssa, cl))
                {
                    found = true;
                }
                SetVersionsToNull(root);
                SequenceHelper.CondenseSequences(root);
                ssau = new SSAUConstructorSparseEx();
                ssau.SplitVariables(root, mt);
                if (IterateStatements(root, ssau))
                {
                    found = true;
                }
                SetVersionsToNull(root);
                if (!found)
                {
                    break;
                }
            }
            // remove unused assignments
            ssau = new SSAUConstructorSparseEx();
            ssau.SplitVariables(root, mt);
            IterateStatements(root, ssau);
            SetVersionsToNull(root);
        }
        private static bool IsAnonymous(StructClass cl, StructClass enclosingCl)
        {
            // checking super class and interfaces
            int[] interfaces = cl.GetInterfaces();
            if (interfaces.Length > 0)
            {
                bool hasNonTrivialSuperClass = cl.superClass != null && !VarType.Vartype_Object.Equals
                                                   (new VarType(cl.superClass.GetString(), true));
                if (hasNonTrivialSuperClass || interfaces.Length > 1)
                {
                    // can't have multiple 'sources'
                    string message = "Inconsistent anonymous class definition: '" + cl.qualifiedName
                                     + "'. Multiple interfaces and/or super class defined.";
                    DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn
                                                               );
                    return(false);
                }
            }
            else if (cl.superClass == null)
            {
                // neither interface nor super class defined
                string message = "Inconsistent anonymous class definition: '" + cl.qualifiedName
                                 + "'. Neither interface nor super class defined.";
                DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn
                                                           );
                return(false);
            }
            // FIXME: check constructors
            // FIXME: check enclosing class/method
            ConstantPool pool       = enclosingCl.GetPool();
            int          refCounter = 0;
            bool         refNotNew  = false;
            StructEnclosingMethodAttribute attribute = cl.GetAttribute(StructGeneralAttribute
                                                                       .Attribute_Enclosing_Method);
            string enclosingMethod = attribute != null?attribute.GetMethodName() : null;

            // checking references in the enclosing class
            foreach (StructMethod mt in enclosingCl.GetMethods())
            {
                if (enclosingMethod != null && !enclosingMethod.Equals(mt.GetName()))
                {
                    continue;
                }
                try
                {
                    mt.ExpandData();
                    InstructionSequence seq = mt.GetInstructionSequence();
                    if (seq != null)
                    {
                        int len = seq.Length();
                        for (int i = 0; i < len; i++)
                        {
                            Instruction instr = seq.GetInstr(i);
                            switch (instr.opcode)
                            {
                            case opc_checkcast:
                            case opc_instanceof:
                            {
                                if (cl.qualifiedName.Equals(pool.GetPrimitiveConstant(instr.Operand(0)).GetString
                                                                ()))
                                {
                                    refCounter++;
                                    refNotNew = true;
                                }
                                break;
                            }

                            case opc_new:
                            case opc_anewarray:
                            case opc_multianewarray:
                            {
                                if (cl.qualifiedName.Equals(pool.GetPrimitiveConstant(instr.Operand(0)).GetString
                                                                ()))
                                {
                                    refCounter++;
                                }
                                break;
                            }

                            case opc_getstatic:
                            case opc_putstatic:
                            {
                                if (cl.qualifiedName.Equals(pool.GetLinkConstant(instr.Operand(0)).classname))
                                {
                                    refCounter++;
                                    refNotNew = true;
                                }
                                break;
                            }
                            }
                        }
                    }
                    mt.ReleaseResources();
                }
                catch (IOException)
                {
                    string message = "Could not read method while checking anonymous class definition: '"
                                     + enclosingCl.qualifiedName + "', '" + InterpreterUtil.MakeUniqueKey(mt.GetName
                                                                                                              (), mt.GetDescriptor()) + "'";
                    DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn
                                                               );
                    return(false);
                }
                if (refCounter > 1 || refNotNew)
                {
                    string message = "Inconsistent references to the class '" + cl.qualifiedName + "' which is supposed to be anonymous";
                    DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn
                                                               );
                    return(false);
                }
            }
            return(true);
        }
Exemple #25
0
        private void BuildInheritanceTree()
        {
            Dictionary <string, ClassWrapperNode> nodes = new Dictionary <string, ClassWrapperNode
                                                                          >();
            Dictionary <string, StructClass> classes        = context.GetClasses();
            List <ClassWrapperNode>          rootClasses    = new List <ClassWrapperNode>();
            List <ClassWrapperNode>          rootInterfaces = new List <ClassWrapperNode>();

            foreach (StructClass cl in classes.Values)
            {
                if (!cl.IsOwn())
                {
                    continue;
                }
                LinkedList <StructClass>      stack         = new LinkedList <StructClass>();
                LinkedList <ClassWrapperNode> stackSubNodes = new LinkedList <ClassWrapperNode>();
                stack.AddLast(cl);
                stackSubNodes.AddLast((ClassWrapperNode)null);
                while (!(stack.Count == 0))
                {
                    StructClass      clStr     = Sharpen.Collections.RemoveFirst(stack);
                    ClassWrapperNode child     = Sharpen.Collections.RemoveFirst(stackSubNodes);
                    ClassWrapperNode node      = nodes.GetOrNull(clStr.qualifiedName);
                    bool             isNewNode = (node == null);
                    if (isNewNode)
                    {
                        Sharpen.Collections.Put(nodes, clStr.qualifiedName, node = new ClassWrapperNode(clStr
                                                                                                        ));
                    }
                    if (child != null)
                    {
                        node.AddSubclass(child);
                    }
                    if (!isNewNode)
                    {
                        break;
                    }
                    else
                    {
                        bool isInterface  = clStr.HasModifier(ICodeConstants.Acc_Interface);
                        bool found_parent = false;
                        if (isInterface)
                        {
                            foreach (string ifName in clStr.GetInterfaceNames())
                            {
                                StructClass clParent = classes.GetOrNull(ifName);
                                if (clParent != null)
                                {
                                    stack.AddLast(clParent);
                                    stackSubNodes.AddLast(node);
                                    found_parent = true;
                                }
                            }
                        }
                        else if (clStr.superClass != null)
                        {
                            // null iff java/lang/Object
                            StructClass clParent = classes.GetOrNull(clStr.superClass.GetString());
                            if (clParent != null)
                            {
                                stack.AddLast(clParent);
                                stackSubNodes.AddLast(node);
                                found_parent = true;
                            }
                        }
                        if (!found_parent)
                        {
                            // no super class or interface
                            (isInterface ? rootInterfaces : rootClasses).Add(node);
                        }
                    }
                }
            }
            this.rootClasses    = rootClasses;
            this.rootInterfaces = rootInterfaces;
        }
        public VarDefinitionHelper(Statement root, StructMethod mt, VarProcessor varproc)
        {
            // statement.id, defined vars
            mapVarDefStatements = new Dictionary <int, Statement>();
            mapStatementVars    = new Dictionary <int, HashSet <int> >();
            implDefVars         = new HashSet <int>();
            this.varproc        = varproc;
            VarNamesCollector vc     = varproc.GetVarNamesCollector();
            bool             thisvar = !mt.HasModifier(ICodeConstants.Acc_Static);
            MethodDescriptor md      = MethodDescriptor.ParseDescriptor(mt.GetDescriptor());
            int paramcount           = 0;

            if (thisvar)
            {
                paramcount = 1;
            }
            paramcount += [email protected];
            // method parameters are implicitly defined
            int varindex = 0;

            for (int i = 0; i < paramcount; i++)
            {
                implDefVars.Add(varindex);
                varproc.SetVarName(new VarVersionPair(varindex, 0), vc.GetFreeName(varindex));
                if (thisvar)
                {
                    if (i == 0)
                    {
                        varindex++;
                    }
                    else
                    {
                        varindex += md.@params[i - 1].stackSize;
                    }
                }
                else
                {
                    varindex += md.@params[i].stackSize;
                }
            }
            if (thisvar)
            {
                StructClass current_class = (StructClass)DecompilerContext.GetProperty(DecompilerContext
                                                                                       .Current_Class);
                Sharpen.Collections.Put(varproc.GetThisVars(), new VarVersionPair(0, 0), current_class
                                        .qualifiedName);
                varproc.SetVarName(new VarVersionPair(0, 0), "this");
                vc.AddName("this");
            }
            // catch variables are implicitly defined
            LinkedList <Statement> stack = new LinkedList <Statement>();

            stack.AddLast(root);
            while (!(stack.Count == 0))
            {
                Statement         st      = Sharpen.Collections.RemoveFirst(stack);
                List <VarExprent> lstVars = null;
                if (st.type == Statement.Type_Catchall)
                {
                    lstVars = ((CatchAllStatement)st).GetVars();
                }
                else if (st.type == Statement.Type_Trycatch)
                {
                    lstVars = ((CatchStatement)st).GetVars();
                }
                if (lstVars != null)
                {
                    foreach (VarExprent var in lstVars)
                    {
                        implDefVars.Add(var.GetIndex());
                        varproc.SetVarName(new VarVersionPair(var), vc.GetFreeName(var.GetIndex()));
                        var.SetDefinition(true);
                    }
                }
                Sharpen.Collections.AddAll(stack, st.GetStats());
            }
            InitStatement(root);
        }
 public void TestObjectWithStruct()
 {
     var nodeContainer = new NodeContainer();
     var instance = new StructClass { Member1 = 3, Member2 = new Struct() };
     var rootNode = nodeContainer.GetOrCreateNode(instance);
     var visitor = new TestVisitor();
     visitor.Visit(rootNode);
     var expectedNodes = new[]
     {
         rootNode,
         rootNode.TryGetChild(nameof(StructClass.Member1)),
         rootNode.TryGetChild(nameof(StructClass.Member2)),
         rootNode.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member1)),
         rootNode.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)),
     };
     var expectedPaths = new[]
     {
         new GraphNodePath(rootNode),
         new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member1)),
         new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)),
         new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)).PushMember(nameof(Struct.Member1)),
         new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)).PushMember(nameof(Struct.Member2)),
     };
     VerifyNodesAndPath(expectedNodes, expectedPaths, visitor);
 }
 public void TestObjectWithStruct()
 {
     var nodeContainer = new NodeContainer();
     var instance1 = new StructClass { Member1 = 3, Member2 = new Struct { Member2 = new SimpleClass() } };
     var instance2 = new StructClass { Member1 = 3, Member2 = new Struct { Member2 = new SimpleClass() } };
     var source = nodeContainer.GetOrCreateNode(instance1);
     var target = nodeContainer.GetOrCreateNode(instance2);
     var linker = new TestLinker();
     linker.LinkGraph(source, target);
     var expectedLinks = new Dictionary<IGraphNode, IGraphNode>
     {
         { source, target },
         { source.TryGetChild(nameof(StructClass.Member1)), target.TryGetChild(nameof(StructClass.Member1)) },
         { source.TryGetChild(nameof(StructClass.Member2)), target.TryGetChild(nameof(StructClass.Member2)) },
         { source.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member1)), target.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member1)) },
         { source.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)), target.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)) },
         { source.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)).Target, target.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)).Target },
         { source.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)).Target.TryGetChild(nameof(SimpleClass.Member1)), target.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)).Target.TryGetChild(nameof(SimpleClass.Member1)) },
         { source.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)).Target.TryGetChild(nameof(SimpleClass.Member2)), target.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)).Target.TryGetChild(nameof(SimpleClass.Member2)) },
     };
     VerifyLinks(expectedLinks, linker);
 }
Exemple #29
0
 public ClassWrapper(StructClass classStruct)
 {
     this.classStruct = classStruct;
 }
Exemple #30
0
        private bool SimplifyStackVarsExprents(List <Exprent> list, StructClass cl)
        {
            bool res   = false;
            int  index = 0;

            while (index < list.Count)
            {
                Exprent current = list[index];
                Exprent ret     = IsSimpleConstructorInvocation(current);
                if (ret != null)
                {
                    list[index] = ret;
                    res         = true;
                    continue;
                }
                // lambda expression (Java 8)
                ret = IsLambda(current, cl);
                if (ret != null)
                {
                    list[index] = ret;
                    res         = true;
                    continue;
                }
                // remove monitor exit
                if (IsMonitorExit(current))
                {
                    list.RemoveAtReturningValue(index);
                    res = true;
                    continue;
                }
                // trivial assignment of a stack variable
                if (IsTrivialStackAssignment(current))
                {
                    list.RemoveAtReturningValue(index);
                    res = true;
                    continue;
                }
                if (index == list.Count - 1)
                {
                    break;
                }
                Exprent next = list[index + 1];
                // constructor invocation
                if (IsConstructorInvocationRemote(list, index))
                {
                    list.RemoveAtReturningValue(index);
                    res = true;
                    continue;
                }
                // remove getClass() invocation, which is part of a qualified new
                if (DecompilerContext.GetOption(IFernflowerPreferences.Remove_Get_Class_New))
                {
                    if (IsQualifiedNewGetClass(current, next))
                    {
                        list.RemoveAtReturningValue(index);
                        res = true;
                        continue;
                    }
                }
                // direct initialization of an array
                int arrCount = IsArrayInitializer(list, index);
                if (arrCount > 0)
                {
                    for (int i = 0; i < arrCount; i++)
                    {
                        list.RemoveAtReturningValue(index + 1);
                    }
                    res = true;
                    continue;
                }
                // add array initializer expression
                if (AddArrayInitializer(current, next))
                {
                    list.RemoveAtReturningValue(index + 1);
                    res = true;
                    continue;
                }
                // integer ++expr and --expr  (except for vars!)
                Exprent func = IsPPIorMMI(current);
                if (func != null)
                {
                    list[index] = func;
                    res         = true;
                    continue;
                }
                // expr++ and expr--
                if (IsIPPorIMM(current, next) || IsIPPorIMM2(current, next))
                {
                    list.RemoveAtReturningValue(index + 1);
                    res = true;
                    continue;
                }
                // assignment on stack
                if (IsStackAssignment(current, next))
                {
                    list.RemoveAtReturningValue(index + 1);
                    res = true;
                    continue;
                }
                if (!firstInvocation && IsStackAssignment2(current, next))
                {
                    list.RemoveAtReturningValue(index + 1);
                    res = true;
                    continue;
                }
                index++;
            }
            return(res);
        }
Exemple #31
0
        private static void ExtractDynamicInitializers(ClassWrapper wrapper)
        {
            StructClass cl          = wrapper.GetClassStruct();
            bool        isAnonymous = DecompilerContext.GetClassProcessor().GetMapRootClasses().GetOrNull
                                          (cl.qualifiedName).type == ClassesProcessor.ClassNode.Class_Anonymous;
            List <List <Exprent> > lstFirst          = new List <List <Exprent> >();
            List <MethodWrapper>   lstMethodWrappers = new List <MethodWrapper>();

            foreach (MethodWrapper method in wrapper.GetMethods())
            {
                if (ICodeConstants.Init_Name.Equals(method.methodStruct.GetName()) && method.root
                    != null)
                {
                    // successfully decompiled constructor
                    Statement firstData = Statements.FindFirstData(method.root);
                    if (firstData == null || (firstData.GetExprents().Count == 0))
                    {
                        return;
                    }
                    lstFirst.Add(firstData.GetExprents());
                    lstMethodWrappers.Add(method);
                    Exprent exprent = firstData.GetExprents()[0];
                    if (!isAnonymous)
                    {
                        // FIXME: doesn't make sense
                        if (exprent.type != Exprent.Exprent_Invocation || !Statements.IsInvocationInitConstructor
                                ((InvocationExprent)exprent, method, wrapper, false))
                        {
                            return;
                        }
                    }
                }
            }
            if ((lstFirst.Count == 0))
            {
                return;
            }
            while (true)
            {
                string  fieldWithDescr = null;
                Exprent value          = null;
                for (int i = 0; i < lstFirst.Count; i++)
                {
                    List <Exprent> lst = lstFirst[i];
                    if (lst.Count < (isAnonymous ? 1 : 2))
                    {
                        return;
                    }
                    Exprent exprent = lst[isAnonymous ? 0 : 1];
                    bool    found   = false;
                    if (exprent.type == Exprent.Exprent_Assignment)
                    {
                        AssignmentExprent assignExpr = (AssignmentExprent)exprent;
                        if (assignExpr.GetLeft().type == Exprent.Exprent_Field)
                        {
                            FieldExprent fExpr = (FieldExprent)assignExpr.GetLeft();
                            if (!fExpr.IsStatic() && fExpr.GetClassname().Equals(cl.qualifiedName) && cl.HasField
                                    (fExpr.GetName(), fExpr.GetDescriptor().descriptorString))
                            {
                                // check for the physical existence of the field. Could be defined in a superclass.
                                if (IsExprentIndependent(assignExpr.GetRight(), lstMethodWrappers[i]))
                                {
                                    string fieldKey = InterpreterUtil.MakeUniqueKey(fExpr.GetName(), fExpr.GetDescriptor
                                                                                        ().descriptorString);
                                    if (fieldWithDescr == null)
                                    {
                                        fieldWithDescr = fieldKey;
                                        value          = assignExpr.GetRight();
                                    }
                                    else if (!fieldWithDescr.Equals(fieldKey) || !value.Equals(assignExpr.GetRight()))
                                    {
                                        return;
                                    }
                                    found = true;
                                }
                            }
                        }
                    }
                    if (!found)
                    {
                        return;
                    }
                }
                if (!wrapper.GetDynamicFieldInitializers().ContainsKey(fieldWithDescr))
                {
                    wrapper.GetDynamicFieldInitializers().AddWithKey(value, fieldWithDescr);
                    foreach (List <Exprent> lst in lstFirst)
                    {
                        lst.RemoveAtReturningValue(isAnonymous ? 0 : 1);
                    }
                }
                else
                {
                    return;
                }
            }
        }
        public virtual void LoadClasses(IIdentifierRenamer renamer)
        {
            Dictionary <string, ClassesProcessor.Inner> mapInnerClasses = new Dictionary <string
                                                                                          , ClassesProcessor.Inner>();
            Dictionary <string, HashSet <string> > mapNestedClassReferences = new Dictionary <string
                                                                                              , HashSet <string> >();
            Dictionary <string, HashSet <string> > mapEnclosingClassReferences = new Dictionary
                                                                                 <string, HashSet <string> >();
            Dictionary <string, string> mapNewSimpleNames = new Dictionary <string, string>();
            bool bDecompileInner = DecompilerContext.GetOption(IFernflowerPreferences.Decompile_Inner
                                                               );
            bool verifyAnonymousClasses = DecompilerContext.GetOption(IFernflowerPreferences
                                                                      .Verify_Anonymous_Classes);

            // create class nodes
            foreach (StructClass cl in context.GetClasses().Values)
            {
                if (cl.IsOwn() && !mapRootClasses.ContainsKey(cl.qualifiedName))
                {
                    if (bDecompileInner)
                    {
                        StructInnerClassesAttribute inner = cl.GetAttribute(StructGeneralAttribute.Attribute_Inner_Classes
                                                                            );
                        if (inner != null)
                        {
                            foreach (StructInnerClassesAttribute.Entry entry in inner.GetEntries())
                            {
                                string innerName = entry.innerName;
                                // original simple name
                                string simpleName = entry.simpleName;
                                string savedName  = mapNewSimpleNames.GetOrNull(innerName);
                                if (savedName != null)
                                {
                                    simpleName = savedName;
                                }
                                else if (simpleName != null && renamer != null && renamer.ToBeRenamed(IIdentifierRenamer.Type
                                                                                                      .Element_Class, simpleName, null, null))
                                {
                                    simpleName = renamer.GetNextClassName(innerName, simpleName);
                                    Sharpen.Collections.Put(mapNewSimpleNames, innerName, simpleName);
                                }
                                ClassesProcessor.Inner rec = new ClassesProcessor.Inner();
                                rec.simpleName = simpleName;
                                rec.type       = entry.simpleNameIdx == 0 ? ClassesProcessor.ClassNode.Class_Anonymous :
                                                 entry.outerNameIdx == 0 ? ClassesProcessor.ClassNode.Class_Local : ClassesProcessor.ClassNode
                                                 .Class_Member;
                                rec.accessFlags = entry.accessFlags;
                                // enclosing class
                                string enclClassName = entry.outerNameIdx != 0 ? entry.enclosingName : cl.qualifiedName;
                                if (enclClassName == null || innerName.Equals(enclClassName))
                                {
                                    continue;
                                }
                                // invalid name or self reference
                                if (rec.type == ClassesProcessor.ClassNode.Class_Member && !innerName.Equals(enclClassName
                                                                                                             + '$' + entry.simpleName))
                                {
                                    continue;
                                }
                                // not a real inner class
                                StructClass enclosingClass = context.GetClasses().GetOrNull(enclClassName);
                                if (enclosingClass != null && enclosingClass.IsOwn())
                                {
                                    // own classes only
                                    ClassesProcessor.Inner existingRec = mapInnerClasses.GetOrNull(innerName);
                                    if (existingRec == null)
                                    {
                                        Sharpen.Collections.Put(mapInnerClasses, innerName, rec);
                                    }
                                    else if (!ClassesProcessor.Inner.Equal(existingRec, rec))
                                    {
                                        string message = "Inconsistent inner class entries for " + innerName + "!";
                                        DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn
                                                                                   );
                                    }
                                    // reference to the nested class
                                    mapNestedClassReferences.ComputeIfAbsent(enclClassName, (string k) => new HashSet
                                                                             <string>()).Add(innerName);
                                    // reference to the enclosing class
                                    mapEnclosingClassReferences.ComputeIfAbsent(innerName, (string k) => new HashSet <
                                                                                    string>()).Add(enclClassName);
                                }
                            }
                        }
                    }
                    ClassesProcessor.ClassNode node = new ClassesProcessor.ClassNode(ClassesProcessor.ClassNode
                                                                                     .Class_Root, cl);
                    node.access = cl.GetAccessFlags();
                    Sharpen.Collections.Put(mapRootClasses, cl.qualifiedName, node);
                }
            }
            if (bDecompileInner)
            {
                // connect nested classes
                foreach (KeyValuePair <string, ClassesProcessor.ClassNode> ent in mapRootClasses)
                {
                    // root class?
                    if (!mapInnerClasses.ContainsKey(ent.Key))
                    {
                        HashSet <string>    setVisited = new HashSet <string>();
                        LinkedList <string> stack      = new LinkedList <string>();
                        stack.AddLast(ent.Key);
                        setVisited.Add(ent.Key);
                        while (!(stack.Count == 0))
                        {
                            string superClass = Sharpen.Collections.RemoveFirst(stack);
                            ClassesProcessor.ClassNode superNode        = mapRootClasses.GetOrNull(superClass);
                            HashSet <string>           setNestedClasses = mapNestedClassReferences.GetOrNull(superClass);
                            if (setNestedClasses != null)
                            {
                                StructClass scl = superNode.classStruct;
                                StructInnerClassesAttribute inner = scl.GetAttribute(StructGeneralAttribute.Attribute_Inner_Classes
                                                                                     );
                                if (inner == null || (inner.GetEntries().Count == 0))
                                {
                                    DecompilerContext.GetLogger().WriteMessage(superClass + " does not contain inner classes!"
                                                                               , IFernflowerLogger.Severity.Warn);
                                    continue;
                                }
                                foreach (StructInnerClassesAttribute.Entry entry in inner.GetEntries())
                                {
                                    string nestedClass = entry.innerName;
                                    if (!setNestedClasses.Contains(nestedClass))
                                    {
                                        continue;
                                    }
                                    if (!setVisited.Add(nestedClass))
                                    {
                                        continue;
                                    }
                                    ClassesProcessor.ClassNode nestedNode = mapRootClasses.GetOrNull(nestedClass);
                                    if (nestedNode == null)
                                    {
                                        DecompilerContext.GetLogger().WriteMessage("Nested class " + nestedClass + " missing!"
                                                                                   , IFernflowerLogger.Severity.Warn);
                                        continue;
                                    }
                                    ClassesProcessor.Inner rec = mapInnerClasses.GetOrNull(nestedClass);
                                    //if ((Integer)arr[2] == ClassNode.CLASS_MEMBER) {
                                    // FIXME: check for consistent naming
                                    //}
                                    nestedNode.simpleName = rec.simpleName;
                                    nestedNode.type       = rec.type;
                                    nestedNode.access     = rec.accessFlags;
                                    // sanity checks of the class supposed to be anonymous
                                    if (verifyAnonymousClasses && nestedNode.type == ClassesProcessor.ClassNode.Class_Anonymous &&
                                        !IsAnonymous(nestedNode.classStruct, scl))
                                    {
                                        nestedNode.type = ClassesProcessor.ClassNode.Class_Local;
                                    }
                                    if (nestedNode.type == ClassesProcessor.ClassNode.Class_Anonymous)
                                    {
                                        StructClass cl = nestedNode.classStruct;
                                        // remove static if anonymous class (a common compiler bug)
                                        nestedNode.access &= ~ICodeConstants.Acc_Static;
                                        int[] interfaces = cl.GetInterfaces();
                                        if (interfaces.Length > 0)
                                        {
                                            nestedNode.anonymousClassType = new VarType(cl.GetInterface(0), true);
                                        }
                                        else
                                        {
                                            nestedNode.anonymousClassType = new VarType(cl.superClass.GetString(), true);
                                        }
                                    }
                                    else if (nestedNode.type == ClassesProcessor.ClassNode.Class_Local)
                                    {
                                        // only abstract and final are permitted (a common compiler bug)
                                        nestedNode.access &= (ICodeConstants.Acc_Abstract | ICodeConstants.Acc_Final);
                                    }
                                    superNode.nested.Add(nestedNode);
                                    nestedNode.parent = superNode;
                                    Sharpen.Collections.AddAll(nestedNode.enclosingClasses, mapEnclosingClassReferences
                                                               .GetOrNull(nestedClass));
                                    stack.AddLast(nestedClass);
                                }
                            }
                        }
                    }
                }
            }
        }