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. |