Skip to content

Commit dd00fa6

Browse files
andrewyuqmanodnyab
andauthored
Make Amazon Q inline inlay compatiable with JB remote 2024.1+ (#4649)
* Make Amazon Q inline inlay compatiable with JB remote 2024.1+ Adapt the change of APIs for the following: 1. line inlays: InlineSuffixRenderer -> InlineCompletionLineRenderer 2. block inlays: InlineBlockElementRenderer -> InlineCompletionLineRenderer JB will use InlineCompletionLineRenderer to render inlays in remote regardless of whether it's single or multi-line inlays. * detekt * changelog and addressing comments --------- Co-authored-by: manodnyab <[email protected]>
1 parent 2f9865f commit dd00fa6

File tree

3 files changed

+86
-16
lines changed

3 files changed

+86
-16
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type" : "bugfix",
3+
"description" : "Amazon Q: Fix an issue where inline suggestion will not properly show in JetBrains remote env 2024.1+"
4+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package software.aws.toolkits.jetbrains.services.codewhisperer.inlay
4+
5+
import com.intellij.codeInsight.inline.completion.render.InlineBlockElementRenderer
6+
import com.intellij.openapi.editor.Editor
7+
import com.intellij.openapi.editor.EditorCustomElementRenderer
8+
import com.intellij.openapi.editor.markup.TextAttributes
9+
import com.intellij.xdebugger.ui.DebuggerColors
10+
11+
// from 232-241.1, we have `InlineSuffixRenderer`, but with 241.2+ it becomes `InlineCompletionLineRenderer`
12+
// for both line and block inlays. Also InlineBlockElementRenderer is deprecated
13+
// 242 is not yet handled by this
14+
object InlineCompletionRemoteRendererFactory {
15+
private var hasOldLineConstructor = true
16+
private val lineConstructor = run {
17+
val clazz =
18+
try {
19+
Class.forName("com.intellij.codeInsight.inline.completion.render.InlineSuffixRenderer")
20+
} catch (e: ClassNotFoundException) {
21+
hasOldLineConstructor = false
22+
Class.forName("com.intellij.codeInsight.inline.completion.render.InlineCompletionLineRenderer")
23+
}
24+
if (hasOldLineConstructor) {
25+
clazz.getConstructor(Editor::class.java, String::class.java)
26+
} else {
27+
clazz.getConstructor(Editor::class.java, String::class.java, TextAttributes::class.java)
28+
}
29+
}
30+
private var hasNewBlockConstructor = true
31+
private val blockConstructor = run {
32+
val clazz =
33+
try {
34+
Class.forName("com.intellij.codeInsight.inline.completion.render.InlineCompletionLineRenderer")
35+
} catch (e: ClassNotFoundException) {
36+
hasNewBlockConstructor = false
37+
Class.forName("com.intellij.codeInsight.inline.completion.render.InlineBlockElementRenderer")
38+
}
39+
clazz.getConstructor(Editor::class.java, List::class.java)
40+
}
41+
42+
fun createLineInlay(editor: Editor, text: String): EditorCustomElementRenderer =
43+
(
44+
if (hasOldLineConstructor) {
45+
lineConstructor.newInstance(editor, text)
46+
} else {
47+
lineConstructor.newInstance(editor, text, editor.colorsScheme.getAttributes(DebuggerColors.INLINED_VALUES_EXECUTION_LINE))
48+
}
49+
) as EditorCustomElementRenderer
50+
51+
fun createBlockInlays(editor: Editor, block: List<String>): List<EditorCustomElementRenderer> =
52+
if (hasNewBlockConstructor) {
53+
// 241.2+
54+
val textBlockClazz = Class.forName("com.intellij.codeInsight.inline.completion.render.InlineCompletionRenderTextBlock")
55+
val textBlockConstructor = textBlockClazz.getConstructor(String::class.java, TextAttributes::class.java)
56+
block.map {
57+
blockConstructor.newInstance(
58+
editor,
59+
listOf(textBlockConstructor.newInstance(it, editor.colorsScheme.getAttributes(DebuggerColors.INLINED_VALUES_EXECUTION_LINE)))
60+
) as EditorCustomElementRenderer
61+
}
62+
} else {
63+
listOf(InlineBlockElementRenderer(editor, block))
64+
}
65+
}

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/inlay/CodeWhispererInlayManager.kt

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
package software.aws.toolkits.jetbrains.services.codewhisperer.inlay
55

6-
import com.intellij.codeInsight.inline.completion.render.InlineBlockElementRenderer
7-
import com.intellij.codeInsight.inline.completion.render.InlineSuffixRenderer
86
import com.intellij.idea.AppMode
97
import com.intellij.openapi.components.Service
108
import com.intellij.openapi.components.service
@@ -46,7 +44,7 @@ class CodeWhispererInlayManager {
4644
if (!AppMode.isRemoteDevHost()) {
4745
CodeWhispererInlayInlineRenderer(firstLine)
4846
} else {
49-
InlineSuffixRenderer(editor, firstLine)
47+
InlineCompletionRemoteRendererFactory.createLineInlay(editor, firstLine)
5048
}
5149
val inlineInlay = editor.inlayModel.addInlineElement(startOffset, true, firstLineRenderer)
5250
inlineInlay?.let {
@@ -58,22 +56,25 @@ class CodeWhispererInlayManager {
5856
if (otherLines.isEmpty()) {
5957
return
6058
}
61-
val otherLinesRenderer =
59+
val otherLinesRenderers =
6260
if (!AppMode.isRemoteDevHost()) {
63-
CodeWhispererInlayBlockRenderer(otherLines)
61+
listOf(CodeWhispererInlayBlockRenderer(otherLines))
6462
} else {
65-
InlineBlockElementRenderer(editor, otherLines.split("\n"))
63+
InlineCompletionRemoteRendererFactory.createBlockInlays(editor, otherLines.split("\n"))
64+
}
65+
66+
otherLinesRenderers.forEach { otherLinesRenderer ->
67+
val blockInlay = editor.inlayModel.addBlockElement(
68+
startOffset,
69+
true,
70+
false,
71+
0,
72+
otherLinesRenderer
73+
)
74+
blockInlay?.let {
75+
existingInlays.add(it)
76+
Disposer.register(popup, it)
6677
}
67-
val blockInlay = editor.inlayModel.addBlockElement(
68-
startOffset,
69-
true,
70-
false,
71-
0,
72-
otherLinesRenderer
73-
)
74-
blockInlay?.let {
75-
existingInlays.add(it)
76-
Disposer.register(popup, it)
7778
}
7879
}
7980

0 commit comments

Comments
 (0)