‘com.intellij.codeInsight.codeVisionProvider’Why is this extension point not supported in 2022.2?

Answered

‘com.intellij.codeInsight.codeVisionProvider’Why is this extension point not supported in 2022.2?

报错如下图所示:

0
10 comments

Please provide more details.

0

I have a version compatibility issue regarding 'Inlay Hints'

 

 

It can be displayed normally in 'IntelliJ IDEA2022.3.3'. as the picture shows:

Exhibiting exception in 'IntelliJ IDEA2022.2.3'. as the picture shows:

 

Error message:

java.lang.AbstractMethodError: Receiver class com.github.liminany.leanissjetbrainsideextension.inlay.CodeVisionInlay does not define or inherit an implementation of the resolved method 'abstract java.lang.String getGroupId()' of interface com.intellij.codeInsight.codeVision.CodeVisionProvider.
    at com.intellij.codeInsight.codeVision.CodeVisionHost.collectPlaceholders(CodeVisionHost.kt:182)
    at com.intellij.openapi.fileEditor.impl.text.PsiAwareTextEditorImpl.loadEditorInBackground(PsiAwareTextEditorImpl.java:70)
    at com.intellij.openapi.fileEditor.impl.text.AsyncEditorLoader.lambda$scheduleLoading$0(AsyncEditorLoader.java:95)
    at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:791)
    at com.intellij.openapi.fileEditor.impl.text.AsyncEditorLoader.lambda$scheduleLoading$1(AsyncEditorLoader.java:93)
    at com.intellij.openapi.application.impl.NonBlockingReadActionImpl$Submission.insideReadAction(NonBlockingReadActionImpl.java:536)
    at com.intellij.openapi.application.impl.NonBlockingReadActionImpl$Submission.lambda$attemptComputation$3(NonBlockingReadActionImpl.java:501)
    at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1154)
    at com.intellij.openapi.progress.util.ProgressIndicatorUtils.lambda$runInReadActionWithWriteActionPriority$0(ProgressIndicatorUtils.java:75)
    at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runActionAndCancelBeforeWrite(ProgressIndicatorUtils.java:158)
    at com.intellij.openapi.progress.util.ProgressIndicatorUtils.lambda$runWithWriteActionPriority$1(ProgressIndicatorUtils.java:115)
    at com.intellij.openapi.progress.ProgressManager.lambda$runProcess$0(ProgressManager.java:66)
    at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:188)
    at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$12(CoreProgressManager.java:608)
    at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:683)
    at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:639)
    at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:607)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:60)
    at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:175)
    at com.intellij.openapi.progress.ProgressManager.runProcess(ProgressManager.java:66)
    at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runWithWriteActionPriority(ProgressIndicatorUtils.java:112)
    at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(ProgressIndicatorUtils.java:75)
    at com.intellij.openapi.application.impl.NonBlockingReadActionImpl$Submission.attemptComputation(NonBlockingReadActionImpl.java:501)
    at com.intellij.openapi.application.impl.NonBlockingReadActionImpl$Submission.lambda$transferToBgThread$1(NonBlockingReadActionImpl.java:408)
    at com.intellij.util.concurrency.BoundedTaskExecutor.doRun(BoundedTaskExecutor.java:241)
    at com.intellij.util.concurrency.BoundedTaskExecutor.access$200(BoundedTaskExecutor.java:31)
    at com.intellij.util.concurrency.BoundedTaskExecutor$1.execute(BoundedTaskExecutor.java:214)
    at com.intellij.util.ConcurrencyUtil.runUnderThreadName(ConcurrencyUtil.java:212)
    at com.intellij.util.concurrency.BoundedTaskExecutor$1.run(BoundedTaskExecutor.java:203)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:702)
    at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:699)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:699)
    at java.base/java.lang.Thread.run(Thread.java:833)

 

 

 

my code:

 

class CodeVisionInlay : CodeVisionProvider<Unit>{
    companion object {
        internal const val id: String = "SmartChat"
    }

    override fun isAvailableFor(project: Project): Boolean {
        return true
    }

    override fun precomputeOnUiThread(editor: Editor) {
    }

    override fun preparePreview(editor: Editor, file: PsiFile) {
    }

    override fun computeCodeVision(editor: Editor, uiData: Unit): CodeVisionState {
        return runReadAction {
            val project = editor.project ?: return@runReadAction CodeVisionState.READY_EMPTY
            val document = editor.document
            val file = PsiDocumentManager.getInstance(project).getPsiFile(document)
                ?: return@runReadAction CodeVisionState.READY_EMPTY
            val lenses = ArrayList<Pair<TextRange, CodeVisionEntry>>()

            val traverser = SyntaxTraverser.psiTraverser(file)
            for (element in traverser.preOrderDfsTraversal()) {
                //在每个方法代码块上镶嵌提示内容
                if (element is PsiMethod) {
                    val textRange = InlayHintsUtils.getTextRangeWithoutLeadingCommentsAndWhitespaces(element)
                    val length = editor.document.textLength
                    val adjustedRange =
                     TextRange(Integer.min(textRange.startOffset, length), Integer.min(textRange.endOffset, length))
                    //嵌入提示的图标
                    val icon = ToolUtils.getImages("/images/pluginIcon.svg")//AllIcons.Vcs.Author
                    //点击嵌入提示触发的事件
                    val clickHandler = CodeAuthorClickHandler(element)
                    val entry = ClickableTextCodeVisionEntry("Sma", id, onClick = clickHandler, null, "Sma", "Sma", emptyList())
                    entry.showInMorePopup = false
                    lenses.add(adjustedRange to entry)
                }
            }
            return@runReadAction CodeVisionState.Ready(lenses)
        }

    }


    private class CodeAuthorClickHandler(val element: PsiElement) : (MouseEvent?, Editor) -> Unit {
        override fun invoke(event: MouseEvent?, editor: Editor) {
            if ((event != null) ) {
                JBPopupFactory.getInstance().createListPopup(
                    PluginDartIconActioinMenuList(
                        element = element
                    )
                ).show(RelativePoint(event.locationOnScreen))
            }

        }
    }

    override val name: String
        get() = "SmartChat"
    override val relativeOrderings: List<CodeVisionRelativeOrdering>
        get() = emptyList()
    override val defaultAnchor: CodeVisionAnchorKind
        get() = CodeVisionAnchorKind.NearScroll
    override val id: String
        get() = Companion.id


    data class PluginDartIconActionMenuItem(val key:String,val title: String, val type: String, val icon: Icon)
    class PluginDartIconActioinMenuList(val element: PsiElement) : BaseListPopupStep<PluginDartIconActionMenuItem>() {
        //按钮组列表
        private val menus = getMenus()
        init {
            super.init(element.text, menus, menus.map { it.icon })
        }
        override fun getTextFor(value: PluginDartIconActionMenuItem?): String {
            return value?.title ?: "未知选项"
        }

        override fun onChosen(selectedValue: PluginDartIconActionMenuItem?, finalChoice: Boolean): PopupStep<*>? {
            val key = selectedValue?.key;
            val title =  selectedValue?.title
            val project = PsiManager.getInstance(element.getProject()).project
            val service = project.service<MyProjectService>()

            if(service.jbCefBrowser == null) {
                val notificationGroup = NotificationGroup("AISE.Notification", NotificationDisplayType.BALLOON, true)
                val notify = notificationGroup.createNotification("Please open SmartChat chat window before using SmartChat context menu(Menu->View->Tool Window->SmartChat). ", NotificationType.WARNING)
                Notifications.Bus.notify(notify)
                println("jbCefBrowser is null !")
            }
            val selectedText = element.text;
            val msgJSON = JSONObject()
            msgJSON.put("type","sendCodeContextMessage.jetBrains")
            msgJSON.put("content","")
            msgJSON.put("id",System.currentTimeMillis())
            msgJSON.put("key",key)
            msgJSON.put("visibleText","")
            //代码块内容
            msgJSON.put("selectedContent", selectedText)
            msgJSON.put("triggerSource","ext.contextMenu")
            val data = JSONArray()
            msgJSON["selection"] = data

            if (selectedText !== null ) {
                service.jbCefBrowser!!.cefBrowser.mainFrame.executeJavaScript("window.pluginCallBrowser(${msgJSON.toJSONString()})",
                    service.jbCefBrowser!!.cefBrowser.mainFrame.url, 0) //JSONStyle.NO_COMPRESS
            }
            else {
                val notificationGroup = NotificationGroup("AISE.Notification", NotificationDisplayType.BALLOON, true)
                val notify = notificationGroup.createNotification("No code block selected for "+title, NotificationType.INFORMATION)
                Notifications.Bus.notify(notify)
            }
            return super.onChosen(selectedValue, finalChoice)
        }
        fun getMenus(): List<PluginDartIconActionMenuItem> {
            val listOfValues = mutableListOf<PluginDartIconActionMenuItem>()
            //提示词菜单,后期会通过接口获取
            val jsonArrayString = """
        [
            {
                "key": "Dev_Code_Explain",    //提示词唯一标识
                "text": "explain",            //提示词文本
                "description": "New York",   //提示词描述
                "actionClassName":"ToolbarDecorator",  //图标组
                "icon":"Export" //图标组下其中的一个元素
            },
            {
                "key": "Dev_Code_Review",
                "text": "review",
                "description": "review",
                "actionClassName":"Nodes",
                "icon":"Field"
            },
            {
                "key": "Dev_Code_GenUT",
                "text": "generate unit tests",
                "description": "generate unit tests",
                "actionClassName":"Nodes",
                "icon":"TestSourceFolder"

            }
        ]
    """
            val gson = Gson()
            // 使用TypeToken创建一个Type,以便Gson知道如何解析List<Map>
            val listType = object : TypeToken<List<Map<String, String>>>() {}.type
            // 将JSON字符串转换为List<Map>
            val list: List<Map<String, String>> = gson.fromJson(jsonArrayString, listType)
            for (element in list) {
                val firstMap: Map<String, String> = element
                val key = firstMap["key"].toString()
                val text = firstMap["text"].toString()
                //图片组
                val actionClassName = firstMap["actionClassName"].toString()
                //图片组下的一个图标
                val icon = firstMap["icon"].toString()
                //从idea图标库中获取图标
                val iconImage = ToolUtils.getIconName(actionClassName,icon)
                //动态添加提示词菜单
                listOfValues.add(
                    PluginDartIconActionMenuItem(
                        key = key,
                        title = text,
                        type = "navToPub",
                        icon = iconImage
                    ))
            }
            return listOfValues
        }
    }
}
 

 

 

 

 

0

Please note, this API is marked as Experimental and may change at any time https://plugins.jetbrains.com/docs/intellij/verifying-plugin-compatibility.html#unstable-api

What is the target IDE platform you're building your plugin against? It should be the lowest supported IDE version.

0

Yes, I know that's unstable. But that's not what I meant.

0

When a higher version of the plug-in is installed into a lower version of 'IDEA', what should be done so that the original functions of the plug-in are not affected?

0

There is nothing you can do to prevent such errors, other than following the recommendation of building against the lowest supported IDE version (assuming API will be kept backwards-compatible, which might not be the case for this API). You can use Plugin Verifier locally to check compliance https://plugins.jetbrains.com/docs/intellij/verifying-plugin-compatibility.html. 

Alternatively, you can target and build distinct versions of your plugin for each IDE version where there are breaking changes.

0

Can I do this? Make a judgment on the version number of 'IntelliJ IDEA' in the plug-in. If 'IntelliJ IDEA' is a new version, execute the new features in the plug-in. If 'IntelliJ IDEA' is an old version, the code for new features in the plug-in will not be executed. Keep the original functionality of the plug-in unaffected. Is this possible?

0

No, you need to build and release distinct versions of your plugin -- each targeting exact range of supported IDE version(s).

0

Okay, thank you.I'll think of other methods.

0

Please sign in to leave a comment.