From 2f6fb4091b956de45052395cce702b6b9de0c6fa Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Mon, 26 Feb 2018 15:34:28 +0300 Subject: [PATCH] making `LambdaArgument` methods nullable overridden `LambdaArgument.getArgumentExpression` removed because it is already nullable in parent #EA-117013 --- .../kotlin/contracts/EffectsExtractingVisitor.kt | 2 +- .../org/jetbrains/kotlin/psi/KtLambdaArgument.kt | 4 +--- .../org/jetbrains/kotlin/psi/ValueArgument.kt | 4 +--- .../kotlin/resolve/calls/tasks/dynamicCalls.kt | 13 +++++++------ .../resolve/calls/tower/PSICallResolver.kt | 4 ++-- .../generators/ErrorExpressionGenerator.kt | 6 +----- .../idea/references/KtInvokeFunctionReference.kt | 2 +- .../kotlin/idea/core/psiModificationUtils.kt | 6 +++++- .../idea/codeInliner/ReplacementPerformer.kt | 6 +++++- .../idea/codeInliner/UsageReplacementStrategy.kt | 2 +- .../upDownMover/KotlinExpressionMover.java | 4 +++- .../ScopeFunctionConversionInspection.kt | 12 ++++++------ .../collections/SimplifyCallChainFix.kt | 16 ++++++++-------- .../ConvertTryFinallyToUseCallIntention.kt | 2 +- .../MoveLambdaInsideParenthesesIntention.kt | 3 +-- .../intentions/ObjectLiteralToLambdaIntention.kt | 2 +- .../ExtractableCodeDescriptor.kt | 2 +- .../uast/kotlin/KotlinUastLanguagePlugin.kt | 2 +- 18 files changed, 47 insertions(+), 45 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectsExtractingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectsExtractingVisitor.kt index cae15b7248a..58d9c031fbb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectsExtractingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectsExtractingVisitor.kt @@ -173,7 +173,7 @@ class EffectsExtractingVisitor( valueArgumentsByIndex?.mapTo(arguments) { val valueArgument = (it as? ExpressionValueArgument)?.valueArgument ?: return null when (valueArgument) { - is KtLambdaArgument -> ESLambda(valueArgument.getLambdaExpression()) + is KtLambdaArgument -> valueArgument.getLambdaExpression()?.let { ESLambda(it) } ?: return null else -> extractOrGetCached(valueArgument.getArgumentExpression() ?: return null) } } ?: return null diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtLambdaArgument.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtLambdaArgument.kt index 9279df94e35..1554d3692f0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtLambdaArgument.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtLambdaArgument.kt @@ -20,9 +20,7 @@ import com.intellij.lang.ASTNode class KtLambdaArgument(node: ASTNode) : KtValueArgument(node), LambdaArgument { - override fun getArgumentExpression() = super.getArgumentExpression()!! - - override fun getLambdaExpression(): KtLambdaExpression = getArgumentExpression().unpackFunctionLiteral()!! + override fun getLambdaExpression(): KtLambdaExpression? = getArgumentExpression()?.unpackFunctionLiteral() } fun KtExpression.unpackFunctionLiteral(allowParentheses: Boolean = false): KtLambdaExpression? { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/ValueArgument.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/ValueArgument.kt index 8e5203415cc..e55b8bc7dd7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/ValueArgument.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/ValueArgument.kt @@ -37,9 +37,7 @@ interface ValueArgument { } interface LambdaArgument : ValueArgument { - fun getLambdaExpression(): KtLambdaExpression - - override fun getArgumentExpression(): KtExpression + fun getLambdaExpression(): KtLambdaExpression? } interface ValueArgumentName { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt index caeee922c57..58b5bda036b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt @@ -31,11 +31,8 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.getValue -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.types.createDynamicType +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.expressions.OperatorConventions -import org.jetbrains.kotlin.types.isDynamic import org.jetbrains.kotlin.utils.Printer import java.util.* @@ -53,7 +50,8 @@ class DynamicCallableDescriptors(storageManager: StorageManager, builtIns: Kotli override fun getContributedFunctions(name: Name, location: LookupLocation): Collection { if (isAugmentedAssignmentConvention(name)) return listOf() if (call.callType == Call.CallType.INVOKE - && call.valueArgumentList == null && call.functionLiteralArguments.isEmpty()) { + && call.valueArgumentList == null && call.functionLiteralArguments.isEmpty() + ) { // this means that we are looking for "imaginary" invokes, // e.g. in `+d` we are looking for property "plus" with member "invoke" return listOf() @@ -217,7 +215,10 @@ class DynamicCallableDescriptors(storageManager: StorageManager, builtIns: Kotli if (hasSpreadOperator) { for (funLiteralArg in call.functionLiteralArguments) { - addParameter(funLiteralArg, getFunctionType(funLiteralArg.getLambdaExpression()), null) + addParameter( + funLiteralArg, + funLiteralArg.getLambdaExpression()?.let { getFunctionType(it) } ?: TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE, + null) } break diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index 77b33ad8f61..0a3892519a1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -462,8 +462,8 @@ class PSICallResolver( oldCall.valueArguments.last() } else { if (externalLambdaArguments.size > 2) { - externalLambdaArguments.drop(1).forEach { - context.trace.report(Errors.MANY_LAMBDA_EXPRESSION_ARGUMENTS.on(it.getLambdaExpression())) + externalLambdaArguments.drop(1).mapNotNull { it.getLambdaExpression() }.forEach { + context.trace.report(Errors.MANY_LAMBDA_EXPRESSION_ARGUMENTS.on(it)) } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ErrorExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ErrorExpressionGenerator.kt index 047d108e286..8213f53c720 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ErrorExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ErrorExpressionGenerator.kt @@ -50,17 +50,13 @@ class ErrorExpressionGenerator(statementGenerator: StatementGenerator) : Stateme receiverExpression.genExpr() } - ktCall.valueArguments.forEach { + (ktCall.valueArguments + ktCall.lambdaArguments).forEach { val ktArgument = it.getArgumentExpression() if (ktArgument != null) { irErrorCall.addArgument(ktArgument.genExpr()) } } - ktCall.lambdaArguments.forEach { - irErrorCall.addArgument(it.getArgumentExpression().genExpr()) - } - irErrorCall } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReference.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReference.kt index 86173bc77c5..eff19bed6c9 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReference.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReference.kt @@ -76,7 +76,7 @@ class KtInvokeFunctionReference(expression: KtCallExpression) : KtSimpleReferenc val functionLiteralArguments = expression.lambdaArguments for (functionLiteralArgument in functionLiteralArguments) { - val functionLiteralExpression = functionLiteralArgument.getArgumentExpression().unpackFunctionLiteral() ?: continue + val functionLiteralExpression = functionLiteralArgument.getLambdaExpression() ?: continue list.add(getRange(functionLiteralExpression.leftCurlyBrace)) val rightCurlyBrace = functionLiteralExpression.rightCurlyBrace if (rightCurlyBrace != null) { diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt index 8367fc42d37..c71681de792 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt @@ -41,6 +41,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParenthese import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.isError +import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments import org.jetbrains.kotlin.utils.SmartList @Suppress("UNCHECKED_CAST") @@ -56,7 +57,10 @@ inline fun PsiElement.replaced(newElement: T): T { fun T.copied(): T = copy() as T fun KtLambdaArgument.moveInsideParentheses(bindingContext: BindingContext): KtCallExpression { - return moveInsideParenthesesAndReplaceWith(this.getArgumentExpression(), bindingContext) + val ktExpression = this.getArgumentExpression() + ?: throw KotlinExceptionWithAttachments("no argument expression for $this") + .withAttachment("lambdaExpression", this.text) + return moveInsideParenthesesAndReplaceWith(ktExpression, bindingContext) } fun KtLambdaArgument.moveInsideParenthesesAndReplaceWith( diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInliner/ReplacementPerformer.kt b/idea/src/org/jetbrains/kotlin/idea/codeInliner/ReplacementPerformer.kt index 44b6b7375ce..ed4626226ae 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInliner/ReplacementPerformer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInliner/ReplacementPerformer.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.psi.psiUtil.canPlaceAfterSimpleNameEntry import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression +import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments import java.util.* internal abstract class ReplacementPerformer( @@ -210,7 +211,10 @@ internal class ExpressionReplacementPerformer( val runExpression = psiFactory.createExpressionByPattern("run { $0 }", elementToBeReplaced) as KtCallExpression val runAfterReplacement = elementToBeReplaced.replaced(runExpression) - val block = runAfterReplacement.lambdaArguments[0].getLambdaExpression().bodyExpression!! + val ktLambdaArgument = runAfterReplacement.lambdaArguments[0] + val block = ktLambdaArgument.getLambdaExpression()?.bodyExpression + ?: throw KotlinExceptionWithAttachments("cant get body expression for $ktLambdaArgument") + .withAttachment("ktLambdaArgument", ktLambdaArgument.text) elementToBeReplaced = block.statements.single() return elementToBeReplaced diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInliner/UsageReplacementStrategy.kt b/idea/src/org/jetbrains/kotlin/idea/codeInliner/UsageReplacementStrategy.kt index 371a608f135..a09246005cb 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInliner/UsageReplacementStrategy.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInliner/UsageReplacementStrategy.kt @@ -164,7 +164,7 @@ private fun UsageReplacementStrategy.specialUsageProcessing(usage: KtSimpleNameE val grandParent = usageParent.parent val specifySignature = SpecifyExplicitLambdaSignatureIntention() for (lambdaArgument in lambdaArguments) { - val lambdaExpression = lambdaArgument.getLambdaExpression() + val lambdaExpression = lambdaArgument.getLambdaExpression() ?: continue val functionDescriptor = lambdaExpression.functionLiteral.resolveToDescriptorIfAny() as? FunctionDescriptor ?: continue if (functionDescriptor.valueParameters.isNotEmpty()) { diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/upDownMover/KotlinExpressionMover.java b/idea/src/org/jetbrains/kotlin/idea/codeInsight/upDownMover/KotlinExpressionMover.java index 9265e0aeb24..b865d8cc393 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/upDownMover/KotlinExpressionMover.java +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/upDownMover/KotlinExpressionMover.java @@ -217,7 +217,9 @@ public class KotlinExpressionMover extends AbstractKotlinUpDownMover { List functionLiterals = callExpression.getLambdaArguments(); if (functionLiterals.isEmpty()) return null; - return functionLiterals.get(0).getLambdaExpression().getBodyExpression(); + KtLambdaExpression lambdaExpression = functionLiterals.get(0).getLambdaExpression(); + if (lambdaExpression == null) return null; + return lambdaExpression.getBodyExpression(); } @Nullable diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt index 4d5cae50a85..3fe727c1d34 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt @@ -72,9 +72,9 @@ private fun getCounterpart(expression: KtCallExpression): String? { val callee = expression.calleeExpression as? KtNameReferenceExpression ?: return null val calleeName = callee.getReferencedName() val counterpartName = counterpartNames[calleeName] - val lambdaArgument = expression.lambdaArguments.singleOrNull() - if (counterpartName != null && lambdaArgument != null) { - if (lambdaArgument.getLambdaExpression().valueParameters.isNotEmpty()) { + val lambdaExpression = expression.lambdaArguments.singleOrNull()?.getLambdaExpression() + if (counterpartName != null && lambdaExpression != null) { + if (lambdaExpression.valueParameters.isNotEmpty()) { return null } val bindingContext = callee.analyze(BodyResolveMode.PARTIAL) @@ -151,7 +151,7 @@ abstract class ConvertScopeFunctionFix(private val counterpartName: String) : Lo val bindingContext = callExpression.analyze() val lambda = callExpression.lambdaArguments.firstOrNull() ?: return - val functionLiteral = lambda.getLambdaExpression().functionLiteral + val functionLiteral = lambda.getLambdaExpression()?.functionLiteral ?: return val lambdaDescriptor = bindingContext[FUNCTION, functionLiteral] ?: return val replacements = ReplacementCollection() @@ -186,13 +186,13 @@ class ConvertScopeFunctionToParameter(counterpartName: String) : ConvertScopeFun ) { val project = lambda.project val factory = KtPsiFactory(project) - val functionLiteral = lambda.getLambdaExpression().functionLiteral + val functionLiteral = lambda.getLambdaExpression()?.functionLiteral val lambdaExtensionReceiver = lambdaDescriptor.extensionReceiverParameter val lambdaDispatchReceiver = lambdaDescriptor.dispatchReceiverParameter var parameterName = "it" val scopes = mutableSetOf() - if (needUniqueNameForParameter(lambda, scopes)) { + if (functionLiteral != null && needUniqueNameForParameter(lambda, scopes)) { val parameterType = lambdaExtensionReceiver?.type ?: lambdaDispatchReceiver?.type parameterName = findUniqueParameterName(parameterType, scopes) replacements.createParameter = { diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifyCallChainFix.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifyCallChainFix.kt index 61eafb4c7be..3268f51a156 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifyCallChainFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifyCallChainFix.kt @@ -47,16 +47,16 @@ class SimplifyCallChainFix(val newName: String) : LocalQuickFix { val lastArgumentPrefix = if (newName.startsWith("joinTo")) "transform = " else "" val arguments = secondCallExpression.valueArgumentList?.arguments.orEmpty().map { it.text } + firstCallExpression.valueArgumentList?.arguments.orEmpty().map { "$lastArgumentPrefix${it.text}" } - val lambdaArgument = firstCallExpression.lambdaArguments.singleOrNull() + val lambdaExpression = firstCallExpression.lambdaArguments.singleOrNull()?.getLambdaExpression() val argumentsText = arguments.ifNotEmpty { joinToString(prefix = "(", postfix = ")") } ?: "" - val newQualifiedExpression = if (lambdaArgument != null) factory.createExpressionByPattern( - "$0$1$2 $3 $4", - receiverExpression ?: "", - operationSign, - newName, - argumentsText, - lambdaArgument.getLambdaExpression().text + val newQualifiedExpression = if (lambdaExpression != null) factory.createExpressionByPattern( + "$0$1$2 $3 $4", + receiverExpression ?: "", + operationSign, + newName, + argumentsText, + lambdaExpression.text ) else factory.createExpressionByPattern( "$0$1$2 $3", diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTryFinallyToUseCallIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTryFinallyToUseCallIntention.kt index b5d7e21f688..c03dd4af40f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTryFinallyToUseCallIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTryFinallyToUseCallIntention.kt @@ -76,7 +76,7 @@ class ConvertTryFinallyToUseCallIntention : SelfTargetingRangeIntention return } val lambda = call.lambdaArguments.firstOrNull() ?: return - val lambdaParameter = lambda.getLambdaExpression().valueParameters.firstOrNull() ?: return + val lambdaParameter = lambda.getLambdaExpression()?.valueParameters?.firstOrNull() ?: return editor?.selectionModel?.setSelection(lambdaParameter.startOffset, lambdaParameter.endOffset) } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/MoveLambdaInsideParenthesesIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/MoveLambdaInsideParenthesesIntention.kt index 4038ed90fce..0ee52f54544 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/MoveLambdaInsideParenthesesIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/MoveLambdaInsideParenthesesIntention.kt @@ -22,13 +22,12 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.core.moveInsideParentheses import org.jetbrains.kotlin.psi.KtLambdaArgument import org.jetbrains.kotlin.psi.psiUtil.containsInside -import org.jetbrains.kotlin.psi.unpackFunctionLiteral class MoveLambdaInsideParenthesesIntention : SelfTargetingIntention( KtLambdaArgument::class.java, "Move lambda argument into parentheses" ), LowPriorityAction { override fun isApplicableTo(element: KtLambdaArgument, caretOffset: Int): Boolean { - val body = element.getArgumentExpression().unpackFunctionLiteral()?.bodyExpression ?: return true + val body = element.getLambdaExpression()?.bodyExpression ?: return true return !body.textRange.containsInside(caretOffset) } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ObjectLiteralToLambdaIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ObjectLiteralToLambdaIntention.kt index 380cac698fa..b003f7bcd41 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ObjectLiteralToLambdaIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ObjectLiteralToLambdaIntention.kt @@ -145,7 +145,7 @@ class ObjectLiteralToLambdaIntention : SelfTargetingRangeIntention KotlinConverter.convertExpression(element, givenParent, requiredType) - is KtLambdaArgument -> KotlinConverter.convertExpression(element.getLambdaExpression(), givenParent, requiredType) + is KtLambdaArgument -> element.getLambdaExpression()?.let { KotlinConverter.convertExpression(it, givenParent, requiredType) } is KtLightAnnotationForSourceEntry.LightExpressionValue<*> -> { val expression = element.originalExpression when (expression) {