Optimize runtime representation for callable reference subclasses
Instead of generating overrides for getOwner/getName/getSignature in each anonymous class representing a callable reference, pass them to the superclass' constructor and store as fields. This occupies some small memory but helps to reduce the size of the generated class files, and will be helpful for adding further runtime information to callable references, such as information about implicit conversions this reference has been subject to. Represent owner as java.lang.Class + boolean instead of KDeclarationContainer, so that the unnecessary wrapping Class->KClass wouldn't happen before it's needed, and also to make sure all callable references remain serializable. Note that the argument type where the "is declaration container a class" is passed is int instead of boolean. The plan is to pass the aforementioned implicit conversion information as bits of this same integer value. #KT-27362 Fixed
This commit is contained in:
@@ -32,6 +32,18 @@ public abstract class CallableReference implements KCallable, Serializable {
|
||||
@SinceKotlin(version = "1.1")
|
||||
protected final Object receiver;
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
private final Class owner;
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
private final String name;
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
private final String signature;
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
private final boolean isTopLevel;
|
||||
|
||||
@SinceKotlin(version = "1.1")
|
||||
public static final Object NO_RECEIVER = NoReceiver.INSTANCE;
|
||||
|
||||
@@ -50,7 +62,20 @@ public abstract class CallableReference implements KCallable, Serializable {
|
||||
|
||||
@SinceKotlin(version = "1.1")
|
||||
protected CallableReference(Object receiver) {
|
||||
this(receiver, null, null, null, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param flags Bitmask where bits represent the following flags:<br/>
|
||||
* <li><ul>0 - the owner of this reference is a package, not a class.</ul></li>
|
||||
*/
|
||||
@SinceKotlin(version = "1.4")
|
||||
protected CallableReference(Object receiver, Class owner, String name, String signature, int flags) {
|
||||
this.receiver = receiver;
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.signature = signature;
|
||||
this.isTopLevel = (flags & 1) == 1;
|
||||
}
|
||||
|
||||
protected abstract KCallable computeReflected();
|
||||
@@ -79,14 +104,16 @@ public abstract class CallableReference implements KCallable, Serializable {
|
||||
return result;
|
||||
}
|
||||
|
||||
// The following methods provide the information identifying this callable, which is used by the reflection implementation.
|
||||
// They are supposed to be overridden in each subclass (each anonymous class generated for a callable reference).
|
||||
// The following methods provide the information identifying this callable, which is used by the reflection implementation and
|
||||
// by equals/hashCode/toString. For callable references compiled prior to 1.4, these methods were overridden in each subclass
|
||||
// (each anonymous class generated for a callable reference).
|
||||
|
||||
/**
|
||||
* @return the class or package where the callable should be located, usually specified on the LHS of the '::' operator
|
||||
*/
|
||||
public KDeclarationContainer getOwner() {
|
||||
throw new AbstractMethodError();
|
||||
return owner == null ? null :
|
||||
isTopLevel ? Reflection.getOrCreateKotlinPackage(owner) : Reflection.getOrCreateKotlinClass(owner);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +121,7 @@ public abstract class CallableReference implements KCallable, Serializable {
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
throw new AbstractMethodError();
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +133,7 @@ public abstract class CallableReference implements KCallable, Serializable {
|
||||
* but only as a unique and unambiguous way to map a function/property descriptor to a string.
|
||||
*/
|
||||
public String getSignature() {
|
||||
throw new AbstractMethodError();
|
||||
return signature;
|
||||
}
|
||||
|
||||
// The following methods are the delegating implementations of reflection functions. They are called when you're using reflection
|
||||
|
||||
@@ -9,7 +9,7 @@ import kotlin.SinceKotlin;
|
||||
import kotlin.reflect.KCallable;
|
||||
import kotlin.reflect.KFunction;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@SuppressWarnings({"rawtypes", "unused"})
|
||||
public class FunctionReference extends CallableReference implements FunctionBase, KFunction {
|
||||
private final int arity;
|
||||
|
||||
@@ -19,7 +19,12 @@ public class FunctionReference extends CallableReference implements FunctionBase
|
||||
|
||||
@SinceKotlin(version = "1.1")
|
||||
public FunctionReference(int arity, Object receiver) {
|
||||
super(receiver);
|
||||
this(arity, receiver, null, null, null, 0);
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
public FunctionReference(int arity, Object receiver, Class owner, String name, String signature, int flags) {
|
||||
super(receiver, owner, name, signature, flags);
|
||||
this.arity = arity;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,33 +5,27 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.SinceKotlin;
|
||||
import kotlin.reflect.KClass;
|
||||
import kotlin.reflect.KDeclarationContainer;
|
||||
|
||||
@SuppressWarnings({"unused", "NullableProblems"})
|
||||
@SuppressWarnings({"unused", "rawtypes"})
|
||||
public class FunctionReferenceImpl extends FunctionReference {
|
||||
private final KDeclarationContainer owner;
|
||||
private final String name;
|
||||
private final String signature;
|
||||
|
||||
public FunctionReferenceImpl(int arity, KDeclarationContainer owner, String name, String signature) {
|
||||
super(arity);
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.signature = signature;
|
||||
super(
|
||||
arity, NO_RECEIVER,
|
||||
((ClassBasedDeclarationContainer) owner).getJClass(), name, signature,
|
||||
owner instanceof KClass ? 0 : 1
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KDeclarationContainer getOwner() {
|
||||
return owner;
|
||||
@SinceKotlin(version = "1.4")
|
||||
public FunctionReferenceImpl(int arity, Class owner, String name, String signature, int flags) {
|
||||
super(arity, NO_RECEIVER, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
@SinceKotlin(version = "1.4")
|
||||
public FunctionReferenceImpl(int arity, Object receiver, Class owner, String name, String signature, int flags) {
|
||||
super(arity, receiver, owner, name, signature, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ package kotlin.jvm.internal;
|
||||
import kotlin.SinceKotlin;
|
||||
import kotlin.reflect.KMutableProperty;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@SuppressWarnings({"rawtypes", "unused"})
|
||||
public abstract class MutablePropertyReference extends PropertyReference implements KMutableProperty {
|
||||
public MutablePropertyReference() {
|
||||
}
|
||||
@@ -17,4 +17,9 @@ public abstract class MutablePropertyReference extends PropertyReference impleme
|
||||
public MutablePropertyReference(Object receiver) {
|
||||
super(receiver);
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
public MutablePropertyReference(Object receiver, Class owner, String name, String signature, int flags) {
|
||||
super(receiver, owner, name, signature, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,11 @@ public abstract class MutablePropertyReference0 extends MutablePropertyReference
|
||||
super(receiver);
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
public MutablePropertyReference0(Object receiver, Class owner, String name, String signature, int flags) {
|
||||
super(receiver, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KCallable computeReflected() {
|
||||
return Reflection.mutableProperty0(this);
|
||||
|
||||
+14
-19
@@ -5,33 +5,28 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.SinceKotlin;
|
||||
import kotlin.reflect.KClass;
|
||||
import kotlin.reflect.KDeclarationContainer;
|
||||
|
||||
@SuppressWarnings({"unused", "NullableProblems"})
|
||||
@SuppressWarnings({"unused", "rawtypes"})
|
||||
public class MutablePropertyReference0Impl extends MutablePropertyReference0 {
|
||||
private final KDeclarationContainer owner;
|
||||
private final String name;
|
||||
private final String signature;
|
||||
|
||||
public MutablePropertyReference0Impl(KDeclarationContainer owner, String name, String signature) {
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.signature = signature;
|
||||
super(
|
||||
NO_RECEIVER,
|
||||
((ClassBasedDeclarationContainer) owner).getJClass(), name, signature,
|
||||
owner instanceof KClass ? 0 : 1
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KDeclarationContainer getOwner() {
|
||||
return owner;
|
||||
@SinceKotlin(version = "1.4")
|
||||
public MutablePropertyReference0Impl(Class owner, String name, String signature, int flags) {
|
||||
super(NO_RECEIVER, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
@SinceKotlin(version = "1.4")
|
||||
public MutablePropertyReference0Impl(Object receiver, Class owner, String name, String signature, int flags) {
|
||||
super(receiver, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,6 +13,7 @@ import kotlin.reflect.KProperty1;
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "unused", "NullableProblems"})
|
||||
public abstract class MutablePropertyReference1 extends MutablePropertyReference implements KMutableProperty1 {
|
||||
public MutablePropertyReference1() {
|
||||
super();
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.1")
|
||||
@@ -20,6 +21,11 @@ public abstract class MutablePropertyReference1 extends MutablePropertyReference
|
||||
super(receiver);
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
public MutablePropertyReference1(Object receiver, Class owner, String name, String signature, int flags) {
|
||||
super(receiver, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KCallable computeReflected() {
|
||||
return Reflection.mutableProperty1(this);
|
||||
|
||||
+14
-19
@@ -5,33 +5,28 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.SinceKotlin;
|
||||
import kotlin.reflect.KClass;
|
||||
import kotlin.reflect.KDeclarationContainer;
|
||||
|
||||
@SuppressWarnings({"unused", "NullableProblems"})
|
||||
@SuppressWarnings({"unused", "rawtypes"})
|
||||
public class MutablePropertyReference1Impl extends MutablePropertyReference1 {
|
||||
private final KDeclarationContainer owner;
|
||||
private final String name;
|
||||
private final String signature;
|
||||
|
||||
public MutablePropertyReference1Impl(KDeclarationContainer owner, String name, String signature) {
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.signature = signature;
|
||||
super(
|
||||
NO_RECEIVER,
|
||||
((ClassBasedDeclarationContainer) owner).getJClass(), name, signature,
|
||||
owner instanceof KClass ? 0 : 1
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KDeclarationContainer getOwner() {
|
||||
return owner;
|
||||
@SinceKotlin(version = "1.4")
|
||||
public MutablePropertyReference1Impl(Class owner, String name, String signature, int flags) {
|
||||
super(NO_RECEIVER, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
@SinceKotlin(version = "1.4")
|
||||
public MutablePropertyReference1Impl(Object receiver, Class owner, String name, String signature, int flags) {
|
||||
super(receiver, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -10,8 +10,17 @@ import kotlin.reflect.KCallable;
|
||||
import kotlin.reflect.KMutableProperty2;
|
||||
import kotlin.reflect.KProperty2;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "NullableProblems"})
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "NullableProblems", "unused"})
|
||||
public abstract class MutablePropertyReference2 extends MutablePropertyReference implements KMutableProperty2 {
|
||||
public MutablePropertyReference2() {
|
||||
super();
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
public MutablePropertyReference2(Class owner, String name, String signature, int flags) {
|
||||
super(NO_RECEIVER, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KCallable computeReflected() {
|
||||
return Reflection.mutableProperty2(this);
|
||||
|
||||
+10
-21
@@ -5,33 +5,22 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.SinceKotlin;
|
||||
import kotlin.reflect.KClass;
|
||||
import kotlin.reflect.KDeclarationContainer;
|
||||
|
||||
@SuppressWarnings({"unused", "NullableProblems"})
|
||||
@SuppressWarnings({"unused", "rawtypes"})
|
||||
public class MutablePropertyReference2Impl extends MutablePropertyReference2 {
|
||||
private final KDeclarationContainer owner;
|
||||
private final String name;
|
||||
private final String signature;
|
||||
|
||||
public MutablePropertyReference2Impl(KDeclarationContainer owner, String name, String signature) {
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.signature = signature;
|
||||
super(
|
||||
((ClassBasedDeclarationContainer) owner).getJClass(), name, signature,
|
||||
owner instanceof KClass ? 0 : 1
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KDeclarationContainer getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
@SinceKotlin(version = "1.4")
|
||||
public MutablePropertyReference2Impl(Class owner, String name, String signature, int flags) {
|
||||
super(owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,11 @@ public abstract class PropertyReference extends CallableReference implements KPr
|
||||
super(receiver);
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
public PropertyReference(Object receiver, Class owner, String name, String signature, int flags) {
|
||||
super(receiver, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SinceKotlin(version = "1.1")
|
||||
protected KProperty getReflected() {
|
||||
|
||||
@@ -20,6 +20,11 @@ public abstract class PropertyReference0 extends PropertyReference implements KP
|
||||
super(receiver);
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
public PropertyReference0(Object receiver, Class owner, String name, String signature, int flags) {
|
||||
super(receiver, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KCallable computeReflected() {
|
||||
return Reflection.property0(this);
|
||||
|
||||
@@ -5,33 +5,28 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.SinceKotlin;
|
||||
import kotlin.reflect.KClass;
|
||||
import kotlin.reflect.KDeclarationContainer;
|
||||
|
||||
@SuppressWarnings({"unused", "NullableProblems"})
|
||||
@SuppressWarnings({"unused", "rawtypes"})
|
||||
public class PropertyReference0Impl extends PropertyReference0 {
|
||||
private final KDeclarationContainer owner;
|
||||
private final String name;
|
||||
private final String signature;
|
||||
|
||||
public PropertyReference0Impl(KDeclarationContainer owner, String name, String signature) {
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.signature = signature;
|
||||
super(
|
||||
NO_RECEIVER,
|
||||
((ClassBasedDeclarationContainer) owner).getJClass(), name, signature,
|
||||
owner instanceof KClass ? 0 : 1
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KDeclarationContainer getOwner() {
|
||||
return owner;
|
||||
@SinceKotlin(version = "1.4")
|
||||
public PropertyReference0Impl(Class owner, String name, String signature, int flags) {
|
||||
super(NO_RECEIVER, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
@SinceKotlin(version = "1.4")
|
||||
public PropertyReference0Impl(Object receiver, Class owner, String name, String signature, int flags) {
|
||||
super(receiver, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,6 +12,7 @@ import kotlin.reflect.KProperty1;
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "unused", "NullableProblems"})
|
||||
public abstract class PropertyReference1 extends PropertyReference implements KProperty1 {
|
||||
public PropertyReference1() {
|
||||
super();
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.1")
|
||||
@@ -19,6 +20,11 @@ public abstract class PropertyReference1 extends PropertyReference implements KP
|
||||
super(receiver);
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
public PropertyReference1(Object receiver, Class owner, String name, String signature, int flags) {
|
||||
super(receiver, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KCallable computeReflected() {
|
||||
return Reflection.property1(this);
|
||||
|
||||
@@ -5,33 +5,28 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.SinceKotlin;
|
||||
import kotlin.reflect.KClass;
|
||||
import kotlin.reflect.KDeclarationContainer;
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@SuppressWarnings({"unused", "rawtypes"})
|
||||
public class PropertyReference1Impl extends PropertyReference1 {
|
||||
private final KDeclarationContainer owner;
|
||||
private final String name;
|
||||
private final String signature;
|
||||
|
||||
public PropertyReference1Impl(KDeclarationContainer owner, String name, String signature) {
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.signature = signature;
|
||||
super(
|
||||
NO_RECEIVER,
|
||||
((ClassBasedDeclarationContainer) owner).getJClass(), name, signature,
|
||||
owner instanceof KClass ? 0 : 1
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KDeclarationContainer getOwner() {
|
||||
return owner;
|
||||
@SinceKotlin(version = "1.4")
|
||||
public PropertyReference1Impl(Class owner, String name, String signature, int flags) {
|
||||
super(NO_RECEIVER, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
@SinceKotlin(version = "1.4")
|
||||
public PropertyReference1Impl(Object receiver, Class owner, String name, String signature, int flags) {
|
||||
super(receiver, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,8 +9,17 @@ import kotlin.SinceKotlin;
|
||||
import kotlin.reflect.KCallable;
|
||||
import kotlin.reflect.KProperty2;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "NullableProblems"})
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "NullableProblems", "unused"})
|
||||
public abstract class PropertyReference2 extends PropertyReference implements KProperty2 {
|
||||
public PropertyReference2() {
|
||||
super();
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
public PropertyReference2(Class owner, String name, String signature, int flags) {
|
||||
super(NO_RECEIVER, owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KCallable computeReflected() {
|
||||
return Reflection.property2(this);
|
||||
|
||||
@@ -5,33 +5,22 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.SinceKotlin;
|
||||
import kotlin.reflect.KClass;
|
||||
import kotlin.reflect.KDeclarationContainer;
|
||||
|
||||
@SuppressWarnings({"unused", "NullableProblems"})
|
||||
@SuppressWarnings({"unused", "rawtypes"})
|
||||
public class PropertyReference2Impl extends PropertyReference2 {
|
||||
private final KDeclarationContainer owner;
|
||||
private final String name;
|
||||
private final String signature;
|
||||
|
||||
public PropertyReference2Impl(KDeclarationContainer owner, String name, String signature) {
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.signature = signature;
|
||||
super(
|
||||
((ClassBasedDeclarationContainer) owner).getJClass(), name, signature,
|
||||
owner instanceof KClass ? 0 : 1
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KDeclarationContainer getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
@SinceKotlin(version = "1.4")
|
||||
public PropertyReference2Impl(Class owner, String name, String signature, int flags) {
|
||||
super(owner, name, signature, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -46,6 +46,11 @@ public class Reflection {
|
||||
return factory.createKotlinClass(javaClass, internalName);
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.4")
|
||||
public static KDeclarationContainer getOrCreateKotlinPackage(Class javaClass) {
|
||||
return factory.getOrCreateKotlinPackage(javaClass, "");
|
||||
}
|
||||
|
||||
public static KDeclarationContainer getOrCreateKotlinPackage(Class javaClass, String moduleName) {
|
||||
return factory.getOrCreateKotlinPackage(javaClass, moduleName);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user