Skip to content
This repository has been archived by the owner on Jan 2, 2025. It is now read-only.

Commit

Permalink
Interim changes (#21)
Browse files Browse the repository at this point in the history
Signed-off-by: Laird Nelson <ljnelson@gmail.com>
  • Loading branch information
ljnelson authored Sep 29, 2024
1 parent 838c07f commit 24b3e67
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 96 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Maven dependency:
<groupId>org.microbean</groupId>
<artifactId>microbean-lang</artifactId>
<!-- Always check https://search.maven.org/artifact/org.microbean/microbean-lang for up-to-date available versions. -->
<version>0.0.19</version>
<version>0.0.20</version>
</dependency>
```

Expand Down
17 changes: 12 additions & 5 deletions lang/src/main/java/org/microbean/lang/Lang.java
Original file line number Diff line number Diff line change
Expand Up @@ -2127,8 +2127,8 @@ private static final TypeMirror[] typeArray(final Type[] ts) {
/**
* Asynchronously and idempotently initializes the {@link Lang} class for use.
*
* <p>This method is automatically called when appropriate, but is {@code public} to support eager initialization use
* cases.</p>
* <p>This method is automatically called by the internals of this class when appropriate, but is {@code public} to
* support eager initialization use cases.</p>
*/
// Idempotent.
public static final void initialize() {
Expand Down Expand Up @@ -2292,6 +2292,11 @@ public final boolean sameType(final TypeMirror t, final TypeMirror s) {
return t == s || Lang.sameType(t, s);
}

@Override
public final boolean subtype(final TypeMirror t, final TypeMirror s) {
return t == s || Lang.subtype(t, s);
}

@Override
public final TypeElement typeElement(final CharSequence canonicalName) {
return Lang.typeElement(canonicalName);
Expand Down Expand Up @@ -2466,8 +2471,10 @@ public final void run() {
options.add("-verbose");
}

final DiagnosticLogger diagnosticLogger = new DiagnosticLogger(Locale.getDefault());
final StandardJavaFileManager sjfm = jc.getStandardFileManager(diagnosticLogger, Locale.getDefault(), Charset.defaultCharset());
final Locale defaultLocale = Locale.getDefault();

final DiagnosticLogger diagnosticLogger = new DiagnosticLogger(defaultLocale);
final StandardJavaFileManager sjfm = jc.getStandardFileManager(diagnosticLogger, defaultLocale, Charset.defaultCharset());

// (Any "loading" is actually performed by, e.g. com.sun.tools.javac.jvm.ClassReader.fillIn(), not reflective
// machinery. Once a class has been so loaded, com.sun.tools.javac.code.Symtab#getClass(ModuleSymbol, Name) will
Expand All @@ -2480,7 +2487,7 @@ public final void run() {
List.of("java.lang.annotation.RetentionPolicy"), // arbitrary, but loads the least amount of stuff up front
null); // compilation units; null means we aren't actually compiling anything
task.setProcessors(List.of(new P()));
task.setLocale(Locale.getDefault());
task.setLocale(defaultLocale);
task.addModules(additionalRootModuleNames);

if (LOGGER.isLoggable(DEBUG)) {
Expand Down
98 changes: 52 additions & 46 deletions lang/src/main/java/org/microbean/lang/TypeAndElementSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ public DeclaredType declaredType(final TypeElement typeElement,

public boolean sameType(final TypeMirror t, final TypeMirror s);

public boolean subtype(final TypeMirror t, final TypeMirror s);

public TypeElement typeElement(final CharSequence canonicalName);

// Note that Elements#getTypeElement(ModuleElement, CharSequence), to which this basically ultimately delegates, says
Expand All @@ -91,49 +93,48 @@ public DeclaredType declaredType(final TypeElement typeElement,
*/


public default ArrayType arrayType(final Class<?> c) {
if (!c.isArray()) {
throw new IllegalArgumentException("c: " + c);
}
return this.arrayTypeOf(this.type(c.getComponentType()));
}

public default ArrayType arrayType(final GenericArrayType g) {
return this.arrayTypeOf(this.type(g.getGenericComponentType()));
public default ArrayType arrayType(final Type t) {
return switch (t) {
case null -> throw new NullPointerException("t");
case Class<?> c when c.isArray() -> this.arrayTypeOf(this.type(c.getComponentType()));
case GenericArrayType g -> this.arrayTypeOf(this.type(g.getGenericComponentType()));
default -> throw new IllegalArgumentException("t: " + t);
};
}

public default DeclaredType declaredType(final CharSequence canonicalName) {
return this.declaredType(this.typeElement(canonicalName));
}

public default DeclaredType declaredType(final Class<?> c) {
if (c.isArray() || c.isPrimitive() || c.isLocalClass() || c.isAnonymousClass()) {
throw new IllegalArgumentException("c: " + c);
public default DeclaredType declaredType(final Type t) {
return switch (t) {
case null -> throw new NullPointerException("t");
case Class<?> c when c.isArray() || c.isPrimitive() || c.isLocalClass() || c.isAnonymousClass()
-> throw new IllegalArgumentException("t: " + t);
case Class<?> c -> {
final Class<?> ec = c.getEnclosingClass();
yield ec == null ? this.declaredType(this.typeElement(c)) : this.declaredType(this.declaredType(ec), this.typeElement(c));
}
final Class<?> ec = c.getEnclosingClass();
return this.declaredType(ec == null ? null : this.declaredType(ec), this.typeElement(c));
}

public default DeclaredType declaredType(final ParameterizedType p) {
return
this.declaredType(switch (p.getOwnerType()) {
case null -> null;
case Class<?> c -> this.declaredType(c);
case ParameterizedType pt -> this.declaredType(pt);
default -> throw new IllegalArgumentException("p: " + p);
},
this.typeElement((Class<?>)p.getRawType()),
this.typeArray(p.getActualTypeArguments()));
case ParameterizedType p -> this.declaredType(switch (p.getOwnerType()) {
case null -> null;
case Class<?> c -> this.declaredType(c);
case ParameterizedType pt -> this.declaredType(pt);
default -> throw new IllegalArgumentException("t: " + t);
},
this.typeElement(p.getRawType()),
this.typeArray(p.getActualTypeArguments()));
default -> throw new IllegalArgumentException("t: " + t);
};
}

public default Optional<? extends ConstantDesc> describeConstable(final AnnotatedConstruct a) {
return switch (a) {
case null -> Optional.of(NULL);
case Constable c -> c.describeConstable();
case null -> Optional.of(NULL);
case Constable c -> c.describeConstable();
case ConstantDesc cd -> Optional.of(cd); // future proofing
case TypeMirror t -> Optional.empty();
case Element e -> Optional.empty();
default -> throw new IllegalArgumentException("a: " + a);
case TypeMirror t -> Optional.empty();
case Element e -> Optional.empty();
default -> throw new IllegalArgumentException("a: " + a);
};
}

Expand All @@ -146,16 +147,17 @@ public default PrimitiveType primitiveType(final Class<?> c) {

public default TypeMirror type(final Type t) {
return switch (t) {
case null -> throw new NullPointerException();
case Class<?> c when c == void.class -> this.noType(TypeKind.VOID);
case Class<?> c when c.isArray() -> this.arrayType(c);
case Class<?> c when c.isPrimitive() -> this.primitiveType(c);
case Class<?> c -> this.declaredType(c);
case ParameterizedType p -> this.declaredType(p);
case GenericArrayType g -> this.arrayType(g);
case java.lang.reflect.TypeVariable<?> tv -> this.typeVariable(tv);
case java.lang.reflect.WildcardType w -> this.wildcardType(w);
default -> throw new IllegalArgumentException("t: " + t);
case null -> throw new NullPointerException();
case Class<?> c when c == void.class -> this.noType(TypeKind.VOID);
case Class<?> c when c.isArray() -> this.arrayType(c);
case Class<?> c when c.isPrimitive() -> this.primitiveType(c);
case Class<?> c when c.isLocalClass() || c.isAnonymousClass() -> throw new IllegalArgumentException("t: " + t);
case Class<?> c -> this.declaredType(c);
case ParameterizedType p -> this.declaredType(p);
case GenericArrayType g -> this.arrayType(g);
case java.lang.reflect.TypeVariable<?> tv -> this.typeVariable(tv);
case java.lang.reflect.WildcardType w -> this.wildcardType(w);
default -> throw new IllegalArgumentException("t: " + t);
};
}

Expand All @@ -167,11 +169,15 @@ public default TypeMirror[] typeArray(final Type[] ts) {
return rv;
}

public default TypeElement typeElement(final Class<?> c) {
if (c.isArray() || c.isPrimitive() || c.isLocalClass() || c.isAnonymousClass()) {
throw new IllegalArgumentException("c: " + c);
}
return this.typeElement(c.getCanonicalName());
public default TypeElement typeElement(final Type t) {
return switch (t) {
case null -> throw new NullPointerException("t");
case Class<?> c when c.isArray() || c.isPrimitive() || c.isLocalClass() || c.isAnonymousClass()
-> throw new IllegalArgumentException("t: " + t);
case Class<?> c -> this.typeElement(c.getCanonicalName());
case ParameterizedType p -> this.typeElement(p.getRawType());
default -> throw new IllegalArgumentException("t: " + t);
};
}

public default WildcardType wildcardType(final java.lang.reflect.WildcardType t) {
Expand Down
55 changes: 31 additions & 24 deletions lang/src/main/java/org/microbean/lang/visitor/AdaptingVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
import static org.microbean.lang.type.Types.asElement;

/**
* Does something adapting-like.
* Does something adapting-like. Looks to be related to type variable resolution.
*
* <p>Usage: call {@link #adapt(DeclaredType, DeclaredType)}, not {@link #visit(TypeMirror)}.</p>
*
Expand All @@ -67,6 +67,7 @@ final class AdaptingVisitor extends SimpleTypeVisitor14<Void, TypeMirror> {

private final Types types;

// The compiler calls this "mapping"; the class is called "Adapting"; I think they are the same thing
private final Map<DelegatingElement, TypeMirror> mapping;

private final SameTypeVisitor sameTypeVisitor;
Expand All @@ -92,6 +93,10 @@ final class AdaptingVisitor extends SimpleTypeVisitor14<Void, TypeMirror> {
this.to = Objects.requireNonNull(to, "to");
}

final void adaptSelf(final DeclaredType target) {
this.adapt((DeclaredType)target.asElement().asType(), target);
}

final void adapt(final DeclaredType source, final DeclaredType target) {
this.visitDeclared(source, target);
final int fromSize = this.from.size();
Expand All @@ -103,10 +108,29 @@ final void adapt(final DeclaredType source, final DeclaredType target) {
}
}

final void adaptSelf(final DeclaredType target) {
this.adapt((DeclaredType)target.asElement().asType(), target);
private final void adaptRecursive(final Collection<? extends TypeMirror> source, final Collection<? extends TypeMirror> target) {
if (source.size() == target.size()) {
final Iterator<? extends TypeMirror> sourceIterator = source.iterator();
final Iterator<? extends TypeMirror> targetIterator = target.iterator();
while (sourceIterator.hasNext()) {
assert targetIterator.hasNext();
this.adaptRecursive(sourceIterator.next(), targetIterator.next());
}
}
}

private final void adaptRecursive(final TypeMirror source, final TypeMirror target) {
final TypeMirrorPair pair = new TypeMirrorPair(this.sameTypeVisitor, source, target);
if (this.cache.add(pair)) {
try {
this.visit(source, target);
} finally {
this.cache.remove(pair);
}
}
}

// Adapts the component type of source.
@Override
public final Void visitArray(final ArrayType source, final TypeMirror target) {
assert source.getKind() == TypeKind.ARRAY;
Expand All @@ -116,6 +140,8 @@ public final Void visitArray(final ArrayType source, final TypeMirror target) {
return null;
}

// Adapts type arguments of source. "Recursive" means something like "go into type parameters etc."
// Adapting a type argument takes effect on wildcard-extending type variables only, it looks like.
@Override
public final Void visitDeclared(final DeclaredType source, final TypeMirror target) {
assert source.getKind() == TypeKind.DECLARED;
Expand All @@ -135,6 +161,7 @@ public final Void visitTypeVariable(final TypeVariable source, final TypeMirror
this.from.add(source);
this.to.add(target);
} else if (val.getKind() == TypeKind.WILDCARD && target.getKind() == TypeKind.WILDCARD) {
// This block is the only place in this entire class where the magic happens.
final WildcardType valWc = (WildcardType)val;
final TypeMirror valSuperBound = valWc.getSuperBound();
final TypeMirror valExtendsBound = valWc.getExtendsBound();
Expand Down Expand Up @@ -172,6 +199,7 @@ public final Void visitTypeVariable(final TypeVariable source, final TypeMirror
return null;
}

// Adapts the bounds of a wildcard.
@Override
public final Void visitWildcard(final WildcardType source, final TypeMirror target) {
assert source.getKind() == TypeKind.WILDCARD;
Expand All @@ -191,26 +219,5 @@ public final Void visitWildcard(final WildcardType source, final TypeMirror targ
return null;
}

private final void adaptRecursive(final TypeMirror source, final TypeMirror target) {
final TypeMirrorPair pair = new TypeMirrorPair(this.sameTypeVisitor, source, target);
if (this.cache.add(pair)) {
try {
this.visit(source, target);
} finally {
this.cache.remove(pair);
}
}
}

private final void adaptRecursive(final Collection<? extends TypeMirror> source, final Collection<? extends TypeMirror> target) {
if (source.size() == target.size()) {
final Iterator<? extends TypeMirror> sourceIterator = source.iterator();
final Iterator<? extends TypeMirror> targetIterator = target.iterator();
while (sourceIterator.hasNext()) {
assert targetIterator.hasNext();
this.adaptRecursive(sourceIterator.next(), targetIterator.next());
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public final boolean test(final Element e, final Element f) {
case DECLARED:
switch (s.getKind()) {
case DECLARED:
if (this.equality.equals(e, f)) { // in place of ==
if (this.equality.equals(e, f)) { // already checked e == f
// Both are completely interchangeable DeclaredTypes; can't say which comes first.
return false;
}
Expand All @@ -77,7 +77,7 @@ public final boolean test(final Element e, final Element f) {
case TYPEVAR:
switch (s.getKind()) {
case TYPEVAR:
if (this.equality.equals(e, f)) { // in place of ==
if (this.equality.equals(e, f)) { // already checked e == f
// Both are completely interchangeable TypeVariables; can't say which comes first.
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,15 @@ public final TypeMirror visitDeclared(final DeclaredType t, final Void x) {
@Override // SimpleTypeVisitor14
public final TypeMirror visitIntersection(final IntersectionType t, final Void x) {
assert t.getKind() == TypeKind.INTERSECTION;
return t.getBounds().get(0); // TODO: presumes first bound will be the supertype; see https://github.com/openjdk/jdk/blob/jdk-19+25/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java#L1268
// Since an intersection type is always ordered from most specialized to least, it follows that the direct supertype
// of an intersection type is its first bound. See
// https://docs.oracle.com/javase/specs/jls/se22/html/jls-4.html#jls-4.10.2
//
// TODO: wait, no, this isn't correct at all. The JLS says: "The direct supertypes of an intersection type T1 &
// ... & Tn are Ti (1 ≤ i ≤ n)." But javac's Types class sets the supertype_field (singular) field to the first
// element of the list. See
// https://github.com/openjdk/jdk/blob/jdk-19+25/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java#L1268.
return t.getBounds().get(0);
}

@Override // SimpleTypeVisitor14
Expand Down
6 changes: 2 additions & 4 deletions lang/src/test/java/org/microbean/lang/TestErase.java
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,10 @@ public final PrimitiveType primitiveType(final TypeKind k) {
public boolean sameType(final TypeMirror t, final TypeMirror s) {
return javacModelTypes.isSameType(t, s);
}
/*
@Override
public final TypeElement typeElement(final CharSequence m, final CharSequence n) {
return elements.getTypeElement(elements.getModuleElement(m), n);
public boolean subtype(final TypeMirror t, final TypeMirror s) {
return javacModelTypes.isSubtype(t, s);
}
*/
@Override
public final TypeElement typeElement(final CharSequence n) {
return elements.getTypeElement(n);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,10 @@ public final PrimitiveType primitiveType(final TypeKind k) {
public boolean sameType(final TypeMirror t, final TypeMirror s) {
return javacModelTypes.isSameType(t, s);
}
/*
@Override
public final TypeElement typeElement(final CharSequence m, final CharSequence n) {
return elements.getTypeElement(elements.getModuleElement(m), n);
public boolean subtype(final TypeMirror t, final TypeMirror s) {
return javacModelTypes.isSubtype(t, s);
}
*/
@Override
public final TypeElement typeElement(final CharSequence n) {
return elements.getTypeElement(n);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,10 @@ public final PrimitiveType primitiveType(final TypeKind k) {
public boolean sameType(final TypeMirror t, final TypeMirror s) {
return javacModelTypes.isSameType(t, s);
}
/*
@Override
public final TypeElement typeElement(final CharSequence m, final CharSequence n) {
return elements.getTypeElement(elements.getModuleElement(m), n);
public boolean subtype(final TypeMirror t, final TypeMirror s) {
return javacModelTypes.isSubtype(t, s);
}
*/
@Override
public final TypeElement typeElement(final CharSequence n) {
return elements.getTypeElement(n);
Expand Down
Loading

0 comments on commit 24b3e67

Please sign in to comment.