OSDN Git Service

Update license.
[qt-creator-jp/qt-creator-jp.git] / tests / auto / icheckbuild / parsemanager.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 **
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 **
23 ** Other Usage
24 **
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **************************************************************************/
32
33 #include "parsemanager.h"
34 #include "cplusplus/CppDocument.h"
35 #include "Control.h"
36 #include "Literals.h"
37 #include "Overview.h"
38 #include "Scope.h"
39 #include "TranslationUnit.h"
40 #include "AST.h"
41 #include "Symbols.h"
42 #include "Bind.h"
43 #include <QDebug>
44 #include "Name.h"
45 #include "cpptools/cppmodelmanager.h"
46 #include <QTextStream>
47
48 using namespace CppTools;
49 using namespace CppTools::Internal;
50
51
52 using namespace CPlusPlus;
53
54 //<------------------------------------------------------- Compare function for the internal structures
55 /**********************************
56 Compares function with function
57 with return type, function name
58 and their arguments and arguments
59 types.
60 **********************************/
61 bool FUNCTIONITEM::isEqualTo(FUNCTIONITEM *cpfct, bool ignoreName/* = true*/)
62 {
63     if(ignoreName)
64         return function->isEqualTo(cpfct->function, true);
65     return function->isEqualTo(cpfct->function);
66 }
67
68 /*****************************************************************
69 Compares two property regarding
70 of their function definition,
71 type definition, function arguments
72 and function types.
73
74 Q_PROPERTY( ConnectionState state READ state NOTIFY stateChanged);
75 ******************************************************************/
76 bool PROPERTYITEM::isEqualTo(PROPERTYITEM *cpppt)
77 {
78     if (!ast->type_id || !cpppt->ast->type_id)
79         return false;
80     if (type != cpppt->type)
81         return false;
82
83     if (!ast->property_name || !ast->property_name->name || !ast->property_name->name->identifier())
84         return false;
85     QString thistypename = ast->property_name->name->identifier()->chars();
86
87     if (!cpppt->ast->property_name || !cpppt->ast->property_name->name || !cpppt->ast->property_name->name->identifier())
88         return false;
89     QString cppttypename = cpppt->ast->property_name->name->identifier()->chars();
90     if(thistypename != cppttypename)
91         return false;
92
93     if ((this->readAst == 0) != (cpppt->readAst == 0))
94         return false;
95     if((this->writeAst == 0) != (cpppt->writeAst == 0))
96         return false;
97     if((this->resetAst == 0) != (cpppt->resetAst == 0))
98         return false;
99     if((this->notifyAst == 0) != (cpppt->notifyAst == 0))
100         return false;
101     //check for read function
102     if(this->readAst){
103         if(!this->readFct || !cpppt->readFct)
104             return false;
105         if(!this->readFct->isEqualTo(cpppt->readFct))
106             return false;
107     }
108     //check for write function
109     if(this->writeAst){
110         if(!this->writeFct || !cpppt->writeFct)
111             return false;
112         if(!this->writeFct->isEqualTo(cpppt->writeFct))
113             return false;
114     }
115     //check for reset function
116     if(this->resetAst){
117         if(!this->resetFct || !cpppt->resetFct)
118             return false;
119         if(!this->resetFct->isEqualTo(cpppt->resetFct))
120             return false;
121     }
122     //check for notify function
123     if(this->notifyAst){
124         if(!this->notifyFct || !cpppt->notifyFct)
125             return false;
126         if(!this->notifyFct->isEqualTo(cpppt->notifyFct))
127             return false;
128     }
129     return true;
130 }
131
132 /*****************************************************************
133 Compares two enums regarding
134 of their values created by the getEnumValueStringList function.
135 *****************************************************************/
136 bool QENUMITEM::isEqualTo(QENUMITEM *cpenum)
137 {
138     if(this->values.count() != cpenum->values.count())
139         return false;
140     foreach(QString str, this->values){
141         if(!cpenum->values.contains(str))
142             return false;
143     }
144     return true;
145 }
146
147 /*****************************************************************
148 Compares two flags regarding
149 of their enum definitions and their
150 values created by the getEnumValueStringList function.
151 *****************************************************************/
152 bool QFLAGITEM::isEqualTo(QFLAGITEM *cpflag)
153 {
154     if(this->enumvalues.count() != cpflag->enumvalues.count())
155         return false;
156     foreach(QString str, this->enumvalues){
157         if(!cpflag->enumvalues.contains(str))
158             return false;
159     }
160     return true;
161 }
162
163
164
165 ParseManager::ParseManager()
166 : pCppPreprocessor(0)
167 {
168
169 }
170
171 ParseManager::~ParseManager()
172 {
173     if(pCppPreprocessor)
174         delete pCppPreprocessor;
175     if(::m_resultFile){
176         ::m_resultFile->close();
177         delete ::m_resultFile;
178         ::m_resultFile = 0;
179     }
180 }
181
182 /**************************************
183 Function for setting the include
184 Paths
185 **************************************/
186 void ParseManager::setIncludePath(const QStringList &includePath)
187 {
188     m_includePaths = includePath;
189 }
190
191 /**************************************
192 public Function that starts the parsing
193 all of the files in the sourceFiles
194 string list.
195 **************************************/
196 void ParseManager::parse(const QStringList &sourceFiles)
197 {
198     m_errormsgs.clear();
199     if(pCppPreprocessor){
200         delete pCppPreprocessor;
201         pCppPreprocessor = 0;
202     }
203
204     if (! sourceFiles.isEmpty()) {
205         m_strHeaderFile = sourceFiles[0];
206         pCppPreprocessor = new CppTools::Internal::CppPreprocessor(QPointer<CPlusPlus::ParseManager>(this));
207         pCppPreprocessor->setIncludePaths(m_includePaths);
208         pCppPreprocessor->setFrameworkPaths(m_frameworkPaths);
209         parse(pCppPreprocessor, sourceFiles);
210     }
211 }
212
213 /*********************************************
214 private function that prepare the filelist
215 to parse and starts the parser.
216 *********************************************/
217 void ParseManager::parse(CppTools::Internal::CppPreprocessor *preproc,
218                             const QStringList &files)
219 {
220     if (files.isEmpty())
221         return;
222
223     //check if file is C++ header file
224     QStringList headers;
225     foreach (const QString &file, files) {
226         const QFileInfo fileInfo(file);
227         QString ext = fileInfo.suffix();
228         if (ext.toLower() == "h")
229             headers.append(file);
230     }
231
232     foreach (const QString &file, files) {
233         preproc->snapshot.remove(file);
234     }
235     preproc->setTodo(headers);
236     QString conf = QLatin1String("<configuration>");
237
238     preproc->run(conf);
239     for (int i = 0; i < headers.size(); ++i) {
240         QString fileName = headers.at(i);
241         preproc->run(fileName);
242     }
243 }
244
245 //This function creates a class list for each class and its base classes in
246 //the header file that needs to be checked.
247 //e.g.
248 //      Cl1          Cl2
249 //     __|__        __|__
250 //    |     |      |     |
251 //   Cl11  Cl12   Cl21  Cl22
252 //
253 //==> list[0] = {Cl1, Cl11, Cl12}
254 //    list[1] = {Cl2, Cl21, Cl22}
255
256 QList<CLASSTREE*> ParseManager::CreateClassLists(bool isInterfaceHeader)
257 {
258     QList<CLASSTREE*>ret;
259     QList<CLASSLISTITEM*> classlist;
260     QList<CLASSLISTITEM*> allclasslist;
261
262     Trace("Following classes scaned for header file: " + m_strHeaderFile);
263     //Iteration over all parsed documents
264     if(getPreProcessor()){
265         for (Snapshot::const_iterator it = getPreProcessor()->snapshot.begin()
266             ; it != getPreProcessor()->snapshot.end(); ++it)
267         {
268             Document::Ptr doc = (*it);
269             if(doc){
270                 QFileInfo fileinf(doc->fileName());
271                 QFileInfo fileinf1(m_strHeaderFile);
272                 //Get the Translated unit
273                 Control* ctrl = doc->control();
274                 TranslationUnit* trlUnit = ctrl->translationUnit();
275                 AST* pAst = trlUnit->ast();
276                 TranslationUnitAST *ptrAst = 0;
277                 if(pAst && (ptrAst = pAst->asTranslationUnit())){
278                     //iteration over all translated declaration in this document
279                     for (DeclarationListAST *pDecllist = ptrAst->declaration_list; pDecllist; pDecllist = pDecllist->next) {
280                         if(pDecllist->value){
281                             SimpleDeclarationAST *pSimpleDec = pDecllist->value->asSimpleDeclaration();
282                             if(pSimpleDec){
283                                 //Iteration over class specifier
284                                 for (SpecifierListAST *pSimpleDecDecllist = pSimpleDec->decl_specifier_list; pSimpleDecDecllist; pSimpleDecDecllist = pSimpleDecDecllist->next) {
285                                     ClassSpecifierAST * pclassspec = pSimpleDecDecllist->value->asClassSpecifier();
286                                     if(pclassspec){
287                                         CLASSLISTITEM* item = new CLASSLISTITEM();
288                                         item->classspec = pclassspec;
289                                         item->trlUnit = trlUnit;
290                                         allclasslist.push_back(item);
291                                         QString classname = item->trlUnit->spell(item->classspec->name->firstToken());
292                                         Trace("- " + classname + " class scaned");
293
294                                         //We found a class that is defined in the header file that needs to be checked
295                                         if(fileinf.fileName().toLower() == fileinf1.fileName().toLower()){
296                                             CLASSTREE* cltree = new CLASSTREE();
297                                             cltree->highestlevelclass = item;
298                                             cltree->classlist.push_back(item);
299                                             ret.push_back(cltree);
300                                         }
301                                     }
302                                 }
303                             }
304                         }
305                     }
306                 }
307             }
308         }
309     }
310     //after we search for the classes we need to search for the baseclasses
311     Trace("Following classes found in Header file: " + m_strHeaderFile);
312     foreach(CLASSTREE *cltree, ret){
313         QString classname = cltree->highestlevelclass->trlUnit->spell(cltree->highestlevelclass->classspec->name->firstToken());
314         Trace("- " + classname + " class found");
315         QList<CLASSLISTITEM*> baseclasslist;
316         getBaseClasses(cltree->highestlevelclass, baseclasslist, allclasslist, 0, isInterfaceHeader);
317         cltree->classlist.append(baseclasslist);
318     }
319     return ret;
320 }
321
322 /********************************************
323 Gets all the baseclass from a class and
324 add those base classes into the baseclasslist
325 ********************************************/
326 void ParseManager::getBaseClasses(const CLASSLISTITEM* pclass
327                                   , QList<CLASSLISTITEM*> &baseclasslist
328                                   , const QList<CLASSLISTITEM*> &allclasslist
329                                   , int level
330                                   , bool isInterfaceHeader)
331 {
332     //iteration over the base_clause_list of the current class
333     QString levelmarker = "  ";
334     for(int i = 0; i < level; i++)
335         levelmarker += "   ";
336     levelmarker += "|- ";
337     QList<CLASSLISTITEM*>child;
338
339     for(BaseSpecifierListAST *pBaseSpecList = pclass->classspec->base_clause_list; pBaseSpecList; pBaseSpecList = pBaseSpecList->next)
340     {
341         BaseSpecifierAST *pBaseSpec = pBaseSpecList->value;
342         bool found = false;
343         foreach(CLASSLISTITEM* pclspec, allclasslist)
344         {
345             if(pclspec->classspec->symbol->name()
346                 && pBaseSpec->symbol->name()
347                 && pclspec->classspec->symbol->name()->isEqualTo(pBaseSpec->symbol->name()))
348             {
349                 child.push_back(pclspec);
350                 baseclasslist.push_back(pclspec);
351                 QString classname = pclspec->trlUnit->spell(pclspec->classspec->name->firstToken());
352                 Trace(levelmarker + classname + " class found");
353                 found = true;
354                 break;
355             }
356         }
357         if(!found && pBaseSpec->name){
358             QString classname = pclass->trlUnit->spell(pBaseSpec->name->firstToken());
359             if(isInterfaceHeader)
360                 Trace(levelmarker + classname + " class not found! Interface classes should not be inherited from Qt Objects!");
361             else
362                 Trace(levelmarker + classname + " class not found!");
363         }
364     }
365     //call the function recursive because all the basclasses can have other base classes
366     foreach(CLASSLISTITEM* pchclass, child){
367         getBaseClasses(pchclass, baseclasslist, allclasslist, ++level, isInterfaceHeader);
368     }
369 }
370
371 /**************************************************
372 This function finds and creates all Elements wich
373 are significant for MetaDatas.
374 Those element will be added in the aparameter
375 lists.
376 **************************************************/
377 void ParseManager::getElements(QList<FUNCTIONITEM*> &functionlist
378                                , QList<PROPERTYITEM*> &propertylist
379                                , QList<QENUMITEM*> &qenumlist
380                                , QList<ENUMITEM*> &enumlist
381                                , QList<QFLAGITEM*> &qflaglist
382                                , QList<QDECLAREFLAGSITEM*> &qdeclareflaglist
383                                , const QList<CLASSLISTITEM*> classitems
384                                , const CLASSLISTITEM* highestlevelclass)
385 {
386     foreach(CLASSLISTITEM* classitem, classitems){
387         QString classname = "";
388         if(classitem->classspec->name)
389             classname = classitem->trlUnit->spell(classitem->classspec->name->firstToken());
390         for (DeclarationListAST *pmemberlist = classitem->classspec->member_specifier_list; pmemberlist; pmemberlist = pmemberlist->next) {
391             /**********
392             Functions
393             **********/
394             if (FunctionDefinitionAST *pfctdef = pmemberlist->value->asFunctionDefinition()){
395                 FUNCTIONITEM* item = new FUNCTIONITEM;
396                 item->trlUnit = classitem->trlUnit;
397                 item->function = pfctdef->symbol;
398                 item->classAst = classitem->classspec;
399                 item->highestlevelclass = highestlevelclass;
400                 functionlist.push_back(item);
401                 if(isMetaObjFunction(item))
402                     Trace("  - " + getTraceFuntionString(item, classname) + " found");
403             }
404
405             SimpleDeclarationAST *pdecl = pmemberlist->value->asSimpleDeclaration();
406             if(pdecl){
407                 for(List<Symbol*>* decllist = pdecl->symbols; decllist; decllist = decllist->next)
408                 {
409                     Function* pfct = decllist->value->type()->asFunctionType();
410                     if(pfct){
411                         FUNCTIONITEM* item = new FUNCTIONITEM();
412                         item->trlUnit = classitem->trlUnit;
413                         item->function = pfct;
414                         item->classAst = classitem->classspec;
415                         item->highestlevelclass = highestlevelclass;
416                         functionlist.push_back(item);
417                         if(isMetaObjFunction(item))
418                             Trace("  - " + getTraceFuntionString(item, classname) + " found");
419                     }
420                 }
421                 /******
422                 enum
423                 ******/
424                 for(List<SpecifierAST*>* decllist = pdecl->decl_specifier_list; decllist; decllist = decllist->next)
425                 {
426                     EnumSpecifierAST * penum = decllist->value->asEnumSpecifier();
427                     if(penum){
428                         ENUMITEM* item = new ENUMITEM();
429                         item->ast = penum;
430                         item->highestlevelclass = highestlevelclass;
431                         item->trlUnit = classitem->trlUnit;
432                         enumlist.push_back(item);
433                     }
434                 }
435             }
436             else{
437                 /**********
438                 Q_PROPERTY
439                 **********/
440                 if(QtPropertyDeclarationAST *ppdecl = pmemberlist->value->asQtPropertyDeclaration()) {
441                     propertylist.push_back(PROPERTYITEM::create(ppdecl, highestlevelclass));
442                     if (ppdecl->property_name && ppdecl->property_name->name && ppdecl->property_name->name->identifier()) {
443                         Trace("  - Q_PROPERTY: " + QLatin1String(ppdecl->property_name->name->identifier()->chars()) + " found");
444                     }
445                 } else{
446                     /**********
447                     Q_ENUM
448                     **********/
449                     if (QtEnumDeclarationAST *pqenum = pmemberlist->value->asQtEnumDeclaration()) {
450                         for (NameListAST *plist = pqenum->enumerator_list; plist; plist = plist->next) {
451                             QENUMITEM* item = new QENUMITEM;
452                             item->name = plist->value->name->identifier()->chars();
453                             item->highestlevelclass = highestlevelclass;
454                             qenumlist.push_back(item);
455                             Trace("  - Q_ENUM: " + classname + "::" + item->name + " found");
456                         }
457                     }
458                     else{
459                         /**********
460                         Q_FLAGS
461                         **********/
462                         if (QtFlagsDeclarationAST *pqflags = pmemberlist->value->asQtFlagsDeclaration()){
463                             for (NameListAST *plist = pqflags->flag_enums_list; plist; plist = plist->next) {
464                                 QFLAGITEM* item = new QFLAGITEM;
465                                 item->name = plist->value->name;
466                                 item->highestlevelclass = highestlevelclass;
467                                 qflaglist.push_back(item);
468                                 Trace("  - Q_FLAGS: " + classname + "::" + item->name->identifier()->chars() + " found");
469                             }
470                         }
471 #if 0
472                         /*The code for Q_DECLARE_FLAGS was wrong. It's optional, and only does a typedef.
473                         That means, if you do the typedef yourself and not use Q_DECLARE_FLAGS, that *is* valid.
474                         Meaning, if one would want to do a check like the ones in this app, one has to check the defined types in the class scope.*/
475                         else {
476                             /****************
477                             Q_DECLARE_FLAGS
478                             ****************/
479                             QtDeclareFlagsDeclarationAST *pqdeclflags = pmemberlist->value->asQDeclareFlagsDeclarationAST();
480                             if(pqdeclflags){
481                                 QDECLAREFLAGSITEM* item = new QDECLAREFLAGSITEM();
482                                 item->ast = pqdeclflags;
483                                 item->highestlevelclass = highestlevelclass;
484                                 item->trlUnit = classitem->trlUnit;
485                                 qdeclareflaglist.push_back(item);
486                             }
487                         }
488 #endif
489                     }
490                 }
491             }
492         }
493     }
494 }
495
496 /*********************************************
497 Function that starts the comare between the
498 parser result and their metadata content.
499 *********************************************/
500 bool ParseManager::checkAllMetadatas(ParseManager* pInterfaceParserManager, QString resultfile)
501 {
502     bool ret = true;
503
504     //Create output file
505     if(resultfile != "" && ::m_resultFile == 0){
506         ::m_resultFile = new QFile(resultfile);
507         if (!::m_resultFile->open(QFile::WriteOnly | QFile::Truncate)) {
508             delete ::m_resultFile;
509             ::m_resultFile = 0;
510          }
511     }
512
513     /************************************************
514     Get all elements from the interface header file
515     ************************************************/
516     Trace("### Get all elements from the interface header file ###");
517     QList<CLASSTREE*> ilookuplist = pInterfaceParserManager->CreateClassLists(true);
518     QList<QList<FUNCTIONITEM*> > ifunctionslookuplist;
519     QList<QList<PROPERTYITEM*> > ipropertieslookuplist;
520     QList<QList<QENUMITEM*> > iqenumlookuplist;
521     QList<QList<ENUMITEM*> > ienumlookuplist;
522     QList<QList<QFLAGITEM*> > iqflaglookuplist;
523     QList<QList<QDECLAREFLAGSITEM*> > iqdeclareflaglookuplist;
524     Trace("Following MetaData found:");
525     foreach(CLASSTREE* iclasstree, ilookuplist){
526         QList<FUNCTIONITEM*>functionlist;
527         QList<PROPERTYITEM*>propertylist;
528         QList<QENUMITEM*>qenumlist;
529         QList<ENUMITEM*>enumlist;
530         QList<QFLAGITEM*> qflaglist;
531         QList<QDECLAREFLAGSITEM*> qdeclareflag;
532         getElements(functionlist
533             , propertylist
534             , qenumlist
535             , enumlist
536             , qflaglist
537             , qdeclareflag
538             , iclasstree->classlist
539             , iclasstree->highestlevelclass);
540         if(functionlist.size() > 0)
541             ifunctionslookuplist.append(functionlist);
542         if(propertylist.size() > 0)
543             ipropertieslookuplist.append(propertylist);
544         if(qenumlist.size() > 0)
545             iqenumlookuplist.append(qenumlist);
546         if(enumlist.size() > 0)
547             ienumlookuplist.append(enumlist);
548         if(qflaglist.size() > 0)
549             iqflaglookuplist.append(qflaglist);
550         if(qdeclareflag.size() > 0)
551             iqdeclareflaglookuplist.append(qdeclareflag);
552     }
553
554     /************************************************
555     Get all elements from the compare header file
556     ************************************************/
557     Trace("\n");
558     Trace("### Get all elements from the compare header file ###");
559     QList<CLASSTREE*> lookuplist = CreateClassLists(false);
560     QList<QList<FUNCTIONITEM*> > functionslookuplist;
561     QList<QList<PROPERTYITEM*> > propertieslookuplist;
562     QList<QList<QENUMITEM*> > qenumlookuplist;
563     QList<QList<ENUMITEM*> > enumlookuplist;
564     QList<QList<QFLAGITEM*> > qflaglookuplist;
565     QList<QList<QDECLAREFLAGSITEM*> > qdeclareflaglookuplist;
566     Trace("Following MetaData found:");
567     foreach(CLASSTREE* classtree, lookuplist){
568         QList<FUNCTIONITEM*>functionlist;
569         QList<PROPERTYITEM*>propertylist;
570         QList<QENUMITEM*>qenumlist;
571         QList<ENUMITEM*>enumlist;
572         QList<QFLAGITEM*> qflaglist;
573         QList<QDECLAREFLAGSITEM*> qdeclareflag;
574         getElements(functionlist
575             , propertylist
576             , qenumlist
577             , enumlist
578             , qflaglist
579             , qdeclareflag
580             , classtree->classlist
581             , classtree->highestlevelclass);
582         if(functionlist.size() > 0)
583             functionslookuplist.append(functionlist);
584         if(propertylist.size() > 0)
585             propertieslookuplist.append(propertylist);
586         if(qenumlist.size() > 0)
587             qenumlookuplist.append(qenumlist);
588         if(enumlist.size() > 0)
589             enumlookuplist.append(enumlist);
590         if(qflaglist.size() > 0)
591             qflaglookuplist.append(qflaglist);
592         if(qdeclareflag.size() > 0)
593             qdeclareflaglookuplist.append(qdeclareflag);
594     }
595
596     Trace("\n");
597     Trace("### Result: ###");
598     /******************************
599     Check for function
600     ******************************/
601     Trace("Compare all interface MetaData functions:");
602     QList<FUNCTIONITEM*> missingifcts = checkMetadataFunctions(functionslookuplist, ifunctionslookuplist);
603     if(missingifcts.size() > 0){
604         foreach(FUNCTIONITEM* ifct, missingifcts){
605             m_errormsgs.append(getErrorMessage(ifct));
606         }
607         ret =  false;
608         Trace("- Failed!");
609     }
610     else{
611         Trace("- OK");
612     }
613
614     /******************************
615     Check for properies
616     ******************************/
617     Trace("Compare all interface MetaData properties:");
618     QList<PROPERTYITEM*> missingippts = checkMetadataProperties(propertieslookuplist, functionslookuplist, ipropertieslookuplist, ifunctionslookuplist);
619     if(missingippts.size() > 0){
620         foreach(PROPERTYITEM* ippt, missingippts){
621             m_errormsgs.append(getErrorMessage(ippt));
622         }
623         ret =  false;
624         Trace("- Failed!");
625     }
626     else{
627         Trace("- OK");
628     }
629
630     /******************************
631     Check for enums
632     ******************************/
633     Trace("Compare all interface MetaData enums:");
634     QList<QENUMITEM*> missingiqenums = checkMetadataEnums(qenumlookuplist, enumlookuplist, iqenumlookuplist, ienumlookuplist);
635     if(missingiqenums.size() > 0){
636         foreach(QENUMITEM* ienum, missingiqenums){
637             m_errormsgs.append(getErrorMessage(ienum));
638         }
639         ret =  false;
640         Trace("- Failed!");
641     }
642     else{
643         Trace("- OK");
644     }
645
646     /******************************
647     Check for flags
648     ******************************/
649     Trace("Compare all interface MetaData flags:");
650     QList<QFLAGITEM*> missingiqflags = checkMetadataFlags(qflaglookuplist, qdeclareflaglookuplist, enumlookuplist
651                                                         , iqflaglookuplist, iqdeclareflaglookuplist, ienumlookuplist);
652     if(missingiqflags.size() > 0){
653         foreach(QFLAGITEM* iflags, missingiqflags){
654             m_errormsgs.append(getErrorMessage(iflags));
655         }
656         ret =  false;
657         Trace("- Failed!");
658     }
659     else{
660         Trace("- OK");
661     }
662
663     /******************************
664     Add summary
665     ******************************/
666     Trace("\n");
667     Trace("### summary ###");
668     if(m_errormsgs.size() > 0){
669         Trace("- Folowing interface items are missing:");
670         foreach(QString msg, m_errormsgs)
671             Trace("  - " + msg);
672     }
673     else
674         Trace("Interface is full defined.");
675
676     //now delet all Classitems
677     foreach(CLASSTREE* l, ilookuplist){
678         l->classlist.clear();
679     }
680     foreach(CLASSTREE* l, lookuplist){
681         l->classlist.clear();
682     }
683     //delete all functionitems
684     foreach(QList<FUNCTIONITEM*>l, ifunctionslookuplist){
685         l.clear();
686     }
687     foreach(QList<FUNCTIONITEM*>l, functionslookuplist){
688         l.clear();
689     }
690     //delete all properties
691     foreach(QList<PROPERTYITEM*>l, ipropertieslookuplist){
692         l.clear();
693     }
694     foreach(QList<PROPERTYITEM*>l, propertieslookuplist){
695         l.clear();
696     }
697     //delete all qenums
698     foreach(QList<QENUMITEM*>l, iqenumlookuplist){
699         l.clear();
700     }
701     foreach(QList<QENUMITEM*>l, iqenumlookuplist){
702         l.clear();
703     }
704     //delete all enums
705     foreach(QList<ENUMITEM*>l, ienumlookuplist){
706         l.clear();
707     }
708     foreach(QList<ENUMITEM*>l, enumlookuplist){
709         l.clear();
710     }
711     //delete all qflags
712     foreach(QList<QFLAGITEM*>l, iqflaglookuplist){
713         l.clear();
714     }
715     foreach(QList<QFLAGITEM*>l, qflaglookuplist){
716         l.clear();
717     }
718     //delete all qdeclareflags
719     foreach(QList<QDECLAREFLAGSITEM*>l, iqdeclareflaglookuplist){
720         l.clear();
721     }
722     foreach(QList<QDECLAREFLAGSITEM*>l, qdeclareflaglookuplist){
723         l.clear();
724     }
725
726     return ret;
727 }
728
729 //<-------------------------------------------------------  Start of MetaData functions
730 /***********************************
731 Function that checks all functions
732 which will occur in the MetaData
733 ***********************************/
734 QList<FUNCTIONITEM*> ParseManager::checkMetadataFunctions(const QList<QList<FUNCTIONITEM*> > &classfctlist, const QList<QList<FUNCTIONITEM*> > &iclassfctlist)
735 {
736     QList<FUNCTIONITEM*> missingifcts;
737     //Compare each function from interface with function from header (incl. baseclass functions)
738     QList<FUNCTIONITEM*> ifcts;
739     foreach(QList<FUNCTIONITEM*>ifunctionlist, iclassfctlist){
740         ifcts.clear();
741         //check if one header class contains all function from one interface header class
742         if(classfctlist.count() > 0){
743             foreach(QList<FUNCTIONITEM*>functionlist, classfctlist){
744                 QList<FUNCTIONITEM*> tmpl = containsAllMetadataFunction(functionlist, ifunctionlist);
745                 if(tmpl.size() == 0){
746                     ifcts.clear();
747                     break;
748                 }
749                 else
750                     ifcts.append(tmpl);
751             }
752         }
753         else {
754             foreach(FUNCTIONITEM *pfct, ifunctionlist)
755                 pfct->classWichIsNotFound << "<all classes>";
756             ifcts.append(ifunctionlist);
757         }
758         missingifcts.append(ifcts);
759     }
760     return missingifcts;
761 }
762
763 /*********************************************
764 Helper function to check if a function will
765 occure in the MetaData.
766 *********************************************/
767 bool ParseManager::isMetaObjFunction(FUNCTIONITEM* fct)
768 {
769     if(fct->function->isInvokable()
770         || fct->function->isSignal()
771         || fct->function->isSlot())
772         return true;
773     return false;
774 }
775
776 /****************************************************
777 Check if all function from iclassfctlist are defined
778 in the classfctlist as well.
779 It will return all the function they are missing.
780 ****************************************************/
781 QList<FUNCTIONITEM*> ParseManager::containsAllMetadataFunction(const QList<FUNCTIONITEM*> &classfctlist, const QList<FUNCTIONITEM*> &iclassfctlist)
782 {
783     QList<FUNCTIONITEM*> ret;
784     foreach(FUNCTIONITEM* ifct, iclassfctlist){
785         if(isMetaObjFunction(ifct)){
786             bool found = false;
787             QStringList missingimplinclasses;
788             ClassSpecifierAST* clspec = 0;
789             QString classname = "";
790             foreach(FUNCTIONITEM* fct, classfctlist){
791                 if(clspec != fct->highestlevelclass->classspec){
792                     clspec = fct->highestlevelclass->classspec;
793                     //get the classname
794                     unsigned int firsttoken = clspec->name->firstToken();
795                     classname += fct->trlUnit->spell(firsttoken);
796                     if(missingimplinclasses.indexOf(classname) < 0)
797                         missingimplinclasses.push_back(classname);
798                 }
799                 if(fct->isEqualTo(ifct, false)){
800                     found = true;
801                     missingimplinclasses.clear();
802                     Trace("- " + getTraceFuntionString(fct, classname) + " implemented");
803                     break;
804                 }
805             }
806             if(!found){
807                 ifct->classWichIsNotFound.append(missingimplinclasses);
808                 ret.push_back(ifct);
809                 QString classname = ifct->trlUnit->spell(ifct->highestlevelclass->classspec->name->firstToken());
810                 Trace("- " + getTraceFuntionString(ifct, classname) + " not implemented!");
811             }
812         }
813     }
814     return ret;
815 }
816
817 /************************************
818 Function that gives back an error
819 string for a MetaData function
820 mismatch.
821 ************************************/
822 QStringList ParseManager::getErrorMessage(FUNCTIONITEM* fct)
823 {
824     QStringList ret;
825     QString fctstring = "";
826     QString fcttype = "";
827
828     foreach(QString classname, fct->classWichIsNotFound){
829         QString tmp;
830         QTextStream out(&tmp);
831
832         fcttype = "";
833         fctstring = classname;
834         fctstring += "::";
835
836         unsigned int token = fct->function->sourceLocation() - 1;
837         while(fct->trlUnit->tokenAt(token).isNot(T_EOF_SYMBOL)){
838             fctstring += fct->trlUnit->tokenAt(token).spell();
839             if(*fct->trlUnit->tokenAt(token).spell() == ')')
840                 break;
841             fctstring += " ";
842             token++;
843         }
844
845         Function* pfct = fct->function;
846         if(pfct){
847             fcttype = "type: ";
848             //Check for private, protected and public
849             if(pfct->isPublic())
850                 fcttype = "public ";
851             if(pfct->isProtected())
852                 fcttype = "protected ";
853             if(pfct->isPrivate())
854                 fcttype = "private ";
855
856             if(pfct->isVirtual())
857                 fcttype += "virtual ";
858             if(pfct->isPureVirtual())
859                 fcttype += "pure virtual ";
860
861             if(pfct->isSignal())
862                 fcttype += "Signal ";
863             if(pfct->isSlot())
864                 fcttype += "Slot ";
865             if(pfct->isNormal())
866                 fcttype += "Normal ";
867             if(pfct->isInvokable())
868                 fcttype += "Invokable ";
869         }
870         out << fcttype << fctstring;
871         ret << tmp;
872     }
873     return ret;
874 }
875 //--->
876
877 //<-------------------------------------------------------  Start of Q_PROPERTY checks
878 /***********************************
879 Function that checks all Property
880 which will occur in the MetaData
881 ***********************************/
882 QList<PROPERTYITEM*> ParseManager::checkMetadataProperties(const QList<QList<PROPERTYITEM*> > &classproplist
883                                                                          , const QList<QList<FUNCTIONITEM*> > &classfctlist
884                                                                          , const QList<QList<PROPERTYITEM*> > &iclassproplist
885                                                                          , const QList<QList<FUNCTIONITEM*> > &iclassfctlist)
886 {
887     QList<PROPERTYITEM*> missingiprops;
888     //assign the property functions
889     foreach(QList<PROPERTYITEM*>proplist, classproplist){
890         foreach(PROPERTYITEM* prop, proplist){
891             assignPropertyFunctions(prop, classfctlist);
892         }
893     }
894
895     foreach(QList<PROPERTYITEM*>proplist, iclassproplist){
896         foreach(PROPERTYITEM* prop, proplist){
897             assignPropertyFunctions(prop, iclassfctlist);
898         }
899     }
900
901     //Compare each qproperty from interface with qproperty from header (incl. baseclass functions)
902     QList<PROPERTYITEM*> ippts;
903     foreach(QList<PROPERTYITEM*>ipropertylist, iclassproplist){
904         ippts.clear();
905         //check if one header class contains all function from one interface header class
906         if(classproplist.count() > 0){
907             foreach(QList<PROPERTYITEM*>propertylist, classproplist){
908                 QList<PROPERTYITEM*> tmpl = containsAllPropertyFunction(propertylist, ipropertylist);
909                 if(tmpl.size() == 0)
910                     ippts.clear();
911                 else
912                     ippts.append(tmpl);
913             }
914         }
915         else {
916             foreach(PROPERTYITEM *pprop, ipropertylist){
917                 pprop->classWichIsNotFound << "<all classes>";
918                 QString name = pprop->ast->property_name->name->identifier()->chars();
919                 Trace("- Property: <all classes>::" + name + " not found!");
920             }
921             ippts.append(ipropertylist);
922         }
923         missingiprops.append(ippts);
924     }
925     return missingiprops;
926 }
927
928 static QString findName(ExpressionAST *ast)
929 {
930     // The "old" icheck code assumed that functions were only a single identifier, so I'll assume the same:
931     if (NameAST *nameAST = ast->asName())
932         return nameAST->name->identifier()->chars();
933     else
934         return QString();
935 }
936
937 /**************************************
938 Function that resolves the dependensies
939 between Q_PROPERTY
940 and thier READ, WRITE, NOTIFY and RESET
941 functions.
942 ***************************************/
943 void ParseManager::assignPropertyFunctions(PROPERTYITEM* prop, const QList<QList<FUNCTIONITEM*> > &fctlookuplist)
944 {
945     //get the name of the needed functions
946     QString readfctname;
947     QString writefctname;
948     QString resetfctname;
949     QString notifyfctname;
950
951     int needtofind = 0;
952     if(prop->readAst){
953         readfctname = findName(prop->readAst);
954         needtofind++;
955     }
956     if(prop->writeAst){
957         writefctname = findName(prop->writeAst);
958         needtofind++;
959     }
960     if(prop->resetAst){
961         resetfctname = findName(prop->resetAst);
962         needtofind++;
963     }
964     if(prop->notifyAst){
965         notifyfctname = findName(prop->notifyAst);
966         needtofind++;
967     }
968     //Now iterate over all function to find all functions wich are defined in the Q_PROPERTY macro
969     if(needtofind > 0){
970         prop->foundalldefinedfct = false;
971         foreach(QList<FUNCTIONITEM*> fctlist, fctlookuplist){
972             foreach(FUNCTIONITEM* pfct, fctlist){
973                 QString fctname = pfct->trlUnit->spell(pfct->function->sourceLocation());
974                 //check the function type against the property type
975                 FullySpecifiedType retTy = pfct->function->returnType();
976
977                 if (!fctname.isEmpty() && retTy.isValid()) {
978                     if(prop->readAst && fctname == readfctname){
979                         if (prop->type != retTy)
980                             continue;
981                         prop->readFct = pfct;
982                         needtofind--;
983                     }
984                     if(prop->writeAst && fctname == writefctname){
985                         prop->writeFct = pfct;
986                         needtofind--;
987                     }
988                     if(prop->resetAst && fctname == resetfctname){
989                         prop->resetFct = pfct;
990                         needtofind--;
991                     }
992                     if(prop->notifyAst && fctname == notifyfctname){
993                         prop->notifyFct = pfct;
994                         needtofind--;
995                     }
996                     if(needtofind <= 0){
997                         //a flag that indicates if a function was missing
998                         prop->foundalldefinedfct = true;
999                         return;
1000                     }
1001                 }
1002             }
1003         }
1004     }
1005 }
1006
1007 /**************************************
1008 Function that checks if all functions
1009 dependencies in Q_PROPERTY have the
1010 same arguments and retunr value.
1011 ***************************************/
1012 QList<PROPERTYITEM*> ParseManager::containsAllPropertyFunction(const QList<PROPERTYITEM*> &classproplist, const QList<PROPERTYITEM*> &iclassproplist)
1013 {
1014     QList<PROPERTYITEM*> ret;
1015     foreach(PROPERTYITEM* ipropt, iclassproplist){
1016         if(ipropt->foundalldefinedfct){
1017             bool found = false;
1018             QStringList missingimplinclasses;
1019             ClassSpecifierAST* clspec = 0;
1020             QString classname = "";
1021             foreach(PROPERTYITEM* propt, classproplist){
1022                 if(clspec != propt->highestlevelclass->classspec){
1023                     clspec = propt->highestlevelclass->classspec;
1024                     //get the classname
1025                     unsigned int firsttoken = clspec->name->firstToken();
1026                     classname += propt->trlUnit->spell(firsttoken);
1027                     if(missingimplinclasses.indexOf(classname) < 0)
1028                         missingimplinclasses.push_back(classname);
1029                 }
1030                 if(propt->isEqualTo(ipropt)){
1031                     found = true;
1032                     missingimplinclasses.clear();
1033                     Trace("- Property: " + classname + "::" + propt->ast->property_name->name->identifier()->chars() + " found");
1034                     break;
1035                 }
1036             }
1037             if(!found){
1038                 ipropt->classWichIsNotFound.append(missingimplinclasses);
1039                 ret.push_back(ipropt);
1040                 QString classname = ipropt->trlUnit->spell(ipropt->highestlevelclass->classspec->name->firstToken());
1041                 Trace("- Property: " + classname + "::" + ipropt->ast->property_name->name->identifier()->chars() + " not found!");
1042             }
1043         }
1044         else{
1045             QString classname = ipropt->trlUnit->spell(ipropt->highestlevelclass->classspec->name->firstToken());
1046             Overview oo;
1047             QString proptype = oo(ipropt->type);
1048             Trace("- Property: " + classname + "::" + proptype + " functions are missing!");
1049             ret.push_back(ipropt);
1050         }
1051     }
1052     return ret;
1053 }
1054
1055 /************************************
1056 Function that gives back an error
1057 string for a Q_PROPERTY mismatch.
1058 ************************************/
1059 QStringList ParseManager::getErrorMessage(PROPERTYITEM* ppt)
1060 {
1061     QStringList ret;
1062     QString pptstring = "";
1063
1064     if(!ppt->foundalldefinedfct)
1065     {
1066         QString tmp;
1067         QTextStream out(&tmp);
1068
1069         unsigned int firsttoken = ppt->highestlevelclass->classspec->name->firstToken();
1070         unsigned int lasttoken = ppt->highestlevelclass->classspec->name->lastToken();
1071         for(unsigned int i = firsttoken; i < lasttoken; i++){
1072             out << ppt->trlUnit->spell(i);
1073         }
1074         out << "::";
1075         firsttoken = ppt->ast->firstToken();
1076         lasttoken = ppt->ast->lastToken();
1077         for(unsigned int i = firsttoken; i <= lasttoken; i++){
1078             out << ppt->trlUnit->spell(i) << " ";
1079         }
1080         out << endl << " -";
1081         if(ppt->readAst && !ppt->readFct)
1082             out << "READ ";
1083         if(ppt->writeAst && !ppt->writeFct)
1084             out << "WRITE ";
1085         if(ppt->resetAst && !ppt->resetFct)
1086             out << "RESET.";
1087         if(ppt->notifyAst && !ppt->notifyFct)
1088             out << "NOTIFY ";
1089         out << "functions missing." << endl;
1090         ret << tmp;
1091     }
1092     for(int i = 0; i < ppt->classWichIsNotFound.size(); i++){
1093         QString tmp;
1094         QTextStream out(&tmp);
1095
1096         pptstring = ppt->classWichIsNotFound[i];
1097         pptstring += "::";
1098
1099         unsigned int firsttoken = ppt->ast->firstToken();
1100         unsigned int lasttoken = ppt->ast->lastToken();
1101         for(unsigned int i = firsttoken; i <= lasttoken; i++){
1102             pptstring += ppt->trlUnit->spell(i);
1103             pptstring += " ";
1104         }
1105
1106         out << pptstring;
1107         ret << tmp;
1108     }
1109     return ret;
1110 }
1111 //--->
1112
1113
1114 //<------------------------------------------------------- Start of Q_ENUMS checks
1115 /***********************************
1116 Function that checks all enums
1117 which will occur in the MetaData
1118 ***********************************/
1119 QList<QENUMITEM*> ParseManager::checkMetadataEnums(const QList<QList<QENUMITEM*> > &classqenumlist
1120                                                 , const QList<QList<ENUMITEM*> > &classenumlist
1121                                                 , const QList<QList<QENUMITEM*> > &iclassqenumlist
1122                                                 , const QList<QList<ENUMITEM*> > &iclassenumlist)
1123 {
1124     QList<QENUMITEM*> missingiqenums;
1125     //assign the property functions
1126     foreach(QList<QENUMITEM*>qenumlist, classqenumlist){
1127         foreach(QENUMITEM* qenum, qenumlist){
1128             assignEnumValues(qenum, classenumlist);
1129         }
1130     }
1131     foreach(QList<QENUMITEM*>qenumlist, iclassqenumlist){
1132         foreach(QENUMITEM* qenum, qenumlist){
1133             assignEnumValues(qenum, iclassenumlist);
1134         }
1135     }
1136
1137     //Compare each qenum from interface with qenum from header (incl. baseclass functions)
1138     QList<QENUMITEM*> iqenums;
1139     foreach(QList<QENUMITEM*>iqenumlist, iclassqenumlist){
1140         iqenums.clear();
1141         //check if one header class contains all function from one interface header class
1142         if(classqenumlist.count() > 0){
1143             foreach(QList<QENUMITEM*>qenumlist, classqenumlist){
1144                 QList<QENUMITEM*> tmpl = containsAllEnums(qenumlist, iqenumlist);
1145                 if(tmpl.size() == 0)
1146                     iqenums.clear();
1147                 else
1148                     iqenums.append(tmpl);
1149
1150             }
1151         }
1152         else {
1153             foreach(QENUMITEM *qenum, iqenumlist){
1154                 qenum->classWichIsNotFound << "<all classes>";
1155                 Trace("- Enum: <all classes>::" + qenum->name + " not found!");
1156             }
1157             iqenums.append(iqenumlist);
1158         }
1159         missingiqenums.append(iqenums);
1160     }
1161
1162     return missingiqenums;
1163 }
1164
1165 /*********************************************
1166 Helper function which creates a string out of
1167 an enumerator including its values.
1168 *********************************************/
1169 QStringList ParseManager::getEnumValueStringList(ENUMITEM *penum, QString mappedenumname/* = ""*/)
1170 {
1171     QStringList ret;
1172     EnumSpecifierAST *penumsec = penum->ast;
1173     QString enumname = penum->trlUnit->spell(penumsec->name->firstToken());
1174     int enumvalue = 0;
1175     //now iterrate over all enumitems and create a string like following:
1176     //EnumName.EnumItemName.Value
1177     //ConnectionState.disconnected.0
1178     for (EnumeratorListAST *plist = penum->ast->enumerator_list; plist; plist = plist->next) {
1179         QString value = enumname;
1180         if(mappedenumname.size() > 0)
1181             value = mappedenumname;
1182         value += ".";
1183         value += penum->trlUnit->spell(plist->value->identifier_token);
1184         value += ".";
1185         if(plist->value->equal_token > 0 && plist->value->expression){
1186             QString v = penum->trlUnit->spell(plist->value->expression->firstToken());
1187             bool ch;
1188             int newval = enumvalue;
1189             if(v.indexOf("0x") >= 0)
1190                 newval = v.toInt(&ch, 16);
1191             else
1192                 newval = v.toInt(&ch, 10);
1193             if(ch)
1194                 enumvalue = newval;
1195         }
1196         value += QString::number(enumvalue);
1197         enumvalue++;
1198         // now add this enumitem string in the VALUE list
1199         ret << value;
1200     }
1201     return ret;
1202 }
1203
1204 /**************************************
1205 Function that resolves the dependensies
1206 between Q_ENUMS and enums.
1207 ***************************************/
1208 void ParseManager::assignEnumValues(QENUMITEM* qenum, const QList<QList<ENUMITEM*> > &enumlookuplist)
1209 {
1210     //iterate over all enums and find the one with the same name like enumname
1211     bool found = false;
1212     foreach (QList<ENUMITEM*> penumlist, enumlookuplist) {
1213         foreach(ENUMITEM *penum, penumlist){
1214             EnumSpecifierAST *penumsec = penum->ast;
1215             QString enumname1 = penum->trlUnit->spell(penumsec->name->firstToken());
1216             if(qenum->name == enumname1){
1217                 qenum->values << getEnumValueStringList(penum);
1218                 found = true;
1219                 break;
1220             }
1221         }
1222         if(!found)
1223             qenum->foundallenums = false;
1224     }
1225 }
1226
1227 /***********************************
1228 Function that checkt if the Q_ENUMS
1229 are completed defined and if the
1230 Enum values are the same.
1231 ***********************************/
1232 QList<QENUMITEM*> ParseManager::containsAllEnums(const QList<QENUMITEM*> &classqenumlist, const QList<QENUMITEM*> &iclassqenumlist)
1233 {
1234     Overview oo;
1235
1236     QList<QENUMITEM*> ret;
1237     foreach(QENUMITEM* iqenum, iclassqenumlist){
1238         bool found = false;
1239         QStringList missingimplinclasses;
1240         ClassSpecifierAST* clspec = 0;
1241         QString classname = "";
1242         foreach(QENUMITEM* qenum, classqenumlist){
1243             if(clspec != qenum->highestlevelclass->classspec){
1244                 clspec = qenum->highestlevelclass->classspec;
1245                 //get the classname
1246                 classname += oo(clspec->symbol);
1247                 if(missingimplinclasses.indexOf(classname) < 0)
1248                     missingimplinclasses.push_back(classname);
1249             }
1250             if(qenum->isEqualTo(iqenum)){
1251                 found = true;
1252                 missingimplinclasses.clear();
1253                 Trace("- Enum: " + classname + "::" + qenum->name + " found");
1254                 break;
1255             }
1256         }
1257         if(!found){
1258             iqenum->classWichIsNotFound.append(missingimplinclasses);
1259             ret.push_back(iqenum);
1260             QString classname = oo(iqenum->highestlevelclass->classspec->symbol);
1261             Trace("- Enum: " + classname + "::" + iqenum->name + " not found!");
1262         }
1263     }
1264     return ret;
1265 }
1266
1267 /************************************
1268 Function that gives back an error
1269 string for a Q_ENUMS mismatch.
1270 ************************************/
1271 QStringList ParseManager::getErrorMessage(QENUMITEM* qenum)
1272 {
1273     Overview oo;
1274     QStringList ret;
1275
1276     if(!qenum->foundallenums)
1277     {
1278         QString tmp;
1279         QTextStream out(&tmp);
1280
1281         out << oo(qenum->highestlevelclass->classspec->symbol);
1282         out << "::Q_ENUMS " << qenum->name << " enum missing.";
1283         ret << tmp;
1284     }
1285
1286     for (int i = 0; i < qenum->classWichIsNotFound.size(); i++){
1287         QString tmp;
1288         QTextStream out(&tmp);
1289
1290         out << qenum->classWichIsNotFound[i] << "::Q_ENUMS "
1291                 << qenum->name;
1292         ret << tmp;
1293     }
1294     return ret;
1295 }
1296 //--->
1297
1298 //<------------------------------------------------------- Start of Q_FLAGS checks
1299 /***********************************
1300 Function that checks all flags
1301 which will occur in the MetaData
1302 ***********************************/
1303 QList<QFLAGITEM*> ParseManager::checkMetadataFlags(const QList<QList<QFLAGITEM*> > &classqflaglist
1304                                             , const QList<QList<QDECLAREFLAGSITEM*> > &classqdeclareflaglist
1305                                             , const QList<QList<ENUMITEM*> > &classenumlist
1306                                             , const QList<QList<QFLAGITEM*> > &iclassqflaglist
1307                                             , const QList<QList<QDECLAREFLAGSITEM*> > &iclassqdeclareflaglist
1308                                             , const QList<QList<ENUMITEM*> > &iclassenumlist)
1309 {
1310     QList<QFLAGITEM*> missingqflags;
1311     //assign the enums to the flags
1312     foreach(QList<QFLAGITEM*>qflaglist, classqflaglist){
1313         foreach(QFLAGITEM* qflag, qflaglist){
1314             assignFlagValues(qflag, classqdeclareflaglist, classenumlist);
1315         }
1316     }
1317     foreach(QList<QFLAGITEM*>qflaglist, iclassqflaglist){
1318         foreach(QFLAGITEM* qflag, qflaglist){
1319             assignFlagValues(qflag, iclassqdeclareflaglist, iclassenumlist);
1320         }
1321     }
1322
1323     //Compare each qenum from interface with qenum from header (incl. baseclass functions)
1324     QList<QFLAGITEM*> iqflags;
1325     foreach(QList<QFLAGITEM*>iqflaglist, iclassqflaglist){
1326         iqflags.clear();
1327         //check if one header class contains all function from one interface header class
1328         if(classqflaglist.count() >0){
1329             foreach(QList<QFLAGITEM*>qflaglist, classqflaglist){
1330                 QList<QFLAGITEM*> tmpl = containsAllFlags(qflaglist, iqflaglist);
1331                 if(tmpl.size() == 0)
1332                     iqflags.clear();
1333                 else
1334                     iqflags.append(tmpl);
1335
1336             }
1337         }
1338         else {
1339             foreach(QFLAGITEM *pflag, iqflaglist){
1340                 pflag->classWichIsNotFound << "<all classes>";
1341                 QString name= pflag->name->identifier()->chars();
1342                 Trace("- Flag: <all classes>::" + name + " not found!");
1343             }
1344             iqflags.append(iqflaglist);
1345         }
1346         missingqflags.append(iqflags);
1347     }
1348     return missingqflags;
1349 }
1350
1351 /**************************************
1352 Function that resolves the dependensies
1353 between Q_FLAG, Q_DECLARE_FLAGS
1354 and enums.
1355 ***************************************/
1356 void ParseManager::assignFlagValues(QFLAGITEM* qflags, const QList<QList<QDECLAREFLAGSITEM*> > &qdeclareflagslookuplist, const QList<QList<ENUMITEM*> > &enumlookuplist)
1357 {
1358     QString enumname;
1359
1360     //try to find if there is a deflare flag macro with the same name as in qflagname
1361     Scope *classMembers = qflags->highestlevelclass->classspec->symbol;
1362     Symbol *s = classMembers->find(qflags->name);
1363     if (s->isTypedef()) {
1364         FullySpecifiedType ty = s->type();
1365         if (Enum *e = ty->asEnumType()) {
1366             enumname = e->name()->identifier()->chars();
1367         }
1368     }
1369
1370     //now we have the right enum name now we need to find the enum
1371     bool found = false;
1372     foreach(QList<ENUMITEM*> enumitemlist, enumlookuplist){
1373         foreach(ENUMITEM* enumitem, enumitemlist){
1374             EnumSpecifierAST *penumspec = enumitem->ast;
1375             QString enumspecname = enumitem->trlUnit->spell(penumspec->name->firstToken());
1376             if(enumspecname == enumname){
1377                 qflags->enumvalues << getEnumValueStringList(enumitem, qflags->name->identifier()->chars());
1378                 found = true;
1379                 break;
1380             }
1381         }
1382         if(found)
1383             break;
1384     }
1385     if(!found)
1386         qflags->foundallenums = false;
1387 }
1388
1389 /*****************************************
1390 Function that compares if all enums
1391 and flags assigned by using the Q_FLAGS
1392 are complete defined.
1393 *****************************************/
1394 QList<QFLAGITEM*> ParseManager::containsAllFlags(const QList<QFLAGITEM*> &classqflaglist, const QList<QFLAGITEM*> &iclassqflaglist)
1395 {
1396     QList<QFLAGITEM*> ret;
1397     foreach(QFLAGITEM* iqflags, iclassqflaglist){
1398         if(iqflags->foundallenums){
1399             bool found = false;
1400             QStringList missingimplinclasses;
1401             ClassSpecifierAST* clspec = 0;
1402             QString classname = "";
1403             foreach(QFLAGITEM* qflags, classqflaglist){
1404                 if(clspec != qflags->highestlevelclass->classspec){
1405                     clspec = qflags->highestlevelclass->classspec;
1406                     //get the classname
1407                     classname += clspec->symbol->name()->identifier()->chars();
1408                     if(missingimplinclasses.indexOf(classname) < 0)
1409                         missingimplinclasses.push_back(classname);
1410                 }
1411                 if(qflags->isEqualTo(iqflags)){
1412                     found = true;
1413                     missingimplinclasses.clear();
1414                     Trace("- Flag: " + classname + "::" + qflags->name->identifier()->chars() + " found");
1415                     break;
1416                 }
1417             }
1418             if(!found){
1419                 iqflags->classWichIsNotFound.append(missingimplinclasses);
1420                 ret.push_back(iqflags);
1421                 QString classname = iqflags->highestlevelclass->classspec->symbol->name()->identifier()->chars();
1422                 Trace("- Flag: " + classname + "::" + iqflags->name->identifier()->chars() + " not found!");
1423             }
1424         }
1425         else
1426             ret.push_back(iqflags);
1427     }
1428     return ret;
1429 }
1430
1431 /************************************
1432 Function that gives back an error
1433 string for a Q_FLAGS mismatch.
1434 ************************************/
1435 QStringList ParseManager::getErrorMessage(QFLAGITEM* pfg)
1436 {
1437     Overview oo;
1438     QStringList ret;
1439
1440     if(!pfg->foundallenums)
1441     {
1442         QString tmp;
1443         QTextStream out(&tmp);
1444
1445         out << oo(pfg->highestlevelclass->classspec->symbol->name());
1446         out << "::Q_FLAGS "<<pfg->name->identifier()->chars()<< ": enum missing.";
1447         ret << tmp;
1448     }
1449     for(int i = 0; i < pfg->classWichIsNotFound.size(); i++){
1450         QString tmp;
1451         QTextStream out(&tmp);
1452
1453         out << pfg->classWichIsNotFound[i] << "::Q_FLAGS " << oo(pfg->name);
1454         ret << tmp;
1455     }
1456     return ret;
1457 }
1458
1459 inline QString ParseManager::getTraceFuntionString(const FUNCTIONITEM *fctitem, const QString& classname)
1460 {
1461     QString ret;
1462
1463     if(fctitem->function->isPublic())
1464         ret = "public ";
1465     if(fctitem->function->isProtected())
1466         ret = "protected ";
1467     if(fctitem->function->isPrivate())
1468         ret = "private ";
1469
1470     if(fctitem->function->isVirtual())
1471         ret += "virtual ";
1472     if(fctitem->function->isPureVirtual())
1473         ret += "pure virtual ";
1474
1475     if(fctitem->function->isSignal())
1476         ret += "Signal ";
1477     if(fctitem->function->isSlot())
1478         ret += "Slot ";
1479     if(fctitem->function->isNormal())
1480         ret += "Normal ";
1481     if(fctitem->function->isInvokable())
1482         ret += "Invokable ";
1483
1484     ret += classname;
1485     ret += "::";
1486     ret += fctitem->trlUnit->spell(fctitem->function->sourceLocation());
1487     return ret;
1488 }
1489
1490 void ParseManager::Trace(QString value)
1491 {
1492     if(::m_resultFile){
1493         QTextStream out(::m_resultFile);
1494         if(value == "\n")
1495             out << endl;
1496         else
1497             out << value << endl;
1498     }
1499 }
1500
1501 PROPERTYITEM *PROPERTYITEM::create(QtPropertyDeclarationAST *ast, const CLASSLISTITEM *clazz)
1502 {
1503     PROPERTYITEM *item = new PROPERTYITEM;
1504     item->ast = ast;
1505     item->highestlevelclass = clazz;
1506     item->trlUnit = clazz->trlUnit;
1507
1508     if (ast->type_id) {
1509         Bind bind(item->trlUnit);
1510         item->type = bind(ast->type_id, clazz->classspec->symbol);
1511     }
1512
1513     for (QtPropertyDeclarationItemListAST *it = ast->property_declaration_items;
1514          it; it = it->next) {
1515         if (!it->value->item_name_token)
1516             continue;
1517         const char *name = item->trlUnit->spell(it->value->item_name_token);
1518         if (!qstrcmp(name, "READ"))
1519             item->readAst = it->value->expression;
1520         else if (!qstrcmp(name, "WRITE"))
1521             item->writeAst = it->value->expression;
1522         else if (!qstrcmp(name, "RESET"))
1523             item->resetAst = it->value->expression;
1524         else if (!qstrcmp(name, "NOTIFY"))
1525             item->notifyAst = it->value->expression;
1526     }
1527
1528     return item;
1529 }
1530
1531 //--->