src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java
changeset 51094 a49d106e9b7c
parent 49917 1871c5d07caf
child 53242 e81edc1f6f7e
equal deleted inserted replaced
51093:4db6e8715e35 51094:a49d106e9b7c
    24  */
    24  */
    25 
    25 
    26 package com.sun.tools.javac.model;
    26 package com.sun.tools.javac.model;
    27 
    27 
    28 import java.util.Collections;
    28 import java.util.Collections;
       
    29 import java.util.HashMap;
    29 import java.util.HashSet;
    30 import java.util.HashSet;
    30 import java.util.LinkedHashSet;
    31 import java.util.LinkedHashSet;
    31 import java.util.Map;
    32 import java.util.Map;
       
    33 import java.util.Optional;
    32 import java.util.Set;
    34 import java.util.Set;
    33 import java.util.stream.Collectors;
    35 import java.util.stream.Collectors;
    34 
    36 
    35 import javax.lang.model.AnnotatedConstruct;
    37 import javax.lang.model.AnnotatedConstruct;
    36 import javax.lang.model.SourceVersion;
    38 import javax.lang.model.SourceVersion;
   182             return nameToSymbol((ModuleSymbol) module, strName, clazz);
   184             return nameToSymbol((ModuleSymbol) module, strName, clazz);
   183         }
   185         }
   184     }
   186     }
   185 
   187 
   186     private final Set<String> alreadyWarnedDuplicates = new HashSet<>();
   188     private final Set<String> alreadyWarnedDuplicates = new HashSet<>();
   187 
   189     private final Map<Pair<String, String>, Optional<Symbol>> resultCache = new HashMap<>();
       
   190 
       
   191     @SuppressWarnings("unchecked")
   188     private <S extends Symbol> S unboundNameToSymbol(String methodName,
   192     private <S extends Symbol> S unboundNameToSymbol(String methodName,
   189                                                      String nameStr,
   193                                                      String nameStr,
   190                                                      Class<S> clazz) {
   194                                                      Class<S> clazz) {
   191         if (modules.getDefaultModule() == syms.noModule) { //not a modular mode:
   195         if (modules.getDefaultModule() == syms.noModule) { //not a modular mode:
   192             return nameToSymbol(syms.noModule, nameStr, clazz);
   196             return nameToSymbol(syms.noModule, nameStr, clazz);
   193         }
   197         }
   194 
   198 
   195         Set<S> found = new LinkedHashSet<>();
   199         return (S) resultCache.computeIfAbsent(Pair.of(methodName, nameStr), p -> {
   196 
   200             Set<S> found = new LinkedHashSet<>();
   197         for (ModuleSymbol msym : modules.allModules()) {
   201 
   198             S sym = nameToSymbol(msym, nameStr, clazz);
   202             for (ModuleSymbol msym : modules.allModules()) {
   199 
   203                 S sym = nameToSymbol(msym, nameStr, clazz);
   200             if (sym == null)
   204 
   201                 continue;
   205                 if (sym == null)
   202 
   206                     continue;
   203             if (clazz == ClassSymbol.class) {
   207 
   204                 // Always include classes
   208                 if (clazz == ClassSymbol.class) {
   205                 found.add(sym);
   209                     // Always include classes
   206             } else if (clazz == PackageSymbol.class) {
       
   207                 // In module mode, ignore the "spurious" empty packages that "enclose" module-specific packages.
       
   208                 // For example, if a module contains classes or package info in package p.q.r, it will also appear
       
   209                 // to have additional packages p.q and p, even though these packages have no content other
       
   210                 // than the subpackage.  We don't want those empty packages showing up in searches for p or p.q.
       
   211                 if (!sym.members().isEmpty() || ((PackageSymbol) sym).package_info != null) {
       
   212                     found.add(sym);
   210                     found.add(sym);
       
   211                 } else if (clazz == PackageSymbol.class) {
       
   212                     // In module mode, ignore the "spurious" empty packages that "enclose" module-specific packages.
       
   213                     // For example, if a module contains classes or package info in package p.q.r, it will also appear
       
   214                     // to have additional packages p.q and p, even though these packages have no content other
       
   215                     // than the subpackage.  We don't want those empty packages showing up in searches for p or p.q.
       
   216                     if (!sym.members().isEmpty() || ((PackageSymbol) sym).package_info != null) {
       
   217                         found.add(sym);
       
   218                     }
   213                 }
   219                 }
   214             }
   220             }
   215         }
   221 
   216 
   222             if (found.size() == 1) {
   217         if (found.size() == 1) {
   223                 return Optional.of(found.iterator().next());
   218             return found.iterator().next();
   224             } else if (found.size() > 1) {
   219         } else if (found.size() > 1) {
   225                 //more than one element found, produce a note:
   220             //more than one element found, produce a note:
   226                 if (alreadyWarnedDuplicates.add(methodName + ":" + nameStr)) {
   221             if (alreadyWarnedDuplicates.add(methodName + ":" + nameStr)) {
   227                     String moduleNames = found.stream()
   222                 String moduleNames = found.stream()
   228                                               .map(s -> s.packge().modle)
   223                                           .map(s -> s.packge().modle)
   229                                               .map(m -> m.toString())
   224                                           .map(m -> m.toString())
   230                                               .collect(Collectors.joining(", "));
   225                                           .collect(Collectors.joining(", "));
   231                     log.note(Notes.MultipleElements(methodName, nameStr, moduleNames));
   226                 log.note(Notes.MultipleElements(methodName, nameStr, moduleNames));
   232                 }
   227             }
   233                 return Optional.empty();
   228             return null;
   234             } else {
   229         } else {
   235                 //not found:
   230             //not found, or more than one element found:
   236                 return Optional.empty();
   231             return null;
   237             }
   232         }
   238         }).orElse(null);
   233     }
   239     }
   234 
   240 
   235     /**
   241     /**
   236      * Returns a symbol given the type's or package's canonical name,
   242      * Returns a symbol given the type's or package's canonical name,
   237      * or null if the name isn't found.
   243      * or null if the name isn't found.
   785     private static <T> T cast(Class<T> clazz, Object o) {
   791     private static <T> T cast(Class<T> clazz, Object o) {
   786         if (! clazz.isInstance(o))
   792         if (! clazz.isInstance(o))
   787             throw new IllegalArgumentException(o.toString());
   793             throw new IllegalArgumentException(o.toString());
   788         return clazz.cast(o);
   794         return clazz.cast(o);
   789     }
   795     }
       
   796 
       
   797     public void newRound() {
       
   798         resultCache.clear();
       
   799     }
   790 }
   800 }