From 918a379cc317aed3c9d7c3ae1c0b3269b5adaa55 Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Thu, 18 Jul 2024 11:00:19 -0700 Subject: [PATCH] DelegatingElement is now Constable (#18) Signed-off-by: Laird Nelson --- README.md | 2 +- .../org/microbean/lang/ConstantDescs.java | 4 + .../lang/element/DelegatingElement.java | 98 ++++++++++++++----- .../lang/type/DelegatingTypeMirror.java | 76 +++++++------- 4 files changed, 117 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index c38f017a..f6b4dc97 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Maven dependency: org.microbean microbean-lang - 0.0.15 + 0.0.17 ``` diff --git a/lang/src/main/java/org/microbean/lang/ConstantDescs.java b/lang/src/main/java/org/microbean/lang/ConstantDescs.java index 79ad0917..774775c7 100644 --- a/lang/src/main/java/org/microbean/lang/ConstantDescs.java +++ b/lang/src/main/java/org/microbean/lang/ConstantDescs.java @@ -28,6 +28,10 @@ public final class ConstantDescs { public static final ClassDesc CD_DeclaredType = ClassDesc.of("javax.lang.model.type.DeclaredType"); + public static final ClassDesc CD_DelegatingElement = ClassDesc.of("org.microbean.lang.element.DelegatingElement"); + + public static final ClassDesc CD_DelegatingTypeMirror = ClassDesc.of("org.microbean.lang.type.DelegatingTypeMirror"); + public static final ClassDesc CD_Element = ClassDesc.of("javax.lang.model.element.Element"); public static final ClassDesc CD_Equality = ClassDesc.of("org.microbean.lang.Equality"); diff --git a/lang/src/main/java/org/microbean/lang/element/DelegatingElement.java b/lang/src/main/java/org/microbean/lang/element/DelegatingElement.java index 9862e168..5ff977d8 100644 --- a/lang/src/main/java/org/microbean/lang/element/DelegatingElement.java +++ b/lang/src/main/java/org/microbean/lang/element/DelegatingElement.java @@ -15,11 +15,18 @@ import java.lang.annotation.Annotation; +import java.lang.constant.Constable; +import java.lang.constant.ConstantDesc; +import java.lang.constant.DynamicConstantDesc; +import java.lang.constant.MethodHandleDesc; +import java.lang.constant.MethodTypeDesc; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.function.Supplier; @@ -52,6 +59,14 @@ import org.microbean.lang.type.DelegatingTypeMirror; import org.microbean.lang.type.NoType; +import static java.lang.constant.ConstantDescs.BSM_INVOKE; +import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC; + +import static org.microbean.lang.ConstantDescs.CD_DelegatingElement; +import static org.microbean.lang.ConstantDescs.CD_Equality; +import static org.microbean.lang.ConstantDescs.CD_TypeAndElementSource; +import static org.microbean.lang.ConstantDescs.CD_Element; + /** * An {@link Element} that implements all known {@link Element} subinterfaces and delegates to an underlying {@link * Element} for all operations. @@ -60,9 +75,9 @@ * * @author Laird Nelson */ -@SuppressWarnings("preview") public final class DelegatingElement - implements ExecutableElement, + implements Constable, + ExecutableElement, ModuleElement, PackageElement, Parameterizable, @@ -119,14 +134,29 @@ private DelegatingElement(final Element delegate, @Override // Element public final R accept(final ElementVisitor v, final P p) { return switch (this.getKind()) { - case ANNOTATION_TYPE, CLASS, ENUM, INTERFACE, RECORD -> v.visitType(this, p); - case TYPE_PARAMETER -> v.visitTypeParameter(this, p); - case BINDING_VARIABLE, ENUM_CONSTANT, EXCEPTION_PARAMETER, FIELD, LOCAL_VARIABLE, PARAMETER, RESOURCE_VARIABLE -> v.visitVariable(this, p); - case RECORD_COMPONENT -> v.visitRecordComponent(this, p); - case CONSTRUCTOR, INSTANCE_INIT, METHOD, STATIC_INIT -> v.visitExecutable(this, p); - case PACKAGE -> v.visitPackage(this, p); - case MODULE -> v.visitModule(this, p); - case OTHER -> v.visitUnknown(this, p); + case + ANNOTATION_TYPE, + CLASS, + ENUM, + INTERFACE, + RECORD -> v.visitType(this, p); + case TYPE_PARAMETER -> v.visitTypeParameter(this, p); + case + BINDING_VARIABLE, + ENUM_CONSTANT, + EXCEPTION_PARAMETER, + FIELD, LOCAL_VARIABLE, + PARAMETER, + RESOURCE_VARIABLE -> v.visitVariable(this, p); + case RECORD_COMPONENT -> v.visitRecordComponent(this, p); + case + CONSTRUCTOR, + INSTANCE_INIT, + METHOD, + STATIC_INIT -> v.visitExecutable(this, p); + case PACKAGE -> v.visitPackage(this, p); + case MODULE -> v.visitModule(this, p); + case OTHER -> v.visitUnknown(this, p); }; } @@ -139,11 +169,29 @@ public final Element delegate() { return this.delegateSupplier.get(); } + @Override // Constable + public final Optional describeConstable() { + return this.ehc.describeConstable() + .flatMap(ehcDesc -> (this.tes instanceof Constable c ? c.describeConstable() : Optional.empty()) + .flatMap(tesDesc -> this.tes.describeConstable(this.delegate()) + .map(delegateDesc -> DynamicConstantDesc.of(BSM_INVOKE, + MethodHandleDesc.ofMethod(STATIC, + CD_DelegatingElement, + "of", + MethodTypeDesc.of(CD_DelegatingElement, + CD_Element, + CD_TypeAndElementSource, + CD_Equality)), + delegateDesc, + tesDesc, + ehcDesc)))); + } + @Override // RecordComponentElement public final ExecutableElement getAccessor() { return switch (this.getKind()) { case RECORD_COMPONENT -> this.wrap(((RecordComponentElement)this.delegate()).getAccessor()); - default -> null; + default -> null; }; } @@ -193,8 +241,8 @@ public final AnnotationValue getDefaultValue() { @Override // ModuleElement public final List getDirectives() { return switch (this.getKind()) { - case MODULE -> ((ModuleElement)this.delegate()).getDirectives(); - default -> List.of(); + case MODULE -> ((ModuleElement)this.delegate()).getDirectives(); // TODO: wrap? Probably not necessary + default -> List.of(); }; } @@ -212,7 +260,7 @@ public final Element getEnclosingElement() { public final Element getGenericElement() { return switch (this.getKind()) { case TYPE_PARAMETER -> this.wrap(((TypeParameterElement)this.delegate()).getGenericElement()); - default -> null; // illegal state + default -> null; // illegal state }; } @@ -239,7 +287,7 @@ public final Set getModifiers() { public final NestingKind getNestingKind() { return switch (this.getKind()) { case ANNOTATION_TYPE, CLASS, ENUM, INTERFACE, RECORD -> ((TypeElement)this.delegate()).getNestingKind(); - default -> null; + default -> null; }; } @@ -247,14 +295,13 @@ public final NestingKind getNestingKind() { public final List getParameters() { return switch (this.getKind()) { case CONSTRUCTOR, METHOD -> this.wrap(((ExecutableElement)this.delegate()).getParameters()); - default -> List.of(); + default -> List.of(); }; } @Override // ModuleElement, PackageElement, TypeElement public final Name getQualifiedName() { return switch (this.getKind()) { - // case ANNOTATION_TYPE, CLASS, ENUM, INTERFACE, MODULE, PACKAGE, RECORD -> ((QualifiedNameable)this.delegate()).getQualifiedName(); case ANNOTATION_TYPE, CLASS, ENUM, INTERFACE, MODULE, PACKAGE, RECORD -> org.microbean.lang.element.Name.of(((QualifiedNameable)this.delegate()).getQualifiedName()); default -> org.microbean.lang.element.Name.of(); @@ -272,8 +319,8 @@ public final TypeMirror getReceiverType() { @Override // TypeElement public final List getRecordComponents() { return switch (this.getKind()) { - case RECORD -> ((TypeElement)this.delegate()).getRecordComponents(); - default -> List.of(); + case RECORD -> this.wrap(((TypeElement)this.delegate()).getRecordComponents()); + default -> List.of(); }; } @@ -284,7 +331,6 @@ public final TypeMirror getReturnType() { @Override // Element public final Name getSimpleName() { - // return this.delegate().getSimpleName(); return org.microbean.lang.element.Name.of(this.delegate().getSimpleName()); } @@ -309,7 +355,7 @@ public final List getThrownTypes() { public final List getTypeParameters() { return switch (this.getKind()) { case CLASS, CONSTRUCTOR, ENUM, INTERFACE, RECORD, METHOD -> this.wrap(((Parameterizable)this.delegate()).getTypeParameters()); - default -> List.of(); + default -> List.of(); }; } @@ -317,7 +363,7 @@ public final List getTypeParameters() { public final boolean isDefault() { return switch (this.getKind()) { case METHOD -> ((ExecutableElement)this.delegate()).isDefault(); - default -> false; + default -> false; }; } @@ -325,16 +371,16 @@ public final boolean isDefault() { public final boolean isOpen() { return switch (this.getKind()) { case MODULE -> ((ModuleElement)this.delegate()).isOpen(); - default -> false; + default -> false; }; } @Override // ModuleElement, PackageElement public final boolean isUnnamed() { return switch (this.getKind()) { - case MODULE -> ((ModuleElement)this.delegate()).isUnnamed(); + case MODULE -> ((ModuleElement)this.delegate()).isUnnamed(); case PACKAGE -> ((PackageElement)this.delegate()).isUnnamed(); - default -> false; + default -> this.getSimpleName().isEmpty(); }; } @@ -342,7 +388,7 @@ public final boolean isUnnamed() { public final boolean isVarArgs() { return switch (this.getKind()) { case CONSTRUCTOR, METHOD -> ((ExecutableElement)this.delegate()).isVarArgs(); - default -> false; + default -> false; }; } diff --git a/lang/src/main/java/org/microbean/lang/type/DelegatingTypeMirror.java b/lang/src/main/java/org/microbean/lang/type/DelegatingTypeMirror.java index 7499cbce..d37688af 100644 --- a/lang/src/main/java/org/microbean/lang/type/DelegatingTypeMirror.java +++ b/lang/src/main/java/org/microbean/lang/type/DelegatingTypeMirror.java @@ -15,7 +15,6 @@ import java.lang.annotation.Annotation; -import java.lang.constant.ClassDesc; import java.lang.constant.Constable; import java.lang.constant.ConstantDesc; import java.lang.constant.DynamicConstantDesc; @@ -58,6 +57,7 @@ import static java.lang.constant.ConstantDescs.BSM_INVOKE; import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC; +import static org.microbean.lang.ConstantDescs.CD_DelegatingTypeMirror; import static org.microbean.lang.ConstantDescs.CD_Equality; import static org.microbean.lang.ConstantDescs.CD_TypeAndElementSource; import static org.microbean.lang.ConstantDescs.CD_TypeMirror; @@ -84,14 +84,6 @@ public final class DelegatingTypeMirror WildcardType { - /* - * Static fields. - */ - - - private static final ClassDesc CD_DelegatingTypeMirror = ClassDesc.of("org.microbean.lang.type.DelegatingTypeMirror"); - - /* * Instance fields. */ @@ -137,18 +129,30 @@ private DelegatingTypeMirror(final TypeMirror delegate, final TypeAndElementSour @Override // TypeMirror public final R accept(final TypeVisitor v, final P p) { return switch (this.getKind()) { - case ARRAY -> v.visitArray(this, p); - case DECLARED -> v.visitDeclared(this, p); - case ERROR -> v.visitError(this, p); - case EXECUTABLE -> v.visitExecutable(this, p); + case ARRAY -> v.visitArray(this, p); + case DECLARED -> v.visitDeclared(this, p); + case ERROR -> v.visitError(this, p); + case EXECUTABLE -> v.visitExecutable(this, p); case INTERSECTION -> v.visitIntersection(this, p); - case MODULE, NONE, PACKAGE, VOID -> v.visitNoType(this, p); - case NULL -> v.visitNull(this, p); - case BOOLEAN, BYTE, CHAR, DOUBLE, FLOAT, INT, LONG, SHORT -> v.visitPrimitive(this, p); - case TYPEVAR -> v.visitTypeVariable(this, p); - case UNION -> v.visitUnion(this, p); - case WILDCARD -> v.visitWildcard(this, p); - case OTHER -> v.visitUnknown(this, p); + case + MODULE, + NONE, + PACKAGE, + VOID -> v.visitNoType(this, p); + case NULL -> v.visitNull(this, p); + case + BOOLEAN, + BYTE, + CHAR, + DOUBLE, + FLOAT, + INT, + LONG, + SHORT -> v.visitPrimitive(this, p); + case TYPEVAR -> v.visitTypeVariable(this, p); + case UNION -> v.visitUnion(this, p); + case WILDCARD -> v.visitWildcard(this, p); + case OTHER -> v.visitUnknown(this, p); }; } @@ -156,8 +160,8 @@ public final R accept(final TypeVisitor v, final P p) { public final Element asElement() { return switch (this.getKind()) { case DECLARED -> DelegatingElement.of(((DeclaredType)this.delegate()).asElement(), this.elementSource, this.ehc); - case TYPEVAR -> DelegatingElement.of(((TypeVariable)this.delegate()).asElement(), this.elementSource, this.ehc); - default -> null; + case TYPEVAR -> DelegatingElement.of(((TypeVariable)this.delegate()).asElement(), this.elementSource, this.ehc); + default -> null; }; } @@ -169,7 +173,7 @@ public final TypeMirror delegate() { public final List getAlternatives() { return switch (this.getKind()) { case UNION -> this.wrap(((UnionType)this.delegate()).getAlternatives()); - default -> List.of(); + default -> List.of(); }; } @@ -193,7 +197,7 @@ public final A[] getAnnotationsByType(final Class anno public final List getBounds() { return switch (this.getKind()) { case INTERSECTION -> this.wrap(((IntersectionType)this.delegate()).getBounds()); - default -> List.of(); + default -> List.of(); }; } @@ -201,7 +205,7 @@ public final List getBounds() { public final TypeMirror getComponentType() { return switch (this.getKind()) { case ARRAY -> this.wrap(((ArrayType)this.delegate()).getComponentType()); - default -> NoType.NONE; + default -> NoType.NONE; }; } @@ -209,7 +213,7 @@ public final TypeMirror getComponentType() { public final TypeMirror getEnclosingType() { return switch(this.getKind()) { case DECLARED -> this.wrap(((DeclaredType)this.delegate()).getEnclosingType()); - default -> NoType.NONE; + default -> NoType.NONE; }; } @@ -217,7 +221,7 @@ public final TypeMirror getEnclosingType() { public final TypeMirror getExtendsBound() { return switch (this.getKind()) { case WILDCARD -> this.wrap(((WildcardType)this.delegate()).getExtendsBound()); - default -> null; + default -> null; }; } @@ -230,7 +234,7 @@ public final TypeKind getKind() { public final TypeMirror getLowerBound() { return switch (this.getKind()) { case TYPEVAR -> this.wrap(((TypeVariable)this.delegate()).getLowerBound()); - default -> org.microbean.lang.type.NullType.INSTANCE; // bottom type, not NONE type + default -> org.microbean.lang.type.NullType.INSTANCE; // bottom type, not NONE type }; } @@ -238,7 +242,7 @@ public final TypeMirror getLowerBound() { public final TypeMirror getUpperBound() { return switch (this.getKind()) { case TYPEVAR -> this.wrap(((TypeVariable)this.delegate()).getUpperBound()); - default -> this.wrap(this.elementSource.typeElement("java.lang.Object").asType()); + default -> this.wrap(this.elementSource.typeElement("java.lang.Object").asType()); }; } @@ -246,7 +250,7 @@ public final TypeMirror getUpperBound() { public final List getParameterTypes() { return switch (this.getKind()) { case EXECUTABLE -> this.wrap(((ExecutableType)this.delegate()).getParameterTypes()); - default -> List.of(); + default -> List.of(); }; } @@ -254,7 +258,7 @@ public final List getParameterTypes() { public final TypeMirror getReceiverType() { return switch (this.getKind()) { case EXECUTABLE -> this.wrap(((ExecutableType)this.delegate()).getReceiverType()); - default -> null; + default -> null; }; } @@ -262,7 +266,7 @@ public final TypeMirror getReceiverType() { public final TypeMirror getReturnType() { return switch (this.getKind()) { case EXECUTABLE -> this.wrap(((ExecutableType)this.delegate()).getReturnType()); - default -> null; + default -> null; }; } @@ -270,7 +274,7 @@ public final TypeMirror getReturnType() { public final TypeMirror getSuperBound() { return switch (this.getKind()) { case WILDCARD -> this.wrap(((WildcardType)this.delegate()).getSuperBound()); - default -> null; + default -> null; }; } @@ -278,7 +282,7 @@ public final TypeMirror getSuperBound() { public final List getThrownTypes() { return switch (this.getKind()) { case EXECUTABLE -> this.wrap(((ExecutableType)this.delegate()).getThrownTypes()); - default -> List.of(); + default -> List.of(); }; } @@ -286,7 +290,7 @@ public final List getThrownTypes() { public final List getTypeArguments() { return switch (this.getKind()) { case DECLARED -> this.wrap(((DeclaredType)this.delegate()).getTypeArguments()); - default -> List.of(); + default -> List.of(); }; } @@ -294,7 +298,7 @@ public final List getTypeArguments() { public final List getTypeVariables() { return switch (this.getKind()) { case EXECUTABLE -> this.wrap(((ExecutableType)this.delegate()).getTypeVariables()); - default -> List.of(); + default -> List.of(); }; }