FIR IDE: implement assignment statement references

This commit is contained in:
Ilya Kirillov
2021-01-07 17:34:36 +01:00
parent 14d2b1be49
commit e060778528
8 changed files with 88 additions and 4 deletions
@@ -256,7 +256,6 @@ object UnusedChecker : FirControlFlowChecker() {
vararg qualifiedAccesses: FirQualifiedAccess,
): PathAwareVariableStatusInfo {
fun retrieveSymbol(qualifiedAccess: FirQualifiedAccess): FirPropertySymbol? {
if (qualifiedAccess.source?.kind is FirFakeSourceElementKind) return null
val reference = qualifiedAccess.calleeReference as? FirResolvedNamedReference ?: return null
val symbol = reference.resolvedSymbol as? FirPropertySymbol ?: return null
return if (symbol !in localProperties) null else symbol
@@ -873,8 +873,9 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
return buildAssignmentOperatorStatement {
source = baseSource
this.operation = operation
// TODO: take good psi
leftArgument = this@generateAssignment?.convert() ?: buildErrorExpression {
leftArgument = withDefaultSourceElementKind(FirFakeSourceElementKind.DesugaredCompoundAssignment) {
this@generateAssignment?.convert()
} ?: buildErrorExpression {
source = null
diagnostic = ConeSimpleDiagnostic(
"Unsupported left value of assignment: ${baseSource?.psi?.text}", DiagnosticKind.ExpressionRequired
@@ -353,7 +353,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
explicitReceiver = leftArgument
argumentList = buildUnaryArgumentList(rightArgument)
calleeReference = buildSimpleNamedReference {
source = assignmentOperatorStatement.source
source = assignmentOperatorStatement.source?.fakeElement(FirFakeSourceElementKind.DesugaredCompoundAssignment)
this.name = name
candidateSymbol = null
}
@@ -254,6 +254,16 @@ public class FirReferenceResolveTestGenerated extends AbstractFirReferenceResolv
runTest("idea/testData/resolve/references/JavaReference.kt");
}
@TestMetadata("KotlinPropertyAssignment.kt")
public void testKotlinPropertyAssignment() throws Exception {
runTest("idea/testData/resolve/references/KotlinPropertyAssignment.kt");
}
@TestMetadata("KotlinPropertyWithGetterAndSetterAssignment.kt")
public void testKotlinPropertyWithGetterAndSetterAssignment() throws Exception {
runTest("idea/testData/resolve/references/KotlinPropertyWithGetterAndSetterAssignment.kt");
}
@TestMetadata("MultiDeclarationExtension.kt")
public void testMultiDeclarationExtension() throws Exception {
runTest("idea/testData/resolve/references/MultiDeclarationExtension.kt");
@@ -156,12 +156,20 @@ internal object FirReferenceResolveHelper {
}
is FirReturnExpression -> getSymbolsByReturnExpression(expression, fir, symbolBuilder)
is FirErrorNamedReference -> getSymbolsByErrorNamedReference(fir, symbolBuilder)
is FirVariableAssignment -> getSymbolsByVariableAssignment(fir, session, symbolBuilder)
is FirResolvable -> getSymbolsByResolvable(fir, expression, session, symbolBuilder)
is FirNamedArgumentExpression -> getSymbolsByNameArgumentExpression(expression, analysisSession, symbolBuilder)
else -> handleUnknownFirElement(expression, analysisSession, session, symbolBuilder)
}
}
@OptIn(ExperimentalStdlibApi::class)
private fun getSymbolsByVariableAssignment(
fir: FirVariableAssignment,
session: FirSession,
symbolBuilder: KtSymbolByFirBuilder
): Collection<KtSymbol> = fir.calleeReference.toTargetSymbol(session, symbolBuilder)
private fun getSymbolsByNameArgumentExpression(
expression: KtSimpleNameExpression,
analysisSession: KtFirAnalysisSession,
@@ -0,0 +1,27 @@
class A {
var something: Int = 10
}
fun A.foo(a: A) {
print(a.<caret>something)
a.<caret>something = 1
a.<caret>something += 1
a.<caret>something++
--a.<caret>something
<caret>something++
(<caret>something)++
(<caret>something) = 1
(a.<caret>something) = 1
}
// MULTIRESOLVE
// REF1: (in A).something
// REF2: (in A).something
// REF3: (in A).something
// REF4: (in A).something
// REF5: (in A).something
// REF6: (in A).something
// REF7: (in A).something
// REF8: (in A).something
// REF9: (in A).something
@@ -0,0 +1,29 @@
class A {
var something: Int
set(value) {}
get() = 10
}
fun A.foo(a: A) {
print(a.<caret>something)
a.<caret>something = 1
a.<caret>something += 1
a.<caret>something++
--a.<caret>something
<caret>something++
(<caret>something)++
(<caret>something) = 1
(a.<caret>something) = 1
}
// MULTIRESOLVE
// REF1: (in A).something
// REF2: (in A).something
// REF3: (in A).something
// REF4: (in A).something
// REF5: (in A).something
// REF6: (in A).something
// REF7: (in A).something
// REF8: (in A).something
// REF9: (in A).something
@@ -254,6 +254,16 @@ public class ReferenceResolveTestGenerated extends AbstractReferenceResolveTest
runTest("idea/testData/resolve/references/JavaReference.kt");
}
@TestMetadata("KotlinPropertyAssignment.kt")
public void testKotlinPropertyAssignment() throws Exception {
runTest("idea/testData/resolve/references/KotlinPropertyAssignment.kt");
}
@TestMetadata("KotlinPropertyWithGetterAndSetterAssignment.kt")
public void testKotlinPropertyWithGetterAndSetterAssignment() throws Exception {
runTest("idea/testData/resolve/references/KotlinPropertyWithGetterAndSetterAssignment.kt");
}
@TestMetadata("MultiDeclarationExtension.kt")
public void testMultiDeclarationExtension() throws Exception {
runTest("idea/testData/resolve/references/MultiDeclarationExtension.kt");