]> git.saurik.com Git - wxWidgets.git/blob - utils/ifacecheck/src/xmlparser.h
a few other means to avoid false positives
[wxWidgets.git] / utils / ifacecheck / src / xmlparser.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: xmlparser.h
3 // Purpose: Parser of the API/interface XML files
4 // Author: Francesco Montorsi
5 // Created: 2008/03/17
6 // RCS-ID: $Id$
7 // Copyright: (c) 2008 Francesco Montorsi
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11
12 #ifndef _XMLPARSER_H_
13 #define _XMLPARSER_H_
14
15 #include <wx/txtstrm.h>
16 #include <wx/dynarray.h>
17 #include <wx/xml/xml.h>
18 #include <wx/platinfo.h>
19
20
21 /*
22 IMPORTANT
23 =========
24
25 Any fix aimed to reduce "false positives" which involves
26 references to a specific wxWidgets class is marked in
27 ifacecheck sources with the string:
28
29 // ADHOC-FIX:
30 // ...fix description...
31 */
32
33
34
35 // helper macros
36 #define LogMessage(fmt, ...) { if (g_bLogEnabled) { wxPrintf(fmt "\n", __VA_ARGS__); fflush(stdout); }}
37 #define LogWarning(fmt, ...) { if (g_bLogEnabled) { wxPrintf(fmt "\n", __VA_ARGS__); fflush(stdout); }}
38 #define LogError(fmt, ...) { if (g_bLogEnabled) { wxPrintf("ERROR: " fmt "\n", __VA_ARGS__); fflush(stdout); }}
39 #define wxPrint(str) { wxPrintf(str); fflush(stdout); }
40
41 // enable/disable logging
42 extern bool g_bLogEnabled;
43
44 class LogNull
45 {
46 public:
47 LogNull() { g_bLogEnabled = false; }
48 ~LogNull() { g_bLogEnabled = true; }
49 };
50
51
52
53 // ----------------------------------------------------------------------------
54 // Represents a type with or without const/static/ qualifier
55 // and with or without & and * operators
56 // ----------------------------------------------------------------------------
57 class wxType
58 {
59 public:
60 wxType() {}
61 wxType(const wxString& type)
62 { SetTypeFromString(type); }
63
64 void SetTypeFromString(const wxString& t);
65 wxString GetAsString() const
66 { return m_strType; }
67
68 // returns this type _without_ any decoration,
69 // including the & (which indicates this is a reference),
70 // the * (which indicates this is a pointer), etc.
71 wxString GetAsCleanString() const
72 { return m_strTypeClean; }
73
74 bool IsConst() const
75 { return m_strType.Contains("const"); }
76 bool IsStatic() const
77 { return m_strType.Contains("static"); }
78 bool IsPointer() const
79 { return m_strType.Contains("*"); }
80 bool IsReference() const
81 { return m_strType.Contains("&"); }
82
83 bool operator==(const wxType& m) const;
84 bool operator!=(const wxType& m) const
85 { return !(*this == m); }
86
87 bool IsOk() const;
88
89 protected:
90 wxString m_strType,
91 m_strTypeClean; // m_strType "cleaned" of its attributes
92 // (only for internal use)
93 };
94
95 extern wxType wxEmptyType;
96 WX_DECLARE_OBJARRAY(wxType, wxTypeArray);
97
98
99 // ----------------------------------------------------------------------------
100 // Represents a type used as argument for some wxMethod
101 // ----------------------------------------------------------------------------
102 class wxArgumentType : public wxType
103 {
104 public:
105 wxArgumentType() {}
106 wxArgumentType(const wxString& type, const wxString& defVal,
107 const wxString& argName = wxEmptyString)
108 { SetTypeFromString(type); SetDefaultValue(defVal); m_strArgName = argName; }
109
110 void SetArgumentName(const wxString& name)
111 { m_strArgName=name.Strip(wxString::both); }
112 wxString GetArgumentName() const
113 { return m_strArgName; }
114
115 void SetDefaultValue(const wxString& defval,
116 const wxString& defvalForCmp = wxEmptyString);
117 wxString GetDefaultValue() const
118 { return m_strDefaultValue; }
119
120 // returns the default value used for comparisons
121 wxString GetDefaultCleanValue() const
122 { return m_strDefaultValueForCmp; }
123
124 bool HasDefaultValue() const
125 { return !m_strDefaultValue.IsEmpty(); }
126
127 bool operator==(const wxArgumentType& m) const;
128 bool operator!=(const wxArgumentType& m) const
129 { return !(*this == m); }
130
131 protected:
132 wxString m_strDefaultValue;
133
134 // this string may differ from m_strDefaultValue if there were
135 // preprocessor substitutions or other "replacements" done to
136 // avoid false errors.
137 wxString m_strDefaultValueForCmp;
138
139 // the argument name
140 wxString m_strArgName;
141 };
142
143 extern wxArgumentType wxEmptyArgumentType;
144 WX_DECLARE_OBJARRAY(wxArgumentType, wxArgumentTypeArray);
145
146
147 enum wxMethodAccessSpecifier
148 {
149 wxMAS_PUBLIC,
150 wxMAS_PROTECTED,
151 wxMAS_PRIVATE
152 };
153
154 // ----------------------------------------------------------------------------
155 // Represents a single prototype of a class' member.
156 // ----------------------------------------------------------------------------
157 class wxMethod
158 {
159 public:
160 wxMethod()
161 { m_bConst=m_bVirtual=m_bPureVirtual=m_bStatic=m_bDeprecated=false;
162 m_nLine=-1; m_nAvailability=wxPORT_UNKNOWN; m_access=wxMAS_PUBLIC; }
163
164 wxMethod(const wxType& rettype, const wxString& name,
165 const wxArgumentTypeArray& arguments,
166 bool isConst, bool isStatic, bool isVirtual)
167 : m_retType(rettype), m_strName(name.Strip(wxString::both)),
168 m_bConst(isConst), m_bStatic(isStatic), m_bVirtual(isVirtual)
169 { SetArgumentTypes(arguments); m_nLine=-1; }
170
171
172 public: // getters
173
174 // bWithArgumentNames = output argument names?
175 // bCleanDefaultValues = output clean argument default values?
176 // bDeprecated = output [deprecated] next to deprecated methods?
177 // bAccessSpec = output [public], [protected] or [private] next to method?
178 //
179 // TODO: convert to readable flags this set of bools
180 wxString GetAsString(bool bWithArgumentNames = true,
181 bool bCleanDefaultValues = false,
182 bool bDeprecated = false,
183 bool bAccessSpec = false) const;
184
185 // parser of the prototype:
186 // all these functions return strings with spaces stripped
187 wxType GetReturnType() const
188 { return m_retType; }
189 wxString GetName() const
190 { return m_strName; }
191 const wxArgumentTypeArray& GetArgumentTypes() const
192 { return m_args; }
193 wxArgumentTypeArray& GetArgumentTypes()
194 { return m_args; }
195 int GetLocation() const
196 { return m_nLine; }
197 int GetAvailability() const
198 { return m_nAvailability; }
199 wxMethodAccessSpecifier GetAccessSpecifier() const
200 { return m_access; }
201
202 bool IsConst() const
203 { return m_bConst; }
204 bool IsStatic() const
205 { return m_bStatic; }
206 bool IsVirtual() const
207 { return m_bVirtual; }
208 bool IsPureVirtual() const
209 { return m_bPureVirtual; }
210
211 bool IsOk() const;
212 bool IsCtor() const
213 { return m_retType==wxEmptyType && !m_strName.StartsWith("~"); }
214 bool IsDtor() const
215 { return m_retType==wxEmptyType && m_strName.StartsWith("~"); }
216 bool IsOperator() const
217 { return m_strName.StartsWith("operator"); }
218
219 bool IsDeprecated() const
220 { return m_bDeprecated; }
221
222
223
224 public: // setters
225
226 void SetReturnType(const wxType& t)
227 { m_retType=t; }
228 void SetName(const wxString& name)
229 { m_strName=name; }
230 void SetArgumentTypes(const wxArgumentTypeArray& arr)
231 { m_args=arr; }
232 void SetConst(bool c = true)
233 { m_bConst=c; }
234 void SetStatic(bool c = true)
235 { m_bStatic=c; }
236 void SetVirtual(bool c = true)
237 { m_bVirtual=c; }
238 void SetPureVirtual(bool c = true)
239 {
240 m_bPureVirtual=c;
241 if (c) m_bVirtual=c; // pure virtual => virtual
242 }
243 void SetDeprecated(bool c = true)
244 { m_bDeprecated=c; }
245 void SetLocation(int lineNumber)
246 { m_nLine=lineNumber; }
247 void SetAvailability(int nAvail)
248 { m_nAvailability=nAvail; }
249 void SetAccessSpecifier(wxMethodAccessSpecifier spec)
250 { m_access=spec; }
251
252 public: // misc
253
254 bool operator==(const wxMethod&) const;
255 bool operator!=(const wxMethod& m) const
256 { return !(*this == m); }
257
258 // this function works like operator== but tests everything:
259 // - method name
260 // - return type
261 // - argument types
262 // except for the method attributes (const,static,virtual,pureVirtual,deprecated)
263 bool MatchesExceptForAttributes(const wxMethod& m) const;
264
265 // returns true if this is a ctor which has default values for all its
266 // argument, thus is able to act also as default ctor
267 bool ActsAsDefaultCtor() const;
268
269 // dumps the contents of this class in the given stream
270 void Dump(wxTextOutputStream& stream) const;
271
272 protected:
273 wxType m_retType;
274 wxString m_strName;
275 wxArgumentTypeArray m_args;
276
277 // misc attributes:
278 bool m_bConst;
279 bool m_bStatic;
280 bool m_bVirtual;
281 bool m_bPureVirtual;
282 bool m_bDeprecated;
283
284 // m_nLine can be -1 if no location infos are available
285 int m_nLine;
286
287 // this is a combination of wxPORT_* flags (see wxPortId) or wxPORT_UNKNOWN
288 // if this method should be available for all wxWidgets ports.
289 // NOTE: this is not used for comparing wxMethod objects
290 // (gccXML never gives this kind of info).
291 int m_nAvailability;
292
293 // the access specifier for this method
294 wxMethodAccessSpecifier m_access;
295 };
296
297 WX_DECLARE_OBJARRAY(wxMethod, wxMethodArray);
298 WX_DEFINE_ARRAY(const wxMethod*, wxMethodPtrArray);
299
300
301 // we need wxClassPtrArray to be defined _before_ wxClass itself,
302 // since wxClass uses wxClassPtrArray.
303 class wxClass;
304 WX_DEFINE_ARRAY(const wxClass*, wxClassPtrArray);
305
306 class wxXmlInterface;
307
308
309 // ----------------------------------------------------------------------------
310 // Represents a class of the wx API/interface.
311 // ----------------------------------------------------------------------------
312 class wxClass
313 {
314 public:
315 wxClass() {}
316 wxClass(const wxString& name, const wxString& headername)
317 : m_strName(name), m_strHeader(headername) {}
318
319
320 public: // setters
321
322 void SetHeader(const wxString& header)
323 { m_strHeader=header; }
324 void SetName(const wxString& name)
325 { m_strName=name; }
326 void SetAvailability(int nAvail)
327 { m_nAvailability=nAvail; }
328 void SetParent(unsigned int k, const wxString& name)
329 { m_parents[k]=name; }
330
331 public: // getters
332
333 bool IsOk() const
334 { return !m_strName.IsEmpty() && !m_methods.IsEmpty(); }
335
336 bool IsValidCtorForThisClass(const wxMethod& m) const;
337 bool IsValidDtorForThisClass(const wxMethod& m) const;
338
339 wxString GetName() const
340 { return m_strName; }
341 wxString GetHeader() const
342 { return m_strHeader; }
343 wxString GetNameWithoutTemplate() const;
344
345 unsigned int GetMethodCount() const
346 { return m_methods.GetCount(); }
347 wxMethod& GetMethod(unsigned int n) const
348 { return m_methods[n]; }
349 wxMethod& GetLastMethod() const
350 { return m_methods.Last(); }
351
352 int GetAvailability() const
353 { return m_nAvailability; }
354
355 //const wxClass *GetParent(unsigned int i) const
356 const wxString& GetParent(unsigned int i) const
357 { return m_parents[i]; }
358 unsigned int GetParentCount() const
359 { return m_parents.GetCount(); }
360
361 public: // misc
362
363 void AddMethod(const wxMethod& func)
364 { m_methods.Add(func); }
365
366 void AddParent(const wxString& parent)//wxClass* parent)
367 { m_parents.Add(parent); }
368
369 // returns a single result (the first, which is also the only
370 // one if CheckConsistency() return true)
371 const wxMethod* FindMethod(const wxMethod& m) const;
372
373 // like FindMethod() but this one searches also recursively in
374 // the parents of this class.
375 const wxMethod* RecursiveUpwardFindMethod(const wxMethod& m,
376 const wxXmlInterface* allclasses) const;
377
378 // returns an array of pointers to the overloaded methods with the
379 // same given name
380 wxMethodPtrArray FindMethodsNamed(const wxString& name) const;
381
382 // like FindMethodsNamed() but this one searches also recursively in
383 // the parents of this class.
384 wxMethodPtrArray RecursiveUpwardFindMethodsNamed(const wxString& name,
385 const wxXmlInterface* allclasses) const;
386
387 // dumps all methods to the given output stream
388 void Dump(wxTextOutputStream& stream) const;
389
390 // slow check
391 bool CheckConsistency() const;
392
393 protected:
394 wxString m_strName;
395 wxString m_strHeader;
396 wxMethodArray m_methods;
397
398 // name of the base classes: we store the names and not the pointers
399 // because this makes _much_ easier the parsing process!
400 // (basically because when parsing class X which derives from Y,
401 // we may have not parsed yet class Y!)
402 wxArrayString m_parents;
403
404 // see the wxMethod::m_nAvailability field for more info
405 int m_nAvailability;
406 };
407
408 WX_DECLARE_OBJARRAY(wxClass, wxClassArray);
409
410
411
412 // ----------------------------------------------------------------------------
413 // wxXmlInterface
414 // ----------------------------------------------------------------------------
415 class wxXmlInterface
416 {
417 public:
418 wxXmlInterface() {}
419
420 const wxClass* FindClass(const wxString& classname) const
421 {
422 for (unsigned int i=0; i<m_classes.GetCount(); i++)
423 if (m_classes[i].GetName() == classname)
424 return &m_classes[i];
425 return NULL;
426 }
427
428 void Dump(const wxString& filename);
429
430 const wxClassArray& GetClasses() const
431 { return m_classes; }
432
433 unsigned int GetClassesCount() const
434 { return m_classes.GetCount(); }
435
436 unsigned int GetMethodCount() const
437 {
438 unsigned int methods = 0;
439 for (unsigned i=0; i < m_classes.GetCount(); i++)
440 methods += m_classes[i].GetMethodCount();
441 return methods;
442 }
443
444 // pass a full-path header filename:
445 wxClassPtrArray FindClassesDefinedIn(const wxString& headerfile) const;
446
447 void ShowProgress()
448 { /*wxPrint(".");*/ }
449
450 bool CheckParseResults() const;
451
452 protected:
453 wxClassArray m_classes;
454 };
455
456 #if 1
457 // for wxTypeIdHashMap, keys == gccxml IDs and values == associated type strings
458 // e.g. key = "0x123f" and value = "const wxAboutDialogInfo&"
459 WX_DECLARE_HASH_MAP( unsigned long, wxString,
460 wxIntegerHash, wxIntegerEqual,
461 wxTypeIdHashMap );
462
463 WX_DECLARE_STRING_HASH_MAP( wxString, wxStringHashMap );
464 #else
465 #include <map>
466 typedef std::basic_string<char> stlString;
467 typedef std::map<unsigned long, stlString> wxTypeIdHashMap;
468 #endif
469
470
471 // ----------------------------------------------------------------------------
472 // Represents the real interface of wxWidgets
473 // Loads it from the XML produced by gccXML: http://www.gccxml.org
474 // ----------------------------------------------------------------------------
475 class wxXmlGccInterface : public wxXmlInterface
476 {
477 public:
478 wxXmlGccInterface()
479 {
480 // FIXME: we should retrieve this from the XML file!
481 // here we suppose the XML was created for the currently-running port
482 m_portId = wxPlatformInfo::Get().GetPortId();
483 }
484
485 bool Parse(const wxString& filename);
486 bool ParseMethod(const wxXmlNode *p,
487 const wxTypeIdHashMap& types,
488 wxMethod& m);
489
490 wxPortId GetInterfacePort() const
491 { return m_portId; }
492
493 wxString GetInterfacePortName() const
494 { return wxPlatformInfo::GetPortIdName(m_portId, false); }
495
496 protected:
497 // the port for which the gcc XML was generated
498 wxPortId m_portId;
499 };
500
501
502 // ----------------------------------------------------------------------------
503 // Represents the interface of the doxygen headers of wxWidgets
504 // Loads it from the XML produced by Doxygen: http://www.doxygen.org
505 // ----------------------------------------------------------------------------
506 class wxXmlDoxygenInterface : public wxXmlInterface
507 {
508 public:
509 wxXmlDoxygenInterface() {}
510
511 // !!SPEEDUP-TODO!!
512 // Using wxXmlDocument::Load as is, the entire XML file is parsed
513 // and an entire tree of wxXmlNodes is built in memory.
514 // We need however only small portions of the Doxygen-generated XML: to speedup the
515 // processing we could detach the expat callbacks when we detect the beginning of a
516 // node we're not interested about, or just don't create a wxXmlNode for it!
517 // This needs a modification of wxXml API.
518
519 bool Parse(const wxString& filename);
520 bool ParseCompoundDefinition(const wxString& filename);
521 bool ParseMethod(const wxXmlNode*, wxMethod&, wxString& header);
522
523 // this class can take advantage of the preprocessor output to give
524 // a minor number of false positive warnings in the final comparison
525 void AddPreprocessorValue(const wxString& name, const wxString& val)
526 { m_preproc[name]=val; }
527
528 protected:
529 wxStringHashMap m_preproc;
530 };
531
532
533
534 #endif // _XMLPARSER_H_
535