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