Cleanup: constructor consistency checker
This commit is contained in:
@@ -113,58 +113,59 @@ class ConstructorConsistencyChecker private constructor(
|
|||||||
.filterIsInstance<PropertyDescriptor>()
|
.filterIsInstance<PropertyDescriptor>()
|
||||||
.filter { trace.get(BindingContext.BACKING_FIELD_REQUIRED, it) == true }
|
.filter { trace.get(BindingContext.BACKING_FIELD_REQUIRED, it) == true }
|
||||||
pseudocode.traverse(
|
pseudocode.traverse(
|
||||||
TraversalOrder.FORWARD, variablesData.variableInitializers, { instruction, enterData, _ ->
|
TraversalOrder.FORWARD, variablesData.variableInitializers
|
||||||
|
) { instruction, enterData, _ ->
|
||||||
|
|
||||||
fun firstUninitializedNotNullProperty() = propertyDescriptors.firstOrNull {
|
fun firstUninitializedNotNullProperty() = propertyDescriptors.firstOrNull {
|
||||||
!it.type.isMarkedNullable && !KotlinBuiltIns.isPrimitiveType(it.type) &&
|
!it.type.isMarkedNullable && !KotlinBuiltIns.isPrimitiveType(it.type) &&
|
||||||
!it.isLateInit && !(enterData.getOrNull(it)?.definitelyInitialized() ?: false)
|
!it.isLateInit && !(enterData.getOrNull(it)?.definitelyInitialized() ?: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleLeakingThis(expression: KtExpression) {
|
fun handleLeakingThis(expression: KtExpression) {
|
||||||
if (!finalClass) {
|
if (!finalClass) {
|
||||||
|
trace.record(
|
||||||
|
BindingContext.LEAKING_THIS, target(expression),
|
||||||
|
LeakingThisDescriptor.NonFinalClass(classDescriptor, classOrObject)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
val uninitializedProperty = firstUninitializedNotNullProperty()
|
||||||
|
if (uninitializedProperty != null) {
|
||||||
trace.record(
|
trace.record(
|
||||||
BindingContext.LEAKING_THIS, target(expression),
|
BindingContext.LEAKING_THIS, target(expression),
|
||||||
LeakingThisDescriptor.NonFinalClass(classDescriptor, classOrObject)
|
LeakingThisDescriptor.PropertyIsNull(uninitializedProperty, classOrObject)
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
val uninitializedProperty = firstUninitializedNotNullProperty()
|
|
||||||
if (uninitializedProperty != null) {
|
|
||||||
trace.record(
|
|
||||||
BindingContext.LEAKING_THIS, target(expression),
|
|
||||||
LeakingThisDescriptor.PropertyIsNull(uninitializedProperty, classOrObject)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (instruction.owner != pseudocode) {
|
if (instruction.owner != pseudocode) {
|
||||||
return@traverse
|
return@traverse
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instruction is KtElementInstruction) {
|
if (instruction is KtElementInstruction) {
|
||||||
val element = instruction.element
|
val element = instruction.element
|
||||||
when (instruction) {
|
when (instruction) {
|
||||||
is ReadValueInstruction ->
|
is ReadValueInstruction ->
|
||||||
if (element is KtThisExpression) {
|
if (element is KtThisExpression) {
|
||||||
if (!safeThisUsage(element)) {
|
if (!safeThisUsage(element)) {
|
||||||
|
handleLeakingThis(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is MagicInstruction ->
|
||||||
|
if (instruction.kind == MagicKind.IMPLICIT_RECEIVER) {
|
||||||
|
if (element is KtCallExpression) {
|
||||||
|
if (!safeCallUsage(element)) {
|
||||||
|
handleLeakingThis(element)
|
||||||
|
}
|
||||||
|
} else if (element is KtReferenceExpression) {
|
||||||
|
if (!safeReferenceUsage(element)) {
|
||||||
handleLeakingThis(element)
|
handleLeakingThis(element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is MagicInstruction ->
|
}
|
||||||
if (instruction.kind == MagicKind.IMPLICIT_RECEIVER) {
|
|
||||||
if (element is KtCallExpression) {
|
|
||||||
if (!safeCallUsage(element)) {
|
|
||||||
handleLeakingThis(element)
|
|
||||||
}
|
|
||||||
} else if (element is KtReferenceExpression) {
|
|
||||||
if (!safeReferenceUsage(element)) {
|
|
||||||
handleLeakingThis(element)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
Reference in New Issue
Block a user