mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
[kotlin] IJPL-166464 add support for exclude list configuration for Kotlin parameter name hints
GitOrigin-RevId: 73cac11669f137cc1d07e3b352e16fd8cdca1cd3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
356725b73f
commit
287e6fe067
@@ -143,8 +143,8 @@
|
||||
defaultValue="true"
|
||||
restartRequired="true"/>
|
||||
|
||||
<registryKey key="kotlin.k2.auto.import.from.subclass.objects.enabled"
|
||||
defaultValue="true"
|
||||
<registryKey key="kotlin.k2.auto.import.from.subclass.objects.enabled"
|
||||
defaultValue="true"
|
||||
description="Enable auto-import of declarations inherited by objects in K2 Mode of Kotlin Plugin"/>
|
||||
|
||||
<registryKey key="kotlin.k2.auto.import.mismatched.arguments.factory.enabled"
|
||||
@@ -253,6 +253,15 @@
|
||||
descriptionKey="inlay.kotlin.parameters.hints.compiled"/>
|
||||
</codeInsight.declarativeInlayProvider>
|
||||
|
||||
<codeInsight.declarativeInlayProviderCustomSettingsProvider
|
||||
language="kotlin"
|
||||
providerId="kotlin.parameters.hints"
|
||||
implementationClass="org.jetbrains.kotlin.idea.k2.codeinsight.hints.KtParameterHintsCustomSettingsProvider"/>
|
||||
|
||||
<codeInsight.parameterHintsExcludeListConfigProvider
|
||||
language="kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.k2.codeinsight.hints.KtParameterHintsExcludeListConfigProvider"/>
|
||||
|
||||
<codeInsight.declarativeInlayProvider
|
||||
language="kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.k2.codeinsight.hints.KtCallChainHintsProvider"
|
||||
@@ -328,6 +337,11 @@
|
||||
class="org.jetbrains.kotlin.idea.k2.codeinsight.generate.KotlinGenerateToStringAction"/>
|
||||
<add-to-group group-id="GenerateGroup" anchor="first"/>
|
||||
</group>
|
||||
|
||||
<action id="KtAddToExcludeListAction"
|
||||
class="org.jetbrains.kotlin.idea.k2.codeinsight.hints.KtAddToExcludeListAction">
|
||||
<add-to-group group-id="InlayMenu"/>
|
||||
</action>
|
||||
</actions>
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<codeinsight.quickfix.registrar implementation="org.jetbrains.kotlin.idea.k2.codeinsight.quickFixes.createFromUsage.K2CreateFromUsageQuickFixesRegistrar"/>
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.analysis.api.analyze
|
||||
import org.jetbrains.kotlin.analysis.api.resolution.successfulFunctionCallOrNull
|
||||
import org.jetbrains.kotlin.analysis.api.resolution.symbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KaAnonymousFunctionSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KaFunctionSymbol
|
||||
import org.jetbrains.kotlin.idea.codeInsight.hints.SHOW_IMPLICIT_RECEIVERS_AND_PARAMS
|
||||
import org.jetbrains.kotlin.idea.codeInsight.hints.SHOW_RETURN_EXPRESSIONS
|
||||
import org.jetbrains.kotlin.idea.codeInsight.hints.isFollowedByNewLine
|
||||
@@ -181,3 +182,11 @@ class KtLambdasHintsProvider : AbstractKtInlayHintsProvider() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context(KaSession)
|
||||
internal fun KaFunctionSymbol.isExcludeListed(excludeListMatchers: List<Matcher>): Boolean {
|
||||
val callableFqName = callableId?.asSingleFqName()?.asString() ?: return false
|
||||
val parameterNames = valueParameters.map { it.name.asString() }
|
||||
return excludeListMatchers.any { it.isMatching(callableFqName, parameterNames) }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.k2.codeinsight.hints
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightBundle
|
||||
import com.intellij.codeInsight.hints.ExcludeListDialog
|
||||
import com.intellij.codeInsight.hints.declarative.*
|
||||
import com.intellij.codeInsight.hints.filtering.Matcher
|
||||
import com.intellij.codeInsight.hints.filtering.MatcherConstructor
|
||||
import com.intellij.codeInsight.hints.parameters.AbstractDeclarativeParameterHintsCustomSettingsProvider
|
||||
import com.intellij.codeInsight.hints.parameters.ParameterHintsExcludeListConfigProvider
|
||||
import com.intellij.codeInsight.hints.parameters.ParameterHintsExcludeListService
|
||||
import com.intellij.lang.Language
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.util.NlsActions
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
@@ -19,6 +28,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.KaNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbolOrigin
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KaValueParameterSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.types.KaFunctionType
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.codeInsight.hints.SHOW_COMPILED_PARAMETERS
|
||||
import org.jetbrains.kotlin.idea.codeInsight.hints.SHOW_EXCLUDED_PARAMETERS
|
||||
import org.jetbrains.kotlin.idea.codeinsights.impl.base.ArgumentNameCommentInfo
|
||||
@@ -29,84 +39,9 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifFalse
|
||||
|
||||
class KtParameterHintsProvider : AbstractKtInlayHintsProvider() {
|
||||
private val excludeListMatchers: List<Matcher> by lazy {
|
||||
setOf(
|
||||
"*listOf", "*setOf", "*arrayOf", "*ListOf", "*SetOf", "*ArrayOf", "*assert*(*)", "*mapOf", "*MapOf",
|
||||
"kotlin.require*(*)", "kotlin.check*(*)", "*contains*(value)", "*containsKey(key)", "kotlin.lazyOf(value)",
|
||||
"*SequenceBuilder.resume(value)", "*SequenceBuilder.yield(value)",
|
||||
|
||||
/* Gradle DSL especially annoying hints */
|
||||
"org.gradle.api.Project.property(propertyName)",
|
||||
"org.gradle.api.Project.hasProperty(propertyName)",
|
||||
"org.gradle.api.Project.findProperty(propertyName)",
|
||||
"org.gradle.api.Project.file(path)",
|
||||
"org.gradle.api.Project.uri(path)",
|
||||
"jvmArgs(arguments)",
|
||||
"org.gradle.kotlin.dsl.DependencyHandlerScope.*(notation)",
|
||||
"org.gradle.kotlin.dsl.PluginDependenciesSpecScope.*(*)",
|
||||
"org.gradle.kotlin.dsl.*(dependencyNotation)",
|
||||
"org.gradle.api.tasks.util.*include(includes)",
|
||||
"org.gradle.api.tasks.util.*exclude(excludes)",
|
||||
"org.gradle.kotlin.dsl.kotlin(module)",
|
||||
"org.gradle.kotlin.dsl.kotlin(module,version)",
|
||||
"org.gradle.kotlin.dsl.project(path,configuration)",
|
||||
"org.gradle.api.provider.Property.set(value)",
|
||||
"org.gradle.api.plugins.ObjectConfigurationAction.plugin(pluginId)",
|
||||
|
||||
/* copied from com.intellij.codeInsight.hints.JavaInlayParameterHintsProvider.defaultBlackList */
|
||||
// TODO: IJPL-166464 should provide API like InlayParameterHintsProvider#getBlackListDependencyLanguage
|
||||
|
||||
"(begin*, end*)",
|
||||
"(start*, end*)",
|
||||
"(first*, last*)",
|
||||
"(first*, second*)",
|
||||
"(from*, to*)",
|
||||
"(min*, max*)",
|
||||
"(key, value)",
|
||||
"(format, arg*)",
|
||||
"(message)",
|
||||
"(message, error)",
|
||||
|
||||
"*Exception",
|
||||
|
||||
"*.set*(*)",
|
||||
"*.add(*)",
|
||||
"*.set(*,*)",
|
||||
"*.get(*)",
|
||||
"*.create(*)",
|
||||
"*.getProperty(*)",
|
||||
"*.setProperty(*,*)",
|
||||
"*.print(*)",
|
||||
"*.println(*)",
|
||||
"*.append(*)",
|
||||
"*.charAt(*)",
|
||||
"*.indexOf(*)",
|
||||
"*.contains(*)",
|
||||
"*.startsWith(*)",
|
||||
"*.endsWith(*)",
|
||||
"*.equals(*)",
|
||||
"*.equal(*)",
|
||||
"*.compareTo(*)",
|
||||
"*.compare(*,*)",
|
||||
|
||||
"java.lang.Math.*",
|
||||
"org.slf4j.Logger.*",
|
||||
|
||||
"*.singleton(*)",
|
||||
"*.singletonList(*)",
|
||||
|
||||
"*.Set.of",
|
||||
"*.ImmutableList.of",
|
||||
"*.ImmutableMultiset.of",
|
||||
"*.ImmutableSortedMultiset.of",
|
||||
"*.ImmutableSortedSet.of",
|
||||
"*.Arrays.asList"
|
||||
|
||||
).mapNotNull { MatcherConstructor.createMatcher(it) }
|
||||
}
|
||||
|
||||
override fun collectFromElement(
|
||||
element: PsiElement,
|
||||
sink: InlayTreeSink
|
||||
@@ -128,14 +63,28 @@ class KtParameterHintsProvider : AbstractKtInlayHintsProvider() {
|
||||
val functionSymbol: KaFunctionSymbol = functionCall.symbol
|
||||
val valueParameters: List<KaValueParameterSymbol> = functionSymbol.valueParameters
|
||||
|
||||
val excludeListed = functionSymbol.isExcludeListed(excludeListMatchers)
|
||||
val excludeListed: Boolean
|
||||
val contextMenuPayloads: List<InlayPayload>?
|
||||
val callableFqName = functionSymbol.callableId?.asSingleFqName()?.asString()
|
||||
if (callableFqName != null) {
|
||||
val parameterNames = valueParameters.map { it.name.asString() }
|
||||
excludeListed = isExcludeListed(callableFqName, parameterNames)
|
||||
contextMenuPayloads = excludeListed.ifFalse {
|
||||
createAddToExcludeListActionPayloads(
|
||||
callableFqName, callableFqName + "(" + parameterNames.joinToString(", ") + ")", KotlinLanguage.INSTANCE
|
||||
)
|
||||
}
|
||||
} else {
|
||||
excludeListed = false
|
||||
contextMenuPayloads = null
|
||||
}
|
||||
|
||||
sink.whenOptionEnabled(SHOW_EXCLUDED_PARAMETERS.name) {
|
||||
if (excludeListed) {
|
||||
val valueParametersWithNames =
|
||||
calculateValueParametersWithNames(functionSymbol, callElement, valueParameters) ?: return@whenOptionEnabled
|
||||
|
||||
collectFromParameters(functionCall.argumentMapping, valueParametersWithNames, sink)
|
||||
collectFromParameters(functionCall.argumentMapping, valueParametersWithNames, contextMenuPayloads, sink)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,10 +100,10 @@ class KtParameterHintsProvider : AbstractKtInlayHintsProvider() {
|
||||
|
||||
if (compiledSource) {
|
||||
sink.whenOptionEnabled(SHOW_COMPILED_PARAMETERS.name) {
|
||||
collectFromParameters(functionCall.argumentMapping, valueParametersWithNames, sink)
|
||||
collectFromParameters(functionCall.argumentMapping, valueParametersWithNames, contextMenuPayloads, sink)
|
||||
}
|
||||
} else {
|
||||
collectFromParameters(functionCall.argumentMapping, valueParametersWithNames, sink)
|
||||
collectFromParameters(functionCall.argumentMapping, valueParametersWithNames, contextMenuPayloads, sink)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,6 +141,7 @@ class KtParameterHintsProvider : AbstractKtInlayHintsProvider() {
|
||||
private fun collectFromParameters(
|
||||
args: Map<KtExpression, KaVariableSignature<KaValueParameterSymbol>>,
|
||||
valueParametersWithNames: List<Pair<KaValueParameterSymbol, Name?>>,
|
||||
contextMenuPayloads: List<InlayPayload>?,
|
||||
sink: InlayTreeSink
|
||||
) {
|
||||
for ((symbol, name) in valueParametersWithNames) {
|
||||
@@ -215,7 +165,11 @@ class KtParameterHintsProvider : AbstractKtInlayHintsProvider() {
|
||||
|
||||
name.takeUnless(Name::isSpecial)?.asString()?.let { stringName ->
|
||||
val element = arg.getParentOfType<KtValueArgument>(true, KtValueArgumentList::class.java) ?: arg
|
||||
sink.addPresentation(InlineInlayPosition(element.startOffset, true), hintFormat = HintFormat.default) {
|
||||
sink.addPresentation(
|
||||
InlineInlayPosition(element.startOffset, true),
|
||||
payloads = contextMenuPayloads,
|
||||
hintFormat = HintFormat.default
|
||||
) {
|
||||
if (symbol.isVararg) text(Typography.ellipsis.toString())
|
||||
text(stringName,
|
||||
symbol.psi?.createSmartPointer()?.let {
|
||||
@@ -261,8 +215,87 @@ class KtParameterHintsProvider : AbstractKtInlayHintsProvider() {
|
||||
}
|
||||
|
||||
context(KaSession)
|
||||
internal fun KaFunctionSymbol.isExcludeListed(excludeListMatchers: List<Matcher>): Boolean {
|
||||
val callableFqName = callableId?.asSingleFqName()?.asString() ?: return false
|
||||
val parameterNames = valueParameters.map { it.name.asString() }
|
||||
return excludeListMatchers.any { it.isMatching(callableFqName, parameterNames) }
|
||||
}
|
||||
internal fun isExcludeListed(callableFqName: String, parameterNames: List<String>): Boolean {
|
||||
return ParameterHintsExcludeListService.getInstance().isExcluded(
|
||||
callableFqName,
|
||||
parameterNames,
|
||||
KotlinLanguage.INSTANCE
|
||||
)
|
||||
}
|
||||
|
||||
class KtParameterHintsExcludeListConfigProvider : ParameterHintsExcludeListConfigProvider {
|
||||
override fun getDefaultExcludeList(): Set<String> = setOf(
|
||||
"*listOf", "*setOf", "*arrayOf", "*ListOf", "*SetOf", "*ArrayOf", "*assert*(*)", "*mapOf", "*MapOf",
|
||||
"kotlin.require*(*)", "kotlin.check*(*)", "*contains*(value)", "*containsKey(key)", "kotlin.lazyOf(value)",
|
||||
"*SequenceBuilder.resume(value)", "*SequenceBuilder.yield(value)",
|
||||
|
||||
/* Gradle DSL especially annoying hints */
|
||||
"org.gradle.api.Project.property(propertyName)",
|
||||
"org.gradle.api.Project.hasProperty(propertyName)",
|
||||
"org.gradle.api.Project.findProperty(propertyName)",
|
||||
"org.gradle.api.Project.file(path)",
|
||||
"org.gradle.api.Project.uri(path)",
|
||||
"jvmArgs(arguments)",
|
||||
"org.gradle.kotlin.dsl.DependencyHandlerScope.*(notation)",
|
||||
"org.gradle.kotlin.dsl.PluginDependenciesSpecScope.*(*)",
|
||||
"org.gradle.kotlin.dsl.*(dependencyNotation)",
|
||||
// TODO '*' wildcard is only supported at the start or end of the method name
|
||||
// "org.gradle.api.tasks.util.*include(includes)",
|
||||
// "org.gradle.api.tasks.util.*exclude(excludes)",
|
||||
"org.gradle.kotlin.dsl.kotlin(module)",
|
||||
"org.gradle.kotlin.dsl.kotlin(module,version)",
|
||||
"org.gradle.kotlin.dsl.project(path,configuration)",
|
||||
"org.gradle.api.provider.Property.set(value)",
|
||||
"org.gradle.api.plugins.ObjectConfigurationAction.plugin(pluginId)",
|
||||
)
|
||||
|
||||
override fun getExcludeListDependencyLanguage(): Language = JavaLanguage.INSTANCE
|
||||
}
|
||||
|
||||
class KtParameterHintsCustomSettingsProvider : AbstractDeclarativeParameterHintsCustomSettingsProvider()
|
||||
|
||||
private const val METHOD_NAME: String = "addToExcludeList.name"
|
||||
private const val PATTERN_TO_ADD: String = "addToExcludeList.pattern"
|
||||
private const val LANG_ID: String = "addToExcludeList.lang"
|
||||
|
||||
fun createAddToExcludeListActionPayloads(methodName: String, patternToAdd: String, language: Language?): List<InlayPayload> = buildList {
|
||||
add(InlayPayload(METHOD_NAME, StringInlayActionPayload(methodName)))
|
||||
add(InlayPayload(PATTERN_TO_ADD, StringInlayActionPayload(patternToAdd)))
|
||||
if (language != null) {
|
||||
add(InlayPayload(LANG_ID, StringInlayActionPayload(language.id)))
|
||||
}
|
||||
}
|
||||
|
||||
class KtAddToExcludeListAction : AnAction() {
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
val methodName = e.getInlayPayloads()?.getStringPayload(METHOD_NAME)
|
||||
|
||||
if (methodName == null) {
|
||||
e.presentation.isEnabledAndVisible = false
|
||||
} else {
|
||||
e.presentation.isEnabledAndVisible = true
|
||||
e.presentation.text = getDisableHintText(methodName)
|
||||
}
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val payloads = e.getInlayPayloads() ?: return
|
||||
val patternToAdd = payloads.getStringPayload(PATTERN_TO_ADD)?: return
|
||||
val lang = payloads.getStringPayload(LANG_ID)?.let { Language.findLanguageByID(it) } ?: return
|
||||
val config = ParameterHintsExcludeListService.getInstance().getConfig(lang) ?: return
|
||||
ExcludeListDialog(config, patternToAdd).show()
|
||||
}
|
||||
|
||||
|
||||
@NlsActions.ActionText
|
||||
private fun getDisableHintText(methodName: String): String =
|
||||
CodeInsightBundle.message("inlay.hints.show.settings", methodName)
|
||||
}
|
||||
|
||||
private fun AnActionEvent.getInlayPayloads(): Map<String, InlayActionPayload>? =
|
||||
getData(InlayHintsProvider.INLAY_PAYLOADS)
|
||||
|
||||
private fun Map<String, InlayActionPayload>.getStringPayload(key: String): String? =
|
||||
(get(key) as? StringInlayActionPayload)?.text
|
||||
Reference in New Issue
Block a user