diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/analysis/AnalyzerUtil.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/analysis/AnalyzerUtil.kt index c5cc0673799..f20e6217b80 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/analysis/AnalyzerUtil.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/analysis/AnalyzerUtil.kt @@ -17,11 +17,16 @@ package org.jetbrains.kotlin.idea.analysis import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.frontendService +import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.BindingTraceContext +import org.jetbrains.kotlin.resolve.DelegatingBindingTrace +import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore +import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.scopes.LexicalScope @@ -68,3 +73,31 @@ import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor ): KotlinType? { return computeTypeInfoInContext(scope, contextExpression, trace, dataFlowInfo, expectedType).type } + +@JvmOverloads fun KtExpression.analyzeAsReplacement( + expressionToBeReplaced: KtExpression, + bindingContext: BindingContext, + scope: LexicalScope, + trace: BindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for analyzeAsReplacement()"), + contextDependency: ContextDependency = ContextDependency.INDEPENDENT +): BindingContext { + return analyzeInContext(scope, + expressionToBeReplaced, + dataFlowInfo = bindingContext.getDataFlowInfoBefore(expressionToBeReplaced), + expectedType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, expressionToBeReplaced] ?: TypeUtils.NO_EXPECTED_TYPE, + isStatement = expressionToBeReplaced.isUsedAsStatement(bindingContext), + trace = trace, + contextDependency = contextDependency) +} + +@JvmOverloads fun KtExpression.analyzeAsReplacement( + expressionToBeReplaced: KtExpression, + bindingContext: BindingContext, + resolutionFacade: ResolutionFacade = expressionToBeReplaced.getResolutionFacade(), + trace: BindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for analyzeAsReplacement()"), + contextDependency: ContextDependency = ContextDependency.INDEPENDENT +): BindingContext { + val scope = expressionToBeReplaced.getResolutionScope(bindingContext, resolutionFacade) + return analyzeAsReplacement(expressionToBeReplaced, bindingContext, scope, trace, contextDependency) +} + diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/OptimizedImportsBuilder.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/OptimizedImportsBuilder.kt index a9c97a69cef..ea159d5b709 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/OptimizedImportsBuilder.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/OptimizedImportsBuilder.kt @@ -20,7 +20,7 @@ import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.idea.analysis.analyzeInContext +import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.resolve.frontendService @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.renderer.render import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.BindingTraceContext import org.jetbrains.kotlin.resolve.ImportPath import org.jetbrains.kotlin.resolve.lazy.FileScopeProvider import org.jetbrains.kotlin.resolve.scopes.ImportingScope @@ -188,7 +189,7 @@ class OptimizedImportsBuilder( val bindingContext = element.analyze() val expressionToAnalyze = getExpressionToAnalyze(element) ?: continue val newScope = element.getResolutionScope(bindingContext, file.getResolutionFacade()).replaceImportingScopes(newFileScope) - val newBindingContext = expressionToAnalyze.analyzeInContext(newScope, expressionToAnalyze) + val newBindingContext = expressionToAnalyze.analyzeAsReplacement(expressionToAnalyze, bindingContext, newScope, trace = BindingTraceContext()) testLog?.append("Additional checking of reference $ref\n") diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/ShortenReferences.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/ShortenReferences.kt index b45c5092237..acc90ac4571 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/ShortenReferences.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/ShortenReferences.kt @@ -22,7 +22,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.impl.source.PostprocessReformattingAspect import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.idea.analysis.analyzeInContext +import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.core.ShortenReferences.Options import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport @@ -432,9 +432,8 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT val varAsFunResolvedCall = callee.getResolvedCall(bindingContext) as? VariableAsFunctionResolvedCall if (targets.isEmpty()) return Skip - val scope = element.getResolutionScope(bindingContext, resolutionFacade) val selectorCopy = selector.copy() as KtReferenceExpression - val newContext = selectorCopy.analyzeInContext(scope, selector) + val newContext = selectorCopy.analyzeAsReplacement(element, bindingContext, resolutionFacade) val newCallee = selectorCopy.getCalleeExpressionIfAny() as KtReferenceExpression val targetsWhenShort = newCallee.targets(newContext) val varAsFunResolvedCallWhenShort = newCallee.getResolvedCall(newContext) as? VariableAsFunctionResolvedCall @@ -505,8 +504,7 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT override fun analyzeQualifiedElement(element: KtThisExpression, bindingContext: BindingContext): AnalyzeQualifiedElementResult { val targetBefore = element.instanceReference.targets(bindingContext).singleOrNull() ?: return Skip - val scope = element.getResolutionScope(bindingContext, resolutionFacade) - val newContext = simpleThis.analyzeInContext(scope, element) + val newContext = simpleThis.analyzeAsReplacement(element, bindingContext, resolutionFacade) val targetAfter = simpleThis.instanceReference.targets(newContext).singleOrNull() return if (targetBefore == targetAfter) ShortenNow else Skip } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/AddForLoopIndicesIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/AddForLoopIndicesIntention.kt index 945d17ba8ea..b7b35d1de48 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/AddForLoopIndicesIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/AddForLoopIndicesIntention.kt @@ -21,11 +21,9 @@ import com.intellij.codeInsight.template.TemplateBuilderImpl import com.intellij.openapi.editor.Editor import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiDocumentManager -import org.jetbrains.kotlin.idea.analysis.analyzeInContext +import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.core.replaced -import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset @@ -46,10 +44,9 @@ class AddForLoopIndicesIntention : SelfTargetingRangeIntention( val resolvedCall = loopRange.getResolvedCall(bindingContext) if (resolvedCall?.resultingDescriptor?.fqNameUnsafe?.asString() in WITH_INDEX_FQ_NAMES) return null // already withIndex() call - val resolutionScope = element.getResolutionScope(bindingContext, element.getResolutionFacade()) val potentialExpression = createWithIndexExpression(loopRange) - val newBindingContext = potentialExpression.analyzeInContext(resolutionScope, loopRange) + val newBindingContext = potentialExpression.analyzeAsReplacement(loopRange, bindingContext) val newResolvedCall = potentialExpression.getResolvedCall(newBindingContext) ?: return null if (newResolvedCall.resultingDescriptor.fqNameUnsafe.asString() !in WITH_INDEX_FQ_NAMES) return null diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitSuperQualifierIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitSuperQualifierIntention.kt index 813e3ddae77..d5fbe1f6d37 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitSuperQualifierIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitSuperQualifierIntention.kt @@ -20,11 +20,9 @@ import com.intellij.codeInspection.CleanupLocalInspectionTool import com.intellij.codeInspection.ProblemHighlightType import com.intellij.openapi.editor.Editor import com.intellij.openapi.util.TextRange -import org.jetbrains.kotlin.idea.analysis.analyzeInContext +import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection -import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.KtQualifiedExpression import org.jetbrains.kotlin.psi.KtSuperExpression @@ -32,13 +30,9 @@ import org.jetbrains.kotlin.psi.createExpressionByPattern import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForReceiver import org.jetbrains.kotlin.psi.psiUtil.startOffset -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoAfter -import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.ErrorUtils -import org.jetbrains.kotlin.types.TypeUtils class RemoveExplicitSuperQualifierInspection : IntentionBasedInspection(RemoveExplicitSuperQualifierIntention::class), CleanupLocalInspectionTool { override val problemHighlightType: ProblemHighlightType @@ -54,12 +48,9 @@ class RemoveExplicitSuperQualifierIntention : SelfTargetingRangeIntention(ReplaceWithOperatorAssignmentIntention::class) @@ -50,11 +47,7 @@ class ReplaceWithOperatorAssignmentIntention : SelfTargetingOffsetIndependentInt // now check that the resulting operator assignment will be resolved val opAssign = buildOperatorAssignment(element) opAssign.getContainingKtFile().doNotAnalyze = null //TODO: strange hack - val resolutionScope = element.getResolutionScope(bindingContext, element.getResolutionFacade()) - val newBindingContext = opAssign.analyzeInContext(resolutionScope, - contextExpression = element, - dataFlowInfo = bindingContext.getDataFlowInfoBefore(element), - isStatement = true) + val newBindingContext = opAssign.analyzeAsReplacement(element, bindingContext) return newBindingContext.diagnostics.forElement(opAssign.operationReference).isEmpty() } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/matchAndConvert.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/matchAndConvert.kt index bdc97b12389..8a5287e6067 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/matchAndConvert.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/matchAndConvert.kt @@ -21,21 +21,17 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode import org.jetbrains.kotlin.cfg.pseudocode.PseudocodeUtil import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode -import org.jetbrains.kotlin.idea.analysis.analyzeInContext +import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.intentions.loopToCallChain.result.* import org.jetbrains.kotlin.idea.intentions.loopToCallChain.sequence.* import org.jetbrains.kotlin.idea.project.builtIns import org.jetbrains.kotlin.idea.util.CommentSaver -import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils.isSubtypeOfClass -import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoAfter -import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore import org.jetbrains.kotlin.resolve.calls.smartcasts.ExplicitSmartCasts import org.jetbrains.kotlin.resolve.calls.smartcasts.ImplicitSmartCasts import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode @@ -270,9 +266,7 @@ private fun checkSmartCastsPreserved(loop: KtForExpression, matchResult: MatchRe val callChain = matchResult.generateCallChain(loop) - val resolutionScope = loop.getResolutionScope(bindingContext, loop.getResolutionFacade()) - val dataFlowInfo = bindingContext.getDataFlowInfoBefore(loop) - val newBindingContext = callChain.analyzeInContext(resolutionScope, loop, dataFlowInfo = dataFlowInfo) + val newBindingContext = callChain.analyzeAsReplacement(loop, bindingContext) var preservedSmartCastCount = 0 callChain.forEachDescendantOfType { expression -> diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/utils.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/utils.kt index bb25826a3cd..288059216e3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/utils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/utils.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.Severity +import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement import org.jetbrains.kotlin.idea.analysis.analyzeInContext import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade @@ -275,11 +276,7 @@ fun tryChangeAndCheckErrors( performChange(expressionCopy) - val resolutionScope = block.getResolutionScope(bindingContext, block.getResolutionFacade()) - val newBindingContext = blockCopy.analyzeInContext(scope = resolutionScope, - contextExpression = block, - dataFlowInfo = bindingContext.getDataFlowInfoBefore(block), - trace = DelegatingBindingTrace(bindingContext, "Temporary trace")) + val newBindingContext = blockCopy.analyzeAsReplacement(block, bindingContext) return newBindingContext.diagnostics.none { it.severity == Severity.ERROR && !scopeToExcludeCopy.isAncestor(it.psiElement)