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: check every module when looking if a file is inside the project #164

Merged
merged 7 commits into from
Nov 20, 2024
70 changes: 70 additions & 0 deletions src/main/kotlin/com/vaadin/plugin/copilot/CopilotPluginUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ import com.intellij.openapi.application.WriteAction
import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir
import com.intellij.openapi.project.modules
import com.intellij.openapi.roots.CompilerModuleExtension
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.vfs.*
import com.vaadin.plugin.copilot.handler.*
import com.vaadin.plugin.utils.VaadinIcons
Expand All @@ -18,9 +22,24 @@ import java.io.BufferedWriter
import java.io.IOException
import java.io.StringWriter
import java.util.*
import org.jetbrains.jps.model.java.JavaResourceRootType
import org.jetbrains.jps.model.java.JavaSourceRootType

class CopilotPluginUtil {

@JvmRecord
data class ModuleInfo(
val name: String,
val contentRoots: Array<String>,
val javaSourcePaths: Array<String>,
val javaTestSourcePaths: Array<String>,
val resourcePaths: Array<String>,
val testResourcePaths: Array<String>,
val outputPath: String?
)

@JvmRecord data class ProjectInfo(val basePath: String?, val modules: List<CopilotPluginUtil.ModuleInfo>)

companion object {

private val LOG: Logger = Logger.getInstance(CopilotPluginUtil::class.java)
Expand Down Expand Up @@ -153,5 +172,56 @@ class CopilotPluginUtil {
fun getDotFile(project: Project): VirtualFile? {
return getDotFileDirectory(project)?.findFile(DOTFILE)
}

/**
* Returns a list of all modules in the project. Each module contains information about the module name, content
* roots, source paths, test source paths, resource paths, test resource paths, and output path.
*/
fun getModulesInfo(project: Project): ArrayList<ModuleInfo> {
val modules = ArrayList<ModuleInfo>()
ModuleManager.getInstance(project).modules.forEach { module ->
val moduleRootManager = ModuleRootManager.getInstance(module)
val contentRoots = moduleRootManager.contentRoots.map { it.path }

val compilerModuleExtension = CompilerModuleExtension.getInstance(module)
val outputPath = compilerModuleExtension?.compilerOutputPath

// Note that the JavaSourceRootType.SOURCE also includes Kotlin source folders
// Only include folder if is is not in the output path
val javaSourcePaths = moduleRootManager.getSourceRoots(JavaSourceRootType.SOURCE).map({ it.path })
val javaTestSourcePaths =
moduleRootManager.getSourceRoots(JavaSourceRootType.TEST_SOURCE).map({ it.path })

val resourcePaths = moduleRootManager.getSourceRoots(JavaResourceRootType.RESOURCE).map { it.path }
val testResourcePaths =
moduleRootManager.getSourceRoots(JavaResourceRootType.TEST_RESOURCE).map { it.path }

modules.add(
ModuleInfo(
module.name,
contentRoots.toTypedArray(),
javaSourcePaths.toTypedArray(),
javaTestSourcePaths.toTypedArray(),
resourcePaths.toTypedArray(),
testResourcePaths.toTypedArray(),
outputPath?.path))
}
return modules
}

/**
* Returns a map of all base directories related to the project. This includes any external module and the main
* project base folders. For the main project, the base directory is the project root and the module name is
* "base-module".
*/
fun getBaseDirectoriesForProject(project: Project): Map<String, List<String>> {
MarcinVaadin marked this conversation as resolved.
Show resolved Hide resolved

val moduleBaseDirectories = mutableMapOf<String, List<String>>()
getModulesInfo(project).forEach { module ->
moduleBaseDirectories[module.name] = module.contentRoots.toList()
}
moduleBaseDirectories["base-module"] = listOf(project.basePath) as List<String>
MarcinVaadin marked this conversation as resolved.
Show resolved Hide resolved
return moduleBaseDirectories
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.findDocument
import com.intellij.psi.PsiDocumentManager
import com.vaadin.plugin.copilot.CopilotPluginUtil
import com.vaadin.plugin.copilot.CopilotPluginUtil.Companion.getBaseDirectoriesForProject
import com.vaadin.plugin.copilot.service.CopilotUndoManager
import io.netty.handler.codec.http.HttpResponseStatus
import java.io.File
Expand Down Expand Up @@ -45,7 +46,9 @@ abstract class AbstractHandler(val project: Project) : Handler {
fun isFileInsideProject(project: Project, file: File): Boolean {
if (file.exists()) {
val path = file.toPath()
return path.toRealPath().startsWith(project.basePath!!)
MarcinVaadin marked this conversation as resolved.
Show resolved Hide resolved
return getBaseDirectoriesForProject(project).values.flatten().any { baseDirectory ->
path.startsWith(baseDirectory)
}
} else {
// New file
return isFileInsideProject(project, file.parentFile)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,58 +1,16 @@
package com.vaadin.plugin.copilot.handler

import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir
import com.intellij.openapi.roots.CompilerModuleExtension
import com.intellij.openapi.roots.ModuleRootManager
import com.vaadin.plugin.copilot.CopilotPluginUtil
import com.vaadin.plugin.copilot.CopilotPluginUtil.Companion.getModulesInfo
import io.netty.handler.codec.http.HttpResponseStatus
import org.jetbrains.jps.model.java.JavaResourceRootType
import org.jetbrains.jps.model.java.JavaSourceRootType

class GetModulePathsHandler(project: Project) : AbstractHandler(project) {

@JvmRecord data class ProjectInfo(val basePath: String?, val modules: List<ModuleInfo>)

@JvmRecord
data class ModuleInfo(
val name: String,
val contentRoots: Array<String>,
val javaSourcePaths: Array<String>,
val javaTestSourcePaths: Array<String>,
val resourcePaths: Array<String>,
val testResourcePaths: Array<String>,
val outputPath: String?
)

override fun run(): HandlerResponse {
val modules = ArrayList<ModuleInfo>()
ModuleManager.getInstance(project).modules.forEach { module: Module ->
val moduleRootManager = ModuleRootManager.getInstance(module)
val contentRoots = moduleRootManager.contentRoots.map { it.path }

val compilerModuleExtension = CompilerModuleExtension.getInstance(module)
val outputPath = compilerModuleExtension?.compilerOutputPath

// Note that the JavaSourceRootType.SOURCE also includes Kotlin source folders
// Only include folder if is is not in the output path
val javaSourcePaths = moduleRootManager.getSourceRoots(JavaSourceRootType.SOURCE).map({ it.path })
val javaTestSourcePaths = moduleRootManager.getSourceRoots(JavaSourceRootType.TEST_SOURCE).map({ it.path })

val resourcePaths = moduleRootManager.getSourceRoots(JavaResourceRootType.RESOURCE).map { it.path }
val testResourcePaths = moduleRootManager.getSourceRoots(JavaResourceRootType.TEST_RESOURCE).map { it.path }

modules.add(
ModuleInfo(
module.name,
contentRoots.toTypedArray(),
javaSourcePaths.toTypedArray(),
javaTestSourcePaths.toTypedArray(),
resourcePaths.toTypedArray(),
testResourcePaths.toTypedArray(),
outputPath?.path))
}
val projectInfo = ProjectInfo(project.guessProjectDir()?.path, modules)
val modules = getModulesInfo(project)
val projectInfo = CopilotPluginUtil.ProjectInfo(project.guessProjectDir()?.path, modules)
val data = mapOf("project" to projectInfo)
return HandlerResponse(HttpResponseStatus.OK, data)
}
Expand Down