mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-86123 Add navigation to attribute for keyword pattern inlay hints
GitOrigin-RevId: aeabf8a75d4725be7a17a20be34a22ad45a31c15
This commit is contained in:
committed by
intellij-monorepo-bot
parent
1c34e08d66
commit
af0f19abb9
@@ -70,6 +70,9 @@
|
||||
optionId="python.type.inlays.function.return"/>
|
||||
</codeInsight.declarativeInlayProvider>
|
||||
|
||||
<codeInsight.inlayActionHandler implementationClass="com.jetbrains.python.inlayHints.PyPseudoKeywordPatternInlayActionHandler"
|
||||
handlerId="py.pseudo.keyword.pattern"/>
|
||||
|
||||
|
||||
<!-- Requirements.txt support. Can't extract module due to circular dependency between it and community.impl (RequirementsFile inspection)-->
|
||||
<completion.contributor language="Requirements"
|
||||
|
||||
+5
-2
@@ -41,9 +41,12 @@ public final class PyKeywordPatternReference extends PsiReferenceBase.Poly<PyKey
|
||||
PyKeywordPattern keywordPattern = getElement();
|
||||
TypeEvalContext typeContext = TypeEvalContext.codeInsightFallback(keywordPattern.getProject());
|
||||
PyResolveContext resolveContext = PyResolveContext.defaultContext(typeContext);
|
||||
return resolveKeyword(classPattern, keywordPattern.getKeyword(), resolveContext);
|
||||
}
|
||||
|
||||
public static ResolveResult[] resolveKeyword(PyClassPattern classPattern, String keyword, PyResolveContext resolveContext) {
|
||||
return StreamEx.of(resolveToClassTypes(classPattern, resolveContext))
|
||||
.flatMap(t -> StreamEx.of(ContainerUtil.notNullize(t.resolveMember(keywordPattern.getKeyword(),
|
||||
null, AccessDirection.READ, resolveContext))))
|
||||
.flatMap(t -> StreamEx.of(ContainerUtil.notNullize(t.resolveMember(keyword, null, AccessDirection.READ, resolveContext))))
|
||||
.toArray(ResolveResult.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.inlayHints
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightBundle
|
||||
import com.intellij.codeInsight.hint.HintManager
|
||||
import com.intellij.codeInsight.hints.declarative.*
|
||||
import com.intellij.codeInsight.hints.declarative.impl.PresentationTreeBuilderImpl.Companion.MAX_SEGMENT_TEXT_LENGTH
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.event.EditorMouseEvent
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.SmartPointerManager
|
||||
import com.intellij.psi.SmartPsiElementPointer
|
||||
import com.intellij.util.PsiNavigateUtil
|
||||
import com.intellij.util.concurrency.annotations.RequiresEdt
|
||||
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider.REVEAL_TYPE
|
||||
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider.REVEAL_TYPE_EXT
|
||||
import com.jetbrains.python.documentation.PythonDocumentationProvider
|
||||
@@ -14,9 +23,14 @@ import com.jetbrains.python.psi.PyClassPattern
|
||||
import com.jetbrains.python.psi.PyFunction
|
||||
import com.jetbrains.python.psi.PyKeywordPattern
|
||||
import com.jetbrains.python.psi.impl.PyClassPatternImpl
|
||||
import com.jetbrains.python.psi.impl.references.PyKeywordPatternReference
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext
|
||||
import com.jetbrains.python.psi.types.PyClassType
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class PyTypeInlayHintsProvider : InlayHintsProvider {
|
||||
companion object {
|
||||
@@ -28,7 +42,7 @@ class PyTypeInlayHintsProvider : InlayHintsProvider {
|
||||
override fun createCollector(file: PsiFile, editor: Editor): InlayHintsCollector? = Collector()
|
||||
|
||||
private class Collector : SharedBypassCollector {
|
||||
val hintFormat = HintFormat.Companion.default
|
||||
val hintFormat = HintFormat.default
|
||||
.withFontSize(HintFontSize.ABitSmallerThanInEditor)
|
||||
.withHorizontalMargin(HintMarginPadding.MarginAndSmallerPadding)
|
||||
|
||||
@@ -96,13 +110,51 @@ class PyTypeInlayHintsProvider : InlayHintsProvider {
|
||||
val classType = typeEvalContext.getType(classPattern) as? PyClassType ?: return
|
||||
val matchArgs = PyClassPatternImpl.getMatchArgs(classType, typeEvalContext) ?: return
|
||||
classPattern.argumentList.patterns.mapIndexed { idx, pattern ->
|
||||
if (pattern is PyKeywordPattern) return
|
||||
if (pattern is PyKeywordPattern) return // positional patterns can only be before keyword patterns
|
||||
val name = matchArgs.getOrNull(idx) ?: return@mapIndexed
|
||||
sink.addPresentation(position = InlineInlayPosition(pattern.textRange.startOffset, false), hintFormat = hintFormat) {
|
||||
text(name)
|
||||
val navigationData = InlayActionData(
|
||||
PyPseudoKeywordPatternInlayActionHandler.Payload(SmartPointerManager.createPointer(classPattern), name),
|
||||
PyPseudoKeywordPatternInlayActionHandler.HANDLER_NAME
|
||||
)
|
||||
text(name, actionData = navigationData)
|
||||
text("=")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class PyPseudoKeywordPatternInlayActionHandler(private val cs: CoroutineScope) : InlayActionHandler {
|
||||
companion object {
|
||||
const val HANDLER_NAME: String = "py.pseudo.keyword.pattern"
|
||||
}
|
||||
|
||||
data class Payload(val classPattern: SmartPsiElementPointer<PyClassPattern>, val keyword: String) : InlayActionPayload
|
||||
|
||||
@RequiresEdt
|
||||
override fun handleClick(e: EditorMouseEvent, payload: InlayActionPayload) {
|
||||
payload as Payload
|
||||
|
||||
cs.launch {
|
||||
val resolveResults = readAction {
|
||||
val classPattern = payload.classPattern.element ?: return@readAction null
|
||||
val keyword = payload.keyword
|
||||
val typeEvalContext = TypeEvalContext.userInitiated(classPattern.project, classPattern.containingFile)
|
||||
PyKeywordPatternReference.resolveKeyword(classPattern, keyword, PyResolveContext.defaultContext(typeEvalContext))
|
||||
}
|
||||
val element = resolveResults?.firstOrNull()?.element ?: run {
|
||||
withContext(Dispatchers.EDT) {
|
||||
HintManager.getInstance().showInformationHint(e.editor, CodeInsightBundle.message("declaration.navigation.nowhere.to.go"))
|
||||
}
|
||||
return@launch
|
||||
}
|
||||
|
||||
withContext(Dispatchers.EDT) {
|
||||
PsiNavigateUtil.navigate(element)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user