Java-to-Sprig wrapper generator (sprig wrap)
sprig wrap imports a Java class mechanically and exposes it as ordinary, editable Sprig source:
sprig wrap <fully.qualified.JavaClass> --out FILE.spr [--member NAME] [--force] [--json]It is an ecosystem-coverage tool: unsupported Java members are reported with the same structured interop reasons sprig api uses instead of being guessed.
Classification stays shared
wrap does not re-decide JVM support. It reads the same JvmMetadata.Support classification as the checker and sprig api, so a member that api marks unsupported is skipped, and adapters listed by the metadata are the adapters the generator emits.
Generated shape
- A Sprig class holding the raw host reference:
class Client:withlet host: HostClient. - Constructors become free functions (
client_new, with parameter-type suffixes when overloaded). - Static methods and fields become free functions; instance methods and fields become class methods; fields are readable accessors only.
- Generic static methods become explicit generic free functions (
generic T: func ...). Instance generic methods are skipped because a raw receiver cannot bind their type variables. - Overloads keep the natural name when there is one wrappable overload and otherwise use deterministic parameter-type suffixes (
parse_string,parse_string_string). Overloads that collapse to the same safe signature are skipped withoverload-collision.
Mapping policy
| Java shape | Sprig surface |
|---|---|
| supported scalars/boxes/references | direct mapping via the shared profile |
java.util.Optional<T> | T? (Optional.empty/Optional.of conversion) |
java.util.List<T> parameter | List[T] via jvm.list_copy[T] (independent copy) |
java.util.List<T> result | List[T]? via jvm.list_snapshot[T] (immutable snapshot) |
java.util.Map<K,V> | Map[K, V] via the explicit adapters |
| checked exceptions | preserved in the generated throws declaration |
| arrays, varargs, wildcards, generic arrays | skipped with the shared reason |
callable (Fn0..Fn3) shapes | skipped in v1 (sprig-callable-boundary) |
direct char/Character/Short/Byte parameters | skipped (value-adapter-unsupported) |
| nested collections inside adapter elements | skipped (nested-collection-unsupported) |
No implicit conversion is generated and raw generic evidence is never turned into concrete evidence: an erased Java type stays erased in the wrapper.
Overwrite and checking policy
- An existing
--outfile is never replaced without--force; there is no merge or in-place regeneration in v1. - The generated text is formatted with the canonical formatter and then checked under the same classpath/project dependencies as
sprig api. - If checking fails, no file is written and a
SPR-WRAP-CHECKdiagnostic is reported. A successful run overwrites only according to--force. - Output is deterministic: no timestamps, stable ordering, byte-for-byte reproducible.
Report
--json returns inputClass, outputPath, generatedMembers, skippedMembers and warnings. Each skipped member carries its Java signature, stable reasonCodes and a human explanation, making wrap a measurement tool for ecosystem coverage.
Editability
The generated file is a normal module. It can be edited by hand and compiled or executed without the generator, without generated bytecode, runtime reflection or hidden metadata.
Host build integration
wrap is a developer tool; the generated file becomes part of the host build. A verified pattern (Gradle/Loom, and the same shape for other JVM builds):
- the host build exports the exact compile classpath it uses (for example a
sprigClasspathtask writing a classpath file); sprig wrap --classpathandsprig api --classpathconsume that file;sprig build --emit-java-only -d <dir>emits Java that the host compiles together with the Sprig runtime and any Java bridge;- generated classes, runtime classes and bridge classes all reach the final artifact.
The website guide Fabric / JVM framework integration records the verified wiring, packaging pitfalls and the clean-build checklist.
Known limitations
Instance generic methods, generic bounds (<T extends Number>), arrays in public façade signatures, callables, varargs, wildcards and generic arrays are outside v1. List/Map adapters accept one level of directly representable elements; nested collections are skipped rather than silently erased.
