1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Parser of the API/interface XML files
4 // Author: Francesco Montorsi
7 // Copyright: (c) 2008 Francesco Montorsi
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
15 #include <wx/txtstrm.h>
16 #include <wx/dynarray.h>
17 #include <wx/xml/xml.h>
18 #include <wx/platinfo.h>
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:
30 // ...fix description...
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); }
41 // enable/disable logging
42 extern bool g_bLogEnabled
;
47 LogNull() { g_bLogEnabled
= false; }
48 ~LogNull() { g_bLogEnabled
= true; }
53 // ----------------------------------------------------------------------------
54 // Represents a type with or without const/static/ qualifier
55 // and with or without & and * operators
56 // ----------------------------------------------------------------------------
61 wxType(const wxString
& type
)
62 { SetTypeFromString(type
); }
64 void SetTypeFromString(const wxString
& t
);
65 wxString
GetAsString() const
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
; }
75 { return m_strType
.Contains("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("&"); }
83 bool operator==(const wxType
& m
) const;
84 bool operator!=(const wxType
& m
) const
85 { return !(*this == m
); }
91 m_strTypeClean
; // m_strType "cleaned" of its attributes
92 // (only for internal use)
95 extern wxType wxEmptyType
;
96 WX_DECLARE_OBJARRAY(wxType
, wxTypeArray
);
99 // ----------------------------------------------------------------------------
100 // Represents a type used as argument for some wxMethod
101 // ----------------------------------------------------------------------------
102 class wxArgumentType
: public wxType
106 wxArgumentType(const wxString
& type
, const wxString
& defVal
,
107 const wxString
& argName
= wxEmptyString
)
108 { SetTypeFromString(type
); SetDefaultValue(defVal
); m_strArgName
= argName
; }
110 void SetArgumentName(const wxString
& name
)
111 { m_strArgName
=name
.Strip(wxString::both
); }
112 wxString
GetArgumentName() const
113 { return m_strArgName
; }
115 void SetDefaultValue(const wxString
& defval
,
116 const wxString
& defvalForCmp
= wxEmptyString
);
117 wxString
GetDefaultValue() const
118 { return m_strDefaultValue
; }
120 // returns the default value used for comparisons
121 wxString
GetDefaultCleanValue() const
122 { return m_strDefaultValueForCmp
; }
124 bool HasDefaultValue() const
125 { return !m_strDefaultValue
.IsEmpty(); }
127 bool operator==(const wxArgumentType
& m
) const;
128 bool operator!=(const wxArgumentType
& m
) const
129 { return !(*this == m
); }
132 wxString m_strDefaultValue
;
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
;
140 wxString m_strArgName
;
143 extern wxArgumentType wxEmptyArgumentType
;
144 WX_DECLARE_OBJARRAY(wxArgumentType
, wxArgumentTypeArray
);
147 enum wxMethodAccessSpecifier
154 // ----------------------------------------------------------------------------
155 // Represents a single prototype of a class' member.
156 // ----------------------------------------------------------------------------
161 { m_bConst
=m_bVirtual
=m_bPureVirtual
=m_bStatic
=m_bDeprecated
=false;
162 m_nLine
=-1; m_nAvailability
=wxPORT_UNKNOWN
; m_access
=wxMAS_PUBLIC
; }
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; }
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?
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;
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
193 wxArgumentTypeArray
& GetArgumentTypes()
195 int GetLocation() const
197 int GetAvailability() const
198 { return m_nAvailability
; }
199 wxMethodAccessSpecifier
GetAccessSpecifier() const
204 bool IsStatic() const
205 { return m_bStatic
; }
206 bool IsVirtual() const
207 { return m_bVirtual
; }
208 bool IsPureVirtual() const
209 { return m_bPureVirtual
; }
213 { return m_retType
==wxEmptyType
&& !m_strName
.StartsWith("~"); }
215 { return m_retType
==wxEmptyType
&& m_strName
.StartsWith("~"); }
216 bool IsOperator() const
217 { return m_strName
.StartsWith("operator"); }
219 bool IsDeprecated() const
220 { return m_bDeprecated
; }
226 void SetReturnType(const wxType
& t
)
228 void SetName(const wxString
& name
)
230 void SetArgumentTypes(const wxArgumentTypeArray
& arr
)
232 void SetConst(bool c
= true)
234 void SetStatic(bool c
= true)
236 void SetVirtual(bool c
= true)
238 void SetPureVirtual(bool c
= true)
241 if (c
) m_bVirtual
=c
; // pure virtual => virtual
243 void SetDeprecated(bool c
= true)
245 void SetLocation(int lineNumber
)
246 { m_nLine
=lineNumber
; }
247 void SetAvailability(int nAvail
)
248 { m_nAvailability
=nAvail
; }
249 void SetAccessSpecifier(wxMethodAccessSpecifier spec
)
254 bool operator==(const wxMethod
&) const;
255 bool operator!=(const wxMethod
& m
) const
256 { return !(*this == m
); }
258 // this function works like operator== but tests everything:
262 // except for the method attributes (const,static,virtual,pureVirtual,deprecated)
263 bool MatchesExceptForAttributes(const wxMethod
& m
) const;
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;
269 // dumps the contents of this class in the given stream
270 void Dump(wxTextOutputStream
& stream
) const;
275 wxArgumentTypeArray m_args
;
284 // m_nLine can be -1 if no location infos are available
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).
293 // the access specifier for this method
294 wxMethodAccessSpecifier m_access
;
297 WX_DECLARE_OBJARRAY(wxMethod
, wxMethodArray
);
298 WX_DEFINE_ARRAY(const wxMethod
*, wxMethodPtrArray
);
301 // we need wxClassPtrArray to be defined _before_ wxClass itself,
302 // since wxClass uses wxClassPtrArray.
304 WX_DEFINE_ARRAY(const wxClass
*, wxClassPtrArray
);
306 class wxXmlInterface
;
309 // ----------------------------------------------------------------------------
310 // Represents a class of the wx API/interface.
311 // ----------------------------------------------------------------------------
316 wxClass(const wxString
& name
, const wxString
& headername
)
317 : m_strName(name
), m_strHeader(headername
) {}
322 void SetHeader(const wxString
& header
)
323 { m_strHeader
=header
; }
324 void SetName(const wxString
& name
)
326 void SetAvailability(int nAvail
)
327 { m_nAvailability
=nAvail
; }
328 void SetParent(unsigned int k
, const wxString
& name
)
329 { m_parents
[k
]=name
; }
334 { return !m_strName
.IsEmpty() && !m_methods
.IsEmpty(); }
336 bool IsValidCtorForThisClass(const wxMethod
& m
) const;
337 bool IsValidDtorForThisClass(const wxMethod
& m
) const;
339 wxString
GetName() const
340 { return m_strName
; }
341 wxString
GetHeader() const
342 { return m_strHeader
; }
343 wxString
GetNameWithoutTemplate() const;
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(); }
352 int GetAvailability() const
353 { return m_nAvailability
; }
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(); }
363 void AddMethod(const wxMethod
& func
)
364 { m_methods
.Add(func
); }
366 void AddParent(const wxString
& parent
)//wxClass* parent)
367 { m_parents
.Add(parent
); }
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;
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;
378 // returns an array of pointers to the overloaded methods with the
380 wxMethodPtrArray
FindMethodsNamed(const wxString
& name
) const;
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;
387 // dumps all methods to the given output stream
388 void Dump(wxTextOutputStream
& stream
) const;
391 bool CheckConsistency() const;
395 wxString m_strHeader
;
396 wxMethodArray m_methods
;
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
;
404 // see the wxMethod::m_nAvailability field for more info
408 WX_DECLARE_OBJARRAY(wxClass
, wxClassArray
);
412 // ----------------------------------------------------------------------------
414 // ----------------------------------------------------------------------------
420 const wxClass
* FindClass(const wxString
& classname
) const
422 for (unsigned int i
=0; i
<m_classes
.GetCount(); i
++)
423 if (m_classes
[i
].GetName() == classname
)
424 return &m_classes
[i
];
428 void Dump(const wxString
& filename
);
430 const wxClassArray
& GetClasses() const
431 { return m_classes
; }
433 unsigned int GetClassesCount() const
434 { return m_classes
.GetCount(); }
436 unsigned int GetMethodCount() const
438 unsigned int methods
= 0;
439 for (unsigned i
=0; i
< m_classes
.GetCount(); i
++)
440 methods
+= m_classes
[i
].GetMethodCount();
444 // pass a full-path header filename:
445 wxClassPtrArray
FindClassesDefinedIn(const wxString
& headerfile
) const;
448 { /*wxPrint(".");*/ }
450 bool CheckParseResults() const;
453 wxClassArray m_classes
;
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
,
463 WX_DECLARE_STRING_HASH_MAP( wxString
, wxStringHashMap
);
466 typedef std::basic_string
<char> stlString
;
467 typedef std::map
<unsigned long, stlString
> wxTypeIdHashMap
;
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
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();
485 bool Parse(const wxString
& filename
);
486 bool ParseMethod(const wxXmlNode
*p
,
487 const wxTypeIdHashMap
& types
,
490 wxPortId
GetInterfacePort() const
493 wxString
GetInterfacePortName() const
494 { return wxPlatformInfo::GetPortIdName(m_portId
, false); }
497 // the port for which the gcc XML was generated
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
509 wxXmlDoxygenInterface() {}
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.
519 bool Parse(const wxString
& filename
);
520 bool ParseCompoundDefinition(const wxString
& filename
);
521 bool ParseMethod(const wxXmlNode
*, wxMethod
&, wxString
& header
);
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
; }
529 wxStringHashMap m_preproc
;
534 #endif // _XMLPARSER_H_