001package Torello.JavaDoc; 002 003 004// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 005// Standard-Java Imports 006// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 007 008import java.io.IOException; 009import java.util.Optional; 010 011 012// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 013// Java-HTML Imports 014// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 015 016import Torello.Java.*; 017 018import static Torello.Java.C.*; 019import static Torello.JavaDoc.PF.*; 020 021import Torello.Java.Additional.Ret2; 022 023import Torello.JDUInternal.DATA_RECORDS.MainLoopData.CallableSignature; 024 025 026// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 027// The new Source-Code Parser: com.sun.source.* 028// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 029 030import com.sun.source.tree.MethodTree; 031 032 033/** 034 * <B STYLE='color:darkred;'>Reflection Class:</B> 035 * 036 * Holds all information extracted from <CODE>'.java'</CODE> Source-Files about Method's 037 * identified in that file. 038 * 039 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_GET_INST> 040 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_METHOD> 041 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_DIAGRAM> 042 */ 043@JDHeaderBackgroundImg(EmbedTagFileID={"REFLECTION_EXTENSION"}) 044public class Method 045 extends Callable 046 implements java.io.Serializable, Comparable<Method>, Cloneable 047{ 048 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 049 public static final long serialVersionUID = 1; 050 051 /** 052 * The return type of the {@code method}, as a {@code String}. If this is a method with a 053 * {@code 'void'} return-type, this shall be "void". 054 * 055 * <BR /><BR /><B>NOTE:</B> The parsed return-type will include the full-package name of the 056 * returned class (or interface), if the {@code method} returns a class or interface. 057 */ 058 public final String returnType; 059 060 /** 061 * The return type of the {@code method}, as a {@code String}.<BR /><BR /> 062 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_JOW_TITLE> 063 */ 064 public final String returnTypeJOW; 065 066 067 // ******************************************************************************************** 068 // ******************************************************************************************** 069 // Reference-Hook: com.sun.source.tree 070 // ******************************************************************************************** 071 // ******************************************************************************************** 072 073 074 /** 075 * <EMBED CLASS='external-html' DATA-FILE-ID=SSTB_HOOK_FIELD> 076 * 077 * If a user decides to make use of the native Sun/Oracle {@code MethodTree} instance that was 078 * used to build this {@code Method} instance, it may be retrieved from this {@code transient} 079 * field. 080 */ 081 public final transient MethodTree methodTree; 082 083 084 // ******************************************************************************************** 085 // ******************************************************************************************** 086 // Constructor - com.sun.source.tree 087 // ******************************************************************************************** 088 // ******************************************************************************************** 089 090 091 /** 092 * <EMBED CLASS="defs" DATA-KIND=Method DATA-ENTITY=MethodTree> 093 * <EMBED CLASS='external-html' DATA-FILE-ID=RC_DESCRIPTION> 094 * @param mt <EMBED CLASS='external-html' DATA-FILE-ID=RC_PARAM_TREE> 095 * @param util <EMBED CLASS='external-html' DATA-FILE-ID=RC_PARAM_UTIL> 096 */ 097 public Method(MethodTree mt, TreeUtils util) 098 { 099 super(mt, mt.getName().toString(), Entity.METHOD, util); 100 101 this.returnType = mt.getReturnType().toString(); 102 this.returnTypeJOW = StrSource.typeToJavaIdentifier(this.returnType); 103 this.methodTree = mt; 104 } 105 106 107 // ******************************************************************************************** 108 // ******************************************************************************************** 109 // Constructor: Used Internally by SignatureParse / SummaryHTMLFile 110 // ******************************************************************************************** 111 // ******************************************************************************************** 112 113 114 // Ensures that the Version with longer type-information strings is used. 115 // Java Doc often uses longer type strings than is available from the source-code parse 116 // Remember, JavaParser Symbol-Solver doesn't work well, and the Sun/Oracle Parser doesn't have 117 // a linker at all. 118 // 119 // Called from JDUInternal.ParseHTML.SignatureParse: 120 // This is used when the JavaDocHTMLFile is asking that a method be retrieved based on 121 // input from **BOTH** the HTML-File **AND** the Source-File 122 123 public Method(CallableSignature cSig, Method mFromSourceParser) 124 { 125 // Does the same thing as the loop statement below, but for the "parameterTypes" 126 super(cSig, mFromSourceParser); 127 128 // Java Doc always produces "java.lang.String", while JP just gives "String" 129 // 130 // REMEMBER: JP is lazy when it comes to "Package Information" for types. 131 // Java-Doc includes it often - BUT NOT ALWAYS. (See above comment) 132 // 133 // Remember, though, the rest of the JavaParser fields are filled out, Java Doc 134 // leaves out all the other information that JP retrieves. 135 136 this.returnType = 137 (cSig.returnType.length() > mFromSourceParser.returnType.length()) 138 ? cSig.returnType 139 : mFromSourceParser.returnType; 140 141 // This should never matter. They must be identical. 142 this.returnTypeJOW = mFromSourceParser.returnTypeJOW; 143 144 // Save the reference hook 145 this.methodTree = mFromSourceParser.methodTree; 146 } 147 148 // Used for "Synthetic Methods ONLY!" Literally, this line is the only way this particular 149 // Constructor could ever be called: 150 // 151 // From JDUInternal.ParseHTML.SignatureParse: 152 // if (StrCmpr.equalsXOR(cSig.name, "valueOf", "values")) return new Method(cSig); 153 154 public Method(CallableSignature cSig) 155 { 156 // Does the same thing as the loop statement below, but for the "parameterTypes" 157 super(cSig, Entity.METHOD); 158 159 this.returnType = cSig.returnType; 160 this.returnTypeJOW = cSig.returnTypeJOW; 161 this.methodTree = null; 162 } 163 164 165 // ******************************************************************************************** 166 // ******************************************************************************************** 167 // toString() 168 // ******************************************************************************************** 169 // ******************************************************************************************** 170 171 172 /** 173 * Generates a {@code String} of this {@code method}, with most information included. 174 * 175 * <BR /><BR /><B>NOTE:</B> This will not return every piece of information contained by this 176 * class. For example, both the method body, and any possible JavaDoc Comments are not 177 * included. For a more enhanced {@code toString()} version, call the one that accepts flags. 178 * 179 * @return A printable {@code String} of this method. 180 * 181 * @see PF 182 * @see #toString(int) 183 * @see StrCSV#toCSV(String[], boolean, boolean, Integer) 184 */ 185 public String toString() 186 { 187 return 188 "Name: [" + name + "]\n" + 189 "Signature: [" + StrPrint.abbrevEndRDSF(signature, MAX_STR_LEN, true) + "]\n" + 190 "Modifiers: [" + StrCSV.toCSV(modifiers, true, true, null) + "]\n" + 191 printedParameterNamesTS() + 192 printedParameterTypesTS() + 193 "Return Type: [" + returnType + "]\n" + 194 printedExceptionsTS() + 195 196 // This will **NEVER** be null - unless 'this' instance was built from an HTML File, 197 // rather than a source-code file. Instances like that are only used temporarily, and 198 // are garbage collected instantly. Do this check anyway (just in case). 199 200 "Location: " + ((this.location == null) 201 ? "null" 202 : ('[' + this.location.quickSummary() + ']')); 203 } 204 205 /** 206 * This class expects a flags that has been masked using the constant ({@code public, static, 207 * final int}) fields of class {@link PF}. Please view this class for more information about 208 * the flags available for modifying the return-value of this {@code toString()} method. 209 * 210 * @param flags These are the toString flags from class PF ("Print Flags"). View available 211 * flags listed in class {@link PF}. 212 * 213 * @return A printable {@code String} of this method, with comment information included as well. 214 * 215 * @see StrCSV#toCSV(String[], boolean, boolean, Integer) 216 * @see #toString() 217 * @see PF 218 */ 219 public String toString(int flags) 220 { 221 boolean color = (flags & UNIX_COLORS) > 0; 222 Ret2<Boolean, Boolean> jow = jowFlags(flags); 223 224 return 225 printedName("Method", 20, color) + 226 printedSignature(20, color) + 227 printedModifiers(20) + 228 printedParamNames() + 229 printedParamTypes(jow) + 230 printedReturnType(jow, color) + 231 printedExceptions() + 232 printedLocation(20, color, (flags & BRIEF_LOCATION) > 0) + 233 234 // The previous method does not add a '\n' end to the end of the returned string 235 // These are both optional, they add a '\n' AT THE BEGINNING if one of them is included 236 237 printedComments(20, color, (flags & JAVADOC_COMMENTS) > 0) + 238 printedCallableBody(flags); 239 } 240 241 private String printedReturnType(Ret2<Boolean, Boolean> jow, boolean color) 242 { 243 String rt = null, rtJOW = null; 244 245 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 246 // Worry about the colors first 247 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 248 249 if (jow.a || jow.b) 250 rtJOW = color ? (BGREEN + returnTypeJOW + RESET) : returnTypeJOW; 251 252 if (! jow.b) 253 rt = color ? (BGREEN + returnType + RESET) : returnType; 254 255 256 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 257 // Now print the string 258 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 259 260 if (jow.b /*onlyJOW*/) return "Return Simple-Type: [" + rtJOW + "]\n"; 261 262 else if (jow.a /*addJOW*/) return 263 "Return Type: [" + rt + "]\n" + 264 "Return Simple-Type: [" + rtJOW + "]\n"; 265 266 else return "Return Type: [" + rt + "]\n"; 267 } 268 269 270 // ******************************************************************************************** 271 // ******************************************************************************************** 272 // CompareTo & Equals 273 // ******************************************************************************************** 274 // ******************************************************************************************** 275 276 277 /** 278 * Java's {@code interface Comparable<T>} requirements. This does a very simple comparison 279 * using the two method's {@code name} field. If the name comparison will not 280 * suffice in making a decision, then the number of parameters, and parameter-types are used 281 * to making the sort-decision. 282 * 283 * @param m Any other {@code Method} to be compared to {@code 'this' Method} 284 * 285 * @return An integer that fulfils Java's {@code interface Comparable<Method> public boolean 286 * compareTo(Method m)} method requirements. 287 */ 288 public int compareTo(Method m) 289 { 290 // Identical References 291 if (this == m) return 0; 292 293 // Sorting by ignoring case is best - usually for the looks of a list 294 // NOTE: Returning '0' is bad, because a TreeSet will remove duplicate-elements. This 295 // means two different meethods with the same name would not "fit" into a treeset. 296 297 int ret = this.name.compareToIgnoreCase(m.name); 298 if (ret != 0) return ret; 299 300 // Try to identify a different without ignoring case. 301 ret = this.name.compareTo(m.name); 302 if (ret != 0) return ret; 303 304 ret = this.numParameters() - m.numParameters(); 305 if (ret != 0) return ret; 306 307 for (int i=0; i < this.parameterTypesJOW.size(); i++) 308 { 309 ret = this.parameterTypesJOW.get(i).compareTo(m.parameterTypesJOW.get(i)); 310 if (ret != 0) return ret; 311 } 312 313 return 0; 314 } 315 316 /** 317 * This <I>should be called an "atypical version" of </I>the usual {@code equals(Object other)} 318 * method. This version of equals merely compares the name and parameters-list of the method. 319 * The presumption here is that the definition of a 'method' only has 320 * meaning - <I>at all</I> - inside the context of a {@code class, interface, } or 321 * {@code enumerated-type} where that method is defined. Since inside any {@code '.java'} 322 * source-code file, there may only be one method with a given name and parameter-list, this 323 * shall return {@code TRUE} whenever the method being compared has the same name and parameter 324 * types as {@code 'this'} does. 325 * 326 * @param other This may be any other {@code method}. It is <I><B>strongly suggested</B></I> 327 * that this be a {@code method} defined in the same {@code '.java'} source-code file as 328 * {@code 'this' method}. 329 * 330 * @return This method returns {@code TRUE} when {@code 'this'} instance of {@code Method} has 331 * <B>both</B> the same {@code public final Sting name} <B>and</B> the same parameter-list as 332 * {@code 'other'}. 333 */ 334 public boolean equals(Method other) 335 { 336 // The method's must have the same name! 337 if (! this.name.equals(other.name)) return false; 338 339 // If the number of parameters in the 'other' instance of Method differ from the number 340 // of parameters in 'this' Method, then return FALSE immediately. It cannot be a match. 341 342 if (this.numParameters() != other.numParameters()) return false; 343 344 // If both of these have zero parameters, and their names have matched, return true 345 // immediately 346 347 if (this.numParameters() == 0) return true; 348 349 // If any of the parameter-names are different, break immediately and return false; 350 for (int i=0; i < this.parameterNames.size(); i++) 351 if (! this.parameterNames.get(i).equals(other.parameterNames.get(i))) return false; 352 353 // If the parameter-types listed by the javadoc '.html' file differ from the parameter 354 // types listed in the original '.java' source-code file, then break immediately. 355 // 356 // NOTE: The "package-information" for the FULL CLASS OR INTERFACE NAME is not always 357 // available. 358 359 for (int i=0; i < this.parameterTypesJOW.size(); i++) 360 if (! this.parameterTypesJOW.get(i).equals(other.parameterTypesJOW.get(i))) 361 return false; 362 363 // ALL TEST PASSED 364 return true; 365 } 366}