From f837b9369e54d42e4319c10b63ce5bf6aed5deb1 Mon Sep 17 00:00:00 2001 From: Akash Yadav Date: Sat, 20 Jul 2024 20:16:47 +0530 Subject: [PATCH] fix: remove Realm DB --- .idea/compiler.xml | 2 + .idea/kotlinc.xml | 2 +- build.gradle.kts | 1 - core/app/build.gradle.kts | 1 - .../itsaky/androidide/app/IDEApplication.kt | 3 - core/database/.gitignore | 1 - core/database/build.gradle.kts | 41 -- core/database/consumer-rules.pro | 0 core/database/proguard-rules.pro | 21 - .../itsaky/androidide/db/IRealmProvider.kt | 91 --- .../androidide/db/internal/DatabaseEntity.kt | 66 --- .../db/internal/InternalDBRealmModule.kt | 28 - .../db/internal/RealmProviderImpl.kt | 115 ---- .../db/utils/realmDictionaryExts.kt | 60 -- core/indexing-api/build.gradle.kts | 4 - .../androidide/indexing/AbstractDBIndex.kt | 59 -- .../androidide/indexing/IDatabaseIndex.kt | 33 -- .../com/itsaky/androidide/indexing/IIndex.kt | 6 +- .../itsaky/androidide/indexing/IIndexable.kt | 4 +- core/indexing-core/build.gradle.kts | 3 - .../indexing/core/IndexingCoreRealmModule.kt | 26 - .../editor/adapters/CompletionListAdapter.kt | 2 +- gradle/libs.versions.toml | 2 - java/lsp/build.gradle.kts | 3 - .../lsp/java/indexing/JavaClassCRUDTest.kt | 2 +- .../lsp/java/indexing/ModelBuilderTestUtil.kt | 2 +- .../lsp/java/indexing/SharedModelCRUDTest.kt | 2 +- .../lsp/java/indexing/IJavaIndexable.kt | 25 - .../lsp/java/indexing/IJavaSymbol.kt | 29 - .../androidide/lsp/java/indexing/IJavaType.kt | 73 --- .../lsp/java/indexing/ISharedJavaIndexable.kt | 36 -- .../java/indexing/JavaIndexingRealmModule.kt | 59 -- .../lsp/java/indexing/JavaJarModelBuilder.kt | 424 -------------- .../indexing/classfile/AnnotationElement.kt | 91 --- .../java/indexing/classfile/JavaAnnotation.kt | 105 ---- .../lsp/java/indexing/classfile/JavaClass.kt | 98 ---- .../java/indexing/classfile/JavaConstant.kt | 152 ----- .../lsp/java/indexing/classfile/JavaEnum.kt | 97 ---- .../lsp/java/indexing/classfile/JavaField.kt | 65 --- .../java/indexing/classfile/JavaInterface.kt | 96 ---- .../lsp/java/indexing/classfile/JavaMethod.kt | 83 --- .../classfile/annotationElementValues.kt | 340 ------------ .../indexing/internal/JavaIndexServiceImpl.kt | 43 -- .../lsp/java/utils/DescriptorUtils.kt | 232 -------- .../{indexing/classfile => utils}/JavaType.kt | 53 +- .../java/indexing/AndroidJarModelingRule.kt | 65 --- .../lsp/java/indexing/DescriptorUtilsTest.kt | 121 ---- .../lsp/java/indexing/JavaIndexWorkerTest.kt | 524 ------------------ settings.gradle.kts | 1 - testing/androidTest/build.gradle.kts | 5 - testing/benchmarks/build.gradle.kts | 1 - 51 files changed, 15 insertions(+), 3383 deletions(-) delete mode 100644 core/database/.gitignore delete mode 100644 core/database/build.gradle.kts delete mode 100644 core/database/consumer-rules.pro delete mode 100644 core/database/proguard-rules.pro delete mode 100644 core/database/src/main/java/com/itsaky/androidide/db/IRealmProvider.kt delete mode 100644 core/database/src/main/java/com/itsaky/androidide/db/internal/DatabaseEntity.kt delete mode 100644 core/database/src/main/java/com/itsaky/androidide/db/internal/InternalDBRealmModule.kt delete mode 100644 core/database/src/main/java/com/itsaky/androidide/db/internal/RealmProviderImpl.kt delete mode 100644 core/database/src/main/java/com/itsaky/androidide/db/utils/realmDictionaryExts.kt delete mode 100644 core/indexing-api/src/main/java/com/itsaky/androidide/indexing/AbstractDBIndex.kt delete mode 100644 core/indexing-api/src/main/java/com/itsaky/androidide/indexing/IDatabaseIndex.kt delete mode 100644 core/indexing-core/src/main/java/com/itsaky/androidide/indexing/core/IndexingCoreRealmModule.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/IJavaIndexable.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/IJavaSymbol.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/IJavaType.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/ISharedJavaIndexable.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/JavaIndexingRealmModule.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/JavaJarModelBuilder.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/AnnotationElement.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaAnnotation.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaClass.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaConstant.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaEnum.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaField.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaInterface.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaMethod.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/annotationElementValues.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/internal/JavaIndexServiceImpl.kt delete mode 100644 java/lsp/src/main/java/com/itsaky/androidide/lsp/java/utils/DescriptorUtils.kt rename java/lsp/src/main/java/com/itsaky/androidide/lsp/java/{indexing/classfile => utils}/JavaType.kt (79%) delete mode 100644 java/lsp/src/test/java/com/itsaky/androidide/lsp/java/indexing/AndroidJarModelingRule.kt delete mode 100644 java/lsp/src/test/java/com/itsaky/androidide/lsp/java/indexing/DescriptorUtilsTest.kt delete mode 100644 java/lsp/src/test/java/com/itsaky/androidide/lsp/java/indexing/JavaIndexWorkerTest.kt diff --git a/.idea/compiler.xml b/.idea/compiler.xml index aaa7ffdad..7b2ca4a83 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -116,6 +116,7 @@ + @@ -272,6 +273,7 @@ + diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 8d81632f8..148fdd246 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index e8d4749f4..d7aca97f3 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -42,7 +42,6 @@ buildscript { dependencies { classpath(libs.kotlin.gradle.plugin) classpath(libs.nav.safe.args.gradle.plugin) - classpath(libs.realm.gradle.plugin) } } diff --git a/core/app/build.gradle.kts b/core/app/build.gradle.kts index 9f3fc46b5..7028cdac9 100755 --- a/core/app/build.gradle.kts +++ b/core/app/build.gradle.kts @@ -28,7 +28,6 @@ plugins { id("kotlin-android") id("kotlin-kapt") id("kotlin-parcelize") - id("realm-android") id("androidx.navigation.safeargs.kotlin") id("com.itsaky.androidide.desugaring") } diff --git a/core/app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt b/core/app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt index 57f32048e..46789db4f 100755 --- a/core/app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt +++ b/core/app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt @@ -58,7 +58,6 @@ import com.itsaky.androidide.utils.flashError import com.termux.app.TermuxApplication import com.termux.shared.reflection.ReflectionUtils import io.github.rosemoe.sora.widget.schemes.EditorColorScheme -import io.realm.Realm import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -110,8 +109,6 @@ class IDEApplication : TermuxApplication() { EventBus.getDefault().register(this) - Realm.init(this) - AppCompatDelegate.setDefaultNightMode(GeneralPreferences.uiMode) if (IThemeManager.getInstance().getCurrentTheme() == IDETheme.MATERIAL_YOU) { diff --git a/core/database/.gitignore b/core/database/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/core/database/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/core/database/build.gradle.kts b/core/database/build.gradle.kts deleted file mode 100644 index 969171f1f..000000000 --- a/core/database/build.gradle.kts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - - -import com.itsaky.androidide.build.config.BuildConfig - -plugins { - id("com.android.library") - id("kotlin-android") - id("kotlin-kapt") - id("realm-android") -} - - - -android { - namespace = "${BuildConfig.packageName}.database" -} - -dependencies { - kapt(libs.google.auto.service) - implementation(libs.google.auto.service.annotations) - - implementation(projects.core.common) - implementation(projects.logging.logger) - implementation(projects.utilities.shared) -} \ No newline at end of file diff --git a/core/database/consumer-rules.pro b/core/database/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/core/database/proguard-rules.pro b/core/database/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/core/database/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/core/database/src/main/java/com/itsaky/androidide/db/IRealmProvider.kt b/core/database/src/main/java/com/itsaky/androidide/db/IRealmProvider.kt deleted file mode 100644 index 2bf6ec341..000000000 --- a/core/database/src/main/java/com/itsaky/androidide/db/IRealmProvider.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.db - -import com.itsaky.androidide.utils.ServiceLoader -import io.realm.Realm -import io.realm.RealmConfiguration - -/** - * An [IRealmProvider] provides the instance of [Realm]. - * - * @author Akash Yadav - */ -interface IRealmProvider { - - /** - * Get the [Realm] instance. - * - * @param path The path of the database. - */ - fun get(path: String): Realm { - return get(path, null) - } - - /** - * Get the [Realm] instance. - * - * @param path The path of the database. - * @param config An optional function to configure the [RealmConfiguration] builder. - */ - fun get(path: String, config: (RealmConfiguration.Builder.() -> Unit)?): Realm - - companion object { - - private lateinit var sInstance: IRealmProvider - - /** - * The separator used to separate segments in an index path. - */ - const val PATH_SEPARATOR = '/' - - /** - * Create the path for the given segments. - * - * @param first The first (root) path segment. - * @param rest The rest of the path segments. - * @return The created path string. - */ - @JvmStatic - fun createPath(first: String, vararg rest: String): String { - - val sb = StringBuilder() - sb.append(PATH_SEPARATOR) - sb.append(first) - - for (segment in rest) { - sb.append(PATH_SEPARATOR) - sb.append(segment) - } - - return sb.toString() - } - - /** - * Get the [IRealmProvider] instance, finding the implementation if necessary. - */ - @JvmStatic - fun instance(): IRealmProvider { - if (!Companion::sInstance.isInitialized) { - val clazz = IRealmProvider::class.java - sInstance = ServiceLoader.load(clazz, clazz.classLoader).findFirstOrThrow() - } - return sInstance - } - } -} \ No newline at end of file diff --git a/core/database/src/main/java/com/itsaky/androidide/db/internal/DatabaseEntity.kt b/core/database/src/main/java/com/itsaky/androidide/db/internal/DatabaseEntity.kt deleted file mode 100644 index 0974859f5..000000000 --- a/core/database/src/main/java/com/itsaky/androidide/db/internal/DatabaseEntity.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.db.internal - -import io.realm.RealmObject -import io.realm.annotations.PrimaryKey -import io.realm.annotations.RealmField -import io.realm.annotations.Required - -/** - * An entity to store information about all registered box stores. - * - * @author Akash Yadav - */ -open class DatabaseEntity( - @Required - @PrimaryKey - @RealmField("path") - var path: String = "", - - @Required - @RealmField("name") - var name: String = "", - - @Required - @RealmField("directory") - var directory: String = "", -) : RealmObject() { - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is DatabaseEntity) return false - - if (path != other.path) return false - if (name != other.name) return false - if (directory != other.directory) return false - - return true - } - - override fun hashCode(): Int { - var result = path.hashCode() - result = 31 * result + name.hashCode() - result = 31 * result + directory.hashCode() - return result - } - - override fun toString(): String { - return "DatabaseEntity(path='$path', name='$name', directory='$directory')" - } -} \ No newline at end of file diff --git a/core/database/src/main/java/com/itsaky/androidide/db/internal/InternalDBRealmModule.kt b/core/database/src/main/java/com/itsaky/androidide/db/internal/InternalDBRealmModule.kt deleted file mode 100644 index 4c5a9a7dd..000000000 --- a/core/database/src/main/java/com/itsaky/androidide/db/internal/InternalDBRealmModule.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.db.internal - -import io.realm.annotations.RealmModule - -/** - * [RealmModule] for the internal database entitites. - * - * @author Akash Yadav - */ -@RealmModule(library = true, classes = [DatabaseEntity::class]) -internal class InternalDBRealmModule \ No newline at end of file diff --git a/core/database/src/main/java/com/itsaky/androidide/db/internal/RealmProviderImpl.kt b/core/database/src/main/java/com/itsaky/androidide/db/internal/RealmProviderImpl.kt deleted file mode 100644 index b7bb28974..000000000 --- a/core/database/src/main/java/com/itsaky/androidide/db/internal/RealmProviderImpl.kt +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.db.internal - -import com.google.auto.service.AutoService -import com.itsaky.androidide.db.IRealmProvider -import com.itsaky.androidide.utils.Environment -import io.realm.Realm -import io.realm.RealmConfiguration -import org.slf4j.LoggerFactory - -/** - * Default implementation of [IRealmProvider]. - * - * @author Akash Yadav - */ -@AutoService(IRealmProvider::class) -@Suppress("unused") -internal class RealmProviderImpl : IRealmProvider { - - companion object { - private val log = LoggerFactory.getLogger(RealmProviderImpl::class.java) - - // must be a relative path, with no special characters except '_' '-' and '/' (path sep) - private val dbNameRegex = Regex("^[a-zA-Z0-9_\\-/]+$") - private const val MASTER_DB_NAME = "master" - private const val MASTER_DB_PATH = "/$MASTER_DB_NAME" - } - - private val masterDb: Realm by lazy { - createDb(MASTER_DB_PATH) { - modules(InternalDBRealmModule()) - } - } - - override fun get(path: String, config: (RealmConfiguration.Builder.() -> Unit)?): Realm { - require(path != MASTER_DB_PATH) { - "Master DB is internal to AndroidIDE" - } - - return createDb(path, config) - } - - private fun createDb(path: String, confFunc: (RealmConfiguration.Builder.() -> Unit)?): Realm { - val (parentPath, name) = validateDbPath(path) - - val configBuilder = RealmConfiguration.Builder() - confFunc?.also { configure -> configBuilder.configure() } - - var dbDir = Environment.REALM_DB_DIR - if (parentPath.isNotEmpty()) { - dbDir = dbDir.resolve(parentPath) - } - - val dbName = "${name}.realm" - val config = configBuilder - .name(dbName) - .directory(dbDir) - .allowQueriesOnUiThread(false) - .allowWritesOnUiThread(false) - .compactOnLaunch() - .build() - - log.info("Creating DB at $dbDir/$dbName") - - if (parentPath.isEmpty() && name != MASTER_DB_NAME) { - masterDb.executeTransactionAsync { realm -> - realm.insertOrUpdate(DatabaseEntity(name = name, path = path, directory = dbDir.absolutePath)) - } - } - - return Realm.getInstance(config) - } - - private fun validateDbPath(path: String): Pair { - val idx = path.indexOfLast { it == IRealmProvider.PATH_SEPARATOR } - require( - path.matches(dbNameRegex) - && path[0] == IRealmProvider.PATH_SEPARATOR - && idx >= 0 - && path.indexOf("//") == -1 - ) { - "Invalid DB path: $path" - } - - val parentPath = if (idx > 1) { - path.substring(1, idx) - } else "" - - val name = path.substring(idx + 1) - - if (name == MASTER_DB_NAME) { - require(parentPath.isEmpty()) { - "Master DB must not have any parent path" - } - } - - return parentPath to name - } -} \ No newline at end of file diff --git a/core/database/src/main/java/com/itsaky/androidide/db/utils/realmDictionaryExts.kt b/core/database/src/main/java/com/itsaky/androidide/db/utils/realmDictionaryExts.kt deleted file mode 100644 index 4408fc98d..000000000 --- a/core/database/src/main/java/com/itsaky/androidide/db/utils/realmDictionaryExts.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.db.utils - -import io.realm.RealmDictionary - -/** - * Check if two RealmDictionaries are equal. - */ -fun RealmDictionary?.isEqualTo(other: Any?): Boolean { - // implementation taken from java/util/AbstractMap from JDK 21 - if (other == this) return true - if (other == null || this == null) return false - if (other !is RealmDictionary<*>) return false - if (this.size != other.size) return false - - try { - for (entry in this.entries) { - val key = entry.key - val value = entry.value - if (value == null) { - if (!(other[key] == null && other.containsKey(key))) { - return false - } - } else { - if (value != other[key]) { - return false - } - } - } - } catch (e: ClassCastException) { - return false - } catch (e: NullPointerException) { - return false - } - - return true -} - -/** - * Generate the hash code for a RealmDictionary. - */ -fun RealmDictionary.hash(): Int { - return this.entries.sumOf { it.hashCode() } -} \ No newline at end of file diff --git a/core/indexing-api/build.gradle.kts b/core/indexing-api/build.gradle.kts index c9bad0810..6af9850cf 100644 --- a/core/indexing-api/build.gradle.kts +++ b/core/indexing-api/build.gradle.kts @@ -22,11 +22,8 @@ plugins { id("com.android.library") id("kotlin-android") id("kotlin-kapt") - id("realm-android") } - - android { namespace = "${BuildConfig.packageName}.indexing.api" } @@ -36,7 +33,6 @@ dependencies { implementation(libs.google.auto.service.annotations) api(projects.core.common) - api(projects.core.database) api(projects.core.projects) api(projects.logging.logger) api(projects.utilities.shared) diff --git a/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/AbstractDBIndex.kt b/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/AbstractDBIndex.kt deleted file mode 100644 index cb13321fb..000000000 --- a/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/AbstractDBIndex.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.indexing - -import io.realm.Realm - -/** - * Abstract implementation of [IIndex] for indexing data in the database. - * - * @property params The index parameters. - * @author Akash Yadav - */ -abstract class AbstractDBIndex( - protected val params: IIndexParams? -) : IDatabaseIndex { - - protected abstract val realm: Realm - - override fun index(symbol: T) { - realm.executeTransaction { - it.insertOrUpdate(symbol) - } - } - - override fun indexAsync(symbol: T) { - realm.executeTransactionAsync { - it.insertOrUpdate(symbol) - } - } - - override fun indexAll(symbols: Collection) { - realm.executeTransaction { - it.insertOrUpdate(symbols) - } - } - - override fun indexAllAsync(symbols: Collection) { - realm.executeTransactionAsync { it.insertOrUpdate(symbols) } - } - - override fun delete() { - realm.deleteAll() - } -} \ No newline at end of file diff --git a/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/IDatabaseIndex.kt b/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/IDatabaseIndex.kt deleted file mode 100644 index 76dc71bac..000000000 --- a/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/IDatabaseIndex.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.indexing - -import io.realm.RealmQuery - -/** - * An index which is stored in the database. - * - * @author Akash Yadav - */ -interface IDatabaseIndex : IIndex { - - /** - * Perform a query on the Realm database. - */ - fun query(): RealmQuery -} \ No newline at end of file diff --git a/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/IIndex.kt b/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/IIndex.kt index e8d92968d..7d96be5d4 100644 --- a/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/IIndex.kt +++ b/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/IIndex.kt @@ -17,8 +17,6 @@ package com.itsaky.androidide.indexing -import com.itsaky.androidide.db.IRealmProvider - /** * An index of symbols of type [IndexableT]. * @@ -28,6 +26,8 @@ interface IIndex { companion object { + const val PATH_SEPARATOR = '/' + /** * The default batch size for indexing. */ @@ -44,7 +44,7 @@ interface IIndex { * Create an index path. */ fun createIndexPath(parentPath: String, name: String): String = - "${parentPath}${IRealmProvider.PATH_SEPARATOR}${name}" + "${parentPath}${PATH_SEPARATOR}${name}" } /** diff --git a/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/IIndexable.kt b/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/IIndexable.kt index 667667471..c037b92ea 100644 --- a/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/IIndexable.kt +++ b/core/indexing-api/src/main/java/com/itsaky/androidide/indexing/IIndexable.kt @@ -17,11 +17,9 @@ package com.itsaky.androidide.indexing -import io.realm.RealmModel - /** * An indexable object. * * @author Akash Yadav */ -interface IIndexable : RealmModel \ No newline at end of file +interface IIndexable \ No newline at end of file diff --git a/core/indexing-core/build.gradle.kts b/core/indexing-core/build.gradle.kts index d063b16b5..b29249e8d 100644 --- a/core/indexing-core/build.gradle.kts +++ b/core/indexing-core/build.gradle.kts @@ -22,11 +22,8 @@ plugins { id("com.android.library") id("kotlin-android") id("kotlin-kapt") - id("realm-android") } - - android { namespace = "${BuildConfig.packageName}.indexing.core" } diff --git a/core/indexing-core/src/main/java/com/itsaky/androidide/indexing/core/IndexingCoreRealmModule.kt b/core/indexing-core/src/main/java/com/itsaky/androidide/indexing/core/IndexingCoreRealmModule.kt deleted file mode 100644 index 08f2f1b13..000000000 --- a/core/indexing-core/src/main/java/com/itsaky/androidide/indexing/core/IndexingCoreRealmModule.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.indexing.core - -import io.realm.annotations.RealmModule - -/** - * @author Akash Yadav - */ -@RealmModule(classes = []) -class IndexingCoreRealmModule \ No newline at end of file diff --git a/editor/impl/src/main/java/com/itsaky/androidide/editor/adapters/CompletionListAdapter.kt b/editor/impl/src/main/java/com/itsaky/androidide/editor/adapters/CompletionListAdapter.kt index 282b6940a..f5860688d 100755 --- a/editor/impl/src/main/java/com/itsaky/androidide/editor/adapters/CompletionListAdapter.kt +++ b/editor/impl/src/main/java/com/itsaky/androidide/editor/adapters/CompletionListAdapter.kt @@ -27,7 +27,7 @@ import android.widget.TextView import com.itsaky.androidide.editor.R import com.itsaky.androidide.editor.databinding.LayoutCompletionItemBinding import com.itsaky.androidide.lookup.Lookup -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaType +import com.itsaky.androidide.lsp.java.utils.JavaType import com.itsaky.androidide.lsp.models.ClassCompletionData import com.itsaky.androidide.lsp.models.CompletionItemKind.CLASS import com.itsaky.androidide.lsp.models.CompletionItemKind.CONSTRUCTOR diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e7b3d424a..11a73e790 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -161,8 +161,6 @@ tooling-builderModel = { module = "com.android.tools.build:builder-model", versi tooling-gradleApi = { module = "com.itsaky.androidide.gradle:gradle-tooling-api", version.ref = "gradle-tooling" } tooling-slf4j = { module = "org.slf4j:slf4j-api", version = "2.0.12" } -realm-gradle-plugin = { module = "io.realm:realm-gradle-plugin", version.ref = "realm" } - # Classpaths android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "agp" } kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } diff --git a/java/lsp/build.gradle.kts b/java/lsp/build.gradle.kts index e17747a5b..0a25dc30a 100644 --- a/java/lsp/build.gradle.kts +++ b/java/lsp/build.gradle.kts @@ -22,11 +22,8 @@ plugins { id("com.android.library") id("kotlin-android") id("kotlin-kapt") - id("realm-android") } - - android { namespace = "${BuildConfig.packageName}.lsp.java" diff --git a/java/lsp/src/androidTest/java/com/itsaky/androidide/lsp/java/indexing/JavaClassCRUDTest.kt b/java/lsp/src/androidTest/java/com/itsaky/androidide/lsp/java/indexing/JavaClassCRUDTest.kt index 458ee380b..5760cb225 100644 --- a/java/lsp/src/androidTest/java/com/itsaky/androidide/lsp/java/indexing/JavaClassCRUDTest.kt +++ b/java/lsp/src/androidTest/java/com/itsaky/androidide/lsp/java/indexing/JavaClassCRUDTest.kt @@ -20,7 +20,7 @@ package com.itsaky.androidide.lsp.java.indexing import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat import com.itsaky.androidide.lsp.java.indexing.classfile.JavaClass -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaType +import com.itsaky.androidide.lsp.java.utils.JavaType import com.itsaky.androidide.testing.android.rules.RealmDBTestRule import io.realm.RealmList import io.realm.RealmObject diff --git a/java/lsp/src/androidTest/java/com/itsaky/androidide/lsp/java/indexing/ModelBuilderTestUtil.kt b/java/lsp/src/androidTest/java/com/itsaky/androidide/lsp/java/indexing/ModelBuilderTestUtil.kt index 1493097ba..0977c25ea 100644 --- a/java/lsp/src/androidTest/java/com/itsaky/androidide/lsp/java/indexing/ModelBuilderTestUtil.kt +++ b/java/lsp/src/androidTest/java/com/itsaky/androidide/lsp/java/indexing/ModelBuilderTestUtil.kt @@ -20,7 +20,7 @@ package com.itsaky.androidide.lsp.java.indexing import com.itsaky.androidide.lsp.java.indexing.classfile.JavaClass import com.itsaky.androidide.lsp.java.indexing.classfile.JavaField import com.itsaky.androidide.lsp.java.indexing.classfile.JavaMethod -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaType +import com.itsaky.androidide.lsp.java.utils.JavaType import io.realm.RealmList import openjdk.tools.classfile.AccessFlags diff --git a/java/lsp/src/androidTest/java/com/itsaky/androidide/lsp/java/indexing/SharedModelCRUDTest.kt b/java/lsp/src/androidTest/java/com/itsaky/androidide/lsp/java/indexing/SharedModelCRUDTest.kt index 30d8c59e8..889c4601d 100644 --- a/java/lsp/src/androidTest/java/com/itsaky/androidide/lsp/java/indexing/SharedModelCRUDTest.kt +++ b/java/lsp/src/androidTest/java/com/itsaky/androidide/lsp/java/indexing/SharedModelCRUDTest.kt @@ -25,7 +25,7 @@ import com.itsaky.androidide.lsp.java.indexing.classfile.ClassAnnotationElementV import com.itsaky.androidide.lsp.java.indexing.classfile.EnumAnnotationElementValue import com.itsaky.androidide.lsp.java.indexing.classfile.IAnnotationElementValue import com.itsaky.androidide.lsp.java.indexing.classfile.JavaConstant -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaType +import com.itsaky.androidide.lsp.java.utils.JavaType import com.itsaky.androidide.lsp.java.indexing.classfile.PrimitiveAnnotationElementValue import com.itsaky.androidide.testing.android.rules.RealmDBTestRule import io.realm.RealmAny diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/IJavaIndexable.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/IJavaIndexable.kt deleted file mode 100644 index 30b0dbef5..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/IJavaIndexable.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing - -import com.itsaky.androidide.indexing.IIndexable - -/** - * @author Akash Yadav - */ -interface IJavaIndexable : IIndexable \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/IJavaSymbol.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/IJavaSymbol.kt deleted file mode 100644 index 07ebb9f2e..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/IJavaSymbol.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing - -/** - * A java symbol. - * - * @property accessFlags Access flags of the symbol. - * @property apiInfo Info about the APIs in which this symbol was added, deprecated or removed in. - * @author Akash Yadav - */ -interface IJavaSymbol : IJavaIndexable { - var accessFlags: Int -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/IJavaType.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/IJavaType.kt deleted file mode 100644 index fccc6db64..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/IJavaType.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing - -import io.realm.RealmList -import io.realm.annotations.Required - -/** - * A Java user type. May be a class, interface, enum, or annotation. Qualified name of a type or a - * package name is always represented in the (partially) internal form. For example, the fully qualified - * of `java.lang.Object` is `java/lang/Object` and the package name is `java/lang`. - * - * @property fqn The fully qualified name of the type. - * @property name The simple name of the type. - * @property packageName The package name of the type. - * @property superInterfacesFqn The fully qualified names of the interfaces implemented by the type. - * @property fields The fields of the type. - * @property methods The methods of the type. - * @property isClass Whether the type is a class. - * @property isInterface Whether the type is an interface. - * @property isAnnotation Whether the type is an annotation. - * @property isEnum Whether the type is an enum. - * @author Akash Yadav - */ -interface IJavaType : IJavaSymbol { - var fqn: String? - var name: String? - var packageName: String? - var isInner: Boolean - - /** - * The fully qualified name of the superclass of the type. - * - * Info about fields and methods are availabe in the class file itself. Hhowever, a class may - * extend a class (or implement an interface) which may be defined in other jar files. As a result, - * we only store the fully qualifed names of the classes and interfaces then add an index based on - * these fully qualifed names in the database. - * - * This property is not [Required] because we also index `java/lang/Object`, which does not have - * a superclass. - */ - var superClassFqn: String? - var superInterfacesFqn: RealmList? - var fields: RealmList? - var methods: RealmList? - - val isClass: Boolean - get() = false - - val isInterface: Boolean - get() = false - - val isAnnotation: Boolean - get() = false - - val isEnum: Boolean - get() = false -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/ISharedJavaIndexable.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/ISharedJavaIndexable.kt deleted file mode 100644 index fd89363a5..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/ISharedJavaIndexable.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing - -/** - * An [IJavaIndexable] model which is shared between other models. - * - * @author Akash Yadav - */ -interface ISharedJavaIndexable : IJavaIndexable { - - /** - * A unique ID for the indexable. - */ - var id: Int? - - /** - * Compute and update the ID of this indexable. - */ - fun computeId() -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/JavaIndexingRealmModule.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/JavaIndexingRealmModule.kt deleted file mode 100644 index 14f5b8931..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/JavaIndexingRealmModule.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing - -import com.itsaky.androidide.lsp.java.indexing.classfile.AnnotationAnnotationElementValue -import com.itsaky.androidide.lsp.java.indexing.classfile.AnnotationElement -import com.itsaky.androidide.lsp.java.indexing.classfile.ArrayAnnotationElementValue -import com.itsaky.androidide.lsp.java.indexing.classfile.ClassAnnotationElementValue -import com.itsaky.androidide.lsp.java.indexing.classfile.EnumAnnotationElementValue -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaAnnotation -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaClass -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaConstant -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaEnum -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaField -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaInterface -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaMethod -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaType -import com.itsaky.androidide.lsp.java.indexing.classfile.PrimitiveAnnotationElementValue -import io.realm.annotations.RealmModule - -/** - * [RealmModule] for the indexing databased for Java. - * - * @author Akash Yadav - */ -@RealmModule( - library = true, classes = [ - AnnotationElement::class, - AnnotationAnnotationElementValue::class, - ArrayAnnotationElementValue::class, - ClassAnnotationElementValue::class, - EnumAnnotationElementValue::class, - PrimitiveAnnotationElementValue::class, - JavaAnnotation::class, - JavaClass::class, - JavaConstant::class, - JavaEnum::class, - JavaField::class, - JavaInterface::class, - JavaMethod::class, - JavaType::class, - ] -) -internal class JavaIndexingRealmModule \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/JavaJarModelBuilder.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/JavaJarModelBuilder.kt deleted file mode 100644 index a70038026..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/JavaJarModelBuilder.kt +++ /dev/null @@ -1,424 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing - -import androidx.annotation.VisibleForTesting -import com.itsaky.androidide.lsp.java.indexing.classfile.AnnotationAnnotationElementValue -import com.itsaky.androidide.lsp.java.indexing.classfile.AnnotationElement -import com.itsaky.androidide.lsp.java.indexing.classfile.AnnotationElement.Companion.newAnnotationElement -import com.itsaky.androidide.lsp.java.indexing.classfile.ArrayAnnotationElementValue -import com.itsaky.androidide.lsp.java.indexing.classfile.ClassAnnotationElementValue -import com.itsaky.androidide.lsp.java.indexing.classfile.EnumAnnotationElementValue -import com.itsaky.androidide.lsp.java.indexing.classfile.IAnnotationElementValue -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaAnnotation -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaClass -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaConstant -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaEnum -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaField -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaInterface -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaMethod -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaType -import com.itsaky.androidide.lsp.java.indexing.classfile.PrimitiveAnnotationElementValue -import com.itsaky.androidide.lsp.java.utils.DescriptorUtils -import io.realm.RealmAny -import io.realm.RealmDictionary -import io.realm.RealmList -import openjdk.tools.classfile.AccessFlags -import openjdk.tools.classfile.Annotation.Annotation_element_value -import openjdk.tools.classfile.Annotation.Array_element_value -import openjdk.tools.classfile.Annotation.Class_element_value -import openjdk.tools.classfile.Annotation.Enum_element_value -import openjdk.tools.classfile.Annotation.Primitive_element_value -import openjdk.tools.classfile.Annotation.element_value -import openjdk.tools.classfile.AnnotationDefault_attribute -import openjdk.tools.classfile.Attribute -import openjdk.tools.classfile.ClassFile -import openjdk.tools.classfile.ConstantPool -import openjdk.tools.classfile.ConstantPool.CONSTANT_Double_info -import openjdk.tools.classfile.ConstantPool.CONSTANT_Float_info -import openjdk.tools.classfile.ConstantPool.CONSTANT_Integer_info -import openjdk.tools.classfile.ConstantPool.CONSTANT_Long_info -import openjdk.tools.classfile.ConstantPool.CONSTANT_String_info -import openjdk.tools.classfile.ConstantPool.CONSTANT_Utf8_info -import openjdk.tools.classfile.ConstantPool.CPInfo -import openjdk.tools.classfile.ConstantValue_attribute -import java.io.File -import java.util.zip.ZipFile - -/** - * [JavaJarModelBuilder] builds models for Java classes in a JAR file. - * - * @author Akash Yadav - */ -class JavaJarModelBuilder(private val jar: File) { - - // for testing purposes - // prefer using consumeTypes(Function) - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - fun buildTypes(): List> { - val types = mutableListOf>() - consumeTypes { types.add(it) } - return types - } - - fun consumeTypes(consumer: (IJavaType<*, *>) -> Unit) { - ZipFile(jar).use { jar -> - jar.entries().asSequence().filter { it.name.endsWith(".class") }.forEach { entry -> - jar.getInputStream(entry).buffered().use { inputStream -> - val classFile = ClassFile.read(inputStream)!! - - // build model only if the class is not an anonymous or local class - if (classFile.getAttribute(Attribute.EnclosingMethod) == null) { - val type = buildType(classFile) - consumer(type) - } - } - } - } - } - - private fun buildType(classFile: ClassFile): IJavaType<*, *> { - val classInfo = classFile.constant_pool.getClassInfo(classFile.this_class) - val fqn = classInfo.baseName - val (pck, name, isInner) = splitFqn(fqn) - return buildType(fqn, pck, name, isInner, classFile) - } - - /** - * Split the given fully qualified name of a class and return the package name and the simple name - * of the class, along with whether the class is an inner class. - */ - private fun splitFqn(fqn: String): Triple { - val dolIdx = fqn.lastIndexOf('$') - - // start looking for '/' from the index of the last '$' - // a '/' will always appear before a '$' - val slaIdx = fqn.lastIndexOf('/', startIndex = if (dolIdx == -1) fqn.lastIndex else dolIdx - 1) - - if (slaIdx == -1 && dolIdx != -1) { - // fqn == SomeClass$InnerClass (inner class of a class in the root package) - // pck is empty, but fqn is not the class's simple name - return Triple("", fqn.substring(dolIdx + 1), true) - } - - if (slaIdx == -1) { - // fqn == SomeClass (class in the root package) - // pck is empty and fqn is class's simple name - return Triple("", fqn, false) - } - - if (dolIdx == -1) { - // fqn == com/example/SomeClass - return Triple(fqn.substring(0, slaIdx), fqn.substring(slaIdx + 1), false) - } - - // fqn == com/example/SomeClass$InnerClass - return Triple(fqn.substring(0, slaIdx), fqn.substring(dolIdx + 1), true) - } - - private fun buildType( - fqn: String, - pck: String, - name: String, - isInner: Boolean, - classFile: ClassFile - ): IJavaType<*, *> { - return when { - classFile.access_flags.`is`(AccessFlags.ACC_ENUM) -> buildEnum(fqn, name, pck, classFile) - classFile.access_flags.`is`(AccessFlags.ACC_ANNOTATION) -> buildAnnotation( - fqn, - name, - pck, - classFile - ) - - classFile.access_flags.`is`(AccessFlags.ACC_INTERFACE) -> buildInterface( - fqn, - name, - pck, - classFile - ) - - else -> buildClass(fqn, name, pck, classFile) - }.also { - it.isInner = isInner - } - } - - private fun buildClass(fqn: String, name: String, pck: String, classFile: ClassFile): JavaClass { - return JavaClass.newInstance(fqn, name, pck, classFile.access_flags.flags).apply { - setSuperClass(classFile) - setSuperInterfaces(classFile) - setFields(classFile) - setMethods(classFile) - } - } - - private fun buildInterface( - fqn: String, name: String, pck: String, classFile: ClassFile - ): JavaInterface { - return JavaInterface.newInstance(fqn, name, pck, classFile.access_flags.flags).apply { - setSuperClass(classFile) - setSuperInterfaces(classFile) - setFields(classFile) - setMethods(classFile) - } - } - - private fun buildAnnotation( - fqn: String, name: String, pck: String, classFile: ClassFile - ): JavaAnnotation { - return JavaAnnotation.newInstance(fqn, name, pck, classFile.access_flags.flags).apply { - setSuperClass(classFile) - setSuperInterfaces(classFile) - setFields(classFile) - setAnnotationElements(classFile) - } - } - - private fun buildEnum(fqn: String, name: String, pck: String, classFile: ClassFile): JavaEnum { - return JavaEnum.newInstance(fqn, name, pck, classFile.access_flags.flags).apply { - setSuperClass(classFile) - setSuperInterfaces(classFile) - setFields(classFile) - setMethods(classFile) - } - } - - private fun IJavaType<*, *>.setSuperInterfaces(classFile: ClassFile) { - val interfaces = RealmList() - for (iface in classFile.interfaces) { - val ifaceInfo = classFile.constant_pool.getClassInfo(iface) - interfaces.add(ifaceInfo.baseName!!) - } - - superInterfacesFqn = interfaces - } - - private fun IJavaType<*, *>.setSuperClass(classFile: ClassFile) { - if (classFile.super_class == 0) { - // From https://docs.oracle.com/javase/specs/jvms/se21/html/jvms-4.html#jvms-4.5 - // If the value of the super_class field is 0, then this class represents the java/lang/Object class itself - // and hence, doesn't have a super class. - return - } - - val superclassInfo = classFile.constant_pool.getClassInfo(classFile.super_class) - superClassFqn = superclassInfo.baseName!! - } - - private fun IJavaType<*, JavaMethod>.setMethods(classFile: ClassFile) { - methods = RealmList().apply { - classFile.methods.forEach { method -> - val descriptor = classFile.constant_pool.getUTF8Value(method.descriptor.index) - val methodName = method.getName(classFile.constant_pool) - val methodType = DescriptorUtils.returnType(descriptor) - val paramTypes = RealmList().apply { - addAll(DescriptorUtils.paramTypes(descriptor)) - } - - add(JavaMethod.newInstance(methodName, paramTypes, methodType, method.access_flags.flags)) - } - } - } - - private fun IJavaType.setFields(classFile: ClassFile) { - fields = RealmList().apply { - classFile.fields.forEach { field -> - val descriptor = classFile.constant_pool.getUTF8Value(field.descriptor.index) - val fieldName = field.getName(classFile.constant_pool) - val fieldType = DescriptorUtils.type(descriptor) - - add(JavaField.newField(fieldName, fieldType, field.access_flags.flags).apply { - field.attributes.get(Attribute.ConstantValue)?.also { constAttr -> - val constantValue = constAttr as ConstantValue_attribute - val constant = classFile.constant_pool.get(constantValue.constantvalue_index) - val isStringType = fieldType.isStringType() - val javaConstant = if (fieldType.isPrimitive() || isStringType) { - toJavaConstant(fieldType.kind, constant, if (isStringType) 's' else null) - } else { - throw IllegalArgumentException("Invalid field type for constant value: $fieldType") - } - - this.constantValue = javaConstant - } - }) - } - } - } - - private fun JavaAnnotation.setAnnotationElements(classFile: ClassFile) { - methods = RealmList().apply { - classFile.methods.forEach { method -> - val descriptor = classFile.constant_pool.getUTF8Value(method.descriptor.index) - val methodName = method.getName(classFile.constant_pool) - val methodType = DescriptorUtils.returnType(descriptor) - - add( - newAnnotationElement( - methodName, methodType, method.access_flags.flags - ).apply { - val annotationDefault = - method.attributes.get(Attribute.AnnotationDefault) as? AnnotationDefault_attribute? - if (annotationDefault != null) { - val defaultValue = annotationDefault.default_value - val value = toAnnotationElementValue(defaultValue, classFile) - this.defaultValue = value.let(RealmAny::valueOf) ?: RealmAny.nullValue() - } - }) - } - } - } - - private fun toAnnotationElementValue( - defaultValue: element_value, classFile: ClassFile - ): IAnnotationElementValue { - val char = defaultValue.tag.toChar() - var kind = JavaType.kindForType(char) - if (char == 's') { - kind = JavaType.KIND_REF - } - - var value: IAnnotationElementValue? = when (kind) { - JavaType.KIND_BOOLEAN, - JavaType.KIND_BYTE, - JavaType.KIND_CHAR, - JavaType.KIND_SHORT, - JavaType.KIND_INT, - JavaType.KIND_LONG, - JavaType.KIND_FLOAT, - JavaType.KIND_DOUBLE -> PrimitiveAnnotationElementValue.newInstance( - // annotation value kinds are same as JavaType.KIND_* - kind = kind, - value = toPrimitiveConstant( - classFile.constant_pool, kind, char, defaultValue as Primitive_element_value - ) - ) - - else -> null - } - - if (value == null) { - value = when (char) { - 's' -> PrimitiveAnnotationElementValue.newInstance( - kind = IAnnotationElementValue.KIND_STRING, - value = toPrimitiveConstant( - classFile.constant_pool, - JavaType.KIND_REF, - char, - defaultValue as Primitive_element_value - ) - ) - - 'e' -> { - val enum = defaultValue as Enum_element_value - EnumAnnotationElementValue.newInstance( - name = classFile.constant_pool.getUTF8Value(enum.const_name_index), - type = DescriptorUtils.type(classFile.constant_pool.getUTF8Value(enum.type_name_index)) - ) - } - - 'c' -> { - // even though the name is given as "class_info_index", the constant at that index - // is actually a CONSTANT_Utf8_info representing a return type descriptor (JLS $4.3.3) - // this has been clearly mentioned in the Java Language Specification - ClassAnnotationElementValue.newInstance( - DescriptorUtils.type( - classFile.constant_pool.getUTF8Value( - (defaultValue as Class_element_value).class_info_index - ) - ) - ) - } - - '@' -> { - val annotation = (defaultValue as Annotation_element_value).annotation_value - AnnotationAnnotationElementValue.newInstance(type = DescriptorUtils.type( - classFile.constant_pool.getUTF8Value( - annotation.type_index - ) - ), - values = RealmDictionary().apply { - for (pair in annotation.element_value_pairs) { - this[classFile.constant_pool.getUTF8Value(pair.element_name_index)] = - toAnnotationElementValue(pair.value, classFile).let { elementValue -> - RealmAny.valueOf(elementValue) - } - } - }) - } - - '[' -> { - ArrayAnnotationElementValue.newInstance(values = RealmList().apply { - (defaultValue as Array_element_value).values.forEach { element -> - add(toAnnotationElementValue(element, classFile).let { elementValue -> - RealmAny.valueOf(elementValue) - }) - } - }) - } - - else -> throw IllegalArgumentException("Unknown value tag: ${defaultValue.tag}") - } - } - return value - } - - private fun toPrimitiveConstant( - constantPool: ConstantPool, kind: Int, char: Char, prim: Primitive_element_value - ): JavaConstant { - if (kind == JavaType.KIND_REF && char != 's') { - throw IllegalArgumentException("Unknown value tag: $char") - } - - val constant = constantPool.get(prim.const_value_index) - return toJavaConstant(kind, constant, char) - } - - private fun toJavaConstant( - kind: Int, constant: CPInfo, char: Char? - ): JavaConstant { - val realmAny = when (kind) { - JavaType.KIND_BOOLEAN, - JavaType.KIND_BYTE, - JavaType.KIND_CHAR, - JavaType.KIND_SHORT, - JavaType.KIND_INT -> (constant as CONSTANT_Integer_info).value.let { - RealmAny.valueOf(it) - } - - JavaType.KIND_LONG -> (constant as CONSTANT_Long_info).value.let { RealmAny.valueOf(it) } - JavaType.KIND_FLOAT -> (constant as CONSTANT_Float_info).value.let { RealmAny.valueOf(it) } - JavaType.KIND_DOUBLE -> (constant as CONSTANT_Double_info).value.let { RealmAny.valueOf(it) } - else -> if (char == 's') { - if (constant is CONSTANT_String_info) { - constant.string - } else { - (constant as CONSTANT_Utf8_info).value - }.let { RealmAny.valueOf(it) } - } else { - throw IllegalArgumentException("Unknown value tag: $char") - } - } - - return JavaConstant.newInstance( - kind = kind, - value = realmAny - ) - } -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/AnnotationElement.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/AnnotationElement.kt deleted file mode 100644 index f0fe17bdc..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/AnnotationElement.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing.classfile - -import com.itsaky.androidide.lsp.java.indexing.IJavaSymbol -import io.realm.RealmAny -import io.realm.RealmResults -import io.realm.annotations.Index -import io.realm.annotations.LinkingObjects -import io.realm.annotations.RealmClass -import io.realm.annotations.RealmField -import io.realm.annotations.Required - -/** - * A method defined in an annotation type. - * - * @property defaultValue The default value of the annotation element. - * @author Akash Yadav - */ -@RealmClass(embedded = true) -open class AnnotationElement : IJavaSymbol { - - @Index - @Required - @RealmField("name") - var name: String? = null - - @RealmField("type") - var type: JavaType? = null - - @RealmField("accessFlags") - override var accessFlags: Int = 0 - - @LinkingObjects("methods") - val ofClass: RealmResults? = null - - /** - * The default value of the annotation element. One of the following: - * - [PrimitiveAnnotationElementValue] - * - [EnumAnnotationElementValue] - * - [ArrayAnnotationElementValue] - * - [ClassAnnotationElementValue] - * - [AnnotationAnnotationElementValue] - */ - @RealmField("defaultValue") - var defaultValue: RealmAny? = null - - /** - * Returns the signature of the method. - */ - fun signature(): String { - val sb = StringBuilder() - sb.append(name) - sb.append("(") - sb.append(")") - sb.append(type?.internalForm()) - return sb.toString() - } - - companion object { - @JvmStatic - fun newAnnotationElement( - name: String, - type: JavaType, - accessFlags: Int, - defaultValue: RealmAny? = null - ): AnnotationElement { - return AnnotationElement().apply { - this.name = name - this.type = type - this.accessFlags = accessFlags - this.defaultValue = defaultValue - } - } - } -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaAnnotation.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaAnnotation.kt deleted file mode 100644 index 4a3a7d4a2..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaAnnotation.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing.classfile - -import com.itsaky.androidide.lsp.java.indexing.IJavaType -import io.realm.RealmList -import io.realm.annotations.Index -import io.realm.annotations.PrimaryKey -import io.realm.annotations.RealmClass -import io.realm.annotations.RealmField -import io.realm.annotations.Required - -/** - * A Java annotation type. - * - * Implementation note: - * An annotation type is a Java interface, and hence, it inherits from [JavaInterface] instead of - * [IJavaType]. Also, [IJavaType.isInterface] and [IJavaType.isAnnotation] both - * return `true` for annotation types. - * - * @author Akash Yadav - */ - -@RealmClass -open class JavaAnnotation : IJavaType { - - @Index - @PrimaryKey - @Required - @RealmField("fqn") - override var fqn: String? = null - - @Required - @RealmField("name") - override var name: String? = null - - @Required - @RealmField("pck") - override var packageName: String? = null - - @RealmField("isInner") - override var isInner: Boolean = false - - @RealmField("superClassFqn") - override var superClassFqn: String? = null - - @RealmField("superInterfacesFqn") - override var superInterfacesFqn: RealmList? = null - - @RealmField("accessFlags") - override var accessFlags: Int = 0 - - @RealmField("fields") - override var fields: RealmList? = null - - @RealmField("methods") - override var methods: RealmList? = null - - override val isInterface: Boolean - get() = true - - override val isAnnotation: Boolean - get() = true - - companion object { - @JvmStatic - fun newInstance( - fqn: String, - name: String, - packageName: String, - accessFlags: Int, - isInner: Boolean = false, - superInterfacesFqn: RealmList? = null, - fields: RealmList? = null, - methods: RealmList? = null - ): JavaAnnotation { - return JavaAnnotation().apply { - this.fqn = fqn - this.name = name - this.packageName = packageName - this.isInner = isInner - this.superClassFqn = superClassFqn - this.superInterfacesFqn = superInterfacesFqn - this.accessFlags = accessFlags - this.fields = fields - this.methods = methods - } - } - } -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaClass.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaClass.kt deleted file mode 100644 index 8fcde79eb..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaClass.kt +++ /dev/null @@ -1,98 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing.classfile - -import com.itsaky.androidide.lsp.java.indexing.IJavaType -import io.realm.RealmList -import io.realm.annotations.Index -import io.realm.annotations.PrimaryKey -import io.realm.annotations.RealmClass -import io.realm.annotations.RealmField -import io.realm.annotations.Required - -/** - * A Java class type. - * - * @author Akash Yadav - */ - -@RealmClass -open class JavaClass : IJavaType { - - @Index - @PrimaryKey - @Required - @RealmField("fqn") - override var fqn: String? = null - - @Required - @RealmField("name") - override var name: String? = null - - @Required - @RealmField("pck") - override var packageName: String? = null - - @RealmField("isInner") - override var isInner: Boolean = false - - @RealmField("superClassFqn") - override var superClassFqn: String? = null - - @RealmField("superInterfacesFqn") - override var superInterfacesFqn: RealmList? = null - - @RealmField("accessFlags") - override var accessFlags: Int = 0 - - @RealmField("fields") - override var fields: RealmList? = null - - @RealmField("methods") - override var methods: RealmList? = null - - override val isClass: Boolean - get() = true - - companion object { - @JvmStatic - fun newInstance( - fqn: String, - name: String, - packageName: String, - accessFlags: Int, - isInner: Boolean = false, - superClassFqn: String? = null, - superInterfacesFqn: RealmList? = null, - fields: RealmList? = null, - methods: RealmList? = null - ): JavaClass { - return JavaClass().apply { - this.fqn = fqn - this.name = name - this.packageName = packageName - this.isInner = isInner - this.superClassFqn = superClassFqn - this.superInterfacesFqn = superInterfacesFqn - this.accessFlags = accessFlags - this.fields = fields - this.methods = methods - } - } - } -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaConstant.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaConstant.kt deleted file mode 100644 index 7a042f55a..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaConstant.kt +++ /dev/null @@ -1,152 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing.classfile - -import com.google.common.base.Objects -import com.itsaky.androidide.lsp.java.indexing.ISharedJavaIndexable -import io.realm.RealmAny -import io.realm.annotations.PrimaryKey -import io.realm.annotations.RealmClass -import io.realm.annotations.RealmField - -/** - * A constant value in Java. - * - * A unique ID is used as the primary key in order to ensure that a constant is not stored multiple - * times in the database. Also, a string constant always has type [JavaType.KIND_REF]. A constant - * is never of type [JavaType.KIND_VOID]. - * - * @property id A unique ID which is generated for the constant. - * @property kind The kind of contant. See [JavaType] for a list of kinds. - * @property value The value of the constant. Cast this value based on the value of [kind]. - * @author Akash Yadav - */ -@RealmClass -open class JavaConstant : ISharedJavaIndexable { - - @PrimaryKey - @RealmField("id") - override var id: Int? = null - - @RealmField("kind") - var kind: Int = JavaType.KIND_UNKNOWN - private set - - @RealmField("value") - var value: RealmAny? = null - private set - - companion object { - fun newInstance(kind: Int, value: RealmAny): JavaConstant { - return JavaConstant().apply { - this.kind = kind - this.value = value - this.computeId() - } - } - } - - fun update(kind: Int = this.kind, value: RealmAny? = this.value) { - this.kind = kind - this.value = value - this.computeId() - } - - fun update(src: JavaConstant) { - this.kind = src.kind - this.value = src.value - this.computeId() - } - - - override fun computeId() { - this.id = Objects.hashCode(this.kind, this.kind, this.value) - } - - // boolean, byte, short, int are stored as int in the bytecode - - fun asBoolean(): Boolean? { - return safeCast(JavaType.KIND_BOOLEAN) { asInteger() == 1 } - } - - fun asByte(): Byte? { - return safeCast(JavaType.KIND_BYTE) { asInteger()?.toByte() } - } - - fun asShort(): Short? { - return safeCast(JavaType.KIND_SHORT) { asInteger()?.toShort() } - } - - fun asInt(): Int? { - return safeCast(JavaType.KIND_INT) { asInteger() } - } - - fun asLong(): Long? { - return safeCast(JavaType.KIND_LONG) { asLong() } - } - - fun asFloat(): Float? { - return safeCast(JavaType.KIND_FLOAT) { asFloat() } - } - - fun asDouble(): Double? { - return safeCast(JavaType.KIND_DOUBLE) { asDouble() } - } - - fun asString(): String? { - return safeCast(JavaType.KIND_REF) { asString() } - } - - fun asChar(): Char? { - return safeCast(JavaType.KIND_CHAR) { asInteger()?.toChar() } - } - - private inline fun safeCast(kind: Int, action: RealmAny.() -> R): R? { - return value?.let { - if (this.kind == kind) { - try { - it.action() - } catch (ex: ClassCastException) { - throw IllegalStateException("Kind == $kind but safeCast failed", ex) - } - } else null - } - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is JavaConstant) return false - - if (id != other.id) return false - if (kind != other.kind) return false - if (value != other.value) return false - - return true - } - - override fun hashCode(): Int { - var result = id ?: 0 - result = 31 * result + kind - result = 31 * result + (value?.hashCode() ?: 0) - return result - } - - override fun toString(): String { - return "JavaConstant(id=$id, kind=$kind, value=$value)" - } -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaEnum.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaEnum.kt deleted file mode 100644 index 78d9ca644..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaEnum.kt +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing.classfile - -import com.itsaky.androidide.lsp.java.indexing.IJavaType -import io.realm.RealmList -import io.realm.annotations.Index -import io.realm.annotations.PrimaryKey -import io.realm.annotations.RealmClass -import io.realm.annotations.RealmField -import io.realm.annotations.Required - -/** - * A Java enum type. - * - * @author Akash Yadav - */ -@RealmClass -open class JavaEnum : IJavaType { - - @Index - @PrimaryKey - @Required - @RealmField("fqn") - override var fqn: String? = null - - @Required - @RealmField("name") - override var name: String? = null - - @Required - @RealmField("pck") - override var packageName: String? = null - - @RealmField("isInner") - override var isInner: Boolean = false - - @RealmField("superClassFqn") - override var superClassFqn: String? = null - - @RealmField("superInterfacesFqn") - override var superInterfacesFqn: RealmList? = null - - @RealmField("accessFlags") - override var accessFlags: Int = 0 - - @RealmField("fields") - override var fields: RealmList? = null - - @RealmField("methods") - override var methods: RealmList? = null - - override val isEnum: Boolean - get() = true - - companion object { - @JvmStatic - fun newInstance( - fqn: String, - name: String, - packageName: String, - accessFlags: Int, - isInner: Boolean = false, - superClassFqn: String? = null, - superInterfacesFqn: RealmList? = null, - fields: RealmList? = null, - methods: RealmList? = null - ): JavaEnum { - return JavaEnum().apply { - this.fqn = fqn - this.name = name - this.packageName = packageName - this.isInner = isInner - this.superClassFqn = superClassFqn - this.superInterfacesFqn = superInterfacesFqn - this.accessFlags = accessFlags - this.fields = fields - this.methods = methods - } - } - } -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaField.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaField.kt deleted file mode 100644 index b1b809ffa..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaField.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing.classfile - -import com.itsaky.androidide.lsp.java.indexing.IJavaSymbol -import io.realm.RealmResults -import io.realm.annotations.Index -import io.realm.annotations.LinkingObjects -import io.realm.annotations.RealmClass -import io.realm.annotations.RealmField - -/** - * @author Akash Yadav - */ -@RealmClass(embedded = true) -open class JavaField : IJavaSymbol { - - @Index - @RealmField("name") - var name: String? = null - - @RealmField("type") - var type: JavaType? = null - - @RealmField("accessFlags") - override var accessFlags: Int = 0 - - @RealmField("constantValue") - var constantValue: JavaConstant? = null - - @LinkingObjects("fields") - val ofClass: RealmResults? = null - - companion object { - @JvmStatic - fun newField( - name: String, - type: JavaType, - accessFlags: Int, - constantValue: JavaConstant? = null - ): JavaField { - return JavaField().apply { - this.name = name - this.type = type - this.accessFlags = accessFlags - this.constantValue = constantValue - } - } - } -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaInterface.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaInterface.kt deleted file mode 100644 index 130e055cf..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaInterface.kt +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing.classfile - -import com.itsaky.androidide.lsp.java.indexing.IJavaType -import io.realm.RealmList -import io.realm.annotations.Index -import io.realm.annotations.PrimaryKey -import io.realm.annotations.RealmClass -import io.realm.annotations.RealmField -import io.realm.annotations.Required - -/** - * A Java interface type. - * - * @author Akash Yadav - */ - -@RealmClass -open class JavaInterface : IJavaType { - - @Index - @PrimaryKey - @Required - @RealmField("fqn") - override var fqn: String? = null - - @Required - @RealmField("name") - override var name: String? = null - - @Required - @RealmField("pck") - override var packageName: String? = null - - @RealmField("isInner") - override var isInner: Boolean = false - - @RealmField("superClassFqn") - override var superClassFqn: String? = null - - @RealmField("superInterfacesFqn") - override var superInterfacesFqn: RealmList? = null - - @RealmField("accessFlags") - override var accessFlags: Int = 0 - - @RealmField("fields") - override var fields: RealmList? = null - - @RealmField("methods") - override var methods: RealmList? = null - - override val isInterface: Boolean - get() = true - - companion object { - @JvmStatic - fun newInstance( - fqn: String, - name: String, - packageName: String, - accessFlags: Int, - isInner: Boolean = false, - superInterfacesFqn: RealmList? = null, - fields: RealmList? = null, - methods: RealmList? = null - ): JavaInterface { - return JavaInterface().apply { - this.fqn = fqn - this.name = name - this.packageName = packageName - this.isInner = isInner - this.superInterfacesFqn = superInterfacesFqn - this.accessFlags = accessFlags - this.fields = fields - this.methods = methods - } - } - } -} diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaMethod.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaMethod.kt deleted file mode 100644 index 69635b067..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaMethod.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing.classfile - -import com.itsaky.androidide.lsp.java.indexing.IJavaSymbol -import io.realm.RealmList -import io.realm.RealmResults -import io.realm.annotations.Index -import io.realm.annotations.LinkingObjects -import io.realm.annotations.RealmClass -import io.realm.annotations.RealmField -import io.realm.annotations.Required - -/** - * @author Akash Yadav - */ - -@RealmClass(embedded = true) -open class JavaMethod : IJavaSymbol { - @Index - @Required - @RealmField("name") - var name: String? = null - - @RealmField("paramTypes") - var paramsTypes: RealmList? = null - - @RealmField("returnType") - var returnType: JavaType? = null - - @RealmField("accessFlags") - override var accessFlags: Int = 0 - - @LinkingObjects("methods") - val ofClass: RealmResults? = null - - /** - * Returns the signature of the method. - */ - fun signature(): String { - val sb = StringBuilder() - sb.append(name) - sb.append("(") - paramsTypes?.forEach { - sb.append(it.internalForm()) - } - sb.append(")") - sb.append(returnType?.internalForm()) - return sb.toString() - } - - companion object { - @JvmStatic - fun newInstance( - name: String, - paramsTypes: RealmList, - returnType: JavaType, - accessFlags: Int, - ): JavaMethod { - return JavaMethod().apply { - this.name = name - this.paramsTypes = paramsTypes - this.returnType = returnType - this.accessFlags = accessFlags - } - } - } -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/annotationElementValues.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/annotationElementValues.kt deleted file mode 100644 index 743352a7a..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/annotationElementValues.kt +++ /dev/null @@ -1,340 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing.classfile - -import com.google.common.base.Objects -import com.itsaky.androidide.db.utils.hash -import com.itsaky.androidide.db.utils.isEqualTo -import com.itsaky.androidide.lsp.java.indexing.ISharedJavaIndexable -import io.realm.RealmAny -import io.realm.RealmDictionary -import io.realm.RealmList -import io.realm.annotations.PrimaryKey -import io.realm.annotations.RealmClass -import io.realm.annotations.RealmField -import io.realm.annotations.Required - -sealed interface IAnnotationElementValue : ISharedJavaIndexable { - var kind: Int - - companion object { - const val KIND_UNKNOWN = JavaType.KIND_UNKNOWN - const val KIND_BOOLEAN = JavaType.KIND_BOOLEAN - const val KIND_BYTE = JavaType.KIND_BYTE - const val KIND_CHAR = JavaType.KIND_CHAR - const val KIND_DOUBLE = JavaType.KIND_DOUBLE - const val KIND_FLOAT = JavaType.KIND_FLOAT - const val KIND_INT = JavaType.KIND_INT - const val KIND_LONG = JavaType.KIND_LONG - const val KIND_SHORT = JavaType.KIND_SHORT - - const val KIND_STRING = JavaType.__KIND_STRING - const val KIND_CLASS = JavaType.__KIND_CLASS - const val KIND_ENUM = JavaType.__KIND_ENUM - const val KIND_ANNOTATION = JavaType.__KIND_ANNOTATION - const val KIND_ARRAY = JavaType.__KIND_ARRAY - } -} - - -@RealmClass -open class PrimitiveAnnotationElementValue : IAnnotationElementValue { - - @PrimaryKey - @Required - @RealmField("id") - override var id: Int? = null - - @RealmField("kind") - override var kind: Int = 0 - - @RealmField("value") - var value: JavaConstant? = null - - override fun computeId() { - this.id = Objects.hashCode(this.kind, this.value) - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is PrimitiveAnnotationElementValue) return false - - if (id != other.id) return false - if (kind != other.kind) return false - if (value != other.value) return false - - return true - } - - override fun hashCode(): Int { - var result = id ?: 0 - result = 31 * result + kind - result = 31 * result + (value?.hashCode() ?: 0) - return result - } - - override fun toString(): String { - return "PrimitiveAnnotationElementValue(id=$id, kind=$kind, value=$value)" - } - - companion object { - @JvmStatic - fun newInstance(kind: Int, value: JavaConstant): PrimitiveAnnotationElementValue { - return PrimitiveAnnotationElementValue().apply { - this.kind = kind - this.value = value - this.computeId() - } - } - } -} - - -@RealmClass -open class EnumAnnotationElementValue : IAnnotationElementValue { - @PrimaryKey - @Required - @RealmField("id") - override var id: Int? = null - - @RealmField("kind") - override var kind: Int = IAnnotationElementValue.KIND_ENUM - - @RealmField("name") - var name: String? = null - - @RealmField("type") - var type: JavaType? = null - - override fun computeId() { - this.id = Objects.hashCode(this.kind, this.name, this.type) - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is EnumAnnotationElementValue) return false - - if (id != other.id) return false - if (kind != other.kind) return false - if (name != other.name) return false - if (type != other.type) return false - - return true - } - - override fun hashCode(): Int { - var result = id ?: 0 - result = 31 * result + kind - result = 31 * result + (name?.hashCode() ?: 0) - result = 31 * result + (type?.hashCode() ?: 0) - return result - } - - override fun toString(): String { - return "EnumAnnotationElementValue(id=$id, kind=$kind, name=$name, type=$type)" - } - - companion object { - @JvmStatic - fun newInstance(name: String, type: JavaType): EnumAnnotationElementValue { - return EnumAnnotationElementValue().apply { - this.name = name - this.type = type - this.computeId() - } - } - } -} - - -@RealmClass -open class ArrayAnnotationElementValue : IAnnotationElementValue { - - @PrimaryKey - @Required - @RealmField("id") - override var id: Int? = null - - @RealmField("kind") - override var kind: Int = IAnnotationElementValue.KIND_ARRAY - - @RealmField("numValues") - var numValues: Int = 0 - - /** - * The elements of the array element value. Always of type [IAnnotationElementValue]. - */ - @RealmField("values") - var values: RealmList? = null - - override fun computeId() { - this.id = Objects.hashCode(this.kind, this.numValues, this.values) - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is ArrayAnnotationElementValue) return false - - if (id != other.id) return false - if (kind != other.kind) return false - if (numValues != other.numValues) return false - if (values != other.values) return false - - return true - } - - override fun hashCode(): Int { - var result = id ?: 0 - result = 31 * result + kind - result = 31 * result + numValues - result = 31 * result + (values?.hashCode() ?: 0) - return result - } - - override fun toString(): String { - return "ArrayAnnotationElementValue(id=$id, kind=$kind, numValues=$numValues, values=$values)" - } - - companion object { - @JvmStatic - fun newInstance(values: RealmList): ArrayAnnotationElementValue { - return ArrayAnnotationElementValue().apply { - this.numValues = values.size - this.values = values - this.computeId() - } - } - } -} - - -@RealmClass -open class ClassAnnotationElementValue : IAnnotationElementValue { - - @PrimaryKey - @Required - @RealmField("id") - override var id: Int? = null - - @RealmField("kind") - override var kind: Int = IAnnotationElementValue.KIND_CLASS - - @RealmField("type") - var type: JavaType? = null - - override fun computeId() { - this.id = Objects.hashCode(this.kind, this.type) - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is ClassAnnotationElementValue) return false - - if (id != other.id) return false - if (kind != other.kind) return false - if (type != other.type) return false - - return true - } - - override fun hashCode(): Int { - var result = id ?: 0 - result = 31 * result + kind - result = 31 * result + (type?.hashCode() ?: 0) - return result - } - - override fun toString(): String { - return "ClassAnnotationElementValue(id=$id, kind=$kind, type=$type)" - } - - companion object { - @JvmStatic - fun newInstance(type: JavaType): ClassAnnotationElementValue { - return ClassAnnotationElementValue().apply { - this.type = type - this.computeId() - } - } - } -} - - -@RealmClass -open class AnnotationAnnotationElementValue : IAnnotationElementValue { - - @PrimaryKey - @Required - @RealmField("id") - override var id: Int? = null - - @RealmField("kind") - override var kind: Int = IAnnotationElementValue.KIND_ANNOTATION - - @RealmField("type") - var type: JavaType? = null - - /** - * The named elements of the annotation element value. Always of type [IAnnotationElementValue]. - */ - @RealmField("values") - var values: RealmDictionary? = null - - override fun computeId() { - // RealmDictionary seems to not override hashCode() - this.id = Objects.hashCode(this.kind, this.type, this.values?.hash()) - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is AnnotationAnnotationElementValue) return false - - if (id != other.id) return false - if (kind != other.kind) return false - if (type != other.type) return false - if (!values.isEqualTo(other)) return false - - return true - } - - override fun hashCode(): Int { - var result = id ?: 0 - result = 31 * result + kind - result = 31 * result + (type?.hashCode() ?: 0) - result = 31 * result + (values?.hashCode() ?: 0) - return result - } - - override fun toString(): String { - return "AnnotationAnnotationElementValue(id=$id, kind=$kind, type=$type, values=$values)" - } - - companion object { - @JvmStatic - fun newInstance( - type: JavaType, - values: RealmDictionary - ): AnnotationAnnotationElementValue { - return AnnotationAnnotationElementValue().apply { - this.type = type - this.values = values - this.computeId() - } - } - } -} diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/internal/JavaIndexServiceImpl.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/internal/JavaIndexServiceImpl.kt deleted file mode 100644 index 34b69d377..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/internal/JavaIndexServiceImpl.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing.internal - -import com.google.auto.service.AutoService -import com.itsaky.androidide.indexing.IIndexService -import com.itsaky.androidide.projects.IWorkspace -import java.io.File - -/** - * @author Akash Yadav - */ -@AutoService(IIndexService::class) -internal class JavaIndexServiceImpl : IIndexService { - - override val displayName: String - get() = "Java LSP Indexing Service" - - override fun scanFiles(workspace: IWorkspace): Collection { - return emptySet() - } - - override suspend fun indexFiles( - workspace: IWorkspace, - files: Collection - ) { - } -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/utils/DescriptorUtils.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/utils/DescriptorUtils.kt deleted file mode 100644 index f6f2e8781..000000000 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/utils/DescriptorUtils.kt +++ /dev/null @@ -1,232 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.utils - -import com.itsaky.androidide.lsp.java.indexing.IJavaType -import com.itsaky.androidide.lsp.java.indexing.classfile.AnnotationElement -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaField -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaMethod -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaType -import java.util.Objects - -/** - * @author Akash Yadav - */ -object DescriptorUtils { - - /** - * Create a method ID for the given method. - */ - fun createMethodId( - klass: IJavaType<*, *>, - method: JavaMethod - ): Int { - return Objects.hash(klass.fqn, method.name, method.paramsTypes, method.returnType) - } - - /** - * Create a method ID for the given method. - */ - fun createMethodId( - klass: IJavaType<*, *>, - element: AnnotationElement - ): Int { - return Objects.hash(klass.fqn, element.name, element.type) - } - - /** - * Create a field ID for the given field. The string representation is similar to how fields - * are represented in Smali. - * - * ``` - * Lcom/example/Foo;->bar:I - * ``` - */ - fun createFieldId( - klass: IJavaType<*, *>, - field: JavaField - ): Int { - return Objects.hash(klass.fqn, field.name, field.type) - } - - /** - * Parse the return type of a method descriptor. - * - * @param descriptor The method descriptor. - */ - fun returnType(descriptor: String): JavaType { - val idx = descriptor.indexOfLast { it == ')' } - if (descriptor[0] != '(' || idx == -1) { - throw IllegalArgumentException("Invalid method descriptor: $descriptor") - } - - return type(descriptor.substring(idx + 1)) - } - - /** - * Parse the parameter types of a method descriptor. - * - * @param descriptor The method descriptor. - */ - fun paramTypes(descriptor: String): List { - val idx = descriptor.indexOfLast { it == ')' } - if (descriptor[0] != '(' || idx == -1) { - throw IllegalArgumentException("Invalid method descriptor: $descriptor") - } - - val types = mutableListOf() - val params = descriptor.substring(1, idx) - var i = 0 - while (i < params.length) { - types.add( - when (params[i]) { - 'L' -> { - val end = params.indexOf(';', startIndex = i + 1) - referenceType(params, fromIndex = i, toIndex = end).also { - i = end + 1 - } - } - - '[' -> arrayType(params, fromIndex = i).also { - // number of '[' - // + length of type (I or java/lang/String) - // + 2 if kind is ref (because refs have 'L' and ';') - i += it.arrayDims + it.name!!.length + (if (it.kind == JavaType.KIND_REF) 2 else 0) - } - - else -> primitive(params[i].toString()).also { - ++i - } - } - ) - } - - return types - } - - /** - * Parse a type descriptor. A type descriptor can be any of : - * - a primitive type descriptor - * - a reference type descriptor - * - an array type descriptor - * - * @param descriptor The type descriptor. - */ - fun type(descriptor: String): JavaType { - if (descriptor.startsWith("L")) { - return referenceType(descriptor) - } - - if (descriptor.startsWith("[")) { - return arrayType(descriptor) - } - - if (descriptor.length != 1) { - throw IllegalArgumentException("Invalid type descriptor: $descriptor") - } - - return primitive(descriptor) - } - - /** - * Parse a primitive type descriptor. - * - * @param descriptor The primitive type descriptor. - */ - fun primitive(descriptor: String): JavaType = primitive(descriptor[0]) - - /** - * Parse a primitive type descriptor. - * - * @param char The primitive type. - */ - fun primitive(char: Char): JavaType { - val primitive = JavaType.primitiveFor(char) - return requireNotNull(primitive) { - "Invalid type descriptor: $char" - } - } - - /** - * Parse a reference type descriptor. - * - * Format: - * ``` - * Lcom/example/Foo; - * ``` - * - * @param descriptor The descriptor of a reference type - * @param fromIndex The index of the first character of the reference type name. - * @param toIndex The index of the last character of the reference type name (inclusive). - */ - fun referenceType( - descriptor: String, fromIndex: Int = 0, toIndex: Int = descriptor.length - 1 - ): JavaType { - if (descriptor[fromIndex] != 'L' || descriptor[toIndex] != ';') { - throw IllegalArgumentException("Invalid reference type descriptor: $descriptor, fromIndex: $fromIndex, toIndex: $toIndex") - } - - return when (descriptor) { - "Ljava/lang/String;" -> JavaType.STRING - "Ljava/lang/Object;" -> JavaType.OBJECT - "Ljava/lang/Class;" -> JavaType.CLASS - else -> { - // remove leading 'L' and trailing ';' - val name = descriptor.substring(fromIndex + 1, toIndex) - JavaType.newInstance(name = name, kind = JavaType.KIND_REF) - } - } - } - - - /** - * Parse an array type descriptor. - * - * Format: - * ``` - * [I - * [[I - * [[Lcom/example/Foo; - * ``` - * - * @param descriptor The array type descriptor. - * @param fromIndex The index of the first character of the array type descriptor. - */ - fun arrayType(descriptor: String, fromIndex: Int = 0): JavaType { - if (descriptor[fromIndex] != '[') { - throw IllegalArgumentException("Invalid array type descriptor: $descriptor, fromIndex: $fromIndex") - } - - var idx = fromIndex + 1 - var dims = 1 - while (descriptor[idx] == '[') { - idx++ - dims++ - } - - val type = if (descriptor[idx] == 'L') { - referenceType( - descriptor, fromIndex = idx, toIndex = descriptor.indexOf(';', startIndex = idx + 1) - ) - } else { - primitive(descriptor[idx]) - } - - return JavaType.newInstance(name = type.name, kind = type.kind, arrayDims = dims) - } -} \ No newline at end of file diff --git a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaType.kt b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/utils/JavaType.kt similarity index 79% rename from java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaType.kt rename to java/lsp/src/main/java/com/itsaky/androidide/lsp/java/utils/JavaType.kt index 206529d25..e812d76ea 100644 --- a/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/indexing/classfile/JavaType.kt +++ b/java/lsp/src/main/java/com/itsaky/androidide/lsp/java/utils/JavaType.kt @@ -15,38 +15,17 @@ * along with AndroidIDE. If not, see . */ -package com.itsaky.androidide.lsp.java.indexing.classfile - -import com.google.common.base.Objects -import com.itsaky.androidide.lsp.java.indexing.ISharedJavaIndexable -import com.itsaky.androidide.models.ICloneable -import io.realm.annotations.Index -import io.realm.annotations.PrimaryKey -import io.realm.annotations.RealmClass -import io.realm.annotations.RealmField -import io.realm.annotations.Required +package com.itsaky.androidide.lsp.java.utils /** * @author Akash Yadav */ +open class JavaType { -@RealmClass -open class JavaType : ISharedJavaIndexable, ICloneable { - - @Required - @PrimaryKey - @RealmField("id") - override var id: Int? = null - - @Index - @Required - @RealmField("name") var name: String? = null - @RealmField("kind") var kind: Int = KIND_UNKNOWN - @RealmField("arrayDims") var arrayDims: Int = 0 /** @@ -76,14 +55,7 @@ open class JavaType : ISharedJavaIndexable, ICloneable { */ fun isPrimitive(): Boolean { return when (kind) { - KIND_BOOLEAN, - KIND_BYTE, - KIND_CHAR, - KIND_DOUBLE, - KIND_FLOAT, - KIND_INT, - KIND_LONG, - KIND_SHORT -> true + KIND_BOOLEAN, KIND_BYTE, KIND_CHAR, KIND_DOUBLE, KIND_FLOAT, KIND_INT, KIND_LONG, KIND_SHORT -> true else -> false } @@ -117,14 +89,6 @@ open class JavaType : ISharedJavaIndexable, ICloneable { return name == CLASS.name } - override fun clone(): JavaType { - return newInstance(name = name, kind = kind, arrayDims = arrayDims) - } - - override fun computeId() { - this.id = Objects.hashCode(this.kind, this.name, this.arrayDims) - } - override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is JavaType) return false @@ -144,7 +108,7 @@ open class JavaType : ISharedJavaIndexable, ICloneable { } override fun toString(): String { - return "JavaType(id=$id, name=$name, kind=$kind, arrayDims=$arrayDims)" + return "JavaType(name=$name, kind=$kind, arrayDims=$arrayDims)" } companion object { @@ -160,14 +124,6 @@ open class JavaType : ISharedJavaIndexable, ICloneable { const val KIND_VOID = 8 const val KIND_REF = 9 - // kind values used in IAnnotationElementValue - // defined here for convenience - internal const val __KIND_STRING = 10 - internal const val __KIND_CLASS = 11 - internal const val __KIND_ENUM = 12 - internal const val __KIND_ANNOTATION = 13 - internal const val __KIND_ARRAY = 14 - const val TYPE_BOOLEAN = 'Z' const val TYPE_BYTE = 'B' const val TYPE_CHAR = 'C' @@ -264,7 +220,6 @@ open class JavaType : ISharedJavaIndexable, ICloneable { this.name = name this.kind = kind this.arrayDims = arrayDims - this.computeId() } } diff --git a/java/lsp/src/test/java/com/itsaky/androidide/lsp/java/indexing/AndroidJarModelingRule.kt b/java/lsp/src/test/java/com/itsaky/androidide/lsp/java/indexing/AndroidJarModelingRule.kt deleted file mode 100644 index 3d4ae0dd2..000000000 --- a/java/lsp/src/test/java/com/itsaky/androidide/lsp/java/indexing/AndroidJarModelingRule.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing - -import com.google.common.truth.Truth.assertThat -import com.itsaky.androidide.utils.FileProvider -import org.junit.rules.TestRule -import org.junit.runner.Description -import org.junit.runners.model.Statement -import java.io.File - -/** - * @author Akash Yadav - */ -class AndroidJarModelingRule : TestRule { - - private val androidJar: File by lazy { - FileProvider.projectRoot() - .resolve("utilities") - .resolve("framework-stubs") - .resolve("libs") - .resolve("android.jar") - .toFile().also { - check(it.exists()) { - "android.jar file could not be found" - } - } - } - - private val androidJarIndexer: JavaJarModelBuilder by lazy { - assertThat(androidJar.exists()).isTrue() - JavaJarModelBuilder(androidJar) - } - - val types: List> by lazy { - androidJarIndexer.buildTypes() - } - - override fun apply(base: Statement?, description: Description?): Statement { - - // call 'types' to build the type models - types - - base?.evaluate() - - return object : Statement() { - override fun evaluate() {} - } - } -} \ No newline at end of file diff --git a/java/lsp/src/test/java/com/itsaky/androidide/lsp/java/indexing/DescriptorUtilsTest.kt b/java/lsp/src/test/java/com/itsaky/androidide/lsp/java/indexing/DescriptorUtilsTest.kt deleted file mode 100644 index 55de3e392..000000000 --- a/java/lsp/src/test/java/com/itsaky/androidide/lsp/java/indexing/DescriptorUtilsTest.kt +++ /dev/null @@ -1,121 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing - -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaType -import com.itsaky.androidide.lsp.java.utils.DescriptorUtils -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner - -/** - * @author Akash Yadav - */ -@RunWith(RobolectricTestRunner::class) -class DescriptorUtilsTest { - - @Test - fun testReturnType() { - val descriptor1 = "(I)V" - val expected1 = JavaType.newInstance(name = "V", kind = JavaType.KIND_VOID) - assertEquals(expected1, DescriptorUtils.returnType(descriptor1)) - - val descriptor2 = "(Ljava/lang/String;)I" - val expected2 = JavaType.newInstance(name = "I", kind = JavaType.KIND_INT) - assertEquals(expected2, DescriptorUtils.returnType(descriptor2)) - - val descriptor3 = "(I[Ljava/lang/String;)V" - val expected3 = JavaType.newInstance(name = "V", kind = JavaType.KIND_VOID) - assertEquals(expected3, DescriptorUtils.returnType(descriptor3)) - } - - @Test(expected = IllegalArgumentException::class) - fun testReturnTypeInvalidDescriptor() { - DescriptorUtils.returnType("Ljava/lang/String;I") - } - - @Test - fun testParamTypes() { - val descriptor1 = "(I)V" - val expected1 = listOf(JavaType.newInstance(name = "I", kind = JavaType.KIND_INT)) - assertEquals(expected1, DescriptorUtils.paramTypes(descriptor1)) - - val descriptor2 = "(Ljava/lang/String;I)V" - val expected2 = listOf( - JavaType.newInstance(name = "java/lang/String", kind = JavaType.KIND_REF), - JavaType.newInstance(name = "I", kind = JavaType.KIND_INT) - ) - assertEquals(expected2, DescriptorUtils.paramTypes(descriptor2)) - - val descriptor3 = "([I[Ljava/lang/String;)V" - val expected3 = listOf( - JavaType.newInstance(name = "I", kind = JavaType.KIND_INT, arrayDims = 1), - JavaType.newInstance(name = "java/lang/String", kind = JavaType.KIND_REF, arrayDims = 1) - ) - assertEquals(expected3, DescriptorUtils.paramTypes(descriptor3)) - } - - @Test(expected = IllegalArgumentException::class) - fun testParamTypesInvalidDescriptor() { - DescriptorUtils.paramTypes("Ljava/lang/String;I") - } - - @Test - fun testPrimitive() { - val booleanType = JavaType.newInstance(name = "Z", kind = JavaType.KIND_BOOLEAN) - assertEquals(booleanType, DescriptorUtils.primitive('Z')) - - val intType = JavaType.newInstance(name = "I", kind = JavaType.KIND_INT) - assertEquals(intType, DescriptorUtils.primitive('I')) - } - - @Test(expected = IllegalArgumentException::class) - fun testPrimitiveInvalidType() { - DescriptorUtils.primitive('X') - } - - @Test - fun testReferenceType() { - val descriptor = "Ljava/lang/String;" - val expected = JavaType.newInstance(name = "java/lang/String", kind = JavaType.KIND_REF) - assertEquals(expected, DescriptorUtils.referenceType(descriptor)) - } - - @Test(expected = IllegalArgumentException::class) - fun testReferenceTypeInvalidDescriptor() { - DescriptorUtils.referenceType("Ljava/lang/String") - } - - @Test - fun testArrayType() { - val descriptor1 = "[I" - val expected1 = JavaType.newInstance(name = "I", kind = JavaType.KIND_INT, arrayDims = 1) - assertEquals(expected1, DescriptorUtils.arrayType(descriptor1)) - - val descriptor2 = "[[Ljava/lang/String;" - val expected2 = - JavaType.newInstance(name = "java/lang/String", kind = JavaType.KIND_REF, arrayDims = 2) - assertEquals(expected2, DescriptorUtils.arrayType(descriptor2)) - } - - @Test(expected = IllegalArgumentException::class) - fun testArrayTypeInvalidDescriptor() { - DescriptorUtils.arrayType("Ljava/lang/String;") - } -} \ No newline at end of file diff --git a/java/lsp/src/test/java/com/itsaky/androidide/lsp/java/indexing/JavaIndexWorkerTest.kt b/java/lsp/src/test/java/com/itsaky/androidide/lsp/java/indexing/JavaIndexWorkerTest.kt deleted file mode 100644 index 8b770846a..000000000 --- a/java/lsp/src/test/java/com/itsaky/androidide/lsp/java/indexing/JavaIndexWorkerTest.kt +++ /dev/null @@ -1,524 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -package com.itsaky.androidide.lsp.java.indexing - -import android.view.View -import com.google.common.truth.Truth.assertThat -import com.itsaky.androidide.lsp.java.indexing.classfile.AnnotationElement -import com.itsaky.androidide.lsp.java.indexing.classfile.IAnnotationElementValue -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaAnnotation -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaClass -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaEnum -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaField -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaInterface -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaMethod -import com.itsaky.androidide.lsp.java.indexing.classfile.JavaType -import com.itsaky.androidide.lsp.java.indexing.classfile.PrimitiveAnnotationElementValue -import io.realm.RealmAny -import openjdk.tools.classfile.AccessFlags -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import java.lang.reflect.Modifier - -/** - * @author Akash Yadav - */ -@RunWith(RobolectricTestRunner::class) -class JavaJarModelBuilderTest { - - @Rule - @JvmField - val indexRule = AndroidJarModelingRule() - - private val types: List> - get() = indexRule.types - - @Test - fun `test JavaClass properties`() { - val sampleClass = types.firstOrNull { it.fqn == "java/lang/String" } - - assertThat(sampleClass).isNotNull() - sampleClass?.let { - assertThat(it.fqn).isEqualTo("java/lang/String") - assertThat(it.name).isEqualTo("String") - assertThat(it.packageName).isEqualTo("java/lang") - assertThat(it.superClassFqn).isEqualTo("java/lang/Object") - assertThat(it.superInterfacesFqn).containsAtLeast( - "java/io/Serializable", - "java/lang/Comparable", - "java/lang/CharSequence" - ) - } - } - - @Test - fun `test JavaField properties`() { - val sampleClass = types.firstOrNull { it.fqn == "java/lang/String" } - val fields = sampleClass?.fields - - assertThat(fields).isNotEmpty() - fields?.forEach { f -> - val field = f as JavaField - assertThat(field.name).isNotEmpty() - assertThat(field.accessFlags).isGreaterThan(0) - assertThat(field.type).isNotNull() - } - - // java.lang.String in Android only has a single public field - assertThat(fields?.size).isEqualTo(1) - - val field = fields?.firstOrNull() as JavaField? - assertThat(field).isNotNull() - assertThat(field?.name).isEqualTo("CASE_INSENSITIVE_ORDER") - assertThat(field?.type?.name).isEqualTo("java/util/Comparator") - assertThat(field?.type?.internalForm()).isEqualTo("Ljava/util/Comparator;") - assertThat(field?.type?.kind).isEqualTo(JavaType.KIND_REF) - assertThat(Modifier.isPublic(field?.accessFlags ?: 0)).isTrue() - assertThat(Modifier.isStatic(field?.accessFlags ?: 0)).isTrue() - assertThat(Modifier.isFinal(field?.accessFlags ?: 0)).isTrue() - } - - @Test - fun `test JavaMethod properties`() { - val sampleClass = types.firstOrNull { it.fqn == "java/lang/String" } - val methods = sampleClass?.methods - - assertThat(methods).isNotEmpty() - methods?.forEach { mth -> - val method = mth as JavaMethod - assertThat(method.name).isNotEmpty() - assertThat(method.accessFlags).isGreaterThan(0) - assertThat(method.paramsTypes).isNotNull() - assertThat(method.returnType).isNotNull() - } - - assertThat(methods?.size).isAtLeast(1) - - val method = (methods as List?)?.firstOrNull { it.name == "compareTo" } - assertThat(method).isNotNull() - assertThat(method?.name).isEqualTo("compareTo") - assertThat(method?.paramsTypes?.size).isEqualTo(1) - assertThat(method?.returnType?.name).isEqualTo("I") - assertThat(Modifier.isPublic(method?.accessFlags ?: 0)).isTrue() - assertThat(Modifier.isStatic(method?.accessFlags ?: 0)).isFalse() - assertThat(Modifier.isFinal(method?.accessFlags ?: 0)).isFalse() - - val param = method?.paramsTypes?.firstOrNull() - assertThat(param).isNotNull() - assertThat(param?.name).isEqualTo("java/lang/String") - assertThat(param?.internalForm()).isEqualTo("Ljava/lang/String;") - assertThat(param?.kind).isEqualTo(JavaType.KIND_REF) - assertThat(param?.arrayDims).isEqualTo(0) - } - - @Test - fun `test JavaType properties`() { - val sampleClass = types.firstOrNull { it.fqn == "java/lang/String" } - val fields = sampleClass?.fields - val methods = sampleClass?.methods - - fields?.forEach { f -> - val field = f as JavaField - assertThat(field.type?.name).isNotEmpty() - assertThat(field.type?.kind).isNotEqualTo(JavaType.KIND_UNKNOWN) - } - - methods?.forEach { mth -> - val method = mth as JavaMethod - method.paramsTypes?.forEach { paramType -> - assertThat(paramType.name).isNotEmpty() - assertThat(paramType.kind).isNotEqualTo(JavaType.KIND_UNKNOWN) - } - assertThat(method.returnType?.name).isNotEmpty() - assertThat(method.returnType?.kind).isNotEqualTo(JavaType.KIND_UNKNOWN) - } - } - - @Test - fun `test integer constant field values`() { - val viewClass: IJavaType = - types.first { it.fqn == "android/view/View" } as IJavaType - assertThat(viewClass.fields).isNotEmpty() - - val fields = viewClass.fields!! - val visible = fields.firstOrNull { it.name == "VISIBLE" } - assertThat(visible).isNotNull() - assertThat(visible?.type).isEqualTo(JavaType.INT) - - val constantValue = visible?.constantValue - assertThat(constantValue).isNotNull() - assertThat(constantValue?.kind).isEqualTo(JavaType.KIND_INT) - assertThat(constantValue?.value?.type).isEqualTo(RealmAny.Type.INTEGER) - assertThat(constantValue?.asInt()).isNotNull() - assertThat(constantValue?.asInt()).isEqualTo(View.VISIBLE) - } - - @Test - fun `test object type`() { - val obj = types.firstOrNull { it.fqn == "java/lang/Object" } - assertThat(obj).isNotNull() - assertThat(obj?.name).isEqualTo("Object") - assertThat(obj?.superClassFqn).isNull() - assertThat(obj?.superInterfacesFqn).isEmpty() - assertThat(obj?.fields).isEmpty() - assertThat(obj?.methods).isNotEmpty() - assertThat(obj?.isAnnotation).isFalse() - assertThat(obj?.isInterface).isFalse() - assertThat(obj?.isEnum).isFalse() - assertThat(obj?.isClass).isTrue() - assertThat(obj).isInstanceOf(JavaClass::class.java) - assertThat(obj?.packageName).isEqualTo("java/lang") - - val access = AccessFlags(obj!!.accessFlags) - assertThat(access.`is`(AccessFlags.ACC_PUBLIC)).isTrue() - assertThat(access.`is`(AccessFlags.ACC_STATIC)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_INTERFACE)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_ANNOTATION)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_ENUM)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_ABSTRACT)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_FINAL)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_NATIVE)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_NATIVE)).isFalse() - } - - @Test - fun `test class simple name`() { - val obj = types.firstOrNull { it.fqn == "android/view/View" } - assertThat(obj).isNotNull() - assertThat(obj?.name).isEqualTo("View") - assertThat(obj?.packageName).isEqualTo("android/view") - assertThat(obj?.superClassFqn).isEqualTo("java/lang/Object") - assertThat(obj?.superInterfacesFqn).isNotEmpty() - assertThat(obj?.fields).isNotEmpty() - assertThat(obj?.methods).isNotEmpty() - assertThat(obj?.isAnnotation).isFalse() - assertThat(obj?.isInterface).isFalse() - assertThat(obj?.isEnum).isFalse() - assertThat(obj?.isClass).isTrue() - assertThat(obj).isInstanceOf(JavaClass::class.java) - - val access = AccessFlags(obj!!.accessFlags) - assertThat(access.`is`(AccessFlags.ACC_PUBLIC)).isTrue() - assertThat(access.`is`(AccessFlags.ACC_STATIC)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_INTERFACE)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_ANNOTATION)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_ENUM)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_ABSTRACT)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_FINAL)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_NATIVE)).isFalse() - assertThat(access.`is`(AccessFlags.ACC_NATIVE)).isFalse() - } - - @Test - fun `test class superclass name`() { - types.firstOrNull { it.fqn == "android/view/View" }.also { - assertThat(it).isNotNull() - assertThat(it?.superClassFqn).isEqualTo("java/lang/Object") - } - } - - @Test - fun `test class super interface names`() { - types.firstOrNull { it.fqn == "android/view/View" }.also { - assertThat(it).isNotNull() - assertThat(it?.superInterfacesFqn).containsExactly( - "android/graphics/drawable/Drawable\$Callback", - "android/view/KeyEvent\$Callback", - "android/view/accessibility/AccessibilityEventSource" - ) - } - } - - @Test - fun `test interface super interface names`() { - types.firstOrNull { it.fqn == "java/io/Closeable" }.also { - assertThat(it).isNotNull() - assertThat(it?.superInterfacesFqn).containsExactly("java/lang/AutoCloseable") - } - } - - @Test - fun `test class fields`() { - types.firstOrNull { it.fqn == "android/view/View" }.also { view -> - assertThat(view).isNotNull() - assertThat(view?.fields?.map { field -> (field as JavaField).name }).containsAtLeast( - "VISIBLE", - "INVISIBLE", - "GONE", - "FOCUS_DOWN", - "FOCUS_UP", - "FOCUS_LEFT", - "FOCUS_RIGHT", - "FOCUS_BACKWARD", - "FOCUS_FORWARD", - ) - } - - types.firstOrNull { it.fqn == "android/view/ViewGroup\$LayoutParams" }.also { view -> - assertThat(view).isNotNull() - assertThat(view?.fields?.map { field -> (field as JavaField).name }).containsAtLeast( - "WRAP_CONTENT", - "MATCH_PARENT", - "FILL_PARENT", - ) - } - } - - @Test - fun `test interface fields`() { - types.firstOrNull { it.fqn == "android/provider/CalendarContract\$CalendarSyncColumns" } - .also { view -> - assertThat(view).isNotNull() - assertThat(view?.fields?.map { field -> (field as JavaField).name }).containsAtLeast( - "CAL_SYNC1", - "CAL_SYNC2", - "CAL_SYNC3", - "CAL_SYNC4", - "CAL_SYNC5", - "CAL_SYNC6", - "CAL_SYNC7", - "CAL_SYNC8", - "CAL_SYNC9", - "CAL_SYNC10", - ) - } - } - - @Test - fun `test mandatory enum fields`() { - types.filterIsInstance().forEach { enum -> - assertThat(enum.fields?.map { it.name }).contains("\$VALUES") - } - } - - @Test - fun `test enum fields`() { - types.firstOrNull { it.fqn == "android/net/wifi/SupplicantState" }.also { enum -> - assertThat(enum?.fields?.map { (it as JavaField).name }) - .containsAtLeast( - "DISCONNECTED", - "INTERFACE_DISABLED", - "INACTIVE", - "SCANNING", - "AUTHENTICATING", - "ASSOCIATING", - "ASSOCIATED", - "FOUR_WAY_HANDSHAKE", - "COMPLETED", - "GROUP_HANDSHAKE", - "DORMANT", - "UNINITIALIZED", - "INVALID" - ) - } - } - - @Test - fun `test annotation fields`() { - // android.jar doesn't seem to contain annotation classes with some fields - // TODO: add test for verifying how annotation fields are handled - } - - @Test - fun `test class methods`() { - types.firstOrNull { it.fqn == "android/view/View" }.also { view -> - assertThat(view).isNotNull() - assertThat(view?.methods?.map { field -> (field as JavaMethod).signature() }).containsAtLeast( - "setId(I)V", - "getId()I", - "setOnClickListener(Landroid/view/View\$OnClickListener;)V", - "hasOnClickListeners()Z", - "hasOnLongClickListeners()Z", - "setAccessibilityDelegate(Landroid/view/View\$AccessibilityDelegate;)V", - "getAccessibilityDelegate()Landroid/view/View\$AccessibilityDelegate;", - "setAccessibilityLiveRegion(I)V", - "getAccessibilityLiveRegion()I", - "setAccessibilityHeading(Z)V", - "isAccessibilityHeading()Z", - "setPadding(IIII)V", - "setPaddingRelative(IIII)V", - ) - } - } - - @Test - fun `test interface methods`() { - types.firstOrNull { it.fqn == "android/view/View\$OnClickListener" }.also { view -> - assertThat(view).isNotNull() - assertThat(view?.methods?.map { field -> (field as JavaMethod).signature() }) - .contains("onClick(Landroid/view/View;)V") - } - types.firstOrNull { it.fqn == "android/view/View\$OnLongClickListener" }.also { view -> - assertThat(view).isNotNull() - assertThat(view?.methods?.map { field -> (field as JavaMethod).signature() }) - .containsAtLeast( - "onLongClick(Landroid/view/View;)Z", - "onLongClickUseDefaultHapticFeedback(Landroid/view/View;)Z" - ) - } - } - - @Test - fun `test mandatory enum methods`() { - types.filterIsInstance().forEach { enum -> - assertThat(enum.methods?.map { it.signature() }).containsAtLeast( - "values()[L${enum.fqn};", - "\$values()[L${enum.fqn};", - "valueOf(Ljava/lang/String;)L${enum.fqn};", - "()V" - ) - } - } - - @Test - fun `test enum methods`() { - types.firstOrNull { it.fqn == "android/icu/text/DisplayContext" }.also { enum -> - assertThat(enum?.methods?.map { (it as JavaMethod).signature() }).contains( - "type()Landroid/icu/text/DisplayContext\$Type;" - ) - } - } - - @Test - fun `test annotation methods`() { - types.firstOrNull { it.fqn == "android/annotation/TargetApi" }.also { annotation -> - assertThat(annotation?.methods?.map { (it as AnnotationElement).signature() }).containsExactly( - "value()I" - ) - } - } - - @Test - fun `test annotation methods with default values`() { - types.firstOrNull { it.fqn == "java/lang/Deprecated" }.also { annotation -> - assertThat(annotation?.methods).isNotEmpty() - - val since = - annotation?.methods?.find { (it as AnnotationElement).name == "since" } as AnnotationElement - assertThat(since.type).isEqualTo(JavaType.STRING) - - var defValue = since.defaultValue - assertThat(defValue).isNotNull() - assertThat(defValue?.valueClass).isEqualTo(PrimitiveAnnotationElementValue::class.java) - - var defVal = defValue?.asRealmModel(PrimitiveAnnotationElementValue::class.java) - assertThat(defVal).isNotNull() - assertThat(defVal?.kind).isEqualTo(IAnnotationElementValue.KIND_STRING) - assertThat(defVal?.value).isNotNull() - assertThat(defVal?.value?.kind).isEqualTo(JavaType.KIND_REF) - assertThat(defVal?.value?.asString()).isEqualTo("") - assertThat(defVal?.value?.asBoolean()).isNull() - assertThat(defVal?.value?.asByte()).isNull() - assertThat(defVal?.value?.asShort()).isNull() - assertThat(defVal?.value?.asChar()).isNull() - assertThat(defVal?.value?.asInt()).isNull() - assertThat(defVal?.value?.asLong()).isNull() - assertThat(defVal?.value?.asFloat()).isNull() - assertThat(defVal?.value?.asDouble()).isNull() - - val forRemoval = - annotation.methods?.find { (it as AnnotationElement).name == "forRemoval" } as AnnotationElement - assertThat(forRemoval.type).isEqualTo(JavaType.BOOLEAN) - - defValue = forRemoval.defaultValue - assertThat(defValue).isNotNull() - assertThat(defValue?.valueClass).isEqualTo(PrimitiveAnnotationElementValue::class.java) - - defVal = defValue?.asRealmModel(PrimitiveAnnotationElementValue::class.java) - assertThat(defVal).isNotNull() - assertThat(defVal?.kind).isEqualTo(IAnnotationElementValue.KIND_BOOLEAN) - assertThat(defVal?.value).isNotNull() - assertThat(defVal?.value?.kind).isEqualTo(JavaType.KIND_BOOLEAN) - assertThat(defVal?.value?.asBoolean()).isEqualTo(false) - assertThat(defVal?.value?.asByte()).isNull() - assertThat(defVal?.value?.asShort()).isNull() - assertThat(defVal?.value?.asChar()).isNull() - assertThat(defVal?.value?.asInt()).isNull() - assertThat(defVal?.value?.asLong()).isNull() - assertThat(defVal?.value?.asFloat()).isNull() - assertThat(defVal?.value?.asDouble()).isNull() - assertThat(defVal?.value?.asString()).isNull() - } - } - - @Test - fun `test annotation methods with array value`() { - types.firstOrNull { it.fqn == "java/lang/SuppressWarnings" }.also { annotation -> - assertThat(annotation?.methods).isNotEmpty() - - val value = - annotation?.methods?.find { (it as AnnotationElement).name == "value" } as AnnotationElement - assertThat(value.type?.kind).isEqualTo(JavaType.KIND_REF) - assertThat(value.type?.name).isEqualTo("java/lang/String") - assertThat(value.type?.arrayDims).isEqualTo(1) - - val defValue = value.defaultValue - assertThat(defValue).isNull() - } - } - - @Test - fun `test class type classification`() { - types.firstOrNull { it.fqn == "android/view/View" }.also { - assertThat(it).isNotNull() - assertThat(it?.isClass).isTrue() - assertThat(it?.isInterface).isFalse() - assertThat(it?.isAnnotation).isFalse() - assertThat(it?.isEnum).isFalse() - assertThat(it).isInstanceOf(JavaClass::class.java) - } - } - - @Test - fun `test interface type classification`() { - types.firstOrNull { it.fqn == "android/view/View\$OnClickListener" }.also { - assertThat(it).isNotNull() - assertThat(it?.isClass).isFalse() - assertThat(it?.isInterface).isTrue() - assertThat(it?.isAnnotation).isFalse() - assertThat(it?.isEnum).isFalse() - assertThat(it).isInstanceOf(JavaInterface::class.java) - } - } - - @Test - fun `test annotation type classification`() { - types.firstOrNull { it.fqn == "java/lang/Deprecated" }.also { - assertThat(it).isNotNull() - assertThat(it?.isClass).isFalse() - assertThat(it?.isInterface).isTrue() - assertThat(it?.isAnnotation).isTrue() - assertThat(it?.isEnum).isFalse() - assertThat(it).isInstanceOf(JavaAnnotation::class.java) - } - } - - @Test - fun `test enum type classification`() { - types.firstOrNull { it.fqn == "android/icu/text/DisplayContext" }.also { - assertThat(it).isNotNull() - assertThat(it?.isClass).isFalse() - assertThat(it?.isInterface).isFalse() - assertThat(it?.isAnnotation).isFalse() - assertThat(it?.isEnum).isTrue() - assertThat(it).isInstanceOf(JavaEnum::class.java) - } - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 798ed9681..752cb21bd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -126,7 +126,6 @@ include( ":core:actions", ":core:app", ":core:common", - ":core:database", ":core:indexing-api", ":core:indexing-core", ":core:lsp-api", diff --git a/testing/androidTest/build.gradle.kts b/testing/androidTest/build.gradle.kts index bbada5339..b3b9b776f 100644 --- a/testing/androidTest/build.gradle.kts +++ b/testing/androidTest/build.gradle.kts @@ -42,11 +42,6 @@ configurations.api { dependencies { - // compileOnly so that we can provide the APIs for the related test rules - // if a module needs to use those APIs, it needs to explicitly add the database module as a - // dependency - compileOnly(projects.core.database) - api(libs.google.protobuf) api(libs.tests.androidx.espresso.core) api(libs.tests.androidx.espresso.contrib) diff --git a/testing/benchmarks/build.gradle.kts b/testing/benchmarks/build.gradle.kts index 723f4947b..c5ad72998 100644 --- a/testing/benchmarks/build.gradle.kts +++ b/testing/benchmarks/build.gradle.kts @@ -66,7 +66,6 @@ dependencies { androidTestImplementation(libs.androidx.benchmark.junit4) androidTestImplementation(projects.core.common) - androidTestImplementation(projects.core.database) androidTestImplementation(projects.core.indexingApi) androidTestImplementation(projects.java.lsp) androidTestImplementation(projects.utilities.shared)