Minor: rename and refactor contract-related PSI checks in ktPsiUtil

This commit is contained in:
Dmitry Savvinov
2018-07-19 19:06:21 +03:00
parent b943140f3a
commit 724b7bf363
3 changed files with 22 additions and 19 deletions
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.contracts.description.ContractProviderKey
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.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.isContractDescriptionCallFastCheck import org.jetbrains.kotlin.psi.psiUtil.isContractDescriptionCallPsiCheck
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
class ContractParsingServices(val languageVersionSettings: LanguageVersionSettings) { class ContractParsingServices(val languageVersionSettings: LanguageVersionSettings) {
fun checkContractAndRecordIfPresent(expression: KtExpression, trace: BindingTrace, scope: LexicalScope, isFirstStatement: Boolean) { fun checkContractAndRecordIfPresent(expression: KtExpression, trace: BindingTrace, scope: LexicalScope, isFirstStatement: Boolean) {
val ownerDescriptor = scope.ownerDescriptor val ownerDescriptor = scope.ownerDescriptor
if (!isContractDescriptionCallFastCheck(expression) || ownerDescriptor !is FunctionDescriptor) return if (!expression.isContractDescriptionCallPsiCheck() || ownerDescriptor !is FunctionDescriptor) return
val contractProvider = ownerDescriptor.getUserData(ContractProviderKey) ?: return val contractProvider = ownerDescriptor.getUserData(ContractProviderKey) ?: return
val isFeatureTurnedOn = languageVersionSettings.supportsFeature(LanguageFeature.AllowContractsForCustomFunctions) || val isFeatureTurnedOn = languageVersionSettings.supportsFeature(LanguageFeature.AllowContractsForCustomFunctions) ||
@@ -42,7 +42,7 @@ class ContractParsingServices(val languageVersionSettings: LanguageVersionSettin
languageVersionSettings.getFlag(AnalysisFlag.Flags.allowKotlinPackage) languageVersionSettings.getFlag(AnalysisFlag.Flags.allowKotlinPackage)
val contractDescriptor = when { val contractDescriptor = when {
!isContractDescriptionCallPreciseCheck(expression, trace.bindingContext) -> null !expression.isContractDescriptionCallPreciseCheck(trace.bindingContext) -> null
!isFeatureTurnedOn -> { !isFeatureTurnedOn -> {
trace.report( trace.report(
@@ -65,15 +65,15 @@ class ContractParsingServices(val languageVersionSettings: LanguageVersionSettin
contractProvider.setContractDescription(contractDescriptor) contractProvider.setContractDescription(contractDescriptor)
} }
internal fun isContractDescriptionCall(expression: KtExpression, context: BindingContext): Boolean =
expression.isContractDescriptionCallPsiCheck() && expression.isContractDescriptionCallPreciseCheck(context)
private fun parseContract(expression: KtExpression?, trace: BindingTrace, ownerDescriptor: FunctionDescriptor): ContractDescription? = private fun parseContract(expression: KtExpression?, trace: BindingTrace, ownerDescriptor: FunctionDescriptor): ContractDescription? =
PsiContractParserDispatcher(trace, this).parseContract(expression, ownerDescriptor) PsiContractParserDispatcher(trace, this).parseContract(expression, ownerDescriptor)
internal fun isContractDescriptionCall(expression: KtExpression, context: BindingContext): Boolean =
isContractDescriptionCallFastCheck(expression) && isContractDescriptionCallPreciseCheck(expression, context)
private fun isContractAllowedHere(scope: LexicalScope): Boolean = private fun isContractAllowedHere(scope: LexicalScope): Boolean =
scope.kind == LexicalScopeKind.CODE_BLOCK && (scope.parent as? LexicalScope)?.kind == LexicalScopeKind.FUNCTION_INNER_SCOPE scope.kind == LexicalScopeKind.CODE_BLOCK && (scope.parent as? LexicalScope)?.kind == LexicalScopeKind.FUNCTION_INNER_SCOPE
private fun isContractDescriptionCallPreciseCheck(expression: KtExpression, context: BindingContext): Boolean = private fun KtExpression.isContractDescriptionCallPreciseCheck(context: BindingContext): Boolean =
expression.getResolvedCall(context)?.resultingDescriptor?.isContractCallDescriptor() ?: false getResolvedCall(context)?.resultingDescriptor?.isContractCallDescriptor() ?: false
} }
@@ -39,7 +39,7 @@ import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.fastCheckIfContractPresent import org.jetbrains.kotlin.psi.psiUtil.isContractPresentPsiCheck
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
import org.jetbrains.kotlin.resolve.DescriptorResolver.getDefaultModality import org.jetbrains.kotlin.resolve.DescriptorResolver.getDefaultModality
@@ -242,7 +242,7 @@ class FunctionDescriptorResolver(
// We need to enable contracts if we're compiling "kotlin"-package to be able to ship contracts in stdlib in 1.2 // We need to enable contracts if we're compiling "kotlin"-package to be able to ship contracts in stdlib in 1.2
languageVersionSettings.getFlag(AnalysisFlag.allowKotlinPackage) languageVersionSettings.getFlag(AnalysisFlag.allowKotlinPackage)
if (!isContractsEnabled || !fastCheckIfContractPresent(function)) return emptyContract if (!isContractsEnabled || !function.isContractPresentPsiCheck()) return emptyContract
return provideByDeferredForceResolve return provideByDeferredForceResolve
} }
@@ -293,17 +293,20 @@ inline fun <reified T : KtElement, R> flatMapDescendantsOfTypeVisitor(
// ----------- Contracts ------------------------------------------------------------------------------------------------------------------- // ----------- Contracts -------------------------------------------------------------------------------------------------------------------
fun fastCheckIfContractPresent(element: KtElement): Boolean { fun KtElement.isContractPresentPsiCheck(): Boolean {
if (!isContractAllowedHere(element)) return false val contractAllowedHere = this is KtNamedFunction &&
val firstExpression = ((element as? KtFunction)?.bodyExpression as? KtBlockExpression)?.statements?.firstOrNull() ?: return false isTopLevel &&
return isContractDescriptionCallFastCheck(firstExpression) hasBlockBody() &&
!hasModifier(KtTokens.OPERATOR_KEYWORD)
if (!contractAllowedHere) return false
val firstExpression = ((this as? KtFunction)?.bodyExpression as? KtBlockExpression)?.statements?.firstOrNull() ?: return false
return firstExpression.isContractDescriptionCallPsiCheck()
} }
private fun isContractAllowedHere(element: KtElement): Boolean = fun KtExpression.isContractDescriptionCallPsiCheck(): Boolean =
element is KtNamedFunction && element.isTopLevel && element.hasBlockBody() && !element.hasModifier(KtTokens.OPERATOR_KEYWORD) this is KtCallExpression && calleeExpression?.text == "contract"
fun isContractDescriptionCallFastCheck(expression: KtExpression): Boolean =
expression is KtCallExpression && expression.calleeExpression?.text == "contract"
// ----------- Other ----------------------------------------------------------------------------------------------------------------------- // ----------- Other -----------------------------------------------------------------------------------------------------------------------