1 11 package org.eclipse.jdt.internal.debug.eval.ast.engine; 12 13 14 import java.util.Iterator ; 15 import java.util.List ; 16 17 import org.eclipse.jdt.core.Signature; 18 import org.eclipse.jdt.debug.core.IJavaReferenceType; 19 import org.eclipse.jdt.internal.debug.core.model.JDIReferenceType; 20 21 import com.sun.jdi.ClassNotLoadedException; 22 import com.sun.jdi.ClassNotPreparedException; 23 import com.sun.jdi.ClassType; 24 import com.sun.jdi.Field; 25 import com.sun.jdi.InterfaceType; 26 import com.sun.jdi.Method; 27 import com.sun.jdi.ReferenceType; 28 import com.sun.jdi.Type; 29 30 public class BinaryBasedSourceGenerator { 31 32 private static final String RUN_METHOD_NAME= "___run"; private static final String EVAL_METHOD_NAME= "___eval"; private static final String ANONYMOUS_CLASS_NAME= "___EvalClass"; 36 37 private String [] fLocalVariableTypeNames; 38 39 private String [] fLocalVariableNames; 40 41 private boolean fIsInStaticMethod; 42 43 private StringBuffer fSource; 44 45 private int fRunMethodStartOffset; 46 private int fRunMethodLength; 47 private int fCodeSnippetPosition; 48 49 private String fCompilationUnitName; 50 51 55 private int fSourceMajorLevel; 56 private int fSourceMinorLevel; 57 58 public BinaryBasedSourceGenerator(String [] localTypesNames, String [] localVariables, boolean isInStaticMethod, String sourceLevel) { 59 fLocalVariableTypeNames= localTypesNames; 60 fLocalVariableNames= localVariables; 61 fIsInStaticMethod= isInStaticMethod; 62 int index = sourceLevel.indexOf('.'); 63 String num = sourceLevel.substring(0, index); 64 fSourceMajorLevel = Integer.valueOf(num).intValue(); 65 num = sourceLevel.substring(index + 1); 66 fSourceMinorLevel = Integer.valueOf(num).intValue(); 67 } 68 69 72 public void buildSource(JDIReferenceType referenceType) { 73 ReferenceType reference= (ReferenceType)referenceType.getUnderlyingType(); 74 fSource= buildTypeDeclaration(reference, buildRunMethod(reference), null); 75 } 76 77 80 public void buildSourceStatic(IJavaReferenceType type) { 81 Type underlyingType= ((JDIReferenceType)type).getUnderlyingType(); 82 if (!(underlyingType instanceof ReferenceType)) { 83 return; 84 } 85 ReferenceType refType= (ReferenceType)underlyingType; 86 fSource= buildTypeDeclaration(refType, buildRunMethod(refType), null, false); 87 String packageName = getPackageName(refType.name()); 88 if (packageName != null) { 89 fSource.insert(0, "package " + packageName + ";\n"); fCodeSnippetPosition += 10 + packageName.length(); 91 } 92 fCompilationUnitName= getSimpleName(refType.name()); 93 } 94 95 protected String getUniqueMethodName(String methodName, ReferenceType type) { 96 List methods= type.methodsByName(methodName); 97 while (!methods.isEmpty()) { 98 methodName += '_'; 99 methods= type.methodsByName(methodName); 100 } 101 return methodName; 102 } 103 104 private StringBuffer buildRunMethod(ReferenceType type) { 105 StringBuffer source = new StringBuffer (); 106 107 if (isInStaticMethod()) { 108 source.append("static "); } 110 111 source.append("void "); source.append(getUniqueMethodName(RUN_METHOD_NAME, type)); 113 source.append('('); 114 for(int i= 0, length= fLocalVariableNames.length; i < length; i++) { 115 source.append(getDotName(fLocalVariableTypeNames[i])); 116 source.append(' '); 117 source.append(fLocalVariableNames[i]); 118 if (i + 1 < length) 119 source.append(", "); } 121 source.append(") throws Throwable {"); source.append('\n'); 123 fCodeSnippetPosition= source.length(); 124 fRunMethodStartOffset= fCodeSnippetPosition; 125 126 source.append('\n'); 127 source.append('}').append('\n'); 128 fRunMethodLength= source.length(); 129 return source; 130 } 131 132 private StringBuffer buildTypeDeclaration(ReferenceType referenceType, StringBuffer buffer, String nestedTypeName) { 133 134 Field thisField= null; 135 136 List fields= referenceType.visibleFields(); 137 for (Iterator iterator= fields.iterator(); iterator.hasNext();) { 138 Field field= (Field) iterator.next(); 139 if (field.name().startsWith("this$")) { thisField = field; 141 break; 142 } 143 } 144 145 StringBuffer source = buildTypeDeclaration(referenceType, buffer, nestedTypeName, thisField != null); 146 147 if (thisField == null) { 148 String packageName = getPackageName(referenceType.name()); 149 if (packageName != null) { 150 source.insert(0, "package " + packageName + ";\n"); fCodeSnippetPosition += 10 + packageName.length(); 152 } 153 if (isAnonymousTypeName(referenceType.name())) { 154 fCompilationUnitName= ANONYMOUS_CLASS_NAME; 155 } else { 156 fCompilationUnitName= getSimpleName(referenceType.name()); 157 } 158 } else { 159 try { 160 return buildTypeDeclaration((ReferenceType) thisField.type(), source, referenceType.name()); 161 } catch (ClassNotLoadedException e) { 162 } 163 } 164 165 return source; 166 } 167 168 private StringBuffer buildTypeDeclaration(ReferenceType referenceType, StringBuffer buffer, String nestedTypeName, boolean hasEnclosingInstance) { 169 StringBuffer source= new StringBuffer (); 170 171 String typeName= referenceType.name(); 172 173 boolean isAnonymousType= isAnonymousTypeName(typeName); 174 175 if (isAnonymousType) { 176 ClassType classType= (ClassType) referenceType; 177 178 List interfaceList= classType.interfaces(); 179 String superClassName= classType.superclass().name(); 180 if (hasEnclosingInstance) { 181 source.append("void "); source.append(getUniqueMethodName(EVAL_METHOD_NAME, referenceType)); 183 source.append("() {\nnew "); if (interfaceList.size() != 0) { 185 source.append(getDotName(((InterfaceType)interfaceList.get(0)).name())); 186 } else { 187 source.append(getDotName(superClassName)); 188 } 189 source.append("()"); } else { 191 source.append("public class ").append(ANONYMOUS_CLASS_NAME).append(" "); if (interfaceList.size() != 0) { 193 source.append(" implements ").append(getDotName(((InterfaceType)interfaceList.get(0)).name())); } else { 195 source.append(" extends ").append(getDotName(superClassName)); } 197 } 198 199 } else { 200 if (referenceType.isFinal()) { 201 source.append("final "); } 203 204 if (referenceType.isStatic()) { 205 source.append("static "); } 207 208 if (referenceType instanceof ClassType) { 209 ClassType classType= (ClassType) referenceType; 210 211 if (classType.isAbstract()) { 212 source.append("abstract "); } 214 215 source.append("class "); 217 source.append(getSimpleName(typeName)).append(' '); 218 219 String genericSignature= referenceType.genericSignature(); 220 if (genericSignature != null && isSourceLevelGreaterOrEqual(1, 5)) { 221 String [] typeParameters= Signature.getTypeParameters(genericSignature); 222 if (typeParameters.length > 0) { 223 source.append('<'); 224 source.append(Signature.getTypeVariable(typeParameters[0])); 225 String [] typeParameterBounds= Signature.getTypeParameterBounds(typeParameters[0]); 226 source.append(" extends ").append(Signature.toString(typeParameterBounds[0]).replace('/', '.')); for (int i= 1; i < typeParameterBounds.length; i++) { 228 source.append(" & ").append(Signature.toString(typeParameterBounds[i]).replace('/', '.')); } 230 for (int j= 1; j < typeParameters.length; j++) { 231 source.append(',').append(Signature.getTypeVariable(typeParameters[j])); 232 typeParameterBounds= Signature.getTypeParameterBounds(typeParameters[j]); 233 source.append(" extends ").append(Signature.toString(typeParameterBounds[0]).replace('/', '.')); for (int i= 1; i < typeParameterBounds.length; i++) { 235 source.append(" & ").append(Signature.toString(typeParameterBounds[i]).replace('/', '.')); } 237 } 238 source.append("> "); } 240 String [] superClassInterfaces= SignatureExt.getTypeSuperClassInterfaces(genericSignature); 241 int length= superClassInterfaces.length; 242 if (length > 0) { 243 source.append("extends ").append(Signature.toString(superClassInterfaces[0]).replace('/', '.')); if (length > 1) { 245 source.append(" implements ").append(Signature.toString(superClassInterfaces[1]).replace('/', '.')); for (int i = 2; i < length; i++) { 247 source.append(',').append(Signature.toString(superClassInterfaces[1])); 248 } 249 } 250 } 251 } else { 252 253 ClassType superClass= classType.superclass(); 254 if (superClass != null) { 255 source.append("extends ").append(getDotName(superClass.name())).append(' '); } 257 258 List interfaces; 259 try { 260 interfaces= classType.interfaces(); 261 } catch (ClassNotPreparedException e) { 262 return new StringBuffer (); 263 } 264 if (interfaces.size() != 0) { 265 source.append("implements "); Iterator iterator= interfaces.iterator(); 267 InterfaceType interface_= (InterfaceType)iterator.next(); 268 source.append(getDotName(interface_.name())); 269 while (iterator.hasNext()) { 270 source.append(',').append(getDotName(((InterfaceType)iterator.next()).name())); 271 } 272 } 273 } 274 } else if (referenceType instanceof InterfaceType) { 275 if (buffer != null) { 276 source.append("abstract class "); source.append(getSimpleName(typeName)).append("___ implements "); source.append(typeName.replace('$', '.')).append(" {\n"); fCodeSnippetPosition += source.length(); 280 source.append(buffer).append("}\n"); } 282 283 return source; 284 } 285 } 286 287 source.append(" {\n"); 289 if (buffer != null && !(referenceType instanceof InterfaceType)) { 290 fCodeSnippetPosition += source.length(); 291 source.append(buffer); 292 } 293 294 List fields= referenceType.fields(); 295 for (Iterator iterator= fields.iterator(); iterator.hasNext();) { 296 Field field= (Field) iterator.next(); 297 if (!field.name().startsWith("this$")) { source.append(buildFieldDeclaration(field)); 299 } 300 } 301 302 List methods= referenceType.methods(); 303 for (Iterator iterator = methods.iterator(); iterator.hasNext();) { 304 Method method= (Method) iterator.next(); 305 if (!method.isConstructor() && !method.isStaticInitializer() && !method.isBridge()) { 306 source.append(buildMethodDeclaration(method)); 307 } 308 } 309 310 List nestedTypes= referenceType.nestedTypes(); 311 if (nestedTypeName == null) { 312 for (Iterator iterator = nestedTypes.iterator(); iterator.hasNext();) { 313 ReferenceType nestedType= (ReferenceType) iterator.next(); 314 if (isADirectInnerType(typeName, nestedType.name())) { 315 source.append(buildTypeDeclaration(nestedType, null, null, true)); 316 } 317 } 318 } else { 319 for (Iterator iterator = nestedTypes.iterator(); iterator.hasNext();) { 320 ReferenceType nestedType= (ReferenceType) iterator.next(); 321 if (!nestedTypeName.equals(nestedType.name()) && isADirectInnerType(typeName, nestedType.name())) { 322 source.append(buildTypeDeclaration(nestedType, null, null, true)); 323 } 324 } 325 } 326 327 if (isAnonymousType & hasEnclosingInstance) { 328 source.append("};\n"); } 330 331 source.append("}\n"); 333 return source; 334 } 335 336 private StringBuffer buildFieldDeclaration(Field field) { 337 StringBuffer source = new StringBuffer (); 338 339 if (field.isFinal()) { 340 source.append("final "); } 342 343 if (field.isStatic()) { 344 source.append("static "); } 346 347 if (field.isPublic()) { 348 source.append("public "); } else if (field.isPrivate()) { 350 source.append("private "); } else if (field.isProtected()) { 352 source.append("protected "); } 354 355 source.append(getDotName(field.typeName())).append(' ').append(field.name()).append(';').append('\n'); 356 357 return source; 358 } 359 360 private StringBuffer buildMethodDeclaration(Method method) { 361 StringBuffer source= new StringBuffer (); 362 363 if (method.isFinal()) { 364 source.append("final "); } 366 367 if (method.isStatic()) { 368 source.append("static "); } 370 371 if (method.isNative()) { 372 source.append("native "); } else if (method.isAbstract()) { 374 source.append("abstract "); } 376 377 if (method.isPublic()) { 378 source.append("public "); } else if (method.isPrivate()) { 380 source.append("private "); } else if (method.isProtected()) { 382 source.append("protected "); } 384 385 String genericSignature= method.genericSignature(); 386 if (genericSignature != null && isSourceLevelGreaterOrEqual(1, 5)) { 387 String [] typeParameters= Signature.getTypeParameters(genericSignature); 388 if (typeParameters.length > 0) { 389 source.append('<'); 390 source.append(Signature.getTypeVariable(typeParameters[0])); 391 String [] typeParameterBounds= Signature.getTypeParameterBounds(typeParameters[0]); 392 source.append(" extends ").append(Signature.toString(typeParameterBounds[0]).replace('/', '.')); for (int i= 1; i < typeParameterBounds.length; i++) { 394 source.append(" & ").append(Signature.toString(typeParameterBounds[i]).replace('/', '.')); } 396 for (int j= 1; j < typeParameters.length; j++) { 397 source.append(',').append(Signature.getTypeVariable(typeParameters[j])); 398 typeParameterBounds= Signature.getTypeParameterBounds(typeParameters[j]); 399 source.append(" extends ").append(Signature.toString(typeParameterBounds[0]).replace('/', '.')); for (int i= 1; i < typeParameterBounds.length; i++) { 401 source.append(" & ").append(Signature.toString(typeParameterBounds[i]).replace('/', '.')); } 403 } 404 source.append("> "); } 406 407 source.append(Signature.toString(Signature.getReturnType(genericSignature)).replace('/', '.')).append(' ').append(method.name()).append('('); 408 409 String [] parameterTypes= Signature.getParameterTypes(genericSignature); 410 int i= 0; 411 if (parameterTypes.length != 0) { 412 source.append(Signature.toString(parameterTypes[0]).replace('/', '.')).append(" arg").append(i++); if (method.isVarArgs()) { 414 for (int j= 1; j < parameterTypes.length - 1; j++) { 415 source.append(',').append(Signature.toString(parameterTypes[j]).replace('/', '.')).append(" arg").append(i++); } 417 String typeName= Signature.toString(parameterTypes[parameterTypes.length - 1]).replace('/', '.'); 418 source.append(',').append(typeName.substring(0,typeName.length() - 2)).append("...").append(" arg").append(i++); } else { 420 for (int j= 1; j < parameterTypes.length; j++) { 421 source.append(',').append(Signature.toString(parameterTypes[j]).replace('/', '.')).append(" arg").append(i++); } 423 } 424 } 425 source.append(')'); 426 } else { 427 source.append(getDotName(method.returnTypeName())).append(' ').append(method.name()).append('('); 428 429 List arguments= method.argumentTypeNames(); 430 int i= 0; 431 if (arguments.size() != 0) { 432 Iterator iterator= arguments.iterator(); 433 source.append(getDotName((String ) iterator.next())).append(" arg").append(i++); if (method.isVarArgs()) { 435 while (iterator.hasNext()) { 436 source.append(','); 437 String argName = getDotName((String ) iterator.next()); 438 if (!iterator.hasNext()) { 439 source.append(argName.substring(0,argName.length() - 2)).append("..."); } else { 441 source.append(argName); 442 } 443 source.append(" arg").append(i++); } 445 } else { 446 while (iterator.hasNext()) { 447 source.append(',').append(getDotName((String ) iterator.next())).append(" arg").append(i++); } 449 } 450 } 451 source.append(')'); 452 } 453 454 if (method.isAbstract() || method.isNative()) { 455 source.append(";\n"); } else { 458 source.append('{').append('\n'); 459 source.append(getReturnStatement(method.returnTypeName())); 460 source.append('}').append('\n'); 461 } 462 463 return source; 464 } 465 466 private String getReturnStatement(String returnTypeName) { 467 String typeName= getSimpleName(returnTypeName); 468 if (typeName.charAt(typeName.length() - 1) == ']') { 469 return "return null;\n"; } 471 switch (typeName.charAt(0)) { 472 case 'v': 473 return ""; case 'b': 475 if (typeName.charAt(1) == 'o') { 476 return "return false;\n"; } 478 case 's': 479 case 'c': 480 case 'i': 481 case 'l': 482 case 'd': 483 case 'f': 484 return "return 0;\n"; default: 486 return "return null;\n"; } 488 } 489 490 private String getDotName(String typeName) { 491 return typeName.replace('$', '.'); 492 } 493 494 private boolean isAnonymousTypeName(String typeName) { 495 char char0 = getSimpleName(typeName).charAt(0); 496 return '0' <= char0 && char0 <= '9'; 497 } 498 499 private String getSimpleName(String qualifiedName) { 500 int pos = qualifiedName.lastIndexOf('$'); 501 if (pos == -1) { 502 pos = qualifiedName.lastIndexOf('.'); 503 } 504 return ((pos == -1)? qualifiedName : qualifiedName.substring(pos + 1)); 505 } 506 507 private String getPackageName(String qualifiedName) { 508 int pos = qualifiedName.lastIndexOf('.'); 509 return ((pos == -1)? null : qualifiedName.substring(0, pos)); 510 } 511 512 private boolean isADirectInnerType(String typeName, String nestedTypeName) { 513 String end= nestedTypeName.substring(typeName.length() + 1); 514 return end.indexOf('$') == -1; 515 } 516 517 private boolean isInStaticMethod() { 518 return fIsInStaticMethod; 519 } 520 521 public StringBuffer getSource() { 522 return fSource; 523 } 524 525 public int getCodeSnippetPosition() { 526 return fCodeSnippetPosition; 527 } 528 529 public String getCompilationUnitName() { 530 return fCompilationUnitName; 531 } 532 533 public int getSnippetStart() { 534 return fCodeSnippetPosition - 2; 535 } 536 537 public int getRunMethodStart() { 538 return fCodeSnippetPosition - fRunMethodStartOffset; 539 } 540 541 public int getRunMethodLength() { 542 return fRunMethodLength; 543 } 544 545 553 public boolean isSourceLevelGreaterOrEqual(int major, int minor) { 554 return (fSourceMajorLevel > major) || 555 (fSourceMajorLevel == major && fSourceMinorLevel >= minor); 556 } 557 } 558 | Popular Tags |