Skip to content
This repository has been archived by the owner on Sep 3, 2023. It is now read-only.

Commit

Permalink
Release 0.3.1
Browse files Browse the repository at this point in the history
  • Loading branch information
afollestad committed Aug 3, 2019
1 parent 08a282c commit 066e49b
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 79 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ constructor parameters, they are filled for you by generated code.

```gradle
dependencies {
implementation "com.afollestad:ulfberht:0.3.0"
kapt "com.afollestad:ulfbert-processor:0.3.0"
implementation "com.afollestad:ulfberht:0.3.1"
kapt "com.afollestad:ulfbert-processor:0.3.1"
}
```

Expand Down
6 changes: 2 additions & 4 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
0.3.0
0.3.1

* Fixes to generics support. E.g., you could provide `SomeClass<String>` and `SomeClass<Int>`
separately and it'll work as you'd think.
* Other bug fixes.
* Important generics support bug fixes.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ interface BaseComponent : ScopeObserver {
genericArgs: Set<KClass<*>> = emptySet(),
qualifier: String? = null
): T {
return getProvider(
return getProvider<T>(
wantedType = wantedType,
genericArgs = genericArgs,
qualifier = qualifier,
Expand All @@ -52,7 +52,7 @@ interface BaseComponent : ScopeObserver {
}

fun <T : Any> getProvider(
wantedType: KClass<T>,
wantedType: KClass<*>,
genericArgs: Set<KClass<*>> = emptySet(),
qualifier: String? = null,
calledBy: BaseComponent? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ interface BaseModule {

/** Retrieves a provided class via its [Provider]. */
fun <T : Any> get(
wantedType: KClass<T>,
wantedType: KClass<*>,
genericArgs: Set<KClass<*>> = emptySet(),
qualifier: String? = null
): T {
return getProvider(
return getProvider<T>(
wantedType = wantedType,
qualifier = qualifier,
calledBy = null
Expand All @@ -46,7 +46,7 @@ interface BaseModule {

/** Retrieves a [Provider] for a provided class. */
fun <T : Any> getProvider(
wantedType: KClass<T>,
wantedType: KClass<*>,
genericArgs: Set<KClass<*>> = emptySet(),
qualifier: String? = null,
calledBy: BaseComponent? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class ComponentParent_Component(
override var runtimeDependencies: Map<String?, Any>? = null

override fun <T : Any> getProvider(
wantedType: KClass<T>,
wantedType: KClass<*>,
genericArgs: Set<KClass<*>>,
qualifier: String?,
calledBy: BaseComponent?
Expand All @@ -72,7 +72,7 @@ class ComponentChild1_Component(
override var runtimeDependencies: Map<String?, Any>? = null

override fun <T : Any> getProvider(
wantedType: KClass<T>,
wantedType: KClass<*>,
genericArgs: Set<KClass<*>>,
qualifier: String?,
calledBy: BaseComponent?
Expand All @@ -96,7 +96,7 @@ class ComponentChild2_Component(
override var runtimeDependencies: Map<String?, Any>? = null

override fun <T : Any> getProvider(
wantedType: KClass<T>,
wantedType: KClass<*>,
genericArgs: Set<KClass<*>>,
qualifier: String?,
calledBy: BaseComponent?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ abstract class TestBaseModule : BaseModule {
override val cachedProviders: MutableMap<String, Provider<*>> = mutableMapOf()

override fun <T : Any> getProvider(
wantedType: KClass<T>,
wantedType: KClass<*>,
genericArgs: Set<KClass<*>>,
qualifier: String?,
calledBy: BaseComponent?
Expand Down
4 changes: 2 additions & 2 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ ext.versions = [
minSdk : 19,
compileSdk : 29,
buildTools : '29.0.0',
publishVersion : '0.3.0',
publishVersionCode: 7,
publishVersion : '0.3.1',
publishVersionCode: 8,

gradlePlugin : '3.4.2',
spotlessPlugin : '3.24.0',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import com.afollestad.ulfberht.util.Types.BASE_COMPONENT
import com.afollestad.ulfberht.util.Types.BASE_MODULE
import com.afollestad.ulfberht.util.Types.GET_SCOPE_METHOD
import com.afollestad.ulfberht.util.Types.KCLASS_OF_ANY
import com.afollestad.ulfberht.util.Types.KCLASS_OF_T
import com.afollestad.ulfberht.util.Types.LIFECYCLE_EVENT_ON_DESTROY
import com.afollestad.ulfberht.util.Types.LIFECYCLE_OBSERVER
import com.afollestad.ulfberht.util.Types.LOGGER
Expand Down Expand Up @@ -228,10 +227,11 @@ internal class ComponentBuilder(
"""
if ($CALLED_BY === this) return null
$MODULES_LIST_NAME.forEach { module ->
module.$GET_PROVIDER_NAME($WANTED_TYPE, $GENERIC_ARGS, $QUALIFIER, $CALLED_BY ?: this)
module.$GET_PROVIDER_NAME<%T>($WANTED_TYPE, $GENERIC_ARGS, $QUALIFIER, $CALLED_BY ?: this)
?.let { return it }
}
""".trimIndent() + "\n"
""".trimIndent() + "\n",
TYPE_VARIABLE_T
)
)
}
Expand All @@ -249,7 +249,7 @@ internal class ComponentBuilder(

return FunSpec.builder(GET_PROVIDER_NAME)
.addAnnotation(SUPPRESS_UNCHECKED_CAST)
.addParameter(WANTED_TYPE, KCLASS_OF_T)
.addParameter(WANTED_TYPE, KCLASS_OF_ANY)
.addParameter(GENERIC_ARGS, SET.parameterizedBy(KCLASS_OF_ANY))
.addParameter(QUALIFIER, NULLABLE_KOTLIN_STRING)
.addParameter(CALLED_BY, NULLABLE_BASE_COMPONENT)
Expand Down Expand Up @@ -293,7 +293,7 @@ internal class ComponentBuilder(
add(")")
}
code.applyIf(qualifier != null) {
add(", $QUALIFIER = %S)", qualifier)
add(", $QUALIFIER = %S", qualifier)
}
code.add(")")
code.applyIf(fieldTypeAndArgs.hasGenericArgs) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,32 @@ import com.afollestad.ulfberht.util.Names.CACHED_PROVIDERS_NAME
import com.afollestad.ulfberht.util.Names.CALLED_BY
import com.afollestad.ulfberht.util.Names.CLASS_HEADER
import com.afollestad.ulfberht.util.Names.COMPONENT_PARAM_NAME
import com.afollestad.ulfberht.util.Names.FACTORY_EXTENSION_NAME
import com.afollestad.ulfberht.util.Names.GENERIC_ARGS
import com.afollestad.ulfberht.util.Names.GET_PROVIDER_NAME
import com.afollestad.ulfberht.util.Names.IS_SUBCLASS_OF_EXTENSION_NAME
import com.afollestad.ulfberht.util.Names.LIBRARY_PACKAGE
import com.afollestad.ulfberht.util.Names.MODULE_NAME_SUFFIX
import com.afollestad.ulfberht.util.Names.FACTORY_EXTENSION_NAME
import com.afollestad.ulfberht.util.Names.GENERIC_ARGS
import com.afollestad.ulfberht.util.Names.QUALIFIER
import com.afollestad.ulfberht.util.Names.SINGLETON_PROVIDER_EXTENSION_NAME
import com.afollestad.ulfberht.util.Names.WANTED_TYPE
import com.afollestad.ulfberht.util.ProcessorUtil.applyIf
import com.afollestad.ulfberht.util.ProcessorUtil.asFileName
import com.afollestad.ulfberht.util.ProcessorUtil.asTypeElement
import com.afollestad.ulfberht.util.ProcessorUtil.error
import com.afollestad.ulfberht.util.ProcessorUtil.filterMethods
import com.afollestad.ulfberht.util.ProcessorUtil.getAnnotationMirror
import com.afollestad.ulfberht.util.ProcessorUtil.getConstructorParamsTypesAndArgs
import com.afollestad.ulfberht.util.ProcessorUtil.getFullClassName
import com.afollestad.ulfberht.util.ProcessorUtil.getMethodParamsTypeAndArgs
import com.afollestad.ulfberht.util.ProcessorUtil.getPackage
import com.afollestad.ulfberht.util.ProcessorUtil.getConstructorParamsAndQualifiers
import com.afollestad.ulfberht.util.ProcessorUtil.hasAnnotationMirror
import com.afollestad.ulfberht.util.ProcessorUtil.isAbstractClass
import com.afollestad.ulfberht.util.ProcessorUtil.qualifier
import com.afollestad.ulfberht.util.ProcessorUtil.asFileName
import com.afollestad.ulfberht.util.ProcessorUtil.error
import com.afollestad.ulfberht.util.ProcessorUtil.getMethodParamsAndQualifiers
import com.afollestad.ulfberht.util.ProcessorUtil.asTypeAndArgs
import com.afollestad.ulfberht.util.ProcessorUtil.returnTypeAsTypeAndArgs
import com.afollestad.ulfberht.util.TypeAndArgs
import com.afollestad.ulfberht.util.Types.BASE_COMPONENT
import com.afollestad.ulfberht.util.Types.BASE_MODULE
import com.afollestad.ulfberht.util.Types.KCLASS_OF_ANY
import com.afollestad.ulfberht.util.Types.KCLASS_OF_T
import com.afollestad.ulfberht.util.Types.NULLABLE_BASE_COMPONENT
import com.afollestad.ulfberht.util.Types.NULLABLE_KOTLIN_STRING
import com.afollestad.ulfberht.util.Types.PROVIDER
Expand Down Expand Up @@ -218,7 +216,7 @@ internal class ModuleBuilder(
.addAnnotation(SUPPRESS_UNCHECKED_CAST)
.addModifiers(OVERRIDE)
.addTypeVariable(TYPE_VARIABLE_T)
.addParameter(WANTED_TYPE, KCLASS_OF_T)
.addParameter(WANTED_TYPE, KCLASS_OF_ANY)
.addParameter(GENERIC_ARGS, SET.parameterizedBy(KCLASS_OF_ANY))
.addParameter(QUALIFIER, NULLABLE_KOTLIN_STRING)
.addParameter(CALLED_BY, NULLABLE_BASE_COMPONENT)
Expand All @@ -238,39 +236,39 @@ internal class ModuleBuilder(
val parameterType = method.parameters.single()
.asType()

val returnType = method.returnType
if (!environment.typeUtils.isSubtype(parameterType, returnType)) {
if (!environment.typeUtils.isSubtype(parameterType, method.returnType)) {
environment.error(
"@Binds method ${method.simpleName}() parameter of type " +
"$parameterType must be a subclass of $returnType"
"$parameterType must be a subclass of ${method.returnType}"
)
return null
}

val returnTypeAndArgs = returnType.asTypeAndArgs(environment)
val returnTypeAndArgs = method.returnTypeAsTypeAndArgs(environment)
val methodName = method.simpleName.toString()
val providerMethodName = method.providerGetName()

providedTypeMethodNameMap[returnTypeAndArgs] =
MethodNameAndQualifier(
name = methodName,
qualifier = method.getAnnotationMirror<Binds>().qualifier
qualifier = returnTypeAndArgs.qualifier
)

val fieldTypeConstructorParams = parameterType
.asTypeElement()
.getConstructorParamsAndQualifiers(environment)
.getConstructorParamsTypesAndArgs(environment)

val code = CodeBlock.builder()
.apply {
val paramBreak = fieldTypeConstructorParams.lineBreak
val factoryNamePrefix = if (fieldTypeConstructorParams.size > 1) " " else " "
val factoryNamePrefix = if (fieldTypeConstructorParams.count() > 1) " " else " "

add("return %N {$paramBreak$factoryNamePrefix%T(", providerMethodName, parameterType)
if (!construct(fieldTypeConstructorParams, returnTypeAndArgs.fullType)) {
return null
}
if (fieldTypeConstructorParams.size > 1) add("\n ")

if (fieldTypeConstructorParams.count() > 1) add("\n ")
add(") $paramBreak}\n")
}
.build()
Expand All @@ -288,27 +286,29 @@ internal class ModuleBuilder(
): FunSpec? {
val originalMethodName = method.simpleName.toString()
val newMethodName = "$PROVIDE_FUNCTION_PREFIX${originalMethodName.capitalize()}"
val returnTypeAndArgs = method.returnType.asTypeAndArgs(environment)
val returnTypeAndArgs = method.returnTypeAsTypeAndArgs(environment)

providedTypeMethodNameMap[returnTypeAndArgs] =
MethodNameAndQualifier(
name = newMethodName,
qualifier = method.getAnnotationMirror<Provides>().qualifier
qualifier = returnTypeAndArgs.qualifier
)

val code = CodeBlock.builder()
.apply {
val paramBreak = method.parameters.lineBreak
val factoryNamePrefix = if (method.parameters.size > 1) " " else " "
val methodParams = method.getMethodParamsTypeAndArgs(environment)
val paramBreak = methodParams.lineBreak
val factoryNamePrefix = if (methodParams.count() > 1) " " else " "

add(
"return %N {$paramBreak$factoryNamePrefix%N(",
method.providerGetName(),
originalMethodName
)
if (!construct(method.getMethodParamsAndQualifiers(), returnTypeAndArgs.fullType)) {
if (!construct(methodParams, returnTypeAndArgs.fullType)) {
return null
}

if (method.parameters.size > 1) add("\n ")
add(") $paramBreak}\n")
}
Expand All @@ -322,21 +322,32 @@ internal class ModuleBuilder(
}

private fun CodeBlock.Builder.construct(
params: List<Pair<TypeName, String?>>,
params: Sequence<TypeAndArgs>,
returnType: TypeName
): Boolean {
apply {
val indent = params.indent
val paramBreak = params.lineBreak

for ((index, typeAndQualifier) in params.withIndex()) {
val (type, qualifier) = typeAndQualifier
if (index > 0) add(",")
for ((paramIndex, typeAndArgs) in params.withIndex()) {
val type = typeAndArgs.erasedType
val qualifier = typeAndArgs.qualifier
if (paramIndex > 0) add(",")

add("$paramBreak${indent}get(%T::class", type)
if (typeAndArgs.hasGenericArgs) {
add(", $GENERIC_ARGS = setOf(")
for ((argIndex, typeArg) in typeAndArgs.genericArgs.withIndex()) {
if (argIndex > 0) add(", ")
add("%T::class", typeArg)
}
add(")")
}
if (qualifier != null) {
add("$paramBreak${indent}get(%T::class, $QUALIFIER = %S)", type, qualifier)
} else {
add("$paramBreak${indent}get(%T::class)", type)
add(", $QUALIFIER = %S", qualifier)
}
add(")")

if (!dependencyGraph.put(returnType, type)) {
// Dependency issue detected
return false
Expand All @@ -346,9 +357,9 @@ internal class ModuleBuilder(
return true
}

private val List<*>.indent get() = if (size > 1) " " else ""
private val Sequence<*>.indent get() = if (count() > 1) " " else ""

private val List<*>.lineBreak get() = if (size > 1) "\n" else ""
private val Sequence<*>.lineBreak get() = if (count() > 1) "\n" else ""

private fun Element.providerGetName(): String {
return if (hasAnnotationMirror<Singleton>()) {
Expand Down
Loading

0 comments on commit 066e49b

Please sign in to comment.