[FE] Add tests for 'containingClassForStaticMemberAttr'

This commit is contained in:
Yan Zhulanow
2022-11-26 00:37:02 +09:00
committed by Space Team
parent 4489ccf864
commit 10fc86ef92
28 changed files with 604 additions and 50 deletions
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.checkers.diagnostics.factories
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
@@ -16,7 +16,7 @@ interface DebugInfoDiagnosticFactory {
val withExplicitDefinitionOnly: Boolean
fun createDiagnostic(
expression: KtExpression,
element: KtElement,
bindingContext: BindingContext,
dataFlowValueFactory: DataFlowValueFactory?,
languageVersionSettings: LanguageVersionSettings?,
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
import org.jetbrains.kotlin.diagnostics.PositioningStrategies
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
@@ -25,13 +25,13 @@ class DebugInfoDiagnosticFactory0 private constructor(
override val withExplicitDefinitionOnly: Boolean = false
override fun createDiagnostic(
expression: KtExpression,
element: KtElement,
bindingContext: BindingContext,
dataFlowValueFactory: DataFlowValueFactory?,
languageVersionSettings: LanguageVersionSettings?,
moduleDescriptor: ModuleDescriptorImpl?
): Diagnostic {
return DebugInfoDiagnostic(expression, this)
return DebugInfoDiagnostic(element, this)
}
override val name: String
@@ -13,9 +13,16 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1
import org.jetbrains.kotlin.diagnostics.PositioningStrategies
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.diagnostics.rendering.Renderers
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.util.getCall
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
class DebugInfoDiagnosticFactory1 : DiagnosticFactory1<PsiElement, String>,
DebugInfoDiagnosticFactory {
@@ -27,7 +34,7 @@ class DebugInfoDiagnosticFactory1 : DiagnosticFactory1<PsiElement, String>,
override val withExplicitDefinitionOnly: Boolean
override fun createDiagnostic(
expression: KtExpression,
element: KtElement,
bindingContext: BindingContext,
dataFlowValueFactory: DataFlowValueFactory?,
languageVersionSettings: LanguageVersionSettings?,
@@ -35,18 +42,32 @@ class DebugInfoDiagnosticFactory1 : DiagnosticFactory1<PsiElement, String>,
) = when (privateName) {
EXPRESSION_TYPE.privateName -> {
val (type, dataFlowTypes) = CheckerTestUtil.getTypeInfo(
expression,
element,
bindingContext,
dataFlowValueFactory,
languageVersionSettings,
moduleDescriptor
)
this.on(expression, Renderers.renderExpressionType(type, dataFlowTypes))
this.on(element, Renderers.renderExpressionType(type, dataFlowTypes))
}
CALL.privateName -> {
val (fqName, typeCall) = CheckerTestUtil.getCallDebugInfo(expression, bindingContext)
this.on(expression, Renderers.renderCallInfo(fqName, typeCall))
val (fqName, typeCall) = CheckerTestUtil.getCallDebugInfo(element, bindingContext)
this.on(element, Renderers.renderCallInfo(fqName, typeCall))
}
CALLABLE_OWNER.privateName -> {
val resolvedCall = element.getCall(bindingContext)?.getResolvedCall(bindingContext)
if (resolvedCall != null) {
val callableDescriptor = resolvedCall.resultingDescriptor
val text = renderCallableOwner(
callableDescriptor.fqNameSafe,
callableDescriptor.containingDeclaration.fqNameOrNull(),
isImplicit = false
)
this.on(element, text)
} else {
this.on(element, "")
}
}
else -> throw NotImplementedError("Creation diagnostic '$name' isn't supported.")
}
@@ -70,6 +91,11 @@ class DebugInfoDiagnosticFactory1 : DiagnosticFactory1<PsiElement, String>,
Severity.INFO,
true
)
val CALLABLE_OWNER = create(
"CALLABLE_OWNER",
Severity.INFO,
true
)
val CALL = create(
"CALL",
Severity.INFO,
@@ -83,5 +109,20 @@ class DebugInfoDiagnosticFactory1 : DiagnosticFactory1<PsiElement, String>,
fun create(name: String, severity: Severity, withExplicitDefinitionOnly: Boolean): DebugInfoDiagnosticFactory1 {
return DebugInfoDiagnosticFactory1(name, severity, withExplicitDefinitionOnly)
}
fun renderCallableOwner(callableId: CallableId, ownerId: ClassId?, isExplicit: Boolean): String {
return renderCallableOwner(callableId.asFqNameForDebugInfo(), ownerId?.asSingleFqName(), isExplicit)
}
private fun renderCallableOwner(callableFqName: FqName, ownerFqName: FqName?, isImplicit: Boolean): String {
return buildString {
append(callableFqName.asString())
append(" in ")
if (isImplicit) {
append("implicit ")
}
append(ownerFqName?.asString() ?: "<unknown>")
}
}
}
}
@@ -27,9 +27,7 @@ import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.oldFashionedDescription
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.AnalyzingUtils
@@ -177,15 +175,17 @@ object CheckerTestUtil {
//noinspection unchecked
val factoryListForDiagnosticsOnExpression = listOf(
BindingContext.EXPRESSION_TYPE_INFO to DebugInfoDiagnosticFactory1.EXPRESSION_TYPE,
BindingContext.SMARTCAST to DebugInfoDiagnosticFactory0.SMARTCAST,
BindingContext.IMPLICIT_RECEIVER_SMARTCAST to DebugInfoDiagnosticFactory0.IMPLICIT_RECEIVER_SMARTCAST,
BindingContext.SMARTCAST_NULL to DebugInfoDiagnosticFactory0.CONSTANT,
BindingContext.LEAKING_THIS to DebugInfoDiagnosticFactory0.LEAKING_THIS,
BindingContext.IMPLICIT_EXHAUSTIVE_WHEN to DebugInfoDiagnosticFactory0.IMPLICIT_EXHAUSTIVE
BindingContext.EXPRESSION_TYPE_INFO to listOf(DebugInfoDiagnosticFactory1.EXPRESSION_TYPE),
BindingContext.SMARTCAST to listOf(DebugInfoDiagnosticFactory0.SMARTCAST),
BindingContext.IMPLICIT_RECEIVER_SMARTCAST to listOf(DebugInfoDiagnosticFactory0.IMPLICIT_RECEIVER_SMARTCAST),
BindingContext.SMARTCAST_NULL to listOf(DebugInfoDiagnosticFactory0.CONSTANT),
BindingContext.LEAKING_THIS to listOf(DebugInfoDiagnosticFactory0.LEAKING_THIS),
BindingContext.IMPLICIT_EXHAUSTIVE_WHEN to listOf(DebugInfoDiagnosticFactory0.IMPLICIT_EXHAUSTIVE)
)
val factoryListForDiagnosticsOnCall = listOf(BindingContext.RESOLVED_CALL to DebugInfoDiagnosticFactory1.CALL)
val factoryListForDiagnosticsOnCall = listOf(
BindingContext.RESOLVED_CALL to listOf(DebugInfoDiagnosticFactory1.CALL, DebugInfoDiagnosticFactory1.CALLABLE_OWNER)
)
renderDiagnosticsByFactoryList(
factoryListForDiagnosticsOnExpression, root, bindingContext, configuration,
@@ -195,13 +195,13 @@ object CheckerTestUtil {
renderDiagnosticsByFactoryList(
factoryListForDiagnosticsOnCall, root, bindingContext, configuration,
dataFlowValueFactory, moduleDescriptor, diagnosedRanges, debugAnnotations
) { it.callElement as? KtExpression }
) { it.callElement }
return debugAnnotations
}
private fun <T, K> renderDiagnosticsByFactoryList(
factoryList: List<Pair<WritableSlice<out T, out K>, DebugInfoDiagnosticFactory>>,
factoryList: List<Pair<WritableSlice<out T, out K>, List<DebugInfoDiagnosticFactory>>>,
root: PsiElement,
bindingContext: BindingContext,
configuration: DiagnosticsRenderingConfiguration,
@@ -209,23 +209,25 @@ object CheckerTestUtil {
moduleDescriptor: ModuleDescriptorImpl?,
diagnosedRanges: Map<IntRange, MutableSet<String>>?,
debugAnnotations: MutableList<ActualDiagnostic>,
toExpression: (T) -> KtExpression? = { it as? KtExpression }
elementProvider: (T) -> KtElement? = { it as? KtElement }
) {
for ((context, factory) in factoryList) {
for ((context, factories) in factoryList) {
for ((element, _) in bindingContext.getSliceContents(context)) {
renderDiagnostics(
factory,
toExpression(element) ?: continue,
root, bindingContext, configuration, dataFlowValueFactory, moduleDescriptor, diagnosedRanges,
debugAnnotations
)
for (factory in factories) {
renderDiagnostics(
factory,
elementProvider(element) ?: continue,
root, bindingContext, configuration, dataFlowValueFactory, moduleDescriptor, diagnosedRanges,
debugAnnotations
)
}
}
}
}
private fun renderDiagnostics(
factory: DebugInfoDiagnosticFactory,
expression: KtExpression,
element: KtElement,
root: PsiElement,
bindingContext: BindingContext,
configuration: DiagnosticsRenderingConfiguration,
@@ -237,11 +239,11 @@ object CheckerTestUtil {
if (factory !is DiagnosticFactory<*>) return
val needRender = !factory.withExplicitDefinitionOnly
|| diagnosedRanges?.get(expression.startOffset..expression.endOffset)?.contains(factory.name) == true
|| diagnosedRanges?.get(element.startOffset..element.endOffset)?.contains(factory.name) == true
if (PsiTreeUtil.isAncestor(root, expression, false) && needRender) {
if (PsiTreeUtil.isAncestor(root, element, false) && needRender) {
val diagnostic = factory.createDiagnostic(
expression,
element,
bindingContext,
dataFlowValueFactory,
configuration.languageVersionSettings,