From e0544e8d19763d20addbc57c91d4e40ff85109ce Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Fri, 13 Aug 2010 14:36:45 +0200
Subject: [PATCH] Process the objc classes and protocols

---
 src/shared/cplusplus/Bind.cpp | 142 +++++++++++++++++++++++++++-------
 src/shared/cplusplus/Bind.h   |   7 +-
 2 files changed, 118 insertions(+), 31 deletions(-)

diff --git a/src/shared/cplusplus/Bind.cpp b/src/shared/cplusplus/Bind.cpp
index 12a2b41d0dd..ddbf370a71f 100644
--- a/src/shared/cplusplus/Bind.cpp
+++ b/src/shared/cplusplus/Bind.cpp
@@ -803,16 +803,19 @@ bool Bind::visit(ObjCProtocolRefsAST *ast)
     return false;
 }
 
-void Bind::objCProtocolRefs(ObjCProtocolRefsAST *ast)
+void Bind::objCProtocolRefs(ObjCProtocolRefsAST *ast, Symbol *objcClassOrProtocol)
 {
     if (! ast)
         return;
 
-    // unsigned less_token = ast->less_token;
     for (NameListAST *it = ast->identifier_list; it; it = it->next) {
-        /*const Name *value =*/ this->name(it->value);
+        const Name *protocolName = this->name(it->value);
+        ObjCBaseProtocol *baseProtocol = control()->newObjCBaseProtocol(it->value->firstToken(), protocolName);
+        if (ObjCClass *klass = objcClassOrProtocol->asObjCClass())
+            klass->addProtocol(baseProtocol);
+        else if (ObjCProtocol *proto = objcClassOrProtocol->asObjCProtocol())
+            proto->addProtocol(baseProtocol);
     }
-    // unsigned greater_token = ast->greater_token;
 }
 
 bool Bind::visit(ObjCMessageArgumentAST *ast)
@@ -855,8 +858,10 @@ bool Bind::visit(ObjCInstanceVariablesDeclarationAST *ast)
     return false;
 }
 
-void Bind::objCInstanceVariablesDeclaration(ObjCInstanceVariablesDeclarationAST *ast)
+void Bind::objCInstanceVariablesDeclaration(ObjCInstanceVariablesDeclarationAST *ast, ObjCClass *klass)
 {
+    (void) klass;
+
     if (! ast)
         return;
 
@@ -2043,45 +2048,116 @@ bool Bind::visit(ObjCClassForwardDeclarationAST *ast)
     return false;
 }
 
+unsigned Bind::calculateScopeStart(ObjCClassDeclarationAST *ast) const
+{
+    if (ast->inst_vars_decl)
+        if (unsigned pos = ast->inst_vars_decl->lbrace_token)
+            return tokenAt(pos).end();
+
+    if (ast->protocol_refs)
+        if (unsigned pos = ast->protocol_refs->lastToken())
+            return tokenAt(pos - 1).end();
+
+    if (ast->superclass)
+        if (unsigned pos = ast->superclass->lastToken())
+            return tokenAt(pos - 1).end();
+
+    if (ast->colon_token)
+        return tokenAt(ast->colon_token).end();
+
+    if (ast->rparen_token)
+        return tokenAt(ast->rparen_token).end();
+
+    if (ast->category_name)
+        if (unsigned pos = ast->category_name->lastToken())
+            return tokenAt(pos - 1).end();
+
+    if (ast->lparen_token)
+        return tokenAt(ast->lparen_token).end();
+
+    if (ast->class_name)
+        if (unsigned pos = ast->class_name->lastToken())
+            return tokenAt(pos - 1).end();
+
+    return tokenAt(ast->firstToken()).offset;
+}
+
 bool Bind::visit(ObjCClassDeclarationAST *ast)
 {
-    FullySpecifiedType type;
+    FullySpecifiedType declSpecifiers;
     for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
-        type = this->specifier(it->value, type);
+        declSpecifiers = this->specifier(it->value, declSpecifiers);
     }
-    // unsigned interface_token = ast->interface_token;
-    // unsigned implementation_token = ast->implementation_token;
-    /*const Name *class_name =*/ this->name(ast->class_name);
-    // unsigned lparen_token = ast->lparen_token;
-    /*const Name *category_name =*/ this->name(ast->category_name);
-    // unsigned rparen_token = ast->rparen_token;
-    // unsigned colon_token = ast->colon_token;
-    /*const Name *superclass =*/ this->name(ast->superclass);
-    this->objCProtocolRefs(ast->protocol_refs);
-    this->objCInstanceVariablesDeclaration(ast->inst_vars_decl);
+    const Name *class_name = this->name(ast->class_name);
+    const Name *category_name = this->name(ast->category_name);
+
+    const unsigned sourceLocation = ast->class_name ? ast->class_name->firstToken() : ast->firstToken();
+
+    ObjCClass *klass = control()->newObjCClass(sourceLocation, class_name);
+    ast->symbol = klass;
+    _scope->addMember(klass);
+
+    klass->setStartOffset(calculateScopeStart(ast));
+    klass->setEndOffset(tokenAt(ast->lastToken() - 1).begin());
+
+    if (ast->interface_token)
+        klass->setInterface(true);
+
+    klass->setCategoryName(category_name);
+
+    Scope *previousScope = switchScope(klass);
+
+    if (const Name *superclass = this->name(ast->superclass)) {
+        ObjCBaseClass *superKlass = control()->newObjCBaseClass(ast->superclass->firstToken(), superclass);
+        klass->setBaseClass(superKlass);
+    }
+
+    this->objCProtocolRefs(ast->protocol_refs, klass);
+    this->objCInstanceVariablesDeclaration(ast->inst_vars_decl, klass);
     for (DeclarationListAST *it = ast->member_declaration_list; it; it = it->next) {
         this->declaration(it->value);
     }
-    // unsigned end_token = ast->end_token;
-    // ObjCClass *symbol = ast->symbol;
+    (void) switchScope(previousScope);
     return false;
 }
 
 bool Bind::visit(ObjCProtocolForwardDeclarationAST *ast)
 {
-    FullySpecifiedType type;
+    FullySpecifiedType declSpecifiers;
     for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
-        type = this->specifier(it->value, type);
+        declSpecifiers = this->specifier(it->value, declSpecifiers);
     }
-    // unsigned protocol_token = ast->protocol_token;
+
+    List<ObjCForwardProtocolDeclaration *> **symbolTail = &ast->symbols;
+
+    // unsigned class_token = ast->class_token;
     for (NameListAST *it = ast->identifier_list; it; it = it->next) {
-        /*const Name *value =*/ this->name(it->value);
+        const Name *name = this->name(it->value);
+
+        const unsigned sourceLocation = it->value ? it->value->firstToken() : ast->firstToken();
+        ObjCForwardProtocolDeclaration *fwd = control()->newObjCForwardProtocolDeclaration(sourceLocation, name);
+        setDeclSpecifiers(fwd, declSpecifiers);
+        _scope->addMember(fwd);
+
+        *symbolTail = new (translationUnit()->memoryPool()) List<ObjCForwardProtocolDeclaration *>(fwd);
+        symbolTail = &(*symbolTail)->next;
     }
-    // unsigned semicolon_token = ast->semicolon_token;
-    // List<ObjCForwardProtocolDeclaration *> *symbols = ast->symbols;
+
     return false;
 }
 
+unsigned Bind::calculateScopeStart(ObjCProtocolDeclarationAST *ast) const
+{
+    if (ast->protocol_refs)
+        if (unsigned pos = ast->protocol_refs->lastToken())
+            return tokenAt(pos - 1).end();
+    if (ast->name)
+        if (unsigned pos = ast->name->lastToken())
+            return tokenAt(pos - 1).end();
+
+    return tokenAt(ast->firstToken()).offset;
+}
+
 bool Bind::visit(ObjCProtocolDeclarationAST *ast)
 {
     FullySpecifiedType type;
@@ -2089,13 +2165,21 @@ bool Bind::visit(ObjCProtocolDeclarationAST *ast)
         type = this->specifier(it->value, type);
     }
     // unsigned protocol_token = ast->protocol_token;
-    /*const Name *name =*/ this->name(ast->name);
-    this->objCProtocolRefs(ast->protocol_refs);
+    const Name *name = this->name(ast->name);
+
+    const unsigned sourceLocation = ast->name ? ast->name->firstToken() : ast->firstToken();
+    ObjCProtocol *protocol = control()->newObjCProtocol(sourceLocation, name);
+    protocol->setStartOffset(calculateScopeStart(ast));
+    protocol->setEndOffset(tokenAt(ast->lastToken() - 1).end());
+    ast->symbol = protocol;
+    _scope->addMember(protocol);
+
+    Scope *previousScope = switchScope(protocol);
+    this->objCProtocolRefs(ast->protocol_refs, protocol);
     for (DeclarationListAST *it = ast->member_declaration_list; it; it = it->next) {
         this->declaration(it->value);
     }
-    // unsigned end_token = ast->end_token;
-    // ObjCProtocol *symbol = ast->symbol;
+    (void) switchScope(previousScope);
     return false;
 }
 
diff --git a/src/shared/cplusplus/Bind.h b/src/shared/cplusplus/Bind.h
index 3a97316ae9a..adb210afbbe 100644
--- a/src/shared/cplusplus/Bind.h
+++ b/src/shared/cplusplus/Bind.h
@@ -91,6 +91,9 @@ protected:
     int switchVisibility(int visibility);
     int switchMethodKey(int methodKey);
 
+    unsigned calculateScopeStart(ObjCClassDeclarationAST *ast) const;
+    unsigned calculateScopeStart(ObjCProtocolDeclarationAST *ast) const;
+
     const Name *objCSelectorArgument(ObjCSelectorArgumentAST *ast, bool *hasArg);
     void attribute(AttributeAST *ast);
     FullySpecifiedType declarator(DeclaratorAST *ast, const FullySpecifiedType &init, DeclaratorIdAST **declaratorId);
@@ -109,10 +112,10 @@ protected:
     int cppOperator(OperatorAST *ast);
     void parameterDeclarationClause(ParameterDeclarationClauseAST *ast, unsigned lparen_token, Function *fun);
     void translationUnit(TranslationUnitAST *ast);
-    void objCProtocolRefs(ObjCProtocolRefsAST *ast);
+    void objCProtocolRefs(ObjCProtocolRefsAST *ast, Symbol *objcClassOrProtocol);
     void objCMessageArgument(ObjCMessageArgumentAST *ast);
     void objCTypeName(ObjCTypeNameAST *ast);
-    void objCInstanceVariablesDeclaration(ObjCInstanceVariablesDeclarationAST *ast);
+    void objCInstanceVariablesDeclaration(ObjCInstanceVariablesDeclarationAST *ast, ObjCClass *klass);
     void objCPropertyAttribute(ObjCPropertyAttributeAST *ast);
     void objCMessageArgumentDeclaration(ObjCMessageArgumentDeclarationAST *ast);
     void objCMethodPrototype(ObjCMethodPrototypeAST *ast);
-- 
GitLab