Skip to content

Commit d0c06ca

Browse files
authored
Support AGP 3.6+ in the iid compatibility check. (#1409)
* Support AGP 3.6+ in the iid compatibility check. AGP 3.6 introduced a breaking change to lint-api making the check fail. The change switch to use reflection to support both versions of the api. Additionally the change makes the check failures more developer friendly to make sure this check does not cause failures in upcoming AGP versions. Versions tested: 3.2 through 4.1.0-alpha04 Fixes #1407 * Cleanup, unittests for version logic
1 parent 4273e0d commit d0c06ca

File tree

4 files changed

+109
-14
lines changed

4 files changed

+109
-14
lines changed

firebase-installations/customer-lint-checks/customer-lint-checks.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ dependencies {
2727
testImplementation "com.android.tools.lint:lint:$lintVersion"
2828
testImplementation "com.android.tools.lint:lint-tests:$lintVersion"
2929
testImplementation "com.android.tools:testutils:$lintVersion"
30+
testImplementation "com.google.truth:truth:$googleTruthVersion"
3031
}
3132

3233
compileKotlin.kotlinOptions.apiVersion = '1.2'

firebase-installations/customer-lint-checks/src/main/java/com/google/firebase/installations/lint/Checks.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ import com.android.tools.lint.detector.api.Issue
2020

2121
class Checks : IssueRegistry() {
2222
override val issues: List<Issue>
23-
get() = listOf(IncompatibleIidVersionDetector.INCOMPATIBLE_IID_VERSION)
23+
get() = listOf(
24+
IncompatibleIidVersionDetector.INCOMPATIBLE_IID_VERSION,
25+
IncompatibleIidVersionDetector.IID_COMPATIBILITY_CHECK_FAILURE
26+
)
2427

2528
override val api: Int
2629
get() = CURRENT_API

firebase-installations/customer-lint-checks/src/main/java/com/google/firebase/installations/lint/IncompatibleIidVersionDetector.kt

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@
1414

1515
package com.google.firebase.installations.lint
1616

17-
import com.android.builder.model.MavenCoordinates
17+
import com.android.builder.model.Variant
1818
import com.android.tools.lint.detector.api.Category
1919
import com.android.tools.lint.detector.api.Context
2020
import com.android.tools.lint.detector.api.Detector
2121
import com.android.tools.lint.detector.api.Implementation
2222
import com.android.tools.lint.detector.api.Issue
2323
import com.android.tools.lint.detector.api.Location
24+
import com.android.tools.lint.detector.api.Project
2425
import com.android.tools.lint.detector.api.Severity
2526
import com.android.tools.lint.detector.api.Scope
2627
import java.util.EnumSet
@@ -46,18 +47,29 @@ class IncompatibleIidVersionDetector : Detector() {
4647
severity = Severity.ERROR,
4748
implementation = IMPLEMENTATION
4849
)
49-
}
5050

51-
override fun beforeCheckEachProject(context: Context) {
52-
if (!context.project.isGradleProject) {
53-
return
54-
}
51+
@JvmField
52+
val IID_COMPATIBILITY_CHECK_FAILURE = Issue.create(
53+
id = "IidCompatibilityCheckFailure",
54+
briefDescription = "Firebase IID Compatibility Check Unable To Run",
55+
explanation = """
56+
The check failed to run as it encountered unknown failure.
57+
This is most likely caused by a new version of Android Gradle Plugin that this check does not support.
58+
Please make sure your build does not depend on firebase-iid version earlier than 20.1.1 as it will cause issues.
59+
""",
60+
category = Category.LINT,
61+
priority = 1,
62+
severity = Severity.INFORMATIONAL,
63+
implementation = IMPLEMENTATION
64+
)
65+
}
5566

56-
for (variant in context.project.gradleProjectModel.variants) {
67+
override fun beforeCheckEachProject(context: Context) = catching(context) {
68+
for (variant in getVariants(context.project)) {
5769
for (lib in variant.mainArtifact.dependencies.libraries) {
5870
val coordinates = lib.resolvedCoordinates
5971
if (coordinates.groupId == "com.google.firebase" && coordinates.artifactId == "firebase-iid") {
60-
if (!isCompatibleVersion(coordinates)) {
72+
if (!isCompatibleVersion(coordinates.version)) {
6173
context.report(INCOMPATIBLE_IID_VERSION,
6274
Location.create(context.file),
6375
"Incompatible IID version found in variant ${variant.name}: ${lib.name.removeSuffix("@aar")}.\n" +
@@ -68,18 +80,45 @@ class IncompatibleIidVersionDetector : Detector() {
6880
}
6981
}
7082

71-
private fun isCompatibleVersion(coordinates: MavenCoordinates): Boolean {
72-
val versionComponents = coordinates.version.split('.', limit = 3).toTypedArray()
83+
private fun getVariants(project: Project): List<Variant> {
84+
if (!project.isGradleProject) {
85+
return listOf()
86+
}
87+
88+
// using reflection here due to breaking change in lint-api 26.6.0 that changed the return type
89+
// of getGradleProject()
90+
val method = project.javaClass.getMethod("getGradleProjectModel")
91+
method.isAccessible = true
92+
val model = method.invoke(project)
93+
val variantsMethod = model.javaClass.getMethod("getVariants")
94+
variantsMethod.isAccessible = true
95+
return variantsMethod.invoke(model) as List<Variant>
96+
}
97+
98+
internal fun isCompatibleVersion(version: String): Boolean {
99+
val versionComponents = version.split('.', limit = 3).toTypedArray()
73100

74101
// Incompatible if major version is before v20
75-
if (20 > versionComponents.get(0).toInt()) {
102+
if (20 > versionComponents[0].toInt()) {
76103
return false
77104
}
78105
// Compatible if major version is after v21
79-
if (21 <= versionComponents.get(0).toInt()) {
106+
if (21 <= versionComponents[0].toInt()) {
80107
return true
81108
}
82109
// Its compatible if major version is v20 and minor version is after v20.1
83-
return 1 <= versionComponents.get(1).toInt()
110+
return 1 <= versionComponents[1].toInt()
111+
}
112+
113+
private inline fun catching(context: Context, block: () -> Unit) {
114+
try {
115+
block()
116+
} catch (ex: Throwable) {
117+
context.report(
118+
IID_COMPATIBILITY_CHECK_FAILURE,
119+
Location.create(context.file),
120+
"Check failed with exception: $ex"
121+
)
122+
}
84123
}
85124
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2020 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.installations.lint
16+
17+
import com.google.common.truth.Truth.assertThat
18+
import org.junit.Test
19+
import org.junit.runner.RunWith
20+
import org.junit.runners.JUnit4
21+
22+
@RunWith(JUnit4::class)
23+
class VersionTests {
24+
companion object Detector {
25+
val detector = IncompatibleIidVersionDetector()
26+
}
27+
28+
@Test
29+
fun `isCompatibleVersion with 19_0_0 should be false`() {
30+
assertThat(detector.isCompatibleVersion("19.0.0")).isFalse()
31+
}
32+
33+
@Test
34+
fun `isCompatibleVersion with 20_0_0 should be false`() {
35+
assertThat(detector.isCompatibleVersion("20.0.0")).isFalse()
36+
}
37+
38+
@Test
39+
fun `isCompatibleVersion with 20_1_0 should be true`() {
40+
assertThat(detector.isCompatibleVersion("20.1.0")).isTrue()
41+
}
42+
43+
@Test
44+
fun `isCompatibleVersion with 20_1_1 should be true`() {
45+
assertThat(detector.isCompatibleVersion("20.1.1")).isTrue()
46+
}
47+
48+
@Test
49+
fun `isCompatibleVersion with 21_0_0 should be true`() {
50+
assertThat(detector.isCompatibleVersion("21.0.0")).isTrue()
51+
}
52+
}

0 commit comments

Comments
 (0)