Code cleanup: CFG (several inspections applied)
This commit is contained in:
committed by
Mikhail Glukhikh
parent
43f9035d07
commit
9a5b5393f5
@@ -33,63 +33,47 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
|
||||
delegateBuilder.loadUnit(expression)
|
||||
}
|
||||
|
||||
override fun loadConstant(expression: KtExpression, constant: CompileTimeConstant<*>?): InstructionWithValue {
|
||||
return delegateBuilder.loadConstant(expression, constant)
|
||||
}
|
||||
override fun loadConstant(expression: KtExpression, constant: CompileTimeConstant<*>?): InstructionWithValue =
|
||||
delegateBuilder.loadConstant(expression, constant)
|
||||
|
||||
override fun createAnonymousObject(expression: KtObjectLiteralExpression): InstructionWithValue {
|
||||
return delegateBuilder.createAnonymousObject(expression)
|
||||
}
|
||||
override fun createAnonymousObject(expression: KtObjectLiteralExpression): InstructionWithValue =
|
||||
delegateBuilder.createAnonymousObject(expression)
|
||||
|
||||
override fun createLambda(expression: KtFunction): InstructionWithValue {
|
||||
return delegateBuilder.createLambda(expression)
|
||||
}
|
||||
override fun createLambda(expression: KtFunction): InstructionWithValue = delegateBuilder.createLambda(expression)
|
||||
|
||||
override fun loadStringTemplate(expression: KtStringTemplateExpression, inputValues: List<PseudoValue>): InstructionWithValue {
|
||||
return delegateBuilder.loadStringTemplate(expression, inputValues)
|
||||
}
|
||||
override fun loadStringTemplate(expression: KtStringTemplateExpression, inputValues: List<PseudoValue>): InstructionWithValue =
|
||||
delegateBuilder.loadStringTemplate(expression, inputValues)
|
||||
|
||||
override fun magic(
|
||||
instructionElement: KtElement,
|
||||
valueElement: KtElement?,
|
||||
inputValues: List<PseudoValue>,
|
||||
kind: MagicKind): MagicInstruction {
|
||||
return delegateBuilder.magic(instructionElement, valueElement, inputValues, kind)
|
||||
}
|
||||
kind: MagicKind): MagicInstruction = delegateBuilder.magic(instructionElement, valueElement, inputValues, kind)
|
||||
|
||||
override fun merge(expression: KtExpression, inputValues: List<PseudoValue>): MergeInstruction {
|
||||
return delegateBuilder.merge(expression, inputValues)
|
||||
}
|
||||
override fun merge(expression: KtExpression, inputValues: List<PseudoValue>): MergeInstruction =
|
||||
delegateBuilder.merge(expression, inputValues)
|
||||
|
||||
override fun readVariable(
|
||||
expression: KtExpression,
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
receiverValues: Map<PseudoValue, ReceiverValue>): ReadValueInstruction {
|
||||
return delegateBuilder.readVariable(expression, resolvedCall, receiverValues)
|
||||
}
|
||||
receiverValues: Map<PseudoValue, ReceiverValue>): ReadValueInstruction =
|
||||
delegateBuilder.readVariable(expression, resolvedCall, receiverValues)
|
||||
|
||||
override fun call(
|
||||
valueElement: KtElement,
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
receiverValues: Map<PseudoValue, ReceiverValue>,
|
||||
arguments: Map<PseudoValue, ValueParameterDescriptor>): CallInstruction {
|
||||
return delegateBuilder.call(valueElement, resolvedCall, receiverValues, arguments)
|
||||
}
|
||||
arguments: Map<PseudoValue, ValueParameterDescriptor>): CallInstruction =
|
||||
delegateBuilder.call(valueElement, resolvedCall, receiverValues, arguments)
|
||||
|
||||
override fun predefinedOperation(
|
||||
expression: KtExpression,
|
||||
operation: ControlFlowBuilder.PredefinedOperation,
|
||||
inputValues: List<PseudoValue>): OperationInstruction {
|
||||
return delegateBuilder.predefinedOperation(expression, operation, inputValues)
|
||||
}
|
||||
inputValues: List<PseudoValue>): OperationInstruction = delegateBuilder.predefinedOperation(expression, operation, inputValues)
|
||||
|
||||
override fun createUnboundLabel(): Label {
|
||||
return delegateBuilder.createUnboundLabel()
|
||||
}
|
||||
override fun createUnboundLabel(): Label = delegateBuilder.createUnboundLabel()
|
||||
|
||||
override fun createUnboundLabel(name: String): Label {
|
||||
return delegateBuilder.createUnboundLabel(name)
|
||||
}
|
||||
override fun createUnboundLabel(name: String): Label = delegateBuilder.createUnboundLabel(name)
|
||||
|
||||
override fun bindLabel(label: Label) {
|
||||
delegateBuilder.bindLabel(label)
|
||||
@@ -123,21 +107,13 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
|
||||
delegateBuilder.throwException(throwExpression, thrownValue)
|
||||
}
|
||||
|
||||
override fun getSubroutineExitPoint(labelElement: KtElement): Label? {
|
||||
return delegateBuilder.getSubroutineExitPoint(labelElement)
|
||||
}
|
||||
override fun getSubroutineExitPoint(labelElement: KtElement): Label? = delegateBuilder.getSubroutineExitPoint(labelElement)
|
||||
|
||||
override fun getLoopConditionEntryPoint(loop: KtLoopExpression): Label? {
|
||||
return delegateBuilder.getLoopConditionEntryPoint(loop)
|
||||
}
|
||||
override fun getLoopConditionEntryPoint(loop: KtLoopExpression): Label? = delegateBuilder.getLoopConditionEntryPoint(loop)
|
||||
|
||||
override fun getLoopExitPoint(loop: KtLoopExpression): Label? {
|
||||
return delegateBuilder.getLoopExitPoint(loop)
|
||||
}
|
||||
override fun getLoopExitPoint(loop: KtLoopExpression): Label? = delegateBuilder.getLoopExitPoint(loop)
|
||||
|
||||
override fun enterLoop(expression: KtLoopExpression): LoopInfo {
|
||||
return delegateBuilder.enterLoop(expression)
|
||||
}
|
||||
override fun enterLoop(expression: KtLoopExpression): LoopInfo = delegateBuilder.enterLoop(expression)
|
||||
|
||||
override fun enterLoopBody(expression: KtLoopExpression) {
|
||||
delegateBuilder.enterLoopBody(expression)
|
||||
@@ -162,9 +138,7 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
|
||||
delegateBuilder.enterSubroutine(subroutine)
|
||||
}
|
||||
|
||||
override fun exitSubroutine(subroutine: KtElement): Pseudocode {
|
||||
return delegateBuilder.exitSubroutine(subroutine)
|
||||
}
|
||||
override fun exitSubroutine(subroutine: KtElement): Pseudocode = delegateBuilder.exitSubroutine(subroutine)
|
||||
|
||||
override val currentSubroutine: KtElement
|
||||
get() = delegateBuilder.currentSubroutine
|
||||
@@ -216,17 +190,13 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
|
||||
delegateBuilder.mark(element)
|
||||
}
|
||||
|
||||
override fun getBoundValue(element: KtElement?): PseudoValue? {
|
||||
return delegateBuilder.getBoundValue(element)
|
||||
}
|
||||
override fun getBoundValue(element: KtElement?): PseudoValue? = delegateBuilder.getBoundValue(element)
|
||||
|
||||
override fun bindValue(value: PseudoValue, element: KtElement) {
|
||||
delegateBuilder.bindValue(value, element)
|
||||
}
|
||||
|
||||
override fun newValue(element: KtElement?): PseudoValue {
|
||||
return delegateBuilder.newValue(element)
|
||||
}
|
||||
override fun newValue(element: KtElement?): PseudoValue = delegateBuilder.newValue(element)
|
||||
|
||||
override fun enterBlockScope(block: KtElement) {
|
||||
delegateBuilder.enterBlockScope(block)
|
||||
|
||||
@@ -102,13 +102,9 @@ enum class InitState(private val s: String) {
|
||||
|
||||
class VariableControlFlowState private constructor(val initState: InitState, val isDeclared: Boolean) {
|
||||
|
||||
fun definitelyInitialized(): Boolean {
|
||||
return initState == InitState.INITIALIZED
|
||||
}
|
||||
fun definitelyInitialized(): Boolean = initState == InitState.INITIALIZED
|
||||
|
||||
fun mayBeInitialized(): Boolean {
|
||||
return initState != InitState.NOT_INITIALIZED
|
||||
}
|
||||
fun mayBeInitialized(): Boolean = initState != InitState.NOT_INITIALIZED
|
||||
|
||||
override fun toString(): String {
|
||||
if (initState == InitState.NOT_INITIALIZED && !isDeclared) return "-"
|
||||
@@ -134,17 +130,14 @@ class VariableControlFlowState private constructor(val initState: InitState, val
|
||||
InitState.NOT_INITIALIZED -> if (isDeclared) VS_NT else VS_NF
|
||||
}
|
||||
|
||||
fun createInitializedExhaustively(isDeclared: Boolean): VariableControlFlowState {
|
||||
return create(InitState.INITIALIZED_EXHAUSTIVELY, isDeclared)
|
||||
}
|
||||
fun createInitializedExhaustively(isDeclared: Boolean): VariableControlFlowState =
|
||||
create(InitState.INITIALIZED_EXHAUSTIVELY, isDeclared)
|
||||
|
||||
fun create(isInitialized: Boolean, isDeclared: Boolean = false): VariableControlFlowState {
|
||||
return create(if (isInitialized) InitState.INITIALIZED else InitState.NOT_INITIALIZED, isDeclared)
|
||||
}
|
||||
fun create(isInitialized: Boolean, isDeclared: Boolean = false): VariableControlFlowState =
|
||||
create(if (isInitialized) InitState.INITIALIZED else InitState.NOT_INITIALIZED, isDeclared)
|
||||
|
||||
fun create(isDeclaredHere: Boolean, mergedEdgesData: VariableControlFlowState?): VariableControlFlowState {
|
||||
return create(true, isDeclaredHere || mergedEdgesData != null && mergedEdgesData.isDeclared)
|
||||
}
|
||||
fun create(isDeclaredHere: Boolean, mergedEdgesData: VariableControlFlowState?): VariableControlFlowState =
|
||||
create(true, isDeclaredHere || mergedEdgesData != null && mergedEdgesData.isDeclared)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,9 +155,7 @@ enum class VariableUseState(private val priority: Int) {
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun isUsed(variableUseState: VariableUseState?): Boolean {
|
||||
return variableUseState != null && variableUseState != UNUSED
|
||||
}
|
||||
fun isUsed(variableUseState: VariableUseState?): Boolean = variableUseState != null && variableUseState != UNUSED
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@ import org.jetbrains.kotlin.types.TypeUtils.*
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
import org.jetbrains.kotlin.types.isFlexible
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import java.util.*
|
||||
|
||||
class ControlFlowInformationProvider private constructor(
|
||||
private val subroutine: KtElement,
|
||||
@@ -311,7 +310,7 @@ class ControlFlowInformationProvider private constructor(
|
||||
}
|
||||
|
||||
private fun PropertyDescriptor.isDefinitelyInitialized(): Boolean {
|
||||
if (trace.get(BACKING_FIELD_REQUIRED, this) ?: false) return false
|
||||
if (trace.get(BACKING_FIELD_REQUIRED, this) == true) return false
|
||||
val property = DescriptorToSourceUtils.descriptorToDeclaration(this)
|
||||
if (property is KtProperty && property.hasDelegate()) return false
|
||||
return true
|
||||
@@ -432,14 +431,14 @@ class ControlFlowInformationProvider private constructor(
|
||||
if (operationReference != null) {
|
||||
val descriptor = trace.get(BindingContext.REFERENCE_TARGET, operationReference)
|
||||
if (descriptor is FunctionDescriptor) {
|
||||
if (descriptor.returnType?.let { KotlinBuiltIns.isUnit(it) } ?: false) {
|
||||
if (descriptor.returnType?.let { KotlinBuiltIns.isUnit(it) } == true) {
|
||||
hasReassignMethodReturningUnit = true
|
||||
}
|
||||
}
|
||||
if (descriptor == null) {
|
||||
val descriptors = trace.get(BindingContext.AMBIGUOUS_REFERENCE_TARGET, operationReference) ?: emptyList()
|
||||
for (referenceDescriptor in descriptors) {
|
||||
if ((referenceDescriptor as? FunctionDescriptor)?.returnType?.let { KotlinBuiltIns.isUnit(it) } ?: false) {
|
||||
if ((referenceDescriptor as? FunctionDescriptor)?.returnType?.let { KotlinBuiltIns.isUnit(it) } == true) {
|
||||
hasReassignMethodReturningUnit = true
|
||||
}
|
||||
}
|
||||
@@ -476,10 +475,10 @@ class ControlFlowInformationProvider private constructor(
|
||||
}
|
||||
|
||||
private fun checkAssignmentBeforeDeclaration(ctxt: VariableInitContext, expression: KtExpression) =
|
||||
if (ctxt.enterInitState?.isDeclared ?: false
|
||||
|| ctxt.exitInitState?.isDeclared ?: false
|
||||
|| ctxt.enterInitState?.mayBeInitialized() ?: false
|
||||
|| !(ctxt.exitInitState?.mayBeInitialized() ?: false)) {
|
||||
if (ctxt.enterInitState?.isDeclared == true
|
||||
|| ctxt.exitInitState?.isDeclared == true
|
||||
|| ctxt.enterInitState?.mayBeInitialized() == true
|
||||
|| ctxt.exitInitState?.mayBeInitialized() != true) {
|
||||
false
|
||||
}
|
||||
else {
|
||||
@@ -492,10 +491,10 @@ class ControlFlowInformationProvider private constructor(
|
||||
private fun checkInitializationForCustomSetter(ctxt: VariableInitContext, expression: KtExpression): Boolean {
|
||||
val variableDescriptor = ctxt.variableDescriptor
|
||||
if (variableDescriptor !is PropertyDescriptor
|
||||
|| ctxt.enterInitState?.mayBeInitialized() ?: false
|
||||
|| !(ctxt.exitInitState?.mayBeInitialized() ?: false)
|
||||
|| ctxt.enterInitState?.mayBeInitialized() == true
|
||||
|| ctxt.exitInitState?.mayBeInitialized() != true
|
||||
|| !variableDescriptor.isVar
|
||||
|| !(trace.get(BindingContext.BACKING_FIELD_REQUIRED, variableDescriptor) ?: false)) {
|
||||
|| trace.get(BindingContext.BACKING_FIELD_REQUIRED, variableDescriptor) != true) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -528,7 +527,7 @@ class ControlFlowInformationProvider private constructor(
|
||||
val declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode, false)
|
||||
for (variable in declaredVariables) {
|
||||
if (variable is PropertyDescriptor) {
|
||||
if (initializers.incoming.getOrNull(variable)?.definitelyInitialized() ?: false) continue
|
||||
if (initializers.incoming.getOrNull(variable)?.definitelyInitialized() == true) continue
|
||||
trace.record(BindingContext.IS_UNINITIALIZED, variable)
|
||||
}
|
||||
}
|
||||
@@ -947,7 +946,7 @@ class ControlFlowInformationProvider private constructor(
|
||||
val tailInstructionDetector = TailInstructionDetector(subroutine)
|
||||
return traverseFollowingInstructions(
|
||||
this,
|
||||
HashSet<Instruction>(),
|
||||
hashSetOf(),
|
||||
TraversalOrder.FORWARD
|
||||
) {
|
||||
if (it == this@isTailCall || it.accept(tailInstructionDetector))
|
||||
|
||||
@@ -117,9 +117,8 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
|
||||
private val conditionVisitor = object : KtVisitorVoid() {
|
||||
|
||||
private fun getSubjectExpression(condition: KtWhenCondition): KtExpression? {
|
||||
return condition.getStrictParentOfType<KtWhenExpression>()?.subjectExpression
|
||||
}
|
||||
private fun getSubjectExpression(condition: KtWhenCondition): KtExpression? =
|
||||
condition.getStrictParentOfType<KtWhenExpression>()?.subjectExpression
|
||||
|
||||
override fun visitWhenConditionInRange(condition: KtWhenConditionInRange) {
|
||||
if (!generateCall(condition.operationReference)) {
|
||||
@@ -181,17 +180,14 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSyntheticValue(instructionElement: KtElement, kind: MagicKind, vararg from: KtElement): PseudoValue {
|
||||
return builder.magic(instructionElement, null, elementsToValues(from.asList()), kind).outputValue
|
||||
}
|
||||
private fun createSyntheticValue(instructionElement: KtElement, kind: MagicKind, vararg from: KtElement): PseudoValue =
|
||||
builder.magic(instructionElement, null, elementsToValues(from.asList()), kind).outputValue
|
||||
|
||||
private fun createNonSyntheticValue(to: KtElement, from: List<KtElement?>, kind: MagicKind): PseudoValue {
|
||||
return builder.magic(to, to, elementsToValues(from), kind).outputValue
|
||||
}
|
||||
private fun createNonSyntheticValue(to: KtElement, from: List<KtElement?>, kind: MagicKind): PseudoValue =
|
||||
builder.magic(to, to, elementsToValues(from), kind).outputValue
|
||||
|
||||
private fun createNonSyntheticValue(to: KtElement, kind: MagicKind, vararg from: KtElement?): PseudoValue {
|
||||
return createNonSyntheticValue(to, from.asList(), kind)
|
||||
}
|
||||
private fun createNonSyntheticValue(to: KtElement, kind: MagicKind, vararg from: KtElement?): PseudoValue =
|
||||
createNonSyntheticValue(to, from.asList(), kind)
|
||||
|
||||
private fun mergeValues(from: List<KtExpression>, to: KtExpression) {
|
||||
builder.merge(to, elementsToValues(from))
|
||||
@@ -208,18 +204,16 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
return if (value != null || element is KtDeclaration) value else builder.newValue(element)
|
||||
}
|
||||
|
||||
private fun elementsToValues(from: List<KtElement?>): List<PseudoValue> {
|
||||
return from.mapNotNull { element -> getBoundOrUnreachableValue(element) }
|
||||
}
|
||||
private fun elementsToValues(from: List<KtElement?>): List<PseudoValue> =
|
||||
from.mapNotNull { element -> getBoundOrUnreachableValue(element) }
|
||||
|
||||
private fun generateInitializer(declaration: KtDeclaration, initValue: PseudoValue) {
|
||||
builder.write(declaration, declaration, initValue, getDeclarationAccessTarget(declaration), emptyMap())
|
||||
}
|
||||
|
||||
private fun getResolvedCallAccessTarget(element: KtElement?): AccessTarget {
|
||||
return element.getResolvedCall(trace.bindingContext)?.let { AccessTarget.Call(it) }
|
||||
?: AccessTarget.BlackBox
|
||||
}
|
||||
private fun getResolvedCallAccessTarget(element: KtElement?): AccessTarget =
|
||||
element.getResolvedCall(trace.bindingContext)?.let { AccessTarget.Call(it) }
|
||||
?: AccessTarget.BlackBox
|
||||
|
||||
private fun getDeclarationAccessTarget(element: KtElement): AccessTarget {
|
||||
val descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element)
|
||||
@@ -533,9 +527,8 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun isIncrementOrDecrement(operationType: IElementType): Boolean {
|
||||
return operationType === KtTokens.PLUSPLUS || operationType === KtTokens.MINUSMINUS
|
||||
}
|
||||
private fun isIncrementOrDecrement(operationType: IElementType): Boolean =
|
||||
operationType === KtTokens.PLUSPLUS || operationType === KtTokens.MINUSMINUS
|
||||
|
||||
override fun visitIfExpression(expression: KtIfExpression) {
|
||||
mark(expression)
|
||||
@@ -668,7 +661,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
builder.bindLabel(onException)
|
||||
val catchLabels = LinkedList<Label>()
|
||||
val catchClausesSize = catchClauses.size
|
||||
for (i in 0..catchClausesSize - 1 - 1) {
|
||||
for (i in 0 until catchClausesSize - 1) {
|
||||
catchLabels.add(builder.createUnboundLabel("catch " + i))
|
||||
}
|
||||
if (!catchLabels.isEmpty()) {
|
||||
@@ -1148,7 +1141,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
entry,
|
||||
resolvedCall,
|
||||
getReceiverValues(resolvedCall),
|
||||
emptyMap<PseudoValue, ValueParameterDescriptor>()).outputValue
|
||||
emptyMap()).outputValue
|
||||
}
|
||||
else {
|
||||
initializer?.let { createSyntheticValue(entry, MagicKind.UNRESOLVED_CALL, it) }
|
||||
@@ -1273,7 +1266,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
// For the last entry of exhaustive when,
|
||||
// attempt to jump further should lead to error, not to "done"
|
||||
if (!iterator.hasNext() && WhenChecker.isWhenExhaustive(expression, trace)) {
|
||||
builder.magic(expression, null, emptyList<PseudoValue>(), MagicKind.EXHAUSTIVE_WHEN_ELSE)
|
||||
builder.magic(expression, null, emptyList(), MagicKind.EXHAUSTIVE_WHEN_ELSE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ fun <D> Pseudocode.traverse(
|
||||
if (instruction is LocalFunctionDeclarationInstruction) {
|
||||
instruction.body.traverse(traversalOrder, edgesMap, analyzeInstruction)
|
||||
}
|
||||
val edges = edgesMap.get(instruction)
|
||||
val edges = edgesMap[instruction]
|
||||
if (edges != null) {
|
||||
analyzeInstruction(instruction, edges.incoming, edges.outgoing)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.cfg.pseudocodeTraverser.traverse
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||
import java.util.*
|
||||
|
||||
class PseudocodeVariableDataCollector(
|
||||
private val bindingContext: BindingContext,
|
||||
@@ -68,7 +67,7 @@ class PseudocodeVariableDataCollector(
|
||||
} as I
|
||||
}
|
||||
|
||||
fun computeBlockScopeVariableInfo(pseudocode: Pseudocode): BlockScopeVariableInfo {
|
||||
private fun computeBlockScopeVariableInfo(pseudocode: Pseudocode): BlockScopeVariableInfo {
|
||||
val blockScopeVariableInfo = BlockScopeVariableInfoImpl()
|
||||
pseudocode.traverse(TraversalOrder.FORWARD, { instruction ->
|
||||
if (instruction is VariableDeclarationInstruction) {
|
||||
@@ -96,7 +95,7 @@ class BlockScopeVariableInfoImpl : BlockScopeVariableInfo {
|
||||
|
||||
fun registerVariableDeclaredInScope(variable: VariableDescriptor, blockScope: BlockScope) {
|
||||
declaredIn[variable] = blockScope
|
||||
val variablesInScope = scopeVariables.getOrPut(blockScope, { ArrayList<VariableDescriptor>() })
|
||||
val variablesInScope = scopeVariables.getOrPut(blockScope, { arrayListOf() })
|
||||
variablesInScope.add(variable)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class UnreachableCodeImpl(
|
||||
) : UnreachableCode {
|
||||
|
||||
// This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
|
||||
override val elements = KtPsiUtil.findRootExpressions(unreachableElements)
|
||||
override val elements: Set<KtElement> = KtPsiUtil.findRootExpressions(unreachableElements)
|
||||
|
||||
override fun getUnreachableTextRanges(element: KtElement): List<TextRange> {
|
||||
return if (element.hasChildrenInSet(reachableElements)) {
|
||||
@@ -54,9 +54,8 @@ class UnreachableCodeImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtElement.hasChildrenInSet(set: Set<KtElement>): Boolean {
|
||||
return PsiTreeUtil.collectElements(this) { it != this }.any { it in set }
|
||||
}
|
||||
private fun KtElement.hasChildrenInSet(set: Set<KtElement>): Boolean =
|
||||
PsiTreeUtil.collectElements(this) { it != this }.any { it in set }
|
||||
|
||||
private fun KtElement.getLeavesOrReachableChildren(): List<PsiElement> {
|
||||
val children = ArrayList<PsiElement>()
|
||||
@@ -74,7 +73,7 @@ class UnreachableCodeImpl(
|
||||
return children
|
||||
}
|
||||
|
||||
fun List<PsiElement>.removeReachableElementsWithMeaninglessSiblings(): List<PsiElement> {
|
||||
private fun List<PsiElement>.removeReachableElementsWithMeaninglessSiblings(): List<PsiElement> {
|
||||
fun PsiElement.isMeaningless() = this is PsiWhiteSpace
|
||||
|| this.node?.elementType == KtTokens.COMMA
|
||||
|| this is PsiComment
|
||||
|
||||
+14
-36
@@ -90,9 +90,9 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
||||
|
||||
private inner class ControlFlowInstructionsGeneratorWorker(scopingElement: KtElement, override val returnSubroutine: KtElement) : ControlFlowBuilder {
|
||||
|
||||
val pseudocode: PseudocodeImpl
|
||||
private val error: Label
|
||||
private val sink: Label
|
||||
val pseudocode: PseudocodeImpl = PseudocodeImpl(scopingElement)
|
||||
private val error: Label = pseudocode.createLabel("error", null)
|
||||
private val sink: Label = pseudocode.createLabel("sink", null)
|
||||
|
||||
private val valueFactory = object : PseudoValueFactoryImpl() {
|
||||
override fun newValue(element: KtElement?, instruction: InstructionWithValue?): PseudoValue {
|
||||
@@ -104,23 +104,13 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
this.pseudocode = PseudocodeImpl(scopingElement)
|
||||
this.error = pseudocode.createLabel("error", null)
|
||||
this.sink = pseudocode.createLabel("sink", null)
|
||||
}
|
||||
|
||||
private fun add(instruction: Instruction) {
|
||||
pseudocode.addInstruction(instruction)
|
||||
}
|
||||
|
||||
override fun createUnboundLabel(): Label {
|
||||
return pseudocode.createLabel("L" + labelCount++, null)
|
||||
}
|
||||
override fun createUnboundLabel(): Label = pseudocode.createLabel("L" + labelCount++, null)
|
||||
|
||||
override fun createUnboundLabel(name: String): Label {
|
||||
return pseudocode.createLabel("L" + labelCount++, name)
|
||||
}
|
||||
override fun createUnboundLabel(name: String): Label = pseudocode.createLabel("L" + labelCount++, name)
|
||||
|
||||
override fun enterLoop(expression: KtLoopExpression): LoopInfo {
|
||||
val info = LoopInfo(
|
||||
@@ -166,19 +156,13 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
||||
override val currentSubroutine: KtElement
|
||||
get() = pseudocode.correspondingElement
|
||||
|
||||
override fun getLoopConditionEntryPoint(loop: KtLoopExpression): Label? {
|
||||
return elementToLoopInfo[loop]?.conditionEntryPoint
|
||||
}
|
||||
override fun getLoopConditionEntryPoint(loop: KtLoopExpression): Label? = elementToLoopInfo[loop]?.conditionEntryPoint
|
||||
|
||||
override fun getLoopExitPoint(loop: KtLoopExpression): Label? {
|
||||
// It's quite possible to have null here, see testBreakInsideLocal
|
||||
return elementToLoopInfo[loop]?.exitPoint
|
||||
}
|
||||
override fun getLoopExitPoint(loop: KtLoopExpression): Label? =// It's quite possible to have null here, see testBreakInsideLocal
|
||||
elementToLoopInfo[loop]?.exitPoint
|
||||
|
||||
override fun getSubroutineExitPoint(labelElement: KtElement): Label? {
|
||||
// It's quite possible to have null here, e.g. for non-local returns (see KT-10823)
|
||||
return elementToSubroutineInfo[labelElement]?.exitPoint
|
||||
}
|
||||
override fun getSubroutineExitPoint(labelElement: KtElement): Label? =// It's quite possible to have null here, e.g. for non-local returns (see KT-10823)
|
||||
elementToSubroutineInfo[labelElement]?.exitPoint
|
||||
|
||||
private val currentScope: BlockScope
|
||||
get() = blockScopes.peek()
|
||||
@@ -233,17 +217,13 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
||||
add(MarkInstruction(element, currentScope))
|
||||
}
|
||||
|
||||
override fun getBoundValue(element: KtElement?): PseudoValue? {
|
||||
return pseudocode.getElementValue(element)
|
||||
}
|
||||
override fun getBoundValue(element: KtElement?): PseudoValue? = pseudocode.getElementValue(element)
|
||||
|
||||
override fun bindValue(value: PseudoValue, element: KtElement) {
|
||||
pseudocode.bindElementToValue(element, value)
|
||||
}
|
||||
|
||||
override fun newValue(element: KtElement?): PseudoValue {
|
||||
return valueFactory.newValue(element, null)
|
||||
}
|
||||
override fun newValue(element: KtElement?): PseudoValue = valueFactory.newValue(element, null)
|
||||
|
||||
override fun returnValue(returnExpression: KtExpression, returnValue: PseudoValue, subroutine: KtElement) {
|
||||
val exitPoint = getSubroutineExitPoint(subroutine) ?: return
|
||||
@@ -396,9 +376,7 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
||||
override fun predefinedOperation(
|
||||
expression: KtExpression,
|
||||
operation: ControlFlowBuilder.PredefinedOperation,
|
||||
inputValues: List<PseudoValue>): OperationInstruction {
|
||||
return magic(expression, expression, inputValues, getMagicKind(operation))
|
||||
}
|
||||
inputValues: List<PseudoValue>): OperationInstruction = magic(expression, expression, inputValues, getMagicKind(operation))
|
||||
|
||||
private fun getMagicKind(operation: ControlFlowBuilder.PredefinedOperation) = when (operation) {
|
||||
ControlFlowBuilder.PredefinedOperation.AND -> MagicKind.AND
|
||||
@@ -417,7 +395,7 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
||||
private fun read(
|
||||
expression: KtExpression,
|
||||
resolvedCall: ResolvedCall<*>? = null,
|
||||
receiverValues: Map<PseudoValue, ReceiverValue> = emptyMap<PseudoValue, ReceiverValue>()
|
||||
receiverValues: Map<PseudoValue, ReceiverValue> = emptyMap()
|
||||
) = read(expression, if (resolvedCall != null) AccessTarget.Call(resolvedCall) else AccessTarget.BlackBox, receiverValues)
|
||||
}
|
||||
|
||||
|
||||
@@ -123,9 +123,7 @@ class PseudocodeImpl(override val correspondingElement: KtElement) : Pseudocode
|
||||
get() = mutableInstructionList
|
||||
|
||||
//for tests only
|
||||
fun getLabels(): List<PseudocodeLabel> {
|
||||
return labels
|
||||
}
|
||||
fun getLabels(): List<PseudocodeLabel> = labels
|
||||
|
||||
fun addExitInstruction(exitInstruction: SubroutineExitInstruction) {
|
||||
addInstruction(exitInstruction)
|
||||
@@ -215,7 +213,7 @@ class PseudocodeImpl(override val correspondingElement: KtElement) : Pseudocode
|
||||
if (usage is MergeInstruction) return
|
||||
valueUsages.getOrPut(
|
||||
value
|
||||
) { arrayListOf<Instruction>() }.add(usage)
|
||||
) { arrayListOf() }.add(usage)
|
||||
}
|
||||
|
||||
fun postProcess() {
|
||||
@@ -333,9 +331,7 @@ class PseudocodeImpl(override val correspondingElement: KtElement) : Pseudocode
|
||||
}
|
||||
}
|
||||
|
||||
private fun getJumpTarget(targetLabel: Label): Instruction {
|
||||
return targetLabel.resolveToInstruction()
|
||||
}
|
||||
private fun getJumpTarget(targetLabel: Label): Instruction = targetLabel.resolveToInstruction()
|
||||
|
||||
private fun getNextPosition(currentPosition: Int): Instruction {
|
||||
val targetPosition = currentPosition + 1
|
||||
@@ -349,18 +345,15 @@ class PseudocodeImpl(override val correspondingElement: KtElement) : Pseudocode
|
||||
return result
|
||||
}
|
||||
|
||||
override fun instructionForElement(element: KtElement): KtElementInstruction? {
|
||||
return representativeInstructions[element]
|
||||
}
|
||||
override fun instructionForElement(element: KtElement): KtElementInstruction? = representativeInstructions[element]
|
||||
|
||||
private fun repeatWhole(originalPseudocode: PseudocodeImpl) {
|
||||
repeatInternal(originalPseudocode, null, null, 0)
|
||||
parent = originalPseudocode.parent
|
||||
}
|
||||
|
||||
fun repeatPart(startLabel: Label, finishLabel: Label, labelCount: Int): Int {
|
||||
return repeatInternal(startLabel.pseudocode as PseudocodeImpl, startLabel, finishLabel, labelCount)
|
||||
}
|
||||
fun repeatPart(startLabel: Label, finishLabel: Label, labelCount: Int): Int =
|
||||
repeatInternal(startLabel.pseudocode as PseudocodeImpl, startLabel, finishLabel, labelCount)
|
||||
|
||||
private fun repeatInternal(
|
||||
originalPseudocode: PseudocodeImpl,
|
||||
@@ -387,7 +380,7 @@ class PseudocodeImpl(override val correspondingElement: KtElement) : Pseudocode
|
||||
for (label in originalToCopy.values) {
|
||||
labels.add(label)
|
||||
}
|
||||
for (index in startIndex..finishIndex - 1) {
|
||||
for (index in startIndex until finishIndex) {
|
||||
val originalInstruction = originalPseudocode.mutableInstructionList[index]
|
||||
repeatLabelsBindingForInstruction(originalInstruction, originalToCopy, originalLabelsForInstruction)
|
||||
val copy = copyInstruction(originalInstruction, originalToCopy)
|
||||
|
||||
@@ -30,9 +30,7 @@ class PseudocodeLabel internal constructor(
|
||||
|
||||
override var targetInstructionIndex = -1
|
||||
|
||||
override fun toString(): String {
|
||||
return if (comment == null) name else "$name [$comment]"
|
||||
}
|
||||
override fun toString(): String = if (comment == null) name else "$name [$comment]"
|
||||
|
||||
override fun resolveToInstruction(): Instruction {
|
||||
val index = targetInstructionIndex
|
||||
@@ -43,7 +41,6 @@ class PseudocodeLabel internal constructor(
|
||||
return instructionList[index]
|
||||
}
|
||||
|
||||
fun copy(newPseudocode: PseudocodeImpl, newLabelIndex: Int): PseudocodeLabel {
|
||||
return PseudocodeLabel(newPseudocode, "L" + newLabelIndex, "copy of $name, $comment")
|
||||
}
|
||||
fun copy(newPseudocode: PseudocodeImpl, newLabelIndex: Int): PseudocodeLabel =
|
||||
PseudocodeLabel(newPseudocode, "L" + newLabelIndex, "copy of $name, $comment")
|
||||
}
|
||||
|
||||
@@ -71,12 +71,10 @@ fun or(predicates: Collection<TypePredicate>): TypePredicate? =
|
||||
else -> ForSomeType(predicates.toList())
|
||||
}
|
||||
|
||||
fun KotlinType.getSubtypesPredicate(): TypePredicate {
|
||||
return when {
|
||||
KotlinBuiltIns.isAnyOrNullableAny(this) && isMarkedNullable -> AllTypes
|
||||
TypeUtils.canHaveSubtypes(KotlinTypeChecker.DEFAULT, this) -> AllSubtypes(this)
|
||||
else -> SingleType(this)
|
||||
}
|
||||
fun KotlinType.getSubtypesPredicate(): TypePredicate = when {
|
||||
KotlinBuiltIns.isAnyOrNullableAny(this) && isMarkedNullable -> AllTypes
|
||||
TypeUtils.canHaveSubtypes(KotlinTypeChecker.DEFAULT, this) -> AllSubtypes(this)
|
||||
else -> SingleType(this)
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ abstract class InstructionImpl(override val blockScope: BlockScope): Instruction
|
||||
|
||||
override var owner: Pseudocode
|
||||
get() = _owner!!
|
||||
set(value: Pseudocode) {
|
||||
set(value) {
|
||||
assert(_owner == null || _owner == value)
|
||||
_owner = value
|
||||
}
|
||||
|
||||
-1
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.cfg.pseudocode.instructions
|
||||
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.*
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.*
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.*
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
|
||||
|
||||
+23
-67
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.cfg.pseudocode.instructions
|
||||
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.*
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.*
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.*
|
||||
@@ -24,91 +23,48 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.*
|
||||
abstract class InstructionVisitorWithResult<out R> {
|
||||
abstract fun visitInstruction(instruction: Instruction): R
|
||||
|
||||
open fun visitAccessInstruction(instruction: AccessValueInstruction): R {
|
||||
return visitInstructionWithNext(instruction)
|
||||
}
|
||||
open fun visitAccessInstruction(instruction: AccessValueInstruction): R = visitInstructionWithNext(instruction)
|
||||
|
||||
open fun visitReadValue(instruction: ReadValueInstruction): R {
|
||||
return visitAccessInstruction(instruction)
|
||||
}
|
||||
open fun visitReadValue(instruction: ReadValueInstruction): R = visitAccessInstruction(instruction)
|
||||
|
||||
open fun visitLocalFunctionDeclarationInstruction(instruction: LocalFunctionDeclarationInstruction): R {
|
||||
return visitInstructionWithNext(instruction)
|
||||
}
|
||||
open fun visitLocalFunctionDeclarationInstruction(instruction: LocalFunctionDeclarationInstruction): R =
|
||||
visitInstructionWithNext(instruction)
|
||||
|
||||
open fun visitVariableDeclarationInstruction(instruction: VariableDeclarationInstruction): R {
|
||||
return visitInstructionWithNext(instruction)
|
||||
}
|
||||
open fun visitVariableDeclarationInstruction(instruction: VariableDeclarationInstruction): R = visitInstructionWithNext(instruction)
|
||||
|
||||
open fun visitUnconditionalJump(instruction: UnconditionalJumpInstruction): R {
|
||||
return visitJump(instruction)
|
||||
}
|
||||
open fun visitUnconditionalJump(instruction: UnconditionalJumpInstruction): R = visitJump(instruction)
|
||||
|
||||
open fun visitConditionalJump(instruction: ConditionalJumpInstruction): R {
|
||||
return visitJump(instruction)
|
||||
}
|
||||
open fun visitConditionalJump(instruction: ConditionalJumpInstruction): R = visitJump(instruction)
|
||||
|
||||
open fun visitReturnValue(instruction: ReturnValueInstruction): R {
|
||||
return visitJump(instruction)
|
||||
}
|
||||
open fun visitReturnValue(instruction: ReturnValueInstruction): R = visitJump(instruction)
|
||||
|
||||
open fun visitReturnNoValue(instruction: ReturnNoValueInstruction): R {
|
||||
return visitJump(instruction)
|
||||
}
|
||||
open fun visitReturnNoValue(instruction: ReturnNoValueInstruction): R = visitJump(instruction)
|
||||
|
||||
open fun visitThrowExceptionInstruction(instruction: ThrowExceptionInstruction): R {
|
||||
return visitJump(instruction)
|
||||
}
|
||||
open fun visitThrowExceptionInstruction(instruction: ThrowExceptionInstruction): R = visitJump(instruction)
|
||||
|
||||
open fun visitNondeterministicJump(instruction: NondeterministicJumpInstruction): R {
|
||||
return visitInstruction(instruction)
|
||||
}
|
||||
open fun visitNondeterministicJump(instruction: NondeterministicJumpInstruction): R = visitInstruction(instruction)
|
||||
|
||||
open fun visitSubroutineExit(instruction: SubroutineExitInstruction): R {
|
||||
return visitInstruction(instruction)
|
||||
}
|
||||
open fun visitSubroutineExit(instruction: SubroutineExitInstruction): R = visitInstruction(instruction)
|
||||
|
||||
open fun visitSubroutineSink(instruction: SubroutineSinkInstruction): R {
|
||||
return visitInstruction(instruction)
|
||||
}
|
||||
open fun visitSubroutineSink(instruction: SubroutineSinkInstruction): R = visitInstruction(instruction)
|
||||
|
||||
open fun visitJump(instruction: AbstractJumpInstruction): R {
|
||||
return visitInstruction(instruction)
|
||||
}
|
||||
open fun visitJump(instruction: AbstractJumpInstruction): R = visitInstruction(instruction)
|
||||
|
||||
open fun visitInstructionWithNext(instruction: InstructionWithNext): R {
|
||||
return visitInstruction(instruction)
|
||||
}
|
||||
open fun visitInstructionWithNext(instruction: InstructionWithNext): R = visitInstruction(instruction)
|
||||
|
||||
open fun visitSubroutineEnter(instruction: SubroutineEnterInstruction): R {
|
||||
return visitInstructionWithNext(instruction)
|
||||
}
|
||||
open fun visitSubroutineEnter(instruction: SubroutineEnterInstruction): R = visitInstructionWithNext(instruction)
|
||||
|
||||
open fun visitWriteValue(instruction: WriteValueInstruction): R {
|
||||
return visitAccessInstruction(instruction)
|
||||
}
|
||||
open fun visitWriteValue(instruction: WriteValueInstruction): R = visitAccessInstruction(instruction)
|
||||
|
||||
open fun visitLoadUnitValue(instruction: LoadUnitValueInstruction): R {
|
||||
return visitInstructionWithNext(instruction)
|
||||
}
|
||||
open fun visitLoadUnitValue(instruction: LoadUnitValueInstruction): R = visitInstructionWithNext(instruction)
|
||||
|
||||
open fun visitOperation(instruction: OperationInstruction): R {
|
||||
return visitInstructionWithNext(instruction)
|
||||
}
|
||||
open fun visitOperation(instruction: OperationInstruction): R = visitInstructionWithNext(instruction)
|
||||
|
||||
open fun visitCallInstruction(instruction: CallInstruction): R {
|
||||
return visitOperation(instruction)
|
||||
}
|
||||
open fun visitCallInstruction(instruction: CallInstruction): R = visitOperation(instruction)
|
||||
|
||||
open fun visitMerge(instruction: MergeInstruction): R {
|
||||
return visitOperation(instruction)
|
||||
}
|
||||
open fun visitMerge(instruction: MergeInstruction): R = visitOperation(instruction)
|
||||
|
||||
open fun visitMarkInstruction(instruction: MarkInstruction): R {
|
||||
return visitInstructionWithNext(instruction)
|
||||
}
|
||||
open fun visitMarkInstruction(instruction: MarkInstruction): R = visitInstructionWithNext(instruction)
|
||||
|
||||
open fun visitMagic(instruction: MagicInstruction): R {
|
||||
return visitOperation(instruction)
|
||||
}
|
||||
open fun visitMagic(instruction: MagicInstruction): R = visitOperation(instruction)
|
||||
}
|
||||
|
||||
+3
-8
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValueFactory
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.*
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
@@ -82,9 +81,7 @@ class ReadValueInstruction private constructor(
|
||||
visitor.visitReadValue(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitReadValue(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitReadValue(this)
|
||||
|
||||
override fun toString(): String {
|
||||
val inVal = if (receiverValues.isEmpty()) "" else "|${receiverValues.keys.joinToString()}"
|
||||
@@ -109,7 +106,7 @@ class WriteValueInstruction(
|
||||
target: AccessTarget,
|
||||
receiverValues: Map<PseudoValue, ReceiverValue>,
|
||||
val lValue: KtElement,
|
||||
val rValue: PseudoValue
|
||||
private val rValue: PseudoValue
|
||||
) : AccessValueInstruction(assignment, blockScope, target, receiverValues) {
|
||||
override val inputValues: List<PseudoValue>
|
||||
get() = (receiverValues.keys as Collection<PseudoValue>) + rValue
|
||||
@@ -118,9 +115,7 @@ class WriteValueInstruction(
|
||||
visitor.visitWriteValue(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitWriteValue(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitWriteValue(this)
|
||||
|
||||
override fun toString(): String {
|
||||
val lhs = (lValue as? KtNamedDeclaration)?.name ?: render(lValue)
|
||||
|
||||
+3
-7
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.cfg.pseudocode.instructions.eval
|
||||
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValueFactory
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.TypePredicate
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionWithNext
|
||||
@@ -48,9 +47,8 @@ abstract class OperationInstruction protected constructor(
|
||||
return this
|
||||
}
|
||||
|
||||
protected fun setResult(factory: PseudoValueFactory?, valueElement: KtElement? = element): OperationInstruction {
|
||||
return setResult(factory?.newValue(valueElement, this))
|
||||
}
|
||||
protected fun setResult(factory: PseudoValueFactory?, valueElement: KtElement? = element): OperationInstruction =
|
||||
setResult(factory?.newValue(valueElement, this))
|
||||
}
|
||||
|
||||
class CallInstruction private constructor(
|
||||
@@ -76,9 +74,7 @@ class CallInstruction private constructor(
|
||||
visitor.visitCallInstruction(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitCallInstruction(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitCallInstruction(this)
|
||||
|
||||
override fun createCopy() =
|
||||
CallInstruction(element, blockScope, resolvedCall, receiverValues, arguments).setResult(resultValue)
|
||||
|
||||
+2
-6
@@ -35,13 +35,9 @@ abstract class AbstractJumpInstruction(
|
||||
|
||||
protected abstract fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction
|
||||
|
||||
fun copy(newLabel: Label): Instruction {
|
||||
return updateCopyInfo(createCopy(newLabel, blockScope))
|
||||
}
|
||||
fun copy(newLabel: Label): Instruction = updateCopyInfo(createCopy(newLabel, blockScope))
|
||||
|
||||
override fun createCopy(): InstructionImpl {
|
||||
return createCopy(targetLabel, blockScope)
|
||||
}
|
||||
override fun createCopy(): InstructionImpl = createCopy(targetLabel, blockScope)
|
||||
|
||||
override val nextInstructions: Collection<Instruction>
|
||||
get() = listOfNotNull(resolvedTarget)
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ class ConditionalJumpInstruction(
|
||||
val onTrue: Boolean,
|
||||
blockScope: BlockScope,
|
||||
targetLabel: Label,
|
||||
val conditionValue: PseudoValue?) : AbstractJumpInstruction(element, targetLabel, blockScope) {
|
||||
private val conditionValue: PseudoValue?) : AbstractJumpInstruction(element, targetLabel, blockScope) {
|
||||
private var _nextOnTrue: Instruction? = null
|
||||
private var _nextOnFalse: Instruction? = null
|
||||
|
||||
|
||||
+6
-13
@@ -30,7 +30,7 @@ class NondeterministicJumpInstruction(
|
||||
element: KtElement,
|
||||
targetLabels: List<Label>,
|
||||
blockScope: BlockScope,
|
||||
val inputValue: PseudoValue?
|
||||
private val inputValue: PseudoValue?
|
||||
) : KtElementInstructionImpl(element, blockScope), JumpInstruction {
|
||||
private var _next: Instruction? = null
|
||||
private val _resolvedTargets: MutableMap<Label, Instruction> = linkedMapOf()
|
||||
@@ -63,9 +63,7 @@ class NondeterministicJumpInstruction(
|
||||
visitor.visitNondeterministicJump(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitNondeterministicJump(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitNondeterministicJump(this)
|
||||
|
||||
override fun toString(): String {
|
||||
val inVal = if (inputValue != null) "|$inputValue" else ""
|
||||
@@ -73,15 +71,10 @@ class NondeterministicJumpInstruction(
|
||||
return "jmp?($labels$inVal)"
|
||||
}
|
||||
|
||||
override fun createCopy(): InstructionImpl {
|
||||
return createCopy(targetLabels)
|
||||
}
|
||||
override fun createCopy(): InstructionImpl = createCopy(targetLabels)
|
||||
|
||||
fun copy(newTargetLabels: MutableList<Label>): Instruction {
|
||||
return updateCopyInfo(createCopy(newTargetLabels))
|
||||
}
|
||||
fun copy(newTargetLabels: MutableList<Label>): Instruction = updateCopyInfo(createCopy(newTargetLabels))
|
||||
|
||||
private fun createCopy(newTargetLabels: List<Label>): InstructionImpl {
|
||||
return NondeterministicJumpInstruction(element, newTargetLabels, blockScope, inputValue)
|
||||
}
|
||||
private fun createCopy(newTargetLabels: List<Label>): InstructionImpl =
|
||||
NondeterministicJumpInstruction(element, newTargetLabels, blockScope, inputValue)
|
||||
}
|
||||
|
||||
+1
-3
@@ -32,9 +32,7 @@ class ReturnNoValueInstruction(
|
||||
visitor.visitReturnNoValue(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitReturnNoValue(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitReturnNoValue(this)
|
||||
|
||||
override fun toString(): String = "ret $targetLabel"
|
||||
|
||||
|
||||
+4
-9
@@ -39,17 +39,12 @@ class ReturnValueInstruction(
|
||||
visitor.visitReturnValue(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitReturnValue(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitReturnValue(this)
|
||||
|
||||
override fun toString(): String {
|
||||
return "ret(*|$returnedValue) $targetLabel"
|
||||
}
|
||||
override fun toString(): String = "ret(*|$returnedValue) $targetLabel"
|
||||
|
||||
override fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction {
|
||||
return ReturnValueInstruction((element as KtExpression), blockScope, newLabel, returnedValue, subroutine)
|
||||
}
|
||||
override fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction =
|
||||
ReturnValueInstruction((element as KtExpression), blockScope, newLabel, returnedValue, subroutine)
|
||||
|
||||
val returnExpressionIfAny: KtReturnExpression? = element as? KtReturnExpression
|
||||
}
|
||||
|
||||
+4
-9
@@ -36,15 +36,10 @@ class ThrowExceptionInstruction(
|
||||
visitor.visitThrowExceptionInstruction(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitThrowExceptionInstruction(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitThrowExceptionInstruction(this)
|
||||
|
||||
override fun toString(): String {
|
||||
return "throw (${element.text}|$thrownValue)"
|
||||
}
|
||||
override fun toString(): String = "throw (${element.text}|$thrownValue)"
|
||||
|
||||
override fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction {
|
||||
return ThrowExceptionInstruction((element as KtThrowExpression), blockScope, newLabel, thrownValue)
|
||||
}
|
||||
override fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction =
|
||||
ThrowExceptionInstruction((element as KtThrowExpression), blockScope, newLabel, thrownValue)
|
||||
}
|
||||
|
||||
+1
-3
@@ -29,9 +29,7 @@ class UnconditionalJumpInstruction(
|
||||
visitor.visitUnconditionalJump(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitUnconditionalJump(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitUnconditionalJump(this)
|
||||
|
||||
override fun toString(): String = "jmp(${targetLabel.name})"
|
||||
|
||||
|
||||
+1
-3
@@ -49,9 +49,7 @@ class LocalFunctionDeclarationInstruction(
|
||||
visitor.visitLocalFunctionDeclarationInstruction(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitLocalFunctionDeclarationInstruction(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitLocalFunctionDeclarationInstruction(this)
|
||||
|
||||
override fun toString(): String = "d(${render(element)})"
|
||||
|
||||
|
||||
+1
-3
@@ -31,9 +31,7 @@ class MarkInstruction(
|
||||
visitor.visitMarkInstruction(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitMarkInstruction(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitMarkInstruction(this)
|
||||
|
||||
override fun createCopy() = MarkInstruction(element, blockScope)
|
||||
|
||||
|
||||
+1
-3
@@ -31,9 +31,7 @@ class SubroutineEnterInstruction(
|
||||
visitor.visitSubroutineEnter(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitSubroutineEnter(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitSubroutineEnter(this)
|
||||
|
||||
override fun toString(): String = "<START>"
|
||||
|
||||
|
||||
+1
-3
@@ -40,9 +40,7 @@ class SubroutineExitInstruction(
|
||||
visitor.visitSubroutineExit(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitSubroutineExit(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitSubroutineExit(this)
|
||||
|
||||
override fun toString(): String = if (isError) "<ERROR>" else "<END>"
|
||||
|
||||
|
||||
+1
-3
@@ -35,9 +35,7 @@ class SubroutineSinkInstruction(
|
||||
visitor.visitSubroutineSink(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitSubroutineSink(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitSubroutineSink(this)
|
||||
|
||||
override fun toString(): String = debugLabel
|
||||
|
||||
|
||||
+1
-3
@@ -40,9 +40,7 @@ class VariableDeclarationInstruction(
|
||||
visitor.visitVariableDeclarationInstruction(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitVariableDeclarationInstruction(this)
|
||||
}
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitVariableDeclarationInstruction(this)
|
||||
|
||||
override fun toString(): String = "v(${render(element)})"
|
||||
|
||||
|
||||
@@ -123,11 +123,10 @@ fun getExpectedTypePredicate(
|
||||
val i = inputValueIndex - argValueOffset
|
||||
if (i < 0 || i >= callArguments.size) continue
|
||||
|
||||
val mapping = candidateCall.getArgumentMapping(callArguments.get(i))
|
||||
if (mapping !is ArgumentMatch) continue
|
||||
val mapping = candidateCall.getArgumentMapping(callArguments[i]) as? ArgumentMatch ?: continue
|
||||
|
||||
val candidateParameter = mapping.valueParameter
|
||||
val resolvedArgument = candidateArgumentMap.get(candidateParameter)
|
||||
val resolvedArgument = candidateArgumentMap[candidateParameter]
|
||||
val expectedType = if (resolvedArgument is VarargValueArgument)
|
||||
candidateParameter.varargElementType
|
||||
else
|
||||
@@ -206,19 +205,15 @@ fun getExpectedTypePredicate(
|
||||
|
||||
VALUE_CONSUMER -> {
|
||||
val element = it.element
|
||||
when {
|
||||
element.getStrictParentOfType<KtWhileExpression>()?.condition == element ->
|
||||
addSubtypesOf(builtIns.booleanType)
|
||||
|
||||
element is KtProperty -> {
|
||||
when (element) {
|
||||
element.getStrictParentOfType<KtWhileExpression>()?.condition -> addSubtypesOf(builtIns.booleanType)
|
||||
is KtProperty -> {
|
||||
val propertyDescriptor = bindingContext[DECLARATION_TO_DESCRIPTOR, element] as? PropertyDescriptor
|
||||
propertyDescriptor?.accessors?.map {
|
||||
addByExplicitReceiver(bindingContext[DELEGATED_PROPERTY_RESOLVED_CALL, it])
|
||||
}
|
||||
}
|
||||
|
||||
element is KtDelegatedSuperTypeEntry ->
|
||||
addSubtypesOf(bindingContext[TYPE, element.typeReference])
|
||||
is KtDelegatedSuperTypeEntry -> addSubtypesOf(bindingContext[TYPE, element.typeReference])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +242,7 @@ val Instruction.sideEffectFree: Boolean
|
||||
|
||||
fun Instruction.calcSideEffectFree(): Boolean {
|
||||
if (this !is InstructionWithValue) return false
|
||||
if (!inputValues.all { it.createdAt?.sideEffectFree ?: false }) return false
|
||||
if (!inputValues.all { it.createdAt?.sideEffectFree == true }) return false
|
||||
|
||||
return when (this) {
|
||||
is ReadValueInstruction -> target.let {
|
||||
|
||||
Reference in New Issue
Block a user