CFG refactoring: extractVariableDescriptorFrom
(cherry picked from commit 95add79)
This commit is contained in:
committed by
Mikhail Glukhikh
parent
25d8af3112
commit
902232c8ad
@@ -541,7 +541,7 @@ class ControlFlowInformationProvider private constructor(
|
|||||||
val ctxt = VariableUseContext(instruction, reportedDiagnosticMap)
|
val ctxt = VariableUseContext(instruction, reportedDiagnosticMap)
|
||||||
val declaredVariables = pseudocodeVariablesData.getDeclaredVariables(instruction.owner, false)
|
val declaredVariables = pseudocodeVariablesData.getDeclaredVariables(instruction.owner, false)
|
||||||
val variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(
|
val variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(
|
||||||
instruction, false, trace.bindingContext)
|
instruction, trace.bindingContext)
|
||||||
if (variableDescriptor == null
|
if (variableDescriptor == null
|
||||||
|| !declaredVariables.contains(variableDescriptor)
|
|| !declaredVariables.contains(variableDescriptor)
|
||||||
|| !ExpressionTypingUtils.isLocal(variableDescriptor.containingDeclaration, variableDescriptor)) {
|
|| !ExpressionTypingUtils.isLocal(variableDescriptor.containingDeclaration, variableDescriptor)) {
|
||||||
@@ -884,7 +884,7 @@ class ControlFlowInformationProvider private constructor(
|
|||||||
internal val instruction: Instruction,
|
internal val instruction: Instruction,
|
||||||
internal val reportedDiagnosticMap: MutableMap<Instruction, DiagnosticFactory<*>>
|
internal val reportedDiagnosticMap: MutableMap<Instruction, DiagnosticFactory<*>>
|
||||||
) {
|
) {
|
||||||
internal val variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, trace.bindingContext)
|
internal val variableDescriptor = PseudocodeUtil.extractVariableDescriptorFromReference(instruction, trace.bindingContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class VariableInitContext(
|
private inner class VariableInitContext(
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
|||||||
if (instruction !is WriteValueInstruction && instruction !is VariableDeclarationInstruction) {
|
if (instruction !is WriteValueInstruction && instruction !is VariableDeclarationInstruction) {
|
||||||
return enterInstructionData
|
return enterInstructionData
|
||||||
}
|
}
|
||||||
val variable = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false, bindingContext) ?: return enterInstructionData
|
val variable = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, bindingContext) ?: return enterInstructionData
|
||||||
val exitInstructionData = enterInstructionData.copy()
|
val exitInstructionData = enterInstructionData.copy()
|
||||||
if (instruction is WriteValueInstruction) {
|
if (instruction is WriteValueInstruction) {
|
||||||
// if writing to already initialized object
|
// if writing to already initialized object
|
||||||
@@ -172,7 +172,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, bindingContext)
|
val variableDescriptor = PseudocodeUtil.extractVariableDescriptorFromReference(instruction, bindingContext)
|
||||||
if (variableDescriptor == null || instruction !is ReadValueInstruction && instruction !is WriteValueInstruction) {
|
if (variableDescriptor == null || instruction !is ReadValueInstruction && instruction !is WriteValueInstruction) {
|
||||||
Edges(enterResult, enterResult)
|
Edges(enterResult, enterResult)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ import org.jetbrains.kotlin.cfg.ControlFlowProcessor;
|
|||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction;
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction;
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.AccessTarget;
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.AccessTarget;
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.AccessValueInstruction;
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.AccessValueInstruction;
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.ReadValueInstruction;
|
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.WriteValueInstruction;
|
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.VariableDeclarationInstruction;
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.VariableDeclarationInstruction;
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||||
@@ -31,7 +29,6 @@ import org.jetbrains.kotlin.psi.KtDeclaration;
|
|||||||
import org.jetbrains.kotlin.psi.KtElement;
|
import org.jetbrains.kotlin.psi.KtElement;
|
||||||
import org.jetbrains.kotlin.psi.KtExpression;
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.ResolvedCallUtilKt;
|
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.ResolvedCallUtilKt;
|
||||||
@@ -41,6 +38,8 @@ import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static org.jetbrains.kotlin.resolve.BindingContextUtils.variableDescriptorForDeclaration;
|
||||||
|
|
||||||
public class PseudocodeUtil {
|
public class PseudocodeUtil {
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Pseudocode generatePseudocode(@NotNull KtDeclaration declaration, @NotNull final BindingContext bindingContext) {
|
public static Pseudocode generatePseudocode(@NotNull KtDeclaration declaration, @NotNull final BindingContext bindingContext) {
|
||||||
@@ -88,23 +87,37 @@ public class PseudocodeUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull Instruction instruction, boolean onlyReference, @NotNull BindingContext bindingContext) {
|
public static VariableDescriptor extractVariableDescriptorFromReference(
|
||||||
KtElement element = null;
|
@NotNull Instruction instruction,
|
||||||
if (instruction instanceof ReadValueInstruction) {
|
@NotNull BindingContext bindingContext
|
||||||
ReadValueInstruction readValueInstruction = (ReadValueInstruction) instruction;
|
) {
|
||||||
AccessTarget target = readValueInstruction.getTarget();
|
if (instruction instanceof AccessValueInstruction) {
|
||||||
|
KtElement element = ((AccessValueInstruction) instruction).getElement();
|
||||||
|
return element instanceof KtDeclaration ? null : extractVariableDescriptorIfAny(instruction, bindingContext);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static VariableDescriptor extractVariableDescriptorIfAny(
|
||||||
|
@NotNull Instruction instruction,
|
||||||
|
@NotNull BindingContext bindingContext
|
||||||
|
) {
|
||||||
|
if (instruction instanceof VariableDeclarationInstruction) {
|
||||||
|
KtDeclaration declaration = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
|
||||||
|
return variableDescriptorForDeclaration(bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration));
|
||||||
|
}
|
||||||
|
else if (instruction instanceof AccessValueInstruction) {
|
||||||
|
AccessTarget target = ((AccessValueInstruction) instruction).getTarget();
|
||||||
if (target instanceof AccessTarget.Declaration) {
|
if (target instanceof AccessTarget.Declaration) {
|
||||||
return ((AccessTarget.Declaration) target).getDescriptor();
|
return ((AccessTarget.Declaration) target).getDescriptor();
|
||||||
}
|
}
|
||||||
element = readValueInstruction.getElement();
|
else if (target instanceof AccessTarget.Call) {
|
||||||
|
return variableDescriptorForDeclaration(((AccessTarget.Call) target).getResolvedCall().getResultingDescriptor());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (instruction instanceof WriteValueInstruction) {
|
return null;
|
||||||
element = ((WriteValueInstruction) instruction).getLValue();
|
|
||||||
}
|
|
||||||
else if (instruction instanceof VariableDeclarationInstruction) {
|
|
||||||
element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
|
|
||||||
}
|
|
||||||
return BindingContextUtils.extractVariableDescriptorIfAny(bindingContext, element, onlyReference);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When deal with constructed object (not this) treat it like it's fully initialized
|
// When deal with constructed object (not this) treat it like it's fully initialized
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ fun getExpectedTypePredicate(
|
|||||||
fun Instruction.getPrimaryDeclarationDescriptorIfAny(bindingContext: BindingContext): DeclarationDescriptor? {
|
fun Instruction.getPrimaryDeclarationDescriptorIfAny(bindingContext: BindingContext): DeclarationDescriptor? {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is CallInstruction -> return resolvedCall.resultingDescriptor
|
is CallInstruction -> return resolvedCall.resultingDescriptor
|
||||||
else -> PseudocodeUtil.extractVariableDescriptorIfAny(this, false, bindingContext)
|
else -> PseudocodeUtil.extractVariableDescriptorIfAny(this, bindingContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,20 +68,17 @@ public class BindingContextUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull BindingContext bindingContext, @Nullable KtElement element, boolean onlyReference) {
|
public static VariableDescriptor extractVariableDescriptorFromReference(
|
||||||
DeclarationDescriptor descriptor = null;
|
@NotNull BindingContext bindingContext,
|
||||||
if (!onlyReference &&
|
@Nullable KtElement element
|
||||||
(element instanceof KtVariableDeclaration || element instanceof KtParameter ||
|
) {
|
||||||
element instanceof KtEnumEntry || element instanceof KtObjectDeclaration)) {
|
if (element instanceof KtSimpleNameExpression) {
|
||||||
descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
return variableDescriptorForDeclaration(bindingContext.get(BindingContext.REFERENCE_TARGET, (KtSimpleNameExpression) element));
|
||||||
}
|
|
||||||
else if (element instanceof KtSimpleNameExpression) {
|
|
||||||
descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (KtSimpleNameExpression) element);
|
|
||||||
}
|
}
|
||||||
else if (element instanceof KtQualifiedExpression) {
|
else if (element instanceof KtQualifiedExpression) {
|
||||||
descriptor = extractVariableDescriptorIfAny(bindingContext, ((KtQualifiedExpression) element).getSelectorExpression(), onlyReference);
|
return extractVariableDescriptorFromReference(bindingContext, ((KtQualifiedExpression) element).getSelectorExpression());
|
||||||
}
|
}
|
||||||
return variableDescriptorForDeclaration(descriptor);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void recordFunctionDeclarationToDescriptor(@NotNull BindingTrace trace,
|
public static void recordFunctionDeclarationToDescriptor(@NotNull BindingTrace trace,
|
||||||
|
|||||||
+1
-1
@@ -919,7 +919,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
return info.getType() != null;
|
return info.getType() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
|
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorFromReference(trace.getBindingContext(), expression);
|
||||||
|
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
KtExpression reportOn = expression != null ? expression : expressionWithParenthesis;
|
KtExpression reportOn = expression != null ? expression : expressionWithParenthesis;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class KotlinSourcePositionProvider: SourcePositionProvider() {
|
|||||||
val expression = codeFragment.getContentElement()
|
val expression = codeFragment.getContentElement()
|
||||||
if (expression is KtSimpleNameExpression) {
|
if (expression is KtSimpleNameExpression) {
|
||||||
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
|
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
|
||||||
val declarationDescriptor = BindingContextUtils.extractVariableDescriptorIfAny(bindingContext, expression, false)
|
val declarationDescriptor = BindingContextUtils.extractVariableDescriptorFromReference(bindingContext, expression)
|
||||||
val sourceElement = declarationDescriptor?.source
|
val sourceElement = declarationDescriptor?.source
|
||||||
if (sourceElement is KotlinSourceElement) {
|
if (sourceElement is KotlinSourceElement) {
|
||||||
val element = sourceElement.getPsi() ?: return null
|
val element = sourceElement.getPsi() ?: return null
|
||||||
|
|||||||
+1
-1
@@ -133,7 +133,7 @@ fun KtPostfixExpression.inlineBaseExpressionIfApplicableWithPrompt(editor: Edito
|
|||||||
|
|
||||||
fun KtExpression.isStableVariable(): Boolean {
|
fun KtExpression.isStableVariable(): Boolean {
|
||||||
val context = this.analyze()
|
val context = this.analyze()
|
||||||
val descriptor = BindingContextUtils.extractVariableDescriptorIfAny(context, this, false)
|
val descriptor = BindingContextUtils.extractVariableDescriptorFromReference(context, this)
|
||||||
return descriptor is VariableDescriptor &&
|
return descriptor is VariableDescriptor &&
|
||||||
DataFlowValueFactory.isStableValue(descriptor, DescriptorUtils.getContainingModule(descriptor))
|
DataFlowValueFactory.isStableValue(descriptor, DescriptorUtils.getContainingModule(descriptor))
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -92,7 +92,7 @@ private fun List<Instruction>.getModifiedVarDescriptors(bindingContext: BindingC
|
|||||||
val result = HashMap<VariableDescriptor, MutableList<KtExpression>>()
|
val result = HashMap<VariableDescriptor, MutableList<KtExpression>>()
|
||||||
for (instruction in filterIsInstance<WriteValueInstruction>()) {
|
for (instruction in filterIsInstance<WriteValueInstruction>()) {
|
||||||
val expression = instruction.element as? KtExpression
|
val expression = instruction.element as? KtExpression
|
||||||
val descriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false, bindingContext)
|
val descriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, bindingContext)
|
||||||
if (expression != null && descriptor != null) {
|
if (expression != null && descriptor != null) {
|
||||||
result.getOrPut(descriptor) { ArrayList() }.add(expression)
|
result.getOrPut(descriptor) { ArrayList() }.add(expression)
|
||||||
}
|
}
|
||||||
@@ -109,7 +109,7 @@ private fun List<Instruction>.getVarDescriptorsAccessedAfterwards(bindingContext
|
|||||||
traverseFollowingInstructions(instruction, visitedInstructions) {
|
traverseFollowingInstructions(instruction, visitedInstructions) {
|
||||||
when {
|
when {
|
||||||
it is AccessValueInstruction && it !in this ->
|
it is AccessValueInstruction && it !in this ->
|
||||||
PseudocodeUtil.extractVariableDescriptorIfAny(it, false, bindingContext)?.let { accessedAfterwards.add(it) }
|
PseudocodeUtil.extractVariableDescriptorIfAny(it, bindingContext)?.let { accessedAfterwards.add(it) }
|
||||||
|
|
||||||
it is LocalFunctionDeclarationInstruction ->
|
it is LocalFunctionDeclarationInstruction ->
|
||||||
doTraversal(it.body.enterInstruction)
|
doTraversal(it.body.enterInstruction)
|
||||||
|
|||||||
Reference in New Issue
Block a user