diff --git a/README.md b/README.md
index 34a5678..bd639f9 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ dependency:
Always check https://search.maven.org/artifact/org.microbean/microbean-construct
for up-to-date available versions.
-->
- 0.0.23
+ 0.0.24
```
diff --git a/src/main/java/org/microbean/construct/DefaultDomain.java b/src/main/java/org/microbean/construct/DefaultDomain.java
index 8e68663..f316995 100644
--- a/src/main/java/org/microbean/construct/DefaultDomain.java
+++ b/src/main/java/org/microbean/construct/DefaultDomain.java
@@ -13,11 +13,8 @@
*/
package org.microbean.construct;
-import java.lang.constant.ClassDesc;
import java.lang.constant.Constable;
-import java.lang.constant.ConstantDesc;
import java.lang.constant.DynamicConstantDesc;
-import java.lang.constant.MethodHandleDesc;
import java.util.List;
import java.util.Objects;
@@ -54,6 +51,8 @@
import static java.lang.constant.ConstantDescs.BSM_INVOKE;
+import static java.lang.constant.MethodHandleDesc.ofConstructor;
+
/**
* A {@linkplain Domain domain of valid Java constructs} that can be used at annotation processing time or at runtime.
*
@@ -268,10 +267,12 @@ public UniversalType declaredType(DeclaredType enclosingType,
}
@Override // Constable
- public Optional extends ConstantDesc> describeConstable() {
+ public Optional> describeConstable() {
return
- Optional.of(DynamicConstantDesc.of(BSM_INVOKE,
- MethodHandleDesc.ofConstructor(ClassDesc.of(this.getClass().getName()))));
+ Optional.of(DynamicConstantDesc.ofNamed(BSM_INVOKE,
+ this.getClass().getSimpleName(),
+ this.getClass().describeConstable().orElseThrow(),
+ ofConstructor(this.getClass().describeConstable().orElseThrow())));
}
@Override // Domain
diff --git a/src/main/java/org/microbean/construct/UniversalConstruct.java b/src/main/java/org/microbean/construct/UniversalConstruct.java
index 28aba4e..ea13c9d 100644
--- a/src/main/java/org/microbean/construct/UniversalConstruct.java
+++ b/src/main/java/org/microbean/construct/UniversalConstruct.java
@@ -218,21 +218,23 @@ public final T delegate() {
}
@Override // Constable
- public final Optional extends ConstantDesc> describeConstable() {
+ public final Optional> describeConstable() {
final PrimordialDomain primordialDomain = this.domain();
if (domain instanceof Domain d && d instanceof Constable dc) {
final T delegate = this.delegate();
final List annotations = this.annotations; // volatile read; may be null and that's OK
return Constables.describe(delegate, d)
.flatMap(delegateDesc -> Constables.describe(annotations)
- .map(annosDesc -> DynamicConstantDesc.of(BSM_INVOKE,
- ofConstructor(ClassDesc.of(this.getClass().getName()),
- CD_List,
- ClassDesc.of(delegate instanceof TypeMirror ? TypeMirror.class.getName() : Element.class.getName()),
- ClassDesc.of(PrimordialDomain.class.getName())),
- annosDesc,
- delegateDesc,
- dc.describeConstable().orElseThrow())));
+ .map(annosDesc -> DynamicConstantDesc.ofNamed(BSM_INVOKE,
+ this.getClass().getSimpleName(),
+ this.getClass().describeConstable().orElseThrow(),
+ ofConstructor(this.getClass().describeConstable().orElseThrow(),
+ CD_List,
+ (delegate instanceof TypeMirror ? TypeMirror.class : Element.class).describeConstable().orElseThrow(),
+ PrimordialDomain.class.describeConstable().orElseThrow()),
+ annosDesc,
+ delegateDesc,
+ dc.describeConstable().orElseThrow())));
}
return Optional.empty();
}
diff --git a/src/main/java/org/microbean/construct/constant/Constables.java b/src/main/java/org/microbean/construct/constant/Constables.java
index bcb36eb..e33fb65 100644
--- a/src/main/java/org/microbean/construct/constant/Constables.java
+++ b/src/main/java/org/microbean/construct/constant/Constables.java
@@ -1,6 +1,6 @@
/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
*
- * Copyright © 2024 microBean™.
+ * Copyright © 2024–2026 microBean™.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
@@ -81,6 +81,7 @@
import static org.microbean.construct.constant.ConstantDescs.CD_TypeParameterElement;
import static org.microbean.construct.constant.ConstantDescs.CD_TypeMirror;
import static org.microbean.construct.constant.ConstantDescs.CD_TypeVariable;
+import static org.microbean.construct.constant.ConstantDescs.CD_VariableElement;
import static org.microbean.construct.constant.ConstantDescs.CD_WildcardType;
/**
@@ -119,7 +120,7 @@ public static final Optional extends ConstantDesc> describe(final Name n, fina
default -> (d instanceof Constable c ? c.describeConstable() : Optional.empty())
.map(domainDesc -> DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"name",
MethodTypeDesc.of(CD_Name,
CD_CharSequence)),
@@ -218,7 +219,7 @@ public static final Optional extends ConstantDesc> describe(final ExecutableEl
final ConstantDesc[] args = new ConstantDesc[5 + parameterCount];
args[0] =
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"executableElement",
MethodTypeDesc.of(CD_ExecutableElement,
CD_TypeElement,
@@ -271,7 +272,7 @@ public static final Optional extends ConstantDesc> describe(final ModuleElemen
default -> describe(e.getQualifiedName(), d) // getQualifiedName() does not cause symbol completion
.map(nameDesc -> DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"moduleElement",
MethodTypeDesc.of(CD_ModuleElement,
CD_CharSequence)),
@@ -300,7 +301,7 @@ public static final Optional extends ConstantDesc> describe(final PackageEleme
default -> describe(e.getQualifiedName(), d) // getQualifiedName() does not cause symbol completion
.map(nameDesc -> DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"packageElement",
MethodTypeDesc.of(CD_PackageElement,
CD_CharSequence)),
@@ -329,7 +330,7 @@ public static final Optional extends ConstantDesc> describe(final TypeElement
default -> describe(e.getQualifiedName(), d) // getQualifiedName() does not cause symbol completion
.map(nameDesc -> DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"typeElement",
MethodTypeDesc.of(CD_TypeElement,
CD_CharSequence)),
@@ -361,7 +362,7 @@ yield describe(e.getEnclosingElement(), d)
.flatMap(parameterizableDesc -> describe(e.getSimpleName(), d)
.map(nameDesc -> DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"typeParameterElement",
MethodTypeDesc.of(CD_TypeParameterElement,
CD_Parameterizable,
@@ -396,7 +397,7 @@ public static final Optional extends ConstantDesc> describe(final RecordCompon
yield describe((TypeElement)e.getEnclosingElement(), d)
.map(executableDesc -> DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"recordComponentElement",
MethodTypeDesc.of(CD_RecordComponentElement,
CD_ExecutableElement)),
@@ -430,11 +431,13 @@ yield describe(e.getSimpleName(), d)
.flatMap(nameDesc -> describe(e.getEnclosingElement(), d)
.map(enclosingElementDesc -> DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"variableElement",
- MethodTypeDesc.of(CD_Element,
+ MethodTypeDesc.of(CD_VariableElement,
+ CD_Element,
CD_CharSequence)),
((Constable)d).describeConstable().orElseThrow(),
+ enclosingElementDesc,
nameDesc)));
}
}
@@ -498,7 +501,7 @@ public static final Optional extends ConstantDesc> describe(final ArrayType t,
yield describe(t.getComponentType(), d)
.map(componentTypeDesc -> DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"arrayTypeOf",
MethodTypeDesc.of(CD_ArrayType,
CD_TypeMirror)),
@@ -540,7 +543,7 @@ yield switch (t.getKind()) {
final TypeMirror enclosingType = t.getEnclosingType();
// Call
args[0] = ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"declaredType",
MethodTypeDesc.of(CD_DeclaredType,
CD_DeclaredType,
@@ -597,7 +600,7 @@ public static final Optional extends ConstantDesc> describe(final NoType t, fi
yield t.getKind().describeConstable()
.map(typeKindDesc -> DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"noType",
MethodTypeDesc.of(CD_NoType,
CD_TypeKind)),
@@ -628,7 +631,7 @@ public static final Optional extends ConstantDesc> describe(final NullType t,
default -> (d instanceof Constable c ? c.describeConstable() : Optional.empty())
.map(domainDesc -> DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"nullType",
MethodTypeDesc.of(CD_NullType)),
domainDesc));
@@ -661,7 +664,7 @@ public static final Optional extends ConstantDesc> describe(final PrimitiveTyp
yield t.getKind().describeConstable()
.map(typeKindDesc -> DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"primitiveType",
MethodTypeDesc.of(CD_PrimitiveType,
CD_TypeKind)),
@@ -703,7 +706,7 @@ public static final Optional extends ConstantDesc> describe(final TypeVariable
final String name = d.toString(e.getSimpleName());
yield Optional.of(DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"typeVariable",
MethodTypeDesc.of(CD_TypeVariable,
CD_Parameterizable,
@@ -740,7 +743,7 @@ yield describe(t.getExtendsBound(), d)
.flatMap(extendsBoundDesc -> describe(t.getSuperBound(), d)
.map(superBoundDesc -> DynamicConstantDesc.of(BSM_INVOKE,
ofMethod(VIRTUAL,
- ClassDesc.of(Domain.class.getName()),
+ Domain.class.describeConstable().orElseThrow(),
"wildcardType",
MethodTypeDesc.of(CD_WildcardType,
CD_TypeMirror,
@@ -754,10 +757,8 @@ yield describe(t.getExtendsBound(), d)
}
/**
- * Returns a nominal descriptor for the supplied {@link List}, or an {@linkplain Optional#empty() empty} {@link
- * Optional} if the supplied {@link List} cannot be described.
- *
- * @param the supplied {@code list}'s element type
+ * Returns a non-{@code null} nominal descriptor for the supplied {@link List}, or an {@linkplain Optional#empty()
+ * empty} {@link Optional} if the supplied {@link List} cannot be described.
*
* @param list a {@link List} to be described; may be {@code null}; if non-{@code null} must be immutable and
* must not contain {@code null} elements or undefined behavior will result
@@ -766,10 +767,10 @@ yield describe(t.getExtendsBound(), d)
*
* @see #describe(List, Function)
*/
- public static final Optional extends ConstantDesc> describe(final List extends E> list) {
+ public static final Optional extends ConstantDesc> describe(final List> list) {
return describe(list, e -> e instanceof Constable c ? c.describeConstable() : Optional.empty());
}
-
+
/**
* Returns a nominal descriptor for the supplied {@link List}, or an {@linkplain Optional#empty() empty} {@link
* Optional} if the supplied {@link List} cannot be described.
@@ -814,14 +815,14 @@ public static final Optional extends ConstantDesc> describe(final List e
// After 10 parameters, List.of() falls back to varargs.
ofMethodTypeDesc = MethodTypeDesc.of(CD_List, CD_Object.arrayType());
}
- final ConstantDesc[] args = new ConstantDesc[++size];
+ final ConstantDesc[] args = new ConstantDesc[size + 1];
args[0] = ofMethod(INTERFACE_STATIC, CD_List, "of", ofMethodTypeDesc);
- for (int i = 1; i < size; i++) {
+ for (int i = 0; i < size; i++) {
final ConstantDesc eDesc = f.apply(list.get(i)).orElse(null);
if (eDesc == null) {
yield Optional.empty();
}
- args[i] = eDesc;
+ args[i + 1] = eDesc;
}
yield Optional.of(DynamicConstantDesc.of(BSM_INVOKE, args));
}
@@ -879,7 +880,7 @@ public static Optional extends ConstantDesc> describe(final Map exten
// After 20 parameters, Map.of() falls back to varargs.
ofMethodTypeDesc = MethodTypeDesc.of(CD_Map, CD_Object.arrayType());
}
- final ConstantDesc[] args = new ConstantDesc[++size];
+ final ConstantDesc[] args = new ConstantDesc[size + 1];
args[0] = ofMethod(INTERFACE_STATIC, CD_Map, "of", ofMethodTypeDesc);
int i = 1;
for (final Entry extends K, ? extends V> e : map.entrySet()) {
@@ -891,9 +892,8 @@ public static Optional extends ConstantDesc> describe(final Map exten
if (vDesc == null) {
yield Optional.empty();
}
- args[i] = kDesc;
- args[++i] = vDesc;
- ++i;
+ args[i++] = kDesc;
+ args[i++] = vDesc;
}
yield Optional.of(DynamicConstantDesc.of(BSM_INVOKE, args));
}
diff --git a/src/main/java/org/microbean/construct/constant/ConstantDescs.java b/src/main/java/org/microbean/construct/constant/ConstantDescs.java
index 8e1350c..035af17 100644
--- a/src/main/java/org/microbean/construct/constant/ConstantDescs.java
+++ b/src/main/java/org/microbean/construct/constant/ConstantDescs.java
@@ -53,6 +53,8 @@ final class ConstantDescs {
static final ClassDesc CD_TypeVariable = ClassDesc.of("javax.lang.model.type.TypeVariable");
+ static final ClassDesc CD_VariableElement = ClassDesc.of("javax.lang.model.element.VariableElement");
+
static final ClassDesc CD_WildcardType = ClassDesc.of("javax.lang.model.type.WildcardType");
private ConstantDescs() {
diff --git a/src/main/java/org/microbean/construct/element/AnnotationMirrors.java b/src/main/java/org/microbean/construct/element/AnnotationMirrors.java
index ca72bb6..2c32dc5 100644
--- a/src/main/java/org/microbean/construct/element/AnnotationMirrors.java
+++ b/src/main/java/org/microbean/construct/element/AnnotationMirrors.java
@@ -179,6 +179,28 @@ public static final SequencedMap allAnnotati
return m.isEmpty() ? emptySequencedMap() : unmodifiableSequencedMap(m);
}
+ /**
+ * Returns {@code true} if and only if the supplied {@link Collection} of {@link AnnotationMirror}s contains an {@link
+ * AnnotationMirror} that is {@linkplain #sameAnnotation(AnnotationMirror, AnnotationMirror, Predicate) the same} as
+ * the supplied {@link AnnotationMirror}.
+ *
+ * @param c a non-{@code null} {@link Collection} of {@link AnnotationMirror}s
+ *
+ * @param a a non-{@code null} {@link AnnotationMirror}
+ *
+ * @return {@code true} if and only if the supplied {@link Collection} of {@link AnnotationMirror}s contains an {@link
+ * AnnotationMirror} that is {@linkplain #sameAnnotation(AnnotationMirror, AnnotationMirror, Predicate) the same} as
+ * the supplied {@link AnnotationMirror}
+ *
+ * @exception NullPointerException if {@code c} or {@code a} is {@code null}
+ *
+ * @see #contains(collection, AnnotationMirror, Predicate)
+ */
+ public static final boolean contains(final Collection extends AnnotationMirror> c,
+ final AnnotationMirror a) {
+ return contains(c, a, null);
+ }
+
/**
* Returns {@code true} if and only if the supplied {@link Collection} of {@link AnnotationMirror}s contains an {@link
* AnnotationMirror} that is {@linkplain #sameAnnotation(AnnotationMirror, AnnotationMirror, Predicate) the same} as
@@ -199,13 +221,12 @@ public static final SequencedMap allAnnotati
* @exception NullPointerException if {@code c} or {@code a} is {@code null}
*
* @see #sameAnnotation(AnnotationMirror, AnnotationMirror, Predicate)
+ *
+ * @see #containsAll(collection, Collection, Predicate)
*/
public static final boolean contains(final Collection extends AnnotationMirror> c,
final AnnotationMirror a,
final Predicate super ExecutableElement> p) {
- if (c.isEmpty()) {
- return false;
- }
for (final AnnotationMirror ca : c) {
if (sameAnnotation(ca, a, p)) {
return true;
@@ -215,7 +236,27 @@ public static final boolean contains(final Collection extends AnnotationMirror
}
/**
- * Returns {@code true} if and only if {@code c0} contains {@linkplain #sameAnnotation(AnnotationMirror,
+ * Returns {@code true} if and only if {@code c0} contains all {@linkplain #sameAnnotation(AnnotationMirror,
+ * AnnotationMirror, Predicate) the same} {@link AnnotationMirror}s as are found in {@code c1},
+ *
+ * @param c0 a non-{@code null} {@link Collection} of {@link AnnotationMirror}s
+ *
+ * @param c1 a non-{@code null} {@link Collection} of {@link AnnotationMirror}s
+ *
+ * @return {@code true} if and only if {@code c0} contains all {@linkplain #sameAnnotation(AnnotationMirror,
+ * AnnotationMirror, Predicate) the same} {@link AnnotationMirror}s as are found in {@code c1}
+ *
+ * @exception NullPointerException if either {@code c0} or {@code c1} is {@code null}
+ *
+ * @see #containsAll(Collection, Collection, Predicate)
+ */
+ public static final boolean containsAll(final Collection extends AnnotationMirror> c0,
+ final Collection extends AnnotationMirror> c1) {
+ return containsAll(c0, c1, null);
+ }
+
+ /**
+ * Returns {@code true} if and only if {@code c0} contains all {@linkplain #sameAnnotation(AnnotationMirror,
* AnnotationMirror, Predicate) the same} {@link AnnotationMirror}s as are found in {@code c1},
*
* @param c0 a non-{@code null} {@link Collection} of {@link AnnotationMirror}s
@@ -226,11 +267,13 @@ public static final boolean contains(final Collection extends AnnotationMirror
* annotation element, is to be included in comparison operations; may be {@code null} in which case it is as if
* {@code e -> true} were supplied instead
*
- * @return {@code true} if and only if {@code c0} contains {@linkplain #sameAnnotation(AnnotationMirror,
+ * @return {@code true} if and only if {@code c0} contains all {@linkplain #sameAnnotation(AnnotationMirror,
* AnnotationMirror, Predicate) the same} {@link AnnotationMirror}s as are found in {@code c1}
*
* @exception NullPointerException if either {@code c0} or {@code c1} is {@code null}
*
+ * @see #contains(Collection, AnnotationMirror, Predicate)
+ *
* @see #sameAnnotation(AnnotationMirror, AnnotationMirror, Predicate)
*/
public static final boolean containsAll(final Collection extends AnnotationMirror> c0,
@@ -239,14 +282,10 @@ public static final boolean containsAll(final Collection extends AnnotationMir
if (c0.size() < c1.size()) {
return false;
}
- OUTER_LOOP:
- for (final AnnotationMirror a0 : c0) {
- for (final AnnotationMirror a1 : c1) {
- if (sameAnnotation(a0, a1, p)) {
- continue OUTER_LOOP;
- }
+ for (final AnnotationMirror a1 : c1) {
+ if (!contains(c0, a1, p)) {
+ return false;
}
- return false;
}
return true;
}
@@ -488,7 +527,7 @@ public static final RetentionPolicy retentionPolicy(final TypeElement annotation
* @return {@code true} if the supplied {@link AnnotationMirror}s represent the same (otherwise opaque) annotation;
* {@code false} otherwise
*
- * @see #sameAnnotation(AnnotationMirror, AnnotationMirror)
+ * @see #sameAnnotation(AnnotationMirror, AnnotationMirror, Predicate)
*/
public static final boolean sameAnnotation(final AnnotationMirror am0, final AnnotationMirror am1) {
return sameAnnotation(am0, am1, null);
@@ -520,6 +559,28 @@ public static final boolean sameAnnotation(final AnnotationMirror am0,
return am0 == am1 || new SameAnnotationValueVisitor(p).visitAnnotation(am0, am1);
}
+ /**
+ * Returns {@code true} if {@code c0} has all the {@linkplain #sameAnnotation(AnnotationMirror, AnnotationMirror,
+ * Predicate) same annotations} as {@code c1}, and if {@code c1} has all the {@linkplain
+ * #sameAnnotation(AnnotationMirror, AnnotationMirror, Predicate) same annotations} as {@code c0}.
+ *
+ * @param c0 a non-{@code null} {@link Collection} of {@link AnnotationMirror}s
+ *
+ * @param c1 a non-{@code null} {@link Collection} of {@link AnnotationMirror}s
+ *
+ * @return {@code true} if {@code c0} has all the {@linkplain #sameAnnotation(AnnotationMirror, AnnotationMirror,
+ * Predicate) same annotations} as {@code c1}, and if {@code c1} has all the {@linkplain
+ * #sameAnnotation(AnnotationMirror, AnnotationMirror, Predicate) same annotations} as {@code c0}
+ *
+ * @exception NullPointerException if either {@code c0} or {@code c1} is {@code null}
+ *
+ * @see #sameAnnotations(Collection, Collection, Predicate)
+ */
+ public static final boolean sameAnnotations(final Collection extends AnnotationMirror> c0,
+ final Collection extends AnnotationMirror> c1) {
+ return sameAnnotations(c0, c1, null);
+ }
+
/**
* Returns {@code true} if {@code c0} has all the {@linkplain #sameAnnotation(AnnotationMirror, AnnotationMirror,
* Predicate) same annotations} as {@code c1}, and if {@code c1} has all the {@linkplain
@@ -539,6 +600,8 @@ public static final boolean sameAnnotation(final AnnotationMirror am0,
*
* @exception NullPointerException if either {@code c0} or {@code c1} is {@code null}
*
+ * @see #containsAll(Collection, Collection, Predicate)
+ *
* @see #sameAnnotation(AnnotationMirror, AnnotationMirror, Predicate)
*/
public static final boolean sameAnnotations(final Collection extends AnnotationMirror> c0,
diff --git a/src/main/java/org/microbean/construct/element/StringName.java b/src/main/java/org/microbean/construct/element/StringName.java
index 5af677d..55959f3 100644
--- a/src/main/java/org/microbean/construct/element/StringName.java
+++ b/src/main/java/org/microbean/construct/element/StringName.java
@@ -113,14 +113,16 @@ public final boolean contentEquals(final CharSequence cs) {
}
@Override // Constable
- public final Optional extends ConstantDesc> describeConstable() {
+ public final Optional> describeConstable() {
return (this.domain() instanceof Constable c ? c.describeConstable() : Optional.empty())
- .map(domainDesc -> DynamicConstantDesc.of(BSM_INVOKE,
- MethodHandleDesc.ofConstructor(ClassDesc.of(this.getClass().getName()),
- ClassDesc.of(CharSequence.class.getName()),
- ClassDesc.of(PrimordialDomain.class.getName())),
- this.value,
- domainDesc));
+ .map(domainDesc -> DynamicConstantDesc.ofNamed(BSM_INVOKE,
+ this.value,
+ this.getClass().describeConstable().orElseThrow(),
+ MethodHandleDesc.ofConstructor(this.getClass().describeConstable().orElseThrow(),
+ CharSequence.class.describeConstable().orElseThrow(),
+ PrimordialDomain.class.describeConstable().orElseThrow()),
+ this.value,
+ domainDesc));
}
@Override // Record
diff --git a/src/main/java/org/microbean/construct/element/SyntheticAnnotationMirror.java b/src/main/java/org/microbean/construct/element/SyntheticAnnotationMirror.java
index 84b628d..8ad0295 100644
--- a/src/main/java/org/microbean/construct/element/SyntheticAnnotationMirror.java
+++ b/src/main/java/org/microbean/construct/element/SyntheticAnnotationMirror.java
@@ -29,6 +29,7 @@
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.QualifiedNameable;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
@@ -42,6 +43,8 @@
import static java.util.Collections.unmodifiableMap;
+import static java.util.HashMap.newHashMap;
+
import static java.util.LinkedHashMap.newLinkedHashMap;
import static javax.lang.model.element.ElementKind.ANNOTATION_TYPE;
@@ -152,6 +155,7 @@ public SyntheticAnnotationMirror(final TypeElement annotationTypeElement,
*
* @exception NullPointerException if {@code a} is {@code null}
*/
+ // (Copy constructor.)
public SyntheticAnnotationMirror(final AnnotationMirror a) {
super();
this.annotationTypeElement = new SyntheticAnnotationTypeElement((TypeElement)a.getAnnotationType().asElement());
@@ -184,17 +188,19 @@ public SyntheticAnnotationMirror(final AnnotationMirror a) {
@Override // Constable
- public final Optional extends ConstantDesc> describeConstable() {
- return this.annotationTypeElement instanceof Constable c ? c.describeConstable() : Optional.empty()
- .flatMap(elementDesc -> Constables.describe(this.elementValues,
- SyntheticAnnotationMirror::describeExecutableElement,
+ public final Optional> describeConstable() {
+ return (this.annotationTypeElement instanceof Constable c ? c.describeConstable() : Optional.empty())
+ .flatMap(elementDesc -> Constables.describe(this.toSyntheticValues(),
+ String::describeConstable,
SyntheticAnnotationMirror::describeAnnotationValue)
- .map(valuesDesc -> DynamicConstantDesc.of(BSM_INVOKE,
- ofConstructor(ClassDesc.of(this.getClass().getName()),
- ClassDesc.of(TypeElement.class.getName()),
- CD_Map),
- elementDesc,
- valuesDesc)));
+ .map(valuesDesc -> DynamicConstantDesc.ofNamed(BSM_INVOKE,
+ this.getAnnotationType().asElement().getSimpleName().toString(), // supposed to be unqualified, I guess
+ this.getClass().describeConstable().orElseThrow(),
+ ofConstructor(this.getClass().describeConstable().orElseThrow(),
+ TypeElement.class.describeConstable().orElseThrow(),
+ CD_Map),
+ elementDesc,
+ valuesDesc)));
}
@Override // AnnotationMirror
@@ -212,12 +218,25 @@ public final String toString() {
return "@" + this.annotationTypeElement.toString(); // TODO: not anywhere near good enough
}
+ // Called by describeConstable().
+ private final Map extends String, ?> toSyntheticValues() {
+ if (this.elementValues.isEmpty()) {
+ return Map.of();
+ }
+ final Map rv = newHashMap(this.elementValues.size());
+ for (final Entry extends ExecutableElement, ? extends AnnotationValue> e : this.elementValues.entrySet()) {
+ rv.put(e.getKey().getSimpleName().toString(), e.getValue().getValue());
+ }
+ return rv;
+ }
+
/*
* Static methods.
*/
+ // Called by describeConstable().
private static final Optional extends ConstantDesc> describeAnnotationValue(final Object v) {
return switch (v) {
case null -> Optional.empty(); // deliberately not Optional.of(NULL); annotation values cannot be null
@@ -228,15 +247,6 @@ private static final Optional extends ConstantDesc> describeAnnotationValue(fi
};
}
- private static final Optional extends ConstantDesc> describeExecutableElement(final ExecutableElement e) {
- return switch (e) {
- case null -> throw new IllegalStateException();
- case Constable c -> c.describeConstable();
- case ConstantDesc cd -> Optional.of(cd);
- default -> Optional.empty();
- };
- }
-
private static final E element(final Iterable extends E> elements, final CharSequence simpleName) {
for (final E e : elements) {
if (e.getSimpleName().contentEquals(simpleName)) {
diff --git a/src/main/java/org/microbean/construct/element/SyntheticAnnotationTypeElement.java b/src/main/java/org/microbean/construct/element/SyntheticAnnotationTypeElement.java
index 2a51a15..cce8d1c 100644
--- a/src/main/java/org/microbean/construct/element/SyntheticAnnotationTypeElement.java
+++ b/src/main/java/org/microbean/construct/element/SyntheticAnnotationTypeElement.java
@@ -15,9 +15,14 @@
import java.lang.annotation.Annotation;
+import java.lang.constant.Constable;
+import java.lang.constant.ConstantDesc;
+import java.lang.constant.DynamicConstantDesc;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -44,8 +49,15 @@
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.TypeVisitor;
+import org.microbean.construct.constant.Constables;
+
import org.microbean.construct.type.NoneType;
+import static java.lang.constant.ConstantDescs.BSM_INVOKE;
+import static java.lang.constant.ConstantDescs.CD_List;
+
+import static java.lang.constant.MethodHandleDesc.ofConstructor;
+
import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
@@ -70,7 +82,7 @@
*
* @see SyntheticAnnotationMirror
*/
-public final class SyntheticAnnotationTypeElement implements TypeElement {
+public final class SyntheticAnnotationTypeElement implements Constable, TypeElement {
/*
@@ -299,6 +311,7 @@ public SyntheticAnnotationTypeElement(final List extends AnnotationMirror> ann
* @exception IllegalArgumentException if the supplied {@link TypeElement}'s {@link TypeElement#getKind() getKind()}
* method does not return {@link javax.lang.model.element.ElementKind#ANNOTATION_TYPE}
*/
+ // (Copy constructor.)
public SyntheticAnnotationTypeElement(final TypeElement e) {
super();
if (e.getKind() != ANNOTATION_TYPE) {
@@ -348,6 +361,7 @@ public SyntheticAnnotationTypeElement(final TypeElement e) {
*
* @see SyntheticAnnotationMirror
*/
+ // (Canonical.)
public SyntheticAnnotationTypeElement(final List extends AnnotationMirror> annotationMirrors,
final SyntheticName fullyQualifiedName,
final List extends SyntheticAnnotationElement> elements) {
@@ -357,7 +371,7 @@ public SyntheticAnnotationTypeElement(final List extends AnnotationMirror> ann
final int i = fqn.lastIndexOf('.');
this.sn = i >= 0 ? new SyntheticName(fqn.substring(i + 1)) : fullyQualifiedName;
this.fqn = fullyQualifiedName;
- this.type = new Type();
+ this.type = new Type(); // inner class on purpose
if (elements.isEmpty()) {
this.elements = List.of();
} else {
@@ -385,6 +399,22 @@ public final TypeMirror asType() {
return this.type;
}
+ @Override // Constable
+ public final Optional> describeConstable() {
+ return Constables.describe(this.annotationMirrors)
+ .flatMap(amsDesc -> Constables.describe(InternalAnnotationElement.toSyntheticAnnotationElements(this.elements))
+ .map(elementsDesc -> DynamicConstantDesc.ofNamed(BSM_INVOKE,
+ this.getSimpleName().toString(),
+ this.getClass().describeConstable().orElseThrow(),
+ ofConstructor(this.getClass().describeConstable().orElseThrow(),
+ CD_List,
+ SyntheticName.class.describeConstable().orElseThrow(),
+ CD_List),
+ amsDesc,
+ this.fqn.describeConstable().orElseThrow(),
+ elementsDesc)));
+ }
+
@Override // TypeElement (AnnotatedConstruct)
public final List getAnnotationMirrors() {
return this.annotationMirrors;
@@ -882,6 +912,23 @@ public final boolean isVarArgs() {
}
+ /*
+ * Static methods.
+ */
+
+
+ private static List toSyntheticAnnotationElements(final List extends InternalAnnotationElement> iaes) {
+ if (iaes.isEmpty()) {
+ return List.of();
+ }
+ final List saes = new ArrayList<>(iaes.size());
+ for (final InternalAnnotationElement iae : iaes) {
+ saes.add(new SyntheticAnnotationElement(iae.annotationMirrors, iae.t, iae.name, iae.defaultValue));
+ }
+ return unmodifiableList(saes);
+ }
+
+
/*
* Inner and nested classes.
*/
diff --git a/src/main/java/org/microbean/construct/element/SyntheticAnnotationValue.java b/src/main/java/org/microbean/construct/element/SyntheticAnnotationValue.java
index 0d2675f..06a81c2 100644
--- a/src/main/java/org/microbean/construct/element/SyntheticAnnotationValue.java
+++ b/src/main/java/org/microbean/construct/element/SyntheticAnnotationValue.java
@@ -28,6 +28,8 @@
import javax.lang.model.type.TypeMirror;
+import org.microbean.construct.constant.Constables;
+
import static java.lang.constant.ConstantDescs.BSM_INVOKE;
import static java.lang.constant.ConstantDescs.CD_Object;
@@ -114,12 +116,19 @@ public final R accept(final AnnotationValueVisitor v, final P p) {
}
@Override // Constable
- public final Optional extends ConstantDesc> describeConstable() {
- return this.value instanceof Constable c ? c.describeConstable() : Optional.empty()
- .map(valueDesc -> DynamicConstantDesc.of(BSM_INVOKE,
- ofConstructor(ClassDesc.of(this.getClass().getName()),
- CD_Object),
- valueDesc));
+ public final Optional> describeConstable() {
+ final Optional extends ConstantDesc> valueDescOptional = switch (this.value) {
+ case Constable c -> c.describeConstable();
+ case ConstantDesc cd -> Optional.of(cd);
+ case List> l -> Constables.describe(l);
+ default -> Optional.empty();
+ };
+ return valueDescOptional.map(valueDesc -> DynamicConstantDesc.ofNamed(BSM_INVOKE,
+ this.getClass().getSimpleName(),
+ this.getClass().describeConstable().orElseThrow(),
+ ofConstructor(this.getClass().describeConstable().orElseThrow(),
+ CD_Object),
+ valueDesc));
}
@Override // Object
diff --git a/src/main/java/org/microbean/construct/element/SyntheticName.java b/src/main/java/org/microbean/construct/element/SyntheticName.java
index beefc96..ef05402 100644
--- a/src/main/java/org/microbean/construct/element/SyntheticName.java
+++ b/src/main/java/org/microbean/construct/element/SyntheticName.java
@@ -29,7 +29,7 @@
import static java.lang.constant.ConstantDescs.BSM_INVOKE;
import static java.lang.constant.ConstantDescs.CD_String;
-import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC;
+import static java.lang.constant.MethodHandleDesc.ofConstructor;
import static java.util.Objects.requireNonNull;
@@ -114,12 +114,12 @@ public final boolean contentEquals(final CharSequence cs) {
@Override // Constable
public final Optional> describeConstable() {
return
- Optional.of(DynamicConstantDesc.of(BSM_INVOKE,
- MethodHandleDesc.ofMethod(STATIC,
- ClassDesc.of(this.getClass().getName()),
- "of",
- MethodTypeDesc.of(CD_String)),
- this.value));
+ Optional.of(DynamicConstantDesc.ofNamed(BSM_INVOKE,
+ this.value,
+ this.getClass().describeConstable().orElseThrow(),
+ ofConstructor(this.getClass().describeConstable().orElseThrow(),
+ CD_String),
+ this.value));
}
@Override // Object
diff --git a/src/main/java/org/microbean/construct/element/UniversalAnnotation.java b/src/main/java/org/microbean/construct/element/UniversalAnnotation.java
index 4268369..e7baa6c 100644
--- a/src/main/java/org/microbean/construct/element/UniversalAnnotation.java
+++ b/src/main/java/org/microbean/construct/element/UniversalAnnotation.java
@@ -13,7 +13,6 @@
*/
package org.microbean.construct.element;
-import java.lang.constant.ClassDesc;
import java.lang.constant.Constable;
import java.lang.constant.ConstantDesc;
import java.lang.constant.DynamicConstantDesc;
@@ -123,18 +122,22 @@ public final AnnotationMirror delegate() {
}
@Override // Constable
- public Optional extends ConstantDesc> describeConstable() {
- return this.domain instanceof Constable c0 ? c0.describeConstable() : Optional.empty()
- .flatMap(primordialDomainDesc -> this.delegate() instanceof Constable c1 ? c1.describeConstable() : Optional.empty()
- .map(delegateDesc -> DynamicConstantDesc.of(BSM_INVOKE,
- ofMethod(STATIC,
- ClassDesc.of(this.getClass().getName()),
- "of",
- MethodTypeDesc.of(ClassDesc.of(this.getClass().getName()),
- ClassDesc.of(AnnotationMirror.class.getName()),
- ClassDesc.of(PrimordialDomain.class.getName()))),
- delegateDesc,
- primordialDomainDesc)));
+ public final Optional> describeConstable() {
+ // TODO: this.delegate() is never going to be a Constable. It's debatable whether this class should implement
+ // Constable at all.
+ return (this.domain instanceof Constable c0 ? c0.describeConstable() : Optional.empty())
+ .flatMap(primordialDomainDesc -> (this.delegate() instanceof Constable c1 ? c1.describeConstable() : Optional.empty())
+ .map(delegateDesc -> DynamicConstantDesc.ofNamed(BSM_INVOKE,
+ this.getAnnotationType().asElement().getSimpleName().toString(),
+ UniversalAnnotation.class.describeConstable().orElseThrow(),
+ ofMethod(STATIC,
+ UniversalAnnotation.class.describeConstable().orElseThrow(),
+ "of",
+ MethodTypeDesc.of(UniversalAnnotation.class.describeConstable().orElseThrow(),
+ AnnotationMirror.class.describeConstable().orElseThrow(),
+ PrimordialDomain.class.describeConstable().orElseThrow())),
+ delegateDesc,
+ primordialDomainDesc)));
}
/**