mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-30 02:09:59 +07:00
[command-completion] IDEA-373902 Command completion. New actions: Quick Documentation
GitOrigin-RevId: 1b11c9c09af1413480f2f3237387080b14ad7b72
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b27f71e6f8
commit
5b2b71e74e
@@ -1496,6 +1496,7 @@
|
||||
<codeInsight.completion.command.provider language="JAVA" implementationClass="com.intellij.codeInsight.completion.commands.impl.JavaCopyCompletionCommandProvider" order="last"/>
|
||||
<codeInsight.completion.command.provider language="JAVA" implementationClass="com.intellij.codeInsight.completion.commands.impl.JavaTypeHierarchyCompletionCommandProvider" order="last"/>
|
||||
<codeInsight.completion.command.provider language="JAVA" implementationClass="com.intellij.codeInsight.completion.commands.impl.JavaTypeInfoCompletionCommandProvider" order="last"/>
|
||||
<codeInsight.completion.command.provider language="JAVA" implementationClass="com.intellij.codeInsight.completion.commands.impl.JavaQuickDocumentationCompletionCommand" order="last"/>
|
||||
|
||||
<weigher implementationClass="com.intellij.codeInsight.completion.LoggerWeigher" key="completion" id="logger"/>
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion.commands.impl
|
||||
|
||||
import com.intellij.codeInsight.completion.command.commands.AbstractQuickDocumentationCompletionCommand
|
||||
import com.intellij.codeInsight.completion.command.getCommandContext
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
|
||||
public class JavaQuickDocumentationCompletionCommand : AbstractQuickDocumentationCompletionCommand() {
|
||||
override fun findElement(offset: Int, psiFile: PsiFile): PsiElement? {
|
||||
var context = getCommandContext(offset, psiFile) ?: return null
|
||||
if (context is PsiWhiteSpace) context = context.prevSibling
|
||||
if (context !is PsiIdentifier) return null
|
||||
if (context.parent is PsiMember) return context
|
||||
if (((context.parent?.parent as? PsiTypeElement)?.type as? PsiClassType)?.resolve() is PsiMember) return context
|
||||
if (context.parent?.parent is PsiReferenceList && (context.parent as? PsiJavaCodeReferenceElement)?.resolve() is PsiMember) return context
|
||||
val value = PsiTreeUtil.getParentOfType(context, PsiJavaCodeReferenceElement::class.java, false) ?: return null
|
||||
val resolved = value.resolve()
|
||||
if (resolved is PsiMember || resolved is PsiPackage) return value
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -9,12 +9,11 @@ public class JavaTypeHierarchyCompletionCommandProvider : AbstractTypeHierarchyC
|
||||
override fun findElement(offset: Int, psiFile: PsiFile): PsiElement? {
|
||||
var context = getCommandContext(offset, psiFile)
|
||||
if (context is PsiWhiteSpace) context = context.prevSibling
|
||||
if (context is PsiIdentifier && context.parent is PsiClass) return context
|
||||
if (context is PsiIdentifier &&
|
||||
((context.parent?.parent as? PsiTypeElement)?.type as? PsiClassType)?.resolve() is PsiClass) return context
|
||||
if (context is PsiIdentifier &&
|
||||
context.parent?.parent is PsiReferenceList &&
|
||||
(context.parent as? PsiJavaCodeReferenceElement)?.resolve() is PsiClass) return context
|
||||
if (context !is PsiIdentifier) return null
|
||||
if (context.parent is PsiClass) return context
|
||||
if (((context.parent?.parent as? PsiTypeElement)?.type as? PsiClassType)?.resolve() is PsiClass) return context
|
||||
if (context.parent?.parent is PsiReferenceList && (context.parent as? PsiJavaCodeReferenceElement)?.resolve() is PsiClass) return context
|
||||
if (context.parent is PsiNameValuePair) return context
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.codeInsight.completion.commands
|
||||
|
||||
import com.intellij.codeInsight.completion.LightFixtureCompletionTestCase
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.testFramework.NeedsIndex
|
||||
|
||||
@NeedsIndex.SmartMode(reason = "it requires highlighting")
|
||||
class JavaCommandsCompletionQuickDocumentationTest : LightFixtureCompletionTestCase() {
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
Registry.get("ide.completion.command.enabled").setValue(false, getTestRootDisposable())
|
||||
Registry.get("ide.completion.command.force.enabled").setValue(true, getTestRootDisposable())
|
||||
}
|
||||
|
||||
fun testMember() {
|
||||
myFixture.configureByText(JavaFileType.INSTANCE, """
|
||||
class A {
|
||||
void foo.<caret>() {
|
||||
int y = 10;
|
||||
System.out.println(y);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
val elements = myFixture.completeBasic()
|
||||
assertNotNull(elements.firstOrNull { element -> element.lookupString.contains("Quick Documentation", ignoreCase = true) })
|
||||
}
|
||||
|
||||
fun testReference() {
|
||||
myFixture.configureByText(JavaFileType.INSTANCE, """
|
||||
class A {
|
||||
void foo() {
|
||||
int y = 10;
|
||||
System.out.println.<caret>(y);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
val elements = myFixture.completeBasic()
|
||||
assertNotNull(elements.firstOrNull { element -> element.lookupString.contains("Quick Documentation", ignoreCase = true) })
|
||||
}
|
||||
|
||||
fun testNoLocalVariable() {
|
||||
myFixture.configureByText(JavaFileType.INSTANCE, """
|
||||
class A {
|
||||
void foo() {
|
||||
int y = 10;
|
||||
System.out.println(y.<caret>);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
val elements = myFixture.completeBasic()
|
||||
assertNull(elements.firstOrNull { element -> element.lookupString.contains("Quick Documentation", ignoreCase = true) })
|
||||
}
|
||||
}
|
||||
@@ -254,6 +254,11 @@ c:com.intellij.codeInsight.actions.VcsFacade
|
||||
- a:getTextRangeImportList(com.intellij.psi.PsiFile,I):com.intellij.openapi.util.TextRange
|
||||
- p:isApplicable(I,com.intellij.psi.PsiFile,com.intellij.openapi.editor.Editor):Z
|
||||
- a:isImportList(com.intellij.psi.PsiFile,I):Z
|
||||
*a:com.intellij.codeInsight.completion.command.commands.AbstractQuickDocumentationCompletionCommand
|
||||
- com.intellij.codeInsight.completion.command.commands.ActionCommandProvider
|
||||
- <init>():V
|
||||
- p:createCommand(com.intellij.codeInsight.completion.command.CommandCompletionProviderContext):com.intellij.codeInsight.completion.command.commands.ActionCompletionCommand
|
||||
- a:findElement(I,com.intellij.psi.PsiFile):com.intellij.psi.PsiElement
|
||||
*a:com.intellij.codeInsight.completion.command.commands.AbstractRenameActionCommandProvider
|
||||
- com.intellij.codeInsight.completion.command.commands.ActionCommandProvider
|
||||
- <init>():V
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion.command.commands
|
||||
|
||||
import com.intellij.codeInsight.completion.command.CommandCompletionProviderContext
|
||||
import com.intellij.codeInsight.completion.command.HighlightInfoLookup
|
||||
import com.intellij.idea.ActionsBundle
|
||||
import com.intellij.openapi.editor.colors.EditorColors
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
|
||||
abstract class AbstractQuickDocumentationCompletionCommand :
|
||||
ActionCommandProvider(actionId = "QuickJavaDoc",
|
||||
presentableName = ActionsBundle.message("action.QuickJavaDoc.text"),
|
||||
icon = null,
|
||||
priority = -100,
|
||||
previewText = ActionsBundle.message("action.QuickJavaDoc.description")) {
|
||||
|
||||
abstract fun findElement(offset: Int, psiFile: PsiFile): PsiElement?
|
||||
|
||||
override fun createCommand(context: CommandCompletionProviderContext): ActionCompletionCommand? {
|
||||
val element = findElement(context.offset, context.psiFile) ?: return null
|
||||
if (element.textRange == null) return null
|
||||
return ActionCompletionCommand(actionId = super.actionId,
|
||||
presentableActionName = super.presentableName,
|
||||
icon = super.icon,
|
||||
priority = super.priority,
|
||||
previewText = super.previewText,
|
||||
synonyms = super.synonyms,
|
||||
highlightInfo = HighlightInfoLookup(element.textRange, EditorColors.SEARCH_RESULT_ATTRIBUTES, 0))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.completion.impl.k2.contributors.commands
|
||||
|
||||
import com.intellij.codeInsight.completion.command.commands.AbstractQuickDocumentationCompletionCommand
|
||||
import com.intellij.codeInsight.completion.command.getCommandContext
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiMember
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.util.parentOfType
|
||||
import org.jetbrains.kotlin.analysis.api.analyze
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.CommentSaver.Companion.tokenType
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtUserType
|
||||
|
||||
class KotlinQuickDocumentationCompletionCommandProvider : AbstractQuickDocumentationCompletionCommand() {
|
||||
override fun findElement(offset: Int, psiFile: PsiFile): PsiElement? {
|
||||
var context = getCommandContext(offset, psiFile)
|
||||
if (context is PsiWhiteSpace) context = context.prevSibling
|
||||
if (context?.tokenType != KtTokens.IDENTIFIER) return null
|
||||
if (isDeclaration(context.parent)) return context
|
||||
if (context.parent is KtNameReferenceExpression &&
|
||||
context.parent?.parent is KtUserType
|
||||
) {
|
||||
val type = (context.parent?.parent as? KtUserType) ?: return null
|
||||
val resolved = type.referenceExpression?.mainReference?.resolve()
|
||||
analyze(type) {
|
||||
if (isDeclaration(resolved) || resolved is PsiMember) return context
|
||||
}
|
||||
}
|
||||
|
||||
val referenceExpression = context.parentOfType<KtNameReferenceExpression>()
|
||||
if (referenceExpression != null && analyze(referenceExpression) {
|
||||
val resolved = referenceExpression.mainReference.resolve()
|
||||
isDeclaration(resolved) || resolved is PsiMember
|
||||
}) {
|
||||
return referenceExpression
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun isDeclaration(element: PsiElement?): Boolean {
|
||||
return element is KtNamedDeclaration && !(element is KtProperty && element.isLocal)
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package org.jetbrains.kotlin.idea.completion.impl.k2.contributors.commands
|
||||
|
||||
import com.intellij.codeInsight.completion.command.commands.AbstractTypeHierarchyCompletionCommandProvider
|
||||
import com.intellij.codeInsight.completion.command.getCommandContext
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
@@ -25,7 +26,8 @@ class KotlinTypeHierarchyCompletionCommandProvider : AbstractTypeHierarchyComple
|
||||
) {
|
||||
val type = (context.parent?.parent as? KtUserType) ?: return null
|
||||
analyze(type) {
|
||||
if (type.referenceExpression?.mainReference?.resolve() is KtClass) return context
|
||||
val resolved = type.referenceExpression?.mainReference?.resolve()
|
||||
if (resolved is KtClass || resolved is PsiClass) return context
|
||||
}
|
||||
}
|
||||
return null
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.fir.completion.commands
|
||||
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
|
||||
class K2CommandCompletionQuickDocumentationTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
override val pluginMode = KotlinPluginMode.K2
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
Registry.get("ide.completion.command.enabled").setValue(false, getTestRootDisposable())
|
||||
Registry.get("ide.completion.command.force.enabled").setValue(true, getTestRootDisposable())
|
||||
}
|
||||
|
||||
fun testClass() {
|
||||
myFixture.configureByText(
|
||||
"x.kt", """
|
||||
class A.<caret> {
|
||||
fun foo(a: String) {
|
||||
var b = a
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
val elements = myFixture.completeBasic()
|
||||
assertNotNull(elements.firstOrNull() { element -> element.lookupString.contains("Quick Documentation", ignoreCase = true) })
|
||||
}
|
||||
|
||||
fun testReference() {
|
||||
myFixture.configureByText(
|
||||
"x.kt", """
|
||||
class A {
|
||||
fun foo(a: String) {
|
||||
print.<caret>(a)
|
||||
}
|
||||
|
||||
fun print(a: String) {
|
||||
var b = a
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
val elements = myFixture.completeBasic()
|
||||
assertNotNull(elements.firstOrNull() { element -> element.lookupString.contains("Quick Documentation", ignoreCase = true) })
|
||||
}
|
||||
|
||||
fun testNoLocalVariable() {
|
||||
myFixture.configureByText(
|
||||
"x.kt", """
|
||||
class A {
|
||||
fun foo() {
|
||||
val a.<caret> = "1"
|
||||
print(a)
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
val elements = myFixture.completeBasic()
|
||||
assertNull(elements.firstOrNull() { element -> element.lookupString.contains("Quick Documentation", ignoreCase = true) })
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@
|
||||
<codeInsight.completion.command.provider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.completion.impl.k2.contributors.commands.KotlinCopyCompletionCommandProvider" order="last"/>
|
||||
<codeInsight.completion.command.provider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.completion.impl.k2.contributors.commands.KotlinTypeHierarchyCompletionCommandProvider" order="last"/>
|
||||
<codeInsight.completion.command.provider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.completion.impl.k2.contributors.commands.KotlinTypeInfoCompletionCommandProvider" order="last"/>
|
||||
<codeInsight.completion.command.provider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.completion.impl.k2.contributors.commands.KotlinQuickDocumentationCompletionCommandProvider" order="last"/>
|
||||
</extensions>
|
||||
|
||||
</idea-plugin>
|
||||
|
||||
Reference in New Issue
Block a user