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

Revive headless mode for IntelliJ 2024.3 [DO NOT REVIEW] #420

Draft
wants to merge 6 commits into
base: headless-mode
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ lib/evosuite-*.jar
lib/JUnitRunner.jar
**/evosuite-tests/
*.DS_Store
.intellijPlatform

# Test projects
src/test/resources/project/.idea/
Expand Down
41 changes: 39 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ plugins {
// Gradle Qodana Plugin
// id("org.jetbrains.qodana") version "0.1.13"
}

group = properties("pluginGroup")
version = properties("pluginVersion")

Expand All @@ -46,6 +47,8 @@ repositories {
// See https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-repositories-extension.html#default-repositories
intellijPlatform {
defaultRepositories()
intellijDependencies()
localPlatformArtifacts()
Comment on lines +50 to +51
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps, it is not needed.

}
maven("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies")
maven("https://www.jetbrains.com/intellij-repository/snapshots")
Expand All @@ -66,6 +69,7 @@ repositories {
}

if (spaceCredentialsProvided()) {
println("WIth space creds!")
// Add the new source set
val hasGrazieAccess = sourceSets.create("hasGrazieAccess")
// add output of main source set to new source set class path
Expand Down Expand Up @@ -152,6 +156,8 @@ dependencies {
"hasGrazieAccessCompileOnly"(project(":core"))
}

implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.23")

// https://central.sonatype.com/artifact/io.github.oshai/kotlin-logging-jvm/overview
implementation("io.github.oshai:kotlin-logging-jvm:6.0.3")

Expand Down Expand Up @@ -226,7 +232,7 @@ intellijPlatform {
// See https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-extension.html#intellijPlatform-pluginVerification-ides
pluginVerification {
ides {
recommended()
// recommended()
select {
types = listOf(IntelliJPlatformType.IntellijIdeaUltimate)
channels = listOf(ProductRelease.Channel.RELEASE)
Expand Down Expand Up @@ -256,7 +262,6 @@ changelog {
// }

tasks {

compileKotlin {
dependsOn("updateEvosuite")
dependsOn("copyJUnitRunnerLib")
Expand Down Expand Up @@ -391,6 +396,7 @@ abstract class UpdateEvoSuite : DefaultTask() {
tasks.register<UpdateEvoSuite>("updateEvosuite") {
evoSuiteVersion = properties("evosuiteVersion")
}

/**
* Copies the JUnitRunner.jar file to the lib directory of the project.
* This task depends on the "JUnitRunner" module being built beforehand.
Expand All @@ -416,6 +422,37 @@ tasks.register<Copy>("copyJUnitRunnerLib") {
*/
fun String?.orDefault(default: String): String = this ?: default


val headless2 by intellijPlatformTesting.runIde.registering {
type = IntelliJPlatformType.IntellijIdeaCommunity
version = properties("platformVersion")

val root: String? by project
val file: String? by project
val cut: String? by project
val cp: String? by project
val junitv: String? by project
val llm: String? by project
val token: String? by project
val prompt: String? by project
val out: String? by project
val enableCoverage: String? by project

task {
jvmArgumentProviders += CommandLineArgumentProvider {
listOf(
"-Xmx16G",
"-Djava.awt.headless=true",
"--add-exports",
"java.base/jdk.internal.vm=ALL-UNNAMED",
"-Didea.system.path",
)
}

args = listOfNotNull("testspark", root, file, cut, cp, junitv, llm, token, prompt, out, enableCoverage.orDefault("false"))
}
}

/**
* This code sets up a Gradle task for running the plugin in headless mode
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class KotlinTestCompiler(
libPaths: List<String>,
junitLibPaths: List<String>,
kotlinSDKHomeDirectory: String,
private val javaHomeDirectoryPath: String,
) : TestCompiler(libPaths, junitLibPaths) {
private val logger = KotlinLogging.logger { this::class.java }
private val kotlinc: String
Expand All @@ -32,7 +33,6 @@ class KotlinTestCompiler(
* as failed compilation because `kotlinc` will complain about
* `java` command missing in PATH.
*
* TODO(vartiukhov): find a way to locate `java` on Windows
*/
val isCompilerName = if (DataFilesUtil.isWindows()) {
it.name.equals("kotlinc")
Expand All @@ -55,9 +55,14 @@ class KotlinTestCompiler(
logger.info { "[KotlinTestCompiler] Compiling ${path.substringAfterLast('/')}" }

val classPaths = "\"${getClassPaths(projectBuildPath)}\""

// We need to ensure JAVA is in the path variable
// See: https://github.com/JetBrains-Research/TestSpark/issues/410
val setJavaPathOnWindows = "set PATH=%PATH%;$javaHomeDirectoryPath\\bin\\&&"

// Compile file
// See: https://github.com/JetBrains-Research/TestSpark/issues/402
val kotlinc = if (DataFilesUtil.isWindows()) "\"$kotlinc\"" else "'$kotlinc'"
val kotlinc = if (DataFilesUtil.isWindows()) "$setJavaPathOnWindows\"$kotlinc\"" else "'$kotlinc'"

val executionResult = CommandLineRunner.run(
arrayListOf(
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@ import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.ex.ApplicationManagerEx
import com.intellij.openapi.progress.util.ProgressIndicatorBase
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.openapi.startup.StartupManager
import kotlinx.coroutines.runBlocking
import org.jetbrains.idea.maven.MavenCommandLineInspectionProjectConfigurator
import org.jetbrains.idea.maven.project.MavenProjectsManager
import org.jetbrains.plugins.gradle.GradleCommandLineProjectConfigurator
import org.slf4j.LoggerFactory
import java.nio.file.Path
import java.util.function.Predicate
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

class ProjectConfiguratorException : Exception {
Expand Down Expand Up @@ -160,15 +163,17 @@ object ProjectApplicationUtils {
logger.info("Closing project $project...")
ApplicationManager.getApplication().assertIsNonDispatchThread()
// ToDo: move headless mode to another branch
// ApplicationManager.getApplication().invokeAndWait {
// ProjectManagerEx.getInstanceEx().forceCloseProject(project)
// }
ApplicationManager.getApplication().invokeAndWait {
ProjectManager.getInstance().closeAndDispose(project)
// TODO: what is ProjectManagerEx?
// ProjectManagerEx.getInstanceEx().forceCloseProject(project)
}
}

private suspend fun waitAllStartupActivitiesPassed(project: Project): Unit = suspendCoroutine {
logger.info("Waiting all startup activities passed $project...")
// ToDo: move headless mode to another branch
// StartupManager.getInstance(project).runAfterOpened { it.resume(Unit) }
StartupManager.getInstance(project).runAfterOpened { it.resume(Unit) }
waitForInvokeLaterActivities()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,33 +24,43 @@ object TestCompilerFactory {

// TODO add the warning window that for Java we always need the javaHomeDirectoryPath
return when (language) {
SupportedLanguage.Java -> createJavaCompiler(project, libraryPaths, junitLibraryPaths, javaHomeDirectory)
SupportedLanguage.Kotlin -> createKotlinCompiler(libraryPaths, junitLibraryPaths)
SupportedLanguage.Java -> {
val javaSDKHomePath = findJavaSDKHomePath(javaHomeDirectory, project)
JavaTestCompiler(libraryPaths, junitLibraryPaths, javaSDKHomePath)
}
SupportedLanguage.Kotlin -> {
// Kotlinc relies on java to compile kotlin files.
val javaSDKHomePath = findJavaSDKHomePath(javaHomeDirectory, project)
// kotlinc should be under `[kotlinSDKHomeDirectory]/bin/kotlinc`
val kotlinSDKHomeDirectory = KotlinPluginLayout.kotlinc.absolutePath
KotlinTestCompiler(libraryPaths, junitLibraryPaths, kotlinSDKHomeDirectory, javaSDKHomePath)
}
}
}

private fun createJavaCompiler(
/**
* Finds the home path of the Java SDK.
*
* @param javaHomeDirectory The directory where Java SDK is installed. If null, the project's configured SDK path is used.
* @param project The project for which the Java SDK home path is being determined.
* @return The home path of the Java SDK.
* @throws JavaSDKMissingException If no Java SDK is configured for the project.
*/
private fun findJavaSDKHomePath(
javaHomeDirectory: String?,
project: Project,
libraryPaths: List<String>,
junitLibraryPaths: List<String>,
javaHomeDirectory: String? = null,
): JavaTestCompiler {
val javaSDKHomePath = javaHomeDirectory
?: ProjectRootManager.getInstance(project).projectSdk?.homeDirectory?.path
): String {
val javaSDKHomePath =
javaHomeDirectory
?: ProjectRootManager
.getInstance(project)
.projectSdk
?.homeDirectory
?.path

if (javaSDKHomePath == null) {
throw JavaSDKMissingException(LLMMessagesBundle.get("javaSdkNotConfigured"))
}

return JavaTestCompiler(libraryPaths, junitLibraryPaths, javaSDKHomePath)
}

private fun createKotlinCompiler(
libraryPaths: List<String>,
junitLibraryPaths: List<String>,
): KotlinTestCompiler {
// kotlinc should be under `[kotlinSDKHomeDirectory]/bin/kotlinc`
val kotlinSDKHomeDirectory = KotlinPluginLayout.kotlinc.absolutePath
return KotlinTestCompiler(libraryPaths, junitLibraryPaths, kotlinSDKHomeDirectory)
return javaSDKHomePath
}
}
Loading