Skip to content

Commit

Permalink
[FIR] Prohibit referencing java field in case of conflict with proper…
Browse files Browse the repository at this point in the history
…ty..

..from companion object of the derived class

^KT-68056 Fixed
  • Loading branch information
demiurg906 authored and qodana-bot committed May 8, 2024
1 parent b239239 commit b618ee4
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 7 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,23 @@ import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirCallableReferenceAccessChecker
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirPropertyAccessExpressionChecker
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_FIELD_SHADOWED_BY_KOTLIN_PROPERTY
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.isJavaOrEnhancement
import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.isVisible
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.scopes.CallableCopyTypeCalculator
import org.jetbrains.kotlin.fir.scopes.getProperties
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.resolvedType
import org.jetbrains.kotlin.fir.types.toClassSymbol
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlin.fir.visibilityChecker

object FirFieldAccessShadowedByInvisibleKotlinProperty : FirPropertyAccessExpressionChecker(MppCheckerKind.Platform) {
Expand All @@ -51,14 +54,25 @@ private fun checkFieldAccess(

val containingFile = context.containingFile ?: return
val dispatchReceiver = expression.dispatchReceiver ?: return
val dispatchReceiverScope = dispatchReceiver.resolvedType.scope(
checkClashWithInvisibleProperty(context, fieldSymbol, containingFile, dispatchReceiver, reporter, expression)
checkClashWithCompanionProperty(context, fieldSymbol, reporter, expression)
}

private fun checkClashWithInvisibleProperty(
context: CheckerContext,
fieldSymbol: FirFieldSymbol,
containingFile: FirFile,
dispatchReceiver: FirExpression,
reporter: DiagnosticReporter,
expression: FirQualifiedAccessExpression,
) {
val scope = dispatchReceiver.resolvedType.scope(
context.session,
context.scopeSession,
CallableCopyTypeCalculator.Forced,
requiredMembersPhase = null
) ?: return

val properties = dispatchReceiverScope.getProperties(fieldSymbol.name)
val properties = scope.getProperties(fieldSymbol.name)
for (property in properties) {
if (property !is FirPropertySymbol) continue
if (!property.hasBackingField) continue
Expand All @@ -75,3 +89,22 @@ private fun checkFieldAccess(
}
}
}

private fun checkClashWithCompanionProperty(
context: CheckerContext,
fieldSymbol: FirFieldSymbol,
reporter: DiagnosticReporter,
expression: FirQualifiedAccessExpression,
) {
val dispatchReceiverClass = expression.dispatchReceiver?.resolvedType?.toRegularClassSymbol(context.session) ?: return
val companionClass = dispatchReceiverClass.companionObjectSymbol ?: return
val companionScope = companionClass.unsubstitutedScope(context)
val properties = companionScope.getProperties(fieldSymbol.name)
for (property in properties) {
if (property !is FirPropertySymbol) continue
if (property.hasBackingField) {
reporter.reportOn(expression.source, JAVA_FIELD_SHADOWED_BY_KOTLIN_PROPERTY, property, context)
break
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_K1: JVM_IR
// IGNORE_BACKEND_K2: JVM_IR
// COMMENTED[LANGUAGE: +ProperFieldAccessGenerationForFieldAccessShadowedByKotlinProperty] uncomment when KT-52338 is fixed

// FILE: Base.java
public class Base {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// LANGUAGE: -ProperFieldAccessGenerationForFieldAccessShadowedByKotlinProperty
// ISSUE: KT-52338

// FILE: Base.java
public class Base {
protected String TAG = "OK";

public String foo() {
return TAG;
}
}

// FILE: Sub.kt

class Sub : Base() {
companion object {
val TAG = "FAIL"
}

fun log() = <!JAVA_FIELD_SHADOWED_BY_KOTLIN_PROPERTY!>TAG<!>

fun logReference() = this::<!JAVA_FIELD_SHADOWED_BY_KOTLIN_PROPERTY!>TAG<!>.get()

fun logAssignment(): String {
<!JAVA_FIELD_SHADOWED_BY_KOTLIN_PROPERTY!>TAG<!> = "12"
if (foo() != "12") return "Error writing: ${foo()}"
return "OK"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// LANGUAGE: -ProperFieldAccessGenerationForFieldAccessShadowedByKotlinProperty
// ISSUE: KT-52338

// FILE: Base.java
public class Base {
protected String TAG = "OK";

public String foo() {
return TAG;
}
}

// FILE: Sub.kt

class Sub : Base() {
companion object {
val TAG = "FAIL"
}

fun log() = TAG

fun logReference() = this::TAG.get()

fun logAssignment(): String {
TAG = "12"
if (foo() != "12") return "Error writing: ${foo()}"
return "OK"
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b618ee4

Please sign in to comment.