// defined in ifacecheck.cpp
extern bool g_verbose;
+// global variable:
+bool g_bLogEnabled = true;
+
// ----------------------------------------------------------------------------
m_strTypeClean.Replace("&", "");
m_strTypeClean.Replace("[]", "");
m_strTypeClean = m_strTypeClean.Strip(wxString::both);
+
+ // to avoid false errors types like wxStandardPaths and wxStandardPathsBase
+ // need to be considered as the same type
+ if (m_strTypeClean.EndsWith("Base"))
+ m_strTypeClean = m_strTypeClean.Left(m_strTypeClean.Len()-4);
+
+ // 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
}
bool wxType::IsOk() const
IsReference() == m.IsReference())
return true;
+ if (g_verbose)
+ LogMessage("Type '%s' does not match type '%s'", m_strType, m.m_strType);
+
return false;
}
void wxArgumentType::SetDefaultValue(const wxString& defval, const wxString& defvalForCmp)
{
- m_strDefaultValue=defval.Strip(wxString::both);
- m_strDefaultValueForCmp=defvalForCmp.Strip(wxString::both);
+ m_strDefaultValue = defval.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_strDefaultValue == "0u")
- m_strDefaultValue = "0";
+ if (m_strDefaultValueForCmp == "0u")
+ m_strDefaultValueForCmp = "0";
+
+ // fix for unicode strings:
+ m_strDefaultValueForCmp.Replace("\\000\\000\\000", "");
+
+ if (m_strDefaultValueForCmp.StartsWith("wxT(") &&
+ m_strDefaultValueForCmp.EndsWith(")"))
+ {
+ // get rid of the wxT() part
+ unsigned int len = m_strDefaultValueForCmp.Len();
+ m_strDefaultValueForCmp = m_strDefaultValueForCmp.Mid(4,len-5);
+ }
+
/*
if (IsPointer())
- m_strDefaultValue.Replace("0", "NULL");
+ m_strDefaultValueForCmp.Replace("0", "NULL");
else
- m_strDefaultValue.Replace("NULL", "0");
+ m_strDefaultValueForCmp.Replace("NULL", "0");
*/
-
- if (m_strDefaultValue.Contains("wxGetTranslation"))
- m_strDefaultValue = "_(TOFIX)"; // TODO: wxGetTranslation gives problems to gccxml
+ // 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
+
+ // ADHOC-FIX:
+ if (m_strDefaultValueForCmp.Contains("wxGetTranslation"))
+ m_strDefaultValueForCmp = "_(TOFIX)"; // TODO: wxGetTranslation gives problems to gccxml
}
bool wxArgumentType::operator==(const wxArgumentType& m) const
if ((const wxType&)(*this) != (const wxType&)m)
return false;
- const wxString& def1 = m_strDefaultValueForCmp.IsEmpty() ? m_strDefaultValue : m_strDefaultValueForCmp;
- const wxString& def2 = m.m_strDefaultValueForCmp.IsEmpty() ? m.m_strDefaultValue : m.m_strDefaultValueForCmp;
+ // ADHOC-FIX:
+ // default values for style attributes of wxWindow-derived classes in gccxml appear as raw
+ // numbers; avoid false positives in this case!
+ if (m_strArgName == m.m_strArgName && m_strArgName == "style" &&
+ (m_strDefaultValueForCmp.IsNumber() || m.m_strDefaultValueForCmp.IsNumber()))
+ return true;
- if (def1 != def2)
+ if (m_strDefaultValueForCmp != m.m_strDefaultValueForCmp)
{
// maybe the default values are numbers.
// in this case gccXML gives as default values things like '-0x0000001' instead of just '-1'.
// To handle these cases, we try to convert the default value strings to numbers:
long def1val, def2val;
- if (def1.ToLong(&def1val, 0 /* auto-detect */) &&
- def2.ToLong(&def2val, 0 /* auto-detect */))
+ if (m_strDefaultValueForCmp.ToLong(&def1val, 0 /* auto-detect */) &&
+ m.m_strDefaultValueForCmp.ToLong(&def2val, 0 /* auto-detect */))
{
if (def1val == def2val)
return true; // the default values match
}
+ if (g_verbose)
+ LogMessage("Argument type '%s = %s' has different default value from '%s = %s'",
+ m_strType, m_strDefaultValueForCmp, m.m_strType, m.m_strDefaultValueForCmp);
return false;
}
return true;
}
-bool wxMethod::operator==(const wxMethod& m) const
+bool wxMethod::MatchesExceptForAttributes(const wxMethod& m) const
{
if (GetReturnType() != m.GetReturnType() ||
- GetName() != m.GetName() ||
- IsConst() != m.IsConst() ||
- IsStatic() != m.IsStatic() ||
- IsVirtual() != m.IsVirtual() ||
- IsPureVirtual() != m.IsPureVirtual() ||
- IsDeprecated() != m.IsDeprecated())
+ GetName() != m.GetName())
return false;
- if (m_args.GetCount()!=m.m_args.GetCount())
+ if (m_args.GetCount()!=m.m_args.GetCount()) {
+ if (g_verbose)
+ LogMessage("Method '%s' has %d arguments while '%s' has %d arguments",
+ m_strName, m_args.GetCount(), m_strName, m.m_args.GetCount());
return false;
+ }
+ // compare argument types
for (unsigned int i=0; i<m_args.GetCount(); i++)
if (m_args[i] != m.m_args[i])
return false;
return true;
}
-wxString wxMethod::GetAsString(bool bWithArgumentNames) const
+bool wxMethod::operator==(const wxMethod& m) const
+{
+ // check attributes
+ if (IsConst() != m.IsConst() ||
+ IsStatic() != m.IsStatic() ||
+ IsVirtual() != m.IsVirtual() ||
+ IsPureVirtual() != m.IsPureVirtual() ||
+ IsDeprecated() != m.IsDeprecated() ||
+ GetAccessSpecifier() != m.GetAccessSpecifier())
+ return false;
+
+ // check everything else
+ return MatchesExceptForAttributes(m);
+}
+
+wxString wxMethod::GetAsString(bool bWithArgumentNames, bool bCleanDefaultValues,
+ bool bDeprecated, bool bAccessSpec) const
{
wxString ret;
+ // NOTE: for return and argument types, never use wxType::GetAsCleanString
+ // since in that way we'd miss important decorators like &,*,const etc
+
if (m_retType!=wxEmptyType)
ret += m_retType.GetAsString() + " ";
//else; this is a ctor or dtor
if (bWithArgumentNames && !name.IsEmpty())
ret += " " + name;
- const wxString& def = m_args[i].GetDefaultValue();
+ const wxString& def = bCleanDefaultValues ?
+ m_args[i].GetDefaultCleanValue() : m_args[i].GetDefaultValue();
if (!def.IsEmpty())
ret += " = " + def;
if (m_bVirtual || m_bPureVirtual)
ret = "virtual " + ret;
if (m_bPureVirtual)
- ret = ret + " = 0";
+ ret += " = 0";
+ if (m_bDeprecated && bDeprecated)
+ ret += " [deprecated]";
- // in doxygen headers we don't need wxDEPRECATED:
- //if (m_bDeprecated)
- // ret = "wxDEPRECATED( " + ret + " )";
+ if (bAccessSpec)
+ {
+ switch (m_access)
+ {
+ case wxMAS_PUBLIC:
+ ret += " [public]";
+ break;
+ case wxMAS_PROTECTED:
+ ret += " [protected]";
+ break;
+ case wxMAS_PRIVATE:
+ ret += " [private]";
+ break;
+ }
+ }
return ret;
}
LogError("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--;
}
return true;
return NULL;
}
-wxMethodPtrArray wxClass::FindMethodNamed(const wxString& name) const
+wxMethodPtrArray wxClass::FindMethodsNamed(const wxString& name) const
{
wxMethodPtrArray ret;
// wxXmlGccInterface helper declarations
// ----------------------------------------------------------------------------
+// or-able flags for a toResolveTypeItem->attrib:
#define ATTRIB_CONST 1
#define ATTRIB_REFERENCE 2
#define ATTRIB_POINTER 4
toResolveTypeItem(unsigned int refID, unsigned int attribint)
: ref(refID), attribs(attribint) {}
- unsigned long ref, attribs;
+ unsigned long ref, // the referenced type's ID
+ attribs; // the attributes of this reference
};
#if 1
bool getID(unsigned long *id, const wxStringCharType* str)
{
wxStringCharType *end;
-#if wxUSE_UNICODE_UTF8
- unsigned long val = strtoul(str+1, &end, GCCXML_BASE);
-#else
+#if wxUSE_UNICODE_WCHAR
unsigned long val = wcstoul(str+1, &end, GCCXML_BASE);
+#else
+ unsigned long val = strtoul(str+1, &end, GCCXML_BASE);
#endif
// return true only if scan was stopped by the terminating NUL and
// in nodes like <Class> ones... i.e. numeric values separed by " _" token
bool getMemberIDs(wxClassMemberIdHashMap* map, wxClass* p, const wxStringCharType* str)
{
-#if wxUSE_UNICODE_UTF8
- size_t len = strlen(str);
-#else
+#if wxUSE_UNICODE_WCHAR
size_t len = wcslen(str);
+#else
+ size_t len = strlen(str);
#endif
if (len == 0 || str[0] != '_')
while (curpos < end)
{
// curpos always points to the underscore of the next token to parse:
-#if wxUSE_UNICODE_UTF8
- unsigned long id = strtoul(curpos+1, &nexttoken, GCCXML_BASE);
-#else
+#if wxUSE_UNICODE_WCHAR
unsigned long id = wcstoul(curpos+1, &nexttoken, GCCXML_BASE);
+#else
+ unsigned long id = strtoul(curpos+1, &nexttoken, GCCXML_BASE);
#endif
if ( *nexttoken != ' ' || errno == ERANGE || errno == EINVAL )
return false;
wxClassMemberIdHashMap members;
wxTypeIdHashMap types;
wxTypeIdHashMap files;
+ wxTypeIdHashMap typedefs;
// prealloc quite a lot of memory!
m_classes.Alloc(ESTIMATED_NUM_CLASSES);
// register this class also as possible return/argument type:
types[id] = cname;
}
+ else if (n == "Typedef")
+ {
+ unsigned long typeId = 0;
+ if (!getID(&typeId, child->GetAttribute("type"))) {
+ LogError("Invalid type for node %s: %s", n, child->GetAttribute("type"));
+ return false;
+ }
+
+ // this typedef node tell us that every type referenced with the
+ // "typeId" ID should be called with another name:
+ wxString name = child->GetAttribute("name");
+
+ // save this typedef in a separate hashmap...
+ typedefs[typeId] = name;
+
+ types[id] = name;
+ }
else if (n == "PointerType" || n == "ReferenceType" ||
n == "CvQualifiedType" || n == "ArrayType")
{
}
if (argstr.Len() > 0)
- argstr = argstr.Left(argstr.Len()-2);
+ argstr = argstr.Left(argstr.Len()-2); // remove final comma
// these nodes make reference to other types... we'll resolve them later
//toResolveTypes[id] = toResolveTypeItem(ret, 0);
- types[id] = child->GetAttribute("returns") + "(" + argstr + ")";
+ //types[id] = child->GetAttribute("returns") + "(" + argstr + ")";
+
+ types[id] = "TOFIX"; // typically this type will be "fixed" thanks
+ // to a typedef later...
}
else if (n == "File")
{
}
// some nodes with IDs referenced by methods as return/argument types, do reference
- // in turn o ther nodes (see PointerType, ReferenceType and CvQualifierType above);
+ // in turn other nodes (see PointerType, ReferenceType and CvQualifierType above);
// thus we need to resolve their name iteratively:
while (toResolveTypes.size()>0)
{
newtype = newtype + "[]";
// add the resolved type to the list of "primary" types
- types[id] = newtype;
+ if (newtype.Contains("TOFIX") && typedefs[id] != "")
+ types[id] = typedefs[id]; // better use a typedef for this type!
+ else
+ types[id] = newtype;
// this one has been resolved; erase it through its iterator!
toResolveTypes.erase(i);
}
else
{
- LogError("Cannot solve '%s' reference type!", referenced);
+ LogError("Cannot solve '%d' reference type!", referenced);
return false;
}
}
child = doc.GetRoot()->GetChildren();
while (child)
{
- wxString n = child->GetName();
+ wxString n = child->GetName(), acc = child->GetAttribute("access");
- // only register public methods
- if (child->GetAttribute("access") == "public" &&
+ // only register public&protected methods
+ if ((acc == "public" || acc == "protected") &&
(n == "Method" || n == "Constructor" || n == "Destructor" || n == "OperatorMethod"))
{
unsigned long id = 0;
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'",
newfunc.GetName(), p->GetName());
return false;
}
- argtypes.Add(wxArgumentType(idx->second, arg->GetAttribute("default")));
+ argtypes.Add(wxArgumentType(idx->second,
+ arg->GetAttribute("default"),
+ arg->GetAttribute("name")));
}
arg = arg->GetNext();
m.SetPureVirtual(p->GetAttribute("pure_virtual") == "1");
m.SetDeprecated(p->GetAttribute("attributes") == "deprecated");
+ // decode access specifier
+ if (p->GetAttribute("access") == "public")
+ m.SetAccessSpecifier(wxMAS_PUBLIC);
+ else if (p->GetAttribute("access") == "protected")
+ m.SetAccessSpecifier(wxMAS_PROTECTED);
+ else if (p->GetAttribute("access") == "private")
+ m.SetAccessSpecifier(wxMAS_PRIVATE);
+
if (!m.IsOk()) {
LogError("The prototype '%s' is not valid!", m.GetAsString());
return false;
wxXmlNode *subchild = child->GetChildren();
while (subchild)
{
+ wxString kind = subchild->GetAttribute("kind");
+
+ // parse only public&protected functions:
if (subchild->GetName() == "sectiondef" &&
- subchild->GetAttribute("kind") == "public-func")
+ (kind == "public-func" || kind == "protected-func"))
{
wxXmlNode *membernode = subchild->GetChildren();
return false;
}
+ if (kind == "public-func")
+ m.SetAccessSpecifier(wxMAS_PUBLIC);
+ else if (kind == "protected-func")
+ m.SetAccessSpecifier(wxMAS_PROTECTED);
+ else if (kind == "private-func")
+ m.SetAccessSpecifier(wxMAS_PRIVATE);
+
if (absoluteFile.IsEmpty())
absoluteFile = header;
else if (header != absoluteFile)