mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
[Java] IDEA-385244 Support javac standard options completion in terminal
GitOrigin-RevId: b167cb6dbf75bb5431533356620b9e1d2061f938
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f2a9c94d66
commit
f8df55e707
@@ -8,6 +8,7 @@
|
||||
</dependencies>
|
||||
<extensions defaultExtensionNs="org.jetbrains.plugins.terminal">
|
||||
<commandSpecsProvider implementation="com.intellij.java.terminal.JavaShellCommandSpecsProvider"/>
|
||||
<commandSpecsProvider implementation="com.intellij.java.terminal.JavacShellCommandSpecsProvider"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij.openapi.projectRoots">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# "java" command
|
||||
java.command.terminal.description=Runs java.
|
||||
java.command.terminal.help.option.description=Prints the help message to the {0} stream.
|
||||
java.command.terminal.jar.option.description=Launches the main class in a JAR file.
|
||||
@@ -9,4 +10,11 @@ java.command.terminal.enable.preview.option.description=Allows classes to depend
|
||||
java.command.terminal.verbose.option.description=Enables verbose output for the given subsystem.
|
||||
external.java.configuration.run.command=Run ''{0}''\u2026
|
||||
error.stream.name=error
|
||||
output.stream.name=output
|
||||
output.stream.name=output
|
||||
|
||||
# "javac" command
|
||||
java.c.command.terminal.description=Reads Java declarations and compile them into class files.
|
||||
java.c.command.terminal.classpath.option.description=Specifies where to find user class files, and (optionally) annotation processors and source files.
|
||||
java.c.command.terminal.annotation.processing.option.description=Specifies options to pass to annotation processors.
|
||||
java.c.command.terminal.extra.options.command.description=Prints the help for extra options.
|
||||
|
||||
|
||||
@@ -15,10 +15,9 @@ class JavaShellCommandContext private constructor(private val propertyMap: Map<S
|
||||
|
||||
companion object {
|
||||
private const val PROPERTY_SEPARATOR = " = "
|
||||
const val JAVA_SHOW_SETTINGS_PROPERTIES_VERSION_COMMAND: String = "java -XshowSettings:properties -version"
|
||||
|
||||
suspend fun create(context: ShellRuntimeContext): JavaShellCommandContext? {
|
||||
val result = context.runShellCommand(JAVA_SHOW_SETTINGS_PROPERTIES_VERSION_COMMAND)
|
||||
val result = context.createProcessBuilder("java").args("-XshowSettings:properties", "-version").execute()
|
||||
if (result.exitCode != 0) return null
|
||||
val propertyMap = result.output.split('\n').dropLastWhile { it.isBlank() }.asSequence().map { it.trim() }
|
||||
.filter { it.contains(PROPERTY_SEPARATOR) }.mapNotNull {
|
||||
|
||||
+12
-38
@@ -1,9 +1,11 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.terminal
|
||||
|
||||
import com.intellij.execution.vmOptions.VMOptionKind
|
||||
import com.intellij.execution.vmOptions.VMOptionVariant
|
||||
import com.intellij.execution.vmOptions.VMOptionsService
|
||||
import com.intellij.java.terminal.JavaShellCommandUtils.CLASSPATH_ARGUMENT_NAME
|
||||
import com.intellij.java.terminal.JavaShellCommandUtils.UIOptionInfo
|
||||
import com.intellij.java.terminal.JavaShellCommandUtils.addClassPathOption
|
||||
import com.intellij.java.terminal.JavaShellCommandUtils.addOptionsFromData
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.terminal.completion.spec.ShellCommandParserOptions
|
||||
import com.intellij.terminal.completion.spec.ShellCommandSpec
|
||||
@@ -38,6 +40,7 @@ class JavaShellCommandSpecsProvider : ShellCommandSpecsProvider {
|
||||
}
|
||||
|
||||
val errorStreamName: @Nls String = JavaTerminalBundle.message("error.stream.name")
|
||||
|
||||
description(JavaTerminalBundle.message("java.command.terminal.description"))
|
||||
option("-?", "-help", "-h") {
|
||||
exclusiveOn(listOf("--help"))
|
||||
@@ -50,22 +53,19 @@ class JavaShellCommandSpecsProvider : ShellCommandSpecsProvider {
|
||||
}
|
||||
description(JavaTerminalBundle.message("java.command.terminal.jar.option.description"))
|
||||
}
|
||||
|
||||
option("-version") {
|
||||
exclusiveOn(listOf("--version"))
|
||||
description(JavaTerminalBundle.message("java.command.terminal.version.option.description", errorStreamName))
|
||||
}
|
||||
option("-classpath", "-cp") {
|
||||
exclusiveOn(listOf("--class-path"))
|
||||
description(JavaTerminalBundle.message("java.command.terminal.classpath.option.description"))
|
||||
argument {
|
||||
suggestions(JavaShellCommandUtils.classpathSuggestionsGenerator())
|
||||
displayName(CLASSPATH_ARGUMENT_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
option("-showversion") {
|
||||
exclusiveOn(listOf("--show-version"))
|
||||
description(JavaTerminalBundle.message("java.command.terminal.show.version.option.description", errorStreamName))
|
||||
}
|
||||
|
||||
addClassPathOption()
|
||||
|
||||
argument {
|
||||
displayName(MAIN_CLASS_ARGUMENT_NAME)
|
||||
suggestions(ShellDataGenerators.fileSuggestionsGenerator())
|
||||
@@ -78,29 +78,7 @@ class JavaShellCommandSpecsProvider : ShellCommandSpecsProvider {
|
||||
if (path == null) return@withContext null
|
||||
optionsService.getOrComputeOptionsForJdk(path).get()
|
||||
} ?: optionsService.getStandardOptions()
|
||||
jdkOptionsData.options
|
||||
.filter { (it.kind == VMOptionKind.Standard || it.kind == VMOptionKind.Product) && (it.variant != VMOptionVariant.XX)}
|
||||
.toList()
|
||||
.forEach {
|
||||
val optionName = it.optionName
|
||||
val presentableName = "${it.variant.prefix()}$optionName"
|
||||
option(presentableName) {
|
||||
val optionDescription = it.doc
|
||||
if (optionDescription == null) return@option
|
||||
description(optionDescription)
|
||||
|
||||
val info = OPTION_UI_INFO_MAP[presentableName] ?: DEFAULT_UI_OPTION_INSTANCE
|
||||
repeatTimes(info.repeatTimes)
|
||||
info.separator?.let { separator(it) }
|
||||
val argumentName = info.argumentName
|
||||
if (argumentName != null) {
|
||||
argument {
|
||||
if (info.isArgumentOptional) optional()
|
||||
displayName(argumentName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
addOptionsFromData(jdkOptionsData, OPTION_UI_INFO_MAP)
|
||||
}
|
||||
|
||||
private fun ShellChildOptionsContext.addOptionsFromJava11() {
|
||||
@@ -166,7 +144,6 @@ private const val MAIN_CLASS_ARGUMENT_NAME: @NlsSafe String = "mainclass"
|
||||
private const val JAR_FILE_ARGUMENT_NAME: @NlsSafe String = "jar file"
|
||||
private const val CLASS_GC_GNI_ARGUMENT_NAME: @NlsSafe String = "class|gc|gni"
|
||||
private const val CLASS_GC_GNI_MODULE_ARGUMENT_NAME: @NlsSafe String = "$CLASS_GC_GNI_ARGUMENT_NAME|<module>"
|
||||
private val CLASSPATH_ARGUMENT_NAME: @NlsSafe String = "filepath[${JavaShellCommandUtils.getClassPathSeparator()}filepath]"
|
||||
|
||||
private val OPTION_UI_INFO_MAP = mapOf(
|
||||
"-Xms" to UIOptionInfo(separator = "", argumentName = SIZE_ARGUMENT_NAME),
|
||||
@@ -195,7 +172,4 @@ private val OPTION_UI_INFO_MAP = mapOf(
|
||||
"-D" to UIOptionInfo(separator = "", repeatTimes = 0, argumentName = "<name>=<value>"),
|
||||
"-XX:" to UIOptionInfo(repeatTimes = 0),
|
||||
"--source" to UIOptionInfo(argumentName = "version")
|
||||
)
|
||||
|
||||
private data class UIOptionInfo(val separator: String? = null, @NlsSafe val argumentName: String? = null, val repeatTimes: Int = 1, val isArgumentOptional: Boolean = false)
|
||||
private val DEFAULT_UI_OPTION_INSTANCE = UIOptionInfo()
|
||||
)
|
||||
@@ -1,16 +1,65 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.terminal
|
||||
|
||||
import com.intellij.execution.vmOptions.JdkOptionsData
|
||||
import com.intellij.execution.vmOptions.VMOptionKind
|
||||
import com.intellij.execution.vmOptions.VMOptionVariant
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.terminal.completion.spec.ShellCompletionSuggestion
|
||||
import com.intellij.terminal.completion.spec.ShellRuntimeContext
|
||||
import com.intellij.terminal.completion.spec.ShellRuntimeDataGenerator
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.ShellDataGenerators
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.ShellRuntimeDataGenerator
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.dsl.ShellChildOptionsContext
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.dsl.ShellCommandContext
|
||||
|
||||
object JavaShellCommandUtils {
|
||||
internal val DEFAULT_UI_OPTION_INSTANCE = UIOptionInfo()
|
||||
private const val SEPARATOR_NOT_FOUND_INDEX = -1
|
||||
|
||||
internal fun ShellChildOptionsContext.addOptionsFromData(jdkOptionsData: JdkOptionsData, uiMap: Map<String, UIOptionInfo>) {
|
||||
jdkOptionsData.options
|
||||
.filter { (it.kind == VMOptionKind.Standard || it.kind == VMOptionKind.Product) && (it.variant != VMOptionVariant.XX)}
|
||||
.toList()
|
||||
.forEach {
|
||||
val optionName = it.optionName
|
||||
val presentableName = "${it.variant.prefix()}$optionName"
|
||||
option(presentableName) {
|
||||
val optionDescription = it.doc
|
||||
if (optionDescription != null) {
|
||||
description(optionDescription)
|
||||
}
|
||||
|
||||
val info = uiMap[presentableName] ?: DEFAULT_UI_OPTION_INSTANCE
|
||||
repeatTimes(info.repeatTimes)
|
||||
info.separator?.let { separator(it) }
|
||||
val argumentName = info.argumentName
|
||||
if (argumentName != null) {
|
||||
argument {
|
||||
if (info.isArgumentOptional) optional()
|
||||
displayName(argumentName)
|
||||
|
||||
if (info.suggestionsGenerator != null) suggestions(info.suggestionsGenerator)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ShellCommandContext.addClassPathOption() {
|
||||
option("-classpath", "-cp") {
|
||||
exclusiveOn(listOf("--class-path"))
|
||||
description(JavaTerminalBundle.message("java.command.terminal.classpath.option.description"))
|
||||
argument {
|
||||
suggestions(classpathSuggestionsGenerator())
|
||||
displayName(CLASSPATH_ARGUMENT_NAME)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal val CLASSPATH_ARGUMENT_NAME: @NlsSafe String = "filepath[${getClassPathSeparator()}filepath]"
|
||||
|
||||
fun getClassPathSeparator(): String = when {
|
||||
SystemInfo.isWindows -> ";"
|
||||
else -> ":"
|
||||
@@ -42,5 +91,13 @@ object JavaShellCommandUtils {
|
||||
}
|
||||
}
|
||||
|
||||
internal data class UIOptionInfo(
|
||||
val separator: String? = null,
|
||||
@NlsSafe val argumentName: String? = null,
|
||||
val repeatTimes: Int = 1,
|
||||
val isArgumentOptional: Boolean = false,
|
||||
val suggestionsGenerator: ShellRuntimeDataGenerator<List<ShellCompletionSuggestion>>? = null,
|
||||
)
|
||||
|
||||
private data class PathInfo(val typedPrefix: String, val replacementIndexDelta: Int = 0)
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.terminal
|
||||
|
||||
import com.intellij.execution.vmOptions.VMOptionsService
|
||||
import com.intellij.java.terminal.JavaShellCommandUtils.UIOptionInfo
|
||||
import com.intellij.java.terminal.JavaShellCommandUtils.addClassPathOption
|
||||
import com.intellij.java.terminal.JavaShellCommandUtils.addOptionsFromData
|
||||
import com.intellij.java.terminal.JavaShellCommandUtils.classpathSuggestionsGenerator
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.terminal.completion.spec.ShellCommandParserOptions
|
||||
import com.intellij.terminal.completion.spec.ShellCommandSpec
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.*
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.dsl.ShellChildOptionsContext
|
||||
|
||||
internal class JavacShellCommandSpecsProvider : ShellCommandSpecsProvider {
|
||||
override fun getCommandSpecs(): List<ShellCommandSpecInfo> {
|
||||
return listOf(ShellCommandSpecInfo.create(getSpecs(), ShellCommandSpecConflictStrategy.REPLACE))
|
||||
}
|
||||
|
||||
private fun getSpecs(): ShellCommandSpec = ShellCommandSpec("javac") {
|
||||
parserOptions(
|
||||
ShellCommandParserOptions.builder()
|
||||
.flagsArePosixNonCompliant(true)
|
||||
.optionsMustPrecedeArguments(true)
|
||||
.build()
|
||||
)
|
||||
|
||||
description(JavaTerminalBundle.message("java.c.command.terminal.description"))
|
||||
|
||||
dynamicOptions { terminalContext ->
|
||||
val javaContext = JavaShellCommandContext.create(terminalContext)
|
||||
val path = javaContext?.getJrePath()
|
||||
addJavacOptions(path)
|
||||
}
|
||||
|
||||
|
||||
val streamName: @Nls String = JavaTerminalBundle.message("output.stream.name")
|
||||
|
||||
option("-?", "-help") {
|
||||
exclusiveOn(listOf("--help"))
|
||||
description(JavaTerminalBundle.message("java.command.terminal.help.option.description", streamName))
|
||||
}
|
||||
|
||||
option("-X") {
|
||||
exclusiveOn(listOf("--help-extra"))
|
||||
description(JavaTerminalBundle.message("java.c.command.terminal.extra.options.command.description"))
|
||||
}
|
||||
|
||||
option("-version") {
|
||||
exclusiveOn(listOf("--version"))
|
||||
description(JavaTerminalBundle.message("java.command.terminal.version.option.description", streamName))
|
||||
}
|
||||
|
||||
addClassPathOption()
|
||||
|
||||
argument {
|
||||
displayName(SOURCE_FILE_ARGUMENT_NAME)
|
||||
suggestions(ShellDataGenerators.fileSuggestionsGenerator())
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun ShellChildOptionsContext.addJavacOptions(path: String?) {
|
||||
val optionsService = VMOptionsService.getInstance()
|
||||
val jdkOptionsData = withContext(Dispatchers.IO) {
|
||||
|
||||
if (path == null) return@withContext null
|
||||
optionsService.getOrComputeOptionsForJavac(path).get()
|
||||
} ?: optionsService.getStandardJavacOptions()
|
||||
|
||||
addOptionsFromData(jdkOptionsData, UI_OPTION_INFO_MAP)
|
||||
}
|
||||
}
|
||||
|
||||
private const val SOURCE_FILE_ARGUMENT_NAME: @NlsSafe String = "[sourcefiles-or-classnames]"
|
||||
private val UI_OPTION_INFO_MAP = mapOf(
|
||||
"-A" to UIOptionInfo(separator = "", argumentName = "key[=value]"),
|
||||
"--add-modules" to UIOptionInfo(argumentName = "module[,module]*"),
|
||||
"--boot-class-path" to UIOptionInfo(argumentName = "path", suggestionsGenerator = classpathSuggestionsGenerator()),
|
||||
"--class-path" to UIOptionInfo(argumentName = "path", suggestionsGenerator = classpathSuggestionsGenerator()),
|
||||
"-d" to UIOptionInfo(argumentName = "directory", suggestionsGenerator = ShellDataGenerators.fileSuggestionsGenerator(true)),
|
||||
"-encoding" to UIOptionInfo(argumentName = "encoding"),
|
||||
"-endorseddirs" to UIOptionInfo(argumentName = "dirs"),
|
||||
"-extdirs" to UIOptionInfo(argumentName = "directories"),
|
||||
"-g:" to UIOptionInfo(separator = "", argumentName = "none|lines|vars"),
|
||||
"-h" to UIOptionInfo(argumentName = "directory", suggestionsGenerator = ShellDataGenerators.fileSuggestionsGenerator(true)),
|
||||
"-implicit:" to UIOptionInfo(separator = "", argumentName = "none|class", isArgumentOptional = true),
|
||||
"-J" to UIOptionInfo(separator = "", argumentName = "option"),
|
||||
"--limit-modules" to UIOptionInfo(argumentName = "module[,module]*"),
|
||||
"--module" to UIOptionInfo(argumentName = "module-name"),
|
||||
"--module-path" to UIOptionInfo(argumentName = "path"),
|
||||
"--module-source-path" to UIOptionInfo(argumentName = "path"),
|
||||
"--module-version" to UIOptionInfo(argumentName = "version"),
|
||||
"-proc:" to UIOptionInfo(separator = "", argumentName = "none|only|full", isArgumentOptional = true),
|
||||
"-processor" to UIOptionInfo(argumentName = "class[,class]*"),
|
||||
"--processor-module-path" to UIOptionInfo(argumentName = "path", suggestionsGenerator = ShellDataGenerators.fileSuggestionsGenerator()),
|
||||
"--processor-path" to UIOptionInfo(argumentName = "path" , suggestionsGenerator = ShellDataGenerators.fileSuggestionsGenerator()),
|
||||
"-profile" to UIOptionInfo(argumentName = "profile"),
|
||||
"--release" to UIOptionInfo(argumentName = "release"),
|
||||
"-s" to UIOptionInfo(argumentName = "directory", suggestionsGenerator = ShellDataGenerators.fileSuggestionsGenerator(true)),
|
||||
"--source" to UIOptionInfo(argumentName = "release"),
|
||||
"--source-path" to UIOptionInfo(argumentName = "path", suggestionsGenerator = ShellDataGenerators.fileSuggestionsGenerator()),
|
||||
"--system" to UIOptionInfo(argumentName = "jdk"),
|
||||
"--target" to UIOptionInfo(argumentName = "release"),
|
||||
"--upgrade-module-path" to UIOptionInfo(argumentName = "path", suggestionsGenerator = ShellDataGenerators.fileSuggestionsGenerator()),
|
||||
)
|
||||
+10
-67
@@ -1,28 +1,20 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.terminal.completion
|
||||
|
||||
import com.intellij.execution.vmOptions.*
|
||||
import com.intellij.java.terminal.JavaShellCommandContext
|
||||
import com.intellij.java.terminal.JavaShellCommandUtils
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.terminal.completion.spec.ShellCommandResult
|
||||
import com.intellij.terminal.completion.spec.ShellCompletionSuggestion
|
||||
import com.intellij.terminal.completion.spec.ShellFileInfo
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import com.intellij.testFramework.fixtures.BasePlatformTestCase
|
||||
import com.intellij.testFramework.replaceService
|
||||
import junit.framework.TestCase
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.jetbrains.plugins.terminal.TerminalEngine
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.ShellFileSystemSupport
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.ShellDataGeneratorProcessExecutor
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.ShellDataGeneratorProcessOptions
|
||||
import org.jetbrains.plugins.terminal.testFramework.completion.ShellCompletionTestFixture
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
@RunWith(Parameterized::class)
|
||||
class JavaShellCommandSpecsProviderTest(private val engine: TerminalEngine) : BasePlatformTestCase() {
|
||||
internal class JavaShellCommandSpecsProviderTest(engine: TerminalEngine) : JdkCommandsShellSpecsProviderTestBase(engine) {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@@ -31,7 +23,13 @@ class JavaShellCommandSpecsProviderTest(private val engine: TerminalEngine) : Ba
|
||||
|
||||
@Test
|
||||
fun `default options are present`() = runBlocking {
|
||||
val fixture = ShellCompletionTestFixture.builder(project).mockShellCommandResults { _ ->
|
||||
val fixture = ShellCompletionTestFixture.builder(project)
|
||||
.mockProcessesExecutor(object : ShellDataGeneratorProcessExecutor {
|
||||
override suspend fun executeProcess(options: ShellDataGeneratorProcessOptions): ShellCommandResult {
|
||||
return ShellCommandResult.create("", exitCode = 1)
|
||||
}
|
||||
})
|
||||
.mockShellCommandResults { _ ->
|
||||
return@mockShellCommandResults ShellCommandResult.create("", exitCode = 1)
|
||||
}.build()
|
||||
assertSameElements(fixture.getCompletionNames(), listOf("-ea", "-enableassertions", "-da", "-disableassertions", "-esa", "-enablesystemassertions",
|
||||
@@ -101,7 +99,6 @@ class JavaShellCommandSpecsProviderTest(private val engine: TerminalEngine) : Ba
|
||||
assertTrue(completion.all { it.prefixReplacementIndex == argument.length - 1 })
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `classpath suggestion generator simple`() = runBlocking {
|
||||
val fixture = createFixture()
|
||||
@@ -129,58 +126,4 @@ class JavaShellCommandSpecsProviderTest(private val engine: TerminalEngine) : Ba
|
||||
assertSameElements(completion.map { it.name }, listOf("file1.jar", "file2.jar", "dir1/"))
|
||||
assertTrue(completion.all { it.prefixReplacementIndex == argument.length})
|
||||
}
|
||||
|
||||
private fun createFixture(javaVersion: Int = 11): ShellCompletionTestFixture {
|
||||
ApplicationManager.getApplication().replaceService(VMOptionsService::class.java, MockVMOptionsService(), testRootDisposable)
|
||||
val fixture = ShellCompletionTestFixture.builder(project)
|
||||
.setIsReworkedTerminal(engine == TerminalEngine.REWORKED)
|
||||
.mockShellCommandResults { command ->
|
||||
if (command == JavaShellCommandContext.JAVA_SHOW_SETTINGS_PROPERTIES_VERSION_COMMAND) {
|
||||
return@mockShellCommandResults ShellCommandResult.create("java.home = /jre/home\njava.version = ${javaVersion}", exitCode = 0)
|
||||
}
|
||||
|
||||
if (command.startsWith("__jetbrains_intellij_get_directory_files")) {
|
||||
return@mockShellCommandResults ShellCommandResult.create("file1.jar\nfile2.jar\ndir1/", exitCode = 0)
|
||||
}
|
||||
|
||||
return@mockShellCommandResults ShellCommandResult.create("", exitCode = 1)
|
||||
}
|
||||
.mockFileSystemSupport(object : ShellFileSystemSupport {
|
||||
override suspend fun listDirectoryFiles(path: String): List<ShellFileInfo> {
|
||||
return listOf(
|
||||
ShellFileInfo.create("file1.jar", ShellFileInfo.Type.FILE),
|
||||
ShellFileInfo.create("file2.jar", ShellFileInfo.Type.FILE),
|
||||
ShellFileInfo.create("dir1", ShellFileInfo.Type.DIRECTORY),
|
||||
)
|
||||
}
|
||||
})
|
||||
.build()
|
||||
return fixture
|
||||
}
|
||||
|
||||
private suspend fun ShellCompletionTestFixture.getCompletionNames(command: String = "java "): List<String> {
|
||||
val actual: List<ShellCompletionSuggestion> = getCompletions(command)
|
||||
return actual.map { it.name }
|
||||
}
|
||||
|
||||
private class MockVMOptionsService : VMOptionsService {
|
||||
override fun getOrComputeOptionsForJdk(javaHome: String): CompletableFuture<JdkOptionsData> {
|
||||
TestCase.assertEquals("/jre/home", javaHome)
|
||||
return CompletableFuture.completedFuture(
|
||||
JdkOptionsData(
|
||||
listOf(
|
||||
VMOption("settings", null, null, VMOptionKind.Product, null, VMOptionVariant.X),
|
||||
VMOption("lint", null, null, VMOptionKind.Standard, null, VMOptionVariant.X),
|
||||
VMOption("experiment", null, null, VMOptionKind.Experimental, null, VMOptionVariant.X),
|
||||
VMOption("diagnose", null, null, VMOptionKind.Diagnostic, null, VMOptionVariant.X),
|
||||
VMOption("advanced", null, null, VMOptionKind.Product, null, VMOptionVariant.XX),
|
||||
VMOption("add-opens", null, null, VMOptionKind.Product, null, VMOptionVariant.DASH_DASH),
|
||||
VMOption("add-exports", null, null, VMOptionKind.Standard, null, VMOptionVariant.DASH_DASH),
|
||||
VMOption("add-experiment-exports", null, null, VMOptionKind.Experimental, null, VMOptionVariant.DASH_DASH),
|
||||
VMOption("add-diagnostic-exports", null, null, VMOptionKind.Experimental, null, VMOptionVariant.DASH_DASH),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.terminal.completion
|
||||
|
||||
import com.intellij.java.terminal.JavaShellCommandUtils
|
||||
import com.intellij.terminal.completion.spec.ShellCommandResult
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.jetbrains.plugins.terminal.TerminalEngine
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.ShellDataGeneratorProcessExecutor
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.ShellDataGeneratorProcessOptions
|
||||
import org.jetbrains.plugins.terminal.testFramework.completion.ShellCompletionTestFixture
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
@RunWith(Parameterized::class)
|
||||
internal class JavacShellCommandSpecsProviderTest(engine: TerminalEngine) : JdkCommandsShellSpecsProviderTestBase(engine) {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
fun engine(): List<TerminalEngine> = listOf(TerminalEngine.REWORKED, TerminalEngine.NEW_TERMINAL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `default options are present`() = runBlocking {
|
||||
val fixture = ShellCompletionTestFixture.builder(project)
|
||||
.mockProcessesExecutor(object : ShellDataGeneratorProcessExecutor {
|
||||
override suspend fun executeProcess(options: ShellDataGeneratorProcessOptions): ShellCommandResult {
|
||||
return ShellCommandResult.create("", exitCode = 1)
|
||||
}
|
||||
})
|
||||
.mockShellCommandResults { _ ->
|
||||
return@mockShellCommandResults ShellCommandResult.create("", exitCode = 1)
|
||||
}.build()
|
||||
assertSameElements(fixture.getCompletionNames("javac "), listOf(
|
||||
"-A", "-g", "-g:", "-g:none", "-h", "-J", "-d", "-nowarn", "-parameters", "-processor",
|
||||
"-profile", "-s", "-verbose", "-Werror", "-proc:", "-implicit:",
|
||||
"-encoding", "-endorseddirs", "-extdirs", "-cp", "-classpath", "-?", "-help", "-X", "-version"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `double dash options are present`() = runBlocking {
|
||||
val fixture = createFixture()
|
||||
UsefulTestCase.assertContainsElements(fixture.getCompletionNames("javac "), listOf("--enable-preview", "--release", "--source", "--target"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `classpath suggestion generator`() = runBlocking {
|
||||
val separator = JavaShellCommandUtils.getClassPathSeparator()
|
||||
val fixture = createFixture()
|
||||
val argument = "file1.jar$separator"
|
||||
val completion = fixture.getCompletions("javac -cp $argument")
|
||||
assertSameElements(completion.map { it.name }, listOf("file1.jar", "file2.jar", "dir1/"))
|
||||
assertTrue(completion.all { it.prefixReplacementIndex == argument.length })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `boot classpath suggestion generator`() = runBlocking {
|
||||
val separator = JavaShellCommandUtils.getClassPathSeparator()
|
||||
val fixture = createFixture()
|
||||
val argument = "file1.jar$separator"
|
||||
val completion = fixture.getCompletions("javac --boot-class-path $argument")
|
||||
assertSameElements(completion.map { it.name }, listOf("file1.jar", "file2.jar", "dir1/"))
|
||||
assertTrue(completion.all { it.prefixReplacementIndex == argument.length })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.terminal.completion
|
||||
|
||||
import com.intellij.execution.vmOptions.*
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.terminal.completion.spec.ShellCommandResult
|
||||
import com.intellij.terminal.completion.spec.ShellCompletionSuggestion
|
||||
import com.intellij.terminal.completion.spec.ShellFileInfo
|
||||
import com.intellij.testFramework.fixtures.BasePlatformTestCase
|
||||
import com.intellij.testFramework.replaceService
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.plugins.terminal.TerminalEngine
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.ShellDataGeneratorProcessExecutor
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.ShellDataGeneratorProcessOptions
|
||||
import org.jetbrains.plugins.terminal.block.completion.spec.ShellFileSystemSupport
|
||||
import org.jetbrains.plugins.terminal.testFramework.completion.ShellCompletionTestFixture
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
internal abstract class JdkCommandsShellSpecsProviderTestBase(private val engine: TerminalEngine) : BasePlatformTestCase() {
|
||||
protected fun createFixture(javaVersion: Int = 11): ShellCompletionTestFixture {
|
||||
ApplicationManager.getApplication().replaceService(VMOptionsService::class.java, MockVMOptionsService(), testRootDisposable)
|
||||
val fixture = ShellCompletionTestFixture.builder(project)
|
||||
.setIsReworkedTerminal(engine == TerminalEngine.REWORKED)
|
||||
.mockProcessesExecutor(object : ShellDataGeneratorProcessExecutor {
|
||||
override suspend fun executeProcess(options: ShellDataGeneratorProcessOptions): ShellCommandResult {
|
||||
if (options.executable == "java" && options.args == listOf("-XshowSettings:properties", "-version")) {
|
||||
return ShellCommandResult.create("java.home = /jre/home\njava.version = $javaVersion", exitCode = 0)
|
||||
}
|
||||
else if (options.executable == "__jetbrains_intellij_get_directory_files") {
|
||||
return ShellCommandResult.create("file1.jar\nfile2.jar\ndir1/", exitCode = 0)
|
||||
}
|
||||
return ShellCommandResult.create("", exitCode = 1)
|
||||
}
|
||||
})
|
||||
.mockShellCommandResults { command ->
|
||||
if (command.startsWith("__jetbrains_intellij_get_directory_files")) {
|
||||
return@mockShellCommandResults ShellCommandResult.create("file1.jar\nfile2.jar\ndir1/", exitCode = 0)
|
||||
}
|
||||
return@mockShellCommandResults ShellCommandResult.create("", exitCode = 1)
|
||||
}
|
||||
.mockFileSystemSupport(object : ShellFileSystemSupport {
|
||||
override suspend fun listDirectoryFiles(path: String): List<ShellFileInfo> {
|
||||
return listOf(
|
||||
ShellFileInfo.create("file1.jar", ShellFileInfo.Type.FILE),
|
||||
ShellFileInfo.create("file2.jar", ShellFileInfo.Type.FILE),
|
||||
ShellFileInfo.create("dir1", ShellFileInfo.Type.DIRECTORY),
|
||||
)
|
||||
}
|
||||
})
|
||||
.build()
|
||||
return fixture
|
||||
}
|
||||
|
||||
protected suspend fun ShellCompletionTestFixture.getCompletionNames(command: String = "java "): List<String> {
|
||||
val actual: List<ShellCompletionSuggestion> = getCompletions(command)
|
||||
return actual.map { it.name }
|
||||
}
|
||||
|
||||
|
||||
private class MockVMOptionsService : VMOptionsService {
|
||||
override fun getOrComputeOptionsForJdk(javaHome: String): CompletableFuture<JdkOptionsData> {
|
||||
TestCase.assertEquals("/jre/home", javaHome)
|
||||
return CompletableFuture.completedFuture(
|
||||
JdkOptionsData(
|
||||
listOf(
|
||||
VMOption("settings", null, null, VMOptionKind.Product, null, VMOptionVariant.X),
|
||||
VMOption("lint", null, null, VMOptionKind.Standard, null, VMOptionVariant.X),
|
||||
VMOption("experiment", null, null, VMOptionKind.Experimental, null, VMOptionVariant.X),
|
||||
VMOption("diagnose", null, null, VMOptionKind.Diagnostic, null, VMOptionVariant.X),
|
||||
VMOption("advanced", null, null, VMOptionKind.Product, null, VMOptionVariant.XX),
|
||||
VMOption("add-opens", null, null, VMOptionKind.Product, null, VMOptionVariant.DASH_DASH),
|
||||
VMOption("add-exports", null, null, VMOptionKind.Standard, null, VMOptionVariant.DASH_DASH),
|
||||
VMOption("add-experiment-exports", null, null, VMOptionKind.Experimental, null, VMOptionVariant.DASH_DASH),
|
||||
VMOption("add-diagnostic-exports", null, null, VMOptionKind.Experimental, null, VMOptionVariant.DASH_DASH),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun getOrComputeOptionsForJavac(javaHome: String): CompletableFuture<JdkOptionsData> {
|
||||
TestCase.assertEquals("/jre/home", javaHome)
|
||||
return CompletableFuture.completedFuture(
|
||||
JdkOptionsData(
|
||||
listOf(
|
||||
VMOption("boot-class-path", null, null, VMOptionKind.Standard, null, VMOptionVariant.DASH_DASH),
|
||||
VMOption("enable-preview", null, null, VMOptionKind.Standard, null, VMOptionVariant.DASH_DASH),
|
||||
VMOption("release", null, null, VMOptionKind.Standard, null, VMOptionVariant.DASH_DASH),
|
||||
VMOption("source", null, null, VMOptionKind.Standard, null, VMOptionVariant.DASH_DASH),
|
||||
VMOption("target", null, null, VMOptionKind.Standard, null, VMOptionVariant.DASH_DASH),
|
||||
VMOption("experimental", null, null, VMOptionKind.Experimental, null, VMOptionVariant.DASH_DASH),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user