[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");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("smartCastInWhenEntryCondition.kt")
|
||||
public void testSmartCastInWhenEntryCondition() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/smartCastInWhenEntryCondition.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertiesScope.kt")
|
||||
public void testSyntheticPropertiesScope() throws Exception {
|
||||
|
||||
+6
@@ -76,6 +76,12 @@ public class FirIdeNormalAnalysisSourceModuleScopeContextForPositionTestGenerate
|
||||
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
|
||||
@TestMetadata("syntheticPropertiesScope.kt")
|
||||
public void testSyntheticPropertiesScope() throws Exception {
|
||||
|
||||
+6
@@ -76,6 +76,12 @@ public class FirStandaloneNormalAnalysisSourceModuleScopeContextForPositionTestG
|
||||
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
|
||||
@TestMetadata("syntheticPropertiesScope.kt")
|
||||
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.resolve.transformers.body.resolve.BodyResolveContext
|
||||
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.psiUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
@@ -115,18 +116,34 @@ internal class FirTowerDataContextAllElementsCollector : FirResolveContextCollec
|
||||
* - a statement in a block
|
||||
* - an initializer of a declaration
|
||||
* - an expression in when entry
|
||||
* - a right operand in binary expression with operator `&&` or `||`
|
||||
*
|
||||
* Otherwise, invokes this function recursively on the parent.
|
||||
*/
|
||||
private tailrec fun PsiElement.closestParentExpressionWithSameContextOrSelf(): KtExpression? =
|
||||
when {
|
||||
this is KtExpression && (parent is KtBlockExpression || parent is KtDeclarationWithInitializer || isExpressionInWhenEntry) -> this
|
||||
else -> parent?.closestParentExpressionWithSameContextOrSelf()
|
||||
private tailrec fun PsiElement.closestParentExpressionWithSameContextOrSelf(): KtExpression? {
|
||||
if (this is KtExpression) {
|
||||
if (
|
||||
parent is KtBlockExpression ||
|
||||
parent is KtDeclarationWithInitializer ||
|
||||
isExpressionInWhenEntry ||
|
||||
isRightOperandInBinaryLogicOperation
|
||||
) return this
|
||||
}
|
||||
|
||||
return parent?.closestParentExpressionWithSameContextOrSelf()
|
||||
}
|
||||
|
||||
private val KtExpression.isExpressionInWhenEntry: Boolean
|
||||
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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user