Skip to content

Commit 1b0cec9

Browse files
authored
Improves and consolidates Comparator implementations (#5)
Signed-off-by: Laird Nelson <[email protected]>
1 parent 365f0ff commit 1b0cec9

File tree

5 files changed

+149
-159
lines changed

5 files changed

+149
-159
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ dependency:
2727
<groupId>org.microbean</groupId>
2828
<artifactId>microbean-assign</artifactId>
2929
<!-- Always check https://search.maven.org/artifact/org.microbean/microbean-bean for up-to-date available versions. -->
30-
<version>0.0.3</version>
30+
<version>0.0.4</version>
3131
</dependency>
3232
```
3333

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
2+
*
3+
* Copyright © 2025 microBean™.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
6+
* the License. You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
11+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
12+
* specific language governing permissions and limitations under the License.
13+
*/
14+
package org.microbean.assign;
15+
16+
import java.util.Comparator;
17+
18+
import javax.lang.model.type.TypeKind;
19+
20+
/**
21+
* A {@link Comparator} establishing a <a href="https://en.wikipedia.org/wiki/Partially_ordered_set"><dfn>partial
22+
* order</dfn></a> over {@link TypeKind}s such that {@linkplain TypeKind#TYPEVAR type variables} precede {@linkplain
23+
* TypeKind#isPrimitive primitive types}, {@linkplain TypeKind#isPrimitive primitive types} precede {@linkplain
24+
* TypeKind#ARRAY array types}, and {@linkplain TypeKind#ARRAY array types} precede {@linkplain TypeKind#DECLARED
25+
* declared types}.
26+
*
27+
* @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a>
28+
*
29+
* @see #compare(TypeKind, TypeKind)
30+
*/
31+
public final class PrimitiveAndReferenceTypeKindComparator implements Comparator<TypeKind> {
32+
33+
34+
/*
35+
* Static fields.
36+
*/
37+
38+
39+
/**
40+
* The sole instance of this class.
41+
*/
42+
public static final PrimitiveAndReferenceTypeKindComparator INSTANCE = new PrimitiveAndReferenceTypeKindComparator();
43+
44+
45+
/*
46+
* Constructors.
47+
*/
48+
49+
50+
private PrimitiveAndReferenceTypeKindComparator() {
51+
super();
52+
}
53+
54+
55+
/*
56+
* Instance methods.
57+
*/
58+
59+
60+
/**
61+
* Compares the two {@link TypeKind}s and returns the result.
62+
*
63+
* <p>If {@code k0} is {@code null} and {@code k1} is not, returns a positive value.</p>
64+
*
65+
* <p>If {@code k1} is {@code null} and {@code k0} is not, returns a negative value.</p>
66+
*
67+
* <p>If {@code k0} is {@link TypeKind#ARRAY}, and {@code k1} {@linkplain TypeKind#isPrimitive() is primitive},
68+
* returns a positive value.</p>
69+
*
70+
* <p>If {@code k0} is {@link TypeKind#ARRAY}, and {@code k1} is {@link TypeKind#DECLARED}, returns a negative
71+
* value.</p>
72+
*
73+
* <p>If {@code k0} {@linkplain TypeKind#isPrimitive() is primitive}, and {@code k1} is {@link TypeKind#ARRAY} or
74+
* {@link TypeKind#DECLARED}, returns a negative value.</p>
75+
*
76+
* <p>If {@code k0} {@linkplain TypeKind#isPrimitive() is primitive}, and {@code k1} is {@link TypeKind#TYPEVAR},
77+
* returns a positive value.</p>
78+
*
79+
* <p>If {@code k0} is {@link TypeKind#DECLARED}, and {@code k1} is {@link TypeKind#ARRAY}, or {@linkplain
80+
* TypeKind#isPrimitive() is primitive}, or is {@link TypeKind#TYPEVAR}, returns a positive value.</p>
81+
*
82+
* <p>If {@code k0} is {@link TypeKind#TYPEVAR}, and {@code k1} is {@link TypeKind#ARRAY}, or {@linkplain
83+
* TypeKind#isPrimitive() is primitive}, or is {@link TypeKind#DECLARED}, returns a negative value.</p>
84+
*
85+
* <p>Returns {@code 0} in all other cases.
86+
*
87+
* @param k0 a {@link TypeKind}; may be {@code null}
88+
*
89+
* @param k1 a {@link TypeKind}; may be {@code null}
90+
*
91+
* @return a comparison result
92+
*
93+
* @see TypeKind#isPrimitive()
94+
*
95+
* @see TypeKind#ARRAY
96+
*
97+
* @see TypeKind#DECLARED
98+
*
99+
* @see TypeKind#TYPEVAR
100+
*/
101+
@Override // Comparator<TypeKind>
102+
public final int compare(final TypeKind k0, final TypeKind k1) {
103+
return k0 == k1 ? 0 : k0 == null ? 1 : k1 == null ? -1 : switch (k0) {
104+
105+
case ARRAY -> switch (k1) {
106+
// Arrays come after primitives and type variables.
107+
case BOOLEAN, BYTE, CHAR, DOUBLE, FLOAT, INT, LONG, SHORT, TYPEVAR -> 1;
108+
// Arrays come before declared types.
109+
case DECLARED -> -1; // arrays come before declared
110+
default -> 0;
111+
};
112+
113+
case BOOLEAN, BYTE, CHAR, DOUBLE, FLOAT, INT, LONG, SHORT -> switch (k1) {
114+
// Primitives come before arrays and declared types.
115+
case ARRAY, DECLARED -> -1;
116+
// Primitives come after type variables.
117+
case TYPEVAR -> 1;
118+
default -> 0;
119+
};
120+
121+
case DECLARED -> switch (k1) {
122+
// Declared types come after arrays, primitives and type variables.
123+
case ARRAY, BOOLEAN, BYTE, CHAR, DOUBLE, FLOAT, INT, LONG, SHORT, TYPEVAR -> 1;
124+
default -> 0;
125+
};
126+
127+
case TYPEVAR -> switch (k1) {
128+
// Type variables come before arrays, primitives and declared types.
129+
case ARRAY, BOOLEAN, BYTE, CHAR, DECLARED, DOUBLE, FLOAT, INT, LONG, SHORT -> -1;
130+
default -> 0;
131+
};
132+
133+
default -> 0;
134+
};
135+
}
136+
137+
}

src/main/java/org/microbean/assign/PrimitiveTypesThenDeclaredTypesTypeKindComparator.java

Lines changed: 0 additions & 83 deletions
This file was deleted.

src/main/java/org/microbean/assign/TypeVariablesFirstTypeKindComparator.java

Lines changed: 0 additions & 72 deletions
This file was deleted.

src/main/java/org/microbean/assign/Types.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public class Types implements Constable {
9898
public Types(final Domain domain) {
9999
super();
100100
this.domain = Objects.requireNonNull(domain, "domain");
101-
this.c = comparing(TypeMirror::getKind, TypeVariablesFirstTypeKindComparator.INSTANCE)
101+
this.c = comparing(TypeMirror::getKind, PrimitiveAndReferenceTypeKindComparator.INSTANCE)
102102
.thenComparing(new SpecializationComparator(domain))
103103
.thenComparing(Types::erasedName);
104104
}
@@ -279,8 +279,16 @@ public final SupertypeList supertypes(final TypeMirror t, final Predicate<? supe
279279
interfaceTypes.trimToSize();
280280
final int interfaceIndex = interfaceTypes.isEmpty() ? -1 : nonInterfaceTypes.size();
281281
return
282-
new SupertypeList(concat(nonInterfaceTypes.stream(), // non-interface supertypes are already sorted from most-specific to least
283-
interfaceTypes.stream().sorted(this.c)) // have to sort interfaces because you can extend them in any order
282+
new SupertypeList(concat(
283+
// Non-interface supertypes are already sorted from most-specific to least and will not
284+
// contain primitive types. By extension, array types will precede declared types
285+
// (java.lang.Object). If t is a type variable, then either its supertype will be another
286+
// type variable or a declared type, so type variables precede everything.
287+
nonInterfaceTypes.stream(),
288+
// Interfaces need to be explicitly sorted because they can show up in multiple
289+
// implements clauses and you want the set to be determinate.
290+
interfaceTypes.stream().sorted(this.c)
291+
)
284292
.toList(),
285293
interfaceIndex);
286294
}

0 commit comments

Comments
 (0)