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