Upgrade to Kotlin 1.5 (#1397)

* build: upgrade Kotlin to 1.5.0 and Hilt to 2.35.1

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>

* all: address kotlin.time.seconds deprecation

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>

* autofill-parser/openpgp-ktx: require Kotlin 1.5

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>

* all: address string method deprecations

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>

* build: disable NewApi lint

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Harsh Shandilya 2021-04-28 10:27:14 +05:30 committed by GitHub
parent d3bc28c1c3
commit 4880e1db27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 43 additions and 38 deletions

View file

@ -35,6 +35,11 @@ android {
isAbortOnError = true isAbortOnError = true
isCheckReleaseBuilds = false isCheckReleaseBuilds = false
disable("MissingTranslation", "PluralsCandidate", "ImpliedQuantity") 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") flavorDimensions("free")

View file

@ -27,8 +27,8 @@ import dev.msfjarvis.aps.util.settings.PreferenceKeys
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.File import java.io.File
import javax.inject.Inject import javax.inject.Inject
import kotlin.time.Duration
import kotlin.time.ExperimentalTime import kotlin.time.ExperimentalTime
import kotlin.time.seconds
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
@ -121,7 +121,7 @@ class DecryptActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound {
@OptIn(ExperimentalTime::class) @OptIn(ExperimentalTime::class)
private fun startAutoDismissTimer() { private fun startAutoDismissTimer() {
lifecycleScope.launch { lifecycleScope.launch {
delay(60.seconds) delay(Duration.seconds(60))
finish() finish()
} }
} }

View file

@ -60,8 +60,8 @@ object RandomPhonemesGenerator {
private class Element(str: String, val flags: Int) { private class Element(str: String, val flags: Int) {
val upperCase = str.toUpperCase(Locale.ROOT) val upperCase = str.uppercase(Locale.ROOT)
val lowerCase = str.toLowerCase(Locale.ROOT) val lowerCase = str.lowercase(Locale.ROOT)
val length = str.length val length = str.length
val isAmbiguous = str.any { it in PasswordGenerator.AMBIGUOUS_STR } val isAmbiguous = str.any { it in PasswordGenerator.AMBIGUOUS_STR }
} }

View file

@ -101,10 +101,16 @@ class PasswordBuilder(ctx: Context) {
val candidate = wordBank.secureRandomElement() val candidate = wordBank.secureRandomElement()
val s = val s =
when (capsType) { when (capsType) {
CapsType.UPPERCASE -> candidate.toUpperCase(Locale.getDefault()) CapsType.UPPERCASE -> candidate.uppercase(Locale.getDefault())
CapsType.Sentence -> if (i == 0) candidate.capitalize(Locale.getDefault()) else candidate CapsType.Sentence ->
CapsType.TitleCase -> candidate.capitalize(Locale.getDefault()) if (i == 0)
CapsType.lowercase -> candidate.toLowerCase(Locale.getDefault()) 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 CapsType.As_iS -> candidate
} }
password.append(s) password.append(s)

View file

@ -442,8 +442,7 @@ open class SearchableRepositoryAdapter<T : RecyclerView.ViewHolder>(
} }
} }
} }
final override fun getPopupText(position: Int): String { 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())
} }
} }

View file

@ -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`. - 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 ### Fixed
- Fix build warning from undeclared unsigned type use. - Fix build warning from undeclared unsigned type use.

View file

@ -39,19 +39,16 @@ internal class FormField(
HintConstants.AUTOFILL_HINT_USERNAME, HintConstants.AUTOFILL_HINT_USERNAME,
HintConstants.AUTOFILL_HINT_NEW_USERNAME, HintConstants.AUTOFILL_HINT_NEW_USERNAME,
) )
private val HINTS_NEW_PASSWORD = private val HINTS_NEW_PASSWORD =
listOf( listOf(
HintConstants.AUTOFILL_HINT_NEW_PASSWORD, HintConstants.AUTOFILL_HINT_NEW_PASSWORD,
) )
private val HINTS_PASSWORD = private val HINTS_PASSWORD =
HINTS_NEW_PASSWORD + HINTS_NEW_PASSWORD +
listOf( listOf(
HintConstants.AUTOFILL_HINT_PASSWORD, HintConstants.AUTOFILL_HINT_PASSWORD,
HintConstants.AUTOFILL_HINT_WIFI_PASSWORD, HintConstants.AUTOFILL_HINT_WIFI_PASSWORD,
) )
private val HINTS_OTP = private val HINTS_OTP =
listOf( listOf(
HintConstants.AUTOFILL_HINT_SMS_OTP, HintConstants.AUTOFILL_HINT_SMS_OTP,
@ -70,7 +67,6 @@ internal class FormField(
HintConstants.AUTOFILL_HINT_PHONE, HintConstants.AUTOFILL_HINT_PHONE,
HintConstants.AUTOFILL_HINT_PHONE_NUMBER, HintConstants.AUTOFILL_HINT_PHONE_NUMBER,
) )
private val ANDROID_TEXT_FIELD_CLASS_NAMES = private val ANDROID_TEXT_FIELD_CLASS_NAMES =
listOf( listOf(
"android.widget.EditText", "android.widget.EditText",
@ -79,9 +75,7 @@ internal class FormField(
"android.support.v7.widget.AppCompatEditText", "android.support.v7.widget.AppCompatEditText",
"com.google.android.material.textfield.TextInputEditText", "com.google.android.material.textfield.TextInputEditText",
) )
private const val ANDROID_WEB_VIEW_CLASS_NAME = "android.webkit.WebView" private const val ANDROID_WEB_VIEW_CLASS_NAME = "android.webkit.WebView"
private fun isPasswordInputType(inputType: Int): Boolean { private fun isPasswordInputType(inputType: Int): Boolean {
val typeClass = inputType and InputType.TYPE_MASK_CLASS val typeClass = inputType and InputType.TYPE_MASK_CLASS
val typeVariation = inputType and InputType.TYPE_MASK_VARIATION 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() (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 @RequiresApi(Build.VERSION_CODES.O) private fun isSupportedHint(hint: String) = hint in HINTS_FILLABLE
private val EXCLUDED_TERMS = private val EXCLUDED_TERMS =
listOf( listOf(
"url_bar", // Chrome/Edge/Firefox address bar "url_bar", // Chrome/Edge/Firefox address bar
@ -158,14 +151,13 @@ internal class FormField(
private val List<String>.anyMatchesFieldInfo private val List<String>.anyMatchesFieldInfo
get() = any { fieldId.contains(it) || hint.contains(it) || htmlName.contains(it) } get() = any { fieldId.contains(it) || hint.contains(it) || htmlName.contains(it) }
val autofillId: AutofillId = node.autofillId!! val autofillId: AutofillId = node.autofillId!!
// Information for heuristics and exclusion rules based only on the current field // 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 htmlId = node.htmlInfo?.attributes?.firstOrNull { it.first == "id" }?.second
private val resourceId = node.idEntry private val resourceId = node.idEntry
private val fieldId = (htmlId ?: resourceId ?: "").toLowerCase(Locale.US) private val fieldId = (htmlId ?: resourceId ?: "").lowercase(Locale.US)
private val hint = node.hint?.toLowerCase(Locale.US) ?: "" private val hint = node.hint?.lowercase(Locale.US) ?: ""
private val className: String? = node.className private val className: String? = node.className
private val inputType = node.inputType private val inputType = node.inputType
@ -186,10 +178,9 @@ internal class FormField(
private val htmlTag = node.htmlInfo?.tag private val htmlTag = node.htmlInfo?.tag
private val htmlAttributes: Map<String, String> = private val htmlAttributes: Map<String, String> =
node.htmlInfo?.attributes?.filter { it.first != null && it.second != null }?.associate { 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() ?: emptyMap()
private val htmlAttributesDebug = htmlAttributes.entries.joinToString { "${it.key}=${it.value}" } private val htmlAttributesDebug = htmlAttributes.entries.joinToString { "${it.key}=${it.value}" }
private val htmlInputType = htmlAttributes["type"] private val htmlInputType = htmlAttributes["type"]
private val htmlName = htmlAttributes["name"] ?: "" 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 // 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 isAndroidTextField = !isHtmlField && className in ANDROID_TEXT_FIELD_CLASS_NAMES
private val isAndroidPasswordField = isAndroidTextField && hasPasswordInputType private val isAndroidPasswordField = isAndroidTextField && hasPasswordInputType
private val isTextField = isAndroidTextField || isHtmlTextField private val isTextField = isAndroidTextField || isHtmlTextField
// Autofill hint detection for native fields // Autofill hint detection for native fields

View file

@ -144,7 +144,7 @@ internal class PublicSuffixListData(private val rules: ByteArray, private val ex
companion object { companion object {
val WILDCARD_LABEL = byteArrayOf('*'.toByte()) val WILDCARD_LABEL = byteArrayOf('*'.code.toByte())
val PREVAILING_RULE = listOf("*") val PREVAILING_RULE = listOf("*")
val EMPTY_RULE = listOf<String>() val EMPTY_RULE = listOf<String>()
const val EXCEPTION_MARKER = '!' const val EXCEPTION_MARKER = '!'

View file

@ -42,7 +42,7 @@ internal fun ByteArray.binarySearch(labels: List<ByteArray>, labelIndex: Int): S
val byte0 = val byte0 =
if (expectDot) { if (expectDot) {
expectDot = false expectDot = false
'.'.toByte() '.'.code.toByte()
} else { } else {
labels[currentLabelIndex][currentLabelByteIndex] and BITMASK labels[currentLabelIndex][currentLabelByteIndex] and BITMASK
} }
@ -109,7 +109,7 @@ internal fun ByteArray.binarySearch(labels: List<ByteArray>, labelIndex: Int): S
/** Search for a '\n' that marks the start of a value. Don't go back past the start of the array. */ /** 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 { private fun ByteArray.findStartOfLineFromIndex(start: Int): Int {
var index = start var index = start
while (index > -1 && this[index] != '\n'.toByte()) { while (index > -1 && this[index] != '\n'.code.toByte()) {
index-- index--
} }
index++ index++
@ -119,7 +119,7 @@ private fun ByteArray.findStartOfLineFromIndex(start: Int): Int {
/** Search for a '\n' that marks the end of a value. */ /** Search for a '\n' that marks the end of a value. */
private fun ByteArray.findEndOfLineFromIndex(start: Int): Int { private fun ByteArray.findEndOfLineFromIndex(start: Int): Int {
var end = 1 var end = 1
while (this[start + end] != '\n'.toByte()) { while (this[start + end] != '\n'.code.toByte()) {
end++ end++
} }
return end return end

View file

@ -41,8 +41,8 @@ dependencies {
implementation("org.jetbrains.kotlinx:binary-compatibility-validator:0.5.0") implementation("org.jetbrains.kotlinx:binary-compatibility-validator:0.5.0")
implementation("org.jetbrains.dokka:dokka-gradle-plugin:1.4.30") implementation("org.jetbrains.dokka:dokka-gradle-plugin:1.4.30")
implementation("de.undercouch:gradle-download-task:4.1.1") implementation("de.undercouch:gradle-download-task:4.1.1")
implementation("com.google.dagger:hilt-android-gradle-plugin:2.34.1-beta") implementation("com.google.dagger:hilt-android-gradle-plugin:2.35.1")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.32") implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.0")
implementation("com.ncorti.ktfmt.gradle:plugin:0.5.0") implementation("com.ncorti.ktfmt.gradle:plugin:0.5.0")
implementation("com.vanniktech:gradle-maven-publish-plugin:0.13.0") implementation("com.vanniktech:gradle-maven-publish-plugin:0.13.0")
implementation("com.vdurmont:semver4j:3.1.0") implementation("com.vdurmont:semver4j:3.1.0")

View file

@ -36,6 +36,7 @@ internal fun Project.configureForAllProjects() {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
@Suppress("DEPRECATION")
jcenter { jcenter {
content { content {
// https://github.com/zhanghai/AndroidFastScroll/issues/35 // https://github.com/zhanghai/AndroidFastScroll/issues/35
@ -57,7 +58,7 @@ internal fun Project.configureForAllProjects() {
kotlinOptions { kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString() jvmTarget = JavaVersion.VERSION_1_8.toString()
freeCompilerArgs = freeCompilerArgs + additionalCompilerArgs freeCompilerArgs = freeCompilerArgs + additionalCompilerArgs
languageVersion = "1.4" languageVersion = "1.5"
useIR = true useIR = true
} }
} }

View file

@ -13,8 +13,8 @@ import dev.msfjarvis.aps.util.time.UserClock
import dev.msfjarvis.aps.util.totp.Otp import dev.msfjarvis.aps.util.totp.Otp
import dev.msfjarvis.aps.util.totp.TotpFinder import dev.msfjarvis.aps.util.totp.TotpFinder
import kotlin.collections.set import kotlin.collections.set
import kotlin.time.Duration
import kotlin.time.ExperimentalTime import kotlin.time.ExperimentalTime
import kotlin.time.seconds
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -84,10 +84,10 @@ constructor(
scope.launch { scope.launch {
updateTotp(clock.millis()) updateTotp(clock.millis())
val remainingTime = totpPeriod - (System.currentTimeMillis() % totpPeriod) val remainingTime = totpPeriod - (System.currentTimeMillis() % totpPeriod)
delay(remainingTime.seconds) delay(Duration.seconds(remainingTime))
repeat(Int.MAX_VALUE) { repeat(Int.MAX_VALUE) {
updateTotp(clock.millis()) updateTotp(clock.millis())
delay(totpPeriod.seconds) delay(Duration.seconds(totpPeriod))
} }
} }
} }

View file

@ -24,7 +24,7 @@ internal object Otp {
} }
fun calculateCode(secret: String, counter: Long, algorithm: String, digits: String) = runCatching { 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 decodedSecret = BASE_32.decode(secret)
val secretKey = SecretKeySpec(decodedSecret, algo) val secretKey = SecretKeySpec(decodedSecret, algo)
val digest = val digest =

View file

@ -1,9 +1,9 @@
# Centralized versions for dependencies that share versions # Centralized versions for dependencies that share versions
[versions] [versions]
androidx_test = "1.4.0-alpha05" androidx_test = "1.4.0-alpha05"
coroutines = "1.4.3" coroutines = "1.5.0-RC"
hilt = "2.34.1-beta" hilt = "2.35.1"
kotlin = "1.4.32" kotlin = "1.5.0"
lifecycle = "2.4.0-alpha01" lifecycle = "2.4.0-alpha01"
[libraries] [libraries]

View file

@ -2,6 +2,8 @@
### [Unreleased] ### [Unreleased]
- The library now requires Kotlin 1.5.0 configured with `kotlinOptions.languageVersion = "1.5"`.
### [3.0.0] - 2021-04-10 ### [3.0.0] - 2021-04-10
- Relicence under Apache 2.0 - Relicence under Apache 2.0

View file

@ -46,7 +46,7 @@ public object OpenPgpUtils {
} }
private fun convertKeyIdToHex32bit(keyId: Long): String { 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) { while (hexString.length < 8) {
hexString = "0$hexString" hexString = "0$hexString"
} }