Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: better project base path detection #113

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 55 additions & 10 deletions src/main/kotlin/com/vaadin/plugin/VaadinProjectDetector.kt
Original file line number Diff line number Diff line change
@@ -1,33 +1,78 @@
package com.vaadin.plugin

import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir
import com.intellij.openapi.roots.ModuleRootEvent
import com.intellij.openapi.roots.ModuleRootListener
import com.intellij.openapi.startup.ProjectActivity
import com.intellij.openapi.vfs.VfsUtil
import com.vaadin.plugin.listeners.VaadinProjectListener
import com.vaadin.plugin.utils.VaadinProjectUtil.Companion.isVaadinProject
import com.vaadin.plugin.utils.VaadinProjectUtil
import com.vaadin.plugin.utils.VaadinProjectUtil.Companion.findVaadinModule
import java.io.File
import org.jetbrains.idea.maven.project.MavenProjectsManager
import org.jetbrains.plugins.gradle.settings.GradleSettings

class VaadinProjectDetector : ModuleRootListener, ProjectActivity {

private val LOG: Logger = Logger.getInstance(VaadinProjectDetector::class.java)

override fun rootsChanged(event: ModuleRootEvent) {
if (event.project.isOpen && isVaadinProject(event.project)) {
doNotifyAboutVaadinProject(event.project)
LOG.info("Vaadin detected in dependencies of " + event.project.name)
if (event.project.isOpen) {
detectVaadinAndNotify(event.project)
}
}

override suspend fun execute(project: Project) {
if (isVaadinProject(project)) {
doNotifyAboutVaadinProject(project)
LOG.info("Vaadin detected during startup of " + project.name)
detectVaadinAndNotify(project)
}

private fun detectVaadinAndNotify(project: Project) {
findVaadinModule(project)?.let { module ->
LOG.info("Detected Vaadin module: ${module.name}")
val projectRoot = findProjectRoot(project, module)
if (projectRoot == null) {
LOG.warn("Project root not found")
return@let
}
val projectRootFile = VfsUtil.findFileByIoFile(File(projectRoot), true)
if (projectRootFile == null) {
LOG.warn("Project root $projectRootFile is not accessible")
return@let
}
project.putUserData(VaadinProjectUtil.VAADIN_ROOT_MODULE_PATH_KEY, projectRootFile)
project.messageBus.syncPublisher(VaadinProjectListener.TOPIC).vaadinProjectDetected(project)
}
}

private fun doNotifyAboutVaadinProject(project: Project) {
val publisher: VaadinProjectListener = project.messageBus.syncPublisher(VaadinProjectListener.TOPIC)
publisher.vaadinProjectDetected(project)
private fun findProjectRoot(project: Project, module: Module): String? {
val maybeMavenProject = MavenProjectsManager.getInstance(project)
if (maybeMavenProject.isMavenizedProject) {
val rootDir = maybeMavenProject.rootProjects.iterator().next().directory
LOG.info("Maven project root: $rootDir")
return rootDir
}

val maybeGradle = GradleSettings.getInstance(project)
if (!maybeGradle.linkedProjectsSettings.isEmpty()) {
val externalProjectPath = maybeGradle.linkedProjectsSettings.iterator().next().externalProjectPath
if (externalProjectPath != null) {
LOG.info("Gradle project root: $externalProjectPath")
return externalProjectPath
}
}

val externalRootPath = ExternalSystemApiUtil.getExternalRootProjectPath(module)
if (externalRootPath != null) {
LOG.info("External system root: $externalRootPath")
return externalRootPath
}

val guessedPath = project.guessProjectDir()?.path
LOG.info("Project guessed path: $guessedPath")
return guessedPath
}
}
27 changes: 8 additions & 19 deletions src/main/kotlin/com/vaadin/plugin/copilot/CopilotPluginUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ import com.intellij.notification.NotificationType
import com.intellij.notification.Notifications
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.*
import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.PsiManager
import com.vaadin.plugin.copilot.handler.*
import com.vaadin.plugin.utils.VaadinIcons
import com.vaadin.plugin.utils.VaadinProjectUtil
import io.netty.handler.codec.http.HttpResponseStatus
import java.io.BufferedWriter
import java.io.File
import java.io.StringWriter
import java.util.*

Expand Down Expand Up @@ -124,24 +124,13 @@ class CopilotPluginUtil {
}
}

private fun getIdeaDir(project: Project): File {
return File(project.basePath, IDEA_DIR)
private fun getIdeaDir(project: Project): VirtualFile {
val root = project.getUserData(VaadinProjectUtil.VAADIN_ROOT_MODULE_PATH_KEY)
return root!!.findOrCreateDirectory(IDEA_DIR)
}

fun getDotFileDirectory(project: Project): PsiDirectory? {
return ApplicationManager.getApplication().runReadAction<PsiDirectory?> {
VfsUtil.findFileByIoFile(getIdeaDir(project), false)?.let {
return@runReadAction PsiManager.getInstance(project).findDirectory(it)
}
return@runReadAction null
}
}

fun createIdeaDirectoryIfMissing(project: Project) {
WriteCommandAction.runWriteCommandAction(project) {
val ideaDir = getIdeaDir(project).path
VfsUtil.createDirectoryIfMissing(ideaDir)?.let { LOG.info("$ideaDir created") }
}
private fun getDotFileDirectory(project: Project): PsiDirectory? {
return runReadAction { PsiManager.getInstance(project).findDirectory(getIdeaDir(project)) }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package com.vaadin.plugin.copilot.listeners
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.project.ProjectManagerListener
import com.vaadin.plugin.copilot.CopilotPluginUtil
import com.vaadin.plugin.copilot.CopilotPluginUtil.Companion.removeDotFile
import com.vaadin.plugin.copilot.CopilotPluginUtil.Companion.saveDotFile
import com.vaadin.plugin.listeners.VaadinProjectListener

class CopilotVaadinProjectListener : VaadinProjectListener {
Expand All @@ -13,26 +14,18 @@ class CopilotVaadinProjectListener : VaadinProjectListener {
override fun vaadinProjectDetected(project: Project) {
if (!triggered) {
triggered = true
createDotFile(project)
saveDotFile(project)
removeDotFileOnExit(project)
}
}

private fun createDotFile(project: Project) {
val dotFileDirectory = CopilotPluginUtil.getDotFileDirectory(project)
if (dotFileDirectory == null) {
CopilotPluginUtil.createIdeaDirectoryIfMissing(project)
}
CopilotPluginUtil.saveDotFile(project)
}

private fun removeDotFileOnExit(project: Project) {
ProjectManager.getInstance()
.addProjectManagerListener(
project,
object : ProjectManagerListener {
override fun projectClosing(project: Project) {
CopilotPluginUtil.removeDotFile(project)
removeDotFile(project)
}
},
)
Expand Down
10 changes: 7 additions & 3 deletions src/main/kotlin/com/vaadin/plugin/utils/VaadinProjectUtil.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.vaadin.plugin.utils

import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.observable.properties.GraphProperty
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.util.download.DownloadableFileService
import com.intellij.util.io.ZipUtil
Expand All @@ -26,6 +28,8 @@ class VaadinProjectUtil {

private const val VAADIN_LIB_PREFIX = "com.vaadin:"

val VAADIN_ROOT_MODULE_PATH_KEY = Key<VirtualFile>("vaadin_root_module_path")

val PROJECT_DOWNLOADED_PROP_KEY = Key<GraphProperty<Boolean>>("vaadin_project_downloaded")

val PROJECT_MODEL_PROP_KEY = Key<GraphProperty<DownloadableModel?>>("vaadin_project_model")
Expand Down Expand Up @@ -75,11 +79,11 @@ class VaadinProjectUtil {
}
}

fun isVaadinProject(project: Project): Boolean {
return ModuleManager.getInstance(project).modules.any { isVaadinModule(it) }
fun findVaadinModule(project: Project): Module? {
return ModuleManager.getInstance(project).modules.find { isVaadinModule(it) }
}

fun isVaadinModule(module: com.intellij.openapi.module.Module): Boolean {
private fun isVaadinModule(module: Module): Boolean {
var hasVaadin = false
ModuleRootManager.getInstance(module).orderEntries().forEachLibrary { library: Library ->
if (library.name?.contains(VAADIN_LIB_PREFIX) == true) {
Expand Down