Reformat some classes in org.jetbrains.kotlin.cfg according to code style
This commit is contained in:
committed by
Dmitriy Novozhilov
parent
fa79f7bf30
commit
1dd7365e9f
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user