diff --git a/app/src/main/java/com/itsaky/androidide/activities/editor/EditorHandlerActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/editor/EditorHandlerActivity.kt index 87afa2f6e..d09c2791c 100644 --- a/app/src/main/java/com/itsaky/androidide/activities/editor/EditorHandlerActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/editor/EditorHandlerActivity.kt @@ -21,12 +21,11 @@ import android.annotation.SuppressLint import android.content.Context import android.os.Bundle import android.text.TextUtils -import android.util.SparseArray import android.view.Menu import android.view.MenuItem import android.view.ViewGroup.LayoutParams import androidx.appcompat.view.menu.MenuBuilder -import androidx.core.util.forEach +import androidx.collection.MutableIntObjectMap import androidx.core.view.GravityCompat import com.blankj.utilcode.util.ImageUtils import com.blankj.utilcode.util.ThreadUtils @@ -642,7 +641,7 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler { executeAsyncProvideError({ val files = editorViewModel.getOpenedFiles() val dupliCount = mutableMapOf() - val names = SparseArray() + val names = MutableIntObjectMap() val nameBuilder = UniqueNameBuilder("", File.separator) files.forEach { diff --git a/common/build.gradle.kts b/common/build.gradle.kts index d16713ce3..5de4dee93 100755 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -8,24 +8,25 @@ android { } dependencies { - implementation(libs.common.editor) - implementation(libs.common.lang3) - implementation(libs.common.utilcode) - implementation(libs.google.guava) - implementation(libs.google.material) + api(libs.common.editor) + api(libs.common.lang3) + api(libs.common.utilcode) + api(libs.google.guava) + api(libs.google.material) - implementation(libs.androidx.appcompat) - implementation(libs.androidx.preference) - implementation(libs.androidx.vectors) - implementation(libs.androidx.animated.vectors) + api(libs.androidx.appcompat) + api(libs.androidx.collection) + api(libs.androidx.preference) + api(libs.androidx.vectors) + api(libs.androidx.animated.vectors) - implementation(libs.androidx.ktx) - implementation(libs.common.kotlin) + api(libs.androidx.ktx) + api(libs.common.kotlin) - implementation(projects.buildInfo) - implementation(projects.eventbusEvents) - implementation(projects.lexers) - implementation(projects.resources) + api(projects.buildInfo) + api(projects.eventbusEvents) + api(projects.lexers) + api(projects.resources) api(projects.shared) api(projects.logger) diff --git a/common/src/main/java/com/itsaky/androidide/utils/SparseArrayUtils.kt b/common/src/main/java/com/itsaky/androidide/utils/SparseArrayUtils.kt index 6b73925d9..88b088828 100644 --- a/common/src/main/java/com/itsaky/androidide/utils/SparseArrayUtils.kt +++ b/common/src/main/java/com/itsaky/androidide/utils/SparseArrayUtils.kt @@ -22,7 +22,7 @@ import android.util.SparseIntArray /** * Get the value associated with the given key or `null`. */ -fun SparseIntArray.getOrNull(key: Int) : Int? { +fun SparseIntArray.getOrNull(key: Int): Int? { val keyIdx = indexOfKey(key) if (keyIdx >= 0) { return valueAt(keyIdx) diff --git a/editor-treesitter/build.gradle.kts b/editor-treesitter/build.gradle.kts index b4ed76b2b..2661a69f0 100644 --- a/editor-treesitter/build.gradle.kts +++ b/editor-treesitter/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { api(libs.common.editor) api(libs.common.kotlin.coroutines.android) api(libs.androidide.ts) + api(libs.androidx.collection) api(projects.common) api(projects.editorApi) diff --git a/editor-treesitter/src/main/java/io/github/rosemoe/sora/editor/ts/TsTheme.kt b/editor-treesitter/src/main/java/io/github/rosemoe/sora/editor/ts/TsTheme.kt index eb263f105..f3bb45f41 100644 --- a/editor-treesitter/src/main/java/io/github/rosemoe/sora/editor/ts/TsTheme.kt +++ b/editor-treesitter/src/main/java/io/github/rosemoe/sora/editor/ts/TsTheme.kt @@ -24,7 +24,7 @@ package io.github.rosemoe.sora.editor.ts -import android.util.SparseLongArray +import androidx.collection.MutableIntLongMap import com.itsaky.androidide.treesitter.TSQuery import io.github.rosemoe.sora.lang.styling.TextStyle import io.github.rosemoe.sora.widget.schemes.EditorColorScheme @@ -45,7 +45,7 @@ import io.github.rosemoe.sora.widget.schemes.EditorColorScheme class TsTheme(private val tsQuery: TSQuery) { private val styles = mutableMapOf() - private val mapping = SparseLongArray() + private val mapping = MutableIntLongMap() /** * The text style for normal texts @@ -71,10 +71,7 @@ class TsTheme(private val tsQuery: TSQuery) { fun eraseStyleRule(rule: String) = putStyleRule(rule, 0L) fun resolveStyleForPattern(pattern: Int): Long { - val index = mapping.indexOfKey(pattern) - return if (index >= 0) { - mapping.valueAt(index) - } else { + return mapping.getOrElse(pattern) { var mappedName = tsQuery.getCaptureNameForId(pattern) var style = styles[mappedName] ?: 0L while (style == 0L && mappedName.isNotEmpty()) { diff --git a/editor/build.gradle.kts b/editor/build.gradle.kts index 324defc45..8907e748f 100644 --- a/editor/build.gradle.kts +++ b/editor/build.gradle.kts @@ -25,6 +25,7 @@ dependencies { api(libs.androidide.ts.kotlin) api(libs.androidide.ts.log) api(libs.androidide.ts.xml) + api(libs.androidx.collection) api(libs.common.editor) api(projects.editorApi) diff --git a/editor/src/main/java/com/itsaky/androidide/editor/schemes/IDEColorScheme.kt b/editor/src/main/java/com/itsaky/androidide/editor/schemes/IDEColorScheme.kt index 485d2c60c..d4bdc5a2b 100644 --- a/editor/src/main/java/com/itsaky/androidide/editor/schemes/IDEColorScheme.kt +++ b/editor/src/main/java/com/itsaky/androidide/editor/schemes/IDEColorScheme.kt @@ -17,12 +17,9 @@ package com.itsaky.androidide.editor.schemes -import android.util.SparseIntArray -import androidx.core.util.containsKey -import androidx.core.util.set +import androidx.collection.MutableIntIntMap import com.itsaky.androidide.editor.schemes.internal.parser.SchemeParser import com.itsaky.androidide.syntax.colorschemes.DynamicColorScheme -import com.itsaky.androidide.utils.getOrNull import io.github.rosemoe.sora.lang.styling.TextStyle import io.github.rosemoe.sora.widget.schemes.EditorColorScheme import java.io.File @@ -30,8 +27,8 @@ import java.util.TreeSet class IDEColorScheme(internal val file: File, val key: String) : DynamicColorScheme() { - internal val colorIds = SparseIntArray() - internal val editorScheme = SparseIntArray() + internal val colorIds = MutableIntIntMap() + internal val editorScheme = MutableIntIntMap() internal val languages = mutableMapOf() var name: String = "" @@ -64,11 +61,14 @@ class IDEColorScheme(internal val file: File, val key: String) : DynamicColorSch return colorId } - @Suppress("UNNECESSARY_SAFE_CALL") + @Suppress("UNNECESSARY_SAFE_CALL", "USELESS_ELVIS") override fun getColor(type: Int): Int { // getColor is called in superclass constructor // in this case, the below properties will be null - return editorScheme?.getOrNull(type) ?: colorIds?.getOrNull(type) ?: super.getColor(type) + val defaultValue = super.getColor(type) + return editorScheme?.getOrElse(type) { + colorIds?.getOrDefault(type, defaultValue) ?: defaultValue + } ?: defaultValue } override fun isDark(): Boolean { diff --git a/editor/src/main/java/com/itsaky/androidide/editor/schemes/internal/parser/common.kt b/editor/src/main/java/com/itsaky/androidide/editor/schemes/internal/parser/common.kt index c907b2210..204cadd10 100644 --- a/editor/src/main/java/com/itsaky/androidide/editor/schemes/internal/parser/common.kt +++ b/editor/src/main/java/com/itsaky/androidide/editor/schemes/internal/parser/common.kt @@ -17,7 +17,6 @@ package com.itsaky.androidide.editor.schemes.internal.parser -import android.graphics.Color import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonToken.STRING import com.itsaky.androidide.editor.schemes.IDEColorScheme @@ -101,12 +100,13 @@ fun IDEColorScheme.parseLanguage( } } -private fun readerForFileRef(reader: JsonReader, scheme: String, resolveFileRef: (String) -> File): JsonReader { +private fun readerForFileRef(reader: JsonReader, scheme: String, + resolveFileRef: (String) -> File): JsonReader { val value = reader.nextString() if (value.length <= 1 || value[0] != '@') { throw ParseException("Expected a $scheme scheme file reference but was '$value'") } - + val langFile = resolveFileRef(value.substring(1)) if (!langFile.exists() || !langFile.isFile) { throw ParseException("Referenced file does not exist or is not a file '$langFile'") diff --git a/editor/src/test/java/com/itsaky/androidide/editor/schemes/internal/parser/SchemeParserTest.kt b/editor/src/test/java/com/itsaky/androidide/editor/schemes/internal/parser/SchemeParserTest.kt index c1ca517d7..3f211837f 100644 --- a/editor/src/test/java/com/itsaky/androidide/editor/schemes/internal/parser/SchemeParserTest.kt +++ b/editor/src/test/java/com/itsaky/androidide/editor/schemes/internal/parser/SchemeParserTest.kt @@ -18,16 +18,13 @@ package com.itsaky.androidide.editor.schemes.internal.parser import android.graphics.Color -import android.util.SparseIntArray -import androidx.core.util.size import com.google.common.truth.Truth.assertThat import com.itsaky.androidide.editor.schemes.IDEColorScheme -import com.itsaky.androidide.editor.schemes.internal.parser.SchemeParser import io.github.rosemoe.sora.widget.schemes.EditorColorScheme -import java.io.File import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner +import java.io.File /** @author Akash Yadav */ @RunWith(RobolectricTestRunner::class) @@ -40,7 +37,8 @@ class SchemeParserTest { assertThat(scheme.definitions).hasSize(12) assertThat(scheme.colorIds[scheme.definitions["black"] ?: -1]).isEqualTo(Color.BLACK) assertThat(scheme.colorIds[scheme.definitions["white"] ?: -1]).isEqualTo(Color.WHITE) - assertThat(scheme.colorIds[scheme.definitions["9e"] ?: -1]).isEqualTo(Color.parseColor("#9e9e9e")) + assertThat(scheme.colorIds[scheme.definitions["9e"] ?: -1]).isEqualTo( + Color.parseColor("#9e9e9e")) assertThat(scheme.editorScheme.size).isEqualTo(27) assertThat(scheme.editorScheme[EditorColorScheme.WHOLE_BACKGROUND]) @@ -65,12 +63,14 @@ class SchemeParserTest { this.styles["text.debug"].apply { assertThat(this).isNotNull() assertThat(scheme.colorIds[this!!.fg]).isEqualTo(Color.parseColor("#f5f5f5")) - assertThat(scheme.colorIds[this.fg]).isEqualTo(scheme.colorIds[scheme.definitions["f5"] ?: -1]) + assertThat(scheme.colorIds[this.fg]).isEqualTo( + scheme.colorIds[scheme.definitions["f5"] ?: -1]) } this.styles["priority.debug"].apply { assertThat(this).isNotNull() assertThat(scheme.colorIds[this!!.fg]).isEqualTo(Color.WHITE) - assertThat(scheme.colorIds[this.fg]).isEqualTo(scheme.colorIds[scheme.definitions["white"] ?: -1]) + assertThat(scheme.colorIds[this.fg]).isEqualTo( + scheme.colorIds[scheme.definitions["white"] ?: -1]) assertThat(scheme.colorIds[this.bg]).isEqualTo(Color.parseColor("#9e9d24")) assertThat(this.bold || this.italic || this.strikeThrough).isFalse() assertThat(this.completion).isTrue() @@ -78,7 +78,8 @@ class SchemeParserTest { this.styles["priority.error"].apply { assertThat(this).isNotNull() assertThat(scheme.colorIds[this!!.fg]).isEqualTo(Color.BLACK) - assertThat(scheme.colorIds[this.fg]).isEqualTo(scheme.colorIds[scheme.definitions["black"] ?: -1]) + assertThat(scheme.colorIds[this.fg]).isEqualTo( + scheme.colorIds[scheme.definitions["black"] ?: -1]) assertThat(scheme.colorIds[this.bg]).isEqualTo(Color.parseColor("#f44336")) assertThat(this.bold || this.italic || this.strikeThrough).isFalse() assertThat(this.completion).isFalse() @@ -116,12 +117,14 @@ class SchemeParserTest { this.styles["text.debug"].apply { assertThat(this).isNotNull() assertThat(scheme.colorIds[this!!.fg]).isEqualTo(Color.parseColor("#f5f5f5")) - assertThat(scheme.colorIds[this.fg]).isEqualTo(scheme.colorIds[scheme.definitions["f5"] ?: -1]) + assertThat(scheme.colorIds[this.fg]).isEqualTo( + scheme.colorIds[scheme.definitions["f5"] ?: -1]) } this.styles["priority.debug"].apply { assertThat(this).isNotNull() assertThat(scheme.colorIds[this!!.fg]).isEqualTo(Color.WHITE) - assertThat(scheme.colorIds[this.fg]).isEqualTo(scheme.colorIds[scheme.definitions["white"] ?: -1]) + assertThat(scheme.colorIds[this.fg]).isEqualTo( + scheme.colorIds[scheme.definitions["white"] ?: -1]) assertThat(scheme.colorIds[this.bg]).isEqualTo(Color.parseColor("#9e9d24")) assertThat(this.bold || this.italic || this.strikeThrough).isFalse() assertThat(this.completion).isTrue() @@ -129,7 +132,8 @@ class SchemeParserTest { this.styles["priority.error"].apply { assertThat(this).isNotNull() assertThat(scheme.colorIds[this!!.fg]).isEqualTo(Color.BLACK) - assertThat(scheme.colorIds[this.fg]).isEqualTo(scheme.colorIds[scheme.definitions["black"] ?: -1]) + assertThat(scheme.colorIds[this.fg]).isEqualTo( + scheme.colorIds[scheme.definitions["black"] ?: -1]) assertThat(scheme.colorIds[this.bg]).isEqualTo(Color.parseColor("#f44336")) assertThat(this.bold || this.italic || this.strikeThrough).isFalse() assertThat(this.completion).isFalse() @@ -162,12 +166,14 @@ class SchemeParserTest { this.styles["text.debug"].apply { assertThat(this).isNotNull() assertThat(scheme.colorIds[this!!.fg]).isEqualTo(Color.parseColor("#f5f5f5")) - assertThat(scheme.colorIds[this.fg]).isEqualTo(scheme.colorIds[scheme.definitions["f5"] ?: -1]) + assertThat(scheme.colorIds[this.fg]).isEqualTo( + scheme.colorIds[scheme.definitions["f5"] ?: -1]) } this.styles["priority.debug"].apply { assertThat(this).isNotNull() assertThat(scheme.colorIds[this!!.fg]).isEqualTo(Color.WHITE) - assertThat(scheme.colorIds[this.fg]).isEqualTo(scheme.colorIds[scheme.definitions["white"] ?: -1]) + assertThat(scheme.colorIds[this.fg]).isEqualTo( + scheme.colorIds[scheme.definitions["white"] ?: -1]) assertThat(scheme.colorIds[this.bg]).isEqualTo(Color.parseColor("#9e9d24")) assertThat(this.bold || this.italic || this.strikeThrough).isFalse() assertThat(this.completion).isTrue() @@ -175,7 +181,8 @@ class SchemeParserTest { this.styles["priority.error"].apply { assertThat(this).isNotNull() assertThat(scheme.colorIds[this!!.fg]).isEqualTo(Color.BLACK) - assertThat(scheme.colorIds[this.fg]).isEqualTo(scheme.colorIds[scheme.definitions["black"] ?: -1]) + assertThat(scheme.colorIds[this.fg]).isEqualTo( + scheme.colorIds[scheme.definitions["black"] ?: -1]) assertThat(scheme.colorIds[this.bg]).isEqualTo(Color.parseColor("#f44336")) assertThat(this.bold || this.italic || this.strikeThrough).isFalse() assertThat(this.completion).isFalse() @@ -197,7 +204,8 @@ class SchemeParserTest { assertThat(scheme.definitions).hasSize(12) assertThat(scheme.colorIds[scheme.definitions["black"] ?: -1]).isEqualTo(Color.BLACK) assertThat(scheme.colorIds[scheme.definitions["white"] ?: -1]).isEqualTo(Color.WHITE) - assertThat(scheme.colorIds[scheme.definitions["9e"] ?: -1]).isEqualTo(Color.parseColor("#9e9e9e")) + assertThat(scheme.colorIds[scheme.definitions["9e"] ?: -1]).isEqualTo( + Color.parseColor("#9e9e9e")) assertThat(scheme.editorScheme.size).isEqualTo(27) assertThat(scheme.editorScheme[EditorColorScheme.WHOLE_BACKGROUND]) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0d1fe524f..b3498375c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -53,6 +53,7 @@ common-retrofit-gson = { module = "com.squareup.retrofit2:converter-gson", versi androidx-annotation = { module = "androidx.annotation:annotation", version = "1.7.0" } androidx-appcompat = { module = "androidx.appcompat:appcompat", version = "1.6.1" } androidx-cardview = { module = "androidx.cardview:cardview", version = "1.0.0" } +androidx-collection = { module = "androidx.collection:collection", version = "1.4.0-alpha02" } androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version = "2.1.4" } androidx-coordinatorlayout = { module = "androidx.coordinatorlayout:coordinatorlayout", version = "1.2.0" } androidx-drawer = { module = "androidx.drawerlayout:drawerlayout", version = "1.2.0" } diff --git a/subprojects/aaptcompiler/build.gradle.kts b/subprojects/aaptcompiler/build.gradle.kts index 6451309ef..40fd2d340 100644 --- a/subprojects/aaptcompiler/build.gradle.kts +++ b/subprojects/aaptcompiler/build.gradle.kts @@ -32,6 +32,7 @@ android { dependencies { implementation(libs.common.kotlin) + implementation(libs.androidx.collection) implementation(projects.logger) implementation(projects.subprojects.jaxp) diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/proto/ProtoDeserialize.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/proto/ProtoDeserialize.kt index 3e31e6c03..c4a04068e 100755 --- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/proto/ProtoDeserialize.kt +++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/proto/ProtoDeserialize.kt @@ -1,5 +1,6 @@ package com.android.aaptcompiler.proto +import androidx.collection.MutableIntObjectMap import com.android.aapt.ConfigurationOuterClass import com.android.aapt.Resources import com.android.aaptcompiler.AllowNew @@ -40,9 +41,8 @@ import com.android.aaptcompiler.isValidId import com.android.aaptcompiler.parseResourceName import com.android.aaptcompiler.resourceIdFromParts import com.android.aaptcompiler.resourceTypeFromTag -import com.itsaky.androidide.layoutlib.resources.ResourceVisibility import com.android.utils.ILogger -import com.android.utils.SparseArray +import com.itsaky.androidide.layoutlib.resources.ResourceVisibility fun deserializeConfigFromPb( config: ConfigurationOuterClass.Configuration, logger: ILogger?): ConfigDescription? { @@ -639,7 +639,7 @@ fun deserializePackageFromPb( val packageId = if (original.hasPackageId()) original.getPackageId().getId().toByte() else 0.toByte() - val idIndex = SparseArray() + val idIndex = MutableIntObjectMap() val resourcePackage = table.createPackageAllowingDuplicateNames(original.getPackageName(), packageId)