From 2a336f18d81184374b61320b195161e7eb4e4243 Mon Sep 17 00:00:00 2001 From: WarningImHack3r <43064022+WarningImHack3r@users.noreply.github.com> Date: Mon, 8 Jan 2024 20:08:36 +0100 Subject: [PATCH] Fix support for all frameworks - Fix incorrect support for frameworks that don't use folders for components - Fix missing default value for some frameworks - Globally fix alias resolution - Fix imports replacement being broken for some frameworks - Fix support for Vue as its config doesn't contain schema by default for some reason --- README.md | 3 +- .../backend/SourceScanner.kt | 3 +- .../backend/helpers/FileManager.kt | 9 ++- .../backend/sources/Source.kt | 65 ++++++++++------- .../backend/sources/config/VueConfig.kt | 2 +- .../backend/sources/impl/ReactSource.kt | 38 +++++----- .../backend/sources/impl/SolidSource.kt | 23 +++--- .../backend/sources/impl/SvelteSource.kt | 2 + .../backend/sources/impl/VueSource.kt | 71 +++++++++++++------ .../backend/sources/remote/Component.kt | 4 +- .../sources/remote/ComponentWithContents.kt | 4 +- 11 files changed, 140 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index b445715..a61bfe3 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ - Rework `class`es replacement detection mechanism to be 100% accurate - Add tests for this - Add support for Vue's `typescript` option (transpiling TypeScript to JavaScript in `*.vue` files) -- Parse `vite.config.(js|ts)` to resolve aliases as a fallback of `tsconfig.json` ## Description @@ -38,7 +37,9 @@ If you don't see the tool window, you can open it from `View > Tool Windows > sh ## Planned Features +- Parse `vite.config.(js|ts)` (and others like `nuxt.config.ts`) to resolve aliases as a fallback of `tsconfig.json` - Figure out a clean way to refresh the tool window automatically after adding or removing components +- Refresh/recreate the tool window automatically when the project finishes indexing - Add support for monorepos diff --git a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/SourceScanner.kt b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/SourceScanner.kt index 7654903..ab378b1 100644 --- a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/SourceScanner.kt +++ b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/SourceScanner.kt @@ -16,7 +16,8 @@ object SourceScanner { when { contents.contains("shadcn-svelte.com") -> SvelteSource(project) contents.contains("ui.shadcn.com") -> ReactSource(project) - contents.contains("shadcn-vue.com") -> VueSource(project) + contents.contains("shadcn-vue.com") + || contents.contains("\"framework\": \"") -> VueSource(project) contents.contains("shadcn-solid") -> SolidSource(project) else -> null } diff --git a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/helpers/FileManager.kt b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/helpers/FileManager.kt index 6089774..9123acc 100644 --- a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/helpers/FileManager.kt +++ b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/helpers/FileManager.kt @@ -5,6 +5,7 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiFile import com.intellij.psi.search.FilenameIndex import com.intellij.psi.search.GlobalSearchScope +import java.io.IOException import java.nio.file.NoSuchFileException class FileManager(private val project: Project) { @@ -20,7 +21,11 @@ class FileManager(private val project: Project) { } fun deleteFileAtPath(path: String): Boolean { - return getFileAtPath(path)?.delete(this)?.let { true } ?: false + return try { + getFileAtPath(path)?.delete(this)?.let { true } ?: false + } catch (e: IOException) { + false + } } fun getVirtualFilesByName(name: String): Collection { @@ -32,6 +37,8 @@ class FileManager(private val project: Project) { if (!name.startsWith(".")) { !nodeModule && !file.path.substringAfter(project.basePath!!).startsWith(".") } else !nodeModule + }.sortedBy { file -> + name.toRegex().find(file.path)?.range?.first ?: Int.MAX_VALUE } } diff --git a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/Source.kt b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/Source.kt index 526ae05..436bc56 100644 --- a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/Source.kt +++ b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/Source.kt @@ -28,15 +28,18 @@ abstract class Source(val project: Project, private val serializer: // Utility methods protected fun getLocalConfig(): C { - return FileManager(project).getFileContentsAtPath("components.json")?.let { + val file = "components.json" + return FileManager(project).getFileContentsAtPath(file)?.let { try { Json.decodeFromString(serializer, it) } catch (e: Exception) { - throw UnparseableConfigException(project, "Unable to parse components.json", e) + throw UnparseableConfigException(project, "Unable to parse $file", e) } - } ?: throw NoSuchFileException("components.json not found") + } ?: throw NoSuchFileException("$file not found") } + protected abstract fun usesDirectoriesForComponents(): Boolean + protected abstract fun resolveAlias(alias: String): String protected fun cleanAlias(alias: String): String = if (alias.startsWith("\$")) { @@ -55,14 +58,21 @@ abstract class Source(val project: Project, private val serializer: protected fun fetchColors(): JsonElement { val baseColor = getLocalConfig().tailwind.baseColor - val response = RequestSender.sendRequest("$domain/registry/colors/$baseColor.json") - return response.ok { Json.parseToJsonElement(it.body) } ?: throw Exception("Colors not found") + return RequestSender.sendRequest("$domain/registry/colors/$baseColor.json").ok { + Json.parseToJsonElement(it.body) + } ?: throw Exception("Colors not found") + } + + protected open fun getRegistryDependencies(component: ComponentWithContents): List { + return component.registryDependencies.map { registryDependency -> + val dependency = fetchComponent(registryDependency) + listOf(dependency, *getRegistryDependencies(dependency).toTypedArray()) + }.flatten() } // Public methods open fun fetchAllComponents(): List { - val response = RequestSender.sendRequest("$domain/registry/index.json") - return response.ok { + return RequestSender.sendRequest("$domain/registry/index.json").ok { Json.decodeFromString>(it.body) }?.map { ISPComponent(it.name) } ?: emptyList() } @@ -70,27 +80,19 @@ abstract class Source(val project: Project, private val serializer: open fun getInstalledComponents(): List { return FileManager(project).getFileAtPath( "${resolveAlias(getLocalConfig().aliases.components)}/ui" - )?.children?.map { it.name }?.sorted() ?: emptyList() + )?.children?.map { file -> + if (file.isDirectory) file.name else file.name.substringBeforeLast(".") + }?.sorted() ?: emptyList() } open fun addComponent(componentName: String) { - val installedComponents = getInstalledComponents() - fun getRegistryDependencies(component: ComponentWithContents): List { - return component.registryDependencies.filter { - !installedComponents.contains(it) - }.map { registryDependency -> - val dependency = fetchComponent(registryDependency) - listOf(dependency, *getRegistryDependencies(dependency).toTypedArray()) - }.flatten() - } - // Install component val component = fetchComponent(componentName) - val components = setOf(component, *getRegistryDependencies(fetchComponent(componentName)).toTypedArray()) - val config = getLocalConfig() - components.forEach { downloadedComponent -> + val installedComponents = getInstalledComponents() + setOf(component, *getRegistryDependencies(component).filter { + !installedComponents.contains(it.name) + }.toTypedArray()).forEach { downloadedComponent -> downloadedComponent.files.forEach { file -> - val path = "${resolveAlias(config.aliases.components)}/${component.type.substringAfterLast(":")}/${downloadedComponent.name}" val psiFile = PsiFileFactory.getInstance(project).createFileFromText( adaptFileExtensionToConfig(file.name), FileTypeManager.getInstance().getFileTypeByExtension( @@ -98,6 +100,9 @@ abstract class Source(val project: Project, private val serializer: ), adaptFileToConfig(file.content) ) + val path = "${resolveAlias(getLocalConfig().aliases.components)}/${component.type.substringAfterLast(":")}" + if (usesDirectoriesForComponents()) { + "/${downloadedComponent.name}" + } else "" FileManager(project).saveFileAtPath(psiFile, path) } } @@ -138,19 +143,25 @@ abstract class Source(val project: Project, private val serializer: } open fun isComponentUpToDate(componentName: String): Boolean { - val config = getLocalConfig() val remoteComponent = fetchComponent(componentName) return remoteComponent.files.all { file -> FileManager(project).getFileContentsAtPath( - "${resolveAlias(config.aliases.components)}/${remoteComponent.type.substringAfterLast(":")}/${remoteComponent.name}/${file.name}" + "${resolveAlias(getLocalConfig().aliases.components)}/${remoteComponent.type.substringAfterLast(":")}${if (usesDirectoriesForComponents()) { + "/${remoteComponent.name}" + } else ""}/${file.name}" ) == adaptFileToConfig(file.content) } } open fun removeComponent(componentName: String) { val remoteComponent = fetchComponent(componentName) - FileManager(project).deleteFileAtPath( - "${resolveAlias(getLocalConfig().aliases.components)}/${remoteComponent.type.substringAfterLast(":")}/${remoteComponent.name}" - ) + val componentsDir = "${resolveAlias(getLocalConfig().aliases.components)}/${remoteComponent.type.substringAfterLast(":")}" + if (usesDirectoriesForComponents()) { + FileManager(project).deleteFileAtPath("$componentsDir/${remoteComponent.name}") + } else { + remoteComponent.files.forEach { file -> + FileManager(project).deleteFileAtPath("$componentsDir/${file.name}") + } + } } } diff --git a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/config/VueConfig.kt b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/config/VueConfig.kt index eb4ac47..f077248 100644 --- a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/config/VueConfig.kt +++ b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/config/VueConfig.kt @@ -15,7 +15,7 @@ import kotlinx.serialization.Serializable @Suppress("PROVIDED_RUNTIME_TOO_LOW", "kotlin:S117") @Serializable class VueConfig( - override val `$schema`: String, + override val `$schema`: String = "https://shadcn-vue.com/schema.json", override val style: String, val typescript: Boolean = true, override val tailwind: Tailwind, diff --git a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/ReactSource.kt b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/ReactSource.kt index ca18735..3b19b8c 100644 --- a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/ReactSource.kt +++ b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/ReactSource.kt @@ -14,9 +14,12 @@ import java.nio.file.NoSuchFileException class ReactSource(project: Project) : Source(project, ReactConfig.serializer()) { override var framework = "React" + override fun usesDirectoriesForComponents() = false + override fun resolveAlias(alias: String): String { if (!alias.startsWith("$") && !alias.startsWith("@")) return alias - val tsConfig = FileManager(project).getFileContentsAtPath("tsconfig.json") ?: throw NoSuchFileException("tsconfig.json not found") + val configFile = if (getLocalConfig().tsx) "tsconfig.json" else "jsconfig.json" + val tsConfig = FileManager(project).getFileContentsAtPath(configFile) ?: throw NoSuchFileException("$configFile not found") val aliasPath = Json.parseToJsonElement(tsConfig) .jsonObject["compilerOptions"] ?.jsonObject?.get("paths") @@ -37,23 +40,24 @@ class ReactSource(project: Project) : Source(project, ReactConfig.s override fun adaptFileToConfig(contents: String): String { val config = getLocalConfig() - // Note: this condition does not replace UI paths (= $components/$ui) by the components path - // if the UI alias is not set. - // For me, this is a bug, but I'm following what the original code does for parity - // (https://github.com/shadcn-ui/ui/blob/fb614ac2921a84b916c56e9091aa0ae8e129c565/packages/cli/src/utils/transformers/transform-import.ts#L10-L23). - var newContents = if (config.aliases.ui != null) { - contents.replace( - Regex("@/registry/[^/]+/ui"), cleanAlias(config.aliases.ui) + // Note: this does not prevent additional imports other than "cn" from being replaced, + // but I'm once again following what the original code does for parity + // (https://github.com/shadcn-ui/ui/blob/fb614ac2921a84b916c56e9091aa0ae8e129c565/packages/cli/src/utils/transformers/transform-import.ts#L25-L35). + val newContents = Regex(".*\\{.*[ ,\n\t]+cn[ ,].*}.*\"(@/lib/cn).*").replace( + // Note: this condition does not replace UI paths (= $components/$ui) by the components path + // if the UI alias is not set. + // For me, this is a bug, but I'm following what the original code does for parity + // (https://github.com/shadcn-ui/ui/blob/fb614ac2921a84b916c56e9091aa0ae8e129c565/packages/cli/src/utils/transformers/transform-import.ts#L10-L23). + if (config.aliases.ui != null) { + contents.replace( + Regex("@/registry/[^/]+/ui"), cleanAlias(config.aliases.ui) + ) + } else contents.replace( + Regex("@/registry/[^/]+"), cleanAlias(config.aliases.components) ) - } else contents.replace( - Regex("@/registry/[^/]+"), cleanAlias(config.aliases.components) - ) - newContents = newContents.replace( - // Note: this does not prevent additional imports other than "cn" from being replaced, - // but I'm once again following what the original code does for parity - // (https://github.com/shadcn-ui/ui/blob/fb614ac2921a84b916c56e9091aa0ae8e129c565/packages/cli/src/utils/transformers/transform-import.ts#L25-L35). - Regex(".*\\{.*[ ,\n\t]+cn[ ,].*}.*\"@/lib/utils"), config.aliases.utils - ).applyIf(config.rsc) { + ) { result -> + result.groupValues[0].replace(result.groupValues[1], config.aliases.utils) + }.applyIf(config.rsc) { replace( Regex("\"use client\";*\n"), "" ) diff --git a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/SolidSource.kt b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/SolidSource.kt index 1f4d985..80d0f5a 100644 --- a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/SolidSource.kt +++ b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/SolidSource.kt @@ -13,29 +13,32 @@ import java.nio.file.NoSuchFileException class SolidSource(project: Project) : Source(project, SolidConfig.serializer()) { override var framework = "Solid" + override fun usesDirectoriesForComponents() = false + override fun resolveAlias(alias: String): String { if (!alias.startsWith("$") && !alias.startsWith("@")) return alias - val tsConfig = FileManager(project).getFileContentsAtPath("tsconfig.json") ?: throw NoSuchFileException("tsconfig.json not found") + val configFile = "tsconfig.json" + val tsConfig = FileManager(project).getFileContentsAtPath(configFile) ?: throw NoSuchFileException("$configFile not found") val aliasPath = Json.parseToJsonElement(tsConfig) .jsonObject["compilerOptions"] ?.jsonObject?.get("paths") ?.jsonObject?.get("${alias.substringBefore("/")}/*") ?.jsonArray?.get(0) ?.jsonPrimitive?.content ?: throw Exception("Cannot find alias $alias") - return aliasPath.replace(Regex("^\\./"), "") + return aliasPath.replace(Regex("^\\.+/"), "") .replace(Regex("\\*$"), alias.substringAfter("/")) } override fun adaptFileToConfig(contents: String): String { val config = getLocalConfig() - val newContents = contents.replace( - Regex("@/registry/[^/]+"), cleanAlias(config.aliases.components) - ).replace( - // Note: this does not prevent additional imports other than "cn" from being replaced, - // but I'm following what the original code does for parity - // (https://github.com/hngngn/shadcn-solid/blob/b808e0ecc9fd4689572d9fc0dfb7af81606a11f2/packages/cli/src/utils/transformers/transform-import.ts#L20-L29). - Regex(".*\\{.*[ ,\n\t]+cn[ ,].*}.*\"@/lib/cn"), config.aliases.utils - ) + // Note: this does not prevent additional imports other than "cn" from being replaced, + // but I'm following what the original code does for parity + // (https://github.com/hngngn/shadcn-solid/blob/b808e0ecc9fd4689572d9fc0dfb7af81606a11f2/packages/cli/src/utils/transformers/transform-import.ts#L20-L29). + val newContents = Regex(".*\\{.*[ ,\n\t]+cn[ ,].*}.*\"(@/lib/cn).*").replace( + contents.replace( + Regex("@/registry/[^/]+"), cleanAlias(config.aliases.components) + ) + ) { it.groupValues[0].replace(it.groupValues[1], config.aliases.utils) } return if (!config.tailwind.cssVariables) { /** diff --git a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/SvelteSource.kt b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/SvelteSource.kt index f395a09..5e85f23 100644 --- a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/SvelteSource.kt +++ b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/SvelteSource.kt @@ -14,6 +14,8 @@ import java.nio.file.NoSuchFileException class SvelteSource(project: Project) : Source(project, SvelteConfig.serializer()) { override var framework = "Svelte" + override fun usesDirectoriesForComponents() = true + override fun resolveAlias(alias: String): String { if (!alias.startsWith("$") && !alias.startsWith("@")) return alias var tsConfig = FileManager(project).getFileContentsAtPath(".svelte-kit/tsconfig.json") diff --git a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/VueSource.kt b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/VueSource.kt index 0a16dc3..c57b334 100644 --- a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/VueSource.kt +++ b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/impl/VueSource.kt @@ -3,6 +3,7 @@ package com.github.warningimhack3r.intellijshadcnplugin.backend.sources.impl import com.github.warningimhack3r.intellijshadcnplugin.backend.helpers.FileManager import com.github.warningimhack3r.intellijshadcnplugin.backend.sources.Source import com.github.warningimhack3r.intellijshadcnplugin.backend.sources.config.VueConfig +import com.github.warningimhack3r.intellijshadcnplugin.backend.sources.remote.ComponentWithContents import com.github.warningimhack3r.intellijshadcnplugin.notifications.NotificationManager import com.intellij.notification.NotificationType import com.intellij.openapi.project.Project @@ -16,6 +17,38 @@ import java.nio.file.NoSuchFileException class VueSource(project: Project) : Source(project, VueConfig.serializer()) { override var framework = "Vue" + override fun usesDirectoriesForComponents() = true + + override fun resolveAlias(alias: String): String { + if (!alias.startsWith("$") && !alias.startsWith("@")) return alias + + fun resolvePath(configFile: String): String? { + return Json.parseToJsonElement(configFile + .split("\n") + .filterNot { it.trim().startsWith("//") } // remove comments + .joinToString("\n") + ) + .jsonObject["compilerOptions"] + ?.jsonObject?.get("paths") + ?.jsonObject?.get("${alias.substringBefore("/")}/*") + ?.jsonArray?.get(0) + ?.jsonPrimitive?.content + } + + val config = getLocalConfig() + val tsConfigLocation = when (config.framework) { + VueConfig.Framework.NUXT -> ".nuxt/tsconfig.json" + else -> "tsconfig.json" + }.let { if (!config.typescript) "jsconfig.json" else it } + + val tsConfig = FileManager(project).getFileContentsAtPath(tsConfigLocation) ?: throw NoSuchFileException("$tsConfigLocation not found") + val aliasPath = (resolvePath(tsConfig) ?: if (config.typescript) { + resolvePath("tsconfig.app.json") + } else null) ?: throw Exception("Cannot find alias $alias") + return aliasPath.replace(Regex("^\\.+/"), "") + .replace(Regex("\\*$"), alias.substringAfter("/")) + } + override fun adaptFileExtensionToConfig(extension: String): String { return if (!getLocalConfig().typescript) { extension.replace( @@ -25,30 +58,18 @@ class VueSource(project: Project) : Source(project, VueConfig.seriali } else extension } - override fun resolveAlias(alias: String): String { - if (!alias.startsWith("$") && !alias.startsWith("@")) return alias - val tsConfig = FileManager(project).getFileContentsAtPath("tsconfig.json") ?: throw NoSuchFileException("tsconfig.json not found") - val aliasPath = Json.parseToJsonElement(tsConfig) - .jsonObject["compilerOptions"] - ?.jsonObject?.get("paths") - ?.jsonObject?.get("${alias.substringBefore("/")}/*") - ?.jsonArray?.get(0) - ?.jsonPrimitive?.content ?: throw Exception("Cannot find alias $alias") - return aliasPath.replace(Regex("^\\./"), "") - .replace(Regex("\\*$"), alias.substringAfter("/")) - } - override fun adaptFileToConfig(contents: String): String { val config = getLocalConfig() - val newContents = contents.replace( - Regex("@/lib/registry/[^/]+"), cleanAlias(config.aliases.components) - ).replace( - // Note: this does not prevent additional imports other than "cn" from being replaced, - // but I'm following what the original code does for parity - // (https://github.com/radix-vue/shadcn-vue/blob/9d9a6f929ce0f281b4af36161af80ed2bbdc4a16/packages/cli/src/utils/transformers/transform-import.ts#L19-L29). - Regex(".*\\{.*[ ,\n\t]+cn[ ,].*}.*\"@/lib/utils"), - cleanAlias(config.aliases.utils) - ).applyIf(!config.typescript) { + // Note: this does not prevent additional imports other than "cn" from being replaced, + // but I'm following what the original code does for parity + // (https://github.com/radix-vue/shadcn-vue/blob/9d9a6f929ce0f281b4af36161af80ed2bbdc4a16/packages/cli/src/utils/transformers/transform-import.ts#L19-L29). + val newContents = Regex(".*\\{.*[ ,\n\t]+cn[ ,].*}.*\"(@/lib/cn).*").replace( + contents.replace( + Regex("@/registry/[^/]+"), cleanAlias(config.aliases.components) + ) + ) { result -> + result.groupValues[0].replace(result.groupValues[1], cleanAlias(config.aliases.utils)) + }.applyIf(!config.typescript) { NotificationManager(project).sendNotification( "TypeScript option for Vue", "You have TypeScript disabled in your shadcn/ui config. This feature is not supported yet. Please install/update your components with the CLI for now.", @@ -134,4 +155,10 @@ class VueSource(project: Project) : Source(project, VueConfig.seriali } } else newContents } + + override fun getRegistryDependencies(component: ComponentWithContents): List { + return super.getRegistryDependencies(component.copy( + registryDependencies = component.registryDependencies.filterNot { it == "utils" } + )) + } } diff --git a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/remote/Component.kt b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/remote/Component.kt index 9dbc241..19322cd 100644 --- a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/remote/Component.kt +++ b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/remote/Component.kt @@ -14,8 +14,8 @@ import kotlinx.serialization.Serializable @Serializable data class Component( val name: String, - val dependencies: List, - val registryDependencies: List, + val dependencies: List = emptyList(), + val registryDependencies: List = emptyList(), val files: List, val type: String ) diff --git a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/remote/ComponentWithContents.kt b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/remote/ComponentWithContents.kt index 65af3bd..412434e 100644 --- a/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/remote/ComponentWithContents.kt +++ b/src/main/kotlin/com/github/warningimhack3r/intellijshadcnplugin/backend/sources/remote/ComponentWithContents.kt @@ -14,8 +14,8 @@ import kotlinx.serialization.Serializable @Serializable data class ComponentWithContents( val name: String, - val dependencies: List, - val registryDependencies: List, + val dependencies: List = emptyList(), + val registryDependencies: List = emptyList(), val files: List, val type: String ) {