Lines 49-59
Link Here
|
49 |
import com.sun.source.tree.ClassTree; |
49 |
import com.sun.source.tree.ClassTree; |
50 |
import com.sun.source.tree.CompilationUnitTree; |
50 |
import com.sun.source.tree.CompilationUnitTree; |
51 |
import com.sun.source.tree.ExpressionTree; |
51 |
import com.sun.source.tree.ExpressionTree; |
|
|
52 |
import com.sun.source.tree.IdentifierTree; |
53 |
import com.sun.source.tree.ImportTree; |
54 |
import com.sun.source.tree.MemberSelectTree; |
52 |
import com.sun.source.tree.MethodInvocationTree; |
55 |
import com.sun.source.tree.MethodInvocationTree; |
53 |
import com.sun.source.tree.MethodTree; |
56 |
import com.sun.source.tree.MethodTree; |
54 |
import com.sun.source.tree.ModifiersTree; |
57 |
import com.sun.source.tree.ModifiersTree; |
55 |
import com.sun.source.tree.NewClassTree; |
58 |
import com.sun.source.tree.NewClassTree; |
56 |
import com.sun.source.tree.PrimitiveTypeTree; |
59 |
import com.sun.source.tree.PrimitiveTypeTree; |
|
|
60 |
import com.sun.source.tree.Scope; |
57 |
import com.sun.source.tree.StatementTree; |
61 |
import com.sun.source.tree.StatementTree; |
58 |
import com.sun.source.tree.Tree; |
62 |
import com.sun.source.tree.Tree; |
59 |
import com.sun.source.tree.Tree.Kind; |
63 |
import com.sun.source.tree.Tree.Kind; |
Lines 62-69
Link Here
|
62 |
import com.sun.source.tree.WildcardTree; |
66 |
import com.sun.source.tree.WildcardTree; |
63 |
import com.sun.source.util.SourcePositions; |
67 |
import com.sun.source.util.SourcePositions; |
64 |
import com.sun.source.util.TreePath; |
68 |
import com.sun.source.util.TreePath; |
|
|
69 |
import com.sun.source.util.TreePathScanner; |
65 |
import com.sun.source.util.TreeScanner; |
70 |
import com.sun.source.util.TreeScanner; |
|
|
71 |
import com.sun.source.util.Trees; |
66 |
import com.sun.tools.javac.code.Flags; |
72 |
import com.sun.tools.javac.code.Flags; |
|
|
73 |
import com.sun.tools.javac.code.Scope.Entry; |
67 |
import com.sun.tools.javac.code.Symbol.ClassSymbol; |
74 |
import com.sun.tools.javac.code.Symbol.ClassSymbol; |
68 |
import com.sun.tools.javac.code.Type; |
75 |
import com.sun.tools.javac.code.Type; |
69 |
import com.sun.tools.javac.tree.JCTree; |
76 |
import com.sun.tools.javac.tree.JCTree; |
Lines 72-91
Link Here
|
72 |
import java.io.IOException; |
79 |
import java.io.IOException; |
73 |
import java.util.ArrayList; |
80 |
import java.util.ArrayList; |
74 |
import java.util.Collections; |
81 |
import java.util.Collections; |
|
|
82 |
import java.util.Comparator; |
75 |
import java.util.EnumSet; |
83 |
import java.util.EnumSet; |
|
|
84 |
import java.util.HashMap; |
85 |
import java.util.HashSet; |
76 |
import java.util.IdentityHashMap; |
86 |
import java.util.IdentityHashMap; |
77 |
import java.util.Iterator; |
87 |
import java.util.Iterator; |
78 |
import java.util.LinkedList; |
88 |
import java.util.LinkedList; |
79 |
import java.util.List; |
89 |
import java.util.List; |
80 |
import java.util.Map; |
90 |
import java.util.Map; |
81 |
import java.util.Set; |
91 |
import java.util.Set; |
|
|
92 |
|
82 |
import javax.lang.model.SourceVersion; |
93 |
import javax.lang.model.SourceVersion; |
83 |
import javax.lang.model.element.Element; |
94 |
import javax.lang.model.element.Element; |
84 |
|
|
|
85 |
import javax.lang.model.element.ElementKind; |
95 |
import javax.lang.model.element.ElementKind; |
86 |
import javax.lang.model.element.ExecutableElement; |
96 |
import javax.lang.model.element.ExecutableElement; |
87 |
import javax.lang.model.element.Modifier; |
97 |
import javax.lang.model.element.Modifier; |
88 |
import javax.lang.model.element.Name; |
98 |
import javax.lang.model.element.Name; |
|
|
99 |
import javax.lang.model.element.PackageElement; |
89 |
import javax.lang.model.element.TypeElement; |
100 |
import javax.lang.model.element.TypeElement; |
90 |
import javax.lang.model.element.TypeParameterElement; |
101 |
import javax.lang.model.element.TypeParameterElement; |
91 |
import javax.lang.model.element.VariableElement; |
102 |
import javax.lang.model.element.VariableElement; |
Lines 95-100
Link Here
|
95 |
import javax.lang.model.type.TypeMirror; |
106 |
import javax.lang.model.type.TypeMirror; |
96 |
import javax.lang.model.type.TypeVariable; |
107 |
import javax.lang.model.type.TypeVariable; |
97 |
import javax.lang.model.type.WildcardType; |
108 |
import javax.lang.model.type.WildcardType; |
|
|
109 |
import javax.lang.model.util.Elements; |
98 |
import javax.lang.model.util.Types; |
110 |
import javax.lang.model.util.Types; |
99 |
import javax.swing.text.Document; |
111 |
import javax.swing.text.Document; |
100 |
|
112 |
|
Lines 165-171
Link Here
|
165 |
Tree lastMember = null; |
177 |
Tree lastMember = null; |
166 |
for (Tree tree : clazz.getMembers()) { |
178 |
for (Tree tree : clazz.getMembers()) { |
167 |
TreePath path = TreePath.getPath(compilationUnit, tree); |
179 |
TreePath path = TreePath.getPath(compilationUnit, tree); |
168 |
if ((path == null || !utils.isSynthetic(path)) && ClassMemberComparator.compare(member, tree) < 0) { |
180 |
if ((path == null || !utils.isSynthetic(path)) && CLASS_MEMBER_COMPARATOR.compare(member, tree) < 0) { |
169 |
if (gdoc == null) |
181 |
if (gdoc == null) |
170 |
break; |
182 |
break; |
171 |
int pos = (int)(lastMember != null ? sp.getEndPosition(compilationUnit, lastMember) : sp.getStartPosition( compilationUnit,clazz)); |
183 |
int pos = (int)(lastMember != null ? sp.getEndPosition(compilationUnit, lastMember) : sp.getStartPosition( compilationUnit,clazz)); |
Lines 512-517
Link Here
|
512 |
BlockTree body = make.Block(Collections.singletonList(make.ExpressionStatement(make.Assignment(make.MemberSelect(isStatic? make.Identifier(clazz.getSimpleName()) : make.Identifier("this"), name), make.Identifier(name)))), false); //NOI18N |
524 |
BlockTree body = make.Block(Collections.singletonList(make.ExpressionStatement(make.Assignment(make.MemberSelect(isStatic? make.Identifier(clazz.getSimpleName()) : make.Identifier("this"), name), make.Identifier(name)))), false); //NOI18N |
513 |
return make.Method(make.Modifiers(mods), sb, make.Type(copy.getTypes().getNoType(TypeKind.VOID)), Collections.<TypeParameterTree>emptyList(), params, Collections.<ExpressionTree>emptyList(), body, null); |
525 |
return make.Method(make.Modifiers(mods), sb, make.Type(copy.getTypes().getNoType(TypeKind.VOID)), Collections.<TypeParameterTree>emptyList(), params, Collections.<ExpressionTree>emptyList(), body, null); |
514 |
} |
526 |
} |
|
|
527 |
|
528 |
/** |
529 |
* Adds import statements for given elements to a compilation unit. The import section of the |
530 |
* given compilation unit is modified according to the rules specified in the {@link CodeStyle}. |
531 |
* |
532 |
* @param cut the compilation unit to insert imports to |
533 |
* @param toImport the elements to import. |
534 |
* @return the modified compilation unit |
535 |
* @since 0.85 |
536 |
*/ |
537 |
public CompilationUnitTree addImports(CompilationUnitTree cut, Set<Element> toImport) { |
538 |
assert cut != null && toImport != null && toImport.size() > 0; |
539 |
|
540 |
ArrayList<Element> elementsToImport = new ArrayList<Element>(toImport); |
541 |
|
542 |
Trees trees = copy.getTrees(); |
543 |
Elements elements = copy.getElements(); |
544 |
ElementUtilities elementUtilities = copy.getElementUtilities(); |
545 |
CodeStyle cs = CodeStyle.getDefault(copy.getFileObject()); |
546 |
|
547 |
// check weather any conversions to star imports are needed |
548 |
int treshold = cs.countForUsingStarImport(); |
549 |
int staticTreshold = cs.countForUsingStaticStarImport(); |
550 |
Map<PackageElement, Integer> pkgCounts = new HashMap<PackageElement, Integer>(); |
551 |
pkgCounts.put(elements.getPackageElement("java.lang"), -2); //NOI18N |
552 |
pkgCounts.put((PackageElement)trees.getElement(TreePath.getPath(cut, cut.getPackageName())), -2); |
553 |
Map<TypeElement, Integer> typeCounts = new HashMap<TypeElement, Integer>(); |
554 |
Scope scope = trees.getScope(new TreePath(cut)); |
555 |
for (Element e : elementsToImport) { |
556 |
boolean isStatic = false; |
557 |
Element el = null; |
558 |
switch (e.getKind()) { |
559 |
case PACKAGE: |
560 |
el = e; |
561 |
break; |
562 |
case ANNOTATION_TYPE: |
563 |
case CLASS: |
564 |
case ENUM: |
565 |
case INTERFACE: |
566 |
if (e.getEnclosingElement().getKind() == ElementKind.PACKAGE) |
567 |
el = e.getEnclosingElement(); |
568 |
break; |
569 |
case METHOD: |
570 |
case ENUM_CONSTANT: |
571 |
case FIELD: |
572 |
isStatic = true; |
573 |
el = e.getEnclosingElement(); |
574 |
assert e.getModifiers().contains(Modifier.STATIC) && trees.isAccessible(scope, e, (DeclaredType)el.asType()) : "Only static accessible members could be imported"; //NOI18N |
575 |
break; |
576 |
default: |
577 |
assert false : "Illegal element kind: " + e.getKind(); //NOI18N |
578 |
} |
579 |
if (el != null) { |
580 |
Integer cnt = isStatic ? typeCounts.get((TypeElement)el) : pkgCounts.get((PackageElement)el); |
581 |
if (cnt == null) |
582 |
cnt = 0; |
583 |
if (el == e) { |
584 |
cnt = -1; |
585 |
} else if (cnt >= 0) { |
586 |
cnt++; |
587 |
if (isStatic ? cnt >= staticTreshold : cnt >= treshold) |
588 |
cnt = -1; |
589 |
} |
590 |
if (isStatic) { |
591 |
typeCounts.put((TypeElement)el, cnt); |
592 |
} else { |
593 |
pkgCounts.put((PackageElement)el, cnt); |
594 |
} |
595 |
} |
596 |
} |
597 |
List<ImportTree> imports = new ArrayList<ImportTree>(cut.getImports()); |
598 |
for (ImportTree imp : imports) { |
599 |
Element e = getImportedElement(cut, imp, trees); |
600 |
Element el = imp.isStatic() |
601 |
? e.getKind().isClass() || e.getKind().isInterface() ? e : elementUtilities.enclosingTypeElement(e) |
602 |
: e.getKind() == ElementKind.PACKAGE ? e : (e.getKind().isClass() || e.getKind().isInterface()) && e.getEnclosingElement().getKind() == ElementKind.PACKAGE ? e.getEnclosingElement() : null; |
603 |
if (el != null) { |
604 |
Integer cnt = imp.isStatic() ? typeCounts.get((TypeElement)el) : pkgCounts.get((PackageElement)el); |
605 |
if (cnt != null) { |
606 |
if (el == e) { |
607 |
cnt = -2; |
608 |
} else if (cnt >= 0) { |
609 |
cnt++; |
610 |
if (imp.isStatic() ? cnt >= staticTreshold : cnt >= treshold) |
611 |
cnt = -1; |
612 |
} |
613 |
if (imp.isStatic()) { |
614 |
typeCounts.put((TypeElement)el, cnt); |
615 |
} else { |
616 |
pkgCounts.put((PackageElement)el, cnt); |
617 |
} |
618 |
} |
619 |
} |
620 |
} |
621 |
|
622 |
// check for possible name clashes originating from adding the package imports |
623 |
Set<Element> explicitNamedImports = new HashSet<Element>(); |
624 |
Map<Name, TypeElement> usedTypes = null; |
625 |
JCCompilationUnit unit = (JCCompilationUnit) cut; |
626 |
if (unit.starImportScope != null) { |
627 |
for (Map.Entry<PackageElement, Integer> entry : pkgCounts.entrySet()) { |
628 |
if (entry.getValue() == -1) { |
629 |
for (Element element : entry.getKey().getEnclosedElements()) { |
630 |
if (element.getKind().isClass() || element.getKind().isInterface()) { |
631 |
Entry starEntry = unit.starImportScope.lookup((com.sun.tools.javac.util.Name)element.getSimpleName()); |
632 |
if (starEntry.scope != null) { |
633 |
if (usedTypes == null) { |
634 |
usedTypes = getUsedTypes(cut, trees); |
635 |
} |
636 |
TypeElement te = usedTypes.get(element.getSimpleName()); |
637 |
if (te != null) { |
638 |
elementsToImport.add(te); |
639 |
explicitNamedImports.add(te); |
640 |
} |
641 |
} |
642 |
} |
643 |
} |
644 |
} |
645 |
} |
646 |
} |
647 |
|
648 |
// sort the elements to import |
649 |
ImportsComparator comparator = new ImportsComparator(cs, elements); |
650 |
Collections.sort(elementsToImport, comparator); |
651 |
|
652 |
// merge the elements to import with the existing import statemetns |
653 |
TreeMaker make = copy.getTreeMaker(); |
654 |
int currentToImport = elementsToImport.size() - 1; |
655 |
int currentExisting = imports.size() - 1; |
656 |
while (currentToImport >= 0) { |
657 |
Element currentToImportElement = elementsToImport.get(currentToImport); |
658 |
boolean isStatic = false; |
659 |
Element el = null; |
660 |
switch (currentToImportElement.getKind()) { |
661 |
case PACKAGE: |
662 |
el = currentToImportElement; |
663 |
break; |
664 |
case ANNOTATION_TYPE: |
665 |
case CLASS: |
666 |
case ENUM: |
667 |
case INTERFACE: |
668 |
if (currentToImportElement.getEnclosingElement().getKind() == ElementKind.PACKAGE) |
669 |
el = currentToImportElement.getEnclosingElement(); |
670 |
break; |
671 |
case METHOD: |
672 |
case ENUM_CONSTANT: |
673 |
case FIELD: |
674 |
isStatic = true; |
675 |
el = currentToImportElement.getEnclosingElement(); |
676 |
break; |
677 |
} |
678 |
Integer cnt = el == null ? Integer.valueOf(0) : isStatic ? typeCounts.get((TypeElement)el) : pkgCounts.get((PackageElement)el); |
679 |
if (explicitNamedImports.contains(currentToImportElement)) |
680 |
cnt = 0; |
681 |
if (cnt == -2) { |
682 |
currentToImport--; |
683 |
} else { |
684 |
if (cnt == -1) { |
685 |
currentToImportElement = el; |
686 |
if (isStatic) { |
687 |
typeCounts.put((TypeElement)el, -2); |
688 |
} else { |
689 |
pkgCounts.put((PackageElement)el, -2); |
690 |
} |
691 |
} |
692 |
boolean isStar = currentToImportElement.getKind() == ElementKind.PACKAGE |
693 |
|| isStatic && (currentToImportElement.getKind().isClass() || currentToImportElement.getKind().isInterface()); |
694 |
while (currentExisting >= 0) { |
695 |
ImportTree imp = imports.get(currentExisting); |
696 |
Element impElement = getImportedElement(cut, imp, trees); |
697 |
el = imp.isStatic() |
698 |
? impElement.getKind().isClass() || impElement.getKind().isInterface() ? impElement : elementUtilities.enclosingTypeElement(impElement) |
699 |
: impElement.getKind() == ElementKind.PACKAGE ? impElement : (impElement.getKind().isClass() || impElement.getKind().isInterface()) && impElement.getEnclosingElement().getKind() == ElementKind.PACKAGE ? impElement.getEnclosingElement() : null; |
700 |
if (currentToImportElement == impElement || isStar && currentToImportElement == el) { |
701 |
imports.remove(currentExisting); |
702 |
} else if (comparator.compare(currentToImportElement, impElement) > 0) { |
703 |
break; |
704 |
} |
705 |
currentExisting--; |
706 |
} |
707 |
ExpressionTree qualIdent = make.QualIdent(currentToImportElement); |
708 |
if (isStar) |
709 |
qualIdent = make.MemberSelect(qualIdent, elements.getName("*")); //NOI18N |
710 |
imports.add(currentExisting + 1, make.Import(qualIdent, isStatic)); |
711 |
currentToImport--; |
712 |
} |
713 |
} |
714 |
|
715 |
// return a copy of the unit with changed imports section |
716 |
return make.CompilationUnit(cut.getPackageAnnotations(), cut.getPackageName(), imports, cut.getTypeDecls(), cut.getSourceFile()); |
717 |
} |
515 |
|
718 |
|
516 |
/** |
719 |
/** |
517 |
* Take a tree as a parameter, replace resolved fully qualified names with |
720 |
* Take a tree as a parameter, replace resolved fully qualified names with |
Lines 675-684
Link Here
|
675 |
|
878 |
|
676 |
return copy.getTreeUtilities().translate(result, translate); |
879 |
return copy.getTreeUtilities().translate(result, translate); |
677 |
} |
880 |
} |
|
|
881 |
|
882 |
private Element getImportedElement(CompilationUnitTree cut, ImportTree imp, Trees trees) { |
883 |
Tree qualIdent = imp.getQualifiedIdentifier(); |
884 |
if (qualIdent.getKind() != Tree.Kind.MEMBER_SELECT) |
885 |
return trees.getElement(TreePath.getPath(cut, qualIdent)); |
886 |
Name name = ((MemberSelectTree)qualIdent).getIdentifier(); |
887 |
if ("*".contentEquals(name)) //NOI18N |
888 |
return trees.getElement(TreePath.getPath(cut, ((MemberSelectTree)qualIdent).getExpression())); |
889 |
if (imp.isStatic()) { |
890 |
Element parent = trees.getElement(TreePath.getPath(cut, ((MemberSelectTree)qualIdent).getExpression())); |
891 |
if (parent != null && (parent.getKind().isClass() || parent.getKind().isInterface())) { |
892 |
Scope s = trees.getScope(new TreePath(cut)); |
893 |
for (Element e : parent.getEnclosedElements()) { |
894 |
if (name == e.getSimpleName() && e.getModifiers().contains(Modifier.STATIC) && trees.isAccessible(s, e, (DeclaredType)parent.asType())); |
895 |
return e; |
896 |
} |
897 |
return parent; |
898 |
} |
899 |
} |
900 |
return trees.getElement(TreePath.getPath(cut, qualIdent)); |
901 |
} |
902 |
|
903 |
private Map<Name, TypeElement> getUsedTypes(final CompilationUnitTree cut, final Trees trees) { |
904 |
final Map<Name, TypeElement> map = new HashMap<Name, TypeElement>(); |
905 |
new TreePathScanner<Void, Void>() { |
678 |
|
906 |
|
679 |
private static class ClassMemberComparator { |
907 |
@Override |
|
|
908 |
public Void visitIdentifier(IdentifierTree node, Void p) { |
909 |
if (!map.containsKey(node.getName())) { |
910 |
Element element = trees.getElement(getCurrentPath()); |
911 |
if (element != null && (element.getKind().isClass() || element.getKind().isInterface())) { |
912 |
map.put(node.getName(), (TypeElement) element); |
913 |
} |
914 |
} |
915 |
return super.visitIdentifier(node, p); |
916 |
} |
680 |
|
917 |
|
681 |
public static int compare(Tree tree1, Tree tree2) { |
918 |
@Override |
|
|
919 |
public Void visitCompilationUnit(CompilationUnitTree node, Void p) { |
920 |
scan(node.getPackageAnnotations(), p); |
921 |
return scan(node.getTypeDecls(), p); |
922 |
} |
923 |
}.scan(cut, null); |
924 |
return map; |
925 |
} |
926 |
|
927 |
private static class ClassMemberComparator implements Comparator<Tree> { |
928 |
|
929 |
@Override |
930 |
public int compare(Tree tree1, Tree tree2) { |
682 |
if (tree1 == tree2) |
931 |
if (tree1 == tree2) |
683 |
return 0; |
932 |
return 0; |
684 |
return getSortPriority(tree1) - getSortPriority(tree2); |
933 |
return getSortPriority(tree1) - getSortPriority(tree2); |
Lines 715-721
Link Here
|
715 |
return ret; |
964 |
return ret; |
716 |
} |
965 |
} |
717 |
} |
966 |
} |
|
|
967 |
|
968 |
private static ClassMemberComparator CLASS_MEMBER_COMPARATOR = new ClassMemberComparator(); |
718 |
|
969 |
|
|
|
970 |
private static class ImportsComparator implements Comparator<Element> { |
971 |
|
972 |
private CodeStyle.ImportGroups groups; |
973 |
|
974 |
private ImportsComparator(CodeStyle cs, Elements elements) { |
975 |
this.groups = cs.getImportGroups(); |
976 |
} |
977 |
|
978 |
@Override |
979 |
public int compare(Element e1, Element e2) { |
980 |
if (e1 == e2) |
981 |
return 0; |
982 |
|
983 |
StringBuilder sb1 = new StringBuilder(); |
984 |
if (e1.getKind().isField() || e1.getKind() == ElementKind.METHOD) { |
985 |
sb1.append('.').append(e1.getSimpleName()); |
986 |
e1 = e1.getEnclosingElement(); |
987 |
} |
988 |
if (e1.getKind().isClass() || e1.getKind().isInterface()) { |
989 |
sb1.insert(0, ((TypeElement)e1).getQualifiedName()); |
990 |
} else if (e1.getKind() == ElementKind.PACKAGE) { |
991 |
sb1.insert(0, ((PackageElement)e1).getQualifiedName()); |
992 |
} |
993 |
String s1 = sb1.toString(); |
994 |
|
995 |
StringBuilder sb2 = new StringBuilder(); |
996 |
if (e2.getKind().isField() || e2.getKind() == ElementKind.METHOD) { |
997 |
sb2.append('.').append(e2.getSimpleName()); |
998 |
e2 = e2.getEnclosingElement(); |
999 |
} |
1000 |
if (e2.getKind().isClass() || e2.getKind().isInterface()) { |
1001 |
sb2.insert(0, ((TypeElement)e2).getQualifiedName()); |
1002 |
} else if (e2.getKind() == ElementKind.PACKAGE) { |
1003 |
sb2.insert(0, ((PackageElement)e2).getQualifiedName()); |
1004 |
} |
1005 |
String s2 = sb2.toString(); |
1006 |
|
1007 |
int bal = groups.getGroupId(s1) - groups.getGroupId(s2); |
1008 |
|
1009 |
return bal == 0 ? s1.compareTo(s2) : bal; |
1010 |
} |
1011 |
} |
1012 |
|
719 |
/** |
1013 |
/** |
720 |
* Tags first method in the list, in order to select it later inside editor |
1014 |
* Tags first method in the list, in order to select it later inside editor |
721 |
* @param methods list of methods to be implemented/overriden |
1015 |
* @param methods list of methods to be implemented/overriden |