Skip to content

Commit

Permalink
GH-1 All the necessary reworks
Browse files Browse the repository at this point in the history
Signed-off-by: Uladzislau <[email protected]>
  • Loading branch information
KUGDev committed Jun 27, 2024
1 parent cc5d0a8 commit 6788ea2
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 99 deletions.
18 changes: 18 additions & 0 deletions .idea/LanguageServersSettings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions src/main/kotlin/org/zowe/cobol/CobolProjectManagerListener.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.project.ProjectManagerListener
import org.zowe.cobol.init.CobolPluginState
import org.zowe.cobol.init.InitializationOnly
import org.zowe.cobol.state.CobolPluginState
import org.zowe.cobol.state.InitializationOnly
import org.zowe.cobol.state.LanguageSupportStateService

// TODO: doc
/** COBOL project manager listener. Listens to projects changes and react to them respectively */
class CobolProjectManagerListener : ProjectManagerListener {

/**
Expand All @@ -32,10 +32,10 @@ class CobolProjectManagerListener : ProjectManagerListener {
@OptIn(InitializationOnly::class)
override fun projectClosing(project: Project) {
val lsStateService = service<LanguageSupportStateService>()
val pluginState = lsStateService.getPluginState(project) { CobolPluginState() }
val pluginState = lsStateService.getPluginState(project) { CobolPluginState(project) }

if (isLastProjectClosing()) {
pluginState.disableTextMateBundle {}
pluginState.unloadLSPClient {}
pluginState.finishDeinitialization {}
}
}
Expand Down
40 changes: 18 additions & 22 deletions src/main/kotlin/org/zowe/cobol/lsp/CobolLanguageServerFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,43 +18,39 @@ import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.redhat.devtools.lsp4ij.LanguageServerFactory
import com.redhat.devtools.lsp4ij.client.LanguageClientImpl
import com.redhat.devtools.lsp4ij.server.JavaProcessCommandBuilder
import com.redhat.devtools.lsp4ij.server.ProcessStreamConnectionProvider
import com.redhat.devtools.lsp4ij.server.StreamConnectionProvider
import org.zowe.cobol.init.COBOL_PLUGIN_NOTIFICATION_ID
import org.zowe.cobol.init.CobolPluginState
import org.zowe.cobol.init.InitializationOnly
import org.zowe.cobol.state.COBOL_PLUGIN_NOTIFICATION_ID
import org.zowe.cobol.state.CobolPluginState
import org.zowe.cobol.state.InitializationOnly
import org.zowe.cobol.state.LanguageSupportStateService

// TODO: doc
@OptIn(InitializationOnly::class)
/** COBOL language server factory to provide all the necessary functionalities for COBOL language support in the IDE */
class CobolLanguageServerFactory : LanguageServerFactory {

override fun createConnectionProvider(project: Project): StreamConnectionProvider {
val lsStateService = service<LanguageSupportStateService>()
val pluginState = lsStateService.getPluginState(project) { CobolPluginState() }
val pluginState = lsStateService.getPluginState(project) { CobolPluginState(project) }

pluginState.prepareVSIX {}

lateinit var lspRunCommands: MutableList<String>
pluginState.prepareLSP { lspServerPathString ->
lspRunCommands = JavaProcessCommandBuilder(project, "cobol")
.setJar(lspServerPathString)
.create()
lspRunCommands.add("pipeEnabled")
@OptIn(InitializationOnly::class)
if (!pluginState.isLSPServerConnectionReady()) {
pluginState.prepareVSIX {}
pluginState.prepareLSPServerConnection {}
}
return object : ProcessStreamConnectionProvider(lspRunCommands) {}

return pluginState.getReadyLSPServerConnection() as StreamConnectionProvider
}

override fun createLanguageClient(project: Project): LanguageClientImpl {
val lsStateService = service<LanguageSupportStateService>()
val pluginState = lsStateService.getPluginState(project) { CobolPluginState() }
val pluginState = lsStateService.getPluginState(project) { CobolPluginState(project) }

pluginState.prepareTextMateBundle {}
@OptIn(InitializationOnly::class)
if (!pluginState.isLSPClientReady()) {
pluginState.prepareLSPClient {}
pluginState.finishInitialization(COBOL_PLUGIN_NOTIFICATION_ID) {}
}

lateinit var languageClient: LanguageClientImpl
pluginState.finishInitialization(COBOL_PLUGIN_NOTIFICATION_ID) { languageClient = CobolLanguageClient(project)}
return languageClient
return pluginState.getReadyLSPClient() as LanguageClientImpl
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,28 @@
* Zowe Community
*/

package org.zowe.cobol.init
package org.zowe.cobol.state

import com.intellij.openapi.application.PathManager
import com.intellij.openapi.project.Project
import com.intellij.util.io.ZipUtil
import com.jetbrains.rd.util.firstOrNull
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jetbrains.plugins.textmate.TextMateService
import org.jetbrains.plugins.textmate.configuration.TextMateUserBundlesSettings
import com.intellij.openapi.util.io.FileUtil
import com.redhat.devtools.lsp4ij.client.LanguageClientImpl
import com.redhat.devtools.lsp4ij.server.JavaProcessCommandBuilder
import com.redhat.devtools.lsp4ij.server.ProcessStreamConnectionProvider
import com.redhat.devtools.lsp4ij.server.StreamConnectionProvider
import kotlinx.coroutines.runBlocking
import org.zowe.cobol.state.LanguageSupportState
import org.zowe.cobol.lsp.CobolLanguageClient
import java.nio.file.Path
import kotlin.io.path.exists
import kotlin.io.path.pathString

val COBOL_PLUGIN_NOTIFICATION_ID = "org.zowe.cobol.CobolNotificationId"
const val COBOL_PLUGIN_NOTIFICATION_ID = "org.zowe.cobol.CobolNotificationId"

// https://github.com/eclipse-che4z/che-che4z-lsp-for-cobol
private const val VSIX_NAME = "cobol-language-support"
Expand All @@ -38,15 +43,33 @@ private const val TEXTMATE_BUNDLE_NAME = "cobol"
/**
* State of the COBOL plug-in. Provides initialization methods to set up all the things before the correct usage of
* the syntax highlighting and the LSP features
* @property project the project related to the plug-in's state
*/
@OptIn(InitializationOnly::class)
@InitializationOnly
class CobolPluginState : LanguageSupportState() {
class CobolPluginState(private val project: Project) : LanguageSupportState() {

private lateinit var vsixPlacingRootPath: Path
private lateinit var vsixUnpackedPath: Path
private lateinit var packageJsonPath: Path
private lateinit var lspServerPath: Path
private lateinit var lspServerConnection: StreamConnectionProvider
private lateinit var lspClient: LanguageClientImpl

override fun isLSPServerConnectionReady(): Boolean {
return ::lspServerConnection.isInitialized
}

override fun getReadyLSPServerConnection(): Any {
return if (isLSPServerConnectionReady()) lspServerConnection else throw IllegalStateException("LSP server connection is not ready")
}

override fun isLSPClientReady(): Boolean {
return ::lspClient.isInitialized
}

override fun getReadyLSPClient(): Any {
return if (isLSPClientReady()) lspClient else throw IllegalStateException("LSP client is not ready")
}

/**
* Compute all the paths needed for the plug-in's setup
Expand All @@ -62,10 +85,13 @@ class CobolPluginState : LanguageSupportState() {
}

/**
* TODO: docs update
* Unzip .vsix file in the 'resources' folder into the 'build' path, and later use the unzipped files to activate
* a TextMate bundle and an LSP server. If the paths of the unzipped .vsix are already exist, the processing is skipped
* Unzip .vsix file in the 'resources' folder into the 'build' path,
* and later use the unzipped files to activate a TextMate bundle and an LSP server connection.
* If the paths of the unzipped .vsix are already exist, the processing is skipped
* @param prepFun the function for additional preparation steps after the VSIX package is prepared
* @see [LanguageSupportState.prepareVSIX]
*/
@InitializationOnly
override fun prepareVSIX(prepFun: () -> Unit) {
super.prepareVSIX {
runBlocking {
Expand All @@ -88,24 +114,35 @@ class CobolPluginState : LanguageSupportState() {
}
}

// TODO: doc
/** Initialize language server definition. Will run the LSP server command */
override fun prepareLSP(prepFun: (String) -> Unit) {
return super.prepareLSP {
prepFun(lspServerPath.pathString)
/**
* Initialize language server definition. Will run the LSP server command
* @param prepFun the function for additional preparation steps after the LSP server connection instance is prepared
* @see [LanguageSupportState.prepareLSPServerConnection]
*/
@InitializationOnly
override fun prepareLSPServerConnection(prepFun: () -> Unit) {
return super.prepareLSPServerConnection {
val lspRunCommands = JavaProcessCommandBuilder(project, "cobol")
.setJar(lspServerPath.pathString)
.create()
lspRunCommands.add("pipeEnabled")
lspServerConnection = object : ProcessStreamConnectionProvider(lspRunCommands) {}
prepFun()
}
}

/**
* TODO: docs update
* Load a TextMate bundle from previously unzipped .vsix. The version of the bundle to activate is the same as the
* .vsix package has. If there is an already activated version of the bundle with the same name, it will be deleted
* if the version is less than the one it is trying to activate. If the versions are the same, or there are any
* troubles unzipping/using the provided bundle, the processing does not continue, and the bundle that is already
* loaded to the IDE stays there
* loaded to the IDE stays there. As the finishing step, prepares the COBOL LSP client instance
* @param prepFun the function for additional preparation steps after the LSP client instance is prepared
* @see [LanguageSupportState.prepareLSPClient]
*/
override fun prepareTextMateBundle(prepFun: () -> Unit) {
super.prepareTextMateBundle {
@InitializationOnly
override fun prepareLSPClient(prepFun: () -> Unit) {
super.prepareLSPClient {
val emptyBundleName = "$TEXTMATE_BUNDLE_NAME-0.0.0"
val newBundleName = "$TEXTMATE_BUNDLE_NAME-$VSIX_VERSION"
var existingBundles = TextMateUserBundlesSettings.instance?.bundles
Expand All @@ -119,19 +156,24 @@ class CobolPluginState : LanguageSupportState() {
TextMateUserBundlesSettings.instance?.addBundle(vsixUnpackedPath.toString(), newBundleName)
TextMateService.getInstance().reloadEnabledBundles()
}
lspClient = CobolLanguageClient(project)
prepFun()
}
}

// TODO: docs adjust
/** Disable the COBOL plug-in TextMate bundle before the plug-in is unloaded */
override fun disableTextMateBundle(disableFun: () -> Unit) {
super.disableTextMateBundle {
/**
* Disable the COBOL plug-in TextMate bundle before the plug-in is unloaded
* @param unloadFun the function for additional unloading steps before the LSP client instance is unloaded
* @see [LanguageSupportState.unloadLSPClient]
*/
@InitializationOnly
override fun unloadLSPClient(unloadFun: () -> Unit) {
super.unloadLSPClient {
unloadFun()
var existingBundles = TextMateUserBundlesSettings.instance?.bundles
existingBundles = existingBundles?.filter { it.value.name.contains(TEXTMATE_BUNDLE_NAME) } ?: emptyMap()
TextMateUserBundlesSettings.instance?.setBundlesConfig(existingBundles)
TextMateService.getInstance().reloadEnabledBundles()
disableFun()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@
* Zowe Community
*/

package org.zowe.cobol.init
package org.zowe.cobol.state

/** Initialization states enum class to represent available plug-in's states */
enum class InitStates {
DOWN,
TEXTMATE_BUNDLE_UNLOADED,
TEXTMATE_BUNDLE_UNLOAD_TRIGGERED,
VSIX_UNPACK_TRIGGERED,
VSIX_UNPACKED,
LSP_INIT_TRIGGERED,
LSP_INITIALIZED,
TEXTMATE_BUNDLE_LOAD_TRIGGERED,
TEXTMATE_BUNDLE_LOADED,
LSP_CLIENT_UNLOADED,
LSP_CLIENT_UNLOAD_TRIGGERED,
VSIX_PREPARE_TRIGGERED,
VSIX_PREPARED,
LSP_SERVER_CONNECTION_PREPARE_TRIGGERED,
LSP_SERVER_CONNECTION_PREPARED,
LSP_CLIENT_PREPARE_TRIGGERED,
LSP_CLIENT_PREPARED,
UP
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* Zowe Community
*/

package org.zowe.cobol.init
package org.zowe.cobol.state

/**
* Annotation for the restricted initialization methods.
Expand Down
Loading

0 comments on commit 6788ea2

Please sign in to comment.