Skip to content

Commit d0513f8

Browse files
authored
Adds parameterized and rawType methods to Domain.java; improves documentation (#12)
Signed-off-by: Laird Nelson <[email protected]>
1 parent c784cb7 commit d0513f8

File tree

1 file changed

+133
-30
lines changed

1 file changed

+133
-30
lines changed

src/main/java/org/microbean/construct/Domain.java

Lines changed: 133 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.util.Objects;
1818

1919
import javax.lang.model.element.Element;
20+
import javax.lang.model.element.ElementKind;
2021
import javax.lang.model.element.ExecutableElement;
2122
import javax.lang.model.element.ModuleElement;
2223
import javax.lang.model.element.Name;
@@ -87,8 +88,8 @@ public interface Domain {
8788
public ArrayType arrayTypeOf(final TypeMirror componentType);
8889

8990
/**
90-
* Returns the {@link Element} declaring the supplied {@link TypeMirror}, or {@code null} if there is no such {@link
91-
* Element}.
91+
* Returns the {@link Element} declaring the supplied {@link TypeMirror}, <strong>or {@code null} if there is no such
92+
* {@link Element}</strong>.
9293
*
9394
* @param t a {@link TypeMirror}; must not be {@code null}
9495
*
@@ -210,8 +211,8 @@ public interface Domain {
210211

211212
/**
212213
* A convenience method that returns the {@link DeclaredType} {@linkplain TypeElement#asType() of} a {@link
213-
* TypeElement} that bears the supplied {@code canonicalName}, or {@code null} if there is no such {@link TypeElement}
214-
* (and therefore no such {@link DeclaredType}).
214+
* TypeElement} that bears the supplied {@code canonicalName}, <strong>or {@code null} if there is no such {@link
215+
* TypeElement} (and therefore no such {@link DeclaredType})</strong>.
215216
*
216217
* @param canonicalName a valid canonical name; must not be {@code null}
217218
*
@@ -324,8 +325,8 @@ public DeclaredType declaredType(final DeclaredType enclosingType,
324325
/**
325326
* Returns the {@link Element} responsible for declaring the supplied {@link TypeMirror}, which is most commonly a
326327
* {@link DeclaredType}, a {@link TypeVariable}, a {@link NoType} with a {@link TypeKind} of {@link TypeKind#MODULE},
327-
* or a {@link NoType} with a {@link TypeKind} of {@link TypeKind#PACKAGE}, or {@code null} if there is no such {@link
328-
* Element}.
328+
* or a {@link NoType} with a {@link TypeKind} of {@link TypeKind#PACKAGE}, <strong>or {@code null} if there is no
329+
* such {@link Element}</strong>.
329330
*
330331
* @param t a {@link TypeMirror}; must not be {@code null}
331332
*
@@ -337,6 +338,29 @@ public DeclaredType declaredType(final DeclaredType enclosingType,
337338
*/
338339
public Element element(final TypeMirror t);
339340

341+
/**
342+
* A convenience method that returns the <dfn>element type</dfn> of the supplied {@link TypeMirror}.
343+
*
344+
* <p>The element type of an {@linkplain TypeKind#ARRAY array type} is the element type of its {@linkplain
345+
* ArrayType#getComponentType() component type}.</p>.
346+
*
347+
* <p>The element type of every other kind of type is the type itself. Note that the semantics of the prior sentence
348+
* diverge deliberately, primarily for convenience, from those of the relevant section in the Java Language
349+
* Specification.</p>
350+
*
351+
* @param t a {@link TypeMirror}; must not be {@code null}
352+
*
353+
* @return the <dfn>element type</dfn> of the supplied {@link TypeMirror}; never {@code null}
354+
*
355+
* @exception NullPointerException if {@code t} is {@code null}
356+
*
357+
* @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-10.html#jls-10.1 Java Language Specification, section
358+
* 10.1
359+
*/
360+
public default TypeMirror elementType(final TypeMirror t) {
361+
return t.getKind() == TypeKind.ARRAY ? this.elementType(((ArrayType)t).getComponentType()) : t;
362+
}
363+
340364
/**
341365
* Returns the <dfn>erasure</dfn> of the supplied {@link TypeMirror}.
342366
*
@@ -360,7 +384,8 @@ public DeclaredType declaredType(final DeclaredType enclosingType,
360384

361385
/**
362386
* A convenience method that returns an {@link ExecutableElement} representing the static initializer, constructor or
363-
* method described by the supplied arguments, or {@code null} if no such {@link ExecutableElement} exists.
387+
* method described by the supplied arguments, <strong>or {@code null} if no such {@link ExecutableElement}
388+
* exists</strong>.
364389
*
365390
* @param declaringElement a {@link TypeElement} representing the class that declares the executable; must not be
366391
* {@code null}
@@ -373,9 +398,8 @@ public DeclaredType declaredType(final DeclaredType enclosingType,
373398
* @param parameterTypes {@link TypeMirror}s that represent the executable's {@linkplain
374399
* ExecutableElement#getParameters() parameter types}
375400
*
376-
* @return an {@link ExecutableElement} with an {@link javax.lang.model.element.ElementKind} of {@link
377-
* javax.lang.model.element.ElementKind#CONSTRUCTOR}, {@link javax.lang.model.element.ElementKind#METHOD}, or {@link
378-
* javax.lang.model.element.ElementKind#STATIC_INIT}, or {@code null}
401+
* @return an {@link ExecutableElement} with an {@link ElementKind} of {@link ElementKind#CONSTRUCTOR}, {@link
402+
* ElementKind#METHOD}, or {@link ElementKind#STATIC_INIT}, or {@code null}
379403
*
380404
* @exception NullPointerException if any argument is {@code null}
381405
*/
@@ -444,6 +468,42 @@ public default boolean generic(final Element e) {
444468
return false;
445469
}
446470

471+
/**
472+
* A convenience method that returns {@code true} if and only if the supplied {@link Element} represents the (essentially
473+
* primordial) {@code java.lang.Object} {@link Element}.
474+
*
475+
* @param e an {@link Element}; must not be {@code null}
476+
*
477+
* @return {@code true} if and only if the supplied {@link Element} represents the (essentially
478+
* primordial) {@code java.lang.Object} {@link Element}; {@code false} otherwise
479+
*
480+
* @exception NullPointerException if {@code e} is {@code null}
481+
*/
482+
public default boolean javaLangObject(final Element e) {
483+
return
484+
e.getKind() == ElementKind.CLASS &&
485+
((QualifiedNameable)e).getQualifiedName().contentEquals("java.lang.Object");
486+
}
487+
488+
/**
489+
* A convenience method that returns {@code true} if and only if the supplied {@link TypeMirror} represents the {@link
490+
* DeclaredType} declared by the (essentially primordial) {@code java.lang.Object} element.
491+
*
492+
* @param t a {@link TypeMirror}; must not be {@code null}
493+
*
494+
* @return {@code true} represents the {@link
495+
* DeclaredType} declared by the (essentially primordial) {@code java.lang.Object} element; {@code false} otherwise
496+
*
497+
* @exception NullPointerException if {@code t} is {@code null}
498+
*
499+
* @see #javaLangObject(Element)
500+
*/
501+
public default boolean javaLangObject(final TypeMirror t) {
502+
return
503+
t.getKind() == TypeKind.DECLARED &&
504+
javaLangObject(((DeclaredType)t).asElement());
505+
}
506+
447507
/**
448508
* A convenience method that returns the {@link TypeElement} representing the class named {@link Object
449509
* java.lang.Object}.
@@ -471,7 +531,7 @@ public default TypeElement javaLangObject() {
471531

472532
/**
473533
* Returns a {@link ModuleElement} representing the module {@linkplain ModuleElement#getQualifiedName() named} by the
474-
* supplied {@code qualifiedName}, or {@code null} if there is no such {@link ModuleElement}.
534+
* supplied {@code qualifiedName}, <strong>or {@code null} if there is no such {@link ModuleElement}</strong>.
475535
*
476536
* @param qualifiedName a name suitable for naming a module; must not be {@code null}; may be {@linkplain
477537
* CharSequence#isEmpty() empty}, in which case a {@link ModuleElement} representing an <dfn>unnamed module</dfn> will
@@ -540,8 +600,8 @@ public default TypeElement javaLangObject() {
540600
public NullType nullType();
541601

542602
/**
543-
* Returns a {@link PackageElement} representing the package bearing the supplied {@code canonicalName}, or {@code null}
544-
* if there is no such {@link PackageElement}.
603+
* Returns a {@link PackageElement} representing the package bearing the supplied {@code canonicalName}, <strong>or
604+
* {@code null} if there is no such {@link PackageElement}</strong>.
545605
*
546606
* @param canonicalName a canonical name suitable for naming a package; must not be {@code null}; may be {@linkplain
547607
* CharSequence#isEmpty() empty}, in which case a {@link ModuleElement} representing an <dfn>unnamed package</dfn> will
@@ -560,8 +620,8 @@ public default TypeElement javaLangObject() {
560620

561621
/**
562622
* Returns a {@link PackageElement} representing the package bearing the supplied {@code canonicalName} as seen from
563-
* the module represented by the supplied {@link ModuleElement}, or {@code null} if there is no such {@link
564-
* PackageElement}.
623+
* the module represented by the supplied {@link ModuleElement}, <strong>or {@code null} if there is no such {@link
624+
* PackageElement}</strong>.
565625
*
566626
* @param asSeenFrom a {@link ModuleElement}; must not be {@code null}
567627
*
@@ -580,6 +640,25 @@ public default TypeElement javaLangObject() {
580640
*/
581641
public PackageElement packageElement(final ModuleElement asSeenFrom, final CharSequence canonicalName);
582642

643+
/**
644+
* A convenience method that returns {@code true} if and only if {@code t} is a {@link DeclaredType}, {@linkplain
645+
* TypeMirror#getKind() has a <code>TypeKind</code>} of {@link TypeKind#DECLARED DECLARED}, and {@linkplain
646+
* DeclaredType#getTypeArguments() has an empty type arguments list}.
647+
*
648+
* @param t a {@link TypeMirror}; must not be {@code null}
649+
*
650+
* @return {@code true} if and only if {@code t} is a {@link DeclaredType}, {@linkplain
651+
* TypeMirror#getKind() has a <code>TypeKind</code>} of {@link TypeKind#DECLARED DECLARED}, and {@linkplain
652+
* DeclaredType#getTypeArguments() has an empty type arguments list}; {@code false} otherwise
653+
*
654+
* @exception NullPointerException if {@code t} is {@code null}
655+
*/
656+
public default boolean parameterized(final TypeMirror t) {
657+
return
658+
t.getKind() == TypeKind.DECLARED &&
659+
!((DeclaredType)t).getTypeArguments().isEmpty();
660+
}
661+
583662
/**
584663
* Returns the result of applying <dfn>unboxing conversion</dfn> to the (logical) {@link TypeElement} bearing the
585664
* supplied {@code canonicalName}.
@@ -693,8 +772,32 @@ public default PrimitiveType primitiveType(final TypeElement e) {
693772
public PrimitiveType primitiveType(final TypeMirror t);
694773

695774
/**
696-
* Returns a {@link RecordComponentElement} corresponding to the supplied {@link ExecutableElement}, or {@code null}
697-
* if there is no such {@link RecordComponentElement}.
775+
* A convenience method that returns the <dfn>raw type</dfn> corresponding to {@code t}, <strong>or {@code null} if
776+
* {@code t} is <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8">incapable of yielding
777+
* a raw type</a></strong>.
778+
*
779+
* <p>Overrides of this method must conform to the requirements imposed by the relevant section of the relevant
780+
* version of the Java Language Specification concerning raw types.</p>
781+
*
782+
* @param t a {@link TypeMirror}; must not be {@code null}
783+
*
784+
* @return the raw type corresponding to the supplied {@link TypeMirror}, or {@code null} if {@code t} is <a
785+
* href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8">incapable of yielding a raw type</a>
786+
*
787+
* @exception NullPointerException if {@code t} is {@code null}
788+
*
789+
* @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8 Java Language Specification, section 4.8
790+
*/
791+
public default TypeMirror rawType(final TypeMirror t) {
792+
return switch (t.getKind()) {
793+
case ARRAY -> this.rawType(this.elementType(t)); // recursive
794+
default -> this.parameterized(t) ? this.erasure(t) : null;
795+
};
796+
}
797+
798+
/**
799+
* Returns a {@link RecordComponentElement} corresponding to the supplied {@link ExecutableElement}, <strong>or {@code
800+
* null} if there is no such {@link RecordComponentElement}</strong>.
698801
*
699802
* @param e an {@link ExecutableElement} {@linkplain ExecutableElement#getEnclosingElement() enclosed by} a record
700803
* representing an <dfn>accessor method</dfn>; must not be {@code null}
@@ -807,8 +910,8 @@ public default String toString(final CharSequence name) {
807910
}
808911

809912
/**
810-
* Returns a {@link TypeElement} representing the element bearing the supplied <dfn>canonical name</dfn>, or {@code
811-
* null} if there is no such {@link TypeElement}.
913+
* Returns a {@link TypeElement} representing the element bearing the supplied <dfn>canonical name</dfn>, <strong>or
914+
* {@code null} if there is no such {@link TypeElement}</strong>.
812915
*
813916
* @param canonicalName a valid canonical name; must not be {@code null}
814917
*
@@ -825,8 +928,8 @@ public default String toString(final CharSequence name) {
825928

826929
/**
827930
* Returns a {@link TypeElement} representing the element bearing the supplied <dfn>canonical name</dfn>, as read or
828-
* seen from the module represented by the supplied {@link ModuleElement}, or {@code null} if there is no such {@link
829-
* TypeElement}.
931+
* seen from the module represented by the supplied {@link ModuleElement}, <strong>or {@code null} if there is no such
932+
* {@link TypeElement}</strong>.
830933
*
831934
* @param asSeenFrom a {@link ModuleElement}; must not be {@code null}
832935
*
@@ -922,8 +1025,8 @@ public default TypeElement typeElement(final TypeKind primitiveTypeKind) {
9221025
/**
9231026
* Returns the {@link TypeParameterElement} {@linkplain Parameterizable#getTypeParameters() contained} by the supplied
9241027
* {@link Parameterizable} whose {@linkplain TypeParameterElement#getSimpleName() name} {@linkplain
925-
* Name#contentEquals(CharSequence) is equal to} the supplied {@code name}, or {@code null} if there is no such {@link
926-
* TypeParameterElement}.
1028+
* Name#contentEquals(CharSequence) is equal to} the supplied {@code name}, <strong>or {@code null} if there is no
1029+
* such {@link TypeParameterElement}</strong>.
9271030
*
9281031
* @param p a {@link Parameterizable}; must not be {@code null}
9291032
*
@@ -957,8 +1060,8 @@ public default TypeParameterElement typeParameterElement(Parameterizable p, fina
9571060
* A convenience method that returns the {@link TypeVariable} {@linkplain TypeParameterElement#asType() declared by}
9581061
* the {@link TypeParameterElement} {@linkplain Parameterizable#getTypeParameters() contained} by the supplied {@link
9591062
* Parameterizable} whose {@linkplain TypeParameterElement#getSimpleName() name} {@linkplain
960-
* Name#contentEquals(CharSequence) is equal to} the supplied {@code name}, or {@code null} if there is no such {@link
961-
* TypeParameterElement} or {@link TypeVariable}.
1063+
* Name#contentEquals(CharSequence) is equal to} the supplied {@code name}, <strong>or {@code null} if there is no
1064+
* such {@link TypeParameterElement} or {@link TypeVariable}</strong>.
9621065
*
9631066
* @param p a {@link Parameterizable}; must not be {@code null}
9641067
*
@@ -974,10 +1077,10 @@ public default TypeVariable typeVariable(Parameterizable p, final CharSequence n
9741077
}
9751078

9761079
/**
977-
* A convenience method that returns the first {@link VariableElement} with a {@linkplain
978-
* javax.lang.model.element.ElementKind#isVariable() variable <code>ElementKind</code>} and {@linkplain
979-
* Element#getSimpleName() bearing} the supplied {@code simpleName} that the supplied {@code enclosingElement}
980-
* {@linkplain Element#getEnclosedElements() encloses}, or {@code null} if there is no such {@link VariableElement}.
1080+
* A convenience method that returns the first {@link VariableElement} with a {@linkplain ElementKind#isVariable()
1081+
* variable <code>ElementKind</code>} and {@linkplain Element#getSimpleName() bearing} the supplied {@code simpleName}
1082+
* that the supplied {@code enclosingElement} {@linkplain Element#getEnclosedElements() encloses}, <strong>or {@code
1083+
* null} if there is no such {@link VariableElement}</strong>.
9811084
*
9821085
* @param enclosingElement an {@link Element}; must not be {@code null}
9831086
*
@@ -989,7 +1092,7 @@ public default TypeVariable typeVariable(Parameterizable p, final CharSequence n
9891092
*
9901093
* @see Element#getEnclosedElements()
9911094
*
992-
* @see javax.lang.model.element.ElementKind#isVariable()
1095+
* @see ElementKind#isVariable()
9931096
*
9941097
* @see Element#getSimpleName()
9951098
*

0 commit comments

Comments
 (0)