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:
Alexander Udalov
2016-06-27 16:36:29 +03:00
parent f6f825e0dc
commit 6ba32ed624
38 changed files with 278 additions and 290 deletions
@@ -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))
}
}
}
@@ -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)
}
}
@@ -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))
}
}
}
@@ -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()))
}
}
@@ -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))
}
}
}
@@ -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))
}
}
}
@@ -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))
}
}
@@ -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()))
}
}
@@ -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))
}
}
}
}
@@ -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"))
}
}
}
@@ -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
@@ -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
@@ -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"))
}
}
@@ -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
}
@@ -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
))
}
}
@@ -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));
}
}
}
@@ -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) }
@@ -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
@@ -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)
}
}
}
@@ -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))
}
}
}
@@ -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();
}
}
@@ -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))
}
}
@@ -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))
}
}
}
@@ -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()
}
@@ -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() { }
}
@@ -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>()
@@ -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<!>()
}
}
}
@@ -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
@@ -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)
}
}