chore: upgrade to 2025.1 and align dependencies
Some checks are pending
Build / Build (push) Waiting to run
Build / Verify Plugin (push) Blocked by required conditions

This commit is contained in:
Carl-Robert Linnupuu 2025-10-21 18:00:02 +01:00
parent c15976d4d9
commit e5785180c6
11 changed files with 7 additions and 299 deletions

View file

@ -63,7 +63,7 @@ dependencies {
bundledPlugin("com.intellij.java")
bundledPlugin("org.jetbrains.kotlin")
bundledPlugin("Git4Idea")
plugin("PythonCore:241.14494.240")
plugin("PythonCore:251.25410.109")
testFramework(TestFrameworkType.Platform)
testFramework(TestFrameworkType.JUnit5)

View file

@ -8,11 +8,11 @@ pluginVersion = 3.6.4
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 241.1
pluginUntilBuild = 252.*
pluginUntilBuild = 253.*
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
platformType = IC
platformVersion = 2024.1.2
platformVersion = 2025.1.1
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22

View file

@ -1,20 +1,17 @@
package ee.carlrobert.codegpt.actions
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
import com.intellij.openapi.actionSystem.DataContext
import ee.carlrobert.codegpt.CodeGPTKeys
import ee.carlrobert.codegpt.codecompletions.AcceptNextLineInlayAction
import ee.carlrobert.codegpt.codecompletions.AcceptNextWordInlayAction
import ee.carlrobert.codegpt.predictions.OpenPredictionAction
import ee.carlrobert.codegpt.predictions.TriggerCustomPredictionAction
import ee.carlrobert.codegpt.inlineedit.AcceptCurrentInlineEditAction
import ee.carlrobert.codegpt.actions.editor.AcceptInlineEditAction
import ee.carlrobert.codegpt.actions.editor.InlineEditContextMenuAction
import ee.carlrobert.codegpt.actions.editor.InlineEditFloatingMenuAction
import ee.carlrobert.codegpt.inlineedit.AcceptCurrentInlineEditAction
import ee.carlrobert.codegpt.inlineedit.RejectCurrentInlineEditAction
import ee.carlrobert.codegpt.predictions.OpenPredictionAction
import ee.carlrobert.codegpt.predictions.TriggerCustomPredictionAction
class InlayActionPromoter : ActionPromoter {
override fun promote(actions: List<AnAction>, context: DataContext): List<AnAction> {
@ -36,10 +33,6 @@ class InlayActionPromoter : ActionPromoter {
actions.filterIsInstance<TriggerCustomPredictionAction>().takeIf { it.isNotEmpty() }?.let { return it }
actions.filterIsInstance<OpenPredictionAction>().takeIf { it.isNotEmpty() }?.let { return it }
if (InlineCompletionContext.getOrNull(editor) == null) return emptyList()
actions.filterIsInstance<AcceptNextWordInlayAction>().takeIf { it.isNotEmpty() }?.let { return it }
actions.filterIsInstance<AcceptNextLineInlayAction>().takeIf { it.isNotEmpty() }?.let { return it }
return emptyList()
}
}

View file

@ -1,68 +0,0 @@
package ee.carlrobert.codegpt.codecompletions
import com.intellij.codeInsight.inline.completion.InlineCompletion
import com.intellij.codeInsight.inline.completion.InlineCompletionEvent
import com.intellij.codeInsight.inline.completion.InlineCompletionHandler
import com.intellij.codeInsight.inline.completion.InlineCompletionRequest
import com.intellij.codeInsight.inline.completion.session.InlineCompletionSession
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler
import com.intellij.openapi.util.TextRange
abstract class AbstractInlayActionHandler : EditorWriteActionHandler() {
abstract fun InlineCompletionSession.getTextToInsert(): String
abstract fun InlineCompletionHandler.invoke(request: InlineCompletionRequest, range: TextRange)
override fun doExecute(editor: Editor, caret: Caret?, dataContext: DataContext?) {
InlineCompletionSession.getOrNull(editor)?.let { session ->
if (!session.isActive() || !session.context.isCurrentlyDisplaying()) return
// TODO: Implement brace matching
InlineCompletion.getHandlerOrNull(editor)?.apply {
val startOffset = editor.caretModel.offset
val textToInsert = session.getTextToInsert()
withIgnoringDocumentChanges {
val suggestionTextRange =
TextRange(startOffset - textToInsert.length, startOffset)
invoke(session.request, suggestionTextRange)
runWriteAction {
editor.document.insertString(startOffset, textToInsert)
editor.caretModel.moveToOffset(startOffset + textToInsert.length)
}
}
}
}
}
override fun isEnabledForCaret(
editor: Editor,
caret: Caret,
dataContext: DataContext?
): Boolean = InlineCompletionSession.getOrNull(editor)?.let {
it.isActive() && it.context.isCurrentlyDisplaying()
} ?: false
}
internal abstract class ApplyNextInlaySuggestionEvent(
private val originalRequest: InlineCompletionRequest,
private val textRange: TextRange
) : InlineCompletionEvent {
override fun toRequest(): InlineCompletionRequest {
return InlineCompletionRequest(
this,
originalRequest.file,
originalRequest.editor,
originalRequest.document,
textRange.startOffset,
textRange.endOffset,
originalRequest.lookupElement
)
}
}

View file

@ -1,45 +0,0 @@
package ee.carlrobert.codegpt.codecompletions
import ai.grazie.nlp.utils.takeWhitespaces
import com.intellij.codeInsight.hint.HintManagerImpl
import com.intellij.codeInsight.inline.completion.InlineCompletionHandler
import com.intellij.codeInsight.inline.completion.InlineCompletionRequest
import com.intellij.codeInsight.inline.completion.session.InlineCompletionSession
import com.intellij.openapi.editor.actionSystem.EditorAction
import com.intellij.openapi.util.TextRange
class AcceptNextLineInlayAction : EditorAction(Handler()), HintManagerImpl.ActionToIgnore {
companion object {
const val ID = "codegpt.acceptNextInlayLine"
}
private class Handler : AbstractInlayActionHandler() {
override fun InlineCompletionSession.getTextToInsert(): String {
val completionText = context.textToInsert()
val lineBreakIndex = completionText.indexOfFirst { it == '\n' }
return if (lineBreakIndex == -1) {
completionText
} else {
val nextLineStart = lineBreakIndex + 1
val whitespacesLength =
completionText.substring(nextLineStart).takeWhitespaces().length
completionText.substring(0, nextLineStart + whitespacesLength)
}
}
override fun InlineCompletionHandler.invoke(
request: InlineCompletionRequest,
range: TextRange
) {
invokeEvent(ApplyNextLineInlaySuggestionEvent(request, range))
}
}
}
internal class ApplyNextLineInlaySuggestionEvent(
originalRequest: InlineCompletionRequest,
textRange: TextRange
) : ApplyNextInlaySuggestionEvent(originalRequest, textRange)

View file

@ -1,34 +0,0 @@
package ee.carlrobert.codegpt.codecompletions
import com.intellij.codeInsight.hint.HintManagerImpl
import com.intellij.codeInsight.inline.completion.InlineCompletionHandler
import com.intellij.codeInsight.inline.completion.InlineCompletionRequest
import com.intellij.codeInsight.inline.completion.session.InlineCompletionSession
import com.intellij.openapi.editor.actionSystem.EditorAction
import com.intellij.openapi.util.TextRange
class AcceptNextWordInlayAction : EditorAction(Handler()), HintManagerImpl.ActionToIgnore {
companion object {
const val ID = "codegpt.acceptNextInlayWord"
}
private class Handler : AbstractInlayActionHandler() {
override fun InlineCompletionSession.getTextToInsert(): String {
return CompletionSplitter.split(context.textToInsert())
}
override fun InlineCompletionHandler.invoke(
request: InlineCompletionRequest,
range: TextRange
) {
invokeEvent(ApplyNextWordInlaySuggestionEvent(request, range))
}
}
}
internal class ApplyNextWordInlaySuggestionEvent(
originalRequest: InlineCompletionRequest,
textRange: TextRange
) : ApplyNextInlaySuggestionEvent(originalRequest, textRange)

View file

@ -1,9 +1,7 @@
package ee.carlrobert.codegpt.codecompletions
import com.intellij.codeInsight.inline.completion.InlineCompletionProviderPresentation
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.components.service
import com.intellij.openapi.keymap.KeymapUtil
import com.intellij.openapi.project.Project
import com.intellij.ui.components.JBLabel
import ee.carlrobert.codegpt.Icons
@ -17,9 +15,7 @@ class CodeCompletionProviderPresentation : InlineCompletionProviderPresentation
project?.service<CodeCompletionService>()?.getSelectedModelCode() ?: ""
val text = if (selectedModelCode.isNotEmpty()) {
buildString {
append("<html>Model: (<strong>$selectedModelCode</strong>) | ")
append("Accept Word: (<strong>${getShortcutText(AcceptNextWordInlayAction.ID)}</strong>) | ")
append("Accept Line: (<strong>${getShortcutText(AcceptNextLineInlayAction.ID)}</strong>)</html>")
append("<html>Model: (<strong>$selectedModelCode</strong>)</html>")
}
} else {
"ProxyAI"
@ -27,10 +23,4 @@ class CodeCompletionProviderPresentation : InlineCompletionProviderPresentation
return JBLabel(text, Icons.DefaultSmall, SwingConstants.LEADING)
}
private fun getShortcutText(actionId: String): String {
return KeymapUtil.getFirstKeyboardShortcutText(
ActionManager.getInstance().getAction(actionId)
)
}
}

View file

@ -1,12 +1,8 @@
package ee.carlrobert.codegpt.codecompletions
import ai.grazie.nlp.utils.takeWhitespaces
import com.intellij.codeInsight.inline.completion.InlineCompletionEvent
import com.intellij.codeInsight.inline.completion.elements.InlineCompletionGrayTextElement
import com.intellij.codeInsight.inline.completion.suggestion.InlineCompletionSuggestionUpdateManager
import com.intellij.codeInsight.inline.completion.suggestion.InlineCompletionSuggestionUpdateManager.UpdateResult
import com.intellij.codeInsight.inline.completion.suggestion.InlineCompletionSuggestionUpdateManager.UpdateResult.Changed
import com.intellij.codeInsight.inline.completion.suggestion.InlineCompletionSuggestionUpdateManager.UpdateResult.Invalidated
import com.intellij.codeInsight.inline.completion.suggestion.InlineCompletionVariant
import com.intellij.openapi.editor.Editor
import ee.carlrobert.codegpt.CodeGPTKeys.REMAINING_EDITOR_COMPLETION
@ -22,61 +18,6 @@ class CodeCompletionSuggestionUpdateAdapter :
return super.onDocumentChange(event, variant)
}
override fun onCustomEvent(
event: InlineCompletionEvent,
variant: InlineCompletionVariant.Snapshot
): UpdateResult {
if (variant.elements.isEmpty()) return Invalidated
val completionText = variant.elements.joinToString("") { it.text }
return when (event) {
is ApplyNextWordInlaySuggestionEvent -> handleNextWordEvent(event, variant, completionText)
is ApplyNextLineInlaySuggestionEvent -> handleNextLineEvent(event, variant, completionText)
else -> Invalidated
}
}
private fun handleNextWordEvent(
event: ApplyNextWordInlaySuggestionEvent,
variant: InlineCompletionVariant.Snapshot,
completionText: String
): UpdateResult {
val textToInsert = CompletionSplitter.split(completionText)
return createUpdatedVariant(event.toRequest().editor, variant, completionText, textToInsert)
}
private fun handleNextLineEvent(
event: ApplyNextLineInlaySuggestionEvent,
variant: InlineCompletionVariant.Snapshot,
completionText: String
): UpdateResult {
val lineBreakIndex = completionText.indexOf('\n')
if (lineBreakIndex == -1) return Invalidated
val nextLineStart = lineBreakIndex + 1
val whitespacesLength = completionText
.substring(nextLineStart)
.takeWhitespaces()
.length
val textToInsert = completionText.substring(0, nextLineStart + whitespacesLength)
return createUpdatedVariant(event.toRequest().editor, variant, completionText, textToInsert)
}
private fun createUpdatedVariant(
editor: Editor,
variant: InlineCompletionVariant.Snapshot,
completionText: String,
textToInsert: String
): UpdateResult {
updateRemainingCompletion(editor, textToInsert)
return Changed(
variant.copy(
listOf(InlineCompletionGrayTextElement(completionText.removePrefix(textToInsert)))
)
)
}
private fun updateRemainingCompletion(editor: Editor, textToInsert: String) {
val remainingCompletion = REMAINING_EDITOR_COMPLETION.get(editor) ?: ""
if (remainingCompletion.isNotEmpty()) {

View file

@ -86,7 +86,6 @@ class PromptTextField(
document.putUserData(PROMPT_FIELD_KEY, this)
setPlaceholder(CodeGPTBundle.get("toolwindow.chat.textArea.emptyText"))
putClientProperty(UIUtil.HIDE_EDITOR_FROM_DATA_CONTEXT_PROPERTY, true)
installPasteHandler()
}

View file

@ -143,18 +143,6 @@
<keyboard-shortcut first-keystroke="ctrl ENTER" keymap="$default"/>
</action>
<action
id="codegpt.acceptNextInlayWord"
text="Apply next word"
use-shortcut-of="EditorNextWord"
class="ee.carlrobert.codegpt.codecompletions.AcceptNextWordInlayAction"/>
<action
id="codegpt.acceptNextInlayLine"
text="Apply next line"
use-shortcut-of="EditorLineEnd"
class="ee.carlrobert.codegpt.codecompletions.AcceptNextLineInlayAction"/>
<group id="CodeGPTEditorPopup">
<group id="action.editor.group.EditorActionGroup"
text="ProxyAI"

View file

@ -102,62 +102,6 @@ class CodeCompletionServiceTest : IntegrationTest() {
}
}
fun `test apply next partial completion word`() {
useLlamaService(true, FeatureType.CODE_COMPLETION)
service<CodeGPTServiceSettings>().state.nextEditsEnabled = false
myFixture.configureByText(
"CompletionTest.java",
FileUtil.getResourceContent("/codecompletions/code-completion-file.txt")
)
myFixture.editor.caretModel.moveToVisualPosition(VisualPosition(3, 0))
project.service<CodeCompletionCacheService>().clear()
val expectedCompletion = "public void main"
val prefix = """
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
[INPUT]
c
""".trimIndent()
val suffix = """
[\INPUT]
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
""".trimIndent()
expectLlama(StreamHttpExchange { request: RequestEntity ->
assertThat(request.uri.path).isEqualTo("/completion")
assertThat(request.method).isEqualTo("POST")
assertThat(request.body)
.extracting("prompt")
.isEqualTo(
InfillPromptTemplate.CODE_LLAMA.buildPrompt(
InfillRequest.Builder(prefix, suffix, 0).build()
)
)
listOf(
jsonMapResponse(
e("content", expectedCompletion),
e("stop", true)
)
)
})
myFixture.type('c')
assertInlineSuggestion("Failed to display initial inline suggestion.") {
expectedCompletion == it
}
val offsetBeforeApply = myFixture.editor.caretModel.offset
myFixture.performEditorAction(AcceptNextWordInlayAction.ID)
assertInlineSuggestion("Failed to display next partial inline suggestion.") {
myFixture.run {
val appliedText =
editor.document.getText(TextRange(offsetBeforeApply, editor.caretModel.offset))
"public" == appliedText && " void main" == it
}
}
}
fun `_test apply inline suggestions without initial following text`() {
useCodeGPTService(FeatureType.CODE_COMPLETION)
service<CodeGPTServiceSettings>().state.nextEditsEnabled = false