diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 15a7151a1e6d92df18c02f9c91e88e603661d683..763ed6ff1c693583d48e45355021e0e6c3e50733 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -1432,6 +1432,8 @@ bool Preprocessor::isQtReservedWord(const QByteArray ¯oId) const return true; else if (size == 10 && macroId.at(0) == 'Q' && macroId == "Q_PROPERTY") return true; + else if (size == 18 && macroId.at(0) == 'Q' && macroId == "Q_PRIVATE_PROPERTY") + return true; else if (size == 7 && macroId.at(0) == 'Q' && macroId == "Q_ENUMS") return true; else if (size == 7 && macroId.at(0) == 'Q' && macroId == "Q_FLAGS") diff --git a/src/plugins/cpptools/cppcodeformatter.cpp b/src/plugins/cpptools/cppcodeformatter.cpp index fdb179f3a44e62b6ed7584c160298bc1bc99a659..d46c6c7271c3232ffd3c346b09fb67ebea26faa4 100644 --- a/src/plugins/cpptools/cppcodeformatter.cpp +++ b/src/plugins/cpptools/cppcodeformatter.cpp @@ -702,6 +702,7 @@ bool CodeFormatter::tryDeclaration() switch (kind) { case T_Q_ENUMS: case T_Q_PROPERTY: + case T_Q_PRIVATE_PROPERTY: case T_Q_FLAGS: case T_Q_GADGET: case T_Q_OBJECT: diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index 1db8baadeed379dcbd4b8f2a4c839c2d7870e5c0..0ef2b0e062098c6c87e6e4671eaa86704d12c156 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -3387,6 +3387,11 @@ unsigned QtPropertyDeclarationAST::firstToken() const return property_specifier_token; if (lparen_token) return lparen_token; + if (expression) + if (unsigned candidate = expression->firstToken()) + return candidate; + if (comma_token) + return comma_token; if (type_id) if (unsigned candidate = type_id->firstToken()) return candidate; @@ -3415,6 +3420,11 @@ unsigned QtPropertyDeclarationAST::lastToken() const if (type_id) if (unsigned candidate = type_id->lastToken()) return candidate; + if (comma_token) + return comma_token + 1; + if (expression) + if (unsigned candidate = expression->lastToken()) + return candidate; if (lparen_token) return lparen_token + 1; if (property_specifier_token) diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index cacf686da687e93c4e088a2fdbf58db4a28d4df7..267ee29d970e6559bb4428ae5e50282071e10bd4 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -773,6 +773,8 @@ class CPLUSPLUS_EXPORT QtPropertyDeclarationAST: public DeclarationAST public: unsigned property_specifier_token; unsigned lparen_token; + ExpressionAST *expression; // for Q_PRIVATE_PROPERTY(expression, ...) + unsigned comma_token; ExpressionAST *type_id; NameAST *property_name; QtPropertyDeclarationItemListAST *property_declaration_item_list; @@ -782,6 +784,8 @@ public: QtPropertyDeclarationAST() : property_specifier_token(0) , lparen_token(0) + , expression(0) + , comma_token(0) , type_id(0) , property_name(0) , property_declaration_item_list(0) diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp index 3a7ac4782cad49aeb82db3d91f78b8937962b8f2..749f0ce7c30de2eb92615be30ff57cead70d5227 100644 --- a/src/shared/cplusplus/ASTClone.cpp +++ b/src/shared/cplusplus/ASTClone.cpp @@ -198,6 +198,9 @@ QtPropertyDeclarationAST *QtPropertyDeclarationAST::clone(MemoryPool *pool) cons QtPropertyDeclarationAST *ast = new (pool) QtPropertyDeclarationAST; ast->property_specifier_token = property_specifier_token; ast->lparen_token = lparen_token; + if (expression) + ast->expression = expression->clone(pool); + ast->comma_token = comma_token; if (type_id) ast->type_id = type_id->clone(pool); if (property_name) diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp index e14a79f3fbce8fa6933dd791504210af95645d72..c853f6d4d1cf82f0b902558b7437e6901b509b2c 100644 --- a/src/shared/cplusplus/ASTMatcher.cpp +++ b/src/shared/cplusplus/ASTMatcher.cpp @@ -301,6 +301,13 @@ bool ASTMatcher::match(QtPropertyDeclarationAST *node, QtPropertyDeclarationAST pattern->lparen_token = node->lparen_token; + if (! pattern->expression) + pattern->expression = node->expression; + else if (! AST::match(node->expression, pattern->expression, this)) + return false; + + pattern->comma_token = node->comma_token; + if (! pattern->type_id) pattern->type_id = node->type_id; else if (! AST::match(node->type_id, pattern->type_id, this)) diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp index 893339a2a83dc9c9ae4889ea77f68344501d2908..16ce0fc572e757c6a1ac2cbbf1aba90a6fc5b4ca 100644 --- a/src/shared/cplusplus/ASTVisit.cpp +++ b/src/shared/cplusplus/ASTVisit.cpp @@ -154,6 +154,7 @@ void QtPropertyDeclarationItemAST::accept0(ASTVisitor *visitor) void QtPropertyDeclarationAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { + accept(expression, visitor); accept(type_id, visitor); accept(property_name, visitor); accept(property_declaration_item_list, visitor); diff --git a/src/shared/cplusplus/Keywords.cpp b/src/shared/cplusplus/Keywords.cpp index 340f418547eaf26b0a3d42a2be23491f3304e3d8..ed32aeb021caa2f0fbda7361bae99300fcb4a3bb 100644 --- a/src/shared/cplusplus/Keywords.cpp +++ b/src/shared/cplusplus/Keywords.cpp @@ -1442,6 +1442,47 @@ static inline int classify14(const char *s, bool q, bool) { return T_IDENTIFIER; } +static inline int classify18(const char *s, bool q, bool) { + if (q && s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'P') { + if (s[3] == 'R') { + if (s[4] == 'I') { + if (s[5] == 'V') { + if (s[6] == 'A') { + if (s[7] == 'T') { + if (s[8] == 'E') { + if (s[9] == '_') { + if (s[10] == 'P') { + if (s[11] == 'R') { + if (s[12] == 'O') { + if (s[13] == 'P') { + if (s[14] == 'E') { + if (s[15] == 'R') { + if (s[16] == 'T') { + if (s[17] == 'Y') { + return T_Q_PRIVATE_PROPERTY; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return T_IDENTIFIER; +} + static inline int classify19(const char *s, bool q, bool) { if (q && s[0] == 'Q') { if (s[1] == '_') { @@ -1502,6 +1543,7 @@ int Lexer::classify(const char *s, int n, bool q, bool x) { case 13: return classify13(s, q, x); case 14: return classify14(s, q, x); case 16: return classify16(s, q, x); + case 18: return classify18(s, q, x); case 19: return classify19(s, q, x); default: return T_IDENTIFIER; } // switch diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 4bd4a196aaf1660cbb8bc90957c6acee3e0fc316..d7b3dad29f1e549cc82ea094d0d5d2fe36a7536e 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -286,6 +286,7 @@ void Parser::skipUntilDeclaration() case T_Q_SIGNALS: case T_Q_SLOTS: case T_Q_PROPERTY: + case T_Q_PRIVATE_PROPERTY: case T_Q_ENUMS: case T_Q_FLAGS: case T_Q_INTERFACES: @@ -1972,13 +1973,26 @@ bool Parser::parseAccessDeclaration(DeclarationAST *&node) bool Parser::parseQtPropertyDeclaration(DeclarationAST *&node) { DEBUG_THIS_RULE(); - if (LA() != T_Q_PROPERTY) + const bool privateProperty = (LA() == T_Q_PRIVATE_PROPERTY); + if (LA() != T_Q_PROPERTY && !privateProperty) return false; QtPropertyDeclarationAST *ast = new (_pool)QtPropertyDeclarationAST; ast->property_specifier_token = consumeToken(); if (LA() == T_LPAREN) { ast->lparen_token = consumeToken(); + + if (privateProperty) { + if (parsePostfixExpression(ast->expression)) { + match(T_COMMA, &ast->comma_token); + } else { + error(cursor(), + "expected expression before `%s'", + tok().spell()); + return true; + } + } + parseTypeId(ast->type_id); SimpleNameAST *property_name = new (_pool) SimpleNameAST; @@ -2238,6 +2252,7 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node, ClassSpecifierAST * return parseAccessDeclaration(node); case T_Q_PROPERTY: + case T_Q_PRIVATE_PROPERTY: return parseQtPropertyDeclaration(node); case T_Q_ENUMS: diff --git a/src/shared/cplusplus/Token.h b/src/shared/cplusplus/Token.h index 49175692d786399c1aa4ee09e0f4c053d278b4c6..bbc0149543b0d26ebc08f955a895f376938170aa 100644 --- a/src/shared/cplusplus/Token.h +++ b/src/shared/cplusplus/Token.h @@ -244,6 +244,7 @@ enum Kind { T_Q_Q, T_Q_INVOKABLE, T_Q_PROPERTY, + T_Q_PRIVATE_PROPERTY, T_Q_INTERFACES, T_Q_ENUMS, T_Q_FLAGS, diff --git a/tests/tools/cplusplus-dump/dumpers.inc b/tests/tools/cplusplus-dump/dumpers.inc index ec49d7aced927ef99e6c4469127adf7ffff06a4b..fdee4f1c1c145df1baafe0fca47d269154b2e1f7 100644 --- a/tests/tools/cplusplus-dump/dumpers.inc +++ b/tests/tools/cplusplus-dump/dumpers.inc @@ -198,6 +198,9 @@ virtual bool visit(QtPropertyDeclarationAST *ast) terminal(ast->property_specifier_token, ast); if (ast->lparen_token) terminal(ast->lparen_token, ast); + nonterminal(ast->expression); + if (ast->comma_token) + terminal(ast->comma_token, ast); nonterminal(ast->type_id); nonterminal(ast->property_name); for (QtPropertyDeclarationItemListAST *iter = ast->property_declaration_item_list; iter; iter = iter->next)