Reformat some classes in org.jetbrains.kotlin.cfg according to code style

This commit is contained in:
Dmitriy Novozhilov
2018-09-24 14:29:12 +03:00
committed by Dmitriy Novozhilov
parent fa79f7bf30
commit 1dd7365e9f
4 changed files with 96 additions and 77 deletions
@@ -26,7 +26,7 @@ abstract class ControlFlowInfo<S : ControlFlowInfo<S, D>, D : Any>
internal constructor( internal constructor(
protected val map: ImmutableMap<VariableDescriptor, D> = ImmutableHashMap.empty() protected val map: ImmutableMap<VariableDescriptor, D> = ImmutableHashMap.empty()
) : ImmutableMap<VariableDescriptor, D> by map, ReadOnlyControlFlowInfo<D> { ) : ImmutableMap<VariableDescriptor, D> by map, ReadOnlyControlFlowInfo<D> {
abstract protected fun copy(newMap: ImmutableMap<VariableDescriptor, D>): S protected abstract fun copy(newMap: ImmutableMap<VariableDescriptor, D>): S
override fun put(key: VariableDescriptor, value: D): S = put(key, value, this[key].getOrElse(null as D?)) override fun put(key: VariableDescriptor, value: D): S = put(key, value, this[key].getOrElse(null as D?))
@@ -232,7 +232,7 @@ class ControlFlowInformationProvider private constructor(
private fun checkDefiniteReturn(expectedReturnType: KotlinType, unreachableCode: UnreachableCode) { private fun checkDefiniteReturn(expectedReturnType: KotlinType, unreachableCode: UnreachableCode) {
val function = subroutine as? KtDeclarationWithBody val function = subroutine as? KtDeclarationWithBody
?: throw AssertionError("checkDefiniteReturn is called for ${subroutine.text} which is not KtDeclarationWithBody") ?: throw AssertionError("checkDefiniteReturn is called for ${subroutine.text} which is not KtDeclarationWithBody")
if (!function.hasBody()) return if (!function.hasBody()) return
@@ -287,7 +287,8 @@ class ControlFlowInformationProvider private constructor(
if (instruction !is KtElementInstruction if (instruction !is KtElementInstruction
|| instruction is LoadUnitValueInstruction || instruction is LoadUnitValueInstruction
|| instruction is MergeInstruction || instruction is MergeInstruction
|| instruction is MagicInstruction && instruction.synthetic) || instruction is MagicInstruction && instruction.synthetic
)
continue continue
val element = instruction.element val element = instruction.element
@@ -332,7 +333,8 @@ class ControlFlowInformationProvider private constructor(
if (instruction is ReadValueInstruction) { if (instruction is ReadValueInstruction) {
val element = instruction.element val element = instruction.element
if (PseudocodeUtil.isThisOrNoDispatchReceiver(instruction, trace.bindingContext) if (PseudocodeUtil.isThisOrNoDispatchReceiver(instruction, trace.bindingContext)
&& declaredVariables.contains(ctxt.variableDescriptor)) { && declaredVariables.contains(ctxt.variableDescriptor)
) {
checkIsInitialized(ctxt, element, varWithUninitializedErrorGenerated) checkIsInitialized(ctxt, element, varWithUninitializedErrorGenerated)
} }
return@traverse return@traverse
@@ -407,7 +409,8 @@ class ControlFlowInformationProvider private constructor(
} }
is VariableDescriptor -> is VariableDescriptor ->
if (!variableDescriptor.isLateInit && if (!variableDescriptor.isLateInit &&
!(variableDescriptor is MemberDescriptor && variableDescriptor.isEffectivelyExternal())) { !(variableDescriptor is MemberDescriptor && variableDescriptor.isEffectivelyExternal())
) {
report(Errors.UNINITIALIZED_VARIABLE.on(element, variableDescriptor), ctxt) report(Errors.UNINITIALIZED_VARIABLE.on(element, variableDescriptor), ctxt)
} }
} }
@@ -473,7 +476,8 @@ class ControlFlowInformationProvider private constructor(
if (Visibilities.isVisible(receiverValue, variableDescriptor, descriptor) if (Visibilities.isVisible(receiverValue, variableDescriptor, descriptor)
&& setterDescriptor != null && setterDescriptor != null
&& !Visibilities.isVisible(receiverValue, setterDescriptor, descriptor)) { && !Visibilities.isVisible(receiverValue, setterDescriptor, descriptor)
) {
report( report(
Errors.INVISIBLE_SETTER.on( Errors.INVISIBLE_SETTER.on(
expression, variableDescriptor, setterDescriptor.visibility, expression, variableDescriptor, setterDescriptor.visibility,
@@ -486,7 +490,8 @@ class ControlFlowInformationProvider private constructor(
val isThisOrNoDispatchReceiver = PseudocodeUtil.isThisOrNoDispatchReceiver(writeValueInstruction, trace.bindingContext) val isThisOrNoDispatchReceiver = PseudocodeUtil.isThisOrNoDispatchReceiver(writeValueInstruction, trace.bindingContext)
val captured = variableDescriptor?.let { isCapturedWrite(it, writeValueInstruction) } ?: false val captured = variableDescriptor?.let { isCapturedWrite(it, writeValueInstruction) } ?: false
if ((mayBeInitializedNotHere || !hasBackingField || !isThisOrNoDispatchReceiver || captured) && if ((mayBeInitializedNotHere || !hasBackingField || !isThisOrNoDispatchReceiver || captured) &&
variableDescriptor != null && !variableDescriptor.isVar) { variableDescriptor != null && !variableDescriptor.isVar
) {
var hasReassignMethodReturningUnit = false var hasReassignMethodReturningUnit = false
val parent = expression.parent val parent = expression.parent
val operationReference = val operationReference =
@@ -558,7 +563,7 @@ class ControlFlowInformationProvider private constructor(
} }
private fun VariableInitContext.isInitializationBeforeDeclaration(): Boolean = private fun VariableInitContext.isInitializationBeforeDeclaration(): Boolean =
// is not declared // is not declared
enterInitState?.isDeclared != true && exitInitState?.isDeclared != true && enterInitState?.isDeclared != true && exitInitState?.isDeclared != true &&
// wasn't initialized before current instruction // wasn't initialized before current instruction
enterInitState?.mayBeInitialized() != true enterInitState?.mayBeInitialized() != true
@@ -569,19 +574,21 @@ class ControlFlowInformationProvider private constructor(
|| ctxt.enterInitState?.mayBeInitialized() == true || ctxt.enterInitState?.mayBeInitialized() == true
|| ctxt.exitInitState?.mayBeInitialized() != true || ctxt.exitInitState?.mayBeInitialized() != true
|| !variableDescriptor.isVar || !variableDescriptor.isVar
|| trace.get(BindingContext.BACKING_FIELD_REQUIRED, variableDescriptor) != true) { || trace.get(BindingContext.BACKING_FIELD_REQUIRED, variableDescriptor) != true
) {
return false return false
} }
val property = DescriptorToSourceUtils.descriptorToDeclaration(variableDescriptor) as? KtProperty val property = DescriptorToSourceUtils.descriptorToDeclaration(variableDescriptor) as? KtProperty
?: throw AssertionError("$variableDescriptor is not related to KtProperty") ?: throw AssertionError("$variableDescriptor is not related to KtProperty")
val setter = property.setter val setter = property.setter
if (variableDescriptor.modality == Modality.FINAL && (setter == null || !setter.hasBody())) { if (variableDescriptor.modality == Modality.FINAL && (setter == null || !setter.hasBody())) {
return false return false
} }
val variable = if (expression is KtDotQualifiedExpression && val variable = if (expression is KtDotQualifiedExpression &&
expression.receiverExpression is KtThisExpression) { expression.receiverExpression is KtThisExpression
) {
expression.selectorExpression expression.selectorExpression
} else { } else {
expression expression
@@ -626,7 +633,8 @@ class ControlFlowInformationProvider private constructor(
) )
if (variableDescriptor == null if (variableDescriptor == null
|| !declaredVariables.contains(variableDescriptor) || !declaredVariables.contains(variableDescriptor)
|| !ExpressionTypingUtils.isLocal(variableDescriptor.containingDeclaration, variableDescriptor)) { || !ExpressionTypingUtils.isLocal(variableDescriptor.containingDeclaration, variableDescriptor)
) {
return@traverse return@traverse
} }
val variableUseState = enterData.getOrNull(variableDescriptor) val variableUseState = enterData.getOrNull(variableDescriptor)
@@ -675,7 +683,7 @@ class ControlFlowInformationProvider private constructor(
if (!VariableUseState.isUsed(variableUseState)) { if (!VariableUseState.isUsed(variableUseState)) {
if (element.isSingleUnderscore) return if (element.isSingleUnderscore) return
when { when {
// KtDestructuringDeclarationEntry -> KtDestructuringDeclaration -> KtParameter -> KtParameterList // KtDestructuringDeclarationEntry -> KtDestructuringDeclaration -> KtParameter -> KtParameterList
element is KtDestructuringDeclarationEntry && element.parent.parent?.parent is KtParameterList -> element is KtDestructuringDeclarationEntry && element.parent.parent?.parent is KtParameterList ->
report(Errors.UNUSED_DESTRUCTURED_PARAMETER_ENTRY.on(element, variableDescriptor), ctxt) report(Errors.UNUSED_DESTRUCTURED_PARAMETER_ENTRY.on(element, variableDescriptor), ctxt)
@@ -704,7 +712,8 @@ class ControlFlowInformationProvider private constructor(
if (functionDescriptor.isExpect || functionDescriptor.isActual || if (functionDescriptor.isExpect || functionDescriptor.isActual ||
functionDescriptor.isEffectivelyExternal() || functionDescriptor.isEffectivelyExternal() ||
!diagnosticSuppressor.shouldReportUnusedParameter(variableDescriptor)) return !diagnosticSuppressor.shouldReportUnusedParameter(variableDescriptor)
) return
val owner = element.parent.parent val owner = element.parent.parent
when (owner) { when (owner) {
@@ -737,7 +746,8 @@ class ControlFlowInformationProvider private constructor(
|| owner.hasModifier(KtTokens.OVERRIDE_KEYWORD) || owner.hasModifier(KtTokens.OVERRIDE_KEYWORD)
|| OperatorNameConventions.GET_VALUE == functionName || OperatorNameConventions.GET_VALUE == functionName
|| OperatorNameConventions.SET_VALUE == functionName || OperatorNameConventions.SET_VALUE == functionName
|| OperatorNameConventions.PROVIDE_DELEGATE == functionName) { || OperatorNameConventions.PROVIDE_DELEGATE == functionName
) {
return return
} }
if (anonymous) { if (anonymous) {
@@ -819,7 +829,8 @@ class ControlFlowInformationProvider private constructor(
for (branchExpression in branchExpressions) { for (branchExpression in branchExpressions) {
val branchType = trace.getType(branchExpression) ?: return val branchType = trace.getType(branchExpression) ?: return
if (KotlinBuiltIns.isAnyOrNullableAny(branchType) || if (KotlinBuiltIns.isAnyOrNullableAny(branchType) ||
isUsedAsResultOfLambda && KotlinBuiltIns.isUnitOrNullableUnit(branchType)) { isUsedAsResultOfLambda && KotlinBuiltIns.isUnitOrNullableUnit(branchType)
) {
return return
} }
} }
@@ -874,7 +885,8 @@ class ControlFlowInformationProvider private constructor(
val pseudocodeDescriptor = trace[DECLARATION_TO_DESCRIPTOR, pseudocodeElement] val pseudocodeDescriptor = trace[DECLARATION_TO_DESCRIPTOR, pseudocodeElement]
if (subjectClass == null || if (subjectClass == null ||
KotlinBuiltIns.isBooleanOrNullableBoolean(subjectType) || KotlinBuiltIns.isBooleanOrNullableBoolean(subjectType) ||
subjectClass.module == pseudocodeDescriptor?.module) { subjectClass.module == pseudocodeDescriptor?.module
) {
trace.report(REDUNDANT_ELSE_IN_WHEN.on(elseEntry)) trace.report(REDUNDANT_ELSE_IN_WHEN.on(elseEntry))
} }
} }
@@ -925,13 +937,14 @@ class ControlFlowInformationProvider private constructor(
class KindAndCall(var kind: TailRecursionKind, internal val call: ResolvedCall<*>) class KindAndCall(var kind: TailRecursionKind, internal val call: ResolvedCall<*>)
val calls = HashMap<KtElement, KindAndCall>() val calls = HashMap<KtElement, KindAndCall>()
traverseCalls traverse@ { instruction, resolvedCall -> traverseCalls traverse@{ instruction, resolvedCall ->
// is this a recursive call? // is this a recursive call?
val functionDescriptor = resolvedCall.resultingDescriptor val functionDescriptor = resolvedCall.resultingDescriptor
if (functionDescriptor.original != subroutineDescriptor) return@traverse if (functionDescriptor.original != subroutineDescriptor) return@traverse
// Overridden functions using default arguments at tail call are not included: KT-4285 // Overridden functions using default arguments at tail call are not included: KT-4285
if (resolvedCall.call.valueArguments.size != functionDescriptor.valueParameters.size if (resolvedCall.call.valueArguments.size != functionDescriptor.valueParameters.size
&& !functionDescriptor.overriddenDescriptors.isEmpty()) && !functionDescriptor.overriddenDescriptors.isEmpty()
)
return@traverse return@traverse
val element = instruction.element val element = instruction.element
@@ -1095,7 +1108,7 @@ class ControlFlowInformationProvider private constructor(
// For a class primary constructor, we cannot directly get ConstructorDescriptor by KtClassInitializer, // For a class primary constructor, we cannot directly get ConstructorDescriptor by KtClassInitializer,
// so we have to do additional conversion: KtClassInitializer -> KtClassOrObject -> ClassDescriptor -> ConstructorDescriptor // so we have to do additional conversion: KtClassInitializer -> KtClassOrObject -> ClassDescriptor -> ConstructorDescriptor
descriptor.unsubstitutedPrimaryConstructor descriptor.unsubstitutedPrimaryConstructor
?: (descriptor as? ClassDescriptorWithResolutionScopes)?.scopeForInitializerResolution?.ownerDescriptor ?: (descriptor as? ClassDescriptorWithResolutionScopes)?.scopeForInitializerResolution?.ownerDescriptor
} else { } else {
descriptor descriptor
} }
@@ -1107,7 +1120,8 @@ class ControlFlowInformationProvider private constructor(
val returnElement = usage.element val returnElement = usage.element
val parentElement = returnElement.parent val parentElement = returnElement.parent
if (returnElement !is KtReturnExpression && if (returnElement !is KtReturnExpression &&
(parentElement !is KtDeclaration || parentElement is KtFunctionLiteral)) { (parentElement !is KtDeclaration || parentElement is KtFunctionLiteral)
) {
return true return true
} }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * Copyright 2010-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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.cfg package org.jetbrains.kotlin.cfg
@@ -69,19 +58,19 @@ class PseudocodeVariableDataCollector(
private fun computeBlockScopeVariableInfo(pseudocode: Pseudocode): BlockScopeVariableInfo { private fun computeBlockScopeVariableInfo(pseudocode: Pseudocode): BlockScopeVariableInfo {
val blockScopeVariableInfo = BlockScopeVariableInfoImpl() val blockScopeVariableInfo = BlockScopeVariableInfoImpl()
pseudocode.traverse(TraversalOrder.FORWARD, { instruction -> pseudocode.traverse(TraversalOrder.FORWARD) { instruction ->
if (instruction is VariableDeclarationInstruction) { if (instruction is VariableDeclarationInstruction) {
val variableDeclarationElement = instruction.variableDeclarationElement val variableDeclarationElement = instruction.variableDeclarationElement
val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement) ?: return@traverse val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement) ?: return@traverse
val variableDescriptor = BindingContextUtils.variableDescriptorForDeclaration(descriptor) val variableDescriptor = BindingContextUtils.variableDescriptorForDeclaration(descriptor)
?: throw AssertionError( ?: throw AssertionError(
"Variable or class descriptor should correspond to " + "Variable or class descriptor should correspond to " +
"the instruction for ${instruction.element.text}.\n" + "the instruction for ${instruction.element.text}.\n" +
"Descriptor: $descriptor" "Descriptor: $descriptor"
) )
blockScopeVariableInfo.registerVariableDeclaredInScope(variableDescriptor, instruction.blockScope) blockScopeVariableInfo.registerVariableDeclaredInScope(variableDescriptor, instruction.blockScope)
} }
}) }
return blockScopeVariableInfo return blockScopeVariableInfo
} }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * Copyright 2010-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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.cfg package org.jetbrains.kotlin.cfg
@@ -43,7 +32,8 @@ private typealias ImmutableHashSet<T> = javaslang.collection.HashSet<T>
class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingContext: BindingContext) { class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingContext: BindingContext) {
private val containsDoWhile = pseudocode.rootPseudocode.containsDoWhile private val containsDoWhile = pseudocode.rootPseudocode.containsDoWhile
private val pseudocodeVariableDataCollector = PseudocodeVariableDataCollector(bindingContext, pseudocode) private val pseudocodeVariableDataCollector =
PseudocodeVariableDataCollector(bindingContext, pseudocode)
private class VariablesForDeclaration( private class VariablesForDeclaration(
val valsWithTrivialInitializer: Set<VariableDescriptor>, val valsWithTrivialInitializer: Set<VariableDescriptor>,
@@ -86,7 +76,10 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
val localPseudocode = localFunctionDeclarationInstruction.body val localPseudocode = localFunctionDeclarationInstruction.body
addVariablesFromPseudocode(localPseudocode, nonTrivialVariables, valsWithTrivialInitializer) addVariablesFromPseudocode(localPseudocode, nonTrivialVariables, valsWithTrivialInitializer)
} }
return VariablesForDeclaration(valsWithTrivialInitializer, nonTrivialVariables) return VariablesForDeclaration(
valsWithTrivialInitializer,
nonTrivialVariables
)
} }
private fun addVariablesFromPseudocode( private fun addVariablesFromPseudocode(
@@ -123,7 +116,10 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
} }
} }
return VariablesForDeclaration(valsWithTrivialInitializer, nonTrivialVariables) return VariablesForDeclaration(
valsWithTrivialInitializer,
nonTrivialVariables
)
} }
private fun isValWithTrivialInitializer(variableDeclarationElement: KtDeclaration, descriptor: VariableDescriptor) = private fun isValWithTrivialInitializer(variableDeclarationElement: KtDeclaration, descriptor: VariableDescriptor) =
@@ -156,15 +152,20 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
InitControlFlowInfo() InitControlFlowInfo()
) { instruction: Instruction, incomingEdgesData: Collection<InitControlFlowInfo> -> ) { instruction: Instruction, incomingEdgesData: Collection<InitControlFlowInfo> ->
val enterInstructionData = mergeIncomingEdgesDataForInitializers(instruction, incomingEdgesData, blockScopeVariableInfo) val enterInstructionData =
mergeIncomingEdgesDataForInitializers(
instruction,
incomingEdgesData,
blockScopeVariableInfo
)
val exitInstructionData = addVariableInitStateFromCurrentInstructionIfAny( val exitInstructionData = addVariableInitStateFromCurrentInstructionIfAny(
instruction, enterInstructionData, blockScopeVariableInfo instruction, enterInstructionData, blockScopeVariableInfo
) )
Edges(enterInstructionData, exitInstructionData) Edges(enterInstructionData, exitInstructionData)
}.mapValues { (instruction, edges) -> }.mapValues { (instruction, edges) ->
val trivialEdges = resultForValsWithTrivialInitializer[instruction]!! val trivialEdges = resultForValsWithTrivialInitializer[instruction]!!
Edges(trivialEdges.incoming.replaceDelegate(edges.incoming), trivialEdges.outgoing.replaceDelegate(edges.outgoing)) Edges(trivialEdges.incoming.replaceDelegate(edges.incoming), trivialEdges.outgoing.replaceDelegate(edges.outgoing))
} }
} }
private fun computeInitInfoForTrivialVals(): Map<Instruction, Edges<ReadOnlyInitControlFlowInfoImpl>> { private fun computeInitInfoForTrivialVals(): Map<Instruction, Edges<ReadOnlyInitControlFlowInfoImpl>> {
@@ -194,9 +195,9 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
} }
private fun WriteValueInstruction.isTrivialInitializer() = private fun WriteValueInstruction.isTrivialInitializer() =
// WriteValueInstruction having KtDeclaration as an element means // WriteValueInstruction having KtDeclaration as an element means
// it must be a write happened at the same time when // it must be a write happened at the same time when
// the variable (common variable/parameter/object) has been declared // the variable (common variable/parameter/object) has been declared
element is KtDeclaration element is KtDeclaration
private inner class ReadOnlyInitControlFlowInfoImpl( private inner class ReadOnlyInitControlFlowInfoImpl(
@@ -206,7 +207,10 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
) : ReadOnlyInitControlFlowInfo { ) : ReadOnlyInitControlFlowInfo {
override fun getOrNull(variableDescriptor: VariableDescriptor): VariableControlFlowState? { override fun getOrNull(variableDescriptor: VariableDescriptor): VariableControlFlowState? {
if (variableDescriptor in declaredSet) { if (variableDescriptor in declaredSet) {
return VariableControlFlowState.create(isInitialized = variableDescriptor in initSet, isDeclared = true) return VariableControlFlowState.create(
isInitialized = variableDescriptor in initSet,
isDeclared = true
)
} }
return delegate?.getOrNull(variableDescriptor) return delegate?.getOrNull(variableDescriptor)
} }
@@ -255,7 +259,10 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
if (instruction.kind === MagicKind.EXHAUSTIVE_WHEN_ELSE) { if (instruction.kind === MagicKind.EXHAUSTIVE_WHEN_ELSE) {
return enterInstructionData.iterator().fold(enterInstructionData) { result, (key, value) -> return enterInstructionData.iterator().fold(enterInstructionData) { result, (key, value) ->
if (!value.definitelyInitialized()) { if (!value.definitelyInitialized()) {
result.put(key, VariableControlFlowState.createInitializedExhaustively(value.isDeclared)) result.put(
key,
VariableControlFlowState.createInitializedExhaustively(value.isDeclared)
)
} else result } else result
} }
} }
@@ -266,7 +273,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
val variable = val variable =
PseudocodeUtil.extractVariableDescriptorIfAny(instruction, bindingContext) PseudocodeUtil.extractVariableDescriptorIfAny(instruction, bindingContext)
?.takeIf { it in rootVariables.nonTrivialVariables } ?.takeIf { it in rootVariables.nonTrivialVariables }
?: return enterInstructionData ?: return enterInstructionData
var exitInstructionData = enterInstructionData var exitInstructionData = enterInstructionData
if (instruction is WriteValueInstruction) { if (instruction is WriteValueInstruction) {
// if writing to already initialized object // if writing to already initialized object
@@ -275,16 +282,22 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
} }
val enterInitState = enterInstructionData.getOrNull(variable) val enterInitState = enterInstructionData.getOrNull(variable)
val initializationAtThisElement = VariableControlFlowState.create(instruction.element is KtProperty, enterInitState) val initializationAtThisElement =
VariableControlFlowState.create(instruction.element is KtProperty, enterInitState)
exitInstructionData = exitInstructionData.put(variable, initializationAtThisElement, enterInitState) exitInstructionData = exitInstructionData.put(variable, initializationAtThisElement, enterInitState)
} else { } else {
// instruction instanceof VariableDeclarationInstruction // instruction instanceof VariableDeclarationInstruction
val enterInitState = val enterInitState =
enterInstructionData.getOrNull(variable) enterInstructionData.getOrNull(variable)
?: getDefaultValueForInitializers(variable, instruction, blockScopeVariableInfo) ?: getDefaultValueForInitializers(
variable,
instruction,
blockScopeVariableInfo
)
if (!enterInitState.mayBeInitialized() || !enterInitState.isDeclared) { if (!enterInitState.mayBeInitialized() || !enterInitState.isDeclared) {
val variableDeclarationInfo = VariableControlFlowState.create(enterInitState.initState, isDeclared = true) val variableDeclarationInfo =
VariableControlFlowState.create(enterInitState.initState, isDeclared = true)
exitInstructionData = exitInstructionData.put(variable, variableDeclarationInfo, enterInitState) exitInstructionData = exitInstructionData.put(variable, variableDeclarationInfo, enterInitState)
} }
} }
@@ -343,12 +356,11 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
Edges(enterResult, exitResult) Edges(enterResult, exitResult)
} }
}.mapValues { (_, edges) -> }.mapValues { (_, edges) ->
Edges(
Edges( edgesForTrivialVals.incoming.replaceDelegate(edges.incoming),
edgesForTrivialVals.incoming.replaceDelegate(edges.incoming), edgesForTrivialVals.outgoing.replaceDelegate(edges.outgoing)
edgesForTrivialVals.outgoing.replaceDelegate(edges.outgoing) )
) }
}
} }
private fun computeUseInfoForTrivialVals(): Edges<ReadOnlyUseControlFlowInfoImpl> { private fun computeUseInfoForTrivialVals(): Edges<ReadOnlyUseControlFlowInfoImpl> {
@@ -447,7 +459,11 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
var isDeclared = true var isDeclared = true
for (edgeData in incomingEdgesData) { for (edgeData in incomingEdgesData) {
val varControlFlowState = edgeData.getOrNull(variable) val varControlFlowState = edgeData.getOrNull(variable)
?: getDefaultValueForInitializers(variable, instruction, blockScopeVariableInfo) ?: getDefaultValueForInitializers(
variable,
instruction,
blockScopeVariableInfo
)
initState = initState?.merge(varControlFlowState.initState) ?: varControlFlowState.initState initState = initState?.merge(varControlFlowState.initState) ?: varControlFlowState.initState
if (!varControlFlowState.isDeclared) { if (!varControlFlowState.isDeclared) {
isDeclared = false isDeclared = false