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 declaredVariables = pseudocodeVariablesData.getDeclaredVariables(instruction.owner, false)
|
||||
val variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(
|
||||
instruction, false, trace.bindingContext)
|
||||
instruction, trace.bindingContext)
|
||||
if (variableDescriptor == null
|
||||
|| !declaredVariables.contains(variableDescriptor)
|
||||
|| !ExpressionTypingUtils.isLocal(variableDescriptor.containingDeclaration, variableDescriptor)) {
|
||||
@@ -884,7 +884,7 @@ class ControlFlowInformationProvider private constructor(
|
||||
internal val instruction: Instruction,
|
||||
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(
|
||||
|
||||
@@ -125,7 +125,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
||||
if (instruction !is WriteValueInstruction && instruction !is VariableDeclarationInstruction) {
|
||||
return enterInstructionData
|
||||
}
|
||||
val variable = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false, bindingContext) ?: return enterInstructionData
|
||||
val variable = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, bindingContext) ?: return enterInstructionData
|
||||
val exitInstructionData = enterInstructionData.copy()
|
||||
if (instruction is WriteValueInstruction) {
|
||||
// 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) {
|
||||
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.eval.AccessTarget;
|
||||
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.descriptors.VariableDescriptor;
|
||||
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.KtExpression;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.ResolvedCallUtilKt;
|
||||
@@ -41,6 +38,8 @@ import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.variableDescriptorForDeclaration;
|
||||
|
||||
public class PseudocodeUtil {
|
||||
@NotNull
|
||||
public static Pseudocode generatePseudocode(@NotNull KtDeclaration declaration, @NotNull final BindingContext bindingContext) {
|
||||
@@ -88,23 +87,37 @@ public class PseudocodeUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull Instruction instruction, boolean onlyReference, @NotNull BindingContext bindingContext) {
|
||||
KtElement element = null;
|
||||
if (instruction instanceof ReadValueInstruction) {
|
||||
ReadValueInstruction readValueInstruction = (ReadValueInstruction) instruction;
|
||||
AccessTarget target = readValueInstruction.getTarget();
|
||||
public static VariableDescriptor extractVariableDescriptorFromReference(
|
||||
@NotNull Instruction instruction,
|
||||
@NotNull BindingContext bindingContext
|
||||
) {
|
||||
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) {
|
||||
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) {
|
||||
element = ((WriteValueInstruction) instruction).getLValue();
|
||||
}
|
||||
else if (instruction instanceof VariableDeclarationInstruction) {
|
||||
element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
|
||||
}
|
||||
return BindingContextUtils.extractVariableDescriptorIfAny(bindingContext, element, onlyReference);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 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? {
|
||||
return when (this) {
|
||||
is CallInstruction -> return resolvedCall.resultingDescriptor
|
||||
else -> PseudocodeUtil.extractVariableDescriptorIfAny(this, false, bindingContext)
|
||||
else -> PseudocodeUtil.extractVariableDescriptorIfAny(this, bindingContext)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,20 +68,17 @@ public class BindingContextUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull BindingContext bindingContext, @Nullable KtElement element, boolean onlyReference) {
|
||||
DeclarationDescriptor descriptor = null;
|
||||
if (!onlyReference &&
|
||||
(element instanceof KtVariableDeclaration || element instanceof KtParameter ||
|
||||
element instanceof KtEnumEntry || element instanceof KtObjectDeclaration)) {
|
||||
descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
||||
}
|
||||
else if (element instanceof KtSimpleNameExpression) {
|
||||
descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (KtSimpleNameExpression) element);
|
||||
public static VariableDescriptor extractVariableDescriptorFromReference(
|
||||
@NotNull BindingContext bindingContext,
|
||||
@Nullable KtElement element
|
||||
) {
|
||||
if (element instanceof KtSimpleNameExpression) {
|
||||
return variableDescriptorForDeclaration(bindingContext.get(BindingContext.REFERENCE_TARGET, (KtSimpleNameExpression) element));
|
||||
}
|
||||
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,
|
||||
|
||||
+1
-1
@@ -919,7 +919,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
return info.getType() != null;
|
||||
}
|
||||
|
||||
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
|
||||
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorFromReference(trace.getBindingContext(), expression);
|
||||
|
||||
boolean result = true;
|
||||
KtExpression reportOn = expression != null ? expression : expressionWithParenthesis;
|
||||
|
||||
@@ -70,7 +70,7 @@ class KotlinSourcePositionProvider: SourcePositionProvider() {
|
||||
val expression = codeFragment.getContentElement()
|
||||
if (expression is KtSimpleNameExpression) {
|
||||
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
|
||||
val declarationDescriptor = BindingContextUtils.extractVariableDescriptorIfAny(bindingContext, expression, false)
|
||||
val declarationDescriptor = BindingContextUtils.extractVariableDescriptorFromReference(bindingContext, expression)
|
||||
val sourceElement = declarationDescriptor?.source
|
||||
if (sourceElement is KotlinSourceElement) {
|
||||
val element = sourceElement.getPsi() ?: return null
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ fun KtPostfixExpression.inlineBaseExpressionIfApplicableWithPrompt(editor: Edito
|
||||
|
||||
fun KtExpression.isStableVariable(): Boolean {
|
||||
val context = this.analyze()
|
||||
val descriptor = BindingContextUtils.extractVariableDescriptorIfAny(context, this, false)
|
||||
val descriptor = BindingContextUtils.extractVariableDescriptorFromReference(context, this)
|
||||
return descriptor is VariableDescriptor &&
|
||||
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>>()
|
||||
for (instruction in filterIsInstance<WriteValueInstruction>()) {
|
||||
val expression = instruction.element as? KtExpression
|
||||
val descriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false, bindingContext)
|
||||
val descriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, bindingContext)
|
||||
if (expression != null && descriptor != null) {
|
||||
result.getOrPut(descriptor) { ArrayList() }.add(expression)
|
||||
}
|
||||
@@ -109,7 +109,7 @@ private fun List<Instruction>.getVarDescriptorsAccessedAfterwards(bindingContext
|
||||
traverseFollowingInstructions(instruction, visitedInstructions) {
|
||||
when {
|
||||
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 ->
|
||||
doTraversal(it.body.enterInstruction)
|
||||
|
||||
Reference in New Issue
Block a user