From 527a9bd526d854d3f43b633a94af6dea642297db Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@nokia.com> Date: Mon, 30 Nov 2009 16:30:21 +0100 Subject: [PATCH] Inital support for Q_D/Q_Q declarations. --- src/libs/cplusplus/pp-engine.cpp | 4 +++ src/plugins/cppeditor/cppeditor.cpp | 44 ++++++++++++++++++------- src/plugins/cppeditor/cppeditor.h | 5 ++- src/shared/cplusplus/AST.cpp | 14 ++++++++ src/shared/cplusplus/AST.h | 20 +++++++++++ src/shared/cplusplus/ASTMatch0.cpp | 8 +++++ src/shared/cplusplus/ASTMatcher.cpp | 19 +++++++++++ src/shared/cplusplus/ASTMatcher.h | 1 + src/shared/cplusplus/ASTVisit.cpp | 8 +++++ src/shared/cplusplus/ASTVisitor.h | 2 ++ src/shared/cplusplus/ASTfwd.h | 1 + src/shared/cplusplus/CheckStatement.cpp | 33 +++++++++++++++++++ src/shared/cplusplus/CheckStatement.h | 1 + src/shared/cplusplus/Keywords.cpp | 12 ++++++- src/shared/cplusplus/Parser.cpp | 10 ++++++ src/shared/cplusplus/Token.cpp | 2 +- src/shared/cplusplus/Token.h | 4 ++- src/tools/cplusplus/Main.cpp | 26 +++++++-------- 18 files changed, 185 insertions(+), 29 deletions(-) diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index c2bb068bced..2341df2423d 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -1462,6 +1462,10 @@ bool Preprocessor::isQtReservedWord(const QByteArray ¯oId) const return true; else if (size == 6 && macroId.at(0) == 'Q' && macroId == "Q_SLOT") return true; + else if (size == 3 && macroId.at(0) == 'Q' && macroId == "Q_D") + return true; + else if (size == 3 && macroId.at(0) == 'Q' && macroId == "Q_Q") + return true; else if (size == 6 && macroId.at(0) == 'S' && macroId == "SIGNAL") return true; else if (size == 4 && macroId.at(0) == 'S' && macroId == "SLOT") diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 8e177406bc6..e87e533a639 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -186,19 +186,20 @@ private: } }; -class FindUses: protected ASTVisitor +class FindLocalUses: protected ASTVisitor { Scope *_functionScope; - FindScope findScope; public: - FindUses(TranslationUnit *translationUnit) - : ASTVisitor(translationUnit) + FindLocalUses(TranslationUnit *translationUnit) + : ASTVisitor(translationUnit), hasD(false), hasQ(false) { } // local and external uses. SemanticInfo::LocalUseMap localUses; + bool hasD; + bool hasQ; void operator()(FunctionDefinitionAST *ast) { @@ -357,6 +358,16 @@ protected: return false; } + virtual bool visit(QtMemberDeclarationAST *ast) + { + if (tokenKind(ast->q_token) == T_Q_D) + hasD = true; + else + hasQ = true; + + return true; + } + virtual bool visit(ExpressionOrDeclarationStatementAST *ast) { accept(ast->declaration); @@ -929,6 +940,7 @@ void CPPEditor::updateMethodBoxIndex() } void CPPEditor::highlightUses(const QList<SemanticInfo::Use> &uses, + const SemanticInfo &semanticInfo, QList<QTextEdit::ExtraSelection> *selections) { bool isUnused = false; @@ -951,6 +963,14 @@ void CPPEditor::highlightUses(const QList<SemanticInfo::Use> &uses, sel.cursor.setPosition(anchor); sel.cursor.setPosition(position, QTextCursor::KeepAnchor); + if (isUnused) { + if (semanticInfo.hasQ && sel.cursor.selectedText() == QLatin1String("q")) + continue; // skip q + + else if (semanticInfo.hasD && sel.cursor.selectedText() == QLatin1String("d")) + continue; // skip d + } + selections->append(sel); } } @@ -1953,14 +1973,12 @@ void CPPEditor::updateSemanticInfo(const SemanticInfo &semanticInfo) } } - if (uses.size() == 1) { + if (uses.size() == 1) // it's an unused declaration - highlightUses(uses, &unusedSelections); - } else if (good) { - QList<QTextEdit::ExtraSelection> selections; - highlightUses(uses, &selections); - m_renameSelections += selections; - } + highlightUses(uses, semanticInfo, &unusedSelections); + + else if (good && m_renameSelections.isEmpty()) + highlightUses(uses, semanticInfo, &m_renameSelections); } setExtraSelections(UnusedSymbolSelection, unusedSelections); @@ -2078,7 +2096,7 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source) FunctionDefinitionUnderCursor functionDefinitionUnderCursor(translationUnit); FunctionDefinitionAST *currentFunctionDefinition = functionDefinitionUnderCursor(ast, source.line, source.column); - FindUses useTable(translationUnit); + FindLocalUses useTable(translationUnit); useTable(currentFunctionDefinition); SemanticInfo semanticInfo; @@ -2086,6 +2104,8 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source) semanticInfo.snapshot = snapshot; semanticInfo.doc = doc; semanticInfo.localUses = useTable.localUses; + semanticInfo.hasQ = useTable.hasQ; + semanticInfo.hasD = useTable.hasD; return semanticInfo; } diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 16bf04f94ec..716240fd3c9 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -79,10 +79,12 @@ public: typedef QHashIterator<CPlusPlus::Symbol *, QList<Use> > LocalUseIterator; SemanticInfo() - : revision(-1) + : revision(-1), hasQ(false), hasD(false) { } int revision; + bool hasQ: 1; + bool hasD: 1; CPlusPlus::Snapshot snapshot; CPlusPlus::Document::Ptr doc; LocalUseMap localUses; @@ -253,6 +255,7 @@ private: SemanticHighlighter::Source currentSource(bool force = false); void highlightUses(const QList<SemanticInfo::Use> &uses, + const SemanticInfo &semanticInfo, QList<QTextEdit::ExtraSelection> *selections); void createToolBar(CPPEditorEditable *editable); diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index b4b1f1a3efb..e901b67e92d 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -246,7 +246,21 @@ unsigned QtMethodAST::lastToken() const return method_token + 1; } +unsigned QtMemberDeclarationAST::firstToken() const +{ + return q_token; +} +unsigned QtMemberDeclarationAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + else if (type_id) + return type_id->lastToken(); + else if (lparen_token) + return lparen_token + 1; + return q_token + 1; +} unsigned BinaryExpressionAST::firstToken() const { diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index eb647312816..3902fcb5c52 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -246,6 +246,7 @@ public: virtual PostfixDeclaratorAST *asPostfixDeclarator() { return 0; } virtual PostfixExpressionAST *asPostfixExpression() { return 0; } virtual PtrOperatorAST *asPtrOperator() { return 0; } + virtual QtMemberDeclarationAST *asQtMemberDeclaration() { return 0; } virtual QtMethodAST *asQtMethod() { return 0; } virtual QualifiedNameAST *asQualifiedName() { return 0; } virtual ReferenceAST *asReference() { return 0; } @@ -582,6 +583,25 @@ protected: virtual bool match0(AST *, ASTMatcher *); }; +class CPLUSPLUS_EXPORT QtMemberDeclarationAST: public StatementAST +{ +public: + unsigned q_token; + unsigned lparen_token; + ExpressionAST *type_id; + unsigned rparen_token; + +public: + virtual QtMemberDeclarationAST *asQtMemberDeclaration() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + class CPLUSPLUS_EXPORT BinaryExpressionAST: public ExpressionAST { public: diff --git a/src/shared/cplusplus/ASTMatch0.cpp b/src/shared/cplusplus/ASTMatch0.cpp index 7c4ff19ae6e..e16c0788080 100644 --- a/src/shared/cplusplus/ASTMatch0.cpp +++ b/src/shared/cplusplus/ASTMatch0.cpp @@ -128,6 +128,14 @@ bool QtMethodAST::match0(AST *pattern, ASTMatcher *matcher) return false; } +bool QtMemberDeclarationAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (QtMemberDeclarationAST *_other = pattern->asQtMemberDeclaration()) + return matcher->match(this, _other); + + return false; +} + bool BinaryExpressionAST::match0(AST *pattern, ASTMatcher *matcher) { if (BinaryExpressionAST *_other = pattern->asBinaryExpression()) diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp index 9ded92f8ef9..b7920f767f4 100644 --- a/src/shared/cplusplus/ASTMatcher.cpp +++ b/src/shared/cplusplus/ASTMatcher.cpp @@ -274,6 +274,25 @@ bool ASTMatcher::match(QtMethodAST *node, QtMethodAST *pattern) return true; } +bool ASTMatcher::match(QtMemberDeclarationAST *node, QtMemberDeclarationAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->q_token = node->q_token; + + pattern->lparen_token = node->lparen_token; + + if (! pattern->type_id) + pattern->type_id = node->type_id; + else if (! AST::match(node->type_id, pattern->type_id, this)) + return false; + + pattern->rparen_token = node->rparen_token; + + return true; +} + bool ASTMatcher::match(BinaryExpressionAST *node, BinaryExpressionAST *pattern) { (void) node; diff --git a/src/shared/cplusplus/ASTMatcher.h b/src/shared/cplusplus/ASTMatcher.h index f299dc51bbd..c3490ac69be 100644 --- a/src/shared/cplusplus/ASTMatcher.h +++ b/src/shared/cplusplus/ASTMatcher.h @@ -135,6 +135,7 @@ public: virtual bool match(UsingDirectiveAST *node, UsingDirectiveAST *pattern); virtual bool match(WhileStatementAST *node, WhileStatementAST *pattern); virtual bool match(QtMethodAST *node, QtMethodAST *pattern); + virtual bool match(QtMemberDeclarationAST *node, QtMemberDeclarationAST *pattern); virtual bool match(ObjCClassDeclarationAST *node, ObjCClassDeclarationAST *pattern); virtual bool match(ObjCClassForwardDeclarationAST *node, ObjCClassForwardDeclarationAST *pattern); virtual bool match(ObjCProtocolDeclarationAST *node, ObjCProtocolDeclarationAST *pattern); diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp index 6e26f772b24..877dd8df743 100644 --- a/src/shared/cplusplus/ASTVisit.cpp +++ b/src/shared/cplusplus/ASTVisit.cpp @@ -131,6 +131,14 @@ void QtMethodAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +void QtMemberDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(type_id, visitor); + } + visitor->endVisit(this); +} + void BinaryExpressionAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h index 0a42b6f4d4e..7d73ba3ed54 100644 --- a/src/shared/cplusplus/ASTVisitor.h +++ b/src/shared/cplusplus/ASTVisitor.h @@ -198,6 +198,7 @@ public: virtual bool visit(UsingDirectiveAST *) { return true; } virtual bool visit(WhileStatementAST *) { return true; } virtual bool visit(QtMethodAST *) { return true; } + virtual bool visit(QtMemberDeclarationAST *) { return true; } // ObjC++ virtual bool visit(ObjCClassDeclarationAST *) { return true; } @@ -323,6 +324,7 @@ public: virtual void endVisit(UsingDirectiveAST *) { } virtual void endVisit(WhileStatementAST *) { } virtual void endVisit(QtMethodAST *) { } + virtual void endVisit(QtMemberDeclarationAST *) { } // ObjC++ virtual void endVisit(ObjCClassDeclarationAST *) { } diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h index 18f1987d5e9..cefdfdc3815 100644 --- a/src/shared/cplusplus/ASTfwd.h +++ b/src/shared/cplusplus/ASTfwd.h @@ -162,6 +162,7 @@ class PostfixAST; class PostfixDeclaratorAST; class PostfixExpressionAST; class PtrOperatorAST; +class QtMemberDeclarationAST; class QtMethodAST; class QualifiedNameAST; class ReferenceAST; diff --git a/src/shared/cplusplus/CheckStatement.cpp b/src/shared/cplusplus/CheckStatement.cpp index 1273f816105..dec68b1ea4c 100644 --- a/src/shared/cplusplus/CheckStatement.cpp +++ b/src/shared/cplusplus/CheckStatement.cpp @@ -54,6 +54,9 @@ #include "CoreTypes.h" #include "Control.h" #include "Symbols.h" +#include "Names.h" +#include "Literals.h" +#include <string> using namespace CPlusPlus; @@ -307,4 +310,34 @@ bool CheckStatement::visit(WhileStatementAST *ast) return false; } +bool CheckStatement::visit(QtMemberDeclarationAST *ast) +{ + Name *name = 0; + + if (tokenKind(ast->q_token) == T_Q_D) + name = control()->nameId(control()->findOrInsertIdentifier("d")); + else + name = control()->nameId(control()->findOrInsertIdentifier("q")); + + FullySpecifiedType declTy = semantic()->check(ast->type_id, _scope); + + if (tokenKind(ast->q_token) == T_Q_D) { + if (NamedType *namedTy = declTy->asNamedType()) { + if (NameId *nameId = namedTy->name()->asNameId()) { + std::string privateClass; + privateClass += nameId->identifier()->chars(); + privateClass += "Private"; + + Name *privName = control()->nameId(control()->findOrInsertIdentifier(privateClass.c_str(), privateClass.size())); + declTy.setType(control()->namedType(privName)); + } + } + } + + Declaration *symbol = control()->newDeclaration(/*generated*/ 0, name); + symbol->setType(control()->pointerType(declTy)); + + _scope->enterSymbol(symbol); + return false; +} diff --git a/src/shared/cplusplus/CheckStatement.h b/src/shared/cplusplus/CheckStatement.h index 6bd0c868ab9..e31d507a5ef 100644 --- a/src/shared/cplusplus/CheckStatement.h +++ b/src/shared/cplusplus/CheckStatement.h @@ -88,6 +88,7 @@ protected: virtual bool visit(TryBlockStatementAST *ast); virtual bool visit(CatchClauseAST *ast); virtual bool visit(WhileStatementAST *ast); + virtual bool visit(QtMemberDeclarationAST *ast); private: StatementAST *_statement; diff --git a/src/shared/cplusplus/Keywords.cpp b/src/shared/cplusplus/Keywords.cpp index 48af1244736..6da25125f7b 100644 --- a/src/shared/cplusplus/Keywords.cpp +++ b/src/shared/cplusplus/Keywords.cpp @@ -65,7 +65,7 @@ static inline int classify2(const char *s, bool) { return T_IDENTIFIER; } -static inline int classify3(const char *s, bool) { +static inline int classify3(const char *s, bool q) { if (s[0] == 'a') { if (s[1] == 's') { if (s[2] == 'm') { @@ -101,6 +101,16 @@ static inline int classify3(const char *s, bool) { } } } + else if (q && s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'D') { + return T_Q_D; + } + else if (s[2] == 'Q') { + return T_Q_Q; + } + } + } return T_IDENTIFIER; } diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 7e464b7d8ba..a4be22f5b4c 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -2104,6 +2104,16 @@ bool Parser::parseStatement(StatementAST *&node) if (objCEnabled()) return parseObjCSynchronizedStatement(node); + case T_Q_D: + case T_Q_Q: { + QtMemberDeclarationAST *ast = new (_pool) QtMemberDeclarationAST; + ast->q_token = consumeToken(); + match(T_LPAREN, &ast->lparen_token); + parseTypeId(ast->type_id); + match(T_RPAREN, &ast->rparen_token); + node = ast; + } return true; + default: if (LA() == T_IDENTIFIER && LA(2) == T_COLON) return parseLabeledStatement(node); diff --git a/src/shared/cplusplus/Token.cpp b/src/shared/cplusplus/Token.cpp index 48bf61354f0..ce661e43b05 100644 --- a/src/shared/cplusplus/Token.cpp +++ b/src/shared/cplusplus/Token.cpp @@ -91,7 +91,7 @@ static const char *token_names[] = { ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"), ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"), - ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"), ("Q_FOREACH") + ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"), ("Q_FOREACH"), ("Q_D"), ("Q_Q") }; Token::Token() : diff --git a/src/shared/cplusplus/Token.h b/src/shared/cplusplus/Token.h index 3829baa651f..acbe3927ba2 100644 --- a/src/shared/cplusplus/Token.h +++ b/src/shared/cplusplus/Token.h @@ -236,8 +236,10 @@ enum Kind { T_Q_SIGNALS, T_Q_SLOTS, T_Q_FOREACH, + T_Q_D, + T_Q_Q, - T_LAST_KEYWORD = T_Q_FOREACH, + T_LAST_KEYWORD = T_Q_Q, // aliases T_OR = T_PIPE_PIPE, diff --git a/src/tools/cplusplus/Main.cpp b/src/tools/cplusplus/Main.cpp index 342c7751fd1..7c2e65d22df 100644 --- a/src/tools/cplusplus/Main.cpp +++ b/src/tools/cplusplus/Main.cpp @@ -100,7 +100,7 @@ class FindASTNodes: protected ASTVisitor { public: FindASTNodes(Document::Ptr doc, QTextDocument *document) - : ASTVisitor(doc->control()), document(document) + : ASTVisitor(doc->translationUnit()), document(document) { } @@ -159,8 +159,8 @@ class Accept0CG: protected ASTVisitor QTextStream *out; public: - Accept0CG(const QDir &cplusplusDir, Control *control) - : ASTVisitor(control), _cplusplusDir(cplusplusDir), out(0) + Accept0CG(const QDir &cplusplusDir, TranslationUnit *unit) + : ASTVisitor(unit), _cplusplusDir(cplusplusDir), out(0) { } void operator()(AST *ast) @@ -296,8 +296,8 @@ class Match0CG: protected ASTVisitor QTextStream *out; public: - Match0CG(const QDir &cplusplusDir, Control *control) - : ASTVisitor(control), _cplusplusDir(cplusplusDir), out(0) + Match0CG(const QDir &cplusplusDir, TranslationUnit *unit) + : ASTVisitor(unit), _cplusplusDir(cplusplusDir), out(0) { } void operator()(AST *ast) @@ -406,8 +406,8 @@ class MatcherCPPCG: protected ASTVisitor QTextStream *out; public: - MatcherCPPCG(const QDir &cplusplusDir, Control *control) - : ASTVisitor(control), _cplusplusDir(cplusplusDir), out(0) + MatcherCPPCG(const QDir &cplusplusDir, TranslationUnit *unit) + : ASTVisitor(unit), _cplusplusDir(cplusplusDir), out(0) { } void operator()(AST *ast) @@ -560,7 +560,7 @@ class RemoveCastMethods: protected ASTVisitor { public: RemoveCastMethods(Document::Ptr doc, QTextDocument *document) - : ASTVisitor(doc->control()), document(document) {} + : ASTVisitor(doc->translationUnit()), document(document) {} QList<QTextCursor> operator()(AST *ast) { @@ -666,13 +666,13 @@ QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir) out << document.toPlainText(); } - Accept0CG cg(cplusplusDir, AST_h_document->control()); + Accept0CG cg(cplusplusDir, AST_h_document->translationUnit()); cg(AST_h_document->translationUnit()->ast()); - Match0CG cg2(cplusplusDir, AST_h_document->control()); + Match0CG cg2(cplusplusDir, AST_h_document->translationUnit()); cg2(AST_h_document->translationUnit()->ast()); - MatcherCPPCG cg3(cplusplusDir, AST_h_document->control()); + MatcherCPPCG cg3(cplusplusDir, AST_h_document->translationUnit()); cg3(AST_h_document->translationUnit()->ast()); return astDerivedClasses; @@ -682,7 +682,7 @@ class FindASTForwards: protected ASTVisitor { public: FindASTForwards(Document::Ptr doc, QTextDocument *document) - : ASTVisitor(doc->control()), document(document) + : ASTVisitor(doc->translationUnit()), document(document) {} QList<QTextCursor> operator()(AST *ast) @@ -887,5 +887,5 @@ int main(int argc, char *argv[]) astDerivedClasses.sort(); generateASTFwd_h(snapshot, cplusplusDir, astDerivedClasses); - generateASTPatternBuilder_h(cplusplusDir); + //generateASTPatternBuilder_h(cplusplusDir); } -- GitLab