├── .github
├── workflows
│ └── .java-version
├── pull_request_template.md
└── ISSUE_TEMPLATE
│ └── config.yml
├── compiler-compat
├── k2220
│ ├── version.txt
│ └── src
│ │ └── main
│ │ └── resources
│ │ └── META-INF
│ │ └── services
│ │ └── dev.zacsweers.metro.compiler.compat.CompatContext$Factory
├── k230_beta1
│ ├── version.txt
│ └── src
│ │ └── main
│ │ └── resources
│ │ └── META-INF
│ │ └── services
│ │ └── dev.zacsweers.metro.compiler.compat.CompatContext$Factory
├── k2320_dev_5437
│ ├── version.txt
│ └── src
│ │ └── main
│ │ └── resources
│ │ └── META-INF
│ │ └── services
│ │ └── dev.zacsweers.metro.compiler.compat.CompatContext$Factory
├── version-aliases.txt
└── build.gradle.kts
├── compiler-tests
└── src
│ ├── test
│ ├── data
│ │ ├── dump
│ │ │ ├── fir
│ │ │ │ ├── scratch.kt
│ │ │ │ ├── scratch.fir.txt
│ │ │ │ ├── aggregation
│ │ │ │ │ ├── ContributingTypes.kt
│ │ │ │ │ ├── ContributingTypesDependency.kt
│ │ │ │ │ ├── ContributingGraphExtensions.kt
│ │ │ │ │ ├── FirHintGenerationWorks_k22x.kt
│ │ │ │ │ └── FirHintGenerationWorks_k23x.kt
│ │ │ │ └── private-provides-status-transformation
│ │ │ │ │ └── ProvidersAreMadePrivate.kt
│ │ │ └── ir
│ │ │ │ ├── scratch.kt
│ │ │ │ ├── scratch.fir.kt.txt
│ │ │ │ ├── injectconstructor
│ │ │ │ ├── DefaultValuesPropagateToNewInstanceParams.kt
│ │ │ │ └── ConstructorFunctionSignatures.kt
│ │ │ │ ├── provides
│ │ │ │ ├── DefaultValuesPropagateToNewInstanceParams.kt
│ │ │ │ └── JvmFieldProvidersUseFieldAccess.kt
│ │ │ │ ├── dependencygraph
│ │ │ │ ├── EmptyMapMultibindingsUseEmptyMap.kt
│ │ │ │ ├── MapsUseMapBuilderIfNoProvider.kt
│ │ │ │ ├── UnusedScopedBindingsInUnextendedGraphGetNoProviderFields.kt
│ │ │ │ ├── ProviderAccessorsAreTrackedInRefCounting.kt
│ │ │ │ ├── GraphImplClassAsReturnType.kt
│ │ │ │ ├── ExtensionsAreInnerClasses.kt
│ │ │ │ ├── UnusedInstanceBindingsInUnextendedGraphGetNoProviderFields.kt
│ │ │ │ ├── MultipleRefsGetProviderFields.kt
│ │ │ │ ├── LazyPropertiesHaveDeterministicOrder.kt
│ │ │ │ ├── OptionalBindingsHaveValidFieldNames.kt
│ │ │ │ ├── GraphAccessors.kt
│ │ │ │ └── MapBuildersUseInlineInstantiation.kt
│ │ │ │ ├── MultibindingsWithComplexDependenciesGetProperties.kt
│ │ │ │ ├── cycles
│ │ │ │ ├── SelfCycle.kt
│ │ │ │ ├── BindsCycleGraph.kt
│ │ │ │ └── CycleMapGraph.kt
│ │ │ │ ├── visibility
│ │ │ │ ├── InternalVisibility.kt
│ │ │ │ └── InternalVisibilityDifferentModule.kt
│ │ │ │ ├── multibindings
│ │ │ │ ├── MapProvidersParticipateInProviderRefcounting.kt
│ │ │ │ └── MultibindingSourcesGetGettersThroughAliases.kt
│ │ │ │ └── aggregation
│ │ │ │ └── ContributorsWithSameSimpleNames.kt
│ │ ├── diagnostic
│ │ │ ├── functioninject
│ │ │ │ ├── CannotHaveTypeArgs.fir.diag.txt
│ │ │ │ ├── CannotBeScoped.fir.diag.txt
│ │ │ │ ├── CannotHaveExtensionReceivers.fir.diag.txt
│ │ │ │ ├── ContextParamsCannotBeOptional.fir.diag.txt
│ │ │ │ ├── CannotHaveExtensionReceivers.kt
│ │ │ │ ├── CannotHaveTypeArgs.kt
│ │ │ │ ├── CannotBeScoped.kt
│ │ │ │ └── ContextParamsCannotBeOptional.kt
│ │ │ ├── provides
│ │ │ │ ├── Binds_Interface_OkCase.kt
│ │ │ │ ├── PrivateProviderOption_Error.fir.diag.txt
│ │ │ │ ├── ProvidesPropertiesCannotBeMutable.fir.diag.txt
│ │ │ │ ├── Binds_interface_ShouldNotHaveBodies.fir.diag.txt
│ │ │ │ ├── ProvidesShouldBePrivate_InInterface.fir.diag.txt
│ │ │ │ ├── ProvidesShouldBePrivate_InAbstractClass.fir.diag.txt
│ │ │ │ ├── BindsWithBodiesShouldBePrivate_InInterface.fir.diag.txt
│ │ │ │ ├── BindsWithBodiesShouldBePrivate_InAbstractClass.fir.diag.txt
│ │ │ │ ├── ProvidesCannotLiveInObjects.kt
│ │ │ │ ├── LazyAssistedFactoryProvides.fir.diag.txt
│ │ │ │ ├── ProvidesFunctionsCannotBeTopLevel.kt
│ │ │ │ ├── ProvidesMustHaveABody_Interface.kt
│ │ │ │ ├── ProvidesPropertiesCannotBeMutable.kt
│ │ │ │ ├── AssistedParametersAreNotSupportedOnProvides.kt
│ │ │ │ ├── AssistedParametersAreNotSupportedOnProvides.fir.diag.txt
│ │ │ │ ├── ProvidesMustHaveABody_Interface.fir.diag.txt
│ │ │ │ ├── ProvidesMustHaveABody_AbstractClass.kt
│ │ │ │ ├── ProvidesMustHaveABody_AbstractClass.fir.diag.txt
│ │ │ │ ├── PrivateProviderOption_None.kt
│ │ │ │ ├── ProvidesFunctionsCannotBeTopLevel.fir.diag.txt
│ │ │ │ ├── BindsNonThisReturningBodiesShouldError_Interface.kt
│ │ │ │ ├── BindsNonThisReturningBodiesShouldError_AbstractClass.kt
│ │ │ │ ├── ProvidesCannotHaveReceivers_AbstractClass.kt
│ │ │ │ ├── ProvidesCannotHaveReceivers_Interface.kt
│ │ │ │ ├── ProvidesWithExtensionsAndNonThisReturningBodiesShouldError.kt
│ │ │ │ ├── Provides_Interface_MayNotHaveTypeParameters.fir.diag.txt
│ │ │ │ ├── ProvidesNamesMustBeUniqueInContainer.kt
│ │ │ │ ├── ProvidedInjectedClassesWithMatchingTypeKeysAreReportedAsWarnings.fir.diag.txt
│ │ │ │ ├── Provides_AbstractClass_MayNotHaveTypeParameters.fir.diag.txt
│ │ │ │ ├── Binds_interface_BoundTypesMustBeSubtypes.kt
│ │ │ │ ├── ProvidesCannotLiveInObjects.fir.diag.txt
│ │ │ │ ├── Binds_interface_ShouldNotHaveBodies.kt
│ │ │ │ ├── ProvidedInjectedClassesWithMatchingTypeKeysButDifferentScopesAreOk.kt
│ │ │ │ ├── PrivateProviderOption_Error.kt
│ │ │ │ ├── ProvidedInjectedClassesWithMatchingTypeKeysAreReportedAsWarnings.kt
│ │ │ │ ├── ProvidesNamesMustBeUniqueInGraph.fir.diag.txt
│ │ │ │ ├── Binds_interface_BoundTypesMustBeSubtypes.fir.diag.txt
│ │ │ │ ├── ProvidedInjectedClassesWithMatchingTypeKeysAreREportedAsWarnings_Qualified.fir.diag.txt
│ │ │ │ ├── Provides_Interface_MayNotHaveTypeParameters.kt
│ │ │ │ ├── ProvidesNamesMustBeUniqueInGraph.kt
│ │ │ │ ├── ProvidesShouldBePrivate_InInterface.kt
│ │ │ │ ├── Provides_AbstractClass_MayNotHaveTypeParameters.kt
│ │ │ │ ├── BindsWithBodiesShouldBePrivate_InInterface.kt
│ │ │ │ ├── DaggerReusable_IsUnsupported.kt
│ │ │ │ ├── ProvidesNamesMustBeUniqueInContainer.fir.diag.txt
│ │ │ │ ├── BindsWithBodiesShouldBePrivate_InAbstractClass.kt
│ │ │ │ ├── ProvidesMustHaveExplicitReturnTypes.fir.diag.txt
│ │ │ │ ├── BindsMayNotHaveScopes.fir.diag.txt
│ │ │ │ ├── ProvidedInjectedClassesWithMatchingTypeKeysAreREportedAsWarnings_Qualified.kt
│ │ │ │ ├── ProvidesShouldBePrivate_InAbstractClass.kt
│ │ │ │ ├── DaggerReusable_IsUnsupported.fir.diag.txt
│ │ │ │ ├── BindsNonThisReturningBodiesShouldError_Interface.fir.diag.txt
│ │ │ │ ├── BindsNonThisReturningBodiesShouldError_AbstractClass.fir.diag.txt
│ │ │ │ ├── ProvidesCannotHaveReceivers_Interface.fir.diag.txt
│ │ │ │ ├── ProvidesCannotHaveReceivers_AbstractClass.fir.diag.txt
│ │ │ │ ├── BindsMayNotHaveScopes.kt
│ │ │ │ └── ProvidesWithExtensionsAndNonThisReturningBodiesShouldError.fir.diag.txt
│ │ │ ├── inject
│ │ │ │ ├── assisted
│ │ │ │ │ ├── AssistedFactoriesCannotBeLocal.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoriesCannotBePrivate.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoriesCannotBeProtected.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoriesCannotBeEnums.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoriesCannotBeFinal.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoryWithMissingSAM.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoriesCannotBeSealedClasses.fir.diag.txt
│ │ │ │ │ ├── LazyAssistedFactoryInjection.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoriesCannotBeAnnotationClasses.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoriesCannotBeAnnotationObjects.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoriesCannotBeSealedInterfaces.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoryWithMissingSAM.kt
│ │ │ │ │ ├── AssistedFactoriesCannotBeAnnotationClasses.kt
│ │ │ │ │ ├── AssistedFactoryMustTargetAssistedInjectTypesButMissingConstructor.kt
│ │ │ │ │ ├── LazyAssistedFactoryInjection.kt
│ │ │ │ │ ├── AssistedFactoriesCannotBeLocal.kt
│ │ │ │ │ ├── AssistedFactoriesCannotBeSealedClasses.kt
│ │ │ │ │ ├── AssistedFactoriesCannotBeSealedInterfaces.kt
│ │ │ │ │ ├── AssistedFactoriesCannotBePrivate.kt
│ │ │ │ │ ├── AssistedFactoryMustTargetAssistedInjectTypesWithMatchingParameters.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoriesCannotBeProtected.kt
│ │ │ │ │ ├── AssistedFactoryMustTargetAssistedInjectTypesButMissingReturnType.kt
│ │ │ │ │ ├── AssistedFactoryWithMultipleSAMs.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoriesCannotBeFinal.kt
│ │ │ │ │ ├── AssistedFactoryMustTargetAssistedInjectTypesButMissingReturnType.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoriesCannotBeAnnotationObjects.kt
│ │ │ │ │ ├── AssistedFactoryMustTargetAssistedInjectTypesButMissingConstructor.fir.diag.txt
│ │ │ │ │ ├── AssistedFactoryMustTargetAssistedInjectTypesWithMatchingParameters.kt
│ │ │ │ │ ├── AssistedFactoryWithMultipleSAMs.kt
│ │ │ │ │ └── AssistedFactoriesCannotBeEnums.kt
│ │ │ │ ├── InjectingAPlainObjectIsSus.kt
│ │ │ │ ├── member
│ │ │ │ │ ├── FunctionMemberInjectsCannotHaveTypeParams.kt
│ │ │ │ │ ├── MissingMemberInjectionShouldFailBinding1.fir.ir.diag.txt
│ │ │ │ │ ├── MissingMemberInjectionShouldFailBinding2.fir.ir.diag.txt
│ │ │ │ │ └── MembersInjectorParameterWithNoDefaultShouldError.kt
│ │ │ │ ├── InjectingAPlainObjectIsSus.fir.diag.txt
│ │ │ │ ├── ConflictingProvidesAndClassScopes.fir.diag.txt
│ │ │ │ ├── function
│ │ │ │ │ ├── LazyAssistedFactoryFunctionInjection.fir.diag.txt
│ │ │ │ │ └── LazyAssistedFactoryFunctionInjection.kt
│ │ │ │ ├── ProvidingAConstructorInjectedTypeHasASpecificWarning.fir.diag.txt
│ │ │ │ ├── ConflictingProvidesAndClassScopes.kt
│ │ │ │ ├── SuggestInjectClassOnSingleContructor.fir.diag.txt
│ │ │ │ ├── SuggestInjectClassOnSingleContructor.kt
│ │ │ │ └── ProvidingAConstructorInjectedTypeHasASpecificWarning.kt
│ │ │ ├── bindingcontainer
│ │ │ │ ├── CannotAnnotateBothGraphAndContainer.fir.diag.txt
│ │ │ │ ├── CannotAnnotateBothGraphAndContainer.kt
│ │ │ │ ├── IncludedMustBeAContainer.fir.diag.txt
│ │ │ │ ├── AbstractContainersCannotHaveProvides.fir.diag.txt
│ │ │ │ ├── ContributedContainersMustHaveNoArgConstructors.fir.diag.txt
│ │ │ │ ├── AbstractContainersCannotHaveProvides.kt
│ │ │ │ ├── ContributedContainersMustHaveNoArgConstructors.kt
│ │ │ │ ├── IncludedMustBeAContainer.kt
│ │ │ │ ├── ContainersCannotExtendOtherContainers.kt
│ │ │ │ ├── CannotIncludeGenericContainer.kt
│ │ │ │ ├── ContainersCannotExtendOtherContainers.fir.diag.txt
│ │ │ │ ├── CannotIncludeGenericContainer.fir.diag.txt
│ │ │ │ └── NoProvidesOnParams.kt
│ │ │ ├── dependencygraph
│ │ │ │ ├── AsContributionCannotWorkOnContributedExtensions.fir.diag.txt
│ │ │ │ ├── GraphsCannotDirectlyExtendOtherGraphs.fir.diag.txt
│ │ │ │ ├── AsContributionCannotWorkOnContributedExtensionsMultiModule.fir.diag.txt
│ │ │ │ ├── optional
│ │ │ │ │ ├── OptionalBindingIsNotAllowedOnInjectors.kt
│ │ │ │ │ ├── OptionalBindingIsNotAllowedOnInjectors.fir.diag.txt
│ │ │ │ │ ├── RequiredAnnotationResultsInMissingBindingMultiModule.fir.ir.diag.txt
│ │ │ │ │ ├── OptionalBindingParamWarningIfDefault.kt
│ │ │ │ │ ├── DisabledResultsInMissingBindings.kt
│ │ │ │ │ ├── OptionalBindingErrorIfDisabled.kt
│ │ │ │ │ ├── DisabledResultsInMissingBindingsEvenWithAnnotation.kt
│ │ │ │ │ ├── RequiredAnnotationResultsInMissingBindings.kt
│ │ │ │ │ ├── OptionalBindingParamRequiresDefaultValue.kt
│ │ │ │ │ ├── DisabledResultsInMissingBindingMultiModule.kt
│ │ │ │ │ └── RequiredAnnotationResultsInMissingBindingMultiModule.kt
│ │ │ │ ├── MissingBindingHintsShouldReportInternalOnlyIfInternal.fir.ir.diag.txt
│ │ │ │ ├── ConfigurableMaxIrErrors.fir.ir.diag.txt
│ │ │ │ ├── AssistedTypesCannotBeDirectlyQualified.fir.diag.txt
│ │ │ │ ├── leniency
│ │ │ │ │ ├── SomeUnusedAndSomeUsed.kt
│ │ │ │ │ └── SomeUnusedAndSomeUsed.fir.ir.diag.txt
│ │ │ │ ├── GraphsCannotDirectlyExtendOtherGraphs.kt
│ │ │ │ ├── extensions
│ │ │ │ │ └── ExtensionsWithFactoriesMustUseThem.fir.diag.txt
│ │ │ │ ├── AssistedTypesCannotBeProvidedWithoutQualifiers.fir.diag.txt
│ │ │ │ ├── AllDuplicateBindingsAreReported.kt
│ │ │ │ ├── AssistedTypesCannotBeProvidedWithoutQualifiers.kt
│ │ │ │ ├── InternalBindings.fir.ir.diag.txt
│ │ │ │ ├── MultipleMissingDeps.kt
│ │ │ │ ├── dynamic
│ │ │ │ │ └── CreateDynamicGraphCannotBeInLocalClasses.fir.diag.txt
│ │ │ │ ├── MismatchedSingleInScopesDisambiguateSameNameScopes.fir.ir.diag.txt
│ │ │ │ ├── UsefulHintsForMissingImplDeps.kt
│ │ │ │ ├── MismatchedSingleInScopesDisambiguateSameNameScopes.kt
│ │ │ │ ├── MixedCycleParams.fir.ir.diag.txt
│ │ │ │ ├── AssistedTypesCannotBeDirectlyQualified.kt
│ │ │ │ ├── MissingBindingHintsShouldReportInternalOnlyIfInternal.kt
│ │ │ │ └── MixedCycleParams.kt
│ │ │ ├── createGraph
│ │ │ │ ├── CreateGraph_MustBeGraph.kt
│ │ │ │ ├── GraphFactoriesMayNotHaveVarargs.fir.diag.txt
│ │ │ │ ├── CreateGraph_MustBeGraph.fir.diag.txt
│ │ │ │ ├── CreateGraph_MustBeGraphFactory.fir.diag.txt
│ │ │ │ ├── CreateGraph_GraphHasFactory.fir.diag.txt
│ │ │ │ ├── CreateGraph_GraphHasFactory.kt
│ │ │ │ ├── CreateGraph_MustBeGraphFactory.kt
│ │ │ │ ├── GraphFactoriesMayNotHaveVarargs.kt
│ │ │ │ └── CreateGraph_OkCase.kt
│ │ │ ├── interop
│ │ │ │ └── dagger
│ │ │ │ │ ├── DoNotSuggestMovingInjectAnnotationToClassWhenUsingJavaxOrJakartaInject.fir.diag.txt
│ │ │ │ │ ├── ModulesWithConstructorInjectedFields.fir.diag.txt
│ │ │ │ │ ├── DoNotSuggestMovingInjectAnnotationToClassWhenUsingJavaxOrJakartaInject.kt
│ │ │ │ │ ├── MemberInjectionQualifiersAreLookedUp.fir.ir.diag.txt
│ │ │ │ │ ├── PositionalAnnotationArgsError.fir.diag.txt
│ │ │ │ │ ├── PositionalAnnotationArgsError.kt
│ │ │ │ │ ├── PositionalAnnotationArgsWarning.kt
│ │ │ │ │ ├── PositionalAnnotationArgsWarning.fir.diag.txt
│ │ │ │ │ └── BindsOptionalOfDiagnostics.kt
│ │ │ ├── aggregation
│ │ │ │ ├── InternalHintsAreNotVisibleWithoutFriends.fir.ir.diag.txt
│ │ │ │ ├── InternalContributionMissingHint.fir.ir.diag.txt
│ │ │ │ ├── InternalContributionMissingHint.kt
│ │ │ │ └── InternalHintsAreNotVisibleWithoutFriends.kt
│ │ │ └── graph
│ │ │ │ ├── LazyAssistedFactoryGraphAccessor.fir.diag.txt
│ │ │ │ └── LazyAssistedFactoryGraphAccessor.kt
│ │ └── box
│ │ │ ├── multibindings
│ │ │ ├── UnusedMultibindingsDoNotGetValidated.kt
│ │ │ └── LazyMemberInjectedBindings.kt
│ │ │ ├── dependencygraph
│ │ │ ├── GraphsCanHaveExistingImplClases.kt
│ │ │ ├── OpenAccessorsInClasses.kt
│ │ │ ├── leniency
│ │ │ │ ├── UnusedProvidersAreNotValidated.kt
│ │ │ │ └── UnusedProvidersInContainersAreNotValidated.kt
│ │ │ ├── GraphFactoriesSupportGenericProviders.kt
│ │ │ ├── ProvidingEmptyProviderMapDirectly.kt
│ │ │ ├── extensions
│ │ │ │ ├── ExtensionsCanBeDeclaredWithoutFactories.kt
│ │ │ │ ├── ExtensionsUsingDeferredTypesAreValid.kt
│ │ │ │ ├── SimpleExtension.kt
│ │ │ │ ├── FieldInjectorInGraphExtensionContainer.kt
│ │ │ │ ├── MultipleExtensionFactoriesAreValid.kt
│ │ │ │ └── ManagedBindingContainerInstancesPlumbDown.kt
│ │ │ ├── dynamic
│ │ │ │ └── GraphsAreCachedByType.kt
│ │ │ ├── bindingcontainers
│ │ │ │ ├── BindingContainerViaAnnotationCycleIsOk.kt
│ │ │ │ └── BindingContainerViaCreator.kt
│ │ │ ├── ExposingIncludedGraphsDirectly.kt
│ │ │ ├── ProvidingEmptyMultibindingsDirectly.kt
│ │ │ └── OverrideCompatibleAccessorsFromContributedInterface.kt
│ │ │ ├── inject
│ │ │ ├── DefaultValuesPropagateToNewInstanceParams.kt
│ │ │ ├── InjectedTypeInheritsAnAnnotatedAbstractClass.kt
│ │ │ ├── member
│ │ │ │ ├── MultiInheritanceMemberInject.kt
│ │ │ │ ├── MemberInjectorRequest.kt
│ │ │ │ ├── GenericMemberInjectorRequest.kt
│ │ │ │ └── MemberInjectorRequestAsProvidesParam.kt
│ │ │ └── assisted
│ │ │ │ ├── ImplsAreVisibleAcrossModules.kt
│ │ │ │ ├── NoAssistedArgsInAssistedInject.kt
│ │ │ │ ├── AssistedTypesCanBeProvidedWithQualifiers.kt
│ │ │ │ ├── DefaultAssistedFactoryIsGeneratedInFIR.kt
│ │ │ │ └── DefaultAssistedFactoryWithDefaultValues.kt
│ │ │ ├── provides
│ │ │ ├── DefaultValuesPropagateToNewInstanceParams.kt
│ │ │ ├── SimpleFunctionProvider.kt
│ │ │ ├── JvmFieldProvidersAreRespected.kt
│ │ │ ├── CapitalizedProvides.kt
│ │ │ └── QualifiersOnDifferentAnnotationSites.kt
│ │ │ ├── cycles
│ │ │ ├── SimpleBindingIntoMulti.kt
│ │ │ ├── SelfCycle.kt
│ │ │ └── BindsCycleGraph.kt
│ │ │ ├── aggregation
│ │ │ ├── AnyIsAValidSupertype.kt
│ │ │ ├── ExcludesWithOrigin.kt
│ │ │ ├── InternalHintsInGraph.kt
│ │ │ ├── ReplacementsWithOrigin.kt
│ │ │ ├── ContributingMultibileNullableBindings.kt
│ │ │ └── ContributedBindingContainerReplacements.kt
│ │ │ ├── bindingcontainers
│ │ │ ├── PrivateBindsProperty.kt
│ │ │ ├── MultibindsOnlyInContainer.kt
│ │ │ └── SimpleContainersWithHintsWork.kt
│ │ │ ├── member
│ │ │ ├── SimpleAncestorInjectionWithEmptyChild.kt
│ │ │ ├── SimpleAncestorInjectionWithEmptyChildNoFactory.kt
│ │ │ ├── SimpleAncestorInjectionWithEmptyChildWithParentInAnotherModule.kt
│ │ │ └── AncestorInjectionWithEmptyDescendants.kt
│ │ │ └── interop
│ │ │ ├── dagger
│ │ │ ├── DaggerFactoryClassCanBeLoaded.kt
│ │ │ ├── DaggerFactoryClassCanBeLoadedJakarta.kt
│ │ │ ├── DaggerComponentModulesAnnotationInterop.kt
│ │ │ ├── DaggerMultibindsAllowEmptyByDefault.kt
│ │ │ ├── AnotherBindsOptionalPresentTest.kt
│ │ │ ├── InjectedJavaxProviderInteropWorks.kt
│ │ │ ├── JavaxProviderShouldWorkInSet.kt
│ │ │ ├── QualifiedDaggerFactoryClassCanBeLoaded.kt
│ │ │ ├── GenericDaggerFactoryClassCanBeLoaded.kt
│ │ │ ├── JavaxProviderShouldWorkInMap.kt
│ │ │ └── ZeroArgConstructorInjectionGeneratedByAnvil.kt
│ │ │ └── guice
│ │ │ ├── InjectedGuiceProviderInteropWorks.kt
│ │ │ └── InjectedKotlinLazyFromGuiceProviderWorks.kt
│ └── kotlin
│ │ └── dev
│ │ └── zacsweers
│ │ └── metro
│ │ └── compiler
│ │ ├── KotlinTestImportPreprocessor.kt
│ │ ├── MetroDefaultImportPreprocessor.kt
│ │ └── interop
│ │ └── Jsr330Utils.kt
│ ├── generator220
│ └── kotlin
│ │ └── dev
│ │ └── zacsweers
│ │ └── metro
│ │ └── compiler
│ │ └── MetroKotlinStandardLibrariesPathProvider.kt
│ ├── generator230
│ └── kotlin
│ │ └── dev
│ │ └── zacsweers
│ │ └── metro
│ │ └── compiler
│ │ └── MetroKotlinStandardLibrariesPathProvider.kt
│ └── generator2320
│ └── kotlin
│ └── dev
│ └── zacsweers
│ └── metro
│ └── compiler
│ └── MetroKotlinStandardLibrariesPathProvider.kt
├── benchmark
├── startup-android
│ ├── app
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ └── main
│ │ │ ├── res
│ │ │ └── values
│ │ │ │ └── strings.xml
│ │ │ └── kotlin
│ │ │ └── dev
│ │ │ └── zacsweers
│ │ │ └── metro
│ │ │ └── benchmark
│ │ │ └── startup
│ │ │ └── android
│ │ │ ├── MainActivity.kt
│ │ │ └── BenchmarkApplication.kt
│ ├── microbenchmark
│ │ └── src
│ │ │ └── main
│ │ │ └── AndroidManifest.xml
│ └── benchmark
│ │ └── src
│ │ └── main
│ │ └── AndroidManifest.xml
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── startup-jvm
│ ├── build.gradle.kts
│ └── minified-jar
│ │ └── proguard-rules.pro
└── gradle.properties
├── spotless
├── spotless.java
└── spotless.kt
├── runtime
├── gradle.properties
└── src
│ ├── commonMain
│ └── kotlin
│ │ └── dev
│ │ └── zacsweers
│ │ └── metro
│ │ ├── internal
│ │ ├── Factory.kt
│ │ ├── GraphFactoryInvokeFunctionMarker.kt
│ │ ├── MetroImplMarker.kt
│ │ ├── MetroContribution.kt
│ │ ├── InjectedFunctionClass.kt
│ │ ├── AssistedMarker.kt
│ │ └── MultibindingElement.kt
│ │ ├── Includes.kt
│ │ └── Named.kt
│ └── commonTest
│ └── kotlin
│ └── dev
│ └── zacsweers
│ └── metro
│ └── internal
│ └── SimpleCounter.kt
├── docs
├── site-assets
│ └── img
│ │ ├── favicon.ico
│ │ └── favicon-readme.txt
└── benchmark_assets
│ ├── runtime_jvm.png
│ ├── benchmark_abi.png
│ ├── benchmark_noabi.png
│ ├── runtime_android.png
│ ├── runtime_jvm_r8.png
│ └── benchmark_graph_processing.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── metrox-android
├── gradle.properties
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── kotlin
│ └── dev
│ └── zacsweers
│ └── metrox
│ └── android
│ ├── ServiceKey.kt
│ ├── ActivityKey.kt
│ ├── BroadcastReceiverKey.kt
│ └── ContentProviderKey.kt
├── interop-dagger
├── gradle.properties
├── build.gradle.kts
└── api
│ └── interop-dagger.api
├── interop-guice
├── gradle.properties
└── build.gradle.kts
├── interop-javax
├── gradle.properties
├── api
│ └── interop-javax.api
└── build.gradle.kts
├── metrox-viewmodel
├── gradle.properties
└── src
│ └── commonMain
│ └── kotlin
│ └── dev
│ └── zacsweers
│ └── metrox
│ └── viewmodel
│ └── ViewModelScope.kt
├── interop-jakarta
├── gradle.properties
├── api
│ └── interop-jakarta.api
└── build.gradle.kts
├── samples
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── integration-tests
│ ├── README.md
│ └── src
│ │ ├── androidMain
│ │ └── res
│ │ │ └── layout
│ │ │ └── activity_main.xml
│ │ ├── commonTest
│ │ └── kotlin
│ │ │ └── dev
│ │ │ └── zacsweers
│ │ │ └── metro
│ │ │ └── test
│ │ │ └── integration
│ │ │ ├── Callable.kt
│ │ │ ├── Platform.kt
│ │ │ └── Singleton.kt
│ │ ├── jsTest
│ │ └── kotlin
│ │ │ └── dev
│ │ │ └── zacsweers
│ │ │ └── metro
│ │ │ └── test
│ │ │ └── integration
│ │ │ └── Platform.js.kt
│ │ ├── commonJvmTest
│ │ └── kotlin
│ │ │ └── dev
│ │ │ └── zacsweers
│ │ │ └── metro
│ │ │ └── test
│ │ │ └── integration
│ │ │ └── Platform.jvm.kt
│ │ ├── nativeTest
│ │ └── kotlin
│ │ │ └── dev
│ │ │ └── zacsweers
│ │ │ └── metro
│ │ │ └── test
│ │ │ └── integration
│ │ │ └── Platform.native.kt
│ │ ├── commonWasmTest
│ │ └── kotlin
│ │ │ └── dev
│ │ │ └── zacsweers
│ │ │ └── metro
│ │ │ └── test
│ │ │ └── integration
│ │ │ └── Platform.wasm.kt
│ │ └── androidUnitTest
│ │ └── kotlin
│ │ └── dev
│ │ └── zacsweers
│ │ └── metro
│ │ └── test
│ │ └── integration
│ │ └── replaces
│ │ └── AndroidPlatformContribution.kt
├── android-app
│ ├── src
│ │ └── main
│ │ │ ├── res
│ │ │ ├── values
│ │ │ │ └── ic_launcher_background.xml
│ │ │ └── mipmap-anydpi-v26
│ │ │ │ └── ic_launcher.xml
│ │ │ └── kotlin
│ │ │ └── dev
│ │ │ └── zacsweers
│ │ │ └── metro
│ │ │ └── sample
│ │ │ └── android
│ │ │ ├── FragmentKey.kt
│ │ │ └── WorkerKey.kt
│ └── README.md
├── compose-viewmodels
│ ├── app
│ │ └── src
│ │ │ ├── androidMain
│ │ │ ├── res
│ │ │ │ ├── values
│ │ │ │ │ └── ic_launcher_background.xml
│ │ │ │ └── mipmap-anydpi-v26
│ │ │ │ │ └── ic_launcher.xml
│ │ │ └── kotlin
│ │ │ │ └── dev
│ │ │ │ └── zacsweers
│ │ │ │ └── metro
│ │ │ │ └── sample
│ │ │ │ └── composeviewmodels
│ │ │ │ └── app
│ │ │ │ ├── Graphs.kt
│ │ │ │ └── MetroApp.kt
│ │ │ ├── jvmMain
│ │ │ └── kotlin
│ │ │ │ └── dev
│ │ │ │ └── zacsweers
│ │ │ │ └── metro
│ │ │ │ └── sample
│ │ │ │ └── composeviewmodels
│ │ │ │ └── app
│ │ │ │ ├── Graphs.kt
│ │ │ │ └── Main.kt
│ │ │ └── commonMain
│ │ │ └── kotlin
│ │ │ └── dev
│ │ │ └── zacsweers
│ │ │ └── metro
│ │ │ └── sample
│ │ │ └── composeviewmodels
│ │ │ └── app
│ │ │ └── Routes.kt
│ ├── screen-home
│ │ └── build.gradle.kts
│ ├── screen-details
│ │ └── build.gradle.kts
│ └── screen-settings
│ │ └── build.gradle.kts
├── circuit-app
│ └── src
│ │ └── wasmJsMain
│ │ ├── resources
│ │ └── index.html
│ │ └── kotlin
│ │ └── dev
│ │ └── zacsweers
│ │ └── metro
│ │ └── sample
│ │ └── circuit
│ │ └── main.kt
├── interop
│ ├── customAnnotations-kotlinInject
│ │ ├── src
│ │ │ └── commonTest
│ │ │ │ └── kotlin
│ │ │ │ └── dev
│ │ │ │ └── zacsweers
│ │ │ │ └── metro
│ │ │ │ └── sample
│ │ │ │ ├── Singleton.kt
│ │ │ │ └── Named.kt
│ │ └── build.gradle.kts
│ ├── dependencies-kotlinInject
│ │ ├── src
│ │ │ └── test
│ │ │ │ └── kotlin
│ │ │ │ └── dev
│ │ │ │ └── zacsweers
│ │ │ │ └── metro
│ │ │ │ └── sample
│ │ │ │ ├── StringComponent.kt
│ │ │ │ └── StringGraph.kt
│ │ └── build.gradle.kts
│ ├── customAnnotations-guice
│ │ └── build.gradle.kts
│ ├── dependencies-dagger
│ │ ├── build.gradle.kts
│ │ └── src
│ │ │ └── test
│ │ │ └── kotlin
│ │ │ └── dev
│ │ │ └── zacsweers
│ │ │ └── metro
│ │ │ └── sample
│ │ │ ├── StringComponent.kt
│ │ │ └── StringGraph.kt
│ └── customAnnotations-dagger
│ │ └── build.gradle.kts
├── weather-app
│ ├── src
│ │ └── jvmMain
│ │ │ └── kotlin
│ │ │ └── dev
│ │ │ └── zacsweers
│ │ │ └── metro
│ │ │ └── sample
│ │ │ └── weather
│ │ │ └── JvmAppGraph.kt
│ └── README.md
└── graph-analysis
│ └── build.gradle.kts
├── compiler
├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── services
│ │ │ ├── org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
│ │ │ └── org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
│ │ └── kotlin
│ │ └── dev
│ │ └── zacsweers
│ │ └── metro
│ │ └── compiler
│ │ ├── ir
│ │ └── IrBindingContainerCallable.kt
│ │ ├── graph
│ │ ├── MissingBindingHints.kt
│ │ └── BaseTypeKey.kt
│ │ ├── exceptions.kt
│ │ └── OptionalBindingBehavior.kt
└── gradle.properties
├── gradle-plugin
├── gradle.properties
└── src
│ ├── main
│ └── kotlin
│ │ └── dev
│ │ └── zacsweers
│ │ └── metro
│ │ └── gradle
│ │ ├── MetroExtensionMarker.kt
│ │ ├── KotlinVersions.kt
│ │ ├── metroGradleUtil.kt
│ │ └── DiagnosticSeverity.kt
│ └── functionalTest
│ └── kotlin
│ └── dev
│ └── zacsweers
│ └── metro
│ └── gradle
│ └── MetroOptionOverrides.kt
├── metrox-viewmodel-compose
├── gradle.properties
└── api
│ └── metrox-viewmodel-compose.api
├── .idea
├── externalDependencies.xml
└── kotlinTestDataPluginTestDataPaths.xml
├── .gitattributes
├── RELEASING.md
├── scripts
└── generate_docs_dokka.sh
└── .gitignore
/.github/workflows/.java-version:
--------------------------------------------------------------------------------
1 | 24
--------------------------------------------------------------------------------
/compiler-compat/k2220/version.txt:
--------------------------------------------------------------------------------
1 | 2.2.20
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/fir/scratch.kt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/scratch.kt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/compiler-compat/k230_beta1/version.txt:
--------------------------------------------------------------------------------
1 | 2.3.0-Beta1
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/scratch.fir.kt.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/compiler-compat/k2320_dev_5437/version.txt:
--------------------------------------------------------------------------------
1 | 2.3.20-dev-5437
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/fir/scratch.fir.txt:
--------------------------------------------------------------------------------
1 | FILE: scratch.kt
2 |
--------------------------------------------------------------------------------
/benchmark/startup-android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Not necessary for our use
2 | -dontobfuscate
--------------------------------------------------------------------------------
/spotless/spotless.java:
--------------------------------------------------------------------------------
1 | // Copyright (C) $YEAR Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
--------------------------------------------------------------------------------
/spotless/spotless.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) $YEAR Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
--------------------------------------------------------------------------------
/runtime/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Metro Runtime
2 | POM_ARTIFACT_ID=runtime
3 | POM_PACKAGING=jar
4 |
--------------------------------------------------------------------------------
/docs/site-assets/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZacSweers/metro/HEAD/docs/site-assets/img/favicon.ico
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZacSweers/metro/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/metrox-android/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Metrox Android
2 | POM_ARTIFACT_ID=metrox-android
3 | POM_PACKAGING=aar
4 |
--------------------------------------------------------------------------------
/interop-dagger/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Metro Dagger Inteorp
2 | POM_ARTIFACT_ID=interop-dagger
3 | POM_PACKAGING=jar
4 |
--------------------------------------------------------------------------------
/interop-guice/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Metro Guice Interop
2 | POM_ARTIFACT_ID=interop-guice
3 | POM_PACKAGING=jar
4 |
--------------------------------------------------------------------------------
/interop-javax/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Metro Javax Interop
2 | POM_ARTIFACT_ID=interop-javax
3 | POM_PACKAGING=jar
4 |
--------------------------------------------------------------------------------
/metrox-viewmodel/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Metrox ViewModel
2 | POM_ARTIFACT_ID=metrox-viewmodel
3 | POM_PACKAGING=jar
4 |
--------------------------------------------------------------------------------
/docs/benchmark_assets/runtime_jvm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZacSweers/metro/HEAD/docs/benchmark_assets/runtime_jvm.png
--------------------------------------------------------------------------------
/interop-jakarta/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Metro Jakarta Interop
2 | POM_ARTIFACT_ID=interop-jakarta
3 | POM_PACKAGING=jar
4 |
--------------------------------------------------------------------------------
/docs/benchmark_assets/benchmark_abi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZacSweers/metro/HEAD/docs/benchmark_assets/benchmark_abi.png
--------------------------------------------------------------------------------
/docs/benchmark_assets/benchmark_noabi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZacSweers/metro/HEAD/docs/benchmark_assets/benchmark_noabi.png
--------------------------------------------------------------------------------
/docs/benchmark_assets/runtime_android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZacSweers/metro/HEAD/docs/benchmark_assets/runtime_android.png
--------------------------------------------------------------------------------
/docs/benchmark_assets/runtime_jvm_r8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZacSweers/metro/HEAD/docs/benchmark_assets/runtime_jvm_r8.png
--------------------------------------------------------------------------------
/samples/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZacSweers/metro/HEAD/samples/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/benchmark/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZacSweers/metro/HEAD/benchmark/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/injectconstructor/DefaultValuesPropagateToNewInstanceParams.kt:
--------------------------------------------------------------------------------
1 | @Inject class ValueHolder(stringValue: String? = null)
2 |
--------------------------------------------------------------------------------
/docs/benchmark_assets/benchmark_graph_processing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZacSweers/metro/HEAD/docs/benchmark_assets/benchmark_graph_processing.png
--------------------------------------------------------------------------------
/compiler/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor:
--------------------------------------------------------------------------------
1 | dev.zacsweers.metro.compiler.MetroCommandLineProcessor
2 |
--------------------------------------------------------------------------------
/compiler/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar:
--------------------------------------------------------------------------------
1 | dev.zacsweers.metro.compiler.MetroCompilerPluginRegistrar
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/functioninject/CannotHaveTypeArgs.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /CannotHaveTypeArgs.kt:(112,115): error: Injected functions cannot be generic.
2 |
--------------------------------------------------------------------------------
/compiler/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Metro Compiler
2 | POM_ARTIFACT_ID=compiler
3 | POM_PACKAGING=jar
4 |
5 | # kotlinc imposes its own
6 | kotlin.stdlib.default.dependency=false
--------------------------------------------------------------------------------
/compiler-compat/k2220/src/main/resources/META-INF/services/dev.zacsweers.metro.compiler.compat.CompatContext$Factory:
--------------------------------------------------------------------------------
1 | dev.zacsweers.metro.compiler.compat.k2220.CompatContextImpl$Factory
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/functioninject/CannotBeScoped.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /CannotBeScoped.kt:(100,126): error: Injected functions are stateless and should not be scoped.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/Binds_Interface_OkCase.kt:
--------------------------------------------------------------------------------
1 | interface ExampleGraph {
2 | @Binds val Int.bind: Number
3 | @Binds fun String.bind(): CharSequence
4 | }
5 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/PrivateProviderOption_Error.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /PrivateProviderOption_Error.kt:(240,253): error: `@Provides` declarations should be private.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesPropertiesCannotBeMutable.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesPropertiesCannotBeMutable.kt:(150,160): error: @Provides properties cannot be var
2 |
--------------------------------------------------------------------------------
/samples/integration-tests/README.md:
--------------------------------------------------------------------------------
1 | Metro Integration Tests
2 | =======================
3 |
4 | TODO - document remote debugging setup. Ideally an easy way to test individual components
5 |
--------------------------------------------------------------------------------
/compiler-compat/k230_beta1/src/main/resources/META-INF/services/dev.zacsweers.metro.compiler.compat.CompatContext$Factory:
--------------------------------------------------------------------------------
1 | dev.zacsweers.metro.compiler.compat.k230_beta1.CompatContextImpl$Factory
2 |
--------------------------------------------------------------------------------
/gradle-plugin/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Metro Gradle Plugin
2 | POM_ARTIFACT_ID=gradle-plugin
3 | POM_PACKAGING=jar
4 |
5 | # Gradle imposes its own
6 | kotlin.stdlib.default.dependency=false
7 |
--------------------------------------------------------------------------------
/samples/android-app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/functioninject/CannotHaveExtensionReceivers.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /CannotHaveExtensionReceivers.kt:(112,118): error: Injected functions cannot have receiver parameters.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/Binds_interface_ShouldNotHaveBodies.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /Binds_interface_ShouldNotHaveBodies.kt:(226,230): warning: `@Binds` declarations should be private.
2 |
--------------------------------------------------------------------------------
/compiler-compat/k2320_dev_5437/src/main/resources/META-INF/services/dev.zacsweers.metro.compiler.compat.CompatContext$Factory:
--------------------------------------------------------------------------------
1 | dev.zacsweers.metro.compiler.compat.k2320_dev_5437.CompatContextImpl$Factory
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesShouldBePrivate_InInterface.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesShouldBePrivate_InInterface.kt:(239,252): warning: `@Provides` declarations should be private.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/functioninject/ContextParamsCannotBeOptional.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ContextParamsCannotBeOptional.kt:(166,172): error: Context parameters cannot be annotated @OptionalBinding.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeLocal.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoriesCannotBeLocal.kt:(133,152): error: @AssistedFactory declarations cannot be local classes.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesShouldBePrivate_InAbstractClass.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesShouldBePrivate_InAbstractClass.kt:(280,293): warning: `@Provides` declarations should be private.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/provides/DefaultValuesPropagateToNewInstanceParams.kt:
--------------------------------------------------------------------------------
1 | interface IntProvider {
2 | @Provides fun provideInt(stringValue: String? = null): Int = stringValue?.toInt() ?: 0
3 | }
--------------------------------------------------------------------------------
/metrox-viewmodel-compose/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Metrox ViewModel Compose
2 | POM_ARTIFACT_ID=metrox-viewmodel-compose
3 | POM_PACKAGING=jar
4 |
5 | org.jetbrains.compose.experimental.macos.enabled=true
6 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBePrivate.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoriesCannotBePrivate.kt:(150,157): error: @AssistedFactory declarations must be public or internal.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/BindsWithBodiesShouldBePrivate_InInterface.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /BindsWithBodiesShouldBePrivate_InInterface.kt:(247,260): warning: `@Binds` declarations should be private.
2 |
--------------------------------------------------------------------------------
/benchmark/startup-android/microbenchmark/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeProtected.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoriesCannotBeProtected.kt:(150,159): error: @AssistedFactory declarations must be public or internal.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/fir/aggregation/ContributingTypes.kt:
--------------------------------------------------------------------------------
1 | @ContributesTo(AppScope::class)
2 | interface ContributedInterface
3 |
4 | @DependencyGraph(scope = AppScope::class)
5 | interface ExampleGraph
6 |
--------------------------------------------------------------------------------
/samples/android-app/README.md:
--------------------------------------------------------------------------------
1 | # Android Sample
2 |
3 | This is an extremely simple Android sample app that demonstrates using Metro to constructor-inject `Activity`, `Fragment`, and `ViewModel` with multibindings.
4 |
--------------------------------------------------------------------------------
/samples/compose-viewmodels/app/src/androidMain/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
5 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/BindsWithBodiesShouldBePrivate_InAbstractClass.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /BindsWithBodiesShouldBePrivate_InAbstractClass.kt:(252,265): warning: `@Binds` declarations should be private.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/InjectingAPlainObjectIsSus.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | object ObjectClass
3 |
4 | @Inject
5 | class Example(obj: ObjectClass)
6 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/member/FunctionMemberInjectsCannotHaveTypeParams.kt:
--------------------------------------------------------------------------------
1 | class Example {
2 | @Inject fun injectedFunction(value: T) {
3 |
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesCannotLiveInObjects.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | object InvalidContainer {
4 | @Provides fun provideString(): String = "Hello"
5 | }
6 |
--------------------------------------------------------------------------------
/.idea/externalDependencies.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/functioninject/CannotHaveExtensionReceivers.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // ENABLE_TOP_LEVEL_FUNCTION_INJECTION
3 | @Inject
4 | fun String.Example() {
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeEnums.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoriesCannotBeEnums.kt:(161,168): error: @AssistedFactory declarations should be non-sealed abstract classes or interfaces.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeFinal.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoriesCannotBeFinal.kt:(156,163): error: @AssistedFactory declarations should be non-sealed abstract classes or interfaces.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoryWithMissingSAM.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoryWithMissingSAM.kt:(160,167): error: @AssistedFactory declarations must have exactly one abstract function but found none.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/dependencygraph/EmptyMapMultibindingsUseEmptyMap.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | // Uses emptyMap() in code gen
4 | @Multibinds(allowEmpty = true)
5 | val ints: Map
6 | }
--------------------------------------------------------------------------------
/docs/site-assets/img/favicon-readme.txt:
--------------------------------------------------------------------------------
1 | - Emoji Icon Author: Google Noto Emoji fonts
2 | - Emoji Icon Source: https://github.com/googlefonts/noto-emoji/blob/main/svg/emoji_u1f687.svg
3 | - Emoji Icon License: Apache license, version 2.0
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/CannotAnnotateBothGraphAndContainer.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /CannotAnnotateBothGraphAndContainer.kt:(62,78): error: Classes cannot be annotated with both '@BindingContainer' and '@DependencyGraph'.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/functioninject/CannotHaveTypeArgs.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // ENABLE_TOP_LEVEL_FUNCTION_INJECTION
3 | @Inject
4 | fun Example() {
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/functioninject/CannotBeScoped.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // ENABLE_TOP_LEVEL_FUNCTION_INJECTION
3 | @SingleIn(AppScope::class)
4 | @Inject
5 | fun Example() {
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/InjectingAPlainObjectIsSus.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /InjectingAPlainObjectIsSus.kt:(108,119): warning: Suspicious injection of an unqualified object type 'ObjectClass'. This is probably unnecessary or unintentional.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeSealedClasses.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoriesCannotBeSealedClasses.kt:(163,170): error: @AssistedFactory declarations should be non-sealed abstract classes or interfaces.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/LazyAssistedFactoryInjection.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /LazyAssistedFactoryInjection.kt:(105,118): error: Metro does not support injecting Lazy because Foo.Factory is an @AssistedFactory-annotated type.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/ConflictingProvidesAndClassScopes.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ConflictingProvidesAndClassScopes.kt:(181,191): warning: Provided type 'Bar' is already constructor-injected but declares a different scope. This is likely a bug.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeAnnotationClasses.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoriesCannotBeAnnotationClasses.kt:(167,174): error: @AssistedFactory declarations should be non-sealed abstract classes or interfaces.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeAnnotationObjects.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoriesCannotBeAnnotationObjects.kt:(157,164): error: @AssistedFactory declarations should be non-sealed abstract classes or interfaces.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeSealedInterfaces.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoriesCannotBeSealedInterfaces.kt:(167,174): error: @AssistedFactory declarations should be non-sealed abstract classes or interfaces.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/LazyAssistedFactoryProvides.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /LazyAssistedFactoryProvides.kt:(443,466): error: Metro does not support injecting Lazy because MyAssistedFactory is an @AssistedFactory-annotated type.
2 |
--------------------------------------------------------------------------------
/gradle-plugin/src/main/kotlin/dev/zacsweers/metro/gradle/MetroExtensionMarker.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.gradle
4 |
5 | @DslMarker public annotation class MetroExtensionMarker
6 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/AsContributionCannotWorkOnContributedExtensions.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AsContributionCannotWorkOnContributedExtensions.kt:(608,618): error: `asContribution` receiver must be annotated with a `@DependencyGraph` annotation.
2 |
--------------------------------------------------------------------------------
/samples/integration-tests/src/androidMain/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set the default behavior, in case people don't have core.autocrlf set.
2 | * text=auto
3 |
4 | compiler-tests/**/*.java linguist-generated=true
5 | **/yarn.lock linguist-generated=true
6 | **/package-lock.lock linguist-generated=true
7 | *.bat text eol=crlf
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/CannotAnnotateBothGraphAndContainer.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @DependencyGraph
4 | @BindingContainer
5 | interface ConfusedContainer {
6 | @Binds val Int.bind: Number
7 | }
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesFunctionsCannotBeTopLevel.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @DependencyGraph
4 | abstract class ExampleGraph {
5 | abstract val int: Int
6 | }
7 |
8 | @Provides fun provideInt(): Int = 0
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesMustHaveABody_Interface.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | interface ExampleGraph {
4 | @Provides val provideInt: Int
5 | @Provides fun provideString(): String
6 | }
7 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesPropertiesCannotBeMutable.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @DependencyGraph
4 | abstract class ExampleGraph {
5 | abstract val int: Int
6 |
7 | @Provides var provideInt: Int = 0
8 | }
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/GraphsCannotDirectlyExtendOtherGraphs.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /module_main_GraphsCannotDirectlyExtendOtherGraphs.kt:(101,112): error: Graph class 'ChildGraph' may not directly extend graph class 'ParentGraph'. Use @GraphExtension instead.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/AssistedParametersAreNotSupportedOnProvides.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | interface Example {
4 | @Provides
5 | fun provideString(@Assisted int: Int): String = "Hello, assisted parameters"
6 | }
7 |
--------------------------------------------------------------------------------
/samples/integration-tests/src/commonTest/kotlin/dev/zacsweers/metro/test/integration/Callable.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2024 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.test.integration
4 |
5 | fun interface Callable {
6 | fun call(): T
7 | }
8 |
--------------------------------------------------------------------------------
/RELEASING.md:
--------------------------------------------------------------------------------
1 | Releasing
2 | =========
3 |
4 | 1. Update the `CHANGELOG.md` for the impending release.
5 | - If the Kotlin version changed, update `compatibility.md` docs too.
6 | 2. Run `./release.sh (--patch|--minor|--major)`.
7 | 3. Publish the release on the repo's releases tab.
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/function/LazyAssistedFactoryFunctionInjection.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /LazyAssistedFactoryFunctionInjection.kt:(364,387): error: Metro does not support injecting Lazy because MyAssistedFactory is an @AssistedFactory-annotated type.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/fir/aggregation/ContributingTypesDependency.kt:
--------------------------------------------------------------------------------
1 | // MODULE: lib
2 |
3 | @ContributesTo(AppScope::class)
4 | interface ContributedInterface
5 |
6 | // MODULE: main(lib)
7 |
8 | @DependencyGraph(scope = AppScope::class)
9 | interface ExampleGraph
10 |
--------------------------------------------------------------------------------
/runtime/src/commonMain/kotlin/dev/zacsweers/metro/internal/Factory.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2024 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.internal
4 |
5 | import dev.zacsweers.metro.Provider
6 |
7 | public fun interface Factory : Provider
8 |
--------------------------------------------------------------------------------
/benchmark/startup-android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Metro Startup Benchmark
6 |
7 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/AssistedParametersAreNotSupportedOnProvides.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedParametersAreNotSupportedOnProvides.kt:(114,123): error: Assisted parameters are not supported for `@Provides` methods. Create a concrete assisted-injected factory class instead.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/MultibindingsWithComplexDependenciesGetProperties.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | val ints: Set
4 |
5 | @Provides fun provideString(): String = "3"
6 | @Provides @IntoSet fun provideInt(string: String): Int = string.toInt()
7 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesMustHaveABody_Interface.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesMustHaveABody_Interface.kt:(103,113): error: `@Provides` declarations must have bodies.
2 |
3 | /ProvidesMustHaveABody_Interface.kt:(135,148): error: `@Provides` declarations must have bodies.
4 |
--------------------------------------------------------------------------------
/samples/integration-tests/src/commonTest/kotlin/dev/zacsweers/metro/test/integration/Platform.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.test.integration
4 |
5 | expect fun isJvm(): Boolean
6 |
7 | expect fun isWasm(): Boolean
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/multibindings/UnusedMultibindingsDoNotGetValidated.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | @Provides @IntoSet fun provideInt(string: String): Int = string.toInt()
4 | }
5 |
6 | fun box(): String {
7 | val graph = createGraph()
8 | return "OK"
9 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/AsContributionCannotWorkOnContributedExtensionsMultiModule.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /module_main_AsContributionCannotWorkOnContributedExtensionsMultiModule.kt:(361,371): error: `asContribution` receiver must be annotated with a `@DependencyGraph` annotation.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoryWithMissingSAM.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int,
5 | ) {
6 | @AssistedFactory
7 | interface Factory
8 | }
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesMustHaveABody_AbstractClass.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | abstract class ExampleGraph {
4 | @Provides abstract val provideInt: Int
5 | @Provides abstract fun provideString(): String
6 | }
7 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/dependencygraph/MapsUseMapBuilderIfNoProvider.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | @Multibinds
4 | val ints: Map
5 |
6 | val intsWithProviders: Map>
7 |
8 | @Provides @IntoMap @IntKey(3) fun provideInt(): Int = 3
9 | }
--------------------------------------------------------------------------------
/gradle-plugin/src/functionalTest/kotlin/dev/zacsweers/metro/gradle/MetroOptionOverrides.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.gradle
4 |
5 | data class MetroOptionOverrides(val enableFullBindingGraphValidation: Boolean? = null)
6 |
--------------------------------------------------------------------------------
/samples/circuit-app/src/wasmJsMain/resources/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Counter
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeAnnotationClasses.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int,
5 | ) {
6 | @AssistedFactory
7 | annotation class Factory
8 | }
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesMustHaveABody_AbstractClass.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesMustHaveABody_AbstractClass.kt:(117,127): error: `@Provides` declarations must have bodies.
2 |
3 | /ProvidesMustHaveABody_AbstractClass.kt:(158,171): error: `@Provides` declarations must have bodies.
4 |
--------------------------------------------------------------------------------
/compiler/src/main/kotlin/dev/zacsweers/metro/compiler/ir/IrBindingContainerCallable.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.compiler.ir
4 |
5 | internal sealed interface IrBindingContainerCallable {
6 | val typeKey: IrTypeKey
7 | }
8 |
--------------------------------------------------------------------------------
/samples/integration-tests/src/commonTest/kotlin/dev/zacsweers/metro/test/integration/Singleton.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.test.integration
4 |
5 | import dev.zacsweers.metro.Scope
6 |
7 | @Scope annotation class Singleton
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/createGraph/CreateGraph_MustBeGraph.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | interface SomeType
4 |
5 | fun example() {
6 | val someType = createGraph<SomeType>()
7 | val someType2: SomeType = createGraph()
8 | }
9 |
--------------------------------------------------------------------------------
/samples/integration-tests/src/jsTest/kotlin/dev/zacsweers/metro/test/integration/Platform.js.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.test.integration
4 |
5 | actual fun isJvm(): Boolean = false
6 |
7 | actual fun isWasm(): Boolean = false
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/PrivateProviderOption_None.kt:
--------------------------------------------------------------------------------
1 | // PUBLIC_PROVIDER_SEVERITY: NONE
2 | // DISABLE_TRANSFORM_PROVIDERS_TO_PRIVATE
3 |
4 | interface ExampleGraph {
5 | @Provides val provideCharSequence: String get() = "Hello"
6 | @Provides fun provideString(): String = "Hello"
7 | }
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/cycles/SelfCycle.kt:
--------------------------------------------------------------------------------
1 | // DONT_SORT_DECLARATIONS
2 | @DependencyGraph
3 | interface SelfCycleGraph {
4 | fun s(): S
5 | }
6 |
7 | @Suppress("MEMBERS_INJECT_WARNING")
8 | @Inject
9 | class S(val sProvider: Provider) {
10 | @Inject lateinit var sLazy: Lazy
11 | }
12 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/interop-javax/api/interop-javax.api:
--------------------------------------------------------------------------------
1 | public final class dev/zacsweers/metro/interop/javax/JavaxInteropKt {
2 | public static final fun asJavaxProvider (Ldev/zacsweers/metro/Provider;)Ljavax/inject/Provider;
3 | public static final fun asMetroProvider (Ljavax/inject/Provider;)Ldev/zacsweers/metro/Provider;
4 | }
5 |
6 |
--------------------------------------------------------------------------------
/samples/integration-tests/src/commonJvmTest/kotlin/dev/zacsweers/metro/test/integration/Platform.jvm.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.test.integration
4 |
5 | actual fun isJvm(): Boolean = true
6 |
7 | actual fun isWasm(): Boolean = false
8 |
--------------------------------------------------------------------------------
/samples/integration-tests/src/nativeTest/kotlin/dev/zacsweers/metro/test/integration/Platform.native.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.test.integration
4 |
5 | actual fun isJvm(): Boolean = false
6 |
7 | actual fun isWasm(): Boolean = false
8 |
--------------------------------------------------------------------------------
/samples/interop/customAnnotations-kotlinInject/src/commonTest/kotlin/dev/zacsweers/metro/sample/Singleton.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample
4 |
5 | import me.tatarka.inject.annotations.Scope
6 |
7 | @Scope annotation class Singleton
8 |
--------------------------------------------------------------------------------
/samples/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/samples/integration-tests/src/commonWasmTest/kotlin/dev/zacsweers/metro/test/integration/Platform.wasm.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.test.integration
4 |
5 | actual fun isJvm(): Boolean = false
6 |
7 | actual fun isWasm(): Boolean = true
8 |
--------------------------------------------------------------------------------
/benchmark/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoryMustTargetAssistedInjectTypesButMissingConstructor.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | class ExampleClass
3 |
4 | @AssistedFactory
5 | fun interface ExampleClassFactory {
6 | fun create(count: Int): ExampleClass
7 | }
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/functioninject/ContextParamsCannotBeOptional.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // LANGUAGE: +ContextParameters
3 | // ENABLE_TOP_LEVEL_FUNCTION_INJECTION
4 |
5 | @Inject
6 | context(@OptionalBinding string: String)
7 | fun App() {
8 | // ...
9 | }
10 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/ProvidingAConstructorInjectedTypeHasASpecificWarning.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidingAConstructorInjectedTypeHasASpecificWarning.kt:(412,415): warning: Provided type 'Bar' is already constructor-injected and does not need to be provided explicitly. Consider removing this `@Provides` declaration.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/LazyAssistedFactoryInjection.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @AssistedInject
4 | class Foo(factoryProvider: Lazy) {
5 | @AssistedFactory
6 | interface Factory {
7 | fun create(): Foo
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/interop-jakarta/api/interop-jakarta.api:
--------------------------------------------------------------------------------
1 | public final class dev/zacsweers/metro/interop/jakarta/JakartaInteropKt {
2 | public static final fun asJakartaProvider (Ldev/zacsweers/metro/Provider;)Ljakarta/inject/Provider;
3 | public static final fun asMetroProvider (Ljakarta/inject/Provider;)Ldev/zacsweers/metro/Provider;
4 | }
5 |
6 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/IncludedMustBeAContainer.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /IncludedMustBeAContainer.kt:(150,169): error: Included classes must be binding containers but 'SomeBindings' is not.
2 |
3 | /IncludedMustBeAContainer.kt:(240,259): error: Included classes must be binding containers but 'SomeBindings' is not.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/interop/dagger/DoNotSuggestMovingInjectAnnotationToClassWhenUsingJavaxOrJakartaInject.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /DoNotSuggestMovingInjectAnnotationToClassWhenUsingJavaxOrJakartaInject.kt:(285,292): warning: There is only one @Inject-annotated constructor. Consider moving the annotation to the class instead.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesFunctionsCannotBeTopLevel.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesFunctionsCannotBeTopLevel.kt:(150,160): error: @Provides/@Binds declarations must be within an interface, class, or companion object. If you're seeing this, `provideInt` is likely defined as a top-level method which isn't supported.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/dependencygraph/UnusedScopedBindingsInUnextendedGraphGetNoProviderFields.kt:
--------------------------------------------------------------------------------
1 | @SingleIn(AppScope::class)
2 | @DependencyGraph
3 | interface AppGraph {
4 | @Provides @SingleIn(AppScope::class) fun provideString(): String = "Hi"
5 | @Provides private fun provideInt(): Int = 3
6 |
7 | val int: Int
8 | }
--------------------------------------------------------------------------------
/interop-javax/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.jvm)
5 | alias(libs.plugins.mavenPublish)
6 | alias(libs.plugins.testkit)
7 | }
8 |
9 | dependencies {
10 | api(project(":runtime"))
11 | api(libs.javaxInject)
12 | }
13 |
--------------------------------------------------------------------------------
/metrox-viewmodel/src/commonMain/kotlin/dev/zacsweers/metrox/viewmodel/ViewModelScope.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metrox.viewmodel
4 |
5 | /** Scope marker for ViewModel-scoped dependency graphs. */
6 | public abstract class ViewModelScope private constructor()
7 |
--------------------------------------------------------------------------------
/samples/interop/customAnnotations-kotlinInject/src/commonTest/kotlin/dev/zacsweers/metro/sample/Named.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample
4 |
5 | import me.tatarka.inject.annotations.Qualifier
6 |
7 | @Qualifier annotation class Named(val value: String)
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeLocal.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | class ExampleClass
3 |
4 | fun example() {
5 | @AssistedFactory
6 | abstract class ExampleClassFactory {
7 | abstract fun create(count: Int): ExampleClass
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/BindsNonThisReturningBodiesShouldError_Interface.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | interface ExampleGraph {
4 | @Binds val String.provideCharSequence: CharSequence get() = "something else"
5 | @Binds fun Int.provideNumber(): Number = 3
6 | }
7 |
--------------------------------------------------------------------------------
/interop-jakarta/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.jvm)
5 | alias(libs.plugins.mavenPublish)
6 | alias(libs.plugins.testkit)
7 | }
8 |
9 | dependencies {
10 | api(project(":runtime"))
11 | api(libs.jakartaInject)
12 | }
13 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/BindsNonThisReturningBodiesShouldError_AbstractClass.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | abstract class ExampleGraph {
4 | @Binds val String.provideCharSequence: CharSequence get() = "something else"
5 | @Binds fun Int.provideNumber(): Number = 3
6 | }
7 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesCannotHaveReceivers_AbstractClass.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | abstract class ExampleGraph {
4 | @Provides val Long.provideInt: Int get() = this.toInt()
5 | @Provides private fun CharSequence.provideString(): String = "Hello"
6 | }
7 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesCannotHaveReceivers_Interface.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | interface ExampleGraph {
4 | @Provides val Long.provideInt: Int get() = this.toInt()
5 | @Provides private fun CharSequence.provideString(): String = this.toString()
6 | }
7 |
--------------------------------------------------------------------------------
/samples/android-app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/GraphsCanHaveExistingImplClases.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | // Some other class called Impl
4 | class Impl
5 | }
6 |
7 | fun box(): String {
8 | val graph = createGraph()
9 | assertEquals("AppGraph.Impl2", graph::class.qualifiedName)
10 | return "OK"
11 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/inject/DefaultValuesPropagateToNewInstanceParams.kt:
--------------------------------------------------------------------------------
1 | @Inject class ValueHolder(val stringValue: String? = null)
2 |
3 | @DependencyGraph
4 | interface AppGraph {
5 | val holder: ValueHolder
6 | }
7 |
8 | fun box(): String {
9 | assertNull(createGraph().holder.stringValue)
10 | return "OK"
11 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/ConflictingProvidesAndClassScopes.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | @SingleIn(AppScope::class)
3 | @Inject
4 | class Bar()
5 |
6 | @DependencyGraph
7 | interface AppGraph {
8 | val bar: Bar
9 |
10 | @Provides
11 | fun provideBar(): Bar = Bar()
12 | }
13 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/OpenAccessorsInClasses.kt:
--------------------------------------------------------------------------------
1 | abstract class Base {
2 | abstract val int: Int
3 | }
4 |
5 | @DependencyGraph
6 | abstract class AppGraph : Base() {
7 | @Provides fun provideInt(): Int = 3
8 | }
9 |
10 | fun box(): String {
11 | assertEquals(3, createGraph().int)
12 | return "OK"
13 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/provides/DefaultValuesPropagateToNewInstanceParams.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | val int: Int
4 | @Provides fun provideInt(stringValue: String? = null): Int = stringValue?.toInt() ?: 3
5 | }
6 |
7 | fun box(): String {
8 | assertEquals(3, createGraph().int)
9 | return "OK"
10 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/AbstractContainersCannotHaveProvides.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AbstractContainersCannotHaveProvides.kt:(149,159): error: Abstract binding containers cannot contain @Provides callables ('ConfusedContainer' is an interface). Either convert it to an object class or move these declarations to its companion object.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/createGraph/GraphFactoriesMayNotHaveVarargs.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /GraphFactoriesMayNotHaveVarargs.kt:(174,180): error: DependencyGraph.Factory abstract function parameters may not be vararg.
2 |
3 | /GraphFactoriesMayNotHaveVarargs.kt:(323,329): error: GraphExtension.Factory abstract function parameters may not be vararg.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesWithExtensionsAndNonThisReturningBodiesShouldError.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | abstract class ExampleGraph {
4 | @Provides val String.provideCharSequence: CharSequence get() = "hello"
5 | @Provides fun Int.provideNumber(): Number = 3
6 | }
7 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/Provides_Interface_MayNotHaveTypeParameters.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /Provides_Interface_MayNotHaveTypeParameters.kt:(105,108): error: `@Provides` declarations may not have type parameters.
2 |
3 | /Provides_Interface_MayNotHaveTypeParameters.kt:(187,190): error: `@Provides` declarations may not have type parameters.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesNamesMustBeUniqueInContainer.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @BindingContainer
4 | class ExampleBindings {
5 | @Provides fun provideNumber(): Number = 3
6 | @Provides fun provideNumber(string: String): Int = string.length
7 | }
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/interop/dagger/ModulesWithConstructorInjectedFields.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ModulesWithConstructorInjectedFields.kt:(782,804): error: Included binding container 'ProvidersModule's does not have a no-arg constructor and thus cannot be included via annotation. Add a no-arg constructor or declare it as a graph factory parameter instead.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidedInjectedClassesWithMatchingTypeKeysAreReportedAsWarnings.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidedInjectedClassesWithMatchingTypeKeysAreReportedAsWarnings.kt:(154,173): warning: Provided type 'ExampleClass' is already constructor-injected and does not need to be provided explicitly. Consider removing this `@Provides` declaration.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/Provides_AbstractClass_MayNotHaveTypeParameters.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /Provides_AbstractClass_MayNotHaveTypeParameters.kt:(110,113): error: `@Provides` declarations may not have type parameters.
2 |
3 | /Provides_AbstractClass_MayNotHaveTypeParameters.kt:(192,195): error: `@Provides` declarations may not have type parameters.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/dependencygraph/ProviderAccessorsAreTrackedInRefCounting.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | @Provides fun provideInt(): Int = 3
4 |
5 | val int1: Provider
6 | val int2: Provider
7 |
8 | @Provides fun provideLong(): Long = 3L
9 |
10 | val long1: Lazy
11 | val long2: Lazy
12 | }
--------------------------------------------------------------------------------
/samples/compose-viewmodels/app/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeSealedClasses.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int,
5 | ) {
6 | @AssistedFactory
7 | sealed class Factory {
8 | abstract fun create(count: Int): ExampleClass
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeSealedInterfaces.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int,
5 | ) {
6 | @AssistedFactory
7 | sealed interface Factory {
8 | fun create(count: Int): ExampleClass
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/cycles/SimpleBindingIntoMulti.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | val ints: Set
4 |
5 | @Provides fun provideInt(): Int = 3
6 |
7 | @Binds @IntoSet val Int.bind: Int
8 | }
9 |
10 | fun box(): String {
11 | val graph = createGraph()
12 | assertEquals(setOf(3), graph.ints)
13 | return "OK"
14 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/createGraph/CreateGraph_MustBeGraph.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /CreateGraph_MustBeGraph.kt:(127,135): error: `createGraph` type argument 'SomeType' must be annotated with a `@DependencyGraph` annotation.
2 |
3 | /CreateGraph_MustBeGraph.kt:(167,178): error: `createGraph` type argument 'SomeType' must be annotated with a `@DependencyGraph` annotation.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/optional/OptionalBindingIsNotAllowedOnInjectors.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @DependencyGraph
4 | interface AppGraph {
5 | @OptionalBinding
6 | fun inject(@OptionalBinding example: Example)
7 | }
8 |
9 | class Example {
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBePrivate.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int,
5 | ) {
6 | @AssistedFactory
7 | private fun interface Factory {
8 | fun create(count: Int): ExampleClass
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoryMustTargetAssistedInjectTypesWithMatchingParameters.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoryMustTargetAssistedInjectTypesWithMatchingParameters.kt:(83,95): error: Parameter mismatch. Assisted factory and assisted inject constructor parameters must match but found differences:
2 | Missing from factory: kotlin.String
3 |
--------------------------------------------------------------------------------
/samples/weather-app/src/jvmMain/kotlin/dev/zacsweers/metro/sample/weather/JvmAppGraph.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample.weather
4 |
5 | import dev.zacsweers.metro.AppScope
6 | import dev.zacsweers.metro.DependencyGraph
7 |
8 | @DependencyGraph(AppScope::class) interface JvmAppGraph : AppGraph
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/optional/OptionalBindingIsNotAllowedOnInjectors.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /OptionalBindingIsNotAllowedOnInjectors.kt:(125,131): error: Injector functions cannot be annotated with @OptionalBinding.
2 |
3 | /OptionalBindingIsNotAllowedOnInjectors.kt:(132,148): error: Injector function parameters cannot be annotated with @OptionalBinding.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeProtected.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int,
5 | ) {
6 | @AssistedFactory
7 | protected fun interface Factory {
8 | fun create(count: Int): ExampleClass
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoryMustTargetAssistedInjectTypesButMissingReturnType.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // Regression test for https://github.com/ZacSweers/metro/issues/364#issuecomment-2841469320
3 |
4 | @AssistedFactory
5 | fun interface ExampleClassFactory {
6 | fun create(count: Int)
7 | }
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoryWithMultipleSAMs.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoryWithMultipleSAMs.kt:(178,184): error: @AssistedFactory declarations must have exactly one abstract function but found 2.
2 |
3 | /AssistedFactoryWithMultipleSAMs.kt:(219,226): error: @AssistedFactory declarations must have exactly one abstract function but found 2.
4 |
--------------------------------------------------------------------------------
/benchmark/startup-jvm/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.jvm)
5 | alias(libs.plugins.jmh)
6 | }
7 |
8 | dependencies { jmh(project(":app:component")) }
9 |
10 | jmh {
11 | warmupIterations = 4
12 | iterations = 10
13 | fork = 2
14 | resultFormat = "JSON"
15 | }
16 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/Binds_interface_BoundTypesMustBeSubtypes.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | interface ExampleGraph {
4 | // Valid cases
5 | @Binds fun String.bind(): CharSequence
6 |
7 | // Bad cases
8 | @Binds val Number.bind: Int
9 | @Binds fun CharSequence.bind(): String
10 | }
11 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesCannotLiveInObjects.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesCannotLiveInObjects.kt:(104,117): error: @Provides declarations must be within an either a @BindingContainer-annotated class XOR interface, class, or companion object. `provideString` appears to be defined directly within a (non-companion) object that is not annotated @BindingContainer.
2 |
--------------------------------------------------------------------------------
/metrox-viewmodel-compose/api/metrox-viewmodel-compose.api:
--------------------------------------------------------------------------------
1 | public final class dev/zacsweers/metrox/viewmodel/MetroViewModelKt {
2 | public static final fun getLocalMetroViewModelFactory ()Landroidx/compose/runtime/ProvidableCompositionLocal;
3 | public static final fun requireViewModelStoreOwner (Landroidx/compose/runtime/Composer;I)Landroidx/lifecycle/ViewModelStoreOwner;
4 | }
5 |
6 |
--------------------------------------------------------------------------------
/runtime/src/commonTest/kotlin/dev/zacsweers/metro/internal/SimpleCounter.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2024 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.internal
4 |
5 | // Replicates a simple AtomicInt
6 | class SimpleCounter(var count: Int = 0) {
7 | fun incrementAndGet(): Int = ++count
8 |
9 | fun getAndIncrement(): Int = count++
10 | }
11 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/leniency/UnusedProvidersAreNotValidated.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | @Provides
4 | fun unusedString(int: Int): String {
5 | return int.toString()
6 | }
7 |
8 | @Binds val Int.unusedBinding: Number
9 | }
10 |
11 | fun box(): String {
12 | val graph = createGraph()
13 | return "OK"
14 | }
15 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/MissingBindingHintsShouldReportInternalOnlyIfInternal.fir.ir.diag.txt:
--------------------------------------------------------------------------------
1 | /module_main_MissingBindingHintsShouldReportInternalOnlyIfInternal.kt:(128,132): error: [Metro/MissingBinding] Cannot find an @Inject constructor or @Provides-annotated function/property for: Base
2 |
3 | Base is requested at
4 | [AppGraph] AppGraph.base
5 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/Binds_interface_ShouldNotHaveBodies.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // PUBLIC_PROVIDER_SEVERITY: WARN
3 | // DISABLE_TRANSFORM_PROVIDERS_TO_PRIVATE
4 |
5 | interface ExampleGraph {
6 | @Binds val Int.bind: Number get() = this
7 | @Binds fun String.bind(): CharSequence = this
8 | }
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidedInjectedClassesWithMatchingTypeKeysButDifferentScopesAreOk.kt:
--------------------------------------------------------------------------------
1 | @SingleIn(AppScope::class)
2 | @DependencyGraph
3 | interface ExampleGraph {
4 | val exampleClass: ExampleClass
5 |
6 | @Provides @SingleIn(AppScope::class) fun provideExampleClass(): ExampleClass = ExampleClass()
7 | }
8 |
9 | @Inject
10 | class ExampleClass
11 |
--------------------------------------------------------------------------------
/.idea/kotlinTestDataPluginTestDataPaths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/ConfigurableMaxIrErrors.fir.ir.diag.txt:
--------------------------------------------------------------------------------
1 | /ConfigurableMaxIrErrors.kt:(233,237): error: [Metro/MissingBinding] Cannot find an @Inject constructor or @Provides-annotated function/property for: @dev.zacsweers.metro.Named("1") kotlin.Int
2 |
3 | @dev.zacsweers.metro.Named("1") kotlin.Int is requested at
4 | [AppGraph] AppGraph#int1
5 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/visibility/InternalVisibility.kt:
--------------------------------------------------------------------------------
1 | // Test direct invocation checks for internal members in same module
2 |
3 | @Inject class InternalClass internal constructor()
4 |
5 | @DependencyGraph
6 | abstract class AppGraph {
7 | @Provides internal fun provideInt(): Int = 42
8 |
9 | abstract val int: Int
10 | abstract val internalClass: InternalClass
11 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/aggregation/InternalHintsAreNotVisibleWithoutFriends.fir.ir.diag.txt:
--------------------------------------------------------------------------------
1 | /module_main_InternalHintsAreNotVisibleWithoutFriends.kt:(123,134): error: [Metro/MissingBinding] Cannot find an @Inject constructor or @Provides-annotated function/property for: ContributedInterface
2 |
3 | ContributedInterface is requested at
4 | [AppGraph] AppGraph#contributed
5 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/AssistedTypesCannotBeDirectlyQualified.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedTypesCannotBeDirectlyQualified.kt:(104,108): error: @AssistedInject-annotated classes cannot be annotated with qualifier annotations.
2 |
3 | /AssistedTypesCannotBeDirectlyQualified.kt:(295,300): error: @AssistedInject-annotated classes cannot be annotated with qualifier annotations.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeFinal.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int,
5 | ) {
6 | @AssistedFactory
7 | class Factory {
8 | fun create(count: Int): ExampleClass {
9 | throw NotImplementedError()
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/PrivateProviderOption_Error.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // PUBLIC_PROVIDER_SEVERITY: ERROR
3 | // DISABLE_TRANSFORM_PROVIDERS_TO_PRIVATE
4 |
5 | interface ExampleGraph {
6 | @Provides val provideCharSequence: String get() = "Hello"
7 | @Provides fun provideString(): String = "Hello"
8 | }
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidedInjectedClassesWithMatchingTypeKeysAreReportedAsWarnings.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @DependencyGraph
4 | interface ExampleGraph {
5 | val exampleClass: ExampleClass
6 |
7 | @Provides fun provideExampleClass(): ExampleClass = ExampleClass()
8 | }
9 |
10 | @Inject
11 | class ExampleClass
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesNamesMustBeUniqueInGraph.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesNamesMustBeUniqueInGraph.kt:(155,168): error: Class AppGraph cannot contain multiple @Provides callables with the same name 'provideNumber'.
2 |
3 | /ProvidesNamesMustBeUniqueInGraph.kt:(199,212): error: Class AppGraph cannot contain multiple @Provides callables with the same name 'provideNumber'.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/dependencygraph/GraphImplClassAsReturnType.kt:
--------------------------------------------------------------------------------
1 | // ENABLE_GRAPH_IMPL_CLASS_AS_RETURN_TYPE
2 | @GraphExtension(String::class)
3 | interface ChildGraph {
4 | @GraphExtension.Factory @ContributesTo(AppScope::class)
5 | fun interface Factory {
6 | fun create(): ChildGraph
7 | }
8 | }
9 |
10 | @DependencyGraph(AppScope::class)
11 | interface AppGraph
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/leniency/SomeUnusedAndSomeUsed.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 | @DependencyGraph
4 | interface AppGraph {
5 | @Provides fun unusedString(int: Int): String {
6 | return int.toString()
7 | }
8 |
9 | @Binds val Int.unusedBinding: Number
10 |
11 | val number: Number
12 | }
13 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/Binds_interface_BoundTypesMustBeSubtypes.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /Binds_interface_BoundTypesMustBeSubtypes.kt:(181,185): error: Binds receiver type `kotlin.Number` is not a subtype of bound type `kotlin.Int`.
2 |
3 | /Binds_interface_BoundTypesMustBeSubtypes.kt:(217,221): error: Binds receiver type `kotlin.CharSequence` is not a subtype of bound type `kotlin.String`.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidedInjectedClassesWithMatchingTypeKeysAreREportedAsWarnings_Qualified.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidedInjectedClassesWithMatchingTypeKeysAreREportedAsWarnings_Qualified.kt:(170,189): warning: Provided type '@Named("hello") ExampleClass' is already constructor-injected and does not need to be provided explicitly. Consider removing this `@Provides` declaration.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/Provides_Interface_MayNotHaveTypeParameters.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | interface ExampleGraph {
4 | @Provides
5 | fun provideString(): String = "Hello"
6 |
7 | companion object {
8 | @Provides
9 | fun provideInt(): Int = 0
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/multibindings/MapProvidersParticipateInProviderRefcounting.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | @Provides fun provideInt(): Int = 3
4 | @Binds @IntoMap @IntKey(3) fun Int.bindInt(): Int
5 |
6 | // Int is used as a provider in both this accessor and the map, so we should refcount it
7 | val int: Provider
8 | val ints: Map>
9 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/aggregation/AnyIsAValidSupertype.kt:
--------------------------------------------------------------------------------
1 | @Inject @IntKey(3) @ContributesIntoMap(AppScope::class, binding = binding()) class Something
2 |
3 | @DependencyGraph(AppScope::class)
4 | interface AppGraph {
5 | @Multibinds val ints: Map
6 | }
7 |
8 | fun box(): String {
9 | assertTrue(createGraph().ints[3] is Something)
10 | return "OK"
11 | }
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoryMustTargetAssistedInjectTypesButMissingReturnType.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoryMustTargetAssistedInjectTypesButMissingReturnType.kt:(214,220): error: Invalid return type: kotlin.Unit. `@AssistedFactory` target classes must have a single `@AssistedInject`-annotated constructor or be annotated `@AssistedInject` with only a primary constructor.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesNamesMustBeUniqueInGraph.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @DependencyGraph
4 | interface AppGraph {
5 | val number: Number
6 | val int: Int
7 |
8 | @Provides fun provideNumber(): Number = 3
9 | @Provides fun provideNumber(string: String): Int = string.length
10 | }
11 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesShouldBePrivate_InInterface.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // PUBLIC_PROVIDER_SEVERITY: WARN
3 | // DISABLE_TRANSFORM_PROVIDERS_TO_PRIVATE
4 |
5 | interface ExampleGraph {
6 | @Provides val provideCharSequence: String get() = "Hello"
7 | @Provides fun provideString(): String = "Hello"
8 | }
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/Provides_AbstractClass_MayNotHaveTypeParameters.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | abstract class ExampleGraph {
4 | @Provides
5 | fun provideString(): String = "Hello"
6 |
7 | companion object {
8 | @Provides
9 | fun provideInt(): Int = 0
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/samples/interop/dependencies-kotlinInject/src/test/kotlin/dev/zacsweers/metro/sample/StringComponent.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample
4 |
5 | import me.tatarka.inject.annotations.Component
6 | import me.tatarka.inject.annotations.Provides
7 |
8 | @Component abstract class StringComponent(@get:Provides val message: String)
9 |
--------------------------------------------------------------------------------
/samples/weather-app/README.md:
--------------------------------------------------------------------------------
1 | Weather App
2 | ===========
3 |
4 | A simple sample weather app.
5 |
6 | To run the JVM CLI, run
7 |
8 | ```bash
9 | $ ./gradlew -p samples :weather-app:jvmRun -DmainClass=dev.zacsweers.metro.sample.weather.MainKt --quiet
10 | ```
11 |
12 | To change the supplied location, add `--args="--location New York"` to the end, replacing "New York" with your own
13 | query.
14 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/ContributedContainersMustHaveNoArgConstructors.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ContributedContainersMustHaveNoArgConstructors.kt:(132,139): error: Contributed binding container BadContainer1's no-arg constructor must be public or internal.
2 |
3 | /ContributedContainersMustHaveNoArgConstructors.kt:(211,224): error: Contributed binding containers must have a no-arg constructor.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/GraphsCannotDirectlyExtendOtherGraphs.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | // MODULE: lib
4 | @DependencyGraph
5 | interface ParentGraph {
6 | val value: Int
7 |
8 | @Provides
9 | fun provideInt(): Int = 3
10 | }
11 |
12 | // MODULE: main(lib)
13 | @DependencyGraph
14 | interface ChildGraph : ParentGraph
15 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeAnnotationObjects.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int,
5 | ) {
6 | @AssistedFactory
7 | object Factory {
8 | fun create(count: Int): ExampleClass {
9 | throw NotImplementedError()
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoryMustTargetAssistedInjectTypesButMissingConstructor.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedFactoryMustTargetAssistedInjectTypesButMissingConstructor.kt:(160,172): error: Invalid return type: ExampleClass. `@AssistedFactory` target classes must have a single `@AssistedInject`-annotated constructor or be annotated `@AssistedInject` with only a primary constructor.
2 |
--------------------------------------------------------------------------------
/interop-guice/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.jvm)
5 | alias(libs.plugins.mavenPublish)
6 | alias(libs.plugins.testkit)
7 | }
8 |
9 | dependencies {
10 | api(project(":runtime"))
11 | // Guice dropped javax.inject in 7.0
12 | api(project(":interop-jakarta"))
13 | api(libs.guice)
14 | }
15 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/BindsWithBodiesShouldBePrivate_InInterface.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // PUBLIC_PROVIDER_SEVERITY: WARN
3 | // DISABLE_TRANSFORM_PROVIDERS_TO_PRIVATE
4 |
5 | interface ExampleGraph {
6 | @Binds val String.provideCharSequence: CharSequence get() = this
7 | @Binds fun Int.provideNumber(): Number = this
8 | }
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/DaggerReusable_IsUnsupported.kt:
--------------------------------------------------------------------------------
1 | // WITH_DAGGER
2 | // RENDER_DIAGNOSTICS_FULL_TEXT
3 |
4 | import dagger.Reusable
5 |
6 | interface ExampleGraph {
7 | @Reusable
8 | @Provides
9 | fun provideInt(): Int {
10 | return 0
11 | }
12 |
13 | @Reusable
14 | @Binds
15 | val Int.bind: Number
16 | }
17 |
--------------------------------------------------------------------------------
/compiler/src/main/kotlin/dev/zacsweers/metro/compiler/graph/MissingBindingHints.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.compiler.graph
4 |
5 | internal data class MissingBindingHints>(
6 | val messages: List = emptyList(),
7 | val similarBindings: Map = emptyMap(),
8 | )
9 |
--------------------------------------------------------------------------------
/interop-dagger/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.jvm)
5 | alias(libs.plugins.mavenPublish)
6 | alias(libs.plugins.testkit)
7 | }
8 |
9 | dependencies {
10 | api(project(":runtime"))
11 | api(project(":interop-javax"))
12 | api(project(":interop-jakarta"))
13 | api(libs.dagger.runtime)
14 | }
15 |
--------------------------------------------------------------------------------
/benchmark/startup-android/benchmark/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/AbstractContainersCannotHaveProvides.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @BindingContainer
4 | interface ConfusedContainer {
5 | // This is not legal
6 | @Provides fun provideInt(): Int = 3
7 |
8 | companion object {
9 | // This is legal
10 | @Provides fun provideBoolean(): Boolean = false
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/SuggestInjectClassOnSingleContructor.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /SuggestInjectClassOnSingleContructor.kt:(90,97): warning: There is only one @Inject-annotated constructor. Consider moving the annotation to the class instead.
2 |
3 | /SuggestInjectClassOnSingleContructor.kt:(145,152): warning: There is only one @Inject-annotated constructor. Consider moving the annotation to the class instead.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesNamesMustBeUniqueInContainer.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesNamesMustBeUniqueInContainer.kt:(120,133): error: Class ExampleBindings cannot contain multiple @Provides callables with the same name 'provideNumber'.
2 |
3 | /ProvidesNamesMustBeUniqueInContainer.kt:(164,177): error: Class ExampleBindings cannot contain multiple @Provides callables with the same name 'provideNumber'.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/fir/aggregation/ContributingGraphExtensions.kt:
--------------------------------------------------------------------------------
1 | abstract class LoggedInScope
2 |
3 | @GraphExtension(LoggedInScope::class)
4 | interface LoggedInGraph {
5 | @GraphExtension.Factory @ContributesTo(AppScope::class)
6 | interface Factory {
7 | fun createLoggedInGraph(): LoggedInGraph
8 | }
9 | }
10 |
11 | @DependencyGraph(scope = AppScope::class)
12 | interface ExampleGraph
13 |
--------------------------------------------------------------------------------
/runtime/src/commonMain/kotlin/dev/zacsweers/metro/Includes.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro
4 |
5 | /**
6 | * This annotation is used on [DependencyGraph.Factory] creators to indicate that the annotated
7 | * parameter is a container of dependencies.
8 | */
9 | @Target(AnnotationTarget.VALUE_PARAMETER) public annotation class Includes
10 |
--------------------------------------------------------------------------------
/samples/interop/dependencies-kotlinInject/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.jvm)
5 | alias(libs.plugins.ksp)
6 | id("dev.zacsweers.metro")
7 | }
8 |
9 | dependencies {
10 | ksp(libs.kotlinInject.compiler)
11 | implementation(libs.kotlinInject.runtime)
12 | testImplementation(libs.kotlin.test)
13 | }
14 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/extensions/ExtensionsWithFactoriesMustUseThem.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ExtensionsWithFactoriesMustUseThem.kt:(389,402): error: Graph extension 'LoggedInGraph' has a creator type 'LoggedInGraph.Factory' that must be used to create its instances. Either make 'AppGraph' implement 'LoggedInGraph.Factory' or expose an accessor for 'LoggedInGraph.Factory' instead of 'LoggedInGraph' directly.
2 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoryMustTargetAssistedInjectTypesWithMatchingParameters.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int,
5 | @Assisted val message: String,
6 | )
7 |
8 | @AssistedFactory
9 | fun interface ExampleClassFactory {
10 | fun create(count: Int): ExampleClass
11 | }
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/BindsWithBodiesShouldBePrivate_InAbstractClass.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // PUBLIC_PROVIDER_SEVERITY: WARN
3 | // DISABLE_TRANSFORM_PROVIDERS_TO_PRIVATE
4 |
5 | abstract class ExampleGraph {
6 | @Binds val String.provideCharSequence: CharSequence get() = this
7 | @Binds fun Int.provideNumber(): Number = this
8 | }
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesMustHaveExplicitReturnTypes.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesMustHaveExplicitReturnTypes.kt:(278,291): error: Implicit return types are not allowed for `@Provides` declarations. Specify the return type explicitly.
2 |
3 | /ProvidesMustHaveExplicitReturnTypes.kt:(348,358): error: Implicit return types are not allowed for `@Provides` declarations. Specify the return type explicitly.
4 |
--------------------------------------------------------------------------------
/runtime/src/commonMain/kotlin/dev/zacsweers/metro/internal/GraphFactoryInvokeFunctionMarker.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.internal
4 |
5 | import kotlin.annotation.AnnotationTarget.FUNCTION
6 |
7 | /** Marker for generated factories indicating their invoke function. */
8 | @Target(FUNCTION) public annotation class GraphFactoryInvokeFunctionMarker
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/fir/aggregation/FirHintGenerationWorks_k22x.kt:
--------------------------------------------------------------------------------
1 | // GENERATE_CONTRIBUTION_HINTS_IN_FIR
2 | // COMPILER_VERSION: 2.2
3 |
4 | @ContributesTo(AppScope::class)
5 | interface ContributedInterface1
6 |
7 | @ContributesTo(Unit::class)
8 | interface ContributedInterface2
9 |
10 | // Repeated
11 | @ContributesTo(AppScope::class)
12 | @ContributesTo(Unit::class)
13 | interface ContributedInterface3
14 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/fir/aggregation/FirHintGenerationWorks_k23x.kt:
--------------------------------------------------------------------------------
1 | // GENERATE_CONTRIBUTION_HINTS_IN_FIR
2 | // COMPILER_VERSION: 2.3
3 |
4 | @ContributesTo(AppScope::class)
5 | interface ContributedInterface1
6 |
7 | @ContributesTo(Unit::class)
8 | interface ContributedInterface2
9 |
10 | // Repeated
11 | @ContributesTo(AppScope::class)
12 | @ContributesTo(Unit::class)
13 | interface ContributedInterface3
14 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/cycles/BindsCycleGraph.kt:
--------------------------------------------------------------------------------
1 | // DONT_SORT_DECLARATIONS
2 | interface Foo
3 |
4 | @Inject class Bar(val fooProvider: Provider) : Foo
5 |
6 | /**
7 | * A component with a cycle in which a `@Binds` binding depends on the binding that has to be
8 | * deferred.
9 | */
10 | @DependencyGraph
11 | interface BindsCycleGraph {
12 | fun bar(): Bar
13 |
14 | @Binds fun foo(bar: Bar): Foo
15 | }
--------------------------------------------------------------------------------
/compiler/src/main/kotlin/dev/zacsweers/metro/compiler/exceptions.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2024 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.compiler
4 |
5 | /** An exception that signals to end processing but assumes all errors have been reported prior. */
6 | internal class ExitProcessingException : RuntimeException()
7 |
8 | internal fun exitProcessing(): Nothing = throw ExitProcessingException()
9 |
--------------------------------------------------------------------------------
/gradle-plugin/src/main/kotlin/dev/zacsweers/metro/gradle/KotlinVersions.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.gradle
4 |
5 | import org.jetbrains.kotlin.tooling.core.KotlinToolingVersion
6 |
7 | internal object KotlinVersions {
8 | val kotlin230 = KotlinToolingVersion(2, 3, 0, null)
9 | val kotlin2320 = KotlinToolingVersion(2, 3, 20, null)
10 | }
11 |
--------------------------------------------------------------------------------
/samples/interop/customAnnotations-guice/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.jvm)
5 | id("dev.zacsweers.metro")
6 | }
7 |
8 | metro { interop { includeGuice() } }
9 |
10 | dependencies {
11 | implementation(libs.guice)
12 | implementation(libs.guice.assistedInject)
13 | testImplementation(libs.kotlin.test)
14 | }
15 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/bindingcontainers/PrivateBindsProperty.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | val message: Message
4 |
5 | // Bind MessageImpl as Message
6 | @Binds private val MessageImpl.bind: Message get() = this
7 | }
8 |
9 | interface Message
10 |
11 | @Inject
12 | class MessageImpl : Message
13 |
14 | fun box(): String {
15 | assertNotNull(createGraph().message)
16 | return "OK"
17 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/ContributedContainersMustHaveNoArgConstructors.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @ContributesTo(AppScope::class)
4 | @BindingContainer
5 | class BadContainer1 private constructor()
6 |
7 | @ContributesTo(AppScope::class)
8 | @BindingContainer
9 | class BadContainer2(private val foo: String)
10 |
11 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/IncludedMustBeAContainer.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | interface SomeBindings {
4 | @Binds val Int.bind: Number
5 | }
6 |
7 | @BindingContainer(includes = [SomeBindings::class])
8 | interface IncludingContainer
9 |
10 | @DependencyGraph(bindingContainers = [SomeBindings::class])
11 | interface AppGraph
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/BindsMayNotHaveScopes.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /BindsMayNotHaveScopes.kt:(98,124): error: @Binds declarations may not have scopes.
2 |
3 | /BindsMayNotHaveScopes.kt:(164,190): error: @Binds declarations may not have scopes.
4 |
5 | /BindsMayNotHaveScopes.kt:(271,297): error: @Binds declarations may not have scopes.
6 |
7 | /BindsMayNotHaveScopes.kt:(346,372): error: @Binds declarations may not have scopes.
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidedInjectedClassesWithMatchingTypeKeysAreREportedAsWarnings_Qualified.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @DependencyGraph
4 | interface ExampleGraph {
5 | val exampleClass: ExampleClass
6 |
7 | @Provides @Named("hello") fun provideExampleClass(): ExampleClass = ExampleClass()
8 | }
9 |
10 | @Named("hello")
11 | @Inject
12 | class ExampleClass
13 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/dependencygraph/ExtensionsAreInnerClasses.kt:
--------------------------------------------------------------------------------
1 | @GraphExtension
2 | interface LoggedInGraph {
3 | val id: String
4 | val count: Int
5 |
6 | @GraphExtension.Factory
7 | interface Factory {
8 | fun createLoggedInGraph(@Provides id: String): LoggedInGraph
9 | }
10 | }
11 |
12 | @DependencyGraph
13 | interface AppGraph : LoggedInGraph.Factory {
14 | @Provides fun provideCount(): Int = 3
15 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/graph/LazyAssistedFactoryGraphAccessor.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /LazyAssistedFactoryGraphAccessor.kt:(214,237): error: Metro does not support injecting Lazy because MyAssistedFactory is an @AssistedFactory-annotated type.
2 |
3 | /LazyAssistedFactoryGraphAccessor.kt:(265,288): error: Metro does not support injecting Lazy because MyAssistedFactory is an @AssistedFactory-annotated type.
4 |
--------------------------------------------------------------------------------
/metrox-android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
--------------------------------------------------------------------------------
/benchmark/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx8g -Dfile.encoding=UTF-8
2 | org.gradle.parallel=true
3 | org.gradle.caching=true
4 | # Included builds break KGP's annoying "fus" service
5 | org.gradle.configuration-cache=false
6 |
7 | kotlin.code.style=official
8 |
9 | # Android configuration
10 | android.useAndroidX=true
11 | android.enableJetifier=false
12 | # Enable R8 full mode for maximum optimization
13 | android.enableR8.fullMode=true
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/multibindings/MultibindingSourcesGetGettersThroughAliases.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/issues/1397
2 |
3 | abstract class Base
4 |
5 | @Inject class Foo : Base()
6 | @Inject class Bar : Base()
7 |
8 | @DependencyGraph
9 | interface AppGraph {
10 | val values: Set
11 |
12 | @Binds @IntoSet val Foo.bind: Any
13 | @Binds val Bar.bind2: Base
14 | @Binds @IntoSet val Base.bind3: Any
15 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/provides/SimpleFunctionProvider.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface ExampleGraph {
3 | val provider: Provider
4 |
5 | @Provides
6 | fun provideValue(): String = "Hello, world!"
7 | }
8 |
9 | fun box(): String {
10 | var provider = createGraph().provider
11 | assertEquals(provider.invoke(), "Hello, world!")
12 | assertEquals(provider.invoke(), "Hello, world!")
13 | return "OK"
14 | }
15 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/ContainersCannotExtendOtherContainers.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @BindingContainer
4 | interface AnotherContainer
5 |
6 | @BindingContainer
7 | interface ConfusedContainer : AnotherContainer
8 |
9 | interface Intermediate : AnotherContainer
10 |
11 | @BindingContainer
12 | interface ConfusedContainer2 : Intermediate
13 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/createGraph/CreateGraph_MustBeGraphFactory.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /CreateGraph_MustBeGraphFactory.kt:(253,276): error: `createGraphFactory` type argument 'ExampleGraphWithFactory' must be annotated with a `@DependencyGraph.Factory` annotation.
2 |
3 | /CreateGraph_MustBeGraphFactory.kt:(333,351): error: `createGraphFactory` type argument 'ExampleGraphWithFactory' must be annotated with a `@DependencyGraph.Factory` annotation.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoryWithMultipleSAMs.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int,
5 | ) {
6 | @AssistedFactory
7 | interface Factory {
8 | fun create(count: Int): ExampleClass
9 | fun create2(count: Int): ExampleClass
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/interop/dagger/DoNotSuggestMovingInjectAnnotationToClassWhenUsingJavaxOrJakartaInject.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // ENABLE_DAGGER_INTEROP
3 |
4 | // Regression test for https://github.com/ZacSweers/metro/issues/365
5 |
6 | class JavaxInject @javax.inject.Inject constructor()
7 | class JakartaInject @jakarta.inject.Inject constructor()
8 | class MetroInject @Inject constructor()
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/cycles/CycleMapGraph.kt:
--------------------------------------------------------------------------------
1 | // DONT_SORT_DECLARATIONS
2 | @Inject class X(val y: Y)
3 |
4 | @Inject
5 | class Y(
6 | val mapOfProvidersOfX: Map>,
7 | val mapOfProvidersOfY: Map>,
8 | )
9 |
10 | @DependencyGraph
11 | interface CycleMapGraph {
12 | fun y(): Y
13 |
14 | @Binds @IntoMap @StringKey("X") val X.x: X
15 |
16 | @Binds @IntoMap @StringKey("Y") val Y.y: Y
17 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/dependencygraph/UnusedInstanceBindingsInUnextendedGraphGetNoProviderFields.kt:
--------------------------------------------------------------------------------
1 | @SingleIn(AppScope::class)
2 | @DependencyGraph
3 | interface AppGraph {
4 | @Provides private fun provideInt(): Int = 3
5 |
6 | val int: Int
7 |
8 | @DependencyGraph.Factory
9 | interface Factory {
10 | fun create(
11 | // Unused in AppGraph
12 | @Provides string: String
13 | ): AppGraph
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/kotlin/dev/zacsweers/metro/compiler/KotlinTestImportPreprocessor.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.compiler
4 |
5 | import org.jetbrains.kotlin.test.services.TestServices
6 |
7 | class KotlinTestImportPreprocessor(testServices: TestServices) : ImportsPreprocessor(testServices) {
8 | override val additionalImports = setOf("kotlin.test.*")
9 | }
10 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/bindingcontainers/MultibindsOnlyInContainer.kt:
--------------------------------------------------------------------------------
1 | @BindingContainer
2 | interface MyMultibinds {
3 | @Multibinds(allowEmpty = true)
4 | val ints: Set
5 | }
6 |
7 | @DependencyGraph(bindingContainers = [MyMultibinds::class])
8 | interface AppGraph {
9 | val ints: Set
10 | }
11 |
12 | fun box(): String {
13 | val graph = createGraph()
14 | assertEquals(emptySet(), graph.ints)
15 | return "OK"
16 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/provides/JvmFieldProvidersUseFieldAccess.kt:
--------------------------------------------------------------------------------
1 | // In this scenario, generated provider factories' newInstance function gets the field directly
2 | // However, access cannot yet be directly invoked until we support inlining field access calls to
3 | // public fields
4 | @DependencyGraph
5 | abstract class AppGraph {
6 | @Provides @JvmField val stringField: String = "Hello"
7 |
8 | abstract val string: String
9 | }
10 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesShouldBePrivate_InAbstractClass.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // PUBLIC_PROVIDER_SEVERITY: WARN
3 | // DISABLE_TRANSFORM_PROVIDERS_TO_PRIVATE
4 |
5 | abstract class ExampleGraph {
6 | @Provides val provideInt: Int = 0
7 | @Provides val provideCharSequence: String get() = "Hello"
8 | @Provides fun provideString(): String = "Hello"
9 | }
10 |
--------------------------------------------------------------------------------
/scripts/generate_docs_dokka.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Generate API documentation using Dokka
4 | # This script handles the API docs generation that's shared between CI and local builds
5 |
6 | set -e
7 |
8 | echo "Generating API docs using dokka..."
9 |
10 | # Generate the API docs
11 | # --rerun-tasks because Dokka has bugs :(
12 | ./gradlew :dokkaGenerate --rerun-tasks --no-build-cache --no-configuration-cache
13 |
14 | echo "API docs generation complete!"
--------------------------------------------------------------------------------
/runtime/src/commonMain/kotlin/dev/zacsweers/metro/internal/MetroImplMarker.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.internal
4 |
5 | /**
6 | * Marker annotation for generated Metro impl classes. Useful for Metro to discover classes across
7 | * compilations.
8 | */
9 | @Target(AnnotationTarget.CLASS)
10 | @Retention(AnnotationRetention.RUNTIME)
11 | public annotation class MetroImplMarker
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/CannotIncludeGenericContainer.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @BindingContainer
4 | class SomeBindings {
5 | @Provides fun provideInt(): Int = 0
6 | }
7 |
8 | @BindingContainer(includes = [SomeBindings::class])
9 | interface IncludingContainer
10 |
11 | @DependencyGraph(bindingContainers = [SomeBindings::class])
12 | interface AppGraph
13 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/dependencygraph/MultipleRefsGetProviderFields.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | val long: Long
4 | val string: String
5 |
6 | @Provides fun provideLong(holder: IntHolder): Long = holder.int.toLong()
7 | @Provides fun provideString(holder: IntHolder): String = holder.int.toString()
8 | }
9 |
10 | // Should save a field because it's used multiple times
11 | @Inject class IntHolder {
12 | val int: Int = 3
13 | }
--------------------------------------------------------------------------------
/samples/compose-viewmodels/app/src/jvmMain/kotlin/dev/zacsweers/metro/sample/composeviewmodels/app/Graphs.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample.composeviewmodels.app
4 |
5 | import dev.zacsweers.metro.AppScope
6 | import dev.zacsweers.metro.DependencyGraph
7 | import dev.zacsweers.metrox.viewmodel.ViewModelGraph
8 |
9 | @DependencyGraph(AppScope::class) interface AppGraph : ViewModelGraph
10 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/member/SimpleAncestorInjectionWithEmptyChild.kt:
--------------------------------------------------------------------------------
1 | @HasMemberInjections
2 | abstract class Parent {
3 | @Inject
4 | var int: Int = 0
5 | }
6 |
7 | @Inject
8 | class Child : Parent()
9 |
10 | @DependencyGraph
11 | interface AppGraph {
12 | @Provides fun provideInt(): Int = 3
13 | val child: Child
14 | }
15 |
16 | fun box(): String {
17 | val graph = createGraph()
18 | assertEquals(3, graph.child.int)
19 | return "OK"
20 | }
--------------------------------------------------------------------------------
/runtime/src/commonMain/kotlin/dev/zacsweers/metro/internal/MetroContribution.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.internal
4 |
5 | import kotlin.annotation.AnnotationTarget.CLASS
6 | import kotlin.reflect.KClass
7 |
8 | /** Marker for generated nested classes for top-level declarations annotated with @Contributes_. */
9 | @Target(CLASS) public annotation class MetroContribution(val scope: KClass<*>)
10 |
--------------------------------------------------------------------------------
/samples/interop/dependencies-dagger/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.jvm)
5 | // alias(libs.plugins.kotlin.kapt)
6 | alias(libs.plugins.ksp)
7 | id("dev.zacsweers.metro")
8 | }
9 |
10 | // TODO add KSP/KAPT dual mode?
11 | dependencies {
12 | ksp(libs.dagger.compiler)
13 | implementation(libs.dagger.runtime)
14 | testImplementation(libs.kotlin.test)
15 | }
16 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/optional/RequiredAnnotationResultsInMissingBindingMultiModule.fir.ir.diag.txt:
--------------------------------------------------------------------------------
1 | /module_main_RequiredAnnotationResultsInMissingBindingMultiModule.kt:(92,100): error: [Metro/MissingBinding] Cannot find an @Inject constructor or @Provides-annotated function/property for: kotlin.String?
2 |
3 | kotlin.String? is injected at
4 | [AppGraph] Example(…, value)
5 | Example is requested at
6 | [AppGraph] AppGraph.example
7 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/kotlin/dev/zacsweers/metro/compiler/MetroDefaultImportPreprocessor.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.compiler
4 |
5 | import org.jetbrains.kotlin.test.services.TestServices
6 |
7 | class MetroDefaultImportPreprocessor(testServices: TestServices) :
8 | ImportsPreprocessor(testServices) {
9 | override val additionalImports: Set = setOf("dev.zacsweers.metro.*")
10 | }
11 |
--------------------------------------------------------------------------------
/samples/graph-analysis/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | import dev.zacsweers.metro.gradle.DelicateMetroGradleApi
4 |
5 | plugins {
6 | alias(libs.plugins.kotlin.jvm)
7 | id("dev.zacsweers.metro")
8 | }
9 |
10 | @OptIn(DelicateMetroGradleApi::class)
11 | metro { reportsDestination.set(layout.buildDirectory.dir("reports/metro")) }
12 |
13 | kotlin { compilerOptions { optIn.add("kotlin.time.ExperimentalTime") } }
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Ask for help
4 | url: https://github.com/ZacSweers/metro/discussions/new?category=q-a
5 | about: If you have a usage or debugging question, please use the Q&A feature of the repo's Discussions section.
6 | - name: Create an issue without template
7 | url: https://github.com/ZacSweers/metro/issues/new?template=Blank+issue
8 | about: This option is only available for repository maintainers.
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/cycles/SelfCycle.kt:
--------------------------------------------------------------------------------
1 | @Suppress("MEMBERS_INJECT_WARNING")
2 | @Inject
3 | class S(val sProvider: Provider) {
4 | @Inject lateinit var sLazy: Lazy
5 | }
6 |
7 | @DependencyGraph
8 | interface SelfCycleGraph {
9 | fun s(): S
10 | }
11 |
12 | fun box(): String {
13 | val selfCycleGraph = createGraph()
14 | val s = selfCycleGraph.s()
15 | assertNotNull(s.sProvider())
16 | assertNotNull(s.sLazy.value)
17 | return "OK"
18 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/optional/OptionalBindingParamWarningIfDefault.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @DependencyGraph
4 | interface AppGraph {
5 | @Provides
6 | fun provideString(@OptionalBinding value: Int = 3): String = value.toString()
7 | }
8 |
9 | @Inject
10 | class Example(@OptionalBinding val value: Int = 3)
11 |
--------------------------------------------------------------------------------
/compiler/src/main/kotlin/dev/zacsweers/metro/compiler/OptionalBindingBehavior.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.compiler
4 |
5 | /** See the analogous type in the Gradle plugin. */
6 | public enum class OptionalBindingBehavior {
7 | DISABLED,
8 | DEFAULT,
9 | REQUIRE_OPTIONAL_BINDING;
10 |
11 | internal val requiresAnnotatedParameters: Boolean
12 | get() = this == REQUIRE_OPTIONAL_BINDING
13 | }
14 |
--------------------------------------------------------------------------------
/interop-dagger/api/interop-dagger.api:
--------------------------------------------------------------------------------
1 | public final class dev/zacsweers/metro/interop/dagger/DaggerInteropKt {
2 | public static final fun asDaggerLazy (Lkotlin/Lazy;)Ldagger/Lazy;
3 | public static final fun asDaggerMembersInjector (Ldev/zacsweers/metro/MembersInjector;)Ldagger/MembersInjector;
4 | public static final fun asKotlinLazy (Ldagger/Lazy;)Lkotlin/Lazy;
5 | public static final fun asMetroMembersInjector (Ldagger/MembersInjector;)Ldev/zacsweers/metro/MembersInjector;
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/generator220/kotlin/dev/zacsweers/metro/compiler/MetroKotlinStandardLibrariesPathProvider.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.compiler
4 |
5 | import org.jetbrains.kotlin.test.services.KotlinStandardLibrariesPathProvider
6 |
7 | // KotlinStandardLibrariesPathProvider was changed to an interface in 2.3.20
8 | abstract class MetroKotlinStandardLibrariesPathProvider : KotlinStandardLibrariesPathProvider()
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/generator230/kotlin/dev/zacsweers/metro/compiler/MetroKotlinStandardLibrariesPathProvider.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.compiler
4 |
5 | import org.jetbrains.kotlin.test.services.KotlinStandardLibrariesPathProvider
6 |
7 | // KotlinStandardLibrariesPathProvider was changed to an interface in 2.3.20
8 | abstract class MetroKotlinStandardLibrariesPathProvider : KotlinStandardLibrariesPathProvider()
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/generator2320/kotlin/dev/zacsweers/metro/compiler/MetroKotlinStandardLibrariesPathProvider.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.compiler
4 |
5 | import org.jetbrains.kotlin.test.services.KotlinStandardLibrariesPathProvider
6 |
7 | // KotlinStandardLibrariesPathProvider was changed to an interface in 2.3.20
8 | abstract class MetroKotlinStandardLibrariesPathProvider : KotlinStandardLibrariesPathProvider
9 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/aggregation/InternalContributionMissingHint.fir.ir.diag.txt:
--------------------------------------------------------------------------------
1 | /module_main_InternalContributionMissingHint.kt:(129,132): error: [Metro/MissingBinding] Cannot find an @Inject constructor or @Provides-annotated function/property for: Foo
2 |
3 | Foo is requested at
4 | [AppGraph] AppGraph#foo
5 |
6 | Similar bindings:
7 | - Foo (Contributed by 'FooImpl' but that class is internal to its module and its module is not a friend module to this one.)
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/dependencygraph/LazyPropertiesHaveDeterministicOrder.kt:
--------------------------------------------------------------------------------
1 | // DONT_SORT_DECLARATIONS
2 | @DependencyGraph
3 | interface AppGraph {
4 | @Provides fun provideInt(): Int = 3
5 | @Binds @IntoSet fun Int.bindInt(): Int
6 | @Provides @IntoSet fun bindLong(int: Int): Long = int.toLong()
7 | @Provides @IntoSet fun bindDouble(int: Int): Double = int.toDouble()
8 |
9 | val intSet: Set
10 | val doubleSet: Set
11 | val longSet: Set
12 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/dependencygraph/OptionalBindingsHaveValidFieldNames.kt:
--------------------------------------------------------------------------------
1 | // ENABLE_DAGGER_INTEROP
2 | import java.util.Optional
3 |
4 | @DependencyGraph(AppScope::class, bindingContainers = [Bindings::class])
5 | interface AppGraph {
6 | val optional: Optional
7 |
8 | @Provides @SingleIn(AppScope::class) val string: String get() = "Hello"
9 | }
10 |
11 | @dagger.Module
12 | interface Bindings {
13 | @dagger.BindsOptionalOf
14 | fun string(): String
15 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/AssistedTypesCannotBeProvidedWithoutQualifiers.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /AssistedTypesCannotBeProvidedWithoutQualifiers.kt:(262,266): error: [Metro/InvalidBinding] 'Taco' uses assisted injection and cannot be injected directly into 'test.ExampleGraph.exampleClass'. You must inject a corresponding @AssistedFactory type or provide a qualified instance on the graph instead.
2 |
3 | (Hint)
4 | It looks like the @AssistedFactory for 'Taco' may be 'Taco.Factory'.
5 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/assisted/AssistedFactoriesCannotBeEnums.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int,
5 | ) {
6 | @AssistedFactory
7 | enum class Factory {
8 | INSTANCE {
9 | override fun create(count: Int): ExampleClass {
10 | throw NotImplementedError()
11 | }
12 | };
13 | abstract fun create(count: Int): ExampleClass
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/DaggerReusable_IsUnsupported.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /DaggerReusable_IsUnsupported.kt:(128,137): error: Dagger's `@Reusable` is not supported in Metro. See https://zacsweers.github.io/metro/latest/faq#why-doesnt-metro-support-reusable for more information.
2 |
3 | /DaggerReusable_IsUnsupported.kt:(196,205): error: Dagger's `@Reusable` is not supported in Metro. See https://zacsweers.github.io/metro/latest/faq#why-doesnt-metro-support-reusable for more information.
4 |
--------------------------------------------------------------------------------
/runtime/src/commonMain/kotlin/dev/zacsweers/metro/internal/InjectedFunctionClass.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.internal
4 |
5 | import kotlin.annotation.AnnotationTarget.CLASS
6 | import kotlin.annotation.AnnotationTarget.PROPERTY
7 |
8 | /** Marker for generated class wrappers for injected top level functions. */
9 | @Target(CLASS, PROPERTY) public annotation class InjectedFunctionClass(val callableName: String)
10 |
--------------------------------------------------------------------------------
/samples/interop/customAnnotations-dagger/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.jvm)
5 | id("dev.zacsweers.metro")
6 | }
7 |
8 | metro {
9 | interop {
10 | includeDagger()
11 | includeAnvilForDagger()
12 | }
13 | }
14 |
15 | dependencies {
16 | implementation(libs.anvil.annotations)
17 | implementation(libs.dagger.runtime)
18 | testImplementation(libs.kotlin.test)
19 | }
20 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/GraphFactoriesSupportGenericProviders.kt:
--------------------------------------------------------------------------------
1 | interface BaseFactory {
2 | fun create(@Provides value: T): R
3 | }
4 |
5 | @DependencyGraph
6 | interface ExampleGraph {
7 | val value: Int
8 |
9 | @DependencyGraph.Factory
10 | interface Factory : BaseFactory
11 | }
12 |
13 | fun box(): String {
14 | val graph = createGraphFactory().create(3)
15 | assertEquals(graph.value, 3)
16 | return "OK"
17 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/createGraph/CreateGraph_GraphHasFactory.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /CreateGraph_GraphHasFactory.kt:(262,285): error: `createGraph` type argument 'ExampleGraphWithFactory' has a factory at 'ExampleGraphWithFactory.Factory'. Use `createGraphFactory` with that type instead.
2 |
3 | /CreateGraph_GraphHasFactory.kt:(336,347): error: `createGraph` type argument 'ExampleGraphWithFactory' has a factory at 'ExampleGraphWithFactory.Factory'. Use `createGraphFactory` with that type instead.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/dependencygraph/GraphAccessors.kt:
--------------------------------------------------------------------------------
1 | // Golden image test to ensure we don't generate unnecessary wrapping providers over accessors
2 | interface Accessors {
3 | val string: String
4 | val intProvider: Provider
5 | }
6 |
7 | @DependencyGraph
8 | interface ExampleGraph {
9 | val string: String
10 | val int: Int
11 |
12 | @DependencyGraph.Factory
13 | interface Factory {
14 | fun create(@Includes accessors: Accessors): ExampleGraph
15 | }
16 | }
--------------------------------------------------------------------------------
/metrox-android/src/main/kotlin/dev/zacsweers/metrox/android/ServiceKey.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metrox.android
4 |
5 | import android.app.Service
6 | import dev.zacsweers.metro.MapKey
7 | import kotlin.reflect.KClass
8 |
9 | /** A [MapKey] annotation for binding a Service in a multibinding map. */
10 | @MapKey
11 | @Target(AnnotationTarget.CLASS)
12 | public annotation class ServiceKey(val value: KClass)
13 |
--------------------------------------------------------------------------------
/samples/interop/dependencies-dagger/src/test/kotlin/dev/zacsweers/metro/sample/StringComponent.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample
4 |
5 | import dagger.BindsInstance
6 | import dagger.Component
7 |
8 | @Component
9 | interface StringComponent {
10 | val message: String
11 |
12 | @Component.Factory
13 | interface Factory {
14 | fun create(@BindsInstance message: String): StringComponent
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/ContainersCannotExtendOtherContainers.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ContainersCannotExtendOtherContainers.kt:(156,172): error: Binding containers cannot extend other binding containers, use `includes` instead. Container 'ConfusedContainer' extends 'AnotherContainer'.
2 |
3 | /ContainersCannotExtendOtherContainers.kt:(245,263): error: Binding containers cannot extend other binding containers, use `includes` instead. Container 'ConfusedContainer2' extends 'AnotherContainer'.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/optional/DisabledResultsInMissingBindings.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 | // OPTIONAL_DEPENDENCY_BEHAVIOR: DISABLED
4 |
5 | @Inject
6 | class Example(val value: String? = null)
7 |
8 | @DependencyGraph
9 | interface AppGraph {
10 | val example: Example
11 | val int: Int
12 |
13 | @Provides
14 | fun provideInt(long: Long? = null): Int = long?.toInt() ?: 3
15 | }
16 |
--------------------------------------------------------------------------------
/metrox-android/src/main/kotlin/dev/zacsweers/metrox/android/ActivityKey.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metrox.android
4 |
5 | import android.app.Activity
6 | import dev.zacsweers.metro.MapKey
7 | import kotlin.reflect.KClass
8 |
9 | /** A [MapKey] annotation for binding an Activity in a multibinding map. */
10 | @MapKey
11 | @Target(AnnotationTarget.CLASS)
12 | public annotation class ActivityKey(val value: KClass)
13 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/createGraph/CreateGraph_GraphHasFactory.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @DependencyGraph
4 | interface ExampleGraphWithFactory {
5 | @DependencyGraph.Factory
6 | interface Factory {
7 | fun create(): ExampleGraphWithFactory
8 | }
9 | }
10 |
11 | fun example() {
12 | val exampleGraph = createGraph<ExampleGraphWithFactory>()
13 | val exampleGraph2: ExampleGraphWithFactory = createGraph()
14 | }
15 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/createGraph/CreateGraph_MustBeGraphFactory.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @DependencyGraph
4 | interface ExampleGraphWithFactory {
5 | interface Factory {
6 | fun create(): ExampleGraphWithFactory
7 | }
8 | }
9 |
10 | fun example() {
11 | val exampleGraphWithFactory = createGraphFactory<ExampleGraphWithFactory>()
12 | val exampleGraphFactory: ExampleGraphWithFactory = createGraphFactory()
13 | }
14 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/aggregation/InternalContributionMissingHint.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 | // https://github.com/ZacSweers/metro/issues/887
4 |
5 | // MODULE: lib1
6 | interface Foo
7 |
8 | // MODULE: lib2(lib1)
9 | @ContributesBinding(AppScope::class)
10 | @Inject
11 | internal class FooImpl : Foo
12 |
13 | // MODULE: main(lib1 lib2)
14 | @DependencyGraph(AppScope::class)
15 | interface AppGraph {
16 | val foo: Foo
17 | }
18 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/optional/OptionalBindingErrorIfDisabled.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // OPTIONAL_DEPENDENCY_BEHAVIOR: DISABLED
3 |
4 | @DependencyGraph
5 | interface AppGraph {
6 | @Provides
7 | fun provideString(@OptionalBinding value: Int = 3): String = value.toString()
8 | }
9 |
10 | @Inject
11 | class Example(@OptionalBinding val value: Int = 3)
12 |
--------------------------------------------------------------------------------
/runtime/src/commonMain/kotlin/dev/zacsweers/metro/internal/AssistedMarker.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.internal
4 |
5 | /**
6 | * Marker annotation for generated assisted inject factory classes. This is used internally by Metro
7 | * to denote factories that were generated for assisted-injected types.
8 | */
9 | @Target(AnnotationTarget.CLASS)
10 | @Retention(AnnotationRetention.RUNTIME)
11 | public annotation class AssistedMarker
12 |
--------------------------------------------------------------------------------
/samples/interop/dependencies-dagger/src/test/kotlin/dev/zacsweers/metro/sample/StringGraph.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample
4 |
5 | import dev.zacsweers.metro.DependencyGraph
6 | import dev.zacsweers.metro.Provides
7 |
8 | @DependencyGraph
9 | interface StringGraph {
10 | val message: String
11 |
12 | @DependencyGraph.Factory
13 | interface Factory {
14 | fun create(@Provides message: String): StringGraph
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/AllDuplicateBindingsAreReported.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 |
4 | @DependencyGraph
5 | interface AppGraph {
6 | @Provides fun provideString1(): String = "1"
7 | @Provides fun provideString2(): String = "2"
8 | @Provides fun provideString3(): String = "3"
9 | @Provides fun provideString4(): String = "4"
10 | @Provides fun provideString5(): String = "5"
11 | }
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/optional/DisabledResultsInMissingBindingsEvenWithAnnotation.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 | // OPTIONAL_DEPENDENCY_BEHAVIOR: DISABLED
4 |
5 | @Inject
6 | class Example(val value: String? = null)
7 |
8 | @DependencyGraph
9 | interface AppGraph {
10 | val example: Example
11 | val int: Int
12 |
13 | @Provides
14 | fun provideInt(long: Long? = null): Int = long?.toInt() ?: 3
15 | }
16 |
--------------------------------------------------------------------------------
/samples/interop/dependencies-kotlinInject/src/test/kotlin/dev/zacsweers/metro/sample/StringGraph.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample
4 |
5 | import dev.zacsweers.metro.DependencyGraph
6 | import dev.zacsweers.metro.Provides
7 |
8 | @DependencyGraph
9 | interface StringGraph {
10 | val message: String
11 |
12 | @DependencyGraph.Factory
13 | interface Factory {
14 | fun create(@Provides message: String): StringGraph
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/compiler-compat/version-aliases.txt:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2025 Zac Sweers
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # Kotlin compiler versions to test against in CI
5 | #
6 | # This file must be an equal or superset of the available compiler-compat modules.
7 | # Each line is a Kotlin version that has a corresponding k* module.
8 | # Blank lines and comments (starting with #) are ignored.
9 |
10 | 2.2.20
11 | 2.2.21
12 | 2.3.0-Beta1
13 | 2.3.0-Beta2
14 | 2.3.0-RC
15 | 2.3.0-RC2
16 | 2.3.0-RC3
17 | 2.3.0
18 | 2.3.20-dev-5437
19 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/inject/InjectedTypeInheritsAnAnnotatedAbstractClass.kt:
--------------------------------------------------------------------------------
1 | // Regression test for https://github.com/ZacSweers/metro/pull/1454
2 | @DependencyGraph
3 | interface AppGraph {
4 | val foo: FooImpl
5 | }
6 |
7 | @Inject
8 | class FooImpl: Foo()
9 |
10 | @AmazingApi
11 | abstract class Foo {
12 | val value = "foo"
13 | }
14 |
15 | annotation class AmazingApi
16 |
17 | fun box(): String {
18 | val appGraph = createGraph()
19 | assertSame(appGraph.foo.value, "foo")
20 | return "OK"
21 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/AssistedTypesCannotBeProvidedWithoutQualifiers.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @AssistedInject
4 | class Taco(@Assisted val seasoning: String) {
5 | @AssistedFactory
6 | interface Factory {
7 | fun create(seasoning: String): Taco
8 | }
9 | }
10 |
11 | @DependencyGraph
12 | interface AppGraph {
13 | val taco: Taco
14 |
15 | @Provides
16 | fun provideTaco(factory: Taco.Factory): Taco = factory.create("spicy")
17 | }
18 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/SuggestInjectClassOnSingleContructor.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | class SingleEmptyConstructor @Inject constructor()
3 |
4 | class SingleNonEmptyConstructor @Inject constructor(int: Int)
5 |
6 | class InjectPrimaryConstructor @Inject constructor(int: Int) {
7 | constructor() : this(0)
8 | }
9 |
10 | class InjectSecondaryConstructor internal constructor(int: Int) {
11 | @Inject constructor() : this(0)
12 | }
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/build
2 | **/.idea/*
3 | !.idea/externalDependencies.xml
4 | !.idea/kotlinTestDataPluginTestDataPaths.xml
5 | .gradle
6 | .kotlin/
7 | .iml
8 | .project
9 | .classpath
10 | *.iml
11 | local.properties
12 | .DS_Store
13 |
14 | gradle-plugin/docs/
15 | docs/code-of-conduct.md
16 | docs/contributing.md
17 | docs/changelog.md
18 | docs/samples.md
19 | docs/metrox-android.md
20 | docs/metrox-viewmodel.md
21 | docs/metrox-viewmodel-compose.md
22 | docs/api/
23 | site/
24 | temp-clone/
25 | /benchmark/
26 | .cache/
27 | tmp/
28 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/ProvidingEmptyProviderMapDirectly.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/issues/1069
2 | @Inject class MyIntUser(val ints: Map>)
3 |
4 | @DependencyGraph
5 | interface AppGraph {
6 | val user: MyIntUser
7 |
8 | @Provides fun provideSomeMap(): Map> = emptyMap()
9 | }
10 |
11 | fun box(): String {
12 | val graph = createGraph()
13 | val user = graph.user
14 | assertTrue(user.ints.isEmpty())
15 | return "OK"
16 | }
17 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/member/SimpleAncestorInjectionWithEmptyChildNoFactory.kt:
--------------------------------------------------------------------------------
1 | @HasMemberInjections
2 | abstract class Parent {
3 | @Inject
4 | var int: Int = 0
5 | }
6 |
7 | class Child : Parent()
8 |
9 | @DependencyGraph
10 | interface AppGraph {
11 | @Provides fun provideInt(): Int = 3
12 |
13 | fun inject(child: Child)
14 | }
15 |
16 | fun box(): String {
17 | val graph = createGraph()
18 | val child = Child()
19 | graph.inject(child)
20 | assertEquals(3, child.int)
21 | return "OK"
22 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/optional/RequiredAnnotationResultsInMissingBindings.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 | // OPTIONAL_DEPENDENCY_BEHAVIOR: REQUIRE_OPTIONAL_BINDING
4 |
5 | @Inject
6 | class Example(val value: String? = null)
7 |
8 | @DependencyGraph
9 | interface AppGraph {
10 | val example: Example
11 | val int: Int
12 |
13 | @Provides
14 | fun provideInt(long: Long? = null): Int = long?.toInt() ?: 3
15 | }
16 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/BindsNonThisReturningBodiesShouldError_Interface.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /BindsNonThisReturningBodiesShouldError_Interface.kt:(107,126): error: `@Binds` declarations with bodies should just return `this`. See https://zacsweers.github.io/metro/latest/bindings/#binds for more information.
2 |
3 | /BindsNonThisReturningBodiesShouldError_Interface.kt:(183,196): error: `@Binds` declarations with bodies should just return `this`. See https://zacsweers.github.io/metro/latest/bindings/#binds for more information.
4 |
--------------------------------------------------------------------------------
/samples/compose-viewmodels/app/src/commonMain/kotlin/dev/zacsweers/metro/sample/composeviewmodels/app/Routes.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample.composeviewmodels.app
4 |
5 | import kotlinx.serialization.Serializable
6 |
7 | sealed interface Route
8 |
9 | @Serializable data object HomeRoute : Route
10 |
11 | @Serializable data class DetailsRoute(val data: String) : Route
12 |
13 | @Serializable data class SettingsRoute(val userId: String) : Route
14 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/leniency/UnusedProvidersInContainersAreNotValidated.kt:
--------------------------------------------------------------------------------
1 | @BindingContainer
2 | abstract class Bindings {
3 | @Binds abstract val Int.unusedBinding: Number
4 |
5 | companion object {
6 | @Provides
7 | fun unusedString(int: Int): String {
8 | return int.toString()
9 | }
10 | }
11 | }
12 |
13 | @DependencyGraph(bindingContainers = [Bindings::class]) interface AppGraph
14 |
15 | fun box(): String {
16 | val graph = createGraph()
17 | return "OK"
18 | }
19 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/inject/member/MultiInheritanceMemberInject.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/issues/649
2 |
3 | @Inject class Foo
4 |
5 | @Inject class Bar
6 |
7 | @HasMemberInjections
8 | open class Parent {
9 | @Inject lateinit var foo: Foo
10 | }
11 |
12 | class Child : Parent() {
13 | @Inject lateinit var bar: Bar
14 | }
15 |
16 | @DependencyGraph(AppScope::class)
17 | interface TestGraph {
18 | fun inject(target: Child)
19 | }
20 |
21 | fun box(): String {
22 | // TODO()
23 | return "OK"
24 | }
25 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/interop/dagger/DaggerFactoryClassCanBeLoaded.kt:
--------------------------------------------------------------------------------
1 | // ENABLE_DAGGER_KSP
2 |
3 | // FILE: ExampleClass.java
4 | import javax.inject.Inject;
5 |
6 | public class ExampleClass {
7 | @Inject public ExampleClass() {
8 |
9 | }
10 | }
11 |
12 | // FILE: ExampleGraph.kt
13 | @DependencyGraph
14 | interface ExampleGraph {
15 | val exampleClass: ExampleClass
16 | }
17 |
18 | fun box(): String {
19 | val graph = createGraph()
20 | assertNotNull(graph.exampleClass)
21 | return "OK"
22 | }
23 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/CannotIncludeGenericContainer.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /CannotIncludeGenericContainer.kt:(175,194): error: Included binding container 'SomeBindings' is generic and thus cannot be included via annotation. Remove its generics or declare it as a graph factory parameter instead.
2 |
3 | /CannotIncludeGenericContainer.kt:(265,284): error: Included binding container 'SomeBindings' is generic and thus cannot be included via annotation. Remove its generics or declare it as a graph factory parameter instead.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/optional/OptionalBindingParamRequiresDefaultValue.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // OPTIONAL_DEPENDENCY_BEHAVIOR: REQUIRE_OPTIONAL_BINDING
3 |
4 | @DependencyGraph
5 | interface AppGraph {
6 | @Provides
7 | fun provideString(@OptionalBinding value: Int): String = value.toString()
8 | }
9 |
10 | @Inject
11 | class Example(@OptionalBinding val value: Int)
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/member/SimpleAncestorInjectionWithEmptyChildWithParentInAnotherModule.kt:
--------------------------------------------------------------------------------
1 | // MODULE: lib
2 | @HasMemberInjections
3 | abstract class Parent {
4 | @Inject
5 | var int: Int = 0
6 | }
7 |
8 | // MODULE: main(lib)
9 | @Inject
10 | class Child : Parent()
11 |
12 | @DependencyGraph
13 | interface AppGraph {
14 | @Provides fun provideInt(): Int = 3
15 | val child: Child
16 | }
17 |
18 | fun box(): String {
19 | val graph = createGraph()
20 | assertEquals(3, graph.child.int)
21 | return "OK"
22 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/InternalBindings.fir.ir.diag.txt:
--------------------------------------------------------------------------------
1 | /module_main_InternalBindings.kt:(154,162): error: [Metro/MissingBinding] Cannot find an @Inject constructor or @Provides-annotated function/property for: SomeRepository
2 |
3 | SomeRepository is requested at
4 | [AppGraph.Impl.LoggedInGraphImpl] LoggedInGraph.someRepository
5 |
6 | Similar bindings:
7 | - SomeRepository (Contributed by 'SomeRepositoryImpl' but that class is internal to its module and its module is not a friend module to this one.)
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/MultipleMissingDeps.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 |
4 | // Specifically a regression to make sure we don't duplicate "requestedAt" calls
5 |
6 | class Foo1
7 | class Foo2
8 | class Foo3
9 |
10 | @Inject
11 | class InjectedThing(
12 | foo1: Foo1,
13 | foo2: Foo2,
14 | foo3: Foo3,
15 | )
16 |
17 | @DependencyGraph
18 | interface AppGraph {
19 | val injectedThing: InjectedThing
20 | }
21 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/leniency/SomeUnusedAndSomeUsed.fir.ir.diag.txt:
--------------------------------------------------------------------------------
1 | /SomeUnusedAndSomeUsed.kt:(226,229): error: [Metro/MissingBinding] Cannot find an @Inject constructor or @Provides-annotated function/property for: kotlin.Int
2 |
3 | kotlin.Int is injected at
4 | [AppGraph] AppGraph#(…, )
5 | kotlin.Number is requested at
6 | [AppGraph] AppGraph#number
7 |
8 | Similar bindings:
9 | - Number (Supertype). Type: Alias. Source: SomeUnusedAndSomeUsed.kt:10:3
10 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/member/MissingMemberInjectionShouldFailBinding1.fir.ir.diag.txt:
--------------------------------------------------------------------------------
1 | /MissingMemberInjectionShouldFailBinding1.kt:(702,726): error: [Metro/MissingBinding] Cannot find an @Inject constructor or @Provides-annotated function/property for: Implementation
2 |
3 | Implementation is injected at
4 | [TestGraph.$$ContributedSubscopeGraph] SubscopeGraph#bindImplementation(…, instance)
5 |
6 | Similar bindings:
7 | - Base (Supertype). Type: Alias. Source: MissingMemberInjectionShouldFailBinding1.kt:28:3
8 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/member/MissingMemberInjectionShouldFailBinding2.fir.ir.diag.txt:
--------------------------------------------------------------------------------
1 | /MissingMemberInjectionShouldFailBinding2.kt:(505,559): error: [Metro/MissingBinding] Cannot find an @Inject constructor or @Provides-annotated function/property for: dev.zacsweers.metro.MembersInjector
2 |
3 | dev.zacsweers.metro.MembersInjector is injected at
4 | [TestGraph.$$ContributedSubscopeGraph] SubscopeMultibindingModule#bindClassWithoutMembersInjector(…, instance)
5 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/dependencygraph/MapBuildersUseInlineInstantiation.kt:
--------------------------------------------------------------------------------
1 | // DISABLE_TRANSFORM_PROVIDERS_TO_PRIVATE
2 |
3 | interface IntHolder
4 |
5 | @Inject
6 | @IntKey(3)
7 | @ContributesIntoMap(AppScope::class)
8 | class IntHolderImpl : IntHolder
9 |
10 | @DependencyGraph(AppScope::class)
11 | interface AppGraph {
12 | val ints: Map
13 | val intHolder: Map
14 |
15 | @Provides @IntKey(1) @IntoMap fun provideInt1(): Int = 1
16 | @Provides @IntKey(2) @IntoMap fun provideInt2(): Int = 2
17 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/interop/dagger/DaggerFactoryClassCanBeLoadedJakarta.kt:
--------------------------------------------------------------------------------
1 | // ENABLE_DAGGER_KSP
2 |
3 | // FILE: ExampleClass.java
4 | import jakarta.inject.Inject;
5 |
6 | public class ExampleClass {
7 | @Inject public ExampleClass() {
8 |
9 | }
10 | }
11 |
12 | // FILE: ExampleGraph.kt
13 | @DependencyGraph
14 | interface ExampleGraph {
15 | val exampleClass: ExampleClass
16 | }
17 |
18 | fun box(): String {
19 | val graph = createGraph()
20 | assertNotNull(graph.exampleClass)
21 | return "OK"
22 | }
23 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/BindsNonThisReturningBodiesShouldError_AbstractClass.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /BindsNonThisReturningBodiesShouldError_AbstractClass.kt:(112,131): error: `@Binds` declarations with bodies should just return `this`. See https://zacsweers.github.io/metro/latest/bindings/#binds for more information.
2 |
3 | /BindsNonThisReturningBodiesShouldError_AbstractClass.kt:(188,201): error: `@Binds` declarations with bodies should just return `this`. See https://zacsweers.github.io/metro/latest/bindings/#binds for more information.
4 |
--------------------------------------------------------------------------------
/gradle-plugin/src/main/kotlin/dev/zacsweers/metro/gradle/metroGradleUtil.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.gradle
4 |
5 | import java.util.Locale
6 | import org.gradle.api.Project
7 |
8 | internal fun String.capitalizeUS() = replaceFirstChar {
9 | if (it.isLowerCase()) it.titlecase(Locale.US) else it.toString()
10 | }
11 |
12 | internal val Project.logVerbosely: Boolean
13 | get() {
14 | return providers.gradleProperty("metro.logVerbosely").isPresent
15 | }
16 |
--------------------------------------------------------------------------------
/samples/android-app/src/main/kotlin/dev/zacsweers/metro/sample/android/FragmentKey.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample.android
4 |
5 | import androidx.fragment.app.Fragment
6 | import dev.zacsweers.metro.MapKey
7 | import kotlin.reflect.KClass
8 |
9 | /** A [MapKey] annotation for binding Fragments in a multibinding map. */
10 | @MapKey
11 | @Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
12 | annotation class FragmentKey(val value: KClass)
13 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesCannotHaveReceivers_Interface.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesCannotHaveReceivers_Interface.kt:(108,118): error: `@Provides` properties may not be extension properties. Use `@Binds` instead for these. See https://zacsweers.github.io/metro/latest/bindings/#binds for more information.
2 |
3 | /ProvidesCannotHaveReceivers_Interface.kt:(182,195): error: `@Provides` functions may not be extension functions. Use `@Binds` instead for these. See https://zacsweers.github.io/metro/latest/bindings/#binds for more information.
4 |
--------------------------------------------------------------------------------
/metrox-android/src/main/kotlin/dev/zacsweers/metrox/android/BroadcastReceiverKey.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metrox.android
4 |
5 | import android.content.BroadcastReceiver
6 | import dev.zacsweers.metro.MapKey
7 | import kotlin.reflect.KClass
8 |
9 | /** A [MapKey] annotation for binding a BroadcastReceiver in a multibinding map. */
10 | @MapKey
11 | @Target(AnnotationTarget.CLASS)
12 | public annotation class BroadcastReceiverKey(val value: KClass)
13 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/createGraph/GraphFactoriesMayNotHaveVarargs.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @DependencyGraph
4 | interface AppGraph {
5 | @DependencyGraph.Factory
6 | interface Factory {
7 | fun create(@Provides vararg args: String): AppGraph
8 | }
9 | }
10 |
11 | @GraphExtension
12 | interface UnitGraph {
13 | @GraphExtension.Factory
14 | interface Factory {
15 | fun create(@Provides vararg args: String): UnitGraph
16 | }
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/dynamic/CreateDynamicGraphCannotBeInLocalClasses.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /CreateDynamicGraphCannotBeInLocalClasses.kt:(389,442): error: `createDynamicGraphFactory` can only be called from a top-level function or concrete class (non-anonymous, non-local). Containing class 'Local' is a local class.
2 |
3 | /CreateDynamicGraphCannotBeInLocalClasses.kt:(522,575): error: `createDynamicGraphFactory` can only be called from a top-level function or concrete class (non-anonymous, non-local). This call is inside an anonymous object.
4 |
--------------------------------------------------------------------------------
/runtime/src/commonMain/kotlin/dev/zacsweers/metro/internal/MultibindingElement.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.internal
4 |
5 | import dev.zacsweers.metro.Qualifier
6 |
7 | /**
8 | * Disambiguates between multiple elements of the same type in a set. Inspired by Guice.
9 | *
10 | * @param bindingId The ID of the set.
11 | * @param elementId The ID of the element.
12 | */
13 | @Qualifier public annotation class MultibindingElement(val bindingId: String, val elementId: String)
14 |
--------------------------------------------------------------------------------
/samples/compose-viewmodels/app/src/jvmMain/kotlin/dev/zacsweers/metro/sample/composeviewmodels/app/Main.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample.composeviewmodels.app
4 |
5 | import androidx.compose.ui.window.singleWindowApplication
6 | import dev.zacsweers.metro.createGraph
7 |
8 | fun main() {
9 | val appGraph = createGraph()
10 |
11 | singleWindowApplication(title = "Compose ViewModels Sample") {
12 | ComposeApp(appGraph.metroViewModelFactory)
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/benchmark/startup-android/app/src/main/kotlin/dev/zacsweers/metro/benchmark/startup/android/MainActivity.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.benchmark.startup.android
4 |
5 | import android.app.Activity
6 | import android.os.Bundle
7 |
8 | class MainActivity : Activity() {
9 | override fun onCreate(savedInstanceState: Bundle?) {
10 | super.onCreate(savedInstanceState)
11 | // Signal that the app is fully drawn for startup benchmarking
12 | reportFullyDrawn()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/bindingcontainers/SimpleContainersWithHintsWork.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/issues/733
2 | @SingleIn(AppScope::class)
3 | @DependencyGraph(AppScope::class)
4 | interface AppGraph {
5 | val text: String
6 | }
7 |
8 | @ContributesTo(AppScope::class)
9 | @BindingContainer
10 | object SampleDependency {
11 | @Provides fun provideText(): String = "Hello, Metro!"
12 | }
13 |
14 | fun box(): String {
15 | val graph = createGraph()
16 | assertEquals("Hello, Metro!", graph.text)
17 | return "OK"
18 | }
19 |
--------------------------------------------------------------------------------
/compiler/src/main/kotlin/dev/zacsweers/metro/compiler/graph/BaseTypeKey.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.compiler.graph
4 |
5 | internal interface BaseTypeKey> :
6 | Comparable {
7 | val type: Type
8 | val qualifier: Qualifier?
9 |
10 | fun copy(type: Type = this.type, qualifier: Qualifier? = this.qualifier): Subtype
11 |
12 | fun render(short: Boolean, includeQualifier: Boolean = true): String
13 | }
14 |
--------------------------------------------------------------------------------
/gradle-plugin/src/main/kotlin/dev/zacsweers/metro/gradle/DiagnosticSeverity.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.gradle
4 |
5 | public enum class DiagnosticSeverity {
6 | /** Emits no diagnostics/does not check. */
7 | NONE,
8 |
9 | /** Emits a compiler warning if encountered. */
10 | WARN,
11 |
12 | /** Emits a compiler error if encountered and fails compilation. */
13 | ERROR;
14 |
15 | public val isEnabled: Boolean
16 | get() = this != DiagnosticSeverity.NONE
17 | }
18 |
--------------------------------------------------------------------------------
/benchmark/startup-android/app/src/main/kotlin/dev/zacsweers/metro/benchmark/startup/android/BenchmarkApplication.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.benchmark.startup.android
4 |
5 | import android.app.Application
6 | import dev.zacsweers.metro.benchmark.app.component.createAndInitialize
7 |
8 | class BenchmarkApplication : Application() {
9 | override fun onCreate() {
10 | super.onCreate()
11 | // Initialize the Metro dependency graph
12 | createAndInitialize()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/extensions/ExtensionsCanBeDeclaredWithoutFactories.kt:
--------------------------------------------------------------------------------
1 | @GraphExtension
2 | interface LoggedInGraph {
3 | val int: Int
4 | }
5 |
6 | @DependencyGraph
7 | interface AppGraph {
8 | @Provides fun provideInt(): Int = 3
9 |
10 | fun loggedInGraph(): LoggedInGraph
11 |
12 | val loggedInGraphProp: LoggedInGraph
13 | }
14 |
15 | fun box(): String {
16 | val graph = createGraph()
17 | assertEquals(3, graph.loggedInGraph().int)
18 | assertEquals(3, graph.loggedInGraphProp.int)
19 | return "OK"
20 | }
21 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/member/AncestorInjectionWithEmptyDescendants.kt:
--------------------------------------------------------------------------------
1 | @HasMemberInjections
2 | abstract class Parent {
3 | @Inject
4 | var int: Int = 0
5 | }
6 |
7 | @HasMemberInjections
8 | abstract class Child : Parent()
9 |
10 | @Inject
11 | class GrandChild : Child()
12 |
13 | @DependencyGraph
14 | interface AppGraph {
15 | @Provides fun provideInt(): Int = 3
16 |
17 | val grandChild: GrandChild
18 | }
19 |
20 | fun box(): String {
21 | val graph = createGraph()
22 | assertEquals(3, graph.grandChild.int)
23 | return "OK"
24 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesCannotHaveReceivers_AbstractClass.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesCannotHaveReceivers_AbstractClass.kt:(113,123): error: `@Provides` properties may not be extension properties. Use `@Binds` instead for these. See https://zacsweers.github.io/metro/latest/bindings/#binds for more information.
2 |
3 | /ProvidesCannotHaveReceivers_AbstractClass.kt:(187,200): error: `@Provides` functions may not be extension functions. Use `@Binds` instead for these. See https://zacsweers.github.io/metro/latest/bindings/#binds for more information.
4 |
--------------------------------------------------------------------------------
/samples/compose-viewmodels/app/src/androidMain/kotlin/dev/zacsweers/metro/sample/composeviewmodels/app/Graphs.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample.composeviewmodels.app
4 |
5 | import dev.zacsweers.metro.AppScope
6 | import dev.zacsweers.metro.DependencyGraph
7 | import dev.zacsweers.metrox.android.MetroAppComponentProviders
8 | import dev.zacsweers.metrox.viewmodel.ViewModelGraph
9 |
10 | @DependencyGraph(AppScope::class) interface AppGraph : MetroAppComponentProviders, ViewModelGraph
11 |
--------------------------------------------------------------------------------
/runtime/src/commonMain/kotlin/dev/zacsweers/metro/Named.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2024 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro
4 |
5 | /** A simple [Qualifier] that disambiguates based on the [name] value. */
6 | @Target(
7 | AnnotationTarget.CLASS,
8 | AnnotationTarget.FIELD,
9 | AnnotationTarget.FUNCTION,
10 | AnnotationTarget.PROPERTY,
11 | AnnotationTarget.PROPERTY_GETTER,
12 | AnnotationTarget.VALUE_PARAMETER,
13 | AnnotationTarget.TYPE,
14 | )
15 | @Qualifier
16 | public annotation class Named(val name: String)
17 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/inject/assisted/ImplsAreVisibleAcrossModules.kt:
--------------------------------------------------------------------------------
1 | // MODULE: lib
2 | @AssistedInject
3 | class Example(@Assisted val input: String) {
4 | @AssistedFactory
5 | interface Factory {
6 | fun create(input: String): Example
7 | }
8 | }
9 |
10 | // MODULE: main(lib)
11 | @DependencyGraph
12 | interface AppGraph {
13 | val factory: Example.Factory
14 | }
15 |
16 | fun box(): String {
17 | val graph = createGraph()
18 | val instance = graph.factory.create("Hello")
19 | assertEquals("Hello", instance.input)
20 | return "OK"
21 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/interop/dagger/DaggerComponentModulesAnnotationInterop.kt:
--------------------------------------------------------------------------------
1 | // ENABLE_DAGGER_INTEROP
2 | // Similar to DaggerModulesAnnotationInterop.kt but covers components too
3 | import dagger.Component
4 | import dagger.Module
5 |
6 | @Module
7 | class IntModule {
8 | @Provides fun provideInt(): Int = 3
9 | }
10 |
11 | @Component(modules = [IntModule::class])
12 | interface AppComponent {
13 | val int: Int
14 | }
15 |
16 | fun box(): String {
17 | val graph = createGraph()
18 | assertEquals(3, graph.int)
19 | return "OK"
20 | }
21 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/MismatchedSingleInScopesDisambiguateSameNameScopes.fir.ir.diag.txt:
--------------------------------------------------------------------------------
1 | /MismatchedSingleInScopesDisambiguateSameNameScopes.kt:(406,418): error: [Metro/IncompatiblyScopedBindings] test.graph.ExampleGraph (scopes '@dev.zacsweers.metro.SingleIn(test.graph.AppScope::class)') may not reference bindings from different scopes:
2 | test.graph.MyClass (scoped to '@dev.zacsweers.metro.SingleIn(dev.zacsweers.metro.AppScope::class)')
3 | test.graph.MyClass is requested at
4 | [test.graph.ExampleGraph] test.graph.ExampleGraph.myClass
5 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/BindsMayNotHaveScopes.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | interface BindsInterface {
4 | @Binds @SingleIn(AppScope::class) val String.bind: CharSequence
5 | @Binds @SingleIn(AppScope::class) fun String.bindFunction(): CharSequence
6 | }
7 |
8 | abstract class BindsClass {
9 | @Binds @SingleIn(AppScope::class) abstract val String.bind: CharSequence
10 | @Binds @SingleIn(AppScope::class) abstract fun String.bindFunction(): CharSequence
11 | }
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/injectconstructor/ConstructorFunctionSignatures.kt:
--------------------------------------------------------------------------------
1 | // Golden image to validate that we generate the correct signature for
2 | // constructorFunction() IR breadcrumbs
3 |
4 | @Inject class SimpleClass
5 | @Inject class ClassWithBounds
6 | @Inject class ClassWithNullable
7 | @Inject class ClassWithMultiple
8 | @Inject class ClassWithBackRefs
9 | @Inject class ClassWithWheres where E : V
10 | @Inject class ComplexMonster where E : V, V : T, T : Any
--------------------------------------------------------------------------------
/metrox-android/src/main/kotlin/dev/zacsweers/metrox/android/ContentProviderKey.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metrox.android
4 |
5 | import android.content.ContentProvider
6 | import dev.zacsweers.metro.MapKey
7 | import kotlin.reflect.KClass
8 |
9 | /**
10 | * A [MapKey] annotation for binding [ContentProviders][ContentProvider] into a multibinding map.
11 | */
12 | @MapKey
13 | @Target(AnnotationTarget.CLASS)
14 | public annotation class ContentProviderKey(val value: KClass)
15 |
--------------------------------------------------------------------------------
/samples/compose-viewmodels/screen-home/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.multiplatform)
5 | alias(libs.plugins.kotlin.plugin.compose)
6 | alias(libs.plugins.compose)
7 | id("dev.zacsweers.metro")
8 | }
9 |
10 | kotlin {
11 | jvm()
12 |
13 | sourceSets {
14 | commonMain.dependencies {
15 | api("dev.zacsweers.metro:metrox-viewmodel-compose")
16 | implementation(compose.material3)
17 | implementation(compose.runtime)
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/dynamic/GraphsAreCachedByType.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface ExampleGraph
3 |
4 | @BindingContainer
5 | object Bindings
6 |
7 | fun example(
8 | graph: ExampleGraph = createDynamicGraph(Bindings),
9 | graph2: ExampleGraph = createDynamicGraph(Bindings),
10 | ): Pair {
11 | return graph to graph2
12 | }
13 |
14 | fun box(): String {
15 | val (graph1, graph2) = example()
16 | assertEquals(graph1::class.qualifiedName, graph2::class.qualifiedName)
17 | return "OK"
18 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/UsefulHintsForMissingImplDeps.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 |
4 | // MODULE: core
5 | interface Base
6 |
7 | // MODULE: lib1(core)
8 | @Inject
9 | class FooImpl : Base
10 |
11 | // MODULE: lib2(lib1 core)
12 | @ContributesTo(AppScope::class)
13 | @BindingContainer
14 | interface Bindings {
15 | @Binds val FooImpl.bind: Base
16 | }
17 |
18 | // MODULE: main(lib2 core)
19 | @DependencyGraph(AppScope::class)
20 | interface AppGraph {
21 | val base: Base
22 | }
23 |
--------------------------------------------------------------------------------
/samples/compose-viewmodels/screen-details/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.multiplatform)
5 | alias(libs.plugins.kotlin.plugin.compose)
6 | alias(libs.plugins.compose)
7 | id("dev.zacsweers.metro")
8 | }
9 |
10 | kotlin {
11 | jvm()
12 |
13 | sourceSets {
14 | commonMain.dependencies {
15 | api("dev.zacsweers.metro:metrox-viewmodel-compose")
16 | implementation(compose.material3)
17 | implementation(compose.runtime)
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/interop/dagger/DaggerMultibindsAllowEmptyByDefault.kt:
--------------------------------------------------------------------------------
1 | // ENABLE_DAGGER_INTEROP
2 |
3 | // Regression test for https://github.com/ZacSweers/metro/issues/334
4 |
5 | import dagger.multibindings.Multibinds
6 |
7 | @DependencyGraph
8 | interface ExampleGraph {
9 | @Multibinds fun emptySet(): Set
10 | @Multibinds fun emptyMap(): Map
11 | }
12 |
13 | fun box(): String {
14 | val graph = createGraph()
15 | assertTrue(graph.emptySet().isEmpty())
16 | assertTrue(graph.emptyMap().isEmpty())
17 | return "OK"
18 | }
19 |
--------------------------------------------------------------------------------
/samples/integration-tests/src/androidUnitTest/kotlin/dev/zacsweers/metro/test/integration/replaces/AndroidPlatformContribution.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.test.integration.replaces
4 |
5 | import dev.zacsweers.metro.AppScope
6 | import dev.zacsweers.metro.ContributesBinding
7 | import dev.zacsweers.metro.Inject
8 |
9 | @ContributesBinding(AppScope::class, replaces = [DefaultPlatform::class])
10 | @Inject
11 | class AndroidPlatform : Platform {
12 | override val platformName: String = "android"
13 | }
14 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/provides/JvmFieldProvidersAreRespected.kt:
--------------------------------------------------------------------------------
1 | // In this scenario, generated provider factories' newInstance function gets the field directly
2 | @DependencyGraph
3 | abstract class AppGraph {
4 | @Provides @JvmField val stringField: String = "Hello"
5 | // Normal property
6 | @Provides val intAccessor: Int get() = 3
7 |
8 | abstract val string: String
9 | abstract val int: Int
10 | }
11 |
12 | fun box(): String {
13 | val graph = createGraph()
14 | assertEquals("Hello", graph.string)
15 | assertEquals(3, graph.int)
16 | return "OK"
17 | }
--------------------------------------------------------------------------------
/samples/android-app/src/main/kotlin/dev/zacsweers/metro/sample/android/WorkerKey.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample.android
4 |
5 | import androidx.work.ListenableWorker
6 | import dev.zacsweers.metro.MapKey
7 | import kotlin.reflect.KClass
8 |
9 | /** A [MapKey] annotation for binding Worker in a multibinding map. */
10 | @MapKey
11 | @Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY)
12 | @Retention(AnnotationRetention.RUNTIME)
13 | annotation class WorkerKey(val value: KClass)
14 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/inject/member/MemberInjectorRequest.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/discussions/593
2 | class Foo {
3 | @Inject lateinit var message: String
4 | }
5 |
6 | @DependencyGraph
7 | interface AppGraph {
8 | val fooInjector: MembersInjector
9 |
10 | @Provides
11 | fun provideMessage(): String = "message"
12 | }
13 |
14 | fun box(): String {
15 | val graph = createGraph()
16 | val injector = graph.fooInjector
17 | val foo = Foo()
18 | injector.injectMembers(foo)
19 | assertEquals("message", foo.message)
20 | return "OK"
21 | }
22 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/aggregation/InternalHintsAreNotVisibleWithoutFriends.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 | // https://github.com/ZacSweers/metro/issues/694
4 | // The syntax goes name(deps)(friends)(dependsOn)
5 |
6 | // MODULE: lib
7 | interface ContributedInterface
8 |
9 | @ContributesBinding(AppScope::class)
10 | @Inject
11 | internal class Impl : ContributedInterface
12 |
13 | // MODULE: main(lib)
14 | @DependencyGraph(AppScope::class)
15 | interface AppGraph {
16 | val contributed: ContributedInterface
17 | }
18 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/optional/DisabledResultsInMissingBindingMultiModule.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 | // OPTIONAL_DEPENDENCY_BEHAVIOR: DISABLED
4 |
5 | // MODULE: lib
6 | @Inject
7 | class Example(val value: String? = null)
8 |
9 | interface Base {
10 | val int: Int
11 |
12 | @Provides
13 | fun provideInt(long: Long? = null): Int = long?.toInt() ?: 3
14 | }
15 |
16 | // MODULE: main(lib)
17 | @DependencyGraph
18 | interface AppGraph : Base {
19 | val example: Example
20 | }
21 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/bindingcontainers/BindingContainerViaAnnotationCycleIsOk.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph(bindingContainers = [StringBindings::class])
2 | interface AppGraph {
3 | val string: String
4 | }
5 |
6 | // Simple self-referencing container
7 | @BindingContainer(includes = [StringBindings::class])
8 | class StringBindings {
9 | @Provides
10 | fun provideString(): String {
11 | return "string value"
12 | }
13 | }
14 |
15 | fun box(): String {
16 | val graph = createGraph()
17 | assertEquals("string value", graph.string)
18 | return "OK"
19 | }
20 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/inject/assisted/NoAssistedArgsInAssistedInject.kt:
--------------------------------------------------------------------------------
1 | // Regression test for https://github.com/ZacSweers/metro/issues/1235
2 |
3 | @AssistedInject
4 | class Example(val dep: Dependency) {
5 | @AssistedFactory
6 | interface Factory {
7 | fun create(): Example
8 | }
9 | }
10 |
11 | @Inject class Dependency
12 |
13 | @DependencyGraph
14 | interface AppGraph {
15 | val factory: Example.Factory
16 | }
17 |
18 | fun box(): String {
19 | val instance = assertNotNull(createGraph().factory.create())
20 | assertNotNull(instance.dep)
21 | return "OK"
22 | }
23 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/bindingcontainer/NoProvidesOnParams.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @Suppress("ANNOTATION_WILL_BE_APPLIED_ALSO_TO_PROPERTY_OR_FIELD")
4 | @BindingContainer
5 | class InjectedFromConstructorParameter(
6 | @Provides val default: String,
7 | @param:Provides val parameter: String,
8 | @get:Provides val getter: Int,
9 | @property:Provides val property: Long,
10 | @field:Provides val field: Long,
11 | )
12 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/aggregation/ContributorsWithSameSimpleNames.kt:
--------------------------------------------------------------------------------
1 | // MODULE: lib
2 |
3 | // FILE: Impl1.kt
4 | package test1
5 |
6 | @ContributesTo(AppScope::class)
7 | interface ContributedInterface
8 |
9 | // FILE: Impl2.kt
10 | package test2
11 |
12 | @ContributesTo(AppScope::class)
13 | interface ContributedInterface
14 |
15 | // MODULE: main(lib)
16 |
17 | // Note the compiler test framework is ok with generating duplicate IR files, so we do this
18 | // IR dump test to golden image it to watch for regressions
19 | @DependencyGraph(scope = AppScope::class)
20 | interface ExampleGraph
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/aggregation/ExcludesWithOrigin.kt:
--------------------------------------------------------------------------------
1 | interface Foo
2 |
3 | @Origin(RealFoo::class)
4 | @Inject
5 | @ContributesBinding(AppScope::class)
6 | class GeneratedRealFoo : RealFoo()
7 |
8 | abstract class RealFoo : Foo
9 |
10 | @Inject
11 | @ContributesBinding(AppScope::class)
12 | class FakeFoo : Foo
13 |
14 | @DependencyGraph(AppScope::class, excludes = [RealFoo::class])
15 | interface AppGraph {
16 | val foo: Foo
17 | }
18 |
19 | fun box(): String {
20 | val graph = createGraph()
21 | assertEquals("FakeFoo", graph.foo::class.qualifiedName)
22 | return "OK"
23 | }
24 |
--------------------------------------------------------------------------------
/samples/compose-viewmodels/screen-settings/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.multiplatform)
5 | alias(libs.plugins.kotlin.plugin.compose)
6 | alias(libs.plugins.compose)
7 | id("dev.zacsweers.metro")
8 | }
9 |
10 | kotlin {
11 | jvm()
12 |
13 | sourceSets {
14 | commonMain {
15 | dependencies {
16 | api("dev.zacsweers.metro:metrox-viewmodel-compose")
17 | implementation(compose.material3)
18 | implementation(compose.runtime)
19 | }
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/MismatchedSingleInScopesDisambiguateSameNameScopes.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 | // https://github.com/ZacSweers/metro/pull/1565
4 | package test.graph
5 |
6 | // Uses metro's AppScope
7 | @SingleIn(dev.zacsweers.metro.AppScope::class)
8 | @Inject
9 | class MyClass
10 |
11 | // Graph uses a custom AppScope
12 | abstract class AppScope private constructor()
13 |
14 | @SingleIn(AppScope::class)
15 | @DependencyGraph(AppScope::class)
16 | interface ExampleGraph {
17 | val myClass: MyClass
18 | }
19 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/provides/ProvidesWithExtensionsAndNonThisReturningBodiesShouldError.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /ProvidesWithExtensionsAndNonThisReturningBodiesShouldError.kt:(115,134): error: `@Provides` properties may not be extension properties. Use `@Binds` instead for these. See https://zacsweers.github.io/metro/latest/bindings/#binds for more information.
2 |
3 | /ProvidesWithExtensionsAndNonThisReturningBodiesShouldError.kt:(185,198): error: `@Provides` functions may not be extension functions. Use `@Binds` instead for these. See https://zacsweers.github.io/metro/latest/bindings/#binds for more information.
4 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/aggregation/InternalHintsInGraph.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/issues/694
2 | // The syntax goes name(deps)(friends)(dependsOn)
3 |
4 | // MODULE: lib
5 | interface ContributedInterface
6 |
7 | @ContributesBinding(AppScope::class)
8 | @Inject
9 | internal class Impl : ContributedInterface
10 |
11 | // MODULE: main()(lib)
12 | @DependencyGraph(AppScope::class)
13 | internal interface AppGraph {
14 | val contributed: ContributedInterface
15 | }
16 |
17 | fun box(): String {
18 | val graph = createGraph()
19 | assertNotNull(graph.contributed)
20 | return "OK"
21 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/interop/guice/InjectedGuiceProviderInteropWorks.kt:
--------------------------------------------------------------------------------
1 | // ENABLE_GUICE_INTEROP
2 | import com.google.inject.Inject
3 | import com.google.inject.Provider
4 |
5 | @DependencyGraph
6 | interface ExampleGraph {
7 | val fooBar: FooBar
8 | }
9 |
10 | class Foo @Inject constructor()
11 |
12 | class FooBar @Inject constructor(val provider: Provider)
13 |
14 | fun box(): String {
15 | val graph = createGraph()
16 | val fooInstance = graph.fooBar.provider
17 | assertNotNull(fooInstance)
18 | assertEquals(fooInstance.get().javaClass.name, "Foo")
19 | return "OK"
20 | }
21 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/function/LazyAssistedFactoryFunctionInjection.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @AssistedFactory
4 | interface MyAssistedFactory {
5 | fun create(param: String): MyClass
6 | }
7 |
8 | @AssistedInject
9 | class MyClass(
10 | @Assisted val param: String,
11 | val dependency: String
12 | )
13 |
14 | // Function injection with lazy-wrapped assisted factory parameter should be an error
15 | @Inject
16 | fun injectFunction(
17 | factory: Lazy,
18 | other: String
19 | ) {
20 | // Function body
21 | }
22 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/aggregation/ReplacementsWithOrigin.kt:
--------------------------------------------------------------------------------
1 | interface Foo
2 |
3 | @Origin(RealFoo::class)
4 | @Inject
5 | @ContributesBinding(AppScope::class)
6 | class GeneratedRealFoo : RealFoo()
7 |
8 | abstract class RealFoo : Foo
9 |
10 | @Inject
11 | @ContributesBinding(scope = AppScope::class, replaces = [RealFoo::class])
12 | class FakeFoo : Foo
13 |
14 | @DependencyGraph(AppScope::class)
15 | interface AppGraph {
16 | val foo: Foo
17 | }
18 |
19 | fun box(): String {
20 | val graph = createGraph()
21 | assertEquals("FakeFoo", graph.foo::class.qualifiedName)
22 | return "OK"
23 | }
24 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/inject/assisted/AssistedTypesCanBeProvidedWithQualifiers.kt:
--------------------------------------------------------------------------------
1 | @AssistedInject
2 | class Taco(@Assisted val seasoning: String) {
3 | @AssistedFactory
4 | interface Factory {
5 | fun create(seasoning: String): Taco
6 | }
7 | }
8 |
9 | @DependencyGraph
10 | interface AppGraph {
11 | @Named("qualified") val taco: Taco
12 |
13 | @Provides @Named("qualified")
14 | fun provideTaco(factory: Taco.Factory): Taco = factory.create("spicy")
15 | }
16 |
17 | fun box(): String {
18 | val graph = createGraph()
19 | assertEquals("spicy", graph.taco.seasoning)
20 | return "OK"
21 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/inject/member/GenericMemberInjectorRequest.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/discussions/593
2 | class Foo {
3 | @Inject lateinit var message: T
4 | }
5 |
6 | @DependencyGraph
7 | interface AppGraph {
8 | val fooInjector: MembersInjector>
9 |
10 | @Provides
11 | fun provideMessage(): String = "message"
12 | }
13 |
14 | fun box(): String {
15 | val graph = createGraph()
16 | val injector = graph.fooInjector
17 | val foo = Foo()
18 | injector.injectMembers(foo)
19 | assertEquals("message", foo.message)
20 | return "OK"
21 | }
22 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/createGraph/CreateGraph_OkCase.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface ExampleGraph
3 |
4 | @DependencyGraph
5 | interface ExampleGraphWithFactory {
6 | @DependencyGraph.Factory
7 | interface Factory {
8 | fun create(): ExampleGraphWithFactory
9 | }
10 | }
11 |
12 | fun example() {
13 | val exampleGraph = createGraph()
14 | val exampleGraphWithFactory = createGraphFactory().create()
15 | val exampleGraph2: ExampleGraph = createGraph()
16 | val exampleGraphFactory: ExampleGraphWithFactory.Factory = createGraphFactory()
17 | }
18 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/optional/RequiredAnnotationResultsInMissingBindingMultiModule.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 | // OPTIONAL_DEPENDENCY_BEHAVIOR: REQUIRE_OPTIONAL_BINDING
4 |
5 | // MODULE: lib
6 | @Inject
7 | class Example(val value: String? = null)
8 |
9 | interface Base {
10 | val int: Int
11 |
12 | @Provides
13 | fun provideInt(@OptionalBinding long: Long? = null): Int = long?.toInt() ?: 3
14 | }
15 |
16 | // MODULE: main(lib)
17 | @DependencyGraph
18 | interface AppGraph : Base {
19 | val example: Example
20 | }
21 |
--------------------------------------------------------------------------------
/samples/compose-viewmodels/app/src/androidMain/kotlin/dev/zacsweers/metro/sample/composeviewmodels/app/MetroApp.kt:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | package dev.zacsweers.metro.sample.composeviewmodels.app
4 |
5 | import android.app.Application
6 | import dev.zacsweers.metro.createGraph
7 | import dev.zacsweers.metrox.android.MetroAppComponentProviders
8 | import dev.zacsweers.metrox.android.MetroApplication
9 |
10 | class MetroApp : Application(), MetroApplication {
11 | override val appComponentProviders: MetroAppComponentProviders by lazy { createGraph() }
12 | }
13 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/interop/dagger/AnotherBindsOptionalPresentTest.kt:
--------------------------------------------------------------------------------
1 | // ENABLE_DAGGER_INTEROP
2 | import java.util.Optional
3 |
4 | @DependencyGraph(AppScope::class, bindingContainers = [Bindings::class])
5 | interface AppGraph {
6 | val optional: Optional
7 |
8 | @Provides @SingleIn(AppScope::class) val string: String get() = "Hello"
9 | }
10 |
11 | @dagger.Module
12 | interface Bindings {
13 | @dagger.BindsOptionalOf
14 | fun string(): String
15 | }
16 |
17 | fun box(): String {
18 | val graph = createGraph()
19 | assertEquals("Hello", graph.optional.get())
20 | return "OK"
21 | }
22 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/fir/private-provides-status-transformation/ProvidersAreMadePrivate.kt:
--------------------------------------------------------------------------------
1 | interface ExampleProviders {
2 | @Provides
3 | fun shouldBePrivate(): String = "hello"
4 |
5 | @Provides
6 | public fun shouldNotBePrivate1(): String = "hello"
7 |
8 | @Provides
9 | private fun shouldBePrivate2(): String = "hello"
10 |
11 | companion object {
12 | @Provides
13 | fun shouldBePrivate(): String = "hello"
14 |
15 | @Provides
16 | public fun shouldNotBePrivate1(): String = "hello"
17 |
18 | @Provides
19 | internal fun shouldNotBePrivate2(): String = "hello"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/dump/ir/visibility/InternalVisibilityDifferentModule.kt:
--------------------------------------------------------------------------------
1 | // Test direct invocation checks for internal members in different module
2 | // Internal bindings from another module should not support direct invocation
3 |
4 | // MODULE: lib
5 | @Inject class InternalClass internal constructor()
6 |
7 | @BindingContainer
8 | object IntProvider {
9 | @Provides internal fun provideInt(): Int = 42
10 | }
11 |
12 | // MODULE: main(lib)
13 | @DependencyGraph(bindingContainers = [IntProvider::class])
14 | abstract class AppGraph {
15 | abstract val int: Int
16 | abstract val internalClass: InternalClass
17 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/ExposingIncludedGraphsDirectly.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/issues/1144
2 |
3 | @DependencyGraph
4 | interface PushComponent {
5 | fun foo(): Foo
6 |
7 | @DependencyGraph.Factory
8 | interface Factory {
9 | fun create(@Includes foo: Foo): PushComponent
10 | }
11 | }
12 |
13 | interface Foo {
14 | val a: String
15 | }
16 |
17 | fun box(): String {
18 | val foo = object : Foo {
19 | override val a: String = "hello"
20 | }
21 | val graph = createGraphFactory().create(foo)
22 | assertSame(foo, graph.foo())
23 | return "OK"
24 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/provides/CapitalizedProvides.kt:
--------------------------------------------------------------------------------
1 | /*
2 | Regression test for https://github.com/ZacSweers/metro/issues/456
3 | */
4 |
5 | @DependencyGraph(AppScope::class)
6 | interface App {
7 | val suit: Suit
8 | }
9 |
10 | enum class Suit {
11 | HEARTS,
12 | DIAMONDS,
13 | CLUBS,
14 | SPADES,
15 | }
16 |
17 | @ContributesTo(AppScope::class)
18 | interface SuitProvider {
19 | // note the capital S in "fun Suit()"
20 | @Provides @SingleIn(AppScope::class) fun Suit(): Suit = Suit.SPADES
21 | }
22 |
23 | fun box(): String {
24 | assertEquals(createGraph().suit, Suit.SPADES)
25 | return "OK"
26 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/MixedCycleParams.fir.ir.diag.txt:
--------------------------------------------------------------------------------
1 | /MixedCycleParams.kt:(501,511): error: [Metro/DependencyCycle] Found a dependency cycle while processing 'CycleGraph'.
2 | Cycle:
3 | RealA --> B --> FakeA --> A --> RealA
4 |
5 | Trace:
6 | RealA is injected at
7 | [CycleGraph] B()
8 | B is injected at
9 | [CycleGraph] FakeA(…, b)
10 | FakeA is injected at
11 | [CycleGraph] FakeA.$$MetroContributionToUnit#bindsAsA(…, instance)
12 | A is injected at
13 | [CycleGraph] RealA()
14 | RealA is injected at
15 | [CycleGraph] B()
16 | ...
17 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/ProvidingEmptyMultibindingsDirectly.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/issues/1069
2 | @Inject class MyIntUser(val ints: Set, val intsMap: Map)
3 |
4 | @DependencyGraph
5 | interface AppGraph {
6 | val user: MyIntUser
7 |
8 | @Provides fun provideSomeMap(): Map = emptyMap()
9 |
10 | @Provides fun provideInts(): Set = emptySet()
11 | }
12 |
13 | fun box(): String {
14 | val graph = createGraph()
15 | val user = graph.user
16 | assertTrue(user.ints.isEmpty())
17 | assertTrue(user.intsMap.isEmpty())
18 | return "OK"
19 | }
20 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/interop/dagger/MemberInjectionQualifiersAreLookedUp.fir.ir.diag.txt:
--------------------------------------------------------------------------------
1 | /ExampleGraph.kt:(126,138): error: [Metro/MissingBinding] Cannot find an @Inject constructor or @Provides-annotated function/property for: @javax.inject.Named("qualified") Dependency
2 |
3 | @javax.inject.Named("qualified") Dependency is injected at
4 | [ExampleGraph] ExampleGraph.inject()
5 | dev.zacsweers.metro.MembersInjector is requested at
6 | [ExampleGraph] ExampleGraph.inject()
7 |
8 | Similar bindings:
9 | - Dependency (Different qualifier). Type: Alias. Source: DependencyImpl.kt:26:1
10 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/interop/dagger/PositionalAnnotationArgsError.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /PositionalAnnotationArgsError.kt:(283,298): error: Interop annotation @MergeComponent should use named arguments instead of positional arguments for better compatibility in Metro.
2 |
3 | /PositionalAnnotationArgsError.kt:(318,335): error: Interop annotation @MergeComponent should use named arguments instead of positional arguments for better compatibility in Metro.
4 |
5 | /PositionalAnnotationArgsError.kt:(360,378): error: Interop annotation @MergeComponent should use named arguments instead of positional arguments for better compatibility in Metro.
6 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/interop/dagger/PositionalAnnotationArgsError.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // WITH_DAGGER
3 | // WITH_ANVIL
4 | // INTEROP_ANNOTATIONS_NAMED_ARG_SEVERITY: ERROR
5 |
6 | import com.squareup.anvil.annotations.MergeComponent
7 |
8 | interface Providers
9 |
10 | @dagger.Module
11 | interface Bindings
12 |
13 | @MergeComponent(
14 | /* scope = */ AppScope::class,
15 | /* modules = */ [Bindings::class],
16 | /* dependencies = */ [Providers::class]
17 | )
18 | interface AppComponent
19 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/inject/assisted/DefaultAssistedFactoryIsGeneratedInFIR.kt:
--------------------------------------------------------------------------------
1 | // GENERATE_ASSISTED_FACTORIES
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int,
5 | val message: String,
6 | )
7 |
8 | @DependencyGraph
9 | interface AppGraph {
10 | val factory: ExampleClass.Factory
11 | @Provides val string: String get() = "Hello, "
12 | }
13 |
14 | fun box(): String {
15 | val factory = createGraph().factory
16 | // Smoke test to ensure that the FIR-generated
17 | assertEquals(2, factory.create(count = 2).count)
18 | assertEquals(3, factory.create(count = 3).count)
19 | return "OK"
20 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/interop/dagger/PositionalAnnotationArgsWarning.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // WITH_DAGGER
3 | // WITH_ANVIL
4 | // INTEROP_ANNOTATIONS_NAMED_ARG_SEVERITY: WARN
5 |
6 | import com.squareup.anvil.annotations.MergeComponent
7 |
8 | interface Providers
9 |
10 | @dagger.Module
11 | interface Bindings
12 |
13 | @MergeComponent(
14 | /* scope = */ AppScope::class,
15 | /* modules = */ [Bindings::class],
16 | /* dependencies = */ [Providers::class]
17 | )
18 | interface AppComponent
19 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/aggregation/ContributingMultibileNullableBindings.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/issues/779
2 | interface SomeRepo
3 |
4 | @ContributesBinding(AppScope::class, binding = binding())
5 | @ContributesBinding(AppScope::class, binding = binding())
6 | @Inject
7 | class SomeRepoImpl : SomeRepo
8 |
9 | @DependencyGraph(AppScope::class)
10 | interface AppGraph {
11 | val repo: SomeRepo
12 | val nullableRepo: SomeRepo?
13 | }
14 |
15 | fun box(): String {
16 | val graph = createGraph()
17 | assertNotNull(graph.repo)
18 | assertNotNull(graph.nullableRepo)
19 | return "OK"
20 | }
--------------------------------------------------------------------------------
/benchmark/startup-jvm/minified-jar/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Keep the createAndInitialize function as the entry point for benchmarks
2 | -keep class dev.zacsweers.metro.benchmark.app.component.AppComponentKt {
3 | public static *** createAndInitialize();
4 | }
5 |
6 | # Keep AppComponent and its public methods since it's the return type of createAndInitialize
7 | -keep class dev.zacsweers.metro.benchmark.app.component.AppComponent {
8 | public *;
9 | }
10 |
11 | # Don't warn about missing classes
12 | -dontwarn javax.annotation.**
13 | -dontwarn org.jetbrains.annotations.**
14 |
15 | # Optimization settings
16 | -allowaccessmodification
17 | -dontobfuscate
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/interop/dagger/InjectedJavaxProviderInteropWorks.kt:
--------------------------------------------------------------------------------
1 | // ENABLE_DAGGER_INTEROP
2 | package test
3 |
4 | import javax.inject.Inject
5 | import javax.inject.Provider
6 |
7 | @DependencyGraph
8 | interface ExampleGraph {
9 | val fooBar: FooBar
10 | }
11 |
12 | class Foo @Inject constructor()
13 |
14 | class FooBar @Inject constructor(
15 | val provider: Provider
16 | )
17 |
18 | fun box(): String {
19 | val graph = createGraph()
20 | val fooInstance = graph.fooBar.provider
21 | assertNotNull(fooInstance)
22 | assertEquals(fooInstance.get().javaClass.name, "test.Foo")
23 | return "OK"
24 | }
25 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/interop/dagger/JavaxProviderShouldWorkInSet.kt:
--------------------------------------------------------------------------------
1 | // ENABLE_DAGGER_INTEROP
2 | // Ref https://github.com/ZacSweers/metro/pull/666
3 | import javax.inject.Provider
4 |
5 | @DependencyGraph(AppScope::class)
6 | interface AppGraph {
7 | val urlHandlers: Set
8 | }
9 |
10 | interface UrlHandler
11 |
12 | @Inject
13 | @ContributesIntoSet(AppScope::class)
14 | class PostUrlHandler : UrlHandler {
15 | fun handle(url: String) {
16 | url.toString()
17 | }
18 | }
19 |
20 | fun box(): String {
21 | val graph = createGraph()
22 | assertNotNull(graph.urlHandlers.single())
23 | return "OK"
24 | }
25 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/interop/guice/InjectedKotlinLazyFromGuiceProviderWorks.kt:
--------------------------------------------------------------------------------
1 | // ENABLE_GUICE_INTEROP
2 | import com.google.inject.Inject
3 |
4 | @DependencyGraph
5 | interface ExampleGraph {
6 | val fooBar: FooBar
7 | }
8 |
9 | class Foo @Inject constructor()
10 |
11 | class FooBar @Inject constructor(val lazy: Lazy)
12 |
13 | fun box(): String {
14 | val graph = createGraph()
15 | val fooInstance = graph.fooBar.lazy
16 | assertNotNull(fooInstance)
17 | // Verify it's a Kotlin Lazy
18 | assertTrue(fooInstance is Lazy<*>)
19 | assertEquals(fooInstance.value.javaClass.name, "Foo")
20 | return "OK"
21 | }
22 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/AssistedTypesCannotBeDirectlyQualified.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @Named("qualified")
4 | @AssistedInject
5 | class Taco(@Assisted val seasoning: String) {
6 | @AssistedFactory
7 | interface Factory {
8 | fun create(seasoning: String): Taco
9 | }
10 | }
11 |
12 | @Suppress("SUGGEST_CLASS_INJECTION")
13 | @Named("qualified")
14 | class Taco2 @AssistedInject constructor(@Assisted val seasoning: String) {
15 | @AssistedFactory
16 | interface Factory {
17 | fun create(seasoning: String): Taco
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/member/MembersInjectorParameterWithNoDefaultShouldError.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 | // Repro https://github.com/ZacSweers/metro/issues/659
4 | class ClassWithoutMembersInjector
5 |
6 | @DependencyGraph(AppScope::class)
7 | interface TestGraph {
8 |
9 | val injector: MembersInjector<*>
10 |
11 | @Provides
12 | fun provideGenericMembersInjector(
13 | // No default value, we should report this missing
14 | instance: MembersInjector
15 | ): MembersInjector<*> {
16 | return instance
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/interop/dagger/PositionalAnnotationArgsWarning.fir.diag.txt:
--------------------------------------------------------------------------------
1 | /PositionalAnnotationArgsWarning.kt:(282,297): warning: Interop annotation @MergeComponent should use named arguments instead of positional arguments for better compatibility in Metro.
2 |
3 | /PositionalAnnotationArgsWarning.kt:(317,334): warning: Interop annotation @MergeComponent should use named arguments instead of positional arguments for better compatibility in Metro.
4 |
5 | /PositionalAnnotationArgsWarning.kt:(359,377): warning: Interop annotation @MergeComponent should use named arguments instead of positional arguments for better compatibility in Metro.
6 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/interop/dagger/QualifiedDaggerFactoryClassCanBeLoaded.kt:
--------------------------------------------------------------------------------
1 | // ENABLE_DAGGER_KSP
2 |
3 | // FILE: ExampleClass.java
4 | import javax.inject.Inject;
5 | import javax.inject.Named;
6 |
7 | @Named("qualifier")
8 | public class ExampleClass {
9 | @Inject public ExampleClass() {
10 |
11 | }
12 | }
13 |
14 | // FILE: ExampleGraph.kt
15 | import javax.inject.Named
16 |
17 | @DependencyGraph
18 | interface ExampleGraph {
19 | @Named("qualifier") val exampleClass: ExampleClass
20 | }
21 |
22 | fun box(): String {
23 | val graph = createGraph()
24 | assertNotNull(graph.exampleClass)
25 | return "OK"
26 | }
27 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/inject/ProvidingAConstructorInjectedTypeHasASpecificWarning.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // Originally from for https://github.com/ZacSweers/metro/issues/1193
3 |
4 | @DependencyGraph
5 | interface AComponent {
6 | val bar: Bar
7 |
8 | @Provides
9 | fun text(): String = "Hola"
10 | }
11 |
12 | @Inject
13 | class Bar(text: String)
14 |
15 | @DependencyGraph
16 | interface BComponent {
17 | val bar: Bar
18 |
19 | @Provides
20 | fun aComponent(): AComponent = createGraph()
21 |
22 | @Provides
23 | fun bar(aComponent: AComponent): Bar = aComponent.bar
24 | }
25 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/cycles/BindsCycleGraph.kt:
--------------------------------------------------------------------------------
1 | interface Foo
2 |
3 | @Inject class Bar(val fooProvider: Provider) : Foo
4 |
5 | /**
6 | * A component with a cycle in which a `@Binds` binding depends on the binding that has to be
7 | * deferred.
8 | */
9 | @DependencyGraph
10 | interface BindsCycleGraph {
11 | fun bar(): Bar
12 |
13 | @Binds fun foo(bar: Bar): Foo
14 | }
15 |
16 | /**
17 | * Tests that a cycle where a `@Binds` binding depends on a binding that has to be deferred works.
18 | */
19 | fun box(): String {
20 | val bindsCycleGraph = createGraph()
21 | assertNotNull(bindsCycleGraph.bar())
22 | return "OK"
23 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/inject/assisted/DefaultAssistedFactoryWithDefaultValues.kt:
--------------------------------------------------------------------------------
1 | // GENERATE_ASSISTED_FACTORIES
2 | @AssistedInject
3 | class ExampleClass(
4 | @Assisted val count: Int = 2,
5 | val message: String,
6 | )
7 |
8 | @DependencyGraph
9 | interface AppGraph {
10 | val factory: ExampleClass.Factory
11 | @Provides val string: String get() = "hello"
12 | }
13 |
14 | fun box(): String {
15 | val factory = createGraph().factory
16 | // Smoke test to ensure that the FIR-generated create() supports default args
17 | val created = factory.create()
18 | // Default value
19 | assertEquals(2, created.count)
20 | return "OK"
21 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/inject/member/MemberInjectorRequestAsProvidesParam.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/discussions/593
2 | class Foo {
3 | @Inject lateinit var message: String
4 | }
5 |
6 | @DependencyGraph
7 | interface AppGraph {
8 | val foo: Foo
9 |
10 | @Provides fun provideFoo(fooInjector: MembersInjector): Foo {
11 | return Foo().apply { fooInjector.injectMembers(this) }
12 | }
13 |
14 | @Provides
15 | fun provideMessage(): String = "message"
16 | }
17 |
18 | fun box(): String {
19 | val graph = createGraph()
20 | val foo = graph.foo
21 | assertEquals("message", foo.message)
22 | return "OK"
23 | }
24 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/dependencygraph/MissingBindingHintsShouldReportInternalOnlyIfInternal.kt:
--------------------------------------------------------------------------------
1 | // RUN_PIPELINE_TILL: FIR2IR
2 | // RENDER_IR_DIAGNOSTICS_FULL_TEXT
3 |
4 | // Ensures we don't try to mis-report indirect upstream modules as not visible
5 |
6 | // MODULE: core
7 | interface Base
8 |
9 | // MODULE: lib1(core)
10 | @Inject
11 | @ContributesBinding(String::class)
12 | class FooImpl : Base
13 |
14 | // MODULE: main(lib1 core)
15 | @DependencyGraph(AppScope::class)
16 | interface AppGraph {
17 | val base: Base
18 |
19 | val stringGraph: StringGraph
20 | }
21 |
22 | @GraphExtension(String::class)
23 | interface StringGraph
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/extensions/ExtensionsUsingDeferredTypesAreValid.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/pull/977
2 | @GraphExtension
3 | interface LoggedInGraph {
4 | val foo: Foo
5 | }
6 |
7 | @DependencyGraph
8 | @SingleIn(AppScope::class)
9 | interface AppGraph {
10 | val loggedInGraph: LoggedInGraph
11 | }
12 |
13 | @Inject @SingleIn(AppScope::class) class Foo(val fooProvider: Provider)
14 |
15 | fun box(): String {
16 | val graph = createGraph()
17 | val loggedInGraph = graph.loggedInGraph
18 | assertNotNull(loggedInGraph.foo)
19 | assertSame(loggedInGraph.foo, loggedInGraph.foo)
20 | return "OK"
21 | }
22 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/extensions/SimpleExtension.kt:
--------------------------------------------------------------------------------
1 | @GraphExtension
2 | interface LoggedInGraph {
3 | val id: String
4 | val count: Int
5 |
6 | @GraphExtension.Factory
7 | interface Factory {
8 | fun createLoggedInGraph(@Provides id: String): LoggedInGraph
9 | }
10 | }
11 |
12 | @DependencyGraph
13 | interface AppGraph : LoggedInGraph.Factory {
14 | @Provides fun provideCount(): Int = 3
15 | }
16 |
17 | fun box(): String {
18 | val graph = createGraph()
19 | val loggedInGraph = graph.createLoggedInGraph("123")
20 | assertEquals("123", loggedInGraph.id)
21 | assertEquals(3, loggedInGraph.count)
22 | return "OK"
23 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/graph/LazyAssistedFactoryGraphAccessor.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 |
3 | @DependencyGraph
4 | interface MyGraph {
5 | // Graph accessor returning a lazy-wrapped assisted factory should be an error
6 | abstract fun assistedFactory(): Lazy
7 | val assistedFactoryProp: Lazy
8 | }
9 |
10 | @AssistedFactory
11 | interface MyAssistedFactory {
12 | fun create(param: String): MyClass
13 | }
14 |
15 | @AssistedInject
16 | class MyClass(
17 | @Assisted val param: String,
18 | val dependency: String
19 | )
20 |
--------------------------------------------------------------------------------
/compiler-compat/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins { alias(libs.plugins.kotlin.jvm) }
4 |
5 | kotlin {
6 | compilerOptions {
7 | freeCompilerArgs.add("-Xcontext-parameters")
8 | optIn.addAll(
9 | "org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi",
10 | "org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI",
11 | )
12 | }
13 | }
14 |
15 | dependencies {
16 | compileOnly(libs.kotlin.compiler)
17 | compileOnly(libs.kotlin.stdlib)
18 |
19 | testImplementation(libs.junit)
20 | testImplementation(libs.kotlin.test)
21 | testImplementation(libs.truth)
22 | }
23 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/diagnostic/interop/dagger/BindsOptionalOfDiagnostics.kt:
--------------------------------------------------------------------------------
1 | // RENDER_DIAGNOSTICS_FULL_TEXT
2 | // ENABLE_DAGGER_INTEROP
3 |
4 | import dagger.BindsOptionalOf
5 | import java.util.Optional
6 |
7 | @BindingContainer
8 | interface Bindings {
9 | @BindsOptionalOf
10 | fun providerString(): Provider
11 |
12 | @BindsOptionalOf
13 | fun lazyInt(): Lazy
14 |
15 | @BindsOptionalOf
16 | fun providerOfLazyLong(): Provider>
17 |
18 | @BindsOptionalOf
19 | fun optionalOptional(): Optional
20 | }
21 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/aggregation/ContributedBindingContainerReplacements.kt:
--------------------------------------------------------------------------------
1 | // Similar to the BindingContainerViaAnnotation test but contributed
2 | @DependencyGraph(AppScope::class)
3 | interface AppGraph {
4 | val int: Int
5 | }
6 |
7 | @ContributesTo(AppScope::class)
8 | @BindingContainer
9 | object IntBinding1 {
10 | @Provides fun provideInt(): Int = 1
11 | }
12 |
13 | @ContributesTo(AppScope::class, replaces = [IntBinding1::class])
14 | @BindingContainer
15 | object IntBinding2 {
16 | @Provides fun provideInt(): Int = 2
17 | }
18 |
19 | fun box(): String {
20 | val graph = createGraph()
21 | assertEquals(2, graph.int)
22 | return "OK"
23 | }
24 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/provides/QualifiersOnDifferentAnnotationSites.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/issues/807
2 | @DependencyGraph
3 | interface Graph {
4 | @Multibinds(allowEmpty = true)
5 | val set1: Set
6 |
7 | @Named("s2")
8 | val set2: Set
9 |
10 | @Provides
11 | @IntoSet
12 | @Named("s2")
13 | val provideValue1: Int
14 | get() = 1
15 |
16 | @Provides
17 | @IntoSet
18 | @get:Named("s2")
19 | val provideValue2: Int
20 | get() = 2
21 | }
22 |
23 | fun box(): String {
24 | val graph = createGraph()
25 | assertEquals(emptySet(), graph.set1)
26 | assertEquals(setOf(1, 2), graph.set2)
27 | return "OK"
28 | }
--------------------------------------------------------------------------------
/samples/interop/customAnnotations-kotlinInject/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2025 Zac Sweers
2 | // SPDX-License-Identifier: Apache-2.0
3 | plugins {
4 | alias(libs.plugins.kotlin.multiplatform)
5 | id("dev.zacsweers.metro")
6 | }
7 |
8 | kotlin {
9 | jvm()
10 |
11 | sourceSets {
12 | commonMain {
13 | dependencies {
14 | implementation(libs.kotlinInject.runtime)
15 | implementation(libs.kotlinInject.anvil.runtime)
16 | }
17 | }
18 | commonTest { dependencies { implementation(libs.kotlin.test) } }
19 | }
20 | }
21 |
22 | metro {
23 | interop {
24 | includeKotlinInject()
25 | includeAnvilForKotlinInject()
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/OverrideCompatibleAccessorsFromContributedInterface.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface ExampleGraph {
3 |
4 | @DependencyGraph.Factory
5 | interface Factory {
6 | fun create(@Includes serviceProvider: ServiceProvider): ExampleGraph
7 | }
8 | }
9 |
10 | @DependencyGraph(AppScope::class)
11 | interface AppGraph {
12 | val int: Int
13 |
14 | @Provides
15 | fun providesInt(): Int = 3
16 | }
17 |
18 | @ContributesTo(AppScope::class)
19 | interface ServiceProvider {
20 | val int: Int
21 | }
22 |
23 | fun box(): String {
24 | val appGraph = createGraph()
25 | assertEquals(appGraph.int, 3)
26 | return "OK"
27 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/extensions/FieldInjectorInGraphExtensionContainer.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph(AppScope::class)
2 | interface MainGraph {
3 | val childGraph: ChildGraph
4 | }
5 |
6 | @GraphExtension(bindingContainers = [ChildModule::class])
7 | interface ChildGraph {
8 | fun injectFoo(instance: Foo)
9 | }
10 |
11 | @BindingContainer
12 | object ChildModule {
13 | @Provides fun provideTitle(): String = "Foo"
14 | }
15 |
16 | class Foo {
17 | @Inject lateinit var title: String
18 | }
19 |
20 | fun box(): String {
21 | val foo = Foo()
22 | createGraph().childGraph.injectFoo(foo)
23 | assertEquals("Foo", foo.title)
24 | return "OK"
25 | }
26 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/extensions/MultipleExtensionFactoriesAreValid.kt:
--------------------------------------------------------------------------------
1 | // https://github.com/ZacSweers/metro/issues/1143
2 |
3 | @DependencyGraph(AppScope::class)
4 | interface AppGraph {
5 | val loggedInGraphFactory: LoggedInGraph.Factory
6 |
7 | fun userGraphFactory(): LoggedInGraph.Factory
8 | }
9 |
10 | @GraphExtension
11 | interface LoggedInGraph {
12 | @GraphExtension.Factory
13 | interface Factory {
14 | fun create(): LoggedInGraph
15 | }
16 | }
17 |
18 | fun box(): String {
19 | val graph = createGraph()
20 | assertNotNull(graph.loggedInGraphFactory)
21 | assertNotNull(graph.userGraphFactory())
22 | return "OK"
23 | }
24 |
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/dependencygraph/bindingcontainers/BindingContainerViaCreator.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | val string: String
4 |
5 | @DependencyGraph.Factory
6 | interface Factory {
7 | fun create(@Includes stringBindings: StringBindings): AppGraph
8 | }
9 | }
10 |
11 | @BindingContainer
12 | class StringBindings(private val value: String) {
13 | @Provides
14 | fun provideString(): String {
15 | return "string value: $value"
16 | }
17 | }
18 |
19 | fun box(): String {
20 | val graph = createGraphFactory().create(StringBindings("hello"))
21 | assertEquals("string value: hello", graph.string)
22 | return "OK"
23 | }
--------------------------------------------------------------------------------
/compiler-tests/src/test/data/box/multibindings/LazyMemberInjectedBindings.kt:
--------------------------------------------------------------------------------
1 | @DependencyGraph
2 | interface AppGraph {
3 | fun inject(target: ExampleClass)
4 |
5 | @Provides @IntoSet fun provideInt(): Int = 3
6 | @Provides @IntoMap @IntKey(3) fun provideIntIntoMap(): Int = 3
7 | }
8 |
9 | class ExampleClass {
10 | @Inject lateinit var intSet: Lazy>
11 | @Inject lateinit var intMap: Lazy