From e6c0d4692a96d9a66fd4e6d19010e9198c39640f Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Tue, 29 Sep 2015 18:44:53 +0300 Subject: [PATCH] Fix operator warning on 'Constr()()' --- .../resolve/DelegatedPropertyResolver.java | 2 +- .../kotlin/resolve/calls/CallCompleter.kt | 2 +- .../validation/DeprecatedSymbolValidator.kt | 18 +++++++++---- .../resolve/validation/InfixValidator.kt | 8 +++++- .../resolve/validation/OperatorValidator.kt | 26 ++++++++----------- .../validation/SymbolUsageValidator.kt | 7 ++--- .../BasicExpressionTypingVisitor.java | 4 +-- .../ForLoopConventionsChecker.java | 4 +-- .../expressions/MultiDeclarationResolver.kt | 2 +- .../testData/diagnostics/tests/Operators.kt | 5 +++- .../deadCode/deadCallInInvokeCall.kt | 4 +-- .../nullabilityWarnings/invoke.kt | 6 ++--- 12 files changed, 51 insertions(+), 37 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.java index 10679ff5609..f65ebf2eaf8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.java @@ -217,7 +217,7 @@ public class DelegatedPropertyResolver { JetPropertyDelegate delegate = property.getDelegate(); if (delegate != null) { PsiElement byKeyword = delegate.getByKeywordNode().getPsi(); - symbolUsageValidator.validateCall(resultingCall.getResultingDescriptor(), trace, byKeyword); + symbolUsageValidator.validateCall(resultingCall, resultingCall.getResultingDescriptor(), trace, byKeyword); } } trace.record(DELEGATED_PROPERTY_RESOLVED_CALL, accessor, resultingCall); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt index 13b7fed6297..69ceeb4917f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt @@ -86,7 +86,7 @@ public class CallCompleter( resolvedCall.variableCall.getCall().getCalleeExpression() else resolvedCall.getCall().getCalleeExpression() - symbolUsageValidator.validateCall(resolvedCall.getResultingDescriptor(), context.trace, element!!) + symbolUsageValidator.validateCall(resolvedCall, resolvedCall.getResultingDescriptor(), context.trace, element!!) } if (results.isSingleResult() && results.getResultingCall().getStatus().isSuccess()) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/DeprecatedSymbolValidator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/DeprecatedSymbolValidator.kt index ace49dcd77d..953634021b9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/DeprecatedSymbolValidator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/DeprecatedSymbolValidator.kt @@ -33,18 +33,19 @@ import org.jetbrains.kotlin.resolve.annotations.argumentValue import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.PROPERTY_GETTER import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.PROPERTY_SETTER import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall public class DeprecatedSymbolValidator : SymbolUsageValidator { private val JAVA_DEPRECATED = FqName(java.lang.Deprecated::class.java.name) - override fun validateCall(targetDescriptor: CallableDescriptor, trace: BindingTrace, element: PsiElement) { + override fun validateCall(resolvedCall: ResolvedCall<*>?, targetDescriptor: CallableDescriptor, trace: BindingTrace, element: PsiElement) { val deprecated = targetDescriptor.getDeprecatedAnnotation() if (deprecated != null) { val (annotation, target) = deprecated trace.report(createDeprecationDiagnostic(element, target, annotation)) } else if (targetDescriptor is PropertyDescriptor) { - propertyGetterWorkaround(targetDescriptor, trace, element) + propertyGetterWorkaround(resolvedCall, targetDescriptor, trace, element) } } @@ -122,8 +123,15 @@ public class DeprecatedSymbolValidator : SymbolUsageValidator { Errors.DEPRECATED_SYMBOL_WITH_MESSAGE.on(element, descriptor.original, message) } - private val PROPERTY_SET_OPERATIONS = TokenSet.create(JetTokens.EQ, JetTokens.PLUSEQ, JetTokens.MINUSEQ, JetTokens.MULTEQ, JetTokens.DIVEQ, JetTokens.PERCEQ, JetTokens.PLUSPLUS, JetTokens.MINUSMINUS) - fun propertyGetterWorkaround(propertyDescriptor: PropertyDescriptor, trace: BindingTrace, expression: PsiElement) { + private val PROPERTY_SET_OPERATIONS = TokenSet.create(JetTokens.EQ, JetTokens.PLUSEQ, JetTokens.MINUSEQ, JetTokens.MULTEQ, + JetTokens.DIVEQ, JetTokens.PERCEQ, JetTokens.PLUSPLUS, JetTokens.MINUSMINUS) + + fun propertyGetterWorkaround( + resolvedCall: ResolvedCall<*>?, + propertyDescriptor: PropertyDescriptor, + trace: BindingTrace, + expression: PsiElement + ) { // property getters do not come as callable yet, so we analyse surroundings to check for deprecation annotation on getter val binaryExpression = PsiTreeUtil.getParentOfType(expression, javaClass()) if (binaryExpression != null) { @@ -159,6 +167,6 @@ public class DeprecatedSymbolValidator : SymbolUsageValidator { return // skip Type::property } - propertyDescriptor.getGetter()?.let { validateCall(it, trace, expression) } + propertyDescriptor.getGetter()?.let { validateCall(resolvedCall, it, trace, expression) } } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/InfixValidator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/InfixValidator.kt index 272dcb61b0d..970a6ff5e72 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/InfixValidator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/InfixValidator.kt @@ -23,13 +23,19 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.JetBinaryExpression import org.jetbrains.kotlin.psi.JetOperationReferenceExpression import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.types.ErrorUtils public class InfixValidator : SymbolUsageValidator { - override fun validateCall(targetDescriptor: CallableDescriptor, trace: BindingTrace, element: PsiElement) { + override fun validateCall( + resolvedCall: ResolvedCall<*>?, + targetDescriptor: CallableDescriptor, + trace: BindingTrace, + element: PsiElement + ) { val functionDescriptor = targetDescriptor as? FunctionDescriptor ?: return if (functionDescriptor.isDynamic() || ErrorUtils.isError(functionDescriptor)) return if (isInfixCall(element) && !functionDescriptor.isInfix) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/OperatorValidator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/OperatorValidator.kt index 81f008eee22..1e8788ed6b5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/OperatorValidator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/OperatorValidator.kt @@ -21,35 +21,31 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.psi.JetArrayAccessExpression -import org.jetbrains.kotlin.psi.JetElement -import org.jetbrains.kotlin.psi.JetMultiDeclarationEntry -import org.jetbrains.kotlin.psi.JetOperationReferenceExpression +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.bindingContextUtil.get import org.jetbrains.kotlin.resolve.BindingTrace -import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall +import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe -import org.jetbrains.kotlin.resolve.bindingContextUtil.get +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall public class OperatorValidator : SymbolUsageValidator { - override fun validateCall(targetDescriptor: CallableDescriptor, trace: BindingTrace, element: PsiElement) { + override fun validateCall(resolvedCall: ResolvedCall<*>?, targetDescriptor: CallableDescriptor, trace: BindingTrace, element: PsiElement) { val functionDescriptor = targetDescriptor as? FunctionDescriptor ?: return if (functionDescriptor.isDynamic() || ErrorUtils.isError(functionDescriptor)) return val jetElement = element as? JetElement ?: return - val call = trace.bindingContext[BindingContext.CALL, jetElement] + val call = resolvedCall?.call ?: trace.bindingContext[BindingContext.CALL, jetElement] - fun isVariableAsFunctionCall(): Boolean { - if (call == null) return false - val resolvedCall = trace.bindingContext[BindingContext.RESOLVED_CALL, call] ?: return false - return resolvedCall is VariableAsFunctionResolvedCall + fun isInvokeCall(): Boolean { + return call is CallTransformer.CallForImplicitInvoke } fun isMultiDeclaration(): Boolean { - return call?.callElement is JetMultiDeclarationEntry + return (resolvedCall != null) && (call?.callElement is JetMultiDeclarationEntry) } fun isConventionOperator(): Boolean { @@ -59,14 +55,14 @@ public class OperatorValidator : SymbolUsageValidator { fun isArrayAccessExpression() = jetElement is JetArrayAccessExpression - if (isMultiDeclaration()) { + if (isMultiDeclaration() || isInvokeCall()) { if (!functionDescriptor.isOperator && call != null) { report(call.callElement, functionDescriptor, trace) } return } - if (isVariableAsFunctionCall() || isConventionOperator() || isArrayAccessExpression()) { + if (isConventionOperator() || isArrayAccessExpression()) { if (!functionDescriptor.isOperator) { report(jetElement, functionDescriptor, trace) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/SymbolUsageValidator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/SymbolUsageValidator.kt index d04874ac109..53fb7654854 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/SymbolUsageValidator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/SymbolUsageValidator.kt @@ -20,16 +20,17 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall public interface SymbolUsageValidator { public fun validateTypeUsage(targetDescriptor: ClassifierDescriptor, trace: BindingTrace, element: PsiElement) { } - public fun validateCall(targetDescriptor: CallableDescriptor, trace: BindingTrace, element: PsiElement) { } + public fun validateCall(resolvedCall: ResolvedCall<*>?, targetDescriptor: CallableDescriptor, trace: BindingTrace, element: PsiElement) { } public open class Composite(val validators: List) : SymbolUsageValidator { - override fun validateCall(targetDescriptor: CallableDescriptor, trace: BindingTrace, element: PsiElement) { - validators.forEach { it.validateCall(targetDescriptor, trace, element) } + override fun validateCall(resolvedCall: ResolvedCall<*>?, targetDescriptor: CallableDescriptor, trace: BindingTrace, element: PsiElement) { + validators.forEach { it.validateCall(resolvedCall, targetDescriptor, trace, element) } } override fun validateTypeUsage(targetDescriptor: ClassifierDescriptor, trace: BindingTrace, element: PsiElement) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 6337114345b..163ce222b4c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -501,7 +501,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { checker.check(resolvedCall, resolutionContext); } - components.symbolUsageValidator.validateCall(descriptor, trace, expression); + components.symbolUsageValidator.validateCall(resolvedCall, descriptor, trace, expression); } private static boolean isDeclaredInClass(ReceiverParameterDescriptor receiver) { @@ -943,7 +943,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { result = false; } else { if (setter != null) { - components.symbolUsageValidator.validateCall(setter, trace, reportOn); + components.symbolUsageValidator.validateCall(null, setter, trace, reportOn); } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ForLoopConventionsChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ForLoopConventionsChecker.java index b7c84078957..65192c9d392 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ForLoopConventionsChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ForLoopConventionsChecker.java @@ -79,7 +79,7 @@ public class ForLoopConventionsChecker { checkIfOperatorModifierPresent(loopRangeExpression, iteratorFunction, context.trace); - symbolUsageValidator.validateCall(iteratorFunction, context.trace, loopRangeExpression); + symbolUsageValidator.validateCall(iteratorResolvedCall, iteratorFunction, context.trace, loopRangeExpression); JetType iteratorType = iteratorFunction.getReturnType(); JetType hasNextType = checkConventionForIterator(context, loopRangeExpression, iteratorType, "hasNext", @@ -140,7 +140,7 @@ public class ForLoopConventionsChecker { ResolvedCall resolvedCall = nextResolutionResults.getResultingCall(); context.trace.record(resolvedCallKey, loopRangeExpression, resolvedCall); FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor(); - symbolUsageValidator.validateCall(functionDescriptor, context.trace, loopRangeExpression); + symbolUsageValidator.validateCall(resolvedCall, functionDescriptor, context.trace, loopRangeExpression); checkIfOperatorModifierPresent(loopRangeExpression, functionDescriptor, context.trace); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/MultiDeclarationResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/MultiDeclarationResolver.kt index 52d928a0949..5fdf43562b0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/MultiDeclarationResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/MultiDeclarationResolver.kt @@ -57,7 +57,7 @@ public class MultiDeclarationResolver( context.trace.record(BindingContext.COMPONENT_RESOLVED_CALL, entry, results.getResultingCall()) val functionDescriptor = results.getResultingDescriptor() - symbolUsageValidator.validateCall(functionDescriptor, context.trace, entry) + symbolUsageValidator.validateCall(null, functionDescriptor, context.trace, entry) componentType = functionDescriptor.getReturnType() if (componentType != null && !TypeUtils.noExpectedType(expectedType) && !JetTypeChecker.DEFAULT.isSubtypeOf(componentType, expectedType)) { diff --git a/compiler/testData/diagnostics/tests/Operators.kt b/compiler/testData/diagnostics/tests/Operators.kt index d3770468068..53e51606b85 100644 --- a/compiler/testData/diagnostics/tests/Operators.kt +++ b/compiler/testData/diagnostics/tests/Operators.kt @@ -88,8 +88,11 @@ fun a() { !a !c - a() + a() c() + + Example()() + Example2()() } abstract class Base { diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCallInInvokeCall.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCallInInvokeCall.kt index 9285b7122f1..3a761cbe7d2 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCallInInvokeCall.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCallInInvokeCall.kt @@ -1,10 +1,10 @@ fun testInvoke() { - fun Nothing.invoke() = this + operator fun Nothing.invoke() = this todo()() } fun testInvokeWithLambda() { - fun Nothing.invoke(i: Int, f: () -> Int) = f + operator fun Nothing.invoke(i: Int, f: () -> Int) = f todo()(1){ 42 } } diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.kt index 81459c66ebd..4b96ed0b427 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.kt @@ -17,7 +17,7 @@ public class J { // FILE: k.kt fun test() { - J.staticNN() - J.staticN() - J.staticJ() + J.staticNN() + J.staticN() + J.staticJ() } \ No newline at end of file