forked from qt-creator/qt-creator
Removed #ifdefs so all AST nodes are always there.
Also removed the (conditional) invoke_token from DeclarationAST and use the qt_invokable_token to store the Q_INVOKABLE, and fixed the ASTMatch code generation.
This commit is contained in:
@@ -144,7 +144,6 @@ unsigned AccessDeclarationAST::lastToken() const
|
||||
return access_specifier_token + 1;
|
||||
}
|
||||
|
||||
#ifdef ICHECK_BUILD
|
||||
unsigned QPropertyDeclarationAST::firstToken() const
|
||||
{
|
||||
return property_specifier_token;
|
||||
@@ -184,7 +183,6 @@ unsigned QDeclareFlagsDeclarationAST::lastToken() const
|
||||
{
|
||||
return rparen_token;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned ArrayAccessAST::firstToken() const
|
||||
{
|
||||
|
||||
@@ -248,6 +248,10 @@ public:
|
||||
virtual PostfixDeclaratorAST *asPostfixDeclarator() { return 0; }
|
||||
virtual PostfixExpressionAST *asPostfixExpression() { return 0; }
|
||||
virtual PtrOperatorAST *asPtrOperator() { return 0; }
|
||||
virtual QDeclareFlagsDeclarationAST *asQDeclareFlagsDeclaration() { return 0; }
|
||||
virtual QEnumDeclarationAST *asQEnumDeclaration() { return 0; }
|
||||
virtual QFlagsDeclarationAST *asQFlagsDeclaration() { return 0; }
|
||||
virtual QPropertyDeclarationAST *asQPropertyDeclaration() { return 0; }
|
||||
virtual QtMemberDeclarationAST *asQtMemberDeclaration() { return 0; }
|
||||
virtual QtMethodAST *asQtMethod() { return 0; }
|
||||
virtual QualifiedNameAST *asQualifiedName() { return 0; }
|
||||
@@ -278,12 +282,6 @@ public:
|
||||
virtual UsingAST *asUsing() { return 0; }
|
||||
virtual UsingDirectiveAST *asUsingDirective() { return 0; }
|
||||
virtual WhileStatementAST *asWhileStatement() { return 0; }
|
||||
#ifdef ICHECK_BUILD
|
||||
virtual QPropertyDeclarationAST *asQPropertyDeclarationAST() { return 0; }
|
||||
virtual QEnumDeclarationAST *asQEnumDeclarationAST() { return 0; }
|
||||
virtual QFlagsDeclarationAST *asQFlagsDeclarationAST() { return 0; }
|
||||
virtual QDeclareFlagsDeclarationAST *asQDeclareFlagsDeclarationAST() { return 0; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual void accept0(ASTVisitor *visitor) = 0;
|
||||
@@ -312,10 +310,6 @@ public:
|
||||
virtual DeclarationAST *asDeclaration() { return this; }
|
||||
|
||||
virtual DeclarationAST *clone(MemoryPool *pool) const = 0;
|
||||
|
||||
#ifdef ICHECK_BUILD
|
||||
unsigned invoke_token;
|
||||
#endif
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT NameAST: public ExpressionAST
|
||||
@@ -550,7 +544,6 @@ protected:
|
||||
virtual bool match0(AST *, ASTMatcher *);
|
||||
};
|
||||
|
||||
#ifdef ICHECK_BUILD
|
||||
class CPLUSPLUS_EXPORT QPropertyDeclarationAST: public DeclarationAST
|
||||
{
|
||||
/*
|
||||
@@ -581,7 +574,7 @@ public:
|
||||
unsigned rparen_token;
|
||||
|
||||
public:
|
||||
virtual QPropertyDeclarationAST *asQPropertyDeclarationAST() { return this; }
|
||||
virtual QPropertyDeclarationAST *asQPropertyDeclaration() { return this; }
|
||||
|
||||
virtual unsigned firstToken() const;
|
||||
virtual unsigned lastToken() const;
|
||||
@@ -603,7 +596,7 @@ public:
|
||||
EnumeratorListAST *enumerator_list;
|
||||
|
||||
public:
|
||||
virtual QEnumDeclarationAST *asQEnumDeclarationAST() { return this; }
|
||||
virtual QEnumDeclarationAST *asQEnumDeclaration() { return this; }
|
||||
|
||||
virtual unsigned firstToken() const;
|
||||
virtual unsigned lastToken() const;
|
||||
@@ -625,7 +618,7 @@ public:
|
||||
EnumeratorListAST *enumerator_list;
|
||||
|
||||
public:
|
||||
virtual QFlagsDeclarationAST *asQFlagsDeclarationAST() { return this; }
|
||||
virtual QFlagsDeclarationAST *asQFlagsDeclaration() { return this; }
|
||||
|
||||
virtual unsigned firstToken() const;
|
||||
virtual unsigned lastToken() const;
|
||||
@@ -648,7 +641,7 @@ public:
|
||||
unsigned rparen_token;
|
||||
|
||||
public:
|
||||
virtual QDeclareFlagsDeclarationAST *asQDeclareFlagsDeclarationAST() { return this; }
|
||||
virtual QDeclareFlagsDeclarationAST *asQDeclareFlagsDeclaration() { return this; }
|
||||
|
||||
virtual unsigned firstToken() const;
|
||||
virtual unsigned lastToken() const;
|
||||
@@ -659,7 +652,6 @@ protected:
|
||||
virtual void accept0(ASTVisitor *visitor);
|
||||
virtual bool match0(AST *, ASTMatcher *);
|
||||
};
|
||||
#endif
|
||||
|
||||
class CPLUSPLUS_EXPORT AsmDefinitionAST: public DeclarationAST
|
||||
{
|
||||
|
||||
@@ -138,7 +138,6 @@ AccessDeclarationAST *AccessDeclarationAST::clone(MemoryPool *pool) const
|
||||
return ast;
|
||||
}
|
||||
|
||||
#ifdef ICHECK_BUILD
|
||||
QPropertyDeclarationAST *QPropertyDeclarationAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
QPropertyDeclarationAST *ast = new (pool) QPropertyDeclarationAST;
|
||||
@@ -160,14 +159,13 @@ QPropertyDeclarationAST *QPropertyDeclarationAST::clone(MemoryPool *pool) const
|
||||
|
||||
QEnumDeclarationAST *QEnumDeclarationAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
QEnumDeclarationAST *ast = new (pool)QEnumDeclarationAST;
|
||||
QEnumDeclarationAST *ast = new (pool) QEnumDeclarationAST;
|
||||
ast->enum_specifier_token = enum_specifier_token;
|
||||
ast->lparen_token = lparen_token;
|
||||
ast->rparen_token = rparen_token;
|
||||
for (EnumeratorListAST *iter = enumerator_list, **ast_iter = &ast->enumerator_list;
|
||||
iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
|
||||
*ast_iter = new (pool) EnumeratorListAST((iter->value) ? iter->value->clone(pool) : 0);
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
@@ -180,7 +178,6 @@ QFlagsDeclarationAST *QFlagsDeclarationAST::clone(MemoryPool *pool) const
|
||||
for (EnumeratorListAST *iter = enumerator_list, **ast_iter = &ast->enumerator_list;
|
||||
iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
|
||||
*ast_iter = new (pool) EnumeratorListAST((iter->value) ? iter->value->clone(pool) : 0);
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
@@ -192,10 +189,8 @@ QDeclareFlagsDeclarationAST *QDeclareFlagsDeclarationAST::clone(MemoryPool *pool
|
||||
ast->flag_token = flag_token;
|
||||
ast->enum_token = enum_token;
|
||||
ast->rparen_token = rparen_token;
|
||||
|
||||
return ast;
|
||||
}
|
||||
#endif
|
||||
|
||||
AsmDefinitionAST *AsmDefinitionAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
|
||||
@@ -27,6 +27,15 @@
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is automatically generated.
|
||||
// Changes will be lost.
|
||||
//
|
||||
|
||||
|
||||
#include "AST.h"
|
||||
#include "ASTMatcher.h"
|
||||
|
||||
@@ -96,10 +105,9 @@ bool AccessDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef ICHECK_BUILD
|
||||
bool QPropertyDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
{
|
||||
if (QPropertyDeclarationAST *_other = pattern->asQPropertyDeclarationAST())
|
||||
if (QPropertyDeclarationAST *_other = pattern->asQPropertyDeclaration())
|
||||
return matcher->match(this, _other);
|
||||
|
||||
return false;
|
||||
@@ -107,7 +115,7 @@ bool QPropertyDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
|
||||
bool QEnumDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
{
|
||||
if (QEnumDeclarationAST *_other = pattern->asQEnumDeclarationAST())
|
||||
if (QEnumDeclarationAST *_other = pattern->asQEnumDeclaration())
|
||||
return matcher->match(this, _other);
|
||||
|
||||
return false;
|
||||
@@ -115,7 +123,7 @@ bool QEnumDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
|
||||
bool QFlagsDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
{
|
||||
if (QFlagsDeclarationAST *_other = pattern->asQFlagsDeclarationAST())
|
||||
if (QFlagsDeclarationAST *_other = pattern->asQFlagsDeclaration())
|
||||
return matcher->match(this, _other);
|
||||
|
||||
return false;
|
||||
@@ -123,12 +131,11 @@ bool QFlagsDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
|
||||
bool QDeclareFlagsDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
{
|
||||
if (QDeclareFlagsDeclarationAST *_other = pattern->asQDeclareFlagsDeclarationAST())
|
||||
if (QDeclareFlagsDeclarationAST *_other = pattern->asQDeclareFlagsDeclaration())
|
||||
return matcher->match(this, _other);
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool AsmDefinitionAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
{
|
||||
|
||||
@@ -27,9 +27,17 @@
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is automatically generated.
|
||||
// Changes will be lost.
|
||||
//
|
||||
|
||||
#include "AST.h"
|
||||
#include "ASTMatcher.h"
|
||||
#include "TranslationUnit.h"
|
||||
|
||||
using namespace CPlusPlus;
|
||||
|
||||
@@ -195,14 +203,9 @@ bool ASTMatcher::match(AccessDeclarationAST *node, AccessDeclarationAST *pattern
|
||||
|
||||
pattern->colon_token = node->colon_token;
|
||||
|
||||
#ifdef ICHECK_BUILD
|
||||
pattern->invoke_token = node->invoke_token;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef ICHECK_BUILD
|
||||
bool ASTMatcher::match(QPropertyDeclarationAST *node, QPropertyDeclarationAST *pattern)
|
||||
{
|
||||
(void) node;
|
||||
@@ -210,14 +213,30 @@ bool ASTMatcher::match(QPropertyDeclarationAST *node, QPropertyDeclarationAST *p
|
||||
|
||||
pattern->property_specifier_token = node->property_specifier_token;
|
||||
|
||||
pattern->lparen_token = node->lparen_token;
|
||||
|
||||
pattern->type_token = node->type_token;
|
||||
|
||||
pattern->type_name_token = node->type_name_token;
|
||||
|
||||
pattern->read_token = node->read_token;
|
||||
|
||||
pattern->read_function_token = node->read_function_token;
|
||||
|
||||
pattern->write_token = node->write_token;
|
||||
|
||||
pattern->write_function_token = node->write_function_token;
|
||||
|
||||
pattern->reset_token = node->reset_token;
|
||||
|
||||
pattern->reset_function_token = node->reset_function_token;
|
||||
|
||||
pattern->notify_token = node->notify_token;
|
||||
|
||||
pattern->notify_function_token = node->notify_function_token;
|
||||
|
||||
pattern->rparen_token = node->rparen_token;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -228,6 +247,10 @@ bool ASTMatcher::match(QEnumDeclarationAST *node, QEnumDeclarationAST *pattern)
|
||||
|
||||
pattern->enum_specifier_token = node->enum_specifier_token;
|
||||
|
||||
pattern->lparen_token = node->lparen_token;
|
||||
|
||||
pattern->rparen_token = node->rparen_token;
|
||||
|
||||
if (! pattern->enumerator_list)
|
||||
pattern->enumerator_list = node->enumerator_list;
|
||||
else if (! AST::match(node->enumerator_list, pattern->enumerator_list, this))
|
||||
@@ -243,6 +266,10 @@ bool ASTMatcher::match(QFlagsDeclarationAST *node, QFlagsDeclarationAST *pattern
|
||||
|
||||
pattern->flags_specifier_token = node->flags_specifier_token;
|
||||
|
||||
pattern->lparen_token = node->lparen_token;
|
||||
|
||||
pattern->rparen_token = node->rparen_token;
|
||||
|
||||
if (! pattern->enumerator_list)
|
||||
pattern->enumerator_list = node->enumerator_list;
|
||||
else if (! AST::match(node->enumerator_list, pattern->enumerator_list, this))
|
||||
@@ -257,12 +284,17 @@ bool ASTMatcher::match(QDeclareFlagsDeclarationAST *node, QDeclareFlagsDeclarati
|
||||
(void) pattern;
|
||||
|
||||
pattern->declareflags_specifier_token = node->declareflags_specifier_token;
|
||||
|
||||
pattern->lparen_token = node->lparen_token;
|
||||
|
||||
pattern->flag_token = node->flag_token;
|
||||
|
||||
pattern->enum_token = node->enum_token;
|
||||
|
||||
pattern->rparen_token = node->rparen_token;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ASTMatcher::match(AsmDefinitionAST *node, AsmDefinitionAST *pattern)
|
||||
{
|
||||
@@ -2204,6 +2236,8 @@ bool ASTMatcher::match(ObjCTypeNameAST *node, ObjCTypeNameAST *pattern)
|
||||
|
||||
pattern->lparen_token = node->lparen_token;
|
||||
|
||||
pattern->type_qualifier_token = node->type_qualifier_token;
|
||||
|
||||
if (! pattern->type_id)
|
||||
pattern->type_id = node->type_id;
|
||||
else if (! AST::match(node->type_id, pattern->type_id, this))
|
||||
@@ -2433,8 +2467,12 @@ bool ASTMatcher::match(ObjCSynthesizedPropertyAST *node, ObjCSynthesizedProperty
|
||||
(void) node;
|
||||
(void) pattern;
|
||||
|
||||
pattern->property_identifier_token = node->property_identifier_token;
|
||||
|
||||
pattern->equals_token = node->equals_token;
|
||||
|
||||
pattern->alias_identifier_token = node->alias_identifier_token;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,12 +40,10 @@ public:
|
||||
virtual ~ASTMatcher();
|
||||
|
||||
virtual bool match(AccessDeclarationAST *node, AccessDeclarationAST *pattern);
|
||||
#ifdef ICHECK_BUILD
|
||||
virtual bool match(QPropertyDeclarationAST *node, QPropertyDeclarationAST *pattern);
|
||||
virtual bool match(QEnumDeclarationAST *node, QEnumDeclarationAST *pattern);
|
||||
virtual bool match(QFlagsDeclarationAST *node, QFlagsDeclarationAST *pattern);
|
||||
virtual bool match(QDeclareFlagsDeclarationAST *node, QDeclareFlagsDeclarationAST *pattern);
|
||||
#endif
|
||||
virtual bool match(ArrayAccessAST *node, ArrayAccessAST *pattern);
|
||||
virtual bool match(ArrayDeclaratorAST *node, ArrayDeclaratorAST *pattern);
|
||||
virtual bool match(ArrayInitializerAST *node, ArrayInitializerAST *pattern);
|
||||
|
||||
@@ -27,6 +27,15 @@
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is automatically generated.
|
||||
// Changes will be lost.
|
||||
//
|
||||
|
||||
|
||||
#include "AST.h"
|
||||
#include "ASTVisitor.h"
|
||||
|
||||
@@ -99,7 +108,6 @@ void AccessDeclarationAST::accept0(ASTVisitor *visitor)
|
||||
visitor->endVisit(this);
|
||||
}
|
||||
|
||||
#ifdef ICHECK_BUILD
|
||||
void QPropertyDeclarationAST::accept0(ASTVisitor *visitor)
|
||||
{
|
||||
if (visitor->visit(this)) {
|
||||
@@ -110,6 +118,7 @@ void QPropertyDeclarationAST::accept0(ASTVisitor *visitor)
|
||||
void QEnumDeclarationAST::accept0(ASTVisitor *visitor)
|
||||
{
|
||||
if (visitor->visit(this)) {
|
||||
accept(enumerator_list, visitor);
|
||||
}
|
||||
visitor->endVisit(this);
|
||||
}
|
||||
@@ -117,6 +126,7 @@ void QEnumDeclarationAST::accept0(ASTVisitor *visitor)
|
||||
void QFlagsDeclarationAST::accept0(ASTVisitor *visitor)
|
||||
{
|
||||
if (visitor->visit(this)) {
|
||||
accept(enumerator_list, visitor);
|
||||
}
|
||||
visitor->endVisit(this);
|
||||
}
|
||||
@@ -127,7 +137,6 @@ void QDeclareFlagsDeclarationAST::accept0(ASTVisitor *visitor)
|
||||
}
|
||||
visitor->endVisit(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
void AsmDefinitionAST::accept0(ASTVisitor *visitor)
|
||||
{
|
||||
|
||||
@@ -103,12 +103,10 @@ public:
|
||||
virtual void postVisit(AST *) {}
|
||||
|
||||
virtual bool visit(AccessDeclarationAST *) { return true; }
|
||||
#ifdef ICHECK_BUILD
|
||||
virtual bool visit(QPropertyDeclarationAST *) { return true; }
|
||||
virtual bool visit(QEnumDeclarationAST *) { return true; }
|
||||
virtual bool visit(QFlagsDeclarationAST *) { return true; }
|
||||
virtual bool visit(QDeclareFlagsDeclarationAST *) { return true; }
|
||||
#endif
|
||||
virtual bool visit(ArrayAccessAST *) { return true; }
|
||||
virtual bool visit(ArrayDeclaratorAST *) { return true; }
|
||||
virtual bool visit(ArrayInitializerAST *) { return true; }
|
||||
@@ -235,12 +233,10 @@ public:
|
||||
virtual bool visit(ObjCSynchronizedStatementAST *) { return true; }
|
||||
|
||||
virtual void endVisit(AccessDeclarationAST *) { }
|
||||
#ifdef ICHECK_BUILD
|
||||
virtual void endVisit(QPropertyDeclarationAST *) { }
|
||||
virtual void endVisit(QEnumDeclarationAST *) { }
|
||||
virtual void endVisit(QFlagsDeclarationAST *) { }
|
||||
virtual void endVisit(QDeclareFlagsDeclarationAST *) { }
|
||||
#endif
|
||||
virtual void endVisit(ArrayAccessAST *) { }
|
||||
virtual void endVisit(ArrayDeclaratorAST *) { }
|
||||
virtual void endVisit(ArrayInitializerAST *) { }
|
||||
|
||||
@@ -60,12 +60,6 @@ class ASTVisitor;
|
||||
class ASTMatcher;
|
||||
|
||||
class AccessDeclarationAST;
|
||||
#ifdef ICHECK_BUILD
|
||||
class QPropertyDeclarationAST;
|
||||
class QEnumDeclarationAST;
|
||||
class QFlagsDeclarationAST;
|
||||
class QDeclareFlagsDeclarationAST;
|
||||
#endif
|
||||
class ArrayAccessAST;
|
||||
class ArrayDeclaratorAST;
|
||||
class ArrayInitializerAST;
|
||||
@@ -168,6 +162,10 @@ class PostfixAST;
|
||||
class PostfixDeclaratorAST;
|
||||
class PostfixExpressionAST;
|
||||
class PtrOperatorAST;
|
||||
class QDeclareFlagsDeclarationAST;
|
||||
class QEnumDeclarationAST;
|
||||
class QFlagsDeclarationAST;
|
||||
class QPropertyDeclarationAST;
|
||||
class QtMemberDeclarationAST;
|
||||
class QtMethodAST;
|
||||
class QualifiedNameAST;
|
||||
|
||||
@@ -171,7 +171,7 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
|
||||
const bool isQ_SLOT = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SLOT;
|
||||
const bool isQ_SIGNAL = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SIGNAL;
|
||||
#ifdef ICHECK_BUILD
|
||||
const bool isQ_INVOKABLE = (ast->invoke_token > 0);
|
||||
const bool isQ_INVOKABLE = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_INVOKABLE;
|
||||
#endif
|
||||
|
||||
List<Declaration *> **decl_it = &ast->symbols;
|
||||
|
||||
@@ -3087,13 +3087,9 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node,
|
||||
{
|
||||
DEBUG_THIS_RULE();
|
||||
unsigned qt_invokable_token = 0;
|
||||
if (acceptStructDeclarator && (LA() == T_Q_SIGNAL || LA() == T_Q_SLOT))
|
||||
if (acceptStructDeclarator
|
||||
&& (LA() == T_Q_SIGNAL || LA() == T_Q_SLOT || LA() == T_Q_INVOKABLE))
|
||||
qt_invokable_token = consumeToken();
|
||||
#ifdef ICHECK_BUILD
|
||||
unsigned invoke_token = 0;
|
||||
if (LA() == T_Q_INVOKABLE)
|
||||
invoke_token = consumeToken();
|
||||
#endif
|
||||
|
||||
// parse a simple declaration, a function definition,
|
||||
// or a contructor declaration.
|
||||
|
||||
@@ -238,16 +238,13 @@ enum Kind {
|
||||
T_Q_FOREACH,
|
||||
T_Q_D,
|
||||
T_Q_Q,
|
||||
#ifndef ICHECK_BUILD
|
||||
T_LAST_KEYWORD = T_Q_Q,
|
||||
#else
|
||||
T_Q_INVOKABLE,
|
||||
T_Q_PROPERTY,
|
||||
T_Q_ENUMS,
|
||||
T_Q_FLAGS,
|
||||
T_Q_DECLARE_FLAGS,
|
||||
T_LAST_KEYWORD = T_Q_DECLARE_FLAGS,
|
||||
#endif
|
||||
|
||||
// aliases
|
||||
T_OR = T_PIPE_PIPE,
|
||||
T_AND = T_AMPER_AMPER,
|
||||
|
||||
Reference in New Issue
Block a user