/** * Adds a method to the output. * * @param code The code the method belongs to. * @param resolvedMethod The method to add to the output. * @param className The name of the enclosing class the method belongs to. * @param sb The string builder the output is appended to. * @return True, if the method has code. False, if the method is just a declaration. */ private static boolean addMethod( final ResolvedCode code, final ResolvedMethod resolvedMethod, final String className, final StringBuilder sb) { sb.append("\t"); final String flattenedReturnType = ActionScript3Helpers.flattenNamespaceName(resolvedMethod.getReturnType()); sb.append(flattenedReturnType); if (!flattenedReturnType.isEmpty()) { // This path is taken for all methods but constructors. sb.append(" "); } final String functionName = ActionScript3Helpers.flattenNamespaceName(resolvedMethod.getName()); if (functionName.startsWith(className)) { // To make code more readable, strip fully qualified type // information. sb.append(functionName.substring(className.length() + 1)); } else { sb.append(functionName); } sb.append("("); // Print the method arguments. for (final String[] argument : resolvedMethod.getArguments()) { if (argument != resolvedMethod.getArguments().get(0)) { sb.append(", "); } sb.append(ActionScript3Helpers.flattenNamespaceName(argument)); } sb.append(")"); // Print the code. final AS3Code methodCode = resolvedMethod.getCode(); if (methodCode == null) { sb.append(";\n"); return false; } else { sb.append("\n"); sb.append("\t{"); sb.append("\n"); sb.append(getCodeText(code, methodCode, "\t\t")); sb.append("\t}\n"); return true; } }
/** * Adds the class header to the output. * * @param resolvedClass Provides the class information. * @param sb The string builder the output is appended to. */ private static void addClassHeader(final ResolvedClass resolvedClass, final StringBuilder sb) { sb.append("class "); // Add the class name. final String className = ActionScript3Helpers.flattenNamespaceName(resolvedClass.getName()); sb.append(className); // Add the opening class parentheses. sb.append("\n{\n"); }
/** * Resolves and adds an multiname instruction to the output. * * @param sb The string builder the output is appended to. * @param mnemonic The mnemonic of the instruction. * @param multiName The multiname index. * @param code The code the instruction belongs to. */ private static void addMultiname( final StringBuilder sb, final String mnemonic, final int multiName, final ResolvedCode code) { final String[] multinameString = code.resolveMultiname(multiName); sb.append(mnemonic); sb.append(" "); if (multinameString == null) { sb.append(String.format("??? [0x%08X]", multiName)); } else { sb.append( String.format( "%s [0x%08X]", ActionScript3Helpers.flattenNamespaceName(multinameString), multiName)); } }
/** * Generates a printable string that represents all code in a given resolved ActionScript 3 code * snippet. * * @param code The resolved code to display. * @return The generated ActionScript 3 code string. */ public static String getCodeText(final ResolvedCode code) { final StringBuilder sb = new StringBuilder(); for (final ResolvedClass resolvedClass : code.getClasses()) { // Start out with the class definition. addClassHeader(resolvedClass, sb); boolean hadCode = false; // Start preparing all the methods for printing. Add the instance // constructor and the class constructor for printing. final ResolvedMethod staticConstructor = resolvedClass.getStaticConstructor(); final ResolvedMethod constructor = resolvedClass.getConstructor(); final List<ResolvedMethod> resolvedMethods = resolvedClass.getMethods(); resolvedMethods.add(0, constructor); if (staticConstructor.getCode() != null) { // Only add the static constructor if it actually has code. resolvedMethods.add(0, staticConstructor); } final String className = ActionScript3Helpers.flattenNamespaceName(resolvedClass.getName()); // Print the individual methods now. for (final ResolvedMethod resolvedMethod : resolvedMethods) { if (resolvedMethod != resolvedMethods.get(0)) { if (hadCode || resolvedMethod.getCode() != null) { sb.append("\n"); } } hadCode = addMethod(code, resolvedMethod, className, sb); } addClassFooter(sb); } return sb.toString(); }