Skip to content

Commit e74204f

Browse files
authored
Fix project build with platformVersion >= 2024 (#2492)
## Changes 1. Fixed package for `InlineCompletionSuggestion` 2. Added separate versions of `CodyInlineCompletionProvider` for IJ 2023 and 2024 (although 2024 version will be used only if `platformVersion` is changed explicitly, e.g. using `-PplatformVersion=2024.2`). 3. Fixed build definition issues for IJ 2024, mostly connected with missing VCS packages. ## Test plan Verify that completions and opening Revision Diff in Sourcegraph Web works: * In IntelliJ 2023.2 * In IntelliJ 2024.2 * In IntelliJ 2024.2 in split mode (or using remote directly)
1 parent 510e082 commit e74204f

File tree

9 files changed

+196
-38
lines changed

9 files changed

+196
-38
lines changed

build.gradle.kts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ plugins {
6363
val platformVersion: String by project
6464
val platformType: String by project
6565
val javaVersion: String by project
66+
val majorPlatformVersion = platformVersion.split(".").first()
6667

6768
group = properties("pluginGroup")!!
6869

@@ -126,6 +127,10 @@ dependencies {
126127
instrumentationTools()
127128
pluginVerifier()
128129
testFramework(TestFrameworkType.Platform)
130+
131+
if (majorPlatformVersion.toInt() >= 2024) {
132+
bundledModule("intellij.platform.vcs.dvcs.impl")
133+
}
129134
}
130135

131136
implementation("org.commonmark:commonmark:0.22.0")
@@ -257,6 +262,8 @@ fun Test.sharedIntegrationTestConfig(buildCodyDir: File, mode: String) {
257262

258263
include("**/AllSuites.class")
259264

265+
maxHeapSize = "8G"
266+
260267
jvmArgs(
261268
"-Djava.system.class.loader=com.intellij.util.lang.PathClassLoader",
262269
"--add-opens=java.desktop/java.awt.event=ALL-UNNAMED",
@@ -586,6 +593,8 @@ tasks {
586593
test { dependsOn(project.tasks.getByPath("buildCody")) }
587594

588595
sourceSets {
596+
main { kotlin.srcDir("src/intellij${majorPlatformVersion}/kotlin") }
597+
589598
create("integrationTest") {
590599
kotlin.srcDir("src/integrationTest/kotlin")
591600
compileClasspath += main.get().output + configurations.testCompileClasspath.get()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.intellij.codeInsight.inline.completion.suggestion
2+
3+
import com.intellij.codeInsight.inline.completion.elements.InlineCompletionElement
4+
import com.intellij.openapi.util.UserDataHolderBase
5+
import kotlinx.coroutines.flow.Flow
6+
import kotlinx.coroutines.flow.FlowCollector
7+
8+
interface InlineCompletionSuggestion {
9+
10+
object Empty : InlineCompletionSuggestion {}
11+
}
12+
13+
interface InlineCompletionSingleSuggestion : InlineCompletionSuggestion {
14+
15+
companion object {
16+
17+
/** @see [InlineCompletionVariant.build] */
18+
fun build(
19+
data: UserDataHolderBase = UserDataHolderBase(),
20+
buildElements:
21+
suspend FlowCollector<InlineCompletionElement>.(data: UserDataHolderBase) -> Unit
22+
): InlineCompletionSingleSuggestion {
23+
return object : InlineCompletionSingleSuggestion {}
24+
}
25+
26+
/** @see InlineCompletionVariant.build */
27+
fun build(
28+
data: UserDataHolderBase = UserDataHolderBase(),
29+
elements: Flow<InlineCompletionElement>
30+
): InlineCompletionSingleSuggestion {
31+
return object : InlineCompletionSingleSuggestion {}
32+
}
33+
}
34+
}

src/main/kotlin/com/sourcegraph/cody/autocomplete/CodyInlineCompletionProvider.kt renamed to src/intellij2023/kotlin/com/sourcegraph/cody/autocomplete/CodyInlineCompletionProvider.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package com.sourcegraph.cody.autocomplete
22

33
import com.intellij.codeInsight.inline.completion.*
44
import com.intellij.codeInsight.inline.completion.elements.InlineCompletionGrayTextElement
5+
import com.intellij.codeInsight.inline.completion.suggestion.InlineCompletionSingleSuggestion
6+
import com.intellij.codeInsight.inline.completion.suggestion.InlineCompletionSuggestion
57
import com.intellij.openapi.application.ApplicationInfo
68
import com.intellij.openapi.application.ApplicationManager
79
import com.intellij.openapi.application.ReadAction
@@ -36,9 +38,9 @@ class CodyInlineCompletionProvider : InlineCompletionProvider {
3638
suspend fun getSuggestion(request: InlineCompletionRequest): InlineCompletionSuggestion {
3739
ApplicationManager.getApplication().assertIsNonDispatchThread()
3840
val editor = request.editor
39-
val project = editor.project ?: return InlineCompletionSuggestion.empty()
41+
val project = editor.project ?: return InlineCompletionSuggestion.Empty
4042
if (!isImplicitAutocompleteEnabledForEditor(editor)) {
41-
return InlineCompletionSuggestion.empty()
43+
return InlineCompletionSuggestion.Empty
4244
}
4345
val lookupString: String? = null // todo: can we use this provider for lookups?
4446

@@ -56,9 +58,9 @@ class CodyInlineCompletionProvider : InlineCompletionProvider {
5658
val completions =
5759
fetchCompletions(project, editor, triggerKind, cancellationToken, lookupString)
5860
.completeOnTimeout(null, 1, TimeUnit.SECONDS)
59-
.get() ?: return InlineCompletionSuggestion.empty()
61+
.get() ?: return InlineCompletionSuggestion.Empty
6062

61-
return InlineCompletionSuggestion.withFlow {
63+
return InlineCompletionSingleSuggestion.build {
6264
completions.items
6365
.firstNotNullOfOrNull {
6466
WriteCommandAction.runWriteCommandAction<InlineCompletionGrayTextElement?>(
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package com.sourcegraph.cody.autocomplete
2+
3+
import com.intellij.codeInsight.inline.completion.*
4+
import com.intellij.codeInsight.inline.completion.elements.InlineCompletionGrayTextElement
5+
import com.intellij.codeInsight.inline.completion.suggestion.InlineCompletionSingleSuggestion
6+
import com.intellij.codeInsight.inline.completion.suggestion.InlineCompletionSuggestion
7+
import com.intellij.openapi.application.ApplicationInfo
8+
import com.intellij.openapi.application.ApplicationManager
9+
import com.intellij.openapi.application.ReadAction
10+
import com.intellij.openapi.client.ClientSessionsManager
11+
import com.intellij.openapi.command.WriteCommandAction
12+
import com.intellij.openapi.diagnostic.Logger
13+
import com.intellij.openapi.editor.Editor
14+
import com.intellij.openapi.editor.event.DocumentEvent
15+
import com.intellij.openapi.project.Project
16+
import com.intellij.openapi.util.TextRange
17+
import com.intellij.util.concurrency.annotations.RequiresReadLock
18+
import com.sourcegraph.cody.agent.CodyAgentService
19+
import com.sourcegraph.cody.agent.protocol.AutocompleteResult
20+
import com.sourcegraph.cody.agent.protocol.CompletionItemParams
21+
import com.sourcegraph.cody.statusbar.CodyStatusService.Companion.resetApplication
22+
import com.sourcegraph.cody.vscode.CancellationToken
23+
import com.sourcegraph.cody.vscode.InlineCompletionTriggerKind
24+
import com.sourcegraph.cody.vscode.IntelliJTextDocument
25+
import com.sourcegraph.config.ConfigUtil
26+
import com.sourcegraph.utils.CodyEditorUtil.getTextRange
27+
import com.sourcegraph.utils.CodyEditorUtil.isImplicitAutocompleteEnabledForEditor
28+
import com.sourcegraph.utils.CodyFormatter
29+
import java.util.concurrent.CompletableFuture
30+
import java.util.concurrent.TimeUnit
31+
import java.util.concurrent.atomic.AtomicReference
32+
33+
class CodyInlineCompletionProvider : InlineCompletionProvider {
34+
private val logger = Logger.getInstance(CodyInlineCompletionProvider::class.java)
35+
private val currentJob = AtomicReference(CancellationToken())
36+
override val id = InlineCompletionProviderID("Cody")
37+
38+
override suspend fun getSuggestion(request: InlineCompletionRequest): InlineCompletionSuggestion {
39+
ApplicationManager.getApplication().assertIsNonDispatchThread()
40+
val editor = request.editor
41+
val project = editor.project ?: return InlineCompletionSuggestion.Empty
42+
if (!isImplicitAutocompleteEnabledForEditor(editor)) {
43+
return InlineCompletionSuggestion.Empty
44+
}
45+
val lookupString: String? = null // todo: can we use this provider for lookups?
46+
47+
cancelCurrentJob(project)
48+
val cancellationToken = CancellationToken()
49+
currentJob.set(cancellationToken)
50+
51+
val triggerKind =
52+
if (request.event is InlineCompletionEvent.DirectCall) {
53+
InlineCompletionTriggerKind.INVOKE
54+
} else {
55+
InlineCompletionTriggerKind.AUTOMATIC
56+
}
57+
58+
val completions =
59+
fetchCompletions(project, editor, triggerKind, cancellationToken, lookupString)
60+
.completeOnTimeout(null, 1, TimeUnit.SECONDS)
61+
.get() ?: return InlineCompletionSuggestion.Empty
62+
63+
return InlineCompletionSingleSuggestion.build {
64+
completions.items
65+
.firstNotNullOfOrNull {
66+
WriteCommandAction.runWriteCommandAction<InlineCompletionGrayTextElement?>(
67+
editor.project) {
68+
val range = getTextRange(editor.document, it.range)
69+
val originalText = editor.document.getText(range)
70+
71+
val formattedCompletionText: String =
72+
if (System.getProperty("cody.autocomplete.enableFormatting") == "false") {
73+
it.insertText
74+
} else {
75+
CodyFormatter.formatStringBasedOnDocument(
76+
it.insertText, project, editor.document, range, request.endOffset)
77+
}
78+
79+
val completionText = formattedCompletionText.removeSuffix(originalText)
80+
if (completionText.trim().isBlank()) {
81+
null
82+
} else {
83+
84+
CodyAgentService.withAgent(project) { agent ->
85+
agent.server.completionSuggested(CompletionItemParams(it.id))
86+
}
87+
88+
InlineCompletionGrayTextElement(completionText)
89+
}
90+
}
91+
}
92+
?.let { emit(it) }
93+
}
94+
}
95+
96+
@RequiresReadLock
97+
private fun fetchCompletions(
98+
project: Project,
99+
editor: Editor,
100+
triggerKind: InlineCompletionTriggerKind,
101+
cancellationToken: CancellationToken,
102+
lookupString: String?,
103+
): CompletableFuture<AutocompleteResult?> {
104+
val textDocument = IntelliJTextDocument(editor, project)
105+
val offset = ReadAction.compute<Int, Throwable> { editor.caretModel.offset }
106+
val lineNumber = editor.document.getLineNumber(offset)
107+
val caretPositionInLine = offset - editor.document.getLineStartOffset(lineNumber)
108+
val originalText = editor.document.getText(TextRange(offset - caretPositionInLine, offset))
109+
110+
val result = CompletableFuture<AutocompleteResult?>()
111+
Utils.triggerAutocompleteAsync(
112+
project,
113+
editor,
114+
offset,
115+
textDocument,
116+
triggerKind,
117+
cancellationToken,
118+
lookupString,
119+
originalText,
120+
logger) { autocompleteResult ->
121+
result.complete(autocompleteResult)
122+
}
123+
return result
124+
}
125+
126+
private fun cancelCurrentJob(project: Project?) {
127+
currentJob.get().abort()
128+
project?.let { resetApplication(it) }
129+
}
130+
131+
override fun isEnabled(event: InlineCompletionEvent): Boolean {
132+
return isEnabled()
133+
}
134+
135+
fun isEnabled(event: DocumentEvent): Boolean {
136+
return isEnabled()
137+
}
138+
139+
private fun isEnabled(): Boolean {
140+
val ideVersion = ApplicationInfo.getInstance().build.baselineVersion
141+
val isRemoteDev = ClientSessionsManager.getAppSession()?.isRemote ?: false
142+
return ideVersion >= 233 &&
143+
isRemoteDev &&
144+
ConfigUtil.isCodyEnabled() &&
145+
ConfigUtil.isCodyAutocompleteEnabled()
146+
}
147+
}

src/main/kotlin/com/intellij/codeInsight/inline/completion/InlineCompletionSuggestion.kt

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)