FIR: Handle visibility of public setter of protected synthetic property like in K1
K1 allows writing access to a public setter of a protected synthetic property only if the call is inside a subclass. K2 previously allowed that unconditionally. This changes brings the behavior in line with K1. ^KT-56050 Fixed
This commit is contained in:
committed by
Space Team
parent
1990883bdc
commit
f6c189be7b
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
|||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.descriptors.java.JavaVisibilities
|
import org.jetbrains.kotlin.descriptors.java.JavaVisibilities
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
|
||||||
@@ -16,8 +17,10 @@ import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
|||||||
import org.jetbrains.kotlin.fir.resolve.SupertypeSupplier
|
import org.jetbrains.kotlin.fir.resolve.SupertypeSupplier
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol
|
import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
|
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.isSubclassOf
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.lastIsInstanceOrNull
|
||||||
|
|
||||||
@NoMutableState
|
@NoMutableState
|
||||||
object FirJavaVisibilityChecker : FirVisibilityChecker() {
|
object FirJavaVisibilityChecker : FirVisibilityChecker() {
|
||||||
@@ -47,7 +50,7 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() {
|
|||||||
|
|
||||||
// FE1.0 allows calling public setters with property assignment syntax if the getter is protected.
|
// FE1.0 allows calling public setters with property assignment syntax if the getter is protected.
|
||||||
if (!isCallToPropertySetter || symbol !is FirSimpleSyntheticPropertySymbol) return false
|
if (!isCallToPropertySetter || symbol !is FirSimpleSyntheticPropertySymbol) return false
|
||||||
symbol.setterSymbol?.visibility == Visibilities.Public
|
symbol.setterSymbol?.visibility == Visibilities.Public && symbol.isCalledFromSubclass(containingDeclarations, session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,6 +59,14 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirSimpleSyntheticPropertySymbol.isCalledFromSubclass(
|
||||||
|
containingDeclarations: List<FirDeclaration>,
|
||||||
|
session: FirSession
|
||||||
|
): Boolean {
|
||||||
|
val containingClassLookupTag = this.containingClassLookupTag() ?: return false
|
||||||
|
return containingDeclarations.any { it is FirClass && it.isSubclassOf(containingClassLookupTag, session, false) }
|
||||||
|
}
|
||||||
|
|
||||||
override fun platformOverrideVisibilityCheck(
|
override fun platformOverrideVisibilityCheck(
|
||||||
candidateInDerivedClass: FirBasedSymbol<*>,
|
candidateInDerivedClass: FirBasedSymbol<*>,
|
||||||
symbolInBaseClass: FirBasedSymbol<*>,
|
symbolInBaseClass: FirBasedSymbol<*>,
|
||||||
|
|||||||
+96
-6
@@ -1,9 +1,9 @@
|
|||||||
// FILE: j/Super.java
|
// FILE: j/Super.java
|
||||||
package j
|
package j
|
||||||
|
|
||||||
public abstract class Super {
|
public class Super {
|
||||||
protected abstract String getName();
|
protected String getName() { return "" };
|
||||||
public abstract void setName(String s);
|
public void setName(String s) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: k/test.kt
|
// FILE: k/test.kt
|
||||||
@@ -11,20 +11,110 @@ public abstract class Super {
|
|||||||
package k
|
package k
|
||||||
import j.Super
|
import j.Super
|
||||||
|
|
||||||
abstract class Sub: Super() {
|
abstract class Sub : Super() {
|
||||||
fun test(s: Super) {
|
fun test(s: Super) {
|
||||||
s.<!INVISIBLE_REFERENCE!>name<!>
|
s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
s.name = ""
|
s.name = ""
|
||||||
s.name = s.<!INVISIBLE_REFERENCE!>name<!>
|
s.name = s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
s.setName("")
|
s.setName("")
|
||||||
|
|
||||||
|
val anon1 = object : Super() {
|
||||||
|
fun testAnon() {
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
|
s.name = ""
|
||||||
|
s.name = s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val anon2 = object {
|
||||||
|
fun testAnon() {
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
|
s.name = ""
|
||||||
|
s.name = s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class Nested1 : Super() {
|
||||||
|
fun test(s: Super) {
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
|
s.name = ""
|
||||||
|
s.name = s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Nested2 {
|
||||||
|
fun test(s: Super) {
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
|
s.name = ""
|
||||||
|
s.name = s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class NonSub {
|
||||||
|
fun test(s: Super) {
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!> = ""
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!> = s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
|
||||||
|
val anon1 = object : Super() {
|
||||||
|
fun testAnon() {
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
|
s.name = ""
|
||||||
|
s.name = s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val anon2 = object {
|
||||||
|
fun testAnon() {
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!> = ""
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!> = s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class Nested1 : Super() {
|
||||||
|
fun test(s: Super) {
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
|
s.name = ""
|
||||||
|
s.name = s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Nested2 {
|
||||||
|
fun test(s: Super) {
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!> = ""
|
||||||
|
s.<!INVISIBLE_REFERENCE!>name<!> = s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test(s: Super) {
|
fun test(s: Super) {
|
||||||
s.<!INVISIBLE_REFERENCE!>name<!>
|
s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
s.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
s.name = ""
|
s.<!INVISIBLE_REFERENCE!>name<!> = ""
|
||||||
s.name = s.<!INVISIBLE_REFERENCE!>name<!>
|
s.<!INVISIBLE_REFERENCE!>name<!> = s.<!INVISIBLE_REFERENCE!>name<!>
|
||||||
s.setName("")
|
s.setName("")
|
||||||
}
|
}
|
||||||
|
|||||||
+94
-4
@@ -1,9 +1,9 @@
|
|||||||
// FILE: j/Super.java
|
// FILE: j/Super.java
|
||||||
package j
|
package j
|
||||||
|
|
||||||
public abstract class Super {
|
public class Super {
|
||||||
protected abstract String getName();
|
protected String getName() { return "" };
|
||||||
public abstract void setName(String s);
|
public void setName(String s) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: k/test.kt
|
// FILE: k/test.kt
|
||||||
@@ -11,13 +11,103 @@ public abstract class Super {
|
|||||||
package k
|
package k
|
||||||
import j.Super
|
import j.Super
|
||||||
|
|
||||||
abstract class Sub: Super() {
|
abstract class Sub : Super() {
|
||||||
fun test(s: Super) {
|
fun test(s: Super) {
|
||||||
s.<!INVISIBLE_MEMBER!>name<!>
|
s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
s.<!INVISIBLE_MEMBER!>getName<!>()
|
s.<!INVISIBLE_MEMBER!>getName<!>()
|
||||||
s.name = ""
|
s.name = ""
|
||||||
s.name = s.<!INVISIBLE_MEMBER!>name<!>
|
s.name = s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
s.setName("")
|
s.setName("")
|
||||||
|
|
||||||
|
val anon1 = object : Super() {
|
||||||
|
fun testAnon() {
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.<!INVISIBLE_MEMBER!>getName<!>()
|
||||||
|
s.name = ""
|
||||||
|
s.name = s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val anon2 = object {
|
||||||
|
fun testAnon() {
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.<!INVISIBLE_MEMBER!>getName<!>()
|
||||||
|
s.name = ""
|
||||||
|
s.name = s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class Nested1 : Super() {
|
||||||
|
fun test(s: Super) {
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.<!INVISIBLE_MEMBER!>getName<!>()
|
||||||
|
s.name = ""
|
||||||
|
s.name = s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Nested2 {
|
||||||
|
fun test(s: Super) {
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.<!INVISIBLE_MEMBER!>getName<!>()
|
||||||
|
s.name = ""
|
||||||
|
s.name = s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class NonSub {
|
||||||
|
fun test(s: Super) {
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.<!INVISIBLE_MEMBER!>getName<!>()
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!> = ""
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!> = s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
|
||||||
|
val anon1 = object : Super() {
|
||||||
|
fun testAnon() {
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.<!INVISIBLE_MEMBER!>getName<!>()
|
||||||
|
s.name = ""
|
||||||
|
s.name = s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val anon2 = object {
|
||||||
|
fun testAnon() {
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.<!INVISIBLE_MEMBER!>getName<!>()
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!> = ""
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!> = s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class Nested1 : Super() {
|
||||||
|
fun test(s: Super) {
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.<!INVISIBLE_MEMBER!>getName<!>()
|
||||||
|
s.name = ""
|
||||||
|
s.name = s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Nested2 {
|
||||||
|
fun test(s: Super) {
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.<!INVISIBLE_MEMBER!>getName<!>()
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!> = ""
|
||||||
|
s.<!INVISIBLE_MEMBER!>name<!> = s.<!INVISIBLE_MEMBER!>name<!>
|
||||||
|
s.setName("")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+50
-5
@@ -2,12 +2,12 @@ package
|
|||||||
|
|
||||||
package j {
|
package j {
|
||||||
|
|
||||||
public abstract class Super {
|
public open class Super {
|
||||||
public constructor Super()
|
public constructor Super()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
protected/*protected and package*/ abstract fun getName(): kotlin.String!
|
protected/*protected and package*/ open fun getName(): kotlin.String!
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public abstract fun setName(/*0*/ s: kotlin.String!): kotlin.Unit
|
public open fun setName(/*0*/ s: kotlin.String!): kotlin.Unit
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,13 +15,58 @@ package j {
|
|||||||
package k {
|
package k {
|
||||||
public fun test(/*0*/ s: j.Super): kotlin.Unit
|
public fun test(/*0*/ s: j.Super): kotlin.Unit
|
||||||
|
|
||||||
|
public abstract class NonSub {
|
||||||
|
public constructor NonSub()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final fun test(/*0*/ s: j.Super): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
public final inner class Nested1 : j.Super {
|
||||||
|
public constructor Nested1()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
protected/*protected and package*/ open override /*1*/ /*fake_override*/ fun getName(): kotlin.String!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun setName(/*0*/ s: kotlin.String!): kotlin.Unit
|
||||||
|
public final fun test(/*0*/ s: j.Super): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Nested2 {
|
||||||
|
public constructor Nested2()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final fun test(/*0*/ s: j.Super): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public abstract class Sub : j.Super {
|
public abstract class Sub : j.Super {
|
||||||
public constructor Sub()
|
public constructor Sub()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
protected/*protected and package*/ abstract override /*1*/ /*fake_override*/ fun getName(): kotlin.String!
|
protected/*protected and package*/ open override /*1*/ /*fake_override*/ fun getName(): kotlin.String!
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public abstract override /*1*/ /*fake_override*/ fun setName(/*0*/ s: kotlin.String!): kotlin.Unit
|
public open override /*1*/ /*fake_override*/ fun setName(/*0*/ s: kotlin.String!): kotlin.Unit
|
||||||
public final fun test(/*0*/ s: j.Super): kotlin.Unit
|
public final fun test(/*0*/ s: j.Super): kotlin.Unit
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
public final inner class Nested1 : j.Super {
|
||||||
|
public constructor Nested1()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
protected/*protected and package*/ open override /*1*/ /*fake_override*/ fun getName(): kotlin.String!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun setName(/*0*/ s: kotlin.String!): kotlin.Unit
|
||||||
|
public final fun test(/*0*/ s: j.Super): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Nested2 {
|
||||||
|
public constructor Nested2()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final fun test(/*0*/ s: j.Super): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
-2
@@ -5,8 +5,8 @@ import JavaClass
|
|||||||
|
|
||||||
fun foo(javaClass: JavaClass) {
|
fun foo(javaClass: JavaClass) {
|
||||||
val v = javaClass.<!INVISIBLE_REFERENCE!>something<!>
|
val v = javaClass.<!INVISIBLE_REFERENCE!>something<!>
|
||||||
javaClass.something = 1
|
javaClass.<!INVISIBLE_REFERENCE!>something<!> = 1
|
||||||
javaClass.<!INVISIBLE_REFERENCE!>something<!>++
|
javaClass.<!INVISIBLE_REFERENCE, INVISIBLE_REFERENCE!>something<!>++
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: JavaClass.java
|
// FILE: JavaClass.java
|
||||||
|
|||||||
Reference in New Issue
Block a user