001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2024–2026 microBean™. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 006 * the License. You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 011 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 012 * specific language governing permissions and limitations under the License. 013 */ 014package org.microbean.construct; 015 016import java.lang.reflect.Constructor; 017import java.lang.reflect.Executable; 018import java.lang.reflect.GenericArrayType; 019import java.lang.reflect.GenericDeclaration; 020import java.lang.reflect.Method; 021import java.lang.reflect.ParameterizedType; 022import java.lang.reflect.Type; 023 024import java.util.ArrayList; 025import java.util.List; 026 027import javax.lang.model.AnnotatedConstruct; 028 029import javax.lang.model.element.AnnotationMirror; 030import javax.lang.model.element.Element; 031import javax.lang.model.element.ElementKind; 032import javax.lang.model.element.ExecutableElement; 033import javax.lang.model.element.ModuleElement; 034import javax.lang.model.element.Name; 035import javax.lang.model.element.PackageElement; 036import javax.lang.model.element.Parameterizable; 037import javax.lang.model.element.QualifiedNameable; 038import javax.lang.model.element.RecordComponentElement; 039import javax.lang.model.element.TypeElement; 040import javax.lang.model.element.TypeParameterElement; 041import javax.lang.model.element.VariableElement; 042 043import javax.lang.model.type.ArrayType; 044import javax.lang.model.type.DeclaredType; 045import javax.lang.model.type.ExecutableType; 046import javax.lang.model.type.NoType; 047import javax.lang.model.type.NullType; 048import javax.lang.model.type.PrimitiveType; 049import javax.lang.model.type.TypeKind; 050import javax.lang.model.type.TypeMirror; 051import javax.lang.model.type.TypeVariable; 052import javax.lang.model.type.WildcardType; 053 054import javax.lang.model.util.Elements; 055import javax.lang.model.util.Elements.Origin; 056 057import org.microbean.construct.element.AnnotationMirrors; 058import org.microbean.construct.element.UniversalElement; 059 060import org.microbean.construct.type.UniversalType; 061 062import static java.util.Collections.unmodifiableList; 063 064import static java.util.Objects.requireNonNull; 065 066import static javax.lang.model.type.TypeKind.DECLARED; 067 068/** 069 * A representation of a domain of valid Java constructs. 070 * 071 * <p>A <dfn id="domain">domain</dfn> is a set of valid Java <a href="#construct">constructs</a>. A {@link Domain} 072 * provides access to a domain and its members.</p> 073 * 074 * <p>A Java <dfn id="construct">construct</dfn> is either a <a href="#type">type</a> or an <a 075 * href="#element">element</a>.</p> 076 * 077 * <p>A <dfn id="type">type</dfn> is a usage of a Java type, most commonly represented as a {@link TypeMirror}.</p> 078 * 079 * <p>An <dfn id="element">element</dfn> ia a declaration of a Java program element, most commonly represented as an 080 * {@link Element}.</p> 081 * 082 * <p>Domains impose constraints on the <a href="#type">types</a> and <a href="#element">elements</a> they contain, and 083 * on the kinds and semantics of operations that can be performed on them.</p> 084 * 085 * <p>This interface is modeled on a deliberately restricted combination of the {@link javax.lang.model.util.Elements} 086 * and {@link javax.lang.model.util.Types} interfaces.</p> 087 * 088 * <p>{@link Domain} implementations must be thread-safe.</p> 089 * 090 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 091 * 092 * @see PrimordialDomain 093 * 094 * @see <a href="https://bugs.openjdk.org/browse/JDK-8055219">JDK-8055219</a> 095 */ 096@SuppressWarnings("try") 097public interface Domain extends PrimordialDomain { 098 099 /** 100 * Returns an immutable, determinate, non-{@code null} {@link List} of {@link AnnotationMirror} instances representing 101 * all annotations <dfn>present</dfn> on an element, whether <dfn>directly present</dfn> or present via inheritance. 102 * 103 * <p>The default implementation of this method calls {@link UniversalElement#of(Element, Domain)} with the supplied 104 * {@code element} and {@code this} as arguments, calls the {@link 105 * AnnotationMirrors#allAnnotationMirrors(Element)} with the result, and returns the result.</p> 106 * 107 * @param element the {@link Element} whose present annotations should be returned; must not be {@code null} 108 * 109 * @return an immutable, determinate, non-{@code null} {@link List} of {@link AnnotationMirror} instances representing 110 * all annotations <dfn>present</dfn> on an element, whether <dfn>directly present</dfn> or present via inheritance 111 * 112 * @exception NullPointerException if {@code element} is {@code null} 113 * 114 * @see AnnotationMirrors#allAnnotationMirrors(Element) 115 * 116 * @see javax.lang.model.util.Elements#getAllAnnotationMirrors(Element) 117 */ 118 public default List<? extends AnnotationMirror> allAnnotationMirrors(final Element element) { 119 return AnnotationMirrors.allAnnotationMirrors(UniversalElement.of(element, this)); // handles locking, symbol completion 120 } 121 122 /** 123 * Returns a non-{@code null}, determinate, immutable {@link List} whose elements comprise the <dfn>members</dfn> of 124 * the supplied {@link TypeElement}, whether they are inherited or declared directly. 125 * 126 * <p>If the supplied {@link TypeElement} is a {@linkplain ElementKind#CLASS class}, the returned {@link List} will 127 * also include the class' constructors, but not any local or anonymous classes.</p> 128 * 129 * @param e a {@link TypeElement}; must not be {@code null} 130 * 131 * @return a non-{@code null}, determinate, immutable {@link List} whose elements comprise the <dfn>members</dfn> of 132 * the supplied {@link TypeElement}, whether they are inherited or declared directly 133 * 134 * @exception NullPointerException if {@code e} is {@code null} 135 * 136 * @see Elements#getAllMembers(TypeElement) 137 */ 138 public abstract List<? extends Element> allMembers(TypeElement e); 139 140 /** 141 * An <strong>experimental</strong> method that returns an {@link Element} that is {@linkplain Element#equals(Object) 142 * equal to} the supplied {@link Element} but {@linkplain Element#getAnnotationMirrors() with} a {@link List} of 143 * annotations {@linkplain List#equals(Object) equal to} the supplied {@link List} of {@link AnnotationMirror}s. 144 * 145 * <p>The supplied {@link Element} may be modified in place if the return value of its {@link 146 * Element#getAnnotationMirrors() getAnnotationMirrors()} method is mutable.</p> 147 * 148 * <p>No validation of any kind is performed on either argument.</p> 149 * 150 * @param annotations a {@link List} of {@link AnnotationMirror}s; must not be {@code null} 151 * 152 * @param e an {@link Element}; must not be {@code null} 153 * 154 * @return an {@link Element} that is {@linkplain Element#equals(Object) equal to} the supplied {@link Element} but 155 * {@linkplain Element#getAnnotationMirrors() with} a {@link List} of annotations {@linkplain List#equals(Object) 156 * equal to} the supplied {@link List} of {@link AnnotationMirror}s 157 * 158 * @exception NullPointerException if any argument is {@code null} 159 * 160 * @see UniversalElement#getAnnotationMirrors() 161 */ 162 public default Element annotate(final List<? extends AnnotationMirror> annotations, final Element e) { 163 final UniversalElement ue = UniversalElement.of(e, this); 164 final List<AnnotationMirror> l = ue.getAnnotationMirrors(); 165 l.clear(); 166 l.addAll(annotations); 167 return ue; 168 } 169 170 /** 171 * An <strong>experimental</strong> method that returns a {@link TypeMirror} that is {@linkplain 172 * TypeMirror#equals(Object) equal to} the supplied {@link TypeMirror} but {@linkplain 173 * TypeMirror#getAnnotationMirrors() with} a {@link List} of annotations {@linkplain List#equals(Object) equal to} the 174 * supplied {@link List} of {@link AnnotationMirror}s. 175 * 176 * <p>The supplied {@link TypeMirror} may be modified in place if the return value of its {@link 177 * TypeMirror#getAnnotationMirrors() getAnnotationMirrors()} method is mutable.</p> 178 * 179 * <p>No validation of any kind is performed on either argument.</p> 180 * 181 * @param annotations a {@link List} of {@link AnnotationMirror}s; must not be {@code null} 182 * 183 * @param t a {@link TypeMirror}; must not be {@code null} 184 * 185 * @return a {@link TypeMirror} that is {@linkplain TypeMirror#equals(Object) equal to} the supplied {@link 186 * TypeMirror} but {@linkplain TypeMirror#getAnnotationMirrors() with} a {@link List} of annotations {@linkplain 187 * List#equals(Object) equal to} the supplied {@link List} of {@link AnnotationMirror}s 188 * 189 * @exception NullPointerException if any argument is {@code null} 190 * 191 * @see UniversalType#getAnnotationMirrors() 192 */ 193 public default TypeMirror annotate(final List<? extends AnnotationMirror> annotations, final TypeMirror t) { 194 final UniversalType ut = UniversalType.of(t, this); 195 final List<AnnotationMirror> l = ut.getAnnotationMirrors(); 196 l.clear(); 197 l.addAll(annotations); 198 return ut; 199 } 200 201 /** 202 * Returns an {@link ArrayType} whose {@linkplain ArrayType#getComponentType() component type} is {@linkplain 203 * #sameType(TypeMirror, TypeMirror) the same as} the supplied {@code componentType}. 204 * 205 * @param componentType the component type; must not be {@code null} 206 * 207 * @return a non-{@code null} {@link ArrayType} whose {@linkplain ArrayType#getComponentType() component type} is 208 * {@linkplain #sameType(TypeMirror, TypeMirror) the same as} the supplied {@code componentType} 209 * 210 * @exception NullPointerException if {@code componentType} is {@code null} 211 * 212 * @exception IllegalArgumentException if {@code componentType} is not a valid component type 213 * 214 * @see javax.lang.model.util.Types#getArrayType(TypeMirror) 215 */ 216 // Type factory method 217 public ArrayType arrayTypeOf(final TypeMirror componentType); 218 219 /** 220 * Returns a non-{@code null} {@link TypeMirror} representing the type of the supplied {@link Element} when that 221 * {@link Element} is viewed as a member of, or otherwise directly contained by, the supplied {@code containingType}. 222 * 223 * <p>For example, when viewed as a member of the parameterized type {@link java.util.Set Set<String>}, the 224 * {@link java.util.Set#add(Object)} method (represented as an {@link ExecutableElement}) {@linkplain 225 * ExecutableElement#asType() has} a {@linkplain ExecutableType type} whose {@linkplain 226 * ExecutableType#getParameterTypes() method parameter is of type} {@link String} (not {@link String}'s erasure).</p> 227 * 228 * @param containingType the containing {@link DeclaredType}; must not be {@code null} 229 * 230 * @param e the member {@link Element}; must not be {@code null} 231 * 232 * @return a non-{@code null} {@linkplain TypeMirror type} representing the {@linkplain Element#asType() type of} the 233 * supplied {@link Element} when viewed as a member of the supplied {@code containingType}; never {@code null} 234 * 235 * @exception NullPointerException if either {@code containingType} or {@code e} is {@code null} 236 * 237 * @exception IllegalArgumentException if {@code e} cannot be viewed as a member of the supplied {@code 238 * containingType} (because it is the wrong {@linkplain Element#getKind() kind}, for example) 239 * 240 * @see javax.lang.model.util.Types#asMemberOf(DeclaredType, Element) 241 */ 242 public TypeMirror asMemberOf(final DeclaredType containingType, final Element e); 243 244 /** 245 * Returns {@code true} if and only if the supplied {@code payload} (the first argument) is considered assignable to 246 * the supplied {@code receiver} (the second argument) according to <a 247 * href="https://docs.oracle.com/javase/specs/jls/se21/html/jls-5.html#jls-5.2">the rules of the Java Language 248 * Specification</a>; <strong>note the counterintuitive order of the parameters</strong>. 249 * 250 * <p>Perhaps surprisingly, the "left hand side" of the putative assignment is represented by the second parameter 251 * ({@code receiver}). The "right hand side" of the putative assignment is represented by the first parameter 252 * ({@code payload}). This follows the contract of the {@link javax.lang.model.util.Types#isAssignable(TypeMirror, 253 * TypeMirror)} method, on which this method is modeled.</p> 254 * 255 * @param payload the {@link TypeMirror} being assigned; must not be {@code null} 256 * 257 * @param receiver the {@link TypeMirror} receiving the assignment; must not be {@code null} 258 * 259 * @return {@code true} if and only if {@code payload} is assignable to {@code receiver} according to <a 260 * href="https://docs.oracle.com/javase/specs/jls/se21/html/jls-5.html#jls-5.2">the rules of the Java Language 261 * Specification</a> 262 * 263 * @exception NullPointerException if either {@code payload} or {@code receiver} is {@code null} 264 * 265 * @exception IllegalArgumentException if either {@link TypeMirror} is not one that can take part in an assignment 266 * 267 * @see javax.lang.model.util.Types#isAssignable(TypeMirror, TypeMirror) 268 * 269 * @spec https://docs.oracle.com/javase/specs/jls/se21/html/jls-5.html#jls-5.2 Java Language Specification, section 270 * 5.2 271 */ 272 // Note the strange positioning of payload and receiver. 273 public boolean assignable(final TypeMirror payload, final TypeMirror receiver); 274 275 /** 276 * Returns the (non-{@code null}) <a 277 * href="https://docs.oracle.com/javase/specs/jls/se21/html/jls-13.html#jls-13.1"><dfn>binary name</dfn></a> of the 278 * supplied {@link TypeElement}. 279 * 280 * @param e a {@link TypeElement}; must not be {@code null} 281 * 282 * @return a non-{@code null} {@link Name} 283 * 284 * @exception NullPointerException if {@code e} is {@code null} 285 * 286 * @see javax.lang.model.util.Elements#getBinaryName(TypeElement) 287 * 288 * @spec https://docs.oracle.com/javase/specs/jls/se21/html/jls-13.html#jls-13.1 Java Language Specification, section 289 * 13.1 290 */ 291 public Name binaryName(final TypeElement e); 292 293 /** 294 * Returns {@code true} if and only if the supplied {@link ExecutableElement} represents a <dfn>bridge method</dfn>. 295 * 296 * @param e an {@link ExecutableElement}; must not be {@code null} 297 * 298 * @return {@code true} if and only if the supplied {@link ExecutableElement} represents a bridge method 299 * 300 * @exception NullPointerException if {@code e} is {@code null} 301 * 302 * @see javax.lang.model.util.Elements#isBridge(ExecutableElement) 303 * 304 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.4.8.3 Java Language Specification, 305 * section 8.4.8.3 306 * 307 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-15.html#jls-15.12.4.5 Java Language Specification, 308 * section 15.12.4.5 309 */ 310 public boolean bridge(final ExecutableElement e); 311 312 /** 313 * Applies <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.10"><dfn>capture 314 * conversion</dfn></a> to the supplied {@link TypeMirror}, which is normally a {@linkplain TypeKind#WILDCARD wildcard 315 * type}. 316 * 317 * @param wildcard a {@link TypeMirror}; must not be {@code null}; if not a {@linkplain TypeKind#WILDCARD wildcard 318 * type}, then it will be returned unchanged 319 * 320 * @return a non-{@code null} {@link TypeMirror} representing the result of <a 321 * href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.10">capture conversion</a> applied to 322 * the supplied {@link TypeMirror} 323 * 324 * @exception NullPointerException if {@code wildcard} is {@code null} 325 * 326 * @see javax.lang.model.util.Types#capture(TypeMirror) 327 * 328 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.10 Java Language Specification, section 329 * 5.1.10 330 */ 331 public TypeMirror capture(final TypeMirror wildcard); 332 333 /** 334 * Returns {@code true} if and only if {@code candidateContainer} <dfn>contains</dfn> {@code candidate}, according to 335 * the <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5.1">Java Language Specification, 336 * section 4.5.1</a>. 337 * 338 * @param candidateContainer the putative containing type; normally a {@linkplain TypeKind#WILDCARD wildcard type}; 339 * must not be {@code null} 340 * 341 * @param candidate the putative contained type; must not be {@code null} 342 * 343 * @return {@code true} if and only if {@code candidateContainer} <dfn>contains</dfn> {@code candidate}, according to 344 * the <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5.1">Java Language Specification, 345 * section 4.5.1</a>; {@code false} otherwise 346 * 347 * @exception NullPointerException if either argument is {@code null} 348 * 349 * @exception IllegalArgumentException if either argument is either an {@linkplain TypeKind#EXECUTABLE executable 350 * type}, a {@linkplain TypeKind#MODULE module type}, or a {@linkplain TypeKind#PACKAGE package type} 351 * 352 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5.1 Java Language Specification, section 353 * 4.5.1 354 */ 355 public boolean contains(final TypeMirror candidateContainer, final TypeMirror candidate); 356 357 /** 358 * A convenience method that returns the {@link DeclaredType} {@linkplain TypeElement#asType() of} a {@link 359 * TypeElement} that bears the supplied {@code canonicalName}, <strong>or {@code null} if there is no such {@link 360 * TypeElement} (and therefore no such {@link DeclaredType})</strong>. 361 * 362 * @param canonicalName a valid canonical name; must not be {@code null} 363 * 364 * @return a {@link DeclaredType} with a {@link TypeKind} of {@link TypeKind#DECLARED}, or {@code null} 365 * 366 * @see #typeElement(CharSequence) 367 * 368 * @see #declaredType(TypeElement, TypeMirror...) 369 * 370 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.7 Java Language Specification, section 371 * 6.7 372 */ 373 // (Convenience.) 374 public default DeclaredType declaredType(final CharSequence canonicalName) { 375 final TypeElement e = this.typeElement(canonicalName); 376 return e == null ? null : this.declaredType(e); 377 } 378 379 /** 380 * Returns the {@link DeclaredType} {@linkplain TypeElement#asType() of} the supplied {@link TypeElement} with the 381 * supplied {@link TypeMirror} arguments (if any), yielding a parameterized type. 382 * 383 * <p>Given a {@link TypeElement} representing the class named {@link java.util.Set java.util.Set} and a {@link 384 * TypeMirror} representing the type declared by {@link String java.lang.String}, for example, this method will return 385 * a {@link DeclaredType} representing the parameterized type corresponding to {@link java.util.Set 386 * java.util.Set<java.lang.String>}.</p> 387 * 388 * <p>The number of supplied type arguments must either equal the number of the supplied {@link TypeElement}'s 389 * {@linkplain TypeElement#getTypeParameters() formal type parameters}, or must be zero. If it is zero, and if the 390 * supplied {@link TypeElement} {@linkplain #generic(Element) is generic}, then the supplied {@link TypeElement}'s raw 391 * type is returned.</p> 392 * 393 * <p>If a parameterized type is returned, {@linkplain DeclaredType#asElement() its <code>TypeElement</code>} must not 394 * be contained within a {@linkplain #generic(Element) generic} outer class. The parameterized type {@code 395 * Outer<String>.Inner<Number>}, for example, may be constructed by first using this method to get the type {@code 396 * Outer<String>}, and then invoking {@link #declaredType(DeclaredType, TypeElement, TypeMirror...)}.</p> 397 * 398 * @param typeElement a {@link TypeElement}; must not be {@code null} 399 * 400 * @param typeArguments any type arguments (represented by {@link TypeMirror}s); must not be {@code null} 401 * 402 * @return a non-{@code null} {@link DeclaredType} with a {@link TypeKind} of {@link TypeKind#DECLARED} 403 * 404 * @exception NullPointerException if {@code typeElement} or {@code typeArguments} is {@code null} 405 * 406 * @see javax.lang.model.util.Types#getDeclaredType(TypeElement, TypeMirror...) 407 * 408 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5 Java Language Specification, section 4.5 409 */ 410 // Type factory method. 411 public DeclaredType declaredType(final TypeElement typeElement, 412 final TypeMirror... typeArguments); 413 414 /** 415 * Returns the {@link DeclaredType} {@linkplain TypeElement#asType() of} the supplied {@link TypeElement} with the 416 * supplied {@link TypeMirror} arguments (if any), given a containing {@link DeclaredType} of which it is a member, 417 * yielding a parameterized type. 418 * 419 * <p>Given a {@link DeclaredType} representing the parameterized type corresponding to {@code Outer<}{@link 420 * String}{@code >} (see the {@link #declaredType(TypeElement, TypeMirror...)} method), a {@link TypeElement} 421 * representing the class named {@code Outer.Inner} and a {@link DeclaredType} representing the non-generic class 422 * corresponding to {@link Number}, for example, this method will return a {@link DeclaredType} representing the 423 * parameterized type corresponding to {@code Outer<}{@link String}{@code >}{@code .Inner<}{@link Number}{@code >}.</p> 424 * 425 * <p>The number of supplied type arguments must either equal the number of the supplied {@link TypeElement}'s 426 * {@linkplain TypeElement#getTypeParameters() formal type parameters}, or must be zero. If it is zero, and if the 427 * supplied {@link TypeElement} {@link #generic(Element) is generic}, then the supplied {@link TypeElement}'s raw type 428 * is returned.</p> 429 * 430 * @param enclosingType a {@link DeclaredType} representing the containing type; must not be {@code null} 431 * 432 * @param typeElement a {@link TypeElement}; must not be {@code null} 433 * 434 * @param typeArguments any type arguments (represented by {@link TypeMirror}s); must not be {@code null} 435 * 436 * @return a non-{@code null} {@link DeclaredType} with a {@link TypeKind} of {@link TypeKind#DECLARED} 437 * 438 * @exception NullPointerException if {@code enclosingType}, {@code typeElement}, or {@code typeArguments} is {@code 439 * null} 440 * 441 * @see #declaredType(TypeElement, TypeMirror...) 442 * 443 * @see javax.lang.model.util.Types#getDeclaredType(DeclaredType, TypeElement, TypeMirror...) 444 * 445 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5 Java Language Specification, section 4.5 446 */ 447 // Type factory method. 448 public DeclaredType declaredType(final DeclaredType enclosingType, 449 final TypeElement typeElement, 450 final TypeMirror... typeArguments); 451 452 /** 453 * Returns a non-{@code null} {@link List} of the <dfn>direct supertypes</dfn> of the supplied {@link TypeMirror}, 454 * which is normally a {@linkplain TypeKind#DECLARED declared type}. 455 * 456 * <p>The direct supertypes returned by this method are actually a subset of the direct supertypes of a type as 457 * defined in the <a href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-4.html#jls-4.10">Java Language 458 * Specification, section 4.10</a>. Specifically, the subset contains only those types that can be expressed in the 459 * {@code extends} or {@code implements} clauses of the Java language. For example, a type {@code Baz} can declare 460 * only that it {@code extends Foo<Bar>}, not {@code Foo<?>}, even though {@code Foo<?>} is a specification-described 461 * direct supertype of {@code Baz}.</p> 462 * 463 * @param t a {@link TypeMirror}; must not be {@code null}; must not be an {@linkplain TypeKind#EXECUTABLE executable 464 * type}, a {@linkplain TypeKind#MODULE module type}, or a {@linkplain TypeKind#PACKAGE package type} 465 * 466 * @return a non-{@code null}, immutable {@link List} of {@link TypeMirror}s representing the direct supertypes 467 * 468 * @exception NullPointerException if {@code t} is {@code null} 469 * 470 * @exception IllegalArgumentException if either argument is either an {@linkplain TypeKind#EXECUTABLE executable 471 * type}, a {@linkplain TypeKind#MODULE module type}, or a {@linkplain TypeKind#PACKAGE package type} 472 * 473 * @see javax.lang.model.util.Types#directSupertypes(TypeMirror) 474 * 475 * @see <a href="https://bugs.openjdk.org/browse/JDK-8055219">JDK-8055219</a> 476 * 477 * @spec https://docs.oracle.com/javase/specs/jls/se25/html/jls-4.html#jls-4.10 Java Language Specification, section 478 * 4.10 479 */ 480 public List<? extends TypeMirror> directSupertypes(final TypeMirror t); 481 482 /** 483 * Returns the {@link Element} responsible for declaring the supplied {@link TypeMirror}, which is most commonly a 484 * {@link DeclaredType}, a {@link TypeVariable}, a {@link NoType} with a {@link TypeKind} of {@link TypeKind#MODULE}, 485 * or a {@link NoType} with a {@link TypeKind} of {@link TypeKind#PACKAGE}, <strong>or {@code null} if there is no 486 * such {@link Element}</strong>. 487 * 488 * @param t a {@link TypeMirror}; must not be {@code null} 489 * 490 * @return an {@link Element}, or {@code null} 491 * 492 * @exception NullPointerException if {@code t} is {@code null} 493 * 494 * @see javax.lang.model.util.Types#asElement(TypeMirror) 495 */ 496 public Element element(final TypeMirror t); 497 498 /** 499 * A convenience method that returns the <dfn>element type</dfn> of the supplied {@link TypeMirror}. 500 * 501 * <p>The element type of an {@linkplain TypeKind#ARRAY array type} is the element type of its {@linkplain 502 * ArrayType#getComponentType() component type}.</p>. 503 * 504 * <p>The element type of every other kind of type is the type itself. Note that the semantics of the prior sentence 505 * diverge deliberately, primarily for convenience, from those of the relevant section in the Java Language 506 * Specification.</p> 507 * 508 * @param t a {@link TypeMirror}; must not be {@code null} 509 * 510 * @return the <dfn>element type</dfn> of the supplied {@link TypeMirror}; never {@code null} 511 * 512 * @exception NullPointerException if {@code t} is {@code null} 513 * 514 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-10.html#jls-10.1 Java Language Specification, section 515 * 10.1 516 */ 517 // (Convenience.) 518 public default TypeMirror elementType(final TypeMirror t) { 519 return switch (t) { 520 case null -> throw new NullPointerException("t"); 521 case UniversalType ut -> ut.elementType(); 522 default -> { 523 try (var lock = lock()) { 524 yield t.getKind() == TypeKind.ARRAY ? this.elementType(((ArrayType)t).getComponentType()) : t; 525 } 526 } 527 }; 528 } 529 530 /** 531 * Returns the <dfn>erasure</dfn> of the supplied {@link TypeMirror}. 532 * 533 * @param <T> a {@link TypeMirror} specialization 534 * 535 * @param t the {@link TypeMirror} representing the type whose erasure should be returned; must not be {@code null} 536 * 537 * @return the erasure of the supplied {@link TypeMirror}; never {@code null} 538 * 539 * @exception NullPointerException if {@code t} is {@code null} 540 * 541 * @exception IllegalArgumentException if {@code t} is a {@link NoType} with a {@link TypeKind} of {@link 542 * TypeKind#MODULE}, or a {@link NoType} with a {@link TypeKind} of {@link TypeKind#PACKAGE} 543 * 544 * @see javax.lang.model.util.Types#erasure(TypeMirror) 545 * 546 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.6 Java Language Specification, section 547 * 4.6 548 */ 549 public <T extends TypeMirror> T erasure(final T t); 550 551 /** 552 * Returns an {@link ExecutableElement} corresponding to the supplied {@link Executable}. 553 * 554 * @param e an {@link Executable}; must not be {@code null} 555 * 556 * @return an {@link ExecutableElement} corresponding to the supplied {@link Executable}; never {@code null} 557 * 558 * @exception NullPointerException if {@code e} is {@code null} 559 * 560 * @exception IllegalArgumentException if somehow {@code e} is neither a {@link Constructor} nor a {@link Method} 561 */ 562 // (Convenience.) 563 public default ExecutableElement executableElement(final Executable e) { 564 return switch (e) { 565 case null -> throw new NullPointerException("e"); 566 case Constructor<?> c -> 567 this.executableElement(this.typeElement(c.getDeclaringClass().getCanonicalName()), 568 this.noType(TypeKind.VOID), 569 "<init>", 570 this.types(c.getParameterTypes())); 571 case Method m -> 572 this.executableElement(this.typeElement(m.getDeclaringClass().getCanonicalName()), 573 this.type(m.getReturnType()), 574 m.getName(), 575 this.types(m.getParameterTypes())); 576 default -> throw new IllegalArgumentException("e: " + e); 577 }; 578 } 579 580 581 /** 582 * A convenience method that returns an {@link ExecutableElement} representing the static initializer, constructor or 583 * method described by the supplied arguments, <strong>or {@code null} if no such {@link ExecutableElement} 584 * exists</strong>. 585 * 586 * @param declaringElement a {@link TypeElement} representing the class that declares the executable; must not be 587 * {@code null} 588 * 589 * @param returnType the {@linkplain ExecutableElement#getReturnType() return type} of the executable; must not be 590 * {@code null} 591 * 592 * @param name the {@linkplain ExecutableElement#getSimpleName() name} of the executable; must not be {@code null} 593 * 594 * @param parameterTypes {@link TypeMirror}s that represent the executable's {@linkplain 595 * ExecutableElement#getParameters() parameter types} 596 * 597 * @return an {@link ExecutableElement} with an {@link ElementKind} of {@link ElementKind#CONSTRUCTOR}, {@link 598 * ElementKind#METHOD}, or {@link ElementKind#STATIC_INIT}, or {@code null} 599 * 600 * @exception NullPointerException if any argument is {@code null} 601 */ 602 // (Convenience.) 603 public default ExecutableElement executableElement(final TypeElement declaringElement, 604 final TypeMirror returnType, 605 final CharSequence name, 606 final TypeMirror... parameterTypes) { 607 return switch (declaringElement) { 608 case null -> throw new NullPointerException("declaringElement"); 609 case UniversalElement ue -> { 610 final List<? extends UniversalElement> ees = ue.getEnclosedElements(); 611 yield ees.stream() 612 .sequential() 613 .filter(e -> e.getKind().isExecutable() && e.getSimpleName().contentEquals(name)) 614 .map(UniversalElement.class::cast) 615 .filter(ee -> { 616 if (!this.sameType(returnType, ee.getReturnType())) { 617 return false; 618 } 619 final List<? extends UniversalElement> ps = ee.getParameters(); 620 if (ps.size() != parameterTypes.length) { 621 return false; 622 } 623 for (int i = 0; i < parameterTypes.length; i++) { 624 if (!this.sameType(ps.get(i).asType(), parameterTypes[i])) { 625 return false; 626 } 627 } 628 return true; 629 }) 630 .findFirst() 631 .orElse(null); 632 } 633 default -> { 634 try (var lock = this.lock()) { 635 final List<? extends Element> ees = declaringElement.getEnclosedElements(); 636 yield ees.stream() 637 .sequential() 638 .filter(e -> e.getKind().isExecutable() && e.getSimpleName().contentEquals(name)) 639 .map(ExecutableElement.class::cast) 640 .filter(ee -> { 641 if (!this.sameType(returnType, ee.getReturnType())) { 642 return false; 643 } 644 final List<? extends VariableElement> ps = ee.getParameters(); 645 if (ps.size() != parameterTypes.length) { 646 return false; 647 } 648 for (int i = 0; i < parameterTypes.length; i++) { 649 if (!this.sameType(ps.get(i).asType(), parameterTypes[i])) { 650 return false; 651 } 652 } 653 return true; 654 }) 655 .findFirst() 656 .orElse(null); 657 } 658 } 659 }; 660 } 661 662 /** 663 * A convenience method that returns {@code true} if and only if the supplied {@link Element} is <dfn>generic</dfn>. 664 * 665 * @param e an {@link Element}; must not be {@code null} 666 * 667 * @return {@code true} if and only if the supplied {@link Element} is <dfn>generic</dfn>; {@code false} otherwise 668 * 669 * @exception NullPointerException if {@code e} is {@code null} 670 * 671 * @see Parameterizable 672 * 673 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.1.2 Java Language Specification, section 674 * 8.1.2 675 * 676 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.4.4 Java Language Specification, section 677 * 8.4.4 678 * 679 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.8.4 Java Language Specification, section 680 * 8.8.4 681 * 682 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-9.html#jls-9.1.2 Java Language Specification, section 683 * 9.1.2 684 */ 685 // (Convenience.) 686 public default boolean generic(final Element e) { 687 return switch (e) { 688 case null -> throw new NullPointerException("e"); 689 case UniversalElement ue -> ue.generic(); 690 case Parameterizable p -> { 691 try (var lock = this.lock()) { 692 yield switch (e.getKind()) { 693 case CLASS, CONSTRUCTOR, ENUM, INTERFACE, METHOD, RECORD -> !p.getTypeParameters().isEmpty(); 694 default -> false; 695 }; 696 } 697 } 698 default -> false; 699 }; 700 } 701 702 /** 703 * A convenience method that returns {@code true} if and only if the supplied {@link TypeMirror} is declared by an 704 * {@link Element} that {@linkplain #generic(Element) is generic}. 705 * 706 * @param t a {@link TypeMirror}; must not be {@code null} 707 * 708 * @return {@code true} if and only if the supplied {@link TypeMirror} is declared by an {@link Element} that 709 * {@linkplain #generic(Element) is generic} 710 * 711 * @exception NullPointerException if {@code t} is {@code null} 712 * 713 * @see #generic(Element) 714 * 715 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.1.2 Java Language Specification, section 716 * 8.1.2 717 * 718 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.4.4 Java Language Specification, section 719 * 8.4.4 720 * 721 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.8.4 Java Language Specification, section 722 * 8.8.4 723 * 724 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-9.html#jls-9.1.2 Java Language Specification, section 725 * 9.1.2 726 */ 727 // (Convenience.) 728 public default boolean generic(final TypeMirror t) { 729 return switch (t) { 730 case null -> throw new NullPointerException("t"); 731 case UniversalType ut -> ut.generic(); 732 default -> { 733 try (var lock = this.lock()) { 734 final Element e = this.element(t); 735 yield e != null && this.generic(e); 736 } 737 } 738 }; 739 } 740 741 /** 742 * A convenience method that returns {@code true} if and only if the supplied {@link Element} represents the (essentially 743 * primordial) {@code java.lang.Object} {@link Element}. 744 * 745 * @param e an {@link Element}; must not be {@code null} 746 * 747 * @return {@code true} if and only if the supplied {@link Element} represents the (essentially 748 * primordial) {@code java.lang.Object} {@link Element}; {@code false} otherwise 749 * 750 * @exception NullPointerException if {@code e} is {@code null} 751 */ 752 // (Convenience.) 753 public default boolean javaLangObject(final Element e) { 754 return switch (e) { 755 case null -> throw new NullPointerException("e"); 756 case UniversalElement ue -> ue.javaLangObject(); 757 default -> { 758 try (var lock = this.lock()) { 759 yield 760 e.getKind() == ElementKind.CLASS && 761 ((QualifiedNameable)e).getQualifiedName().contentEquals("java.lang.Object"); 762 } 763 } 764 }; 765 } 766 767 /** 768 * A convenience method that returns {@code true} if and only if the supplied {@link TypeMirror} represents the {@link 769 * DeclaredType} declared by the (essentially primordial) {@code java.lang.Object} element. 770 * 771 * @param t a {@link TypeMirror}; must not be {@code null} 772 * 773 * @return {@code true} represents the {@link 774 * DeclaredType} declared by the (essentially primordial) {@code java.lang.Object} element; {@code false} otherwise 775 * 776 * @exception NullPointerException if {@code t} is {@code null} 777 * 778 * @see #javaLangObject(Element) 779 */ 780 // (Convenience.) 781 public default boolean javaLangObject(final TypeMirror t) { 782 return switch (t) { 783 case null -> throw new NullPointerException("t"); 784 case UniversalType ut -> ut.javaLangObject(); 785 default -> { 786 try (var lock = this.lock()) { 787 yield 788 t.getKind() == DECLARED && 789 javaLangObject(((DeclaredType)t).asElement()); 790 } 791 } 792 }; 793 } 794 795 /** 796 * A convenience method that returns the {@link TypeElement} representing the class named {@link Object 797 * java.lang.Object}. 798 * 799 * @return a non-{@code null} {@link TypeElement} whose {@linkplain TypeElement#getQualifiedName() qualified name} is 800 * {@linkplain Name#contentEquals(CharSequence) equal to} {@code java.lang.Object} 801 * 802 * @see #typeElement(CharSequence) 803 */ 804 // (Convenience.) 805 public default TypeElement javaLangObject() { 806 return this.typeElement("java.lang.Object"); 807 } 808 809 // (Convenience.) 810 @Override // PrimordialDomain 811 public default DeclaredType javaLangObjectType() { 812 return (DeclaredType)this.javaLangObject().asType(); 813 } 814 815 /** 816 * Returns a {@link ModuleElement} representing the module {@linkplain ModuleElement#getQualifiedName() named} by the 817 * supplied {@code qualifiedName}, <strong>or {@code null} if there is no such {@link ModuleElement}</strong>. 818 * 819 * @param qualifiedName a name suitable for naming a module; must not be {@code null}; may be {@linkplain 820 * CharSequence#isEmpty() empty}, in which case a {@link ModuleElement} representing an <dfn>unnamed module</dfn> will 821 * be returned 822 * 823 * @return a {@link ModuleElement}, or {@code null} 824 * 825 * @exception NullPointerException if {@code qualifiedName} is {@code null} 826 * 827 * @see javax.lang.model.util.Elements#getModuleElement(CharSequence) 828 * 829 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-7.html#jls-7.7 Java Language Specification, section 830 * 7.7 831 */ 832 // Element factory method. 833 public ModuleElement moduleElement(final CharSequence qualifiedName); 834 835 /** 836 * Returns a {@link Name} representing the supplied {@link CharSequence}. 837 * 838 * @param name a {@link CharSequence}; must not be {@code null} 839 * 840 * @return a non-{@code null} {@link Name} representing the supplied {@link name} 841 * 842 * @exception NullPointerException if {@code name} is {@code null} 843 * 844 * @see #lock() 845 * 846 * @see javax.lang.model.util.Elements#getName(CharSequence) 847 */ 848 // Element factory method. 849 public Name name(final CharSequence name); 850 851 /** 852 * Returns a {@link NoType} {@linkplain TypeMirror#getKind() bearing} the supplied {@link TypeKind}, if the supplied 853 * {@link TypeKind} is either {@link TypeKind#NONE} or {@link TypeKind#VOID}. 854 * 855 * @param kind a {@link TypeKind}; must be either {@link TypeKind#NONE} or {@link TypeKind#VOID} 856 * 857 * @return a non-{@code null} {@link NoType} {@linkplain TypeMirror#getKind() bearing} the supplied {@link TypeKind} 858 * 859 * @exception NullPointerException if {@code kind} is {@code null} 860 * 861 * @exception IllegalArgumentException if {@code kind} is non-{@code null} and neither {@link TypeKind#NONE} nor 862 * {@link TypeKind#VOID} 863 * 864 * @see TypeKind#NONE 865 * 866 * @see TypeKind#VOID 867 * 868 * @see javax.lang.model.util.Types#getNoType(TypeKind) 869 * 870 * @see NoType 871 * 872 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.4.5 Java Language Specification, section 873 * 8.4.5 874 */ 875 // Type factory method. 876 @Override // PrimordialDomain 877 public NoType noType(final TypeKind kind); 878 879 /** 880 * Returns a {@link NullType} implementation {@linkplain TypeMirror#getKind() whose <code>TypeKind</code>} is {@link 881 * TypeKind#NULL}. 882 * 883 * @return a non-{@code null} {@link NullType} 884 * 885 * @see javax.lang.model.util.Types#getNullType() 886 * 887 * @see NullType 888 * 889 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.1 Java Language Specification, section 4.1 890 */ 891 // Type factory method. 892 @Override // PrimordialDomain 893 public NullType nullType(); 894 895 /** 896 * Returns the {@linkplain Origin origin} of the supplied {@link Element}. 897 * 898 * @param e a non-{@code null} {@link Element} 899 * 900 * @return a non-{@code null} {@link Origin} 901 * 902 * @see Elements#getOrigin(Element) 903 * 904 * @see Origin 905 */ 906 public Origin origin(final Element e); 907 908 /** 909 * Returns a {@link PackageElement} representing the package bearing the supplied {@code canonicalName}, <strong>or 910 * {@code null} if there is no such {@link PackageElement}</strong>. 911 * 912 * @param canonicalName a canonical name suitable for naming a package; must not be {@code null}; may be {@linkplain 913 * CharSequence#isEmpty() empty}, in which case a {@link ModuleElement} representing an <dfn>unnamed package</dfn> will 914 * be returned 915 * 916 * @return a {@link PackageElement}, or {@code null} 917 * 918 * @exception NullPointerException if {@code canonicalName} is {@code null} 919 * 920 * @see javax.lang.model.util.Elements#getPackageElement(CharSequence) 921 * 922 * @see PackageElement 923 * 924 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.7 Java Language Specification, section 925 * 6.7 926 */ 927 // Element factory method. 928 public PackageElement packageElement(final CharSequence canonicalName); 929 930 /** 931 * Returns a {@link PackageElement} representing the package bearing the supplied {@code canonicalName} as seen from 932 * the module represented by the supplied {@link ModuleElement}, <strong>or {@code null} if there is no such {@link 933 * PackageElement}</strong>. 934 * 935 * @param asSeenFrom a {@link ModuleElement}; must not be {@code null} 936 * 937 * @param canonicalName a canonical name suitable for naming a package; must not be {@code null}; may be {@linkplain 938 * CharSequence#isEmpty() empty}, in which case a {@link ModuleElement} representing an <dfn>unnamed package</dfn> will 939 * be returned 940 * 941 * @return a {@link PackageElement}, or {@code null} 942 * 943 * @exception NullPointerException if either {@code asSeenFrom} or {@code canonicalName} is {@code null} 944 * 945 * @see javax.lang.model.util.Elements#getPackageElement(ModuleElement, CharSequence) 946 * 947 * @see PackageElement 948 * 949 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.7 Java Language Specification, section 950 * 6.7 951 */ 952 // Element factory method. 953 public PackageElement packageElement(final ModuleElement asSeenFrom, final CharSequence canonicalName); 954 955 /** 956 * Returns a {@link Parameterizable} corresponding to the supplied (reflective) {@link GenericDeclaration}. 957 * 958 * @param gd a {@link GenericDeclaration}; must not be {@code null} 959 * 960 * @return a {@link Parameterizable} corresponding to the supplied {@link GenericDeclaration}; never {@code null} 961 * 962 * @exception NullPointerException if {@code gd} is {@code null} 963 * 964 * @exception IllegalArgumentException if {@code gd} is neither a {@link Class} nor an {@link Executable} 965 * 966 * @see Parameterizable 967 */ 968 // (Convenience.) 969 public default Parameterizable parameterizable(final GenericDeclaration gd) { 970 return switch (gd) { 971 case null -> throw new NullPointerException("gd"); 972 case Class<?> c -> this.typeElement(c.getCanonicalName()); 973 case Executable e -> this.executableElement(e); 974 default -> throw new IllegalArgumentException("gd: " + gd); 975 }; 976 } 977 978 /** 979 * A convenience method that returns {@code true} if and only if {@code t} is a {@link DeclaredType}, {@linkplain 980 * TypeMirror#getKind() has a <code>TypeKind</code>} of {@link TypeKind#DECLARED DECLARED}, and {@linkplain 981 * DeclaredType#getTypeArguments() has a non-empty type arguments list}. 982 * 983 * @param t a {@link TypeMirror}; must not be {@code null} 984 * 985 * @return {@code true} if and only if {@code t} is a {@link DeclaredType}, {@linkplain 986 * TypeMirror#getKind() has a <code>TypeKind</code>} of {@link TypeKind#DECLARED DECLARED}, and {@linkplain 987 * DeclaredType#getTypeArguments() has a non-empty type arguments list}; {@code false} otherwise 988 * 989 * @exception NullPointerException if {@code t} is {@code null} 990 */ 991 // (Convenience.) 992 public default boolean parameterized(final TypeMirror t) { 993 return switch (t) { 994 case null -> throw new NullPointerException("t"); 995 case UniversalType ut -> ut.parameterized(); 996 default -> { 997 try (var lock = this.lock()) { 998 yield t.getKind() == DECLARED && !((DeclaredType)t).getTypeArguments().isEmpty(); 999 } 1000 } 1001 }; 1002 } 1003 1004 /** 1005 * Returns the result of applying <dfn>unboxing conversion</dfn> to the (logical) {@link TypeElement} bearing the 1006 * supplied {@code canonicalName}. 1007 * 1008 * @param canonicalName a canonical name of either a primitive type or a so-called "wrapper" type; must not be {@code 1009 * null} 1010 * 1011 * @return a non-{@code null} {@link PrimitiveType} with a {@linkplain TypeKind#isPrimitive() primitive} {@link 1012 * TypeKind} 1013 * 1014 * @exception NullPointerException if {@code canonicalName} is {@code null} 1015 * 1016 * @exception IllegalArgumentException if {@code canonicalName} {@linkplain #toString(CharSequence) converted to a 1017 * <code>String</code>} {@linkplain String#equals(Object) is not equal to} {@code boolean}, {@code byte}, {@code 1018 * char}, {@code double}, {@code float}, {@code int}, {@code long}, {@code short}, {@link Boolean java.lang.Boolean}, 1019 * {@link Byte java.lang.Byte}, {@link Character java.lang.Character}, {@link Double java.lang.Double}, {@link Float 1020 * java.lang.Float}, {@link Integer java.lang.Integer}, {@link Long java.lang.Long}, or {@link Short java.lang.Short} 1021 * 1022 * @see #primitiveType(TypeKind) 1023 * 1024 * @see PrimitiveType 1025 * 1026 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.8 Java Language Specification, section 1027 * 5.1.8 1028 * 1029 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.7 Java Language Specification, section 1030 * 6.7 1031 */ 1032 // (Convenience.) 1033 // (Unboxing.) 1034 public default PrimitiveType primitiveType(final CharSequence canonicalName) { 1035 final String s = this.toString(requireNonNull(canonicalName, "canonicalName")); 1036 return switch (s) { 1037 case "boolean", "java.lang.Boolean" -> this.primitiveType(TypeKind.BOOLEAN); 1038 case "byte", "java.lang.Byte" -> this.primitiveType(TypeKind.BYTE); 1039 case "char", "java.lang.Character" -> this.primitiveType(TypeKind.CHAR); 1040 case "double", "java.lang.Double" -> this.primitiveType(TypeKind.DOUBLE); 1041 case "float", "java.lang.Float" -> this.primitiveType(TypeKind.FLOAT); 1042 case "int", "java.lang.Integer" -> this.primitiveType(TypeKind.INT); 1043 case "long", "java.lang.Long" -> this.primitiveType(TypeKind.LONG); 1044 case "short", "java.lang.Short" -> this.primitiveType(TypeKind.SHORT); 1045 default -> throw new IllegalArgumentException("canonicalName: " + s); 1046 }; 1047 } 1048 1049 /** 1050 * Returns the result of applying <dfn>unboxing conversion</dfn> to the {@linkplain Element#asType() type declared by 1051 * the supplied <code>TypeElement</code>}. 1052 * 1053 * @param e a {@link TypeElement}; must not be {@code null} 1054 * 1055 * @return a non-{@code null} {@link PrimitiveType} with a {@linkplain TypeKind#isPrimitive() primitive} {@link 1056 * TypeKind} 1057 * 1058 * @exception NullPointerException if {@code e} is {@code null} 1059 * 1060 * @exception IllegalArgumentException if there is no unboxing conversion that can be applied to the {@linkplain 1061 * Element#asType() type declared by <code>e</code>} 1062 * 1063 * @see javax.lang.model.util.Types#unboxedType(TypeMirror) 1064 * 1065 * @see #primitiveType(TypeMirror) 1066 * 1067 * @see PrimitiveType 1068 * 1069 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.8 Java Language Specification, section 1070 * 5.1.8 1071 */ 1072 // (Convenience.) 1073 // (Unboxing.) 1074 public default PrimitiveType primitiveType(final TypeElement e) { 1075 return this.primitiveType(e.asType()); 1076 } 1077 1078 /** 1079 * Returns the {@link PrimitiveType} corresponding to the supplied {@link TypeKind} (if it {@linkplain 1080 * TypeKind#isPrimitive() is primitive}). 1081 * 1082 * @param kind a {@linkplain TypeKind#isPrimitive() primitive} {@link TypeKind}; must not be {@code null} 1083 * 1084 * @return a non-{@code null} {@link PrimitiveType} {@linkplain TypeMirror#getKind() with} a {@linkplain 1085 * TypeKind#isPrimitive() primitive} {@link TypeKind} 1086 * 1087 * @exception NullPointerException if {@code kind} is {@code null} 1088 * 1089 * @exception IllegalArgumentException if {@code kind} {@linkplain TypeKind#isPrimitive() is not primitive} 1090 * 1091 * @see javax.lang.model.util.Types#getPrimitiveType(TypeKind) 1092 * 1093 * @see PrimitiveType 1094 * 1095 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.2 Java Language Specification, section 1096 * 4.2 1097 */ 1098 // (Canonical.) 1099 // Type factory method. 1100 public PrimitiveType primitiveType(final TypeKind kind); 1101 1102 /** 1103 * Returns the result of applying <dfn>unboxing conversion</dfn> to the supplied {@link TypeMirror}. 1104 * 1105 * @param t a {@link TypeMirror}; must not be {@code null} 1106 * 1107 * @return a non-{@code null} {@link PrimitiveType} with a {@linkplain TypeKind#isPrimitive() primitive} {@link 1108 * TypeKind} 1109 * 1110 * @exception NullPointerException if {@code t} is {@code null} 1111 * 1112 * @exception IllegalArgumentException if there is no unboxing conversion that can be applied to {@code t} 1113 * 1114 * @see javax.lang.model.util.Types#unboxedType(TypeMirror) 1115 * 1116 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.8 Java Language Specification, section 1117 * 5.1.8 1118 */ 1119 // (Canonical.) 1120 // (Unboxing.) 1121 // Type factory method. 1122 public PrimitiveType primitiveType(final TypeMirror t); 1123 1124 /** 1125 * A convenience method that returns {@code true} if and only if the supplied {@link TypeMirror} represents a 1126 * <dfn>prototypical type</dfn>. 1127 * 1128 * <p>Prototypical types are not defined by the Java Language Specification. They are partially defined by the 1129 * {@linkplain TypeElement#asType() specification of the <code>TypeElement#asType()</code> 1130 * method}.</p> 1131 * 1132 * @param t a {@link TypeMirror}; must not be {@code null} 1133 * 1134 * @return {@code true} if and only if {@code t} represents a <dfn>prototypical type</dfn> 1135 * 1136 * @exception NullPointerException if {@code t} is {@code null} 1137 * 1138 * @see TypeElement#asType() 1139 */ 1140 // (Convenience.) 1141 public default boolean prototypical(final TypeMirror t) { 1142 return switch (t) { 1143 case null -> throw new NullPointerException("t"); 1144 case UniversalType ut -> ut.prototypical(); 1145 default -> { 1146 try (var lock = this.lock()) { 1147 yield t.getKind() == DECLARED && t.equals(((DeclaredType)t).asElement().asType()); 1148 } 1149 } 1150 }; 1151 } 1152 1153 /** 1154 * A convenience method that returns {@code true} if and only if the supplied {@link TypeMirror} is a <dfn>raw 1155 * type</dfn> according to <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8">the rules 1156 * of the Java Language Specification</a> 1157 * 1158 * @param t a {@link TypeMirror}; must not be {@code null} 1159 * 1160 * @return {@code true} if and only if the supplied {@link TypeMirror} is a <dfn>raw type</dfn> according to <a 1161 * href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8">the rules of the Java Language 1162 * Specification</a> 1163 * 1164 * @exception NullPointerException if {@code t} is {@code null} 1165 * 1166 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8 Java Language Specification, section 4.8 1167 */ 1168 // (Convenience.) 1169 public default boolean raw(final TypeMirror t) { 1170 return switch (t) { 1171 case null -> throw new NullPointerException("t"); 1172 case UniversalType ut -> ut.raw(); 1173 default -> { 1174 try (var lock = this.lock()) { 1175 yield switch (t.getKind()) { 1176 case ARRAY -> raw(elementType((ArrayType)t)); 1177 case DECLARED -> { 1178 final DeclaredType dt = (DeclaredType)t; 1179 yield generic(dt.asElement()) && dt.getTypeArguments().isEmpty(); 1180 } 1181 default -> false; 1182 }; 1183 } 1184 } 1185 }; 1186 } 1187 1188 /** 1189 * A convenience method that returns the <dfn>raw type</dfn> corresponding to {@code t}, <strong>or {@code null} if 1190 * {@code t} is <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8">incapable of yielding 1191 * a raw type</a></strong>. 1192 * 1193 * <p>Overrides of this method must conform to the requirements imposed by the relevant section of the relevant 1194 * version of the Java Language Specification concerning raw types.</p> 1195 * 1196 * @param t a {@link TypeMirror}; must not be {@code null} 1197 * 1198 * @return the raw type corresponding to the supplied {@link TypeMirror}, or {@code null} if {@code t} is <a 1199 * href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8">incapable of yielding a raw type</a> 1200 * 1201 * @exception NullPointerException if {@code t} is {@code null} 1202 * 1203 * @see #parameterized(TypeMirror) 1204 * 1205 * @see #elementType(TypeMirror) 1206 * 1207 * @see #erasure(TypeMirror) 1208 * 1209 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8 Java Language Specification, section 1210 * 4.8 1211 */ 1212 // (Convenience.) 1213 public default TypeMirror rawType(TypeMirror t) { 1214 return switch (t) { 1215 case null -> throw new NullPointerException("t"); 1216 case UniversalType ut -> ut.elementType().parameterized() ? this.erasure(ut) : null; 1217 default -> this.parameterized(this.elementType(t)) ? this.erasure(t) : null; 1218 }; 1219 } 1220 1221 /** 1222 * Returns a {@link RecordComponentElement} corresponding to the supplied {@link ExecutableElement}, <strong>or {@code 1223 * null} if there is no such {@link RecordComponentElement}</strong>. 1224 * 1225 * @param e an {@link ExecutableElement} {@linkplain ExecutableElement#getEnclosingElement() enclosed by} a record 1226 * representing an <dfn>accessor method</dfn>; must not be {@code null} 1227 * 1228 * @return a {@link RecordComponentElement} corresponding to the supplied {@link ExecutableElement}, or {@code null} 1229 * 1230 * @exception NullPointerException if {@code e} is {@code null} 1231 * 1232 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.10.3 Java Language Specification, section 1233 * 8.10.3 1234 */ 1235 public RecordComponentElement recordComponentElement(final ExecutableElement e); 1236 1237 /** 1238 * Returns {@code true} if and only if the two arguments represent the <dfn>same type</dfn>. 1239 * 1240 * <p>This method differs from the {@link javax.lang.model.util.Types#isSameType(TypeMirror, TypeMirror)} method in 1241 * two ways:</p> 1242 * 1243 * <ul> 1244 * 1245 * <li>Its arguments may be {@code null}. If both arguments are {@code null}, {@code true} is returned. If only one 1246 * argument is {@code null}, {@code false} is returned.</li> 1247 * 1248 * <li>If the same Java object reference is passed as both arguments, {@code true} is returned (even if it {@linkplain 1249 * TypeMirror#getKind() has a <code>TypeKind</code>} of {@link TypeKind#WILDCARD}).</li> 1250 * 1251 * </ul> 1252 * 1253 * @param t0 the first {@link TypeMirror}; may be {@code null} 1254 * 1255 * @param t1 the second {@link TypeMirror}; may be {@code null} 1256 * 1257 * @return {@code true} if and only if the two arguments represent the <dfn>same type</dfn>; {@code false} otherwise 1258 * 1259 * @see javax.lang.model.util.Types#isSameType(TypeMirror, TypeMirror) 1260 * 1261 * @see <a href="https://bugs.openjdk.org/browse/JDK-8055219">JDK-8055219</a> 1262 * 1263 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.3.4 Java Language Specification, section 1264 * 4.3.4 1265 * 1266 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5.1 Java Language Specification, section 1267 * 4.5.1 1268 */ 1269 public boolean sameType(final TypeMirror t0, final TypeMirror t1); 1270 1271 /** 1272 * Returns {@code true} if and only if {@code et0} is a <dfn>subsignature</dfn> of {@code et1}. 1273 * 1274 * @param et0 the first {@link ExecutableType}; must not be {@code null} 1275 * 1276 * @param et1 the second {@link ExecutableType}; must not be {@code null} 1277 * 1278 * @return {@code true} if and only if {@code et0} is a <dfn>subsignature</dfn> of {@code et1} 1279 * 1280 * @exception NullPointerException if either argument is {@code null} 1281 * 1282 * @exception ClassCastException if this method is implemented in terms of the {@link 1283 * javax.lang.model.util.Types#isSubsignature(ExecutableType, ExecutableType)} method, and if each of the supplied 1284 * {@link ExecutableType} arguments does not have an {@linkplain TypeKind#EXECUTABLE <code>EXECUTABLE</code> 1285 * <code>TypeKind</code>}; this exception type is undocumented by the {@link 1286 * javax.lang.model.util.Types#isSubsignature(ExecutableType, ExecutableType)} method and so is subject to change 1287 * without prior notice 1288 * 1289 * @see javax.lang.model.util.Types#isSubsignature(ExecutableType, ExecutableType) 1290 * 1291 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.4.2 Java Language Specification, section 1292 * 8.4.2 1293 */ 1294 public boolean subsignature(final ExecutableType et0, final ExecutableType et1); 1295 1296 /** 1297 * Returns {@code true} if and only if {@code candidateSubtype} is a <dfn>subtype</dfn> of {@code supertype}. 1298 * 1299 * @param candidateSubtype the first {@link TypeMirror}; must not be {@code null} 1300 * 1301 * @param supertype the second {@link TypeMirror}; must not be {@code null} 1302 * 1303 * @return {@code true} if and only if {@code candidateSubtype} is a <dfn>subtype</dfn> of {@code supertype} 1304 * 1305 * @exception NullPointerException if either argument is {@code null} 1306 * 1307 * @see javax.lang.model.util.Types#isSubtype(TypeMirror, TypeMirror) 1308 * 1309 * @spec https://docs.oracle.com/javase/specs/jls/se25/html/jls-4.html#jls-4.10 Java Language Specification, section 1310 * 4.10 1311 */ 1312 public boolean subtype(TypeMirror candidateSubtype, TypeMirror supertype); 1313 1314 /** 1315 * A convenience method that returns the {@link TypeMirror} corresponding to the supplied (reflective) {@link Type}. 1316 * 1317 * @param t a {@link Type}; must not be {@code null} 1318 * 1319 * @return the {@link TypeMirror} corresponding to the supplied {@link Type}; never {@code null} 1320 * 1321 * @exception NullPointerException if {@code t} is {@code null} 1322 * 1323 * @exception IllegalArgumentException if {@code t} is not a {@link Class}, {@link GenericArrayType}, {@link 1324 * ParameterizedType}, {@link java.lang.reflect.TypeVariable} or {@link java.lang.reflect.WildcardType} 1325 */ 1326 // (Convenience.) 1327 public default TypeMirror type(final Type t) { 1328 // TODO: anywhere there is domain.declaredType(), consider passing 1329 // domain.moduleElement(this.getClass().getModule().getName()) as the first argument. Not sure how this works 1330 // exactly but I think it might be necessary. 1331 return switch (t) { 1332 case null -> throw new NullPointerException("t"); 1333 case Class<?> c when t == boolean.class -> this.primitiveType(TypeKind.BOOLEAN); 1334 case Class<?> c when t == byte.class -> this.primitiveType(TypeKind.BYTE); 1335 case Class<?> c when t == char.class -> this.primitiveType(TypeKind.CHAR); 1336 case Class<?> c when t == double.class -> this.primitiveType(TypeKind.DOUBLE); 1337 case Class<?> c when t == float.class -> this.primitiveType(TypeKind.FLOAT); 1338 case Class<?> c when t == int.class -> this.primitiveType(TypeKind.INT); 1339 case Class<?> c when t == long.class -> this.primitiveType(TypeKind.LONG); 1340 case Class<?> c when t == short.class -> this.primitiveType(TypeKind.SHORT); 1341 case Class<?> c when t == void.class -> this.noType(TypeKind.VOID); 1342 case Class<?> c when t == Object.class -> this.javaLangObject().asType(); // cheap and easy optimization 1343 case Class<?> c when c.isArray() -> this.arrayTypeOf(this.type(c.getComponentType())); 1344 case Class<?> c -> this.declaredType(c.getCanonicalName()); 1345 case GenericArrayType g -> this.arrayTypeOf(this.type(g.getGenericComponentType())); 1346 case ParameterizedType pt when pt.getOwnerType() == null -> 1347 this.declaredType(this.typeElement(((Class<?>)pt.getRawType()).getCanonicalName()), 1348 this.types(pt.getActualTypeArguments())); 1349 case ParameterizedType pt -> 1350 this.declaredType((DeclaredType)this.type(pt.getOwnerType()), 1351 this.typeElement(((Class<?>)pt.getRawType()).getCanonicalName()), 1352 this.types(pt.getActualTypeArguments())); 1353 case java.lang.reflect.TypeVariable<?> tv -> this.typeVariable(this.parameterizable(tv.getGenericDeclaration()), tv.getName()); 1354 case java.lang.reflect.WildcardType w when w.getLowerBounds().length <= 0 -> this.wildcardType(this.type(w.getUpperBounds()[0]), null); 1355 case java.lang.reflect.WildcardType w -> this.wildcardType(null, this.type(w.getLowerBounds()[0])); 1356 default -> throw new IllegalArgumentException("t: " + t); 1357 }; 1358 } 1359 1360 /** 1361 * A convenience method that returns an array of {@link TypeMirror}s whose elements correspond, in order, to the 1362 * elements in the supplied {@link Type} array. 1363 * 1364 * @param ts an array of {@link Type}s; must not be {@code null} 1365 * 1366 * @return an array of {@link TypeMirror}s whose elements correspond, in order, to the elements in the supplied {@link 1367 * Type} array; never {@code null} 1368 * 1369 * @exception NullPointerException if {@code ts} is {@code null} or contains {@code null} elements 1370 * 1371 * @exception IllegalArgumentException if any element of {@code ts} is deemed illegal by the {@link #type(Type)} 1372 * method 1373 * 1374 * @see #type(Type) 1375 */ 1376 // (Convenience.) 1377 public default TypeMirror[] types(final Type[] ts) { 1378 return switch (ts.length) { 1379 case 0 -> new TypeMirror[0]; 1380 case 1 -> new TypeMirror[] { this.type(ts[0]) }; 1381 default -> { 1382 final TypeMirror[] rv = new TypeMirror[ts.length]; 1383 for (int i = 0; i < ts.length; i++) { 1384 rv[i] = this.type(ts[i]); 1385 } 1386 yield rv; 1387 } 1388 }; 1389 } 1390 1391 /** 1392 * Returns a {@link TypeElement} representing the element bearing the supplied <dfn>canonical name</dfn>, <strong>or 1393 * {@code null} if there is no such {@link TypeElement}</strong>. 1394 * 1395 * @param canonicalName a valid canonical name; must not be {@code null} 1396 * 1397 * @return a {@link TypeElement}, or {@code null} 1398 * 1399 * @exception NullPointerException if {@code canonicalName} is {@code null} 1400 * 1401 * @see javax.lang.model.util.Elements#getTypeElement(CharSequence) 1402 * 1403 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.7 Java Language Specification, section 1404 * 6.7 1405 */ 1406 // Element factory method. 1407 public TypeElement typeElement(final CharSequence canonicalName); 1408 1409 /** 1410 * Returns a {@link TypeElement} representing the element bearing the supplied <dfn>canonical name</dfn>, as read or 1411 * seen from the module represented by the supplied {@link ModuleElement}, <strong>or {@code null} if there is no such 1412 * {@link TypeElement}</strong>. 1413 * 1414 * @param asSeenFrom a {@link ModuleElement}; must not be {@code null} 1415 * 1416 * @param canonicalName a valid canonical name; must not be {@code null} 1417 * 1418 * @return a {@link TypeElement}, or {@code null} 1419 * 1420 * @exception NullPointerException if either {@code asSeenFrom} or {@code canonicalName} is {@code null} 1421 * 1422 * @see javax.lang.model.util.Elements#getTypeElement(ModuleElement, CharSequence) 1423 * 1424 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.7 Java Language Specification, section 1425 * 6.7 1426 */ 1427 // Element factory method. 1428 public TypeElement typeElement(final ModuleElement asSeenFrom, final CharSequence canonicalName); 1429 1430 /** 1431 * Returns a {@link TypeElement} representing the result of applying <dfn>boxing conversion</dfn> to the primitive 1432 * type represented by the supplied {@link PrimitiveType} argument. 1433 * 1434 * <p>The default implementation of this method calls the {@link #typeElement(TypeKind)} method with the supplied 1435 * {@link PrimitiveType}'s {@linkplain TypeMirror#getKind() affiliated <code>TypeKind</code>} and returns its 1436 * result.</p> 1437 * 1438 * @param t a {@link PrimitiveType} with a {@link TypeKind} that {@linkplain TypeKind#isPrimitive() is primitive}; 1439 * must not be {@code null} 1440 * 1441 * @return a non-{@code null} {@link TypeElement} representing the result of applying boxing conversion to the 1442 * supplied argument 1443 * 1444 * @exception NullPointerException if {@code t} is {@code null} 1445 * 1446 * @exception ClassCastException if this method is implemented in terms of the {@link 1447 * javax.lang.model.util.Types#boxedClass(PrimitiveType)} method, and if the supplied {@link PrimitiveType} does not 1448 * have a {@linkplain TypeKind#isPrimitive() primitive <code>TypeKind</code>}; this exception type is undocumented by 1449 * the {@link javax.lang.model.util.Types#boxedClass(PrimitiveType)} method and so is subject to change without prior 1450 * notice 1451 * 1452 * @exception IllegalArgumentException if {@code primitiveTypeKind} {@linkplain TypeKind#isPrimitive() is not 1453 * primitive} 1454 * 1455 * @see #typeElement(TypeKind) 1456 * 1457 * @see javax.lang.model.util.Types#boxedClass(PrimitiveType) 1458 * 1459 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.7 Java Language Specification, section 1460 * 5.1.7 1461 */ 1462 // Element factory method. 1463 // (Canonical.) 1464 // (Boxing.) 1465 public default TypeElement typeElement(final PrimitiveType t) { 1466 return switch (t) { 1467 case null -> throw new NullPointerException("t"); 1468 case UniversalType ut -> this.typeElement(ut.getKind()); 1469 default -> { 1470 try (var lock = this.lock()) { 1471 yield this.typeElement(t.getKind()); 1472 } 1473 } 1474 }; 1475 } 1476 1477 /** 1478 * Returns a {@link TypeElement} representing the result of applying <dfn>boxing conversion</dfn> to the primitive 1479 * type represented by the supplied {@link TypeKind} argument, if it {@linkplain TypeKind#isPrimitive() is primitive}. 1480 * 1481 * @param primitiveTypeKind a {@link TypeKind} that {@linkplain TypeKind#isPrimitive() is primitive}; must not be 1482 * {@code null} 1483 * 1484 * @return a non-{@code null} {@link TypeElement} representing the result of applying boxing conversion to the 1485 * supplied argument 1486 * 1487 * @exception IllegalArgumentException if {@code primitiveTypeKind} {@linkplain TypeKind#isPrimitive() is not 1488 * primitive} 1489 * 1490 * @see #typeElement(PrimitiveType) 1491 * 1492 * @see javax.lang.model.util.Types#boxedClass(PrimitiveType) 1493 * 1494 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.7 Java Language Specification, section 1495 * 5.1.7 1496 */ 1497 // (Convenience.) 1498 // (Boxing.) 1499 public default TypeElement typeElement(final TypeKind primitiveTypeKind) { 1500 return switch (primitiveTypeKind) { 1501 case BOOLEAN -> this.typeElement("java.lang.Boolean"); 1502 case BYTE -> this.typeElement("java.lang.Byte"); 1503 case CHAR -> this.typeElement("java.lang.Character"); 1504 case DOUBLE -> this.typeElement("java.lang.Double"); 1505 case FLOAT -> this.typeElement("java.lang.Float"); 1506 case INT -> this.typeElement("java.lang.Integer"); 1507 case LONG -> this.typeElement("java.lang.Long"); 1508 case SHORT -> this.typeElement("java.lang.Short"); 1509 default -> throw new IllegalArgumentException("primitiveTypeKind: " + primitiveTypeKind); 1510 }; 1511 } 1512 1513 /** 1514 * Returns the {@link TypeParameterElement} {@linkplain Parameterizable#getTypeParameters() contained} by the supplied 1515 * {@link Parameterizable} whose {@linkplain TypeParameterElement#getSimpleName() name} {@linkplain 1516 * Name#contentEquals(CharSequence) is equal to} the supplied {@code name}, <strong>or {@code null} if there is no 1517 * such {@link TypeParameterElement}</strong>. 1518 * 1519 * @param p a {@link Parameterizable}; must not be {@code null} 1520 * 1521 * @param name a name valid for a type parameter; must not be {@code null} 1522 * 1523 * @return a {@link TypeParameterElement}, or {@code null} 1524 */ 1525 // (Convenience.) 1526 public default TypeParameterElement typeParameterElement(Parameterizable p, final CharSequence name) { 1527 requireNonNull(p, "p"); 1528 requireNonNull(name, "name"); 1529 while (p != null) { 1530 switch (p) { 1531 case UniversalElement ue: 1532 for (final UniversalElement tpe : ue.getTypeParameters()) { 1533 if (tpe.getSimpleName().contentEquals(name)) { 1534 return tpe; 1535 } 1536 } 1537 p = ue.getEnclosingElement(); 1538 break; 1539 default: 1540 try (var lock = this.lock()) { 1541 for (final TypeParameterElement tpe : p.getTypeParameters()) { 1542 if (tpe.getSimpleName().contentEquals(name)) { 1543 return tpe; 1544 } 1545 } 1546 p = (Parameterizable)((Element)p).getEnclosingElement(); 1547 } 1548 break; 1549 } 1550 } 1551 return null; 1552 } 1553 1554 /** 1555 * A convenience method that returns the {@link TypeVariable} {@linkplain TypeParameterElement#asType() declared by} 1556 * the {@link TypeParameterElement} {@linkplain Parameterizable#getTypeParameters() contained} by the supplied {@link 1557 * Parameterizable} whose {@linkplain TypeParameterElement#getSimpleName() name} {@linkplain 1558 * Name#contentEquals(CharSequence) is equal to} the supplied {@code name}, <strong>or {@code null} if there is no 1559 * such {@link TypeParameterElement} or {@link TypeVariable}</strong>. 1560 * 1561 * @param p a {@link Parameterizable}; must not be {@code null} 1562 * 1563 * @param name a name valid for a type parameter; must not be {@code null} 1564 * 1565 * @return a {@link TypeVariable}, or {@code null} 1566 * 1567 * @see #typeParameterElement(Parameterizable, CharSequence) 1568 */ 1569 // (Convenience.) 1570 public default TypeVariable typeVariable(Parameterizable p, final CharSequence name) { 1571 final TypeParameterElement e = this.typeParameterElement(p, name); 1572 return e == null ? null : (TypeVariable)e.asType(); 1573 } 1574 1575 /** 1576 * A convenience method that returns the first {@link VariableElement} {@linkplain Element#getSimpleName() bearing} 1577 * the supplied {@code simpleName} that the supplied {@code enclosingElement} {@linkplain 1578 * Element#getEnclosedElements() encloses}, <strong>or {@code null} if there is no such {@link 1579 * VariableElement}</strong>. 1580 * 1581 * @param enclosingElement an {@link Element}; must not be {@code null} 1582 * 1583 * @param simpleName a {@link CharSequence}; must not be {@code null} 1584 * 1585 * @return a {@link VariableElement}, or {@code null} 1586 * 1587 * @exception NullPointerException if either argument is {@code null} 1588 * 1589 * @see Element#getEnclosedElements() 1590 * 1591 * @see Element#getSimpleName() 1592 * 1593 * @see VariableElement 1594 */ 1595 // (Convenience.) 1596 public default VariableElement variableElement(final Element enclosingElement, final CharSequence simpleName) { 1597 requireNonNull(simpleName, "simpleName"); 1598 return switch (enclosingElement) { 1599 case null -> throw new NullPointerException("enclosingElement"); 1600 case UniversalElement ue -> { 1601 for (final UniversalElement ee : ue.getEnclosedElements()) { 1602 if (ee.getSimpleName().contentEquals(simpleName)) { 1603 yield ee; 1604 } 1605 } 1606 yield null; 1607 } 1608 default -> { 1609 try (var lock = lock()) { 1610 for (final Element ee : enclosingElement.getEnclosedElements()) { 1611 if (ee.getSimpleName().contentEquals(simpleName)) { 1612 yield (VariableElement)ee; 1613 } 1614 } 1615 } 1616 yield null; 1617 } 1618 }; 1619 } 1620 1621 /** 1622 * A convenience method that returns a new {@link WildcardType} {@linkplain TypeMirror#getKind() with a 1623 * <code>TypeKind</code>} of {@link TypeKind#WILDCARD}, an {@linkplain WildcardType#getExtendsBound() extends bound} 1624 * of {@code null}, and a {@linkplain WildcardType#getSuperBound() super bound} of {@code null}. 1625 * 1626 * @return a new, non-{@code null} {@link WildcardType} 1627 * 1628 * @see #wildcardType(TypeMirror, TypeMirror) 1629 * 1630 * @see javax.lang.model.util.Types#getWildcardType(TypeMirror, TypeMirror) 1631 * 1632 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5.1 Java Language Specification, section 1633 * 4.5.1 1634 */ 1635 // (Convenience.) 1636 public default WildcardType wildcardType() { 1637 return this.wildcardType(null, null); 1638 } 1639 1640 /** 1641 * Returns a new {@link WildcardType} {@linkplain TypeMirror#getKind() with a <code>TypeKind</code>} of {@link 1642 * TypeKind#WILDCARD}, an {@linkplain WildcardType#getExtendsBound() extends bound} of the supplied {@code 1643 * extendsBound}, and a {@linkplain WildcardType#getSuperBound() super bound} of the supplied {@code superBound}. 1644 * 1645 * <p>Any argument may be {@code null}. Both arguments may not be non-{@code null}.</p> 1646 * 1647 * @param extendsBound the upper bound of the new {@link WildcardType}; may be {@code null} 1648 * 1649 * @param superBound the lower bound of the new {@link WildcardType}; may be {@code null} 1650 * 1651 * @return a new, non-{@code null} {@link WildcardType} 1652 * 1653 * @exception IllegalArgumentException if both arguments are non-{@code null} or otherwise unsuitable for being the 1654 * bounds of a {@link WildcardType} 1655 * 1656 * @see javax.lang.model.util.Types#getWildcardType(TypeMirror, TypeMirror) 1657 * 1658 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5.1 Java Language Specification, section 1659 * 4.5.1 1660 */ 1661 // Type factory method. 1662 public WildcardType wildcardType(TypeMirror extendsBound, TypeMirror superBound); 1663 1664}