Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debug_win #206

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
workflow: node.js.yml
workflow_search: true
repo: smallcloudai/refact-chat-js
branch: main
branch: alpha
name: refact-chat-js-latest
path: ./src/main/resources/webview/dist

Expand Down
2 changes: 1 addition & 1 deletion refact_lsp
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.10.5
wind_debug
38 changes: 0 additions & 38 deletions src/main/kotlin/com/smallcloud/refactai/Initializer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,44 +40,6 @@ class Initializer : ProjectActivity, Disposable {
PluginInstaller.addStateListener(UninstallListener())
UpdateChecker.instance

ApplicationManager.getApplication()
.messageBus
.connect(PluginState.instance)
.subscribe(KeymapManagerListener.TOPIC, object : KeymapManagerListener {
override fun shortcutsChanged(
keymap: Keymap,
actionIds: MutableCollection<String?>,
fromSettings: Boolean
) {
if (Thread.currentThread().stackTrace.count { it.className.startsWith("com.smallcloud.refactai.Initializer") } > 1) {
return
}
for (id in actionIds) {
if (!listOf(IdeActions.ACTION_INSERT_INLINE_COMPLETION, ACTION_ID_).contains(id)) {
continue
}
val shortcuts = keymap.getShortcuts(id)
if (id == IdeActions.ACTION_INSERT_INLINE_COMPLETION) {
keymap.removeAllActionShortcuts(ACTION_ID_)
for (shortcut in shortcuts) {
keymap.addShortcut(
ACTION_ID_,
shortcut
)
}
} else if (id == ACTION_ID_) {
keymap.removeAllActionShortcuts(IdeActions.ACTION_INSERT_INLINE_COMPLETION)
for (shortcut in shortcuts) {
keymap.addShortcut(
IdeActions.ACTION_INSERT_INLINE_COMPLETION,
shortcut
)
}
}
}
}
})

ApplicationManager.getApplication().getService(CloudMessageService::class.java)
if (!isJcefCanStart()) {
emitInfo(RefactAIBundle.message("notifications.chatCanNotStartWarning"), false)
Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/com/smallcloud/refactai/Resources.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ object Resources {
val defaultCodeCompletionUrlSuffix = URI("v1/code-completion")
val cloudUserMessage: URI = defaultCloudUrl.resolve("/v1/user-message")
val defaultReportUrlSuffix: URI = URI("v1/telemetry-network")
val defaultChatReportUrlSuffix: URI = URI("v1/telemetry-chat")
val defaultSnippetAcceptedUrlSuffix: URI = URI("v1/snippet-accepted")
val version: String = getVersion()
const val client: String = "jetbrains"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package com.smallcloud.refactai.code_lens

import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.service
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.LogicalPosition
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.wm.ToolWindowManager
import com.smallcloud.refactai.Resources
import com.smallcloud.refactai.panes.RefactAIToolboxPaneFactory
import com.smallcloud.refactai.statistic.UsageStatistic
import com.smallcloud.refactai.statistic.UsageStats
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.io.path.relativeTo

Expand Down Expand Up @@ -50,6 +53,7 @@ class CodeLensAction(
chat?.activate {
RefactAIToolboxPaneFactory.chat?.requestFocus()
RefactAIToolboxPaneFactory.chat?.executeCodeLensCommand(formatMessage(), sendImmediately, openNewTab)
editor.project?.service<UsageStats>()?.addChatStatistic(true, UsageStatistic("openChatByCodelens"), "")
}

// If content is empty, then it's "Open Chat" instruction, selecting range of code in active tab
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Document
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.ui.components.JBLabel
import com.intellij.util.application
import com.intellij.util.ui.JBFont
Expand Down Expand Up @@ -50,6 +51,9 @@ import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import com.smallcloud.refactai.io.InferenceGlobalContext.Companion.instance as InferenceGlobalContext

val EditorRefactLastSnippetTelemetryIdKey = Key.create<Int>("refact.snippetTelemetryId")
val EditorRefactLastCompletionIsMultilineKey = Key.create<Boolean>("refact.lastCompletion.isMultiline")

private class Default : InlineCompletionSuggestionUpdateManager.Adapter {
override fun onDocumentChange(
event: InlineCompletionEvent.DocumentChange,
Expand Down Expand Up @@ -144,17 +148,16 @@ class RefactAICompletionProvider : DebouncedInlineCompletionProvider() {

override fun restartOn(event: InlineCompletionEvent): Boolean = false

private fun getActiveFile(document: Document, project: Project?): String? {
val projectPath = project?.basePath ?: return null
private fun getActiveFile(document: Document): String? {
val file = FileDocumentManager.getInstance().getFile(document) ?: return null
return Path(file.path).toUri().toString().replace(Path(projectPath).toUri().toString(), "")
return Path(file.path).toString()
}

private class Context(val request: SMCRequest, val editorState: EditorTextState, val force: Boolean = false)


private fun makeContext(request: InlineCompletionRequest): Context? {
val fileName = getActiveFile(request.document, request.editor.project) ?: return null
val fileName = getActiveFile(request.document) ?: return null
if (PrivacyService.instance.getPrivacy(FileDocumentManager.getInstance().getFile(request.document))
== Privacy.DISABLED && !InferenceGlobalContext.isSelfHosted
) return null
Expand Down Expand Up @@ -253,10 +256,11 @@ class RefactAICompletionProvider : DebouncedInlineCompletionProvider() {
send(it)
delay(2)
}
EditorRefactLastSnippetTelemetryIdKey[request.editor] = completion.snippetTelemetryId
EditorRefactLastCompletionIsMultilineKey[request.editor] = completion.multiline
}
}
awaitClose()

})

private fun getSingleLineElements(
Expand Down
35 changes: 28 additions & 7 deletions src/main/kotlin/com/smallcloud/refactai/listeners/AcceptAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,39 @@ import com.intellij.codeInsight.hint.HintManagerImpl.ActionToIgnore
import com.intellij.codeInsight.inline.completion.InlineCompletion
import com.intellij.codeInsight.inline.completion.session.InlineCompletionContext
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.components.service
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.actionSystem.EditorAction
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler
import com.smallcloud.refactai.Resources
import com.smallcloud.refactai.codecompletion.EditorRefactLastCompletionIsMultilineKey
import com.smallcloud.refactai.codecompletion.EditorRefactLastSnippetTelemetryIdKey
import com.smallcloud.refactai.codecompletion.InlineCompletionGrayTextElementCustom
import com.smallcloud.refactai.modes.ModeProvider
import com.smallcloud.refactai.statistic.UsageStats

const val ACTION_ID_ = "TabPressedAction"

class TabPressedAction : EditorAction(InlineCompletionHandler()), ActionToIgnore {
class TabPressedAction : EditorAction(InsertInlineCompletionHandler()), ActionToIgnore {
val ACTION_ID = ACTION_ID_

init {
this.templatePresentation.icon = Resources.Icons.LOGO_RED_16x16
}

class InlineCompletionHandler : EditorWriteActionHandler() {
class InsertInlineCompletionHandler : EditorWriteActionHandler() {
private val logger = Logger.getInstance("RefactTabPressedAction")
override fun executeWriteAction(editor: Editor, caret: Caret?, dataContext: DataContext) {
Logger.getInstance("RefactTabPressedAction").debug("executeWriteAction")
logger.warn("executeWriteAction")
val provider = ModeProvider.getOrCreateModeProvider(editor)
if (provider.isInCompletionMode()) {
InlineCompletion.getHandlerOrNull(editor)?.insert()
EditorRefactLastSnippetTelemetryIdKey[editor]?.also {
editor.project?.service<UsageStats>()?.snippetAccepted(it)
EditorRefactLastSnippetTelemetryIdKey[editor] = null
EditorRefactLastCompletionIsMultilineKey[editor] = null
}
} else {
provider.onTabPressed(editor, caret, dataContext)
}
Expand All @@ -39,14 +48,26 @@ class TabPressedAction : EditorAction(InlineCompletionHandler()), ActionToIgnore
caret: Caret,
dataContext: DataContext
): Boolean {
logger.warn("isEnabledForCaret")
val provider = ModeProvider.getOrCreateModeProvider(editor)
if (provider.isInCompletionMode()) {
logger.warn("provider.isInCompletionMode()")
val ctx = InlineCompletionContext.getOrNull(editor) ?: return false
if (ctx.state.elements.size != 1) return false
if (ctx.state.elements.isEmpty()) return false
val elem = ctx.state.elements.first()
if (elem !is InlineCompletionGrayTextElementCustom.Presentable) return false
return elem.delta == caret.logicalPosition.column
val isMultiline = EditorRefactLastCompletionIsMultilineKey[editor]
logger.warn("isMultiline = $isMultiline")
logger.warn("elem is InlineCompletionGrayTextElementCustom.Presentable = ${elem is InlineCompletionGrayTextElementCustom.Presentable}")
if (isMultiline && elem is InlineCompletionGrayTextElementCustom.Presentable) {
logger.warn("elem.delta = ${elem.delta}")
logger.warn("caret.logicalPosition.column = ${caret.logicalPosition.column}")
logger.warn("elem.element.text = start'${elem.element.text}'end")
logger.warn("elem.element.text = start'${editor.document.text.lines()[caret.logicalPosition.line]}'end")
return elem.delta == caret.logicalPosition.column
}
return true
} else {
logger.warn("else provider.isInCompletionMode()")
return ModeProvider.getOrCreateModeProvider(editor).modeInActiveState()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.smallcloud.refactai.listeners

import com.intellij.codeInsight.inline.completion.session.InlineCompletionContext
import com.intellij.openapi.actionSystem.ActionPromoter
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.CommonDataKeys
Expand All @@ -10,9 +11,12 @@ class AcceptActionsPromoter : ActionPromoter {
private fun getEditor(dataContext: DataContext): Editor? {
return CommonDataKeys.EDITOR.getData(dataContext)
}
override fun promote(actions: MutableList<out AnAction>, context: DataContext): MutableList<AnAction> {
if (getEditor(context) == null)
return actions.toMutableList()
return actions.filterIsInstance<TabPressedAction>().toMutableList()
override fun promote(actions: MutableList<out AnAction>, context: DataContext): List<AnAction> {
val editor = getEditor(context) ?: return emptyList()
if (InlineCompletionContext.getOrNull(editor) == null) {
return emptyList()
}
actions.filterIsInstance<TabPressedAction>().takeIf { it.isNotEmpty() }?.let { return it }
return emptyList()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class GenerateGitCommitMessageAction : AnAction(
val lspService =
event.project?.service<com.smallcloud.refactai.lsp.LSPProcessHolder>() ?: return@invokeLater

val isEnabled = lspService.isWorking && (commitWorkflowUi.getIncludedChanges().isNotEmpty() && commitWorkflowUi.getIncludedUnversionedFiles().isNotEmpty())
val isEnabled = lspService.isWorking && (commitWorkflowUi.getIncludedChanges().isNotEmpty() || commitWorkflowUi.getIncludedUnversionedFiles().isNotEmpty())

event.presentation.isEnabled = isEnabled
event.presentation.text = if (lspService.isWorking) {
Expand All @@ -54,7 +54,6 @@ class GenerateGitCommitMessageAction : AnAction(
return
}


val gitDiff = getDiff(event, project) ?: return
val commitWorkflowUi = event.getData(VcsDataKeys.COMMIT_WORKFLOW_UI)
if (commitWorkflowUi != null) {
Expand Down Expand Up @@ -87,7 +86,6 @@ class GenerateGitCommitMessageAction : AnAction(

try {
val includedChanges = commitWorkflowUi.getIncludedChanges()
commitWorkflowUi.getIncludedUnversionedFiles()
val filePatches = IdeaTextPatchBuilder.buildPatch(
project, includedChanges, projectFileVcsRoot.toNioPath(), false, true
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package com.smallcloud.refactai.panes.sharedchat

import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.components.service
import com.intellij.openapi.wm.ToolWindowManager
import com.smallcloud.refactai.Resources
import com.smallcloud.refactai.panes.RefactAIToolboxPaneFactory
import com.smallcloud.refactai.statistic.UsageStatistic
import com.smallcloud.refactai.statistic.UsageStats
import com.smallcloud.refactai.utils.getLastUsedProject

class ChatPaneInvokeAction: AnAction(Resources.Icons.LOGO_RED_16x16) {
Expand All @@ -14,8 +17,9 @@ class ChatPaneInvokeAction: AnAction(Resources.Icons.LOGO_RED_16x16) {

fun actionPerformed() {
val chat = ToolWindowManager.getInstance(getLastUsedProject()).getToolWindow("Refact")
chat?.activate{
chat?.activate {
RefactAIToolboxPaneFactory.focusChat()
getLastUsedProject().service<UsageStats>().addChatStatistic(true, UsageStatistic("openChatByShortcut"), "")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ class SharedChatPane(val project: Project) : JPanel(), Disposable {
}

val webView by lazy {
System.setProperty("ide.browser.jcef.log.level", "info")
// System.setProperty("ide.browser.jcef.log.level", "info")
browser.webView
}

Expand Down
43 changes: 43 additions & 0 deletions src/main/kotlin/com/smallcloud/refactai/statistic/UsageStats.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.intellij.openapi.components.service
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.util.concurrency.AppExecutorUtil
import com.smallcloud.refactai.Resources.defaultChatReportUrlSuffix
import com.smallcloud.refactai.Resources.defaultReportUrlSuffix
import com.smallcloud.refactai.Resources.defaultSnippetAcceptedUrlSuffix
import com.smallcloud.refactai.io.sendRequest
Expand Down Expand Up @@ -93,6 +94,48 @@ class UsageStats(private val project: Project): Disposable {
}
}
}

fun addChatStatistic(
positive: Boolean,
stat: UsageStatistic,
errorMessage: Any
) {
var errorMessageStr = errorMessage.toString()
val gson = Gson()
if (errorMessageStr.length > 200) {
errorMessageStr = errorMessageStr.substring(0, 200) + "…"
}

val errorMessageJson = gson.toJson(errorMessageStr)
var scope = stat.scope
if (stat.subScope.isNotEmpty()) {
scope += ":" + stat.subScope
}

val scopeJson = gson.toJson(scope)
val body = gson.toJson(
mapOf(
"success" to positive,
"error_message" to errorMessageJson,
"scope" to scopeJson,
)
)
val url = getLSPProcessHolder(project)!!.url.resolve(defaultChatReportUrlSuffix)
execService.submit {
try {
val res = sendRequest(url, "POST", body=body)
if (res.body.isNullOrEmpty()) return@submit

val json = gson.fromJson(res.body, JsonObject::class.java)
val success = if (json.has("success")) json.get("success").asInt else null
if (success != null && success != 1) {
throw Exception(json.get("human_readable_message").asString)
}
} catch (e: Exception) {
Logger.getInstance(UsageStats::class.java).warn("report to $url failed: $e")
}
}
}

companion object {
@JvmStatic
Expand Down
16 changes: 9 additions & 7 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,11 @@ integrated into a single package that follows your privacy settings.</p>
</extensions>
<actions>
<action class="com.smallcloud.refactai.listeners.TabPressedAction"
id="TabPressedAction"
id="InsertInlineCompletionAction"
text="Accept Inline Completion"
overrides="true"
description="Refact AI Accept Inline Completion">
<add-to-group group-id="InlineCompletion" anchor="first"/>
<keyboard-shortcut first-keystroke="TAB" keymap="$default"/>
</action>
<action class="com.smallcloud.refactai.listeners.CancelPressedAction"
Expand Down Expand Up @@ -182,12 +184,12 @@ integrated into a single package that follows your privacy settings.</p>
<separator/>
</group>
<!-- Temporary disable; JB has broken vcs plugin in 2024.3 -->
<!-- <group id="RefactAI.GenerateGitCommitMessageGroup">-->
<!-- <add-to-group group-id="Vcs.MessageActionGroup" anchor="first"/>-->
<!-- <action-->
<!-- id="RefactAIGenerateGitCommitMessage"-->
<!-- class="com.smallcloud.refactai.listeners.GenerateGitCommitMessageAction" />-->
<!-- </group>-->
<group id="RefactAI.GenerateGitCommitMessageGroup">
<add-to-group group-id="Vcs.MessageActionGroup" anchor="first"/>
<action
id="RefactAIGenerateGitCommitMessage"
class="com.smallcloud.refactai.listeners.GenerateGitCommitMessageAction" />
</group>
</actions>
<resource-bundle>bundles.RefactAI</resource-bundle>
<applicationListeners>
Expand Down
Loading