23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package com.sun.tools.javac.code; |
26 package com.sun.tools.javac.code; |
27 |
27 |
|
28 import com.sun.tools.javac.code.Kinds.Kind; |
28 import java.util.*; |
29 import java.util.*; |
29 |
30 |
|
31 import com.sun.tools.javac.code.Symbol.TypeSymbol; |
|
32 import com.sun.tools.javac.tree.JCTree.JCImport; |
30 import com.sun.tools.javac.util.*; |
33 import com.sun.tools.javac.util.*; |
31 import com.sun.tools.javac.util.List; |
34 import com.sun.tools.javac.util.List; |
32 |
35 |
33 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; |
36 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; |
34 import static com.sun.tools.javac.code.Scope.LookupKind.RECURSIVE; |
37 import static com.sun.tools.javac.code.Scope.LookupKind.RECURSIVE; |
|
38 import java.util.stream.Stream; |
|
39 import java.util.stream.StreamSupport; |
35 |
40 |
36 /** A scope represents an area of visibility in a Java program. The |
41 /** A scope represents an area of visibility in a Java program. The |
37 * Scope class is a container for symbols which provides |
42 * Scope class is a container for symbols which provides |
38 * efficient access to symbols given their names. Scopes are implemented |
43 * efficient access to symbols given their names. Scopes are implemented |
39 * as hash tables with "open addressing" and "double hashing". |
44 * as hash tables with "open addressing" and "double hashing". |
670 else return shadowed.next(sf); |
675 else return shadowed.next(sf); |
671 } |
676 } |
672 |
677 |
673 } |
678 } |
674 |
679 |
675 public static class NamedImportScope extends CompoundScope { |
680 public static class ImportScope extends CompoundScope { |
|
681 |
|
682 public ImportScope(Symbol owner) { |
|
683 super(owner); |
|
684 } |
|
685 |
|
686 /**Finalize the content of the ImportScope to speed-up future lookups. |
|
687 * No further changes to class hierarchy or class content will be reflected. |
|
688 */ |
|
689 public void finalizeScope() { |
|
690 for (List<Scope> scopes = this.subScopes; scopes.nonEmpty(); scopes = scopes.tail) { |
|
691 Scope impScope = scopes.head; |
|
692 |
|
693 if (impScope instanceof FilterImportScope && impScope.owner.kind == Kind.TYP) { |
|
694 WriteableScope finalized = WriteableScope.create(impScope.owner); |
|
695 |
|
696 for (Symbol sym : impScope.getSymbols()) { |
|
697 finalized.enter(sym); |
|
698 } |
|
699 |
|
700 finalized.addScopeListener(new ScopeListener() { |
|
701 @Override |
|
702 public void symbolAdded(Symbol sym, Scope s) { |
|
703 Assert.error("The scope is sealed."); |
|
704 } |
|
705 @Override |
|
706 public void symbolRemoved(Symbol sym, Scope s) { |
|
707 Assert.error("The scope is sealed."); |
|
708 } |
|
709 }); |
|
710 |
|
711 scopes.head = finalized; |
|
712 } |
|
713 } |
|
714 } |
|
715 |
|
716 } |
|
717 |
|
718 public static class NamedImportScope extends ImportScope { |
676 |
719 |
677 public NamedImportScope(Symbol owner, Scope currentFileScope) { |
720 public NamedImportScope(Symbol owner, Scope currentFileScope) { |
678 super(owner); |
721 super(owner); |
679 prependSubScope(currentFileScope); |
722 prependSubScope(currentFileScope); |
680 } |
723 } |
681 |
724 |
682 public void importByName(Scope delegate, Scope origin, Name name, ImportFilter filter) { |
725 public Scope importByName(Types types, Scope origin, Name name, ImportFilter filter) { |
683 appendScope(new FilterImportScope(delegate, origin, name, filter, true)); |
726 return appendScope(new FilterImportScope(types, origin, name, filter, true)); |
684 } |
727 } |
685 |
728 |
686 public void importType(Scope delegate, Scope origin, Symbol sym) { |
729 public Scope importType(Scope delegate, Scope origin, Symbol sym) { |
687 appendScope(new SingleEntryScope(delegate.owner, sym, origin)); |
730 return appendScope(new SingleEntryScope(delegate.owner, sym, origin)); |
688 } |
731 } |
689 |
732 |
690 private void appendScope(Scope newScope) { |
733 private Scope appendScope(Scope newScope) { |
691 List<Scope> existingScopes = this.subScopes.reverse(); |
734 List<Scope> existingScopes = this.subScopes.reverse(); |
692 subScopes = List.of(existingScopes.head); |
735 subScopes = List.of(existingScopes.head); |
693 subScopes = subScopes.prepend(newScope); |
736 subScopes = subScopes.prepend(newScope); |
694 for (Scope s : existingScopes.tail) { |
737 for (Scope s : existingScopes.tail) { |
695 subScopes = subScopes.prepend(s); |
738 subScopes = subScopes.prepend(s); |
696 } |
739 } |
|
740 return newScope; |
697 } |
741 } |
698 |
742 |
699 private static class SingleEntryScope extends Scope { |
743 private static class SingleEntryScope extends Scope { |
700 |
744 |
701 private final Symbol sym; |
745 private final Symbol sym; |
733 } |
777 } |
734 |
778 |
735 } |
779 } |
736 } |
780 } |
737 |
781 |
738 public static class StarImportScope extends CompoundScope { |
782 public static class StarImportScope extends ImportScope { |
739 |
783 |
740 public StarImportScope(Symbol owner) { |
784 public StarImportScope(Symbol owner) { |
741 super(owner); |
785 super(owner); |
742 } |
786 } |
743 |
787 |
744 public void importAll(Scope delegate, |
788 public void importAll(Types types, Scope origin, |
745 Scope origin, |
|
746 ImportFilter filter, |
789 ImportFilter filter, |
747 boolean staticImport) { |
790 boolean staticImport) { |
748 for (Scope existing : subScopes) { |
791 for (Scope existing : subScopes) { |
749 Assert.check(existing instanceof FilterImportScope); |
792 Assert.check(existing instanceof FilterImportScope); |
750 FilterImportScope fis = (FilterImportScope) existing; |
793 FilterImportScope fis = (FilterImportScope) existing; |
751 if (fis.delegate == delegate && fis.origin == origin && |
794 if (fis.origin == origin && fis.filter == filter && |
752 fis.filter == filter && fis.staticImport == staticImport) |
795 fis.staticImport == staticImport) |
753 return ; //avoid entering the same scope twice |
796 return ; //avoid entering the same scope twice |
754 } |
797 } |
755 prependSubScope(new FilterImportScope(delegate, origin, null, filter, staticImport)); |
798 prependSubScope(new FilterImportScope(types, origin, null, filter, staticImport)); |
756 } |
799 } |
757 |
800 |
758 } |
801 } |
759 |
802 |
760 public interface ImportFilter { |
803 public interface ImportFilter { |
761 public boolean accepts(Scope origin, Symbol sym); |
804 public boolean accepts(Scope origin, Symbol sym); |
762 } |
805 } |
763 |
806 |
764 private static class FilterImportScope extends Scope { |
807 private static class FilterImportScope extends Scope { |
765 |
808 |
766 private final Scope delegate; |
809 private final Types types; |
767 private final Scope origin; |
810 private final Scope origin; |
768 private final Name filterName; |
811 private final Name filterName; |
769 private final ImportFilter filter; |
812 private final ImportFilter filter; |
770 private final boolean staticImport; |
813 private final boolean staticImport; |
771 |
814 |
772 public FilterImportScope(Scope delegate, |
815 public FilterImportScope(Types types, |
773 Scope origin, |
816 Scope origin, |
774 Name filterName, |
817 Name filterName, |
775 ImportFilter filter, |
818 ImportFilter filter, |
776 boolean staticImport) { |
819 boolean staticImport) { |
777 super(delegate.owner); |
820 super(origin.owner); |
778 this.delegate = delegate; |
821 this.types = types; |
779 this.origin = origin; |
822 this.origin = origin; |
780 this.filterName = filterName; |
823 this.filterName = filterName; |
781 this.filter = filter; |
824 this.filter = filter; |
782 this.staticImport = staticImport; |
825 this.staticImport = staticImport; |
783 } |
826 } |
784 |
827 |
785 @Override |
828 @Override |
786 public Iterable<Symbol> getSymbols(Filter<Symbol> sf, LookupKind lookupKind) { |
829 public Iterable<Symbol> getSymbols(final Filter<Symbol> sf, final LookupKind lookupKind) { |
787 if (filterName != null) |
830 if (filterName != null) |
788 return getSymbolsByName(filterName, sf, lookupKind); |
831 return getSymbolsByName(filterName, sf, lookupKind); |
789 return new FilteredIterable(delegate.getSymbols(sf, lookupKind)); |
832 SymbolImporter si = new SymbolImporter(staticImport) { |
|
833 @Override |
|
834 Iterable<Symbol> doLookup(TypeSymbol tsym) { |
|
835 return tsym.members().getSymbols(sf, lookupKind); |
|
836 } |
|
837 }; |
|
838 return si.importFrom((TypeSymbol) origin.owner) :: iterator; |
790 } |
839 } |
791 |
840 |
792 @Override |
841 @Override |
793 public Iterable<Symbol> getSymbolsByName(Name name, |
842 public Iterable<Symbol> getSymbolsByName(final Name name, |
794 Filter<Symbol> sf, |
843 final Filter<Symbol> sf, |
795 LookupKind lookupKind) { |
844 final LookupKind lookupKind) { |
796 if (filterName != null && filterName != name) |
845 if (filterName != null && filterName != name) |
797 return Collections.emptyList(); |
846 return Collections.emptyList(); |
798 return new FilteredIterable(delegate.getSymbolsByName(name, sf, lookupKind)); |
847 SymbolImporter si = new SymbolImporter(staticImport) { |
|
848 @Override |
|
849 Iterable<Symbol> doLookup(TypeSymbol tsym) { |
|
850 return tsym.members().getSymbolsByName(name, sf, lookupKind); |
|
851 } |
|
852 }; |
|
853 return si.importFrom((TypeSymbol) origin.owner) :: iterator; |
799 } |
854 } |
800 |
855 |
801 @Override |
856 @Override |
802 public Scope getOrigin(Symbol byName) { |
857 public Scope getOrigin(Symbol byName) { |
803 return origin; |
858 return origin; |
806 @Override |
861 @Override |
807 public boolean isStaticallyImported(Symbol byName) { |
862 public boolean isStaticallyImported(Symbol byName) { |
808 return staticImport; |
863 return staticImport; |
809 } |
864 } |
810 |
865 |
811 private class FilteredIterator implements Iterator<Symbol> { |
866 abstract class SymbolImporter { |
812 private final Iterator<Symbol> delegate; |
867 Set<Symbol> processed = new HashSet<>(); |
813 private Symbol next; |
868 List<Iterable<Symbol>> delegates = List.nil(); |
814 |
869 final boolean inspectSuperTypes; |
815 public FilteredIterator(Iterator<Symbol> delegate) { |
870 public SymbolImporter(boolean inspectSuperTypes) { |
816 this.delegate = delegate; |
871 this.inspectSuperTypes = inspectSuperTypes; |
817 update(); |
872 } |
818 } |
873 Stream<Symbol> importFrom(TypeSymbol tsym) { |
819 |
874 if (tsym == null || !processed.add(tsym)) |
820 void update() { |
875 return Stream.empty(); |
821 while (delegate.hasNext()) { |
876 |
822 if (filter.accepts(origin, next = delegate.next())) |
877 Stream<Symbol> result = Stream.empty(); |
823 return; |
878 |
824 } |
879 if (inspectSuperTypes) { |
825 |
880 // also import inherited names |
826 next = null; |
881 result = importFrom(types.supertype(tsym.type).tsym); |
827 } |
882 for (Type t : types.interfaces(tsym.type)) |
828 |
883 result = Stream.concat(importFrom(t.tsym), result); |
829 @Override |
884 } |
830 public boolean hasNext() { |
885 |
831 return next != null; |
886 return Stream.concat(StreamSupport.stream(doLookup(tsym).spliterator(), false) |
832 } |
887 .filter(s -> filter.accepts(origin, s)), |
833 |
888 result); |
834 @Override |
889 } |
835 public Symbol next() { |
890 abstract Iterable<Symbol> doLookup(TypeSymbol tsym); |
836 Symbol result = next; |
|
837 |
|
838 update(); |
|
839 |
|
840 return result; |
|
841 } |
|
842 |
|
843 @Override |
|
844 public void remove() { |
|
845 throw new UnsupportedOperationException("Not supported."); |
|
846 } |
|
847 |
|
848 } |
|
849 |
|
850 private class FilteredIterable implements Iterable<Symbol> { |
|
851 |
|
852 private final Iterable<Symbol> unfiltered; |
|
853 |
|
854 public FilteredIterable(Iterable<Symbol> unfiltered) { |
|
855 this.unfiltered = unfiltered; |
|
856 } |
|
857 |
|
858 @Override |
|
859 public Iterator<Symbol> iterator() { |
|
860 return new FilteredIterator(unfiltered.iterator()); |
|
861 } |
|
862 } |
891 } |
863 |
892 |
864 } |
893 } |
865 |
894 |
866 /** A class scope adds capabilities to keep track of changes in related |
895 /** A class scope adds capabilities to keep track of changes in related |