Extract some cfg utilities into separate files
These utilties are used not only within CFG, but from the frontend and idea as well. Therefore upon extraction of CFG into another module, these two new files will remain in 'frontend'.
This commit is contained in:
committed by
Alexander Udalov
parent
a9b9cced15
commit
5ad0033d42
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.codegen.coroutines
|
|||||||
import com.intellij.util.ArrayUtil
|
import com.intellij.util.ArrayUtil
|
||||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
||||||
import org.jetbrains.kotlin.cfg.index
|
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
|
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
@@ -35,6 +34,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
import org.jetbrains.kotlin.resolve.indexOrMinusOne
|
||||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||||
@@ -263,7 +263,7 @@ class CoroutineCodegenForLambda private constructor(
|
|||||||
|
|
||||||
private fun ParameterDescriptor.isUnused(): Boolean =
|
private fun ParameterDescriptor.isUnused(): Boolean =
|
||||||
originalSuspendFunctionDescriptor is AnonymousFunctionDescriptor &&
|
originalSuspendFunctionDescriptor is AnonymousFunctionDescriptor &&
|
||||||
bindingContext[BindingContext.SUSPEND_LAMBDA_PARAMETER_USED, originalSuspendFunctionDescriptor to index()] != true
|
bindingContext[BindingContext.SUSPEND_LAMBDA_PARAMETER_USED, originalSuspendFunctionDescriptor to indexOrMinusOne()] != true
|
||||||
|
|
||||||
private val generateErasedCreate: Boolean = allFunctionParameters().size <= 1
|
private val generateErasedCreate: Boolean = allFunctionParameters().size <= 1
|
||||||
|
|
||||||
|
|||||||
@@ -34,18 +34,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||||
|
|
||||||
interface LeakingThisDescriptor {
|
|
||||||
val classOrObject: KtClassOrObject
|
|
||||||
|
|
||||||
data class PropertyIsNull(val property: PropertyDescriptor, override val classOrObject: KtClassOrObject) : LeakingThisDescriptor
|
|
||||||
|
|
||||||
data class NonFinalClass(val klass: ClassDescriptor, override val classOrObject: KtClassOrObject) : LeakingThisDescriptor
|
|
||||||
|
|
||||||
data class NonFinalProperty(val property: PropertyDescriptor, override val classOrObject: KtClassOrObject) : LeakingThisDescriptor
|
|
||||||
|
|
||||||
data class NonFinalFunction(val function: FunctionDescriptor, override val classOrObject: KtClassOrObject) : LeakingThisDescriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConstructorConsistencyChecker private constructor(
|
class ConstructorConsistencyChecker private constructor(
|
||||||
private val classOrObject: KtClassOrObject,
|
private val classOrObject: KtClassOrObject,
|
||||||
private val classDescriptor: ClassDescriptor,
|
private val classDescriptor: ClassDescriptor,
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext.*
|
import org.jetbrains.kotlin.resolve.BindingContext.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
@@ -56,6 +55,7 @@ import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
|
|||||||
import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor
|
import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
import org.jetbrains.kotlin.resolve.indexOrMinusOne
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils.*
|
import org.jetbrains.kotlin.types.TypeUtils.*
|
||||||
@@ -437,31 +437,31 @@ class ControlFlowInformationProvider private constructor(
|
|||||||
val containingDeclarationDescriptor = variableDescriptor.containingDeclaration
|
val containingDeclarationDescriptor = variableDescriptor.containingDeclaration
|
||||||
// Do not consider top-level properties
|
// Do not consider top-level properties
|
||||||
if (containingDeclarationDescriptor is PackageFragmentDescriptor) return false
|
if (containingDeclarationDescriptor is PackageFragmentDescriptor) return false
|
||||||
var parentDeclaration = getElementParentDeclaration(writeValueInstruction.element)
|
var parentDeclaration = writeValueInstruction.element.getElementParentDeclaration()
|
||||||
|
|
||||||
loop@ while (true) {
|
loop@ while (true) {
|
||||||
val context = trace.bindingContext
|
val context = trace.bindingContext
|
||||||
val parentDescriptor = getDeclarationDescriptorIncludingConstructors(context, parentDeclaration)
|
val parentDescriptor = parentDeclaration.getDeclarationDescriptorIncludingConstructors(context)
|
||||||
if (parentDescriptor == containingDeclarationDescriptor) {
|
if (parentDescriptor == containingDeclarationDescriptor) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
when (parentDeclaration) {
|
when (parentDeclaration) {
|
||||||
is KtObjectDeclaration, is KtClassInitializer -> {
|
is KtObjectDeclaration, is KtClassInitializer -> {
|
||||||
// anonymous objects / initializers count here the same as its owner
|
// anonymous objects / initializers count here the same as its owner
|
||||||
parentDeclaration = getElementParentDeclaration(parentDeclaration)
|
parentDeclaration = parentDeclaration.getElementParentDeclaration()
|
||||||
}
|
}
|
||||||
is KtDeclarationWithBody -> {
|
is KtDeclarationWithBody -> {
|
||||||
// If it is captured write in lambda that is called in-place, then skip it (treat as parent)
|
// If it is captured write in lambda that is called in-place, then skip it (treat as parent)
|
||||||
val maybeEnclosingLambdaExpr = parentDeclaration.parent
|
val maybeEnclosingLambdaExpr = parentDeclaration.parent
|
||||||
if (maybeEnclosingLambdaExpr is KtLambdaExpression && trace[LAMBDA_INVOCATIONS, maybeEnclosingLambdaExpr] != null) {
|
if (maybeEnclosingLambdaExpr is KtLambdaExpression && trace[LAMBDA_INVOCATIONS, maybeEnclosingLambdaExpr] != null) {
|
||||||
parentDeclaration = getElementParentDeclaration(parentDeclaration)
|
parentDeclaration = parentDeclaration.getElementParentDeclaration()
|
||||||
continue@loop
|
continue@loop
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentDeclaration is KtFunction && parentDeclaration.isLocal) return true
|
if (parentDeclaration is KtFunction && parentDeclaration.isLocal) return true
|
||||||
// miss non-local function or accessor just once
|
// miss non-local function or accessor just once
|
||||||
parentDeclaration = getElementParentDeclaration(parentDeclaration)
|
parentDeclaration = parentDeclaration.getElementParentDeclaration()
|
||||||
return getDeclarationDescriptorIncludingConstructors(context, parentDeclaration) != containingDeclarationDescriptor
|
return parentDeclaration.getDeclarationDescriptorIncludingConstructors(context) != containingDeclarationDescriptor
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
return true
|
return true
|
||||||
@@ -851,7 +851,7 @@ class ControlFlowInformationProvider private constructor(
|
|||||||
if (descriptor is ParameterDescriptor) {
|
if (descriptor is ParameterDescriptor) {
|
||||||
val containing = descriptor.containingDeclaration
|
val containing = descriptor.containingDeclaration
|
||||||
if (containing is AnonymousFunctionDescriptor && containing.isSuspend) {
|
if (containing is AnonymousFunctionDescriptor && containing.isSuspend) {
|
||||||
trace.record(SUSPEND_LAMBDA_PARAMETER_USED, containing to descriptor.index())
|
trace.record(SUSPEND_LAMBDA_PARAMETER_USED, containing to descriptor.indexOrMinusOne())
|
||||||
}
|
}
|
||||||
} else if (descriptor is LocalVariableDescriptor) {
|
} else if (descriptor is LocalVariableDescriptor) {
|
||||||
val containing = descriptor.containingDeclaration
|
val containing = descriptor.containingDeclaration
|
||||||
@@ -1222,26 +1222,6 @@ class ControlFlowInformationProvider private constructor(
|
|||||||
) : VariableContext(instruction, map)
|
) : VariableContext(instruction, map)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
// Should return KtDeclarationWithBody, KtClassOrObject, or KtClassInitializer
|
|
||||||
fun getElementParentDeclaration(element: KtElement) =
|
|
||||||
getParentOfType(element, KtDeclarationWithBody::class.java, KtClassOrObject::class.java, KtClassInitializer::class.java)
|
|
||||||
|
|
||||||
fun getDeclarationDescriptorIncludingConstructors(context: BindingContext, declaration: KtDeclaration?): DeclarationDescriptor? {
|
|
||||||
val descriptor = context.get(
|
|
||||||
DECLARATION_TO_DESCRIPTOR,
|
|
||||||
(declaration as? KtClassInitializer)?.containingDeclaration ?: declaration
|
|
||||||
)
|
|
||||||
return if (descriptor is ClassDescriptor && declaration is KtClassInitializer) {
|
|
||||||
// For a class primary constructor, we cannot directly get ConstructorDescriptor by KtClassInitializer,
|
|
||||||
// so we have to do additional conversion: KtClassInitializer -> KtClassOrObject -> ClassDescriptor -> ConstructorDescriptor
|
|
||||||
descriptor.unsubstitutedPrimaryConstructor
|
|
||||||
?: (descriptor as? ClassDescriptorWithResolutionScopes)?.scopeForInitializerResolution?.ownerDescriptor
|
|
||||||
} else {
|
|
||||||
descriptor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isUsedAsResultOfLambda(usages: List<Instruction>): Boolean {
|
private fun isUsedAsResultOfLambda(usages: List<Instruction>): Boolean {
|
||||||
for (usage in usages) {
|
for (usage in usages) {
|
||||||
if (usage is ReturnValueInstruction) {
|
if (usage is ReturnValueInstruction) {
|
||||||
@@ -1318,10 +1298,3 @@ class ControlFlowInformationProvider private constructor(
|
|||||||
|| diagnosticFactory === UNUSED_CHANGED_VALUE
|
|| diagnosticFactory === UNUSED_CHANGED_VALUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ParameterDescriptor.index(): Int =
|
|
||||||
when (this) {
|
|
||||||
is ReceiverParameterDescriptor -> -1
|
|
||||||
is ValueParameterDescriptor -> index
|
|
||||||
else -> error("expected either receiver or value parameter, but got: $this")
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.cfg
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
|
||||||
|
interface LeakingThisDescriptor {
|
||||||
|
val classOrObject: KtClassOrObject
|
||||||
|
|
||||||
|
data class PropertyIsNull(val property: PropertyDescriptor, override val classOrObject: KtClassOrObject) : LeakingThisDescriptor
|
||||||
|
|
||||||
|
data class NonFinalClass(val klass: ClassDescriptor, override val classOrObject: KtClassOrObject) : LeakingThisDescriptor
|
||||||
|
|
||||||
|
data class NonFinalProperty(val property: PropertyDescriptor, override val classOrObject: KtClassOrObject) : LeakingThisDescriptor
|
||||||
|
|
||||||
|
data class NonFinalFunction(val function: FunctionDescriptor, override val classOrObject: KtClassOrObject) : LeakingThisDescriptor
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.cfg
|
||||||
|
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil.getParentOfType
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR
|
||||||
|
|
||||||
|
val KtElement.containingDeclarationForPseudocode: KtDeclaration?
|
||||||
|
get() = getParentOfType(this, KtDeclarationWithBody::class.java, KtClassOrObject::class.java, KtScript::class.java)
|
||||||
|
?: getNonStrictParentOfType<KtProperty>()
|
||||||
|
|
||||||
|
// Should return KtDeclarationWithBody, KtClassOrObject, or KtClassInitializer
|
||||||
|
fun KtElement.getElementParentDeclaration(): KtDeclaration? =
|
||||||
|
getParentOfType(this, KtDeclarationWithBody::class.java, KtClassOrObject::class.java, KtClassInitializer::class.java)
|
||||||
|
|
||||||
|
fun KtDeclaration?.getDeclarationDescriptorIncludingConstructors(context: BindingContext): DeclarationDescriptor? {
|
||||||
|
val descriptor = context.get(DECLARATION_TO_DESCRIPTOR, (this as? KtClassInitializer)?.containingDeclaration ?: this)
|
||||||
|
return if (descriptor is ClassDescriptor && this is KtClassInitializer) {
|
||||||
|
// For a class primary constructor, we cannot directly get ConstructorDescriptor by KtClassInitializer,
|
||||||
|
// so we have to do additional conversion: KtClassInitializer -> KtClassOrObject -> ClassDescriptor -> ConstructorDescriptor
|
||||||
|
descriptor.unsubstitutedPrimaryConstructor
|
||||||
|
?: (descriptor as? ClassDescriptorWithResolutionScopes)?.scopeForInitializerResolution?.ownerDescriptor
|
||||||
|
} else {
|
||||||
|
descriptor
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,9 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.cfg.pseudocode
|
package org.jetbrains.kotlin.cfg.pseudocode
|
||||||
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.cfg.Label
|
import org.jetbrains.kotlin.cfg.Label
|
||||||
|
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.MagicKind.*
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.MagicKind.*
|
||||||
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.ThrowExceptionInst
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
@@ -279,10 +278,6 @@ fun Pseudocode.getElementValuesRecursively(element: KtElement): List<PseudoValue
|
|||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
val KtElement.containingDeclarationForPseudocode: KtDeclaration?
|
|
||||||
get() = PsiTreeUtil.getParentOfType(this, KtDeclarationWithBody::class.java, KtClassOrObject::class.java, KtScript::class.java)
|
|
||||||
?: getNonStrictParentOfType<KtProperty>()
|
|
||||||
|
|
||||||
fun KtDeclaration.getContainingPseudocode(context: BindingContext): Pseudocode? {
|
fun KtDeclaration.getContainingPseudocode(context: BindingContext): Pseudocode? {
|
||||||
val enclosingPseudocodeDeclaration = (this as? KtFunctionLiteral)?.let {
|
val enclosingPseudocodeDeclaration = (this as? KtFunctionLiteral)?.let {
|
||||||
it.parents.firstOrNull { it is KtDeclaration && it !is KtFunctionLiteral } as? KtDeclaration
|
it.parents.firstOrNull { it is KtDeclaration && it !is KtFunctionLiteral } as? KtDeclaration
|
||||||
|
|||||||
+8
-12
@@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.smartcasts
|
package org.jetbrains.kotlin.resolve.calls.smartcasts
|
||||||
|
|
||||||
import org.jetbrains.kotlin.cfg.ControlFlowInformationProvider
|
import org.jetbrains.kotlin.cfg.getDeclarationDescriptorIncludingConstructors
|
||||||
|
import org.jetbrains.kotlin.cfg.getElementParentDeclaration
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
@@ -102,10 +103,8 @@ fun hasNoWritersInClosures(
|
|||||||
bindingContext: BindingContext
|
bindingContext: BindingContext
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return writers.none { (_, writerDeclaration) ->
|
return writers.none { (_, writerDeclaration) ->
|
||||||
val writerDescriptor = writerDeclaration?.let {
|
writerDeclaration != null &&
|
||||||
ControlFlowInformationProvider.getDeclarationDescriptorIncludingConstructors(bindingContext, it)
|
variableContainingDeclaration != writerDeclaration.getDeclarationDescriptorIncludingConstructors(bindingContext)
|
||||||
}
|
|
||||||
writerDeclaration != null && variableContainingDeclaration != writerDescriptor
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +112,7 @@ private fun isAccessedInsideClosureAfterAllWriters(
|
|||||||
writers: Set<AssignedVariablesSearcher.Writer>,
|
writers: Set<AssignedVariablesSearcher.Writer>,
|
||||||
accessElement: KtElement
|
accessElement: KtElement
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val parent = ControlFlowInformationProvider.getElementParentDeclaration(accessElement) ?: return false
|
val parent = accessElement.getElementParentDeclaration() ?: return false
|
||||||
return writers.none { (assignment) -> !assignment.before(parent) }
|
return writers.none { (assignment) -> !assignment.before(parent) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,9 +125,7 @@ private fun isAccessedBeforeAllClosureWriters(
|
|||||||
// All writers should be before access element, with the exception:
|
// All writers should be before access element, with the exception:
|
||||||
// writer which is the same with declaration site does not count
|
// writer which is the same with declaration site does not count
|
||||||
writers.mapNotNull { it.declaration }.forEach { writerDeclaration ->
|
writers.mapNotNull { it.declaration }.forEach { writerDeclaration ->
|
||||||
val writerDescriptor = ControlFlowInformationProvider.getDeclarationDescriptorIncludingConstructors(
|
val writerDescriptor = writerDeclaration.getDeclarationDescriptorIncludingConstructors(bindingContext)
|
||||||
bindingContext, writerDeclaration
|
|
||||||
)
|
|
||||||
// Access is after some writerDeclaration
|
// Access is after some writerDeclaration
|
||||||
if (variableContainingDeclaration != writerDescriptor && !accessElement.before(writerDeclaration)) {
|
if (variableContainingDeclaration != writerDescriptor && !accessElement.before(writerDeclaration)) {
|
||||||
return false
|
return false
|
||||||
@@ -156,10 +153,9 @@ private fun isAccessedInsideClosure(
|
|||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
accessElement: KtElement
|
accessElement: KtElement
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val parent = ControlFlowInformationProvider.getElementParentDeclaration(accessElement)
|
val parent = accessElement.getElementParentDeclaration()
|
||||||
return if (parent != null) // Access is at the same declaration: not in closure, lower: in closure
|
return if (parent != null) // Access is at the same declaration: not in closure, lower: in closure
|
||||||
ControlFlowInformationProvider.getDeclarationDescriptorIncludingConstructors(bindingContext, parent) !=
|
parent.getDeclarationDescriptorIncludingConstructors(bindingContext) != variableContainingDeclaration
|
||||||
variableContainingDeclaration
|
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve
|
package org.jetbrains.kotlin.resolve
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
|
||||||
import org.jetbrains.kotlin.types.DeferredType
|
import org.jetbrains.kotlin.types.DeferredType
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||||
@@ -28,10 +25,16 @@ fun FunctionDescriptor.isFunctionForExpectTypeFromCastFeature(): Boolean {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun CallableMemberDescriptor.isEffectivelyFinal(ignoreEnumClassFinality: Boolean): Boolean =
|
internal fun CallableMemberDescriptor.isEffectivelyFinal(ignoreEnumClassFinality: Boolean): Boolean =
|
||||||
modality == Modality.FINAL ||
|
modality == Modality.FINAL ||
|
||||||
containingDeclaration.let { parent ->
|
containingDeclaration.let { parent ->
|
||||||
(ignoreEnumClassFinality || !DescriptorUtils.isEnumClass(parent)) &&
|
(ignoreEnumClassFinality || !DescriptorUtils.isEnumClass(parent)) &&
|
||||||
parent is ClassDescriptor && parent.modality == Modality.FINAL
|
parent is ClassDescriptor && parent.modality == Modality.FINAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ParameterDescriptor.indexOrMinusOne(): Int =
|
||||||
|
when (this) {
|
||||||
|
is ReceiverParameterDescriptor -> -1
|
||||||
|
is ValueParameterDescriptor -> index
|
||||||
|
else -> error("expected either receiver or value parameter, but got: $this")
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.util
|
package org.jetbrains.kotlin.util
|
||||||
|
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import com.intellij.psi.PsiElementVisitor
|
|||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
import com.intellij.psi.util.parentOfType
|
import com.intellij.psi.util.parentOfType
|
||||||
import com.intellij.psi.util.parentsOfType
|
import com.intellij.psi.util.parentsOfType
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
|
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import com.intellij.openapi.vfs.VirtualFile
|
|||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||||
import org.jetbrains.kotlin.asJava.toLightClass
|
import org.jetbrains.kotlin.asJava.toLightClass
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
|
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
||||||
import kotlin.system.measureNanoTime
|
import kotlin.system.measureNanoTime
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import com.intellij.psi.PsiElementVisitor
|
|||||||
import com.intellij.psi.search.searches.ReferencesSearch
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
|
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.PseudocodeUtil
|
import org.jetbrains.kotlin.cfg.pseudocode.PseudocodeUtil
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
|
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionWithNext
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionWithNext
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.AccessTarget
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.AccessTarget
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
|
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement
|
import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import com.intellij.openapi.util.Ref
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
|
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.PseudocodeUtil
|
import org.jetbrains.kotlin.cfg.pseudocode.PseudocodeUtil
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
|
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
|
||||||
import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement
|
import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.result.*
|
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.result.*
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.idea.quickfix
|
|||||||
|
|
||||||
import com.intellij.codeInsight.intention.IntentionAction
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
|
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
|
||||||
import org.jetbrains.kotlin.codegen.inline.isInlineOrInsideInline
|
import org.jetbrains.kotlin.codegen.inline.isInlineOrInsideInline
|
||||||
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
|
|||||||
+1
@@ -11,6 +11,7 @@ import com.intellij.psi.util.PsiTreeUtil
|
|||||||
import com.intellij.refactoring.util.RefactoringUIUtil
|
import com.intellij.refactoring.util.RefactoringUIUtil
|
||||||
import com.intellij.util.containers.MultiMap
|
import com.intellij.util.containers.MultiMap
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.*
|
import org.jetbrains.kotlin.cfg.pseudocode.*
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import com.intellij.util.Processor
|
|||||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
|
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
|
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
|
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.getContainingPseudocode
|
import org.jetbrains.kotlin.cfg.pseudocode.getContainingPseudocode
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.KtElementInstruction
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.KtElementInstruction
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
|
||||||
|
|||||||
Reference in New Issue
Block a user