[FIR] store tower data context for operand in and/or binary expression
KTIJ-26113
This commit is contained in:
committed by
teamcity
parent
2f2eb86195
commit
af6672c87d
+6
@@ -76,6 +76,12 @@ public class FirIdeDependentAnalysisSourceModuleScopeContextForPositionTestGener
|
|||||||
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/simpleScopeContextForPosition.kt");
|
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/simpleScopeContextForPosition.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartCastInWhenEntryCondition.kt")
|
||||||
|
public void testSmartCastInWhenEntryCondition() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/smartCastInWhenEntryCondition.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("syntheticPropertiesScope.kt")
|
@TestMetadata("syntheticPropertiesScope.kt")
|
||||||
public void testSyntheticPropertiesScope() throws Exception {
|
public void testSyntheticPropertiesScope() throws Exception {
|
||||||
|
|||||||
+6
@@ -76,6 +76,12 @@ public class FirIdeNormalAnalysisSourceModuleScopeContextForPositionTestGenerate
|
|||||||
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/simpleScopeContextForPosition.kt");
|
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/simpleScopeContextForPosition.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartCastInWhenEntryCondition.kt")
|
||||||
|
public void testSmartCastInWhenEntryCondition() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/smartCastInWhenEntryCondition.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("syntheticPropertiesScope.kt")
|
@TestMetadata("syntheticPropertiesScope.kt")
|
||||||
public void testSyntheticPropertiesScope() throws Exception {
|
public void testSyntheticPropertiesScope() throws Exception {
|
||||||
|
|||||||
+6
@@ -76,6 +76,12 @@ public class FirStandaloneNormalAnalysisSourceModuleScopeContextForPositionTestG
|
|||||||
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/simpleScopeContextForPosition.kt");
|
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/simpleScopeContextForPosition.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartCastInWhenEntryCondition.kt")
|
||||||
|
public void testSmartCastInWhenEntryCondition() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/smartCastInWhenEntryCondition.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("syntheticPropertiesScope.kt")
|
@TestMetadata("syntheticPropertiesScope.kt")
|
||||||
public void testSyntheticPropertiesScope() throws Exception {
|
public void testSyntheticPropertiesScope() throws Exception {
|
||||||
|
|||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
class A
|
||||||
|
|
||||||
|
class B
|
||||||
|
|
||||||
|
private fun Any.test(): Int = when {
|
||||||
|
this is A && <expr>a</expr> -> 10
|
||||||
|
this is B && b -> 2
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
element: a
|
||||||
|
implicit receivers:
|
||||||
|
type: A
|
||||||
|
owner symbol: KtFirFunctionSymbol
|
||||||
|
|
||||||
|
scopes:
|
||||||
|
LocalScope, index = 0
|
||||||
|
packages: 0
|
||||||
|
classifiers: 0
|
||||||
|
callables: 0
|
||||||
|
constructors: 0
|
||||||
|
|
||||||
|
TypeScope, index = 1
|
||||||
|
packages: 0
|
||||||
|
classifiers: 0
|
||||||
|
callables: 3
|
||||||
|
fun equals(other: kotlin.Any?): kotlin.Boolean
|
||||||
|
fun hashCode(): kotlin.Int
|
||||||
|
fun toString(): kotlin.String
|
||||||
|
constructors: 1
|
||||||
|
constructor()
|
||||||
|
|
||||||
|
LocalScope, index = 2
|
||||||
|
packages: 0
|
||||||
|
classifiers: 0
|
||||||
|
callables: 0
|
||||||
|
constructors: 0
|
||||||
|
|
||||||
|
ExplicitSimpleImportingScope, index = 3
|
||||||
|
packages: 0
|
||||||
|
classifiers: 0
|
||||||
|
callables: 0
|
||||||
|
constructors: 0
|
||||||
|
|
||||||
|
PackageMemberScope, index = 4
|
||||||
|
packages: 6
|
||||||
|
META-INF
|
||||||
|
java
|
||||||
|
javax
|
||||||
|
kotlin
|
||||||
|
org
|
||||||
|
sun
|
||||||
|
classifiers: 2
|
||||||
|
class A
|
||||||
|
class B
|
||||||
|
callables: 1
|
||||||
|
fun kotlin.Any.test(): kotlin.Int
|
||||||
|
constructors: 0
|
||||||
|
|
||||||
|
DefaultSimpleImportingScope, index = 5
|
||||||
|
|
||||||
|
DefaultSimpleImportingScope, index = 6
|
||||||
|
|
||||||
|
ExplicitStarImportingScope, index = 7
|
||||||
|
packages: 0
|
||||||
|
classifiers: 0
|
||||||
|
callables: 0
|
||||||
|
constructors: 0
|
||||||
|
|
||||||
|
DefaultSimpleImportingScope, index = 8
|
||||||
|
|
||||||
|
DefaultStarImportingScope, index = 9
|
||||||
|
|
||||||
+285
@@ -0,0 +1,285 @@
|
|||||||
|
element: a
|
||||||
|
implicit receivers:
|
||||||
|
type: KtUsualClassType:
|
||||||
|
annotationsList: []
|
||||||
|
ownTypeArguments: []
|
||||||
|
type: A
|
||||||
|
owner symbol: KtFirFunctionSymbol
|
||||||
|
|
||||||
|
scopes:
|
||||||
|
LocalScope, index = 0
|
||||||
|
packages: 0
|
||||||
|
classifiers: 0
|
||||||
|
callables: 0
|
||||||
|
constructors: 0
|
||||||
|
|
||||||
|
TypeScope, index = 1
|
||||||
|
packages: 0
|
||||||
|
classifiers: 0
|
||||||
|
callables: 3
|
||||||
|
KtFunctionSymbol:
|
||||||
|
annotationsList: []
|
||||||
|
callableIdIfNonLocal: kotlin/Any.equals
|
||||||
|
contextReceivers: []
|
||||||
|
contractEffects: []
|
||||||
|
hasStableParameterNames: true
|
||||||
|
isActual: false
|
||||||
|
isBuiltinFunctionInvoke: false
|
||||||
|
isExpect: false
|
||||||
|
isExtension: false
|
||||||
|
isExternal: false
|
||||||
|
isInfix: false
|
||||||
|
isInline: false
|
||||||
|
isOperator: true
|
||||||
|
isOverride: false
|
||||||
|
isStatic: false
|
||||||
|
isSuspend: false
|
||||||
|
modality: OPEN
|
||||||
|
name: equals
|
||||||
|
origin: LIBRARY
|
||||||
|
receiverParameter: null
|
||||||
|
returnType: KtUsualClassType:
|
||||||
|
annotationsList: []
|
||||||
|
ownTypeArguments: []
|
||||||
|
type: kotlin/Boolean
|
||||||
|
symbolKind: CLASS_MEMBER
|
||||||
|
typeParameters: []
|
||||||
|
valueParameters: [
|
||||||
|
KtValueParameterSymbol:
|
||||||
|
annotationsList: []
|
||||||
|
callableIdIfNonLocal: null
|
||||||
|
contextReceivers: []
|
||||||
|
generatedPrimaryConstructorProperty: null
|
||||||
|
hasDefaultValue: false
|
||||||
|
isCrossinline: false
|
||||||
|
isExtension: false
|
||||||
|
isImplicitLambdaParameter: false
|
||||||
|
isNoinline: false
|
||||||
|
isVararg: false
|
||||||
|
name: other
|
||||||
|
origin: LIBRARY
|
||||||
|
receiverParameter: null
|
||||||
|
returnType: KtUsualClassType:
|
||||||
|
annotationsList: []
|
||||||
|
ownTypeArguments: []
|
||||||
|
type: kotlin/Any?
|
||||||
|
symbolKind: LOCAL
|
||||||
|
typeParameters: []
|
||||||
|
]
|
||||||
|
visibility: Public
|
||||||
|
KtFunctionSymbol:
|
||||||
|
annotationsList: []
|
||||||
|
callableIdIfNonLocal: kotlin/Any.hashCode
|
||||||
|
contextReceivers: []
|
||||||
|
contractEffects: []
|
||||||
|
hasStableParameterNames: true
|
||||||
|
isActual: false
|
||||||
|
isBuiltinFunctionInvoke: false
|
||||||
|
isExpect: false
|
||||||
|
isExtension: false
|
||||||
|
isExternal: false
|
||||||
|
isInfix: false
|
||||||
|
isInline: false
|
||||||
|
isOperator: false
|
||||||
|
isOverride: false
|
||||||
|
isStatic: false
|
||||||
|
isSuspend: false
|
||||||
|
modality: OPEN
|
||||||
|
name: hashCode
|
||||||
|
origin: LIBRARY
|
||||||
|
receiverParameter: null
|
||||||
|
returnType: KtUsualClassType:
|
||||||
|
annotationsList: []
|
||||||
|
ownTypeArguments: []
|
||||||
|
type: kotlin/Int
|
||||||
|
symbolKind: CLASS_MEMBER
|
||||||
|
typeParameters: []
|
||||||
|
valueParameters: []
|
||||||
|
visibility: Public
|
||||||
|
KtFunctionSymbol:
|
||||||
|
annotationsList: []
|
||||||
|
callableIdIfNonLocal: kotlin/Any.toString
|
||||||
|
contextReceivers: []
|
||||||
|
contractEffects: []
|
||||||
|
hasStableParameterNames: true
|
||||||
|
isActual: false
|
||||||
|
isBuiltinFunctionInvoke: false
|
||||||
|
isExpect: false
|
||||||
|
isExtension: false
|
||||||
|
isExternal: false
|
||||||
|
isInfix: false
|
||||||
|
isInline: false
|
||||||
|
isOperator: false
|
||||||
|
isOverride: false
|
||||||
|
isStatic: false
|
||||||
|
isSuspend: false
|
||||||
|
modality: OPEN
|
||||||
|
name: toString
|
||||||
|
origin: LIBRARY
|
||||||
|
receiverParameter: null
|
||||||
|
returnType: KtUsualClassType:
|
||||||
|
annotationsList: []
|
||||||
|
ownTypeArguments: []
|
||||||
|
type: kotlin/String
|
||||||
|
symbolKind: CLASS_MEMBER
|
||||||
|
typeParameters: []
|
||||||
|
valueParameters: []
|
||||||
|
visibility: Public
|
||||||
|
constructors: 1
|
||||||
|
KtConstructorSymbol:
|
||||||
|
annotationsList: []
|
||||||
|
callableIdIfNonLocal: null
|
||||||
|
containingClassIdIfNonLocal: A
|
||||||
|
contextReceivers: []
|
||||||
|
hasStableParameterNames: true
|
||||||
|
isActual: false
|
||||||
|
isExpect: false
|
||||||
|
isExtension: false
|
||||||
|
isPrimary: true
|
||||||
|
origin: SOURCE_MEMBER_GENERATED
|
||||||
|
receiverParameter: null
|
||||||
|
returnType: KtUsualClassType:
|
||||||
|
annotationsList: []
|
||||||
|
ownTypeArguments: []
|
||||||
|
type: A
|
||||||
|
symbolKind: CLASS_MEMBER
|
||||||
|
typeParameters: []
|
||||||
|
valueParameters: []
|
||||||
|
visibility: Public
|
||||||
|
|
||||||
|
LocalScope, index = 2
|
||||||
|
packages: 0
|
||||||
|
classifiers: 0
|
||||||
|
callables: 0
|
||||||
|
constructors: 0
|
||||||
|
|
||||||
|
ExplicitSimpleImportingScope, index = 3
|
||||||
|
packages: 0
|
||||||
|
classifiers: 0
|
||||||
|
callables: 0
|
||||||
|
constructors: 0
|
||||||
|
|
||||||
|
PackageMemberScope, index = 4
|
||||||
|
packages: 6
|
||||||
|
KtPackageSymbol:
|
||||||
|
fqName: META-INF
|
||||||
|
origin: SOURCE
|
||||||
|
KtPackageSymbol:
|
||||||
|
fqName: java
|
||||||
|
origin: SOURCE
|
||||||
|
KtPackageSymbol:
|
||||||
|
fqName: javax
|
||||||
|
origin: SOURCE
|
||||||
|
KtPackageSymbol:
|
||||||
|
fqName: kotlin
|
||||||
|
origin: SOURCE
|
||||||
|
KtPackageSymbol:
|
||||||
|
fqName: org
|
||||||
|
origin: SOURCE
|
||||||
|
KtPackageSymbol:
|
||||||
|
fqName: sun
|
||||||
|
origin: SOURCE
|
||||||
|
classifiers: 2
|
||||||
|
KtNamedClassOrObjectSymbol:
|
||||||
|
annotationsList: []
|
||||||
|
classIdIfNonLocal: A
|
||||||
|
classKind: CLASS
|
||||||
|
companionObject: null
|
||||||
|
contextReceivers: []
|
||||||
|
isActual: false
|
||||||
|
isData: false
|
||||||
|
isExpect: false
|
||||||
|
isExternal: false
|
||||||
|
isFun: false
|
||||||
|
isInline: false
|
||||||
|
isInner: false
|
||||||
|
modality: FINAL
|
||||||
|
name: A
|
||||||
|
origin: SOURCE
|
||||||
|
superTypes: [
|
||||||
|
KtUsualClassType:
|
||||||
|
annotationsList: []
|
||||||
|
ownTypeArguments: []
|
||||||
|
type: kotlin/Any
|
||||||
|
]
|
||||||
|
symbolKind: TOP_LEVEL
|
||||||
|
typeParameters: []
|
||||||
|
visibility: Public
|
||||||
|
KtNamedClassOrObjectSymbol:
|
||||||
|
annotationsList: []
|
||||||
|
classIdIfNonLocal: B
|
||||||
|
classKind: CLASS
|
||||||
|
companionObject: null
|
||||||
|
contextReceivers: []
|
||||||
|
isActual: false
|
||||||
|
isData: false
|
||||||
|
isExpect: false
|
||||||
|
isExternal: false
|
||||||
|
isFun: false
|
||||||
|
isInline: false
|
||||||
|
isInner: false
|
||||||
|
modality: FINAL
|
||||||
|
name: B
|
||||||
|
origin: SOURCE
|
||||||
|
superTypes: [
|
||||||
|
KtUsualClassType:
|
||||||
|
annotationsList: []
|
||||||
|
ownTypeArguments: []
|
||||||
|
type: kotlin/Any
|
||||||
|
]
|
||||||
|
symbolKind: TOP_LEVEL
|
||||||
|
typeParameters: []
|
||||||
|
visibility: Public
|
||||||
|
callables: 1
|
||||||
|
KtFunctionSymbol:
|
||||||
|
annotationsList: []
|
||||||
|
callableIdIfNonLocal: /test
|
||||||
|
contextReceivers: []
|
||||||
|
contractEffects: []
|
||||||
|
hasStableParameterNames: true
|
||||||
|
isActual: false
|
||||||
|
isBuiltinFunctionInvoke: false
|
||||||
|
isExpect: false
|
||||||
|
isExtension: true
|
||||||
|
isExternal: false
|
||||||
|
isInfix: false
|
||||||
|
isInline: false
|
||||||
|
isOperator: false
|
||||||
|
isOverride: false
|
||||||
|
isStatic: false
|
||||||
|
isSuspend: false
|
||||||
|
modality: FINAL
|
||||||
|
name: test
|
||||||
|
origin: SOURCE
|
||||||
|
receiverParameter: KtReceiverParameterSymbol:
|
||||||
|
annotationsList: []
|
||||||
|
origin: SOURCE
|
||||||
|
owningCallableSymbol: KtFunctionSymbol(/test)
|
||||||
|
type: KtUsualClassType:
|
||||||
|
annotationsList: []
|
||||||
|
ownTypeArguments: []
|
||||||
|
type: kotlin/Any
|
||||||
|
returnType: KtUsualClassType:
|
||||||
|
annotationsList: []
|
||||||
|
ownTypeArguments: []
|
||||||
|
type: kotlin/Int
|
||||||
|
symbolKind: TOP_LEVEL
|
||||||
|
typeParameters: []
|
||||||
|
valueParameters: []
|
||||||
|
visibility: Private
|
||||||
|
constructors: 0
|
||||||
|
|
||||||
|
DefaultSimpleImportingScope, index = 5
|
||||||
|
|
||||||
|
DefaultSimpleImportingScope, index = 6
|
||||||
|
|
||||||
|
ExplicitStarImportingScope, index = 7
|
||||||
|
packages: 0
|
||||||
|
classifiers: 0
|
||||||
|
callables: 0
|
||||||
|
constructors: 0
|
||||||
|
|
||||||
|
DefaultSimpleImportingScope, index = 8
|
||||||
|
|
||||||
|
DefaultStarImportingScope, index = 9
|
||||||
|
|
||||||
+21
-4
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement
|
|||||||
import org.jetbrains.kotlin.fir.psi
|
import org.jetbrains.kotlin.fir.psi
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
@@ -115,18 +116,34 @@ internal class FirTowerDataContextAllElementsCollector : FirResolveContextCollec
|
|||||||
* - a statement in a block
|
* - a statement in a block
|
||||||
* - an initializer of a declaration
|
* - an initializer of a declaration
|
||||||
* - an expression in when entry
|
* - an expression in when entry
|
||||||
|
* - a right operand in binary expression with operator `&&` or `||`
|
||||||
*
|
*
|
||||||
* Otherwise, invokes this function recursively on the parent.
|
* Otherwise, invokes this function recursively on the parent.
|
||||||
*/
|
*/
|
||||||
private tailrec fun PsiElement.closestParentExpressionWithSameContextOrSelf(): KtExpression? =
|
private tailrec fun PsiElement.closestParentExpressionWithSameContextOrSelf(): KtExpression? {
|
||||||
when {
|
if (this is KtExpression) {
|
||||||
this is KtExpression && (parent is KtBlockExpression || parent is KtDeclarationWithInitializer || isExpressionInWhenEntry) -> this
|
if (
|
||||||
else -> parent?.closestParentExpressionWithSameContextOrSelf()
|
parent is KtBlockExpression ||
|
||||||
|
parent is KtDeclarationWithInitializer ||
|
||||||
|
isExpressionInWhenEntry ||
|
||||||
|
isRightOperandInBinaryLogicOperation
|
||||||
|
) return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return parent?.closestParentExpressionWithSameContextOrSelf()
|
||||||
|
}
|
||||||
|
|
||||||
private val KtExpression.isExpressionInWhenEntry: Boolean
|
private val KtExpression.isExpressionInWhenEntry: Boolean
|
||||||
get() = this == (parent as? KtWhenEntry)?.expression
|
get() = this == (parent as? KtWhenEntry)?.expression
|
||||||
|
|
||||||
|
private val KtExpression.isRightOperandInBinaryLogicOperation: Boolean
|
||||||
|
get() {
|
||||||
|
val binaryLogicOperation = (parent as? KtBinaryExpression)
|
||||||
|
?.takeIf { it.operationToken == KtTokens.ANDAND || it.operationToken == KtTokens.OROR }
|
||||||
|
|
||||||
|
return this == binaryLogicOperation?.right
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if [element] is considered to be a part of [this] class header.
|
* Returns true if [element] is considered to be a part of [this] class header.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user