From 148db22e342cdb37043aa26903375dd24bd207e8 Mon Sep 17 00:00:00 2001 From: Gray Mackall <34871572+gmackall@users.noreply.github.com> Date: Thu, 30 Jan 2025 11:20:26 -0800 Subject: [PATCH] [FGP Kotlin conversion] Convert `Deeplink` and `IntentFilterCheck` (#161835) Converts `Deeplink` and `IntentFilterCheck` from Groovy to Kotlin, and pulls them out to their own files. Also writes a test for the equals method for `Deeplink`, as it is a custom equals method. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: Gray Mackall --- .../gradle/src/main/groovy/flutter.groovy | 29 ++----------- .../gradle/src/main/kotlin/Deeplink.kt | 27 ++++++++++++ .../src/main/kotlin/IntentFilterCheck.kt | 13 ++++++ .../gradle/src/test/kotlin/DeeplinkTest.kt | 41 +++++++++++++++++++ 4 files changed, 84 insertions(+), 26 deletions(-) create mode 100644 packages/flutter_tools/gradle/src/main/kotlin/Deeplink.kt create mode 100644 packages/flutter_tools/gradle/src/main/kotlin/IntentFilterCheck.kt create mode 100644 packages/flutter_tools/gradle/src/test/kotlin/DeeplinkTest.kt diff --git a/packages/flutter_tools/gradle/src/main/groovy/flutter.groovy b/packages/flutter_tools/gradle/src/main/groovy/flutter.groovy index c843546f3dd..b4ec30052b0 100644 --- a/packages/flutter_tools/gradle/src/main/groovy/flutter.groovy +++ b/packages/flutter_tools/gradle/src/main/groovy/flutter.groovy @@ -5,6 +5,8 @@ import com.android.build.OutputFile import com.flutter.gradle.BaseApplicationNameHandler +import com.flutter.gradle.Deeplink +import com.flutter.gradle.IntentFilterCheck import groovy.json.JsonGenerator import groovy.xml.QName import java.nio.file.Paths @@ -546,7 +548,7 @@ class FlutterPlugin implements Plugin { schemes.each { scheme -> hosts.each { host -> paths.each { path -> - appLinkSettings.deeplinks.add(new Deeplink(scheme: scheme, host: host, path: path, intentFilterCheck: intentFilterCheck)) + appLinkSettings.deeplinks.add(new Deeplink(scheme, host, path, intentFilterCheck)) } } } @@ -1572,31 +1574,6 @@ class AppLinkSettings { } -class IntentFilterCheck { - - boolean hasAutoVerify - boolean hasActionView - boolean hasDefaultCategory - boolean hasBrowsableCategory - -} - -class Deeplink { - String scheme, host, path - IntentFilterCheck intentFilterCheck - boolean equals(Object o) { - if (o == null) { - throw new NullPointerException() - } - if (o.getClass() != getClass()) { - return false - } - return scheme == o.scheme && - host == o.host && - path == o.path - } -} - abstract class BaseFlutterTask extends DefaultTask { @Internal diff --git a/packages/flutter_tools/gradle/src/main/kotlin/Deeplink.kt b/packages/flutter_tools/gradle/src/main/kotlin/Deeplink.kt new file mode 100644 index 00000000000..1398682ae0b --- /dev/null +++ b/packages/flutter_tools/gradle/src/main/kotlin/Deeplink.kt @@ -0,0 +1,27 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package com.flutter.gradle + +// TODO(gmackall): Identify which of these can be val instead of var. +class Deeplink(var scheme: String?, var host: String?, var path: String?, var intentFilterCheck: IntentFilterCheck?) { + // TODO(gmackall): This behavior was kept identical to the original Groovy behavior as part of + // the Groovy->Kotlin conversion, but should be changed once the conversion is complete. + override fun equals(other: Any?): Boolean { + if (other == null) { + throw NullPointerException() + } + if (other.javaClass != javaClass) { + return false + } + val otherAsDeeplink = other as Deeplink + return scheme == otherAsDeeplink.scheme && + host == otherAsDeeplink.host && + path == otherAsDeeplink.path + } + + override fun hashCode(): Int { + return scheme.hashCode() + host.hashCode() + path.hashCode() + } +} diff --git a/packages/flutter_tools/gradle/src/main/kotlin/IntentFilterCheck.kt b/packages/flutter_tools/gradle/src/main/kotlin/IntentFilterCheck.kt new file mode 100644 index 00000000000..2d7a810dd73 --- /dev/null +++ b/packages/flutter_tools/gradle/src/main/kotlin/IntentFilterCheck.kt @@ -0,0 +1,13 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package com.flutter.gradle + +class IntentFilterCheck { + // TODO(gmackall): Identify which of these can be val instead of var. + var hasAutoVerify = false + var hasActionView = false + var hasDefaultCategory = false + var hasBrowsableCategory = false +} diff --git a/packages/flutter_tools/gradle/src/test/kotlin/DeeplinkTest.kt b/packages/flutter_tools/gradle/src/test/kotlin/DeeplinkTest.kt new file mode 100644 index 00000000000..28c747d6716 --- /dev/null +++ b/packages/flutter_tools/gradle/src/test/kotlin/DeeplinkTest.kt @@ -0,0 +1,41 @@ +package com.flutter.gradle + +import org.gradle.internal.impldep.org.junit.Assert.assertThrows +import kotlin.test.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class DeeplinkTest { + @Test + fun `equals should return true for equal objects`() { + val deeplink1 = Deeplink("scheme1", "host1", "path1", null) + val deeplink2 = Deeplink("scheme1", "host1", "path1", null) + + assertTrue { deeplink1 == deeplink2 } + } + + @Test + fun `equals should return false for unequal objects`() { + val deeplink1 = Deeplink("scheme1", "host1", "path1", null) + val deeplink2 = Deeplink("scheme2", "host2", "path2", null) + + assertFalse { deeplink1 == deeplink2 } + } + + @Test + fun `equals should return false for other of different type`() { + val deeplink1 = Deeplink("scheme1", "host1", "path1", null) + val notADeeplink = 5 + + assertFalse { deeplink1.equals(notADeeplink) } + } + + @Suppress("UnusedEquals") + @Test + fun `equals should throw NullPointerException for null other`() { + val deeplink1 = Deeplink("scheme1", "host1", "path1", null) + val deeplink2 = null + + assertThrows(NullPointerException::class.java, { deeplink1.equals(deeplink2) }) + } +}