Skip to content

Commit

Permalink
Merge branch 'compose-1.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
raamcosta committed Jan 22, 2023
2 parents 65e05da + f1c1b8f commit eefc631
Show file tree
Hide file tree
Showing 27 changed files with 522 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -254,12 +254,13 @@ internal class AnimatedNavHostEngine(
destination,
navBackStackEntry,
navController,
this
this,
dependenciesContainerBuilder
)
}

if (contentWrapper == null) {
with(destination) { scope.Content(dependenciesContainerBuilder) }
with(destination) { scope.Content() }
} else {
contentWrapper as DestinationLambda<T>
contentWrapper(scope)
Expand All @@ -281,12 +282,13 @@ internal class AnimatedNavHostEngine(
destination,
navBackStackEntry,
navController,
this
this,
dependenciesContainerBuilder
)
}

if (contentWrapper == null) {
with(destination) { scope.Content(dependenciesContainerBuilder) }
with(destination) { scope.Content() }
} else {
contentWrapper as DestinationLambda<T>
contentWrapper(scope)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,47 @@ package com.ramcosta.composedestinations.animations.scope
import androidx.compose.animation.AnimatedVisibilityScope
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.runtime.Composable
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavController
import com.ramcosta.composedestinations.navigation.DependenciesContainerBuilder
import com.ramcosta.composedestinations.scope.*
import com.ramcosta.composedestinations.spec.DestinationSpec

@ExperimentalAnimationApi
internal class AnimatedDestinationScopeImpl<T>(
destination: DestinationSpec<T>,
navBackStackEntry: NavBackStackEntry,
navController: NavController,
override val destination: DestinationSpec<T>,
override val navBackStackEntry: NavBackStackEntry,
override val navController: NavController,
animatedVisibilityScope: AnimatedVisibilityScope,
) : DestinationScopeImpl<T>(
destination,
navBackStackEntry,
navController,
), AnimatedDestinationScope<T>, AnimatedVisibilityScope by animatedVisibilityScope
override val dependenciesContainerBuilder: @Composable DependenciesContainerBuilder<*>.() -> Unit,
) : DestinationScopeImpl<T>(),
AnimatedDestinationScope<T>,
AnimatedVisibilityScope by animatedVisibilityScope

internal class BottomSheetDestinationScopeImpl<T>(
destination: DestinationSpec<T>,
navBackStackEntry: NavBackStackEntry,
navController: NavController,
override val destination: DestinationSpec<T>,
override val navBackStackEntry: NavBackStackEntry,
override val navController: NavController,
columnScope: ColumnScope,
) : DestinationScopeImpl<T>(
destination,
navBackStackEntry,
navController,
), BottomSheetDestinationScope<T>, ColumnScope by columnScope
override val dependenciesContainerBuilder: @Composable DependenciesContainerBuilder<*>.() -> Unit,
) : DestinationScopeImpl<T>(),
BottomSheetDestinationScope<T>,
ColumnScope by columnScope

@ExperimentalAnimationApi
internal class AnimatedNavGraphBuilderDestinationScopeImpl<T>(
destination: DestinationSpec<T>,
navBackStackEntry: NavBackStackEntry,
override val destination: DestinationSpec<T>,
override val navBackStackEntry: NavBackStackEntry,
animatedVisibilityScope: AnimatedVisibilityScope,
) : NavGraphBuilderDestinationScopeImpl<T>(
destination,
navBackStackEntry,
), AnimatedNavGraphBuilderDestinationScope<T>, AnimatedVisibilityScope by animatedVisibilityScope
) : NavGraphBuilderDestinationScopeImpl<T>(),
AnimatedNavGraphBuilderDestinationScope<T>,
AnimatedVisibilityScope by animatedVisibilityScope

internal class BottomSheetNavGraphBuilderDestinationScopeImpl<T>(
destination: DestinationSpec<T>,
navBackStackEntry: NavBackStackEntry,
override val destination: DestinationSpec<T>,
override val navBackStackEntry: NavBackStackEntry,
columnScope: ColumnScope,
) : NavGraphBuilderDestinationScopeImpl<T>(
destination,
navBackStackEntry,
), BottomSheetNavGraphBuilderDestinationScope<T>, ColumnScope by columnScope
) : NavGraphBuilderDestinationScopeImpl<T>(),
BottomSheetNavGraphBuilderDestinationScope<T>,
ColumnScope by columnScope
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const val DESTINATION_ANNOTATION_ROUTE_ARGUMENT = "route"
const val DESTINATION_ANNOTATION_START_ARGUMENT = "start"
const val DESTINATION_ANNOTATION_NAV_GRAPH_ARGUMENT = "navGraph"
const val DESTINATION_ANNOTATION_STYLE_ARGUMENT = "style"
const val DESTINATION_ANNOTATION_WRAPPERS_ARGUMENT = "wrappers"
const val DESTINATION_ANNOTATION_NAV_ARGS_DELEGATE_ARGUMENT = "navArgsDelegate"
const val DESTINATION_ANNOTATION_DEEP_LINKS_ARGUMENT = "deepLinks"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface DestinationGeneratingParams {
val requireOptInAnnotationTypes: List<Importable>
val navArgsDelegateType: NavArgsDelegateType?
val activityDestinationParams: ActivityDestinationParams?
val composableWrappers: List<Importable>
}

data class RawDestinationGenParams(
Expand All @@ -31,5 +32,6 @@ data class RawDestinationGenParams(
override val composableReceiverSimpleName: String?,
override val requireOptInAnnotationTypes: List<Importable>,
override val navArgsDelegateType: NavArgsDelegateType?,
override val activityDestinationParams: ActivityDestinationParams? = null
override val activityDestinationParams: ActivityDestinationParams? = null,
override val composableWrappers: List<Importable>
): DestinationGeneratingParams
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,7 @@ class SingleDestinationWriter(

return """
@Composable
override fun DestinationScope<${navArgsDataClassName()}>.Content(
dependenciesContainerBuilder: @Composable DependenciesContainerBuilder<${navArgsDataClassName()}>.() -> Unit
) {
override fun DestinationScope<${navArgsDataClassName()}>.Content() {
%s1
}
""".trimIndent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,54 @@ class DestinationContentFunctionWriter(

val (args, needsDependencyContainer) = prepareArguments()
if (needsDependencyContainer) {
val rememberPlaceholder = importableHelper.addAndGetPlaceholder(
Importable(
"remember",
"androidx.compose.runtime.remember"
)
)
functionCallCode += "\t\tval dependencyContainer = $rememberPlaceholder { DestinationDependenciesContainer(this) }\n"
functionCallCode += "\t\tdependencyContainer.apply { dependenciesContainerBuilder() }\n\n"
functionCallCode += "\t\tval dependencyContainer = buildDependencies()\n"
}

if (navArgs.isNotEmpty() && destination.navArgsDelegateType == null) {
functionCallCode += "\t\tval (${argNamesInLine()}) = navArgs\n"
}

val receiver = prepareReceiver()
functionCallCode += "\t\t$receiver${composableName}($args)"
functionCallCode += wrappingPrefix()

val composableCall = "\t\t${prepareReceiver()}${composableName}($args)"

functionCallCode += if (composableWrappers.isEmpty()) composableCall
else "\t" + composableCall.replace("\n", "\n\t")

functionCallCode += wrappingSuffix()

return functionCallCode.toString()
}

private fun DestinationGeneratingParams.wrappingPrefix(): String {
val wrappingPrefix = when {
composableWrappers.size == 1 -> {
val wrapPlaceholder = importableHelper.addAndGetPlaceholder(
Importable("Wrap", "com.ramcosta.composedestinations.wrapper.Wrap")
)
"\t\t$wrapPlaceholder(${importableHelper.addAndGetPlaceholder(composableWrappers.first())}) {\n"
}

composableWrappers.isNotEmpty() -> {
val wrapPlaceholder = importableHelper.addAndGetPlaceholder(
Importable("Wrap", "com.ramcosta.composedestinations.wrapper.Wrap")
)
"\t\t$wrapPlaceholder(${composableWrappers.joinToString(", ") { importableHelper.addAndGetPlaceholder(it) }}) {\n"
}

else -> ""
}
return wrappingPrefix
}

private fun DestinationGeneratingParams.wrappingSuffix(): String {
return if (composableWrappers.isNotEmpty()) {
"\n\t\t}"
} else {
""
}
}

private fun argNamesInLine(): String {
return navArgs.joinToString(", ") { it.name }
}
Expand Down Expand Up @@ -132,10 +160,18 @@ class DestinationContentFunctionWriter(

!parameter.hasDefault -> {
needsDependencyContainer = true

val requirePlaceholder = importableHelper.addAndGetPlaceholder(
Importable(
"require",
"com.ramcosta.composedestinations.navigation.require"
)
)

if (parameter.isMarkedNavHostParam) {
"dependencyContainer.require(true)"
"dependencyContainer.$requirePlaceholder(true)"
} else {
"dependencyContainer.require()"
"dependencyContainer.$requirePlaceholder()"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ object DefaultParameterValueReader {
): DefaultValue {

var result = auxText
if (result.contains("(")) {
if (!result.firstParenthesisIsClosing() && result.contains("(")) {
result = result.defaultValueCodeWithFunctionCalls()
} else {
val index = result.indexOfFirst { it == ' ' || it == ',' || it == '\n' || it == ')' }
Expand Down Expand Up @@ -130,6 +130,13 @@ object DefaultParameterValueReader {
}
}

private fun String.firstParenthesisIsClosing(): Boolean {
val indexOfFirstOpening = this.indexOfFirst { it == '(' }
val indexOfFirstClosing = this.indexOfFirst { it == ')' }

return indexOfFirstClosing < indexOfFirstOpening
}

private fun String.defaultValueCodeWithFunctionCalls(): String {
var idx = 0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package com.ramcosta.composedestinations.ksp.processors
import com.google.devtools.ksp.*
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.*
import com.google.devtools.ksp.symbol.ClassKind
import com.ramcosta.composedestinations.codegen.commons.*
import com.ramcosta.composedestinations.codegen.facades.Logger
import com.ramcosta.composedestinations.codegen.model.*
import com.ramcosta.composedestinations.codegen.model.Visibility
import com.ramcosta.composedestinations.ksp.commons.*
Expand Down Expand Up @@ -94,7 +94,8 @@ class KspToCodeGenDestinationsMapper(
action = activityDestinationAnnotation.getNullableString("action"),
dataUri = activityDestinationAnnotation.getNullableString("dataUri"),
dataPattern = activityDestinationAnnotation.getNullableString("dataPattern")
)
),
composableWrappers = emptyList()
)
}

Expand Down Expand Up @@ -151,6 +152,7 @@ class KspToCodeGenDestinationsMapper(
cleanRoute = cleanRoute,
destinationStyleType = destinationAnnotation.getDestinationStyleType(composableName),
parameters = parameters.map { it.toParameter(composableName) },
composableWrappers = destinationAnnotation.getDestinationWrappers(),
deepLinks = deepLinksAnnotations.map { it.toDeepLink() },
navGraphInfo = getNavGraphInfo(destinationAnnotation),
composableReceiverSimpleName = extensionReceiver?.toString(),
Expand Down Expand Up @@ -259,6 +261,21 @@ class KspToCodeGenDestinationsMapper(
return DestinationStyleType.Animated(type, ksStyleType.declaration.findAllRequireOptInAnnotations())
}

private fun KSAnnotation.getDestinationWrappers(): List<Importable> {
val ksTypes = findArgumentValue<ArrayList<KSType>>(DESTINATION_ANNOTATION_WRAPPERS_ARGUMENT)!!

return ksTypes.map {
if ((it.declaration as? KSClassDeclaration)?.classKind != ClassKind.OBJECT) {
throw IllegalDestinationsSetup("DestinationWrappers need to be objects! (check ${it.declaration.simpleName.asString()})")
}

Importable(
it.declaration.simpleName.asString(),
it.declaration.qualifiedName!!.asString()
)
}
}

private fun KSAnnotation.prepareRoute(composableName: String): String {
val cleanRoute = findArgumentValue<String>(DESTINATION_ANNOTATION_ROUTE_ARGUMENT)!!
return if (cleanRoute == DESTINATION_ANNOTATION_DEFAULT_ROUTE_PLACEHOLDER) composableName.toSnakeCase() else cleanRoute
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ class DefaultParameterValueReaderTest {
argType = "String",
expected = DefaultValue("\"defaultArg\"")
),
TestCase(
lineText = " arg1: String? = null,",
argName = "arg1",
argType = "String",
expected = DefaultValue("null")
),
TestCase(
lineText = "internal fun EditRitual(nav: RespawnNavigator, ritualId: Uuid? = null) = AnalyticsScreen(\"EditRitual\") {",
argName = "ritualId",
argType = "Uuid",
imports = listOf("com.ramcosta.package.Uuid"),
expected = DefaultValue("null", listOf())
),
TestCase(
lineText = " arg1: String? = \"defaultArg\"",
argName = "arg1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,11 @@ internal class WearNavHostEngine(
}

internal class WearDestinationScope<T>(
destination: DestinationSpec<T>,
navBackStackEntry: NavBackStackEntry,
navController: NavController,
) : DestinationScopeImpl<T>(
destination,
navBackStackEntry,
navController,
)
override val destination: DestinationSpec<T>,
override val navBackStackEntry: NavBackStackEntry,
override val navController: NavController,
override val dependenciesContainerBuilder: @Composable DependenciesContainerBuilder<*>.() -> Unit,
) : DestinationScopeImpl<T>()

@Suppress("UNCHECKED_CAST")
@Composable
Expand All @@ -146,12 +143,13 @@ internal class WearNavHostEngine(
WearDestinationScope(
destination,
navBackStackEntry,
navController
navController,
dependenciesContainerBuilder
)
}

if (contentLambda == null) {
with(destination) { scope.Content(dependenciesContainerBuilder) }
with(destination) { scope.Content() }
} else {
contentLambda as DestinationLambda<T>
contentLambda(scope)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,13 @@ internal class DefaultNavHostEngine : NavHostEngine {
DestinationScopeImpl.Default(
destination,
navBackStackEntry,
navController
navController,
dependenciesContainerBuilder,
)
}

if (contentLambda == null) {
with(destination) { scope.Content(dependenciesContainerBuilder) }
with(destination) { scope.Content() }
} else {
contentLambda as DestinationLambda<T>
contentLambda(scope)
Expand Down
Loading

0 comments on commit eefc631

Please sign in to comment.