diff --git a/plugins/kotlin/fir/kotlin.fir.iml b/plugins/kotlin/fir/kotlin.fir.iml index de95a21bc6a4..cebf539cb110 100644 --- a/plugins/kotlin/fir/kotlin.fir.iml +++ b/plugins/kotlin/fir/kotlin.fir.iml @@ -8,7 +8,7 @@ - + diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelFunctionParameterInfoHandler.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelFunctionParameterInfoHandler.kt new file mode 100644 index 000000000000..51d6b2e1d0c6 --- /dev/null +++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelFunctionParameterInfoHandler.kt @@ -0,0 +1,454 @@ +// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.kotlin.idea.parameterInfo + +import com.intellij.codeInsight.CodeInsightBundle +import com.intellij.lang.parameterInfo.CreateParameterInfoContext +import com.intellij.lang.parameterInfo.ParameterInfoHandlerWithTabActionSupport +import com.intellij.lang.parameterInfo.ParameterInfoUIContext +import com.intellij.lang.parameterInfo.UpdateParameterInfoContext +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.ui.Gray +import com.intellij.ui.JBColor +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.analyse +import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeRendererOptions +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtValueParameterSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.idea.project.languageVersionSettings +import org.jetbrains.kotlin.lexer.KtSingleValueToken +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.load.java.NULLABILITY_ANNOTATIONS +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.allChildren +import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.checkWithAttachment +import java.awt.Color +import kotlin.reflect.KClass + +class KotlinHighLevelFunctionParameterInfoHandler : + KotlinHighLevelParameterInfoWithCallHandlerBase( + KtValueArgumentList::class, KtValueArgument::class + ) { + override fun getActualParameters(arguments: KtValueArgumentList) = arguments.arguments.toTypedArray() + + override fun getActualParametersRBraceType(): KtSingleValueToken = KtTokens.RPAR + + override fun getArgumentListAllowedParentClasses() = setOf(KtCallElement::class.java) +} + +class KotlinHighLevelLambdaParameterInfoHandler : + KotlinHighLevelParameterInfoWithCallHandlerBase(KtLambdaArgument::class, KtLambdaArgument::class) { + + override fun getActualParameters(lambdaArgument: KtLambdaArgument) = arrayOf(lambdaArgument) + + override fun getActualParametersRBraceType(): KtSingleValueToken = KtTokens.RBRACE + + override fun getArgumentListAllowedParentClasses() = setOf(KtLambdaArgument::class.java) + + override fun getParameterIndex(context: UpdateParameterInfoContext, argumentList: KtLambdaArgument): Int { + val size = (argumentList.parent as? KtCallElement)?.valueArguments?.size ?: 1 + return size - 1 + } +} + +class KotlinHighLevelArrayAccessParameterInfoHandler : + KotlinHighLevelParameterInfoWithCallHandlerBase(KtContainerNode::class, KtExpression::class) { + + override fun getArgumentListAllowedParentClasses() = setOf(KtArrayAccessExpression::class.java) + + override fun getActualParameters(containerNode: KtContainerNode): Array = + containerNode.allChildren.filterIsInstance().toList().toTypedArray() + + override fun getActualParametersRBraceType(): KtSingleValueToken = KtTokens.RBRACKET +} + +// TODO: Overall structure is similar to FE 1.0 version (KotlinParameterInfoWithCallHandlerBase). Extract common logic to base class. +abstract class KotlinHighLevelParameterInfoWithCallHandlerBase( + private val argumentListClass: KClass, + private val argumentClass: KClass +) : ParameterInfoHandlerWithTabActionSupport { + + companion object { + @JvmField + val GREEN_BACKGROUND: Color = JBColor(Color(231, 254, 234), Gray._100) + + val STOP_SEARCH_CLASSES: Set> = setOf( + KtNamedFunction::class.java, + KtVariableDeclaration::class.java, + KtValueArgumentList::class.java, + KtLambdaArgument::class.java, + KtContainerNode::class.java, + KtTypeArgumentList::class.java + ) + } + + override fun getActualParameterDelimiterType(): KtSingleValueToken = KtTokens.COMMA + + override fun getArgListStopSearchClasses(): Set> = STOP_SEARCH_CLASSES + + override fun getArgumentListClass() = argumentListClass.java + + override fun showParameterInfo(element: TArgumentList, context: CreateParameterInfoContext) { + context.showHint(element, element.textRange.startOffset, this) + } + + override fun findElementForParameterInfo(context: CreateParameterInfoContext): TArgumentList? { + val file = context.file as? KtFile ?: return null + + val token = file.findElementAt(context.offset) ?: return null + val argumentList = PsiTreeUtil.getParentOfType(token, argumentListClass.java, true, *STOP_SEARCH_CLASSES.toTypedArray()) + ?: return null + + val callElement = argumentList.parent as? KtElement ?: return null + return analyse(callElement) { + // TODO: FE 1.0 plugin collects all candidates (i.e., all overloads), even if arguments do not match. Not just resolved call. + // See Call.resolveCandidates() in core/src/org/jetbrains/kotlin/idea/core/Utils.kt. Note `replaceCollectAllCandidates(true)`. + + val resolvedCall = when (callElement) { + is KtCallElement -> callElement.resolveCall() + is KtArrayAccessExpression -> callElement.resolveCall() + else -> return null + } + + val candidates = resolvedCall?.targetFunction?.candidates ?: return null + context.itemsToShow = candidates.map { CandidateInfo(it.createPointer()) }.toTypedArray() + + argumentList + } + } + + override fun findElementForUpdatingParameterInfo(context: UpdateParameterInfoContext): TArgumentList? { + val element = context.file.findElementAt(context.offset) ?: return null + return PsiTreeUtil.getParentOfType(element, argumentListClass.java) + } + + @OptIn(ExperimentalStdlibApi::class) + override fun updateParameterInfo(argumentList: TArgumentList, context: UpdateParameterInfoContext) { + if (context.parameterOwner !== argumentList) { + context.removeHint() + } + val parameterIndex = getParameterIndex(context, argumentList) + context.setCurrentParameter(parameterIndex) + + val callElement = argumentList.parent as? KtElement ?: return + analyse(callElement) { + val (resolvedCall, valueArguments, arguments) = when (callElement) { + is KtCallElement -> { + val valueArguments = callElement.valueArgumentList?.arguments + Triple(callElement.resolveCall(), valueArguments, valueArguments?.map { it.getArgumentExpression() } ?: listOf()) + } + is KtArrayAccessExpression -> Triple(callElement.resolveCall(), null, callElement.indexExpressions) + else -> return@analyse + } + val candidates = resolvedCall?.targetFunction?.candidates ?: return@analyse + + for (objectToView in context.objectsToView) { + val candidateInfo = objectToView as? CandidateInfo ?: continue + // Find candidate matching the one in CandidateInfo + // TODO: restoreSymbol does not work for static members (see Nullability.kt test), + // functional values (see FunctionalValue*.kt tests), and Java functions (see useJava*FromLib.kt tests). + // HL API gets a different symbol because a new ScopeSession() is used, and therefore a new enhanced FirFunction is created. + val candidateToMatch = candidateInfo.candidate.restoreSymbol() ?: return@analyse + val candidate = candidates.firstOrNull { it == candidateToMatch } ?: return@analyse + + // For array set calls, we only want the index arguments in brackets, which are all except the last (the value to set). + val isArraySetCall = candidate.callableIdIfNonLocal?.let { + val isSet = it.callableName == OperatorNameConventions.SET + isSet && callElement is KtArrayAccessExpression + } ?: false + // TODO: Get substituted value parameters. Not currently available in HL API. See SubstituteFromArguments*.kt tests + val valueParameters = candidate.valueParameters.let { if (isArraySetCall) it.dropLast(1) else it } + val setValueParameter = if (isArraySetCall) candidate.valueParameters.last() else null + + // TODO: When resolvedCall is KtFunctionalTypeVariableCall, the candidate is FunctionN.invoke() and parameter names are "p1", "p2", etc. + // We need to get the type of the target variable, and retrieve the parameter names from the type (KtFunctionalType). + // The names need to be added to KtFunctionalType (currently only types are there) and populated in KtSymbolByFirBuilder.TypeBuilder. + + val parameterToIndex = buildMap { + valueParameters.forEachIndexed { index, parameter -> put(parameter, index) } + } + + val parameterIndexToText = buildMap { + valueParameters.forEachIndexed { index, parameter -> + // TODO: Add hasSynthesizedParameterNames to HL API. + // See resolveValueParameters() in core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt + val hasSynthesizedParameterNames = false + val parameterText = renderParameter(parameter, includeName = !hasSynthesizedParameterNames) + put(index, parameterText) + } + } + + // TODO: The argument mapping should also be per-candidate once we have all candidates available. + val argumentMapping = resolvedCall.argumentMapping + val argumentToParameterIndex = LinkedHashMap(argumentMapping.size).apply { + for ((argumentExpression, parameterForArgument) in argumentMapping) { + if (parameterForArgument == setValueParameter) continue + put(argumentExpression, parameterToIndex.getValue(parameterForArgument)) + } + } + + // TODO: This should be changed when there are multiple candidates available; need to know which one the call is resolved to + val isCallResolvedToCandidate = candidates.size == 1 + + candidateInfo.callInfo = CallInfo( + callElement, + valueArguments, + arguments, + argumentToParameterIndex, + valueParameters.size, + parameterIndexToText, + isCallResolvedToCandidate + ) + } + } + } + + protected open fun getParameterIndex(context: UpdateParameterInfoContext, argumentList: TArgumentList): Int { + val offset = context.offset + return argumentList.allChildren + .takeWhile { it.startOffset < offset } + .count { it.node.elementType == KtTokens.COMMA } + } + + private fun KtAnalysisSession.renderParameter(parameter: KtValueParameterSymbol, includeName: Boolean): String { + return buildString { + val annotationFqNames = + parameter.annotations + .filter { + // For primary constructor parameters, the annotation use site must be "param" or unspecified. + it.useSiteTarget == null || it.useSiteTarget == AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER + } + .mapNotNull { it.classId?.asSingleFqName() } + .filter { it !in NULLABILITY_ANNOTATIONS } + annotationFqNames.forEach { append("@${it.shortName().asString()} ") } + + if (parameter.isVararg) { + append("vararg ") + } + + if (includeName) { + append(parameter.name) + append(": ") + } + + append(parameter.annotatedType.type.render(KtTypeRendererOptions.SHORT_NAMES)) + + if (parameter.hasDefaultValue) { + // TODO: append(" = " + defaultValue). + // HL API currently doesn't give actual default value. + } + } + } + + override fun updateUI(itemToShow: CandidateInfo, context: ParameterInfoUIContext) { + if (!updateUIOrFail(itemToShow, context)) { + context.isUIComponentEnabled = false + return + } + } + + /** + * This function sets up the presentation for a candidate's parameters, via the call to `setupUIComponentPresentation()` at the end. + * + * The logic for parameter order in the text is as follows: + * 1. In general, the parameters are listed in the order they are listed in the candidate. + * 2. However, the call may have a named argument that's NOT in its own position. In this case, you will have all parameters + * corresponding to named arguments first (in their order in the call), followed by any unused parameters in the order they + * are listed in the candidate. See NamedParameter*.kt tests. + * 3. Substituted types and default values should be rendered. + * + * The logic for surrounding parameters in brackets (e.g., "[x: Int], ...") is as follows: + * 1. When an argument is named, the parameter for that argument is surrounded in brackets. + * 2. When the named argument is NOT in its own position, then its corresponding parameter and all parameters after that are + * surrounded in brackets (i.e., `namedMode = true` in the code below). This is because all arguments must be named after it. + * See NamedParameter4.kt test. + * 3. When the named argument IS in its own position, and LanguageFeature.MixedNamedArgumentsInTheirOwnPosition is DISABLED, then + * `namedMode = true` as described above. See MixedNamedArguments2.kt test. + * + * The logic for highlighting a parameter (i.e., by setting `highlight(Start|End)Offset`) is as follows: + * 1. A parameter is highlighted when the cursor is on the corresponding argument in the candidate's mapping. + * 2. If the argument on the cursor does NOT map to a parameter (e.g., on N-th argument but there are < N parameters), + * then NO parameter is highlighted. + * 3. If the cursor is after a trailing comma with no argument, then we assume the user is about to enter an argument in that + * position. If there are N commas in the call arguments, AND if there are > N parameters, then the parameter in the + * N+1 position is highlighted, (e.g., the 3rd parameter for `foo(Int, Int, Int)` is highlighted in `foo(1, 2, )`). + * If there are <= N parameters, then NO parameter is highlighted (e.g., `foo(1, 2, 3, )`). + * + * `setupUIComponentPresentation()` is called with `disabled = true` when any of the following are true: + * 1. If the argument on the cursor does NOT map to a parameter (e.g., on N-th argument but there are < N parameters), + * 2. If any of the arguments before the cursor do NOT match the type of the corresponding parameter. + * 3. If the cursor is after a trailing comma with no argument, AND LanguageFeature.TrailingCommas is DISABLED, AND there are + * already enough arguments in the call. (We assume the user is about to enter an argument in that position.) + * + * `setupUIComponentPresentation()` is called with `backgroundColor = GREEN_BACKGROUND` if the call resolves to this candidate, + * even if there are type mismatches. Otherwise (e.g., the candidate is an overload with the same name), a default color is used. + * + * `setupUIComponentPresentation()` is called with `strikeout = true` if the candidate is annotated with `@Deprecated`. + */ + private fun updateUIOrFail(itemToShow: CandidateInfo, context: ParameterInfoUIContext): Boolean { + + if (context.parameterOwner == null || !context.parameterOwner.isValid) return false + if (!argumentListClass.java.isInstance(context.parameterOwner)) return false + + val currentArgumentIndex = context.currentParameterIndex + if (currentArgumentIndex < 0) return false + + val callInfo = itemToShow.callInfo ?: return false + val (callElement, valueArguments, arguments, argumentMapping, valueParameterCount, parameterIndexToText, isCallResolvedToCandidate) = callInfo + + val supportsMixedNamedArgumentsInTheirOwnPosition = + callElement.languageVersionSettings.supportsFeature(LanguageFeature.MixedNamedArgumentsInTheirOwnPosition) + + // TODO: This matches FE 1.0 plugin behavior. Consider just returning false here + checkWithAttachment( + arguments.size >= currentArgumentIndex, + lazyMessage = { "currentArgumentIndex: $currentArgumentIndex has to be not more than number of arguments ${arguments.size}" }, + attachments = { + it.withAttachment("file.kt", callElement.containingFile.text) + it.withAttachment("info.txt", itemToShow) + } + ) + + var highlightStartOffset = -1 + var highlightEndOffset = -1 + var isDisabledBeforeHighlight = false + val usedParameterIndices = HashSet() + val text = buildString { + var namedMode = false + var argumentIndex = 0 + + fun appendParameter( + parameterIndex: Int, + shouldHighlight: Boolean = false, + isNamed: Boolean = false, + markUsedUnusedParameterBorder: Boolean = false + ) { + argumentIndex++ + + if (length > 0) { + append(", ") + if (markUsedUnusedParameterBorder) { + // TODO: This matches FE 1.0 plugin behavior, but consider removing "disable before highlight". + // It's odd that we disable the used parameters, even though they might match. See NamedParameter3.kt test: + // `y = false` matches, and we disable it even though the next argument could match too (e.g., `x = `). + + // Highlight the space after the comma; highlighted text needs to be at least one character long + highlightStartOffset = length - 1 + highlightEndOffset = length + isDisabledBeforeHighlight = true + } + } + + if (shouldHighlight) { + highlightStartOffset = length + } + + val surroundInBrackets = isNamed || namedMode + if (surroundInBrackets) { + append("[") + } + append(parameterIndexToText[parameterIndex]) + if (surroundInBrackets) { + append("]") + } + + if (shouldHighlight) { + highlightEndOffset = length + } + } + + if (valueArguments != null) { + for (valueArgument in valueArguments) { + val parameterIndex = argumentMapping[valueArgument.getArgumentExpression()] ?: continue + if (!usedParameterIndices.add(parameterIndex)) continue + + if (valueArgument.isNamed() && + !(supportsMixedNamedArgumentsInTheirOwnPosition && parameterIndex == argumentIndex) + ) { + // "Named mode" (all arguments should be named) begins when there is a named argument NOT in their own position + // or named arguments in their own position is not supported. + namedMode = true + } + + val shouldHighlight = argumentIndex == currentArgumentIndex + appendParameter(parameterIndex, shouldHighlight, valueArgument.isNamed()) + } + } else { + // This is for array get/set calls which don't have KtValueArguments. + for (argument in arguments) { + val parameterIndex = argumentMapping[argument] ?: continue + if (!usedParameterIndices.add(parameterIndex)) continue + + val shouldHighlight = argumentIndex == currentArgumentIndex + appendParameter(parameterIndex, shouldHighlight) + } + } + + for (parameterIndex in 0 until valueParameterCount) { + if (parameterIndex !in usedParameterIndices) { + if (argumentIndex != parameterIndex) { + namedMode = true + } + // Highlight the first unused parameter if it is in the correct position + val shouldHighlight = !namedMode && highlightStartOffset == -1 + appendParameter( + parameterIndex, + shouldHighlight, + markUsedUnusedParameterBorder = namedMode && highlightStartOffset == -1 + ) + } + } + + if (length == 0) { + append(CodeInsightBundle.message("parameter.info.no.parameters")) + } + } + + val backgroundColor = if (isCallResolvedToCandidate) GREEN_BACKGROUND else context.defaultParameterColor + // TODO: Strikeout if deprecated. Deprecation status not currently in HL API + val strikeout = false + + // Disabled when there are too many arguments. + val allParametersUsed = usedParameterIndices.size == valueParameterCount + val supportsTrailingCommas = callElement.languageVersionSettings.supportsFeature(LanguageFeature.TrailingCommas) + val afterTrailingComma = arguments.isNotEmpty() && currentArgumentIndex == arguments.size + val tooManyArgs = allParametersUsed && ((!supportsTrailingCommas && afterTrailingComma) || arguments.size > valueParameterCount) + + // TODO: Also disable if not all arguments before the current are matched. Need to check this in updateParameterInfo() + // See UpdateInTyping.kt tests + val hasMismatchBeforeCurrent = false + + val isDisabled = tooManyArgs || hasMismatchBeforeCurrent + + context.setupUIComponentPresentation( + text, + highlightStartOffset, + highlightEndOffset, + isDisabled, + strikeout, + isDisabledBeforeHighlight, + backgroundColor + ) + + return true + } + + data class CallInfo( + val callElement: KtElement, + val valueArguments: List?, + val arguments: List, + val argumentToParameterIndex: LinkedHashMap, + val valueParameterCount: Int, + val parameterIndexToText: Map, + val isCallResolvedToCandidate: Boolean + ) + + data class CandidateInfo( + val candidate: KtSymbolPointer, + var callInfo: CallInfo? = null // Populated in updateParameterInfo() + ) +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/annotations/ConstructorCall.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/annotations/ConstructorCall.kt index 0e22111f6a2a..8ecc5a8822de 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/annotations/ConstructorCall.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/annotations/ConstructorCall.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR annotation class Fancy class Foo(@Fancy foo: Int) diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/annotations/ConstructorCallWithUseSite.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/annotations/ConstructorCallWithUseSite.kt index 30ee34a98703..7e827c19c110 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/annotations/ConstructorCallWithUseSite.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/annotations/ConstructorCallWithUseSite.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR // WITH_STDLIB annotation class Fancy diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/annotations/FunctionCall.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/annotations/FunctionCall.kt index 2149f9f17fd3..088739bce5b6 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/annotations/FunctionCall.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/annotations/FunctionCall.kt @@ -1,4 +1,5 @@ -// IGNORE_FIR +package test + annotation class Fancy private fun abc(@Fancy foo: Int) { diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/arrayAccess/Set.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/arrayAccess/Set.kt index 53b544d9e9fa..0f0c09cb12e6 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/arrayAccess/Set.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/arrayAccess/Set.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR class A { operator fun get(x: Int) {} operator fun set(x: String, y: Int, value: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/arrayAccess/SetTooManyArgs.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/arrayAccess/SetTooManyArgs.kt index 206e37c99d88..472f06274fe0 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/arrayAccess/SetTooManyArgs.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/arrayAccess/SetTooManyArgs.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR // COMPILER_ARGUMENTS: -XXLanguage:-NewInference class A { diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/arrayAccess/Simple.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/arrayAccess/Simple.kt index 6056ff2b1854..cff806a46264 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/arrayAccess/Simple.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/arrayAccess/Simple.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR class C { operator fun get(pInt: Int, pString: String){} } diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/Conflicting.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/Conflicting.kt index 8ad1c991e948..cc1ce65bd883 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/Conflicting.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/Conflicting.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR // Possible parameter info, for index, lambda and arguments. // Test is flaky without the fix. In IDEA there's a blinking without the fix with different popups. diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/ExtensionOnCapturedScopeChange.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/ExtensionOnCapturedScopeChange.kt index d5a5920366f6..917a77fa5d23 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/ExtensionOnCapturedScopeChange.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/ExtensionOnCapturedScopeChange.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR fun String.method1(fn: String.() -> Unit = {}) {} fun String.method2(param1: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/ExtensionOnClassObject.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/ExtensionOnClassObject.kt index c8ea011e0019..14e69004c687 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/ExtensionOnClassObject.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/ExtensionOnClassObject.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR interface A fun A.foo(i: Int) = i diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/Invoke.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/Invoke.kt index 61c56567fe88..4c95b257943c 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/Invoke.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/Invoke.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR package test class A { diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NamedParameter3.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NamedParameter3.kt index 112b455e5fee..dee1f70daf2e 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NamedParameter3.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NamedParameter3.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR open class A(x: Int) { fun m(x: Int, y: Boolean) = 1 diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NoAnnotations.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NoAnnotations.kt index e28b608e8990..690c4848c628 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NoAnnotations.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NoAnnotations.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR fun foo(@Suppress("UNCHECKED_CAST") p: () -> Unit){} fun bar() { diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NoShadowedDeclarations.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NoShadowedDeclarations.kt index 3a197d587e09..248b18d329fe 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NoShadowedDeclarations.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NoShadowedDeclarations.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR // WITH_STDLIB class A diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NoShadowedDeclarations2.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NoShadowedDeclarations2.kt index fff4b7c0ddd0..35916c56b146 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NoShadowedDeclarations2.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NoShadowedDeclarations2.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR fun A.some(s: String) { } diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NotGreen.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NotGreen.kt index ca366e146a3e..bca07c182ec0 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NotGreen.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NotGreen.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR open class A(x: Int) { fun m(x: Int, y: Boolean) = 2 fun m(x: Int) = 1 diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NullableTypeCall.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NullableTypeCall.kt index 5a46e0d7e15d..abc6a4c2cf96 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NullableTypeCall.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/NullableTypeCall.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR class A() fun A.index(x: Int) : Int { diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/PrivateConstructor.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/PrivateConstructor.kt index 2aecd873209f..3735c5bff59c 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/PrivateConstructor.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/PrivateConstructor.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR class A private constructor(f: Boolean) { constructor(): this(true) } diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/Simple.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/Simple.kt index 886768ec4bfa..bff96f7c820a 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/Simple.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/Simple.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR open class A(x: Int) { fun m(x: Int, y: Boolean) = 2 diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/SimpleConstructor.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/SimpleConstructor.kt index 530b9c466f41..9f53d58657ad 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/SimpleConstructor.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/SimpleConstructor.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR open class A(x: Int) { } diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/SmartCastReceiver.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/SmartCastReceiver.kt index f9fe5a6d49b2..bb898df9d47c 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/SmartCastReceiver.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/SmartCastReceiver.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR interface I fun I.foo(p: Int): Boolean = true diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/SmartCastReceiver2.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/SmartCastReceiver2.kt index 5036bdaf7127..d68300043094 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/SmartCastReceiver2.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/SmartCastReceiver2.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR interface I fun I.foo(p: Int): Boolean = true diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TooManyArgs.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TooManyArgs.kt index 72f3bdce4cfb..b94d7ecf5203 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TooManyArgs.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TooManyArgs.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR // COMPILER_ARGUMENTS: -XXLanguage:-TrailingCommas open class A(x: Int) { fun m(x: Int, y: Boolean) = 2 diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TooManyArgs2.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TooManyArgs2.kt index 4147472208df..2b0692e5d979 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TooManyArgs2.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TooManyArgs2.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR open class A(x: Int) { fun m(x: Int, y: Int) = 2 diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TrailingComma.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TrailingComma.kt index 7acdfa95b950..9d7d8fb76ef2 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TrailingComma.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TrailingComma.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR open class A(x: Int) { fun m(x: Int, y: Boolean) = 1 diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TypeAliasConstructor.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TypeAliasConstructor.kt index fa9f5876b06a..4c136a16698f 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TypeAliasConstructor.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/TypeAliasConstructor.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR class A(val a: Int) { constructor(val b: String) : this(b.toInt()) } diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/deprecatedSinceKotlinNotApplicable.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/deprecatedSinceKotlinNotApplicable.kt index da4dfabcff2d..be3882e4ad4b 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/deprecatedSinceKotlinNotApplicable.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/deprecatedSinceKotlinNotApplicable.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR @Suppress("DEPRECATED_SINCE_KOTLIN_OUTSIDE_KOTLIN_SUBPACKAGE") @Deprecated("") @DeprecatedSinceKotlin(warningSince = "999.999") diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/lambdaArgument.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/lambdaArgument.kt index 7c1e2a7f2718..5aede0b0c349 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/lambdaArgument.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/lambdaArgument.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR fun test() { foo { it.length } } diff --git a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/lambdaArgument2.kt b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/lambdaArgument2.kt index c24d8b9201bb..586a4f5196bb 100644 --- a/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/lambdaArgument2.kt +++ b/plugins/kotlin/idea/tests/testData/parameterInfo/functionCall/lambdaArgument2.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR fun test() { foo({ 1 }, { 2 }) { it.length } } diff --git a/plugins/kotlin/resources-fir/resources/META-INF/plugin.xml b/plugins/kotlin/resources-fir/resources/META-INF/plugin.xml index d7b17bfec67f..02746c533e52 100644 --- a/plugins/kotlin/resources-fir/resources/META-INF/plugin.xml +++ b/plugins/kotlin/resources-fir/resources/META-INF/plugin.xml @@ -167,6 +167,13 @@ The Kotlin FIR plugin provides language support in IntelliJ IDEA and Android Stu serviceInterface="org.jetbrains.kotlin.idea.api.ResolveAllowanceService"/> + + + +