Fix unreported deprecation on variables called as functions

#KT-16272 Fixed
This commit is contained in:
Alexander Udalov
2017-02-10 18:06:40 +03:00
parent 6793861fd4
commit 57f2feb6fb
5 changed files with 36 additions and 31 deletions
@@ -53,7 +53,6 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
import org.jetbrains.kotlin.types.expressions.FakeCallResolver
import java.util.* import java.util.*
class CallCompleter( class CallCompleter(
@@ -62,7 +61,6 @@ class CallCompleter(
private val dataFlowAnalyzer: DataFlowAnalyzer, private val dataFlowAnalyzer: DataFlowAnalyzer,
private val callCheckers: Iterable<CallChecker>, private val callCheckers: Iterable<CallChecker>,
private val builtIns: KotlinBuiltIns, private val builtIns: KotlinBuiltIns,
private val fakeCallResolver: FakeCallResolver,
private val languageVersionSettings: LanguageVersionSettings, private val languageVersionSettings: LanguageVersionSettings,
private val compilerConfiguration: CompilerConfiguration private val compilerConfiguration: CompilerConfiguration
) { ) {
@@ -86,7 +84,7 @@ class CallCompleter(
temporaryTrace.commit() temporaryTrace.commit()
} }
if (resolvedCall != null) { if (resolvedCall != null && context.trace.wantsDiagnostics()) {
val calleeExpression = if (resolvedCall is VariableAsFunctionResolvedCall) val calleeExpression = if (resolvedCall is VariableAsFunctionResolvedCall)
resolvedCall.variableCall.call.calleeExpression resolvedCall.variableCall.call.calleeExpression
else else
@@ -95,10 +93,12 @@ class CallCompleter(
if (calleeExpression != null && !calleeExpression.isFakeElement) calleeExpression if (calleeExpression != null && !calleeExpression.isFakeElement) calleeExpression
else resolvedCall.call.callElement else resolvedCall.call.callElement
if (context.trace.wantsDiagnostics()) { val callCheckerContext = CallCheckerContext(context, languageVersionSettings, compilerConfiguration)
val callCheckerContext = CallCheckerContext(context, languageVersionSettings, compilerConfiguration) for (callChecker in callCheckers) {
for (callChecker in callCheckers) { callChecker.check(resolvedCall, reportOn, callCheckerContext)
callChecker.check(resolvedCall, reportOn, callCheckerContext)
if (resolvedCall is VariableAsFunctionResolvedCall) {
callChecker.check(resolvedCall.variableCall, reportOn, callCheckerContext)
} }
} }
} }
@@ -17,13 +17,15 @@
package org.jetbrains.kotlin.resolve.calls.resolvedCallUtil package org.jetbrains.kotlin.resolve.calls.resolvedCallUtil
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.KtThisExpression
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
@@ -74,29 +76,16 @@ fun ResolvedCall<*>.getExplicitReceiverValue(): ReceiverValue? {
} }
} }
fun ResolvedCall<*>.getImplicitReceiverValue(): ImplicitReceiver? { fun ResolvedCall<*>.getImplicitReceiverValue(): ImplicitReceiver? =
return when (explicitReceiverKind) { getImplicitReceivers().firstOrNull() as? ImplicitReceiver
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER -> extensionReceiver ?: dispatchReceiver
ExplicitReceiverKind.DISPATCH_RECEIVER -> extensionReceiver
ExplicitReceiverKind.EXTENSION_RECEIVER -> dispatchReceiver
else -> null
} as? ImplicitReceiver
}
fun ResolvedCall<*>.getImplicitReceivers(): Collection<ReceiverValue> { fun ResolvedCall<*>.getImplicitReceivers(): Collection<ReceiverValue> =
if (this is VariableAsFunctionResolvedCall) { when (explicitReceiverKind) {
val receivers = variableCall.getImplicitReceivers() + functionCall.getImplicitReceivers() ExplicitReceiverKind.NO_EXPLICIT_RECEIVER -> listOfNotNull(extensionReceiver, dispatchReceiver)
assert(receivers.size <= 3) { "There are ${receivers.size} for $this call" } ExplicitReceiverKind.DISPATCH_RECEIVER -> listOfNotNull(extensionReceiver)
return receivers ExplicitReceiverKind.EXTENSION_RECEIVER -> listOfNotNull(dispatchReceiver)
} ExplicitReceiverKind.BOTH_RECEIVERS -> emptyList()
}
return when (explicitReceiverKind) {
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER -> listOfNotNull(dispatchReceiver, extensionReceiver)
ExplicitReceiverKind.DISPATCH_RECEIVER -> listOfNotNull(extensionReceiver)
ExplicitReceiverKind.EXTENSION_RECEIVER -> listOfNotNull(dispatchReceiver)
ExplicitReceiverKind.BOTH_RECEIVERS -> emptyList()
}
}
private fun ResolvedCall<*>.hasSafeNullableReceiver(context: CallResolutionContext<*>): Boolean { private fun ResolvedCall<*>.hasSafeNullableReceiver(context: CallResolutionContext<*>): Boolean {
if (!call.isSafeCall()) return false if (!call.isSafeCall()) return false
@@ -0,0 +1,6 @@
@Deprecated("No")
val f: () -> Unit = {}
fun test() {
<!DEPRECATION!>f<!>()
}
@@ -0,0 +1,4 @@
package
@kotlin.Deprecated(message = "No") public val f: () -> kotlin.Unit
public fun test(): kotlin.Unit
@@ -6340,6 +6340,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("propertyWithInvoke.kt")
public void testPropertyWithInvoke() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/deprecated/propertyWithInvoke.kt");
doTest(fileName);
}
@TestMetadata("typeUsage.kt") @TestMetadata("typeUsage.kt")
public void testTypeUsage() throws Exception { public void testTypeUsage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/deprecated/typeUsage.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/deprecated/typeUsage.kt");