-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add lens for JS, TS and Java * add "ask" * add analytics * provider per language * set 'freeCompilerArgs += "-Xjvm-default=enable"' * support kotlin * support php * support rust * revert * typescript * small changes * fix test * Yair/code lens tests (#705) * tests * tests * add java dependency only when running tests * try * fix * remove unneeded --------- Co-authored-by: Amir Tuval <[email protected]> * pass isChatEnabled function to the inlayHintProvider * fix tests --------- Co-authored-by: Amir Tuval <[email protected]>
- Loading branch information
1 parent
c599d57
commit 15641f6
Showing
15 changed files
with
282 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
Common/src/main/java/com/tabnineCommon/chat/lens/TabnineLensBaseProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.tabnineCommon.chat.lens | ||
|
||
import com.intellij.codeInsight.hints.ChangeListener | ||
import com.intellij.codeInsight.hints.ImmediateConfigurable | ||
import com.intellij.codeInsight.hints.InlayHintsProvider | ||
import com.intellij.codeInsight.hints.InlayHintsSink | ||
import com.intellij.codeInsight.hints.NoSettings | ||
import com.intellij.codeInsight.hints.SettingsKey | ||
import com.intellij.openapi.editor.Editor | ||
import com.intellij.psi.PsiFile | ||
import javax.swing.JComponent | ||
import javax.swing.JPanel | ||
|
||
open class TabnineLensBaseProvider(private val supportedElementTypes: List<String>, private val isChatEnabled: () -> Boolean) : InlayHintsProvider<NoSettings> { | ||
override fun getCollectorFor( | ||
file: PsiFile, | ||
editor: Editor, | ||
settings: NoSettings, | ||
sink: InlayHintsSink | ||
) = TabnineLensCollector(editor, supportedElementTypes, isChatEnabled) | ||
|
||
override val key: SettingsKey<NoSettings> = SettingsKey("tabnine.chat.inlay.provider") | ||
|
||
override val name: String = "Tabnine: chat actions" | ||
|
||
override val previewText: String? = null | ||
|
||
override fun createSettings(): NoSettings = NoSettings() | ||
|
||
override fun createConfigurable(settings: NoSettings): ImmediateConfigurable { | ||
return object : ImmediateConfigurable { | ||
override fun createComponent(listener: ChangeListener): JComponent { | ||
return JPanel() | ||
} | ||
} | ||
} | ||
} | ||
|
||
open class TabnineLensJavaBaseProvider(isChatEnabled: () -> Boolean) : TabnineLensBaseProvider(listOf("CLASS", "METHOD"), isChatEnabled) | ||
open class TabnineLensPythonBaseProvider(isChatEnabled: () -> Boolean) : TabnineLensBaseProvider(listOf("Py:CLASS_DECLARATION", "Py:FUNCTION_DECLARATION"), isChatEnabled) | ||
open class TabnineLensTypescriptBaseProvider(isChatEnabled: () -> Boolean) : TabnineLensBaseProvider(listOf("JS:FUNCTION_DECLARATION", "JS:ES6_CLASS", "JS:CLASS", "JS:TYPESCRIPT_FUNCTION", "JS:TYPESCRIPT_CLASS"), isChatEnabled) | ||
open class TabnineLensKotlinBaseProvider(isChatEnabled: () -> Boolean) : TabnineLensBaseProvider(listOf("CLASS", "FUN"), isChatEnabled) | ||
open class TabnineLensPhpBaseProvider(isChatEnabled: () -> Boolean) : TabnineLensBaseProvider(listOf("Class", "Class method", "Function"), isChatEnabled) | ||
open class TabnineLensRustBaseProvider(isChatEnabled: () -> Boolean) : TabnineLensBaseProvider(listOf("FUNCTION"), isChatEnabled) |
120 changes: 120 additions & 0 deletions
120
Common/src/main/java/com/tabnineCommon/chat/lens/TabnineLensCollector.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package com.tabnineCommon.chat.lens | ||
|
||
import com.intellij.codeInsight.hints.FactoryInlayHintsCollector | ||
import com.intellij.codeInsight.hints.InlayHintsSink | ||
import com.intellij.codeInsight.hints.InlayPresentationFactory | ||
import com.intellij.codeInsight.hints.presentation.InlayPresentation | ||
import com.intellij.openapi.editor.Editor | ||
import com.intellij.openapi.ui.Messages | ||
import com.intellij.openapi.util.TextRange | ||
import com.intellij.psi.PsiElement | ||
import com.intellij.psi.util.elementType | ||
import com.intellij.refactoring.suggested.startOffset | ||
import com.tabnineCommon.binary.requests.analytics.EventRequest | ||
import com.tabnineCommon.chat.actions.common.ChatActionCommunicator | ||
import com.tabnineCommon.general.DependencyContainer | ||
import com.tabnineCommon.general.StaticConfig | ||
import java.awt.Point | ||
import java.awt.event.MouseEvent | ||
|
||
class TabnineLensCollector( | ||
editor: Editor, | ||
private val enabledElementTypes: List<String>, | ||
private val isChatEnabled: () -> Boolean | ||
) : FactoryInlayHintsCollector(editor) { | ||
companion object { | ||
private const val ID = "com.tabnine.chat.lens" | ||
} | ||
|
||
private val binaryRequestFacade = DependencyContainer.instanceOfBinaryRequestFacade() | ||
|
||
override fun collect(element: PsiElement, editor: Editor, sink: InlayHintsSink): Boolean { | ||
if (!isChatEnabled()) { | ||
return false | ||
} | ||
if (element.elementType.toString() in enabledElementTypes) { | ||
sink.addBlockElement( | ||
offset = element.startOffset, | ||
relatesToPrecedingText = true, | ||
showAbove = true, | ||
priority = 0, | ||
presentation = factory.seq( | ||
factory.textSpacePlaceholder(countLeadingWhitespace(editor, element), false), | ||
factory.icon(StaticConfig.getTabnineLensIcon()), | ||
buildQuickActionItem("Explain", "/explain-code", editor, element, false), | ||
buildQuickActionItem("Test", "/generate-test-for-code", editor, element, true), | ||
buildQuickActionItem("Document", "/document-code", editor, element, true), | ||
buildQuickActionItem("Fix", "/fix-code", editor, element, true), | ||
buildAskActionItem("Ask", editor, element), | ||
) | ||
) | ||
} | ||
return true | ||
} | ||
|
||
private fun buildQuickActionItem(label: String, intent: String, editor: Editor, element: PsiElement, includeSeparator: Boolean): InlayPresentation { | ||
return factory.seq( | ||
factory.smallText(" "), | ||
factory.smallText(if (includeSeparator) "| " else ""), | ||
factory.referenceOnHover( | ||
factory.smallText(label), | ||
object : InlayPresentationFactory.ClickListener { | ||
override fun onClick(event: MouseEvent, translated: Point) { | ||
sendClickEvent(intent) | ||
|
||
selectElementRange(editor, element) | ||
ChatActionCommunicator.sendMessageToChat(editor.project!!, ID, intent) | ||
} | ||
}, | ||
) | ||
) | ||
} | ||
|
||
private fun buildAskActionItem(label: String, editor: Editor, element: PsiElement): InlayPresentation { | ||
return factory.seq( | ||
factory.smallText(" "), | ||
factory.smallText("| "), | ||
factory.referenceOnHover( | ||
factory.smallText(label), | ||
object : InlayPresentationFactory.ClickListener { | ||
override fun onClick(event: MouseEvent, translated: Point) { | ||
sendClickEvent("ask") | ||
|
||
val result = | ||
Messages.showInputDialog("How can I assist with this code?", "Ask Tabnine", StaticConfig.getTabnineIcon()) | ||
.takeUnless { it.isNullOrBlank() } | ||
?: return | ||
|
||
selectElementRange(editor, element) | ||
ChatActionCommunicator.sendMessageToChat(editor.project!!, ID, result) | ||
} | ||
}, | ||
) | ||
) | ||
} | ||
|
||
private fun selectElementRange(editor: Editor, element: PsiElement) { | ||
val selectionModel = editor.selectionModel | ||
val range = element.textRange | ||
selectionModel.setSelection(range.startOffset, range.endOffset) | ||
} | ||
|
||
private fun sendClickEvent(intent: String) { | ||
binaryRequestFacade.executeRequest( | ||
EventRequest( | ||
"chat-code-lens-click", | ||
mapOf("intent" to intent) | ||
) | ||
) | ||
} | ||
|
||
private fun countLeadingWhitespace(editor: Editor, element: PsiElement): Int { | ||
val lineNumber = editor.document.getLineNumber(element.startOffset) | ||
return editor.document.getText( | ||
TextRange( | ||
editor.document.getLineStartOffset(lineNumber), | ||
editor.document.getLineEndOffset(lineNumber) | ||
) | ||
).takeWhile { it.isWhitespace() }.length | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
Tabnine/src/main/java/com/tabnine/chat/lens/TabnineLens.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.tabnine.chat.lens | ||
|
||
import com.tabnine.chat.ChatEnabledState | ||
import com.tabnineCommon.chat.lens.TabnineLensJavaBaseProvider | ||
import com.tabnineCommon.chat.lens.TabnineLensKotlinBaseProvider | ||
import com.tabnineCommon.chat.lens.TabnineLensPhpBaseProvider | ||
import com.tabnineCommon.chat.lens.TabnineLensPythonBaseProvider | ||
import com.tabnineCommon.chat.lens.TabnineLensRustBaseProvider | ||
import com.tabnineCommon.chat.lens.TabnineLensTypescriptBaseProvider | ||
|
||
open class TabnineLensJavaProvider : TabnineLensJavaBaseProvider({ ChatEnabledState.instance.get().enabled }) | ||
open class TabnineLensPythonProvider : TabnineLensPythonBaseProvider({ ChatEnabledState.instance.get().enabled }) | ||
open class TabnineLensTypescriptProvider : TabnineLensTypescriptBaseProvider({ ChatEnabledState.instance.get().enabled }) | ||
open class TabnineLensKotlinProvider : TabnineLensKotlinBaseProvider({ ChatEnabledState.instance.get().enabled }) | ||
open class TabnineLensPhpProvider : TabnineLensPhpBaseProvider({ ChatEnabledState.instance.get().enabled }) | ||
open class TabnineLensRustProvider : TabnineLensRustBaseProvider({ ChatEnabledState.instance.get().enabled }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
|
||
import com.intellij.codeInsight.hints.CollectorWithSettings | ||
import com.intellij.codeInsight.hints.InlayHintsSinkImpl | ||
import com.intellij.codeInsight.hints.NoSettings | ||
import com.intellij.openapi.editor.Inlay | ||
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixture4TestCase | ||
import com.tabnineCommon.chat.lens.TabnineLensJavaBaseProvider | ||
import org.junit.Test | ||
|
||
class TabnineLensIntegrationTest : LightPlatformCodeInsightFixture4TestCase() { | ||
|
||
@Test | ||
fun `should show inlay hints for java function when chat is enabled`() { | ||
setJavaFile() | ||
val provider = TabnineLensJavaBaseProvider { true } | ||
runCollector(provider) | ||
val inlays = getRenderedInlays() | ||
|
||
assertEquals(inlays[0].offset, 0) | ||
assertEquals(inlays[1].offset, 20) | ||
assertEquals(inlays.size, 2) | ||
} | ||
|
||
@Test | ||
fun `should not show inlay hints for java function when chat is disabled`() { | ||
setJavaFile() | ||
val provider = TabnineLensJavaBaseProvider { false } | ||
runCollector(provider) | ||
val inlays = getRenderedInlays() | ||
|
||
assertEquals(inlays.size, 0) | ||
} | ||
|
||
private fun setJavaFile() { | ||
myFixture.configureByText( | ||
"Test.java", | ||
"public class Test {\n public void test() {\n System.out.println(\"Hello World\");\n }\n}" | ||
) | ||
} | ||
|
||
private fun runCollector(provider: TabnineLensJavaBaseProvider) { | ||
val file = myFixture.file | ||
val editor = myFixture.editor | ||
val sink = InlayHintsSinkImpl(editor) | ||
|
||
val collector = provider.getCollectorFor(file, editor, NoSettings(), sink) | ||
val collectorWithSettings = CollectorWithSettings(collector, provider.key, file.language, sink) | ||
collectorWithSettings.collectTraversingAndApply( | ||
editor, | ||
file, | ||
true | ||
) | ||
} | ||
|
||
private fun getRenderedInlays(): MutableList<Inlay<*>> { | ||
return myFixture.editor.inlayModel.getBlockElementsInRange( | ||
myFixture.file.textRange.startOffset, | ||
myFixture.file.textRange.endOffset | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
TabnineSelfHosted/src/main/java/com/tabnineSelfHosted/chat/lens/TabnineLens.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.tabnineSelfHosted.chat.lens | ||
|
||
import com.tabnineCommon.chat.lens.TabnineLensJavaBaseProvider | ||
import com.tabnineCommon.chat.lens.TabnineLensKotlinBaseProvider | ||
import com.tabnineCommon.chat.lens.TabnineLensPhpBaseProvider | ||
import com.tabnineCommon.chat.lens.TabnineLensPythonBaseProvider | ||
import com.tabnineCommon.chat.lens.TabnineLensRustBaseProvider | ||
import com.tabnineCommon.chat.lens.TabnineLensTypescriptBaseProvider | ||
import com.tabnineSelfHosted.chat.SelfHostedChatEnabledState | ||
|
||
open class TabnineLensJavaProvider : TabnineLensJavaBaseProvider({ SelfHostedChatEnabledState.instance.get().enabled }) | ||
open class TabnineLensPythonProvider : TabnineLensPythonBaseProvider({ SelfHostedChatEnabledState.instance.get().enabled }) | ||
open class TabnineLensTypescriptProvider : TabnineLensTypescriptBaseProvider({ SelfHostedChatEnabledState.instance.get().enabled }) | ||
open class TabnineLensKotlinProvider : TabnineLensKotlinBaseProvider({ SelfHostedChatEnabledState.instance.get().enabled }) | ||
open class TabnineLensPhpProvider : TabnineLensPhpBaseProvider({ SelfHostedChatEnabledState.instance.get().enabled }) | ||
open class TabnineLensRustProvider : TabnineLensRustBaseProvider({ SelfHostedChatEnabledState.instance.get().enabled }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters