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

Commit 24b3e67

Browse files
authored
Interim changes (#21)
Signed-off-by: Laird Nelson <[email protected]>
1 parent 838c07f commit 24b3e67

11 files changed

+120
-96
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Maven dependency:
2727
<groupId>org.microbean</groupId>
2828
<artifactId>microbean-lang</artifactId>
2929
<!-- Always check https://search.maven.org/artifact/org.microbean/microbean-lang for up-to-date available versions. -->
30-
<version>0.0.19</version>
30+
<version>0.0.20</version>
3131
</dependency>
3232
```
3333

lang/src/main/java/org/microbean/lang/Lang.java

+12-5
Original file line numberDiff line numberDiff line change
@@ -2127,8 +2127,8 @@ private static final TypeMirror[] typeArray(final Type[] ts) {
21272127
/**
21282128
* Asynchronously and idempotently initializes the {@link Lang} class for use.
21292129
*
2130-
* <p>This method is automatically called when appropriate, but is {@code public} to support eager initialization use
2131-
* cases.</p>
2130+
* <p>This method is automatically called by the internals of this class when appropriate, but is {@code public} to
2131+
* support eager initialization use cases.</p>
21322132
*/
21332133
// Idempotent.
21342134
public static final void initialize() {
@@ -2292,6 +2292,11 @@ public final boolean sameType(final TypeMirror t, final TypeMirror s) {
22922292
return t == s || Lang.sameType(t, s);
22932293
}
22942294

2295+
@Override
2296+
public final boolean subtype(final TypeMirror t, final TypeMirror s) {
2297+
return t == s || Lang.subtype(t, s);
2298+
}
2299+
22952300
@Override
22962301
public final TypeElement typeElement(final CharSequence canonicalName) {
22972302
return Lang.typeElement(canonicalName);
@@ -2466,8 +2471,10 @@ public final void run() {
24662471
options.add("-verbose");
24672472
}
24682473

2469-
final DiagnosticLogger diagnosticLogger = new DiagnosticLogger(Locale.getDefault());
2470-
final StandardJavaFileManager sjfm = jc.getStandardFileManager(diagnosticLogger, Locale.getDefault(), Charset.defaultCharset());
2474+
final Locale defaultLocale = Locale.getDefault();
2475+
2476+
final DiagnosticLogger diagnosticLogger = new DiagnosticLogger(defaultLocale);
2477+
final StandardJavaFileManager sjfm = jc.getStandardFileManager(diagnosticLogger, defaultLocale, Charset.defaultCharset());
24712478

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

24862493
if (LOGGER.isLoggable(DEBUG)) {

lang/src/main/java/org/microbean/lang/TypeAndElementSource.java

+52-46
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ public DeclaredType declaredType(final TypeElement typeElement,
7474

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

77+
public boolean subtype(final TypeMirror t, final TypeMirror s);
78+
7779
public TypeElement typeElement(final CharSequence canonicalName);
7880

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

9395

94-
public default ArrayType arrayType(final Class<?> c) {
95-
if (!c.isArray()) {
96-
throw new IllegalArgumentException("c: " + c);
97-
}
98-
return this.arrayTypeOf(this.type(c.getComponentType()));
99-
}
100-
101-
public default ArrayType arrayType(final GenericArrayType g) {
102-
return this.arrayTypeOf(this.type(g.getGenericComponentType()));
96+
public default ArrayType arrayType(final Type t) {
97+
return switch (t) {
98+
case null -> throw new NullPointerException("t");
99+
case Class<?> c when c.isArray() -> this.arrayTypeOf(this.type(c.getComponentType()));
100+
case GenericArrayType g -> this.arrayTypeOf(this.type(g.getGenericComponentType()));
101+
default -> throw new IllegalArgumentException("t: " + t);
102+
};
103103
}
104104

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

109-
public default DeclaredType declaredType(final Class<?> c) {
110-
if (c.isArray() || c.isPrimitive() || c.isLocalClass() || c.isAnonymousClass()) {
111-
throw new IllegalArgumentException("c: " + c);
109+
public default DeclaredType declaredType(final Type t) {
110+
return switch (t) {
111+
case null -> throw new NullPointerException("t");
112+
case Class<?> c when c.isArray() || c.isPrimitive() || c.isLocalClass() || c.isAnonymousClass()
113+
-> throw new IllegalArgumentException("t: " + t);
114+
case Class<?> c -> {
115+
final Class<?> ec = c.getEnclosingClass();
116+
yield ec == null ? this.declaredType(this.typeElement(c)) : this.declaredType(this.declaredType(ec), this.typeElement(c));
112117
}
113-
final Class<?> ec = c.getEnclosingClass();
114-
return this.declaredType(ec == null ? null : this.declaredType(ec), this.typeElement(c));
115-
}
116-
117-
public default DeclaredType declaredType(final ParameterizedType p) {
118-
return
119-
this.declaredType(switch (p.getOwnerType()) {
120-
case null -> null;
121-
case Class<?> c -> this.declaredType(c);
122-
case ParameterizedType pt -> this.declaredType(pt);
123-
default -> throw new IllegalArgumentException("p: " + p);
124-
},
125-
this.typeElement((Class<?>)p.getRawType()),
126-
this.typeArray(p.getActualTypeArguments()));
118+
case ParameterizedType p -> this.declaredType(switch (p.getOwnerType()) {
119+
case null -> null;
120+
case Class<?> c -> this.declaredType(c);
121+
case ParameterizedType pt -> this.declaredType(pt);
122+
default -> throw new IllegalArgumentException("t: " + t);
123+
},
124+
this.typeElement(p.getRawType()),
125+
this.typeArray(p.getActualTypeArguments()));
126+
default -> throw new IllegalArgumentException("t: " + t);
127+
};
127128
}
128129

129130
public default Optional<? extends ConstantDesc> describeConstable(final AnnotatedConstruct a) {
130131
return switch (a) {
131-
case null -> Optional.of(NULL);
132-
case Constable c -> c.describeConstable();
132+
case null -> Optional.of(NULL);
133+
case Constable c -> c.describeConstable();
133134
case ConstantDesc cd -> Optional.of(cd); // future proofing
134-
case TypeMirror t -> Optional.empty();
135-
case Element e -> Optional.empty();
136-
default -> throw new IllegalArgumentException("a: " + a);
135+
case TypeMirror t -> Optional.empty();
136+
case Element e -> Optional.empty();
137+
default -> throw new IllegalArgumentException("a: " + a);
137138
};
138139
}
139140

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

147148
public default TypeMirror type(final Type t) {
148149
return switch (t) {
149-
case null -> throw new NullPointerException();
150-
case Class<?> c when c == void.class -> this.noType(TypeKind.VOID);
151-
case Class<?> c when c.isArray() -> this.arrayType(c);
152-
case Class<?> c when c.isPrimitive() -> this.primitiveType(c);
153-
case Class<?> c -> this.declaredType(c);
154-
case ParameterizedType p -> this.declaredType(p);
155-
case GenericArrayType g -> this.arrayType(g);
156-
case java.lang.reflect.TypeVariable<?> tv -> this.typeVariable(tv);
157-
case java.lang.reflect.WildcardType w -> this.wildcardType(w);
158-
default -> throw new IllegalArgumentException("t: " + t);
150+
case null -> throw new NullPointerException();
151+
case Class<?> c when c == void.class -> this.noType(TypeKind.VOID);
152+
case Class<?> c when c.isArray() -> this.arrayType(c);
153+
case Class<?> c when c.isPrimitive() -> this.primitiveType(c);
154+
case Class<?> c when c.isLocalClass() || c.isAnonymousClass() -> throw new IllegalArgumentException("t: " + t);
155+
case Class<?> c -> this.declaredType(c);
156+
case ParameterizedType p -> this.declaredType(p);
157+
case GenericArrayType g -> this.arrayType(g);
158+
case java.lang.reflect.TypeVariable<?> tv -> this.typeVariable(tv);
159+
case java.lang.reflect.WildcardType w -> this.wildcardType(w);
160+
default -> throw new IllegalArgumentException("t: " + t);
159161
};
160162
}
161163

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

170-
public default TypeElement typeElement(final Class<?> c) {
171-
if (c.isArray() || c.isPrimitive() || c.isLocalClass() || c.isAnonymousClass()) {
172-
throw new IllegalArgumentException("c: " + c);
173-
}
174-
return this.typeElement(c.getCanonicalName());
172+
public default TypeElement typeElement(final Type t) {
173+
return switch (t) {
174+
case null -> throw new NullPointerException("t");
175+
case Class<?> c when c.isArray() || c.isPrimitive() || c.isLocalClass() || c.isAnonymousClass()
176+
-> throw new IllegalArgumentException("t: " + t);
177+
case Class<?> c -> this.typeElement(c.getCanonicalName());
178+
case ParameterizedType p -> this.typeElement(p.getRawType());
179+
default -> throw new IllegalArgumentException("t: " + t);
180+
};
175181
}
176182

177183
public default WildcardType wildcardType(final java.lang.reflect.WildcardType t) {

lang/src/main/java/org/microbean/lang/visitor/AdaptingVisitor.java

+31-24
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
import static org.microbean.lang.type.Types.asElement;
4242

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

6868
private final Types types;
6969

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

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

96+
final void adaptSelf(final DeclaredType target) {
97+
this.adapt((DeclaredType)target.asElement().asType(), target);
98+
}
99+
95100
final void adapt(final DeclaredType source, final DeclaredType target) {
96101
this.visitDeclared(source, target);
97102
final int fromSize = this.from.size();
@@ -103,10 +108,29 @@ final void adapt(final DeclaredType source, final DeclaredType target) {
103108
}
104109
}
105110

106-
final void adaptSelf(final DeclaredType target) {
107-
this.adapt((DeclaredType)target.asElement().asType(), target);
111+
private final void adaptRecursive(final Collection<? extends TypeMirror> source, final Collection<? extends TypeMirror> target) {
112+
if (source.size() == target.size()) {
113+
final Iterator<? extends TypeMirror> sourceIterator = source.iterator();
114+
final Iterator<? extends TypeMirror> targetIterator = target.iterator();
115+
while (sourceIterator.hasNext()) {
116+
assert targetIterator.hasNext();
117+
this.adaptRecursive(sourceIterator.next(), targetIterator.next());
118+
}
119+
}
108120
}
109121

122+
private final void adaptRecursive(final TypeMirror source, final TypeMirror target) {
123+
final TypeMirrorPair pair = new TypeMirrorPair(this.sameTypeVisitor, source, target);
124+
if (this.cache.add(pair)) {
125+
try {
126+
this.visit(source, target);
127+
} finally {
128+
this.cache.remove(pair);
129+
}
130+
}
131+
}
132+
133+
// Adapts the component type of source.
110134
@Override
111135
public final Void visitArray(final ArrayType source, final TypeMirror target) {
112136
assert source.getKind() == TypeKind.ARRAY;
@@ -116,6 +140,8 @@ public final Void visitArray(final ArrayType source, final TypeMirror target) {
116140
return null;
117141
}
118142

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

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

194-
private final void adaptRecursive(final TypeMirror source, final TypeMirror target) {
195-
final TypeMirrorPair pair = new TypeMirrorPair(this.sameTypeVisitor, source, target);
196-
if (this.cache.add(pair)) {
197-
try {
198-
this.visit(source, target);
199-
} finally {
200-
this.cache.remove(pair);
201-
}
202-
}
203-
}
204-
205-
private final void adaptRecursive(final Collection<? extends TypeMirror> source, final Collection<? extends TypeMirror> target) {
206-
if (source.size() == target.size()) {
207-
final Iterator<? extends TypeMirror> sourceIterator = source.iterator();
208-
final Iterator<? extends TypeMirror> targetIterator = target.iterator();
209-
while (sourceIterator.hasNext()) {
210-
assert targetIterator.hasNext();
211-
this.adaptRecursive(sourceIterator.next(), targetIterator.next());
212-
}
213-
}
214-
}
215222

216223
}

lang/src/main/java/org/microbean/lang/visitor/PrecedesPredicate.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public final boolean test(final Element e, final Element f) {
6161
case DECLARED:
6262
switch (s.getKind()) {
6363
case DECLARED:
64-
if (this.equality.equals(e, f)) { // in place of ==
64+
if (this.equality.equals(e, f)) { // already checked e == f
6565
// Both are completely interchangeable DeclaredTypes; can't say which comes first.
6666
return false;
6767
}
@@ -77,7 +77,7 @@ public final boolean test(final Element e, final Element f) {
7777
case TYPEVAR:
7878
switch (s.getKind()) {
7979
case TYPEVAR:
80-
if (this.equality.equals(e, f)) { // in place of ==
80+
if (this.equality.equals(e, f)) { // already checked e == f
8181
// Both are completely interchangeable TypeVariables; can't say which comes first.
8282
return false;
8383
}

lang/src/main/java/org/microbean/lang/visitor/SupertypeVisitor.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,15 @@ public final TypeMirror visitDeclared(final DeclaredType t, final Void x) {
151151
@Override // SimpleTypeVisitor14
152152
public final TypeMirror visitIntersection(final IntersectionType t, final Void x) {
153153
assert t.getKind() == TypeKind.INTERSECTION;
154-
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
154+
// Since an intersection type is always ordered from most specialized to least, it follows that the direct supertype
155+
// of an intersection type is its first bound. See
156+
// https://docs.oracle.com/javase/specs/jls/se22/html/jls-4.html#jls-4.10.2
157+
//
158+
// TODO: wait, no, this isn't correct at all. The JLS says: "The direct supertypes of an intersection type T1 &
159+
// ... & Tn are Ti (1 ≤ i ≤ n)." But javac's Types class sets the supertype_field (singular) field to the first
160+
// element of the list. See
161+
// https://github.com/openjdk/jdk/blob/jdk-19+25/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java#L1268.
162+
return t.getBounds().get(0);
155163
}
156164

157165
@Override // SimpleTypeVisitor14

lang/src/test/java/org/microbean/lang/TestErase.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,10 @@ public final PrimitiveType primitiveType(final TypeKind k) {
151151
public boolean sameType(final TypeMirror t, final TypeMirror s) {
152152
return javacModelTypes.isSameType(t, s);
153153
}
154-
/*
155154
@Override
156-
public final TypeElement typeElement(final CharSequence m, final CharSequence n) {
157-
return elements.getTypeElement(elements.getModuleElement(m), n);
155+
public boolean subtype(final TypeMirror t, final TypeMirror s) {
156+
return javacModelTypes.isSubtype(t, s);
158157
}
159-
*/
160158
@Override
161159
public final TypeElement typeElement(final CharSequence n) {
162160
return elements.getTypeElement(n);

lang/src/test/java/org/microbean/lang/TestSameTypeVisitor.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,10 @@ public final PrimitiveType primitiveType(final TypeKind k) {
117117
public boolean sameType(final TypeMirror t, final TypeMirror s) {
118118
return javacModelTypes.isSameType(t, s);
119119
}
120-
/*
121120
@Override
122-
public final TypeElement typeElement(final CharSequence m, final CharSequence n) {
123-
return elements.getTypeElement(elements.getModuleElement(m), n);
121+
public boolean subtype(final TypeMirror t, final TypeMirror s) {
122+
return javacModelTypes.isSubtype(t, s);
124123
}
125-
*/
126124
@Override
127125
public final TypeElement typeElement(final CharSequence n) {
128126
return elements.getTypeElement(n);

lang/src/test/java/org/microbean/lang/TestSupertypeVisitor.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,10 @@ public final PrimitiveType primitiveType(final TypeKind k) {
137137
public boolean sameType(final TypeMirror t, final TypeMirror s) {
138138
return javacModelTypes.isSameType(t, s);
139139
}
140-
/*
141140
@Override
142-
public final TypeElement typeElement(final CharSequence m, final CharSequence n) {
143-
return elements.getTypeElement(elements.getModuleElement(m), n);
141+
public boolean subtype(final TypeMirror t, final TypeMirror s) {
142+
return javacModelTypes.isSubtype(t, s);
144143
}
145-
*/
146144
@Override
147145
public final TypeElement typeElement(final CharSequence n) {
148146
return elements.getTypeElement(n);

0 commit comments

Comments
 (0)