Interface JavaTypeFactory
- All Known Implementing Classes:
DefaultJavaTypeFactory
JavaType instances during parsing.
Two method families correspond to two construction shapes:
compute*— stub-then-initialize. The factory constructs a stub, registers it in the cache, then runs aConsumerthat populates the stub viaunsafeSet. Registering before the initializer runs is what makes recursive resolution during the initializer safe — reserved for types whose construction graph can recurse back to the same key:computeClass(java.lang.String, long, org.openrewrite.java.tree.JavaType.FullyQualified.Kind, java.util.function.Consumer<org.openrewrite.java.tree.JavaType.Class>)— Java's class graph is mutually recursive (Foo extends Bar; Bar.field is Foo).computeParameterized(java.lang.String, java.util.function.Consumer<org.openrewrite.java.tree.JavaType.Parameterized>)— F-bounded polymorphism (Comparable<T extends Comparable<T>>) and Kotlin parameterized self-refs.computeGenericTypeVariable(java.lang.String, java.lang.String, org.openrewrite.java.tree.JavaType.GenericTypeVariable.Variance, java.util.function.Consumer<org.openrewrite.java.tree.JavaType.GenericTypeVariable>)— type variable bounds can reference the variable itself (<T extends Comparable<T>>).
*For— atomic build. The caller supplies aSupplierthat returns a fully-constructed instance; the factory caches and returns it. No half-built object is ever observable through the cache. Used for variants without self-recursion on the same key:methodFor(java.lang.String, java.util.function.Supplier<org.openrewrite.java.tree.JavaType.Method>, java.util.function.Consumer<org.openrewrite.java.tree.JavaType.Method>),variableFor(java.lang.String, java.util.function.Supplier<org.openrewrite.java.tree.JavaType.Variable>),arrayFor(java.lang.String, java.util.function.Supplier<org.openrewrite.java.tree.JavaType.Array>),intersectionFor(java.lang.String, java.util.function.Supplier<org.openrewrite.java.tree.JavaType.Intersection>).
Parser code that needs a canonical identity-stable JavaType.Class
for an FQN that has no Symbol/AST node (synthesized JVM facades, library
placeholders, etc.) should call computeClass(java.lang.String, long, org.openrewrite.java.tree.JavaType.FullyQualified.Kind, java.util.function.Consumer<org.openrewrite.java.tree.JavaType.Class>) with an empty
initializer. There is no separate "lookup" surface — the absence of
richer attribution is signaled at the call site by an empty initializer.
Key formats
Two distinct keying schemes coexist; mixing them within one factory lifetime is a caller bug.- FQN keys —
computeClass(java.lang.String, long, org.openrewrite.java.tree.JavaType.FullyQualified.Kind, java.util.function.Consumer<org.openrewrite.java.tree.JavaType.Class>)is keyed on the fully-qualified name (e.g.java.util.List,com.acme.Outer$Innerfor nested types). Universal across languages: every parser maps aJavaType.Classto its FQN the same way. Thefqnvalue is exactly whatJavaType.FullyQualified.getFullyQualifiedName()returns. - Signature keys — every other
compute*and*Formethod accepts an opaquesignaturestring. The signature must uniquely identify the type within a single factory lifetime, and callers must obtain it from aJavaTypeSignatureBuilderconsistent with the rest of the parser session. Different parsers produce different signature shapes (e.g.JvmsTypeSignatureBuilderfor javac-driven Java parsing vs. per-language builders for Groovy/Kotlin/Scala/reflection); the factory does not inspect the format, but signatures from different builders are NOT interchangeable across one parser session's cache. The canonical reference shapes are documented onJavaTypeSignatureBuilder: e.g. methodscom.MyThing{name=add,return=void,parameters=[Integer]}, variablescom.MyThing{name=MY_FIELD}, genericsGeneric{U extends java.lang.Comparable}, parameterizedsjava.util.List<java.util.List<Integer>>, arraysInteger[].
-
Method Summary
Modifier and TypeMethodDescriptionarrayFor(String signature, Supplier<JavaType.Array> builder) Atomic build forJavaType.Array.computeClass(String fqn, long flags, JavaType.FullyQualified.Kind kind, Consumer<JavaType.Class> initializer) Cache-or-build for a fully-attributedJavaType.Class.computeGenericTypeVariable(String signature, String name, JavaType.GenericTypeVariable.Variance variance, Consumer<JavaType.GenericTypeVariable> initializer) Cache-or-build forJavaType.GenericTypeVariable.computeParameterized(String signature, Consumer<JavaType.Parameterized> initializer) Cache-or-build forJavaType.Parameterized.intersectionFor(String signature, Supplier<JavaType.Intersection> builder) Atomic build forJavaType.Intersection.methodFor(String signature, Supplier<JavaType.Method> stub, Consumer<JavaType.Method> initializer) Build forJavaType.Methodwith cycle-breaking on the same key.variableFor(String signature, Supplier<JavaType.Variable> builder) Atomic build forJavaType.Variable.
-
Method Details
-
computeClass
JavaType.Class computeClass(String fqn, long flags, JavaType.FullyQualified.Kind kind, Consumer<JavaType.Class> initializer) Cache-or-build for a fully-attributedJavaType.Class.If a Class is already cached for
fqn, the cached instance is returned andinitializerdoes not run. Otherwise a stub is constructed withflagsandkindpopulated, registered in the cache, and the initializer runs to populate the remaining fields (typically viaJavaType.Class.unsafeSet(java.util.List<org.openrewrite.java.tree.JavaType>, org.openrewrite.java.tree.JavaType.FullyQualified, org.openrewrite.java.tree.JavaType.FullyQualified, java.util.List<org.openrewrite.java.tree.JavaType.FullyQualified>, java.util.List<org.openrewrite.java.tree.JavaType.FullyQualified>, java.util.List<org.openrewrite.java.tree.JavaType.Variable>, java.util.List<org.openrewrite.java.tree.JavaType.Method>)).- Parameters:
fqn- the fully-qualified name of the class, in the formJavaType.FullyQualified.getFullyQualifiedName()returns.
-
computeParameterized
JavaType.Parameterized computeParameterized(String signature, Consumer<JavaType.Parameterized> initializer) Cache-or-build forJavaType.Parameterized. The initializer's recursivetype(...)calls on type arguments can re-encounter the same signature (e.g. F-bounded polymorphism, Kotlin parameterized self-refs). The pre-registered stub lets those recursive lookups observe a usable partially-populated instance rather than re-entering the builder and looping. The initializer typically seeds the stub with its raw class viaJavaType.Parameterized.unsafeSet(org.openrewrite.java.tree.JavaType.FullyQualified, java.util.List<org.openrewrite.java.tree.JavaType>)before resolving type arguments.- Parameters:
signature- an opaque per-factory key fromJavaTypeSignatureBuilder.parameterizedSignature(java.lang.Object)— canonical shapejava.util.List<java.util.List<Integer>>.
-
computeGenericTypeVariable
JavaType.GenericTypeVariable computeGenericTypeVariable(String signature, String name, JavaType.GenericTypeVariable.Variance variance, Consumer<JavaType.GenericTypeVariable> initializer) Cache-or-build forJavaType.GenericTypeVariable. Type variable bounds can reference the variable itself — e.g.<T extends Comparable<T>>whereT's upper bound is aJavaType.Parameterizedthat referencesTitself. Pre-registering the stub before the initializer runs makes the recursive lookup find the stub instead of looping.- Parameters:
signature- an opaque per-factory key fromJavaTypeSignatureBuilder.genericSignature(java.lang.Object)— canonical shapeGeneric{U extends java.lang.Comparable}(covariant) orGeneric{U super java.lang.Comparable}(contravariant).
-
methodFor
JavaType.Method methodFor(String signature, Supplier<JavaType.Method> stub, Consumer<JavaType.Method> initializer) Build forJavaType.Methodwith cycle-breaking on the same key. UnlikevariableFor(java.lang.String, java.util.function.Supplier<org.openrewrite.java.tree.JavaType.Variable>)/arrayFor(java.lang.String, java.util.function.Supplier<org.openrewrite.java.tree.JavaType.Array>)/intersectionFor(java.lang.String, java.util.function.Supplier<org.openrewrite.java.tree.JavaType.Intersection>), a method's attribution can recurse back to its own signature: an annotation-element method whose own annotations reference an annotation whose element is that same method (the Spring@AliasForshape —value()is annotated@AliasFor, and@AliasFor's element isvalue()). So this mirrorscomputeClass(java.lang.String, long, org.openrewrite.java.tree.JavaType.FullyQualified.Kind, java.util.function.Consumer<org.openrewrite.java.tree.JavaType.Class>):stubconstructs the bare instance from non-recursive header fields, which is cached beforeinitializerruns the (possibly self-referential) attribution onto that same instance. A re-entrant lookup on the same signature then hits the cached stub instead of recursing — the signature and cache are the cycle-breaker, the same way they are forcomputeClass(java.lang.String, long, org.openrewrite.java.tree.JavaType.FullyQualified.Kind, java.util.function.Consumer<org.openrewrite.java.tree.JavaType.Class>).- Parameters:
signature- an opaque per-factory key from aJavaTypeSignatureBuilder— canonical shapecom.MyThing{name=add,return=void,parameters=[Integer]}.stub- constructs the bare method from non-recursive header fields (name, flags, parameter names, default value, declared formal type names); must not resolve any type that could recurse to this signature.initializer- populates the cached stub's recursive attribution (declaring type, return type, parameter types, thrown exceptions, annotations) viaunsafeSet.
-
variableFor
Atomic build forJavaType.Variable.- Parameters:
signature- an opaque per-factory key from aJavaTypeSignatureBuilder— canonical shapecom.MyThing{name=MY_FIELD}.
-
arrayFor
Atomic build forJavaType.Array.- Parameters:
signature- an opaque per-factory key fromJavaTypeSignatureBuilder.arraySignature(java.lang.Object)— canonical shapeInteger[].
-
intersectionFor
Atomic build forJavaType.Intersection.- Parameters:
signature- an opaque per-factory key from aJavaTypeSignatureBuilderbuilt from the intersection's component bounds.
-