diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt index 97aff80e15c..8005943432a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt @@ -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> ) { - internal val variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, trace.bindingContext) + internal val variableDescriptor = PseudocodeUtil.extractVariableDescriptorFromReference(instruction, trace.bindingContext) } private inner class VariableInitContext( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariablesData.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariablesData.kt index c63b97469c0..75959fc66f7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariablesData.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariablesData.kt @@ -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) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeUtil.java index 551a0a3f910..e9fc6f86124 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeUtil.java @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/pseudocodeUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/pseudocodeUtils.kt index 857a94ff84b..1f3e38f5c1f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/pseudocodeUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/pseudocodeUtils.kt @@ -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) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContextUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContextUtils.java index f6d811b2093..6f32873f870 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContextUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContextUtils.java @@ -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, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 8b7e5ab79ca..854d0551646 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -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; diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinSourcePositionProvider.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinSourcePositionProvider.kt index 3dd4cab21f7..46d71d1738d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinSourcePositionProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinSourcePositionProvider.kt @@ -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 diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt index d7f246df27c..b6eb143da8d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt @@ -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)) } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt index d8ef049099f..59714a55fb6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt @@ -92,7 +92,7 @@ private fun List.getModifiedVarDescriptors(bindingContext: BindingC val result = HashMap>() for (instruction in filterIsInstance()) { 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.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)