Removed descriptors usage from IR copier
This commit is contained in:
@@ -35,13 +35,14 @@ class IrCallImpl(
|
||||
override val symbol: IrFunctionSymbol,
|
||||
override val descriptor: FunctionDescriptor,
|
||||
typeArgumentsCount: Int,
|
||||
valueArgumentsCount: Int,
|
||||
origin: IrStatementOrigin? = null,
|
||||
override val superQualifierSymbol: IrClassSymbol? = null
|
||||
) :
|
||||
IrCallWithIndexedArgumentsBase(
|
||||
startOffset, endOffset, type,
|
||||
typeArgumentsCount,
|
||||
symbol.descriptor.valueParameters.size,
|
||||
valueArgumentsCount,
|
||||
origin
|
||||
),
|
||||
IrCall {
|
||||
@@ -54,7 +55,20 @@ class IrCallImpl(
|
||||
descriptor: FunctionDescriptor,
|
||||
origin: IrStatementOrigin? = null,
|
||||
superQualifierSymbol: IrClassSymbol? = null
|
||||
) : this(startOffset, endOffset, type, symbol, descriptor, descriptor.typeParametersCount, origin, superQualifierSymbol)
|
||||
) : this(startOffset, endOffset, type, symbol, descriptor, descriptor.typeParametersCount,
|
||||
descriptor.valueParameters.size, origin, superQualifierSymbol)
|
||||
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: IrType,
|
||||
symbol: IrFunctionSymbol,
|
||||
descriptor: FunctionDescriptor,
|
||||
typeArgumentsCount: Int,
|
||||
origin: IrStatementOrigin? = null,
|
||||
superQualifierSymbol: IrClassSymbol? = null
|
||||
) : this(startOffset, endOffset, type, symbol, descriptor, typeArgumentsCount,
|
||||
descriptor.valueParameters.size, origin, superQualifierSymbol)
|
||||
|
||||
@Deprecated("Creates unbound symbols")
|
||||
constructor(
|
||||
@@ -71,6 +85,7 @@ class IrCallImpl(
|
||||
createFunctionSymbol(descriptor),
|
||||
descriptor,
|
||||
typeArgumentsCount,
|
||||
descriptor.valueParameters.size,
|
||||
origin,
|
||||
createClassSymbolOrNull(superQualifierDescriptor)
|
||||
)
|
||||
|
||||
+15
-4
@@ -30,14 +30,15 @@ class IrDelegatingConstructorCallImpl(
|
||||
type: IrType,
|
||||
override val symbol: IrConstructorSymbol,
|
||||
override val descriptor: ClassConstructorDescriptor,
|
||||
typeArgumentsCount: Int
|
||||
typeArgumentsCount: Int,
|
||||
valueArgumentsCount: Int
|
||||
) :
|
||||
IrCallWithIndexedArgumentsBase(
|
||||
startOffset,
|
||||
endOffset,
|
||||
type,
|
||||
typeArgumentsCount = typeArgumentsCount,
|
||||
valueArgumentsCount = symbol.descriptor.valueParameters.size
|
||||
valueArgumentsCount = valueArgumentsCount
|
||||
),
|
||||
IrDelegatingConstructorCall {
|
||||
|
||||
@@ -47,7 +48,16 @@ class IrDelegatingConstructorCallImpl(
|
||||
type: IrType,
|
||||
symbol: IrConstructorSymbol,
|
||||
descriptor: ClassConstructorDescriptor
|
||||
) : this(startOffset, endOffset, type, symbol, descriptor, descriptor.typeParametersCount)
|
||||
) : this(startOffset, endOffset, type, symbol, descriptor, descriptor.typeParametersCount, descriptor.valueParameters.size)
|
||||
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: IrType,
|
||||
symbol: IrConstructorSymbol,
|
||||
descriptor: ClassConstructorDescriptor,
|
||||
typeArgumentsCount: Int
|
||||
) : this(startOffset, endOffset, type, symbol, descriptor, typeArgumentsCount, descriptor.valueParameters.size)
|
||||
|
||||
@Deprecated("Creates unbound symbol")
|
||||
constructor(
|
||||
@@ -60,7 +70,8 @@ class IrDelegatingConstructorCallImpl(
|
||||
startOffset, endOffset, type,
|
||||
IrConstructorSymbolImpl(descriptor.original),
|
||||
descriptor,
|
||||
typeArgumentsCount
|
||||
typeArgumentsCount,
|
||||
descriptor.valueParameters.size
|
||||
)
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
|
||||
|
||||
+13
-4
@@ -29,14 +29,15 @@ class IrEnumConstructorCallImpl(
|
||||
endOffset: Int,
|
||||
type: IrType,
|
||||
override val symbol: IrConstructorSymbol,
|
||||
typeArgumentsCount: Int
|
||||
typeArgumentsCount: Int,
|
||||
valueArgumentsCount: Int
|
||||
) :
|
||||
IrCallWithIndexedArgumentsBase(
|
||||
startOffset,
|
||||
endOffset,
|
||||
type,
|
||||
typeArgumentsCount = typeArgumentsCount,
|
||||
valueArgumentsCount = symbol.descriptor.valueParameters.size
|
||||
valueArgumentsCount = valueArgumentsCount
|
||||
),
|
||||
IrEnumConstructorCall {
|
||||
|
||||
@@ -45,7 +46,15 @@ class IrEnumConstructorCallImpl(
|
||||
endOffset: Int,
|
||||
type: IrType,
|
||||
symbol: IrConstructorSymbol
|
||||
) : this(startOffset, endOffset, type, symbol, symbol.descriptor.typeParametersCount)
|
||||
) : this(startOffset, endOffset, type, symbol, symbol.descriptor.typeParametersCount, symbol.descriptor.valueParameters.size)
|
||||
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: IrType,
|
||||
symbol: IrConstructorSymbol,
|
||||
typeArgumentsCount: Int
|
||||
) : this(startOffset, endOffset, type, symbol, typeArgumentsCount, symbol.descriptor.valueParameters.size)
|
||||
|
||||
@Deprecated("Creates unbound symbols")
|
||||
constructor(
|
||||
@@ -54,7 +63,7 @@ class IrEnumConstructorCallImpl(
|
||||
type: IrType,
|
||||
descriptor: ClassConstructorDescriptor,
|
||||
typeArgumentsCount: Int
|
||||
) : this(startOffset, endOffset, type, IrConstructorSymbolImpl(descriptor), typeArgumentsCount)
|
||||
) : this(startOffset, endOffset, type, IrConstructorSymbolImpl(descriptor), typeArgumentsCount, descriptor.valueParameters.size)
|
||||
|
||||
override val descriptor: ClassConstructorDescriptor get() = symbol.descriptor
|
||||
|
||||
|
||||
+14
-2
@@ -31,6 +31,7 @@ class IrFunctionReferenceImpl(
|
||||
override val symbol: IrFunctionSymbol,
|
||||
override val descriptor: FunctionDescriptor,
|
||||
typeArgumentsCount: Int,
|
||||
valueArgumentsCount: Int,
|
||||
origin: IrStatementOrigin? = null
|
||||
) :
|
||||
IrCallWithIndexedArgumentsBase(
|
||||
@@ -38,11 +39,21 @@ class IrFunctionReferenceImpl(
|
||||
endOffset,
|
||||
type,
|
||||
typeArgumentsCount,
|
||||
symbol.descriptor.valueParameters.size,
|
||||
valueArgumentsCount,
|
||||
origin
|
||||
),
|
||||
IrFunctionReference {
|
||||
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: IrType,
|
||||
symbol: IrFunctionSymbol,
|
||||
descriptor: FunctionDescriptor,
|
||||
typeArgumentsCount: Int,
|
||||
origin: IrStatementOrigin? = null
|
||||
): this(startOffset, endOffset, type, symbol, descriptor, typeArgumentsCount, descriptor.valueParameters.size, origin)
|
||||
|
||||
@Deprecated("Creates unbound symbol")
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
@@ -51,7 +62,8 @@ class IrFunctionReferenceImpl(
|
||||
descriptor: FunctionDescriptor,
|
||||
typeArgumentsCount: Int,
|
||||
origin: IrStatementOrigin? = null
|
||||
) : this(startOffset, endOffset, type, createFunctionSymbol(descriptor.original), descriptor, typeArgumentsCount, origin)
|
||||
) : this(startOffset, endOffset, type, createFunctionSymbol(descriptor.original), descriptor,
|
||||
typeArgumentsCount, descriptor.valueParameters.size, origin)
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitFunctionReference(this, data)
|
||||
|
||||
+100
-29
@@ -27,6 +27,8 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import java.util.*
|
||||
|
||||
inline fun <reified T : IrElement> T.deepCopyWithSymbols(initialParent: IrDeclarationParent? = null): T {
|
||||
@@ -36,10 +38,24 @@ inline fun <reified T : IrElement> T.deepCopyWithSymbols(initialParent: IrDeclar
|
||||
return transform(DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper), null).patchDeclarationParents(initialParent) as T
|
||||
}
|
||||
|
||||
interface SymbolRenamer {
|
||||
fun getClassName(symbol: IrClassSymbol): Name = symbol.owner.name
|
||||
fun getFunctionName(symbol: IrSimpleFunctionSymbol): Name = symbol.owner.name
|
||||
fun getFieldName(symbol: IrFieldSymbol): Name = symbol.owner.name
|
||||
fun getFileName(symbol: IrFileSymbol): FqName = symbol.owner.fqName
|
||||
fun getExternalPackageFragmentName(symbol: IrExternalPackageFragmentSymbol): FqName = symbol.owner.fqName
|
||||
fun getEnumEntryName(symbol: IrEnumEntrySymbol): Name = symbol.owner.name
|
||||
fun getVariableName(symbol: IrVariableSymbol): Name = symbol.owner.name
|
||||
fun getTypeParameterName(symbol: IrTypeParameterSymbol): Name = symbol.owner.name
|
||||
fun getValueParameterName(symbol: IrValueParameterSymbol): Name = symbol.owner.name
|
||||
|
||||
object DEFAULT : SymbolRenamer
|
||||
}
|
||||
|
||||
open class DeepCopyIrTreeWithSymbols(
|
||||
private val symbolRemapper: SymbolRemapper,
|
||||
private val typeRemapper: TypeRemapper
|
||||
private val typeRemapper: TypeRemapper,
|
||||
private val symbolRenamer: SymbolRenamer = SymbolRenamer.DEFAULT
|
||||
) : IrElementTransformerVoid() {
|
||||
|
||||
init {
|
||||
@@ -78,7 +94,8 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
|
||||
override fun visitExternalPackageFragment(declaration: IrExternalPackageFragment, data: Nothing?): IrExternalPackageFragment =
|
||||
IrExternalPackageFragmentImpl(
|
||||
symbolRemapper.getDeclaredExternalPackageFragment(declaration.symbol)
|
||||
symbolRemapper.getDeclaredExternalPackageFragment(declaration.symbol),
|
||||
symbolRenamer.getExternalPackageFragmentName(declaration.symbol)
|
||||
).apply {
|
||||
declaration.transformDeclarationsTo(this)
|
||||
}
|
||||
@@ -86,7 +103,8 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
override fun visitFile(declaration: IrFile): IrFile =
|
||||
IrFileImpl(
|
||||
declaration.fileEntry,
|
||||
symbolRemapper.getDeclaredFile(declaration.symbol)
|
||||
symbolRemapper.getDeclaredFile(declaration.symbol),
|
||||
symbolRenamer.getFileName(declaration.symbol)
|
||||
).apply {
|
||||
transformAnnotations(declaration)
|
||||
fileAnnotations.addAll(declaration.fileAnnotations)
|
||||
@@ -100,7 +118,16 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
IrClassImpl(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
mapDeclarationOrigin(declaration.origin),
|
||||
symbolRemapper.getDeclaredClass(declaration.symbol)
|
||||
symbolRemapper.getDeclaredClass(declaration.symbol),
|
||||
symbolRenamer.getClassName(declaration.symbol),
|
||||
declaration.kind,
|
||||
declaration.visibility,
|
||||
declaration.modality,
|
||||
declaration.isCompanion,
|
||||
declaration.isInner,
|
||||
declaration.isData,
|
||||
declaration.isExternal,
|
||||
declaration.isInline
|
||||
).apply {
|
||||
transformAnnotations(declaration)
|
||||
copyTypeParametersFrom(declaration)
|
||||
@@ -124,7 +151,14 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
IrFunctionImpl(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
mapDeclarationOrigin(declaration.origin),
|
||||
symbolRemapper.getDeclaredFunction(declaration.symbol)
|
||||
symbolRemapper.getDeclaredFunction(declaration.symbol),
|
||||
symbolRenamer.getFunctionName(declaration.symbol),
|
||||
declaration.visibility,
|
||||
declaration.modality,
|
||||
declaration.isInline,
|
||||
declaration.isExternal,
|
||||
declaration.isTailrec,
|
||||
declaration.isSuspend
|
||||
).apply {
|
||||
declaration.overriddenSymbols.mapTo(overriddenSymbols) {
|
||||
symbolRemapper.getReferencedFunction(it) as IrSimpleFunctionSymbol
|
||||
@@ -136,7 +170,12 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
IrConstructorImpl(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
mapDeclarationOrigin(declaration.origin),
|
||||
symbolRemapper.getDeclaredConstructor(declaration.symbol)
|
||||
symbolRemapper.getDeclaredConstructor(declaration.symbol),
|
||||
declaration.name,
|
||||
declaration.visibility,
|
||||
declaration.isInline,
|
||||
declaration.isExternal,
|
||||
declaration.isPrimary
|
||||
).apply {
|
||||
transformFunctionChildren(declaration)
|
||||
}
|
||||
@@ -163,7 +202,7 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
mapDeclarationOrigin(declaration.origin),
|
||||
declaration.isDelegated,
|
||||
declaration.descriptor,
|
||||
declaration.descriptor, // TODO
|
||||
declaration.backingField?.transform(),
|
||||
declaration.getter?.transform(),
|
||||
declaration.setter?.transform()
|
||||
@@ -176,7 +215,12 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
mapDeclarationOrigin(declaration.origin),
|
||||
symbolRemapper.getDeclaredField(declaration.symbol),
|
||||
declaration.type.remapType()
|
||||
symbolRenamer.getFieldName(declaration.symbol),
|
||||
declaration.type.remapType(),
|
||||
declaration.visibility,
|
||||
declaration.isFinal,
|
||||
declaration.isExternal,
|
||||
declaration.isStatic
|
||||
).apply {
|
||||
transformAnnotations(declaration)
|
||||
declaration.overriddenSymbols.mapTo(overriddenSymbols) {
|
||||
@@ -189,7 +233,7 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
IrLocalDelegatedPropertyImpl(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
mapDeclarationOrigin(declaration.origin),
|
||||
declaration.descriptor,
|
||||
declaration.descriptor, // TODO
|
||||
declaration.type.remapType(),
|
||||
declaration.delegate.transform(),
|
||||
declaration.getter.transform(),
|
||||
@@ -202,7 +246,8 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
IrEnumEntryImpl(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
mapDeclarationOrigin(declaration.origin),
|
||||
symbolRemapper.getDeclaredEnumEntry(declaration.symbol)
|
||||
symbolRemapper.getDeclaredEnumEntry(declaration.symbol),
|
||||
symbolRenamer.getEnumEntryName(declaration.symbol)
|
||||
).apply {
|
||||
transformAnnotations(declaration)
|
||||
correspondingClass = declaration.correspondingClass?.transform()
|
||||
@@ -223,7 +268,11 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
mapDeclarationOrigin(declaration.origin),
|
||||
symbolRemapper.getDeclaredVariable(declaration.symbol),
|
||||
declaration.type.remapType()
|
||||
symbolRenamer.getVariableName(declaration.symbol),
|
||||
declaration.type.remapType(),
|
||||
declaration.isVar,
|
||||
declaration.isConst,
|
||||
declaration.isLateinit
|
||||
).apply {
|
||||
transformAnnotations(declaration)
|
||||
initializer = declaration.initializer?.transform()
|
||||
@@ -239,7 +288,11 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
IrTypeParameterImpl(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
mapDeclarationOrigin(declaration.origin),
|
||||
symbolRemapper.getDeclaredTypeParameter(declaration.symbol)
|
||||
symbolRemapper.getDeclaredTypeParameter(declaration.symbol),
|
||||
symbolRenamer.getTypeParameterName(declaration.symbol),
|
||||
declaration.index,
|
||||
declaration.isReified,
|
||||
declaration.variance
|
||||
).apply {
|
||||
transformAnnotations(declaration)
|
||||
}
|
||||
@@ -263,8 +316,12 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
mapDeclarationOrigin(declaration.origin),
|
||||
symbolRemapper.getDeclaredValueParameter(declaration.symbol),
|
||||
symbolRenamer.getValueParameterName(declaration.symbol),
|
||||
declaration.index,
|
||||
declaration.type.remapType(),
|
||||
declaration.varargElementType?.remapType()
|
||||
declaration.varargElementType?.remapType(),
|
||||
declaration.isCrossinline,
|
||||
declaration.isNoinline
|
||||
).apply {
|
||||
transformAnnotations(declaration)
|
||||
defaultValue = declaration.defaultValue?.transform()
|
||||
@@ -305,12 +362,22 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
)
|
||||
|
||||
override fun visitBlock(expression: IrBlock): IrBlock =
|
||||
IrBlockImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type.remapType(),
|
||||
mapStatementOrigin(expression.origin),
|
||||
expression.statements.map { it.transform() }
|
||||
)
|
||||
if (expression is IrReturnableBlock)
|
||||
IrReturnableBlockImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type.remapType(),
|
||||
symbolRemapper.getReferencedReturnableBlock(expression.symbol),
|
||||
mapStatementOrigin(expression.origin),
|
||||
expression.statements.map { it.transform() },
|
||||
expression.sourceFileName
|
||||
)
|
||||
else
|
||||
IrBlockImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type.remapType(),
|
||||
mapStatementOrigin(expression.origin),
|
||||
expression.statements.map { it.transform() }
|
||||
)
|
||||
|
||||
override fun visitComposite(expression: IrComposite): IrComposite =
|
||||
IrCompositeImpl(
|
||||
@@ -408,8 +475,9 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type.remapType(),
|
||||
newCallee,
|
||||
expression.descriptor, // TODO substitute referenced descriptor
|
||||
newCallee.descriptor,
|
||||
expression.typeArgumentsCount,
|
||||
expression.valueArgumentsCount,
|
||||
mapStatementOrigin(expression.origin),
|
||||
symbolRemapper.getReferencedClassOrNull(expression.superQualifierSymbol)
|
||||
).apply {
|
||||
@@ -426,8 +494,8 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
|
||||
private fun <T : IrMemberAccessExpression> T.transformValueArguments(original: T) {
|
||||
transformReceiverArguments(original)
|
||||
mapValueParameters { valueParameter ->
|
||||
original.getValueArgument(valueParameter)?.transform()
|
||||
for (i in 0 until original.valueArgumentsCount) {
|
||||
putValueArgument(i, original.getValueArgument(i)?.transform())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,7 +505,7 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type.remapType(),
|
||||
newConstructor,
|
||||
expression.descriptor,
|
||||
newConstructor.descriptor,
|
||||
expression.typeArgumentsCount
|
||||
).apply {
|
||||
copyRemappedTypeArgumentsFrom(expression)
|
||||
@@ -465,18 +533,21 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
expression.argument.transform()
|
||||
)
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrFunctionReference =
|
||||
IrFunctionReferenceImpl(
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrFunctionReference {
|
||||
val symbol = symbolRemapper.getReferencedFunction(expression.symbol)
|
||||
return IrFunctionReferenceImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type.remapType(),
|
||||
symbolRemapper.getReferencedFunction(expression.symbol),
|
||||
expression.descriptor, // TODO substitute referenced descriptor
|
||||
symbol,
|
||||
symbol.descriptor,
|
||||
expression.typeArgumentsCount,
|
||||
expression.valueArgumentsCount,
|
||||
mapStatementOrigin(expression.origin)
|
||||
).apply {
|
||||
copyRemappedTypeArgumentsFrom(expression)
|
||||
transformValueArguments(expression)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitPropertyReference(expression: IrPropertyReference): IrPropertyReference =
|
||||
IrPropertyReferenceImpl(
|
||||
@@ -509,7 +580,7 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type.remapType(),
|
||||
symbolRemapper.getReferencedClassifier(expression.symbol),
|
||||
expression.classType
|
||||
expression.classType.remapType()
|
||||
)
|
||||
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrInstanceInitializerCall =
|
||||
@@ -524,7 +595,7 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type.remapType(),
|
||||
expression.operator,
|
||||
expression.typeOperand,
|
||||
expression.typeOperand.remapType(),
|
||||
symbolRemapper.getReferencedClassifier(expression.typeOperandClassifier),
|
||||
expression.argument.transform()
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user