mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
CharSequence instead of String
This commit is contained in:
@@ -35,6 +35,7 @@ import com.intellij.util.containers.ConcurrentMostlySingularMultiMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MostlySingularMultiMap;
|
||||
import com.intellij.util.containers.WeakKeyWeakValueHashMap;
|
||||
import com.intellij.util.text.CharSequenceReader;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -47,7 +48,6 @@ import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@@ -173,7 +173,7 @@ public abstract class BaseExternalAnnotationsManager extends ExternalAnnotations
|
||||
DataParsingSaxHandler handler = new DataParsingSaxHandler(file);
|
||||
try {
|
||||
SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
|
||||
saxParser.parse(new InputSource(new StringReader(escapeAttributes(file.getText()))), handler);
|
||||
saxParser.parse(new InputSource(new CharSequenceReader(escapeAttributes(file.getViewProvider().getContents()))), handler);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
@@ -298,7 +298,7 @@ public abstract class BaseExternalAnnotationsManager extends ExternalAnnotations
|
||||
// Old external annotations sometimes are bad XML: they have "<" and ">" characters in attributes values. To prevent SAX parser from
|
||||
// failing, we escape attributes values.
|
||||
@NotNull
|
||||
private static String escapeAttributes(@NotNull String invalidXml) {
|
||||
private static CharSequence escapeAttributes(@NotNull CharSequence invalidXml) {
|
||||
// We assume that XML has single- and double-quote characters only for attribute values, therefore we don't any complex parsing,
|
||||
// just have binary inAttribute state
|
||||
StringBuilder buf = new StringBuilder(invalidXml.length());
|
||||
@@ -319,7 +319,7 @@ public abstract class BaseExternalAnnotationsManager extends ExternalAnnotations
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
return buf;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -350,7 +350,7 @@ public final class LoadTextUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Charset extractCharsetFromFileContent(@Nullable Project project, @NotNull VirtualFile virtualFile, @NotNull String text) {
|
||||
public static Charset extractCharsetFromFileContent(@Nullable Project project, @NotNull VirtualFile virtualFile, @NotNull CharSequence text) {
|
||||
return ObjectUtils.notNull(charsetFromContentOrNull(project, virtualFile, text), virtualFile.getCharset());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-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.
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import com.intellij.util.text.CharSequenceReader;
|
||||
import com.intellij.util.text.StringFactory;
|
||||
import net.n3.nanoxml.*;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -44,7 +45,7 @@ public class NanoXmlUtil {
|
||||
}
|
||||
|
||||
private static MyXMLReader createReader(PsiFile psiFile) {
|
||||
return new MyXMLReader(new StringReader(psiFile.getText()));
|
||||
return new MyXMLReader(new CharSequenceReader(psiFile.getViewProvider().getContents()));
|
||||
}
|
||||
|
||||
public static void parseFile(PsiFile psiFile, final IXMLBuilder builder) {
|
||||
|
||||
@@ -41,6 +41,7 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.encoding.ChangeFileEncodingAction;
|
||||
import com.intellij.openapi.vfs.encoding.EncodingUtil;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
@@ -91,11 +92,12 @@ public class LossyEncodingInspection extends LocalInspectionTool {
|
||||
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
if (InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)) return null;
|
||||
if (!file.isPhysical()) return null;
|
||||
if (file.getViewProvider().getBaseLanguage() != file.getLanguage()) return null;
|
||||
FileViewProvider viewProvider = file.getViewProvider();
|
||||
if (viewProvider.getBaseLanguage() != file.getLanguage()) return null;
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (virtualFile == null) return null;
|
||||
if (!virtualFile.isInLocalFileSystem()) return null;
|
||||
String text = file.getText();
|
||||
CharSequence text = viewProvider.getContents();
|
||||
Charset charset = LoadTextUtil.extractCharsetFromFileContent(file.getProject(), virtualFile, text);
|
||||
|
||||
// no sense in checking transparently decoded file: all characters there are already safely encoded
|
||||
@@ -165,7 +167,7 @@ public class LossyEncodingInspection extends LocalInspectionTool {
|
||||
private static void checkIfCharactersWillBeLostAfterSave(@NotNull PsiFile file,
|
||||
@NotNull InspectionManager manager,
|
||||
boolean isOnTheFly,
|
||||
@NotNull String text,
|
||||
@NotNull CharSequence text,
|
||||
@NotNull Charset charset,
|
||||
@NotNull List<ProblemDescriptor> descriptors) {
|
||||
int errorCount = 0;
|
||||
|
||||
@@ -137,7 +137,7 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
|
||||
int found = countNewLinesIn(shred.getPrefix(), pos, line);
|
||||
if (found != -1) return found;
|
||||
|
||||
String text = hostText.substring(hostRange.getStartOffset(), hostRange.getEndOffset());
|
||||
CharSequence text = hostText.subSequence(hostRange.getStartOffset(), hostRange.getEndOffset());
|
||||
found = countNewLinesIn(text, pos, line);
|
||||
if (found != -1) return found;
|
||||
|
||||
@@ -150,9 +150,9 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
|
||||
}
|
||||
|
||||
// returns startOffset found, or -1 if need to continue searching
|
||||
private static int countNewLinesIn(String text, int[] pos, int line) {
|
||||
private static int countNewLinesIn(CharSequence text, int[] pos, int line) {
|
||||
int offsetInside = 0;
|
||||
for (int i = text.indexOf('\n'); i != -1; i = text.indexOf('\n', offsetInside)) {
|
||||
for (int i = StringUtil.indexOf(text, '\n'); i != -1; i = StringUtil.indexOf(text,'\n', offsetInside)) {
|
||||
int curLine = ++pos[0];
|
||||
int lineLength = i + 1 - offsetInside;
|
||||
int offset = pos[1] += lineLength;
|
||||
@@ -256,9 +256,9 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
|
||||
Segment currentRange = shred.getHostRangeMarker();
|
||||
if (currentRange == null) continue;
|
||||
int rangeLength = currentRange.getEndOffset() - currentRange.getStartOffset();
|
||||
String rangeText = hostText.substring(currentRange.getStartOffset(), currentRange.getEndOffset());
|
||||
CharSequence rangeText = hostText.subSequence(currentRange.getStartOffset(), currentRange.getEndOffset());
|
||||
|
||||
lineNumber += StringUtil.getLineBreakCount(rangeText.substring(0, Math.min(offset, rangeLength)));
|
||||
lineNumber += StringUtil.getLineBreakCount(rangeText.subSequence(0, Math.min(offset, rangeLength)));
|
||||
if (offset < rangeLength) {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-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.
|
||||
@@ -71,9 +71,8 @@ public class FormattingDocumentModelImpl implements FormattingDocumentModel {
|
||||
return new FormattingDocumentModelImpl(document, file);
|
||||
}
|
||||
else {
|
||||
return new FormattingDocumentModelImpl(new DocumentImpl(file.getText()), file);
|
||||
return new FormattingDocumentModelImpl(new DocumentImpl(file.getViewProvider().getContents()), file);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -82,7 +81,7 @@ public class FormattingDocumentModelImpl implements FormattingDocumentModel {
|
||||
final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
|
||||
if (document == null) return null;
|
||||
if (PsiDocumentManager.getInstance(project).isUncommited(document)) return null;
|
||||
PsiToDocumentSynchronizer synchronizer = ((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(file.getProject())).getSynchronizer();
|
||||
PsiToDocumentSynchronizer synchronizer = ((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(project)).getSynchronizer();
|
||||
if (synchronizer.isDocumentAffectedByTransactions(document)) return null;
|
||||
|
||||
return document;
|
||||
|
||||
@@ -969,9 +969,14 @@ public class StringUtil extends StringUtilRt {
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
public static String trimLeading(@NotNull String string) {
|
||||
return trimLeading((CharSequence)string).toString();
|
||||
}
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
public static CharSequence trimLeading(@NotNull CharSequence string) {
|
||||
int index = 0;
|
||||
while (index < string.length() && Character.isWhitespace(string.charAt(index))) index++;
|
||||
return string.substring(index);
|
||||
return string.subSequence(index, string.length());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -985,9 +990,15 @@ public class StringUtil extends StringUtilRt {
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
public static String trimTrailing(@NotNull String string) {
|
||||
return trimTrailing((CharSequence)string).toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
public static CharSequence trimTrailing(@NotNull CharSequence string) {
|
||||
int index = string.length() - 1;
|
||||
while (index >= 0 && Character.isWhitespace(string.charAt(index))) index--;
|
||||
return string.substring(0, index + 1);
|
||||
return string.subSequence(0, index + 1);
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
@@ -1184,6 +1195,11 @@ public class StringUtil extends StringUtilRt {
|
||||
public static List<String> split(@NotNull String s, @NotNull String separator) {
|
||||
return split(s, separator, true);
|
||||
}
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
public static List<CharSequence> split(@NotNull CharSequence s, @NotNull CharSequence separator) {
|
||||
return split(s, separator, true, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
@@ -1196,23 +1212,29 @@ public class StringUtil extends StringUtilRt {
|
||||
@Contract(pure = true)
|
||||
public static List<String> split(@NotNull String s, @NotNull String separator,
|
||||
boolean excludeSeparator, boolean excludeEmptyStrings) {
|
||||
if (separator.isEmpty()) {
|
||||
return (List)split((CharSequence)s,separator,excludeSeparator,excludeEmptyStrings);
|
||||
}
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
public static List<CharSequence> split(@NotNull CharSequence s, @NotNull CharSequence separator,
|
||||
boolean excludeSeparator, boolean excludeEmptyStrings) {
|
||||
if (separator.length() == 0) {
|
||||
return Collections.singletonList(s);
|
||||
}
|
||||
List<String> result = new ArrayList<String>();
|
||||
List<CharSequence> result = new ArrayList<CharSequence>();
|
||||
int pos = 0;
|
||||
while (true) {
|
||||
int index = s.indexOf(separator, pos);
|
||||
int index = indexOf(s,separator, pos);
|
||||
if (index == -1) break;
|
||||
final int nextPos = index + separator.length();
|
||||
String token = s.substring(pos, excludeSeparator ? index : nextPos);
|
||||
if (!token.isEmpty() || !excludeEmptyStrings) {
|
||||
CharSequence token = s.subSequence(pos, excludeSeparator ? index : nextPos);
|
||||
if (token.length() != 0 || !excludeEmptyStrings) {
|
||||
result.add(token);
|
||||
}
|
||||
pos = nextPos;
|
||||
}
|
||||
if (pos < s.length() || !excludeEmptyStrings && pos == s.length()) {
|
||||
result.add(s.substring(pos, s.length()));
|
||||
result.add(s.subSequence(pos, s.length()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1828,7 +1850,12 @@ public class StringUtil extends StringUtilRt {
|
||||
|
||||
@Contract(pure = true)
|
||||
public static int indexOf(@NotNull CharSequence sequence, @NotNull CharSequence infix) {
|
||||
for (int i = 0; i <= sequence.length() - infix.length(); i++) {
|
||||
return indexOf(sequence, infix, 0);
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public static int indexOf(@NotNull CharSequence sequence, @NotNull CharSequence infix, int start) {
|
||||
for (int i = start; i <= sequence.length() - infix.length(); i++) {
|
||||
if (startsWith(sequence, i, infix)) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-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.
|
||||
@@ -34,7 +34,7 @@ public class XmlCharsetDetector {
|
||||
@NonNls private static final byte[] XML_PROLOG_END_BYTES = CharsetToolkit.getUtf8Bytes(XML_PROLOG_END);
|
||||
|
||||
@Nullable
|
||||
public static String extractXmlEncodingFromProlog(final byte[] bytes) {
|
||||
public static String extractXmlEncodingFromProlog(@NotNull byte[] bytes) {
|
||||
int index = 0;
|
||||
if (CharsetToolkit.hasUTF8Bom(bytes)) {
|
||||
index = CharsetToolkit.UTF8_BOM.length;
|
||||
@@ -67,7 +67,7 @@ public class XmlCharsetDetector {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String extractXmlEncodingFromProlog(@NotNull String text) {
|
||||
public static String extractXmlEncodingFromProlog(@NotNull CharSequence text) {
|
||||
int index = 0;
|
||||
|
||||
index = skipWhiteSpace(index, text);
|
||||
@@ -108,7 +108,7 @@ public class XmlCharsetDetector {
|
||||
return start;
|
||||
}
|
||||
|
||||
private static int skipWhiteSpace(int start, @NotNull String text) {
|
||||
private static int skipWhiteSpace(int start, @NotNull CharSequence text) {
|
||||
while (start < text.length()) {
|
||||
char c = text.charAt(start);
|
||||
if (!Character.isWhitespace(c)) break;
|
||||
|
||||
@@ -31,7 +31,10 @@ import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassRe
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiReferenceProcessor;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.psi.xml.*;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlAttributeValue;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.uiDesigner.UIFormXmlConstants;
|
||||
import com.intellij.uiDesigner.compiler.Utils;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
@@ -118,7 +121,7 @@ public class FormReferenceProvider extends PsiReferenceProvider {
|
||||
final Project project = file.getProject();
|
||||
final XmlTag rootTag = ApplicationManager.getApplication().runReadAction(new Computable<XmlTag>() {
|
||||
public XmlTag compute() {
|
||||
final XmlFile xmlFile = (XmlFile) PsiFileFactory.getInstance(project).createFileFromText("a.xml", XmlFileType.INSTANCE, file.getText());
|
||||
final XmlFile xmlFile = (XmlFile) PsiFileFactory.getInstance(project).createFileFromText("a.xml", XmlFileType.INSTANCE, file.getViewProvider().getContents());
|
||||
return xmlFile.getRootTag();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.text.CharSequenceReader;
|
||||
import icons.PythonPsiApiIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -32,7 +33,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.IllegalCharsetNameException;
|
||||
@@ -88,7 +88,7 @@ public class PythonFileType extends LanguageFileType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Charset extractCharsetFromFileContent(@Nullable Project project, @Nullable VirtualFile file, @NotNull String content) {
|
||||
public Charset extractCharsetFromFileContent(@Nullable Project project, @Nullable VirtualFile file, @NotNull CharSequence content) {
|
||||
final String charsetName = getCharsetFromEncodingDeclaration(content);
|
||||
if (charsetName == null) {
|
||||
return null;
|
||||
@@ -119,12 +119,12 @@ public class PythonFileType extends LanguageFileType {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getCharsetFromEncodingDeclaration(@Nullable String content) {
|
||||
if (content == null || content.isEmpty()) {
|
||||
private static String getCharsetFromEncodingDeclaration(@Nullable CharSequence content) {
|
||||
if (content == null || content.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
final BufferedReader reader = new BufferedReader(new StringReader(content));
|
||||
final BufferedReader reader = new BufferedReader(new CharSequenceReader(content));
|
||||
try {
|
||||
for (int i = 0; i < MAX_CHARSET_ENCODING_LINE; i++) {
|
||||
final String line = reader.readLine();
|
||||
|
||||
@@ -84,7 +84,7 @@ public class HtmlFileType extends XmlLikeFileType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Charset extractCharsetFromFileContent(@Nullable final Project project, @Nullable final VirtualFile file, @NotNull final String content) {
|
||||
public Charset extractCharsetFromFileContent(@Nullable final Project project, @Nullable final VirtualFile file, @NotNull final CharSequence content) {
|
||||
String name = XmlCharsetDetector.extractXmlEncodingFromProlog(content);
|
||||
Charset charset = CharsetToolkit.forName(name);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public abstract class XmlLikeFileType extends LanguageFileType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Charset extractCharsetFromFileContent(final Project project, @Nullable final VirtualFile file, @NotNull final String content) {
|
||||
public Charset extractCharsetFromFileContent(final Project project, @Nullable final VirtualFile file, @NotNull final CharSequence content) {
|
||||
String name = XmlCharsetDetector.extractXmlEncodingFromProlog(content);
|
||||
Charset charset = CharsetToolkit.forName(name);
|
||||
return charset == null ? CharsetToolkit.UTF8_CHARSET : charset;
|
||||
|
||||
@@ -455,16 +455,16 @@ public class HtmlUtil {
|
||||
private static final TerminateException INSTANCE = new TerminateException();
|
||||
}
|
||||
|
||||
public static Charset detectCharsetFromMetaTag(@NotNull String content) {
|
||||
public static Charset detectCharsetFromMetaTag(@NotNull CharSequence content) {
|
||||
// check for <meta http-equiv="charset=CharsetName" > or <meta charset="CharsetName"> and return Charset
|
||||
// because we will lightly parse and explicit charset isn't used very often do quick check for applicability
|
||||
int charPrefix = content.indexOf(CHARSET);
|
||||
int charPrefix = StringUtil.indexOf(content, CHARSET);
|
||||
do {
|
||||
if (charPrefix == -1) return null;
|
||||
int charsetPrefixEnd = charPrefix + CHARSET.length();
|
||||
while (charsetPrefixEnd < content.length() && Character.isWhitespace(content.charAt(charsetPrefixEnd))) ++charsetPrefixEnd;
|
||||
if (charsetPrefixEnd < content.length() && content.charAt(charsetPrefixEnd) == '=') break;
|
||||
charPrefix = content.indexOf(CHARSET, charsetPrefixEnd);
|
||||
charPrefix = StringUtil.indexOf(content,CHARSET, charsetPrefixEnd);
|
||||
} while(true);
|
||||
|
||||
final Ref<String> charsetNameRef = new Ref<String>();
|
||||
|
||||
@@ -1346,12 +1346,12 @@ public class XmlUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String extractXmlEncodingFromProlog(final byte[] content) {
|
||||
public static String extractXmlEncodingFromProlog(@NotNull byte[] content) {
|
||||
return XmlCharsetDetector.extractXmlEncodingFromProlog(content);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String extractXmlEncodingFromProlog(String text) {
|
||||
public static String extractXmlEncodingFromProlog(@NotNull CharSequence text) {
|
||||
return XmlCharsetDetector.extractXmlEncodingFromProlog(text);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user