1 19 20 package org.netbeans.api.java.source; 21 22 import com.sun.tools.javac.code.Symtab; 23 import com.sun.tools.javac.jvm.Target; 24 import com.sun.tools.javac.model.JavacElements; 25 import java.util.List ; 26 import javax.lang.model.element.Element; 27 import javax.lang.model.element.ElementKind; 28 import javax.lang.model.element.ExecutableElement; 29 import javax.lang.model.element.PackageElement; 30 import javax.lang.model.element.TypeElement; 31 import javax.lang.model.element.TypeParameterElement; 32 import javax.lang.model.element.VariableElement; 33 import org.netbeans.modules.java.source.ElementHandleAccessor; 34 import org.netbeans.modules.java.source.usages.ClassFileUtil; 35 36 72 public final class ElementHandle<T extends Element> { 73 74 static { 75 ElementHandleAccessor.INSTANCE = new ElementHandleAccessorImpl (); 76 } 77 78 private ElementKind kind; 79 private String [] signatures; 80 81 82 private ElementHandle(final ElementKind kind, String [] signatures) { 83 assert kind != null; 84 assert signatures != null; 85 this.kind = kind; 86 this.signatures = signatures; 87 } 88 89 90 97 @SuppressWarnings ("unchecked") public T resolve (final CompilationInfo compilationInfo) { 99 assert compilationInfo != null; 100 switch (this.kind) { 101 case PACKAGE: 102 assert signatures.length == 1; 103 return (T) compilationInfo.getElements().getPackageElement(signatures[0]); 104 case CLASS: 105 case INTERFACE: 106 case ENUM: 107 case ANNOTATION_TYPE: 108 case OTHER: 109 assert signatures.length == 1; 110 return (T) getTypeElementByBinaryName (signatures[0], compilationInfo); 111 case METHOD: 112 case CONSTRUCTOR: 113 case INSTANCE_INIT: 114 case STATIC_INIT: 115 { 116 assert signatures.length == 3; 117 final TypeElement type = getTypeElementByBinaryName (signatures[0], compilationInfo); 118 if (type != null) { 119 final List <? extends Element> members = type.getEnclosedElements(); 120 for (Element member : members) { 121 if (this.kind == member.getKind()) { 122 String [] desc = ClassFileUtil.createExecutableDescriptor((ExecutableElement)member); 123 assert desc.length == 3; 124 if (this.signatures[1].equals(desc[1]) && this.signatures[2].equals(desc[2])) { 125 return (T) member; 126 } 127 } 128 } 129 } 130 break; 131 } 132 case FIELD: 133 case ENUM_CONSTANT: 134 { 135 assert signatures.length == 3; 136 final TypeElement type = getTypeElementByBinaryName (signatures[0], compilationInfo); 137 if (type != null) { 138 final List <? extends Element> members = type.getEnclosedElements(); 139 for (Element member : members) { 140 if (this.kind == member.getKind()) { 141 String [] desc = ClassFileUtil.createFieldDescriptor((VariableElement)member); 142 assert desc.length == 3; 143 if (this.signatures[1].equals(desc[1]) && this.signatures[2].equals(desc[2])) { 144 return (T) member; 145 } 146 } 147 } 148 } 149 break; 150 } 151 case TYPE_PARAMETER: 152 { 153 if (signatures.length == 2) { 154 TypeElement type = getTypeElementByBinaryName (signatures[0], compilationInfo); 155 if (type != null) { 156 List <? extends TypeParameterElement> tpes = type.getTypeParameters(); 157 for (TypeParameterElement tpe : tpes) { 158 if (tpe.getSimpleName().contentEquals(signatures[1])) { 159 return (T)tpe; 160 } 161 } 162 } 163 } 164 else if (signatures.length == 4) { 165 final TypeElement type = getTypeElementByBinaryName (signatures[0], compilationInfo); 166 if (type != null) { 167 final List <? extends Element> members = type.getEnclosedElements(); 168 for (Element member : members) { 169 if (member.getKind() == ElementKind.METHOD || member.getKind() == ElementKind.CONSTRUCTOR) { 170 String [] desc = ClassFileUtil.createExecutableDescriptor((ExecutableElement)member); 171 assert desc.length == 3; 172 if (this.signatures[1].equals(desc[1]) && this.signatures[2].equals(desc[2])) { 173 assert member instanceof ExecutableElement; 174 List <? extends TypeParameterElement> tpes =((ExecutableElement)member).getTypeParameters(); 175 for (TypeParameterElement tpe : tpes) { 176 if (tpe.getSimpleName().contentEquals(signatures[3])) { 177 return (T) tpe; 178 } 179 } 180 } 181 } 182 } 183 } 184 } 185 else { 186 throw new IllegalStateException (); 187 } 188 break; 189 } 190 default: 191 throw new IllegalStateException (); 192 } 193 return null; 194 } 195 196 197 206 public boolean signatureEquals (final ElementHandle<? extends Element> handle) { 207 if (this.kind != handle.kind || this.signatures.length != handle.signatures.length) { 208 return false; 209 } 210 for (int i=0; i<signatures.length; i++) { 211 if (!signatures[i].equals(handle.signatures[i])) { 212 return false; 213 } 214 } 215 return true; 216 } 217 218 219 227 public String getBinaryName () throws IllegalStateException { 228 if ((this.kind.isClass() && !isArray(signatures[0])) || this.kind.isInterface()) { 229 return this.signatures[0]; 230 } 231 else { 232 throw new IllegalStateException (); 233 } 234 } 235 236 237 245 public String getQualifiedName () throws IllegalStateException { 246 if ((this.kind.isClass() && !isArray(signatures[0])) || this.kind.isInterface()) { 247 return this.signatures[0].replace (Target.DEFAULT.syntheticNameChar(),'.'); } 249 else { 250 throw new IllegalStateException (); 251 } 252 } 253 254 255 264 public boolean signatureEquals (final T element) { 265 if (!element.getKind().equals(getKind())) { 266 return false; 267 } 268 final ElementHandle<T> handle = create (element); 269 return signatureEquals (handle); 270 } 271 272 279 public ElementKind getKind () { 280 return this.kind; 281 } 282 283 284 295 public static<T extends Element> ElementHandle<T> create (final T element) throws IllegalArgumentException { 296 assert element != null; 297 ElementKind kind = element.getKind(); 298 String [] signatures; 299 switch (kind) { 300 case PACKAGE: 301 assert element instanceof PackageElement; 302 signatures = new String []{((PackageElement)element).getQualifiedName().toString()}; 303 break; 304 case CLASS: 305 case INTERFACE: 306 case ENUM: 307 case ANNOTATION_TYPE: 308 assert element instanceof TypeElement; 309 signatures = new String [] {ClassFileUtil.encodeClassNameOrArray((TypeElement)element)}; 310 break; 311 case METHOD: 312 case CONSTRUCTOR: 313 case INSTANCE_INIT: 314 case STATIC_INIT: 315 assert element instanceof ExecutableElement; 316 signatures = ClassFileUtil.createExecutableDescriptor((ExecutableElement)element); 317 break; 318 case FIELD: 319 case ENUM_CONSTANT: 320 assert element instanceof VariableElement; 321 signatures = ClassFileUtil.createFieldDescriptor((VariableElement)element); 322 break; 323 case TYPE_PARAMETER: 324 assert element instanceof TypeParameterElement; 325 TypeParameterElement tpe = (TypeParameterElement) element; 326 Element ge = tpe.getGenericElement(); 327 ElementKind gek = ge.getKind(); 328 if (gek.isClass() || gek.isInterface()) { 329 assert ge instanceof TypeElement; 330 signatures = new String [2]; 331 signatures[0] = ClassFileUtil.encodeClassNameOrArray((TypeElement)ge); 332 signatures[1] = tpe.getSimpleName().toString(); 333 } 334 else if (gek == ElementKind.METHOD || gek == ElementKind.CONSTRUCTOR) { 335 assert ge instanceof ExecutableElement; 336 String [] _sigs = ClassFileUtil.createExecutableDescriptor((ExecutableElement)ge); 337 signatures = new String [_sigs.length + 1]; 338 System.arraycopy(_sigs, 0, signatures, 0, _sigs.length); 339 signatures[_sigs.length] = tpe.getSimpleName().toString(); 340 } 341 else { 342 throw new IllegalArgumentException (gek.toString()); 343 } 344 break; 345 default: 346 throw new IllegalArgumentException (kind.toString()); 347 } 348 return new ElementHandle<T> (kind, signatures); 349 } 350 351 352 public @Override String toString () { 353 final StringBuilder result = new StringBuilder (); 354 result.append (this.getClass().getSimpleName()); 355 result.append ('['); result.append ("kind=" +this.kind.toString()); result.append ("; sigs="); for (String sig : this.signatures) { 359 result.append (sig); 360 result.append (' '); } 362 result.append (']'); return result.toString(); 364 } 365 366 367 368 @Override 369 public int hashCode () { 370 return signatures.length == 0 || signatures[0] == null ? 0 : signatures[0].hashCode(); 371 } 372 373 374 @Override 375 public boolean equals (Object other) { 376 if (other instanceof ElementHandle) { 377 return signatureEquals((ElementHandle)other); 378 } 379 return false; 380 } 381 382 383 387 String [] getSignature () { 388 return this.signatures; 389 } 390 391 392 private static class ElementHandleAccessorImpl extends ElementHandleAccessor { 393 394 public ElementHandle create(ElementKind kind, String ... descriptors) { 395 assert kind != null; 396 assert descriptors != null; 397 switch (kind) { 398 case PACKAGE: 399 if (descriptors.length != 1) { 400 throw new IllegalArgumentException (); 401 } 402 return new ElementHandle<PackageElement> (kind, descriptors); 403 case CLASS: 404 case INTERFACE: 405 case ENUM: 406 case ANNOTATION_TYPE: 407 case OTHER: 408 if (descriptors.length != 1) { 409 throw new IllegalArgumentException (); 410 } 411 return new ElementHandle<TypeElement> (kind, descriptors); 412 case METHOD: 413 case CONSTRUCTOR: 414 case INSTANCE_INIT: 415 case STATIC_INIT: 416 if (descriptors.length != 3) { 417 throw new IllegalArgumentException (); 418 } 419 return new ElementHandle<ExecutableElement> (kind, descriptors); 420 case FIELD: 421 case ENUM_CONSTANT: 422 if (descriptors.length != 3) { 423 throw new IllegalArgumentException (); 424 } 425 return new ElementHandle<VariableElement> (kind, descriptors); 426 default: 427 throw new IllegalArgumentException (); 428 } 429 } 430 } 431 432 private static TypeElement getTypeElementByBinaryName (final String signature, final CompilationInfo ci) { 433 if (isArray(signature)) { 434 return Symtab.instance(ci.getJavacTask().getContext()).arrayClass; 435 } 436 else { 437 assert ci.getElements() instanceof JavacElements; 438 final JavacElements elements = (JavacElements) ci.getElements(); 439 return (TypeElement) elements.getTypeElementByBinaryName(signature); 440 } 441 } 442 443 private static boolean isArray (String signature) { 444 return signature.length() == 1 && signature.charAt(0) == '['; 445 } 446 447 } 448 | Popular Tags |