diff --git a/README.md b/README.md index f38c512..444c6b4 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ dependency: org.microbean microbean-assign - 0.0.3 + 0.0.4 ``` diff --git a/src/main/java/org/microbean/assign/PrimitiveAndReferenceTypeKindComparator.java b/src/main/java/org/microbean/assign/PrimitiveAndReferenceTypeKindComparator.java new file mode 100644 index 0000000..4a1febf --- /dev/null +++ b/src/main/java/org/microbean/assign/PrimitiveAndReferenceTypeKindComparator.java @@ -0,0 +1,137 @@ +/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- + * + * Copyright © 2025 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.assign; + +import java.util.Comparator; + +import javax.lang.model.type.TypeKind; + +/** + * A {@link Comparator} establishing a partial + * order over {@link TypeKind}s such that {@linkplain TypeKind#TYPEVAR type variables} precede {@linkplain + * TypeKind#isPrimitive primitive types}, {@linkplain TypeKind#isPrimitive primitive types} precede {@linkplain + * TypeKind#ARRAY array types}, and {@linkplain TypeKind#ARRAY array types} precede {@linkplain TypeKind#DECLARED + * declared types}. + * + * @author Laird Nelson + * + * @see #compare(TypeKind, TypeKind) + */ +public final class PrimitiveAndReferenceTypeKindComparator implements Comparator { + + + /* + * Static fields. + */ + + + /** + * The sole instance of this class. + */ + public static final PrimitiveAndReferenceTypeKindComparator INSTANCE = new PrimitiveAndReferenceTypeKindComparator(); + + + /* + * Constructors. + */ + + + private PrimitiveAndReferenceTypeKindComparator() { + super(); + } + + + /* + * Instance methods. + */ + + + /** + * Compares the two {@link TypeKind}s and returns the result. + * + *

If {@code k0} is {@code null} and {@code k1} is not, returns a positive value.

+ * + *

If {@code k1} is {@code null} and {@code k0} is not, returns a negative value.

+ * + *

If {@code k0} is {@link TypeKind#ARRAY}, and {@code k1} {@linkplain TypeKind#isPrimitive() is primitive}, + * returns a positive value.

+ * + *

If {@code k0} is {@link TypeKind#ARRAY}, and {@code k1} is {@link TypeKind#DECLARED}, returns a negative + * value.

+ * + *

If {@code k0} {@linkplain TypeKind#isPrimitive() is primitive}, and {@code k1} is {@link TypeKind#ARRAY} or + * {@link TypeKind#DECLARED}, returns a negative value.

+ * + *

If {@code k0} {@linkplain TypeKind#isPrimitive() is primitive}, and {@code k1} is {@link TypeKind#TYPEVAR}, + * returns a positive value.

+ * + *

If {@code k0} is {@link TypeKind#DECLARED}, and {@code k1} is {@link TypeKind#ARRAY}, or {@linkplain + * TypeKind#isPrimitive() is primitive}, or is {@link TypeKind#TYPEVAR}, returns a positive value.

+ * + *

If {@code k0} is {@link TypeKind#TYPEVAR}, and {@code k1} is {@link TypeKind#ARRAY}, or {@linkplain + * TypeKind#isPrimitive() is primitive}, or is {@link TypeKind#DECLARED}, returns a negative value.

+ * + *

Returns {@code 0} in all other cases. + * + * @param k0 a {@link TypeKind}; may be {@code null} + * + * @param k1 a {@link TypeKind}; may be {@code null} + * + * @return a comparison result + * + * @see TypeKind#isPrimitive() + * + * @see TypeKind#ARRAY + * + * @see TypeKind#DECLARED + * + * @see TypeKind#TYPEVAR + */ + @Override // Comparator + public final int compare(final TypeKind k0, final TypeKind k1) { + return k0 == k1 ? 0 : k0 == null ? 1 : k1 == null ? -1 : switch (k0) { + + case ARRAY -> switch (k1) { + // Arrays come after primitives and type variables. + case BOOLEAN, BYTE, CHAR, DOUBLE, FLOAT, INT, LONG, SHORT, TYPEVAR -> 1; + // Arrays come before declared types. + case DECLARED -> -1; // arrays come before declared + default -> 0; + }; + + case BOOLEAN, BYTE, CHAR, DOUBLE, FLOAT, INT, LONG, SHORT -> switch (k1) { + // Primitives come before arrays and declared types. + case ARRAY, DECLARED -> -1; + // Primitives come after type variables. + case TYPEVAR -> 1; + default -> 0; + }; + + case DECLARED -> switch (k1) { + // Declared types come after arrays, primitives and type variables. + case ARRAY, BOOLEAN, BYTE, CHAR, DOUBLE, FLOAT, INT, LONG, SHORT, TYPEVAR -> 1; + default -> 0; + }; + + case TYPEVAR -> switch (k1) { + // Type variables come before arrays, primitives and declared types. + case ARRAY, BOOLEAN, BYTE, CHAR, DECLARED, DOUBLE, FLOAT, INT, LONG, SHORT -> -1; + default -> 0; + }; + + default -> 0; + }; + } + +} diff --git a/src/main/java/org/microbean/assign/PrimitiveTypesThenDeclaredTypesTypeKindComparator.java b/src/main/java/org/microbean/assign/PrimitiveTypesThenDeclaredTypesTypeKindComparator.java deleted file mode 100644 index e550a16..0000000 --- a/src/main/java/org/microbean/assign/PrimitiveTypesThenDeclaredTypesTypeKindComparator.java +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2025 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.assign; - -import java.util.Comparator; - -import javax.lang.model.type.TypeKind; - -/** - * A {@link Comparator} establishing a partial order over {@link TypeKind}s such that {@linkplain - * TypeKind#isPrimitive primitive types} precede {@linkplain TypeKind#DECLARED declared types}. - * - * @author Laird Nelson - * - * @see #compare(TypeKind, TypeKind) - */ -public final class PrimitiveTypesThenDeclaredTypesTypeKindComparator implements Comparator { - - /** - * The sole instance of this class. - */ - public static final PrimitiveTypesThenDeclaredTypesTypeKindComparator INSTANCE = new PrimitiveTypesThenDeclaredTypesTypeKindComparator(); - - private PrimitiveTypesThenDeclaredTypesTypeKindComparator() { - super(); - } - - /** - * Compares the two {@link TypeKind}s and returns the result. - * - *

If {@code k0 == k1}, returns {@code 0}.

- * - *

If {@code k0} is {@code null} and {@code k1} is not, returns a positive value.

- * - *

If {@code k1} is {@code null} and {@code k0} is not, returns a negative value.

- * - *

If {@code k0} {@linkplain TypeKind#isPrimitive() is primitive} and {@code k1} is {@link TypeKind#DECLARED}, - * returns a negative value.

- * - *

If {@code k0} is {@link TypeKind#DECLARED} and {@code k1} {@linkplain TypeKind#isPrimitive() is primitive}, - * returns a positive value.

- * - *

Returns {@code 0} in all other cases. - * - * @param k0 a {@link TypeKind}; may be {@code null} - * - * @param k1 a {@link TypeKind}; may be {@code null} - * - * @return a comparison result - * - * @see TypeKind#isPrimitive() - * - * @see TypeKind#DECLARED - */ - @Override // Comparator - public final int compare(final TypeKind k0, final TypeKind k1) { - if (k0 == k1) { - return 0; - } else if (k0 == null) { - return 1; - } else if (k1 == null) { - return -1; - } else if (k0.isPrimitive()) { - return k1 == TypeKind.DECLARED ? -1 : 0; - } else if (k0 == TypeKind.DECLARED) { - return k1.isPrimitive() ? 1 : 0; - } else { - return 0; - } - } - -} diff --git a/src/main/java/org/microbean/assign/TypeVariablesFirstTypeKindComparator.java b/src/main/java/org/microbean/assign/TypeVariablesFirstTypeKindComparator.java deleted file mode 100644 index 28e1dc4..0000000 --- a/src/main/java/org/microbean/assign/TypeVariablesFirstTypeKindComparator.java +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- - * - * Copyright © 2025 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.assign; - -import java.util.Comparator; - -import javax.lang.model.type.TypeKind; - -/** - * A {@link Comparator} establishing a partial order over {@link TypeKind}s such that {@linkplain - * TypeKind#TYPEVAR type variables} precede all other kinds of types. - * - * @author Laird Nelson - * - * @see #compare(TypeKind, TypeKind) - */ -public final class TypeVariablesFirstTypeKindComparator implements Comparator { - - /** - * The sole instance of this class. - */ - public static final TypeVariablesFirstTypeKindComparator INSTANCE = new TypeVariablesFirstTypeKindComparator(); - - private TypeVariablesFirstTypeKindComparator() { - super(); - } - - /** - * Compares the two {@link TypeKind}s and returns the result. - * - *

If {@code k0 == k1}, returns {@code 0}.

- * - *

If {@code k0} is {@code null} and {@code k1} is not, returns a positive value.

- * - *

If {@code k0} is {@link TypeKind#TYPEVAR} or {@code k1} is {@code null} and {@code k0} is not, returns a - * negative value.

- * - *

Returns {@code 0} in all other cases. - * - * @param k0 a {@link TypeKind}; may be {@code null} - * - * @param k1 a {@link TypeKind}; may be {@code null} - * - * @return a comparison result - * - * @see TypeKind#TYPEVAR - */ - @Override // Comparator - public final int compare(final TypeKind k0, final TypeKind k1) { - if (k0 == k1) { - return 0; - } else if (k0 == null) { - return 1; - } else if (k0 == TypeKind.TYPEVAR || k1 == null) { - return -1; - } else { - return 0; - } - } - -} diff --git a/src/main/java/org/microbean/assign/Types.java b/src/main/java/org/microbean/assign/Types.java index 8d32f95..89328d3 100644 --- a/src/main/java/org/microbean/assign/Types.java +++ b/src/main/java/org/microbean/assign/Types.java @@ -98,7 +98,7 @@ public class Types implements Constable { public Types(final Domain domain) { super(); this.domain = Objects.requireNonNull(domain, "domain"); - this.c = comparing(TypeMirror::getKind, TypeVariablesFirstTypeKindComparator.INSTANCE) + this.c = comparing(TypeMirror::getKind, PrimitiveAndReferenceTypeKindComparator.INSTANCE) .thenComparing(new SpecializationComparator(domain)) .thenComparing(Types::erasedName); } @@ -279,8 +279,16 @@ public final SupertypeList supertypes(final TypeMirror t, final Predicate