Skip to content

Commit

Permalink
Merge branch 'v2-compose-1.6'
Browse files Browse the repository at this point in the history
# Conflicts:
#	compose-destinations-codegen/src/main/java/com/ramcosta/composedestinations/codegen/writers/sub/DestinationContentFunctionWriter.kt
  • Loading branch information
raamcosta committed May 22, 2024
2 parents f2bf917 + 39f3150 commit dca44f5
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private fun RawNavGraphTree.addStartRouteTreeToParticipantsOfPublicAPIs() {
if (startDestination != null || startNestedGraph != null) {
throw IllegalDestinationsSetup(
"${annotationType.preferredSimpleName} defines external route with `start = true` but " +
"'${(startDestination?.composableName ?: startNestedGraph?.annotationType?.preferredSimpleName)}' is also defined " +
"'${(startDestination?.annotatedName ?: startNestedGraph?.annotationType?.preferredSimpleName)}' is also defined " +
"as its start. Use external annotations with `start = true` only when start route is not in the current module!"
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package com.ramcosta.composedestinations.codegen.model

import com.ramcosta.composedestinations.codegen.commons.GENERATED_DESTINATION_SUFFIX
import com.ramcosta.composedestinations.codegen.commons.toSnakeCase
import com.ramcosta.composedestinations.codegen.commons.toValidClassName
import com.ramcosta.composedestinations.codegen.moduleName

interface DestinationGeneratingParams {
val sourceIds: List<String>
val name: String
val composableName: String
val composableQualifiedName: String
val annotatedName: String
val annotatedQualifiedName: String
val visibility: Visibility
val baseRoute: String
val parameters: List<Parameter>
Expand All @@ -21,11 +26,9 @@ interface DestinationGeneratingParams {

data class RawDestinationGenParams(
override val sourceIds: List<String>,
override val name: String,
override val composableName: String,
override val composableQualifiedName: String,
override val annotatedName: String,
override val annotatedQualifiedName: String,
override val visibility: Visibility,
override val baseRoute: String,
override val parameters: List<Parameter>,
override val deepLinks: List<DeepLink>,
override val navGraphInfo: NavGraphInfo?,
Expand All @@ -36,4 +39,37 @@ data class RawDestinationGenParams(
override val activityDestinationParams: ActivityDestinationParams? = null,
override val composableWrappers: List<Importable>,
override val isParentStart: Boolean,
): DestinationGeneratingParams
private val hasMultipleDestinations: Boolean,
private val routeOverride: String?,
) : DestinationGeneratingParams {

private val destinationNames: DestinationNames by lazy {
if (routeOverride != null) {
return@lazy DestinationNames(
route = routeOverride,
destination = routeOverride.toValidClassName() + GENERATED_DESTINATION_SUFFIX
)
}

val moduleNamePrefix = moduleName.takeIf { it.isNotBlank() }?.let { "${it.toSnakeCase()}/" } ?: ""
val routeWithNoModule = if (hasMultipleDestinations) {
val navGraphName = navGraphInfo?.graphType?.simpleName
?.removeSuffix("NavGraph")
?.removeSuffix("Graph")
.orEmpty()
"${navGraphName.toSnakeCase()}/${annotatedName.toSnakeCase()}"
} else {
annotatedName.toSnakeCase()
}

DestinationNames(
route = "$moduleNamePrefix$routeWithNoModule",
destination = routeWithNoModule.toValidClassName() + GENERATED_DESTINATION_SUFFIX
)
}

override val name: String get() = destinationNames.destination
override val baseRoute: String get() = destinationNames.route

private class DestinationNames(val route: String, val destination: String)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.ramcosta.composedestinations.codegen.model

import com.ramcosta.composedestinations.codegen.commons.toSnakeCase
import com.ramcosta.composedestinations.codegen.moduleName
import java.util.Locale

interface NavGraphGenParams {
val sourceIds: List<String>
Expand Down Expand Up @@ -31,7 +33,7 @@ data class RawNavGraphGenParams(
override val isParentStart: Boolean? = null,
override val visibility: Visibility,
override val externalRoutes: List<ExternalRoute>,
private val routeOverride: String? = null,
private val routeOverride: String? = null
) : NavGraphGenParams {

override val externalNavGraphs: List<ExternalRoute.NavGraph> = externalRoutes.filterIsInstance<ExternalRoute.NavGraph>()
Expand All @@ -49,9 +51,14 @@ data class RawNavGraphGenParams(
}

override val baseRoute: String by lazy(LazyThreadSafetyMode.NONE) {
routeOverride ?: name
routeOverride ?: nameWithModuleName()
.replace("(?i)navgraph".toRegex(), "")
.replace("(?i)graph".toRegex(), "")
.toSnakeCase()
}

private fun nameWithModuleName(): String {
val moduleNamePrefix = moduleName.takeIf { it.isNotBlank() }?.let { "${it.toSnakeCase()}/" } ?: ""
return "$moduleNamePrefix${name.replaceFirstChar { it.lowercase(Locale.US) }}"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,13 @@ internal class InitialValidator(
return if (navArgsDelegateTypeLocal == null) {
parameters.filter { it.isNavArg() }
} else {
navArgsDelegateTypeLocal.validateNavArgs("Composable '${composableName}': ")
navArgsDelegateTypeLocal.validateNavArgs("Composable '${annotatedName}': ")

val navArgInFuncParams =
parameters.firstOrNull { it.isNavArg() && it.type.value.importable != navArgsDelegateTypeLocal.type }
if (navArgInFuncParams != null) {
throw IllegalDestinationsSetup(
"Composable '${composableName}': annotated " +
"Composable '${annotatedName}': annotated " +
"function cannot define arguments of navigation type if using a '$DESTINATION_ANNOTATION_NAV_ARGS_DELEGATE_ARGUMENT' class. (check argument '${navArgInFuncParams.name})'"
)
}
Expand Down Expand Up @@ -145,7 +145,7 @@ internal class InitialValidator(
if (!codeGenConfig.generateNavGraphs) {

Logger.instance.warn(
"'${composableName}' composable: is annotated with a `NavGraph` annotation, but it will be ignored." +
"'${annotatedName}' composable: is annotated with a `NavGraph` annotation, but it will be ignored." +
"Reason: nav graphs generation was disabled by ksp gradle configuration."
)
}
Expand All @@ -155,7 +155,7 @@ internal class InitialValidator(
if (composableReceiverType?.importable?.qualifiedName == ANIMATED_VISIBILITY_SCOPE_QUALIFIED_NAME) {
if (destinationStyleType !is DestinationStyleType.Animated && destinationStyleType !is DestinationStyleType.Default) {
throw IllegalDestinationsSetup(
"'${composableName}' composable: " +
"'${annotatedName}' composable: " +
"Only destinations with a DestinationStyle.Animated or DestinationStyle.Default style may have a $ANIMATED_VISIBILITY_SCOPE_SIMPLE_NAME receiver!"
)
}
Expand All @@ -166,14 +166,14 @@ internal class InitialValidator(
if (composableReceiverType?.importable?.qualifiedName == COLUMN_SCOPE_QUALIFIED_NAME) {
if (!isBottomSheetDependencyPresent) {
throw MissingRequiredDependency(
"'${composableName}' composable: " +
"'${annotatedName}' composable: " +
"You need to include $BOTTOM_SHEET_DEPENDENCY dependency to use a $COLUMN_SCOPE_SIMPLE_NAME receiver!"
)
}

if (destinationStyleType !is DestinationStyleType.BottomSheet) {
throw IllegalDestinationsSetup(
"'${composableName}' composable: " +
"'${annotatedName}' composable: " +
"Only destinations with a DestinationStyleBottomSheet style may have a $COLUMN_SCOPE_SIMPLE_NAME receiver!"
)
}
Expand All @@ -189,7 +189,7 @@ internal class InitialValidator(
}

if (navGraphRoutes.contains(baseRoute)) {
throw IllegalDestinationsSetup("There is a NavGraph with same base route as destination '$composableName'")
throw IllegalDestinationsSetup("There is a NavGraph with same base route as destination '$annotatedName'")
}
}

Expand All @@ -203,7 +203,7 @@ internal class InitialValidator(
val destinationResultOriginForAllResultTypes = mutableSetOf<String>()

resultRecipientParams.forEach { parameter ->
Logger.instance.info("validateClosedResultRecipients | checking param $composableName ${parameter.name}")
Logger.instance.info("validateClosedResultRecipients | checking param $annotatedName ${parameter.name}")

val resultType = (parameter.type.typeArguments[1] as? TypeArgument.Typed)?.type
?: throw IllegalDestinationsSetup(
Expand All @@ -222,7 +222,7 @@ internal class InitialValidator(
if (info == null || info.resultTypeQualifiedName != resultType.importable.qualifiedName || info.isResultTypeNullable != resultType.isNullable) {
throw IllegalDestinationsSetup(
"Composable correspondent to '${resultOriginQualifiedName}' must receive a 'ResultBackNavigator<${resultType.toTypeCode()}>'" +
" parameter in order to be used as result originator for '${composableName}'"
" parameter in order to be used as result originator for '${annotatedName}'"
)
}

Expand All @@ -235,22 +235,22 @@ internal class InitialValidator(

val resultOriginDestinationParams =
destinationsByName.value[resultOriginDestinationName]
?: throw IllegalDestinationsSetup("Non existent Destination ('$resultOriginDestinationName') as the ResultRecipient's result origin (type aliases are not allowed here) for '$composableName'.")
?: throw IllegalDestinationsSetup("Non existent Destination ('$resultOriginDestinationName') as the ResultRecipient's result origin (type aliases are not allowed here) for '$annotatedName'.")

resultOriginDestinationParams.parameters.firstOrNull {
it.type.importable.qualifiedName == RESULT_BACK_NAVIGATOR_QUALIFIED_NAME &&
(it.type.typeArguments.firstOrNull() as? TypeArgument.Typed)?.type == resultType
}
?: throw IllegalDestinationsSetup(
"Composable '${resultOriginDestinationParams.composableName}' must receive a ResultBackNavigator" +
" of type '${resultType.toTypeCode()}' in order to be used as result originator for '${composableName}'"
"Composable '${resultOriginDestinationParams.annotatedName}' must receive a ResultBackNavigator" +
" of type '${resultType.toTypeCode()}' in order to be used as result originator for '${annotatedName}'"
)
}
}

if (destinationResultOriginForAllResultTypes.size != resultRecipientParams.size) {
throw IllegalDestinationsSetup(
"Composable '${composableName}': " +
"Composable '${annotatedName}': " +
"has multiple ResultRecipients with the same Destination, only one recipient is allowed for a given destination!"
)
}
Expand All @@ -259,7 +259,7 @@ internal class InitialValidator(
parameters.filter { it.type.importable.qualifiedName == RESULT_BACK_NAVIGATOR_QUALIFIED_NAME }
if (resultBackNavigatorParams.size > 1) {
throw IllegalDestinationsSetup(
"Composable '${composableName}': " +
"Composable '${annotatedName}': " +
"Destination annotated Composables must have at most one ResultBackNavigator"
)
}
Expand Down Expand Up @@ -324,7 +324,7 @@ internal class InitialValidator(

private fun DestinationGeneratingParams.validateResultType(resultType: TypeInfo) {
if (resultType.typeArguments.isNotEmpty()) {
throw IllegalDestinationsSetup("Composable $composableName, ${resultType.toTypeCode()}: Result types cannot have type arguments!")
throw IllegalDestinationsSetup("Composable $annotatedName, ${resultType.toTypeCode()}: Result types cannot have type arguments!")
}

val primitives = listOf(
Expand All @@ -336,7 +336,7 @@ internal class InitialValidator(
)
if (resultType.importable.qualifiedName !in primitives && !resultType.isSerializable && !resultType.isParcelable) {
throw IllegalDestinationsSetup(
"Composable $composableName, ${resultType.toTypeCode()}: " +
"Composable $annotatedName, ${resultType.toTypeCode()}: " +
"Result types must be one of: ${
listOf(
"String",
Expand All @@ -355,7 +355,7 @@ internal class InitialValidator(
private fun DestinationGeneratingParams.checkVisibilityToNavGraph() {
if (navGraphInfo == null && visibility != Visibility.PUBLIC) {
throw IllegalDestinationsSetup(
"$composableName has visibility $visibility but it's using 'ExternalModuleGraph'. In order for it to be included in an external module graph, it has to be public!"
"$annotatedName has visibility $visibility but it's using 'ExternalModuleGraph'. In order for it to be included in an external module graph, it has to be public!"
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ internal class MermaidGraphWriter(
private val ExternalRoute.Destination.mermaidVisualName get() = generatedType.simpleName.removeSuffix("Destination")

private val CodeGenProcessedDestination.mermaidId get() = baseRoute.replace("graph", "g")
private val CodeGenProcessedDestination.mermaidVisualName get() = composableName
private val CodeGenProcessedDestination.mermaidVisualName get() = annotatedName

private val NavGraphGenParams.mermaidId get() = baseRoute.replace("graph", "g")
private val NavGraphGenParams.mermaidVisualName get() = annotationType.simpleName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,16 @@ internal class SingleDestinationWriter(
importableHelper,
navArgResolver,
navArgs,
"Composable '${destination.composableName}'"
"Composable '${destination.annotatedName}'"
)

init {
if (destination.isParentStart && destination.navGraphInfo?.isNavHostGraph == true && destination.navArgs.any { it.isMandatory }) {
throw IllegalDestinationsSetup("\"'${destination.composableName}' composable: Start destinations of NavHostGraphs cannot have mandatory navigation arguments!")
throw IllegalDestinationsSetup("\"'${destination.annotatedName}' composable: Start destinations of NavHostGraphs cannot have mandatory navigation arguments!")
}

importableHelper.addAll(destinationTemplate.imports)
importableHelper.addPriorityQualifiedImport(destination.composableQualifiedName, destination.composableName)
importableHelper.addPriorityQualifiedImport(destination.annotatedQualifiedName, destination.annotatedName)
}

fun write() = with(destination) {
Expand All @@ -81,7 +81,7 @@ internal class SingleDestinationWriter(
importableHelper = importableHelper,
sourceCode = destinationTemplate.sourceCode
.replace(DESTINATION_NAME, name)
.replace(USER_COMPOSABLE_DESTINATION, composableName)
.replace(USER_COMPOSABLE_DESTINATION, annotatedName)
.replaceSuperclassDestination()
.addNavArgsDataClass()
.replace(REQUIRE_OPT_IN_ANNOTATIONS_PLACEHOLDER, objectWideRequireOptInAnnotationsCode())
Expand Down Expand Up @@ -192,8 +192,8 @@ internal class SingleDestinationWriter(
)

val activityClassImportable = Importable(
composableName,
composableQualifiedName
annotatedName,
annotatedQualifiedName
)

return """override val targetPackage: String? = @targetPackage@
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class DestinationContentFunctionWriter(

functionCallCode += wrappingPrefix()

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

functionCallCode += if (composableWrappers.isEmpty()) composableCall
else "\t" + composableCall.replace("\n", "\n\t")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ internal class NavGraphsPrettyKdocWriter(
KdocRoute(
false,
it.isParentStart,
Importable(it.composableName, it.composableQualifiedName),
Importable(it.annotatedName, it.annotatedQualifiedName),
true
)
} +
Expand Down
Loading

0 comments on commit dca44f5

Please sign in to comment.