From 4880e1db276b4cf2ec29eeffbd38539ca643b4be Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Wed, 28 Apr 2021 10:27:14 +0530 Subject: [PATCH] Upgrade to Kotlin 1.5 (#1397) * build: upgrade Kotlin to 1.5.0 and Hilt to 2.35.1 Signed-off-by: Harsh Shandilya * all: address kotlin.time.seconds deprecation Signed-off-by: Harsh Shandilya * autofill-parser/openpgp-ktx: require Kotlin 1.5 Signed-off-by: Harsh Shandilya * all: address string method deprecations Signed-off-by: Harsh Shandilya * build: disable NewApi lint Signed-off-by: Harsh Shandilya --- app/build.gradle.kts | 5 +++++ .../msfjarvis/aps/ui/crypto/DecryptActivity.kt | 4 ++-- .../aps/util/pwgen/RandomPhonemesGenerator.kt | 4 ++-- .../aps/util/pwgenxkpwd/PasswordBuilder.kt | 14 ++++++++++---- .../viewmodel/SearchableRepositoryViewModel.kt | 3 +-- autofill-parser/CHANGELOG.md | 2 ++ .../autofillparser/FormField.kt | 16 +++------------- .../lib/publicsuffixlist/PublicSuffixListData.kt | 2 +- .../lib/publicsuffixlist/ext/ByteArray.kt | 6 +++--- buildSrc/build.gradle.kts | 4 ++-- buildSrc/src/main/java/BaseProjectConfig.kt | 3 ++- .../msfjarvis/aps/data/passfile/PasswordEntry.kt | 6 +++--- .../kotlin/dev/msfjarvis/aps/util/totp/Otp.kt | 2 +- gradle/libs.versions.toml | 6 +++--- openpgp-ktx/CHANGELOG.md | 2 ++ .../me/msfjarvis/openpgpktx/util/OpenPgpUtils.kt | 2 +- 16 files changed, 43 insertions(+), 38 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d54b5ea9..e4543813 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -35,6 +35,11 @@ android { isAbortOnError = true isCheckReleaseBuilds = false disable("MissingTranslation", "PluralsCandidate", "ImpliedQuantity") + // Kotlin 1.5 + AGP 4.1.3 trip up NewApi for Kotlin intrinsics like forEach + // This can be fixed by either switching to AGP 4.2.0-rc1, or disabling it + // outright. + // https://issuetracker.google.com/issues/185418482 + disable("NewApi") } flavorDimensions("free") diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt index 72a9a80d..8edd8f0b 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt @@ -27,8 +27,8 @@ import dev.msfjarvis.aps.util.settings.PreferenceKeys import java.io.ByteArrayOutputStream import java.io.File import javax.inject.Inject +import kotlin.time.Duration import kotlin.time.ExperimentalTime -import kotlin.time.seconds import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collect @@ -121,7 +121,7 @@ class DecryptActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound { @OptIn(ExperimentalTime::class) private fun startAutoDismissTimer() { lifecycleScope.launch { - delay(60.seconds) + delay(Duration.seconds(60)) finish() } } diff --git a/app/src/main/java/dev/msfjarvis/aps/util/pwgen/RandomPhonemesGenerator.kt b/app/src/main/java/dev/msfjarvis/aps/util/pwgen/RandomPhonemesGenerator.kt index 1b2d0fb7..0b8ca872 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/pwgen/RandomPhonemesGenerator.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/pwgen/RandomPhonemesGenerator.kt @@ -60,8 +60,8 @@ object RandomPhonemesGenerator { private class Element(str: String, val flags: Int) { - val upperCase = str.toUpperCase(Locale.ROOT) - val lowerCase = str.toLowerCase(Locale.ROOT) + val upperCase = str.uppercase(Locale.ROOT) + val lowerCase = str.lowercase(Locale.ROOT) val length = str.length val isAmbiguous = str.any { it in PasswordGenerator.AMBIGUOUS_STR } } diff --git a/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/PasswordBuilder.kt b/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/PasswordBuilder.kt index cc8257b4..3eb2cce7 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/PasswordBuilder.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/PasswordBuilder.kt @@ -101,10 +101,16 @@ class PasswordBuilder(ctx: Context) { val candidate = wordBank.secureRandomElement() val s = when (capsType) { - CapsType.UPPERCASE -> candidate.toUpperCase(Locale.getDefault()) - CapsType.Sentence -> if (i == 0) candidate.capitalize(Locale.getDefault()) else candidate - CapsType.TitleCase -> candidate.capitalize(Locale.getDefault()) - CapsType.lowercase -> candidate.toLowerCase(Locale.getDefault()) + CapsType.UPPERCASE -> candidate.uppercase(Locale.getDefault()) + CapsType.Sentence -> + if (i == 0) + candidate.replaceFirstChar { + if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() + } + else candidate + CapsType.TitleCase -> + candidate.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } + CapsType.lowercase -> candidate.lowercase(Locale.getDefault()) CapsType.As_iS -> candidate } password.append(s) diff --git a/app/src/main/java/dev/msfjarvis/aps/util/viewmodel/SearchableRepositoryViewModel.kt b/app/src/main/java/dev/msfjarvis/aps/util/viewmodel/SearchableRepositoryViewModel.kt index 881f98f4..f0488537 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/viewmodel/SearchableRepositoryViewModel.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/viewmodel/SearchableRepositoryViewModel.kt @@ -442,8 +442,7 @@ open class SearchableRepositoryAdapter( } } } - final override fun getPopupText(position: Int): String { - return getItem(position).name[0].toString().toUpperCase(Locale.getDefault()) + return getItem(position).name[0].toString().uppercase(Locale.getDefault()) } } diff --git a/autofill-parser/CHANGELOG.md b/autofill-parser/CHANGELOG.md index 1d24d454..71d94cb5 100644 --- a/autofill-parser/CHANGELOG.md +++ b/autofill-parser/CHANGELOG.md @@ -10,6 +10,8 @@ All notable changes to this project will be documented in this file. - Updated `androidx.annotation` to 1.1.0 and `androidx.autofill` to `1.2.0-alpha01`. +- The library now requires Kotlin 1.5.0 configured with `kotlinOptions.languageVersion = "1.5"`. + ### Fixed - Fix build warning from undeclared unsigned type use. diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt index 109da82c..0bd3d404 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt @@ -39,19 +39,16 @@ internal class FormField( HintConstants.AUTOFILL_HINT_USERNAME, HintConstants.AUTOFILL_HINT_NEW_USERNAME, ) - private val HINTS_NEW_PASSWORD = listOf( HintConstants.AUTOFILL_HINT_NEW_PASSWORD, ) - private val HINTS_PASSWORD = HINTS_NEW_PASSWORD + listOf( HintConstants.AUTOFILL_HINT_PASSWORD, HintConstants.AUTOFILL_HINT_WIFI_PASSWORD, ) - private val HINTS_OTP = listOf( HintConstants.AUTOFILL_HINT_SMS_OTP, @@ -70,7 +67,6 @@ internal class FormField( HintConstants.AUTOFILL_HINT_PHONE, HintConstants.AUTOFILL_HINT_PHONE_NUMBER, ) - private val ANDROID_TEXT_FIELD_CLASS_NAMES = listOf( "android.widget.EditText", @@ -79,9 +75,7 @@ internal class FormField( "android.support.v7.widget.AppCompatEditText", "com.google.android.material.textfield.TextInputEditText", ) - private const val ANDROID_WEB_VIEW_CLASS_NAME = "android.webkit.WebView" - private fun isPasswordInputType(inputType: Int): Boolean { val typeClass = inputType and InputType.TYPE_MASK_CLASS val typeVariation = inputType and InputType.TYPE_MASK_VARIATION @@ -117,7 +111,6 @@ internal class FormField( (HTML_INPUT_FIELD_TYPES_USERNAME + HTML_INPUT_FIELD_TYPES_PASSWORD + HTML_INPUT_FIELD_TYPES_OTP).toSet().toList() @RequiresApi(Build.VERSION_CODES.O) private fun isSupportedHint(hint: String) = hint in HINTS_FILLABLE - private val EXCLUDED_TERMS = listOf( "url_bar", // Chrome/Edge/Firefox address bar @@ -158,14 +151,13 @@ internal class FormField( private val List.anyMatchesFieldInfo get() = any { fieldId.contains(it) || hint.contains(it) || htmlName.contains(it) } - val autofillId: AutofillId = node.autofillId!! // Information for heuristics and exclusion rules based only on the current field private val htmlId = node.htmlInfo?.attributes?.firstOrNull { it.first == "id" }?.second private val resourceId = node.idEntry - private val fieldId = (htmlId ?: resourceId ?: "").toLowerCase(Locale.US) - private val hint = node.hint?.toLowerCase(Locale.US) ?: "" + private val fieldId = (htmlId ?: resourceId ?: "").lowercase(Locale.US) + private val hint = node.hint?.lowercase(Locale.US) ?: "" private val className: String? = node.className private val inputType = node.inputType @@ -186,10 +178,9 @@ internal class FormField( private val htmlTag = node.htmlInfo?.tag private val htmlAttributes: Map = node.htmlInfo?.attributes?.filter { it.first != null && it.second != null }?.associate { - Pair(it.first.toLowerCase(Locale.US), it.second.toLowerCase(Locale.US)) + Pair(it.first.lowercase(Locale.US), it.second.lowercase(Locale.US)) } ?: emptyMap() - private val htmlAttributesDebug = htmlAttributes.entries.joinToString { "${it.key}=${it.value}" } private val htmlInputType = htmlAttributes["type"] private val htmlName = htmlAttributes["name"] ?: "" @@ -204,7 +195,6 @@ internal class FormField( // HTML fields with non-fillable types (such as submit buttons) should be excluded here private val isAndroidTextField = !isHtmlField && className in ANDROID_TEXT_FIELD_CLASS_NAMES private val isAndroidPasswordField = isAndroidTextField && hasPasswordInputType - private val isTextField = isAndroidTextField || isHtmlTextField // Autofill hint detection for native fields diff --git a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListData.kt b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListData.kt index dcef3574..7a17a80f 100644 --- a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListData.kt +++ b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListData.kt @@ -144,7 +144,7 @@ internal class PublicSuffixListData(private val rules: ByteArray, private val ex companion object { - val WILDCARD_LABEL = byteArrayOf('*'.toByte()) + val WILDCARD_LABEL = byteArrayOf('*'.code.toByte()) val PREVAILING_RULE = listOf("*") val EMPTY_RULE = listOf() const val EXCEPTION_MARKER = '!' diff --git a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/ext/ByteArray.kt b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/ext/ByteArray.kt index 59627723..5665db60 100644 --- a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/ext/ByteArray.kt +++ b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/ext/ByteArray.kt @@ -42,7 +42,7 @@ internal fun ByteArray.binarySearch(labels: List, labelIndex: Int): S val byte0 = if (expectDot) { expectDot = false - '.'.toByte() + '.'.code.toByte() } else { labels[currentLabelIndex][currentLabelByteIndex] and BITMASK } @@ -109,7 +109,7 @@ internal fun ByteArray.binarySearch(labels: List, labelIndex: Int): S /** Search for a '\n' that marks the start of a value. Don't go back past the start of the array. */ private fun ByteArray.findStartOfLineFromIndex(start: Int): Int { var index = start - while (index > -1 && this[index] != '\n'.toByte()) { + while (index > -1 && this[index] != '\n'.code.toByte()) { index-- } index++ @@ -119,7 +119,7 @@ private fun ByteArray.findStartOfLineFromIndex(start: Int): Int { /** Search for a '\n' that marks the end of a value. */ private fun ByteArray.findEndOfLineFromIndex(start: Int): Int { var end = 1 - while (this[start + end] != '\n'.toByte()) { + while (this[start + end] != '\n'.code.toByte()) { end++ } return end diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 51a07fad..abdc6def 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -41,8 +41,8 @@ dependencies { implementation("org.jetbrains.kotlinx:binary-compatibility-validator:0.5.0") implementation("org.jetbrains.dokka:dokka-gradle-plugin:1.4.30") implementation("de.undercouch:gradle-download-task:4.1.1") - implementation("com.google.dagger:hilt-android-gradle-plugin:2.34.1-beta") - implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.32") + implementation("com.google.dagger:hilt-android-gradle-plugin:2.35.1") + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.0") implementation("com.ncorti.ktfmt.gradle:plugin:0.5.0") implementation("com.vanniktech:gradle-maven-publish-plugin:0.13.0") implementation("com.vdurmont:semver4j:3.1.0") diff --git a/buildSrc/src/main/java/BaseProjectConfig.kt b/buildSrc/src/main/java/BaseProjectConfig.kt index 600a2e41..761146ba 100644 --- a/buildSrc/src/main/java/BaseProjectConfig.kt +++ b/buildSrc/src/main/java/BaseProjectConfig.kt @@ -36,6 +36,7 @@ internal fun Project.configureForAllProjects() { repositories { google() mavenCentral() + @Suppress("DEPRECATION") jcenter { content { // https://github.com/zhanghai/AndroidFastScroll/issues/35 @@ -57,7 +58,7 @@ internal fun Project.configureForAllProjects() { kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8.toString() freeCompilerArgs = freeCompilerArgs + additionalCompilerArgs - languageVersion = "1.4" + languageVersion = "1.5" useIR = true } } diff --git a/format-common/src/main/kotlin/dev/msfjarvis/aps/data/passfile/PasswordEntry.kt b/format-common/src/main/kotlin/dev/msfjarvis/aps/data/passfile/PasswordEntry.kt index 05afd8c2..a65e3494 100644 --- a/format-common/src/main/kotlin/dev/msfjarvis/aps/data/passfile/PasswordEntry.kt +++ b/format-common/src/main/kotlin/dev/msfjarvis/aps/data/passfile/PasswordEntry.kt @@ -13,8 +13,8 @@ import dev.msfjarvis.aps.util.time.UserClock import dev.msfjarvis.aps.util.totp.Otp import dev.msfjarvis.aps.util.totp.TotpFinder import kotlin.collections.set +import kotlin.time.Duration import kotlin.time.ExperimentalTime -import kotlin.time.seconds import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow @@ -84,10 +84,10 @@ constructor( scope.launch { updateTotp(clock.millis()) val remainingTime = totpPeriod - (System.currentTimeMillis() % totpPeriod) - delay(remainingTime.seconds) + delay(Duration.seconds(remainingTime)) repeat(Int.MAX_VALUE) { updateTotp(clock.millis()) - delay(totpPeriod.seconds) + delay(Duration.seconds(totpPeriod)) } } } diff --git a/format-common/src/main/kotlin/dev/msfjarvis/aps/util/totp/Otp.kt b/format-common/src/main/kotlin/dev/msfjarvis/aps/util/totp/Otp.kt index e6efd794..832529e9 100644 --- a/format-common/src/main/kotlin/dev/msfjarvis/aps/util/totp/Otp.kt +++ b/format-common/src/main/kotlin/dev/msfjarvis/aps/util/totp/Otp.kt @@ -24,7 +24,7 @@ internal object Otp { } fun calculateCode(secret: String, counter: Long, algorithm: String, digits: String) = runCatching { - val algo = "Hmac${algorithm.toUpperCase(Locale.ROOT)}" + val algo = "Hmac${algorithm.uppercase(Locale.ROOT)}" val decodedSecret = BASE_32.decode(secret) val secretKey = SecretKeySpec(decodedSecret, algo) val digest = diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dbcfbf30..65d8efdc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,9 +1,9 @@ # Centralized versions for dependencies that share versions [versions] androidx_test = "1.4.0-alpha05" -coroutines = "1.4.3" -hilt = "2.34.1-beta" -kotlin = "1.4.32" +coroutines = "1.5.0-RC" +hilt = "2.35.1" +kotlin = "1.5.0" lifecycle = "2.4.0-alpha01" [libraries] diff --git a/openpgp-ktx/CHANGELOG.md b/openpgp-ktx/CHANGELOG.md index 3ba948d8..6222283c 100644 --- a/openpgp-ktx/CHANGELOG.md +++ b/openpgp-ktx/CHANGELOG.md @@ -2,6 +2,8 @@ ### [Unreleased] +- The library now requires Kotlin 1.5.0 configured with `kotlinOptions.languageVersion = "1.5"`. + ### [3.0.0] - 2021-04-10 - Relicence under Apache 2.0 diff --git a/openpgp-ktx/src/main/java/me/msfjarvis/openpgpktx/util/OpenPgpUtils.kt b/openpgp-ktx/src/main/java/me/msfjarvis/openpgpktx/util/OpenPgpUtils.kt index 75acd692..feadb266 100644 --- a/openpgp-ktx/src/main/java/me/msfjarvis/openpgpktx/util/OpenPgpUtils.kt +++ b/openpgp-ktx/src/main/java/me/msfjarvis/openpgpktx/util/OpenPgpUtils.kt @@ -46,7 +46,7 @@ public object OpenPgpUtils { } private fun convertKeyIdToHex32bit(keyId: Long): String { - var hexString = java.lang.Long.toHexString(keyId and 0xffffffffL).toLowerCase(Locale.ENGLISH) + var hexString = java.lang.Long.toHexString(keyId and 0xffffffffL).lowercase(Locale.ENGLISH) while (hexString.length < 8) { hexString = "0$hexString" }