1 19 package org.netbeans.modules.java.editor.codegen; 20 21 import com.sun.source.tree.AnnotationTree; 22 import com.sun.source.tree.AssignmentTree; 23 import com.sun.source.tree.BlockTree; 24 import com.sun.source.tree.ClassTree; 25 import com.sun.source.tree.ExpressionTree; 26 import com.sun.source.tree.IdentifierTree; 27 import com.sun.source.tree.MemberSelectTree; 28 import com.sun.source.tree.MethodInvocationTree; 29 import com.sun.source.tree.MethodTree; 30 import com.sun.source.tree.ModifiersTree; 31 import com.sun.source.tree.NewClassTree; 32 import com.sun.source.tree.StatementTree; 33 import com.sun.source.tree.Tree; 34 import com.sun.source.tree.TypeParameterTree; 35 import com.sun.source.tree.VariableTree; 36 import com.sun.source.util.TreePath; 37 import com.sun.source.util.TreePathScanner; 38 import com.sun.source.util.Trees; 39 import java.util.ArrayList ; 40 import java.util.Collection ; 41 import java.util.Collections ; 42 import java.util.EnumSet ; 43 import java.util.HashMap ; 44 import java.util.HashSet ; 45 import java.util.Iterator ; 46 import java.util.List ; 47 import java.util.Map ; 48 import java.util.Set ; 49 import javax.lang.model.element.Element; 50 import javax.lang.model.element.ElementKind; 51 import javax.lang.model.element.ExecutableElement; 52 import javax.lang.model.element.Modifier; 53 import javax.lang.model.element.PackageElement; 54 import javax.lang.model.element.TypeElement; 55 import javax.lang.model.element.TypeParameterElement; 56 import javax.lang.model.element.VariableElement; 57 import javax.lang.model.type.DeclaredType; 58 import javax.lang.model.type.ExecutableType; 59 import javax.lang.model.type.TypeKind; 60 import javax.lang.model.type.TypeMirror; 61 import javax.lang.model.util.ElementFilter; 62 import javax.lang.model.util.Types; 63 import javax.lang.model.util.Types; 64 import org.netbeans.api.java.queries.SourceLevelQuery; 65 import org.netbeans.api.java.source.CompilationInfo; 66 import org.netbeans.api.java.source.ElementUtilities; 67 import org.netbeans.api.java.source.SourceUtils; 68 import org.netbeans.api.java.source.TreeMaker; 69 import org.netbeans.api.java.source.WorkingCopy; 70 import org.openide.ErrorManager; 71 import org.openide.filesystems.FileObject; 72 73 77 public class GeneratorUtils { 78 79 private static final ErrorManager ERR = ErrorManager.getDefault().getInstance(GeneratorUtils.class.getName()); 80 public static final int GETTERS_ONLY = 1; 81 public static final int SETTERS_ONLY = 2; 82 83 private GeneratorUtils() { 84 } 85 86 public static ClassTree insertClassMember(WorkingCopy copy, ClassTree clazz, Tree member) { 87 int idx = 0; 88 for (Tree tree : clazz.getMembers()) { 89 if (ClassMemberComparator.compare(member, tree) < 0) 90 break; 91 idx++; 92 } 93 return copy.getTreeMaker().insertClassMember(clazz, idx, member); 94 } 95 96 public static List <? extends ExecutableElement> findUndefs(CompilationInfo info, TypeElement impl) { 97 if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) 98 ERR.log(ErrorManager.INFORMATIONAL, "findUndefs(" + info + ", " + impl + ")"); 99 List <? extends ExecutableElement> undef = findUndefs(info, impl, impl); 100 if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) 101 ERR.log(ErrorManager.INFORMATIONAL, "undef=" + undef); 102 return undef; 103 } 104 105 public static List <? extends ExecutableElement> findOverridable(CompilationInfo info, TypeElement impl) { 106 List <ExecutableElement> overridable = new ArrayList <ExecutableElement>(); 107 List <TypeElement> classes = getAllClasses(impl); 108 109 if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) 110 ERR.log(ErrorManager.INFORMATIONAL, "classes=" + classes); 111 112 for (TypeElement te : classes.subList(1, classes.size())) { 113 for (ExecutableElement ee : ElementFilter.methodsIn(te.getEnclosedElements())) { 114 Set <Modifier> set = EnumSet.copyOf(NOT_OVERRIDABLE); 115 116 set.removeAll(ee.getModifiers()); 117 118 if (set.size() != NOT_OVERRIDABLE.size()) 119 continue; 120 121 123 int thisElement = classes.indexOf(te); 124 125 if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { 126 ERR.log(ErrorManager.INFORMATIONAL, "ee=" + ee); 127 ERR.log(ErrorManager.INFORMATIONAL, "thisElement = " + thisElement); 128 ERR.log(ErrorManager.INFORMATIONAL, "classes.subList(0, thisElement + 1)=" + classes.subList(0, thisElement + 1)); 129 ERR.log(ErrorManager.INFORMATIONAL, "isOverriden(info, ee, classes.subList(0, thisElement + 1))=" + isOverriden(info, ee, classes.subList(0, thisElement + 1))); 130 } 131 132 if (!isOverriden(info, ee, classes.subList(0, thisElement + 1))) { 133 overridable.add(ee); 134 } 135 } 136 } 137 138 return overridable; 139 } 140 141 public static Map <? extends TypeElement, ? extends List <? extends VariableElement>> findAllAccessibleFields(CompilationInfo info, TypeElement clazz) { 142 Map <TypeElement, List <? extends VariableElement>> result = new HashMap <TypeElement, List <? extends VariableElement>>(); 143 144 result.put(clazz, findAllAccessibleFields(info, clazz, clazz)); 145 146 for (TypeElement te : getAllParents(clazz)) { 147 result.put(te, findAllAccessibleFields(info, clazz, te)); 148 } 149 150 return result; 151 } 152 153 public static void scanForFieldsAndConstructors(CompilationInfo info, final TreePath clsPath, final Set <VariableElement> initializedFields, final Set <VariableElement> uninitializedFields, final List <ExecutableElement> constructors) { 154 final Trees trees = info.getTrees(); 155 new TreePathScanner<Void , Boolean >() { 156 @Override 157 public Void visitVariable(VariableTree node, Boolean p) { 158 Element el = trees.getElement(getCurrentPath()); 159 if (el != null && el.getKind() == ElementKind.FIELD && !el.getModifiers().contains(Modifier.STATIC) && node.getInitializer() == null && !initializedFields.remove(el)) 160 uninitializedFields.add((VariableElement)el); 161 return null; 162 } 163 @Override 164 public Void visitAssignment(AssignmentTree node, Boolean p) { 165 Element el = trees.getElement(new TreePath(getCurrentPath(), node.getVariable())); 166 if (el != null && el.getKind() == ElementKind.FIELD && !uninitializedFields.remove(el)) 167 initializedFields.add((VariableElement)el); 168 return null; 169 } 170 @Override 171 public Void visitClass(ClassTree node, Boolean p) { 172 return p ? super.visitClass(node, false) : null; 174 } 175 @Override 176 public Void visitMethod(MethodTree node, Boolean p) { 177 Element el = trees.getElement(getCurrentPath()); 178 if (el != null && el.getKind() == ElementKind.CONSTRUCTOR) 179 constructors.add((ExecutableElement)el); 180 return null; 181 } 182 }.scan(clsPath, Boolean.TRUE); 183 } 184 185 public static void generateAllAbstractMethodImplementations(WorkingCopy wc, TreePath path) { 186 assert path.getLeaf().getKind() == Tree.Kind.CLASS; 187 TypeElement te = (TypeElement)wc.getTrees().getElement(path); 188 if (te != null) { 189 TreeMaker make = wc.getTreeMaker(); 190 ClassTree clazz = (ClassTree)path.getLeaf(); 191 List <Tree> members = new ArrayList <Tree>(clazz.getMembers()); 192 for(ExecutableElement element : findUndefs(wc, te, te)) 193 members.add(createMethodImplementation(wc, element, (DeclaredType)te.asType())); 194 ClassTree nue = make.Class(clazz.getModifiers(), clazz.getSimpleName(), clazz.getTypeParameters(), clazz.getExtendsClause(), (List <ExpressionTree>)clazz.getImplementsClause(), members); 195 wc.rewrite(clazz, nue); 196 } 197 } 198 199 public static void generateAbstractMethodImplementations(WorkingCopy wc, TreePath path, List <? extends ExecutableElement> elements, int index) { 200 assert path.getLeaf().getKind() == Tree.Kind.CLASS; 201 TypeElement te = (TypeElement)wc.getTrees().getElement(path); 202 if (te != null) { 203 TreeMaker make = wc.getTreeMaker(); 204 ClassTree clazz = (ClassTree)path.getLeaf(); 205 List <Tree> members = new ArrayList <Tree>(clazz.getMembers()); 206 List <Tree> methods = new ArrayList <Tree>(); 207 for(ExecutableElement element : elements) 208 methods.add(createMethodImplementation(wc, element, (DeclaredType)te.asType())); 209 members.addAll(index, methods); 210 ClassTree nue = make.Class(clazz.getModifiers(), clazz.getSimpleName(), clazz.getTypeParameters(), clazz.getExtendsClause(), (List <ExpressionTree>)clazz.getImplementsClause(), members); 211 wc.rewrite(clazz, nue); 212 } 213 } 214 215 public static void generateAbstractMethodImplementation(WorkingCopy wc, TreePath path, ExecutableElement element, int index) { 216 assert path.getLeaf().getKind() == Tree.Kind.CLASS; 217 TypeElement te = (TypeElement)wc.getTrees().getElement(path); 218 if (te != null) { 219 ClassTree decl = wc.getTreeMaker().insertClassMember((ClassTree)path.getLeaf(), index, createMethodImplementation(wc, element, (DeclaredType)te.asType())); 220 wc.rewrite(path.getLeaf(), decl); 221 } 222 } 223 224 public static void generateMethodOverrides(WorkingCopy wc, TreePath path, List <? extends ExecutableElement> elements, int index) { 225 assert path.getLeaf().getKind() == Tree.Kind.CLASS; 226 TypeElement te = (TypeElement)wc.getTrees().getElement(path); 227 if (te != null) { 228 TreeMaker make = wc.getTreeMaker(); 229 ClassTree clazz = (ClassTree)path.getLeaf(); 230 List <Tree> members = new ArrayList <Tree>(clazz.getMembers()); 231 List <Tree> methods = new ArrayList <Tree>(); 232 for(ExecutableElement element : elements) 233 methods.add(createMethodImplementation(wc, element, (DeclaredType)te.asType())); 234 members.addAll(index, methods); 235 ClassTree nue = make.Class(clazz.getModifiers(), clazz.getSimpleName(), clazz.getTypeParameters(), clazz.getExtendsClause(), (List <ExpressionTree>)clazz.getImplementsClause(), members); 236 wc.rewrite(clazz, nue); 237 } 238 } 239 240 public static void generateMethodOverride(WorkingCopy wc, TreePath path, ExecutableElement element, int index) { 241 assert path.getLeaf().getKind() == Tree.Kind.CLASS; 242 TypeElement te = (TypeElement)wc.getTrees().getElement(path); 243 if (te != null) { 244 ClassTree decl = wc.getTreeMaker().insertClassMember((ClassTree)path.getLeaf(), index, createMethodImplementation(wc, element, (DeclaredType)te.asType())); 245 wc.rewrite(path.getLeaf(), decl); 246 } 247 } 248 249 public static void generateConstructor(WorkingCopy wc, TreePath path, Iterable <? extends VariableElement> initFields, ExecutableElement inheritedConstructor, int index) { 250 TreeMaker make = wc.getTreeMaker(); 251 ClassTree clazz = (ClassTree)path.getLeaf(); 252 List <VariableTree> parameters = new ArrayList <VariableTree>(); 253 List <StatementTree> statements = new ArrayList <StatementTree>(); 254 ModifiersTree parameterModifiers = make.Modifiers(EnumSet.noneOf(Modifier.class)); 255 if (inheritedConstructor != null && !inheritedConstructor.getParameters().isEmpty()) { 256 List <ExpressionTree> arguments = new ArrayList <ExpressionTree>(); 257 for (VariableElement ve : inheritedConstructor.getParameters()) { 258 parameters.add(make.Variable(parameterModifiers, ve.getSimpleName(), make.Type(ve.asType()), null)); 259 arguments.add(make.Identifier(ve.getSimpleName())); } 261 statements.add(make.ExpressionStatement(make.MethodInvocation(Collections.<ExpressionTree>emptyList(), make.Identifier("super"), arguments))); 262 } 263 for (VariableElement ve : initFields) { 264 parameters.add(make.Variable(parameterModifiers, ve.getSimpleName(), make.Type(ve.asType()), null)); 265 statements.add(make.ExpressionStatement(make.Assignment(make.MemberSelect(make.Identifier("this"), ve.getSimpleName()), make.Identifier(ve.getSimpleName())))); } 267 BlockTree body = make.Block(statements, false); 268 ClassTree decl = make.insertClassMember(clazz, index, make.Method(make.Modifiers(EnumSet.of(wc.getTreeUtilities().isEnum(clazz) ? Modifier.PRIVATE : Modifier.PUBLIC)), "<init>", null, Collections.<TypeParameterTree> emptyList(), parameters, Collections.<ExpressionTree>emptyList(), body, null)); wc.rewrite(path.getLeaf(), decl); 270 } 271 272 public static void generateGettersAndSetters(WorkingCopy wc, TreePath path, Iterable <? extends VariableElement> fields, int type, int index) { 273 assert path.getLeaf().getKind() == Tree.Kind.CLASS; 274 TypeElement te = (TypeElement)wc.getTrees().getElement(path); 275 if (te != null) { 276 TreeMaker make = wc.getTreeMaker(); 277 ClassTree clazz = (ClassTree)path.getLeaf(); 278 List <Tree> members = new ArrayList <Tree>(clazz.getMembers()); 279 List <Tree> methods = new ArrayList <Tree>(); 280 for(VariableElement element : fields) { 281 if (type != SETTERS_ONLY) 282 methods.add(createGetterMethod(wc, element, (DeclaredType)te.asType())); 283 if (type != GETTERS_ONLY) 284 methods.add(createSetterMethod(wc, element, (DeclaredType)te.asType())); 285 } 286 members.addAll(index, methods); 287 ClassTree nue = make.Class(clazz.getModifiers(), clazz.getSimpleName(), clazz.getTypeParameters(), clazz.getExtendsClause(), (List <ExpressionTree>)clazz.getImplementsClause(), members); 288 wc.rewrite(clazz, nue); 289 } 290 } 291 292 public static boolean hasGetter(CompilationInfo info, VariableElement field, Map <String , List <ExecutableElement>> methods) { 293 CharSequence name = field.getSimpleName(); 294 assert name.length() > 0; 295 TypeMirror type = field.asType(); 296 StringBuilder sb = new StringBuilder (); 297 sb.append(type.getKind() == TypeKind.BOOLEAN ? "is" : "get").append(Character.toUpperCase(name.charAt(0))).append(name.subSequence(1, name.length())); Types types = info.getTypes(); 299 List <ExecutableElement> candidates = methods.get(sb.toString()); 300 if (candidates != null) { 301 for (ExecutableElement candidate : candidates) { 302 if (candidate.getParameters().isEmpty() && types.isSameType(candidate.getReturnType(), type)) 303 return true; 304 } 305 } 306 return false; 307 } 308 309 public static boolean hasSetter(CompilationInfo info, VariableElement field, Map <String , List <ExecutableElement>> methods) { 310 CharSequence name = field.getSimpleName(); 311 assert name.length() > 0; 312 TypeMirror type = field.asType(); 313 StringBuilder sb = new StringBuilder (); 314 sb.append("set").append(Character.toUpperCase(name.charAt(0))).append(name.subSequence(1, name.length())); Types types = info.getTypes(); 316 List <ExecutableElement> candidates = methods.get(sb.toString()); 317 if (candidates != null) { 318 for (ExecutableElement candidate : candidates) { 319 if (candidate.getReturnType().getKind() == TypeKind.VOID && candidate.getParameters().size() == 1 && types.isSameType(candidate.getParameters().get(0).asType(), type)) 320 return true; 321 } 322 } 323 return false; 324 } 325 326 private static MethodTree createMethodImplementation(WorkingCopy wc, ExecutableElement element, DeclaredType type) { 327 TreeMaker make = wc.getTreeMaker(); 328 Set <Modifier> mods = element.getModifiers(); 329 Set <Modifier> flags = mods.isEmpty() ? EnumSet.noneOf(Modifier.class) : EnumSet.copyOf(mods); 330 boolean isAbstract = flags.remove(Modifier.ABSTRACT); 331 flags.remove(Modifier.NATIVE); 332 333 ExecutableType et = (ExecutableType)wc.getTypes().asMemberOf(type, element); 334 List <TypeParameterTree> typeParams = new ArrayList <TypeParameterTree>(); 335 for (TypeParameterElement tpe: element.getTypeParameters()) { 336 List <ExpressionTree> bounds = new ArrayList <ExpressionTree>(); 337 for (TypeMirror bound : tpe.getBounds()) { 338 if (bound.getKind() != TypeKind.NULL) { 339 if (bound.getKind() != TypeKind.DECLARED || !"java.lang.Object".contentEquals(((TypeElement)((DeclaredType)bound).asElement()).getQualifiedName())) bounds.add((ExpressionTree)make.Type(bound)); 342 } 343 } 344 typeParams.add(make.TypeParameter(tpe.getSimpleName(), bounds)); 345 } 346 347 Tree returnType = make.Type(et.getReturnType()); 348 349 List <VariableTree> params = new ArrayList <VariableTree>(); 350 boolean isVarArgs = element.isVarArgs(); 351 Iterator <? extends VariableElement> formArgNames = element.getParameters().iterator(); 352 Iterator <? extends TypeMirror> formArgTypes = et.getParameterTypes().iterator(); 353 ModifiersTree parameterModifiers = make.Modifiers(EnumSet.noneOf(Modifier.class)); 354 while (formArgNames.hasNext() && formArgTypes.hasNext()) { 355 VariableElement formArgName = formArgNames.next(); 356 TypeMirror formArgType = formArgTypes.next(); 357 if (isVarArgs && !formArgNames.hasNext()) 358 parameterModifiers = make.Modifiers(1L<<34, Collections.<AnnotationTree>emptyList()); 359 params.add(make.Variable(parameterModifiers, formArgName.getSimpleName(), make.Type(formArgType), null)); 360 } 361 362 List <ExpressionTree> throwsList = new ArrayList <ExpressionTree>(); 363 for (TypeMirror tm : et.getThrownTypes()) { 364 throwsList.add((ExpressionTree)make.Type(tm)); 365 } 366 367 BlockTree body; 368 List <AnnotationTree> annotations = new ArrayList <AnnotationTree>(); 369 if (isAbstract) { 370 List <StatementTree> blockStatements = new ArrayList <StatementTree>(); 371 TypeElement uoe = wc.getElements().getTypeElement("java.lang.UnsupportedOperationException"); if (uoe != null) { 374 NewClassTree nue = make.NewClass(null, Collections.<ExpressionTree>emptyList(), make.QualIdent(uoe), Collections.singletonList(make.Literal("Not supported yet.")), null); 375 blockStatements.add(make.Throw(nue)); 376 } 377 body = make.Block(blockStatements, false); 378 } else { 379 List <ExpressionTree> arguments = new ArrayList <ExpressionTree>(); 380 for (VariableElement ve : element.getParameters()) { 381 arguments.add(make.Identifier(ve.getSimpleName())); 382 } 383 MethodInvocationTree inv = make.MethodInvocation(Collections.<ExpressionTree>emptyList(), make.MemberSelect(make.Identifier("super"), element.getSimpleName()), arguments); StatementTree statement = wc.getTypes().getNoType(TypeKind.VOID) == element.getReturnType() ? 385 make.ExpressionStatement(inv) : make.Return(inv); 386 body = make.Block(Collections.singletonList(statement), false); 387 388 if (GeneratorUtils.supportsOverride(wc.getFileObject())) { 390 annotations.add(make.Annotation(make.Identifier("Override"), Collections.<ExpressionTree>emptyList())); } 392 } 393 394 return make.Method(make.Modifiers(flags, annotations), element.getSimpleName(), returnType, typeParams, params, throwsList, body, null); 395 } 396 397 private static MethodTree createGetterMethod(WorkingCopy wc, VariableElement element, DeclaredType type) { 398 TreeMaker make = wc.getTreeMaker(); 399 Set <Modifier> mods = EnumSet.of(Modifier.PUBLIC); 400 if (element.getModifiers().contains(Modifier.STATIC)) 401 mods.add(Modifier.STATIC); 402 CharSequence name = element.getSimpleName(); 403 assert name.length() > 0; 404 StringBuilder sb = new StringBuilder (); 405 sb.append(element.asType().getKind() == TypeKind.BOOLEAN ? "is" : "get").append(Character.toUpperCase(name.charAt(0))).append(name.subSequence(1, name.length())); BlockTree body = make.Block(Collections.singletonList(make.Return(make.Identifier(element.getSimpleName()))), false); 407 return make.Method(make.Modifiers(mods), sb, make.Type(element.asType()), Collections.<TypeParameterTree>emptyList(), Collections.<VariableTree>emptyList(), Collections.<ExpressionTree>emptyList(), body, null); 408 } 409 410 private static MethodTree createSetterMethod(WorkingCopy wc, VariableElement element, DeclaredType type) { 411 TreeMaker make = wc.getTreeMaker(); 412 Set <Modifier> mods = EnumSet.of(Modifier.PUBLIC); 413 boolean isStatic = element.getModifiers().contains(Modifier.STATIC); 414 if (isStatic) 415 mods.add(Modifier.STATIC); 416 CharSequence name = element.getSimpleName(); 417 assert name.length() > 0; 418 StringBuilder sb = new StringBuilder (); 419 sb.append("set").append(Character.toUpperCase(name.charAt(0))).append(name.subSequence(1, name.length())); List <VariableTree> params = Collections.singletonList(make.Variable(make.Modifiers(EnumSet.noneOf(Modifier.class)), element.getSimpleName(), make.Type(element.asType()), null)); 421 BlockTree body = make.Block(Collections.singletonList(make.ExpressionStatement(make.Assignment(make.MemberSelect(isStatic? make.Identifier(element.getEnclosingElement().getSimpleName()) : make.Identifier("this"), element.getSimpleName()), make.Identifier(element.getSimpleName())))), false); return make.Method(make.Modifiers(mods), sb, make.Type(wc.getTypes().getNoType(TypeKind.VOID)), Collections.<TypeParameterTree>emptyList(), params, Collections.<ExpressionTree>emptyList(), body, null); 423 } 424 425 private static List <? extends ExecutableElement> findUndefs(CompilationInfo info, TypeElement impl, TypeElement element) { 426 List <ExecutableElement> undef = new ArrayList <ExecutableElement>(); 427 ElementUtilities eu = info.getElementUtilities(); 428 if (element.getModifiers().contains(Modifier.ABSTRACT)) { 429 for (Element e : element.getEnclosedElements()) { 430 if (e.getKind() == ElementKind.METHOD && e.getModifiers().contains(Modifier.ABSTRACT)) { 431 ExecutableElement ee = (ExecutableElement)e; 432 Element eeImpl = eu.getImplementationOf(ee, impl); 433 if (eeImpl == null || eeImpl == ee) 434 undef.add(ee); 435 } 436 } 437 } 438 Types types = info.getTypes(); 439 DeclaredType implType = (DeclaredType)impl.asType(); 440 for (TypeMirror t : types.directSupertypes(element.asType())) { 441 for (ExecutableElement ee : findUndefs(info, impl, (TypeElement)((DeclaredType)t).asElement())) { 442 boolean exists = false; 444 TypeMirror eeType = types.asMemberOf(implType, ee); 445 for (ExecutableElement existing : undef) { 446 if (existing.getSimpleName().contentEquals(ee.getSimpleName())) { 447 TypeMirror existingType = types.asMemberOf(implType, existing); 448 if (types.isSameType(eeType, existingType)) { 449 exists = true; 450 break; 451 } 452 } 453 } 454 if (!exists) 455 undef.add(ee); 456 } 457 } 458 return undef; 459 } 460 461 private static List <? extends VariableElement> findAllAccessibleFields(CompilationInfo info, TypeElement accessibleFrom, TypeElement toScan) { 462 List <VariableElement> result = new ArrayList <VariableElement>(); 463 464 for (VariableElement ve : ElementFilter.fieldsIn(toScan.getEnclosedElements())) { 465 if (ve.getModifiers().contains(Modifier.PUBLIC)) { 467 result.add(ve); 468 continue; 469 } 470 if (ve.getModifiers().contains(Modifier.PRIVATE)) { 471 if (accessibleFrom == toScan) 472 result.add(ve); 473 continue; 474 } 475 if (ve.getModifiers().contains(Modifier.PROTECTED)) { 476 if (getAllParents(accessibleFrom).contains(toScan)) 477 result.add(ve); 478 continue; 479 } 480 } 482 483 return result; 484 } 485 486 public static Collection <TypeElement> getAllParents(TypeElement of) { 487 Set <TypeElement> result = new HashSet <TypeElement>(); 488 489 for (TypeMirror t : of.getInterfaces()) { 490 TypeElement te = (TypeElement) ((DeclaredType)t).asElement(); 491 492 if (te != null) { 493 result.add(te); 494 result.addAll(getAllParents(te)); 495 } else { 496 if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { 497 ERR.log(ErrorManager.INFORMATIONAL, "te=null, t=" + t); 498 } 499 } 500 } 501 502 TypeMirror sup = of.getSuperclass(); 503 TypeElement te = sup.getKind() == TypeKind.DECLARED ? (TypeElement) ((DeclaredType)sup).asElement() : null; 504 505 if (te != null) { 506 result.add(te); 507 result.addAll(getAllParents(te)); 508 } else { 509 if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { 510 ERR.log(ErrorManager.INFORMATIONAL, "te=null, t=" + of); 511 } 512 } 513 514 return result; 515 } 516 517 public static boolean supportsOverride(FileObject file) { 518 return SUPPORTS_OVERRIDE_SOURCE_LEVELS.contains(SourceLevelQuery.getSourceLevel(file)); 519 } 520 521 private static final Set <String > SUPPORTS_OVERRIDE_SOURCE_LEVELS; 522 523 static { 524 SUPPORTS_OVERRIDE_SOURCE_LEVELS = new HashSet (); 525 526 SUPPORTS_OVERRIDE_SOURCE_LEVELS.add("1.5"); 527 SUPPORTS_OVERRIDE_SOURCE_LEVELS.add("1.6"); 528 } 529 530 private static List <TypeElement> getAllClasses(TypeElement of) { 531 List <TypeElement> result = new ArrayList <TypeElement>(); 532 TypeMirror sup = of.getSuperclass(); 533 TypeElement te = sup.getKind() == TypeKind.DECLARED ? (TypeElement) ((DeclaredType)sup).asElement() : null; 534 535 result.add(of); 536 537 if (te != null) { 538 result.addAll(getAllClasses(te)); 539 } else { 540 if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { 541 ERR.log(ErrorManager.INFORMATIONAL, "te=null, t=" + of); 542 } 543 } 544 545 return result; 546 } 547 548 private static boolean isOverriden(CompilationInfo info, ExecutableElement methodBase, List <TypeElement> classes) { 549 if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { 550 ERR.log(ErrorManager.INFORMATIONAL, "isOverriden(" + info + ", " + methodBase + ", " + classes + ")"); 551 } 552 553 for (TypeElement impl : classes) { 554 for (ExecutableElement methodImpl : ElementFilter.methodsIn(impl.getEnclosedElements())) { 555 if ( ERR.isLoggable(ErrorManager.INFORMATIONAL) 556 && info.getElements().overrides(methodImpl, methodBase, impl)) { 557 ERR.log(ErrorManager.INFORMATIONAL, "overrides:"); 558 ERR.log(ErrorManager.INFORMATIONAL, "impl=" + impl); 559 ERR.log(ErrorManager.INFORMATIONAL, "methodImpl=" + methodImpl); 560 } 561 562 if (info.getElements().overrides(methodImpl, methodBase, impl)) 563 return true; 564 } 565 } 566 567 if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { 568 ERR.log(ErrorManager.INFORMATIONAL, "no overriding methods overrides:"); 569 } 570 571 return false; 572 } 573 574 private static final Set <Modifier> NOT_OVERRIDABLE = EnumSet.of(Modifier.ABSTRACT, Modifier.STATIC, Modifier.FINAL); 575 576 public static boolean isAccessible(TypeElement from, Element what) { 577 if (what.getModifiers().contains(Modifier.PUBLIC)) 578 return true; 579 580 TypeElement fromTopLevel = SourceUtils.getOutermostEnclosingTypeElement(from); 581 TypeElement whatTopLevel = SourceUtils.getOutermostEnclosingTypeElement(what); 582 583 if (fromTopLevel.equals(whatTopLevel)) 584 return true; 585 586 if (what.getModifiers().contains(Modifier.PRIVATE)) 587 return false; 588 589 if (what.getModifiers().contains(Modifier.PROTECTED)) { 590 if (getAllClasses(fromTopLevel).contains(SourceUtils.getEnclosingTypeElement(what))) 591 return true; 592 } 593 594 return ((PackageElement) fromTopLevel.getEnclosingElement()).getQualifiedName().toString().contentEquals(((PackageElement) whatTopLevel.getEnclosingElement()).getQualifiedName()); 596 } 597 598 private static class ClassMemberComparator { 599 600 public static int compare(Tree tree1, Tree tree2) { 601 if (tree1 == tree2) 602 return 0; 603 int importanceDiff = getSortPriority(tree1) - getSortPriority(tree2); 604 if (importanceDiff != 0) 605 return importanceDiff; 606 int alphabeticalDiff = getSortText(tree1).compareTo(getSortText(tree2)); 607 if (alphabeticalDiff != 0) 608 return alphabeticalDiff; 609 return -1; 610 } 611 612 private static int getSortPriority(Tree tree) { 613 int ret = 0; 614 ModifiersTree modifiers = null; 615 switch (tree.getKind()) { 616 case CLASS: 617 ret = 400; 618 modifiers = ((ClassTree)tree).getModifiers(); 619 break; 620 case METHOD: 621 MethodTree mt = (MethodTree)tree; 622 if (mt.getName().contentEquals("<init>")) 623 ret = 200; 624 else 625 ret = 300; 626 modifiers = mt.getModifiers(); 627 break; 628 case VARIABLE: 629 ret = 100; 630 modifiers = ((VariableTree)tree).getModifiers(); 631 break; 632 } 633 if (modifiers != null) { 634 if (!modifiers.getFlags().contains(Modifier.STATIC)) 635 ret += 1000; 636 if (modifiers.getFlags().contains(Modifier.PUBLIC)) 637 ret += 10; 638 else if (modifiers.getFlags().contains(Modifier.PROTECTED)) 639 ret += 20; 640 else if (modifiers.getFlags().contains(Modifier.PRIVATE)) 641 ret += 40; 642 else 643 ret += 30; 644 } 645 return ret; 646 } 647 648 private static String getSortText(Tree tree) { 649 switch (tree.getKind()) { 650 case CLASS: 651 return ((ClassTree)tree).getSimpleName().toString(); 652 case METHOD: 653 MethodTree mt = (MethodTree)tree; 654 StringBuilder sortParams = new StringBuilder (); 655 sortParams.append('('); 656 int cnt = 0; 657 for(Iterator <? extends VariableTree> it = mt.getParameters().iterator(); it.hasNext();) { 658 VariableTree param = it.next(); 659 if (param.getType().getKind() == Tree.Kind.IDENTIFIER) 660 sortParams.append(((IdentifierTree)param.getType()).getName().toString()); 661 else if (param.getType().getKind() == Tree.Kind.MEMBER_SELECT) 662 sortParams.append(((MemberSelectTree)param.getType()).getIdentifier().toString()); 663 if (it.hasNext()) { 664 sortParams.append(','); 665 } 666 cnt++; 667 } 668 sortParams.append(')'); 669 return mt.getName().toString() + "#" + ((cnt < 10 ? "0" : "") + cnt) + "#" + sortParams.toString(); case VARIABLE: 671 return ((VariableTree)tree).getName().toString(); 672 } 673 return ""; } 675 } 676 } 677 | Popular Tags |