Refactor CallChecker and subclasses
Encapsulate everything that is needed in checkers into CallCheckerContext. Pass an instance of this context instead of BasicCallResolutionContext to checkers. Also pass an instance of the element to report errors on: this is useful because before this, every checker had its own way of determining where should the error be reported on. Some of them, for example, were not doing anything if Call#calleeExpression returned null, which is wrong, see operatorCall.kt #KT-12875 Open
This commit is contained in:
+12
-16
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.kotlin
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
||||
@@ -25,14 +26,14 @@ import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
|
||||
class JavaAnnotationCallChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
class JavaAnnotationCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val resultingDescriptor = resolvedCall.resultingDescriptor.original
|
||||
if (resultingDescriptor !is JavaConstructorDescriptor ||
|
||||
resultingDescriptor.containingDeclaration.kind != ClassKind.ANNOTATION_CLASS) return
|
||||
@@ -41,7 +42,7 @@ class JavaAnnotationCallChecker : SimpleCallChecker {
|
||||
reportDeprecatedJavaAnnotation(resolvedCall, context)
|
||||
}
|
||||
|
||||
private fun reportDeprecatedJavaAnnotation(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
private fun reportDeprecatedJavaAnnotation(resolvedCall: ResolvedCall<*>, context: CallCheckerContext) {
|
||||
val annotationEntry = resolvedCall.call.callElement as? KtAnnotationEntry ?: return
|
||||
val type = context.trace.get(BindingContext.TYPE, annotationEntry.typeReference) ?: return
|
||||
JavaAnnotationMapper.javaToKotlinNameMap[type.constructor.declarationDescriptor?.let { DescriptorUtils.getFqNameSafe(it) }]?.let {
|
||||
@@ -49,25 +50,20 @@ class JavaAnnotationCallChecker : SimpleCallChecker {
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportErrorsOnPositionedArguments(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
private fun reportErrorsOnPositionedArguments(resolvedCall: ResolvedCall<*>, context: CallCheckerContext) {
|
||||
getJavaAnnotationCallValueArgumentsThatShouldBeNamed(resolvedCall).forEach {
|
||||
reportOnValueArgument(context, it, ErrorsJvm.POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportOnValueArgument(
|
||||
context: BasicCallResolutionContext,
|
||||
argument: Map.Entry<ValueParameterDescriptor, ResolvedValueArgument>,
|
||||
context: CallCheckerContext,
|
||||
arguments: Map.Entry<ValueParameterDescriptor, ResolvedValueArgument>,
|
||||
diagnostic: DiagnosticFactory0<KtExpression>
|
||||
) {
|
||||
argument.value.arguments.forEach {
|
||||
if (it.getArgumentExpression() != null) {
|
||||
context.trace.report(
|
||||
diagnostic.on(
|
||||
it.getArgumentExpression()!!
|
||||
)
|
||||
)
|
||||
}
|
||||
for (valueArgument in arguments.value.arguments) {
|
||||
val argumentExpression = valueArgument.getArgumentExpression() ?: continue
|
||||
context.trace.report(diagnostic.on(argumentExpression))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-9
@@ -30,21 +30,16 @@ import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.elementToReportOn
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
|
||||
|
||||
object AdditionalBuiltInsMembersCallChecker : CallChecker {
|
||||
override fun check(
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
context: BasicCallResolutionContext,
|
||||
languageFeatureSettings: LanguageFeatureSettings
|
||||
) {
|
||||
if (languageFeatureSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)) return
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
if (context.languageFeatureSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)) return
|
||||
val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return
|
||||
|
||||
reportErrorIfAdditionalBuiltinDescriptor(resultingDescriptor, context.trace, resolvedCall.elementToReportOn)
|
||||
reportErrorIfAdditionalBuiltinDescriptor(resultingDescriptor, context.trace, reportOn)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -16,19 +16,20 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
|
||||
class JavaClassOnCompanionChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
class JavaClassOnCompanionChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
if (descriptor !is PropertyDescriptor || descriptor.name.asString() != "javaClass") return
|
||||
|
||||
@@ -45,7 +46,7 @@ class JavaClassOnCompanionChecker : SimpleCallChecker {
|
||||
val arguments = listOf(TypeProjectionImpl(containingClass.defaultType))
|
||||
val expectedType = KotlinTypeFactory.simpleType(Annotations.EMPTY, javaLangClass.typeConstructor, arguments,
|
||||
actualType.isMarkedNullable)
|
||||
context.trace.report(ErrorsJvm.JAVA_CLASS_ON_COMPANION.on(resolvedCall.call.callElement, actualType, expectedType))
|
||||
context.trace.report(ErrorsJvm.JAVA_CLASS_ON_COMPANION.on(reportOn, actualType, expectedType))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-5
@@ -16,12 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.isComputingDeferredType
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
@@ -29,10 +30,10 @@ import org.jetbrains.kotlin.serialization.deserialization.NotFoundClasses
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.newLinkedHashSetWithExpectedSize
|
||||
|
||||
class MissingDependencyClassChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
class MissingDependencyClassChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
for (classId in collectNotFoundClasses(resolvedCall.resultingDescriptor)) {
|
||||
context.trace.report(ErrorsJvm.MISSING_DEPENDENCY_CLASS.on(resolvedCall.call.callElement, classId.asSingleFqName()))
|
||||
context.trace.report(ErrorsJvm.MISSING_DEPENDENCY_CLASS.on(reportOn, classId.asSingleFqName()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -16,18 +16,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
|
||||
class ProtectedInSuperClassCompanionCallChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
class ProtectedInSuperClassCompanionCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val targetDescriptor = resolvedCall.resultingDescriptor.original
|
||||
// Protected non-JVM static
|
||||
if (targetDescriptor.visibility != Visibilities.PROTECTED) return
|
||||
@@ -42,7 +43,7 @@ class ProtectedInSuperClassCompanionCallChecker : SimpleCallChecker {
|
||||
if (!parentClassDescriptors.any { DescriptorUtils.isSubclass(it, companionOwnerDescriptor) }) return
|
||||
// Called not within the same companion object or its owner class
|
||||
if (companionDescriptor !in parentClassDescriptors && companionOwnerDescriptor !in parentClassDescriptors) {
|
||||
context.trace.report(ErrorsJvm.SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC.on(resolvedCall.call.callElement))
|
||||
context.trace.report(ErrorsJvm.SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC.on(reportOn))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-6
@@ -16,10 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast
|
||||
@@ -27,8 +28,8 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||
|
||||
object ProtectedSyntheticExtensionCallChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
object ProtectedSyntheticExtensionCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
|
||||
val sourceFunction = when (descriptor) {
|
||||
@@ -46,10 +47,11 @@ object ProtectedSyntheticExtensionCallChecker : SimpleCallChecker {
|
||||
|
||||
val receiverValue = resolvedCall.extensionReceiver as ReceiverValue
|
||||
val receiverTypes = listOf(receiverValue.type) + context.dataFlowInfo.getPredictableTypes(
|
||||
DataFlowValueFactory.createDataFlowValue(receiverValue, context))
|
||||
DataFlowValueFactory.createDataFlowValue(receiverValue, context.trace.bindingContext, context.scope.ownerDescriptor)
|
||||
)
|
||||
|
||||
if (receiverTypes.none { Visibilities.isVisible(getReceiverValueWithSmartCast(null, it), sourceFunction, from) }) {
|
||||
context.trace.report(Errors.INVISIBLE_MEMBER.on(resolvedCall.call.callElement, descriptor, descriptor.visibility, from))
|
||||
context.trace.report(Errors.INVISIBLE_MEMBER.on(reportOn, descriptor, descriptor.visibility, from))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-5
@@ -16,13 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.NO_REFLECTION_IN_CLASS_PATH
|
||||
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
|
||||
@@ -34,7 +35,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
* If there's no Kotlin reflection implementation found in the classpath, checks that there are no usages
|
||||
* of reflection API which will fail at runtime.
|
||||
*/
|
||||
class ReflectionAPICallChecker(private val module: ModuleDescriptor, storageManager: StorageManager) : SimpleCallChecker {
|
||||
class ReflectionAPICallChecker(private val module: ModuleDescriptor, storageManager: StorageManager) : CallChecker {
|
||||
private val isReflectionAvailable by storageManager.createLazyValue {
|
||||
module.findClassAcrossModuleDependencies(JvmAbi.REFLECTION_FACTORY_IMPL) != null
|
||||
}
|
||||
@@ -44,7 +45,7 @@ class ReflectionAPICallChecker(private val module: ModuleDescriptor, storageMana
|
||||
setOf(reflectionTypes.kProperty0, reflectionTypes.kProperty1, reflectionTypes.kProperty2)
|
||||
}
|
||||
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
if (isReflectionAvailable) return
|
||||
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
@@ -63,6 +64,6 @@ class ReflectionAPICallChecker(private val module: ModuleDescriptor, storageMana
|
||||
kPropertyClasses.any { kProperty -> DescriptorUtils.isSubclass(containingClass, kProperty) } -> return
|
||||
}
|
||||
|
||||
context.trace.report(NO_REFLECTION_IN_CLASS_PATH.on(resolvedCall.getCall().getCallElement()))
|
||||
context.trace.report(NO_REFLECTION_IN_CLASS_PATH.on(reportOn))
|
||||
}
|
||||
}
|
||||
|
||||
+6
-5
@@ -16,17 +16,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.usesDefaultArguments
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
|
||||
class SuperCallWithDefaultArgumentsChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
class SuperCallWithDefaultArgumentsChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val superCallExpression = getSuperCallExpression(resolvedCall.call)
|
||||
if (superCallExpression == null || !resolvedCall.usesDefaultArguments()) return
|
||||
context.trace.report(ErrorsJvm.SUPER_CALL_WITH_DEFAULT_PARAMETERS.on(superCallExpression.parent, resolvedCall.resultingDescriptor.name.asString()))
|
||||
context.trace.report(ErrorsJvm.SUPER_CALL_WITH_DEFAULT_PARAMETERS.on(reportOn, resolvedCall.resultingDescriptor.name.asString()))
|
||||
}
|
||||
}
|
||||
|
||||
+6
-13
@@ -16,20 +16,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
|
||||
class TraitDefaultMethodCallChecker : SimpleCallChecker {
|
||||
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
class TraitDefaultMethodCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
if (getSuperCallExpression(resolvedCall.call) == null) return
|
||||
|
||||
val targetDescriptor = resolvedCall.resultingDescriptor.original
|
||||
@@ -40,13 +38,8 @@ class TraitDefaultMethodCallChecker : SimpleCallChecker {
|
||||
val classifier = DescriptorUtils.getParentOfType(context.scope.ownerDescriptor, ClassifierDescriptor::class.java)
|
||||
|
||||
if (classifier != null && DescriptorUtils.isInterface(classifier)) {
|
||||
context.trace.report(
|
||||
ErrorsJvm.INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER.on(
|
||||
PsiTreeUtil.getParentOfType(resolvedCall.call.callElement, KtExpression::class.java)!!
|
||||
)
|
||||
)
|
||||
context.trace.report(ErrorsJvm.INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER.on(reportOn))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -16,22 +16,23 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED
|
||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||
|
||||
class UnsupportedSyntheticCallableReferenceChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
val expression = context.call.callElement
|
||||
class UnsupportedSyntheticCallableReferenceChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val expression = resolvedCall.call.callElement
|
||||
if (expression !is KtNameReferenceExpression || expression.parent !is KtCallableReferenceExpression) return
|
||||
|
||||
// TODO: support references to synthetic Java extension properties (KT-8575)
|
||||
if (resolvedCall.resultingDescriptor is SyntheticJavaPropertyDescriptor) {
|
||||
context.trace.report(UNSUPPORTED.on(expression, "reference to the synthetic extension property for a Java get/set method"))
|
||||
context.trace.report(UNSUPPORTED.on(reportOn, "reference to the synthetic extension property for a Java get/set method"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry;
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||
import org.jetbrains.kotlin.psi.KtElement;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
@@ -74,12 +73,12 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory0<KtAnnotationEntry> NON_SOURCE_REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<KtAnnotationEntry, FqName> ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtElement> INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtElement> SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtElement> NO_REFLECTION_IN_CLASS_PATH = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<PsiElement> NO_REFLECTION_IN_CLASS_PATH = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory2<KtElement, KotlinType, KotlinType> JAVA_CLASS_ON_COMPANION = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory2<PsiElement, KotlinType, KotlinType> JAVA_CLASS_ON_COMPANION = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory2<KtExpression, KotlinType, KotlinType> JAVA_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
|
||||
|
||||
DiagnosticFactory2<PsiElement, String, String> DUPLICATE_CLASS_NAMES = DiagnosticFactory2.create(ERROR);
|
||||
|
||||
@@ -75,7 +75,7 @@ public interface Errors {
|
||||
DiagnosticFactory3.create(ERROR);
|
||||
DiagnosticFactory3<PsiElement, DeclarationDescriptor, Visibility, DeclarationDescriptor> INVISIBLE_MEMBER = DiagnosticFactory3.create(ERROR, CALL_ELEMENT);
|
||||
|
||||
DiagnosticFactory1<KtExpression, ConstructorDescriptor> PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, ConstructorDescriptor> PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
// Exposed visibility group
|
||||
DiagnosticFactory3<PsiElement, EffectiveVisibility, DescriptorWithRelation, EffectiveVisibility> EXPOSED_PROPERTY_TYPE = DiagnosticFactory3.create(ERROR);
|
||||
@@ -812,7 +812,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtDeclaration> INLINE_PROPERTY_WITH_BACKING_FIELD = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
|
||||
|
||||
DiagnosticFactory0<KtElement> NON_LOCAL_SUSPENSION_POINT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> NON_LOCAL_SUSPENSION_POINT = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
|
||||
// Error sets
|
||||
|
||||
+15
-13
@@ -16,12 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtInstanceExpressionWithLabel
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
|
||||
@@ -29,26 +30,27 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||
|
||||
object ConstructorHeaderCallChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
object ConstructorHeaderCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val dispatchReceiverClass = resolvedCall.dispatchReceiver.classDescriptorForImplicitReceiver
|
||||
val extensionReceiverClass = resolvedCall.extensionReceiver.classDescriptorForImplicitReceiver
|
||||
|
||||
val callElement = resolvedCall.call.callElement
|
||||
val labelReferenceClass =
|
||||
(resolvedCall.call.callElement as? KtInstanceExpressionWithLabel)?.let {
|
||||
instanceExpressionWithLabel ->
|
||||
context.trace.get(BindingContext.REFERENCE_TARGET, instanceExpressionWithLabel.instanceReference) as? ClassDescriptor
|
||||
if (callElement is KtInstanceExpressionWithLabel) {
|
||||
context.trace.get(BindingContext.REFERENCE_TARGET, callElement.instanceReference) as? ClassDescriptor
|
||||
}
|
||||
else null
|
||||
|
||||
if (dispatchReceiverClass == null && extensionReceiverClass == null && labelReferenceClass == null) return
|
||||
|
||||
if (context.scope.parentsWithSelf.any() {
|
||||
it is LexicalScope && it.kind == LexicalScopeKind.CONSTRUCTOR_HEADER
|
||||
&& (it.ownerDescriptor as ConstructorDescriptor).containingDeclaration in
|
||||
setOf(dispatchReceiverClass, extensionReceiverClass, labelReferenceClass)
|
||||
val classes = setOf(dispatchReceiverClass, extensionReceiverClass, labelReferenceClass)
|
||||
|
||||
if (context.scope.parentsWithSelf.any { scope ->
|
||||
scope is LexicalScope && scope.kind == LexicalScopeKind.CONSTRUCTOR_HEADER &&
|
||||
(scope.ownerDescriptor as ConstructorDescriptor).containingDeclaration in classes
|
||||
}) {
|
||||
context.trace.report(
|
||||
Errors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.on(context.call.calleeExpression ?: return, resolvedCall.resultingDescriptor))
|
||||
context.trace.report(Errors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.on(reportOn, resolvedCall.resultingDescriptor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallCandidateResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallPosition
|
||||
@@ -83,14 +84,16 @@ class CallCompleter(
|
||||
}
|
||||
|
||||
if (resolvedCall != null) {
|
||||
for (callChecker in callCheckers) {
|
||||
callChecker.check(resolvedCall, context, languageFeatureSettings)
|
||||
}
|
||||
|
||||
val element = if (resolvedCall is VariableAsFunctionResolvedCall)
|
||||
resolvedCall.variableCall.call.calleeExpression
|
||||
else
|
||||
resolvedCall.call.calleeExpression
|
||||
val reportOn = element ?: resolvedCall.call.callElement
|
||||
|
||||
val callCheckerContext = CallCheckerContext(context, languageFeatureSettings)
|
||||
for (callChecker in callCheckers) {
|
||||
callChecker.check(resolvedCall, reportOn, callCheckerContext)
|
||||
}
|
||||
|
||||
for (validator in symbolUsageValidators) {
|
||||
validator.validateCall(resolvedCall, context.trace, element!!)
|
||||
|
||||
@@ -16,30 +16,30 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeatureSettings
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.types.DeferredType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
interface CallChecker {
|
||||
// TODO: Think about encapsulating these parameters into specific class like CheckerParameters when you're about to add another one
|
||||
fun check(
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
context: BasicCallResolutionContext,
|
||||
languageFeatureSettings: LanguageFeatureSettings
|
||||
)
|
||||
fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext)
|
||||
}
|
||||
|
||||
interface SimpleCallChecker : CallChecker {
|
||||
override fun check(
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
context: BasicCallResolutionContext,
|
||||
languageFeatureSettings: LanguageFeatureSettings
|
||||
) = check(resolvedCall, context)
|
||||
|
||||
fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext)
|
||||
class CallCheckerContext(
|
||||
val trace: BindingTrace,
|
||||
val scope: LexicalScope,
|
||||
val languageFeatureSettings: LanguageFeatureSettings,
|
||||
val dataFlowInfo: DataFlowInfo,
|
||||
val isAnnotationContext: Boolean
|
||||
) {
|
||||
constructor(c: ResolutionContext<*>, languageFeatureSettings: LanguageFeatureSettings) : this(
|
||||
c.trace, c.scope, languageFeatureSettings, c.dataFlowInfo, c.isAnnotationContext
|
||||
)
|
||||
}
|
||||
|
||||
// Use this utility to avoid premature computation of deferred return type of a resolved callable descriptor.
|
||||
@@ -48,6 +48,3 @@ interface SimpleCallChecker : CallChecker {
|
||||
@Suppress("unused")
|
||||
fun CallChecker.isComputingDeferredType(type: KotlinType) =
|
||||
type is DeferredType && type.isComputing
|
||||
|
||||
val ResolvedCall<*>.elementToReportOn: KtElement
|
||||
get() = call.calleeExpression ?: call.callElement
|
||||
|
||||
+5
-9
@@ -16,20 +16,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isArrayOfNothing
|
||||
|
||||
class CallReturnsArrayOfNothingChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
val returnType = resolvedCall.resultingDescriptor.returnType
|
||||
|
||||
if (returnType.containsArrayOfNothing()) {
|
||||
val callElement = resolvedCall.call.callElement
|
||||
val diagnostic = Errors.UNSUPPORTED.on(callElement, "Array<Nothing> in return type is illegal")
|
||||
context.trace.report(diagnostic)
|
||||
class CallReturnsArrayOfNothingChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
if (resolvedCall.resultingDescriptor.returnType.containsArrayOfNothing()) {
|
||||
context.trace.report(Errors.UNSUPPORTED.on(reportOn, "Array<Nothing> in return type is illegal"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -16,21 +16,21 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.CAPTURED_IN_CLOSURE
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.types.expressions.CaptureKind
|
||||
|
||||
class CapturingInClosureChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
class CapturingInClosureChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val variableResolvedCall = if (resolvedCall is VariableAsFunctionResolvedCall) resolvedCall.variableCall else resolvedCall
|
||||
val variableDescriptor = variableResolvedCall.resultingDescriptor as? VariableDescriptor
|
||||
if (variableDescriptor != null) {
|
||||
@@ -68,9 +68,9 @@ class CapturingInClosureChecker : SimpleCallChecker {
|
||||
if (!InlineUtil.canBeInlineArgument(scopeDeclaration)) return false
|
||||
|
||||
if (InlineUtil.isInlinedArgument(scopeDeclaration as KtFunction, context, false)) {
|
||||
val scopeContainerParent = scopeContainer.containingDeclaration
|
||||
assert(scopeContainerParent != null) { "parent is null for " + scopeContainer }
|
||||
return !isCapturedVariable(variableParent, scopeContainerParent!!) || isCapturedInInline(context, scopeContainerParent, variableParent)
|
||||
val scopeContainerParent = scopeContainer.containingDeclaration ?: error("parent is null for $scopeContainer")
|
||||
return !isCapturedVariable(variableParent, scopeContainerParent) ||
|
||||
isCapturedInInline(context, scopeContainerParent, variableParent)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
+6
-7
@@ -17,12 +17,10 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeatureSettings
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.KtOperationReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
|
||||
@@ -30,14 +28,15 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
|
||||
class InfixCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext, languageFeatureSettings: LanguageFeatureSettings) {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val functionDescriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return
|
||||
if (functionDescriptor.isDynamic() || ErrorUtils.isError(functionDescriptor)) return
|
||||
if (functionDescriptor.isInfix || functionDescriptor.isDynamic() || ErrorUtils.isError(functionDescriptor)) return
|
||||
val element = ((resolvedCall as? VariableAsFunctionResolvedCall)?.variableCall ?: resolvedCall).call.calleeExpression
|
||||
if (isInfixCall(element) && !functionDescriptor.isInfix) {
|
||||
val operationRefExpression = element as? KtOperationReferenceExpression ?: return
|
||||
if (isInfixCall(element)) {
|
||||
val containingDeclarationName = functionDescriptor.containingDeclaration.fqNameUnsafe.asString()
|
||||
context.trace.report(Errors.INFIX_MODIFIER_REQUIRED.on(operationRefExpression, functionDescriptor, containingDeclarationName))
|
||||
context.trace.report(Errors.INFIX_MODIFIER_REQUIRED.on(
|
||||
reportOn as? KtOperationReferenceExpression ?: return, functionDescriptor, containingDeclarationName
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+31
-37
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.FunctionTypesKt;
|
||||
import org.jetbrains.kotlin.config.LanguageFeatureSettings;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtToken;
|
||||
@@ -28,7 +27,6 @@ import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
||||
@@ -49,7 +47,7 @@ import static org.jetbrains.kotlin.diagnostics.Errors.USAGE_IS_NOT_INLINABLE;
|
||||
import static org.jetbrains.kotlin.resolve.inline.InlineUtil.allowsNonLocalReturns;
|
||||
import static org.jetbrains.kotlin.resolve.inline.InlineUtil.checkNonLocalReturnUsage;
|
||||
|
||||
class InlineChecker implements SimpleCallChecker {
|
||||
class InlineChecker implements CallChecker {
|
||||
private final FunctionDescriptor descriptor;
|
||||
private final Set<CallableDescriptor> inlinableParameters = new LinkedHashSet<CallableDescriptor>();
|
||||
private final boolean isEffectivelyPublicApiFunction;
|
||||
@@ -68,17 +66,8 @@ class InlineChecker implements SimpleCallChecker {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check(
|
||||
@NotNull ResolvedCall<?> resolvedCall,
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull LanguageFeatureSettings languageFeatureSettings
|
||||
) {
|
||||
SimpleCallChecker.DefaultImpls.check(this, resolvedCall, context, languageFeatureSettings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check(@NotNull ResolvedCall<?> resolvedCall, @NotNull BasicCallResolutionContext context) {
|
||||
KtExpression expression = context.call.getCalleeExpression();
|
||||
public void check(@NotNull ResolvedCall<?> resolvedCall, @NotNull PsiElement reportOn, @NotNull CallCheckerContext context) {
|
||||
KtExpression expression = resolvedCall.getCall().getCalleeExpression();
|
||||
if (expression == null) {
|
||||
return;
|
||||
}
|
||||
@@ -90,7 +79,7 @@ class InlineChecker implements SimpleCallChecker {
|
||||
|
||||
if (inlinableParameters.contains(targetDescriptor)) {
|
||||
if (!isInsideCall(expression)) {
|
||||
context.trace.report(USAGE_IS_NOT_INLINABLE.on(expression, expression, descriptor));
|
||||
context.getTrace().report(USAGE_IS_NOT_INLINABLE.on(expression, expression, descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,10 +122,8 @@ class InlineChecker implements SimpleCallChecker {
|
||||
return parent != null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void checkValueParameter(
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull CallCheckerContext context,
|
||||
@NotNull CallableDescriptor targetDescriptor,
|
||||
@NotNull ValueArgument targetArgument,
|
||||
@NotNull ValueParameterDescriptor targetParameterDescriptor
|
||||
@@ -150,20 +137,20 @@ class InlineChecker implements SimpleCallChecker {
|
||||
if (argumentCallee != null && inlinableParameters.contains(argumentCallee)) {
|
||||
if (InlineUtil.isInline(targetDescriptor) && isInlinableParameter(targetParameterDescriptor)) {
|
||||
if (allowsNonLocalReturns(argumentCallee) && !allowsNonLocalReturns(targetParameterDescriptor)) {
|
||||
context.trace.report(NON_LOCAL_RETURN_NOT_ALLOWED.on(argumentExpression, argumentExpression));
|
||||
context.getTrace().report(NON_LOCAL_RETURN_NOT_ALLOWED.on(argumentExpression, argumentExpression));
|
||||
}
|
||||
else {
|
||||
checkNonLocalReturn(context, argumentCallee, argumentExpression);
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.trace.report(USAGE_IS_NOT_INLINABLE.on(argumentExpression, argumentExpression, descriptor));
|
||||
context.getTrace().report(USAGE_IS_NOT_INLINABLE.on(argumentExpression, argumentExpression, descriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCallWithReceiver(
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull CallCheckerContext context,
|
||||
@NotNull CallableDescriptor targetDescriptor,
|
||||
@Nullable ReceiverValue receiver,
|
||||
@Nullable KtExpression expression
|
||||
@@ -194,13 +181,13 @@ class InlineChecker implements SimpleCallChecker {
|
||||
|
||||
@Nullable
|
||||
private static CallableDescriptor getCalleeDescriptor(
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull CallCheckerContext context,
|
||||
@NotNull KtExpression expression,
|
||||
boolean unwrapVariableAsFunction
|
||||
) {
|
||||
if (!(expression instanceof KtSimpleNameExpression || expression instanceof KtThisExpression)) return null;
|
||||
|
||||
ResolvedCall<?> thisCall = CallUtilKt.getResolvedCall(expression, context.trace.getBindingContext());
|
||||
ResolvedCall<?> thisCall = CallUtilKt.getResolvedCall(expression, context.getTrace().getBindingContext());
|
||||
if (unwrapVariableAsFunction && thisCall instanceof VariableAsFunctionResolvedCall) {
|
||||
return ((VariableAsFunctionResolvedCall) thisCall).getVariableCall().getResultingDescriptor();
|
||||
}
|
||||
@@ -208,27 +195,27 @@ class InlineChecker implements SimpleCallChecker {
|
||||
}
|
||||
|
||||
private void checkLambdaInvokeOrExtensionCall(
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull CallCheckerContext context,
|
||||
@NotNull CallableDescriptor lambdaDescriptor,
|
||||
@NotNull CallableDescriptor callDescriptor,
|
||||
@NotNull KtExpression receiverExpression
|
||||
) {
|
||||
boolean inlinableCall = isInvokeOrInlineExtension(callDescriptor);
|
||||
if (!inlinableCall) {
|
||||
context.trace.report(USAGE_IS_NOT_INLINABLE.on(receiverExpression, receiverExpression, descriptor));
|
||||
context.getTrace().report(USAGE_IS_NOT_INLINABLE.on(receiverExpression, receiverExpression, descriptor));
|
||||
}
|
||||
else {
|
||||
checkNonLocalReturn(context, lambdaDescriptor, receiverExpression);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkRecursion(
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
private void checkRecursion(
|
||||
@NotNull CallCheckerContext context,
|
||||
@NotNull CallableDescriptor targetDescriptor,
|
||||
@NotNull KtElement expression
|
||||
) {
|
||||
if (targetDescriptor.getOriginal() == descriptor) {
|
||||
context.trace.report(Errors.RECURSION_IN_INLINE.on(expression, expression, descriptor));
|
||||
context.getTrace().report(Errors.RECURSION_IN_INLINE.on(expression, expression, descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,10 +237,17 @@ class InlineChecker implements SimpleCallChecker {
|
||||
return isInvoke || InlineUtil.isInline(descriptor);
|
||||
}
|
||||
|
||||
private void checkVisibilityAndAccess(@NotNull CallableDescriptor declarationDescriptor, @NotNull KtElement expression, @NotNull BasicCallResolutionContext context){
|
||||
boolean declarationDescriptorIsPublicApi = DescriptorUtilsKt.isEffectivelyPublicApi(declarationDescriptor) || isDefinedInInlineFunction(declarationDescriptor);
|
||||
if (isEffectivelyPublicApiFunction && !declarationDescriptorIsPublicApi && declarationDescriptor.getVisibility() != Visibilities.LOCAL) {
|
||||
context.trace.report(Errors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, declarationDescriptor, descriptor));
|
||||
private void checkVisibilityAndAccess(
|
||||
@NotNull CallableDescriptor declarationDescriptor,
|
||||
@NotNull KtElement expression,
|
||||
@NotNull CallCheckerContext context
|
||||
) {
|
||||
boolean declarationDescriptorIsPublicApi = DescriptorUtilsKt.isEffectivelyPublicApi(declarationDescriptor) ||
|
||||
isDefinedInInlineFunction(declarationDescriptor);
|
||||
if (isEffectivelyPublicApiFunction &&
|
||||
!declarationDescriptorIsPublicApi &&
|
||||
declarationDescriptor.getVisibility() != Visibilities.LOCAL) {
|
||||
context.getTrace().report(Errors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, declarationDescriptor, descriptor));
|
||||
}
|
||||
else {
|
||||
checkPrivateClassMemberAccess(declarationDescriptor, expression, context);
|
||||
@@ -263,11 +257,11 @@ class InlineChecker implements SimpleCallChecker {
|
||||
private void checkPrivateClassMemberAccess(
|
||||
@NotNull DeclarationDescriptor declarationDescriptor,
|
||||
@NotNull KtElement expression,
|
||||
@NotNull BasicCallResolutionContext context
|
||||
@NotNull CallCheckerContext context
|
||||
) {
|
||||
if (!isEffectivelyPrivateApiFunction) {
|
||||
if (DescriptorUtilsKt.isInsidePrivateClass(declarationDescriptor)) {
|
||||
context.trace.report(Errors.PRIVATE_CLASS_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor));
|
||||
context.getTrace().report(Errors.PRIVATE_CLASS_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -285,14 +279,14 @@ class InlineChecker implements SimpleCallChecker {
|
||||
}
|
||||
|
||||
private void checkNonLocalReturn(
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull CallCheckerContext context,
|
||||
@NotNull CallableDescriptor inlinableParameterDescriptor,
|
||||
@NotNull KtExpression parameterUsage
|
||||
) {
|
||||
if (!allowsNonLocalReturns(inlinableParameterDescriptor)) return;
|
||||
|
||||
if (!checkNonLocalReturnUsage(descriptor, parameterUsage, context.trace)) {
|
||||
context.trace.report(NON_LOCAL_RETURN_NOT_ALLOWED.on(parameterUsage, parameterUsage));
|
||||
if (!checkNonLocalReturnUsage(descriptor, parameterUsage, context.getTrace())) {
|
||||
context.getTrace().report(NON_LOCAL_RETURN_NOT_ALLOWED.on(parameterUsage, parameterUsage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -16,17 +16,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
class InlineCheckerWrapper : SimpleCallChecker {
|
||||
private var checkersCache: WeakReference<MutableMap<DeclarationDescriptor, SimpleCallChecker>>? = null
|
||||
class InlineCheckerWrapper : CallChecker {
|
||||
private var checkersCache: WeakReference<MutableMap<DeclarationDescriptor, CallChecker>>? = null
|
||||
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
if (context.isAnnotationContext) return
|
||||
|
||||
var parentDescriptor: DeclarationDescriptor? = context.scope.ownerDescriptor
|
||||
@@ -34,14 +34,14 @@ class InlineCheckerWrapper : SimpleCallChecker {
|
||||
while (parentDescriptor != null) {
|
||||
if (InlineUtil.isInline(parentDescriptor)) {
|
||||
val checker = getChecker(parentDescriptor as FunctionDescriptor)
|
||||
checker.check(resolvedCall, context)
|
||||
checker.check(resolvedCall, reportOn, context)
|
||||
}
|
||||
|
||||
parentDescriptor = parentDescriptor.containingDeclaration
|
||||
}
|
||||
}
|
||||
|
||||
private fun getChecker(descriptor: FunctionDescriptor): SimpleCallChecker {
|
||||
private fun getChecker(descriptor: FunctionDescriptor): CallChecker {
|
||||
val map = checkersCache?.get() ?: hashMapOf()
|
||||
checkersCache = checkersCache ?: WeakReference(map)
|
||||
return map.getOrPut(descriptor) { InlineChecker(descriptor) }
|
||||
|
||||
+3
-3
@@ -16,15 +16,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
|
||||
class InvokeConventionChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
class InvokeConventionChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
if (resolvedCall is VariableAsFunctionResolvedCallImpl) {
|
||||
val functionCall = resolvedCall.functionCall
|
||||
val variableCall = resolvedCall.variableCall
|
||||
|
||||
+6
-12
@@ -17,14 +17,12 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeatureSettings
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isConventionCall
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
|
||||
@@ -36,17 +34,13 @@ import org.jetbrains.kotlin.util.OperatorNameConventions.UNARY_MINUS
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.UNARY_PLUS
|
||||
|
||||
class OperatorCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext, languageFeatureSettings: LanguageFeatureSettings) {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val functionDescriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return
|
||||
if (!checkNotErrorOrDynamic(functionDescriptor)) return
|
||||
|
||||
val element = resolvedCall.call.calleeExpression ?: resolvedCall.call.callElement
|
||||
val call = resolvedCall.call
|
||||
|
||||
fun isInvokeCall(): Boolean = call is CallTransformer.CallForImplicitInvoke
|
||||
|
||||
fun isMultiDeclaration(): Boolean = call.callElement is KtDestructuringDeclarationEntry
|
||||
|
||||
if (resolvedCall is VariableAsFunctionResolvedCall &&
|
||||
call is CallTransformer.CallForImplicitInvoke && call.itIsVariableAsFunctionCall) {
|
||||
val outerCall = call.outerCall
|
||||
@@ -56,7 +50,7 @@ class OperatorCallChecker : CallChecker {
|
||||
}
|
||||
}
|
||||
|
||||
if (isMultiDeclaration() || isInvokeCall()) {
|
||||
if (call.callElement is KtDestructuringDeclarationEntry || call is CallTransformer.CallForImplicitInvoke) {
|
||||
if (!functionDescriptor.isOperator) {
|
||||
report(call.callElement, functionDescriptor, context.trace)
|
||||
}
|
||||
@@ -66,7 +60,7 @@ class OperatorCallChecker : CallChecker {
|
||||
val isConventionOperator = element is KtOperationReferenceExpression && element.getNameForConventionalOperation() != null
|
||||
if (isConventionOperator || element is KtArrayAccessExpression) {
|
||||
if (!functionDescriptor.isOperator) {
|
||||
report(element, functionDescriptor, context.trace)
|
||||
report(reportOn, functionDescriptor, context.trace)
|
||||
}
|
||||
if (isConventionOperator) {
|
||||
checkDeprecatedUnaryConventions(call, functionDescriptor, context.trace)
|
||||
@@ -85,16 +79,16 @@ class OperatorCallChecker : CallChecker {
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun report(element: PsiElement, descriptor: FunctionDescriptor, sink: DiagnosticSink) {
|
||||
fun report(reportOn: PsiElement, descriptor: FunctionDescriptor, sink: DiagnosticSink) {
|
||||
if (!checkNotErrorOrDynamic(descriptor)) return
|
||||
|
||||
val containingDeclaration = descriptor.containingDeclaration
|
||||
val containingDeclarationName = containingDeclaration.fqNameUnsafe.asString()
|
||||
sink.report(Errors.OPERATOR_MODIFIER_REQUIRED.on(element, descriptor, containingDeclarationName))
|
||||
sink.report(Errors.OPERATOR_MODIFIER_REQUIRED.on(reportOn, descriptor, containingDeclarationName))
|
||||
}
|
||||
|
||||
private fun checkNotErrorOrDynamic(functionDescriptor: FunctionDescriptor): Boolean {
|
||||
return (!functionDescriptor.isDynamic() && !ErrorUtils.isError(functionDescriptor))
|
||||
return !functionDescriptor.isDynamic() && !ErrorUtils.isError(functionDescriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -16,18 +16,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtConstructorCalleeExpression
|
||||
import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||
|
||||
object ProtectedConstructorCallChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
object ProtectedConstructorCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val descriptor = resolvedCall.resultingDescriptor as? ConstructorDescriptor ?: return
|
||||
val constructorOwner = descriptor.containingDeclaration.original
|
||||
val scopeOwner = context.scope.ownerDescriptor
|
||||
@@ -36,7 +36,7 @@ object ProtectedConstructorCallChecker : SimpleCallChecker {
|
||||
// Error already reported
|
||||
if (!Visibilities.isVisibleWithAnyReceiver(descriptor, scopeOwner)) return
|
||||
|
||||
val calleeExpression = resolvedCall.call.calleeExpression ?: return
|
||||
val calleeExpression = resolvedCall.call.calleeExpression
|
||||
|
||||
// Permit constructor super-calls
|
||||
when (calleeExpression) {
|
||||
@@ -53,7 +53,7 @@ object ProtectedConstructorCallChecker : SimpleCallChecker {
|
||||
// of constructor owner
|
||||
@Suppress("DEPRECATION")
|
||||
if (Visibilities.findInvisibleMember(Visibilities.FALSE_IF_PROTECTED, descriptor, scopeOwner) == descriptor) {
|
||||
context.trace.report(Errors.PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL.on(calleeExpression, descriptor))
|
||||
context.trace.report(Errors.PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL.on(reportOn, descriptor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-31
@@ -17,35 +17,24 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.config.LanguageFeatureSettings;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
|
||||
import org.jetbrains.kotlin.psi.KtTypeProjection;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ReifiedTypeParameterSubstitutionChecker implements SimpleCallChecker {
|
||||
public class ReifiedTypeParameterSubstitutionChecker implements CallChecker {
|
||||
@Override
|
||||
public void check(
|
||||
@NotNull ResolvedCall<?> resolvedCall,
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull LanguageFeatureSettings languageFeatureSettings
|
||||
) {
|
||||
SimpleCallChecker.DefaultImpls.check(this, resolvedCall, context, languageFeatureSettings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check(@NotNull ResolvedCall<?> resolvedCall, @NotNull BasicCallResolutionContext context) {
|
||||
public void check(@NotNull ResolvedCall<?> resolvedCall, @NotNull PsiElement reportOn, @NotNull CallCheckerContext context) {
|
||||
Map<TypeParameterDescriptor, KotlinType> typeArguments = resolvedCall.getTypeArguments();
|
||||
for (Map.Entry<TypeParameterDescriptor, KotlinType> entry : typeArguments.entrySet()) {
|
||||
TypeParameterDescriptor parameter = entry.getKey();
|
||||
@@ -56,42 +45,34 @@ public class ReifiedTypeParameterSubstitutionChecker implements SimpleCallChecke
|
||||
continue;
|
||||
}
|
||||
|
||||
KtTypeProjection typeProjection = CollectionsKt.getOrNull(resolvedCall.getCall().getTypeArguments(), parameter.getIndex());
|
||||
PsiElement reportErrorOn = typeProjection != null ? typeProjection : reportOn;
|
||||
|
||||
if (argumentDeclarationDescriptor instanceof TypeParameterDescriptor &&
|
||||
!((TypeParameterDescriptor) argumentDeclarationDescriptor).isReified()) {
|
||||
context.trace.report(
|
||||
Errors.TYPE_PARAMETER_AS_REIFIED.on(getElementToReport(context, parameter.getIndex()), parameter)
|
||||
);
|
||||
context.getTrace().report(Errors.TYPE_PARAMETER_AS_REIFIED.on(reportErrorOn, parameter));
|
||||
}
|
||||
else if (TypeUtilsKt.cannotBeReified(argument)) {
|
||||
context.trace.report(
|
||||
Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument));
|
||||
context.getTrace().report(Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(reportErrorOn, argument));
|
||||
}
|
||||
// REIFIED_TYPE_UNSAFE_SUBSTITUTION is temporary disabled because it seems too strict now (see KT-10847)
|
||||
//else if (TypeUtilsKt.unsafeAsReifiedArgument(argument) && !hasPureReifiableAnnotation(parameter)) {
|
||||
// context.trace.report(
|
||||
// Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument));
|
||||
// context.getTrace().report(Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(reportErrorOn, argument));
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private static final FqName PURE_REIFIABLE_ANNOTATION_FQ_NAME = new FqName("kotlin.internal.PureReifiable");
|
||||
|
||||
private static boolean hasPureReifiableAnnotation(@NotNull TypeParameterDescriptor parameter) {
|
||||
return parameter.getAnnotations().hasAnnotation(PURE_REIFIABLE_ANNOTATION_FQ_NAME) ||
|
||||
isTypeParameterOfKotlinArray(parameter);
|
||||
}
|
||||
*/
|
||||
|
||||
private static boolean isTypeParameterOfKotlinArray(@NotNull TypeParameterDescriptor parameter) {
|
||||
DeclarationDescriptor container = parameter.getContainingDeclaration();
|
||||
return container instanceof ClassDescriptor && KotlinBuiltIns.isNonPrimitiveArray((ClassDescriptor) container);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiElement getElementToReport(@NotNull BasicCallResolutionContext context, int parameterIndex) {
|
||||
if (context.call.getTypeArguments().size() > parameterIndex) {
|
||||
return context.call.getTypeArguments().get(parameterIndex);
|
||||
}
|
||||
KtExpression callee = context.call.getCalleeExpression();
|
||||
return callee != null ? callee : context.call.getCallElement();
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -16,17 +16,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
|
||||
class SafeCallChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
class SafeCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val operationNode = resolvedCall.call.callOperationNode ?: return
|
||||
|
||||
if (operationNode.elementType == KtTokens.SAFE_ACCESS && resolvedCall.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER) {
|
||||
if (operationNode.elementType == KtTokens.SAFE_ACCESS &&
|
||||
resolvedCall.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER) {
|
||||
context.trace.report(Errors.UNEXPECTED_SAFE_CALL.on(operationNode.psi))
|
||||
}
|
||||
}
|
||||
|
||||
+8
-15
@@ -16,18 +16,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageFeatureSettings
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.coroutine.CoroutineReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
|
||||
object CoroutineSuspendCallChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
object CoroutineSuspendCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val descriptor = resolvedCall.candidateDescriptor as? FunctionDescriptor ?: return
|
||||
if (!descriptor.isSuspend || descriptor.initialSignatureDescriptor == null) return
|
||||
|
||||
@@ -35,23 +34,17 @@ object CoroutineSuspendCallChecker : SimpleCallChecker {
|
||||
val callElement = resolvedCall.call.callElement as KtExpression
|
||||
|
||||
if (!InlineUtil.checkNonLocalReturnUsage(dispatchReceiverOwner, callElement, context.trace)) {
|
||||
context.trace.report(Errors.NON_LOCAL_SUSPENSION_POINT.on(resolvedCall.call.calleeExpression ?: callElement))
|
||||
context.trace.report(Errors.NON_LOCAL_SUSPENSION_POINT.on(reportOn))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object BuilderFunctionsCallChecker : CallChecker {
|
||||
override fun check(
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
context: BasicCallResolutionContext,
|
||||
languageFeatureSettings: LanguageFeatureSettings
|
||||
) {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val descriptor = resolvedCall.candidateDescriptor as? FunctionDescriptor ?: return
|
||||
if (descriptor.valueParameters.any { it.isCoroutine }
|
||||
&& !languageFeatureSettings.supportsFeature(LanguageFeature.Coroutines)) {
|
||||
context.trace.report(
|
||||
Errors.UNSUPPORTED_FEATURE.on(
|
||||
resolvedCall.call.calleeExpression ?: resolvedCall.call.callElement, LanguageFeature.Coroutines))
|
||||
if (descriptor.valueParameters.any { it.isCoroutine } &&
|
||||
!context.languageFeatureSettings.supportsFeature(LanguageFeature.Coroutines)) {
|
||||
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(reportOn, LanguageFeature.Coroutines))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-8
@@ -39,8 +39,7 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver;
|
||||
import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver;
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl;
|
||||
@@ -586,10 +585,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
trace.record(RESOLVED_CALL, call, resolvedCall);
|
||||
trace.record(CALL, expression, call);
|
||||
|
||||
BasicCallResolutionContext resolutionContext =
|
||||
BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_CALLABLE_TYPE);
|
||||
CallCheckerContext callCheckerContext = new CallCheckerContext(context, components.languageFeatureSettings);
|
||||
for (CallChecker checker : components.callCheckers) {
|
||||
checker.check(resolvedCall, resolutionContext, components.languageFeatureSettings);
|
||||
checker.check(resolvedCall, expression, callCheckerContext);
|
||||
}
|
||||
for (SymbolUsageValidator validator : components.symbolUsageValidators) {
|
||||
validator.validateCall(resolvedCall, trace, expression);
|
||||
@@ -894,11 +892,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (resolvedCall != null) {
|
||||
// Call must be validated with the actual, not temporary trace in order to report operator diagnostic
|
||||
// Only unary assignment expressions (++, --) and +=/... must be checked, normal assignments have the proper trace
|
||||
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(
|
||||
context.replaceBindingTrace(trace), resolvedCall.getCall(), CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS
|
||||
CallCheckerContext callCheckerContext = new CallCheckerContext(
|
||||
trace, context.scope, components.languageFeatureSettings, context.dataFlowInfo, context.isAnnotationContext
|
||||
);
|
||||
for (CallChecker checker : components.callCheckers) {
|
||||
checker.check(resolvedCall, callResolutionContext, components.languageFeatureSettings);
|
||||
checker.check(resolvedCall, expression, callCheckerContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,13 @@ abstract class A {
|
||||
open class B : A() {
|
||||
fun test() {
|
||||
super.foo("123")
|
||||
<!SUPER_CALL_WITH_DEFAULT_PARAMETERS!>super.foo()<!>
|
||||
super.<!SUPER_CALL_WITH_DEFAULT_PARAMETERS!>foo<!>()
|
||||
|
||||
super.foo2("123")
|
||||
<!SUPER_CALL_WITH_DEFAULT_PARAMETERS!>super.foo2()<!>
|
||||
super.<!SUPER_CALL_WITH_DEFAULT_PARAMETERS!>foo2<!>()
|
||||
|
||||
super.foo3("123")
|
||||
<!SUPER_CALL_WITH_DEFAULT_PARAMETERS!>super.foo3()<!>
|
||||
super.<!SUPER_CALL_WITH_DEFAULT_PARAMETERS!>foo3<!>()
|
||||
}
|
||||
|
||||
override fun foo3(a: String) {
|
||||
|
||||
@@ -19,7 +19,7 @@ class F {
|
||||
// FILE: main.kt
|
||||
fun main(x: A) {
|
||||
x.b().bar()
|
||||
x.<!MISSING_DEPENDENCY_CLASS!>f()<!>.<!UNRESOLVED_REFERENCE!>foobaz<!>()
|
||||
x.<!MISSING_DEPENDENCY_CLASS!>f<!>().<!UNRESOLVED_REFERENCE!>foobaz<!>()
|
||||
|
||||
<!UNRESOLVED_REFERENCE!>D<!>().<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>baz<!>()
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ public interface Test {
|
||||
// FILE: test.kt
|
||||
interface KTrait : Test {
|
||||
fun ktest() {
|
||||
<!INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER!>super.test()<!>
|
||||
super.<!INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER!>test<!>()
|
||||
|
||||
test()
|
||||
}
|
||||
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
open class C(val x: Int)
|
||||
|
||||
class D : C {
|
||||
constructor() : super(
|
||||
{
|
||||
val s = ""
|
||||
<!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>s<!>()
|
||||
""() // TODO: see KT-12875
|
||||
42
|
||||
}())
|
||||
|
||||
operator fun String.invoke() { }
|
||||
}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
package
|
||||
|
||||
public open class C {
|
||||
public constructor C(/*0*/ x: kotlin.Int)
|
||||
public final val x: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class D : C {
|
||||
public constructor D()
|
||||
public final override /*1*/ /*fake_override*/ val x: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
public final operator fun kotlin.String.invoke(): kotlin.Unit
|
||||
}
|
||||
@@ -38,17 +38,17 @@ fun test4(
|
||||
) {}
|
||||
|
||||
fun test5() {
|
||||
<!UNSUPPORTED!>arrayOf<<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>Nothing<!>>()<!>
|
||||
<!UNSUPPORTED!>Array<<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>Nothing<!>>(10) { throw Exception() }<!>
|
||||
<!UNSUPPORTED!>arrayOf<!><<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>Nothing<!>>()
|
||||
<!UNSUPPORTED!>Array<!><<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>Nothing<!>>(10) { throw Exception() }
|
||||
}
|
||||
|
||||
fun <T> foo(): Array<T> = (object {} as Any) as Array<T>
|
||||
|
||||
fun test6() = <!UNSUPPORTED!>foo<Nothing>()<!>
|
||||
fun test6() = <!UNSUPPORTED!>foo<!><Nothing>()
|
||||
|
||||
|
||||
class B<T>(val array: Array<T>)
|
||||
|
||||
fun <T> bar() = B<Array<T>>(arrayOf())
|
||||
|
||||
fun test7() = <!UNSUPPORTED!>bar<Nothing>()<!>
|
||||
fun test7() = <!UNSUPPORTED!>bar<!><Nothing>()
|
||||
|
||||
+6
-6
@@ -44,24 +44,24 @@ class Derived : Base() {
|
||||
fun test() {
|
||||
foo() // Ok
|
||||
gav() // Ok
|
||||
<!SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC!>bar()<!>
|
||||
<!SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC!>baz()<!>
|
||||
<!SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC!>bar<!>()
|
||||
<!SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC!>baz<!>()
|
||||
}
|
||||
|
||||
inner class DerivedInner {
|
||||
fun fromDerivedInner() {
|
||||
foo() // Ok
|
||||
gav() // Ok
|
||||
<!SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC!>bar()<!>
|
||||
<!SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC!>baz()<!>
|
||||
<!SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC!>bar<!>()
|
||||
<!SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC!>baz<!>()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun test2() {
|
||||
gav() // Ok
|
||||
<!SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC!>bar()<!>
|
||||
<!SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC!>baz()<!>
|
||||
<!SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC!>bar<!>()
|
||||
<!SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC!>baz<!>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,8 +5,8 @@ inline fun<reified T> foo(block: () -> T): String = block().toString()
|
||||
inline fun <reified T: Any> javaClass(): Class<T> = T::class.java
|
||||
|
||||
fun box() {
|
||||
val a = <!UNSUPPORTED!><!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>arrayOf<!>(null!!)<!>
|
||||
val b = <!UNSUPPORTED!>Array<<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>Nothing?<!>>(5) { null!! }<!>
|
||||
val a = <!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, UNSUPPORTED!>arrayOf<!>(null!!)
|
||||
val b = <!UNSUPPORTED!>Array<!><<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>Nothing?<!>>(5) { null!! }
|
||||
val c = <!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>foo<!>() { null!! }
|
||||
val d = foo<Any> { null!! }
|
||||
val e = <!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>foo<!> { "1" as Nothing }
|
||||
|
||||
@@ -16703,6 +16703,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("operatorCall.kt")
|
||||
public void testOperatorCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/headerCallChecker/operatorCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("passingInstance.kt")
|
||||
public void testPassingInstance() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/headerCallChecker/passingInstance.kt");
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.google.gwt.dev.js.rhino.CodePosition
|
||||
import com.google.gwt.dev.js.rhino.ErrorReporter
|
||||
import com.google.gwt.dev.js.rhino.Utils.isEndOfLine
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1
|
||||
@@ -36,8 +37,8 @@ import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry
|
||||
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||
@@ -47,7 +48,7 @@ import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
class JsCallChecker(
|
||||
private val constantExpressionEvaluator: ConstantExpressionEvaluator
|
||||
) : SimpleCallChecker {
|
||||
) : CallChecker {
|
||||
|
||||
companion object {
|
||||
private val JS_PATTERN: DescriptorPredicate = PatternBuilder.pattern("kotlin.js.js(String)")
|
||||
@@ -62,7 +63,7 @@ class JsCallChecker(
|
||||
}
|
||||
}
|
||||
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
if (context.isAnnotationContext || !resolvedCall.isJsCall()) return
|
||||
|
||||
val expression = resolvedCall.call.callElement
|
||||
|
||||
+9
-8
@@ -16,27 +16,28 @@
|
||||
|
||||
package org.jetbrains.kotlin.android.synthetic.diagnostic
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.AndroidSyntheticPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.android.synthetic.diagnostic.ErrorsAndroid.*
|
||||
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
|
||||
class AndroidExtensionPropertiesCallChecker : SimpleCallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
||||
val expression = context.call.calleeExpression ?: return
|
||||
class AndroidExtensionPropertiesCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
reportOn as? KtExpression ?: return
|
||||
|
||||
val propertyDescriptor = resolvedCall.resultingDescriptor as? PropertyDescriptor ?: return
|
||||
val containingPackage = propertyDescriptor.containingDeclaration as? AndroidSyntheticPackageFragmentDescriptor ?: return
|
||||
val androidSyntheticProperty = propertyDescriptor as? AndroidSyntheticProperty ?: return
|
||||
|
||||
with (context.trace) {
|
||||
checkUnresolvedWidgetType(expression, androidSyntheticProperty)
|
||||
checkDeprecated(expression, containingPackage)
|
||||
with(context.trace) {
|
||||
checkUnresolvedWidgetType(reportOn, androidSyntheticProperty)
|
||||
checkDeprecated(reportOn, containingPackage)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user