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)); } } }
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); }
public virtual string GetShortName(string fullName, bool imported) { ClassesProcessor.ClassNode node = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(fullName.Replace('.', '/')); //todo[r.sh] anonymous classes? string result = null; if (node != null && node.classStruct.IsOwn()) { result = node.simpleName; while (node.parent != null && node.type == ClassesProcessor.ClassNode.Class_Member ) { //noinspection StringConcatenationInLoop result = node.parent.simpleName + '.' + result; node = node.parent; } if (node.type == ClassesProcessor.ClassNode.Class_Root) { fullName = node.classStruct.qualifiedName; fullName = fullName.Replace('/', '.'); } else { return(result); } } else { fullName = fullName.Replace('$', '.'); } string shortName = fullName; string packageName = string.Empty; int lastDot = fullName.LastIndexOf('.'); if (lastDot >= 0) { shortName = Sharpen.Runtime.Substring(fullName, lastDot + 1); packageName = Sharpen.Runtime.Substring(fullName, 0, lastDot); } StructContext context = DecompilerContext.GetStructContext(); // check for another class which could 'shadow' this one. Three cases: // 1) class with the same short name in the current package // 2) class with the same short name in the default package // 3) inner class with the same short name in the current class, a super class, or an implemented interface bool existsDefaultClass = (context.GetClass(currentPackageSlash + shortName) != null && !packageName.Equals(currentPackagePoint)) || (context.GetClass(shortName) != null && !(currentPackagePoint.Length == 0)) || setInnerClassNames.Contains(shortName ); // current package // default package // inner class if (existsDefaultClass || (mapSimpleNames.ContainsKey(shortName) && !packageName. Equals(mapSimpleNames.GetOrNull(shortName)))) { // don't return full name because if the class is a inner class, full name refers to the parent full name, not the child full name return(result == null ? fullName : (packageName + "." + result)); } else if (!mapSimpleNames.ContainsKey(shortName)) { Sharpen.Collections.Put(mapSimpleNames, shortName, packageName); if (!imported) { setNotImportedNames.Add(shortName); } } return(result == null ? shortName : result); }
private BitSet GetAmbiguousParameters() { StructClass cl = DecompilerContext.GetStructContext().GetClass(classname); if (cl == null) { return(Empty_Bit_Set); } // check number of matches List <MethodDescriptor> matches = new List <MethodDescriptor>(); foreach (StructMethod mt in cl.GetMethods()) { if (name.Equals(mt.GetName())) { MethodDescriptor md = MethodDescriptor.ParseDescriptor(mt.GetDescriptor()); if ([email protected] == [email protected]) { for (int i = 0; i < [email protected]; i++) { if (md.@params[i].typeFamily != descriptor.@params[i].typeFamily) { goto nextMethod_continue; } } matches.Add(md); } } } nextMethod_break :; nextMethod_continue : if (matches.Count == 1) { return(Empty_Bit_Set); } // check if a call is unambiguous StructMethod mt_1 = cl.GetMethod(InterpreterUtil.MakeUniqueKey(name, stringDescriptor )); if (mt_1 != null) { MethodDescriptor md = MethodDescriptor.ParseDescriptor(mt_1.GetDescriptor()); if ([email protected] == lstParameters.Count) { bool exact = true; for (int i = 0; i < [email protected]; i++) { if (!md.@params[i].Equals(lstParameters[i].GetExprType())) { exact = false; break; } } if (exact) { return(Empty_Bit_Set); } } } // mark parameters BitSet ambiguous = new BitSet([email protected]); for (int i = 0; i < [email protected]; i++) { VarType paramType = descriptor.@params[i]; foreach (MethodDescriptor md in matches) { if (!paramType.Equals(md.@params[i])) { ambiguous.Set(i); break; } } } return(ambiguous); }
public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buf = new TextBuffer(); string super_qualifier = null; bool isInstanceThis = false; tracer.AddMapping(bytecode); if (instance is InvocationExprent) { ((InvocationExprent)instance).MarkUsingBoxingResult(); } if (isStatic__) { if (IsBoxingCall() && canIgnoreBoxing) { // process general "boxing" calls, e.g. 'Object[] data = { true }' or 'Byte b = 123' // here 'byte' and 'short' values do not need an explicit narrowing type cast ExprProcessor.GetCastedExprent(lstParameters[0], descriptor.@params[0], buf, indent , false, false, false, false, tracer); return(buf); } ClassesProcessor.ClassNode node = (ClassesProcessor.ClassNode)DecompilerContext.GetProperty (DecompilerContext.Current_Class_Node); if (node == null || !classname.Equals(node.classStruct.qualifiedName)) { buf.Append(DecompilerContext.GetImportCollector().GetShortNameInClassContext(ExprProcessor .BuildJavaClassName(classname))); } } else { if (instance != null && instance.type == Exprent.Exprent_Var) { VarExprent instVar = (VarExprent)instance; VarVersionPair varPair = new VarVersionPair(instVar); VarProcessor varProc = instVar.GetProcessor(); if (varProc == null) { MethodWrapper currentMethod = (MethodWrapper)DecompilerContext.GetProperty(DecompilerContext .Current_Method_Wrapper); if (currentMethod != null) { varProc = currentMethod.varproc; } } string this_classname = null; if (varProc != null) { this_classname = varProc.GetThisVars().GetOrNull(varPair); } if (this_classname != null) { isInstanceThis = true; if (invocationTyp == Invoke_Special) { if (!classname.Equals(this_classname)) { // TODO: direct comparison to the super class? StructClass cl = DecompilerContext.GetStructContext().GetClass(classname); bool isInterface = cl != null && cl.HasModifier(ICodeConstants.Acc_Interface); super_qualifier = !isInterface ? this_classname : classname; } } } } if (functype == Typ_General) { if (super_qualifier != null) { TextUtil.WriteQualifiedSuper(buf, super_qualifier); } else if (instance != null) { TextBuffer res = instance.ToJava(indent, tracer); if (IsUnboxingCall()) { // we don't print the unboxing call - no need to bother with the instance wrapping / casting buf.Append(res); return(buf); } VarType rightType = instance.GetExprType(); VarType leftType = new VarType(ICodeConstants.Type_Object, 0, classname); if (rightType.Equals(VarType.Vartype_Object) && !leftType.Equals(rightType)) { buf.Append("((").Append(ExprProcessor.GetCastTypeName(leftType)).Append(")"); if (instance.GetPrecedence() >= FunctionExprent.GetPrecedence(FunctionExprent.Function_Cast )) { res.Enclose("(", ")"); } buf.Append(res).Append(")"); } else if (instance.GetPrecedence() > GetPrecedence()) { buf.Append("(").Append(res).Append(")"); } else { buf.Append(res); } } } } switch (functype) { case Typ_General: { if (VarExprent.Var_Nameless_Enclosure.Equals(buf.ToString())) { buf = new TextBuffer(); } if (buf.Length() > 0) { buf.Append("."); } buf.Append(name); if (invocationTyp == Invoke_Dynamic) { buf.Append("<invokedynamic>"); } buf.Append("("); break; } case Typ_Clinit: { throw new Exception("Explicit invocation of " + ICodeConstants.Clinit_Name); } case Typ_Init: { if (super_qualifier != null) { buf.Append("super("); } else if (isInstanceThis) { buf.Append("this("); } else if (instance != null) { buf.Append(instance.ToJava(indent, tracer)).Append(".<init>("); } else { throw new Exception("Unrecognized invocation of " + ICodeConstants.Init_Name); } break; } } List <VarVersionPair> mask = null; bool isEnum = false; if (functype == Typ_Init) { ClassesProcessor.ClassNode newNode = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(classname); if (newNode != null) { mask = ExprUtil.GetSyntheticParametersMask(newNode, stringDescriptor, lstParameters .Count); isEnum = newNode.classStruct.HasModifier(ICodeConstants.Acc_Enum) && DecompilerContext .GetOption(IFernflowerPreferences.Decompile_Enum); } } BitSet setAmbiguousParameters = GetAmbiguousParameters(); // omit 'new Type[] {}' for the last parameter of a vararg method call if (lstParameters.Count == [email protected] && IsVarArgCall()) { Exprent lastParam = lstParameters[lstParameters.Count - 1]; if (lastParam.type == Exprent_New && lastParam.GetExprType().arrayDim >= 1) { ((NewExprent)lastParam).SetVarArgParam(true); } } bool firstParameter = true; int start = isEnum ? 2 : 0; for (int i = start; i < lstParameters.Count; i++) { if (mask == null || mask[i] == null) { TextBuffer buff = new TextBuffer(); bool ambiguous = setAmbiguousParameters.Get(i); // 'byte' and 'short' literals need an explicit narrowing type cast when used as a parameter ExprProcessor.GetCastedExprent(lstParameters[i], descriptor.@params[i], buff, indent , true, ambiguous, true, true, tracer); // the last "new Object[0]" in the vararg call is not printed if (buff.Length() > 0) { if (!firstParameter) { buf.Append(", "); } buf.Append(buff); } firstParameter = false; } } buf.Append(')'); return(buf); }