From 500e3fec448f88d8b80ea67e2d92cb6b04d451bb Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Tue, 23 Jul 2024 15:19:15 -0700 Subject: [PATCH] Removes Jandex Maven module; other edits and cleanup (#19) Signed-off-by: Laird Nelson --- jandex/README.md | 43 - jandex/pom.xml | 91 - jandex/src/main/java/module-info.java | 33 - .../org/microbean/lang/jandex/Jandex.java | 1525 ----------------- .../microbean/lang/jandex/package-info.java | 24 - jandex/src/main/javadoc/css/fonts.css | 62 - jandex/src/site/markdown/index.md.vm | 1 - jandex/src/site/site.xml | 37 - .../lang/jandex/TestIsAssignable.java | 17 - .../org/microbean/lang/jandex/TestJandex.java | 299 ---- .../jandex/TestJandexAndTypeParameters.java | 82 - .../lang/jandex/TestJandexTypeUseIssue.java | 124 -- .../org/microbean/lang/jandex/TestObject.java | 96 -- .../microbean/lang/jandex/TestTypeUsages.java | 250 --- ...ypeUseAnnotationOnMethodParameterType.java | 101 -- .../lang/jandex/testjandex/Flabrous.java | 30 - .../lang/jandex/testjandex/Frobnicator.java | 25 - .../lang/jandex/testjandex/package-info.java | 18 - .../main/java/org/microbean/lang/Lang.java | 5 + .../microbean/lang/TypeAndElementSource.java | 10 +- .../lang/element/DelegatingElement.java | 40 +- .../org/microbean/lang/element/Element.java | 21 +- .../lang/type/DelegatingTypeMirror.java | 78 +- .../org/microbean/lang/type/TypeMirror.java | 4 +- .../org/microbean/lang/type/TypeVariable.java | 40 +- .../java/org/microbean/lang/type/Types.java | 87 +- .../lang/visitor/AdaptingVisitor.java | 35 +- .../lang/visitor/AsSuperVisitor.java | 17 +- .../lang/visitor/BoundingClassVisitor.java | 19 +- .../lang/visitor/CaptureVisitor.java | 35 +- .../lang/visitor/ContainsTypeVisitor.java | 25 +- .../microbean/lang/visitor/EraseVisitor.java | 19 +- .../lang/visitor/InterfacesVisitor.java | 16 +- .../lang/visitor/MemberTypeVisitor.java | 30 +- .../lang/visitor/SameTypeVisitor.java | 37 +- .../lang/visitor/StructuralTypeMapping.java | 31 +- .../lang/visitor/SubstituteVisitor.java | 40 +- .../lang/visitor/SubtypeVisitor.java | 33 +- .../lang/visitor/SupertypeVisitor.java | 7 +- .../microbean/lang/visitor/TypeClosure.java | 43 +- .../lang/visitor/TypeClosureVisitor.java | 18 +- .../lang/visitor/TypeMirrorPair.java | 32 +- .../lang/visitor/ValidatingVisitor.java | 19 +- .../org/microbean/lang/visitor/Visitors.java | 2 +- .../java/org/microbean/lang/TestErase.java | 18 +- .../microbean/lang/TestSameTypeVisitor.java | 18 +- .../microbean/lang/TestSupertypeVisitor.java | 18 +- .../org/microbean/lang/TestTypeClosure.java | 11 +- pom.xml | 21 +- 49 files changed, 388 insertions(+), 3299 deletions(-) delete mode 100644 jandex/README.md delete mode 100644 jandex/pom.xml delete mode 100644 jandex/src/main/java/module-info.java delete mode 100644 jandex/src/main/java/org/microbean/lang/jandex/Jandex.java delete mode 100644 jandex/src/main/java/org/microbean/lang/jandex/package-info.java delete mode 100644 jandex/src/main/javadoc/css/fonts.css delete mode 100644 jandex/src/site/markdown/index.md.vm delete mode 100644 jandex/src/site/site.xml delete mode 100644 jandex/src/test/java/org/microbean/lang/jandex/TestIsAssignable.java delete mode 100644 jandex/src/test/java/org/microbean/lang/jandex/TestJandex.java delete mode 100644 jandex/src/test/java/org/microbean/lang/jandex/TestJandexAndTypeParameters.java delete mode 100644 jandex/src/test/java/org/microbean/lang/jandex/TestJandexTypeUseIssue.java delete mode 100644 jandex/src/test/java/org/microbean/lang/jandex/TestObject.java delete mode 100644 jandex/src/test/java/org/microbean/lang/jandex/TestTypeUsages.java delete mode 100644 jandex/src/test/java/org/microbean/lang/jandex/TestTypeUseAnnotationOnMethodParameterType.java delete mode 100644 jandex/src/test/java/org/microbean/lang/jandex/testjandex/Flabrous.java delete mode 100644 jandex/src/test/java/org/microbean/lang/jandex/testjandex/Frobnicator.java delete mode 100644 jandex/src/test/java/org/microbean/lang/jandex/testjandex/package-info.java diff --git a/jandex/README.md b/jandex/README.md deleted file mode 100644 index aba30e6f..00000000 --- a/jandex/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# microBean™ Lang: Jandex - -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.microbean/microbean-lang-jandex/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.microbean/microbean-lang-jandex) - -The microBean™ Lang: Jandex project provides classes and interfaces that implement the Java language model from Jandex -constructs. - -# Status - -This project is currently experimental, in a pre-alpha state, and unsuitable for production use. - -# Compatibility - -**Until further notice, this project's APIs are subject to frequent backwards-incompatible signature and behavior -changes, regardless of project version and without notice.** - -# Requirements - -microBean™ Lang: Jandex requires a Java runtime of version 19 or higher. - -# Installation - -microBean™ Lang: Jandex is or will be available on [Maven Central](https://search.maven.org/). Include microBean™ Lang: -Jandex as a Maven dependency: - -```xml - - org.microbean - microbean-lang-jandex - - 0.0.1 - -``` - -# Documentation - -Full documentation is or will be available at -[microbean.github.io/microbean-lang-jandex](https://microbean.github.io/microbean-lang-jandex/). - -# Related Issues - -* https://github.com/smallrye/jandex/issues/167 - diff --git a/jandex/pom.xml b/jandex/pom.xml deleted file mode 100644 index d5a5c45a..00000000 --- a/jandex/pom.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - 4.0.0 - - microbean-lang-jandex - - - org.microbean - microbean-lang-parent - 0.0.18-SNAPSHOT - - - microBean™ Lang: Jandex - microBean™ Lang: Jandex: An implementation of the Java language model using Jandex constructs. - - - - - - - io.smallrye - jandex - jar - compile - - - - ${project.groupId} - microbean-lang - jar - compile - - - - - - org.hamcrest - hamcrest - jar - test - - - - org.junit.jupiter - junit-jupiter-api - jar - test - - - - org.junit.jupiter - junit-jupiter-engine - jar - test - - - - - - - deployment - - - - maven-javadoc-plugin - - - attach-javadocs - - jar - - - - - - maven-source-plugin - - - attach-sources - - jar-no-fork - - - - - - - - - - diff --git a/jandex/src/main/java/module-info.java b/jandex/src/main/java/module-info.java deleted file mode 100644 index 59736fc9..00000000 --- a/jandex/src/main/java/module-info.java +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * Provides packages related to the Java language model and Jandex. - * - * @author Laird Nelson - */ -@SuppressWarnings({ "requires-automatic", "requires-transitive-automatic" }) -module org.microbean.lang.jandex { - - requires transitive java.compiler; - requires transitive org.jboss.jandex; // yes, even though it's at SmallRye - requires transitive org.microbean.lang; - - exports org.microbean.lang.jandex; - -} diff --git a/jandex/src/main/java/org/microbean/lang/jandex/Jandex.java b/jandex/src/main/java/org/microbean/lang/jandex/Jandex.java deleted file mode 100644 index 839f2920..00000000 --- a/jandex/src/main/java/org/microbean/lang/jandex/Jandex.java +++ /dev/null @@ -1,1525 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023–2024 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package org.microbean.lang.jandex; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import java.util.function.BiFunction; - -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.ModuleElement; -import javax.lang.model.element.NestingKind; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.RecordComponentElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.TypeParameterElement; -import javax.lang.model.element.VariableElement; - -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.ExecutableType; -import javax.lang.model.type.NoType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.TypeVariable; -import javax.lang.model.type.WildcardType; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.ClassInfo.EnclosingMethodInfo; -import org.jboss.jandex.ClassInfo.NestingType; -import org.jboss.jandex.ClassType; -import org.jboss.jandex.DotName; -import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.IndexView; -import org.jboss.jandex.MethodInfo; -import org.jboss.jandex.MethodParameterInfo; -import org.jboss.jandex.ModuleInfo; -import org.jboss.jandex.ModuleInfo.ExportedPackageInfo; -import org.jboss.jandex.ModuleInfo.OpenedPackageInfo; -import org.jboss.jandex.ModuleInfo.ProvidedServiceInfo; -import org.jboss.jandex.ModuleInfo.RequiredModuleInfo; -import org.jboss.jandex.ParameterizedType; -import org.jboss.jandex.PrimitiveType; -import org.jboss.jandex.RecordComponentInfo; -import org.jboss.jandex.Type; -import org.jboss.jandex.TypeParameterTypeTarget; - -import org.microbean.lang.Modeler; - -public final class Jandex extends Modeler { - - private static final Type[] EMPTY_TYPE_ARRAY = new Type[0]; - - private final IndexView i; - - private final BiFunction unindexedClassnameFunction; - - public Jandex(final IndexView i) { - this(i, (n, j) -> { - throw new IllegalArgumentException("class " + n + " not found in IndexView " + j); - }); - } - - public Jandex(final IndexView i, final BiFunction unindexedClassnameFunction) { - super(); - this.i = Objects.requireNonNull(i, "i"); - this.unindexedClassnameFunction = Objects.requireNonNull(unindexedClassnameFunction, "unindexedClassnameFunction"); - } - - public final AnnotationMirror annotation(final AnnotationInstance k) { - return this.annotation(k, org.microbean.lang.element.AnnotationMirror::new, this::build); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final Object v) { - return switch (v) { - case null -> null; - case AnnotationInstance a -> this.annotationValue(a); - case AnnotationMirror a -> this.annotationValue(a); - case javax.lang.model.element.AnnotationValue a -> this.annotationValue(a); - case org.jboss.jandex.AnnotationValue a -> this.annotationValue(a); - case org.jboss.jandex.ClassType c -> this.annotationValue(c); - case Boolean b -> this.annotationValue(b); - case Byte b -> this.annotationValue(b); - case CharSequence s -> this.annotationValue(s); - case Character c -> this.annotationValue(c); - case Collection c -> this.annotationValue(c); - case Double d -> this.annotationValue(d); - case FieldInfo f -> this.annotationValue(f); - case Float f -> this.annotationValue(f); - case Integer i -> this.annotationValue(i); - case Long l -> this.annotationValue(l); - case Object[] o -> this.annotationValue(o); - case Short s -> this.annotationValue(s); - case TypeMirror t -> this.annotationValue(t); - case VariableElement ve -> this.annotationValue(ve); - case boolean[] o -> this.annotationValue(o); - case byte[] o -> this.annotationValue(o); - case char[] o -> this.annotationValue(o); - case double[] o -> this.annotationValue(o); - case float[] o -> this.annotationValue(o); - case int[] o -> this.annotationValue(o); - case long[] o -> this.annotationValue(o); - case short[] o -> this.annotationValue(o); - default -> throw new IllegalArgumentException("v: " + v + (v == null ? "" : "; v.getClass(): " + v.getClass().getName())); - }; - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final AnnotationMirror a) { - return a == null ? null : new org.microbean.lang.element.AnnotationValue(a); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final AnnotationInstance a) { - return a == null ? null : this.annotationValue(this.annotation(a)); - } - - public final V annotationValue(final V v) { - return v; - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final org.jboss.jandex.AnnotationValue v) { - return v == null ? null : switch (v.kind()) { - case ARRAY, BOOLEAN, BYTE, CHARACTER, CLASS, DOUBLE, FLOAT, INTEGER, LONG, NESTED, SHORT, STRING -> this.annotationValue(v.value()); - case ENUM -> this.annotationValue(this.classInfoFor(v.asEnumType()).field(v.asEnum())); - case UNKNOWN -> new org.microbean.lang.element.AnnotationValue(List.of()); - }; - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final Boolean b) { - return b == null ? null : new org.microbean.lang.element.AnnotationValue(b); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final Byte b) { - return b == null ? null : new org.microbean.lang.element.AnnotationValue(b); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final Character c) { - return c == null ? null : new org.microbean.lang.element.AnnotationValue(c); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final CharSequence s) { - return new org.microbean.lang.element.AnnotationValue(s == null ? "" : s.toString()); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final Collection c) { - return new org.microbean.lang.element.AnnotationValue(this.annotationValues(c == null ? List.of() : c)); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final Double d) { - return d == null ? null : new org.microbean.lang.element.AnnotationValue(d); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final ClassInfo c) { - return c == null ? null : this.annotationValue(c.name()); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final ClassType c) { - return c == null ? null : this.annotationValue(c.name()); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final DotName n) { - return n == null ? null : new org.microbean.lang.element.AnnotationValue(n); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final FieldInfo enumConstant) { - if (enumConstant == null) { - return null; - } else if (enumConstant.isEnumConstant() && enumConstant.declaringClass().isEnum()) { - return new org.microbean.lang.element.AnnotationValue(this.element(enumConstant)); - } - throw new IllegalArgumentException("enumConstant: " + enumConstant); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final Float f) { - return f == null ? null : new org.microbean.lang.element.AnnotationValue(f); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final Integer i) { - return i == null ? null : new org.microbean.lang.element.AnnotationValue(i); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final Long l) { - return l == null ? null : new org.microbean.lang.element.AnnotationValue(l); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final Object[] o) { - return new org.microbean.lang.element.AnnotationValue(this.annotationValues(o)); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final Short s) { - return s == null ? null : new org.microbean.lang.element.AnnotationValue(s); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final TypeMirror t) { - return t == null ? null : new org.microbean.lang.element.AnnotationValue(t); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final VariableElement enumConstant) { - if (enumConstant == null) { - return null; - } else if (enumConstant.getKind() == ElementKind.ENUM_CONSTANT) { - return new org.microbean.lang.element.AnnotationValue(enumConstant); - } - throw new IllegalArgumentException("enumConstant: " + enumConstant); - } - - public final List annotationValues(final Collection c) { - if (c == null || c.isEmpty()) { - return List.of(); - } - final List list = new ArrayList<>(c.size()); - for (final Object value : c) { - list.add(this.annotationValue(value)); - } - return Collections.unmodifiableList(list); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final boolean[] o) { - return o == null ? null : this.annotationValue(this.annotationValues(o)); - } - - public final List annotationValues(final boolean[] o) { - if (o == null || o.length <= 0) { - return List.of(); - } - final List list = new ArrayList<>(o.length); - for (final boolean value : o) { - list.add(this.annotationValue(value)); - } - return Collections.unmodifiableList(list); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final byte[] o) { - return o == null ? null : this.annotationValue(this.annotationValues(o)); - } - - public final List annotationValues(final byte[] o) { - if (o == null || o.length <= 0) { - return List.of(); - } - final List list = new ArrayList<>(o.length); - for (final byte value : o) { - list.add(this.annotationValue(value)); - } - return Collections.unmodifiableList(list); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final char[] o) { - return o == null ? null : this.annotationValue(this.annotationValues(o)); - } - - public final List annotationValues(final char[] o) { - if (o == null || o.length <= 0) { - return List.of(); - } - final List list = new ArrayList<>(o.length); - for (final char value : o) { - list.add(this.annotationValue(value)); - } - return Collections.unmodifiableList(list); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final double[] o) { - return o == null ? null : this.annotationValue(this.annotationValues(o)); - } - - public final List annotationValues(final double[] o) { - if (o == null || o.length <= 0) { - return List.of(); - } - final List list = new ArrayList<>(o.length); - for (final double value : o) { - list.add(this.annotationValue(value)); - } - return Collections.unmodifiableList(list); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final float[] o) { - return o == null ? null : this.annotationValue(this.annotationValues(o)); - } - - public final List annotationValues(final float[] o) { - if (o == null || o.length <= 0) { - return List.of(); - } - final List list = new ArrayList<>(o.length); - for (final float value : o) { - list.add(this.annotationValue(value)); - } - return Collections.unmodifiableList(list); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final int[] o) { - return o == null ? null : this.annotationValue(this.annotationValues(o)); - } - - public final List annotationValues(final int[] o) { - if (o == null || o.length <= 0) { - return List.of(); - } - final List list = new ArrayList<>(o.length); - for (final int value : o) { - list.add(this.annotationValue(value)); - } - return Collections.unmodifiableList(list); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final long[] o) { - return o == null ? null : this.annotationValue(this.annotationValues(o)); - } - - public final List annotationValues(final long[] o) { - if (o == null || o.length <= 0) { - return List.of(); - } - final List list = new ArrayList<>(o.length); - for (final long value : o) { - list.add(this.annotationValue(value)); - } - return Collections.unmodifiableList(list); - } - - public final javax.lang.model.element.AnnotationValue annotationValue(final short[] o) { - return o == null ? null : this.annotationValue(this.annotationValues(o)); - } - - public final List annotationValues(final short[] o) { - if (o == null || o.length <= 0) { - return List.of(); - } - final List list = new ArrayList<>(o.length); - for (final short value : o) { - list.add(this.annotationValue(value)); - } - return Collections.unmodifiableList(list); - } - - public final List annotationValues(final Object[] o) { - if (o == null || o.length <= 0) { - return List.of(); - } - final List list = new ArrayList<>(o.length); - for (final Object value : o) { - list.add(this.annotationValue(value)); - } - return Collections.unmodifiableList(list); - } - - - /* - * Element methods. - */ - - - public final Element element(final DotName n) { - final ClassInfo ci = this.classInfoFor(n); - return ci == null ? null : this.element(ci); - } - - @Override // TypeAndElementSource - public final TypeElement typeElement(final ModuleElement m, final CharSequence n) { - return this.typeElement(n); - } - - @Override // TypeAndElementSource - public final TypeElement typeElement(final CharSequence n) { - final ClassInfo ci = this.classInfoFor(n.toString()); - return - ci == null || ci.isModule() ? null : - (TypeElement)this.element(ci); - } - - public final PackageElement packageElement(final DotName n) { - return n == null ? null : this.element(new PackageInfo(n)); - } - - public final PackageElement packageElement(final String n) { - return n == null ? null : this.packageElement(DotName.createSimple(n)); - } - - public final ModuleElement element(final ModuleInfo mi) { - return mi == null ? null : this.element(mi, () -> new org.microbean.lang.element.ModuleElement(mi.isOpen()), this::build); - } - - public final PackageElement element(final PackageInfo pi) { - return pi == null ? null : this.element(pi, org.microbean.lang.element.PackageElement::new, this::build); - } - - public final TypeElement element(final AnnotationInstance ai) { - return ai == null ? null : (TypeElement)this.element(this.classInfoFor(ai.name())); - } - - public final Element element(final ClassInfo ci) { - if (ci == null) { - return null; - } else if (ci.isModule()) { - return this.element(ci.module()); - } else { - return this.element(ci, () -> new org.microbean.lang.element.TypeElement(kind(ci), nestingKind(ci)), this::build); - } - } - - public final Element element(final ClassType ct) { - return ct == null ? null : this.element(this.classInfoFor(ct)); - } - - public final E element(final E e) { - return e; - } - - public final ExecutableElement element(final EnclosingMethodInfo emi) { - return emi == null ? null : this.element(this.classInfoFor(emi.enclosingClass()).method(emi.name(), emi.parameters().toArray(EMPTY_TYPE_ARRAY))); - } - - public final VariableElement element(final FieldInfo fi) { - return fi == null ? null : this.element(fi, () -> new org.microbean.lang.element.VariableElement(kind(fi)), this::build); - } - - public final ExecutableElement element(final MethodInfo mi) { - return mi == null ? null : this.element(mi, () -> new org.microbean.lang.element.ExecutableElement(kind(mi)), this::build); - } - - public final VariableElement element(final MethodParameterInfo mpi) { - return mpi == null ? null : this.element(mpi, () -> new org.microbean.lang.element.VariableElement(ElementKind.PARAMETER), this::build); - } - - public final RecordComponentElement element(final RecordComponentInfo rci) { - return rci == null ? null : this.element(rci, org.microbean.lang.element.RecordComponentElement::new, this::build); - } - - public final TypeParameterElement element(final TypeParameterInfo tpi) { - return tpi == null ? null : this.element(tpi, org.microbean.lang.element.TypeParameterElement::new, this::build); - } - - public final TypeParameterElement element(final TypeParameterTypeTarget tt) { - return tt == null ? null : this.element(new TypeParameterInfo(tt.enclosingTarget(), tt.target().asTypeVariable())); - } - - - /* - * Type methods. - */ - - - public final DeclaredType type(final AnnotationInstance ai) { - return ai == null ? null : this.type(this.classInfoFor(ai)); - } - - public final DeclaredType type(final ClassInfo ci) { - if (ci == null) { - return null; - } else if (ci.isModule()) { - throw new UnsupportedOperationException("Not yet handled"); - } else { - return this.type(ci, org.microbean.lang.type.DeclaredType::new, this::build); - } - } - - public final TypeMirror type(final FieldInfo fi) { - if (fi == null) { - return null; - } - final Type t = fi.type(); - return switch (t.kind()) { - case ARRAY -> this.type(fi, org.microbean.lang.type.ArrayType::new, this::build); - case CLASS, PARAMETERIZED_TYPE -> this.type(fi, org.microbean.lang.type.DeclaredType::new, this::build); - case PRIMITIVE -> this.type(fi, () -> new org.microbean.lang.type.PrimitiveType(kind(t.asPrimitiveType())), this::build); - case TYPE_VARIABLE -> this.type(fi, () -> new org.microbean.lang.type.TypeVariable(this), this::build); - default -> throw new IllegalStateException("t: " + t); - }; - } - - public final ExecutableType type(final MethodInfo mi) { - return mi == null ? null : this.type(mi, org.microbean.lang.type.ExecutableType::new, this::build); - } - - public final TypeMirror type(final MethodParameterInfo mpi) { - if (mpi == null) { - return null; - } - final Type t = mpi.type(); - return switch (t.kind()) { - case ARRAY -> this.type(mpi, org.microbean.lang.type.ArrayType::new, this::build); - case CLASS, PARAMETERIZED_TYPE -> this.type(mpi, org.microbean.lang.type.DeclaredType::new, this::build); - case PRIMITIVE -> this.type(mpi, () -> new org.microbean.lang.type.PrimitiveType(kind(t.asPrimitiveType())), this::build); - case TYPE_VARIABLE -> this.type(mpi, () -> new org.microbean.lang.type.TypeVariable(this), this::build); - default -> throw new IllegalStateException("t: " + t); - }; - } - - public final TypeMirror type(final RecordComponentInfo rci) { - if (rci == null) { - return null; - } - final Type t = rci.type(); - return switch (t.kind()) { - case ARRAY -> this.type(rci, org.microbean.lang.type.ArrayType::new, this::build); - case CLASS, PARAMETERIZED_TYPE -> this.type(rci, org.microbean.lang.type.DeclaredType::new, this::build); - case PRIMITIVE -> this.type(rci, () -> new org.microbean.lang.type.PrimitiveType(kind(t.asPrimitiveType())), this::build); - case TYPE_VARIABLE -> this.type(rci, () -> new org.microbean.lang.type.TypeVariable(this), this::build); - default -> throw new IllegalStateException("rci.type(): " + t); - }; - } - - public final TypeMirror type(final TypeContext k) { - final Type type = k == null ? null : k.type(); - return type == null ? null : switch (type.kind()) { - case ARRAY -> this.type(k, org.microbean.lang.type.ArrayType::new, this::build); - case CLASS, PARAMETERIZED_TYPE -> this.type(k, org.microbean.lang.type.DeclaredType::new, this::build); - case PRIMITIVE -> this.type(type.asPrimitiveType(), () -> new org.microbean.lang.type.PrimitiveType(kind(type.asPrimitiveType())), this::build); - case TYPE_VARIABLE -> this.type(this.typeParameterInfoFor(k)); - // k.kind() had better be TYPE_ARGUMENT below? - case TYPE_VARIABLE_REFERENCE -> this.type(new TypeContext(k.context(), type.asTypeVariableReference().follow(), k.position(), k.kind())); - case UNRESOLVED_TYPE_VARIABLE -> throw new AssertionError(); - case VOID -> org.microbean.lang.type.NoType.VOID; - case WILDCARD_TYPE -> this.type(k, org.microbean.lang.type.WildcardType::new, this::build); - }; - } - - public final T type(final T t) { - return t; - } - - public final javax.lang.model.type.TypeVariable type(final TypeParameterInfo tpi) { - return tpi == null ? null : this.type(tpi, () -> new org.microbean.lang.type.TypeVariable(this), this::build); - } - - @Override // TypeAndElementSource - public final javax.lang.model.type.ArrayType arrayTypeOf(final TypeMirror componentType) { - throw new UnsupportedOperationException("TODO"); - } - - @Override // TypeAndElementSource - public final boolean assignable(final TypeMirror t, final TypeMirror s) { - throw new UnsupportedOperationException("TODO"); - } - - @Override // TypeAndElementSource - public final TypeElement boxedClass(final javax.lang.model.type.PrimitiveType t) { - throw new UnsupportedOperationException("TODO"); - } - - @Override // TypeAndElementSource - public final T erasure(final T t) { - throw new UnsupportedOperationException("TODO"); - } - - @Override // TypeAndElementSource - public final NoType noType(final TypeKind k) { - throw new UnsupportedOperationException("TODO"); - } - - @Override // TypeAndElementSource - public final javax.lang.model.type.PrimitiveType primitiveType(final TypeKind k) { - throw new UnsupportedOperationException("TODO"); - } - - @Override // TypeAndElementSource - public final DeclaredType declaredType(final DeclaredType containingType, final TypeElement typeElement, final TypeMirror... arguments) { - throw new UnsupportedOperationException("TODO"); - } - - @Override // TypeAndElementSource - public final DeclaredType declaredType(final TypeElement typeElement, final TypeMirror... arguments) { - throw new UnsupportedOperationException("TODO"); - } - - @Override // TypeAndElementSource - public final List directSupertypes(final TypeMirror t) { - throw new UnsupportedOperationException("TODO"); - } - - @Override // TypeAndElementSOurce - public final ModuleElement moduleElement(final CharSequence n) { - throw new UnsupportedOperationException("TODO"); - } - - @Override // TypeAndElementSource - public final boolean sameType(final TypeMirror t, final TypeMirror s) { - throw new UnsupportedOperationException("TODO"); - } - - @Override // TypeAndElementSource - public final TypeVariable typeVariable(final java.lang.reflect.TypeVariable t) { - throw new UnsupportedOperationException("TODO"); - } - - public final WildcardType wildcardType(final TypeMirror extendsBound, final TypeMirror superBound) { - throw new UnsupportedOperationException("TODO"); - } - - - - - /* - * Annotation builders. - */ - - - private final void build(final AnnotationInstance ai, final org.microbean.lang.element.AnnotationMirror am) { - final ClassInfo annotationClass = this.classInfoFor(ai.name()); - - final org.microbean.lang.type.DeclaredType t = (org.microbean.lang.type.DeclaredType)this.type(annotationClass); - assert t.asElement() != null; - am.setAnnotationType(t); - - for (final org.jboss.jandex.AnnotationValue v : ai.values()) { - final javax.lang.model.element.ExecutableElement ee = this.element(this.annotationElementFor(annotationClass, v.name())); - assert ee.getEnclosingElement() != null : "ee: " + ee + "; ai: " + ai + "; annotationClass: " + annotationClass + "; v: " + v; - am.putElementValue(ee, this.annotationValue(v)); - } - } - - - /* - * Element builders. - */ - - - private final void build(final ModuleInfo mi, final org.microbean.lang.element.ModuleElement e) { - - // Simple name. - e.setSimpleName(mi.name().toString()); - - // Type. - e.setType(org.microbean.lang.type.NoType.MODULE); - - for (final RequiredModuleInfo rmi : mi.requires()) { - final ModuleInfo rmiMi = this.i.getModuleByName(rmi.name()); - if (rmiMi != null) { - e.addDirective(new org.microbean.lang.element.ModuleElement.RequiresDirective(this.element(rmiMi), - rmi.isStatic(), - rmi.isTransitive())); - } - } - - for (final ExportedPackageInfo epi : mi.exports()) { - final List epiTargets = epi.targets(); - final List targets = new ArrayList<>(epiTargets.size()); - for (final DotName epiTarget : epiTargets) { - final ModuleInfo epiMi = this.i.getModuleByName(epiTarget); - if (epiMi != null) { - targets.add(this.element(epiMi)); - } - } - e.addDirective(new org.microbean.lang.element.ModuleElement.ExportsDirective(this.packageElement(epi.source()), targets)); - } - - for (final OpenedPackageInfo opi : mi.opens()) { - final List opiTargets = opi.targets(); - final List targets = new ArrayList<>(opiTargets.size()); - for (final DotName opiTarget : opiTargets) { - final ModuleInfo epiMi = this.i.getModuleByName(opiTarget); - if (epiMi != null) { - targets.add(this.element(epiMi)); - } - } - e.addDirective(new org.microbean.lang.element.ModuleElement.OpensDirective(this.packageElement(opi.source()), targets)); - } - - for (final ProvidedServiceInfo psi : mi.provides()) { - final List psiProviders = psi.providers(); - final List providers = new ArrayList<>(psiProviders.size()); - for (final DotName psiTarget : psiProviders) { - providers.add((TypeElement)this.element(this.classInfoFor(psiTarget))); - } - e.addDirective(new org.microbean.lang.element.ModuleElement.ProvidesDirective((TypeElement)this.element(psi.service()), providers)); - } - - e.setEnclosedElementsGenerator(() -> { - for (final DotName pn : mi.packages()) { - this.packageElement(pn); - } - }); - - for (final AnnotationInstance ai : mi.annotations()) { - e.addAnnotationMirror(this.annotation(ai)); - } - - } - - private final void build(final PackageInfo pi, final org.microbean.lang.element.PackageElement e) { - final DotName pn = pi.name(); - - // Simple name. - e.setSimpleName(pn.toString()); - - // Type. - e.setType(org.microbean.lang.type.NoType.PACKAGE); - - // Enclosing element. - e.setEnclosingElement(this.element(this.i.getKnownModules().stream() - .filter(m -> m.packages().contains(pn)) - .findFirst() - .orElse(null))); - - e.setEnclosedElementsGenerator(() -> this.i.getClassesInPackage(pn).forEach(this::element)); - } - - private final void build(final ClassInfo ci, final org.microbean.lang.element.TypeElement e) { - // Simple name. - e.setSimpleName(ci.name().local()); - - // Type. Note that we haven't done type parameters yet, so the type arguments belonging to the type won't have - // corresponding type parameters yet. - final org.microbean.lang.type.DeclaredType t = (org.microbean.lang.type.DeclaredType)this.type(ci); - e.setType(t); - - // Defining element. - t.setDefiningElement(e); - - e.setEnclosingElement(switch (e.getNestingKind()) { - // Anonymous and local classes are effectively ignored in the javax.lang.model.* hierarchy. The documentation for - // javax.lang.model.element.Element#getEnclosedElements() says, in part: "A class or interface is considered to - // enclose the fields, methods, constructors, record components, and member classes and interfaces that it directly - // declares. A package encloses the top-level classes and interfaces within it, but is not considered to enclose - // subpackages. A module encloses packages within it. Enclosed elements may include implicitly declared mandated - // elements. Other kinds of elements are not currently considered to enclose any elements; however, that may change - // as this API or the programming language evolves." - // - // Additionally, Jandex provides no access to local or anonymous classes at all. - case ANONYMOUS, LOCAL -> null; - case MEMBER -> this.element(this.classInfoFor(ci.enclosingClass())); - case TOP_LEVEL -> this.packageElement(ci.name().prefix()); - }); - - // Modifiers. - final short modifiers = ci.flags(); - if (java.lang.reflect.Modifier.isAbstract(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.ABSTRACT); - } else if (java.lang.reflect.Modifier.isFinal(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.FINAL); - } - if (java.lang.reflect.Modifier.isPrivate(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.PRIVATE); - } else if (java.lang.reflect.Modifier.isProtected(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.PROTECTED); - } else if (java.lang.reflect.Modifier.isPublic(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.PUBLIC); - } - // TODO: no way to tell if a ClassInfo is sealed. See https://github.com/smallrye/jandex/issues/167. - if (java.lang.reflect.Modifier.isStatic(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.STATIC); - } - - // Supertypes. - int position = 0; - final Type superclassType = ci.superClassType(); - if (superclassType != null) { - assert superclassType.kind() == Type.Kind.CLASS || superclassType.kind() == Type.Kind.PARAMETERIZED_TYPE; - e.setSuperclass(this.type(new TypeContext(ci, superclassType, position++, TypeContext.Kind.EXTENDS))); - } - for (final Type iface : ci.interfaceTypes()) { - e.addInterface(this.type(new TypeContext(ci, iface, position++, TypeContext.Kind.EXTENDS))); - } - position = 0; - - // Type parameters. - for (final org.jboss.jandex.TypeVariable tp : ci.typeParameters()) { - final org.microbean.lang.element.TypeParameterElement tpe = - (org.microbean.lang.element.TypeParameterElement)this.element(new TypeParameterInfo(ci, tp)); - assert ((javax.lang.model.type.TypeVariable)tpe.asType()).asElement() == tpe : - "tpe.asType(): " + tpe.asType() + - "; tpe.asType().asElement(): " + ((javax.lang.model.type.TypeVariable)tpe.asType()).asElement(); - e.addTypeParameter(tpe); - } - assert e.getTypeParameters().size() == ci.typeParameters().size(); - - e.setEnclosedElementsGenerator(() -> { - ci.constructors().forEach(this::element); - ci.unsortedRecordComponents().forEach(this::element); - ci.unsortedFields().forEach(this::element); - ci.unsortedMethods().forEach(this::element); - ci.memberClasses().forEach(this::element); - }); - - for (final AnnotationInstance ai : ci.declaredAnnotations()) { - e.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final FieldInfo fi, final org.microbean.lang.element.VariableElement e) { - // Simple name. - e.setSimpleName(fi.name()); - - // Type. - e.setType(this.type(fi)); - - // Enclosing element. - e.setEnclosingElement(this.element(fi.declaringClass())); - - // Annotations. - for (final AnnotationInstance ai : fi.declaredAnnotations()) { - e.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final MethodInfo mi, final org.microbean.lang.element.ExecutableElement e) { - // Simple name. - if (!mi.isConstructor()) { - e.setSimpleName(mi.name()); - } - - // Type. - e.setType(this.type(mi)); - - // Enclosing element. - final TypeElement ee = (TypeElement)this.element(mi.declaringClass()); - assert ee != null; - e.setEnclosingElement(ee); - assert e.getEnclosingElement() == ee : "e: " + e + "; ee: " + ee; - - // Modifiers. - final short modifiers = mi.flags(); - if (isDefault(mi)) { - e.setDefault(true); - e.addModifier(javax.lang.model.element.Modifier.DEFAULT); - } else { - e.setDefault(false); - if (java.lang.reflect.Modifier.isAbstract(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.ABSTRACT); - } else if (java.lang.reflect.Modifier.isFinal(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.FINAL); - } else if (java.lang.reflect.Modifier.isNative(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.NATIVE); - } - if (java.lang.reflect.Modifier.isStatic(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.STATIC); - } - if (java.lang.reflect.Modifier.isSynchronized(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.SYNCHRONIZED); - } - } - if (java.lang.reflect.Modifier.isPrivate(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.PRIVATE); - } else if (java.lang.reflect.Modifier.isProtected(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.PROTECTED); - } else if (java.lang.reflect.Modifier.isPublic(modifiers)) { - e.addModifier(javax.lang.model.element.Modifier.PUBLIC); - } - - // Type parameters. - for (final org.jboss.jandex.TypeVariable tp : mi.typeParameters()) { - e.addTypeParameter((org.microbean.lang.element.TypeParameterElement)this.element(new TypeParameterInfo(mi, tp))); - } - - // Parameters. - for (final MethodParameterInfo p : mi.parameters()) { - e.addParameter((org.microbean.lang.element.VariableElement)this.element(p)); - } - - for (final AnnotationInstance ai : mi.declaredAnnotations()) { - e.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final MethodParameterInfo mpi, final org.microbean.lang.element.VariableElement e) { - // Simple name. - String n = mpi.name(); - if (n == null) { - n = "arg" + mpi.position(); - } - e.setSimpleName(n); - - // Type. - e.setType(this.type(mpi)); - - // (No enclosing element.) - // e.setEnclosingElement(this.element(mpi.method())); // interestingly not supported by the javax.lang.model.* api - - for (final AnnotationInstance ai : mpi.declaredAnnotations()) { - e.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final RecordComponentInfo r, final org.microbean.lang.element.RecordComponentElement e) { - // Simple name. - e.setSimpleName(r.name()); - - // Type. - e.setType(this.type(r)); - - // Enclosing element. - e.setEnclosingElement(this.element(r)); - - e.setAccessor((org.microbean.lang.element.ExecutableElement)this.element(r.declaringClass().method(r.name()))); - - for (final AnnotationInstance ai : r.declaredAnnotations()) { - e.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final TypeParameterInfo tpi, final org.microbean.lang.element.TypeParameterElement e) { - // Simple name. - e.setSimpleName(tpi.identifier()); - - // Type. - final org.microbean.lang.type.TypeVariable t = (org.microbean.lang.type.TypeVariable)this.type(tpi); - e.setType(t); - - // Defining element. - t.setDefiningElement(e); - - // Enclosing element. - e.setEnclosingElement(switch (tpi.kind()) { - case CLASS -> this.element(tpi.annotationTarget().asClass()); - case METHOD -> this.element(tpi.annotationTarget().asMethod()); - default -> throw new AssertionError(); - }); - - for (final AnnotationInstance ai : tpi.typeVariable().annotations()) { - // This is nice, in a way. We know all of these annotations will be type use annotations, because Jandex doesn't - // really reify type parameters. - // - // Then we know that they can't be CLASS_EXTENDS, EMPTY, METHOD_PARAMETER, THROWS or TYPE_PARAMETER_BOUND, so they - // must be TYPE_PARAMETER. We can't check, because ai.target() is guaranteed by javadoc to be null. But as you can - // see we don't need to check. - e.addAnnotationMirror(this.annotation(ai)); - } - } - - - /* - * Type builders. - */ - - - private final void build(final TypeContext tc, final org.microbean.lang.type.ArrayType t) { - final org.jboss.jandex.ArrayType a = tc.type().asArrayType(); - final Type componentType = a.constituent(); - t.setComponentType(this.type(new TypeContext(tc.context(), componentType, 0, TypeContext.Kind.COMPONENT_TYPE))); - for (final AnnotationInstance ai : a.annotations()) { - t.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final TypeContext tc, final org.microbean.lang.type.DeclaredType t) { - final Type tct = tc.type(); - final ClassInfo ci = this.classInfoFor(tct); - t.setDefiningElement((TypeElement)this.element(ci)); - switch (tct.kind()) { - case CLASS: - t.setEnclosingType(this.type(this.classInfoFor(ci.enclosingClass()))); - break; - case PARAMETERIZED_TYPE: - final ParameterizedType pt = tct.asParameterizedType(); - final Type ownerType = pt.owner(); - t.setEnclosingType(this.type(ownerType == null ? this.classInfoFor(ci.enclosingClass()) : this.classInfoFor(ownerType))); - int position = 0; - for (final Type arg : pt.arguments()) { - t.addTypeArgument(this.type(new TypeContext(tc.context(), arg, position++, TypeContext.Kind.TYPE_ARGUMENT))); - } - break; - default: - throw new AssertionError(); - } - for (final AnnotationInstance ai : tct.annotations()) { - t.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final TypeContext tc, final org.microbean.lang.type.WildcardType w) { - final org.jboss.jandex.WildcardType tcType = tc.type().asWildcardType(); - Type bound = tcType.extendsBound(); - if (bound != null) { - w.setExtendsBound(this.type(new TypeContext(tc.context(), bound, 0, TypeContext.Kind.EXTENDS))); - } - bound = tcType.superBound(); - if (bound != null) { - w.setSuperBound(this.type(new TypeContext(tc.context(), bound, 0, TypeContext.Kind.EXTENDS))); - } - for (final AnnotationInstance ai : tcType.annotations()) { - w.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final ClassInfo ci, final org.microbean.lang.type.DeclaredType t) { - final org.microbean.lang.element.TypeElement e = (org.microbean.lang.element.TypeElement)this.element(ci); - - // Type. - e.setType(t); - - // Defining element. - t.setDefiningElement(e); - - // Need to do enclosing type, if there is one - final ClassInfo enclosingClass = this.classInfoEnclosing(ci); - if (enclosingClass != null) { - t.setEnclosingType(this.type(enclosingClass)); - } - - // Now type arguments (which will be type variables), if there are any. - final List tps = ci.typeParameters(); - for (int i = 0; i < tps.size(); i++) { - t.addTypeArgument(this.type(new TypeContext(ci, tps.get(i), i, TypeContext.Kind.TYPE_ARGUMENT))); - } - - // There isn't a way to get type use annotations on ci. - - } - - private final void build(final FieldInfo fi, final org.microbean.lang.type.ArrayType t) { - final org.jboss.jandex.ArrayType ft = fi.type().asArrayType(); - final org.microbean.lang.element.VariableElement e = (org.microbean.lang.element.VariableElement)this.element(fi); - e.setType(t); - t.setComponentType(this.type(new TypeContext(fi, ft.constituent(), 0, TypeContext.Kind.COMPONENT_TYPE))); - for (final AnnotationInstance ai : ft.annotations()) { - t.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final FieldInfo fi, final org.microbean.lang.type.DeclaredType t) { - final org.jboss.jandex.Type ft = fi.type(); - final org.microbean.lang.element.VariableElement e = (org.microbean.lang.element.VariableElement)this.element(fi); - e.setType(t); - t.setDefiningElement((org.microbean.lang.element.TypeElement)this.element(ft.name())); - for (final AnnotationInstance ai : ft.annotations()) { - t.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final FieldInfo fi, final org.microbean.lang.type.PrimitiveType t) { - final org.microbean.lang.element.VariableElement e = (org.microbean.lang.element.VariableElement)this.element(fi); - e.setType(t); - // Primitive types cannot bear annotations. - } - - private final void build(final FieldInfo fi, final org.microbean.lang.type.TypeVariable t) { - final org.jboss.jandex.TypeVariable ft = fi.type().asTypeVariable(); - final org.microbean.lang.element.VariableElement e = (org.microbean.lang.element.VariableElement)this.element(fi); - e.setType(t); - t.setDefiningElement((org.microbean.lang.element.TypeParameterElement)this.element(typeParameterInfoFor(fi, ft))); - for (final AnnotationInstance ai : ft.annotations()) { - t.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final MethodInfo mi, final org.microbean.lang.type.ExecutableType t) { - for (final MethodParameterInfo mpi : mi.parameters()) { - t.addParameterType(this.type(mpi)); - } - - final Type receiverType; - if (mi.isConstructor()) { - receiverType = mi.declaringClass().enclosingClass() == null ? null : mi.receiverType(); - } else { - receiverType = java.lang.reflect.Modifier.isStatic(mi.flags()) ? null : mi.receiverType(); - } - t.setReceiverType(receiverType == null ? - org.microbean.lang.type.NoType.NONE : - this.type(new TypeContext(mi, receiverType, 0, TypeContext.Kind.RECEIVER))); - t.setReturnType(this.type(new TypeContext(mi, mi.returnType(), 0, TypeContext.Kind.RETURN))); - - int position = 0; - for (final Type et : mi.exceptions()) { - t.addThrownType(this.type(new TypeContext(mi, et, position++, TypeContext.Kind.THROWS))); - } - - position = 0; - for (final org.jboss.jandex.TypeVariable tv : mi.typeParameters()) { - t.addTypeVariable((org.microbean.lang.type.TypeVariable)this.type(new TypeContext(mi, tv, position++, TypeContext.Kind.TYPE_ARGUMENT))); - } - } - - private final void build(final MethodParameterInfo mpi, final org.microbean.lang.type.ArrayType t) { - final org.jboss.jandex.ArrayType mpit = mpi.type().asArrayType(); - final org.microbean.lang.element.VariableElement e = (org.microbean.lang.element.VariableElement)this.element(mpi); - e.setType(t); - t.setComponentType(this.type(new TypeContext(mpi, mpit.constituent(), 0, TypeContext.Kind.COMPONENT_TYPE))); - for (final AnnotationInstance ai : mpit.annotations()) { - t.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final MethodParameterInfo mpi, final org.microbean.lang.type.DeclaredType t) { - final org.jboss.jandex.Type mpit = mpi.type(); - final org.microbean.lang.element.VariableElement e = (org.microbean.lang.element.VariableElement)this.element(mpi); - e.setType(t); - t.setDefiningElement((org.microbean.lang.element.TypeElement)this.element(mpit.name())); - for (final AnnotationInstance ai : mpit.annotations()) { - t.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final MethodParameterInfo mpi, final org.microbean.lang.type.PrimitiveType t) { - final org.microbean.lang.element.VariableElement e = (org.microbean.lang.element.VariableElement)this.element(mpi); - e.setType(t); - // Primitive types cannot bear annotations. - } - - private final void build(final MethodParameterInfo mpi, final org.microbean.lang.type.TypeVariable t) { - final org.jboss.jandex.TypeVariable mpit = mpi.type().asTypeVariable(); - final org.microbean.lang.element.VariableElement e = (org.microbean.lang.element.VariableElement)this.element(mpi); - e.setType(t); - t.setDefiningElement((org.microbean.lang.element.TypeParameterElement)this.element(typeParameterInfoFor(mpi, mpit))); - for (final AnnotationInstance ai : mpit.annotations()) { - t.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final RecordComponentInfo rci, final org.microbean.lang.type.ArrayType t) { - final org.jboss.jandex.ArrayType rcit = rci.type().asArrayType(); - final org.microbean.lang.element.RecordComponentElement e = (org.microbean.lang.element.RecordComponentElement)this.element(rci); - e.setType(t); - t.setComponentType(this.type(new TypeContext(rci, rcit.constituent(), 0, TypeContext.Kind.COMPONENT_TYPE))); - for (final AnnotationInstance ai : rcit.annotations()) { - t.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final RecordComponentInfo rci, final org.microbean.lang.type.DeclaredType t) { - final org.jboss.jandex.Type rcit = rci.type(); - final org.microbean.lang.element.RecordComponentElement e = (org.microbean.lang.element.RecordComponentElement)this.element(rci); - e.setType(t); - t.setDefiningElement((org.microbean.lang.element.TypeElement)this.element(rcit.name())); - for (final AnnotationInstance ai : rcit.annotations()) { - t.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final RecordComponentInfo rci, final org.microbean.lang.type.PrimitiveType t) { - final org.microbean.lang.element.RecordComponentElement e = (org.microbean.lang.element.RecordComponentElement)this.element(rci); - e.setType(t); - // Primitive types cannot bear annotations. - } - - private final void build(final RecordComponentInfo rci, final org.microbean.lang.type.TypeVariable t) { - final org.jboss.jandex.TypeVariable rcit = rci.type().asTypeVariable(); - final org.microbean.lang.element.RecordComponentElement e = (org.microbean.lang.element.RecordComponentElement)this.element(rci); - e.setType(t); - t.setDefiningElement((org.microbean.lang.element.TypeParameterElement)this.element(typeParameterInfoFor(rci, rcit))); - for (final AnnotationInstance ai : rcit.annotations()) { - t.addAnnotationMirror(this.annotation(ai)); - } - } - - private final void build(final TypeParameterInfo tpi, final org.microbean.lang.type.TypeVariable t) { - final org.microbean.lang.element.TypeParameterElement e = (org.microbean.lang.element.TypeParameterElement)this.element(tpi); - - // Type. - e.setType(t); - - // Defining element. - t.setDefiningElement(e); - - final AnnotationTarget context = tpi.annotationTarget(); - final List bounds = tpi.typeVariable().bounds(); - switch (bounds.size()) { - case 0: - break; - case 1: - t.setUpperBound(this.type(new TypeContext(context, bounds.get(0), 0, TypeContext.Kind.BOUND))); - break; - default: - final org.microbean.lang.type.IntersectionType upperBound = new org.microbean.lang.type.IntersectionType(); - int position = 0; - for (final Type bound : bounds) { - upperBound.addBound(this.type(new TypeContext(context, bound, position++, TypeContext.Kind.BOUND))); - } - t.setUpperBound(upperBound); - break; - } - - // I *believe* that when all is said and done, tpi.type().annotations() will reflect annotations on the type - // parameter *element*, not the type use, and so there's no way to get type use annotations here in Jandex. - - } - - // Having PrimitiveType as a parameter here is OK because primitive types cannot bear annotations. - private final void build(final PrimitiveType p, final org.microbean.lang.type.PrimitiveType t) { - - } - - - /* - * Housekeeping. - */ - - - private final MethodInfo annotationElementFor(final ClassInfo ci, final String name) { - if (ci.isAnnotation()) { - return ci.method(name); - } - throw new IllegalArgumentException("ci: " + ci); - } - - private final ClassInfo classInfoFor(final AnnotationInstance ai) { - return ai == null ? null : this.classInfoFor(ai.name()); - } - - private final ClassInfo classInfoFor(final Type t) { - return t == null ? null : switch(t.kind()) { - case CLASS -> this.classInfoFor(t.asClassType()); - case PARAMETERIZED_TYPE -> this.classInfoFor(t.asParameterizedType()); - default -> null; - }; - } - - private final ClassInfo classInfoFor(final ClassType t) { - return t == null ? null : this.classInfoFor(t.name()); - } - - private final ClassInfo classInfoFor(final ParameterizedType t) { - return t == null ? null : this.classInfoFor(t.name()); - } - - private final ClassInfo classInfoFor(final DotName n) { - if (n == null) { - return null; - } - final ClassInfo ci = this.i.getClassByName(n); - return ci == null ? this.unindexedClassnameFunction.apply(n.toString(), this.i) : ci; - } - - private final ClassInfo classInfoFor(final String n) { - if (n == null) { - return null; - } - final ClassInfo ci = this.i.getClassByName(n); - return ci == null ? this.unindexedClassnameFunction.apply(n, this.i) : ci; - } - - private final ClassInfo classInfoEnclosing(final ClassInfo ci) { - return ci == null ? null : this.classInfoFor(ci.enclosingClass()); - } - - final TypeParameterInfo typeParameterInfoFor(final AnnotationTarget context, final org.jboss.jandex.TypeVariable tv) { - return switch (context.kind()) { - case CLASS -> this.typeParameterInfoFor(context.asClass(), tv); - case FIELD -> this.typeParameterInfoFor(context.asField(), tv); - case METHOD -> this.typeParameterInfoFor(context.asMethod(), tv); - case METHOD_PARAMETER -> this.typeParameterInfoFor(context.asMethodParameter(), tv); - case RECORD_COMPONENT -> this.typeParameterInfoFor(context.asRecordComponent(), tv); - case TYPE -> throw new UnsupportedOperationException(); - }; - } - - final TypeParameterInfo typeParameterInfoFor(final ClassInfo context, final org.jboss.jandex.TypeVariable tv) { - final String id = tv.identifier(); - for (final org.jboss.jandex.TypeVariable tp : context.typeParameters()) { - if (tp.identifier().equals(id)) { - return new TypeParameterInfo(context, tp); - } - } - final EnclosingMethodInfo enclosingMethod = context.enclosingMethod(); - return enclosingMethod == null ? this.typeParameterInfoFor(context.enclosingClass(), tv) : this.typeParameterInfoFor(enclosingMethod, tv); - } - - final TypeParameterInfo typeParameterInfoFor(final DotName context, final org.jboss.jandex.TypeVariable tv) { - return this.typeParameterInfoFor(this.classInfoFor(context), tv); - } - - final TypeParameterInfo typeParameterInfoFor(final EnclosingMethodInfo context, final org.jboss.jandex.TypeVariable tv) { - return this.typeParameterInfoFor(this.classInfoFor(context.enclosingClass()).method(context.name(), context.parameters().toArray(new Type[0])), tv); - } - - final TypeParameterInfo typeParameterInfoFor(final FieldInfo context, final org.jboss.jandex.TypeVariable tv) { - return this.typeParameterInfoFor(context.declaringClass(), tv); - } - - final TypeParameterInfo typeParameterInfoFor(final MethodInfo context, final org.jboss.jandex.TypeVariable tv) { - final String id = tv.identifier(); - for (final org.jboss.jandex.TypeVariable tp : context.typeParameters()) { - if (tp.identifier().equals(id)) { - return new TypeParameterInfo(context, tp); - } - } - return this.typeParameterInfoFor(context.declaringClass(), tv); - } - - final TypeParameterInfo typeParameterInfoFor(final MethodParameterInfo context, final org.jboss.jandex.TypeVariable tv) { - return this.typeParameterInfoFor(context.method(), tv); - } - - final TypeParameterInfo typeParameterInfoFor(final RecordComponentInfo context, final org.jboss.jandex.TypeVariable tv) { - return this.typeParameterInfoFor(context.declaringClass(), tv); - } - - final TypeParameterInfo typeParameterInfoFor(final TypeContext tc) { - return this.typeParameterInfoFor(tc.context(), tc.type().asTypeVariable()); - } - - - /* - * Static methods. - */ - - - private static final boolean isDefault(final MethodInfo mi) { - if (mi.declaringClass().isInterface()) { - final short flags = mi.flags(); - return !java.lang.reflect.Modifier.isStatic(flags) && !java.lang.reflect.Modifier.isAbstract(flags); - } - return false; - } - - private static final ElementKind kind(final ClassInfo ci) { - return - ci.isAnnotation() ? ElementKind.ANNOTATION_TYPE : - ci.isEnum() ? ElementKind.ENUM : - ci.isInterface() ? ElementKind.INTERFACE : - ci.isModule() ? ElementKind.MODULE : - ci.isRecord() ? ElementKind.RECORD : - ElementKind.CLASS; - } - - private static final ElementKind kind(final FieldInfo f) { - return f.isEnumConstant() ? ElementKind.ENUM_CONSTANT : ElementKind.FIELD; - } - - private static final ElementKind kind(final MethodInfo m) { - return - m.isConstructor() ? ElementKind.CONSTRUCTOR : - m.name().equals("") ? ElementKind.STATIC_INIT : - m.name().equals("") ? ElementKind.INSTANCE_INIT : - ElementKind.METHOD; - } - - private static final TypeKind kind(final PrimitiveType p) { - return kind(p.primitive()); - } - - private static final TypeKind kind(final PrimitiveType.Primitive p) { - return switch (p) { - case BOOLEAN -> TypeKind.BOOLEAN; - case BYTE -> TypeKind.BYTE; - case CHAR -> TypeKind.CHAR; - case DOUBLE -> TypeKind.DOUBLE; - case FLOAT -> TypeKind.FLOAT; - case INT -> TypeKind.INT; - case LONG -> TypeKind.LONG; - case SHORT -> TypeKind.SHORT; - }; - } - - private static final NestingKind nestingKind(final ClassInfo ci) { - return nestingKind(ci.nestingType()); - } - - private static final NestingKind nestingKind(final NestingType n) { - return switch (n) { - case ANONYMOUS -> NestingKind.ANONYMOUS; // In fact, Jandex will never supply this. - case INNER -> NestingKind.MEMBER; - case LOCAL -> NestingKind.LOCAL; // In fact, Jandex will never supply this. - case TOP_LEVEL -> NestingKind.TOP_LEVEL; - }; - } - - - /* - * Inner and nested classes. - */ - - - public static final record PackageInfo(DotName name) { - - } - - public static final record TypeParameterInfo(AnnotationTarget annotationTarget, org.jboss.jandex.TypeVariable typeVariable) { - - public TypeParameterInfo { - switch (annotationTarget.kind()) { - case CLASS: - case METHOD: - break; - default: - throw new IllegalArgumentException("annotationTarget: " + annotationTarget); - } - Objects.requireNonNull(typeVariable, "typeVariable"); - } - - /** - * Returns the value of the {@code annotationTarget} record component, which will either be a {@link ClassInfo} or a - * {@link MethodInfo}. - * - * @return the value of the {@code annotationTarget} record component, which will either be a {@link ClassInfo} or a - * {@link MethodInfo} - */ - @Override - public final AnnotationTarget annotationTarget() { - return this.annotationTarget; - } - - public final AnnotationTarget.Kind kind() { - return this.annotationTarget().kind(); - } - - public final String identifier() { - return this.typeVariable().identifier(); - } - - } - - // Represents a "type context" in the parlance of - // https://docs.oracle.com/javase/specs/jls/se19/html/jls-4.html#jls-4.11. Not all such type contexts are represented - // here. - public static final class TypeContext { - - private final TypeContext parent; - - private final AnnotationTarget context; - - private final Type type; - - private final int position; - - private final Kind kind; - - private TypeContext(final AnnotationTarget context, final Type type, final int position, final Kind kind) { - this(null, context, type, position, kind); - } - - private TypeContext(final TypeContext parent, final AnnotationTarget context, final Type type, final int position, final Kind kind) { - super(); - validate(parent, context, type, position, kind); - this.parent = parent; - this.context = context; - this.type = type; - this.position = position; - this.kind = kind; - } - - private final TypeContext parent() { - return this.parent; - } - - private final AnnotationTarget context() { - return this.context; - } - - private final Type type() { - return this.type; - } - - private final int position() { - return this.position; - } - - private final Kind kind() { - return this.kind; - } - - @Override - public final int hashCode() { - int hashCode = 17; - Object v = this.parent(); - int c = v == null ? 0 : v.hashCode(); - hashCode = 37 * hashCode + c; - - v = this.context(); - c = v == null ? 0 : v.hashCode(); - hashCode = 37 * hashCode + c; - - v = this.type(); - c = v == null ? 0 : v.hashCode(); - hashCode = 37 * hashCode + c; - - hashCode = 37 * hashCode + this.position(); - - hashCode = 37 * hashCode + this.kind().hashCode(); - - return hashCode; - } - - @Override - public final boolean equals(final Object other) { - if (other == this) { - return true; - } else if (other != null && other.getClass() == this.getClass()) { - final TypeContext her = (TypeContext)other; - return - Objects.equals(this.parent(), her.parent()) && - Objects.equals(this.context(), her.context()) && - Objects.equals(this.type(), her.type()) && - Objects.equals(this.position(), her.position()) && - Objects.equals(this.kind(), her.kind()); - } else { - return false; - } - } - - private static final void validate(final TypeContext parent, final AnnotationTarget context, final Type type, final int position, final Kind kind) { - if (position < 0) { - throw new IndexOutOfBoundsException("position: " + position); - } - } - - // See relevant type contexts from https://docs.oracle.com/javase/specs/jls/se19/html/jls-4.html#jls-4.11 - private static enum Kind { - - // See also https://github.com/openjdk/jdk/blob/jdk-21%2B13/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TargetType.java - - BOUND, // e.g. the "@Bar Glug" in "public class Foo {}" - EXTENDS, // e.g. the "Glug", "Bar" or "Qux" in "public class Foo extends @Baz Bar implements Qux {}" - RETURN, // method return type - THROWS, // (method) throws type - RECEIVER, // method receiver type - TYPE_ARGUMENT, // e.g. the "String" in "public class Foo extends Bar<@Baz String> {}" - COMPONENT_TYPE // e.g. "@Baz"-annotated "[]" in "@Qux String @Bar [] @Baz []" - - } - - } - -} diff --git a/jandex/src/main/java/org/microbean/lang/jandex/package-info.java b/jandex/src/main/java/org/microbean/lang/jandex/package-info.java deleted file mode 100644 index bb9fb7b4..00000000 --- a/jandex/src/main/java/org/microbean/lang/jandex/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * Provides classes and interfaces related to the Java language model and Jandex. - * - * @author Laird Nelson - */ -package org.microbean.lang.jandex; diff --git a/jandex/src/main/javadoc/css/fonts.css b/jandex/src/main/javadoc/css/fonts.css deleted file mode 100644 index bd00dc52..00000000 --- a/jandex/src/main/javadoc/css/fonts.css +++ /dev/null @@ -1,62 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?2?family=Roboto+Mono:ital,wght@0,400;1,400&family=Roboto:ital,wght@0,400;0,700;1,400;1,700&family=Lobster&display=swap'); -body { - font-family: 'Roboto', 'DejaVu Sans', Arial, Helvetica, sans-serif; -} -button { - font-family: 'Roboto', 'DejaVu Sans', Arial, Helvetica, sans-serif; -} -h1, h2, h3 { - font-weight: 700 -} -input { - font-family: 'Roboto', 'DejaVu Sans', Arial, Helvetica, sans-serif; -} -code, tt, pre { - font-family: 'Roboto Mono', 'DejaVu Sans Mono', monospace; -} -.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { - font-family: 'Roboto', 'DejaVu Sans', Arial, Helvetica, sans-serif; -} -div.block { - font-family: 'Roboto', 'DejaVu Sans', Arial, Helvetica, sans-serif; -} -div.table-tabs > button { - font-weight: 700 -} -dl.notes > dt { - font-family: 'Roboto', 'DejaVu Sans', Arial, Helvetica, sans-serif; - font-weight: 700 -} -dl.notes > dd { - font-family: 'Roboto', 'DejaVu Sans', Arial, Helvetica, sans-serif; -} -strong { - font-weight: 700 -} -.caption { - font-weight: 700 -} -.table-header { - font-weight: 700 -} -.col-first a:link, .col-first a:visited, .col-second a:link, .col-second a:visited, .col-first a:link, .col-first a:visited, .col-second a:link, .col-second a:visited, .col-constructor-name a:link, .col-constructor-name a:visited, .col-summary-item-name a:link, .col-summary-item-name a:visited, .constant-values-container a:link, .constant-values-container a:visited, .all-classes-container a:link, .all-classes-container a:visited, .all-packages-container a:link, .all-packages-container a:visited { - font-weight: 700 -} -.deprecated-label, .descfrm-type-label, .implementation-label, .member-name-label, .member-name-link, .module-label-in-package, .module-label-in-type, .override-specify-label, .package-label-in-type, .package-hierarchy-label, .type-name-label, .type-name-link, .search-tag-link, .preview-label { - font-weight: 700 -} -.module-signature, .package-signature, .type-signature, .member-signature { - font-family: 'Roboto Mono', 'DejaVu Sans Mono', monospace; -} -main a[href*="://"]::after { - all: unset; -} -.result-highlight { - font-weight: 700; -} -.ui-widget { - font-family: 'Roboto', 'DejaVu Sans', Arial, Helvetica, sans-serif !important; -} -.ui-autocomplete-category { - font-weight: 700; -} diff --git a/jandex/src/site/markdown/index.md.vm b/jandex/src/site/markdown/index.md.vm deleted file mode 100644 index c79baf67..00000000 --- a/jandex/src/site/markdown/index.md.vm +++ /dev/null @@ -1 +0,0 @@ -#include("../../../README.md") diff --git a/jandex/src/site/site.xml b/jandex/src/site/site.xml deleted file mode 100644 index 3249f3d5..00000000 --- a/jandex/src/site/site.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - org.apache.maven.skins - maven-fluido-skin - 2.0.0-M8 - - - - - - - - - - - - - - - true - false - - - - diff --git a/jandex/src/test/java/org/microbean/lang/jandex/TestIsAssignable.java b/jandex/src/test/java/org/microbean/lang/jandex/TestIsAssignable.java deleted file mode 100644 index 8b9296f2..00000000 --- a/jandex/src/test/java/org/microbean/lang/jandex/TestIsAssignable.java +++ /dev/null @@ -1,17 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package org.microbean.lang.jandex; diff --git a/jandex/src/test/java/org/microbean/lang/jandex/TestJandex.java b/jandex/src/test/java/org/microbean/lang/jandex/TestJandex.java deleted file mode 100644 index 896d78a2..00000000 --- a/jandex/src/test/java/org/microbean/lang/jandex/TestJandex.java +++ /dev/null @@ -1,299 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package org.microbean.lang.jandex; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UncheckedIOException; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import java.net.URI; -import java.net.URISyntaxException; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import java.util.Collection; - -import java.util.function.Predicate; - -import java.util.stream.Stream; - -import javax.lang.model.element.Element; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.EmptyTypeTarget; -import org.jboss.jandex.Index; -import org.jboss.jandex.IndexReader; -import org.jboss.jandex.IndexView; -import org.jboss.jandex.IndexWriter; -import org.jboss.jandex.Indexer; -import org.jboss.jandex.MethodInfo; -import org.jboss.jandex.PrimitiveType; -import org.jboss.jandex.TypeParameterTypeTarget; -import org.jboss.jandex.TypeTarget; -import org.jboss.jandex.TypeVariable; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNotSame; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.fail; - -final class TestJandex { - - private static IndexView jdk; - - private Jandex jandex; - - private TestJandex() { - super(); - } - - @BeforeAll - static final void indexJdk() { - // See https://stackoverflow.com/a/46451977/208288 - jdk = - index(Path.of(URI.create("jrt:/")), - p -> { - // System.out.println("*** p: " + p); - return p.getFileName().toString().endsWith(".class"); - }); - // p -> (p.getNameCount() < 3 || p.getName(2).toString().startsWith("java")) && p.getFileName().toString().endsWith(".class")); - } - - @BeforeEach - final void setup() { - this.jandex = new Jandex(jdk); - } - - @Test - final void testClassInfoIdentity() { - final ClassInfo ci = jdk.getClassByName("java.lang.String"); - assertNotNull(ci); - assertSame(ci, jdk.getClassByName("java.lang.String")); - DotName javaLangString = DotName.createComponentized(null, "java"); - javaLangString = DotName.createComponentized(javaLangString, "lang"); - javaLangString = DotName.createComponentized(javaLangString, "String"); - assertEquals("java.lang.String", javaLangString.toString()); - assertSame(ci, jdk.getClassByName(javaLangString)); - } - - @Test - final void testMethodInfoNonIdentity() { - final MethodInfo mi = jdk.getClassByName("java.lang.String").method("charAt", PrimitiveType.INT); - assertNotNull(mi); - assertEquals(mi, jdk.getClassByName("java.lang.String").method("charAt", PrimitiveType.INT)); - assertNotSame(mi, jdk.getClassByName("java.lang.String").method("charAt", PrimitiveType.INT)); - } - - @Test - final void testPackageStuff() throws IOException, URISyntaxException { - final IndexView i = index(Path.of(org.microbean.lang.jandex.testjandex.Frobnicator.class.getProtectionDomain().getCodeSource().getLocation().toURI()), - p -> p.endsWith(".class")); - final Collection as = i.getAnnotations(org.microbean.lang.jandex.testjandex.Flabrous.class); - // Note that Jandex does not allow you to get package annotations. There is no such thing as PackageInfo. This is - // true even for inherited annotations. - assertEquals(0, as.size()); - } - - @Test - final void testEnum() { - // Nice class to test "circular" type variables. - final Element e = jandex.element(jdk.getClassByName("java.lang.Enum")); - } - - @Test - final void testObject() { - jandex.element(jdk.getClassByName("java.lang.Object")); - } - - @Test - final void testClass() { - jandex.element(jdk.getClassByName("java.lang.Class")); - } - - @Test - final void testDocumented() { - final Element e = jandex.element(jdk.getClassByName("java.lang.annotation.Documented")); - } - - @Test - final void testTypeParameterAnnotations() throws IOException { - final Indexer indexer = new Indexer(); - indexer.indexClass(Flob.class); - final IndexView i = indexer.complete(); - final ClassInfo ci = i.getClassByName(Flob.class.getName()); - - // The class element itself has no declared annotations. - assertEquals(0, ci.declaredAnnotations().size()); - - // The only way to get to the annotations declared on its sole type parameter element is using this horrible - // mechanism. annotations() is documented to return "the annotation instances declared on this annotation target - // and nested annotation targets". This doesn't include nested classes, just fields, constructors and methods, I - // guess. - - // 3 is: - // * 1 @Borf annotation on T, the type parameter declared by Flob - // * 1 @Borf annotation on yeet() - // * 1 @Borf type-use annotation on yeet()'s return value, a String - // * 0 @Borf annotations on Bozo because it isn't seen - assertEquals(3, ci.annotations().size(), "ci.annotations(): " + ci.annotations()); - - // As you can see, Jandex gets confused about what a type parameter is versus what a type variable is. - for (final AnnotationInstance ai : ci.annotations()) { - final AnnotationTarget target = ai.target(); - switch (target.kind()) { - case TYPE: - final TypeTarget tt = target.asType(); - switch (tt.usage()) { - case EMPTY: - final EmptyTypeTarget ett = tt.asEmpty(); - assertFalse(ett.isReceiver()); - assertEquals("java.lang.String", ett.target().name().toString()); - assertEquals("yeet", ett.enclosingTarget().asMethod().name()); - break; - case TYPE_PARAMETER: - // expected - break; - default: - fail(); - } - break; - case METHOD: - break; - default: - fail(); - } - } - - } - - @Test - final void testEnclosingElementOfLocalClassInsideMethod() throws ClassNotFoundException, IOException { - final Indexer indexer = new Indexer(); - indexer.indexClass(Flob.class); - final IndexView i = indexer.complete(); - final ClassInfo ci = i.getClassByName(Flob.class.getName()); - - // Flob declares a method, yeet(), that declares a local class. You can't "get to" the local class at all from - // Jandex. See https://github.com/smallrye/jandex/issues/180#issue-1179577350. - // - // This turns out to be OK, because the javax.lang.model.* hierarchy also doesn't let you "get to" local or - // anonymous classes in any way. - - assertEquals(2, ci.memberClasses().size()); - - // You can't get it from the index… - assertNull(i.getClassByName(Flob.class.getName() + "$1Bozo")); - - // …but it does exist under that name: - assertNotNull(Class.forName(Flob.class.getName() + "$1Bozo")); - - for (final AnnotationInstance a : ci.annotations()) { - final AnnotationTarget target = a.target(); - switch (target.kind()) { - case METHOD: - assertEquals("yeet", target.asMethod().name()); - break; - case TYPE: - // This is where things get stupid. - final TypeTarget tt = target.asType(); - switch (tt.usage()) { - case EMPTY: - final EmptyTypeTarget ett = tt.asEmpty(); - assertFalse(ett.isReceiver()); - assertEquals("java.lang.String", ett.target().name().toString()); - assertEquals("yeet", ett.enclosingTarget().asMethod().name()); - break; - case TYPE_PARAMETER: - // Stupid. Actually an *element* annotation. - assertEquals(0, tt.asTypeParameter().position()); // T in Flob<@Borf T> - break; - default: - fail(); - } - break; - default: - fail(); - } - } - } - - private static final IndexView index(final Path indexRoot, - final Predicate filterPredicate) { - final Indexer indexer = new Indexer(); - try (final Stream pathStream = Files.walk(indexRoot, Integer.MAX_VALUE)) { - pathStream - .filter(filterPredicate) - .forEach(p -> { - try (final InputStream inputStream = Files.newInputStream(p)) { - indexer.index(inputStream); - } catch (final IOException ioException) { - throw new UncheckedIOException(ioException.getMessage(), ioException); - } - }); - } catch (final IOException e) { - throw new UncheckedIOException(e.getMessage(), e); - } - return indexer.complete(); - } - - private static interface Grop { - - void flop(Grop this); - - } - - private static final class Flob<@Borf T> { - - @Borf - private static final String yeet() { - // (Jandex will see nothing in here.) - @Borf - class Bozo {}; - return "Yeet"; - } - - @Borf - private final class Blotz {} - - @Borf - private static final class Greep {} - - } - - @Retention(RetentionPolicy.RUNTIME) - @Target({ ElementType.TYPE, ElementType.TYPE_USE, ElementType.TYPE_PARAMETER, ElementType.METHOD }) - private @interface Borf {} - -} diff --git a/jandex/src/test/java/org/microbean/lang/jandex/TestJandexAndTypeParameters.java b/jandex/src/test/java/org/microbean/lang/jandex/TestJandexAndTypeParameters.java deleted file mode 100644 index e53ce0ec..00000000 --- a/jandex/src/test/java/org/microbean/lang/jandex/TestJandexAndTypeParameters.java +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package org.microbean.lang.jandex; - -import java.io.IOException; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import java.util.List; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.IndexView; -import org.jboss.jandex.Indexer; -import org.jboss.jandex.Type; -import org.jboss.jandex.TypeTarget; -import org.jboss.jandex.TypeVariable; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -final class TestJandexAndTypeParameters { - - private TestJandexAndTypeParameters() { - super(); - } - - @Test - final void testTypeParameters() throws IOException { - final Indexer indexer = new Indexer(); - indexer.indexClass(A.class); - indexer.indexClass(C.class); - final IndexView i = indexer.complete(); - final ClassInfo a = i.getClassByName(A.class.getName()); - assertEquals("B", a.typeParameters().get(0).identifier()); - assertEquals(1, a.annotations().size()); // remember that annotations() "descends into" the class, so indexes all of its "contained" annotations - - // Jandex doesn't have the notion of a type parameter - // element/declaration. javax.lang.model.element.TypeParameterElement does. - - // This sucks. The annotation is clearly labeled as TYPE_PARAMETER and NOT TYPE_USE, but Jandex sees it as TYPE_USE - // anyway (!). However, annotations intended for type-variable-types-underlying-type-parameters are not a thing in the - // Java language, apparently, though they show up in the javax.lang.model.* hierarchy. The proper thing to do seems - // to be to treat all cases that fall under this case as element/declaration annotations on the type parameter - // elements, so this is "expected" according to Jandex's odd interpretation. - // - // Probably there will be a Jandex bug and/or refactoring in this area later. - assertSame(TypeTarget.Usage.TYPE_PARAMETER, a.annotations().get(0).target().asType().usage()); - } - - @Retention(RetentionPolicy.RUNTIME) - @Target({ ElementType.TYPE_PARAMETER }) - private @interface C{} - - private static final class A<@C B> { - - } - -} diff --git a/jandex/src/test/java/org/microbean/lang/jandex/TestJandexTypeUseIssue.java b/jandex/src/test/java/org/microbean/lang/jandex/TestJandexTypeUseIssue.java deleted file mode 100644 index 56f185ef..00000000 --- a/jandex/src/test/java/org/microbean/lang/jandex/TestJandexTypeUseIssue.java +++ /dev/null @@ -1,124 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package org.microbean.lang.jandex; - -import java.io.IOException; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.EmptyTypeTarget; -import org.jboss.jandex.Indexer; -import org.jboss.jandex.IndexView; -import org.jboss.jandex.TypeTarget; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.fail; - -final class TestJandexTypeUseIssue { - - private TestJandexTypeUseIssue() { - super(); - } - - @D - private static final class A { - - // This @D is both: - // * an annotation on the b() element - // * a type-use annotation on the return type of b() (String) - @D - private static final String b() { - - // This @D is never seen - @D - class C {}; - - return "Hello"; - - } - - } - - @Retention(RetentionPolicy.RUNTIME) - @Target({ ElementType.METHOD, ElementType.TYPE, ElementType.TYPE_USE }) - private @interface D {} - - @Test - final void testTypeUse() throws ClassNotFoundException, IOException { - final Indexer indexer = new Indexer(); - indexer.indexClass(A.class); - indexer.indexClass(Class.forName(A.class.getName() + "$1C")); - final IndexView i = indexer.complete(); - final ClassInfo ci = i.getClassByName(A.class.getName()); - - // C does not show up as a member class, as it should not. - assertEquals(0, ci.memberClasses().size()); - - // 3 is: - // * 1 occurrence of @D on A - // * 2 occurrences of @D: - // * 1 occurrence of @D on the usage of the return type of the b() method - // * 1 occurrence of @D on the b() method element - // * 0 occurrences of @D on C (C is never seen by Jandex) - assertEquals(3, ci.annotations().size()); - - int count = 0; - for (final AnnotationInstance a : ci.annotations()) { - final AnnotationTarget target = a.target(); - switch (target.kind()) { - case CLASS: - if (target.asClass() != ci) { - fail(); - } - count++; - break; - case METHOD: - assertEquals("b", target.asMethod().name()); - count++; - break; - case TYPE: - final TypeTarget tt = target.asType(); - switch (tt.usage()) { - case EMPTY: - final EmptyTypeTarget ett = tt.asEmpty(); - assertFalse(ett.isReceiver()); - assertEquals("java.lang.String", ett.target().name().toString()); - assertEquals("b", ett.enclosingTarget().asMethod().name()); - count++; - break; - default: - fail(); - } - break; - default: - fail(); - } - } - assertEquals(3, count); - - } -} diff --git a/jandex/src/test/java/org/microbean/lang/jandex/TestObject.java b/jandex/src/test/java/org/microbean/lang/jandex/TestObject.java deleted file mode 100644 index 8d2a994a..00000000 --- a/jandex/src/test/java/org/microbean/lang/jandex/TestObject.java +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023–2024 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package org.microbean.lang.jandex; - -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; - -import java.net.URI; - -import java.nio.file.Files; -import java.nio.file.Path; - -import java.util.List; - -import java.util.function.Predicate; - -import java.util.stream.Stream; - -import javax.lang.model.element.Element; - -import org.jboss.jandex.Indexer; -import org.jboss.jandex.IndexView; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -final class TestObject { - - private static IndexView jdk; - - private TestObject() { - super(); - } - - @BeforeAll - static final void indexJdk() { - // See https://stackoverflow.com/a/46451977/208288 - jdk = index(Path.of(URI.create("jrt:/")), p -> p.getFileName().toString().endsWith(".class")); - } - - @Test - final void testObject() { - final Element e = new Jandex(jdk).typeElement("java.lang.Object"); - final List es = e.getEnclosedElements(); - } - - @Test - final void testString() { - final Element e = new Jandex(jdk).typeElement("java.lang.String"); - final List es = e.getEnclosedElements(); - es.forEach(ee -> { System.out.println(ee + "; class: " + ee.getClass()); }); - } - - - /* - * Static methods. - */ - - - private static final IndexView index(final Path indexRoot, final Predicate filterPredicate) { - final Indexer indexer = new Indexer(); - try (final Stream pathStream = Files.walk(indexRoot, Integer.MAX_VALUE)) { - pathStream - .filter(filterPredicate) - .forEach(p -> { - try (final InputStream inputStream = Files.newInputStream(p)) { - indexer.index(inputStream); - } catch (final IOException ioException) { - throw new UncheckedIOException(ioException.getMessage(), ioException); - } - }); - } catch (final IOException e) { - throw new UncheckedIOException(e.getMessage(), e); - } - return indexer.complete(); - } - - -} diff --git a/jandex/src/test/java/org/microbean/lang/jandex/TestTypeUsages.java b/jandex/src/test/java/org/microbean/lang/jandex/TestTypeUsages.java deleted file mode 100644 index 04cf908a..00000000 --- a/jandex/src/test/java/org/microbean/lang/jandex/TestTypeUsages.java +++ /dev/null @@ -1,250 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package org.microbean.lang.jandex; - -import java.io.IOException; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import java.util.List; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ArrayType; -import org.jboss.jandex.ClassExtendsTypeTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.EmptyTypeTarget; -import org.jboss.jandex.Indexer; -import org.jboss.jandex.IndexView; -import org.jboss.jandex.MethodParameterTypeTarget; -import org.jboss.jandex.ParameterizedType; -import org.jboss.jandex.Type; -import org.jboss.jandex.TypeTarget; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotSame; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -final class TestTypeUsages { - - private IndexView i; - - private TestTypeUsages() { - super(); - } - - @BeforeEach - final void setup() throws IOException { - final Indexer indexer = new Indexer(); - indexer.indexClass(A.class); - indexer.indexClass(B.class); - indexer.indexClass(E.class); - indexer.indexClass(F.class); - indexer.indexClass(G.class); - indexer.indexClass(H.class); - indexer.indexClass(String.class); - this.i = indexer.complete(); - } - - @AfterEach - final void tearDown() { - - } - - @Test - final void testB() { - final ClassInfo ci = this.i.getClassByName(B.class.getName()); - - for (final AnnotationInstance ai : ci.annotations()) { - final AnnotationTarget target = ai.target(); - switch (target.kind()) { - case CLASS: - // @A on the class itself - assertEquals("A", ai.name().local()); - assertSame(ci, target); - break; - case TYPE: - final TypeTarget tt = target.asType(); - switch (tt.usage()) { - case METHOD_PARAMETER: - final MethodParameterTypeTarget mptt = tt.asMethodParameterType(); - assertEquals(0, mptt.position()); - assertEquals("c", mptt.enclosingTarget().name()); - assertEquals("A", ai.name().local()); - break; - case EMPTY: - final EmptyTypeTarget ett = tt.asEmpty(); - assertFalse(ett.isReceiver()); - final ArrayType at = ett.target().asArrayType(); - switch (ai.name().local()) { - case "A": - assertEquals(1, at.dimensions()); // surprising - assertEquals(1, at.constituent().asArrayType().dimensions()); - break; - case "E": - assertEquals(1, at.dimensions()); - assertEquals("String", at.constituent().name().local()); - break; - default: - fail(); - } - break; - default: - fail(tt.usage().toString()); - } - break; - default: - fail(); - } - } - - } - - @Test - final void testG() { - final ClassInfo ci = this.i.getClassByName(G.class.getName()); - - final List ais = ci.annotations(); - assertEquals(3, ais.size()); - for (final AnnotationInstance ai : ais) { - final AnnotationTarget annotationTarget = ai.target(); - switch (annotationTarget.kind()) { - case TYPE: - final TypeTarget tt = annotationTarget.asType(); - switch (tt.usage()) { - case CLASS_EXTENDS: // really?! - final ClassExtendsTypeTarget cett = tt.asClassExtends(); - - final ClassInfo enclosingTarget = cett.enclosingTarget().asClass(); - assertSame(ci, enclosingTarget); - - assertEquals(65535, cett.position()); // 65535 means superclass; see javadoc - // How do we know this? How do we know that it isn't, say, F? - // - // Obviously for this test we can just assert that the target is the type named by "java.lang.String". But in a - // generic library we'll need a recipe, so we'll do the recipe here. - final Type relevantSupertype = cett.position() == 65535 ? enclosingTarget.superClassType() : enclosingTarget.interfaceTypes().get(cett.position()); - - final Type type = cett.target(); - if (type == relevantSupertype) { - // The annotation in question is a type use annotation on the supertype itself (in this test, it's @H-on-F<@E String, @E String>). - assertEquals("H", ai.name().local()); - } else { - // The annotation in question is a type use annotation on the supertype's type arguments, which implies that - // the supertype is a parameterized type. - assertSame(Type.Kind.PARAMETERIZED_TYPE, relevantSupertype.kind()); - - for (final Type typeArgument : relevantSupertype.asParameterizedType().arguments()) { - // In this test, there are two type arguments, both of type String, both annotated with @E. What is - // particularly interesting is that Jandex stores them with one object. - assertSame(type, typeArgument); - - // Anyway, the point is there is no way to distinguish them at all. - } - } - - switch (relevantSupertype.kind()) { - case CLASS: - // (In this test we know this to be false. In the recipe, this would tell us unambiguously the type usage - // annotation is on the actual thing being extended/implemented.) - fail(); - break; - case PARAMETERIZED_TYPE: - // (In this test we know this to be true.) - - break; - default: - fail(); - } - - // This is really stupid. I guess once the position is 65535, you get the supertype directly? - final Type supertype = ci.superClassType(); - // assertEquals("String", cett.target().name().local()); - break; - default: - fail(); - } - break; - default: - fail(); - } - } - } - - - /* - * Inner and nested classes. - */ - - - @Retention(RUNTIME) - // Note as an interesting curiosity that TYPE_USE implies ANNOTATION_TYPE, TYPE and TYPE_PARAMETER as well. See - // https://mail.openjdk.org/pipermail/compiler-dev/2023-February/022200.html. - @Target({ TYPE, TYPE_USE }) - public @interface A {} - - @Retention(RUNTIME) - // Note as an interesting curiosity that TYPE_USE implies ANNOTATION_TYPE, TYPE and TYPE_PARAMETER as well. See - // https://mail.openjdk.org/pipermail/compiler-dev/2023-February/022200.html. - @Target({ TYPE_USE }) - public @interface E {} - - @Retention(RUNTIME) - // Note as an interesting curiosity that TYPE_USE implies ANNOTATION_TYPE, TYPE and TYPE_PARAMETER as well. See - // https://mail.openjdk.org/pipermail/compiler-dev/2023-February/022200.html. - @Target({ TYPE_USE }) - public @interface H {} - - @A - private static final class B { - - private B() { - super(); - } - - public static final void c(@A String s) {} - - // Yow. @A annotates the array type (of the type denoted by String[][]). @E annotaes the component type (denoted by - // String[]). - public static final String @A [] @E [] d() { - return null; - } - - } - - private static class F {} - - private static class G extends @H F<@E String, @E String> {} - - - -} diff --git a/jandex/src/test/java/org/microbean/lang/jandex/TestTypeUseAnnotationOnMethodParameterType.java b/jandex/src/test/java/org/microbean/lang/jandex/TestTypeUseAnnotationOnMethodParameterType.java deleted file mode 100644 index 4f355097..00000000 --- a/jandex/src/test/java/org/microbean/lang/jandex/TestTypeUseAnnotationOnMethodParameterType.java +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package org.microbean.lang.jandex; - -import java.io.IOException; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.EmptyTypeTarget; -import org.jboss.jandex.Indexer; -import org.jboss.jandex.IndexView; -import org.jboss.jandex.MethodParameterTypeTarget; -import org.jboss.jandex.TypeTarget; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.fail; - -final class TestTypeUseAnnotationOnMethodParameterType { - - private TestTypeUseAnnotationOnMethodParameterType() { - super(); - } - - /** - * This test exists to show that Jandex does something properly that javac does not. - * - *

See the {@code org.microbean.lang.TestTypeUsages} test class for the {@code javac}-based analog, which does not - * handle a type use annotation on a method parameter. I am still not sure if Jandex is wrong, or {@code javac} is - * wrong.

- * - * @exception IOException if there was a problem with the {@link Indexer} - */ - @Test - final void testTypeUseAnnotationOnMethodParameterType() throws IOException { - final Indexer indexer = new Indexer(); - indexer.indexClass(B.class); - final IndexView i = indexer.complete(); - final ClassInfo ci = i.getClassByName(B.class.getName()); - for (final AnnotationInstance a : ci.annotations()) { - final AnnotationTarget target = a.target(); - switch (target.kind()) { - case TYPE: - final TypeTarget tt = target.asType(); - switch (tt.usage()) { - case METHOD_PARAMETER: - final MethodParameterTypeTarget mptt = tt.asMethodParameterType(); - assertEquals(0, mptt.position()); - assertEquals("c", mptt.enclosingTarget().name()); - assertEquals("A", a.name().local()); - break; - default: - fail(); - } - break; - default: - fail(); - } - } - } - - @Retention(RetentionPolicy.RUNTIME) - @Target({ ElementType.TYPE_USE }) - public @interface A {} - - public static final class B { - - public B() { - super(); - } - - public static final void c(@A String s) {} - - } - -} diff --git a/jandex/src/test/java/org/microbean/lang/jandex/testjandex/Flabrous.java b/jandex/src/test/java/org/microbean/lang/jandex/testjandex/Flabrous.java deleted file mode 100644 index 1f85ad5a..00000000 --- a/jandex/src/test/java/org/microbean/lang/jandex/testjandex/Flabrous.java +++ /dev/null @@ -1,30 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package org.microbean.lang.jandex.testjandex; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Inherited -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.PACKAGE) -public @interface Flabrous { - -} diff --git a/jandex/src/test/java/org/microbean/lang/jandex/testjandex/Frobnicator.java b/jandex/src/test/java/org/microbean/lang/jandex/testjandex/Frobnicator.java deleted file mode 100644 index 7782cefb..00000000 --- a/jandex/src/test/java/org/microbean/lang/jandex/testjandex/Frobnicator.java +++ /dev/null @@ -1,25 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package org.microbean.lang.jandex.testjandex; - -public class Frobnicator { - - public Frobnicator() { - super(); - } - -} diff --git a/jandex/src/test/java/org/microbean/lang/jandex/testjandex/package-info.java b/jandex/src/test/java/org/microbean/lang/jandex/testjandex/package-info.java deleted file mode 100644 index 1de3b281..00000000 --- a/jandex/src/test/java/org/microbean/lang/jandex/testjandex/package-info.java +++ /dev/null @@ -1,18 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2023 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -@Flabrous -package org.microbean.lang.jandex.testjandex; diff --git a/lang/src/main/java/org/microbean/lang/Lang.java b/lang/src/main/java/org/microbean/lang/Lang.java index a931ceb3..4fbde8a9 100644 --- a/lang/src/main/java/org/microbean/lang/Lang.java +++ b/lang/src/main/java/org/microbean/lang/Lang.java @@ -2277,6 +2277,11 @@ public final NoType noType(final TypeKind k) { return Lang.noType(k); } + @Override + public final NullType nullType() { + return Lang.nullType(); + } + @Override public final PrimitiveType primitiveType(final TypeKind k) { return Lang.primitiveType(k); diff --git a/lang/src/main/java/org/microbean/lang/TypeAndElementSource.java b/lang/src/main/java/org/microbean/lang/TypeAndElementSource.java index 29ecf639..5a313ffd 100644 --- a/lang/src/main/java/org/microbean/lang/TypeAndElementSource.java +++ b/lang/src/main/java/org/microbean/lang/TypeAndElementSource.java @@ -3,12 +3,12 @@ * Copyright © 2023–2024 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 + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package org.microbean.lang; @@ -27,11 +27,14 @@ import javax.lang.model.element.Element; import javax.lang.model.element.ModuleElement; +import javax.lang.model.element.Parameterizable; import javax.lang.model.element.TypeElement; +import javax.lang.model.element.TypeParameterElement; import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.NoType; +import javax.lang.model.type.NullType; import javax.lang.model.type.PrimitiveType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; @@ -40,6 +43,7 @@ import static java.lang.constant.ConstantDescs.NULL; +// In general: behavior could be undefined for anything accepting a type or element that isn't "from" this source. public interface TypeAndElementSource { public ArrayType arrayTypeOf(final TypeMirror componentType); @@ -64,6 +68,8 @@ public DeclaredType declaredType(final TypeElement typeElement, public NoType noType(final TypeKind k); + public NullType nullType(); + public PrimitiveType primitiveType(final TypeKind k); public boolean sameType(final TypeMirror t, final TypeMirror s); 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 5ff977d8..de8bb87c 100644 --- a/lang/src/main/java/org/microbean/lang/element/DelegatingElement.java +++ b/lang/src/main/java/org/microbean/lang/element/DelegatingElement.java @@ -3,12 +3,12 @@ * Copyright © 2022–2024 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 + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package org.microbean.lang.element; @@ -50,6 +50,7 @@ import javax.lang.model.element.TypeParameterElement; import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import org.microbean.lang.CompletionLock; @@ -57,7 +58,6 @@ import org.microbean.lang.Equality; 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; @@ -188,7 +188,7 @@ public final Optional describeConstable() { } @Override // RecordComponentElement - public final ExecutableElement getAccessor() { + public final DelegatingElement getAccessor() { return switch (this.getKind()) { case RECORD_COMPONENT -> this.wrap(((RecordComponentElement)this.delegate()).getAccessor()); default -> null; @@ -211,7 +211,7 @@ public final A[] getAnnotationsByType(final Class anno } @Override // TypeParameterElement - public final List getBounds() { + public final List getBounds() { return switch (this.getKind()) { case TYPE_PARAMETER -> DelegatingTypeMirror.of(((TypeParameterElement)this.delegate()).getBounds(), this.tes, this.ehc); @@ -247,25 +247,25 @@ public final List getDirectives() { } @Override // Element - public final List getEnclosedElements() { + public final List getEnclosedElements() { return this.wrap(this.delegate().getEnclosedElements()); } @Override // Element - public final Element getEnclosingElement() { + public final DelegatingElement getEnclosingElement() { return this.wrap(this.delegate().getEnclosingElement()); } @Override // TypeParameterElement - public final Element getGenericElement() { + public final DelegatingElement getGenericElement() { return switch (this.getKind()) { case TYPE_PARAMETER -> this.wrap(((TypeParameterElement)this.delegate()).getGenericElement()); - default -> null; // illegal state + default -> this.getEnclosingElement(); // illegal state }; } @Override // TypeElement - public final List getInterfaces() { + public final List getInterfaces() { return switch (this.getKind()) { case ANNOTATION_TYPE, CLASS, ENUM, INTERFACE, RECORD -> DelegatingTypeMirror.of(((TypeElement)this.delegate()).getInterfaces(), this.tes, this.ehc); @@ -287,12 +287,12 @@ 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 -> NestingKind.TOP_LEVEL; // illegal state }; } @Override // ExecutableElement - public final List getParameters() { + public final List getParameters() { return switch (this.getKind()) { case CONSTRUCTOR, METHOD -> this.wrap(((ExecutableElement)this.delegate()).getParameters()); default -> List.of(); @@ -309,15 +309,15 @@ public final Name getQualifiedName() { } @Override // ExecutableElement - public final TypeMirror getReceiverType() { + public final DelegatingTypeMirror getReceiverType() { return this.getKind().isExecutable() ? DelegatingTypeMirror.of(this.asType(), this.tes, this.ehc).getReceiverType() : - null; + DelegatingTypeMirror.of(this.tes.noType(TypeKind.NONE), this.tes, this.ehc); } @Override // TypeElement - public final List getRecordComponents() { + public final List getRecordComponents() { return switch (this.getKind()) { case RECORD -> this.wrap(((TypeElement)this.delegate()).getRecordComponents()); default -> List.of(); @@ -325,7 +325,7 @@ public final List getRecordComponents() { } @Override // ExecutableElement - public final TypeMirror getReturnType() { + public final DelegatingTypeMirror getReturnType() { return DelegatingTypeMirror.of(this.asType(), this.tes, this.ehc).getReturnType(); } @@ -335,16 +335,16 @@ public final Name getSimpleName() { } @Override // TypeElement - public final TypeMirror getSuperclass() { + public final DelegatingTypeMirror getSuperclass() { return switch (this.getKind()) { case ANNOTATION_TYPE, CLASS, ENUM, INTERFACE, RECORD -> DelegatingTypeMirror.of(((TypeElement)this.delegate()).getSuperclass(), this.tes, this.ehc); - default -> NoType.NONE; + default -> DelegatingTypeMirror.of(this.tes.noType(TypeKind.NONE), this.tes, this.ehc); }; } @Override // ExecutableElement - public final List getThrownTypes() { + public final List getThrownTypes() { return this.getKind().isExecutable() ? DelegatingTypeMirror.of(((ExecutableElement)this.delegate()).getThrownTypes(), this.tes, this.ehc) : @@ -352,7 +352,7 @@ public final List getThrownTypes() { } @Override // ExecutableElement - public final List getTypeParameters() { + public final List getTypeParameters() { return switch (this.getKind()) { case CLASS, CONSTRUCTOR, ENUM, INTERFACE, RECORD, METHOD -> this.wrap(((Parameterizable)this.delegate()).getTypeParameters()); default -> List.of(); diff --git a/lang/src/main/java/org/microbean/lang/element/Element.java b/lang/src/main/java/org/microbean/lang/element/Element.java index ca9215fd..59fb1f59 100644 --- a/lang/src/main/java/org/microbean/lang/element/Element.java +++ b/lang/src/main/java/org/microbean/lang/element/Element.java @@ -1,18 +1,15 @@ /* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- * - * Copyright © 2022–2023 microBean™. + * Copyright © 2022–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang.element; @@ -33,8 +30,6 @@ import org.microbean.lang.AnnotatedConstruct; -import org.microbean.lang.type.NoType; - // NOT thread safe public abstract sealed class Element extends AnnotatedConstruct @@ -104,10 +99,6 @@ public final void setType(final TypeMirror type) { } protected TypeMirror validateType(final TypeMirror type) { - if (type == null) { - return NoType.NONE; - } - type.getKind(); // null check return type; } 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 d37688af..fd4c8470 100644 --- a/lang/src/main/java/org/microbean/lang/type/DelegatingTypeMirror.java +++ b/lang/src/main/java/org/microbean/lang/type/DelegatingTypeMirror.java @@ -89,7 +89,7 @@ public final class DelegatingTypeMirror */ - private final TypeAndElementSource elementSource; + private final TypeAndElementSource tes; private final Equality ehc; @@ -101,10 +101,10 @@ public final class DelegatingTypeMirror */ - private DelegatingTypeMirror(final TypeMirror delegate, final TypeAndElementSource elementSource, final Equality ehc) { + private DelegatingTypeMirror(final TypeMirror delegate, final TypeAndElementSource tes, final Equality ehc) { super(); Objects.requireNonNull(delegate, "delegate"); - this.elementSource = elementSource == null ? Lang.typeAndElementSource() : elementSource; + this.tes = tes == null ? Lang.typeAndElementSource() : tes; this.ehc = ehc == null ? new Equality(true) : ehc; this.delegateSupplier = () -> { final TypeMirror unwrappedDelegate = unwrap(delegate); @@ -157,10 +157,10 @@ public final R accept(final TypeVisitor v, final P p) { } @Override // Various - public final Element asElement() { + public final DelegatingElement 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); + case DECLARED -> DelegatingElement.of(((DeclaredType)this.delegate()).asElement(), this.tes, this.ehc); + case TYPEVAR -> DelegatingElement.of(((TypeVariable)this.delegate()).asElement(), this.tes, this.ehc); default -> null; }; } @@ -170,7 +170,7 @@ public final TypeMirror delegate() { } @Override // UnionType - public final List getAlternatives() { + public final List getAlternatives() { return switch (this.getKind()) { case UNION -> this.wrap(((UnionType)this.delegate()).getAlternatives()); default -> List.of(); @@ -194,7 +194,7 @@ public final A[] getAnnotationsByType(final Class anno } @Override // IntersectionType - public final List getBounds() { + public final List getBounds() { return switch (this.getKind()) { case INTERSECTION -> this.wrap(((IntersectionType)this.delegate()).getBounds()); default -> List.of(); @@ -202,23 +202,23 @@ public final List getBounds() { } @Override // ArrayType - public final TypeMirror getComponentType() { + public final DelegatingTypeMirror getComponentType() { return switch (this.getKind()) { case ARRAY -> this.wrap(((ArrayType)this.delegate()).getComponentType()); - default -> NoType.NONE; + default -> this.wrap(this.tes.noType(TypeKind.NONE)); }; } @Override // DeclaredType - public final TypeMirror getEnclosingType() { + public final DelegatingTypeMirror getEnclosingType() { return switch(this.getKind()) { case DECLARED -> this.wrap(((DeclaredType)this.delegate()).getEnclosingType()); - default -> NoType.NONE; + default -> this.wrap(this.tes.noType(TypeKind.NONE)); }; } @Override // WildcardType - public final TypeMirror getExtendsBound() { + public final DelegatingTypeMirror getExtendsBound() { return switch (this.getKind()) { case WILDCARD -> this.wrap(((WildcardType)this.delegate()).getExtendsBound()); default -> null; @@ -231,23 +231,23 @@ public final TypeKind getKind() { } @Override // TypeVariable - public final TypeMirror getLowerBound() { + public final DelegatingTypeMirror 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 -> this.wrap(this.tes.nullType()); // bottom (null) type, not NONE type }; } @Override // TypeVariable - public final TypeMirror getUpperBound() { + public final DelegatingTypeMirror 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.tes.typeElement("java.lang.Object").asType()); }; } @Override // ExecutableType - public final List getParameterTypes() { + public final List getParameterTypes() { return switch (this.getKind()) { case EXECUTABLE -> this.wrap(((ExecutableType)this.delegate()).getParameterTypes()); default -> List.of(); @@ -255,23 +255,23 @@ public final List getParameterTypes() { } @Override // ExecutableType - public final TypeMirror getReceiverType() { + public final DelegatingTypeMirror getReceiverType() { return switch (this.getKind()) { case EXECUTABLE -> this.wrap(((ExecutableType)this.delegate()).getReceiverType()); - default -> null; + default -> this.wrap(this.tes.noType(TypeKind.NONE)); }; } @Override // ExecutableType - public final TypeMirror getReturnType() { + public final DelegatingTypeMirror getReturnType() { return switch (this.getKind()) { case EXECUTABLE -> this.wrap(((ExecutableType)this.delegate()).getReturnType()); - default -> null; + default -> this.wrap(this.tes.noType(TypeKind.VOID)); }; } @Override // WildcardType - public final TypeMirror getSuperBound() { + public final DelegatingTypeMirror getSuperBound() { return switch (this.getKind()) { case WILDCARD -> this.wrap(((WildcardType)this.delegate()).getSuperBound()); default -> null; @@ -279,7 +279,7 @@ public final TypeMirror getSuperBound() { } @Override // ExecutableType - public final List getThrownTypes() { + public final List getThrownTypes() { return switch (this.getKind()) { case EXECUTABLE -> this.wrap(((ExecutableType)this.delegate()).getThrownTypes()); default -> List.of(); @@ -287,7 +287,7 @@ public final List getThrownTypes() { } @Override // DeclaredType - public final List getTypeArguments() { + public final List getTypeArguments() { return switch (this.getKind()) { case DECLARED -> this.wrap(((DeclaredType)this.delegate()).getTypeArguments()); default -> List.of(); @@ -295,7 +295,7 @@ public final List getTypeArguments() { } @Override // ExecutableType - public final List getTypeVariables() { + public final List getTypeVariables() { return switch (this.getKind()) { case EXECUTABLE -> this.wrap(((ExecutableType)this.delegate()).getTypeVariables()); default -> List.of(); @@ -320,8 +320,8 @@ public final String toString() { @Override // Constable public final Optional describeConstable() { return this.ehc.describeConstable() - .flatMap(equalityDesc -> (this.elementSource instanceof Constable c ? c.describeConstable() : Optional.empty()) - .flatMap(elementSourceDesc -> this.elementSource.describeConstable(this.delegate()) + .flatMap(equalityDesc -> (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_DelegatingTypeMirror, @@ -331,16 +331,16 @@ public final Optional describeConstable() { CD_TypeAndElementSource, CD_Equality)), delegateDesc, - elementSourceDesc, + tesDesc, equalityDesc)))); } private final DelegatingTypeMirror wrap(final TypeMirror t) { - return of(t, this.elementSource, this.ehc); + return of(t, this.tes, this.ehc); } private final List wrap(final Collection ts) { - return of(ts, this.elementSource, this.ehc); + return of(ts, this.tes, this.ehc); } @@ -349,28 +349,28 @@ private final List wrap(final Collection of(final Collection ts, final TypeAndElementSource elementSource) { - return of(ts, elementSource, null); + public static final List of(final Collection ts, final TypeAndElementSource tes) { + return of(ts, tes, null); } - public static final List of(final Collection ts, final TypeAndElementSource elementSource, final Equality ehc) { + public static final List of(final Collection ts, final TypeAndElementSource tes, final Equality ehc) { final List newTs = new ArrayList<>(ts.size()); for (final TypeMirror t : ts) { - newTs.add(of(t, elementSource, ehc)); + newTs.add(of(t, tes, ehc)); } return Collections.unmodifiableList(newTs); } - public static final DelegatingTypeMirror of(final TypeMirror t, final TypeAndElementSource elementSource) { - return of(t, elementSource, null); + public static final DelegatingTypeMirror of(final TypeMirror t, final TypeAndElementSource tes) { + return of(t, tes, null); } // Called by describeConstable - public static final DelegatingTypeMirror of(final TypeMirror t, final TypeAndElementSource elementSource, final Equality ehc) { + public static final DelegatingTypeMirror of(final TypeMirror t, final TypeAndElementSource tes, final Equality ehc) { return t == null ? null : t instanceof DelegatingTypeMirror d ? d : - new DelegatingTypeMirror(t, elementSource, ehc); + new DelegatingTypeMirror(t, tes, ehc); } public static final TypeMirror unwrap(TypeMirror t) { diff --git a/lang/src/main/java/org/microbean/lang/type/TypeMirror.java b/lang/src/main/java/org/microbean/lang/type/TypeMirror.java index 3222234b..e2cea4af 100644 --- a/lang/src/main/java/org/microbean/lang/type/TypeMirror.java +++ b/lang/src/main/java/org/microbean/lang/type/TypeMirror.java @@ -3,12 +3,12 @@ * Copyright © 2022–2024 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 + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package org.microbean.lang.type; diff --git a/lang/src/main/java/org/microbean/lang/type/TypeVariable.java b/lang/src/main/java/org/microbean/lang/type/TypeVariable.java index fd4ba2f0..518aa6e6 100644 --- a/lang/src/main/java/org/microbean/lang/type/TypeVariable.java +++ b/lang/src/main/java/org/microbean/lang/type/TypeVariable.java @@ -26,24 +26,24 @@ public non-sealed class TypeVariable extends DefineableType implements javax.lang.model.type.TypeVariable { - private final TypeAndElementSource elementSource; + private final TypeAndElementSource tes; private TypeMirror upperBound; private TypeMirror lowerBound; - public TypeVariable(final TypeAndElementSource elementSource) { + public TypeVariable(final TypeAndElementSource tes) { super(TypeKind.TYPEVAR); - this.elementSource = Objects.requireNonNull(elementSource, "elementSource"); + this.tes = Objects.requireNonNull(tes, "tes"); } - public TypeVariable(final TypeAndElementSource elementSource, final TypeMirror upperBound) { - this(elementSource); + public TypeVariable(final TypeAndElementSource tes, final TypeMirror upperBound) { + this(tes); this.setUpperBound(upperBound); } - public TypeVariable(final TypeAndElementSource elementSource, final TypeMirror upperBound, final TypeMirror lowerBound) { - this(elementSource); + public TypeVariable(final TypeAndElementSource tes, final TypeMirror upperBound, final TypeMirror lowerBound) { + this(tes); this.setUpperBound(upperBound); this.setLowerBound(lowerBound); } @@ -68,7 +68,7 @@ public final void setLowerBound(final TypeMirror lowerBound) { @Override // TypeVariable public final TypeMirror getUpperBound() { final TypeMirror t = this.upperBound; - return t == null ? this.elementSource.typeElement("java.lang.Object").asType() : t; // this is correct; can't just return null + return t == null ? this.tes.typeElement("java.lang.Object").asType() : t; // this is correct; can't just return null } public final void setUpperBound(final TypeMirror upperBound) { @@ -105,28 +105,20 @@ public String toString() { } private final TypeMirror validateUpperBound(final TypeMirror upperBound) { - switch (upperBound.getKind()) { - case DECLARED: - case INTERSECTION: - return upperBound; - case TYPEVAR: + return switch (upperBound.getKind()) { + case DECLARED, INTERSECTION -> upperBound; + case TYPEVAR -> { if (upperBound == this) { throw new IllegalArgumentException("upperBound: " + upperBound); } - return upperBound; - default: - throw new IllegalArgumentException("upperBound: " + upperBound); + yield upperBound; } + default -> throw new IllegalArgumentException("upperBound: " + upperBound); + }; } - - /* - * Static methods. - */ - - - private static final TypeMirror validateLowerBound(final TypeMirror lowerBound) { - return lowerBound == null ? NullType.INSTANCE : lowerBound; + private final TypeMirror validateLowerBound(final TypeMirror lowerBound) { + return lowerBound == null ? this.tes.nullType() : lowerBound; } } diff --git a/lang/src/main/java/org/microbean/lang/type/Types.java b/lang/src/main/java/org/microbean/lang/type/Types.java index 934a6ed6..485e1a70 100644 --- a/lang/src/main/java/org/microbean/lang/type/Types.java +++ b/lang/src/main/java/org/microbean/lang/type/Types.java @@ -3,12 +3,12 @@ * Copyright © 2022–2024 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 + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package org.microbean.lang.type; @@ -41,11 +41,11 @@ public final class Types { // @GuardedBy("itself") private static final WeakHashMap syntheticElements = new WeakHashMap<>(); - private final TypeAndElementSource es; + private final TypeAndElementSource tes; - public Types(final TypeAndElementSource elementSource) { + public Types(final TypeAndElementSource tes) { super(); - this.es = Objects.requireNonNull(elementSource, "elementSource"); + this.tes = Objects.requireNonNull(tes, "tes"); } public final javax.lang.model.type.TypeMirror extendsBound(final javax.lang.model.type.TypeMirror t) { @@ -61,7 +61,7 @@ public final javax.lang.model.type.TypeMirror extendsBound(final javax.lang.mode final javax.lang.model.type.TypeMirror extendsBound = w.getExtendsBound(); if (extendsBound == null) { // Unbounded, so upper bound is Object. - yield this.es.typeElement("java.lang.Object").asType(); + yield this.tes.typeElement("java.lang.Object").asType(); } // Upper-bounded. assert @@ -108,7 +108,7 @@ public final javax.lang.model.type.TypeMirror extendsBound(final javax.lang.mode // So bound gets set to T extends Serializable. There is no way to extract T extends Serializable from a // javax.lang.model.type.WildcardType, and without that ability we have no other information, so we must return // Object.class. - yield this.es.typeElement("java.lang.Object").asType(); + yield this.tes.typeElement("java.lang.Object").asType(); } default -> t; }; @@ -118,42 +118,42 @@ public final javax.lang.model.type.TypeMirror superBound(final javax.lang.model. // See // https://github.com/openjdk/jdk/blob/jdk-20+12/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java#L157-L167 return switch (t.getKind()) { - case WILDCARD -> { - final javax.lang.model.type.TypeMirror superBound = ((javax.lang.model.type.WildcardType)t).getSuperBound(); - yield superBound == null ? org.microbean.lang.type.NullType.INSTANCE : superBound; - } - default -> t; + case WILDCARD -> { + final javax.lang.model.type.TypeMirror superBound = ((javax.lang.model.type.WildcardType)t).getSuperBound(); + yield superBound == null ? this.tes.nullType() : superBound; + } + default -> t; }; } public final javax.lang.model.type.TypeMirror box(final javax.lang.model.type.TypeMirror t) { return t == null ? null : switch (t.getKind()) { - case BOOLEAN -> this.es.typeElement("java.lang.Boolean").asType(); - case BYTE -> this.es.typeElement("java.lang.Byte").asType(); - case CHAR -> this.es.typeElement("java.lang.Character").asType(); - case DOUBLE -> this.es.typeElement("java.lang.Double").asType(); - case FLOAT -> this.es.typeElement("java.lang.Float").asType(); - case INT -> this.es.typeElement("java.lang.Integer").asType(); - case LONG -> this.es.typeElement("java.lang.Long").asType(); - case SHORT -> this.es.typeElement("java.lang.Short").asType(); - case VOID -> this.es.typeElement("java.lang.Void").asType(); - default -> t; + case BOOLEAN -> this.tes.typeElement("java.lang.Boolean").asType(); + case BYTE -> this.tes.typeElement("java.lang.Byte").asType(); + case CHAR -> this.tes.typeElement("java.lang.Character").asType(); + case DOUBLE -> this.tes.typeElement("java.lang.Double").asType(); + case FLOAT -> this.tes.typeElement("java.lang.Float").asType(); + case INT -> this.tes.typeElement("java.lang.Integer").asType(); + case LONG -> this.tes.typeElement("java.lang.Long").asType(); + case SHORT -> this.tes.typeElement("java.lang.Short").asType(); + case VOID -> this.tes.typeElement("java.lang.Void").asType(); + default -> t; }; } public final javax.lang.model.type.TypeMirror unbox(final javax.lang.model.type.TypeMirror t) { return t == null ? null : switch (t.getKind()) { case DECLARED -> switch (((javax.lang.model.element.QualifiedNameable)((javax.lang.model.type.DeclaredType)t).asElement()).getQualifiedName().toString()) { - case "java.lang.Boolean" -> org.microbean.lang.type.PrimitiveType.BOOLEAN; - case "java.lang.Byte" -> org.microbean.lang.type.PrimitiveType.BYTE; - case "java.lang.Character" -> org.microbean.lang.type.PrimitiveType.CHAR; - case "java.lang.Double" -> org.microbean.lang.type.PrimitiveType.DOUBLE; - case "java.lang.Float" -> org.microbean.lang.type.PrimitiveType.FLOAT; - case "java.lang.Integer" -> org.microbean.lang.type.PrimitiveType.INT; - case "java.lang.Long" -> org.microbean.lang.type.PrimitiveType.LONG; - case "java.lang.Short" -> org.microbean.lang.type.PrimitiveType.SHORT; - case "java.lang.Void" -> org.microbean.lang.type.NoType.VOID; - default -> t; + case "java.lang.Boolean" -> this.tes.primitiveType(TypeKind.BOOLEAN); + case "java.lang.Byte" -> this.tes.primitiveType(TypeKind.BYTE); + case "java.lang.Character" -> this.tes.primitiveType(TypeKind.CHAR); + case "java.lang.Double" -> this.tes.primitiveType(TypeKind.DOUBLE); + case "java.lang.Float" -> this.tes.primitiveType(TypeKind.FLOAT); + case "java.lang.Integer" -> this.tes.primitiveType(TypeKind.INT); + case "java.lang.Long" -> this.tes.primitiveType(TypeKind.LONG); + case "java.lang.Short" -> this.tes.primitiveType(TypeKind.SHORT); + case "java.lang.Void" -> this.tes.noType(TypeKind.VOID); + default -> t; }; default -> t; }; @@ -355,20 +355,6 @@ public static final javax.lang.model.element.Element asElement(final javax.lang. } } - // Return the javax.lang.model.type.TypeMirror representing the declaration whose type may currently be being used. - // E.g. given a type denoted by List, return the type denoted by List (from List's usage of - // List) - // - // If it is passed something funny, it just returns what it was passed instead. The compiler does this a lot and I - // think it's confusing. - // - // I don't like this name. - @SuppressWarnings("unchecked") - public static final T typeDeclaration(final T t) { - final javax.lang.model.element.Element e = asElement(t, false /* don't generate synthetic elements */); - return e == null ? t : (T)e.asType(); - } - public static final boolean hasTypeArguments(final javax.lang.model.type.TypeMirror t) { // This is modeled after javac's allparams() method. javac frequently confuses type parameters and type arguments // in its terminology. This implementation could probably be made more efficient. See @@ -397,7 +383,7 @@ public final boolean raw(final javax.lang.model.type.TypeMirror t) { return t == null ? false : switch (t.getKind()) { case ARRAY -> raw(((ArrayType)t).getComponentType()); case DECLARED -> { - final javax.lang.model.type.TypeMirror typeDeclaration = typeDeclaration(t); + final javax.lang.model.type.TypeMirror typeDeclaration = ((javax.lang.model.type.DeclaredType)t).asElement().asType(); yield t != typeDeclaration && // t is a parameterized type, i.e. a type usage, and hasTypeArguments(typeDeclaration) && // the type it parameterizes has type arguments (type variables declared by type parameters) and @@ -407,10 +393,6 @@ public final boolean raw(final javax.lang.model.type.TypeMirror t) { }; } - public static final javax.lang.model.type.WildcardType unboundedWildcardType() { - return new org.microbean.lang.type.WildcardType(); - } - public static final javax.lang.model.type.WildcardType unboundedWildcardType(final List annotationMirrors) { final org.microbean.lang.type.WildcardType t = new org.microbean.lang.type.WildcardType(); t.addAnnotationMirrors(annotationMirrors); @@ -521,8 +503,7 @@ private SyntheticElement(final javax.lang.model.type.TypeMirror t) { @Override public final javax.lang.model.type.TypeMirror asType() { - final javax.lang.model.type.TypeMirror t = this.type.get(); - return t == null ? org.microbean.lang.type.NoType.NONE : t; + return this.type.get(); } private static final javax.lang.model.element.Name generateName(final javax.lang.model.type.TypeMirror t) { diff --git a/lang/src/main/java/org/microbean/lang/visitor/AdaptingVisitor.java b/lang/src/main/java/org/microbean/lang/visitor/AdaptingVisitor.java index 66502c36..646c55b9 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/AdaptingVisitor.java +++ b/lang/src/main/java/org/microbean/lang/visitor/AdaptingVisitor.java @@ -1,18 +1,15 @@ /* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- * - * Copyright © 2023 microBean™. + * Copyright © 2023–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang.visitor; @@ -47,6 +44,9 @@ * Does something adapting-like. * *

Usage: call {@link #adapt(DeclaredType, DeclaredType)}, not {@link #visit(TypeMirror)}.

+ * + *

This is a "one shot" visitor: because it mutates its internal data structures (!) (following the analogous + * structures in the compiler), an instance of this class should not be reused.

*/ // Not thread safe. // Basically done. @@ -54,10 +54,7 @@ final class AdaptingVisitor extends SimpleTypeVisitor14 { /* - * Ported mostly slavishly from the compiler. Some thoughts: - * - * The compiler code is really bad, but presumably battle-tested. I'm guessing that a list of "from" and a list of - * "to" rather than a Map was done on purpose. I cannot begin to think of what the purpose is. + * Ported mostly slavishly from the compiler. */ // The compiler's implementation mutates this list. @@ -66,7 +63,7 @@ final class AdaptingVisitor extends SimpleTypeVisitor14 { // The compiler's implementation mutates this list. private final List to; - private final TypeAndElementSource elementSource; + private final TypeAndElementSource tes; private final Types types; @@ -78,14 +75,14 @@ final class AdaptingVisitor extends SimpleTypeVisitor14 { private final Set cache; - AdaptingVisitor(final TypeAndElementSource elementSource, + AdaptingVisitor(final TypeAndElementSource tes, final Types types, final SameTypeVisitor sameTypeVisitor, final SubtypeVisitor subtypeVisitor, final List from, // mutated final List to) { // mutated super(); - this.elementSource = Objects.requireNonNull(elementSource, "elementSource"); + this.tes = Objects.requireNonNull(tes, "tes"); this.types = Objects.requireNonNull(types, "types"); this.sameTypeVisitor = Objects.requireNonNull(sameTypeVisitor, "sameTypeVisitor"); this.subtypeVisitor = Objects.requireNonNull(subtypeVisitor, "subtypeVisitor"); @@ -99,7 +96,7 @@ final void adapt(final DeclaredType source, final DeclaredType target) { this.visitDeclared(source, target); final int fromSize = this.from.size(); for (int i = 0; i < fromSize; i++) { - final TypeMirror val = this.mapping.get(DelegatingElement.of(asElement(this.from.get(i), true), this.elementSource)); + final TypeMirror val = this.mapping.get(DelegatingElement.of(asElement(this.from.get(i), true), this.tes)); if (this.to.get(i) != val) { this.to.set(i, val); } @@ -131,7 +128,7 @@ public final Void visitDeclared(final DeclaredType source, final TypeMirror targ @Override public final Void visitTypeVariable(final TypeVariable source, final TypeMirror target) { assert source.getKind() == TypeKind.TYPEVAR; - final DelegatingElement sourceElement = DelegatingElement.of(source.asElement(), this.elementSource); + final DelegatingElement sourceElement = DelegatingElement.of(source.asElement(), this.tes); TypeMirror val = this.mapping.get(sourceElement); if (val == null) { val = target; @@ -195,7 +192,7 @@ public final Void visitWildcard(final WildcardType source, final TypeMirror targ } private final void adaptRecursive(final TypeMirror source, final TypeMirror target) { - final TypeMirrorPair pair = new TypeMirrorPair(this.types, this.sameTypeVisitor, source, target); + final TypeMirrorPair pair = new TypeMirrorPair(this.sameTypeVisitor, source, target); if (this.cache.add(pair)) { try { this.visit(source, target); diff --git a/lang/src/main/java/org/microbean/lang/visitor/AsSuperVisitor.java b/lang/src/main/java/org/microbean/lang/visitor/AsSuperVisitor.java index 2422a35f..e57196fb 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/AsSuperVisitor.java +++ b/lang/src/main/java/org/microbean/lang/visitor/AsSuperVisitor.java @@ -1,6 +1,6 @@ /* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- * - * Copyright © 2023 microBean™. + * Copyright © 2023–2024 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 @@ -46,6 +46,9 @@ *

For example, given a type denoted by {@code List}, and a {@link javax.lang.model.element.TypeElement} * denoted by {@code Collection}, the result of visitation will be the type denoted by {@code Collection}.

* + *

So "as super" is probably derived from the fact that after this visitor runs you get a view, of sorts, of your + * parameterized type "as" a parameterized "super" type of a particular kind.

+ * *

{@code javac} does odd things with this and arrays and it is not clear that its documentation matches its * code. Consequently I don't have a lot of faith in the {@link #visitArray(ArrayType, Element)} method as of this * writing.

@@ -70,7 +73,7 @@ public final class AsSuperVisitor extends SimpleTypeVisitor14 seenTypes; // in the compiler, the field is called seenTypes but stores Symbols (Elements). - private final TypeAndElementSource elementSource; + private final TypeAndElementSource tes; private final Equality equality; @@ -80,13 +83,13 @@ public final class AsSuperVisitor extends SimpleTypeVisitor14(); - this.elementSource = Objects.requireNonNull(elementSource, "elementSource"); + this.tes = Objects.requireNonNull(tes, "tes"); this.equality = equality == null ? new Equality(true) : equality; this.types = Objects.requireNonNull(types, "types"); this.supertypeVisitor = Objects.requireNonNull(supertypeVisitor, "supertypeVisitor"); @@ -96,14 +99,14 @@ public final AsSuperVisitor withSupertypeVisitor(final SupertypeVisitor supertyp if (supertypeVisitor == this.supertypeVisitor) { return this; } - return new AsSuperVisitor(this.elementSource, this.equality, this.types, supertypeVisitor); + return new AsSuperVisitor(this.tes, this.equality, this.types, supertypeVisitor); } public final AsSuperVisitor withSubtypeVisitor(final SubtypeVisitor subtypeVisitor) { if (subtypeVisitor == this.subtypeVisitor) { return this; } - final AsSuperVisitor v = new AsSuperVisitor(this.elementSource, this.equality, this.types, this.supertypeVisitor); + final AsSuperVisitor v = new AsSuperVisitor(this.tes, this.equality, this.types, this.supertypeVisitor); v.setSubtypeVisitor(subtypeVisitor); return v; } @@ -156,7 +159,7 @@ private final TypeMirror visitDeclaredOrIntersection(final TypeMirror t, final E return t; } // TODO: may be able to get away with identity instead of DelegatingElement - final DelegatingElement c = DelegatingElement.of(te, this.elementSource); + final DelegatingElement c = DelegatingElement.of(te, this.tes); if (!this.seenTypes.add(c)) { // javac calls it seenTypes but it stores Symbols/Elements return null; } diff --git a/lang/src/main/java/org/microbean/lang/visitor/BoundingClassVisitor.java b/lang/src/main/java/org/microbean/lang/visitor/BoundingClassVisitor.java index 5c421f74..bb10654e 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/BoundingClassVisitor.java +++ b/lang/src/main/java/org/microbean/lang/visitor/BoundingClassVisitor.java @@ -24,15 +24,21 @@ import javax.lang.model.util.SimpleTypeVisitor14; +import org.microbean.lang.TypeAndElementSource; + // A mostly slavish port of // https://github.com/openjdk/jdk/blob/jdk-21%2B22/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java#L2746-L2780. -// To be quite honest I'm not sure how this ever has any effect at all. +// I *believe* this will take something like T extends List and will yield List (which is not the same as erasure +// of a type variable). public final class BoundingClassVisitor extends SimpleTypeVisitor14 { + private final TypeAndElementSource tes; + private final SupertypeVisitor supertypeVisitor; - public BoundingClassVisitor(final SupertypeVisitor supertypeVisitor) { + public BoundingClassVisitor(final TypeAndElementSource tes, final SupertypeVisitor supertypeVisitor) { super(); + this.tes = Objects.requireNonNull(tes, "tes"); this.supertypeVisitor = Objects.requireNonNull(supertypeVisitor, "supertypeVisitor"); } @@ -49,18 +55,25 @@ public final DeclaredType visitDeclared(final DeclaredType t, final Void x) { if (enclosingType == visitedEnclosingType) { return t; } + assert visitedEnclosingType.getKind() == TypeKind.DECLARED; + return tes.declaredType((DeclaredType)visitedEnclosingType, (TypeElement)t.asElement(), t.getTypeArguments().toArray(new TypeMirror[0])); + /* final org.microbean.lang.type.DeclaredType dt = new org.microbean.lang.type.DeclaredType(); dt.addTypeArguments(t.getTypeArguments()); dt.addAnnotationMirrors(t.getAnnotationMirrors()); dt.setDefiningElement((TypeElement)t.asElement()); dt.setEnclosingType(visitedEnclosingType); // note return dt; + */ } @Override public final TypeMirror visitTypeVariable(final TypeVariable t, final Void x) { assert t.getKind() == TypeKind.TYPEVAR; - return this.visit(this.supertypeVisitor.visit(t)); // this effectively erases T extends S to just S + // Recall that the supertype of a type variable is its "leftmost bound". So: + // Given T extends S, yield S. + // Given T extends List, yield List (so this is not erasure). + return this.visit(this.supertypeVisitor.visit(t)); } } diff --git a/lang/src/main/java/org/microbean/lang/visitor/CaptureVisitor.java b/lang/src/main/java/org/microbean/lang/visitor/CaptureVisitor.java index 9018a77d..6139b5f7 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/CaptureVisitor.java +++ b/lang/src/main/java/org/microbean/lang/visitor/CaptureVisitor.java @@ -1,18 +1,15 @@ /* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- * - * Copyright © 2023 microBean™. + * Copyright © 2023–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang.visitor; @@ -47,7 +44,7 @@ // https://github.com/openjdk/jdk/blob/jdk-20+14/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java#L4388-L4456 public final class CaptureVisitor extends SimpleTypeVisitor14 { - private final TypeAndElementSource elementSource; + private final TypeAndElementSource tes; private final Equality equality; @@ -61,13 +58,13 @@ public final class CaptureVisitor extends SimpleTypeVisitor14 private TypeClosureVisitor typeClosureVisitor; - public CaptureVisitor(final TypeAndElementSource elementSource, + public CaptureVisitor(final TypeAndElementSource tes, final Equality equality, final Types types, final SupertypeVisitor supertypeVisitor, // used by internal SubstituteVisitor final MemberTypeVisitor memberTypeVisitor) { super(); - this.elementSource = Objects.requireNonNull(elementSource, "elementSource"); + this.tes = Objects.requireNonNull(tes, "tes"); this.equality = equality == null ? new Equality(true) : equality; this.types = Objects.requireNonNull(types, "types"); this.supertypeVisitor = Objects.requireNonNull(supertypeVisitor, "supertypeVisitor"); @@ -106,7 +103,7 @@ public final TypeMirror visitDeclared(DeclaredType t, final Void x) { if (capturedEnclosingType != enclosingType) { final Element element = t.asElement(); final TypeMirror memberType = this.memberTypeVisitor.visit(capturedEnclosingType, element); - t = (DeclaredType)new SubstituteVisitor(this.elementSource, + t = (DeclaredType)new SubstituteVisitor(this.tes, this.equality, this.supertypeVisitor, ((DeclaredType)element.asType()).getTypeArguments(), @@ -149,18 +146,18 @@ public final TypeMirror visitDeclared(DeclaredType t, final Void x) { captured = true; TypeMirror Ui = currentAHead.getUpperBound(); if (Ui == null) { - Ui = this.elementSource.typeElement("java.lang.Object").asType(); + Ui = this.tes.typeElement("java.lang.Object").asType(); } final Capture Si = (Capture)currentSHead; final WildcardType Ti = (WildcardType)currentTHead; Si.setLowerBound(Ti.getSuperBound()); final TypeMirror TiExtendsBound = Ti.getExtendsBound(); if (TiExtendsBound == null) { - Si.setUpperBound(new SubstituteVisitor(this.elementSource, this.equality, this.supertypeVisitor, A, S).visit(Ui)); + Si.setUpperBound(new SubstituteVisitor(this.tes, this.equality, this.supertypeVisitor, A, S).visit(Ui)); } else { // TiExtendsBound can be DECLARED, INTERSECTION or TYPEVAR Si.setUpperBound(glb(TiExtendsBound, - new SubstituteVisitor(this.elementSource, this.equality, this.supertypeVisitor, A, S).visit(Ui))); + new SubstituteVisitor(this.tes, this.equality, this.supertypeVisitor, A, S).visit(Ui))); } } } @@ -197,7 +194,7 @@ private final TypeMirror glb(final TypeMirror t, final TypeMirror s) { final int size = minimumTypes.size(); switch (size) { case 0: - return this.elementSource.typeElement("java.lang.Object").asType(); + return this.tes.typeElement("java.lang.Object").asType(); case 1: return minimumTypes.get(0); } @@ -242,11 +239,11 @@ private final TypeMirror glb(final List ts) { return t1; } - private static final TypeMirror capturedTypeVariableLowerBound(final TypeMirror capture) { + private final TypeMirror capturedTypeVariableLowerBound(final TypeMirror capture) { if (capture.getKind() == TypeKind.TYPEVAR && capture instanceof Capture c) { final TypeMirror lowerBound = c.getLowerBound(); if (lowerBound == null) { - return org.microbean.lang.type.NullType.INSTANCE; + return this.tes.nullType(); } else { return lowerBound.getKind() == TypeKind.NULL ? lowerBound : capturedTypeVariableLowerBound(lowerBound); // RECURSIVE } diff --git a/lang/src/main/java/org/microbean/lang/visitor/ContainsTypeVisitor.java b/lang/src/main/java/org/microbean/lang/visitor/ContainsTypeVisitor.java index cf008c97..058569e5 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/ContainsTypeVisitor.java +++ b/lang/src/main/java/org/microbean/lang/visitor/ContainsTypeVisitor.java @@ -1,18 +1,15 @@ /* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- * - * Copyright © 2023 microBean™. + * Copyright © 2023–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang.visitor; @@ -62,7 +59,7 @@ // https://github.com/openjdk/jdk/blob/jdk-20+12/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java#L1562-L1611 public final class ContainsTypeVisitor extends SimpleTypeVisitor14 { - private final TypeAndElementSource elementSource; + private final TypeAndElementSource tes; private final Types types; @@ -70,9 +67,9 @@ public final class ContainsTypeVisitor extends SimpleTypeVisitor14 { private final Types types; - public EraseVisitor(final TypeAndElementSource elementSource, final Types types) { - super(elementSource); + public EraseVisitor(final TypeAndElementSource tes, final Types types) { + super(tes); this.types = Objects.requireNonNull(types, "types"); } diff --git a/lang/src/main/java/org/microbean/lang/visitor/InterfacesVisitor.java b/lang/src/main/java/org/microbean/lang/visitor/InterfacesVisitor.java index 14bda356..5ba65a59 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/InterfacesVisitor.java +++ b/lang/src/main/java/org/microbean/lang/visitor/InterfacesVisitor.java @@ -38,7 +38,7 @@ // Basically done public final class InterfacesVisitor extends SimpleTypeVisitor14, Void> { - private final TypeAndElementSource elementSource; + private final TypeAndElementSource tes; private final Equality equality; @@ -48,14 +48,14 @@ public final class InterfacesVisitor extends SimpleTypeVisitor14 visitDeclared(final DeclaredType t, fina } assert this.supertypeVisitor.interfacesVisitor() == this; yield - new SubstituteVisitor(this.elementSource, this.equality, this.supertypeVisitor, formals, allTypeArguments(t)) + new SubstituteVisitor(this.tes, this.equality, this.supertypeVisitor, formals, allTypeArguments(t)) .visit(interfaces, x); default: yield List.of(); @@ -94,15 +94,15 @@ public final List visitDeclared(final DeclaredType t, fina public final List visitIntersection(final IntersectionType t, final Void x) { assert t.getKind() == TypeKind.INTERSECTION; // Here the porting is a little trickier. It turns out that an intersection type caches its supertype and its - // interfaces at construction time, and there's only one place where intersection types are created. In the lang + // interfaces at construction time, and there's only one place where intersection types are created. In the lang // model, that means that an IntersectionType's bounds are its single non-interface supertype, if any, followed by // its interfaces. So we will hand-tool this. final List bounds = t.getBounds(); final int size = bounds.size(); return switch (size) { - case 0 -> List.of(); - case 1 -> isInterface(bounds.get(0)) ? bounds : List.of(); - default -> isInterface(bounds.get(0)) ? bounds : bounds.subList(1, size); + case 0 -> List.of(); // technically illegal + case 1 -> isInterface(bounds.get(0)) ? bounds : List.of(); + default -> isInterface(bounds.get(0)) ? bounds : bounds.subList(1, size); // skip the first element; the rest will be interfaces }; } diff --git a/lang/src/main/java/org/microbean/lang/visitor/MemberTypeVisitor.java b/lang/src/main/java/org/microbean/lang/visitor/MemberTypeVisitor.java index 60950a32..3b16cf80 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/MemberTypeVisitor.java +++ b/lang/src/main/java/org/microbean/lang/visitor/MemberTypeVisitor.java @@ -1,18 +1,15 @@ /* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- * - * Copyright © 2023 microBean™. + * Copyright © 2023–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang.visitor; @@ -34,7 +31,6 @@ import org.microbean.lang.TypeAndElementSource; import org.microbean.lang.Equality; -import org.microbean.lang.type.NoType; import org.microbean.lang.type.Types; import static org.microbean.lang.type.Types.allTypeArguments; @@ -44,7 +40,7 @@ // https://github.com/openjdk/jdk/blob/jdk-20+13/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java#L2294-L2340 public final class MemberTypeVisitor extends SimpleTypeVisitor14 { - private final TypeAndElementSource elementSource; + private final TypeAndElementSource tes; private final Equality equality; @@ -56,14 +52,14 @@ public final class MemberTypeVisitor extends SimpleTypeVisitor14 tMap = new HashMap<>(); for (final TypeMirror ti : this.supertypeVisitor.interfacesVisitor().visitIntersection(t, null)) { assert ti.getKind() == TypeKind.DECLARED; - tMap.put(DelegatingElement.of(((DeclaredType)t).asElement(), this.elementSource), ti); + tMap.put(DelegatingElement.of(((DeclaredType)t).asElement(), this.tes), ti); } for (final TypeMirror si : this.supertypeVisitor.interfacesVisitor().visitIntersection(s, null)) { assert si.getKind() == TypeKind.DECLARED; @@ -300,7 +297,7 @@ private final boolean visitTypeVariable(final TypeVariable t, final WildcardType return s.getExtendsBound() == null && s.getSuperBound() != null && - this.visit(t, this.elementSource.typeElement("java.lang.Object").asType()); + this.visit(t, this.tes.typeElement("java.lang.Object").asType()); } @Override @@ -375,7 +372,7 @@ private final boolean hasSameBounds(final List ts, final if (size != ss.size()) { return false; } else if (size > 0) { - final SubstituteVisitor sv = new SubstituteVisitor(this.elementSource, this.equality, this.supertypeVisitor, ss, ts); + final SubstituteVisitor sv = new SubstituteVisitor(this.tes, this.equality, this.supertypeVisitor, ss, ts); for (int i = 0; i < size; i++) { final TypeVariable t = ts.get(i); final TypeVariable s = ss.get(i); diff --git a/lang/src/main/java/org/microbean/lang/visitor/StructuralTypeMapping.java b/lang/src/main/java/org/microbean/lang/visitor/StructuralTypeMapping.java index 2fc810c0..d26ae14f 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/StructuralTypeMapping.java +++ b/lang/src/main/java/org/microbean/lang/visitor/StructuralTypeMapping.java @@ -1,18 +1,15 @@ /* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- * - * Copyright © 2023 microBean™. + * Copyright © 2023–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang.visitor; @@ -35,11 +32,11 @@ // See https://github.com/openjdk/jdk/blob/jdk-20+11/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java#L244 class StructuralTypeMapping extends SimpleTypeVisitor14 { - protected final TypeAndElementSource elementSource; + protected final TypeAndElementSource tes; - StructuralTypeMapping(final TypeAndElementSource elementSource) { + StructuralTypeMapping(final TypeAndElementSource tes) { super(); - this.elementSource = Objects.requireNonNull(elementSource, "elementSource"); + this.tes = Objects.requireNonNull(tes, "tes"); } @Override // SimpleTypeVisitor6 @@ -74,7 +71,7 @@ public TypeMirror visitArray(final ArrayType t, final S s) { if (componentType == visitedComponentType) { return t; } - return new org.microbean.lang.type.ArrayType(visitedComponentType); + return this.tes.arrayTypeOf(visitedComponentType); } @Override // SimpleTypeVisitor6 @@ -87,11 +84,7 @@ public TypeMirror visitDeclared(final DeclaredType t, final S s) { if (enclosingType == visitedEnclosingType && typeArguments == visitedTypeArguments) { return t; } - final org.microbean.lang.type.DeclaredType r = new org.microbean.lang.type.DeclaredType(); - r.setEnclosingType(visitedEnclosingType); - r.addTypeArguments(visitedTypeArguments); - r.setDefiningElement((javax.lang.model.element.TypeElement)t.asElement()); - return r; + return tes.declaredType((DeclaredType)visitedEnclosingType, (javax.lang.model.element.TypeElement)t.asElement(), visitedTypeArguments.toArray(new TypeMirror[0])); } // See https://github.com/openjdk/jdk/blob/jdk-20+11/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java#L290-L313 @@ -128,7 +121,7 @@ public TypeMirror visitWildcard(final WildcardType t, final S s) { final TypeMirror visitedSuperBound; if (extendsBound == null) { if (superBound == null) { - extendsBound = this.elementSource.typeElement("java.lang.Object").asType(); + extendsBound = this.tes.typeElement("java.lang.Object").asType(); visitedExtendsBound = this.visit(extendsBound, s); visitedSuperBound = null; } else { diff --git a/lang/src/main/java/org/microbean/lang/visitor/SubstituteVisitor.java b/lang/src/main/java/org/microbean/lang/visitor/SubstituteVisitor.java index cc2d9709..91afced2 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/SubstituteVisitor.java +++ b/lang/src/main/java/org/microbean/lang/visitor/SubstituteVisitor.java @@ -1,18 +1,15 @@ /* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- * - * Copyright © 2023 microBean™. + * Copyright © 2023–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang.visitor; @@ -58,12 +55,12 @@ final class SubstituteVisitor extends StructuralTypeMapping { */ - SubstituteVisitor(final TypeAndElementSource elementSource, + SubstituteVisitor(final TypeAndElementSource tes, final Equality equality, final SupertypeVisitor supertypeVisitor, // used only for intersection types List from, List to) { - super(elementSource); + super(tes); this.equality = equality == null ? new Equality(false) : equality; this.supertypeVisitor = Objects.requireNonNull(supertypeVisitor, "supertypeVisitor"); // https://github.com/openjdk/jdk/blob/jdk-20+12/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java#L3321-L3322 @@ -96,7 +93,7 @@ final SubstituteVisitor with(final List from, if (from == this.from && to == this.to) { return this; } - return new SubstituteVisitor(this.elementSource, this.equality, this.supertypeVisitor, from, to); + return new SubstituteVisitor(this.tes, this.equality, this.supertypeVisitor, from, to); } // https://github.com/openjdk/jdk/blob/jdk-20+12/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java#L3382-L3411 @@ -139,8 +136,7 @@ public final ExecutableType visitExecutable(ExecutableType t, final Void x) { @Override public final IntersectionType visitIntersection(final IntersectionType t, final Void x) { assert t.getKind() == TypeKind.INTERSECTION; - // final TypeMirror supertype = this.supertypeVisitor.visit(t, x); // (Returns t.getBounds().get(0).) - final TypeMirror supertype = t.getBounds().get(0); + final TypeMirror supertype = this.supertypeVisitor.visit(t, x); // (Returns t.getBounds().get(0).) final TypeMirror visitedSupertype = this.visit(supertype, x); final List interfaces = this.supertypeVisitor.interfacesVisitor().visit(t, x); final List visitedInterfaces = this.visit(interfaces, x); @@ -228,13 +224,13 @@ private final List newInstances(final List visitUpperBoundsOf(final List visitedUpperBounds = new ArrayList<>(tvs.size()); // could be pointless if nothing changed boolean changed = false; @@ -266,12 +262,12 @@ private final List visitUpperBoundsOf(final List newTvs = new ArrayList<>(tvs.size()); for (final TypeVariable tv : tvs) { final org.microbean.lang.type.TypeVariable newTv = - new org.microbean.lang.type.TypeVariable(this.elementSource, null, tv.getLowerBound()); + new org.microbean.lang.type.TypeVariable(this.tes, null, tv.getLowerBound()); newTv.setDefiningElement((TypeParameterElement)tv.asElement()); newTvs.add(newTv); } @@ -279,8 +275,8 @@ private final List visitUpperBoundsOf(final List visitUpperBoundsOf(final List { - private final TypeAndElementSource elementSource; + private final TypeAndElementSource tes; private final Equality equality; @@ -78,7 +75,7 @@ public final class SubtypeVisitor extends SimpleTypeVisitor14(); - this.elementSource = Objects.requireNonNull(elementSource, "elementSource"); + this.tes = Objects.requireNonNull(tes, "tes"); this.equality = equality == null ? new Equality(true) : equality; this.types = Objects.requireNonNull(types, "types"); this.asSuperVisitor = Objects.requireNonNull(asSuperVisitor, "asSuperVisitor"); @@ -115,7 +112,7 @@ public final SubtypeVisitor withAsSuperVisitor(final AsSuperVisitor asSuperVisit return this; } return - new SubtypeVisitor(this.elementSource, + new SubtypeVisitor(this.tes, this.equality, this.types, asSuperVisitor, @@ -130,7 +127,7 @@ final SubtypeVisitor withCapture(final boolean capture) { if (capture) { if (this.withCaptureVariant == null) { this.withCaptureVariant = - new SubtypeVisitor(this.elementSource, + new SubtypeVisitor(this.tes, this.equality, this.types, this.asSuperVisitor, @@ -143,7 +140,7 @@ final SubtypeVisitor withCapture(final boolean capture) { return this.withCaptureVariant; } else if (this.withoutCaptureVariant == null) { this.withoutCaptureVariant = - new SubtypeVisitor(this.elementSource, + new SubtypeVisitor(this.tes, this.equality, this.types, this.asSuperVisitor, @@ -461,7 +458,7 @@ private final boolean containsTypeRecursive(final TypeMirror t, final TypeMirror if (tTypeArguments.isEmpty() || sTypeArguments.isEmpty()) { return false; } - final TypeMirrorPair pair = new TypeMirrorPair(this.types, this.sameTypeVisitor, t, s); + final TypeMirrorPair pair = new TypeMirrorPair(this.sameTypeVisitor, t, s); if (this.cache.add(pair)) { try { return this.containsTypeVisitor.visit(tTypeArguments, sTypeArguments); @@ -486,7 +483,7 @@ private final TypeMirror rewriteSupers(final TypeMirror t) { if (!allTypeArguments(t).isEmpty()) { final List from = new ArrayList<>(); final List to = new ArrayList<>(); - new AdaptingVisitor(this.elementSource, this.types, this.sameTypeVisitor, this, from, to).adaptSelf((DeclaredType)t); + new AdaptingVisitor(this.tes, this.types, this.sameTypeVisitor, this, from, to).adaptSelf((DeclaredType)t); if (!from.isEmpty()) { final List rewrite = new ArrayList<>(); boolean changed = false; @@ -516,7 +513,7 @@ private final TypeMirror rewriteSupers(final TypeMirror t) { } if (changed) { // (If t is a DeclaredType or a TypeVariable, call asElement().asType() and visit that.) - return new SubstituteVisitor(this.elementSource, this.equality, this.supertypeVisitor, from, rewrite) + return new SubstituteVisitor(this.tes, this.equality, this.supertypeVisitor, from, rewrite) .visit(switch (t.getKind()) { case DECLARED -> ((DeclaredType)t).asElement().asType(); case TYPEVAR -> ((TypeVariable)t).asElement().asType(); diff --git a/lang/src/main/java/org/microbean/lang/visitor/SupertypeVisitor.java b/lang/src/main/java/org/microbean/lang/visitor/SupertypeVisitor.java index 613c9d60..246af148 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/SupertypeVisitor.java +++ b/lang/src/main/java/org/microbean/lang/visitor/SupertypeVisitor.java @@ -30,7 +30,6 @@ import org.microbean.lang.TypeAndElementSource; import org.microbean.lang.Equality; -import org.microbean.lang.type.NoType; import org.microbean.lang.type.Types; // Returns the superclass (or parameterized superclass) of a type, if applicable. See #interfacesVisitor() for returning @@ -73,13 +72,13 @@ public SupertypeVisitor(final TypeAndElementSource tes, final Equality equality, final Types types, final EraseVisitor eraseVisitor) { - super(NoType.NONE); // default return value from the visit*() methods + super(tes.noType(TypeKind.NONE)); // default return value from the visit*() methods this.equality = equality == null ? new Equality(true) : equality; - this.tes = Objects.requireNonNull(tes, "tes"); + this.tes = tes; this.types = Objects.requireNonNull(types, "types"); this.eraseVisitor = Objects.requireNonNull(eraseVisitor, "eraseVisitor"); this.interfacesVisitor = new InterfacesVisitor(tes, this.equality, types, eraseVisitor, this); - this.boundingClassVisitor = new BoundingClassVisitor(this); + this.boundingClassVisitor = new BoundingClassVisitor(tes, this); } diff --git a/lang/src/main/java/org/microbean/lang/visitor/TypeClosure.java b/lang/src/main/java/org/microbean/lang/visitor/TypeClosure.java index 8c6f6c27..8aed5aed 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/TypeClosure.java +++ b/lang/src/main/java/org/microbean/lang/visitor/TypeClosure.java @@ -2,17 +2,14 @@ * * Copyright © 2023–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang.visitor; @@ -58,7 +55,7 @@ public final class TypeClosure { */ - private final TypeAndElementSource elementSource; + private final TypeAndElementSource tes; // DelegatingTypeMirror so things like list.contains(t) will work with arbitrary TypeMirror implementations private final Deque deque; @@ -73,19 +70,19 @@ public final class TypeClosure { */ - TypeClosure(final TypeAndElementSource elementSource, final SupertypeVisitor supertypeVisitor, final SubtypeVisitor subtypeVisitor) { - this(elementSource, new PrecedesPredicate(supertypeVisitor, subtypeVisitor), null); + TypeClosure(final TypeAndElementSource tes, final SupertypeVisitor supertypeVisitor, final SubtypeVisitor subtypeVisitor) { + this(tes, new PrecedesPredicate(supertypeVisitor, subtypeVisitor), null); } - TypeClosure(final TypeAndElementSource elementSource, final BiPredicate precedesPredicate) { - this(elementSource, precedesPredicate, null); + TypeClosure(final TypeAndElementSource tes, final BiPredicate precedesPredicate) { + this(tes, precedesPredicate, null); } - TypeClosure(final TypeAndElementSource elementSource, + TypeClosure(final TypeAndElementSource tes, final BiPredicate precedesPredicate, final BiPredicate equalsPredicate) { super(); - this.elementSource = Objects.requireNonNull(elementSource, "elementSource"); + this.tes = Objects.requireNonNull(tes, "tes"); this.deque = new ArrayDeque<>(10); this.precedesPredicate = Objects.requireNonNull(precedesPredicate, "precedesPredicate"); this.equalsPredicate = equalsPredicate == null ? Equality::equalsIncludingAnnotations : equalsPredicate; @@ -114,7 +111,7 @@ final void union(final TypeMirror t) { final DelegatingTypeMirror head = this.deque.peekFirst(); if (head == null) { - this.deque.addFirst(DelegatingTypeMirror.of(t, this.elementSource)); + this.deque.addFirst(DelegatingTypeMirror.of(t, this.tes)); return; } @@ -132,10 +129,10 @@ final void union(final TypeMirror t) { if (!this.equalsPredicate.test(e, headE)) { if (this.precedesPredicate.test(e, headE)) { - this.deque.addFirst(DelegatingTypeMirror.of(t, this.elementSource)); + this.deque.addFirst(DelegatingTypeMirror.of(t, this.tes)); } else if (this.deque.size() == 1) { // No need to recurse and get fancy; just add last - this.deque.addLast(DelegatingTypeMirror.of(t, this.elementSource)); + this.deque.addLast(DelegatingTypeMirror.of(t, this.tes)); } else { this.deque.removeFirst(); // returns head this.union(t); // RECURSIVE @@ -169,7 +166,7 @@ private final void union(final List list) { switch (t.getKind()) { case DECLARED: case TYPEVAR: - this.deque.addLast(DelegatingTypeMirror.of(t, this.elementSource)); + this.deque.addLast(DelegatingTypeMirror.of(t, this.tes)); break; default: throw new IllegalArgumentException("t: " + t); @@ -211,7 +208,7 @@ private final void union(final List list) { this.deque.addFirst(head0); // put head0 back } else if (this.precedesPredicate.test(head1E, head0E)) { this.union(list.subList(1, size)); // RECURSIVE - this.deque.addFirst(DelegatingTypeMirror.of(head1, this.elementSource)); + this.deque.addFirst(DelegatingTypeMirror.of(head1, this.tes)); } else { this.deque.removeFirst(); // removes head0 this.union(list); // RECURSIVE @@ -225,7 +222,7 @@ final void prepend(final TypeVariable t) { if (t.getKind() != TypeKind.TYPEVAR) { throw new IllegalArgumentException("t: " + t); } - this.deque.addFirst(DelegatingTypeMirror.of(t, this.elementSource)); + this.deque.addFirst(DelegatingTypeMirror.of(t, this.tes)); } // Port of javac's Types#closureMin(List) @@ -240,7 +237,7 @@ final List toMinimumTypes(final SubtypeVisitor subtypeVisi for (int i = 0, next = 1; i < size; i++, next++) { final TypeMirror current = array[i]; - boolean keep = !toSkip.contains(DelegatingTypeMirror.of(current, this.elementSource)); + boolean keep = !toSkip.contains(DelegatingTypeMirror.of(current, this.tes)); if (keep && current.getKind() == TypeKind.TYPEVAR && next < size) { for (int j = next; j < size; j++) { if (subtypeVisitor.withCapture(false).visit(array[j], current)) { @@ -263,7 +260,7 @@ final List toMinimumTypes(final SubtypeVisitor subtypeVisi if (subtypeVisitor.withCapture(false).visit(current, t)) { // As we're processing this.list, we can skip supertypes of current (t, here) because we know current is // already more specialized than they are. - toSkip.add(DelegatingTypeMirror.of(t, this.elementSource)); + toSkip.add(DelegatingTypeMirror.of(t, this.tes)); } } } diff --git a/lang/src/main/java/org/microbean/lang/visitor/TypeClosureVisitor.java b/lang/src/main/java/org/microbean/lang/visitor/TypeClosureVisitor.java index f3afea17..b0b62ab9 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/TypeClosureVisitor.java +++ b/lang/src/main/java/org/microbean/lang/visitor/TypeClosureVisitor.java @@ -16,6 +16,9 @@ import java.util.Objects; import java.util.WeakHashMap; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + import javax.lang.model.type.DeclaredType; import javax.lang.model.type.IntersectionType; import javax.lang.model.type.TypeKind; @@ -50,6 +53,8 @@ public final class TypeClosureVisitor extends SimpleTypeVisitor14 closureCache; @@ -78,6 +83,7 @@ public TypeClosureVisitor(final TypeAndElementSource tes, final SupertypeVisitor supertypeVisitor, final PrecedesPredicate precedesPredicate) { super(); + this.lock = new ReentrantReadWriteLock(); this.tes = Objects.requireNonNull(tes, "tes"); this.supertypeVisitor = Objects.requireNonNull(supertypeVisitor, "supertypeVisitor"); this.precedesPredicate = Objects.requireNonNull(precedesPredicate, "precedesPredicate"); @@ -115,13 +121,16 @@ public final TypeClosure visitTypeVariable(final TypeVariable t, final Void x) { private final TypeClosure visitDeclaredOrIntersectionOrTypeVariable(final TypeMirror t, final Void x) { TypeClosure closure; - synchronized (this.closureCache) { + this.lock.readLock().lock(); + try { closure = this.closureCache.get(t); + } finally { + this.lock.readLock().unlock(); } if (closure == null) { switch (t.getKind()) { case INTERSECTION: - // The closure does not include the intersection type itself. Note that this little nugget effectively removes + // The closure does not include the intersection type itself. Note that this little nugget effectively removes // intersection types from the possible types that will ever be passed to TypeClosure#union(TypeMirror). closure = this.visit(this.supertypeVisitor.visit(t)); break; @@ -182,8 +191,11 @@ private final TypeClosure visitDeclaredOrIntersectionOrTypeVariable(final TypeMi for (final TypeMirror iface : this.supertypeVisitor.interfacesVisitor().visit(t)) { closure.union(this.visit(iface)); } - synchronized (this.closureCache) { + this.lock.writeLock().lock(); + try { closureCache.put(t, closure); + } finally { + this.lock.writeLock().unlock(); } } return closure; diff --git a/lang/src/main/java/org/microbean/lang/visitor/TypeMirrorPair.java b/lang/src/main/java/org/microbean/lang/visitor/TypeMirrorPair.java index 4908ecca..c8d6782f 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/TypeMirrorPair.java +++ b/lang/src/main/java/org/microbean/lang/visitor/TypeMirrorPair.java @@ -1,18 +1,15 @@ /* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- * - * Copyright © 2023 microBean™. + * Copyright © 2023–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang.visitor; @@ -36,20 +33,16 @@ final class TypeMirrorPair { - private final Types types; - private final SameTypeVisitor sameTypeVisitor; private final TypeMirror t; private final TypeMirror s; - TypeMirrorPair(final Types types, - final SameTypeVisitor sameTypeVisitor, + TypeMirrorPair(final SameTypeVisitor sameTypeVisitor, final TypeMirror t, final TypeMirror s) { super(); - this.types = Objects.requireNonNull(types, "types"); this.sameTypeVisitor = Objects.requireNonNull(sameTypeVisitor, "sameTypeVisitor"); this.t = Objects.requireNonNull(t, "t"); this.s = Objects.requireNonNull(s, "s"); @@ -85,7 +78,7 @@ private final int hashCode(final TypeMirror t) { case DECLARED: case INTERSECTION: // return this.hashCode0(t); - int result = 127 * hashCode(enclosingType(t)); + int result = 127 * hashCode(tk == TypeKind.DECLARED ? ((DeclaredType)t).getEnclosingType() : null); final Element e = asElement(t, true); if (e != null) { result += flatName(e).hashCode(); @@ -164,15 +157,6 @@ private final int hashCode(final WildcardType t) { return result; } - private static final TypeMirror enclosingType(final TypeMirror t) { - switch (t.getKind()) { - case DECLARED: - return ((DeclaredType)t).getEnclosingType(); - default: - return org.microbean.lang.type.NoType.NONE; - } - } - private static final Name flatName(final Element e) { /* // form a fully qualified name from a name and an owner, after diff --git a/lang/src/main/java/org/microbean/lang/visitor/ValidatingVisitor.java b/lang/src/main/java/org/microbean/lang/visitor/ValidatingVisitor.java index bfdd1bfd..b1f3f287 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/ValidatingVisitor.java +++ b/lang/src/main/java/org/microbean/lang/visitor/ValidatingVisitor.java @@ -1,18 +1,15 @@ /* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- * - * Copyright © 2023 microBean™. + * Copyright © 2023–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang.visitor; @@ -35,8 +32,8 @@ public final class ValidatingVisitor extends StructuralTypeMapping { - public ValidatingVisitor(final TypeAndElementSource elementSource) { - super(elementSource); + public ValidatingVisitor(final TypeAndElementSource tes) { + super(tes); } @Override // SimpleTypeVisitor6 diff --git a/lang/src/main/java/org/microbean/lang/visitor/Visitors.java b/lang/src/main/java/org/microbean/lang/visitor/Visitors.java index e54df29f..de886920 100644 --- a/lang/src/main/java/org/microbean/lang/visitor/Visitors.java +++ b/lang/src/main/java/org/microbean/lang/visitor/Visitors.java @@ -89,7 +89,7 @@ public Visitors(TypeAndElementSource tes, final Types types = new Types(tes); this.eraseVisitor = new EraseVisitor(tes, types); this.supertypeVisitor = new SupertypeVisitor(tes, types, this.eraseVisitor); - this.boundingClassVisitor = new BoundingClassVisitor(this.supertypeVisitor); + this.boundingClassVisitor = new BoundingClassVisitor(tes, this.supertypeVisitor); this.asSuperVisitor = new AsSuperVisitor(tes, null, types, this.supertypeVisitor); this.memberTypeVisitor = new MemberTypeVisitor(tes, null, types, this.asSuperVisitor, this.eraseVisitor, this.supertypeVisitor); diff --git a/lang/src/test/java/org/microbean/lang/TestErase.java b/lang/src/test/java/org/microbean/lang/TestErase.java index 9bb370a2..86dcf5b0 100644 --- a/lang/src/test/java/org/microbean/lang/TestErase.java +++ b/lang/src/test/java/org/microbean/lang/TestErase.java @@ -2,17 +2,14 @@ * * Copyright © 2022–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang; @@ -28,6 +25,7 @@ import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.NoType; +import javax.lang.model.type.NullType; import javax.lang.model.type.PrimitiveType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; @@ -142,6 +140,10 @@ public final NoType noType(final TypeKind k) { return javacModelTypes.getNoType(k); } @Override + public final NullType nullType() { + return javacModelTypes.getNullType(); + } + @Override public final PrimitiveType primitiveType(final TypeKind k) { return javacModelTypes.getPrimitiveType(k); } diff --git a/lang/src/test/java/org/microbean/lang/TestSameTypeVisitor.java b/lang/src/test/java/org/microbean/lang/TestSameTypeVisitor.java index 479483d6..9727fe98 100644 --- a/lang/src/test/java/org/microbean/lang/TestSameTypeVisitor.java +++ b/lang/src/test/java/org/microbean/lang/TestSameTypeVisitor.java @@ -2,17 +2,14 @@ * * Copyright © 2022–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang; @@ -28,6 +25,7 @@ import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.NoType; +import javax.lang.model.type.NullType; import javax.lang.model.type.PrimitiveType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; @@ -108,6 +106,10 @@ public final NoType noType(final TypeKind k) { return javacModelTypes.getNoType(k); } @Override + public final NullType nullType() { + return javacModelTypes.getNullType(); + } + @Override public final PrimitiveType primitiveType(final TypeKind k) { return javacModelTypes.getPrimitiveType(k); } diff --git a/lang/src/test/java/org/microbean/lang/TestSupertypeVisitor.java b/lang/src/test/java/org/microbean/lang/TestSupertypeVisitor.java index 7bca64cc..108db893 100644 --- a/lang/src/test/java/org/microbean/lang/TestSupertypeVisitor.java +++ b/lang/src/test/java/org/microbean/lang/TestSupertypeVisitor.java @@ -2,17 +2,14 @@ * * Copyright © 2022–2024 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 + * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.microbean.lang; @@ -31,6 +28,7 @@ import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.NoType; +import javax.lang.model.type.NullType; import javax.lang.model.type.PrimitiveType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; @@ -128,6 +126,10 @@ public final NoType noType(final TypeKind k) { return javacModelTypes.getNoType(k); } @Override + public final NullType nullType() { + return javacModelTypes.getNullType(); + } + @Override public final PrimitiveType primitiveType(final TypeKind k) { return javacModelTypes.getPrimitiveType(k); } diff --git a/lang/src/test/java/org/microbean/lang/TestTypeClosure.java b/lang/src/test/java/org/microbean/lang/TestTypeClosure.java index 50be71ac..865c21d3 100644 --- a/lang/src/test/java/org/microbean/lang/TestTypeClosure.java +++ b/lang/src/test/java/org/microbean/lang/TestTypeClosure.java @@ -28,6 +28,7 @@ import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.NoType; +import javax.lang.model.type.NullType; import javax.lang.model.type.PrimitiveType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; @@ -120,6 +121,10 @@ public final NoType noType(final TypeKind k) { return javacModelTypes.getNoType(k); } @Override + public final NullType nullType() { + return javacModelTypes.getNullType(); + } + @Override public final PrimitiveType primitiveType(final TypeKind k) { return javacModelTypes.getPrimitiveType(k); } @@ -202,7 +207,7 @@ public final ArrayType arrayTypeOf(final TypeMirror componentType) { public boolean assignable(final TypeMirror payload, final TypeMirror receiver) { return javacModelTypes.isAssignable(payload, receiver); } - @Override + // @Override public final TypeElement boxedClass(final PrimitiveType t) { return javacModelTypes.boxedClass(t); } @@ -232,6 +237,10 @@ public final NoType noType(final TypeKind k) { return javacModelTypes.getNoType(k); } @Override + public final NullType nullType() { + return javacModelTypes.getNullType(); + } + @Override public final PrimitiveType primitiveType(final TypeKind k) { return javacModelTypes.getPrimitiveType(k); } diff --git a/pom.xml b/pom.xml index ad7cf5af..1797be7b 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,6 @@ bytebuddy - jandex lang @@ -80,17 +79,10 @@ - - io.smallrye - jandex - 3.1.6 - jar - - net.bytebuddy byte-buddy - 1.14.11 + 1.14.18 jar @@ -104,14 +96,14 @@ org.junit.jupiter junit-jupiter-api - 5.10.1 + 5.10.3 jar org.junit.jupiter junit-jupiter-engine - 5.10.1 + 5.10.3 jar @@ -138,13 +130,6 @@ jar - - ${project.groupId} - microbean-lang-jandex - ${project.version} - jar - -