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