android-maps-compose icon indicating copy to clipboard operation
android-maps-compose copied to clipboard

False positive: Calling a Google Map Composable composable function where a UI Composable composable was expected

Open ln-12 opened this issue 1 year ago • 2 comments

I am using version 5.0.4 of this library. On my map, I need to add a composable marker which I am doing via MarkerComposable. This composable is marked with @GoogleMapComposable that should enforce correct usage (introduced in https://github.com/googlemaps/android-maps-compose/pull/130). I think there is an issue here as this gets triggered if I use a standard/non maps composable inside the MarkerComposable as this is then not marked with the @GoogleMapComposable annotation. Probably, there should be an exclude for this specific case as I cannot annotate all composables that I want to use with that annotation (for example a simple Text). Or is there a simple way to suppress it?

For me, this is quite annoying as we enforce our builds to not have any warnings.

Steps to reproduce

  1. Use some composable (Card, Text, ...) inside the MarkerComposable
  2. The build warning "Calling a Google Map Composable composable function where a UI Composable composable was expected" is triggered

Code example

MarkerComposable( // <-- has the @GoogleMapComposable annotation
    // ...
) {
    Text(text = "Hello World") // <-- does not have the @GoogleMapComposable annotation, but is a valid use case
}

ln-12 avatar Jul 08 '24 11:07 ln-12

@ln-12 Hello, from what I tested in the latest version 6.1.1 of Compose maps this does not happen.

ArleyPereira avatar Aug 03 '24 13:08 ArleyPereira

I just checked again after updating to version 6.1.1 and for me this still gives the warning mentioned above when I rebuild my project. It happens in the compileDebugKotlin task.

ln-12 avatar Aug 05 '24 09:08 ln-12

Still happens for me in version 6.8.0

Tommyten avatar Sep 09 '25 06:09 Tommyten

Happens to me after switching to Kotlin 2.2.20. I checked android-maps-compose versions from 6.7.2 to 6.10.0

mrmike avatar Sep 15 '25 11:09 mrmike

Hi folks,

@ln-12 , I am not able to trigger this warning with the version 2.2.20 from Kotlin, as @mrmike stated:

Image

Would you happen to have a repo where this can be reproduced?

kikoso avatar Sep 15 '25 15:09 kikoso

@kikoso no repo on hand, but this triggers the warning on this repo with this patch:

❯ git diff HEAD^1..HEAD
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index cc3a9b5..50428fd 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -11,7 +11,7 @@ gradleMavenPublishPlugin = "0.34.0"
 jacoco-plugin = "0.2.1"
 junit = "4.13.2"
 junitktx = "1.3.0"
+kotlin = "2.2.20"
- kotlin = "2.2.10"
 kotlinxCoroutines = "1.10.2"
 leakcanaryAndroid = "2.14"
 mapsecrets = "2.0.1"
❯ ./gradlew :maps-app-compileDebugKotlin
...
> Task :maps-app:compileDebugKotlin
w: Argument -Xopt-in is deprecated. Please use -opt-in instead
w: file:///home/florian/projects/android-maps-compose/maps-app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt:198:17 Calling a UI Composable composable function where a Google Map Composable composable was expected
w: file:///home/florian/projects/android-maps-compose/maps-app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt:206:17 Calling a UI Composable composable function where a Google Map Composable composable was expected
w: file:///home/florian/projects/android-maps-compose/maps-app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt:219:17 Calling a UI Composable composable function where a Google Map Composable composable was expected
w: file:///home/florian/projects/android-maps-compose/maps-app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt:227:21 Calling a UI Composable composable function where a Google Map Composable composable was expected
w: file:///home/florian/projects/android-maps-compose/maps-app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt:239:21 Calling a UI Composable composable function where a Google Map Composable composable was expected
w: file:///home/florian/projects/android-maps-compose/maps-app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt:242:17 Calling a UI Composable composable function where a Google Map Composable composable was expected
w: file:///home/florian/projects/android-maps-compose/maps-app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt:250:21 Calling a UI Composable composable function where a Google Map Composable composable was expected
w: file:///home/florian/projects/android-maps-compose/maps-app/src/main/java/com/google/maps/android/compose/GoogleMapComposeFragment.kt:103:25 Calling a UI Composable composable function where a Google Map Composable composable was expected
w: file:///home/florian/projects/android-maps-compose/maps-app/src/main/java/com/google/maps/android/compose/MapInColumnActivity.kt:216:13 Calling a UI Composable composable function where a Google Map Composable composable was expected
w: file:///home/florian/projects/android-maps-compose/maps-app/src/main/java/com/google/maps/android/compose/markerexamples/AdvancedMarkersActivity.kt:186:13 'when' is exhaustive so 'else' is redundant here.

The warning is silenced when indicating that content is a @UiComposable.

❯ git diff HEAD^1..HEAD
diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/Marker.kt b/maps-compose/src/main/java/com/google/maps/android/compose/Marker.kt
index f27d331..2e17c99 100644
--- a/maps-compose/src/main/java/com/google/maps/android/compose/Marker.kt
+++ b/maps-compose/src/main/java/com/google/maps/android/compose/Marker.kt
@@ -29,7 +29,6 @@ import androidx.compose.runtime.saveable.Saver
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.runtime.setValue
 import androidx.compose.runtime.snapshots.StateFactoryMarker
+import androidx.compose.ui.UiComposable
 import androidx.compose.ui.geometry.Offset
 import com.google.android.gms.maps.model.AdvancedMarkerOptions
 import com.google.android.gms.maps.model.BitmapDescriptor
@@ -555,7 +554,7 @@ public fun MarkerInfoWindowContent(
     onInfoWindowClick: (Marker) -> Unit = {},
     onInfoWindowClose: (Marker) -> Unit = {},
     onInfoWindowLongClick: (Marker) -> Unit = {},
+    content: (@UiComposable @Composable (Marker) -> Unit)? = null
-    content: (@Composable (Marker) -> Unit)? = null
 ) {
     MarkerImpl(
         state = state,

pikzen avatar Sep 16 '25 04:09 pikzen

Hi @pikzen ,

I am able to reproduce the issue on the new Kotlin version, thanks for the patch.

The documentation for @UiComposable states the following:

Using this annotation explicitly is rarely necessary as the Compose compiler plugin will infer the necessary equivalent annotations automatically

My assumption is that something has changed in the new Kotlin version that invalidates this inference. I will verify that there are no undesired side effects and create a pull request.

Thank you all.

kikoso avatar Sep 16 '25 10:09 kikoso

@ComposableTarget (which @UiComposable/@GoogleMapComposable are) adds some additional information in its documentation:

[...] if a composable function calls another composable function then both must be of the same group of composable functions (that is, have declared or inferred the same applier value). This means that, if the function called is already determined to be in a group, them the function that calls it must also be in the same group. If two functions are called of different groups then the Compose compiler plugin will generate an diagnostic message describing which group was received and which group was expected.
...

In most cases this annotation can be inferred. However, this annotation is required for Composable functions that call ComposeNode directly, for abstract methods, such as interfaces functions (which do not contain a body from which the plugin can infer the annotation), when using a composable lambda in sub-composition, or when a composable lambda is stored in a class field or global variable.

I'd assume the most recent @ComposableTarget is assumed to be true for the entire tree it affects unless specified otherwise, and might even hit the "composable lambda in sub-composition" condition

pikzen avatar Sep 17 '25 08:09 pikzen

:tada: This issue has been resolved in version 6.11.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

googlemaps-bot avatar Sep 18 '25 17:09 googlemaps-bot

Release v6.11.0 has not been published yet

mrmike avatar Sep 19 '25 11:09 mrmike

Hi @mrmike . There was an issue while publishing the new version, aiming to have it published soon.

kikoso avatar Sep 19 '25 13:09 kikoso

:tada: This issue has been resolved in version 6.11.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

googlemaps-bot avatar Sep 22 '25 20:09 googlemaps-bot

Hi @mrmike .The new version has been published.

kikoso avatar Sep 23 '25 04:09 kikoso