From 0edd253b615b485913d2bbb504a146f6aaa89c04 Mon Sep 17 00:00:00 2001
From: Christian Kamm <christian.d.kamm@nokia.com>
Date: Mon, 6 Dec 2010 12:16:45 +0100
Subject: [PATCH] C++: Add QtPropertyDeclaration symbol.

Reviewed-by: Roberto Raggi
---
 src/shared/cplusplus/Bind.cpp                 | 70 ++++++++++++++++---
 src/shared/cplusplus/Bind.h                   |  1 -
 .../cplusplus/CPlusPlusForwardDeclarations.h  |  3 +
 src/shared/cplusplus/Control.cpp              | 11 +++
 src/shared/cplusplus/Control.h                |  3 +
 src/shared/cplusplus/Symbol.h                 |  5 ++
 src/shared/cplusplus/SymbolVisitor.h          |  3 +
 src/shared/cplusplus/Symbols.cpp              | 24 +++++++
 src/shared/cplusplus/Symbols.h                | 46 ++++++++++++
 9 files changed, 154 insertions(+), 12 deletions(-)

diff --git a/src/shared/cplusplus/Bind.cpp b/src/shared/cplusplus/Bind.cpp
index e887240b3b4..a21f73df182 100644
--- a/src/shared/cplusplus/Bind.cpp
+++ b/src/shared/cplusplus/Bind.cpp
@@ -379,15 +379,6 @@ bool Bind::visit(QtPropertyDeclarationItemAST *ast)
     return false;
 }
 
-void Bind::qtPropertyDeclarationItem(QtPropertyDeclarationItemAST *ast)
-{
-    if (! ast)
-        return;
-
-    // unsigned item_name_token = ast->item_name_token;
-    ExpressionTy expression = this->expression(ast->expression);
-}
-
 bool Bind::visit(QtInterfaceNameAST *ast)
 {
     (void) ast;
@@ -1865,15 +1856,72 @@ bool Bind::visit(QtPrivateSlotAST *ast)
     return false;
 }
 
+static void qtPropertyAttribute(TranslationUnit *unit, ExpressionAST *expression,
+                                int *flags,
+                                QtPropertyDeclaration::Flag flag,
+                                QtPropertyDeclaration::Flag function)
+{
+    if (!expression)
+        return;
+    *flags &= ~function & ~flag;
+    if (BoolLiteralAST *boollit = expression->asBoolLiteral()) {
+        const int kind = unit->tokenAt(boollit->literal_token).kind();
+        if (kind == T_TRUE)
+            *flags |= flag;
+    } else {
+        *flags |= function;
+    }
+}
+
 bool Bind::visit(QtPropertyDeclarationAST *ast)
 {
     // unsigned property_specifier_token = ast->property_specifier_token;
     // unsigned lparen_token = ast->lparen_token;
     ExpressionTy type_id = this->expression(ast->type_id);
-    /*const Name *property_name =*/ this->name(ast->property_name);
+    const Name *property_name = this->name(ast->property_name);
+
+    unsigned sourceLocation = ast->firstToken();
+    if (ast->property_name)
+        sourceLocation = ast->property_name->firstToken();
+    QtPropertyDeclaration *propertyDeclaration = control()->newQtPropertyDeclaration(sourceLocation, property_name);
+    propertyDeclaration->setType(type_id);
+
+    int flags = QtPropertyDeclaration::DesignableFlag
+            | QtPropertyDeclaration::ScriptableFlag
+            | QtPropertyDeclaration::StoredFlag;
     for (QtPropertyDeclarationItemListAST *it = ast->property_declaration_item_list; it; it = it->next) {
-        this->qtPropertyDeclarationItem(it->value);
+        if (!it->value || !it->value->item_name_token)
+            continue;
+        std::string name = spell(it->value->item_name_token);
+
+        if (name == "CONSTANT") {
+            flags |= QtPropertyDeclaration::ConstantFlag;
+        } else if (name == "FINAL") {
+            flags |= QtPropertyDeclaration::FinalFlag;
+        } else if (name == "READ") {
+            flags |= QtPropertyDeclaration::ReadFunction;
+        } else if (name == "WRITE") {
+            flags |= QtPropertyDeclaration::WriteFunction;
+        } else if (name == "RESET") {
+            flags |= QtPropertyDeclaration::ResetFunction;
+        } else if (name == "NOTIFY") {
+            flags |= QtPropertyDeclaration::NotifyFunction;
+        } else if (name == "DESIGNABLE") {
+            qtPropertyAttribute(translationUnit(), it->value->expression, &flags,
+                                QtPropertyDeclaration::DesignableFlag, QtPropertyDeclaration::DesignableFunction);
+        } else if (name == "SCRIPTABLE") {
+            qtPropertyAttribute(translationUnit(), it->value->expression, &flags,
+                                QtPropertyDeclaration::ScriptableFlag, QtPropertyDeclaration::ScriptableFunction);
+        } else if (name == "STORED") {
+            qtPropertyAttribute(translationUnit(), it->value->expression, &flags,
+                                QtPropertyDeclaration::StoredFlag, QtPropertyDeclaration::StoredFunction);
+        } else if (name == "USER") {
+            qtPropertyAttribute(translationUnit(), it->value->expression, &flags,
+                                QtPropertyDeclaration::UserFlag, QtPropertyDeclaration::UserFunction);
+        }
     }
+    propertyDeclaration->setFlags(flags);
+    _scope->addMember(propertyDeclaration);
     // unsigned rparen_token = ast->rparen_token;
     return false;
 }
diff --git a/src/shared/cplusplus/Bind.h b/src/shared/cplusplus/Bind.h
index 00bc92e6505..44f6ac2ec12 100644
--- a/src/shared/cplusplus/Bind.h
+++ b/src/shared/cplusplus/Bind.h
@@ -110,7 +110,6 @@ protected:
     const Name *objCSelectorArgument(ObjCSelectorArgumentAST *ast, bool *hasArg);
     void attribute(AttributeAST *ast);
     FullySpecifiedType declarator(DeclaratorAST *ast, const FullySpecifiedType &init, DeclaratorIdAST **declaratorId);
-    void qtPropertyDeclarationItem(QtPropertyDeclarationItemAST *ast);
     void qtInterfaceName(QtInterfaceNameAST *ast);
     void baseSpecifier(BaseSpecifierAST *ast, unsigned colon_token, Class *klass);
     void ctorInitializer(CtorInitializerAST *ast, Function *fun);
diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
index 508cedadac3..c2c54c7e196 100644
--- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
+++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
@@ -131,6 +131,9 @@ class ForwardClassDeclaration;
 
 class Token;
 
+// Qt symbols
+class QtPropertyDeclaration;
+
 // Objective-C symbols
 class ObjCBaseClass;
 class ObjCBaseProtocol;
diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp
index a0308a7e685..9a6f5a61c1e 100644
--- a/src/shared/cplusplus/Control.cpp
+++ b/src/shared/cplusplus/Control.cpp
@@ -403,6 +403,13 @@ public:
         return c;
     }
 
+    QtPropertyDeclaration *newQtPropertyDeclaration(unsigned sourceLocation, const Name *name)
+    {
+        QtPropertyDeclaration *d = new QtPropertyDeclaration(translationUnit, sourceLocation, name);
+        symbols.push_back(d);
+        return d;
+    }
+
     ObjCBaseClass *newObjCBaseClass(unsigned sourceLocation, const Name *name)
     {
         ObjCBaseClass *c = new ObjCBaseClass(translationUnit, sourceLocation, name);
@@ -709,6 +716,10 @@ ForwardClassDeclaration *Control::newForwardClassDeclaration(unsigned sourceLoca
                                                              const Name *name)
 { return d->newForwardClassDeclaration(sourceLocation, name); }
 
+QtPropertyDeclaration *Control::newQtPropertyDeclaration(unsigned sourceLocation,
+                                                         const Name *name)
+{ return d->newQtPropertyDeclaration(sourceLocation, name); }
+
 ObjCBaseClass *Control::newObjCBaseClass(unsigned sourceLocation, const Name *name)
 { return d->newObjCBaseClass(sourceLocation, name); }
 
diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h
index f3a547d8cf9..0d3f613d075 100644
--- a/src/shared/cplusplus/Control.h
+++ b/src/shared/cplusplus/Control.h
@@ -158,6 +158,9 @@ public:
     /// Creates a new ForwardClassDeclaration symbol.
     ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, const Name *name = 0);
 
+    /// Creates a new QtPropertyDeclaration symbol.
+    QtPropertyDeclaration *newQtPropertyDeclaration(unsigned sourceLocation, const Name *name = 0);
+
     ObjCBaseClass *newObjCBaseClass(unsigned sourceLocation, const Name *name);
     ObjCBaseProtocol *newObjCBaseProtocol(unsigned sourceLocation, const Name *name);
 
diff --git a/src/shared/cplusplus/Symbol.h b/src/shared/cplusplus/Symbol.h
index 23a2a2f8cd2..b5bb9ced286 100644
--- a/src/shared/cplusplus/Symbol.h
+++ b/src/shared/cplusplus/Symbol.h
@@ -202,6 +202,9 @@ public:
     /// Returns true if this Symbol is a ForwardClassDeclaration.
     bool isForwardClassDeclaration() const;
 
+    /// Returns true if this Symbol is a QtPropertyDeclaration.
+    bool isQtPropertyDeclaration() const;
+
     bool isObjCBaseClass() const;
     bool isObjCBaseProtocol() const;
 
@@ -238,6 +241,7 @@ public:
     virtual const TypenameArgument *asTypenameArgument() const { return 0; }
     virtual const BaseClass *asBaseClass() const { return 0; }
     virtual const ForwardClassDeclaration *asForwardClassDeclaration() const { return 0; }
+    virtual const QtPropertyDeclaration *asQtPropertyDeclaration() const { return 0; }
     virtual const ObjCBaseClass *asObjCBaseClass() const { return 0; }
     virtual const ObjCBaseProtocol *asObjCBaseProtocol() const { return 0; }
     virtual const ObjCClass *asObjCClass() const { return 0; }
@@ -262,6 +266,7 @@ public:
     virtual TypenameArgument *asTypenameArgument() { return 0; }
     virtual BaseClass *asBaseClass() { return 0; }
     virtual ForwardClassDeclaration *asForwardClassDeclaration() { return 0; }
+    virtual QtPropertyDeclaration *asQtPropertyDeclaration() { return 0; }
     virtual ObjCBaseClass *asObjCBaseClass() { return 0; }
     virtual ObjCBaseProtocol *asObjCBaseProtocol() { return 0; }
     virtual ObjCClass *asObjCClass() { return 0; }
diff --git a/src/shared/cplusplus/SymbolVisitor.h b/src/shared/cplusplus/SymbolVisitor.h
index 8e114935a7c..85959911a36 100644
--- a/src/shared/cplusplus/SymbolVisitor.h
+++ b/src/shared/cplusplus/SymbolVisitor.h
@@ -87,6 +87,9 @@ public:
     virtual bool visit(Block *) { return true; }
     virtual bool visit(ForwardClassDeclaration *) { return true; }
 
+    // Qt
+    virtual bool visit(QtPropertyDeclaration *) { return true; }
+
     // Objective-C
     virtual bool visit(ObjCBaseClass *) { return true; }
     virtual bool visit(ObjCBaseProtocol *) { return true; }
diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp
index 518ceab7dec..128c1d258f6 100644
--- a/src/shared/cplusplus/Symbols.cpp
+++ b/src/shared/cplusplus/Symbols.cpp
@@ -684,6 +684,30 @@ void Class::visitSymbol0(SymbolVisitor *visitor)
     }
 }
 
+
+QtPropertyDeclaration::QtPropertyDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name)
+{ }
+
+QtPropertyDeclaration::~QtPropertyDeclaration()
+{ }
+
+void QtPropertyDeclaration::setType(const FullySpecifiedType &type)
+{ _type = type; }
+
+void QtPropertyDeclaration::setFlags(int flags)
+{ _flags = flags; }
+
+int QtPropertyDeclaration::flags() const
+{ return _flags; }
+
+FullySpecifiedType QtPropertyDeclaration::type() const
+{ return _type; }
+
+void QtPropertyDeclaration::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+
 ObjCBaseClass::ObjCBaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
     : Symbol(translationUnit, sourceLocation, name)
 { }
diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h
index e7a2dec7043..7de9b2249e4 100644
--- a/src/shared/cplusplus/Symbols.h
+++ b/src/shared/cplusplus/Symbols.h
@@ -520,6 +520,52 @@ private:
     std::vector<BaseClass *> _baseClasses;
 };
 
+class CPLUSPLUS_EXPORT QtPropertyDeclaration: public Symbol
+{
+public:
+    enum Flag {
+        ReadFunction = 1 << 0,
+        WriteFunction = 1 << 1,
+        ResetFunction = 1 << 2,
+        NotifyFunction = 1 << 3,
+        DesignableFlag = 1 << 4,
+        DesignableFunction = 1 << 5,
+        ScriptableFlag = 1 << 6,
+        ScriptableFunction = 1 << 7,
+        StoredFlag = 1 << 8,
+        StoredFunction = 1 << 9,
+        UserFlag = 1 << 10,
+        UserFunction = 1 << 11,
+        ConstantFlag = 1 << 12,
+        FinalFlag = 1 << 13,
+    };
+
+public:
+    QtPropertyDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    virtual ~QtPropertyDeclaration();
+
+    void setType(const FullySpecifiedType &type);
+
+    void setFlags(int flags);
+    int flags() const;
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const QtPropertyDeclaration *asQtPropertyDeclaration() const
+    { return this; }
+
+    virtual QtPropertyDeclaration *asQtPropertyDeclaration()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+
+private:
+    FullySpecifiedType _type;
+    int _flags;
+};
+
 class CPLUSPLUS_EXPORT ObjCBaseClass: public Symbol
 {
 public:
-- 
GitLab