langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java
changeset 27857 7e913a535736
parent 27553 75321debd020
child 29149 3fa94aad0264
equal deleted inserted replaced
27856:d4711a6931e2 27857:7e913a535736
    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