001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2024–2025 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.util.List; 017import java.util.Objects; 018 019import javax.lang.model.element.Element; 020import javax.lang.model.element.ElementKind; 021import javax.lang.model.element.ExecutableElement; 022import javax.lang.model.element.ModuleElement; 023import javax.lang.model.element.Name; 024import javax.lang.model.element.PackageElement; 025import javax.lang.model.element.Parameterizable; 026import javax.lang.model.element.QualifiedNameable; 027import javax.lang.model.element.RecordComponentElement; 028import javax.lang.model.element.TypeElement; 029import javax.lang.model.element.TypeParameterElement; 030import javax.lang.model.element.VariableElement; 031 032import javax.lang.model.type.ArrayType; 033import javax.lang.model.type.DeclaredType; 034import javax.lang.model.type.ExecutableType; 035import javax.lang.model.type.NoType; 036import javax.lang.model.type.NullType; 037import javax.lang.model.type.PrimitiveType; 038import javax.lang.model.type.TypeKind; 039import javax.lang.model.type.TypeMirror; 040import javax.lang.model.type.TypeVariable; 041import javax.lang.model.type.WildcardType; 042 043import javax.lang.model.util.Elements; 044import javax.lang.model.util.Elements.Origin; 045 046import org.microbean.construct.element.StringName; 047import org.microbean.construct.element.UniversalElement; 048 049import org.microbean.construct.type.UniversalType; 050 051import static javax.lang.model.element.ElementKind.CONSTRUCTOR; 052import static javax.lang.model.element.ElementKind.METHOD; 053 054/** 055 * A representation of a domain of valid Java constructs. 056 * 057 * <p>A <dfn id="domain">domain</dfn> is a set of valid Java <a href="#construct">constructs</a>. A {@link Domain} 058 * provides access to a domain and its members.</p> 059 * 060 * <p>A Java <dfn id="construct">construct</dfn> is either a <a href="#type">type</a> or an <a 061 * href="#element">element</a>.</p> 062 * 063 * <p>A <dfn id="type">type</dfn> is a usage of a Java type, most commonly represented as a {@link TypeMirror}.</p> 064 * 065 * <p>An <dfn id="element">element</dfn> ia a declaration of a Java program element, most commonly represented as an 066 * {@link Element}.</p> 067 * 068 * <p>Domains impose constraints on the <a href="#type">types</a> and <a href="#element">elements</a> they contain, and 069 * on the kinds and semantics of operations that can be performed on them.</p> 070 * 071 * <p>This interface is modeled on a deliberately restricted combination of the {@link javax.lang.model.util.Elements} 072 * and {@link javax.lang.model.util.Types} interfaces.</p> 073 * 074 * <p>{@link Domain} implementations must be thread-safe.</p> 075 * 076 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 077 */ 078@SuppressWarnings("try") 079public interface Domain { 080 081 /** 082 * Returns an {@link ArrayType} whose {@linkplain ArrayType#getComponentType() component type} is {@linkplain 083 * #sameType(TypeMirror, TypeMirror) the same as} the supplied {@code componentType}. 084 * 085 * @param componentType the component type; must not be {@code null} 086 * 087 * @return a non-{@code null} {@link ArrayType} whose {@linkplain ArrayType#getComponentType() component type} is 088 * {@linkplain #sameType(TypeMirror, TypeMirror) the same as} the supplied {@code componentType} 089 * 090 * @exception NullPointerException if {@code componentType} is {@code null} 091 * 092 * @exception IllegalArgumentException if {@code componentType} is not a valid component type 093 * 094 * @see javax.lang.model.util.Types#getArrayType(TypeMirror) 095 */ 096 public ArrayType arrayTypeOf(final TypeMirror componentType); 097 098 /** 099 * Returns a non-{@code null} {@link TypeMirror} representing the type of the supplied {@link Element} when that 100 * {@link Element} is viewed as a member of, or otherwise directly contained by, the supplied {@code containingType}. 101 * 102 * <p>For example, when viewed as a member of the parameterized type {@link java.util.Set Set<String>}, the 103 * {@link java.util.Set#add(Object)} method (represented as an {@link ExecutableElement}) {@linkplain 104 * ExecutableElement#asType() has} a {@linkplain ExecutableType type} whose {@linkplain 105 * ExecutableType#getParameterTypes() method parameter is of type} {@link String} (not {@link String}'s erasure).</p> 106 * 107 * @param containingType the containing {@link DeclaredType}; must not be {@code null} 108 * 109 * @param e the member {@link Element}; must not be {@code null} 110 * 111 * @return a non-{@code null} {@linkplain TypeMirror type} representing the {@linkplain Element#asType() type of} the 112 * supplied {@link Element} when viewed as a member of the supplied {@code containingType}; never {@code null} 113 * 114 * @exception NullPointerException if either {@code containingType} or {@code e} is {@code null} 115 * 116 * @exception IllegalArgumentException if {@code e} cannot be viewed as a member of the supplied {@code 117 * containingType} (because it is the wrong {@linkplain Element#getKind() kind}, for example) 118 * 119 * @see javax.lang.model.util.Types#asMemberOf(DeclaredType, Element) 120 */ 121 public TypeMirror asMemberOf(final DeclaredType containingType, final Element e); 122 123 /** 124 * Returns {@code true} if and only if the supplied {@code payload} (the first argument) is considered assignable to 125 * the supplied {@code receiver} (the second argument) according to <a 126 * href="https://docs.oracle.com/javase/specs/jls/se21/html/jls-5.html#jls-5.2">the rules of the Java Language 127 * Specification</a>. 128 * 129 * @param payload the {@link TypeMirror} being assigned; must not be {@code null} 130 * 131 * @param receiver the {@link TypeMirror} receiving the assignment; must not be {@code null} 132 * 133 * @return {@code true} if and only if {@code payload} is assignable to {@code receiver} 134 * 135 * @exception NullPointerException if either {@code payload} or {@code receiver} is {@code null} 136 * 137 * @exception IllegalArgumentException if either {@link TypeMirror} is not one that can take part in an assignment 138 * 139 * @see javax.lang.model.util.Types#isAssignable(TypeMirror, TypeMirror) 140 * 141 * @spec https://docs.oracle.com/javase/specs/jls/se21/html/jls-5.html#jls-5.2 Java Language Specification, section 142 * 5.2 143 */ 144 // Note the strange positioning of payload and receiver. 145 public boolean assignable(final TypeMirror payload, final TypeMirror receiver); 146 147 /** 148 * Returns the (non-{@code null}) <a 149 * href="https://docs.oracle.com/javase/specs/jls/se21/html/jls-13.html#jls-13.1"><dfn>binary name</dfn></a> of the 150 * supplied {@link TypeElement}. 151 * 152 * @param e a {@link TypeElement}; must not be {@code null} 153 * 154 * @return a non-{@code null} {@link Name} 155 * 156 * @exception NullPointerException if {@code e} is {@code null} 157 * 158 * @see javax.lang.model.util.Elements#getBinaryName(TypeElement) 159 * 160 * @spec https://docs.oracle.com/javase/specs/jls/se21/html/jls-13.html#jls-13.1 Java Language Specification, section 161 * 13.1 162 */ 163 public Name binaryName(final TypeElement e); 164 165 /** 166 * Returns {@code true} if and only if the supplied {@link ExecutableElement} represents a <dfn>bridge method</dfn>. 167 * 168 * @param e an {@link ExecutableElement}; must not be {@code null} 169 * 170 * @return {@code true} if and only if the supplied {@link ExecutableElement} represents a bridge method 171 * 172 * @exception NullPointerException if {@code e} is {@code null} 173 * 174 * @see javax.lang.model.util.Elements#isBridge(ExecutableElement) 175 * 176 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.4.8.3 Java Language Specification, 177 * section 8.4.8.3 178 * 179 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-15.html#jls-15.12.4.5 Java Language Specification, 180 * section 15.12.4.5 181 */ 182 public boolean bridge(final ExecutableElement e); 183 184 /** 185 * Applies <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.10"><dfn>capture 186 * conversion</dfn></a> to the supplied {@link TypeMirror}, which is normally a {@linkplain TypeKind#WILDCARD wildcard 187 * type}. 188 * 189 * @param wildcard a {@link TypeMirror}; must not be {@code null}; if not a {@linkplain TypeKind#WILDCARD wildcard 190 * type}, then it will be returned unchanged 191 * 192 * @return a non-{@code null} {@link TypeMirror} representing the result of <a 193 * href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.10">capture conversion</a> applied to 194 * the supplied {@link TypeMirror} 195 * 196 * @exception NullPointerException if {@code wildcard} is {@code null} 197 * 198 * @see javax.lang.model.util.Types#capture(TypeMirror) 199 * 200 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.10 Java Language Specification, section 201 * 5.1.10 202 */ 203 public TypeMirror capture(final TypeMirror wildcard); 204 205 /** 206 * Returns {@code true} if and only if {@code candidateContainer} <dfn>contains</dfn> {@code candidate}, according to 207 * the <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5.1">Java Language Specification, 208 * section 4.5.1</a>. 209 * 210 * @param candidateContainer the putative containing type; normally a {@linkplain TypeKind#WILDCARD wildcard type}; 211 * must not be {@code null} 212 * 213 * @param candidate the putative contained type; must not be {@code null} 214 * 215 * @return {@code true} if and only if {@code candidateContainer} <dfn>contains</dfn> {@code candidate}, according to 216 * the <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5.1">Java Language Specification, 217 * section 4.5.1</a>; {@code false} otherwise 218 * 219 * @exception NullPointerException if either argument is {@code null} 220 * 221 * @exception IllegalArgumentException if either argument is either an {@linkplain TypeKind#EXECUTABLE executable 222 * type}, a {@linkplain TypeKind#MODULE module type}, or a {@linkplain TypeKind#PACKAGE package type} 223 * 224 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5.1 Java Language Specification, section 225 * 4.5.1 226 */ 227 public boolean contains(final TypeMirror candidateContainer, final TypeMirror candidate); 228 229 /** 230 * A convenience method that returns the {@link DeclaredType} {@linkplain TypeElement#asType() of} a {@link 231 * TypeElement} that bears the supplied {@code canonicalName}, <strong>or {@code null} if there is no such {@link 232 * TypeElement} (and therefore no such {@link DeclaredType})</strong>. 233 * 234 * @param canonicalName a valid canonical name; must not be {@code null} 235 * 236 * @return a {@link DeclaredType} with a {@link TypeKind} of {@link TypeKind#DECLARED}, or {@code null} 237 * 238 * @see #typeElement(CharSequence) 239 * 240 * @see #declaredType(TypeElement, TypeMirror...) 241 * 242 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.7 Java Language Specification, section 243 * 6.7 244 */ 245 public default DeclaredType declaredType(final CharSequence canonicalName) { 246 final TypeElement e = this.typeElement(canonicalName); 247 return e == null ? null : this.declaredType(e); 248 } 249 250 /** 251 * Returns the {@link DeclaredType} {@linkplain TypeElement#asType() of} the supplied {@link TypeElement} with the 252 * supplied {@link TypeMirror} arguments (if any), yielding a parameterized type. 253 * 254 * <p>Given a {@link TypeElement} representing the class named {@link java.util.Set java.util.Set} and a {@link 255 * TypeMirror} representing the type declared by {@link String java.lang.String}, for example, this method will return 256 * a {@link DeclaredType} representing the parameterized type corresponding to {@link java.util.Set 257 * java.util.Set<java.lang.String>}.</p> 258 * 259 * <p>The number of supplied type arguments must either equal the number of the supplied {@link TypeElement}'s 260 * {@linkplain TypeElement#getTypeParameters() formal type parameters}, or must be zero. If it is zero, and if the 261 * supplied {@link TypeElement} {@link #generic(Element) is generic}, then the supplied {@link TypeElement}'s raw type 262 * is returned.</p> 263 * 264 * <p>If a parameterized type is returned, {@linkplain DeclaredType#asElement() its <code>TypeElement</code>} must not 265 * be contained within a {@linkplain #generic(Element) generic} outer class. The parameterized type {@code 266 * Outer<String>.Inner<Number>}, for example, may be constructed by first using this method to get the type {@code 267 * Outer<String>}, and then invoking {@link #declaredType(DeclaredType, TypeElement, TypeMirror...)}.</p> 268 * 269 * @param typeElement a {@link TypeElement}; must not be {@code null} 270 * 271 * @param typeArguments any type arguments (represented by {@link TypeMirror}s); must not be {@code null} 272 * 273 * @return a non-{@code null} {@link DeclaredType} with a {@link TypeKind} of {@link TypeKind#DECLARED} 274 * 275 * @exception NullPointerException if {@code typeElement} or {@code typeArguments} is {@code null} 276 * 277 * @see javax.lang.model.util.Types#getDeclaredType(TypeElement, TypeMirror...) 278 * 279 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5 Java Language Specification, section 4.5 280 */ 281 public DeclaredType declaredType(final TypeElement typeElement, 282 final TypeMirror... typeArguments); 283 284 /** 285 * Returns the {@link DeclaredType} {@linkplain TypeElement#asType() of} the supplied {@link TypeElement} with the 286 * supplied {@link TypeMirror} arguments (if any), given a containing {@link DeclaredType} of which it is a member, 287 * yielding a parameterized type. 288 * 289 * <p>Given a {@link DeclaredType} representing the parameterized type corresponding to {@code Outer<}{@link 290 * String}{@code >} (see the {@link #declaredType(TypeElement, TypeMirror...)} method), a {@link TypeElement} 291 * representing the class named {@code Outer.Inner} and a {@link DeclaredType} representing the non-generic class 292 * corresponding to {@link Number}, for example, this method will return a {@link DeclaredType} representing the 293 * parameterized type corresponding to {@code Outer<}{@link String}{@code >}{@code .Inner<}{@link Number}{@code >}.</p> 294 * 295 * <p>The number of supplied type arguments must either equal the number of the supplied {@link TypeElement}'s 296 * {@linkplain TypeElement#getTypeParameters() formal type parameters}, or must be zero. If it is zero, and if the 297 * supplied {@link TypeElement} {@link #generic(Element) is generic}, then the supplied {@link TypeElement}'s raw type 298 * is returned.</p> 299 * 300 * @param enclosingType a {@link DeclaredType} representing the containing type; must not be {@code null} 301 * 302 * @param typeElement a {@link TypeElement}; must not be {@code null} 303 * 304 * @param typeArguments any type arguments (represented by {@link TypeMirror}s); must not be {@code null} 305 * 306 * @return a non-{@code null} {@link DeclaredType} with a {@link TypeKind} of {@link TypeKind#DECLARED} 307 * 308 * @exception NullPointerException if {@code enclosingType}, {@code typeElement}, or {@code typeArguments} is {@code 309 * null} 310 * 311 * @see #declaredType(TypeElement, TypeMirror...) 312 * 313 * @see javax.lang.model.util.Types#getDeclaredType(DeclaredType, TypeElement, TypeMirror...) 314 * 315 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5 Java Language Specification, section 4.5 316 */ 317 public DeclaredType declaredType(final DeclaredType enclosingType, 318 final TypeElement typeElement, 319 final TypeMirror... typeArguments); 320 321 /** 322 * Returns a non-{@code null} {@link List} of the <dfn>direct supertypes</dfn> of the supplied {@link TypeMirror}, 323 * which is normally a {@linkplain TypeKind#DECLARED declared type}. 324 * 325 * @param t a {@link TypeMirror}; must not be {@code null}; must not be an {@linkplain TypeKind#EXECUTABLE executable 326 * type}, a {@linkplain TypeKind#MODULE module type}, or a {@linkplain TypeKind#PACKAGE package type} 327 * 328 * @return a non-{@code null}, immutable {@link List} of {@link TypeMirror}s representing the direct supertypes 329 * 330 * @exception NullPointerException if {@code t} is {@code null} 331 * 332 * @exception IllegalArgumentException if either argument is either an {@linkplain TypeKind#EXECUTABLE executable 333 * type}, a {@linkplain TypeKind#MODULE module type}, or a {@linkplain TypeKind#PACKAGE package type} 334 * 335 * @see javax.lang.model.util.Types#directSupertypes(TypeMirror) 336 * 337 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.10 Java Language Specification, section 338 * 4.10 339 */ 340 public List<? extends TypeMirror> directSupertypes(final TypeMirror t); 341 342 /** 343 * Returns the {@link Element} responsible for declaring the supplied {@link TypeMirror}, which is most commonly a 344 * {@link DeclaredType}, a {@link TypeVariable}, a {@link NoType} with a {@link TypeKind} of {@link TypeKind#MODULE}, 345 * or a {@link NoType} with a {@link TypeKind} of {@link TypeKind#PACKAGE}, <strong>or {@code null} if there is no 346 * such {@link Element}</strong>. 347 * 348 * @param t a {@link TypeMirror}; must not be {@code null} 349 * 350 * @return an {@link Element}, or {@code null} 351 * 352 * @exception NullPointerException if {@code t} is {@code null} 353 * 354 * @see javax.lang.model.util.Types#asElement(TypeMirror) 355 */ 356 public Element element(final TypeMirror t); 357 358 /** 359 * A convenience method that returns the <dfn>element type</dfn> of the supplied {@link TypeMirror}. 360 * 361 * <p>The element type of an {@linkplain TypeKind#ARRAY array type} is the element type of its {@linkplain 362 * ArrayType#getComponentType() component type}.</p>. 363 * 364 * <p>The element type of every other kind of type is the type itself. Note that the semantics of the prior sentence 365 * diverge deliberately, primarily for convenience, from those of the relevant section in the Java Language 366 * Specification.</p> 367 * 368 * @param t a {@link TypeMirror}; must not be {@code null} 369 * 370 * @return the <dfn>element type</dfn> of the supplied {@link TypeMirror}; never {@code null} 371 * 372 * @exception NullPointerException if {@code t} is {@code null} 373 * 374 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-10.html#jls-10.1 Java Language Specification, section 375 * 10.1 376 */ 377 public default TypeMirror elementType(final TypeMirror t) { 378 return switch (t) { 379 case null -> throw new NullPointerException("t"); 380 case UniversalType ut -> ut.elementType(); 381 default -> { 382 try (var lock = lock()) { 383 yield t.getKind() == TypeKind.ARRAY ? this.elementType(((ArrayType)t).getComponentType()) : t; 384 } 385 } 386 }; 387 } 388 389 /** 390 * Returns the <dfn>erasure</dfn> of the supplied {@link TypeMirror}. 391 * 392 * @param <T> a {@link TypeMirror} specialization 393 * 394 * @param t the {@link TypeMirror} representing the type whose erasure should be returned; must not be {@code null} 395 * 396 * @return the erasure of the supplied {@link TypeMirror}; never {@code null} 397 * 398 * @exception NullPointerException if {@code t} is {@code null} 399 * 400 * @exception IllegalArgumentException if {@code t} is a {@link NoType} with a {@link TypeKind} of {@link 401 * TypeKind#MODULE}, or a {@link NoType} with a {@link TypeKind} of {@link TypeKind#PACKAGE} 402 * 403 * @see javax.lang.model.util.Types#erasure(TypeMirror) 404 * 405 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.6 Java Language Specification, section 406 * 4.6 407 */ 408 public <T extends TypeMirror> T erasure(final T t); 409 410 /** 411 * A convenience method that returns an {@link ExecutableElement} representing the static initializer, constructor or 412 * method described by the supplied arguments, <strong>or {@code null} if no such {@link ExecutableElement} 413 * exists</strong>. 414 * 415 * @param declaringElement a {@link TypeElement} representing the class that declares the executable; must not be 416 * {@code null} 417 * 418 * @param returnType the {@linkplain ExecutableElement#getReturnType() return type} of the executable; must not be 419 * {@code null} 420 * 421 * @param name the {@linkplain ExecutableElement#getSimpleName() name} of the executable; must not be {@code null} 422 * 423 * @param parameterTypes {@link TypeMirror}s that represent the executable's {@linkplain 424 * ExecutableElement#getParameters() parameter types} 425 * 426 * @return an {@link ExecutableElement} with an {@link ElementKind} of {@link ElementKind#CONSTRUCTOR}, {@link 427 * ElementKind#METHOD}, or {@link ElementKind#STATIC_INIT}, or {@code null} 428 * 429 * @exception NullPointerException if any argument is {@code null} 430 */ 431 public default ExecutableElement executableElement(final TypeElement declaringElement, 432 final TypeMirror returnType, 433 final CharSequence name, 434 final TypeMirror... parameterTypes) { 435 return switch (declaringElement) { 436 case null -> throw new NullPointerException("declaringElement"); 437 case UniversalElement ue -> { 438 final List<? extends UniversalElement> ees = ue.getEnclosedElements(); 439 yield ees.stream() 440 .sequential() 441 .filter(e -> e.getKind().isExecutable() && e.getSimpleName().contentEquals(name)) 442 .map(UniversalElement.class::cast) 443 .filter(ee -> { 444 if (!this.sameType(returnType, ee.getReturnType())) { 445 return false; 446 } 447 final List<? extends UniversalElement> ps = ee.getParameters(); 448 if (ps.size() != parameterTypes.length) { 449 return false; 450 } 451 for (int i = 0; i < parameterTypes.length; i++) { 452 if (!this.sameType(ps.get(i).asType(), parameterTypes[i])) { 453 return false; 454 } 455 } 456 return true; 457 }) 458 .findFirst() 459 .orElse(null); 460 } 461 default -> { 462 try (var lock = this.lock()) { 463 final List<? extends Element> ees = declaringElement.getEnclosedElements(); 464 yield ees.stream() 465 .sequential() 466 .filter(e -> e.getKind().isExecutable() && e.getSimpleName().contentEquals(name)) 467 .map(ExecutableElement.class::cast) 468 .filter(ee -> { 469 if (!this.sameType(returnType, ee.getReturnType())) { 470 return false; 471 } 472 final List<? extends VariableElement> ps = ee.getParameters(); 473 if (ps.size() != parameterTypes.length) { 474 return false; 475 } 476 for (int i = 0; i < parameterTypes.length; i++) { 477 if (!this.sameType(ps.get(i).asType(), parameterTypes[i])) { 478 return false; 479 } 480 } 481 return true; 482 }) 483 .findFirst() 484 .orElse(null); 485 } 486 } 487 }; 488 } 489 490 /** 491 * A convenience method that returns {@code true} if and only if the supplied {@link Element} is <dfn>generic</dfn>. 492 * 493 * @param e an {@link Element}; must not be {@code null} 494 * 495 * @return {@code true} if and only if the supplied {@link Element} is <dfn>generic</dfn>; {@code false} otherwise 496 * 497 * @exception NullPointerException if {@code e} is {@code null} 498 * 499 * @see Parameterizable 500 * 501 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.1.2 Java Language Specification, section 502 * 8.1.2 503 * 504 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.4.4 Java Language Specification, section 505 * 8.4.4 506 * 507 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.8.4 Java Language Specification, section 508 * 8.8.4 509 * 510 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-9.html#jls-9.1.2 Java Language Specification, section 511 * 9.1.2 512 */ 513 public default boolean generic(final Element e) { 514 return switch (e) { 515 case null -> throw new NullPointerException("e"); 516 case UniversalElement ue -> ue.generic(); 517 case Parameterizable p -> { 518 try (var lock = this.lock()) { 519 yield switch (e.getKind()) { 520 case CLASS, CONSTRUCTOR, ENUM, INTERFACE, METHOD, RECORD -> !p.getTypeParameters().isEmpty(); 521 default -> false; 522 }; 523 } 524 } 525 default -> false; 526 }; 527 } 528 529 /** 530 * A convenience method that returns {@code true} if and only if the supplied {@link TypeMirror} is declared by an 531 * {@link Element} that {@linkplain #generic(Element) is generic}. 532 * 533 * @param t a {@link TypeMirror}; must not be {@code null} 534 * 535 * @return {@code true} if and only if the supplied {@link TypeMirror} is declared by an {@link Element} that 536 * {@linkplain #generic(Element) is generic} 537 * 538 * @exception NullPointerException if {@code t} is {@code null} 539 * 540 * @see #generic(Element) 541 * 542 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.1.2 Java Language Specification, section 543 * 8.1.2 544 * 545 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.4.4 Java Language Specification, section 546 * 8.4.4 547 * 548 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.8.4 Java Language Specification, section 549 * 8.8.4 550 * 551 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-9.html#jls-9.1.2 Java Language Specification, section 552 * 9.1.2 553 */ 554 public default boolean generic(final TypeMirror t) { 555 return switch (t) { 556 case null -> throw new NullPointerException("t"); 557 case UniversalType ut -> ut.generic(); 558 default -> { 559 try (var lock = this.lock()) { 560 final Element e = this.element(t); 561 yield e != null && this.generic(e); 562 } 563 } 564 }; 565 } 566 567 /** 568 * A convenience method that returns {@code true} if and only if the supplied {@link Element} represents the (essentially 569 * primordial) {@code java.lang.Object} {@link Element}. 570 * 571 * @param e an {@link Element}; must not be {@code null} 572 * 573 * @return {@code true} if and only if the supplied {@link Element} represents the (essentially 574 * primordial) {@code java.lang.Object} {@link Element}; {@code false} otherwise 575 * 576 * @exception NullPointerException if {@code e} is {@code null} 577 */ 578 public default boolean javaLangObject(final Element e) { 579 return switch (e) { 580 case null -> throw new NullPointerException("e"); 581 case UniversalElement ue -> ue.javaLangObject(); 582 default -> { 583 try (var lock = this.lock()) { 584 yield 585 e.getKind() == ElementKind.CLASS && 586 ((QualifiedNameable)e).getQualifiedName().contentEquals("java.lang.Object"); 587 } 588 } 589 }; 590 } 591 592 /** 593 * A convenience method that returns {@code true} if and only if the supplied {@link TypeMirror} represents the {@link 594 * DeclaredType} declared by the (essentially primordial) {@code java.lang.Object} element. 595 * 596 * @param t a {@link TypeMirror}; must not be {@code null} 597 * 598 * @return {@code true} represents the {@link 599 * DeclaredType} declared by the (essentially primordial) {@code java.lang.Object} element; {@code false} otherwise 600 * 601 * @exception NullPointerException if {@code t} is {@code null} 602 * 603 * @see #javaLangObject(Element) 604 */ 605 public default boolean javaLangObject(final TypeMirror t) { 606 return switch (t) { 607 case null -> throw new NullPointerException("t"); 608 case UniversalType ut -> ut.javaLangObject(); 609 default -> { 610 try (var lock = this.lock()) { 611 yield 612 t.getKind() == TypeKind.DECLARED && 613 javaLangObject(((DeclaredType)t).asElement()); 614 } 615 } 616 }; 617 } 618 619 /** 620 * A convenience method that returns the {@link TypeElement} representing the class named {@link Object 621 * java.lang.Object}. 622 * 623 * @return a non-{@code null} {@link TypeElement} whose {@linkplain TypeElement#getQualifiedName() qualified name} is 624 * {@linkplain Name#contentEquals(CharSequence) equal to} {@code java.lang.Object} 625 * 626 * @see #typeElement(CharSequence) 627 */ 628 public default TypeElement javaLangObject() { 629 return this.typeElement("java.lang.Object"); 630 } 631 632 /** 633 * Semantically locks an opaque lock used to serialize symbol completion, and returns it in the form of an {@link 634 * Unlockable}. 635 * 636 * <p>Implementations of this method must not return {@code null}.</p> 637 * 638 * @return an {@link Unlockable} in a semantically locked state; never {@code null} 639 * 640 * @see Unlockable#close() 641 */ 642 public Unlockable lock(); 643 644 /** 645 * Returns a {@link ModuleElement} representing the module {@linkplain ModuleElement#getQualifiedName() named} by the 646 * supplied {@code qualifiedName}, <strong>or {@code null} if there is no such {@link ModuleElement}</strong>. 647 * 648 * @param qualifiedName a name suitable for naming a module; must not be {@code null}; may be {@linkplain 649 * CharSequence#isEmpty() empty}, in which case a {@link ModuleElement} representing an <dfn>unnamed module</dfn> will 650 * be returned 651 * 652 * @return a {@link ModuleElement}, or {@code null} 653 * 654 * @exception NullPointerException if {@code qualifiedName} is {@code null} 655 * 656 * @see javax.lang.model.util.Elements#getModuleElement(CharSequence) 657 * 658 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-7.html#jls-7.7 Java Language Specification, section 659 * 7.7 660 */ 661 public ModuleElement moduleElement(final CharSequence qualifiedName); 662 663 /** 664 * Returns a {@link Name} representing the supplied {@link CharSequence}. 665 * 666 * @param name a {@link CharSequence}; must not be {@code null} 667 * 668 * @return a non-{@code null} {@link Name} representing the supplied {@link name} 669 * 670 * @exception NullPointerException if {@code name} is {@code null} 671 * 672 * @see #lock() 673 * 674 * @see javax.lang.model.util.Elements#getName(CharSequence) 675 */ 676 public Name name(final CharSequence name); 677 678 /** 679 * Returns a {@link NoType} {@linkplain TypeMirror#getKind() bearing} the supplied {@link TypeKind}, if the supplied 680 * {@link TypeKind} is either {@link TypeKind#NONE} or {@link TypeKind#VOID}. 681 * 682 * @param kind a {@link TypeKind}; must be either {@link TypeKind#NONE} or {@link TypeKind#VOID} 683 * 684 * @return a non-{@code null} {@link NoType} {@linkplain TypeMirror#getKind() bearing} the supplied {@link TypeKind} 685 * 686 * @exception NullPointerException if {@code kind} is {@code null} 687 * 688 * @exception IllegalArgumentException if {@code kind} is non-{@code null} and neither {@link TypeKind#NONE} nor 689 * {@link TypeKind#VOID} 690 * 691 * @see TypeKind#NONE 692 * 693 * @see TypeKind#VOID 694 * 695 * @see javax.lang.model.util.Types#getNoType(TypeKind) 696 * 697 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.4.5 Java Language Specification, section 698 * 8.4.5 699 */ 700 public NoType noType(final TypeKind kind); 701 702 /** 703 * Returns a {@link NullType} implementation {@linkplain TypeMirror#getKind() whose <code>TypeKind</code>} is {@link 704 * TypeKind#NULL}. 705 * 706 * @return a non-{@code null} {@link NullType} 707 * 708 * @see javax.lang.model.util.Types#getNullType() 709 * 710 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.1 Java Language Specification, section 4.1 711 */ 712 public NullType nullType(); 713 714 /** 715 * Returns the {@linkplain Origin origin} of the supplied {@link Element}. 716 * 717 * @param e a non-{@code null} {@link Element} 718 * 719 * @return a non-{@code null} {@link Origin} 720 * 721 * @see Elements#getOrigin(Element) 722 */ 723 public Origin origin(final Element e); 724 725 /** 726 * Returns a {@link PackageElement} representing the package bearing the supplied {@code canonicalName}, <strong>or 727 * {@code null} if there is no such {@link PackageElement}</strong>. 728 * 729 * @param canonicalName a canonical name suitable for naming a package; must not be {@code null}; may be {@linkplain 730 * CharSequence#isEmpty() empty}, in which case a {@link ModuleElement} representing an <dfn>unnamed package</dfn> will 731 * be returned 732 * 733 * @return a {@link PackageElement}, or {@code null} 734 * 735 * @exception NullPointerException if {@code canonicalName} is {@code null} 736 * 737 * @see javax.lang.model.util.Elements#getPackageElement(CharSequence) 738 * 739 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.7 Java Language Specification, section 740 * 6.7 741 */ 742 public PackageElement packageElement(final CharSequence canonicalName); 743 744 /** 745 * Returns a {@link PackageElement} representing the package bearing the supplied {@code canonicalName} as seen from 746 * the module represented by the supplied {@link ModuleElement}, <strong>or {@code null} if there is no such {@link 747 * PackageElement}</strong>. 748 * 749 * @param asSeenFrom a {@link ModuleElement}; must not be {@code null} 750 * 751 * @param canonicalName a canonical name suitable for naming a package; must not be {@code null}; may be {@linkplain 752 * CharSequence#isEmpty() empty}, in which case a {@link ModuleElement} representing an <dfn>unnamed package</dfn> will 753 * be returned 754 * 755 * @return a {@link PackageElement}, or {@code null} 756 * 757 * @exception NullPointerException if either {@code asSeenFrom} or {@code canonicalName} is {@code null} 758 * 759 * @see javax.lang.model.util.Elements#getPackageElement(ModuleElement, CharSequence) 760 * 761 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.7 Java Language Specification, section 762 * 6.7 763 */ 764 public PackageElement packageElement(final ModuleElement asSeenFrom, final CharSequence canonicalName); 765 766 /** 767 * A convenience method that returns {@code true} if and only if {@code t} is a {@link DeclaredType}, {@linkplain 768 * TypeMirror#getKind() has a <code>TypeKind</code>} of {@link TypeKind#DECLARED DECLARED}, and {@linkplain 769 * DeclaredType#getTypeArguments() has an empty type arguments list}. 770 * 771 * @param t a {@link TypeMirror}; must not be {@code null} 772 * 773 * @return {@code true} if and only if {@code t} is a {@link DeclaredType}, {@linkplain 774 * TypeMirror#getKind() has a <code>TypeKind</code>} of {@link TypeKind#DECLARED DECLARED}, and {@linkplain 775 * DeclaredType#getTypeArguments() has an empty type arguments list}; {@code false} otherwise 776 * 777 * @exception NullPointerException if {@code t} is {@code null} 778 */ 779 public default boolean parameterized(final TypeMirror t) { 780 return switch (t) { 781 case null -> throw new NullPointerException("t"); 782 case UniversalType ut -> ut.parameterized(); 783 default -> { 784 try (var lock = this.lock()) { 785 yield t.getKind() == TypeKind.DECLARED && !((DeclaredType)t).getTypeArguments().isEmpty(); 786 } 787 } 788 }; 789 } 790 791 /** 792 * Returns the result of applying <dfn>unboxing conversion</dfn> to the (logical) {@link TypeElement} bearing the 793 * supplied {@code canonicalName}. 794 * 795 * @param canonicalName a canonical name of either a primitive type or a so-called "wrapper" type; must not be {@code 796 * null} 797 * 798 * @return a non-{@code null} {@link PrimitiveType} with a {@linkplain TypeKind#isPrimitive() primitive} {@link 799 * TypeKind} 800 * 801 * @exception NullPointerException if {@code canonicalName} is {@code null} 802 * 803 * @exception IllegalArgumentException if {@code canonicalName} {@linkplain #toString(CharSequence) converted to a 804 * <code>String</code>} {@linkplain String#equals(Object) is not equal to} {@code boolean}, {@code byte}, {@code 805 * char}, {@code double}, {@code float}, {@code int}, {@code long}, {@code short}, {@link Boolean java.lang.Boolean}, 806 * {@link Byte java.lang.Byte}, {@link Character java.lang.Character}, {@link Double java.lang.Double}, {@link Float 807 * java.lang.Float}, {@link Integer java.lang.Integer}, {@link Long java.lang.Long}, or {@link Short java.lang.Short} 808 * 809 * @see #primitiveType(TypeKind) 810 * 811 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.8 Java Language Specification, section 812 * 5.1.8 813 * 814 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.7 Java Language Specification, section 815 * 6.7 816 */ 817 // (Convenience.) 818 // (Unboxing.) 819 public default PrimitiveType primitiveType(final CharSequence canonicalName) { 820 final String s = this.toString(Objects.requireNonNull(canonicalName, "canonicalName")); 821 return switch (s) { 822 case "boolean", "java.lang.Boolean" -> this.primitiveType(TypeKind.BOOLEAN); 823 case "byte", "java.lang.Byte" -> this.primitiveType(TypeKind.BYTE); 824 case "char", "java.lang.Character" -> this.primitiveType(TypeKind.CHAR); 825 case "double", "java.lang.Double" -> this.primitiveType(TypeKind.DOUBLE); 826 case "float", "java.lang.Float" -> this.primitiveType(TypeKind.FLOAT); 827 case "int", "java.lang.Integer" -> this.primitiveType(TypeKind.INT); 828 case "long", "java.lang.Long" -> this.primitiveType(TypeKind.LONG); 829 case "short", "java.lang.Short" -> this.primitiveType(TypeKind.SHORT); 830 default -> throw new IllegalArgumentException("canonicalName: " + s); 831 }; 832 } 833 834 /** 835 * Returns the result of applying <dfn>unboxing conversion</dfn> to the {@linkplain Element#asType() type declared by 836 * the supplied <code>TypeElement</code>}. 837 * 838 * @param e a {@link TypeElement}; must not be {@code null} 839 * 840 * @return a non-{@code null} {@link PrimitiveType} with a {@linkplain TypeKind#isPrimitive() primitive} {@link 841 * TypeKind} 842 * 843 * @exception NullPointerException if {@code e} is {@code null} 844 * 845 * @exception IllegalArgumentException if there is no unboxing conversion that can be applied to the {@linkplain 846 * Element#asType() type declared by <code>e</code>} 847 * 848 * @see javax.lang.model.util.Types#unboxedType(TypeMirror) 849 * 850 * @see #primitiveType(TypeMirror) 851 * 852 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.8 Java Language Specification, section 853 * 5.1.8 854 */ 855 // (Convenience.) 856 // (Unboxing.) 857 public default PrimitiveType primitiveType(final TypeElement e) { 858 return this.primitiveType(e.asType()); 859 } 860 861 /** 862 * Returns the {@link PrimitiveType} corresponding to the supplied {@link TypeKind} (if it {@linkplain 863 * TypeKind#isPrimitive() is primitive}). 864 * 865 * @param kind a {@linkplain TypeKind#isPrimitive() primitive} {@link TypeKind}; must not be {@code null} 866 * 867 * @return a non-{@code null} {@link PrimitiveType} {@linkplain TypeMirror#getKind() with} a {@linkplain 868 * TypeKind#isPrimitive() primitive} {@link TypeKind} 869 * 870 * @exception NullPointerException if {@code kind} is {@code null} 871 * 872 * @exception IllegalArgumentException if {@code kind} {@linkplain TypeKind#isPrimitive() is not primitive} 873 * 874 * @see javax.lang.model.util.Types#getPrimitiveType(TypeKind) 875 * 876 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.2 Java Language Specification, section 877 * 4.2 878 */ 879 // (Canonical.) 880 public PrimitiveType primitiveType(final TypeKind kind); 881 882 /** 883 * Returns the result of applying <dfn>unboxing conversion</dfn> to the supplied {@link TypeMirror}. 884 * 885 * @param t a {@link TypeMirror}; must not be {@code null} 886 * 887 * @return a non-{@code null} {@link PrimitiveType} with a {@linkplain TypeKind#isPrimitive() primitive} {@link 888 * TypeKind} 889 * 890 * @exception NullPointerException if {@code t} is {@code null} 891 * 892 * @exception IllegalArgumentException if there is no unboxing conversion that can be applied to {@code t} 893 * 894 * @see javax.lang.model.util.Types#unboxedType(TypeMirror) 895 * 896 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.8 Java Language Specification, section 897 * 5.1.8 898 */ 899 // (Canonical.) 900 // (Unboxing.) 901 public PrimitiveType primitiveType(final TypeMirror t); 902 903 /** 904 * A convenience method that returns {@code true} if and only if the supplied {@link TypeMirror} is a <dfn>raw 905 * type</dfn> according to <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8">the rules 906 * of the Java Language Specification</a> 907 * 908 * @param t a {@link TypeMirror}; must not be {@code null} 909 * 910 * @return {@code true} if and only if the supplied {@link TypeMirror} is a <dfn>raw type</dfn> according to <a 911 * href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8">the rules of the Java Language 912 * Specification</a> 913 * 914 * @exception NullPointerException if {@code t} is {@code null} 915 * 916 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8 Java Language Specification, section 4.8 917 */ 918 public default boolean raw(final TypeMirror t) { 919 return switch (t) { 920 case null -> throw new NullPointerException("t"); 921 case UniversalType ut -> ut.raw(); 922 default -> { 923 try (var lock = this.lock()) { 924 yield switch (t.getKind()) { 925 case ARRAY -> raw(elementType((ArrayType)t)); 926 case DECLARED -> { 927 final DeclaredType dt = (DeclaredType)t; 928 yield generic(dt.asElement()) && dt.getTypeArguments().isEmpty(); 929 } 930 default -> false; 931 }; 932 } 933 } 934 }; 935 } 936 937 /** 938 * A convenience method that returns the <dfn>raw type</dfn> corresponding to {@code t}, <strong>or {@code null} if 939 * {@code t} is <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8">incapable of yielding 940 * a raw type</a></strong>. 941 * 942 * <p>Overrides of this method must conform to the requirements imposed by the relevant section of the relevant 943 * version of the Java Language Specification concerning raw types.</p> 944 * 945 * @param t a {@link TypeMirror}; must not be {@code null} 946 * 947 * @return the raw type corresponding to the supplied {@link TypeMirror}, or {@code null} if {@code t} is <a 948 * href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8">incapable of yielding a raw type</a> 949 * 950 * @exception NullPointerException if {@code t} is {@code null} 951 * 952 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8 Java Language Specification, section 953 * 4.8 954 */ 955 public default TypeMirror rawType(final TypeMirror t) { 956 return switch (t) { 957 case null -> throw new NullPointerException("t"); 958 case UniversalType ut -> ut.rawType(); 959 default -> { 960 try (var lock = this.lock()) { 961 yield switch (t.getKind()) { 962 case ARRAY -> this.rawType(this.elementType(t)); // recursive 963 default -> this.parameterized(t) ? this.erasure(t) : null; 964 }; 965 } 966 } 967 }; 968 } 969 970 /** 971 * Returns a {@link RecordComponentElement} corresponding to the supplied {@link ExecutableElement}, <strong>or {@code 972 * null} if there is no such {@link RecordComponentElement}</strong>. 973 * 974 * @param e an {@link ExecutableElement} {@linkplain ExecutableElement#getEnclosingElement() enclosed by} a record 975 * representing an <dfn>accessor method</dfn>; must not be {@code null} 976 * 977 * @return a {@link RecordComponentElement} corresponding to the supplied {@link ExecutableElement}, or {@code null} 978 * 979 * @exception NullPointerException if {@code e} is {@code null} 980 * 981 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.10.3 Java Language Specification, section 982 * 8.10.3 983 */ 984 public RecordComponentElement recordComponentElement(final ExecutableElement e); 985 986 /** 987 * Returns {@code true} if and only if the two arguments represent the <dfn>same type</dfn>. 988 * 989 * <p>This method differs from the {@link javax.lang.model.util.Types#isSameType(TypeMirror, TypeMirror)} method in 990 * two ways:</p> 991 * 992 * <ul> 993 * 994 * <li>Its arguments may be {@code null}. If both arguments are {@code null}, {@code true} is returned. If only one 995 * argument is {@code null}, {@code false} is returned.</li> 996 * 997 * <li>If the same Java object reference is passed as both arguments, {@code true} is returned (even if it {@linkplain 998 * TypeMirror#getKind() has a <code>TypeKind</code>} of {@link TypeKind#WILDCARD}).</li> 999 * 1000 * </ul> 1001 * 1002 * @param t0 the first {@link TypeMirror}; may be {@code null} 1003 * 1004 * @param t1 the second {@link TypeMirror}; may be {@code null} 1005 * 1006 * @return {@code true} if and only if the two arguments represent the <dfn>same type</dfn>; {@code false} otherwise 1007 * 1008 * @see javax.lang.model.util.Types#isSameType(TypeMirror, TypeMirror) 1009 * 1010 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.3.4 Java Language Specification, section 1011 * 4.3.4 1012 * 1013 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5.1 Java Language Specification, section 1014 * 4.5.1 1015 */ 1016 public boolean sameType(final TypeMirror t0, final TypeMirror t1); 1017 1018 /** 1019 * Returns {@code true} if and only if {@code et0} is a <dfn>subsignature</dfn> of {@code et1}. 1020 * 1021 * @param et0 the first {@link ExecutableType}; must not be {@code null} 1022 * 1023 * @param et1 the second {@link ExecutableType}; must not be {@code null} 1024 * 1025 * @return {@code true} if and only if {@code et0} is a <dfn>subsignature</dfn> of {@code et1} 1026 * 1027 * @exception NullPointerException if either argument is {@code null} 1028 * 1029 * @exception ClassCastException if this method is implemented in terms of the {@link 1030 * javax.lang.model.util.Types#isSubsignature(ExecutableType, ExecutableType)} method, and if each of the supplied 1031 * {@link ExecutableType} arguments does not have an {@linkplain TypeKind#EXECUTABLE <code>EXECUTABLE</code> 1032 * <code>TypeKind</code>}; this exception type is undocumented by the {@link 1033 * javax.lang.model.util.Types#isSubsignature(ExecutableType, ExecutableType)} method and so is subject to change 1034 * without prior notice 1035 * 1036 * @see javax.lang.model.util.Types#isSubsignature(ExecutableType, ExecutableType) 1037 * 1038 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html#jls-8.4.2 Java Language Specification, section 1039 * 8.4.2 1040 */ 1041 public boolean subsignature(final ExecutableType et0, final ExecutableType et1); 1042 1043 /** 1044 * Returns {@code true} if and only if {@code candidateSubtype} is a <dfn>subtype</dfn> of {@code supertype}. 1045 * 1046 * @param candidateSubtype the first {@link TypeMirror}; must not be {@code null} 1047 * 1048 * @param supertype the second {@link TypeMirror}; must not be {@code null} 1049 * 1050 * @return {@code true} if and only if {@code candidateSubtype} is a <dfn>subtype</dfn> of {@code supertype} 1051 * 1052 * @exception NullPointerException if either argument is {@code null} 1053 * 1054 * @see javax.lang.model.util.Types#isSubtype(TypeMirror, TypeMirror) 1055 * 1056 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.10 Java Language Specification, section 1057 * 4.10 1058 */ 1059 public boolean subtype(TypeMirror candidateSubtype, TypeMirror supertype); 1060 1061 /** 1062 * Converts the supplied {@link CharSequence}, which is often a {@link Name}, into a {@link String}, and returns the 1063 * conversion, {@linkplain #lock() locking} when appropriate to serialize symbol completion. 1064 * 1065 * @param name the {@link CharSequence} to convert; may be {@code null} in which case {@code null} will be returned 1066 * 1067 * @return a {@link String}, or {@code null} if {@code name} was {@code null} 1068 * 1069 * @see #lock() 1070 */ 1071 public default String toString(final CharSequence name) { 1072 return switch (name) { 1073 case null -> null; 1074 case String s -> s; 1075 case StringName sn -> sn.value(); 1076 case Name n -> { 1077 try (var lock = this.lock()) { 1078 yield n.toString(); 1079 } 1080 } 1081 default -> name.toString(); 1082 }; 1083 } 1084 1085 /** 1086 * Returns a {@link TypeElement} representing the element bearing the supplied <dfn>canonical name</dfn>, <strong>or 1087 * {@code null} if there is no such {@link TypeElement}</strong>. 1088 * 1089 * @param canonicalName a valid canonical name; must not be {@code null} 1090 * 1091 * @return a {@link TypeElement}, or {@code null} 1092 * 1093 * @exception NullPointerException if {@code canonicalName} is {@code null} 1094 * 1095 * @see javax.lang.model.util.Elements#getTypeElement(CharSequence) 1096 * 1097 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.7 Java Language Specification, section 1098 * 6.7 1099 */ 1100 public TypeElement typeElement(final CharSequence canonicalName); 1101 1102 /** 1103 * Returns a {@link TypeElement} representing the element bearing the supplied <dfn>canonical name</dfn>, as read or 1104 * seen from the module represented by the supplied {@link ModuleElement}, <strong>or {@code null} if there is no such 1105 * {@link TypeElement}</strong>. 1106 * 1107 * @param asSeenFrom a {@link ModuleElement}; must not be {@code null} 1108 * 1109 * @param canonicalName a valid canonical name; must not be {@code null} 1110 * 1111 * @return a {@link TypeElement}, or {@code null} 1112 * 1113 * @exception NullPointerException if either {@code asSeenFrom} or {@code canonicalName} is {@code null} 1114 * 1115 * @see javax.lang.model.util.Elements#getTypeElement(ModuleElement, CharSequence) 1116 * 1117 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.7 Java Language Specification, section 1118 * 6.7 1119 */ 1120 public TypeElement typeElement(final ModuleElement asSeenFrom, final CharSequence canonicalName); 1121 1122 /** 1123 * Returns a {@link TypeElement} representing the result of applying <dfn>boxing conversion</dfn> to the primitive 1124 * type represented by the supplied {@link PrimitiveType} argument. 1125 * 1126 * <p>The default implementation of this method calls the {@link #typeElement(TypeKind)} method with the supplied 1127 * {@link PrimitiveType}'s {@linkplain TypeMirror#getKind() affiliated <code>TypeKind</code>} and returns its 1128 * result.</p> 1129 * 1130 * @param t a {@link PrimitiveType} with a {@link TypeKind} that {@linkplain TypeKind#isPrimitive() is primitive}; 1131 * must not be {@code null} 1132 * 1133 * @return a non-{@code null} {@link TypeElement} representing the result of applying boxing conversion to the 1134 * supplied argument 1135 * 1136 * @exception NullPointerException if {@code t} is {@code null} 1137 * 1138 * @exception ClassCastException if this method is implemented in terms of the {@link 1139 * javax.lang.model.util.Types#boxedClass(PrimitiveType)} method, and if the supplied {@link PrimitiveType} does not 1140 * have a {@linkplain TypeKind#isPrimitive() primitive <code>TypeKind</code>}; this exception type is undocumented by 1141 * the {@link javax.lang.model.util.Types#boxedClass(PrimitiveType)} method and so is subject to change without prior 1142 * notice 1143 * 1144 * @exception IllegalArgumentException if {@code primitiveTypeKind} {@linkplain TypeKind#isPrimitive() is not 1145 * primitive} 1146 * 1147 * @see #typeElement(TypeKind) 1148 * 1149 * @see javax.lang.model.util.Types#boxedClass(PrimitiveType) 1150 * 1151 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.7 Java Language Specification, section 1152 * 5.1.7 1153 */ 1154 // (Canonical.) 1155 // (Boxing.) 1156 public default TypeElement typeElement(final PrimitiveType t) { 1157 return switch (t) { 1158 case null -> throw new NullPointerException("t"); 1159 case UniversalType ut -> this.typeElement(ut.getKind()); 1160 default -> { 1161 try (var lock = this.lock()) { 1162 yield this.typeElement(t.getKind()); 1163 } 1164 } 1165 }; 1166 } 1167 1168 /** 1169 * Returns a {@link TypeElement} representing the result of applying <dfn>boxing conversion</dfn> to the primitive 1170 * type represented by the supplied {@link TypeKind} argument, if it {@linkplain TypeKind#isPrimitive() is primitive}. 1171 * 1172 * @param primitiveTypeKind a {@link TypeKind} that {@linkplain TypeKind#isPrimitive() is primitive}; must not be 1173 * {@code null} 1174 * 1175 * @return a non-{@code null} {@link TypeElement} representing the result of applying boxing conversion to the 1176 * supplied argument 1177 * 1178 * @exception IllegalArgumentException if {@code primitiveTypeKind} {@linkplain TypeKind#isPrimitive() is not 1179 * primitive} 1180 * 1181 * @see #typeElement(PrimitiveType) 1182 * 1183 * @see javax.lang.model.util.Types#boxedClass(PrimitiveType) 1184 * 1185 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html#jls-5.1.7 Java Language Specification, section 1186 * 5.1.7 1187 */ 1188 // (Convenience.) 1189 // (Boxing.) 1190 public default TypeElement typeElement(final TypeKind primitiveTypeKind) { 1191 return switch (primitiveTypeKind) { 1192 case BOOLEAN -> this.typeElement("java.lang.Boolean"); 1193 case BYTE -> this.typeElement("java.lang.Byte"); 1194 case CHAR -> this.typeElement("java.lang.Character"); 1195 case DOUBLE -> this.typeElement("java.lang.Double"); 1196 case FLOAT -> this.typeElement("java.lang.Float"); 1197 case INT -> this.typeElement("java.lang.Integer"); 1198 case LONG -> this.typeElement("java.lang.Long"); 1199 case SHORT -> this.typeElement("java.lang.Short"); 1200 default -> throw new IllegalArgumentException("primitiveTypeKind: " + primitiveTypeKind); 1201 }; 1202 } 1203 1204 /** 1205 * Returns the {@link TypeParameterElement} {@linkplain Parameterizable#getTypeParameters() contained} by the supplied 1206 * {@link Parameterizable} whose {@linkplain TypeParameterElement#getSimpleName() name} {@linkplain 1207 * Name#contentEquals(CharSequence) is equal to} the supplied {@code name}, <strong>or {@code null} if there is no 1208 * such {@link TypeParameterElement}</strong>. 1209 * 1210 * @param p a {@link Parameterizable}; must not be {@code null} 1211 * 1212 * @param name a name valid for a type parameter; must not be {@code null} 1213 * 1214 * @return a {@link TypeParameterElement}, or {@code null} 1215 */ 1216 public default TypeParameterElement typeParameterElement(Parameterizable p, final CharSequence name) { 1217 Objects.requireNonNull(p, "p"); 1218 Objects.requireNonNull(name, "name"); 1219 while (p != null) { 1220 switch (p) { 1221 case UniversalElement ue: 1222 for (final UniversalElement tpe : ue.getTypeParameters()) { 1223 if (tpe.getSimpleName().contentEquals(name)) { 1224 return tpe; 1225 } 1226 } 1227 p = ue.getEnclosingElement(); 1228 break; 1229 default: 1230 try (var lock = this.lock()) { 1231 for (final TypeParameterElement tpe : p.getTypeParameters()) { 1232 if (tpe.getSimpleName().contentEquals(name)) { 1233 return tpe; 1234 } 1235 } 1236 p = (Parameterizable)((Element)p).getEnclosingElement(); 1237 } 1238 break; 1239 } 1240 } 1241 return null; 1242 } 1243 1244 /** 1245 * A convenience method that returns the {@link TypeVariable} {@linkplain TypeParameterElement#asType() declared by} 1246 * the {@link TypeParameterElement} {@linkplain Parameterizable#getTypeParameters() contained} by the supplied {@link 1247 * Parameterizable} whose {@linkplain TypeParameterElement#getSimpleName() name} {@linkplain 1248 * Name#contentEquals(CharSequence) is equal to} the supplied {@code name}, <strong>or {@code null} if there is no 1249 * such {@link TypeParameterElement} or {@link TypeVariable}</strong>. 1250 * 1251 * @param p a {@link Parameterizable}; must not be {@code null} 1252 * 1253 * @param name a name valid for a type parameter; must not be {@code null} 1254 * 1255 * @return a {@link TypeVariable}, or {@code null} 1256 * 1257 * @see #typeParameterElement(Parameterizable, CharSequence) 1258 */ 1259 public default TypeVariable typeVariable(Parameterizable p, final CharSequence name) { 1260 final TypeParameterElement e = this.typeParameterElement(p, name); 1261 return e == null ? null : (TypeVariable)e.asType(); 1262 } 1263 1264 /** 1265 * A convenience method that returns the first {@link VariableElement} with a {@linkplain ElementKind#isVariable() 1266 * variable <code>ElementKind</code>} and {@linkplain Element#getSimpleName() bearing} the supplied {@code simpleName} 1267 * that the supplied {@code enclosingElement} {@linkplain Element#getEnclosedElements() encloses}, <strong>or {@code 1268 * null} if there is no such {@link VariableElement}</strong>. 1269 * 1270 * @param enclosingElement an {@link Element}; must not be {@code null} 1271 * 1272 * @param simpleName a {@link CharSequence}; must not be {@code null} 1273 * 1274 * @return a {@link VariableElement}, or {@code null} 1275 * 1276 * @exception NullPointerException if either argument is {@code null} 1277 * 1278 * @see Element#getEnclosedElements() 1279 * 1280 * @see ElementKind#isVariable() 1281 * 1282 * @see Element#getSimpleName() 1283 * 1284 * @see VariableElement 1285 */ 1286 public default VariableElement variableElement(final Element enclosingElement, final CharSequence simpleName) { 1287 Objects.requireNonNull(simpleName, "simpleName"); 1288 return switch (enclosingElement) { 1289 case null -> throw new NullPointerException("enclosingElement"); 1290 case UniversalElement ue -> { 1291 for (final UniversalElement ee : ue.getEnclosedElements()) { 1292 if (ee.getKind().isVariable() && ee.getSimpleName().contentEquals(simpleName)) { 1293 yield ee; 1294 } 1295 } 1296 yield null; 1297 } 1298 default -> { 1299 try (var lock = lock()) { 1300 for (final Element ee : enclosingElement.getEnclosedElements()) { 1301 if (ee.getKind().isVariable() && ee.getSimpleName().contentEquals(simpleName)) { 1302 yield (VariableElement)ee; 1303 } 1304 } 1305 } 1306 yield null; 1307 } 1308 }; 1309 } 1310 1311 /** 1312 * A convenience method that returns a new {@link WildcardType} {@linkplain TypeMirror#getKind() with a 1313 * <code>TypeKind</code>} of {@link TypeKind#WILDCARD}, an {@linkplain WildcardType#getExtendsBound() extends bound} 1314 * of {@code null}, and a {@linkplain WildcardType#getSuperBound() super bound} of {@code null}. 1315 * 1316 * @return a new, non-{@code null} {@link WildcardType} 1317 * 1318 * @see #wildcardType(TypeMirror, TypeMirror) 1319 * 1320 * @see javax.lang.model.util.Types#getWildcardType(TypeMirror, TypeMirror) 1321 * 1322 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5.1 Java Language Specification, section 1323 * 4.5.1 1324 */ 1325 public default WildcardType wildcardType() { 1326 return this.wildcardType(null, null); 1327 } 1328 1329 /** 1330 * Returns a new {@link WildcardType} {@linkplain TypeMirror#getKind() with a <code>TypeKind</code>} of {@link 1331 * TypeKind#WILDCARD}, an {@linkplain WildcardType#getExtendsBound() extends bound} of the supplied {@code 1332 * extendsBound}, and a {@linkplain WildcardType#getSuperBound() super bound} of the supplied {@code superBound}. 1333 * 1334 * <p>Any argument may be {@code null}. Both arguments may not be non-{@code null}.</p> 1335 * 1336 * @param extendsBound the upper bound of the new {@link WildcardType}; may be {@code null} 1337 * 1338 * @param superBound the lower bound of the new {@link WildcardType}; may be {@code null} 1339 * 1340 * @return a new, non-{@code null} {@link WildcardType} 1341 * 1342 * @exception IllegalArgumentException if both arguments are non-{@code null} or otherwise unsuitable for being the 1343 * bounds of a {@link WildcardType} 1344 * 1345 * @see javax.lang.model.util.Types#getWildcardType(TypeMirror, TypeMirror) 1346 * 1347 * @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.5.1 Java Language Specification, section 1348 * 4.5.1 1349 */ 1350 public WildcardType wildcardType(TypeMirror extendsBound, TypeMirror superBound); 1351 1352}