Skip to content

Commit

Permalink
Merge pull request #99 from alexander-doroshko/main
Browse files Browse the repository at this point in the history
Remove usages of deprecated LSP API
  • Loading branch information
ajbt200128 authored Nov 27, 2024
2 parents d57fa1b + 1115d8d commit 732350a
Show file tree
Hide file tree
Showing 19 changed files with 86 additions and 186 deletions.
21 changes: 10 additions & 11 deletions src/main/kotlin/com/semgrep/idea/actions/LoginAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@ package com.semgrep.idea.actions

import com.intellij.ide.BrowserUtil
import com.intellij.notification.Notification
import com.intellij.openapi.actionSystem.AnActionEvent
import com.semgrep.idea.lsp.custom_notifications.LoginFinishRequest
import com.semgrep.idea.lsp.custom_requests.LoginRequest
import com.intellij.platform.lsp.api.LspServer
import com.semgrep.idea.lsp.SemgrepLanguageServer
import com.semgrep.idea.lsp.SemgrepService
import kotlinx.coroutines.launch

class LoginAction(private val notification: Notification? = null) : LspAction("Sign In with Semgrep") {
override fun actionPerformed(e: AnActionEvent, servers: List<com.semgrep.idea.lsp.SemgrepLspServer>) {
val loginRequest = LoginRequest(servers.first())
loginRequest.sendRequest().thenApply { response ->
BrowserUtil.browse(response.url)
servers.forEach {
LoginFinishRequest(it, response).sendNotification()
}
override fun actionPerformed(lspServer: LspServer) {
SemgrepService.getInstance(lspServer.project).cs.launch {
val loginResult = lspServer.sendRequest { (it as SemgrepLanguageServer).login() }
?: return@launch
BrowserUtil.browse(loginResult.url)
lspServer.sendNotification { (it as SemgrepLanguageServer).loginFinish(loginResult) }
notification?.expire()
}

}
}
10 changes: 4 additions & 6 deletions src/main/kotlin/com/semgrep/idea/actions/LogoutAction.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package com.semgrep.idea.actions

import com.intellij.openapi.actionSystem.AnActionEvent
import com.semgrep.idea.lsp.custom_notifications.LogoutNotifcation
import com.intellij.platform.lsp.api.LspServer
import com.semgrep.idea.lsp.SemgrepLanguageServer

class LogoutAction : LspAction("Sign out of Semgrep") {
override fun actionPerformed(e: AnActionEvent, servers: List<com.semgrep.idea.lsp.SemgrepLspServer>) {
servers.map {
LogoutNotifcation(it).sendNotification()
}
override fun actionPerformed(lspServer: LspServer) {
lspServer.sendNotification { (it as SemgrepLanguageServer).logout() }
}
}
11 changes: 5 additions & 6 deletions src/main/kotlin/com/semgrep/idea/actions/LspAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ package com.semgrep.idea.actions

import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.platform.lsp.api.LspServer
import com.semgrep.idea.lsp.SemgrepService

abstract class LspAction(text: String) : AnAction(text) {
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
val servers = com.semgrep.idea.lsp.SemgrepLspServer.getInstances(project)
if (servers.isEmpty()) {
return
}
actionPerformed(e, servers)
val lspServer = SemgrepService.getRunningLspServer(project) ?: return
actionPerformed(lspServer)
}

abstract fun actionPerformed(e: AnActionEvent, servers: List<com.semgrep.idea.lsp.SemgrepLspServer>)
abstract fun actionPerformed(lspServer: LspServer)
}
10 changes: 4 additions & 6 deletions src/main/kotlin/com/semgrep/idea/actions/RefreshRulesAction.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package com.semgrep.idea.actions

import com.intellij.openapi.actionSystem.AnActionEvent
import com.semgrep.idea.lsp.custom_notifications.RefreshRulesNotification
import com.intellij.platform.lsp.api.LspServer
import com.semgrep.idea.lsp.SemgrepLanguageServer

class RefreshRulesAction : LspAction("Update Semgrep Rules") {
override fun actionPerformed(e: AnActionEvent, servers: List<com.semgrep.idea.lsp.SemgrepLspServer>) {
servers.map {
RefreshRulesNotification(it).sendNotification()
}
override fun actionPerformed(lspServer: LspServer) {
lspServer.sendNotification { (it as SemgrepLanguageServer).refreshRules() }
}
}
12 changes: 5 additions & 7 deletions src/main/kotlin/com/semgrep/idea/actions/ScanWorkspaceAction.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package com.semgrep.idea.actions

import com.intellij.openapi.actionSystem.AnActionEvent
import com.semgrep.idea.lsp.custom_notifications.ScanWorkspaceNotification
import com.semgrep.idea.lsp.custom_notifications.ScanWorkspaceParams
import com.intellij.platform.lsp.api.LspServer
import com.semgrep.idea.lsp.SemgrepLanguageServer

class ScanWorkspaceAction : LspAction("Scan Workspace with Semgrep") {
override fun actionPerformed(e: AnActionEvent, servers: List<com.semgrep.idea.lsp.SemgrepLspServer>) {
val params = ScanWorkspaceParams(full = false)
servers.map { ScanWorkspaceNotification(it, params).sendNotification() }
override fun actionPerformed(lspServer: LspServer) {
val params = SemgrepLanguageServer.ScanWorkspaceParams(full = false)
lspServer.sendNotification { (it as SemgrepLanguageServer).scanWorkspace(params) }
}

}
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package com.semgrep.idea.actions

import com.intellij.openapi.actionSystem.AnActionEvent
import com.semgrep.idea.lsp.custom_notifications.ScanWorkspaceNotification
import com.semgrep.idea.lsp.custom_notifications.ScanWorkspaceParams
import com.intellij.platform.lsp.api.LspServer
import com.semgrep.idea.lsp.SemgrepLanguageServer

class ScanWorkspaceFullAction : LspAction("Scan Workspace with Semgrep (Including Unmodified Files)") {
override fun actionPerformed(e: AnActionEvent, servers: List<com.semgrep.idea.lsp.SemgrepLspServer>) {
val params = ScanWorkspaceParams(full = true)
servers.map { ScanWorkspaceNotification(it, params).sendNotification() }
override fun actionPerformed(lspServer: LspServer) {
val params = SemgrepLanguageServer.ScanWorkspaceParams(full = true)
lspServer.sendNotification { (it as SemgrepLanguageServer).scanWorkspace(params) }
}

}
8 changes: 4 additions & 4 deletions src/main/kotlin/com/semgrep/idea/lsp/FileSaveManager.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
package com.semgrep.idea.lsp

import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.newvfs.BulkFileListener
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
import org.eclipse.lsp4j.DidSaveTextDocumentParams
import org.eclipse.lsp4j.TextDocumentIdentifier
import java.net.URLEncoder

class FileSaveManager(private val semgrepLspServer: SemgrepLspServer) : BulkFileListener {
class FileSaveManager(private val project: Project) : BulkFileListener {
override fun after(events: MutableList<out VFileEvent>) {
val lspServer = SemgrepService.getRunningLspServer(project) ?: return
val saveEvents = events.filter { it.isFromSave }
saveEvents.forEach {
val uri = URLEncoder.encode(it.path, "UTF-8")
val textDocumentIdentifier = TextDocumentIdentifier(uri)
val params = DidSaveTextDocumentParams(textDocumentIdentifier)
semgrepLspServer.lsp4jServer.textDocumentService.didSave(params)
lspServer.sendNotification { it.textDocumentService.didSave(params) }
}
super.after(events)

}
}
4 changes: 3 additions & 1 deletion src/main/kotlin/com/semgrep/idea/lsp/SemgrepInstaller.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.intellij.javascript.nodejs.interpreter.NodeJsInterpreter
import com.intellij.javascript.nodejs.interpreter.NodeJsInterpreterManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.SystemInfo
import com.intellij.platform.lsp.api.LspServerManager
import com.intellij.util.text.SemVer
import com.semgrep.idea.settings.AppState
import com.semgrep.idea.settings.SemgrepLspSettings
Expand Down Expand Up @@ -33,7 +34,8 @@ object SemgrepInstaller {
val semgrepNotifier = SemgrepNotifier(project)
if (ret == 0) {
semgrepNotifier.notifyInstallSuccess()
SemgrepLspServer.startServersIfNeeded(project)
LspServerManager.getInstance(project)
.stopAndRestartIfNeeded(SemgrepLspServerSupportProvider::class.java)
} else {
semgrepNotifier.notifyInstallFailure(out, ret)
}
Expand Down
7 changes: 4 additions & 3 deletions src/main/kotlin/com/semgrep/idea/lsp/SemgrepLanguageServer.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package com.semgrep.idea.lsp

import com.semgrep.idea.lsp.custom_notifications.ScanWorkspaceParams
import com.semgrep.idea.lsp.custom_requests.LoginResult
import com.semgrep.idea.lsp.custom_requests.LoginStatusResult
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest
import org.eclipse.lsp4j.services.LanguageServer
Expand Down Expand Up @@ -34,4 +31,8 @@ interface SemgrepLanguageServer : LanguageServer {
@JsonNotification("semgrep/refreshRules")
fun refreshRules(params: List<Void> = emptyList())


class LoginResult(val url: String, @Suppress("unused") val sessionId: String)
class LoginStatusResult(val loggedIn: Boolean)
class ScanWorkspaceParams(@Suppress("unused") val full: Boolean)
}
33 changes: 0 additions & 33 deletions src/main/kotlin/com/semgrep/idea/lsp/SemgrepLspServer.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,6 @@ class SemgrepLspServerDescriptor(project: Project) : ProjectWideLspServerDescrip
return SemgrepLsp4jClient(handler)
}

override val lspServerListener: LspServerListener = SemgrepLspServerListener(project)
override val lspServerListener: LspServerListener =
SemgrepLspServerListener(project, clientCapabilities.textDocument?.synchronization?.didSave == true)
}
35 changes: 17 additions & 18 deletions src/main/kotlin/com/semgrep/idea/lsp/SemgrepLspServerListener.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,30 @@ package com.semgrep.idea.lsp
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.platform.lsp.api.LspServerListener
import com.semgrep.idea.lsp.custom_requests.LoginStatusRequest
import com.semgrep.idea.settings.AppState
import com.semgrep.idea.telemetry.SentryWrapper
import com.semgrep.idea.ui.SemgrepNotifier
import kotlinx.coroutines.launch
import org.eclipse.lsp4j.InitializeResult

class SemgrepLspServerListener(val project: Project) : LspServerListener {
class SemgrepLspServerListener(
private val project: Project,
private val nativeDidSaveSupport: Boolean,
) : LspServerListener {

fun checkNudge() {
val settings = AppState.getInstance()
val servers = SemgrepLspServer.getInstances(project)
val first = servers.firstOrNull()
// Check if we've bugged them about logging in
if (first != null && !settings.pluginState.dismissedLoginNudge) {
val loginStatusRequest = LoginStatusRequest(first)
loginStatusRequest.sendRequest().handle { it, _ ->
settings.pluginState.loggedIn = it.loggedIn
SentryWrapper.getInstance().setSentryContext()
if (!it.loggedIn) {
SemgrepNotifier(project).notifyLoginNudge()
}
if (settings.pluginState.dismissedLoginNudge) return
val lspServer = SemgrepService.getRunningLspServer(project) ?: return
SemgrepService.getInstance(project).cs.launch {
val loginStatusResult = lspServer.sendRequest { (it as SemgrepLanguageServer).loginStatus() }
val loggedIn = loginStatusResult != null && loginStatusResult.loggedIn
settings.pluginState.loggedIn = loggedIn
SentryWrapper.getInstance().setSentryContext()
if (!loggedIn) {
SemgrepNotifier(project).notifyLoginNudge()
}

}
}

Expand Down Expand Up @@ -55,12 +56,10 @@ class SemgrepLspServerListener(val project: Project) : LspServerListener {
}

override fun serverInitialized(params: InitializeResult) {
super.serverInitialized(params)
val sentry = SentryWrapper.getInstance()

SemgrepLspServer.getInstances(project).forEach {
project.messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, FileSaveManager(it))
if (!nativeDidSaveSupport) {
project.messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, FileSaveManager(project))
}
val sentry = SentryWrapper.getInstance()
sentry.withSentry {
checkNudge()
checkVersion()
Expand Down
23 changes: 23 additions & 0 deletions src/main/kotlin/com/semgrep/idea/lsp/SemgrepService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.semgrep.idea.lsp

import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.platform.lsp.api.LspServer
import com.intellij.platform.lsp.api.LspServerManager
import com.intellij.platform.lsp.api.LspServerState
import kotlinx.coroutines.CoroutineScope

@Service(Service.Level.PROJECT)
class SemgrepService(val cs: CoroutineScope) {
companion object {
fun getInstance(project: Project): SemgrepService = project.service<SemgrepService>()

// There might be no more than one running server
// because `SemgrepLspServerDescriptor` extends `ProjectWideLspServerDescriptor`
fun getRunningLspServer(project: Project): LspServer? =
LspServerManager.getInstance(project)
.getServersForProvider(SemgrepLspServerSupportProvider::class.java)
.firstOrNull { it.state == LspServerState.Running }
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit 732350a

Please sign in to comment.