001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.java.editor.codegen;
042:
043: import com.sun.source.tree.AssignmentTree;
044: import com.sun.source.tree.ClassTree;
045: import com.sun.source.tree.ExpressionTree;
046: import com.sun.source.tree.IdentifierTree;
047: import com.sun.source.tree.MemberSelectTree;
048: import com.sun.source.tree.MethodTree;
049: import com.sun.source.tree.ModifiersTree;
050: import com.sun.source.tree.Tree;
051: import com.sun.source.tree.VariableTree;
052: import com.sun.source.util.SourcePositions;
053: import com.sun.source.util.TreePath;
054: import com.sun.source.util.TreePathScanner;
055: import com.sun.source.util.Trees;
056: import java.io.IOException;
057: import java.util.ArrayList;
058: import java.util.Collection;
059: import java.util.EnumSet;
060: import java.util.HashMap;
061: import java.util.HashSet;
062: import java.util.Iterator;
063: import java.util.List;
064: import java.util.Map;
065: import java.util.Set;
066: import java.util.logging.Level;
067: import java.util.logging.Logger;
068: import javax.lang.model.element.Element;
069: import javax.lang.model.element.ElementKind;
070: import javax.lang.model.element.ExecutableElement;
071: import javax.lang.model.element.Modifier;
072: import javax.lang.model.element.PackageElement;
073: import javax.lang.model.element.TypeElement;
074: import javax.lang.model.element.VariableElement;
075: import javax.lang.model.type.DeclaredType;
076: import javax.lang.model.type.TypeKind;
077: import javax.lang.model.type.TypeMirror;
078: import javax.lang.model.util.ElementFilter;
079: import javax.lang.model.util.Types;
080: import javax.swing.JButton;
081: import javax.swing.JComponent;
082: import javax.swing.text.Document;
083: import javax.swing.text.JTextComponent;
084: import org.netbeans.api.java.queries.SourceLevelQuery;
085: import org.netbeans.api.java.source.CompilationInfo;
086: import org.netbeans.api.java.source.ElementUtilities;
087: import org.netbeans.api.java.source.GeneratorUtilities;
088: import org.netbeans.api.java.source.ModificationResult;
089: import org.netbeans.api.java.source.SourceUtils;
090: import org.netbeans.api.java.source.TreeMaker;
091: import org.netbeans.api.java.source.TreeUtilities;
092: import org.netbeans.api.java.source.WorkingCopy;
093: import org.netbeans.editor.GuardedDocument;
094: import org.netbeans.editor.GuardedException;
095: import org.netbeans.editor.Utilities;
096: import org.openide.DialogDescriptor;
097: import org.openide.ErrorManager;
098: import org.openide.filesystems.FileObject;
099: import org.openide.util.NbBundle;
100:
101: /**
102: *
103: * @author Jan Lahoda, Dusan Balek
104: */
105: public class GeneratorUtils {
106:
107: private static final ErrorManager ERR = ErrorManager.getDefault()
108: .getInstance(GeneratorUtils.class.getName());
109: private static final String ERROR = "<error>"; //NOI18N
110: public static final int GETTERS_ONLY = 1;
111: public static final int SETTERS_ONLY = 2;
112:
113: private GeneratorUtils() {
114: }
115:
116: public static ClassTree insertClassMember(WorkingCopy copy,
117: TreePath path, Tree member) {
118: assert path.getLeaf().getKind() == Tree.Kind.CLASS;
119: TreeUtilities tu = copy.getTreeUtilities();
120: int idx = 0;
121: for (Tree tree : ((ClassTree) path.getLeaf()).getMembers()) {
122: if (!tu.isSynthetic(new TreePath(path, tree))
123: && ClassMemberComparator.compare(member, tree) < 0)
124: break;
125: idx++;
126: }
127: return copy.getTreeMaker().insertClassMember(
128: (ClassTree) path.getLeaf(), idx, member);
129: }
130:
131: public static List<? extends ExecutableElement> findUndefs(
132: CompilationInfo info, TypeElement impl) {
133: if (ERR.isLoggable(ErrorManager.INFORMATIONAL))
134: ERR.log(ErrorManager.INFORMATIONAL, "findUndefs(" + info
135: + ", " + impl + ")");
136: List<? extends ExecutableElement> undef = info
137: .getElementUtilities().findUnimplementedMethods(impl);
138: if (ERR.isLoggable(ErrorManager.INFORMATIONAL))
139: ERR.log(ErrorManager.INFORMATIONAL, "undef=" + undef);
140: return undef;
141: }
142:
143: public static List<? extends ExecutableElement> findOverridable(
144: CompilationInfo info, TypeElement impl) {
145: List<ExecutableElement> overridable = new ArrayList<ExecutableElement>();
146: List<TypeElement> classes = getAllClasses(impl);
147:
148: if (ERR.isLoggable(ErrorManager.INFORMATIONAL))
149: ERR.log(ErrorManager.INFORMATIONAL, "classes=" + classes);
150:
151: for (TypeElement te : classes.subList(1, classes.size())) {
152: for (ExecutableElement ee : ElementFilter.methodsIn(te
153: .getEnclosedElements())) {
154: Set<Modifier> set = EnumSet.copyOf(NOT_OVERRIDABLE);
155:
156: set.removeAll(ee.getModifiers());
157:
158: if (set.size() != NOT_OVERRIDABLE.size())
159: continue;
160:
161: if (ee.getModifiers().contains(Modifier.PRIVATE)) //do not offer overriding of private methods
162: continue;
163:
164: if (overridesPackagePrivateOutsidePackage(ee, impl)) //do not offer package private methods in case they're from different package
165: continue;
166:
167: int this Element = classes.indexOf(te);
168:
169: if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
170: ERR.log(ErrorManager.INFORMATIONAL, "ee=" + ee);
171: ERR.log(ErrorManager.INFORMATIONAL,
172: "thisElement = " + this Element);
173: ERR.log(ErrorManager.INFORMATIONAL,
174: "classes.subList(0, thisElement + 1)="
175: + classes.subList(0,
176: this Element + 1));
177: ERR.log(ErrorManager.INFORMATIONAL,
178: "isOverriden(info, ee, classes.subList(0, thisElement + 1))="
179: + isOverriden(info, ee,
180: classes.subList(0,
181: this Element + 1)));
182: }
183:
184: if (!isOverriden(info, ee, classes.subList(0,
185: this Element + 1))) {
186: overridable.add(ee);
187: }
188: }
189: }
190:
191: return overridable;
192: }
193:
194: public static Map<? extends TypeElement, ? extends List<? extends VariableElement>> findAllAccessibleFields(
195: CompilationInfo info, TypeElement clazz) {
196: Map<TypeElement, List<? extends VariableElement>> result = new HashMap<TypeElement, List<? extends VariableElement>>();
197:
198: result.put(clazz, findAllAccessibleFields(info, clazz, clazz));
199:
200: for (TypeElement te : getAllParents(clazz)) {
201: result.put(te, findAllAccessibleFields(info, clazz, te));
202: }
203:
204: return result;
205: }
206:
207: public static void scanForFieldsAndConstructors(
208: CompilationInfo info, final TreePath clsPath,
209: final Set<VariableElement> initializedFields,
210: final Set<VariableElement> uninitializedFields,
211: final List<ExecutableElement> constructors) {
212: final Trees trees = info.getTrees();
213: new TreePathScanner<Void, Boolean>() {
214: @Override
215: public Void visitVariable(VariableTree node, Boolean p) {
216: if (ERROR.contentEquals(node.getName()))
217: return null;
218: Element el = trees.getElement(getCurrentPath());
219: if (el != null && el.getKind() == ElementKind.FIELD
220: && !el.getModifiers().contains(Modifier.STATIC)
221: && node.getInitializer() == null
222: && !initializedFields.remove(el))
223: uninitializedFields.add((VariableElement) el);
224: return null;
225: }
226:
227: @Override
228: public Void visitAssignment(AssignmentTree node, Boolean p) {
229: Element el = trees.getElement(new TreePath(
230: getCurrentPath(), node.getVariable()));
231: if (el != null && el.getKind() == ElementKind.FIELD
232: && !uninitializedFields.remove(el))
233: initializedFields.add((VariableElement) el);
234: return null;
235: }
236:
237: @Override
238: public Void visitClass(ClassTree node, Boolean p) {
239: //do not analyse the inner classes:
240: return p ? super .visitClass(node, false) : null;
241: }
242:
243: @Override
244: public Void visitMethod(MethodTree node, Boolean p) {
245: Element el = trees.getElement(getCurrentPath());
246: if (el != null
247: && el.getKind() == ElementKind.CONSTRUCTOR)
248: constructors.add((ExecutableElement) el);
249: return null;
250: }
251: }.scan(clsPath, Boolean.TRUE);
252: }
253:
254: public static void generateAllAbstractMethodImplementations(
255: WorkingCopy wc, TreePath path) {
256: assert path.getLeaf().getKind() == Tree.Kind.CLASS;
257: TypeElement te = (TypeElement) wc.getTrees().getElement(path);
258: if (te != null) {
259: TreeMaker make = wc.getTreeMaker();
260: ClassTree clazz = (ClassTree) path.getLeaf();
261: List<Tree> members = new ArrayList<Tree>(clazz.getMembers());
262: GeneratorUtilities gu = GeneratorUtilities.get(wc);
263: ElementUtilities elemUtils = wc.getElementUtilities();
264: for (ExecutableElement element : elemUtils
265: .findUnimplementedMethods(te))
266: members.add(gu.createAbstractMethodImplementation(te,
267: element));
268: ClassTree nue = make.Class(clazz.getModifiers(), clazz
269: .getSimpleName(), clazz.getTypeParameters(), clazz
270: .getExtendsClause(), (List<ExpressionTree>) clazz
271: .getImplementsClause(), members);
272: wc.rewrite(clazz, nue);
273: }
274: }
275:
276: public static void generateAbstractMethodImplementations(
277: WorkingCopy wc, TreePath path,
278: List<? extends ExecutableElement> elements, int index) {
279: assert path.getLeaf().getKind() == Tree.Kind.CLASS;
280: TypeElement te = (TypeElement) wc.getTrees().getElement(path);
281: if (te != null) {
282: TreeMaker make = wc.getTreeMaker();
283: ClassTree clazz = (ClassTree) path.getLeaf();
284: List<Tree> members = new ArrayList<Tree>(clazz.getMembers());
285: GeneratorUtilities gu = GeneratorUtilities.get(wc);
286: members.addAll(index, gu
287: .createAbstractMethodImplementations(te, elements));
288: ClassTree nue = make.Class(clazz.getModifiers(), clazz
289: .getSimpleName(), clazz.getTypeParameters(), clazz
290: .getExtendsClause(), (List<ExpressionTree>) clazz
291: .getImplementsClause(), members);
292: wc.rewrite(clazz, nue);
293: }
294: }
295:
296: public static void generateAbstractMethodImplementation(
297: WorkingCopy wc, TreePath path, ExecutableElement element,
298: int index) {
299: assert path.getLeaf().getKind() == Tree.Kind.CLASS;
300: TypeElement te = (TypeElement) wc.getTrees().getElement(path);
301: if (te != null) {
302: GeneratorUtilities gu = GeneratorUtilities.get(wc);
303: ClassTree decl = wc.getTreeMaker().insertClassMember(
304: (ClassTree) path.getLeaf(), index,
305: gu.createAbstractMethodImplementation(te, element));
306: wc.rewrite(path.getLeaf(), decl);
307: }
308: }
309:
310: public static void generateMethodOverrides(WorkingCopy wc,
311: TreePath path, List<? extends ExecutableElement> elements,
312: int index) {
313: assert path.getLeaf().getKind() == Tree.Kind.CLASS;
314: TypeElement te = (TypeElement) wc.getTrees().getElement(path);
315: if (te != null) {
316: TreeMaker make = wc.getTreeMaker();
317: ClassTree clazz = (ClassTree) path.getLeaf();
318: List<Tree> members = new ArrayList<Tree>(clazz.getMembers());
319: GeneratorUtilities gu = GeneratorUtilities.get(wc);
320: members.addAll(index, gu.createOverridingMethods(te,
321: elements));
322: ClassTree nue = make.Class(clazz.getModifiers(), clazz
323: .getSimpleName(), clazz.getTypeParameters(), clazz
324: .getExtendsClause(), (List<ExpressionTree>) clazz
325: .getImplementsClause(), members);
326: wc.rewrite(clazz, nue);
327: }
328: }
329:
330: public static void generateMethodOverride(WorkingCopy wc,
331: TreePath path, ExecutableElement element, int index) {
332: assert path.getLeaf().getKind() == Tree.Kind.CLASS;
333: TypeElement te = (TypeElement) wc.getTrees().getElement(path);
334: if (te != null) {
335: GeneratorUtilities gu = GeneratorUtilities.get(wc);
336: ClassTree decl = wc.getTreeMaker().insertClassMember(
337: (ClassTree) path.getLeaf(), index,
338: gu.createOverridingMethod(te, element));
339: wc.rewrite(path.getLeaf(), decl);
340: }
341: }
342:
343: public static void generateConstructor(WorkingCopy wc,
344: TreePath path,
345: Iterable<? extends VariableElement> initFields,
346: ExecutableElement inheritedConstructor, int index) {
347: TreeMaker make = wc.getTreeMaker();
348: ClassTree clazz = (ClassTree) path.getLeaf();
349: TypeElement te = (TypeElement) wc.getTrees().getElement(path);
350: GeneratorUtilities gu = GeneratorUtilities.get(wc);
351: ClassTree decl = make.insertClassMember(clazz, index,
352: gu.createConstructor(te, initFields,
353: inheritedConstructor)); //NOI18N
354: wc.rewrite(path.getLeaf(), decl);
355: }
356:
357: public static void generateConstructors(WorkingCopy wc,
358: TreePath path,
359: Iterable<? extends VariableElement> initFields,
360: List<? extends ExecutableElement> inheritedConstructors,
361: int index) {
362: TreeMaker make = wc.getTreeMaker();
363: ClassTree clazz = (ClassTree) path.getLeaf();
364: TypeElement te = (TypeElement) wc.getTrees().getElement(path);
365: GeneratorUtilities gu = GeneratorUtilities.get(wc);
366: ClassTree decl = clazz;
367: for (ExecutableElement inheritedConstructor : inheritedConstructors) {
368: decl = make.insertClassMember(decl, index, gu
369: .createConstructor(te, initFields,
370: inheritedConstructor)); //NOI18N
371: }
372: wc.rewrite(clazz, decl);
373: }
374:
375: public static void generateGettersAndSetters(WorkingCopy wc,
376: TreePath path, Iterable<? extends VariableElement> fields,
377: int type, int index) {
378: assert path.getLeaf().getKind() == Tree.Kind.CLASS;
379: TypeElement te = (TypeElement) wc.getTrees().getElement(path);
380: if (te != null) {
381: TreeMaker make = wc.getTreeMaker();
382: GeneratorUtilities gu = GeneratorUtilities.get(wc);
383: ClassTree clazz = (ClassTree) path.getLeaf();
384: List<Tree> members = new ArrayList<Tree>(clazz.getMembers());
385: List<Tree> methods = new ArrayList<Tree>();
386: for (VariableElement element : fields) {
387: if (type != SETTERS_ONLY)
388: methods.add(gu.createGetter(te, element));
389: if (type != GETTERS_ONLY)
390: methods.add(gu.createSetter(te, element));
391: }
392: members.addAll(index, methods);
393: ClassTree nue = make.Class(clazz.getModifiers(), clazz
394: .getSimpleName(), clazz.getTypeParameters(), clazz
395: .getExtendsClause(), (List<ExpressionTree>) clazz
396: .getImplementsClause(), members);
397: wc.rewrite(clazz, nue);
398: }
399: }
400:
401: public static boolean hasGetter(CompilationInfo info,
402: VariableElement field,
403: Map<String, List<ExecutableElement>> methods) {
404: CharSequence name = field.getSimpleName();
405: assert name.length() > 0;
406: TypeMirror type = field.asType();
407: StringBuilder sb = new StringBuilder();
408: sb.append(type.getKind() == TypeKind.BOOLEAN ? "is" : "get")
409: .append(Character.toUpperCase(name.charAt(0))).append(
410: name.subSequence(1, name.length())); //NOI18N
411: Types types = info.getTypes();
412: List<ExecutableElement> candidates = methods.get(sb.toString());
413: if (candidates != null) {
414: for (ExecutableElement candidate : candidates) {
415: if (candidate.getParameters().isEmpty()
416: && types.isSameType(candidate.getReturnType(),
417: type))
418: return true;
419: }
420: }
421: return false;
422: }
423:
424: public static boolean hasSetter(CompilationInfo info,
425: VariableElement field,
426: Map<String, List<ExecutableElement>> methods) {
427: CharSequence name = field.getSimpleName();
428: assert name.length() > 0;
429: TypeMirror type = field.asType();
430: StringBuilder sb = new StringBuilder();
431: sb.append("set").append(Character.toUpperCase(name.charAt(0)))
432: .append(name.subSequence(1, name.length())); //NOI18N
433: Types types = info.getTypes();
434: List<ExecutableElement> candidates = methods.get(sb.toString());
435: if (candidates != null) {
436: for (ExecutableElement candidate : candidates) {
437: if (candidate.getReturnType().getKind() == TypeKind.VOID
438: && candidate.getParameters().size() == 1
439: && types.isSameType(candidate.getParameters()
440: .get(0).asType(), type))
441: return true;
442: }
443: }
444: return false;
445: }
446:
447: public static int findClassMemberIndex(WorkingCopy wc,
448: ClassTree clazz, int offset) {
449: int index = 0;
450: SourcePositions sp = wc.getTrees().getSourcePositions();
451: GuardedDocument gdoc = null;
452: try {
453: Document doc = wc.getDocument();
454: if (doc != null && doc instanceof GuardedDocument)
455: gdoc = (GuardedDocument) doc;
456: } catch (IOException ioe) {
457: }
458: Tree lastMember = null;
459: for (Tree tree : clazz.getMembers()) {
460: if (offset <= sp.getStartPosition(wc.getCompilationUnit(),
461: tree)) {
462: if (gdoc == null)
463: break;
464: int pos = (int) (lastMember != null ? sp
465: .getEndPosition(wc.getCompilationUnit(),
466: lastMember) : sp.getStartPosition(wc
467: .getCompilationUnit(), clazz));
468: pos = gdoc.getGuardedBlockChain().adjustToBlockEnd(pos);
469: if (pos <= sp.getStartPosition(wc.getCompilationUnit(),
470: tree))
471: break;
472: }
473: index++;
474: lastMember = tree;
475: }
476: return index;
477: }
478:
479: private static List<? extends VariableElement> findAllAccessibleFields(
480: CompilationInfo info, TypeElement accessibleFrom,
481: TypeElement toScan) {
482: List<VariableElement> result = new ArrayList<VariableElement>();
483:
484: for (VariableElement ve : ElementFilter.fieldsIn(toScan
485: .getEnclosedElements())) {
486: //check if ve is accessible from accessibleFrom:
487: if (ve.getModifiers().contains(Modifier.PUBLIC)) {
488: result.add(ve);
489: continue;
490: }
491: if (ve.getModifiers().contains(Modifier.PRIVATE)) {
492: if (accessibleFrom == toScan)
493: result.add(ve);
494: continue;
495: }
496: if (ve.getModifiers().contains(Modifier.PROTECTED)) {
497: if (getAllParents(accessibleFrom).contains(toScan))
498: result.add(ve);
499: continue;
500: }
501: //TODO:package private:
502: }
503:
504: return result;
505: }
506:
507: public static Collection<TypeElement> getAllParents(TypeElement of) {
508: Set<TypeElement> result = new HashSet<TypeElement>();
509:
510: for (TypeMirror t : of.getInterfaces()) {
511: TypeElement te = (TypeElement) ((DeclaredType) t)
512: .asElement();
513:
514: if (te != null) {
515: result.add(te);
516: result.addAll(getAllParents(te));
517: } else {
518: if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
519: ERR.log(ErrorManager.INFORMATIONAL, "te=null, t="
520: + t);
521: }
522: }
523: }
524:
525: TypeMirror sup = of.getSuperclass();
526: TypeElement te = sup.getKind() == TypeKind.DECLARED ? (TypeElement) ((DeclaredType) sup)
527: .asElement()
528: : null;
529:
530: if (te != null) {
531: result.add(te);
532: result.addAll(getAllParents(te));
533: } else {
534: if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
535: ERR.log(ErrorManager.INFORMATIONAL, "te=null, t=" + of);
536: }
537: }
538:
539: return result;
540: }
541:
542: public static boolean supportsOverride(FileObject file) {
543: return SUPPORTS_OVERRIDE_SOURCE_LEVELS
544: .contains(SourceLevelQuery.getSourceLevel(file));
545: }
546:
547: private static final Set<String> SUPPORTS_OVERRIDE_SOURCE_LEVELS;
548:
549: static {
550: SUPPORTS_OVERRIDE_SOURCE_LEVELS = new HashSet();
551:
552: SUPPORTS_OVERRIDE_SOURCE_LEVELS.add("1.5");
553: SUPPORTS_OVERRIDE_SOURCE_LEVELS.add("1.6");
554: }
555:
556: private static List<TypeElement> getAllClasses(TypeElement of) {
557: List<TypeElement> result = new ArrayList<TypeElement>();
558: TypeMirror sup = of.getSuperclass();
559: TypeElement te = sup.getKind() == TypeKind.DECLARED ? (TypeElement) ((DeclaredType) sup)
560: .asElement()
561: : null;
562:
563: result.add(of);
564:
565: if (te != null) {
566: result.addAll(getAllClasses(te));
567: } else {
568: if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
569: ERR.log(ErrorManager.INFORMATIONAL, "te=null, t=" + of);
570: }
571: }
572:
573: return result;
574: }
575:
576: private static boolean isOverriden(CompilationInfo info,
577: ExecutableElement methodBase, List<TypeElement> classes) {
578: if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
579: ERR.log(ErrorManager.INFORMATIONAL, "isOverriden(" + info
580: + ", " + methodBase + ", " + classes + ")");
581: }
582:
583: for (TypeElement impl : classes) {
584: for (ExecutableElement methodImpl : ElementFilter
585: .methodsIn(impl.getEnclosedElements())) {
586: if (ERR.isLoggable(ErrorManager.INFORMATIONAL)
587: && info.getElements().overrides(methodImpl,
588: methodBase, impl)) {
589: ERR.log(ErrorManager.INFORMATIONAL, "overrides:");
590: ERR.log(ErrorManager.INFORMATIONAL, "impl=" + impl);
591: ERR.log(ErrorManager.INFORMATIONAL, "methodImpl="
592: + methodImpl);
593: }
594:
595: if (info.getElements().overrides(methodImpl,
596: methodBase, impl))
597: return true;
598: }
599: }
600:
601: if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
602: ERR.log(ErrorManager.INFORMATIONAL,
603: "no overriding methods overrides:");
604: }
605:
606: return false;
607: }
608:
609: private static final Set<Modifier> NOT_OVERRIDABLE = /*EnumSet.noneOf(Modifier.class);/*/EnumSet
610: .of(Modifier.ABSTRACT, Modifier.STATIC, Modifier.FINAL);
611:
612: public static boolean isAccessible(TypeElement from, Element what) {
613: if (what.getModifiers().contains(Modifier.PUBLIC))
614: return true;
615:
616: TypeElement fromTopLevel = SourceUtils
617: .getOutermostEnclosingTypeElement(from);
618: TypeElement whatTopLevel = SourceUtils
619: .getOutermostEnclosingTypeElement(what);
620:
621: if (fromTopLevel.equals(whatTopLevel))
622: return true;
623:
624: if (what.getModifiers().contains(Modifier.PRIVATE))
625: return false;
626:
627: if (what.getModifiers().contains(Modifier.PROTECTED)) {
628: if (getAllClasses(fromTopLevel).contains(
629: SourceUtils.getEnclosingTypeElement(what)))
630: return true;
631: }
632:
633: //package private:
634: return ((PackageElement) fromTopLevel.getEnclosingElement())
635: .getQualifiedName().toString().contentEquals(
636: ((PackageElement) whatTopLevel
637: .getEnclosingElement())
638: .getQualifiedName());
639: }
640:
641: static DialogDescriptor createDialogDescriptor(JComponent content,
642: String label) {
643: JButton[] buttons = new JButton[2];
644: buttons[0] = new JButton(NbBundle.getMessage(
645: GeneratorUtils.class, "LBL_generate_button"));
646: buttons[0].getAccessibleContext().setAccessibleDescription(
647: NbBundle.getMessage(GeneratorUtils.class,
648: "A11Y_Generate"));
649: buttons[1] = new JButton(NbBundle.getMessage(
650: GeneratorUtils.class, "LBL_cancel_button"));
651: return new DialogDescriptor(content, label, true, buttons,
652: buttons[0], DialogDescriptor.DEFAULT_ALIGN, null, null);
653:
654: }
655:
656: /**
657: * Detects if this element overrides package private element from superclass
658: * outside package
659: * @param ee elememt to test
660: * @return true if it does
661: */
662: private static boolean overridesPackagePrivateOutsidePackage(
663: ExecutableElement ee, TypeElement impl) {
664: String elemPackageName = ee.getEnclosingElement()
665: .getEnclosingElement().getSimpleName().toString();
666: String currentPackageName = impl.getEnclosingElement()
667: .getSimpleName().toString();
668: if (!ee.getModifiers().contains(Modifier.PRIVATE)
669: && !ee.getModifiers().contains(Modifier.PUBLIC)
670: && !ee.getModifiers().contains(Modifier.PROTECTED)
671: && !currentPackageName.equals(elemPackageName))
672: return true;
673: else
674: return false;
675: }
676:
677: private static class ClassMemberComparator {
678:
679: public static int compare(Tree tree1, Tree tree2) {
680: if (tree1 == tree2)
681: return 0;
682: int importanceDiff = getSortPriority(tree1)
683: - getSortPriority(tree2);
684: if (importanceDiff != 0)
685: return importanceDiff;
686: int alphabeticalDiff = getSortText(tree1).compareTo(
687: getSortText(tree2));
688: if (alphabeticalDiff != 0)
689: return alphabeticalDiff;
690: return -1;
691: }
692:
693: private static int getSortPriority(Tree tree) {
694: int ret = 0;
695: ModifiersTree modifiers = null;
696: switch (tree.getKind()) {
697: case CLASS:
698: ret = 400;
699: modifiers = ((ClassTree) tree).getModifiers();
700: break;
701: case METHOD:
702: MethodTree mt = (MethodTree) tree;
703: if (mt.getName().contentEquals("<init>"))
704: ret = 200;
705: else
706: ret = 300;
707: modifiers = mt.getModifiers();
708: break;
709: case VARIABLE:
710: ret = 100;
711: modifiers = ((VariableTree) tree).getModifiers();
712: break;
713: }
714: if (modifiers != null) {
715: if (!modifiers.getFlags().contains(Modifier.STATIC))
716: ret += 1000;
717: if (modifiers.getFlags().contains(Modifier.PUBLIC))
718: ret += 10;
719: else if (modifiers.getFlags().contains(
720: Modifier.PROTECTED))
721: ret += 20;
722: else if (modifiers.getFlags()
723: .contains(Modifier.PRIVATE))
724: ret += 40;
725: else
726: ret += 30;
727: }
728: return ret;
729: }
730:
731: private static String getSortText(Tree tree) {
732: switch (tree.getKind()) {
733: case CLASS:
734: return ((ClassTree) tree).getSimpleName().toString();
735: case METHOD:
736: MethodTree mt = (MethodTree) tree;
737: StringBuilder sortParams = new StringBuilder();
738: sortParams.append('(');
739: int cnt = 0;
740: for (Iterator<? extends VariableTree> it = mt
741: .getParameters().iterator(); it.hasNext();) {
742: VariableTree param = it.next();
743: if (param.getType().getKind() == Tree.Kind.IDENTIFIER)
744: sortParams.append(((IdentifierTree) param
745: .getType()).getName().toString());
746: else if (param.getType().getKind() == Tree.Kind.MEMBER_SELECT)
747: sortParams.append(((MemberSelectTree) param
748: .getType()).getIdentifier().toString());
749: if (it.hasNext()) {
750: sortParams.append(',');
751: }
752: cnt++;
753: }
754: sortParams.append(')');
755: return mt.getName().toString() + "#"
756: + ((cnt < 10 ? "0" : "") + cnt) + "#"
757: + sortParams.toString(); //NOI18N
758: case VARIABLE:
759: return ((VariableTree) tree).getName().toString();
760: }
761: return ""; //NOI18N
762: }
763: }
764:
765: public static void guardedCommit(JTextComponent component,
766: ModificationResult mr) throws IOException {
767: try {
768: mr.commit();
769: } catch (IOException e) {
770: if (e.getCause() instanceof GuardedException) {
771: String message = NbBundle.getMessage(
772: GeneratorUtils.class, "ERR_CannotApplyGuarded");
773:
774: Utilities.setStatusBoldText(component, message);
775: Logger.getLogger(GeneratorUtils.class.getName()).log(
776: Level.FINE, null, e);
777: }
778: }
779: }
780: }
|