ronantakizawa/codereview-bench huggingface dataset:
Repository: thunderbird/thunderbird-android
File: mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/FetchBodyCallback.kt (Kotlin)

Code before:
package com.fsck.k9.mail.store.imap

import com.fsck.k9.mail.MessagingException
import com.fsck.k9.mail.filter.FixedLengthInputStream
import java.io.IOException

internal class FetchBodyCallback(private val mMessageMap: Map<String, ImapMessage>) : ImapResponseCallback {
    @Throws(MessagingException::class, IOException::class)
    override fun foundLiteral(
        response: ImapResponse,
        literal: FixedLengthInputStream,
    ): Any? {
        if (response.tag == null &&
            ImapResponseParser.equalsIgnoreCase(response[1], "FETCH")
        ) {
            val fetchList = response.getKeyedValue("FETCH") as ImapList
            val uid = fetchList.getKeyedString("UID")

            val message = mMessageMap[uid]
            message?.parse(literal)

            // Return placeholder object
            return 1
        }
        return null
    }
}


Review comment (suggestion):
The `mMessageMap` property could be renamed to `messageMap` to avoid using the Java prefix `m`.

Code after:
package com.fsck.k9.mail.store.imap

import com.fsck.k9.mail.MessagingException
import com.fsck.k9.mail.filter.FixedLengthInputStream
import java.io.IOException

const val LITERAL_HANDLED = 1

internal class FetchBodyCallback(private val messageMap: Map<String, ImapMessage>) : ImapResponseCallback {
    @Throws(MessagingException::class, IOException::class)
    override fun foundLiteral(
        response: ImapResponse,
        literal: FixedLengthInputStream,
    ): Any? {
        if (response.tag == null &&
            ImapResponseParser.equalsIgnoreCase(response[1], "FETCH")
        ) {
            val fetchList = response.getKeyedValue("FETCH") as ImapList
            val uid = fetchList.getKeyedString("UID")

            val message = messageMap[uid]
            message?.parse(literal)

            // Return placeholder object
            return LITERAL_HANDLED
        }
        return null
    }
}
Repository: thunderbird/thunderbird-android
File: mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/SearchResponse.kt (Kotlin)

Code before:
package com.fsck.k9.mail.store.imap

internal class SearchResponse private constructor(
    /**
     * @return A mutable list of numbers from the SEARCH response(s).
     */
    @JvmField val numbers: List<Long>,
) {
    companion object {
        @JvmStatic
        fun parse(responses: List<ImapResponse>): SearchResponse {
            val numbers: MutableList<Long> = ArrayList()

            for (response in responses) {
                parseSingleLine(response, numbers)
            }

            return SearchResponse(numbers)
        }

        private fun parseSingleLine(response: ImapResponse, numbers: MutableList<Long>) {
            if (response.isTagged ||
                response.size < 2 ||
                !ImapResponseParser.equalsIgnoreCase(
                    response[0],
                    Responses.SEARCH,
                )
            ) {
                return
            }


Review comment (suggestion):
```suggestion
    /**
     * @return A list of numbers from the SEARCH response(s).
     */
```

Code after:
package com.fsck.k9.mail.store.imap

internal class SearchResponse private constructor(
    /**
     * @return A list of numbers from the SEARCH response(s).
     */
    val numbers: List<Long>,
) {
    companion object {
        @JvmStatic
        fun parse(responses: List<ImapResponse>): SearchResponse {
            val numbers = mutableListOf<Long>()

            for (response in responses) {
                parseSingleLine(response, numbers)
            }

            return SearchResponse(numbers)
        }

        private fun parseSingleLine(response: ImapResponse, numbers: MutableList<Long>) {
            if (response.isTagged ||
                response.size < 2 ||
                !ImapResponseParser.equalsIgnoreCase(
                    response[0],
                    Responses.SEARCH,
                )
            ) {
                return
            }
Repository: thunderbird/thunderbird-android
File: mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/SearchResponse.kt (Kotlin)

Code before:
package com.fsck.k9.mail.store.imap

internal class SearchResponse private constructor(
    /**
     * @return A mutable list of numbers from the SEARCH response(s).
     */
    @JvmField val numbers: List<Long>,
) {
    companion object {
        @JvmStatic
        fun parse(responses: List<ImapResponse>): SearchResponse {
            val numbers: MutableList<Long> = ArrayList()

            for (response in responses) {
                parseSingleLine(response, numbers)
            }

            return SearchResponse(numbers)
        }

        private fun parseSingleLine(response: ImapResponse, numbers: MutableList<Long>) {
            if (response.isTagged ||
                response.size < 2 ||
                !ImapResponseParser.equalsIgnoreCase(
                    response[0],
                    Responses.SEARCH,
                )
            ) {
                return
            }

            val end = response.size
            for (i in 1..<end) {
                try {
                    val number = response.getLong(i)
                    numbers.add(number)
                } catch (e: NumberFormatException) {

Review comment (suggestion):
```suggestion
            val numbers = mutableListOf<Long>()
```

Code after:
package com.fsck.k9.mail.store.imap

internal class SearchResponse private constructor(
    /**
     * @return A list of numbers from the SEARCH response(s).
     */
    val numbers: List<Long>,
) {
    companion object {
        @JvmStatic
        fun parse(responses: List<ImapResponse>): SearchResponse {
            val numbers = mutableListOf<Long>()

            for (response in responses) {
                parseSingleLine(response, numbers)
            }

            return SearchResponse(numbers)
        }

        private fun parseSingleLine(response: ImapResponse, numbers: MutableList<Long>) {
            if (response.isTagged ||
                response.size < 2 ||
                !ImapResponseParser.equalsIgnoreCase(
                    response[0],
                    Responses.SEARCH,
                )
            ) {
                return
            }

            val end = response.size
            for (i in 1..<end) {
                try {
                    val number = response.getLong(i)
                    numbers.add(number)
                } catch (_: NumberFormatException) {
Repository: thunderbird/thunderbird-android
File: mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/SearchResponse.kt (Kotlin)

Code before:
            val numbers: MutableList<Long> = ArrayList()

            for (response in responses) {
                parseSingleLine(response, numbers)
            }

            return SearchResponse(numbers)
        }

        private fun parseSingleLine(response: ImapResponse, numbers: MutableList<Long>) {
            if (response.isTagged ||
                response.size < 2 ||
                !ImapResponseParser.equalsIgnoreCase(
                    response[0],
                    Responses.SEARCH,
                )
            ) {
                return
            }

            val end = response.size
            for (i in 1..<end) {
                try {
                    val number = response.getLong(i)
                    numbers.add(number)
                } catch (e: NumberFormatException) {
                    return
                }
            }
        }
    }
}


Review comment (suggestion):
Although I don't like suppressing exceptions, as this is what is done in the Java code, it is OK. I just suggest a small change:

```suggestion
                } catch (_: NumberFormatException) {
```

Code after:
            val numbers = mutableListOf<Long>()

            for (response in responses) {
                parseSingleLine(response, numbers)
            }

            return SearchResponse(numbers)
        }

        private fun parseSingleLine(response: ImapResponse, numbers: MutableList<Long>) {
            if (response.isTagged ||
                response.size < 2 ||
                !ImapResponseParser.equalsIgnoreCase(
                    response[0],
                    Responses.SEARCH,
                )
            ) {
                return
            }

            val end = response.size
            for (i in 1..<end) {
                try {
                    val number = response.getLong(i)
                    numbers.add(number)
                } catch (_: NumberFormatException) {
                    return
                }
            }
        }
    }
}
Repository: thunderbird/thunderbird-android
File: mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/SearchResponse.kt (Kotlin)

Code before:
package com.fsck.k9.mail.store.imap

internal class SearchResponse private constructor(
    /**
     * @return A mutable list of numbers from the SEARCH response(s).
     */
    @JvmField val numbers: List<Long>,
) {
    companion object {
        @JvmStatic
        fun parse(responses: List<ImapResponse>): SearchResponse {
            val numbers: MutableList<Long> = ArrayList()

            for (response in responses) {
                parseSingleLine(response, numbers)
            }

            return SearchResponse(numbers)
        }

        private fun parseSingleLine(response: ImapResponse, numbers: MutableList<Long>) {
            if (response.isTagged ||
                response.size < 2 ||
                !ImapResponseParser.equalsIgnoreCase(
                    response[0],
                    Responses.SEARCH,
                )
            ) {

Review comment (suggestion):
This class can be migrated to a data class:
```suggestion
@ConsistentCopyVisibility
internal data class SearchResponse private constructor(
```

Code after:
package com.fsck.k9.mail.store.imap

internal class SearchResponse private constructor(
    /**
     * @return A list of numbers from the SEARCH response(s).
     */
    val numbers: List<Long>,
) {
    companion object {
        @JvmStatic
        fun parse(responses: List<ImapResponse>): SearchResponse {
            val numbers = mutableListOf<Long>()

            for (response in responses) {
                parseSingleLine(response, numbers)
            }

            return SearchResponse(numbers)
        }

        private fun parseSingleLine(response: ImapResponse, numbers: MutableList<Long>) {
            if (response.isTagged ||
                response.size < 2 ||
                !ImapResponseParser.equalsIgnoreCase(
                    response[0],
                    Responses.SEARCH,
                )
            ) {
Repository: thunderbird/thunderbird-android
File: legacy/core/src/main/java/com/fsck/k9/message/html/DisplayHtml.kt (Kotlin)

Code before:
     * displayed.
     */
    private fun cssStylePre(): String {
        val font = if (settings.useFixedWidthFont) "monospace" else "sans-serif"

        return """
            <style type="text/css">
                pre.${EmailTextToHtml.K9MAIL_CSS_CLASS} {
                    white-space: pre-wrap;
                    word-wrap: break-word;
                    font-family: $font;
                    margin-top: 0px;
                }
                a {
                    word-break: break-word;
                    overflow-wrap: break-word;
                }
            </style>
        """.trimIndent()
    }

    private fun cssStyleSignature(): String {
        return """
            <style type="text/css">
                .k9mail-signature {
                    opacity: 0.5;
                }
            </style>
        """.trimIndent()
    }
}


Review comment (bug):
I believe we could be more aggressive and apply the `word-break` and `overflow-wrap` properties to all text, rather than just the `a` tag. This approach is similar to what other email providers do.

Code after:
                    $messageContent
                </body>
            </html>
        """.trimIndent()
    }

    /**
     * Dynamically generates a CSS style block that applies global rules to all elements (`*` selector).
     *
     * The style enforces word-breaking and overflow wrapping to prevent content overflow
     * and ensures long text strings break correctly without causing horizontal scrolling.
     *
     * @return A `<style>` element string that can be dynamically injected into the HTML `<head>`
     * to apply these global styles when rendering messages.
     */
    @Language("HTML")
    private fun cssStyleGlobal(): String {
        return """
            <style type="text/css">
                * {
                    word-break: break-word;
                    overflow-wrap: break-word;
                }
            </style>
        """.trimIndent()
    }

    /**
     * Dynamically generate a CSS style for `<pre>` elements.
     *
     * The style incorporates the user's current preference setting for the font family used for plain text messages.
     *
     * @return A `<style>` element that can be dynamically included in the HTML `<head>` element when messages are
     * displayed.
     */
    @Language("HTML")
    private fun cssStylePre(): String {
        val font = if (settings.useFixedWidthFont) "monospace" else "sans-serif"

        return """
            <style type="text/css">
                pre.${EmailTextToHtml.K9MAIL_CSS_CLASS} {
                    white-space: pre-wrap;
                    word-wrap: break-word;
                    font-family: $font;
                    margin-top: 0px;
                }
            </style>
        """.trimIndent()
    }
Repository: thunderbird/thunderbird-android
File: core/logging/impl-file/src/androidMain/kotlin/net/thunderbird/core/logging/file/AndroidFileSystemManager.kt (Kotlin)

Code before:
package net.thunderbird.core.logging.file

import android.content.ContentResolver
import android.net.Uri
import androidx.core.net.toUri
import kotlinx.io.RawSink
import kotlinx.io.asSink

/**
 * Android implementation of [FileSystemManager] that uses [ContentResolver] to perform file operations.
 */
class AndroidFileSystemManager(
    private val contentResolver: ContentResolver,
) : FileSystemManager {
    override fun openSink(uriString: String, mode: String): RawSink? {
        try {
            val uri: Uri = uriString.toUri()
            return contentResolver.openOutputStream(uri, mode)?.asSink()
        } catch (e: SecurityException) {
            throw e
        }
        return null
    }
}


Review comment (suggestion):
This will raise a `RethrowCaughtException` from detekt. Currently is not reporting probably because we are not running the detekt checks within the Android sourceSet.

Unless you need to modify or consume the exception here, avoid just rethrowing it.

Code after:
package net.thunderbird.core.logging.file

import android.content.ContentResolver
import android.net.Uri
import androidx.core.net.toUri
import kotlinx.io.RawSink
import kotlinx.io.asSink

/**
 * Android implementation of [FileSystemManager] that uses [ContentResolver] to perform file operations.
 */
class AndroidFileSystemManager(
    private val contentResolver: ContentResolver,
) : FileSystemManager {
    override fun openSink(uriString: String, mode: String): RawSink? {
        val uri: Uri = uriString.toUri()
        return contentResolver.openOutputStream(uri, mode)?.asSink()
    }
}
Repository: thunderbird/thunderbird-android
File: core/logging/impl-file/src/androidMain/kotlin/net/thunderbird/core/logging/file/AndroidFileSystemManager.kt (Kotlin)

Code before:
package net.thunderbird.core.logging.file

import android.content.ContentResolver
import android.net.Uri
import androidx.core.net.toUri
import kotlinx.io.RawSink
import kotlinx.io.asSink

/**
 * Android implementation of [FileSystemManager] that uses [ContentResolver] to perform file operations.
 */
class AndroidFileSystemManager(
    private val contentResolver: ContentResolver,
) : FileSystemManager {
    override fun openSink(uriString: String, mode: String): RawSink? {
        try {
            val uri: Uri = uriString.toUri()
            return contentResolver.openOutputStream(uri, mode)?.asSink()
        } catch (e: SecurityException) {
            throw e
        }
        return null
    }
}


Review comment (suggestion):
If you modify or consume the exception and rethrow it inside the catch block, this line of code is unreachable and can be deleted

Code after:
package net.thunderbird.core.logging.file

import android.content.ContentResolver
import android.net.Uri
import androidx.core.net.toUri
import kotlinx.io.RawSink
import kotlinx.io.asSink

/**
 * Android implementation of [FileSystemManager] that uses [ContentResolver] to perform file operations.
 */
class AndroidFileSystemManager(
    private val contentResolver: ContentResolver,
) : FileSystemManager {
    override fun openSink(uriString: String, mode: String): RawSink? {
        val uri: Uri = uriString.toUri()
        return contentResolver.openOutputStream(uri, mode)?.asSink()
    }
}
Repository: thunderbird/thunderbird-android
File: legacy/core/src/main/java/com/fsck/k9/job/FileLogLimitWorkManager.kt (Kotlin)

Code before:
package com.fsck.k9.job

import androidx.lifecycle.LiveData
import androidx.work.BackoffPolicy
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.workDataOf
import java.util.concurrent.TimeUnit

class FileLogLimitWorkManager(
    private val workManager: WorkManager,
) {
    fun scheduleFileLogTimeLimit(contentUriString: String): LiveData<WorkInfo?> {
        val data = workDataOf("exportUriString" to contentUriString)
        val workRequest: OneTimeWorkRequest =
            OneTimeWorkRequestBuilder<SyncDebugWorker>()
                .setInitialDelay(TWENTY_FOUR_HOURS, TimeUnit.HOURS)
                .setInputData(data)
                .addTag(SYNC_TAG)
                .setBackoffCriteria(BackoffPolicy.LINEAR, INITIAL_BACKOFF_DELAY_MINUTES, TimeUnit.MINUTES)
                .build()
        workManager.enqueueUniqueWork(SYNC_TAG, ExistingWorkPolicy.REPLACE, workRequest)
        return workManager.getWorkInfoByIdLiveData(workRequest.id)
    }

    fun cancelFileLogTimeLimit() {
        workManager.cancelUniqueWork(SYNC_TAG)
    }

    companion object {
        const val SYNC_TAG = "sync_debug_timer"
        private const val INITIAL_BACKOFF_DELAY_MINUTES = 5L
        private const val TWENTY_FOUR_HOURS = 24L
    }
}


Review comment (suggestion):
If possible, I would suggest returning a `Flow` instead of a `LiveData` here.

Code after:
package com.fsck.k9.job

import androidx.work.BackoffPolicy
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.workDataOf
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.flow.Flow

class FileLogLimitWorkManager(
    private val workManager: WorkManager,
) {
    fun scheduleFileLogTimeLimit(contentUriString: String): Flow<WorkInfo?> {
        val data = workDataOf("exportUriString" to contentUriString)
        val workRequest: OneTimeWorkRequest =
            OneTimeWorkRequestBuilder<SyncDebugWorker>()
                .setInitialDelay(TWENTY_FOUR_HOURS, TimeUnit.HOURS)
                .setInputData(data)
                .addTag(SYNC_TAG)
                .setBackoffCriteria(BackoffPolicy.LINEAR, INITIAL_BACKOFF_DELAY_MINUTES, TimeUnit.MINUTES)
                .build()
        workManager.enqueueUniqueWork(SYNC_TAG, ExistingWorkPolicy.REPLACE, workRequest)
        return workManager.getWorkInfoByIdFlow(workRequest.id)
    }

    fun cancelFileLogTimeLimit() {
        workManager.cancelUniqueWork(SYNC_TAG)
    }

    companion object {
        const val SYNC_TAG = "sync_debug_timer"
        private const val INITIAL_BACKOFF_DELAY_MINUTES = 5L
        private const val TWENTY_FOUR_HOURS = 24L
    }
}
Repository: thunderbird/thunderbird-android
File: legacy/core/src/main/java/com/fsck/k9/job/FileLogLimitWorkManager.kt (Kotlin)

Code before:
package com.fsck.k9.job

import androidx.lifecycle.LiveData
import androidx.work.BackoffPolicy
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.workDataOf
import java.util.concurrent.TimeUnit

class FileLogLimitWorkManager(
    private val workManager: WorkManager,
) {
    fun scheduleFileLogTimeLimit(contentUriString: String): LiveData<WorkInfo?> {
        val data = workDataOf("exportUriString" to contentUriString)
        val workRequest: OneTimeWorkRequest =
            OneTimeWorkRequestBuilder<SyncDebugWorker>()
                .setInitialDelay(TWENTY_FOUR_HOURS, TimeUnit.HOURS)
                .setInputData(data)
                .addTag(SYNC_TAG)
                .setBackoffCriteria(BackoffPolicy.LINEAR, INITIAL_BACKOFF_DELAY_MINUTES, TimeUnit.MINUTES)
                .build()
        workManager.enqueueUniqueWork(SYNC_TAG, ExistingWorkPolicy.REPLACE, workRequest)
        return workManager.getWorkInfoByIdLiveData(workRequest.id)
    }

    fun cancelFileLogTimeLimit() {
        workManager.cancelUniqueWork(SYNC_TAG)
    }

    companion object {
        const val SYNC_TAG = "sync_debug_timer"
        private const val INITIAL_BACKOFF_DELAY_MINUTES = 5L
        private const val TWENTY_FOUR_HOURS = 24L
    }
}


Review comment (suggestion):
if possible, I would suggest using `workManager.getWorkInfoByIdFlow` instead

Code after:
package com.fsck.k9.job

import androidx.work.BackoffPolicy
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.workDataOf
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.flow.Flow

class FileLogLimitWorkManager(
    private val workManager: WorkManager,
) {
    fun scheduleFileLogTimeLimit(contentUriString: String): Flow<WorkInfo?> {
        val data = workDataOf("exportUriString" to contentUriString)
        val workRequest: OneTimeWorkRequest =
            OneTimeWorkRequestBuilder<SyncDebugWorker>()
                .setInitialDelay(TWENTY_FOUR_HOURS, TimeUnit.HOURS)
                .setInputData(data)
                .addTag(SYNC_TAG)
                .setBackoffCriteria(BackoffPolicy.LINEAR, INITIAL_BACKOFF_DELAY_MINUTES, TimeUnit.MINUTES)
                .build()
        workManager.enqueueUniqueWork(SYNC_TAG, ExistingWorkPolicy.REPLACE, workRequest)
        return workManager.getWorkInfoByIdFlow(workRequest.id)
    }

    fun cancelFileLogTimeLimit() {
        workManager.cancelUniqueWork(SYNC_TAG)
    }

    companion object {
        const val SYNC_TAG = "sync_debug_timer"
        private const val INITIAL_BACKOFF_DELAY_MINUTES = 5L
        private const val TWENTY_FOUR_HOURS = 24L
    }
}