-
CSR
-
Resolution: Approved
-
P3
-
source
-
low
-
New default methods being added to an interface.
-
Java API
-
SE
Summary
Add the three methods getAllTypeElements
, getAllPackageElements
, and getAllModuleElements
with defaults to the utility interface javax.lang.model.Elements
.
Problem
As part of adding modules to the platform, the long-standing condition that there would be at most one type/package for the same canonical name was rendered untrue: two modules can have (non-exported) types or packages whose names are the same.
This is a wrinkle for the javax.lang.model.Elements methods which map from names to type or package elements. The existing methods
PackageElement getPackageElement(CharSequence name) TypeElement getTypeElement(CharSequence name)
were redefined to return null if a type/package could not be uniquely found (JDK-8133896). In addition, overloads of these methods taking a module parameter were added to the API:
PackageElement getPackageElement(ModuleElement module, CharSequence name) TypeElement getTypeElement(ModuleElement module, CharSequence name)
However, this still leaves no easy way to return the same-named elements from whichever module they may be defined in.
One API approach to address this issue would be Elements.getAll{Type, Package}Elements methods. In addition, it is helpful to have a way to see all known modules.
Solution
Add the methods in question
Specification
diff -r f0bc0f34d2cc src/java.compiler/share/classes/javax/lang/model/util/Elements.java
--- a/src/java.compiler/share/classes/javax/lang/model/util/Elements.java Tue Feb 07 16:19:50 2017 -0800
+++ b/src/java.compiler/share/classes/javax/lang/model/util/Elements.java Thu Feb 09 18:48:11 2017 -0800
@@ -25,9 +25,12 @@
package javax.lang.model.util;
-
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.LinkedHashSet;
import javax.lang.model.AnnotatedConstruct;
import javax.lang.model.element.*;
@@ -72,6 +75,47 @@
}
/**
+ * Returns all package elements with the given canonical name.
+ *
+ * There may be more than one package element with the same canonical
+ * name if the package elements are in different modules.
+ *
+ * @implSpec The default implementation of this method calls
+ * {@link #getAllModuleElements(CharSequence)
+ * getAllModuleElements} and stores the result. If the set of
+ * modules is empty, {@link #getPackageElement(CharSequence)
+ * getPackageElement(name)} is called passing through the name
+ * argument. If {@code getPackageElement(name)} is null, an empty set
+ * of package elements is returned; otherwise, a single-element set
+ * with the found package element is returned. If the set of modules
+ * is nonempty, the modules are iterated over and any nonnull
+ * result of {@link getPackageElement(ModuleElement,
+ * CharacterSequence) getPackageElement(module, name)} are
+ * accumulated into a set. The set is then returned.
+ *
+ * @param name the canonical name
+ * @return the package elements, or an empty set if no package with the name can be found
+ * @since 9
+ */
+ default Set<? extends PackageElement> getAllPackageElements(CharSequence name) {
+ Set<? extends ModuleElement> modules = getAllModuleElements();
+ if (modules.isEmpty()) {
+ PackageElement packageElt = getPackageElement(name);
+ return (packageElt != null) ?
+ Collections.singleton(packageElt):
+ Collections.emptySet();
+ } else {
+ Set<PackageElement> result = new LinkedHashSet<>(1); // Usually expect at most 1 result
+ for (ModuleElement module: modules) {
+ PackageElement packageElt = getPackageElement(module, name);
+ if (packageElt != null)
+ result.add(packageElt);
+ }
+ return Collections.unmodifiableSet(result);
+ }
+ }
+
+ /**
* Returns a type element given its canonical name if the type element is unique in the environment.
* If running with modules, all modules in the modules graph are searched for matching
* type elements.
@@ -97,6 +141,47 @@
}
/**
+ * Returns all type elements with the given canonical name.
+ *
+ * There may be more than one type element with the same canonical
+ * name if the type elements are in different modules.
+ *
+ * @implSpec The default implementation of this method calls
+ * {@link #getAllModuleElements(CharSequence)
+ * getAllModuleElements} and stores the result. If the set of
+ * modules is empty, {@link #getTypeElement(CharSequence)
+ * getTypeElement(name)} is called passing through the name
+ * argument. If {@code getTypeElement(name)} is null, an empty set
+ * of type elements is returned; otherwise, a single-element set
+ * with the found type element is returned. If the set of modules
+ * is nonempty, the modules are iterated over and any nonnull
+ * result of {@link getTypeElement(ModuleElement,
+ * CharacterSequence) getTypeElement(module, name)} are
+ * accumulated into a set. The set is then returned.
+ *
+ * @param name the canonical name
+ * @return the type elements, or an empty set if no type with the name can be found
+ * @since 9
+ */
+ default Set<? extends TypeElement> getAllTypeElements(CharSequence name) {
+ Set<? extends ModuleElement> modules = getAllModuleElements();
+ if (modules.isEmpty()) {
+ TypeElement typeElt = getTypeElement(name);
+ return (typeElt != null) ?
+ Collections.singleton(typeElt):
+ Collections.emptySet();
+ } else {
+ Set<TypeElement> result = new LinkedHashSet<>(1); // Usually expect at most 1 result
+ for (ModuleElement module: modules) {
+ TypeElement typeElt = getTypeElement(module, name);
+ if (typeElt != null)
+ result.add(typeElt);
+ }
+ return Collections.unmodifiableSet(result);
+ }
+ }
+
+ /**
* Returns a module element given its fully qualified name.
* If the named module cannot be found, null is returned. One situation where a module
* cannot be found is if the environment does not include modules, such as
@@ -117,6 +202,26 @@
}
/**
+ * Returns all module elements in the current environment.
+ *
+ * If no modules are present, an empty set is returned. One
+ * situation where no modules are present occurs when the
+ * environment does not include modules, such as an annotation
+ * processing environment configured for a {@linkplain
+ * javax.annotation.processing.ProcessingEnvironment#getSourceVersion
+ * source version} without modules.
+ *
+ * @implSpec The default implementation of this method returns
+ * an empty set.
+ *
+ * @return the known module elements, or an empty set if there are no modules
+ * @since 9
+ */
+ default Set<? extends ModuleElement> getAllModuleElements() {
+ return Collections.emptySet();
+ }
+
+ /**
* Returns the values of an annotation's elements, including defaults.
*
* @see AnnotationMirror#getElementValues()
- csr for
-
JDK-8173945 Add methods for Elements.getAll{Type, Package, Module}Elements
-
- Closed
-