Introduced KtExpression.analyzeAsReplacement() utility
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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<KtForExpression>(
|
||||
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
|
||||
|
||||
|
||||
+2
-11
@@ -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<KtSuperExpression>(RemoveExplicitSuperQualifierIntention::class), CleanupLocalInspectionTool {
|
||||
override val problemHighlightType: ProblemHighlightType
|
||||
@@ -54,12 +48,9 @@ class RemoveExplicitSuperQualifierIntention : SelfTargetingRangeIntention<KtSupe
|
||||
|
||||
val bindingContext = selector.analyze(BodyResolveMode.PARTIAL)
|
||||
if (selector.getResolvedCall(bindingContext) == null) return null
|
||||
val resolutionScope = qualifiedExpression.getResolutionScope(bindingContext, selector.getResolutionFacade())
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfoBefore(element)
|
||||
val expectedType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, qualifiedExpression] ?: TypeUtils.NO_EXPECTED_TYPE
|
||||
|
||||
val newQualifiedExpression = KtPsiFactory(element).createExpressionByPattern("$0.$1", toNonQualified(element), selector) as KtQualifiedExpression
|
||||
val newBindingContext = newQualifiedExpression.analyzeInContext(resolutionScope, qualifiedExpression, dataFlowInfo = dataFlowInfo, expectedType = expectedType, isStatement = true)
|
||||
val newBindingContext = newQualifiedExpression.analyzeAsReplacement(qualifiedExpression, bindingContext)
|
||||
val newResolvedCall = newQualifiedExpression.selectorExpression.getResolvedCall(newBindingContext) ?: return null
|
||||
if (ErrorUtils.isError(newResolvedCall.resultingDescriptor)) return null
|
||||
|
||||
|
||||
+2
-9
@@ -20,11 +20,9 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
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.idea.util.psi.patternMatching.matches
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
@@ -32,7 +30,6 @@ import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.psi.doNotAnalyze
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
class ReplaceWithOperatorAssignmentInspection : IntentionBasedInspection<KtBinaryExpression>(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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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<KtExpression> { expression ->
|
||||
|
||||
@@ -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 <TExpression : KtExpression> 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)
|
||||
|
||||
Reference in New Issue
Block a user