Chameleon

Chameleon Svn Source Tree

Root/branches/xZenu/src/util/doxygen/src/dbusxmlscanner.cpp

Source at commit 1322 created 12 years 8 months ago.
By meklort, Add doxygen to utils folder
1/******************************************************************************
2 *
3 *
4 *
5 * Copyright (C) 2009 by Tobias Hunger <tobias@aquazul.com>
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation under the terms of the GNU General Public License is hereby
9 * granted. No representations are made about the suitability of this software
10 * for any purpose. It is provided "as is" without express or implied warranty.
11 * See the GNU General Public License for more details.
12 *
13 * Documents produced by Doxygen are derivative works derived from the
14 * input used in their production; they are not affected by this license.
15 *
16 */
17
18#include "dbusxmlscanner.h"
19
20#include "commentscan.h"
21#include "entry.h"
22
23#include <qfile.h>
24#include <qxml.h>
25#include <qstring.h>
26
27#include "message.h"
28#include "util.h"
29
30// -----------------------------------------------------------------------
31// Convenience defines:
32// -----------------------------------------------------------------------
33
34#define CONDITION(cond, msg) \
35 do {\
36 if (cond)\
37 {\
38 if (m_errorString.isEmpty()) { m_errorString = msg; }\
39 return false;\
40 }\
41 }\
42 while (0)
43
44#define DOC_ERROR(msg) \
45 warn_doc_error(m_fileName.utf8().data(), lineNumber(), msg.utf8().data())
46
47#define COND_DOC_ERROR(cond, msg) \
48 do {\
49 if (cond)\
50 {\
51 DOC_ERROR(msg);\
52 return true;\
53 }\
54 }\
55 while (0)
56
57#define DBUS(name) isDBusElement(namespaceURI, localName, qName, name)
58#define EXTENSION(name) isExtensionElement(namespaceURI, localName, qName, name)
59
60// -----------------------------------------------------------------------
61// DBusXMLHandler class
62// -----------------------------------------------------------------------
63
64const QString EXTENSION_URI("http://psiamp.org/dtd/doxygen_dbusxml.dtd");
65
66class DBusXMLHandler : public QXmlDefaultHandler
67{
68public:
69 DBusXMLHandler(ParserInterface * parser,
70 QXmlSimpleReader * reader,
71 const char * file_name,
72 Entry * root) :
73 m_parser(parser),
74 m_locator(reader),
75 m_currentEntry(0),
76 m_currentInterface(0),
77 m_currentMethod(0),
78 m_currentArgument(0),
79 m_currentProperty(0),
80 m_currentEnum(0),
81 m_fileName(file_name),
82 m_currentComment(0)
83 {
84 setDocumentLocator(&m_locator);
85
86 m_scopeCount = 0;
87
88 // Set up stack cleanup:
89 m_structStack.setAutoDelete(TRUE);
90 m_elementStack.setAutoDelete(TRUE);
91 m_scopeStack.setAutoDelete(TRUE);
92
93 openScopes(root);
94 }
95
96 ~DBusXMLHandler()
97 { closeScopes(); }
98
99 QString errorString()
100 { return m_errorString; }
101
102 bool startElement(const QString &namespaceURI,
103 const QString &localName,
104 const QString &qName,
105 const QXmlAttributes &attributes)
106 {
107 // add to elements stack:
108 m_elementStack.append(new ElementData(qName));
109
110 // First we need a node.
111 if (DBUS("node"))
112 {
113 CONDITION(!m_currentNode.isEmpty(), "Node inside a node.");
114
115 const int idx(indexOf(attributes, "name"));
116 COND_DOC_ERROR(idx < 0, QString("Anonymous node found."));
117
118 m_currentNode = attributes.value(idx);
119 // A node is actually of little interest, so do nothing here.
120 return true;
121 }
122
123 // Then we need an interface.
124 if (DBUS("interface"))
125 {
126 // We need a nodeName for interfaces:
127 CONDITION(m_currentNode.isEmpty(), "Interface without a node.");
128 CONDITION(m_currentInterface, "Interface within another interface.");
129
130 const int idx(indexOf(attributes, "name"));
131 COND_DOC_ERROR(idx < 0, QString("Interface without a name found."));
132
133 // A interface is roughly equivalent to a class:
134 m_currentInterface = createEntry();
135
136 m_currentInterface->section = Entry::CLASS_SEC;
137 m_currentInterface->spec |= Entry::Interface;
138 m_currentInterface->type = "Interface";
139 m_currentInterface->name = substitute(attributes.value(idx), ".", "::");
140
141 openScopes(m_currentInterface);
142
143 return true;
144 }
145
146 if (DBUS("method") || DBUS("signal"))
147 {
148 // We need a interfaceName for methods and signals:
149 CONDITION(!m_currentInterface, "Method or signal found outside a interface.");
150 CONDITION(m_currentMethod, "Method or signal found inside another method or signal.");
151 CONDITION(m_currentProperty, "Methor or signal found inside a property.");
152 CONDITION(!m_structStack.isEmpty(), "Method or signal found inside a struct.");
153 CONDITION(m_currentEnum, "Methor or signal found inside a enum.");
154
155 const int idx(indexOf(attributes, "name"));
156 COND_DOC_ERROR(idx < 0, QString("Method or signal without a name found."));
157
158 m_currentMethod = createEntry();
159
160 m_currentMethod->section = Entry::FUNCTION_SEC;
161 m_currentMethod->name = attributes.value(idx);
162 m_currentMethod->mtype = Method;
163 m_currentMethod->type = "void";
164
165 if (DBUS("signal"))
166 { m_currentMethod->mtype = Signal; }
167 }
168
169 if (DBUS("arg"))
170 {
171 // We need a method for arguments:
172 CONDITION(!m_currentMethod, "Argument found outside a method or signal.");
173 CONDITION(m_currentArgument, "Argument found inside another argument.");
174
175 const int name_idx(indexOf(attributes, "name"));
176 COND_DOC_ERROR(name_idx < 0, QString("Argument without a name found."));
177 COND_DOC_ERROR(!hasType(attributes), QString("Argument without a type found."));
178
179 const int direction_idx(indexOf(attributes, "direction"));
180
181 if ((m_currentMethod->mtype == Signal &&
182 direction_idx >= 0 &&
183 attributes.value(direction_idx) != "in") ||
184 (m_currentMethod->mtype == Method &&
185 direction_idx >= 0 &&
186 attributes.value(direction_idx) != "in" &&
187 attributes.value(direction_idx) != "out"))
188 {
189 m_errorString = "Invalid direction found.";
190 return false;
191 }
192
193 m_currentArgument = new Argument;
194 m_currentArgument->type = getType(attributes);
195 m_currentArgument->name = attributes.value(name_idx);
196 if (direction_idx >= 0)
197 { m_currentArgument->attrib = attributes.value(direction_idx); }
198 else
199 {
200 if (m_currentMethod->mtype == Signal)
201 { m_currentArgument->attrib = "in"; }
202 else
203 { m_currentArgument->attrib = "out"; }
204 }
205 }
206
207 if (DBUS("property"))
208 {
209 CONDITION(m_currentMethod, "Property found inside a method or signal.");
210 CONDITION(!m_currentInterface, "Property found outside an interface.");
211 CONDITION(m_currentProperty, "Property found inside another property.");
212 CONDITION(!m_structStack.isEmpty(), "Property found inside a struct.");
213 CONDITION(m_currentEnum, "Property found inside a enum.");
214
215 const int name_idx(indexOf(attributes, "name"));
216 COND_DOC_ERROR(name_idx < 0, QString("Anonymous property found."));
217 COND_DOC_ERROR(!hasType(attributes), QString("Property without a type found."));
218
219 const int access_idx(indexOf(attributes, "access"));
220 COND_DOC_ERROR(access_idx < 0, QString("Property without a access attribute found."));
221 COND_DOC_ERROR(attributes.value(access_idx) != "read" &&
222 attributes.value(access_idx) != "write" &&
223 attributes.value(access_idx) != "readwrite",
224 QString("Property with invalid access attribute \"%1\" found.").
225 arg(attributes.value(access_idx)));
226
227 m_currentProperty = createEntry();
228
229 m_currentProperty->section = Entry::FUNCTION_SEC;
230
231 if (attributes.value(access_idx) == "read" ||
232 attributes.value(access_idx) == "readwrite")
233 { m_currentProperty->spec |= Entry::Readable; }
234
235 if (attributes.value(access_idx) == "write" ||
236 attributes.value(access_idx) == "readwrite")
237 { m_currentProperty->spec |= Entry::Writable; }
238
239 m_currentProperty->name = attributes.value(name_idx);
240 m_currentProperty->mtype = Property;
241 m_currentProperty->type = getType(attributes);
242 }
243
244 if (EXTENSION("namespace"))
245 {
246 CONDITION(m_currentNode.isEmpty(), "Namespace found outside a node.");
247 CONDITION(m_currentInterface, "Namespace found inside an interface.");
248
249 const int idx(indexOf(attributes, "name"));
250 COND_DOC_ERROR(idx < 0, QString("Anonymous namespace found."));
251
252 m_namespaceStack.append(openNamespace(attributes.value(idx)));
253 openScopes(m_namespaceStack.last());
254 }
255
256 if (EXTENSION("struct"))
257 {
258 CONDITION(m_currentMethod, "Struct found inside a method or signal.");
259 CONDITION(m_currentProperty, "Struct found inside a property.");
260 CONDITION(m_currentEnum, "Struct found inside an enum.");
261
262 const int idx(indexOf(attributes, "name"));
263 COND_DOC_ERROR(idx < 0, QString("Anonymous struct found."));
264
265 Entry * current_struct = createEntry();
266 current_struct->section = Entry::CLASS_SEC;
267 current_struct->spec = Entry::Struct;
268 current_struct->name = attributes.value(idx);
269
270 openScopes(current_struct);
271
272 current_struct->type = current_struct->name + " struct";
273
274 m_structStack.append(new StructData(current_struct));
275 }
276
277 if (EXTENSION("member"))
278 {
279 CONDITION(m_structStack.isEmpty(), "Member found outside of struct.");
280
281 const int name_idx(indexOf(attributes, "name"));
282 COND_DOC_ERROR(name_idx < 0, QString("Anonymous member found."));
283 COND_DOC_ERROR(!hasType(attributes), QString("Member without a type found."));
284
285 createEntry();
286
287 m_currentEntry->section = Entry::VARIABLE_SEC;
288 m_currentEntry->name = attributes.value(name_idx);
289 m_currentEntry->type = getType(attributes);
290
291 QString type(getDBusType(m_currentEntry->type));
292 m_structStack.last()->type.append(type);
293 }
294
295 if (EXTENSION("enum") || EXTENSION("flagset"))
296 {
297 CONDITION(m_currentMethod, "Enum found inside a method or signal.");
298 CONDITION(m_currentProperty, "Enum found inside a property.");
299
300 const int name_idx(indexOf(attributes, "name"));
301 COND_DOC_ERROR(name_idx < 0, QString("Anonymous enum found."));
302
303 const int type_idx(indexOf(attributes, "type"));
304 QString type = "u";
305 if (type_idx >= 0)
306 { type = attributes.value(type_idx); }
307 if (type != "y" && type != "q" && type != "u" && type != "t")
308 { DOC_ERROR(QString("Invalid enum type \"%1\" found.").arg(type)); }
309
310 m_currentEnum = createEntry();
311 m_currentEnum->section = Entry::ENUM_SEC;
312 m_currentEnum->name = attributes.value(name_idx);
313
314 openScopes(m_currentEnum);
315
316 m_currentEnum->type = m_currentEntry->name + " enum";
317
318 addNamedType(type);
319 }
320
321 if (EXTENSION("value"))
322 {
323 CONDITION(!m_currentEnum, "Value found outside an enum.");
324
325 const int name_idx(indexOf(attributes, "name"));
326 COND_DOC_ERROR(name_idx < 0, QString("Anonymous value found."));
327
328 const int value_idx(indexOf(attributes, "value"));
329
330 createEntry();
331
332 m_currentEntry->section = Entry::VARIABLE_SEC;
333 m_currentEntry->name = attributes.value(name_idx);
334 m_currentEntry->type = m_currentEnum->name; // "@"; // enum marker!
335 if (value_idx >= 0)
336 { m_currentEntry->initializer = attributes.value(value_idx); }
337 }
338
339 return true;
340 }
341
342 bool endElement(const QString &namespaceURI,
343 const QString &localName,
344 const QString &qName)
345 {
346 // Clean up elements stack:
347 // Since we made sure to get the elements in the proper order when
348 // adding we do not need to do so again here.
349 COND_DOC_ERROR(m_elementStack.last()->element != qName,
350 QString("Malformed XML: Unexpected closing element found.").
351 arg(m_elementStack.last()->element));
352 m_elementStack.removeLast();
353
354 // Interface:
355 if (DBUS("interface"))
356 {
357 CONDITION(m_currentInterface, "end of interface found without start.");
358 m_currentInterface->endBodyLine = lineNumber();
359 closeScopes();
360 m_currentInterface = 0;
361 }
362
363 if (DBUS("method") || DBUS("signal"))
364 {
365 CONDITION(m_currentMethod, "end of method found without start.");
366 CONDITION(m_currentInterface, "end of method found outside interface.");
367 m_currentMethod->endBodyLine = lineNumber();
368 m_currentInterface->addSubEntry(m_currentMethod);
369 m_currentMethod = 0;
370 }
371
372 if (DBUS("property"))
373 {
374 CONDITION(m_currentMethod, "end of property found without start.");
375 CONDITION(m_currentInterface, "end of property found outside interface.");
376 m_currentProperty->endBodyLine = lineNumber();
377 m_currentInterface->addSubEntry(m_currentProperty);
378 m_currentProperty = 0;
379 }
380
381 if (DBUS("arg"))
382 {
383 CONDITION(m_currentMethod, "end of arg found outside method.");
384 m_currentMethod->argList->append(m_currentArgument);
385 m_currentArgument = 0;
386 }
387
388 if (EXTENSION("namespace"))
389 {
390 Entry * current = m_namespaceStack.last();
391 CONDITION(current, "end of namespace without start.");
392 m_namespaceStack.removeLast();
393
394 current->endBodyLine = lineNumber();
395 closeScopes();
396 }
397
398 if (EXTENSION("struct"))
399 {
400 StructData * data = m_structStack.last();
401 CONDITION(data, "end of struct without start.");
402
403 data->entry->endBodyLine = lineNumber();
404
405 QString current_type;
406 current_type.append(QString("("));
407 current_type.append(data->type);
408 current_type.append(QString(")"));
409
410 addNamedType(current_type);
411
412 closeScopes();
413
414 m_structStack.removeLast();
415 }
416
417 if (EXTENSION("member"))
418 {
419 StructData * data = m_structStack.last();
420 CONDITION(data, "end of struct without start");
421 data->entry->addSubEntry(m_currentEntry);
422 }
423
424 if (EXTENSION("enum") || EXTENSION("flagset"))
425 {
426 CONDITION(m_currentEnum, "end of enum without start");
427 m_currentEnum->endBodyLine = lineNumber();
428 closeScopes();
429
430 m_currentEnum = 0;
431 }
432
433 if (EXTENSION("value"))
434 {
435 CONDITION(m_currentEntry, "end of value without start");
436 m_currentEntry->endBodyLine = lineNumber();
437
438 m_currentEnum->addSubEntry(m_currentEntry);
439 }
440
441 return true;
442 }
443
444 bool characters(const QString & /*chars*/)
445 { return true; }
446
447 bool comment(const QString & comment_)
448 {
449 if (m_currentComment)
450 { handleComment(); }
451
452 m_currentComment = new CommentData(m_fileName, lineNumber(), comment_);
453
454 if (!m_currentComment->shouldIgnore)
455 {
456 delete m_currentComment;
457 m_currentComment = 0;
458 return true;
459 }
460
461 if (m_currentComment->associateWithPrevious)
462 { handleComment(); }
463
464 return true;
465 }
466
467 void handleComment()
468 {
469 if (m_currentComment == 0 || m_currentEntry == 0)
470 { return; }
471
472 QCString text(m_currentComment->text);
473
474 m_currentEntry->docFile = m_currentComment->fileName;
475 m_currentEntry->docLine = m_currentComment->line;
476
477 int position(0);
478 bool needs_entry(false);
479 bool brief(false);
480 Protection prot(Public);
481 int lineNr = lineNumber();
482
483 while (parseCommentBlock(m_parser,
484 m_currentEntry,
485 text, m_fileName.utf8().data(),
486 lineNr,
487 brief, m_currentComment->isJavaStyle,
488 false,
489 prot,
490 position,
491 needs_entry))
492 {
493 if (needs_entry) { createEntry(); }
494 }
495 if (needs_entry) { createEntry(); }
496
497 delete m_currentComment;
498 m_currentComment = 0;
499 }
500
501 QXmlLocator * locator()
502 { return &m_locator; }
503
504 int lineNumber()
505 { return m_locator.lineNumber(); }
506
507 void setSection()
508 {
509 Entry * current = createEntry();
510 current->reset();
511
512 current->name = m_fileName.utf8();
513 current->section = Entry::SOURCE_SEC;
514
515 // Open/Close the scope to do the bookkeeping:
516 openScopes(current);
517 closeScopes();
518 }
519
520private:
521 bool isDBusElement(const QString & namespaceURI,
522 const QString & localName,
523 const QString & qName,
524 const QString & element)
525 {
526 return (namespaceURI.isEmpty() && localName == element && qName == element) ||
527 (namespaceURI.isEmpty() && localName.isEmpty() && qName == element);
528 }
529
530 bool isExtensionElement(const QString & namespaceURI,
531 const QString & localName,
532 const QString & qName,
533 const QString & element)
534 {
535 // isNull happens in startelement if no URI is used.
536 if (namespaceURI.isNull())
537 { return false; }
538
539 // We are in a endElement: URI is always empty there:-(
540 if (namespaceURI.isEmpty())
541 { return qName == m_scopeStack.last()->extensionPrefix + element; }
542
543 // startElemennt: We need to save the qName prefix
544 // since endElement will forget about the namespaceURi:-(
545 if (namespaceURI == EXTENSION_URI)
546 {
547 int pos = qName.find(':');
548 m_scopeStack.last()->extensionPrefix = qName.left(pos + 1);
549 }
550
551 return namespaceURI == EXTENSION_URI && localName == element;
552 }
553
554 bool hasType(const QXmlAttributes & attributes)
555 {
556 const int type_idx(indexOf(attributes, "type"));
557 const int named_type_idx(indexOf(attributes, "named-type"));
558
559 return named_type_idx >= 0 || type_idx >= 0;
560 }
561
562 QString getType(const QXmlAttributes & attributes)
563 {
564 const int type_idx(indexOf(attributes, "type"));
565 const int named_type_idx(indexOf(attributes, "named-type"));
566
567 QString type;
568
569 if (named_type_idx >= 0)
570 {
571 type = attributes.value(named_type_idx);
572 if (!type.startsWith("::"))
573 { type = getCurrentScope(attributes.value(named_type_idx)); }
574 else
575 { type = type.mid(2); }
576 if (m_namedTypeMap.contains(type))
577 {
578 if (type_idx >= 0)
579 {
580 const QString dbus_type(attributes.value(type_idx));
581 if (dbus_type != m_namedTypeMap[type])
582 {
583 DOC_ERROR(QString("Type \"%1\" does not match up with "
584 "previous definition of named type \"%2\" (which was \"%3\".").
585 arg(dbus_type).
586 arg(type).
587 arg(m_namedTypeMap[type]));
588 }
589 }
590 return type;
591 }
592
593 DOC_ERROR(QString("Undefined named type \"%1\" used.").arg(type));
594 }
595
596 if (type_idx >= 0)
597 {
598 type = attributes.value(type_idx);
599
600 QRegExp reg_exp(QCString("(a?[ybnqiuxdtsogv]|a[{]sv[}])"));
601 if (reg_exp.match(type.data()))
602 { return type; }
603
604 DOC_ERROR(QString("Unnamed complex D-Bus type \"%1\" found.").arg(type));
605 }
606
607 return QString();
608 }
609
610 QString getDBusType(const QString & type)
611 {
612 QString scoped_type = type;
613 if (!scoped_type.contains("::"))
614 { scoped_type = getCurrentScope(type); }
615
616 if (m_namedTypeMap.contains(scoped_type))
617 { return m_namedTypeMap[scoped_type]; }
618 else
619 { return type; }
620 }
621
622 void addNamedType(const QString type)
623 {
624 QString scoped_name(getCurrentScope());
625
626 if (m_namedTypeMap.contains(scoped_name))
627 {
628 DOC_ERROR(QString("Named type \"%1\" is already defined.").arg(scoped_name));
629 return;
630 }
631
632 m_namedTypeMap.insert(scoped_name, type);
633 }
634
635 QString getCurrentScope(const QString & type = QString())
636 {
637 QString scoped_name;
638 if (!m_scopeStack.isEmpty())
639 {
640 scoped_name = m_scopeStack.last()->scope->name;
641 scoped_name.append("::");
642 }
643 if (!type.isEmpty())
644 { scoped_name.append(type); }
645 else
646 { scoped_name = scoped_name.left(scoped_name.length() - 2); }
647
648 return scoped_name;
649 }
650
651 int indexOf(const QXmlAttributes & attributes, const QString & name,
652 const QString & type = "CDATA", const bool mandatory = true)
653 {
654 const int idx(attributes.index(name));
655 if (idx < 0 || idx > attributes.length()) { return -1; }
656 if (attributes.type(idx) != type) { return -1; }
657 if (mandatory && attributes.value(idx).isEmpty()) { return -1; }
658
659 return idx;
660 }
661
662 Entry * createEntry()
663 {
664 Entry * entry = new Entry();
665
666 entry->protection = Public ;
667 entry->virt = Normal;
668 entry->stat = false;
669 entry->lang = SrcLangExt_XML;
670 entry->spec = 0;
671
672 entry->fileName = m_fileName;
673 entry->startLine = lineNumber();
674 entry->bodyLine = lineNumber();
675
676 entry->callGraph = false;
677 entry->callerGraph = false;
678
679 initGroupInfo(entry);
680
681 m_currentEntry = entry;
682
683 handleComment();
684
685 return entry;
686 }
687
688 void openScopes(Entry * object)
689 {
690 int cur_scope_separator_pos = 0;
691 int last_scope_separator_pos = 0;
692 while (0 <= (cur_scope_separator_pos = object->name.find("::", last_scope_separator_pos)))
693 {
694 QString scope = object->name.mid(last_scope_separator_pos,
695 cur_scope_separator_pos - last_scope_separator_pos);
696 last_scope_separator_pos = cur_scope_separator_pos + 2;
697
698 Entry * current_namespace = openNamespace(scope);
699
700 if (!m_scopeStack.isEmpty())
701 { m_scopeStack.last()->scope->addSubEntry(current_namespace); }
702
703 m_scopeStack.append(new ScopeData(current_namespace, m_scopeCount));
704 }
705
706 QString scoped_name(getCurrentScope());
707 if (!scoped_name.isEmpty())
708 { scoped_name.append("::"); }
709 scoped_name.append(object->name.mid(last_scope_separator_pos));
710
711 object->name = scoped_name;
712
713 if (!m_scopeStack.isEmpty())
714 { m_scopeStack.last()->scope->addSubEntry(object); }
715 m_scopeStack.append(new ScopeData(object, m_scopeCount));
716
717 ++m_scopeCount;
718 }
719
720 Entry * openNamespace(const QString & name)
721 {
722 Entry * current_namespace = createEntry();
723 QString scoped_name(getCurrentScope());
724 if (!scoped_name.isEmpty())
725 { scoped_name.append("::"); }
726 scoped_name.append(name);
727 current_namespace->name = scoped_name;
728 current_namespace->section = Entry::NAMESPACE_SEC;
729 current_namespace->type = "namespace" ;
730
731 return current_namespace;
732 }
733
734 void closeScopes()
735 {
736 const int current_scope_count(m_scopeStack.last()->count);
737
738 // Do not close the root scope.
739 if (current_scope_count == 0)
740 { return; }
741
742 while (current_scope_count == m_scopeStack.last()->count)
743 { m_scopeStack.removeLast(); }
744 }
745
746 ParserInterface * m_parser;
747
748 QXmlLocator m_locator;
749 QString m_currentNode; // Nodes can not be nested, no entry necessary.
750
751 struct ElementData
752 {
753 ElementData(const QString & e) :
754 element(e)
755 { }
756 ~ElementData() { }
757
758 QString element; //*< The element name
759 QString extensionPrefix; //*< The prefix used for our extension.
760 QString text; //*< The actual xml code.
761 };
762 QList<ElementData> m_elementStack;
763
764 Entry * m_currentEntry; // The currently open entry.
765
766 Entry * m_currentInterface; // Interfaces can not be nested.
767 Entry * m_currentMethod; // Methods can not be nested.
768 Argument * m_currentArgument; // Arguments can not be nested.
769 Entry * m_currentProperty; // Properties can not be nested.
770 Entry * m_currentEnum; // Enums can not be nested.
771 QList<Entry> m_namespaceStack;
772
773 struct StructData
774 {
775 StructData(Entry * e) : entry(e) { }
776 ~StructData() { }
777
778 QString type;
779 Entry * entry;
780 };
781 QList<StructData> m_structStack; // Structs can be nested.
782
783 struct ScopeData
784 {
785 ScopeData(Entry * s, int c) :
786 scope(s),
787 count(c)
788 { }
789 ~ScopeData() { }
790
791 Entry * scope;
792 QString extensionPrefix;
793 int count;
794 };
795 QList<ScopeData> m_scopeStack; // Scopes are nested.
796
797 QString m_fileName;
798
799 struct CommentData
800 {
801 CommentData(const QString & f, const int l, const QString & t) :
802 isJavaStyle(false),
803 isQtStyle(false),
804 line(l),
805 fileName(f)
806 {
807 isJavaStyle = t.startsWith(QChar('*'));
808 isQtStyle = t.startsWith(QChar('!'));
809 shouldIgnore = (!isJavaStyle && !isQtStyle);
810 associateWithPrevious = (t.at(1) == QChar('<'));
811 if (associateWithPrevious)
812 { text = t.mid(2); }
813 else
814 { text = t.mid(1); }
815 }
816 ~CommentData() { }
817
818 QString text;
819 bool isJavaStyle;
820 bool isQtStyle;
821 bool shouldIgnore;
822 bool associateWithPrevious;
823 int line;
824 QString fileName;
825 };
826 CommentData * m_currentComment;
827
828 int m_scopeCount; //*< unique scope id.
829
830 QString m_errorString;
831
832 QMap<QString, QString> m_namedTypeMap;
833};
834
835// -----------------------------------------------------------------------
836// DBusXMLScanner
837// -----------------------------------------------------------------------
838
839DBusXMLScanner::DBusXMLScanner()
840{ }
841
842DBusXMLScanner::~DBusXMLScanner()
843{ }
844
845void DBusXMLScanner::parseInput(const char * fileName,
846 const char * /* fileBuf */,
847 Entry * root)
848{
849 err("Note that the dbusxml parser seems to be broken :-(\nPlease help me to fix it!\n");
850 QFile inputFile(fileName);
851
852 QXmlInputSource inputSource(inputFile);
853 QXmlSimpleReader reader;
854
855 DBusXMLHandler handler(this, &reader, fileName, root);
856 reader.setContentHandler(&handler);
857 reader.setErrorHandler(&handler);
858 reader.setLexicalHandler(&handler);
859
860 groupEnterFile(fileName, 1);
861 handler.setSection();
862 reader.parse(inputSource);
863
864 if (handler.errorString())
865 { err("DBus XML Parser: Error at line %d: %s\n",
866 handler.locator()->lineNumber(),handler.errorString().utf8().data()); }
867
868 groupLeaveFile(fileName, 1);
869}
870
871bool DBusXMLScanner::needsPreprocessing(const QCString & /* extension */)
872{ return (false); }
873
874void DBusXMLScanner::parseCode(CodeOutputInterface & /* codeOutIntf */,
875 const char * /* scopeName */,
876 const QCString & /* input */,
877 bool /* isExampleBlock */,
878 const char * /* exampleName */,
879 FileDef * /* fileDef */,
880 int /* startLine */,
881 int /* endLine */,
882 bool /* inlineFragment */,
883 MemberDef * /* memberDef */,
884 bool /*showLineNumbers*/)
885{ }
886
887void DBusXMLScanner::resetCodeParserState()
888{ }
889
890void DBusXMLScanner::parsePrototype(const char * /* text */)
891{ }
892

Archive Download this file

Revision: 1322