FIR: introduce symbols + type parameter resolve #KT-24064 Fixed
This commit is contained in:
@@ -9,6 +9,9 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeKotlinErrorType
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
@@ -293,6 +296,11 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
|
||||
println()
|
||||
}
|
||||
|
||||
override fun visitResolvedTypeParameter(resolvedTypeParameter: FirResolvedTypeParameter) {
|
||||
print("(resolved) ")
|
||||
visitTypeParameter(resolvedTypeParameter)
|
||||
}
|
||||
|
||||
override fun visitTypeParameter(typeParameter: FirTypeParameter) {
|
||||
typeParameter.annotations.renderAnnotations()
|
||||
typeParameter.variance.renderVariance()
|
||||
@@ -399,33 +407,38 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
|
||||
visitTypeWithNullability(functionType)
|
||||
}
|
||||
|
||||
private fun ConeSymbol.asString(): String {
|
||||
return when (this) {
|
||||
is ConeClassLikeSymbol -> classId.asString()
|
||||
is FirTypeParameterSymbol -> fir.name.asString()
|
||||
else -> "Unsupported: ${this::class}"
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.asString(): String {
|
||||
return when (this) {
|
||||
is ConeKotlinErrorType -> "error: $reason"
|
||||
is ConeClassType -> {
|
||||
is ConeClassLikeType -> {
|
||||
val sb = StringBuilder()
|
||||
val fqName = fqName
|
||||
val packageFqName = fqName.packageFqName
|
||||
if (packageFqName.isRoot) {
|
||||
sb.append("<root>")
|
||||
} else {
|
||||
sb.append(packageFqName.asString().replace('.', '/'))
|
||||
sb.append(symbol.classId.asString())
|
||||
if (typeArguments.isNotEmpty()) {
|
||||
sb.append(typeArguments.joinToString(prefix = "<", postfix = ">") { it ->
|
||||
when (it) {
|
||||
StarProjection -> "*"
|
||||
is ConeKotlinTypeProjectionIn -> "in ${it.type.asString()}"
|
||||
is ConeKotlinTypeProjectionOut -> "out ${it.type.asString()}"
|
||||
is ConeKotlinType -> it.asString()
|
||||
}
|
||||
})
|
||||
}
|
||||
sb.append('.')
|
||||
sb.append(fqName.relativeClassName.asString())
|
||||
sb.append(typeArguments.joinToString { it ->
|
||||
when (it) {
|
||||
StarProjection -> "*"
|
||||
is ConeKotlinTypeProjectionIn -> "in ${it.type.asString()}"
|
||||
is ConeKotlinTypeProjectionOut -> "out ${it.type.asString()}"
|
||||
is ConeKotlinType -> it.asString()
|
||||
}
|
||||
})
|
||||
if (this is ConeAbbreviatedType) {
|
||||
sb.append(" = ${this.directExpansion.asString()}")
|
||||
}
|
||||
sb.toString()
|
||||
}
|
||||
is ConeTypeParameterType -> {
|
||||
symbol.asString()
|
||||
}
|
||||
else -> "Unsupported: $this"
|
||||
}
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.declarations
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirDescriptorOwner
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
|
||||
interface FirResolvedTypeParameter : FirTypeParameter, FirDescriptorOwner<FirResolvedTypeParameter> {
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
|
||||
visitor.visitResolvedTypeParameter(this, data)
|
||||
}
|
||||
@@ -7,16 +7,22 @@ package org.jetbrains.kotlin.fir.declarations
|
||||
|
||||
import org.jetbrains.kotlin.fir.BaseTransformedType
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.symbols.FirSymbolOwner
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirType
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
@BaseTransformedType
|
||||
interface FirTypeParameter : FirNamedDeclaration, FirAnnotationContainer {
|
||||
interface FirTypeParameter : FirNamedDeclaration, FirAnnotationContainer, FirSymbolOwner<FirTypeParameter> {
|
||||
val variance: Variance
|
||||
|
||||
val isReified: Boolean
|
||||
|
||||
val bounds: List<FirType>
|
||||
|
||||
override val symbol: FirTypeParameterSymbol
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
|
||||
visitor.visitTypeParameter(this, data)
|
||||
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.declarations.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirBasedDescriptor
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvedTypeParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
|
||||
class FirResolvedTypeParameterImpl(val delegate: FirTypeParameter, override val descriptor: FirBasedDescriptor<FirResolvedTypeParameter>) :
|
||||
FirResolvedTypeParameter, FirTypeParameter by delegate {
|
||||
|
||||
init {
|
||||
symbol.bind(this)
|
||||
descriptor.bind(this)
|
||||
}
|
||||
|
||||
override fun accept(visitor: FirVisitorVoid) {
|
||||
return super<FirResolvedTypeParameter>.accept(visitor)
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R {
|
||||
return super<FirResolvedTypeParameter>.accept(visitor, data)
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
|
||||
import org.jetbrains.kotlin.fir.transformInplace
|
||||
import org.jetbrains.kotlin.fir.transformSingle
|
||||
import org.jetbrains.kotlin.fir.types.FirType
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
@@ -24,6 +25,7 @@ class FirTypeAliasImpl(
|
||||
override var expandedType: FirType
|
||||
) : FirAbstractMemberDeclaration(session, psi, name, visibility, Modality.FINAL), FirTypeAlias {
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||
typeParameters.transformInplace(transformer, data)
|
||||
expandedType = expandedType.transformSingle(transformer, data)
|
||||
|
||||
return this
|
||||
|
||||
+17
-1
@@ -6,9 +6,13 @@
|
||||
package org.jetbrains.kotlin.fir.declarations.impl
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.transformInplace
|
||||
import org.jetbrains.kotlin.fir.types.FirType
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
@@ -16,7 +20,19 @@ class FirTypeParameterImpl(
|
||||
session: FirSession,
|
||||
psi: PsiElement?,
|
||||
name: Name,
|
||||
override val variance: Variance
|
||||
override val variance: Variance,
|
||||
override val isReified: Boolean,
|
||||
override val symbol: FirTypeParameterSymbol
|
||||
) : FirAbstractNamedAnnotatedDeclaration(session, psi, name), FirTypeParameter {
|
||||
init {
|
||||
symbol.bind(this)
|
||||
}
|
||||
|
||||
override val bounds = mutableListOf<FirType>()
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||
bounds.transformInplace(transformer, data)
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.symbols
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
|
||||
abstract class AbstractFirBasedSymbol<E> : FirBasedSymbol<E> where E : FirElement, E : FirSymbolOwner<E> {
|
||||
|
||||
override lateinit var fir: E
|
||||
|
||||
override fun bind(e: E) {
|
||||
fir = e
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.symbols
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
|
||||
interface FirBasedSymbol<E> : ConeSymbol where E : FirElement, E : FirSymbolOwner<E> {
|
||||
val fir: E
|
||||
|
||||
fun bind(e: E)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.symbols
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
|
||||
interface FirSymbolOwner<E> where E : FirElement, E : FirSymbolOwner<E> {
|
||||
val symbol: FirBasedSymbol<E>
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.symbols.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterSymbol
|
||||
|
||||
class FirTypeParameterSymbol : AbstractFirBasedSymbol<FirTypeParameter>(), ConeTypeParameterSymbol
|
||||
@@ -15,4 +15,4 @@ interface FirResolvedType : FirTypeWithNullability {
|
||||
}
|
||||
|
||||
inline fun <reified T : ConeKotlinType> FirType.coneTypeUnsafe() = (this as FirResolvedType).type as T
|
||||
inline fun <reified T : ConeKotlinType> FirType.coneTypeSafe() = (this as FirResolvedType).type as? T
|
||||
inline fun <reified T : ConeKotlinType> FirType.coneTypeSafe() = (this as? FirResolvedType)?.type as? T
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.types.impl
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.symbols.toSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
@@ -23,7 +24,8 @@ sealed class FirBuiltinType(
|
||||
ClassId(
|
||||
KOTLIN_PACKAGE_FQ_NAME,
|
||||
Name.identifier(name)
|
||||
), emptyList()
|
||||
).toSymbol(),
|
||||
emptyList()
|
||||
)
|
||||
|
||||
final override val isNullable = false
|
||||
|
||||
@@ -6,17 +6,29 @@
|
||||
package org.jetbrains.kotlin.fir.types.impl
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.transformInplace
|
||||
import org.jetbrains.kotlin.fir.transformSingle
|
||||
import org.jetbrains.kotlin.fir.types.FirFunctionType
|
||||
import org.jetbrains.kotlin.fir.types.FirType
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
|
||||
class FirFunctionTypeImpl(
|
||||
session: FirSession,
|
||||
psi: PsiElement?,
|
||||
isNullable: Boolean,
|
||||
override val receiverType: FirType?,
|
||||
override val returnType: FirType
|
||||
override var receiverType: FirType?,
|
||||
override var returnType: FirType
|
||||
) : FirAbstractAnnotatedType(session, psi, isNullable), FirFunctionType {
|
||||
override val valueParameters = mutableListOf<FirValueParameter>()
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||
receiverType = receiverType?.transformSingle(transformer, data)
|
||||
returnType = returnType.transformSingle(transformer, data)
|
||||
valueParameters.transformInplace(transformer, data)
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
+11
-2
@@ -6,14 +6,23 @@
|
||||
package org.jetbrains.kotlin.fir.types.impl
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.transformSingle
|
||||
import org.jetbrains.kotlin.fir.types.FirType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
class FirTypeProjectionWithVarianceImpl(
|
||||
override val session: FirSession,
|
||||
override val psi: PsiElement?,
|
||||
override val variance: Variance,
|
||||
override val type: FirType
|
||||
) : FirTypeProjectionWithVariance
|
||||
override var type: FirType
|
||||
) : FirTypeProjectionWithVariance {
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||
type = type.transformSingle(transformer, data)
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,14 @@
|
||||
package org.jetbrains.kotlin.fir.types.impl
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.transformInplace
|
||||
import org.jetbrains.kotlin.fir.types.FirQualifierPart
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
||||
import org.jetbrains.kotlin.fir.types.FirUserType
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.types.TypeProjectionBase
|
||||
import java.util.*
|
||||
|
||||
class FirUserTypeImpl(
|
||||
@@ -17,4 +22,12 @@ class FirUserTypeImpl(
|
||||
isNullable: Boolean
|
||||
) : FirAbstractAnnotatedType(session, psi, isNullable), FirUserType {
|
||||
override val qualifier = LinkedList<FirQualifierPart>()
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||
for (part in qualifier) {
|
||||
(part.typeArguments as MutableList<FirTypeProjection>).transformInplace(transformer, data)
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
+12
-4
@@ -82,6 +82,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
|
||||
return transformNamedDeclaration(typeParameter, data)
|
||||
}
|
||||
|
||||
open fun transformResolvedTypeParameter(resolvedTypeParameter: FirResolvedTypeParameter, data: D): CompositeTransformResult<FirDeclaration> {
|
||||
return transformTypeParameter(resolvedTypeParameter, data)
|
||||
}
|
||||
|
||||
open fun transformProperty(property: FirProperty, data: D): CompositeTransformResult<FirDeclaration> {
|
||||
return transformDeclaration(property, data)
|
||||
}
|
||||
@@ -246,6 +250,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
|
||||
return transformTypeAlias(typeAlias, data)
|
||||
}
|
||||
|
||||
final override fun visitTypeParameter(typeParameter: FirTypeParameter, data: D): CompositeTransformResult<FirElement> {
|
||||
return transformTypeParameter(typeParameter, data)
|
||||
}
|
||||
|
||||
final override fun visitTypeProjection(typeProjection: FirTypeProjection, data: D): CompositeTransformResult<FirElement> {
|
||||
return transformTypeProjection(typeProjection, data)
|
||||
}
|
||||
@@ -322,10 +330,6 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
|
||||
return transformResolvedImport(resolvedImport, data)
|
||||
}
|
||||
|
||||
final override fun visitTypeParameter(typeParameter: FirTypeParameter, data: D): CompositeTransformResult<FirElement> {
|
||||
return transformTypeParameter(typeParameter, data)
|
||||
}
|
||||
|
||||
final override fun visitFile(file: FirFile, data: D): CompositeTransformResult<FirElement> {
|
||||
return transformFile(file, data)
|
||||
}
|
||||
@@ -346,6 +350,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
|
||||
return transformResolvedTypeAlias(resolvedTypeAlias, data)
|
||||
}
|
||||
|
||||
final override fun visitResolvedTypeParameter(resolvedTypeParameter: FirResolvedTypeParameter, data: D): CompositeTransformResult<FirElement> {
|
||||
return transformResolvedTypeParameter(resolvedTypeParameter, data)
|
||||
}
|
||||
|
||||
final override fun visitStarProjection(starProjection: FirStarProjection, data: D): CompositeTransformResult<FirElement> {
|
||||
return transformStarProjection(starProjection, data)
|
||||
}
|
||||
|
||||
@@ -82,6 +82,10 @@ abstract class FirVisitor<out R, in D> {
|
||||
return visitNamedDeclaration(typeParameter, data)
|
||||
}
|
||||
|
||||
open fun visitResolvedTypeParameter(resolvedTypeParameter: FirResolvedTypeParameter, data: D): R {
|
||||
return visitTypeParameter(resolvedTypeParameter, data)
|
||||
}
|
||||
|
||||
open fun visitProperty(property: FirProperty, data: D): R {
|
||||
return visitDeclaration(property, data)
|
||||
}
|
||||
|
||||
+12
-4
@@ -82,6 +82,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitNamedDeclaration(typeParameter, null)
|
||||
}
|
||||
|
||||
open fun visitResolvedTypeParameter(resolvedTypeParameter: FirResolvedTypeParameter) {
|
||||
visitTypeParameter(resolvedTypeParameter, null)
|
||||
}
|
||||
|
||||
open fun visitProperty(property: FirProperty) {
|
||||
visitDeclaration(property, null)
|
||||
}
|
||||
@@ -246,6 +250,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitTypeAlias(typeAlias)
|
||||
}
|
||||
|
||||
final override fun visitTypeParameter(typeParameter: FirTypeParameter, data: Nothing?) {
|
||||
visitTypeParameter(typeParameter)
|
||||
}
|
||||
|
||||
final override fun visitTypeProjection(typeProjection: FirTypeProjection, data: Nothing?) {
|
||||
visitTypeProjection(typeProjection)
|
||||
}
|
||||
@@ -322,10 +330,6 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitResolvedImport(resolvedImport)
|
||||
}
|
||||
|
||||
final override fun visitTypeParameter(typeParameter: FirTypeParameter, data: Nothing?) {
|
||||
visitTypeParameter(typeParameter)
|
||||
}
|
||||
|
||||
final override fun visitFile(file: FirFile, data: Nothing?) {
|
||||
visitFile(file)
|
||||
}
|
||||
@@ -346,6 +350,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitResolvedTypeAlias(resolvedTypeAlias)
|
||||
}
|
||||
|
||||
final override fun visitResolvedTypeParameter(resolvedTypeParameter: FirResolvedTypeParameter, data: Nothing?) {
|
||||
visitResolvedTypeParameter(resolvedTypeParameter)
|
||||
}
|
||||
|
||||
final override fun visitStarProjection(starProjection: FirStarProjection, data: Nothing?) {
|
||||
visitStarProjection(starProjection)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user