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