backport: 22.0.0
This commit is contained in:
parent
c209294479
commit
add259d506
33 changed files with 378 additions and 270 deletions
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -17,6 +17,31 @@ Changelog structure reference:
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [22.0.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- LSP
|
||||||
|
- Error/Warning banner at the top of the editor when ZLS is misconfigured/not running
|
||||||
|
- ZLS version indicator in the zig settings
|
||||||
|
|
||||||
|
- Toolchain
|
||||||
|
- More descriptive error messages when toolchain detection fails
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Project
|
||||||
|
- !!BREAKING CHANGE!! Changed file format of zig tasks to store command line arguments as strings instead of string lists.
|
||||||
|
This (and newer) versions of the plugin will automatically upgrade tasks from 21.1.0 and before.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Debugging
|
||||||
|
- Breakpoints could not be placed inside zig code in Android Studio
|
||||||
|
|
||||||
|
- Project
|
||||||
|
- Zig run/debug configuration command line arguments would lose quotes around arguments
|
||||||
|
|
||||||
## [21.1.0]
|
## [21.1.0]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
# Code of Merit
|
|
||||||
|
|
||||||
1. The project creators, lead developers, core team, constitute
|
|
||||||
the managing members of the project and have final say in every decision
|
|
||||||
of the project, technical or otherwise, including overruling previous decisions.
|
|
||||||
There are no limitations to this decisional power.
|
|
||||||
|
|
||||||
2. Contributions are an expected result of your membership on the project.
|
|
||||||
Don't expect others to do your work or help you with your work forever.
|
|
||||||
|
|
||||||
3. All members have the same opportunities to seek any challenge they want
|
|
||||||
within the project.
|
|
||||||
|
|
||||||
4. Authority or position in the project will be proportional
|
|
||||||
to the accrued contribution. Seniority must be earned.
|
|
||||||
|
|
||||||
5. Software is evolutive: the better implementations must supersede lesser
|
|
||||||
implementations. Technical advantage is the primary evaluation metric.
|
|
||||||
|
|
||||||
6. This is a space for technical prowess; topics outside of the project
|
|
||||||
will not be tolerated.
|
|
||||||
|
|
||||||
7. Non technical conflicts will be discussed in a separate space. Disruption
|
|
||||||
of the project will not be allowed.
|
|
||||||
|
|
||||||
8. Individual characteristics, including but not limited to,
|
|
||||||
body, sex, sexual preference, race, language, religion, nationality,
|
|
||||||
or political preferences are irrelevant in the scope of the project and
|
|
||||||
will not be taken into account concerning your value or that of your contribution
|
|
||||||
to the project.
|
|
||||||
|
|
||||||
9. Discuss or debate the idea, not the person.
|
|
||||||
|
|
||||||
10. There is no room for ambiguity: Ambiguity will be met with questioning;
|
|
||||||
further ambiguity will be met with silence. It is the responsibility
|
|
||||||
of the originator to provide requested context.
|
|
||||||
|
|
||||||
11. If something is illegal outside the scope of the project, it is illegal
|
|
||||||
in the scope of the project. This Code of Merit does not take precedence over
|
|
||||||
governing law.
|
|
||||||
|
|
||||||
12. This Code of Merit governs the technical procedures of the project not the
|
|
||||||
activities outside of it.
|
|
||||||
|
|
||||||
13. Participation on the project equates to agreement of this Code of Merit.
|
|
||||||
|
|
||||||
14. No objectives beyond the stated objectives of this project are relevant
|
|
||||||
to the project. Any intent to deviate the project from its original purpose
|
|
||||||
of existence will constitute grounds for remedial action which may include
|
|
||||||
expulsion from the project.
|
|
||||||
|
|
||||||
This document is adapted from the Code of Merit, version 1.0.
|
|
||||||
See: https://codeofmerit.org/.
|
|
|
@ -39,7 +39,7 @@ class ZigExecConfigBinary(project: Project, factory: ConfigurationFactory) : Zig
|
||||||
get() = ZigDebugBundle.message("configuration.binary.suggested-name")
|
get() = ZigDebugBundle.message("configuration.binary.suggested-name")
|
||||||
|
|
||||||
override suspend fun buildCommandLineArgs(debug: Boolean): List<String> {
|
override suspend fun buildCommandLineArgs(debug: Boolean): List<String> {
|
||||||
return args.args
|
return args.argsSplit()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getConfigurables(): List<ZigConfigurable<*>> {
|
override fun getConfigurables(): List<ZigConfigurable<*>> {
|
||||||
|
|
|
@ -36,6 +36,6 @@ class ZigDebugParametersBinary @Throws(ExecutionException::class) constructor(dr
|
||||||
ZigDebugParametersBase<ZigProfileStateBinary>(driverConfiguration, toolchain, profileState) {
|
ZigDebugParametersBase<ZigProfileStateBinary>(driverConfiguration, toolchain, profileState) {
|
||||||
private val executableFile = profileState.configuration.exePath.path?.toFile() ?: throw ExecutionException(ZigDebugBundle.message("exception.missing-exe-path"))
|
private val executableFile = profileState.configuration.exePath.path?.toFile() ?: throw ExecutionException(ZigDebugBundle.message("exception.missing-exe-path"))
|
||||||
override fun getInstaller(): Installer {
|
override fun getInstaller(): Installer {
|
||||||
return ZigDebugEmitBinaryInstaller(profileState, toolchain, executableFile, profileState.configuration.args.args)
|
return ZigDebugEmitBinaryInstaller(profileState, toolchain, executableFile, profileState.configuration.args.argsSplit())
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -53,7 +53,7 @@ class ZigDebugParametersBuild(
|
||||||
private lateinit var executableFile: File
|
private lateinit var executableFile: File
|
||||||
|
|
||||||
override fun getInstaller(): Installer {
|
override fun getInstaller(): Installer {
|
||||||
return ZigDebugEmitBinaryInstaller(profileState, toolchain, executableFile, profileState.configuration.exeArgs.args)
|
return ZigDebugEmitBinaryInstaller(profileState, toolchain, executableFile, profileState.configuration.exeArgs.argsSplit())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
@Throws(ExecutionException::class)
|
||||||
|
|
|
@ -32,6 +32,6 @@ import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
||||||
class ZigDebugParametersRun(driverConfiguration: DebuggerDriverConfiguration, toolchain: AbstractZigToolchain, profileState: ZigProfileStateRun) :
|
class ZigDebugParametersRun(driverConfiguration: DebuggerDriverConfiguration, toolchain: AbstractZigToolchain, profileState: ZigProfileStateRun) :
|
||||||
ZigDebugParametersEmitBinaryBase<ZigProfileStateRun>(driverConfiguration, toolchain, profileState) {
|
ZigDebugParametersEmitBinaryBase<ZigProfileStateRun>(driverConfiguration, toolchain, profileState) {
|
||||||
override fun getInstaller(): Installer {
|
override fun getInstaller(): Installer {
|
||||||
return ZigDebugEmitBinaryInstaller(profileState, toolchain, executableFile, profileState.configuration.exeArgs.args)
|
return ZigDebugEmitBinaryInstaller(profileState, toolchain, executableFile, profileState.configuration.exeArgs.argsSplit())
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<idea-plugin package="com.falsepattern.zigbrains.debugger">
|
<idea-plugin package="com.falsepattern.zigbrains.debugger">
|
||||||
<depends>com.intellij.nativeDebug</depends>
|
<depends>com.intellij.modules.cidr.debugger</depends>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<configurationType
|
<configurationType
|
||||||
|
|
|
@ -347,14 +347,18 @@ class ArgsConfigurable(
|
||||||
@Transient private val serializedName: String,
|
@Transient private val serializedName: String,
|
||||||
@Transient @Nls private val guiName: String
|
@Transient @Nls private val guiName: String
|
||||||
) : ZigConfigurable<ArgsConfigurable>, Cloneable {
|
) : ZigConfigurable<ArgsConfigurable>, Cloneable {
|
||||||
var args: List<String> = emptyList()
|
var args: String = ""
|
||||||
|
|
||||||
override fun readExternal(element: Element) {
|
override fun readExternal(element: Element) {
|
||||||
args = element.readStrings(serializedName) ?: return
|
args = element.readString(serializedName) ?: element.readStrings(serializedName)?.joinToString(separator = " ") { if (it.contains(' ')) "\"$it\"" else it } ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun argsSplit(): List<String> {
|
||||||
|
return translateCommandline(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun writeExternal(element: Element) {
|
override fun writeExternal(element: Element) {
|
||||||
element.writeStrings(serializedName, args)
|
element.writeString(serializedName, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createEditor(): ZigConfigModule<ArgsConfigurable> {
|
override fun createEditor(): ZigConfigModule<ArgsConfigurable> {
|
||||||
|
@ -376,12 +380,12 @@ class ArgsConfigurable(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun apply(configurable: ArgsConfigurable): Boolean {
|
override fun apply(configurable: ArgsConfigurable): Boolean {
|
||||||
configurable.args = translateCommandline(argsField.text)
|
configurable.args = argsField.text ?: ""
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reset(configurable: ArgsConfigurable) {
|
override fun reset(configurable: ArgsConfigurable) {
|
||||||
argsField.text = configurable.args.joinToString(separator = " ")
|
argsField.text = configurable.args
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun construct(p: Panel): Unit = with(p) {
|
override fun construct(p: Panel): Unit = with(p) {
|
||||||
|
|
|
@ -48,9 +48,10 @@ class ZigExecConfigBuild(project: Project, factory: ConfigurationFactory): ZigEx
|
||||||
override suspend fun buildCommandLineArgs(debug: Boolean): List<String> {
|
override suspend fun buildCommandLineArgs(debug: Boolean): List<String> {
|
||||||
val result = ArrayList<String>()
|
val result = ArrayList<String>()
|
||||||
result.add("build")
|
result.add("build")
|
||||||
|
val argsSplit = buildSteps.argsSplit()
|
||||||
val steps = if (debug) {
|
val steps = if (debug) {
|
||||||
val truncatedSteps = ArrayList<String>()
|
val truncatedSteps = ArrayList<String>()
|
||||||
for (step in buildSteps.args) {
|
for (step in argsSplit) {
|
||||||
if (step == "run")
|
if (step == "run")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -60,10 +61,10 @@ class ZigExecConfigBuild(project: Project, factory: ConfigurationFactory): ZigEx
|
||||||
truncatedSteps.add(step)
|
truncatedSteps.add(step)
|
||||||
}
|
}
|
||||||
truncatedSteps
|
truncatedSteps
|
||||||
} else buildSteps.args
|
} else argsSplit
|
||||||
result.addAll(steps)
|
result.addAll(steps)
|
||||||
result.addAll(coloredCliFlags(colored.value, debug))
|
result.addAll(coloredCliFlags(colored.value, debug))
|
||||||
result.addAll(extraArgs.args)
|
result.addAll(extraArgs.argsSplit())
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,10 +52,10 @@ class ZigExecConfigRun(project: Project, factory: ConfigurationFactory): ZigExec
|
||||||
if (!debug || optimization.forced) {
|
if (!debug || optimization.forced) {
|
||||||
result.addAll(listOf("-O", optimization.level.name))
|
result.addAll(listOf("-O", optimization.level.name))
|
||||||
}
|
}
|
||||||
result.addAll(compilerArgs.args)
|
result.addAll(compilerArgs.argsSplit())
|
||||||
if (!debug) {
|
if (!debug) {
|
||||||
result.add("--")
|
result.add("--")
|
||||||
result.addAll(exeArgs.args)
|
result.addAll(exeArgs.argsSplit())
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ class ZigExecConfigTest(project: Project, factory: ConfigurationFactory): ZigExe
|
||||||
if (!debug || optimization.forced) {
|
if (!debug || optimization.forced) {
|
||||||
result.addAll(listOf("-O", optimization.level.name))
|
result.addAll(listOf("-O", optimization.level.name))
|
||||||
}
|
}
|
||||||
result.addAll(compilerArgs.args)
|
result.addAll(compilerArgs.argsSplit())
|
||||||
if (debug) {
|
if (debug) {
|
||||||
result.add("--test-no-exec")
|
result.add("--test-no-exec")
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,11 +73,10 @@ data class ZigProjectConfigurationData(
|
||||||
).notify(project)
|
).notify(project)
|
||||||
return@indeterminateStep false
|
return@indeterminateStep false
|
||||||
}
|
}
|
||||||
val result = zig.callWithArgs(workDir, "init")
|
val result = zig.callWithArgs(workDir, "init").getOrElse { throwable ->
|
||||||
if (result == null) {
|
|
||||||
Notification(
|
Notification(
|
||||||
"zigbrains",
|
"zigbrains",
|
||||||
"\"zig init\" could not run because the zig executable was missing!",
|
"Failed to run \"zig init\": ${throwable.message}",
|
||||||
NotificationType.ERROR
|
NotificationType.ERROR
|
||||||
).notify(project)
|
).notify(project)
|
||||||
return@indeterminateStep false
|
return@indeterminateStep false
|
||||||
|
|
|
@ -27,11 +27,11 @@ import com.falsepattern.zigbrains.direnv.DirenvCmd
|
||||||
import com.falsepattern.zigbrains.project.toolchain.LocalZigToolchain
|
import com.falsepattern.zigbrains.project.toolchain.LocalZigToolchain
|
||||||
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainProvider
|
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainProvider
|
||||||
import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT
|
import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT
|
||||||
|
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
|
||||||
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
||||||
import com.intellij.openapi.Disposable
|
import com.intellij.openapi.application.ModalityState
|
||||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.project.ProjectManager
|
|
||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
import com.intellij.openapi.util.UserDataHolderBase
|
import com.intellij.openapi.util.UserDataHolderBase
|
||||||
import com.intellij.openapi.util.io.toNioPathOrNull
|
import com.intellij.openapi.util.io.toNioPathOrNull
|
||||||
|
@ -41,7 +41,7 @@ import com.intellij.platform.ide.progress.withModalProgress
|
||||||
import com.intellij.ui.DocumentAdapter
|
import com.intellij.ui.DocumentAdapter
|
||||||
import com.intellij.ui.JBColor
|
import com.intellij.ui.JBColor
|
||||||
import com.intellij.ui.components.JBCheckBox
|
import com.intellij.ui.components.JBCheckBox
|
||||||
import com.intellij.ui.components.JBLabel
|
import com.intellij.ui.components.JBTextArea
|
||||||
import com.intellij.ui.components.textFieldWithBrowseButton
|
import com.intellij.ui.components.textFieldWithBrowseButton
|
||||||
import com.intellij.ui.dsl.builder.AlignX
|
import com.intellij.ui.dsl.builder.AlignX
|
||||||
import com.intellij.ui.dsl.builder.Panel
|
import com.intellij.ui.dsl.builder.Panel
|
||||||
|
@ -68,7 +68,7 @@ class ZigProjectSettingsPanel(private val project: Project) : ZigProjectConfigur
|
||||||
})
|
})
|
||||||
Disposer.register(this, it)
|
Disposer.register(this, it)
|
||||||
}
|
}
|
||||||
private val toolchainVersion = JBLabel()
|
private val toolchainVersion = JBTextArea().also { it.isEditable = false }
|
||||||
private val stdFieldOverride = JBCheckBox(ZigBrainsBundle.message("settings.project.label.override-std")).apply {
|
private val stdFieldOverride = JBCheckBox(ZigBrainsBundle.message("settings.project.label.override-std")).apply {
|
||||||
addChangeListener {
|
addChangeListener {
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
|
@ -161,35 +161,39 @@ class ZigProjectSettingsPanel(private val project: Project) : ZigProjectConfigur
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private suspend fun updateUI() {
|
private suspend fun updateUI() {
|
||||||
val pathToToolchain = this.pathToToolchain.text.ifBlank { null }?.toNioPathOrNull()
|
|
||||||
delay(200)
|
delay(200)
|
||||||
val toolchain = pathToToolchain?.let { LocalZigToolchain(it) }
|
val pathToToolchain = this.pathToToolchain.text.ifBlank { null }?.toNioPathOrNull()
|
||||||
val zig = toolchain?.zig
|
if (pathToToolchain == null) {
|
||||||
if (zig?.path()?.toFile()?.exists() != true) {
|
withEDTContext(ModalityState.any()) {
|
||||||
toolchainVersion.text = "[zig binary not found]"
|
toolchainVersion.text = "[toolchain path empty or invalid]"
|
||||||
|
if (!stdFieldOverride.isSelected) {
|
||||||
if (!stdFieldOverride.isSelected) {
|
pathToStd.text = ""
|
||||||
pathToStd.text = ""
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val env = zig.getEnv(project)
|
val toolchain = LocalZigToolchain(pathToToolchain)
|
||||||
if (env == null) {
|
val zig = toolchain.zig
|
||||||
toolchainVersion.text = "[failed to run zig env]"
|
val env = zig.getEnv(project).getOrElse { throwable ->
|
||||||
if (!stdFieldOverride.isSelected) {
|
throwable.printStackTrace()
|
||||||
pathToStd.text = ""
|
withEDTContext(ModalityState.any()) {
|
||||||
|
toolchainVersion.text = "[failed to run \"zig env\"]\n${throwable.message}"
|
||||||
|
if (!stdFieldOverride.isSelected) {
|
||||||
|
pathToStd.text = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val version = env.version
|
val version = env.version
|
||||||
val stdPath = env.stdPath(toolchain, project)
|
val stdPath = env.stdPath(toolchain, project)
|
||||||
toolchainVersion.text = version
|
|
||||||
toolchainVersion.foreground = JBColor.foreground()
|
|
||||||
|
|
||||||
if (!stdFieldOverride.isSelected) {
|
withEDTContext(ModalityState.any()) {
|
||||||
pathToStd.text = stdPath?.pathString ?: ""
|
toolchainVersion.text = version
|
||||||
|
toolchainVersion.foreground = JBColor.foreground()
|
||||||
|
if (!stdFieldOverride.isSelected) {
|
||||||
|
pathToStd.text = stdPath?.pathString ?: ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,9 +84,12 @@ class ZigStepDiscoveryService(private val project: Project) {
|
||||||
project.guessProjectDir()?.toNioPathOrNull(),
|
project.guessProjectDir()?.toNioPathOrNull(),
|
||||||
"build", "-l",
|
"build", "-l",
|
||||||
timeoutMillis = currentTimeoutSec * 1000L
|
timeoutMillis = currentTimeoutSec * 1000L
|
||||||
)
|
).getOrElse { throwable ->
|
||||||
|
errorReload(ErrorType.MissingZigExe, throwable.message)
|
||||||
|
null
|
||||||
|
}
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
errorReload(ErrorType.MissingZigExe)
|
{}
|
||||||
} else if (result.checkSuccess(LOG)) {
|
} else if (result.checkSuccess(LOG)) {
|
||||||
currentTimeoutSec = DEFAULT_TIMEOUT_SEC
|
currentTimeoutSec = DEFAULT_TIMEOUT_SEC
|
||||||
val lines = result.stdoutLines
|
val lines = result.stdoutLines
|
||||||
|
|
|
@ -87,7 +87,7 @@ class BuildToolWindowContext(private val project: Project): Disposable {
|
||||||
val factory = firstConfigFactory<ZigConfigTypeBuild>()
|
val factory = firstConfigFactory<ZigConfigTypeBuild>()
|
||||||
val newConfig = manager.createConfiguration("zig build $stepName", factory)
|
val newConfig = manager.createConfiguration("zig build $stepName", factory)
|
||||||
val config = newConfig.configuration as ZigExecConfigBuild
|
val config = newConfig.configuration as ZigExecConfigBuild
|
||||||
config.buildSteps.args = listOf(stepName)
|
config.buildSteps.args = stepName
|
||||||
manager.addConfiguration(newConfig)
|
manager.addConfiguration(newConfig)
|
||||||
return@run newConfig
|
return@run newConfig
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ private fun getViewport(project: Project): JBScrollPane? {
|
||||||
private fun getExistingRunConfig(manager: RunManager, stepName: String): RunnerAndConfigurationSettings? {
|
private fun getExistingRunConfig(manager: RunManager, stepName: String): RunnerAndConfigurationSettings? {
|
||||||
for (config in manager.getConfigurationSettingsList(ZigConfigTypeBuild::class.java)) {
|
for (config in manager.getConfigurationSettingsList(ZigConfigTypeBuild::class.java)) {
|
||||||
val build = config.configuration as? ZigExecConfigBuild ?: continue
|
val build = config.configuration as? ZigExecConfigBuild ?: continue
|
||||||
val steps = build.buildSteps.args
|
val steps = build.buildSteps.argsSplit()
|
||||||
if (steps.size != 1)
|
if (steps.size != 1)
|
||||||
continue
|
continue
|
||||||
if (steps[0] != stepName)
|
if (steps[0] != stepName)
|
||||||
|
|
|
@ -76,7 +76,7 @@ private fun getName(
|
||||||
project: Project
|
project: Project
|
||||||
): String {
|
): String {
|
||||||
val tc = state.toolchain ?: return "Zig"
|
val tc = state.toolchain ?: return "Zig"
|
||||||
val version = runBlocking { tc.zig.getEnv(project)?.version } ?: return "Zig"
|
val version = runBlocking { tc.zig.getEnv(project) }.mapCatching { it.version }.getOrElse { return "Zig" }
|
||||||
return "Zig $version"
|
return "Zig $version"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ private fun getRoots(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (toolchain != null) {
|
if (toolchain != null) {
|
||||||
val stdPath = runBlocking { toolchain.zig.getEnv(project) }?.stdPath(toolchain, project) ?: return emptySet()
|
val stdPath = runBlocking { toolchain.zig.getEnv(project) }.mapCatching { it.stdPath(toolchain, project) }.getOrNull() ?: return emptySet()
|
||||||
val roots = stdPath.refreshAndFindVirtualDirectory() ?: return emptySet()
|
val roots = stdPath.refreshAndFindVirtualDirectory() ?: return emptySet()
|
||||||
return setOf(roots)
|
return setOf(roots)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import com.falsepattern.zigbrains.project.toolchain.ZigToolchainEnvironmentSeria
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import kotlinx.serialization.SerializationException
|
import kotlinx.serialization.SerializationException
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
import java.lang.IllegalStateException
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
class ZigCompilerTool(toolchain: AbstractZigToolchain) : ZigTool(toolchain) {
|
class ZigCompilerTool(toolchain: AbstractZigToolchain) : ZigTool(toolchain) {
|
||||||
|
@ -37,12 +38,12 @@ class ZigCompilerTool(toolchain: AbstractZigToolchain) : ZigTool(toolchain) {
|
||||||
return toolchain.pathToExecutable(toolName)
|
return toolchain.pathToExecutable(toolName)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getEnv(project: Project?): ZigToolchainEnvironmentSerializable? {
|
suspend fun getEnv(project: Project?): Result<ZigToolchainEnvironmentSerializable> {
|
||||||
val stdout = callWithArgs(toolchain.workingDirectory(project), "env")?.stdout ?: return null
|
val stdout = callWithArgs(toolchain.workingDirectory(project), "env").getOrElse { throwable -> return Result.failure(throwable) }.stdout
|
||||||
return try {
|
return try {
|
||||||
envJson.decodeFromString<ZigToolchainEnvironmentSerializable>(stdout)
|
Result.success(envJson.decodeFromString<ZigToolchainEnvironmentSerializable>(stdout))
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
null
|
Result.failure(IllegalStateException("could not deserialize zig env", e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,52 +23,26 @@
|
||||||
package com.falsepattern.zigbrains.project.toolchain.tools
|
package com.falsepattern.zigbrains.project.toolchain.tools
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain
|
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain
|
||||||
|
import com.falsepattern.zigbrains.shared.cli.call
|
||||||
|
import com.falsepattern.zigbrains.shared.cli.createCommandLineSafe
|
||||||
import com.intellij.execution.configurations.GeneralCommandLine
|
import com.intellij.execution.configurations.GeneralCommandLine
|
||||||
import com.intellij.execution.process.ProcessOutput
|
import com.intellij.execution.process.ProcessOutput
|
||||||
import com.intellij.util.io.awaitExit
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.runInterruptible
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.io.path.isRegularFile
|
|
||||||
|
|
||||||
abstract class ZigTool(val toolchain: AbstractZigToolchain) {
|
abstract class ZigTool(val toolchain: AbstractZigToolchain) {
|
||||||
abstract val toolName: String
|
abstract val toolName: String
|
||||||
|
|
||||||
suspend fun callWithArgs(workingDirectory: Path?, vararg parameters: String, timeoutMillis: Long = Long.MAX_VALUE): ProcessOutput? {
|
suspend fun callWithArgs(workingDirectory: Path?, vararg parameters: String, timeoutMillis: Long = Long.MAX_VALUE): Result<ProcessOutput> {
|
||||||
val cli = createBaseCommandLine(workingDirectory, *parameters) ?: return null
|
val cli = createBaseCommandLine(workingDirectory, *parameters).let { it.getOrElse { return Result.failure(it) } }
|
||||||
|
return cli.call(timeoutMillis)
|
||||||
val (process, exitCode) = withContext(Dispatchers.IO) {
|
|
||||||
val process = cli.createProcess()
|
|
||||||
val exit = withTimeoutOrNull(timeoutMillis) {
|
|
||||||
process.awaitExit()
|
|
||||||
}
|
|
||||||
process to exit
|
|
||||||
}
|
|
||||||
return runInterruptible {
|
|
||||||
ProcessOutput(
|
|
||||||
process.inputStream.bufferedReader().use { it.readText() },
|
|
||||||
process.errorStream.bufferedReader().use { it.readText() },
|
|
||||||
exitCode ?: -1,
|
|
||||||
exitCode == null,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun createBaseCommandLine(
|
private suspend fun createBaseCommandLine(
|
||||||
workingDirectory: Path?,
|
workingDirectory: Path?,
|
||||||
vararg parameters: String
|
vararg parameters: String
|
||||||
): GeneralCommandLine? {
|
): Result<GeneralCommandLine> {
|
||||||
val exe = toolchain.pathToExecutable(toolName)
|
val exe = toolchain.pathToExecutable(toolName)
|
||||||
if (!exe.isRegularFile())
|
return createCommandLineSafe(workingDirectory, exe, *parameters)
|
||||||
return null
|
.mapCatching { toolchain.patchCommandLine(it) }
|
||||||
val cli = GeneralCommandLine()
|
|
||||||
.withExePath(exe.toString())
|
|
||||||
.withWorkDirectory(workingDirectory?.toFile())
|
|
||||||
.withParameters(*parameters)
|
|
||||||
.withCharset(Charsets.UTF_8)
|
|
||||||
return toolchain.patchCommandLine(cli)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -23,8 +23,19 @@
|
||||||
package com.falsepattern.zigbrains.shared.cli
|
package com.falsepattern.zigbrains.shared.cli
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||||
|
import com.intellij.execution.configurations.GeneralCommandLine
|
||||||
|
import com.intellij.execution.process.ProcessOutput
|
||||||
import com.intellij.openapi.options.ConfigurationException
|
import com.intellij.openapi.options.ConfigurationException
|
||||||
|
import com.intellij.util.io.awaitExit
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.runInterruptible
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
|
import java.nio.file.Path
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.io.path.exists
|
||||||
|
import kotlin.io.path.isDirectory
|
||||||
|
import kotlin.io.path.pathString
|
||||||
|
|
||||||
|
|
||||||
//From Apache Ant
|
//From Apache Ant
|
||||||
|
@ -100,4 +111,40 @@ fun coloredCliFlags(colored: Boolean, debug: Boolean): List<String> {
|
||||||
} else {
|
} else {
|
||||||
listOf("--color", if (colored) "on" else "off")
|
listOf("--color", if (colored) "on" else "off")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createCommandLineSafe(
|
||||||
|
workingDirectory: Path?,
|
||||||
|
exe: Path,
|
||||||
|
vararg parameters: String,
|
||||||
|
): Result<GeneralCommandLine> {
|
||||||
|
if (!exe.exists())
|
||||||
|
return Result.failure(IllegalArgumentException("file does not exist: ${exe.pathString}"))
|
||||||
|
if (exe.isDirectory())
|
||||||
|
return Result.failure(IllegalArgumentException("file is a directory: ${exe.pathString}"))
|
||||||
|
val cli = GeneralCommandLine()
|
||||||
|
.withExePath(exe.toString())
|
||||||
|
.withWorkDirectory(workingDirectory?.toFile())
|
||||||
|
.withParameters(*parameters)
|
||||||
|
.withCharset(Charsets.UTF_8)
|
||||||
|
return Result.success(cli)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun GeneralCommandLine.call(timeoutMillis: Long = Long.MAX_VALUE): Result<ProcessOutput> {
|
||||||
|
val (process, exitCode) = withContext(Dispatchers.IO) {
|
||||||
|
val process = createProcess()
|
||||||
|
val exit = withTimeoutOrNull(timeoutMillis) {
|
||||||
|
process.awaitExit()
|
||||||
|
}
|
||||||
|
process to exit
|
||||||
|
}
|
||||||
|
return runInterruptible {
|
||||||
|
Result.success(ProcessOutput(
|
||||||
|
process.inputStream.bufferedReader().use { it.readText() },
|
||||||
|
process.errorStream.bufferedReader().use { it.readText() },
|
||||||
|
exitCode ?: -1,
|
||||||
|
exitCode == null,
|
||||||
|
false
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -105,7 +105,7 @@ configuration.build.marker-name=Build and Run
|
||||||
settings.project.group.title=Zig Settings
|
settings.project.group.title=Zig Settings
|
||||||
settings.project.label.direnv=Use direnv
|
settings.project.label.direnv=Use direnv
|
||||||
settings.project.label.toolchain=Toolchain location
|
settings.project.label.toolchain=Toolchain location
|
||||||
settings.project.label.toolchain-version=Toolchain version
|
settings.project.label.toolchain-version=Detected zig version
|
||||||
settings.project.label.override-std=Override standard library
|
settings.project.label.override-std=Override standard library
|
||||||
settings.project.label.std-location=Standard library location
|
settings.project.label.std-location=Standard library location
|
||||||
build.tool.window.tree.steps.label=Steps
|
build.tool.window.tree.steps.label=Steps
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
pluginName=ZigBrains
|
pluginName=ZigBrains
|
||||||
pluginRepositoryUrl=https://github.com/FalsePattern/ZigBrains
|
pluginRepositoryUrl=https://github.com/FalsePattern/ZigBrains
|
||||||
|
|
||||||
pluginVersion=21.1.0
|
pluginVersion=22.0.0
|
||||||
|
|
||||||
pluginSinceBuild=241
|
pluginSinceBuild=241
|
||||||
pluginUntilBuild=241.*
|
pluginUntilBuild=241.*
|
||||||
|
|
|
@ -26,8 +26,12 @@ import com.falsepattern.zigbrains.direnv.DirenvCmd
|
||||||
import com.falsepattern.zigbrains.direnv.emptyEnv
|
import com.falsepattern.zigbrains.direnv.emptyEnv
|
||||||
import com.falsepattern.zigbrains.direnv.getDirenv
|
import com.falsepattern.zigbrains.direnv.getDirenv
|
||||||
import com.falsepattern.zigbrains.lsp.settings.zlsSettings
|
import com.falsepattern.zigbrains.lsp.settings.zlsSettings
|
||||||
|
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.startup.ProjectActivity
|
import com.intellij.openapi.startup.ProjectActivity
|
||||||
|
import com.intellij.ui.EditorNotifications
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.io.path.pathString
|
import kotlin.io.path.pathString
|
||||||
|
|
||||||
class ZLSStartup: ProjectActivity {
|
class ZLSStartup: ProjectActivity {
|
||||||
|
@ -43,5 +47,16 @@ class ZLSStartup: ProjectActivity {
|
||||||
project.zlsSettings.state = zlsState
|
project.zlsSettings.state = zlsState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
project.zigCoroutineScope.launch {
|
||||||
|
var currentState = project.zlsRunningAsync()
|
||||||
|
while (!project.isDisposed) {
|
||||||
|
val running = project.zlsRunningAsync()
|
||||||
|
if (currentState != running) {
|
||||||
|
EditorNotifications.getInstance(project).updateAllNotifications()
|
||||||
|
}
|
||||||
|
currentState = running
|
||||||
|
delay(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -71,15 +71,43 @@ class ZigLanguageServerFactory: LanguageServerFactory, LanguageServerEnablementS
|
||||||
return features
|
return features
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isEnabled(project: Project): Boolean {
|
override fun isEnabled(project: Project) = project.zlsEnabledSync()
|
||||||
return (project.getUserData(ENABLED_KEY) != false) && project.zlsSettings.validate()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setEnabled(enabled: Boolean, project: Project) {
|
override fun setEnabled(enabled: Boolean, project: Project) {
|
||||||
project.putUserData(ENABLED_KEY, enabled)
|
project.zlsEnabled(enabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun Project.zlsEnabledAsync(): Boolean {
|
||||||
|
return (getUserData(ENABLED_KEY) != false) && zlsSettings.validateAsync()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Project.zlsEnabledSync(): Boolean {
|
||||||
|
return (getUserData(ENABLED_KEY) != false) && zlsSettings.validateSync()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Project.zlsEnabled(value: Boolean) {
|
||||||
|
putUserData(ENABLED_KEY, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun Project.zlsRunningAsync(): Boolean {
|
||||||
|
if (!zlsEnabledAsync())
|
||||||
|
return false
|
||||||
|
return zlsRunningLsp4ij()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Project.zlsRunningSync(): Boolean {
|
||||||
|
if (!zlsEnabledSync())
|
||||||
|
return false
|
||||||
|
return zlsRunningLsp4ij()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Project.zlsRunningLsp4ij(): Boolean {
|
||||||
|
val manager = service<LanguageServerManager>()
|
||||||
|
val status = manager.getServerStatus("ZigBrains")
|
||||||
|
return status == ServerStatus.started || status == ServerStatus.starting
|
||||||
|
}
|
||||||
|
|
||||||
class ZLSStarter: LanguageServerStarter {
|
class ZLSStarter: LanguageServerStarter {
|
||||||
override fun startLSP(project: Project, restart: Boolean) {
|
override fun startLSP(project: Project, restart: Boolean) {
|
||||||
project.zigCoroutineScope.launch {
|
project.zigCoroutineScope.launch {
|
||||||
|
@ -87,7 +115,10 @@ class ZLSStarter: LanguageServerStarter {
|
||||||
val status = manager.getServerStatus("ZigBrains")
|
val status = manager.getServerStatus("ZigBrains")
|
||||||
if ((status == ServerStatus.started || status == ServerStatus.starting) && !restart)
|
if ((status == ServerStatus.started || status == ServerStatus.starting) && !restart)
|
||||||
return@launch
|
return@launch
|
||||||
manager.start("ZigBrains")
|
manager.stop("ZigBrains")
|
||||||
|
if (project.zlsSettings.validateAsync()) {
|
||||||
|
manager.start("ZigBrains")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* This file is part of ZigBrains.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023-2025 FalsePattern
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* ZigBrains is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, only version 3 of the License.
|
||||||
|
*
|
||||||
|
* ZigBrains is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.falsepattern.zigbrains.lsp.notification
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.lsp.ZLSBundle
|
||||||
|
import com.falsepattern.zigbrains.lsp.settings.zlsSettings
|
||||||
|
import com.falsepattern.zigbrains.lsp.zlsRunningSync
|
||||||
|
import com.falsepattern.zigbrains.zig.ZigFileType
|
||||||
|
import com.falsepattern.zigbrains.zon.ZonFileType
|
||||||
|
import com.intellij.openapi.fileEditor.FileEditor
|
||||||
|
import com.intellij.openapi.project.DumbAware
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.ui.EditorNotificationPanel
|
||||||
|
import com.intellij.ui.EditorNotificationProvider
|
||||||
|
import java.util.function.Function
|
||||||
|
import javax.swing.JComponent
|
||||||
|
|
||||||
|
class ZigEditorNotificationProvider: EditorNotificationProvider, DumbAware {
|
||||||
|
override fun collectNotificationData(
|
||||||
|
project: Project,
|
||||||
|
file: VirtualFile
|
||||||
|
): Function<in FileEditor, out JComponent?>? {
|
||||||
|
when (file.fileType) {
|
||||||
|
ZigFileType, ZonFileType -> {}
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
if (project.zlsRunningSync()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return Function { editor ->
|
||||||
|
val status: EditorNotificationPanel.Status
|
||||||
|
val message: String
|
||||||
|
if (!project.zlsSettings.validateSync()) {
|
||||||
|
status = EditorNotificationPanel.Status.Error
|
||||||
|
message = ZLSBundle.message("notification.banner.zls-bad-config")
|
||||||
|
} else {
|
||||||
|
status = EditorNotificationPanel.Status.Warning
|
||||||
|
message = ZLSBundle.message("notification.banner.zls-not-running")
|
||||||
|
}
|
||||||
|
EditorNotificationPanel(editor, status).also { it.text = message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ package com.falsepattern.zigbrains.lsp.settings
|
||||||
import com.falsepattern.zigbrains.direnv.emptyEnv
|
import com.falsepattern.zigbrains.direnv.emptyEnv
|
||||||
import com.falsepattern.zigbrains.direnv.getDirenv
|
import com.falsepattern.zigbrains.direnv.getDirenv
|
||||||
import com.falsepattern.zigbrains.lsp.ZLSBundle
|
import com.falsepattern.zigbrains.lsp.ZLSBundle
|
||||||
|
import com.falsepattern.zigbrains.lsp.startLSP
|
||||||
import com.intellij.openapi.components.*
|
import com.intellij.openapi.components.*
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.io.toNioPathOrNull
|
import com.intellij.openapi.util.io.toNioPathOrNull
|
||||||
|
@ -32,9 +33,9 @@ import com.intellij.platform.ide.progress.ModalTaskOwner
|
||||||
import com.intellij.platform.ide.progress.runWithModalProgressBlocking
|
import com.intellij.platform.ide.progress.runWithModalProgressBlocking
|
||||||
import com.intellij.util.application
|
import com.intellij.util.application
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
|
||||||
import kotlin.concurrent.withLock
|
|
||||||
import kotlin.io.path.isExecutable
|
import kotlin.io.path.isExecutable
|
||||||
import kotlin.io.path.isRegularFile
|
import kotlin.io.path.isRegularFile
|
||||||
|
|
||||||
|
@ -51,47 +52,45 @@ class ZLSProjectSettingsService(val project: Project): PersistentStateComponent<
|
||||||
@Volatile
|
@Volatile
|
||||||
private var valid = false
|
private var valid = false
|
||||||
|
|
||||||
private val mutex = ReentrantLock()
|
private val mutex = Mutex()
|
||||||
override fun getState(): ZLSSettings {
|
override fun getState(): ZLSSettings {
|
||||||
return state.copy()
|
return state.copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setState(value: ZLSSettings) {
|
fun setState(value: ZLSSettings) {
|
||||||
mutex.withLock {
|
runBlocking {
|
||||||
this.state = value
|
mutex.withLock {
|
||||||
dirty = true
|
this@ZLSProjectSettingsService.state = value
|
||||||
|
dirty = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
startLSP(project, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadState(state: ZLSSettings) {
|
override fun loadState(state: ZLSSettings) {
|
||||||
mutex.withLock {
|
setState(state)
|
||||||
this.state = state
|
|
||||||
dirty = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isModified(otherData: ZLSSettings): Boolean {
|
suspend fun validateAsync(): Boolean {
|
||||||
return state != otherData
|
|
||||||
}
|
|
||||||
|
|
||||||
fun validate(): Boolean {
|
|
||||||
mutex.withLock {
|
mutex.withLock {
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
val state = this.state
|
val state = this.state
|
||||||
valid = if (application.isDispatchThread) {
|
valid = doValidate(project, state)
|
||||||
runWithModalProgressBlocking(ModalTaskOwner.project(project), ZLSBundle.message("progress.title.validate")) {
|
|
||||||
doValidate(project, state)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
runBlocking {
|
|
||||||
doValidate(project, state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dirty = false
|
dirty = false
|
||||||
}
|
}
|
||||||
return valid
|
return valid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun validateSync() = if (application.isDispatchThread) {
|
||||||
|
runWithModalProgressBlocking(ModalTaskOwner.project(project), ZLSBundle.message("progress.title.validate")) {
|
||||||
|
validateAsync()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
runBlocking {
|
||||||
|
validateAsync()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun doValidate(project: Project, state: ZLSSettings): Boolean {
|
private suspend fun doValidate(project: Project, state: ZLSSettings): Boolean {
|
||||||
|
|
|
@ -38,7 +38,7 @@ data class ZLSSettings(
|
||||||
val enable_argument_placeholders: Boolean = true,
|
val enable_argument_placeholders: Boolean = true,
|
||||||
val completion_label_details: Boolean = true,
|
val completion_label_details: Boolean = true,
|
||||||
val enable_build_on_save: Boolean = false,
|
val enable_build_on_save: Boolean = false,
|
||||||
val build_on_save_args: List<String> = emptyList(),
|
val build_on_save_args: String = "",
|
||||||
val semantic_tokens: SemanticTokens = SemanticTokens.full,
|
val semantic_tokens: SemanticTokens = SemanticTokens.full,
|
||||||
val inlay_hints_show_variable_type_hints: Boolean = true,
|
val inlay_hints_show_variable_type_hints: Boolean = true,
|
||||||
val inlay_hints_show_struct_literal_field_type: Boolean = true,
|
val inlay_hints_show_struct_literal_field_type: Boolean = true,
|
||||||
|
|
|
@ -24,6 +24,7 @@ package com.falsepattern.zigbrains.lsp.settings
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.lsp.config.ZLSConfig
|
import com.falsepattern.zigbrains.lsp.config.ZLSConfig
|
||||||
import com.falsepattern.zigbrains.lsp.config.ZLSConfigProvider
|
import com.falsepattern.zigbrains.lsp.config.ZLSConfigProvider
|
||||||
|
import com.falsepattern.zigbrains.shared.cli.translateCommandline
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
|
||||||
class ZLSSettingsConfigProvider: ZLSConfigProvider {
|
class ZLSSettingsConfigProvider: ZLSConfigProvider {
|
||||||
|
@ -34,7 +35,14 @@ class ZLSSettingsConfigProvider: ZLSConfigProvider {
|
||||||
enable_argument_placeholders = state.enable_argument_placeholders,
|
enable_argument_placeholders = state.enable_argument_placeholders,
|
||||||
completion_label_details = state.completion_label_details,
|
completion_label_details = state.completion_label_details,
|
||||||
enable_build_on_save = state.enable_build_on_save,
|
enable_build_on_save = state.enable_build_on_save,
|
||||||
build_on_save_args = state.build_on_save_args,
|
build_on_save_args = run {
|
||||||
|
val args = state.build_on_save_args
|
||||||
|
return@run if (args.isEmpty()) {
|
||||||
|
emptyList()
|
||||||
|
} else {
|
||||||
|
translateCommandline(args).toList()
|
||||||
|
}
|
||||||
|
},
|
||||||
semantic_tokens = state.semantic_tokens,
|
semantic_tokens = state.semantic_tokens,
|
||||||
inlay_hints_show_variable_type_hints = state.inlay_hints_show_variable_type_hints,
|
inlay_hints_show_variable_type_hints = state.inlay_hints_show_variable_type_hints,
|
||||||
inlay_hints_show_struct_literal_field_type = state.inlay_hints_show_struct_literal_field_type,
|
inlay_hints_show_struct_literal_field_type = state.inlay_hints_show_struct_literal_field_type,
|
||||||
|
|
|
@ -42,11 +42,7 @@ class ZLSSettingsConfigurable(private val project: Project): SubConfigurable {
|
||||||
override fun apply() {
|
override fun apply() {
|
||||||
val data = appSettingsComponent?.data ?: return
|
val data = appSettingsComponent?.data ?: return
|
||||||
val settings = project.zlsSettings
|
val settings = project.zlsSettings
|
||||||
val reloadZLS = settings.isModified(data)
|
|
||||||
settings.state = data
|
settings.state = data
|
||||||
if (reloadZLS) {
|
|
||||||
startLSP(project, true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reset() {
|
override fun reset() {
|
||||||
|
|
|
@ -29,24 +29,38 @@ import com.falsepattern.zigbrains.direnv.getDirenv
|
||||||
import com.falsepattern.zigbrains.lsp.ZLSBundle
|
import com.falsepattern.zigbrains.lsp.ZLSBundle
|
||||||
import com.falsepattern.zigbrains.lsp.config.SemanticTokens
|
import com.falsepattern.zigbrains.lsp.config.SemanticTokens
|
||||||
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
|
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
|
||||||
|
import com.falsepattern.zigbrains.shared.cli.call
|
||||||
|
import com.falsepattern.zigbrains.shared.cli.createCommandLineSafe
|
||||||
import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT
|
import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT
|
||||||
|
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
|
||||||
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
||||||
|
import com.intellij.execution.processTools.mapFlat
|
||||||
|
import com.intellij.openapi.application.ModalityState
|
||||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.project.guessProjectDir
|
||||||
import com.intellij.openapi.ui.ComboBox
|
import com.intellij.openapi.ui.ComboBox
|
||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
|
import com.intellij.openapi.util.io.toNioPathOrNull
|
||||||
|
import com.intellij.openapi.vfs.toNioPathOrNull
|
||||||
import com.intellij.platform.ide.progress.ModalTaskOwner
|
import com.intellij.platform.ide.progress.ModalTaskOwner
|
||||||
import com.intellij.platform.ide.progress.TaskCancellation
|
import com.intellij.platform.ide.progress.TaskCancellation
|
||||||
import com.intellij.platform.ide.progress.withModalProgress
|
import com.intellij.platform.ide.progress.withModalProgress
|
||||||
|
import com.intellij.ui.DocumentAdapter
|
||||||
|
import com.intellij.ui.JBColor
|
||||||
import com.intellij.ui.components.JBCheckBox
|
import com.intellij.ui.components.JBCheckBox
|
||||||
|
import com.intellij.ui.components.JBTextArea
|
||||||
import com.intellij.ui.components.fields.ExtendableTextField
|
import com.intellij.ui.components.fields.ExtendableTextField
|
||||||
import com.intellij.ui.components.textFieldWithBrowseButton
|
import com.intellij.ui.components.textFieldWithBrowseButton
|
||||||
import com.intellij.ui.dsl.builder.AlignX
|
import com.intellij.ui.dsl.builder.AlignX
|
||||||
import com.intellij.ui.dsl.builder.Panel
|
import com.intellij.ui.dsl.builder.Panel
|
||||||
import com.intellij.ui.dsl.builder.Row
|
import com.intellij.ui.dsl.builder.Row
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.jetbrains.annotations.PropertyKey
|
import org.jetbrains.annotations.PropertyKey
|
||||||
import java.lang.IllegalArgumentException
|
import javax.swing.event.DocumentEvent
|
||||||
import java.util.*
|
|
||||||
import kotlin.io.path.pathString
|
import kotlin.io.path.pathString
|
||||||
|
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName")
|
||||||
|
@ -55,13 +69,24 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr
|
||||||
project,
|
project,
|
||||||
ZLSBundle.message("settings.zls-path.browse.title"),
|
ZLSBundle.message("settings.zls-path.browse.title"),
|
||||||
FileChooserDescriptorFactory.createSingleFileDescriptor(),
|
FileChooserDescriptorFactory.createSingleFileDescriptor(),
|
||||||
).also { Disposer.register(this, it) }
|
).also {
|
||||||
|
it.textField.document.addDocumentListener(object: DocumentAdapter() {
|
||||||
|
override fun textChanged(p0: DocumentEvent) {
|
||||||
|
dispatchUpdateUI()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Disposer.register(this, it)
|
||||||
|
}
|
||||||
private val zlsConfigPath = textFieldWithBrowseButton(
|
private val zlsConfigPath = textFieldWithBrowseButton(
|
||||||
project,
|
project,
|
||||||
ZLSBundle.message("settings.zls-config-path.browse.title"),
|
ZLSBundle.message("settings.zls-config-path.browse.title"),
|
||||||
FileChooserDescriptorFactory.createSingleFileDescriptor()
|
FileChooserDescriptorFactory.createSingleFileDescriptor()
|
||||||
).also { Disposer.register(this, it) }
|
).also { Disposer.register(this, it) }
|
||||||
|
|
||||||
|
private val zlsVersion = JBTextArea().also { it.isEditable = false }
|
||||||
|
|
||||||
|
private var debounce: Job? = null
|
||||||
|
|
||||||
private val inlayHints = JBCheckBox()
|
private val inlayHints = JBCheckBox()
|
||||||
private val enable_snippets = JBCheckBox()
|
private val enable_snippets = JBCheckBox()
|
||||||
private val enable_argument_placeholders = JBCheckBox()
|
private val enable_argument_placeholders = JBCheckBox()
|
||||||
|
@ -102,6 +127,9 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr
|
||||||
cell(direnv)
|
cell(direnv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
row(ZLSBundle.message("settings.zls-version.label")) {
|
||||||
|
cell(zlsVersion)
|
||||||
|
}
|
||||||
fancyRow(
|
fancyRow(
|
||||||
"settings.zls-config-path.label",
|
"settings.zls-config-path.label",
|
||||||
"settings.zls-config-path.tooltip"
|
"settings.zls-config-path.tooltip"
|
||||||
|
@ -207,14 +235,7 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr
|
||||||
enable_argument_placeholders.isSelected,
|
enable_argument_placeholders.isSelected,
|
||||||
completion_label_details.isSelected,
|
completion_label_details.isSelected,
|
||||||
enable_build_on_save.isSelected,
|
enable_build_on_save.isSelected,
|
||||||
run {
|
build_on_save_args.text,
|
||||||
val args = build_on_save_args.text ?: ""
|
|
||||||
return@run if (args.isEmpty()) {
|
|
||||||
emptyList()
|
|
||||||
} else {
|
|
||||||
translateCommandline(args).toList()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
semantic_tokens.item ?: SemanticTokens.full,
|
semantic_tokens.item ?: SemanticTokens.full,
|
||||||
inlay_hints_show_variable_type_hints.isSelected,
|
inlay_hints_show_variable_type_hints.isSelected,
|
||||||
inlay_hints_show_struct_literal_field_type.isSelected,
|
inlay_hints_show_struct_literal_field_type.isSelected,
|
||||||
|
@ -240,7 +261,7 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr
|
||||||
enable_argument_placeholders.isSelected = value.enable_argument_placeholders
|
enable_argument_placeholders.isSelected = value.enable_argument_placeholders
|
||||||
completion_label_details.isSelected = value.completion_label_details
|
completion_label_details.isSelected = value.completion_label_details
|
||||||
enable_build_on_save.isSelected = value.enable_build_on_save
|
enable_build_on_save.isSelected = value.enable_build_on_save
|
||||||
build_on_save_args.text = value.build_on_save_args.joinToString(separator = " ") { it }
|
build_on_save_args.text = value.build_on_save_args
|
||||||
semantic_tokens.item = value.semantic_tokens
|
semantic_tokens.item = value.semantic_tokens
|
||||||
inlay_hints_show_variable_type_hints.isSelected = value.inlay_hints_show_variable_type_hints
|
inlay_hints_show_variable_type_hints.isSelected = value.inlay_hints_show_variable_type_hints
|
||||||
inlay_hints_show_struct_literal_field_type.isSelected = value.inlay_hints_show_struct_literal_field_type
|
inlay_hints_show_struct_literal_field_type.isSelected = value.inlay_hints_show_struct_literal_field_type
|
||||||
|
@ -257,6 +278,7 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr
|
||||||
builtin_path.text = value.builtin_path ?: ""
|
builtin_path.text = value.builtin_path ?: ""
|
||||||
build_runner_path.text = value.build_runner_path ?: ""
|
build_runner_path.text = value.build_runner_path ?: ""
|
||||||
global_cache_path.text = value.global_cache_path ?: ""
|
global_cache_path.text = value.global_cache_path ?: ""
|
||||||
|
dispatchUpdateUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun dispatchAutodetect(force: Boolean) {
|
private fun dispatchAutodetect(force: Boolean) {
|
||||||
|
@ -272,12 +294,14 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr
|
||||||
getDirenv().findExecutableOnPATH("zls")?.let {
|
getDirenv().findExecutableOnPATH("zls")?.let {
|
||||||
if (force || zlsPath.text.isBlank()) {
|
if (force || zlsPath.text.isBlank()) {
|
||||||
zlsPath.text = it.pathString
|
zlsPath.text = it.pathString
|
||||||
|
dispatchUpdateUI()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
|
debounce?.cancel("Disposed")
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getDirenv(): Env {
|
private suspend fun getDirenv(): Env {
|
||||||
|
@ -285,6 +309,42 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr
|
||||||
return project.getDirenv()
|
return project.getDirenv()
|
||||||
return emptyEnv
|
return emptyEnv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun dispatchUpdateUI() {
|
||||||
|
debounce?.cancel("New debounce")
|
||||||
|
debounce = project.zigCoroutineScope.launch {
|
||||||
|
updateUI()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun updateUI() {
|
||||||
|
if (project.isDefault)
|
||||||
|
return
|
||||||
|
delay(200)
|
||||||
|
val zlsPath = this.zlsPath.text.ifBlank { null }?.toNioPathOrNull()
|
||||||
|
if (zlsPath == null) {
|
||||||
|
withEDTContext(ModalityState.any()) {
|
||||||
|
zlsVersion.text = "[zls path empty or invalid]"
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val workingDir = project.guessProjectDir()?.toNioPathOrNull()
|
||||||
|
val result = createCommandLineSafe(workingDir, zlsPath, "version")
|
||||||
|
.map { it.withEnvironment(getDirenv().env) }
|
||||||
|
.mapFlat { it.call() }
|
||||||
|
.getOrElse { throwable ->
|
||||||
|
throwable.printStackTrace()
|
||||||
|
withEDTContext(ModalityState.any()) {
|
||||||
|
zlsVersion.text = "[failed to run \"zls version\"]\n${throwable.message}"
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val version = result.stdout
|
||||||
|
withEDTContext(ModalityState.any()) {
|
||||||
|
zlsVersion.text = version
|
||||||
|
zlsVersion.foreground = JBColor.foreground()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Panel.fancyRow(
|
private fun Panel.fancyRow(
|
||||||
|
@ -294,80 +354,4 @@ private fun Panel.fancyRow(
|
||||||
) = row(ZLSBundle.message(label)) {
|
) = row(ZLSBundle.message(label)) {
|
||||||
contextHelp(ZLSBundle.message(tooltip))
|
contextHelp(ZLSBundle.message(tooltip))
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Throws(Exception::class)
|
|
||||||
private fun translateCommandline(toProcess: String): List<String> {
|
|
||||||
if (toProcess.isEmpty()) {
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
val normal = 0
|
|
||||||
val inQuote = 1
|
|
||||||
val inDoubleQuote = 2
|
|
||||||
val inEscape = 3
|
|
||||||
var state = normal
|
|
||||||
var escapeState = normal
|
|
||||||
val tok = StringTokenizer(toProcess, "\\\"' ", true)
|
|
||||||
val v = ArrayList<String>()
|
|
||||||
val current = StringBuilder()
|
|
||||||
|
|
||||||
while (tok.hasMoreTokens()) {
|
|
||||||
val nextTok = tok.nextToken()
|
|
||||||
when (state) {
|
|
||||||
inQuote -> if ("'" == nextTok) {
|
|
||||||
state = normal
|
|
||||||
} else if ("\\" == nextTok) {
|
|
||||||
escapeState = inQuote
|
|
||||||
state = inEscape
|
|
||||||
} else {
|
|
||||||
current.append(nextTok)
|
|
||||||
}
|
|
||||||
|
|
||||||
inDoubleQuote -> if ("\"" == nextTok) {
|
|
||||||
state = normal
|
|
||||||
} else if ("\\" == nextTok) {
|
|
||||||
escapeState = inDoubleQuote
|
|
||||||
state = inEscape
|
|
||||||
} else {
|
|
||||||
current.append(nextTok)
|
|
||||||
}
|
|
||||||
|
|
||||||
inEscape -> {
|
|
||||||
current.append(when(nextTok) {
|
|
||||||
"n" -> "\n"
|
|
||||||
"r" -> "\r"
|
|
||||||
"t" -> "\t"
|
|
||||||
else -> nextTok
|
|
||||||
})
|
|
||||||
state = escapeState
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> if ("'" == nextTok) {
|
|
||||||
state = inQuote
|
|
||||||
} else if ("\"" == nextTok) {
|
|
||||||
state = inDoubleQuote
|
|
||||||
} else if (" " == nextTok) {
|
|
||||||
if (current.isNotEmpty()) {
|
|
||||||
v.add(current.toString())
|
|
||||||
current.setLength(0)
|
|
||||||
}
|
|
||||||
} else if ("\\" == nextTok) {
|
|
||||||
escapeState = normal
|
|
||||||
state = inEscape
|
|
||||||
} else {
|
|
||||||
current.append(nextTok)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current.isNotEmpty()) {
|
|
||||||
v.add(current.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state != inQuote && state != inDoubleQuote) {
|
|
||||||
return v
|
|
||||||
} else {
|
|
||||||
throw IllegalArgumentException("unbalanced quotes in $toProcess")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -39,12 +39,11 @@ class ToolchainZLSConfigProvider: SuspendingZLSConfigProvider {
|
||||||
var state = svc.state
|
var state = svc.state
|
||||||
val toolchain = state.toolchain ?: ZigToolchainProvider.suggestToolchain(project, UserDataHolderBase()) ?: return previous
|
val toolchain = state.toolchain ?: ZigToolchainProvider.suggestToolchain(project, UserDataHolderBase()) ?: return previous
|
||||||
|
|
||||||
val env = toolchain.zig.getEnv(project)
|
val env = toolchain.zig.getEnv(project).getOrElse { throwable ->
|
||||||
|
throwable.printStackTrace()
|
||||||
if (env == null) {
|
|
||||||
Notification(
|
Notification(
|
||||||
"zigbrains-lsp",
|
"zigbrains-lsp",
|
||||||
"Failed to evaluate zig env",
|
"Failed to evaluate \"zig env\": ${throwable.message}",
|
||||||
NotificationType.ERROR
|
NotificationType.ERROR
|
||||||
).notify(project)
|
).notify(project)
|
||||||
return previous
|
return previous
|
||||||
|
|
|
@ -45,6 +45,10 @@
|
||||||
/>
|
/>
|
||||||
<postStartupActivity
|
<postStartupActivity
|
||||||
implementation="com.falsepattern.zigbrains.lsp.ZLSStartup"/>
|
implementation="com.falsepattern.zigbrains.lsp.ZLSStartup"/>
|
||||||
|
|
||||||
|
<editorNotificationProvider
|
||||||
|
implementation="com.falsepattern.zigbrains.lsp.notification.ZigEditorNotificationProvider"
|
||||||
|
/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="com.falsepattern.zigbrains">
|
<extensions defaultExtensionNs="com.falsepattern.zigbrains">
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
settings.group.title=ZLS Settings
|
settings.group.title=ZLS Settings
|
||||||
settings.zls-path.label=Executable path
|
settings.zls-path.label=Executable path
|
||||||
settings.zls-path.tooltip=Path to the ZLS Binary
|
settings.zls-path.tooltip=Path to the ZLS Binary
|
||||||
settings.zls-path.browse.title=Path to the ZLS Binary
|
settings.zls-path.browse.title=Path to the ZLS Binary
|
||||||
|
settings.zls-version.label=Detected ZLS version
|
||||||
settings.zls-config-path.label=Config path
|
settings.zls-config-path.label=Config path
|
||||||
settings.zls-config-path.tooltip=Leave empty to use built-in config generated from the settings below
|
settings.zls-config-path.tooltip=Leave empty to use built-in config generated from the settings below
|
||||||
settings.zls-config-path.browse.title=Path to the Custom ZLS Config File (Optional)
|
settings.zls-config-path.browse.title=Path to the Custom ZLS Config File (Optional)
|
||||||
|
@ -59,6 +60,8 @@ notification.message.zls-config-not-exists.content=ZLS config file does not exis
|
||||||
notification.message.zls-config-not-file.content=ZLS config file is not a regular file: {0}
|
notification.message.zls-config-not-file.content=ZLS config file is not a regular file: {0}
|
||||||
notification.message.zls-config-path-invalid.content=ZLS config path could not be parted: {0}
|
notification.message.zls-config-path-invalid.content=ZLS config path could not be parted: {0}
|
||||||
notification.message.zls-config-autogen-failed.content=Failed to autogenerate ZLS config from toolchain
|
notification.message.zls-config-autogen-failed.content=Failed to autogenerate ZLS config from toolchain
|
||||||
|
notification.banner.zls-not-running=Zig Language Server is not running. Check the [Language Servers] tool menu!
|
||||||
|
notification.banner.zls-bad-config=Zig Language Server is misconfigured. Check [Settings | Languages \\& Frameworks | Zig]!
|
||||||
progress.title.create-connection-provider=Creating ZLS connection provider
|
progress.title.create-connection-provider=Creating ZLS connection provider
|
||||||
progress.title.validate=Validating ZLS
|
progress.title.validate=Validating ZLS
|
||||||
# suppress inspection "UnusedProperty"
|
# suppress inspection "UnusedProperty"
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<depends config-file="zigbrains-core.xml">com.intellij.modules.platform</depends>
|
<depends config-file="zigbrains-core.xml">com.intellij.modules.platform</depends>
|
||||||
<depends config-file="zigbrains-lsp.xml">com.redhat.devtools.lsp4ij</depends>
|
<depends config-file="zigbrains-lsp.xml">com.redhat.devtools.lsp4ij</depends>
|
||||||
<depends config-file="zigbrains-debugger.xml" optional="true">com.intellij.nativeDebug</depends>
|
<depends config-file="zigbrains-debugger.xml" optional="true">com.intellij.modules.cidr.debugger</depends>
|
||||||
<depends config-file="zigbrains-cidr.xml" optional="true">com.intellij.cidr.base</depends>
|
<depends config-file="zigbrains-cidr.xml" optional="true">com.intellij.cidr.base</depends>
|
||||||
<depends config-file="zigbrains-clion.xml" optional="true">com.intellij.clion</depends>
|
<depends config-file="zigbrains-clion.xml" optional="true">com.intellij.clion</depends>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue