// for all others, include the necessary headers
#ifndef WX_PRECOMP
+ #include "wx/crt.h"
#endif
#include "wx/xml/xml.h"
which works at char-level and does everything in a single pass
*/
+ // clean the type string
+ // ---------------------
+
m_strType = t;
// [] is the same as * for gccxml
m_strType.Replace("[]", "*");
m_strType.Replace("long int", "long"); // in wx typically we never write "long int", just "long"
+ m_strType.Replace("long unsigned int", "unsigned long");
+ m_strType.Replace("short unsigned int", "unsigned short");
// make sure the * and & operator always use the same spacing rules
// (to make sure GetAsString() output is always consistent)
m_strType.Replace(" ,", ",");
+ // ADHOC-FIX
+ m_strType.Replace("_wxArraywxArrayStringBase", "wxString");
+ m_strType.Replace("ExitCode", "void*"); // used in wxThread stuff
+
m_strType = m_strType.Strip(wxString::both);
- // now set the clean version
- m_strTypeClean = m_strType;
+
+
+ // clean the type string (this time for the comparison)
+ // ----------------------------------------------------
+
+ m_strTypeClean = m_strType; // begin with the already-cleaned string
m_strTypeClean.Replace("const", "");
m_strTypeClean.Replace("static", "");
m_strTypeClean.Replace("*", "");
if (m_strTypeClean.EndsWith("Base"))
m_strTypeClean = m_strTypeClean.Left(m_strTypeClean.Len()-4);
+ // remove the namespace from the types; there's no problem of conflicts
+ // (except for templates) and this avoids tons of false warnings
+ if (m_strTypeClean.Contains("::") && !m_strTypeClean.Contains("<"))
+ m_strTypeClean = m_strTypeClean.Mid(m_strTypeClean.Find("::")+2);
+
// ADHOC-FIX:
- // doxygen likes to put wxDateTime:: in front of all wxDateTime enums;
- // fix this to avoid false positives
- m_strTypeClean.Replace("wxDateTime::", "");
- m_strTypeClean.Replace("wxStockGDI::", ""); // same story for some other classes
- m_strTypeClean.Replace("wxHelpEvent::", "");
+ m_strTypeClean.Replace("wxWindowID", "int");
}
bool wxType::IsOk() const
return true;
if (g_verbose)
- LogMessage("Type '%s' does not match type '%s'", m_strType, m.m_strType);
+ {
+ wxLogMessage("Type '%s' does not match type '%s'", m_strType, m.m_strType);
+ wxLogMessage(" => TypeClean %s / %s; IsConst %d / %d; IsStatic %d / %d; IsPointer %d / %d; IsReference %d / %d",
+ m_strTypeClean, m.m_strTypeClean, IsConst(), m.IsConst(),
+ IsStatic(), m.IsStatic(), IsPointer(), m.IsPointer(),
+ IsReference(), m.IsReference());
+ }
return false;
}
void wxArgumentType::SetDefaultValue(const wxString& defval, const wxString& defvalForCmp)
{
m_strDefaultValue = defval.Strip(wxString::both);
- m_strDefaultValueForCmp = defvalForCmp.IsEmpty() ? m_strDefaultValue : defvalForCmp.Strip(wxString::both);
+ m_strDefaultValueForCmp = defvalForCmp.IsEmpty() ?
+ m_strDefaultValue : defvalForCmp.Strip(wxString::both);
- // adjust aesthetic form of DefaultValue for the modify mode of ifacecheck:
- // we may need to write it out in an interface header
- if (m_strDefaultValue == "0u")
- m_strDefaultValue = "0";
- // in order to make valid&simple comparison on argument defaults,
- // we reduce some of the multiple forms in which the same things may appear
- // to a single form:
- if (m_strDefaultValueForCmp == "0u")
- m_strDefaultValueForCmp = "0";
+ // clean the default argument strings
+ // ----------------------------------
- m_strDefaultValue.Replace("0x000000001", "1");
- m_strDefaultValueForCmp.Replace("0x000000001", "1");
+ // Note: we adjust the aesthetic form of the m_strDefaultValue string for the "modify mode"
+ // of ifacecheck: we may need to write it out in an interface header
- // fix for unicode strings:
- m_strDefaultValue.Replace("\\000\\000\\000", "");
- m_strDefaultValueForCmp.Replace("\\000\\000\\000", "");
+ wxString *p = NULL;
+ for (int i=0; i<2; i++) // to avoid copying&pasting the code!
+ {
+ if (i == 0) p = &m_strDefaultValue;
+ if (i == 1) p = &m_strDefaultValueForCmp;
+
+ if (*p == "0u" || *p == "0l") *p = "0";
+
+ p->Replace("0x000000001", "1");
+ p->Replace("\\000\\000\\000", ""); // fix for unicode strings:
+ p->Replace("\\011", "\\t");
+ p->Replace("e+0", "");
+ p->Replace("2147483647", "__INT_MAX__");
+
+ // ADHOC-FIX: for wxConv* default values
+ p->Replace("wxConvAuto(wxFONTENCODING_DEFAULT)", "wxConvAuto()");
+ p->Replace("wxGet_wxConvUTF8()", "wxConvUTF8");
+ p->Replace("wxGet_wxConvLocal()", "wxConvLocal");
+ }
+
+
+ // clean ONLY the default argument string specific for comparison
+ // --------------------------------------------------------------
if (m_strDefaultValueForCmp.StartsWith("wxT(") &&
m_strDefaultValueForCmp.EndsWith(")"))
m_strDefaultValueForCmp = m_strDefaultValueForCmp.Mid(4,len-5);
}
-/*
- if (IsPointer())
- m_strDefaultValueForCmp.Replace("0", "NULL");
- else
- m_strDefaultValueForCmp.Replace("NULL", "0");
-*/
// ADHOC-FIX:
// doxygen likes to put wxDateTime:: in front of all wxDateTime enums;
// fix this to avoid false positives
m_strDefaultValueForCmp.Replace("wxDateTime::", "");
m_strDefaultValueForCmp.Replace("wxStockGDI::", ""); // same story for some other classes
m_strDefaultValueForCmp.Replace("wxHelpEvent::", ""); // same story for some other classes
-
- m_strDefaultValueForCmp.Replace("wxGet_wxConvLocal()", "wxConvLocal");
-
m_strDefaultValueForCmp.Replace("* GetColour(COLOUR_BLACK)", "*wxBLACK");
// ADHOC-FIX:
if ((const wxType&)(*this) != (const wxType&)m)
return false;
+ // check if the default values match
+ // ---------------------------------
+
+
// ADHOC-FIX:
// default values for style attributes of wxWindow-derived classes in gccxml appear as raw
// numbers; avoid false positives in this case!
(m.m_strDefaultValueForCmp.IsNumber() && m_strDefaultValueForCmp.StartsWith("wx")))
{
if (g_verbose)
- LogMessage("Supposing '%s' default value to be the same of '%s'...",
+ {
+ wxLogMessage("Supposing '%s' default value to be the same of '%s'...",
m_strDefaultValueForCmp, m.m_strDefaultValueForCmp);
+ }
return true;
}
}
+ else if (m_strTypeClean == "float" || m_strTypeClean == "double")
+ // gccXML translates the default floating values in a hardly usable
+ // format; e.g. 25.2 => 2.51999999999999992894572642398998141288757324219e+1
+ // we avoid check on these...
+ return true;
if (m_strDefaultValueForCmp != m.m_strDefaultValueForCmp)
{
}
if (g_verbose)
- LogMessage("Argument type '%s = %s' has different default value from '%s = %s'",
+ {
+ wxLogMessage("Argument type '%s = %s' has different default value from '%s = %s'",
m_strType, m_strDefaultValueForCmp, m.m_strType, m.m_strDefaultValueForCmp);
+ }
return false;
}
// NOTE: m_retType can be a wxEmptyType, and means that this method
// is a ctor or a dtor.
if (!m_retType.IsOk() && m_retType!=wxEmptyType) {
- LogError("'%s' method has invalid return type: %s", m_retType.GetAsString());
+ wxLogError("'%s' method has invalid return type: %s", m_retType.GetAsString());
return false;
}
// a function can't be both const and static or virtual and static!
if ((m_bConst && m_bStatic) || ((m_bVirtual || m_bPureVirtual) && m_bStatic)) {
- LogError("'%s' method can't be both const/static or virtual/static", m_strName);
+ wxLogError("'%s' method can't be both const/static or virtual/static", m_strName);
return false;
}
for (unsigned int i=0; i<m_args.GetCount(); i++)
if (!m_args[i].IsOk()) {
- LogError("'%s' method has invalid %d-th argument type: %s",
+ wxLogError("'%s' method has invalid %d-th argument type: %s",
m_strName, i+1, m_args[i].GetAsString());
return false;
}
for (unsigned int i=1; i<m_args.GetCount(); i++)
{
if (previousArgHasDefault && !m_args[i].HasDefaultValue()) {
- LogError("'%s' method has %d-th argument which has no default value "
+ wxLogError("'%s' method has %d-th argument which has no default value "
"(while the previous one had one!)",
m_strName, i+1);
return false;
{
if (GetReturnType() != m.GetReturnType() ||
GetName() != m.GetName())
+ {
+ if (g_verbose)
+ {
+ wxLogMessage("The method '%s' does not match method '%s'; different names/rettype", GetName(), m.GetName());
+ }
return false;
+ }
if (m_args.GetCount()!=m.m_args.GetCount()) {
if (g_verbose)
- LogMessage("Method '%s' has %d arguments while '%s' has %d arguments",
+ {
+ wxLogMessage("Method '%s' has %d arguments while '%s' has %d arguments",
m_strName, m_args.GetCount(), m_strName, m.m_args.GetCount());
+ }
return false;
}
return true;
}
+bool wxMethod::ActsAsDefaultCtor() const
+{
+ if (!IsCtor())
+ return false;
+
+ for (unsigned int i=0; i<m_args.GetCount(); i++)
+ if (!m_args[i].HasDefaultValue())
+ return false;
+
+ return true;
+}
+
bool wxMethod::operator==(const wxMethod& m) const
{
// check attributes
IsPureVirtual() != m.IsPureVirtual() ||
IsDeprecated() != m.IsDeprecated() ||
GetAccessSpecifier() != m.GetAccessSpecifier())
+ {
+ if (g_verbose)
+ {
+ wxLogMessage("The method '%s' does not match method '%s'; different attributes", GetName(), m.GetName());
+ }
+
return false;
+ }
// check everything else
return MatchesExceptForAttributes(m);
for (unsigned int j=0; j<m_methods.GetCount(); j++)
if (i!=j && m_methods[i] == m_methods[j])
{
- LogError("class %s has two methods with the same prototype: '%s'",
+ wxLogError("class %s has two methods with the same prototype: '%s'",
m_strName, m_methods[i].GetAsString());
return false;
- ((wxClass*)this)->m_methods.RemoveAt(j);
- j--;
+
+ // fix the problem?
+ //((wxClass*)this)->m_methods.RemoveAt(j);
+ //j--;
}
return true;
{
// ignore non-wx-classes parents
// AD-HOC FIX: discard wxScrolledT_Helper parent as it always gives errors
- if (m_parents[i].StartsWith("wx") || m_parents[i] == "wxScrolledT_Helper")
+ if (m_parents[i].StartsWith("wx") && m_parents[i] != "wxScrolledT_Helper")
{
const wxClass *parent = allclasses->FindClass(m_parents[i]);
if (!parent) {
wxLogError("Could not find parent '%s' of class '%s'...",
- m_parents[i], GetName());
+ m_parents[i], GetName());
return false;
}
for (unsigned int i=0; i<m_parents.GetCount(); i++)
{
// AD-HOC FIX: discard wxScrolledT_Helper parent as it always gives errors
- if (m_parents[i].StartsWith("wx") || m_parents[i] == "wxScrolledT_Helper")
+ if (m_parents[i].StartsWith("wx") && m_parents[i] != "wxScrolledT_Helper")
{
const wxClass *parent = allclasses->FindClass(m_parents[i]);
if (!parent) {
wxLogError("Could not find parent '%s' of class '%s'...",
- m_parents[i], GetName());
+ m_parents[i], GetName());
return false;
}
// dump the classes in alphabetical order
wxSortedClassArray sorted(CompareWxClassObjects);
sorted.Alloc(m_classes.GetCount());
- for (unsigned int i=0; i<m_classes.GetCount(); i++)
+
+ unsigned i;
+ for (i=0; i<m_classes.GetCount(); i++)
sorted.Add(&m_classes[i]);
// now they have been sorted
- for (unsigned int i=0; i<sorted.GetCount(); i++)
+ for (i=0; i<sorted.GetCount(); i++)
sorted[i]->Dump(apiout);
}
-bool wxXmlInterface::CheckParseResults() const
+bool wxXmlInterface::CheckConsistency() const
{
// this check can be quite slow, so do it only for debug releases:
//#ifdef __WXDEBUG__
for (unsigned int i=0; i<m_classes.GetCount(); i++)
+ {
if (!m_classes[i].CheckConsistency())
return false;
+
+ for (unsigned int j=0; j<m_classes.GetCount(); j++)
+ if (i!=j && m_classes[i].GetName() == m_classes[j].GetName())
+ {
+ wxLogError("two classes have the same name: %s",
+ m_classes[i].GetName());
+ return false;
+ }
+ }
//#endif
return true;
// utility to parse gccXML ID values;
// this function is equivalent to wxString(str).Mid(1).ToULong(&id, GCCXML_BASE)
// but is a little bit faster
-bool getID(unsigned long *id, const wxStringCharType* str)
+bool getID(unsigned long *id, const wxString& str)
{
+ const wxStringCharType * const start = str.wx_str()+1;
wxStringCharType *end;
#if wxUSE_UNICODE_WCHAR
- unsigned long val = wcstoul(str+1, &end, GCCXML_BASE);
+ unsigned long val = wcstoul(start, &end, GCCXML_BASE);
#else
- unsigned long val = strtoul(str+1, &end, GCCXML_BASE);
+ unsigned long val = strtoul(start, &end, GCCXML_BASE);
#endif
// return true only if scan was stopped by the terminating NUL and
// if the string was not empty to start with and no under/overflow
// occurred:
- if ( *end != '\0' || end == str+1 || errno == ERANGE || errno == EINVAL )
+ if ( *end != '\0' || end == start || errno == ERANGE || errno == EINVAL )
return false;
*id = val;
}
// utility specialized to parse efficiently the gccXML list of IDs which occur
-// in nodes like <Class> ones... i.e. numeric values separed by " _" token
-bool getMemberIDs(wxClassMemberIdHashMap* map, wxClass* p, const wxStringCharType* str)
+// in nodes like <Class> ones... i.e. numeric values separated by " _" token
+bool getMemberIDs(wxClassMemberIdHashMap* map, wxClass* p, const wxString& str)
{
+ const wxStringCharType * const start = str.wx_str();
#if wxUSE_UNICODE_WCHAR
- size_t len = wcslen(str);
+ size_t len = wcslen(start);
#else
- size_t len = strlen(str);
+ size_t len = strlen(start);
#endif
- if (len == 0 || str[0] != '_')
+ if (len == 0 || start[0] != '_')
return false;
- const wxStringCharType *curpos = str,
- *end = str + len;
+ const wxStringCharType *curpos = start,
+ *end = start + len;
wxStringCharType *nexttoken;
while (curpos < end)
wxXmlNode *child;
int nodes = 0;
- LogMessage("Parsing %s...", filename);
+ wxLogMessage("Parsing %s...", filename);
if (!doc.Load(filename)) {
- LogError("can't load %s", filename);
+ wxLogError("can't load %s", filename);
return false;
}
// start processing the XML file
if (doc.GetRoot()->GetName() != "GCC_XML") {
- LogError("invalid root node for %s", filename);
+ wxLogError("invalid root node for %s", filename);
return false;
}
if (old)
{
- LogError("The version of GCC-XML used for the creation of %s is too old; "
+ wxLogError("The version of GCC-XML used for the creation of %s is too old; "
"the cvs_revision attribute of the root node reports '%s', "
"minimal required is 1.%d.", filename, version, MIN_REVISION);
return false;
// NOTE: <File> nodes can have an id == "f0"...
- LogError("Invalid id for node %s: %s", n, child->GetAttribute("id"));
+ wxLogError("Invalid id for node %s: %s", n, child->GetAttribute("id"));
return false;
}
{
wxString cname = child->GetAttribute("name");
if (cname.IsEmpty()) {
- LogError("Invalid empty name for '%s' node", n);
+ wxLogError("Invalid empty name for '%s' node", n);
return false;
}
if (ids.IsEmpty())
{
if (child->GetAttribute("incomplete") != "1") {
- LogError("Invalid member IDs for '%s' class node: %s",
+ wxLogError("Invalid member IDs for '%s' class node: %s",
cname, child->GetAttribute("id"));
return false;
}
{
// decode the non-empty list of IDs:
if (!getMemberIDs(&members, newClass, ids)) {
- LogError("Invalid member IDs for '%s' class node: %s",
+ wxLogError("Invalid member IDs for '%s' class node: %s",
cname, child->GetAttribute("id"));
return false;
}
{
unsigned long typeId = 0;
if (!getID(&typeId, child->GetAttribute("type"))) {
- LogError("Invalid type for node %s: %s", n, child->GetAttribute("type"));
+ wxLogError("Invalid type for node %s: %s", n, child->GetAttribute("type"));
return false;
}
{
unsigned long type = 0;
if (!getID(&type, child->GetAttribute("type")) || type == 0) {
- LogError("Invalid type for node %s: %s", n, child->GetAttribute("type"));
+ wxLogError("Invalid type for node %s: %s", n, child->GetAttribute("type"));
return false;
}
else if (n == "File")
{
if (!child->GetAttribute("id").StartsWith("f")) {
- LogError("Unexpected file ID: %s", child->GetAttribute("id"));
+ wxLogError("Unexpected file ID: %s", child->GetAttribute("id"));
return false;
}
// they're never used as return/argument types by wxWidgets methods
if (g_verbose)
- LogWarning("Type node '%s' with ID '%s' does not have name attribute",
+ {
+ wxLogWarning("Type node '%s' with ID '%s' does not have name attribute",
n, child->GetAttribute("id"));
+ }
types[id] = "TOFIX";
}
while (toResolveTypes.size()>0)
{
if (g_verbose)
- LogMessage("%d types were collected; %d types need yet to be resolved...",
+ {
+ wxLogMessage("%d types were collected; %d types need yet to be resolved...",
types.size(), toResolveTypes.size());
+ }
for (wxToResolveTypeHashMap::iterator i = toResolveTypes.begin();
i != toResolveTypes.end();)
}
else
{
- LogError("Cannot solve '%d' reference type!", referenced);
+ wxLogError("Cannot solve '%d' reference type!", referenced);
return false;
}
}
}
// resolve header names
- for (unsigned int i=0; i<m_classes.GetCount(); i++)
+ unsigned i;
+ for (i=0; i<m_classes.GetCount(); i++)
{
unsigned long fileID = 0;
if (!getID(&fileID, m_classes[i].GetHeader()) || fileID == 0) {
- LogError("invalid header id: %s", m_classes[i].GetHeader());
+ wxLogError("invalid header id: %s", m_classes[i].GetHeader());
return false;
}
if (idx == files.end())
{
// this is an error!
- LogError("couldn't find file ID '%s'", m_classes[i].GetHeader());
+ wxLogError("couldn't find file ID '%s'", m_classes[i].GetHeader());
}
else
m_classes[i].SetHeader(idx->second);
}
// resolve parent names
- for (unsigned int i=0; i<m_classes.GetCount(); i++)
+ for (i=0; i<m_classes.GetCount(); i++)
{
for (unsigned int k=0; k<m_classes[i].GetParentCount(); k++)
{
unsigned long id;
if (!getID(&id, m_classes[i].GetParent(k))) {
- LogError("invalid parent class ID for '%s'", m_classes[i].GetName());
+ wxLogError("invalid parent class ID for '%s'", m_classes[i].GetName());
return false;
}
if (idx == types.end())
{
// this is an error!
- LogError("couldn't find parent class ID '%d'", id);
+ wxLogError("couldn't find parent class ID '%d'", id);
}
else
// replace k-th parent with its true name:
{
unsigned long id = 0;
if (!getID(&id, child->GetAttribute("id"))) {
- LogError("invalid ID for node '%s' with ID '%s'", n, child->GetAttribute("id"));
+ wxLogError("invalid ID for node '%s' with ID '%s'", n, child->GetAttribute("id"));
return false;
}
// this <Method> node is a method of the i-th class!
wxMethod newfunc;
if (!ParseMethod(child, types, newfunc)) {
- LogError("The method '%s' could not be added to class '%s'",
+ wxLogError("The method '%s' could not be added to class '%s'",
child->GetAttribute("demangled"), p->GetName());
return false;
}
// do some additional check that we can do only here:
if (newfunc.IsCtor() && !p->IsValidCtorForThisClass(newfunc)) {
- LogError("The method '%s' does not seem to be a ctor for '%s'",
+ wxLogError("The method '%s' does not seem to be a ctor for '%s'",
newfunc.GetName(), p->GetName());
return false;
}
if (newfunc.IsDtor() && !p->IsValidDtorForThisClass(newfunc)) {
- LogError("The method '%s' does not seem to be a dtor for '%s'",
+ wxLogError("The method '%s' does not seem to be a dtor for '%s'",
newfunc.GetName(), p->GetName());
return false;
}
if ((++nodes%PROGRESS_RATE)==0) ShowProgress();
}
- if (!CheckParseResults())
- return false;
+ if (!CheckConsistency())
+ return false; // the check failed
return true;
}
if (!getID(&retid, p->GetAttribute("returns")) || retid == 0)
{
if (p->GetName() != "Destructor" && p->GetName() != "Constructor") {
- LogError("Empty return ID for method '%s', with ID '%s'",
+ wxLogError("Empty return ID for method '%s', with ID '%s'",
name, p->GetAttribute("id"));
return false;
}
{
wxTypeIdHashMap::const_iterator retidx = types.find(retid);
if (retidx == types.end()) {
- LogError("Could not find return type ID '%s'", retid);
+ wxLogError("Could not find return type ID '%s'", retid);
return false;
}
ret = wxType(retidx->second);
if (!ret.IsOk()) {
- LogError("Invalid return type '%s' for method '%s', with ID '%s'",
+ wxLogError("Invalid return type '%s' for method '%s', with ID '%s'",
retidx->second, name, p->GetAttribute("id"));
return false;
}
{
unsigned long id = 0;
if (!getID(&id, arg->GetAttribute("type")) || id == 0) {
- LogError("Invalid argument type ID '%s' for method '%s' with ID %s",
+ wxLogError("Invalid argument type ID '%s' for method '%s' with ID %s",
arg->GetAttribute("type"), name, p->GetAttribute("id"));
return false;
}
wxTypeIdHashMap::const_iterator idx = types.find(id);
if (idx == types.end()) {
- LogError("Could not find argument type ID '%s'", id);
+ wxLogError("Could not find argument type ID '%s'", id);
return false;
}
// NOTE: gccxml is smart enough to mark as virtual those functions
// which are declared virtual in base classes but don't have
- // the "virtual" keyword explicitely indicated in the derived
+ // the "virtual" keyword explicitly indicated in the derived
// classes... so we don't need any further logic for virtuals
m.SetVirtual(p->GetAttribute("virtual") == "1");
m.SetAccessSpecifier(wxMAS_PRIVATE);
if (!m.IsOk()) {
- LogError("The prototype '%s' is not valid!", m.GetAsString());
+ wxLogError("The prototype '%s' is not valid!", m.GetAsString());
return false;
}
else if (ref->GetType() == wxXML_TEXT_NODE)
text += ref->GetContent();
else
- LogWarning("Unexpected node type while getting text from '%s' node", n->GetName());
+ wxLogWarning("Unexpected node type while getting text from '%s' node", n->GetName());
ref = ref->GetNext();
}
for (unsigned int i=0; i < ports.GetCount(); i++)
{
if (!ports[i].StartsWith("wx")) {
- LogError("unexpected port ID '%s'", ports[i]);
+ wxLogError("unexpected port ID '%s'", ports[i]);
return false;
}
wxXmlDocument index;
wxXmlNode *compound;
- LogMessage("Parsing %s...", filename);
+ wxLogMessage("Parsing %s...", filename);
if (!index.Load(filename)) {
- LogError("can't load %s", filename);
+ wxLogError("can't load %s", filename);
return false;
}
// start processing the index:
if (index.GetRoot()->GetName() != "doxygenindex") {
- LogError("invalid root node for %s", filename);
+ wxLogError("invalid root node for %s", filename);
return false;
}
}
//wxPrint("\n");
- if (!CheckParseResults())
- return false;
+ if (!CheckConsistency())
+ return false; // the check failed
return true;
}
int nodes = 0;
if (g_verbose)
- LogMessage("Parsing %s...", filename);
+ {
+ wxLogMessage("Parsing %s...", filename);
+ }
if (!doc.Load(filename)) {
- LogError("can't load %s", filename);
+ wxLogError("can't load %s", filename);
return false;
}
// start processing this compound definition XML
if (doc.GetRoot()->GetName() != "doxygen") {
- LogError("invalid root node for %s", filename);
+ wxLogError("invalid root node for %s", filename);
return false;
}
wxXmlNode *subchild = child->GetChildren();
while (subchild)
{
- wxString kind = subchild->GetAttribute("kind");
-
- // parse only public&protected functions:
- if (subchild->GetName() == "sectiondef" &&
- (kind == "public-func" || kind == "protected-func"))
+ // NOTE: when documenting functions using the //@{ and //@}
+ // tags to create function groups, doxygen puts the
+ // contained methods into a "user-defined" section
+ // so we _must_ use the "prot" attribute to distinguish
+ // public/protected methods from private ones and cannot
+ // rely on the kind="public" attribute of <sectiondef>
+ if (subchild->GetName() == "sectiondef")
{
-
wxXmlNode *membernode = subchild->GetChildren();
while (membernode)
{
+ const wxString& accessSpec = membernode->GetAttribute("prot");
+
+ // parse only public&protected functions:
if (membernode->GetName() == "memberdef" &&
- membernode->GetAttribute("kind") == "function")
+ membernode->GetAttribute("kind") == "function" &&
+ (accessSpec == "public" || accessSpec == "protected"))
{
-
wxMethod m;
if (!ParseMethod(membernode, m, header)) {
- LogError("The method '%s' could not be added to class '%s'",
- m.GetName(), klass.GetName());
+ wxLogError("The method '%s' could not be added to class '%s'",
+ m.GetName(), klass.GetName());
return false;
}
- if (kind == "public-func")
+ if (accessSpec == "public")
m.SetAccessSpecifier(wxMAS_PUBLIC);
- else if (kind == "protected-func")
+ else if (accessSpec == "protected")
m.SetAccessSpecifier(wxMAS_PROTECTED);
- else if (kind == "private-func")
+ else if (accessSpec == "private")
m.SetAccessSpecifier(wxMAS_PRIVATE);
if (absoluteFile.IsEmpty())
absoluteFile = header;
else if (header != absoluteFile)
{
- LogError("The method '%s' is documented in a different "
- "file from others (which belong to '%s') ?",
- header, absoluteFile);
+ wxLogError("Found inconsistency in the XML file '%s': "
+ "the method '%s' is documented in the "
+ "file '%s' but the other methods of the same "
+ "class are documented in the file '%s'",
+ filename, m.GetName(), header, absoluteFile);
return false;
}
// add a new class
if (klass.IsOk())
+ {
m_classes.Add(klass);
+ }
else if (g_verbose)
- LogWarning("discarding class '%s' with %d methods...",
- klass.GetName(), klass.GetMethodCount());
+ {
+ wxLogWarning("discarding class '%s' with %d methods...",
+ klass.GetName(), klass.GetMethodCount());
+ }
}
child = child->GetNext();
}
if (typestr.IsEmpty()) {
- LogError("cannot find type node for a param in method '%s'", m.GetName());
+ wxLogError("cannot find type node for a param in method '%s'", m.GetName());
return false;
}
// NOTE: Doxygen is smart enough to mark as virtual those functions
// which are declared virtual in base classes but don't have
- // the "virtual" keyword explicitely indicated in the derived
+ // the "virtual" keyword explicitly indicated in the derived
// classes... so we don't need any further logic for virtuals
m.SetVirtual(p->GetAttribute("virt")=="virtual");
m.SetPureVirtual(p->GetAttribute("virt")=="pure-virtual");
if (!m.IsOk()) {
- LogError("The prototype '%s' is not valid!", m.GetAsString());
+ wxLogError("The prototype '%s' is not valid!", m.GetAsString());
return false;
}