Refactor: extract utils related to DslMarker to a separate object
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.getAbbreviation
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
object DslMarkerUtils {
|
||||
fun extractDslMarkerFqNames(kotlinType: KotlinType): Set<FqName> {
|
||||
val result = mutableSetOf<FqName>()
|
||||
|
||||
result.addAll(kotlinType.annotations.extractDslMarkerFqNames())
|
||||
|
||||
kotlinType.getAbbreviation()?.constructor?.declarationDescriptor?.run {
|
||||
result.addAll(annotations.extractDslMarkerFqNames())
|
||||
safeAs<TypeAliasDescriptor>()?.run {
|
||||
result.addAll(extractDslMarkerFqNames(this.underlyingType))
|
||||
}
|
||||
}
|
||||
|
||||
kotlinType.constructor.declarationDescriptor?.getAllSuperClassifiers()?.asIterable()
|
||||
?.flatMapTo(result) { it.annotations.extractDslMarkerFqNames() }
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun Annotations.extractDslMarkerFqNames() =
|
||||
filter(AnnotationDescriptor::isDslMarker).map { it.fqName!! }
|
||||
|
||||
val DSL_MARKER_FQ_NAME = FqName("kotlin.DslMarker")
|
||||
}
|
||||
|
||||
private fun AnnotationDescriptor.isDslMarker(): Boolean {
|
||||
val classDescriptor = annotationClass ?: return false
|
||||
return classDescriptor.annotations.hasAnnotation(DslMarkerUtils.DSL_MARKER_FQ_NAME)
|
||||
}
|
||||
+4
-42
@@ -18,22 +18,13 @@ package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.calls.DslMarkerUtils.extractDslMarkerFqNames
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getImplicitReceivers
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.getAbbreviation
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
object DslScopeViolationCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
@@ -58,44 +49,15 @@ object DslScopeViolationCallChecker : CallChecker {
|
||||
|
||||
if (receiversUntilOneFromTheCall.isEmpty()) return
|
||||
|
||||
val callDslMarkers = callImplicitReceiver.type.extractDslMarkerFqNames()
|
||||
val callDslMarkers = extractDslMarkerFqNames(callImplicitReceiver.type)
|
||||
if (callDslMarkers.isEmpty()) return
|
||||
|
||||
val closestAnotherReceiverWithSameDslMarker =
|
||||
receiversUntilOneFromTheCall.firstOrNull { receiver -> receiver.type.extractDslMarkerFqNames().any(callDslMarkers::contains) }
|
||||
receiversUntilOneFromTheCall.firstOrNull { receiver -> extractDslMarkerFqNames(receiver.type).any(callDslMarkers::contains) }
|
||||
|
||||
if (closestAnotherReceiverWithSameDslMarker != null) {
|
||||
// TODO: report receivers configuration (what's one is used and what's one is the closest)
|
||||
context.trace.report(Errors.DSL_SCOPE_VIOLATION.on(reportOn, resolvedCall.resultingDescriptor))
|
||||
}
|
||||
}
|
||||
|
||||
fun KotlinType.extractDslMarkerFqNames(): Set<FqName> {
|
||||
val result = mutableSetOf<FqName>()
|
||||
|
||||
result.addAll(annotations.extractDslMarkerFqNames())
|
||||
|
||||
getAbbreviation()?.constructor?.declarationDescriptor?.run {
|
||||
result.addAll(annotations.extractDslMarkerFqNames())
|
||||
safeAs<TypeAliasDescriptor>()?.run {
|
||||
result.addAll(underlyingType.extractDslMarkerFqNames())
|
||||
}
|
||||
}
|
||||
|
||||
constructor.declarationDescriptor?.getAllSuperClassifiers()?.asIterable()
|
||||
?.flatMapTo(result) { it.annotations.extractDslMarkerFqNames() }
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun Annotations.extractDslMarkerFqNames() =
|
||||
filter(AnnotationDescriptor::isDslMarker).map { it.fqName!! }
|
||||
|
||||
private fun AnnotationDescriptor.isDslMarker(): Boolean {
|
||||
val classDescriptor = annotationClass ?: return false
|
||||
return classDescriptor.annotations.hasAnnotation(DSL_MARKER_FQ_NAME)
|
||||
}
|
||||
|
||||
private val DSL_MARKER_FQ_NAME = FqName("kotlin.DslMarker")
|
||||
}
|
||||
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.psi.psiUtil.isImportDirectiveExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isPackageDirectiveExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.DslScopeViolationCallChecker.extractDslMarkerFqNames
|
||||
import org.jetbrains.kotlin.resolve.calls.DslMarkerUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
|
||||
@@ -350,7 +350,7 @@ fun Collection<ReceiverType>.shadowedByDslMarkers(): Set<ReceiverType> {
|
||||
|
||||
this
|
||||
.mapNotNull { receiver ->
|
||||
val dslMarkers = receiver.type.extractDslMarkerFqNames()
|
||||
val dslMarkers = DslMarkerUtils.extractDslMarkerFqNames(receiver.type)
|
||||
(receiver to dslMarkers).takeIf { dslMarkers.isNotEmpty() }
|
||||
}
|
||||
.forEach { (v, dslMarkers) -> dslMarkers.forEach { typesByDslScopes.getOrPut(it, { mutableListOf() }) += v } }
|
||||
|
||||
@@ -44,7 +44,6 @@ import org.jetbrains.kotlin.idea.util.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.DslScopeViolationCallChecker.extractDslMarkerFqNames
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.highlighter.HighlighterExtension
|
||||
import org.jetbrains.kotlin.resolve.calls.DslMarkerUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
@@ -61,6 +62,6 @@ class DslHighlighterExtension : HighlighterExtension() {
|
||||
|
||||
internal fun ClassDescriptor.isDslHighlightingMarker(): Boolean {
|
||||
return annotations.any {
|
||||
it.annotationClass?.fqNameSafe?.asString() == "kotlin.DslMarker"
|
||||
it.annotationClass?.fqNameSafe == DslMarkerUtils.DSL_MARKER_FQ_NAME
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user