Problem
The processor does not verify that a @ServiceProvider class is actually instantiable by ServiceLoader. ServiceLoader requires a provider to be a public, concrete class with a public no‑arg constructor (or a public static provider() method). Annotating an abstract class, a non‑public class, a Kotlin object/inner class, or a class with only parameterized constructors compiles fine but fails at runtime with ServiceConfigurationError. These are exactly the mistakes the tool exists to prevent.
Evidence
addProvider records providers with no instantiability checks (ServiceSchemeProcessor.kt:172-181).
validateProviderTargets only checks the target is a @ServiceContract (ServiceSchemeProcessor.kt:133-154).
@ServiceProvider targets classes (modules/annotations/.../ServiceScheme.kt:10,12-14), so it can be placed on abstract/non‑instantiable classes.
- The runtime integration test only exercises a well‑formed provider (
ServiceSchemeProcessorSpec.kt:801-859), so these failure modes are uncaught.
Proposed implementation
At registration time, emit Diagnostic.Kind.ERROR (tied to the element) when the provider is not loadable by ServiceLoader:
- not
public (top‑level/static nested), or abstract, or a non‑static inner class, and
- lacks both a public no‑arg constructor and a public static
provider() method (coordinate with the provider‑method feature issue).
For Kotlin, account for object (no public ctor) and visibility mapping.
Acceptance criteria
- Annotating a non‑instantiable class with
@ServiceProvider fails compilation with an actionable message.
- Valid providers still pass; tests cover abstract class, non‑public class, missing no‑arg ctor, and (if applicable) Kotlin
object.
Problem
The processor does not verify that a
@ServiceProviderclass is actually instantiable byServiceLoader. ServiceLoader requires a provider to be a public, concrete class with a public no‑arg constructor (or a public staticprovider()method). Annotating an abstract class, a non‑public class, a Kotlinobject/inner class, or a class with only parameterized constructors compiles fine but fails at runtime withServiceConfigurationError. These are exactly the mistakes the tool exists to prevent.Evidence
addProviderrecords providers with no instantiability checks (ServiceSchemeProcessor.kt:172-181).validateProviderTargetsonly checks the target is a@ServiceContract(ServiceSchemeProcessor.kt:133-154).@ServiceProvidertargets classes (modules/annotations/.../ServiceScheme.kt:10,12-14), so it can be placed on abstract/non‑instantiable classes.ServiceSchemeProcessorSpec.kt:801-859), so these failure modes are uncaught.Proposed implementation
At registration time, emit
Diagnostic.Kind.ERROR(tied to the element) when the provider is not loadable by ServiceLoader:public(top‑level/staticnested), or abstract, or a non‑static inner class, andprovider()method (coordinate with the provider‑method feature issue).For Kotlin, account for
object(no public ctor) and visibility mapping.Acceptance criteria
@ServiceProviderfails compilation with an actionable message.object.