Fix operator warning on 'Constr()()'

This commit is contained in:
Yan Zhulanow
2015-09-29 18:44:53 +03:00
parent 7e4fbfaa6d
commit e6c0d4692a
12 changed files with 51 additions and 37 deletions
@@ -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);
@@ -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()) {
@@ -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<JetBinaryExpression>(expression, javaClass<JetBinaryExpression>())
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) }
}
}
@@ -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) {
@@ -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)
}
@@ -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>) : 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) {
@@ -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);
}
}
}
@@ -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<FunctionDescriptor> 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);
@@ -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)) {
+4 -1
View File
@@ -88,8 +88,11 @@ fun a() {
<!OPERATOR_MODIFIER_REQUIRED!>!<!>a
!c
<!OPERATOR_MODIFIER_REQUIRED!>a<!>()
<!OPERATOR_MODIFIER_REQUIRED!>a()<!>
c()
<!OPERATOR_MODIFIER_REQUIRED!>Example()()<!>
Example2()()
}
abstract class Base {
@@ -1,10 +1,10 @@
fun testInvoke() {
fun Nothing.invoke() = this
operator fun Nothing.invoke() = this
todo()<!UNREACHABLE_CODE!>()<!>
}
fun testInvokeWithLambda() {
fun Nothing.invoke(<!UNUSED_PARAMETER!>i<!>: Int, f: () -> Int) = f
operator fun Nothing.invoke(<!UNUSED_PARAMETER!>i<!>: Int, f: () -> Int) = f
todo()<!UNREACHABLE_CODE!>(1){ 42 }<!>
}
@@ -17,7 +17,7 @@ public class J {
// FILE: k.kt
fun test() {
J.<!OPERATOR_MODIFIER_REQUIRED!>staticNN<!>()
J.<!UNSAFE_CALL, OPERATOR_MODIFIER_REQUIRED!>staticN<!>()
J.<!OPERATOR_MODIFIER_REQUIRED!>staticJ<!>()
J.<!OPERATOR_MODIFIER_REQUIRED!>staticNN()<!>
J.<!OPERATOR_MODIFIER_REQUIRED!><!UNSAFE_CALL!>staticN<!>()<!>
J.<!OPERATOR_MODIFIER_REQUIRED!>staticJ()<!>
}