Skip to content

Commit

Permalink
Merge branch 'master' into update_enterprise_marketplace_160823
Browse files Browse the repository at this point in the history
  • Loading branch information
avichay77 authored Aug 17, 2023
2 parents c2e5b2e + 9c645f5 commit 6385c15
Show file tree
Hide file tree
Showing 17 changed files with 176 additions and 65 deletions.
1 change: 0 additions & 1 deletion .github/workflows/production-new-version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ jobs:
git push origin v$NEW_VERSION
publish-production:
if: false
name: Publish to PRODUCTION
runs-on: ubuntu-latest
needs:
Expand Down
9 changes: 3 additions & 6 deletions Common/src/main/java/com/tabnineCommon/chat/ChatBrowser.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.tabnineCommon.chat

import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.ui.jcef.JBCefApp
Expand Down Expand Up @@ -97,12 +96,10 @@ class ChatBrowser(messagesRouter: ChatMessagesRouter, project: Project) {
messagesRouter: ChatMessagesRouter
) {
Logger.getInstance(javaClass).trace("Received message: $it")
val response = messagesRouter.handleRawMessage(it, project)

ApplicationManager.getApplication().invokeLater {
val response = messagesRouter.handleRawMessage(it, project)
Logger.getInstance(javaClass).trace("Sending response: $response")
browser.cefBrowser.executeJavaScript("window.postMessage($response, '*')", "", 0)
}
Logger.getInstance(javaClass).trace("Sending response: $response")
browser.cefBrowser.executeJavaScript("window.postMessage($response, '*')", "", 0)
}

private fun cefLoadHandler(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.tabnineCommon.chat
import InitHandler
import InsertAtCursorHandler
import com.google.gson.JsonElement
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.tabnineCommon.chat.commandHandlers.ChatMessageHandler
import com.tabnineCommon.chat.commandHandlers.GetUserHandler
Expand Down Expand Up @@ -44,10 +45,12 @@ class ChatMessagesRouter {
try {
val commandHandler = commandHandlers[request.command] ?: return noHandlerError(request)

val responsePayload = commandHandler.handleRaw(request.data, project) ?: return ChatMessageResponse(request.id)
val responsePayload =
commandHandler.handleRaw(request.data, project) ?: return ChatMessageResponse(request.id)

return ChatMessageResponse(request.id, responsePayload)
} catch (e: Exception) {
Logger.getInstance(ChatMessagesRouter::class.java).error("Failed to handle request '${request.command}'", e)
return ChatMessageResponse(request.id, error = e.message ?: e.toString())
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,19 @@
package com.tabnineCommon.chat

import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.wm.ToolWindow
import com.intellij.openapi.wm.ex.ToolWindowManagerListener
import com.tabnineCommon.capabilities.CapabilitiesService
import com.tabnineCommon.lifecycle.BinaryStateChangeNotifier
import com.tabnineCommon.lifecycle.BinaryStateService

class ChatToolWindowListener : ToolWindowManagerListener {
companion object {
const val TABNINE_CHAT_TOOL_WINDOW_ID = "Tabnine Chat"
const val MINIMAL_MS_BETWEEN_FORCE_REFRESH_CAPABILITIES = 2_000
}

private var isLoggedIn = false
private var lastForceRefreshCapabilities = System.currentTimeMillis()

init {
ApplicationManager.getApplication().messageBus.connect()
.subscribe(
BinaryStateChangeNotifier.STATE_CHANGED_TOPIC,
BinaryStateChangeNotifier { isLoggedIn = it.isLoggedIn ?: false }
)
}

override fun toolWindowShown(id: String, toolWindow: ToolWindow) {
super.toolWindowShown(id, toolWindow)

Expand All @@ -32,6 +23,10 @@ class ChatToolWindowListener : ToolWindowManagerListener {
}

private fun handleTabnineChatToolWindowShown() {
val isLoggedIn =
ServiceManager.getService(BinaryStateService::class.java).lastStateResponse?.isLoggedIn
?: false

if (isLoggedIn && !ChatEnabled.getInstance().enabled && isTimeForForceRefreshCapabilities()) {
lastForceRefreshCapabilities = System.currentTimeMillis()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.Project
import com.tabnineCommon.chat.commandHandlers.utils.ActionPermissions
import com.tabnineCommon.chat.commandHandlers.utils.AsyncAction

abstract class ChatMessageHandler<RequestPayload, ResponsePayload>(protected val gson: Gson) {
fun handleRaw(data: JsonElement?, project: Project): ResponsePayload? {
Expand All @@ -16,15 +18,17 @@ abstract class ChatMessageHandler<RequestPayload, ResponsePayload>(protected val
}

protected fun getEditorFromProject(project: Project): Editor? {
return try {
val fileEditor = FileEditorManager.getInstance(project).selectedEditor ?: return null
val dataContext = DataManager.getInstance().getDataContext(fileEditor.component)
return AsyncAction(ActionPermissions.WRITE).execute {
try {
val fileEditor = FileEditorManager.getInstance(project).selectedEditor ?: return@execute null
val dataContext = DataManager.getInstance().getDataContext(fileEditor.component)

CommonDataKeys.EDITOR.getData(dataContext)
} catch (e: Exception) {
Logger.getInstance(javaClass).error("Failed to get editor from project: ", e)
null
}
CommonDataKeys.EDITOR.getData(dataContext)
} catch (e: Exception) {
Logger.getInstance(javaClass).error("Failed to get editor from project: ", e)
null
}
}.get()
}

abstract fun handle(payload: RequestPayload?, project: Project): ResponsePayload?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import com.intellij.diff.DiffContext
import com.intellij.diff.contents.DiffContent
import com.intellij.diff.requests.SimpleDiffRequest
import com.intellij.diff.tools.simple.SimpleDiffViewer
import com.intellij.openapi.application.ReadAction
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogWrapper
import com.tabnineCommon.chat.commandHandlers.ChatMessageHandler
import com.tabnineCommon.chat.commandHandlers.utils.ActionPermissions
import com.tabnineCommon.chat.commandHandlers.utils.AsyncAction
import javax.swing.JComponent

data class InsertPayload(val code: String)
Expand All @@ -18,8 +21,13 @@ class InsertAtCursorHandler(gson: Gson) : ChatMessageHandler<InsertPayload, Unit
val code = payload?.code ?: return
val editor = getEditorFromProject(project) ?: return

val shouldInsertText = editor.selectionModel.selectedText?.let {
InsertDiffDialog(project, it, code).showAndGet()
val selectionText = ReadAction.compute<String?, Throwable> {
editor.selectionModel.selectedText
}
val shouldInsertText = selectionText?.let {
AsyncAction(ActionPermissions.WRITE).execute {
InsertDiffDialog(project, it, code).showAndGet()
}.get()
} ?: true

if (!shouldInsertText) return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import com.intellij.util.Processor
import com.tabnineCommon.chat.commandHandlers.utils.ActionPermissions
import com.tabnineCommon.chat.commandHandlers.utils.AsyncAction
import java.awt.Point
import java.util.concurrent.CompletableFuture

data class DiagnosticsContext(
private val diagnosticsText: String? = null,
Expand All @@ -16,7 +19,13 @@ data class DiagnosticsContext(
private val type: EnrichingContextType = EnrichingContextType.Diagnostics

companion object {
fun create(editor: Editor, project: Project): DiagnosticsContext? {
fun createFuture(editor: Editor, project: Project): CompletableFuture<DiagnosticsContext?> {
return AsyncAction(ActionPermissions.WRITE).execute {
create(editor, project)
}
}

private fun create(editor: Editor, project: Project): DiagnosticsContext? {
val visibleRange = getVisibleRange(editor) ?: return null
val highlights = mutableListOf<String>()

Expand Down Expand Up @@ -46,7 +55,7 @@ data class DiagnosticsContext(
return try {
TextRange(startOffset, endOffset)
} catch (e: IllegalArgumentException) {
Logger.getInstance(javaClass).warn("failed to get visible range", e)
Logger.getInstance(DiagnosticsContext::class.java).warn("failed to get visible range", e)
null
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package com.tabnineCommon.chat.commandHandlers.context
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange
import com.tabnineCommon.chat.commandHandlers.utils.ActionPermissions
import com.tabnineCommon.chat.commandHandlers.utils.AsyncAction
import java.util.concurrent.CompletableFuture

data class SelectedCode(val code: String, val filePath: String)

Expand All @@ -24,7 +27,12 @@ data class EditorContext(
}

companion object {
fun create(editor: Editor): EditorContext {
fun createFuture(editor: Editor): CompletableFuture<EditorContext> {
return AsyncAction(ActionPermissions.READ).execute {
create(editor)
}
}
private fun create(editor: Editor): EditorContext {
val fileCode = editor.document.text
val selectedCode = editor.selectionModel.selectedText ?: ""
val currentLineIndex = editor.caretModel.currentCaret.logicalPosition.line
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.tabnineCommon.chat.commandHandlers.context
import com.google.gson.Gson
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.intellij.openapi.application.ReadAction
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiDocumentManager
import com.tabnineCommon.binary.requests.fileMetadata.FileMetadataRequest
Expand All @@ -23,7 +24,11 @@ data class BasicContext(
class GetBasicContextHandler(gson: Gson) : ChatMessageHandler<Unit, BasicContext>(gson) {
private val binaryRequestFacade = DependencyContainer.instanceOfBinaryRequestFacade()

override fun handle(payload: Unit?, project: Project): BasicContext? {
override fun handle(payload: Unit?, project: Project): BasicContext {
return ReadAction.compute<BasicContext, Throwable> { createBasicContext(project) }
}

private fun createBasicContext(project: Project): BasicContext {
val editor = getEditorFromProject(project) ?: return noEditorResponse(project)

val psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.document)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import com.intellij.openapi.project.Project
import com.tabnineCommon.chat.commandHandlers.ChatMessageHandler
import com.tabnineCommon.chat.commandHandlers.context.workspace.WorkspaceCommand
import com.tabnineCommon.chat.commandHandlers.context.workspace.WorkspaceContext
import com.tabnineCommon.chat.commandHandlers.utils.submitReadAction
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit

Expand All @@ -32,12 +31,15 @@ class GetEnrichingContextHandler(gson: Gson) :
val editor = getEditorFromProject(project) ?: return EnrichingContextResponsePayload()

val enrichingContextData = contextTypesSet.map {
submitReadAction {
when (it) {
EnrichingContextType.Editor -> EditorContext.create(editor)
EnrichingContextType.Workspace -> WorkspaceContext.create(editor, project, payload.workspaceCommands ?: emptyList())
EnrichingContextType.Diagnostics -> DiagnosticsContext.create(editor, project)
}
when (it) {
EnrichingContextType.Editor -> EditorContext.createFuture(editor)
EnrichingContextType.Workspace -> WorkspaceContext.createFuture(
editor,
project,
payload.workspaceCommands ?: emptyList()
)

EnrichingContextType.Diagnostics -> DiagnosticsContext.createFuture(editor, project)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package com.tabnineCommon.chat.commandHandlers.context.workspace

import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.tabnineCommon.chat.commandHandlers.utils.ActionPermissions
import com.tabnineCommon.chat.commandHandlers.utils.AsyncAction
import com.tabnineCommon.chat.commandHandlers.utils.StringCaseConverter
import com.tabnineCommon.chat.commandHandlers.utils.SymbolsResolver
import com.tabnineCommon.chat.commandHandlers.utils.submitReadAction
import java.util.concurrent.CompletableFuture

private const val MAX_RESULTS_PER_SYMBOL = 5
Expand All @@ -15,13 +16,13 @@ class FindSymbolsCommandExecutor : CommandsExecutor {
val snakeCaseArg = StringCaseConverter.toSnakeCase(arg)

val tasks = listOf(
submitReadAction {
AsyncAction(ActionPermissions.READ).execute {
SymbolsResolver.resolveSymbols(
project, editor.document, camelCaseArg,
MAX_RESULTS_PER_SYMBOL
)
},
submitReadAction {
AsyncAction(ActionPermissions.READ).execute {
SymbolsResolver.resolveSymbols(
project, editor.document, snakeCaseArg,
MAX_RESULTS_PER_SYMBOL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.tabnineCommon.chat.commandHandlers.context.EnrichingContextData
import com.tabnineCommon.chat.commandHandlers.context.EnrichingContextType
import com.tabnineCommon.chat.commandHandlers.utils.submitReadAction
import com.tabnineCommon.chat.commandHandlers.utils.ActionPermissions
import com.tabnineCommon.chat.commandHandlers.utils.AsyncAction
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
Expand All @@ -25,11 +26,17 @@ data class WorkspaceContext(
private val type: EnrichingContextType = EnrichingContextType.Workspace

companion object {
fun create(editor: Editor, project: Project, workspaceCommands: List<WorkspaceCommand>): WorkspaceContext {
fun createFuture(editor: Editor, project: Project, workspaceCommands: List<WorkspaceCommand>): CompletableFuture<WorkspaceContext> {
return AsyncAction(ActionPermissions.READ).execute {
create(editor, project, workspaceCommands)
}
}

private fun create(editor: Editor, project: Project, workspaceCommands: List<WorkspaceCommand>): WorkspaceContext {
if (workspaceCommands.isEmpty()) return WorkspaceContext(emptyList())

val tasks = workspaceCommands.map { workspaceCommand ->
submitReadAction {
AsyncAction(ActionPermissions.READ).execute {
CommandsExecutor.execute(workspaceCommand, editor, project)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,47 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.util.concurrency.AppExecutorUtil
import java.util.concurrent.CompletableFuture

fun <T> submitReadAction(action: () -> T): CompletableFuture<T> {
val future = CompletableFuture<T>()
AppExecutorUtil.getAppExecutorService().submit {
ApplicationManager.getApplication().runReadAction {
enum class ActionPermissions {
READ,
WRITE
}

/**
* Runs the given action *not* now - the thread in which the action
* is executed depends on the permissions of the action.
*
* READ - runs on a thread provided by `AppExecutorUtil.getAppExecutorService().submit`,
* with read permissions - i.e. acquires a read lock.
*
* WRITE - runs on the AWT thread with write permissions, by calling `ApplicationManager.getApplication().invokeLater`.
*
* The result of the action is then captured in a CompletableFuture, and returned.
*/
class AsyncAction(private val permissions: ActionPermissions) {
fun <T> execute(action: () -> T): CompletableFuture<T> {
val future = CompletableFuture<T>()

val performAction: () -> Unit = {
try {
val result = action()
future.complete(result)
} catch (e: Throwable) {
future.completeExceptionally(e)
}
}

when (permissions) {
ActionPermissions.READ -> AppExecutorUtil.getAppExecutorService().submit {
ApplicationManager.getApplication().runReadAction {
performAction()
}
}

ActionPermissions.WRITE -> ApplicationManager.getApplication().invokeLater {
performAction()
}
}

return future
}
return future
}
Loading

0 comments on commit 6385c15

Please sign in to comment.