Commit 527a9bd5 authored by Roberto Raggi's avatar Roberto Raggi

Inital support for Q_D/Q_Q declarations.

parent 5fc8324b
......@@ -1462,6 +1462,10 @@ bool Preprocessor::isQtReservedWord(const QByteArray &macroId) 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")
......
......@@ -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;
}
......@@ -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);
......
......@@ -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
{
......
......@@ -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:
......
......@@ -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())
......
......@@ -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;
......
......@@ -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);
......
......@@ -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)) {
......
......@@ -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 *) { }
......
......@@ -162,6 +162,7 @@ class PostfixAST;
class PostfixDeclaratorAST;
class PostfixExpressionAST;
class PtrOperatorAST;
class QtMemberDeclarationAST;
class QtMethodAST;
class QualifiedNameAST;
class ReferenceAST;
......
......@@ -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;
}
......@@ -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;
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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() :
......
......@@ -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,
......
......@@ -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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment