Allow contracts on final non-override members since 1.4
This commit is contained in:
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
|
||||
@@ -259,8 +258,9 @@ class FunctionDescriptorResolver(
|
||||
if (function !is KtNamedFunction) return null
|
||||
|
||||
val isContractsEnabled = languageVersionSettings.supportsFeature(LanguageFeature.AllowContractsForCustomFunctions)
|
||||
val isAllowedOnMembers = languageVersionSettings.supportsFeature(LanguageFeature.AllowContractsForNonOverridableMembers)
|
||||
|
||||
if (!isContractsEnabled || !function.mayHaveContract()) return null
|
||||
if (!isContractsEnabled || !function.mayHaveContract(isAllowedOnMembers)) return null
|
||||
|
||||
return LazyContractProvider(storageManager) {
|
||||
AstLoadingFilter.forceAllowTreeLoading(function.containingFile, ThrowableComputable {
|
||||
|
||||
+34
-7
@@ -6,11 +6,9 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.contracts.parsing.isContractCallDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.isOverridable
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isFirstStatement
|
||||
@@ -25,6 +23,8 @@ object ContractNotAllowedCallChecker : CallChecker {
|
||||
val descriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return
|
||||
if (!descriptor.isContractCallDescriptor()) return
|
||||
|
||||
val allowedOnMembers = context.languageVersionSettings.supportsFeature(LanguageFeature.AllowContractsForNonOverridableMembers)
|
||||
|
||||
val callElement = resolvedCall.call.callElement
|
||||
var hasErrors = false
|
||||
|
||||
@@ -40,7 +40,24 @@ object ContractNotAllowedCallChecker : CallChecker {
|
||||
contractNotAllowed("Contracts are allowed only for functions")
|
||||
|
||||
var inFunctionBodyBlock = true
|
||||
if (scope.ownerDescriptor.containingDeclaration !is PackageFragmentDescriptor
|
||||
|
||||
val declarationOwner = scope.ownerDescriptor.containingDeclaration
|
||||
val acceptableParent = if (allowedOnMembers) {
|
||||
var owner = declarationOwner
|
||||
var result = true
|
||||
while (owner !is PackageFragmentDescriptor) {
|
||||
if (owner !is ClassDescriptor) {
|
||||
result = false
|
||||
break
|
||||
}
|
||||
owner = owner.containingDeclaration
|
||||
}
|
||||
result
|
||||
} else {
|
||||
declarationOwner is PackageFragmentDescriptor
|
||||
}
|
||||
|
||||
if (!acceptableParent
|
||||
|| scope.kind != LexicalScopeKind.CODE_BLOCK
|
||||
|| (scope.parent as? LexicalScope)?.kind != LexicalScopeKind.FUNCTION_INNER_SCOPE
|
||||
) {
|
||||
@@ -48,13 +65,23 @@ object ContractNotAllowedCallChecker : CallChecker {
|
||||
contractNotAllowed("Contracts are allowed only in function body block")
|
||||
inFunctionBodyBlock = false
|
||||
} else {
|
||||
contractNotAllowed("Contracts are allowed only for top-level functions")
|
||||
val message = if (allowedOnMembers)
|
||||
"Contracts are allowed only for functions"
|
||||
else
|
||||
"Contracts are allowed only for top-level functions"
|
||||
contractNotAllowed(message)
|
||||
}
|
||||
}
|
||||
|
||||
if (functionDescriptor?.isOperator == true) contractNotAllowed("Contracts are not allowed for operator functions")
|
||||
|
||||
if (functionDescriptor?.isOverridable == true) contractNotAllowed("Contracts are not allowed for open functions")
|
||||
|
||||
if (!allowedOnMembers && functionDescriptor?.isOverridable == true) {
|
||||
contractNotAllowed("Contracts are not allowed for open functions")
|
||||
}
|
||||
if (allowedOnMembers && functionDescriptor?.isOverridableOrOverrides == true) {
|
||||
contractNotAllowed("Contracts are not allowed for open or override functions")
|
||||
}
|
||||
|
||||
if (!callElement.isFirstStatement() && inFunctionBodyBlock) {
|
||||
contractNotAllowed("Contract should be the first statement")
|
||||
|
||||
Reference in New Issue
Block a user