Skip to content

Skeletal javax.lang.model Implementation, Plus Concrete Realization Backed by Core Reflection, Akin to JEP 119

License

Notifications You must be signed in to change notification settings

fschopp/java-types

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Skeletal implementation of interface javax.lang.model.util.Types, plus concrete realization backed by core Java Reflection API, akin to JDK Enhancement Proposal (JEP) 119

Status

Build Status Maven Central

Overview

  • source compatible with Java 7 and 8
  • algorithms, relations, and properties of Java Language Specification implemented exclusively in terms of javax.lang.model interfaces; therefore supports different concrete implementations of javax.lang.model interfaces
  • besides the generic skeletal implementation of javax.lang.model.util.Types, also includes a concrete implementation backed by the Java Reflection API
  • implemented in plain Java with no dependencies; easily embeddable in projects that have Java types as part of their domain model (for instance, domain-specific languages on top of the JVM that need some sort of support for Java generic types)
  • contract tests for the methods and classes that clients of the library need to provide in order to support other implementations of javax.lang.model interfaces
  • tests have virtually full code coverage
  • contains a complete implementation of javax.lang.model.util.Types methods pertaining to JLS §4 (including primitive types, reference types, type variables, parameterized types, type erasure, raw types, intersection types, and subtyping) and §5.1.10 (capture conversion)
  • also includes method for resolving formal type parameters to actual type arguments (for example, determining the actual type argument to Comparable<T>, given type Integer)
  • methods pertaining to non-type elements (notably, ExecutableElement and VariableElement) not currently implemented
  • Code makes use of JSR 305 annotations (e.g., @Nullable)

License

Revised BSD (3-Clause) License

Binary Releases

Published releases (compiled for Java 7 and up) are available on Maven Central.

<dependency>
    <groupId>net.florianschoppmann.java</groupId>
    <artifactId>java-types</artifactId>
    <version>1.0.1</version>
</dependency>

Documentation

Usage Examples

The following examples show some use cases of class ReflectionTypes, the Java Reflection API-based implementation of javax.lang.model.util.Types provided by this project. While the bulk of the functionality of ReflectionTypes is provided by an abstract, skeletal-implementation class called AbstractTypes, class ReflectionTypes provides methods typeElement() and typeMirror() that facilitate converting Java classes and generic types to TypeElement and TypeMirror instances.

Test whether one type is a subtype of another

(see JLS §4.10 and its references)

ReflectionTypes types = ReflectionTypes.getInstance();
// listSuperNumberType: List<? super Number>
DeclaredType listSuperNumberType = types.getDeclaredType(
    types.typeElement(List.class),
    types.getWildcardType(null, types.typeMirror(Number.class))
);
// iterableExtendsNumberType: Iterable<? extends Number>
DeclaredType iterableExtendsNumberType = types.getDeclaredType(
    types.typeElement(Iterable.class),
    types.getWildcardType(types.typeMirror(Number.class), null)
);
// iterableType: Iterable<?>
DeclaredType iterableType = types.getDeclaredType(
    types.typeElement(Iterable.class),
    types.getWildcardType(null, null)
);
assert types.isSubtype(listSuperNumberType, iterableType);
assert types.isSubtype(iterableExtendsNumberType, iterableType);
assert !types.isSubtype(listSuperNumberType, iterableExtendsNumberType);

Resolve actual type arguments

(see JLS §4.5, §8.1, and their references)

ReflectionTypes types = ReflectionTypes.getInstance();
// actual type arguments to Comparable, given the (raw) subtype ScheduledFuture
List<? extends TypeMirror> typeArguments = types.resolveActualTypeArguments(
    types.typeElement(Comparable.class),
    types.typeMirror(ScheduledFuture.class)
);
assert typeArguments.equals(
    Collections.singletonList(types.typeMirror(Delayed.class))
);

Capture conversion with mutually recursive type-variable bounds

(taken from Example 8.1.2-1 of JLS 8, see also JLS §5.1.10 and its references)

// The following are top-level definitions
interface ConvertibleTo<T> {
    T convert();
}
class ReprChange<T extends ConvertibleTo<S>,
                 S extends ConvertibleTo<T>> {
    T t;
    void set(S s) { t = s.convert();    }
    S get()       { return t.convert(); }
}
class Amount implements ConvertibleTo<Integer> {
    @Override public Integer convert() { return 42; }
}

// [...]

ReflectionTypes types = ReflectionTypes.getInstance();
// reprChangeType: ReprChange<Amount, ?>
DeclaredType reprChangeType = types.getDeclaredType(
    types.typeElement(ReprChange.class),
    types.typeMirror(Amount.class),
    types.getWildcardType(null, null)
);
TypeMirror convertedType = types.capture(reprChangeType);

TypeVariable capturedS
    = (TypeVariable) ((DeclaredType) convertedType).getTypeArguments().get(1);
// convertibleToAmountType: ConvertibleTo<Amount>
DeclaredType convertibleToAmountType = types.getDeclaredType(
    types.typeElement(ConvertibleTo.class),
    types.typeMirror(Amount.class)
);
assert capturedS.getUpperBound().equals(convertibleToAmountType);

About

Skeletal javax.lang.model Implementation, Plus Concrete Realization Backed by Core Reflection, Akin to JEP 119

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages