fix(sort): alphanumeric comparator - #17390
Conversation
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
|
/backport to stable-34.1.x |
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
|
blue-Light-Screenshot test failed, but no output was generated. Maybe a preliminary stage failed. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
This PR replaces the legacy natural-sort implementation with a new Kotlin-based AlphanumericComparator and expands/modernizes unit tests to validate comparator correctness and ordering across more edge cases (per linked issue).
Changes:
- Introduces
com.owncloud.android.utils.sort.AlphanumericComparator(+ChunkKind) and updates call sites to use it. - Removes the previous
thirdparties.daveKoeller.AlphanumComparatorimplementation. - Reworks
NaturalSortTestin Kotlin and broadens coverage (expected orders + comparator contract checks).
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| app/src/test/java/com/nextcloud/client/utils/NaturalSortTest.kt | Converts and expands natural-sort tests; adds locale setup and contract validations. |
| app/src/main/java/thirdparties/daveKoeller/AlphanumComparator.java | Removes the legacy third-party comparator implementation. |
| app/src/main/java/com/owncloud/android/utils/sort/ChunkKind.kt | Adds chunk-kind enum used by the new comparator. |
| app/src/main/java/com/owncloud/android/utils/sort/AlphanumericComparator.kt | Adds new Kotlin comparator implementation based on chunking + collator comparisons. |
| app/src/main/java/com/owncloud/android/utils/FileSortOrderByName.kt | Switches sorting logic to use the new comparator. |
| app/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/BackupFragment.kt | Switches backup file sorting to the new comparator. |
| app/src/main/java/com/owncloud/android/datamodel/OCFile.java | Updates compareTo to use the new comparator’s static compare. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| private val collators: ThreadLocal<Collator> = ThreadLocal.withInitial { Collator.getInstance() } | ||
|
|
||
| private val collator: Collator | ||
| get() = collators.get() ?: Collator.getInstance() |
| private fun compareChunks(ours: String, theirs: String): Int { | ||
| val kind = kindOf(ours[0]) | ||
| val byKind = kind.compareTo(kindOf(theirs[0])) | ||
| if (byKind != 0) { | ||
| return byKind | ||
| } |
| fun sortingNeverThrowsRegardlessOfInputOrder() { | ||
| val comparator = AlphanumericComparator<String>() | ||
| val names = largeNameListWithIgnorableCharacters() | ||
|
|
||
| val failures = (0 until SORT_ATTEMPTS).mapNotNull { seed -> | ||
| runCatching { names.shuffled(Random(seed)).sortedWith(comparator) } | ||
| .exceptionOrNull() | ||
| ?.let { "seed $seed: ${it.message}" } | ||
| } | ||
|
|
||
| assertTrue("Sorting must never throw, but failed for ${failures.take(FAILURES_TO_REPORT)}", failures.isEmpty()) | ||
| } |
| /* | ||
| * Nextcloud - Android Client | ||
| * | ||
| * SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com> | ||
| * SPDX-License-Identifier: AGPL-3.0-or-later | ||
| */ |
|
master-IT test failed: https://www.kaminsky.me/nc-dev/android-integrationTests/17390-IT-master-15-21 |
Changes
Test