Drop AbstractLazyResolveDescriptorRendererTest with DescriptorRendererTest refactoring
This commit is contained in:
-171
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.lazy;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.ConfigurationKind;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
|
||||
import org.jetbrains.jet.context.ContextPackage;
|
||||
import org.jetbrains.jet.context.GlobalContextImpl;
|
||||
import org.jetbrains.jet.di.InjectorForLazyResolve;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.ModuleDescriptorImpl;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.TopDownAnalyzerFacadeForJVM;
|
||||
import org.jetbrains.jet.lang.resolve.kotlin.JavaDeclarationCheckerProvider;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.psi.PsiPackage.JetPsiFactory;
|
||||
|
||||
public abstract class AbstractLazyResolveDescriptorRendererTest extends KotlinTestWithEnvironment {
|
||||
@Override
|
||||
protected JetCoreEnvironment createEnvironment() {
|
||||
return createEnvironmentWithMockJdk(ConfigurationKind.ALL);
|
||||
}
|
||||
|
||||
protected DeclarationDescriptor getDescriptor(JetDeclaration declaration, ResolveSession resolveSession) {
|
||||
return resolveSession.resolveToDescriptor(declaration);
|
||||
}
|
||||
|
||||
protected void doTest(@NotNull String testFile) throws IOException {
|
||||
String fileText = FileUtil.loadFile(new File(testFile), true);
|
||||
|
||||
JetFile psiFile = JetPsiFactory(getProject()).createFile(fileText);
|
||||
Collection<JetFile> files = Lists.newArrayList(psiFile);
|
||||
|
||||
final ModuleDescriptorImpl lazyModule = TopDownAnalyzerFacadeForJVM.createJavaModule("<lazy module>");
|
||||
lazyModule.addDependencyOnModule(lazyModule);
|
||||
lazyModule.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule());
|
||||
lazyModule.seal();
|
||||
GlobalContextImpl globalContext = ContextPackage.GlobalContext();
|
||||
final ResolveSession resolveSession = new InjectorForLazyResolve(
|
||||
getProject(), globalContext, lazyModule,
|
||||
new FileBasedDeclarationProviderFactory(globalContext.getStorageManager(), files),
|
||||
new BindingTraceContext(),
|
||||
JavaDeclarationCheckerProvider.INSTANCE$).getResolveSession();
|
||||
lazyModule.initialize(resolveSession.getPackageFragmentProvider());
|
||||
|
||||
final List<DeclarationDescriptor> descriptors = new ArrayList<DeclarationDescriptor>();
|
||||
psiFile.accept(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitJetFile(@NotNull JetFile file) {
|
||||
FqName fqName = file.getPackageFqName();
|
||||
if (!fqName.isRoot()) {
|
||||
PackageViewDescriptor packageDescriptor = lazyModule.getPackage(fqName);
|
||||
descriptors.add(packageDescriptor);
|
||||
}
|
||||
file.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassObject(@NotNull JetClassObject classObject) {
|
||||
classObject.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitParameter(@NotNull JetParameter parameter) {
|
||||
PsiElement declaringElement = parameter.getParent().getParent();
|
||||
if (declaringElement instanceof JetFunctionType) {
|
||||
return;
|
||||
}
|
||||
if (declaringElement instanceof JetNamedFunction) {
|
||||
JetNamedFunction jetNamedFunction = (JetNamedFunction) declaringElement;
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) getDescriptor(jetNamedFunction, resolveSession);
|
||||
addCorrespondingParameterDescriptor(functionDescriptor, parameter);
|
||||
}
|
||||
else if (declaringElement instanceof JetClass) {
|
||||
// Primary constructor parameter
|
||||
JetClass jetClass = (JetClass) declaringElement;
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) getDescriptor(jetClass, resolveSession);
|
||||
addCorrespondingParameterDescriptor(classDescriptor.getConstructors().iterator().next(), parameter);
|
||||
}
|
||||
else {
|
||||
super.visitParameter(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
private void addCorrespondingParameterDescriptor(FunctionDescriptor functionDescriptor, JetParameter parameter) {
|
||||
for (ValueParameterDescriptor valueParameterDescriptor : functionDescriptor.getValueParameters()) {
|
||||
if (valueParameterDescriptor.getName().equals(parameter.getNameAsName())) {
|
||||
descriptors.add(valueParameterDescriptor);
|
||||
}
|
||||
}
|
||||
parameter.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPropertyAccessor(@NotNull JetPropertyAccessor accessor) {
|
||||
JetProperty parent = (JetProperty) accessor.getParent();
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) getDescriptor(parent, resolveSession);
|
||||
if (accessor.isGetter()) {
|
||||
descriptors.add(propertyDescriptor.getGetter());
|
||||
}
|
||||
else {
|
||||
descriptors.add(propertyDescriptor.getSetter());
|
||||
}
|
||||
accessor.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAnonymousInitializer(@NotNull JetClassInitializer initializer) {
|
||||
initializer.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDeclaration(@NotNull JetDeclaration element) {
|
||||
DeclarationDescriptor descriptor = getDescriptor(element, resolveSession);
|
||||
descriptors.add(descriptor);
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
descriptors.addAll(((ClassDescriptor) descriptor).getConstructors());
|
||||
}
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJetElement(@NotNull JetElement element) {
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
});
|
||||
|
||||
StringBuilder renderedDescriptors = new StringBuilder();
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
if (renderedDescriptors.length() != 0) {
|
||||
renderedDescriptors.append("\n");
|
||||
}
|
||||
renderedDescriptors.append(DescriptorRenderer.FQ_NAMES_IN_TYPES.render(descriptor));
|
||||
}
|
||||
|
||||
Document document = new DocumentImpl(psiFile.getText());
|
||||
assertEquals(JetTestUtils.getLastCommentedLines(document), renderedDescriptors.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.renderer
|
||||
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.jet.lang.psi.JetVisitorVoid
|
||||
import org.jetbrains.jet.lang.psi.JetElement
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl
|
||||
import org.jetbrains.jet.JetTestUtils
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment
|
||||
import org.jetbrains.jet.ConfigurationKind
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import java.io.File
|
||||
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration
|
||||
import org.jetbrains.jet.lang.resolve.java.TopDownAnalyzerFacadeForJVM
|
||||
import org.jetbrains.jet.context.GlobalContext
|
||||
import org.jetbrains.jet.di.InjectorForLazyResolve
|
||||
import org.jetbrains.jet.lang.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
|
||||
import org.jetbrains.jet.cli.jvm.compiler.CliLightClassGenerationSupport
|
||||
import org.jetbrains.jet.lang.resolve.kotlin.JavaDeclarationCheckerProvider
|
||||
import org.jetbrains.jet.lang.psi.JetFile
|
||||
import org.jetbrains.jet.lang.psi.JetClassObject
|
||||
import org.jetbrains.jet.lang.psi.JetParameter
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionType
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
import org.jetbrains.jet.lang.psi.JetClass
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.jet.lang.psi.JetPropertyAccessor
|
||||
import org.jetbrains.jet.lang.psi.JetProperty
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.jet.lang.psi.JetClassInitializer
|
||||
import org.jetbrains.jet.lang.resolve.lazy.KotlinTestWithEnvironment
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.jet.lang.psi.JetPsiFactory
|
||||
|
||||
public abstract class AbstractDescriptorRendererTest : KotlinTestWithEnvironment() {
|
||||
protected open fun getDescriptor(declaration: JetDeclaration, resolveSession: ResolveSession): DeclarationDescriptor {
|
||||
return resolveSession.resolveToDescriptor(declaration)
|
||||
}
|
||||
|
||||
public fun doTest(path: String) {
|
||||
val fileText = FileUtil.loadFile(File(path), true)
|
||||
val psiFile = JetPsiFactory(getProject()).createFile(fileText)
|
||||
|
||||
val lazyModule = TopDownAnalyzerFacadeForJVM.createSealedJavaModule()
|
||||
val globalContext = GlobalContext()
|
||||
|
||||
val resolveSession = InjectorForLazyResolve(
|
||||
getProject(), globalContext, lazyModule,
|
||||
FileBasedDeclarationProviderFactory(globalContext.storageManager, listOf(psiFile)),
|
||||
CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace(),
|
||||
JavaDeclarationCheckerProvider).getResolveSession()
|
||||
|
||||
lazyModule.initialize(resolveSession.getPackageFragmentProvider())
|
||||
|
||||
val descriptors = ArrayList<DeclarationDescriptor>()
|
||||
|
||||
psiFile.accept(object : JetVisitorVoid() {
|
||||
override fun visitJetFile(file: JetFile) {
|
||||
val fqName = file.getPackageFqName()
|
||||
if (!fqName.isRoot()) {
|
||||
val packageDescriptor = lazyModule.getPackage(fqName)
|
||||
descriptors.add(packageDescriptor)
|
||||
}
|
||||
file.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitClassObject(classObject: JetClassObject) {
|
||||
classObject.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitParameter(parameter: JetParameter) {
|
||||
val declaringElement = parameter.getParent().getParent()
|
||||
when (declaringElement) {
|
||||
is JetFunctionType -> return
|
||||
is JetNamedFunction ->
|
||||
addCorrespondingParameterDescriptor(getDescriptor(declaringElement, resolveSession) as FunctionDescriptor, parameter)
|
||||
is JetClass -> {
|
||||
val jetClass: JetClass = declaringElement
|
||||
val classDescriptor = getDescriptor(jetClass, resolveSession) as ClassDescriptor
|
||||
addCorrespondingParameterDescriptor(classDescriptor.getConstructors().first(), parameter)
|
||||
}
|
||||
else -> super.visitParameter(parameter)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitPropertyAccessor(accessor: JetPropertyAccessor) {
|
||||
val parent = accessor.getParent() as JetProperty
|
||||
val propertyDescriptor = getDescriptor(parent, resolveSession) as PropertyDescriptor
|
||||
if (accessor.isGetter()) {
|
||||
descriptors.add(propertyDescriptor.getGetter())
|
||||
}
|
||||
else {
|
||||
descriptors.add(propertyDescriptor.getSetter())
|
||||
}
|
||||
accessor.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitAnonymousInitializer(initializer: JetClassInitializer) {
|
||||
initializer.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitDeclaration(element: JetDeclaration) {
|
||||
val descriptor = getDescriptor(element, resolveSession)
|
||||
descriptors.add(descriptor)
|
||||
if (descriptor is ClassDescriptor) {
|
||||
descriptors.addAll(descriptor.getConstructors())
|
||||
}
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitJetElement(element: JetElement) {
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
|
||||
private fun addCorrespondingParameterDescriptor(functionDescriptor: FunctionDescriptor, parameter: JetParameter) {
|
||||
for (valueParameterDescriptor in functionDescriptor.getValueParameters()) {
|
||||
if (valueParameterDescriptor.getName() == parameter.getNameAsName()) {
|
||||
descriptors.add(valueParameterDescriptor)
|
||||
}
|
||||
}
|
||||
parameter.acceptChildren(this)
|
||||
}
|
||||
})
|
||||
|
||||
val renderedDescriptors = descriptors.map { DescriptorRenderer.FQ_NAMES_IN_TYPES.render(it) }.joinToString(separator = "\n")
|
||||
|
||||
val document = DocumentImpl(psiFile.getText())
|
||||
UsefulTestCase.assertSameLines(JetTestUtils.getLastCommentedLines(document), renderedDescriptors.toString())
|
||||
}
|
||||
|
||||
override fun createEnvironment(): JetCoreEnvironment {
|
||||
return createEnvironmentWithMockJdk(ConfigurationKind.JDK_ONLY)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.renderer;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.ConfigurationKind;
|
||||
import org.jetbrains.jet.JetLiteFixture;
|
||||
import org.jetbrains.jet.JetTestCaseBuilder;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.analyzer.AnalysisResult;
|
||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetVisitorVoid;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.JvmResolveUtil;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DescriptorRendererTest extends JetLiteFixture {
|
||||
|
||||
@Override
|
||||
protected JetCoreEnvironment createEnvironment() {
|
||||
return createEnvironmentWithMockJdk(ConfigurationKind.JDK_ONLY);
|
||||
}
|
||||
|
||||
public void testGlobalProperties() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testGlobalFunctions() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testClasses() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testEnum() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testUnitType() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testFunctionTypes() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testErrorType() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testInheritedMembersVisibility() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testKeywordsInNames() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testFunctionTypesInSignature() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JetTestCaseBuilder.getTestDataPathBase() + "/renderer";
|
||||
}
|
||||
|
||||
private void doTest() throws IOException {
|
||||
String fileName = getTestName(false) + ".kt";
|
||||
JetFile psiFile = createPsiFile(null, fileName, loadFile(fileName));
|
||||
AnalysisResult analysisResult =
|
||||
JvmResolveUtil.analyzeOneFileWithJavaIntegration(psiFile);
|
||||
final BindingContext bindingContext = analysisResult.getBindingContext();
|
||||
final List<DeclarationDescriptor> descriptors = new ArrayList<DeclarationDescriptor>();
|
||||
|
||||
FqName fqName = psiFile.getPackageFqName();
|
||||
if (!fqName.isRoot()) {
|
||||
PackageViewDescriptor packageDescriptor = analysisResult.getModuleDescriptor().getPackage(fqName);
|
||||
descriptors.add(packageDescriptor);
|
||||
}
|
||||
|
||||
psiFile.acceptChildren(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitJetElement(@NotNull JetElement element) {
|
||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
||||
if (descriptor != null) {
|
||||
descriptors.add(descriptor);
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
descriptors.addAll(((ClassDescriptor) descriptor).getConstructors());
|
||||
}
|
||||
}
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
});
|
||||
|
||||
StringBuilder renderedDescriptors = new StringBuilder();
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
if (renderedDescriptors.length() != 0) {
|
||||
renderedDescriptors.append("\n");
|
||||
}
|
||||
renderedDescriptors.append(DescriptorRenderer.FQ_NAMES_IN_TYPES.render(descriptor));
|
||||
}
|
||||
|
||||
Document document = new DocumentImpl(psiFile.getText());
|
||||
assertSameLines(JetTestUtils.getLastCommentedLines(document), renderedDescriptors.toString());
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.lazy;
|
||||
package org.jetbrains.jet.renderer;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.jet.JUnit3RunnerWithInners;
|
||||
@@ -31,7 +31,7 @@ import java.util.regex.Pattern;
|
||||
@TestMetadata("compiler/testData/renderer")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class LazyResolveDescriptorRendererTestGenerated extends AbstractLazyResolveDescriptorRendererTest {
|
||||
public class DescriptorRendererTestGenerated extends AbstractDescriptorRendererTest {
|
||||
public void testAllFilesPresentInRenderer() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/renderer"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
Reference in New Issue
Block a user