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