add pure virtual function parsing; give more informative warnings; fix the initial line to delete when in modify mode

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@52769 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Francesco Montorsi
2008-03-24 18:44:46 +00:00
parent e4f1d811cc
commit a7be99c803
3 changed files with 93 additions and 37 deletions

View File

@@ -195,27 +195,20 @@ int IfaceCheckApp::CompareClasses(const wxClass* iface, const wxClassPtrArray& a
searchedclasses += "/" + api[j]->GetName(); searchedclasses += "/" + api[j]->GetName();
searchedclasses.Remove(0, 1); searchedclasses.Remove(0, 1);
// shorten the name of the header so the log file is more readable // shorten the name of the header so the log file is more readable
wxString header = iface->GetHeader().AfterLast('/'); wxString header = iface->GetHeader().AfterLast('/');
for (unsigned int i=0; i<iface->GetMethodCount(); i++) for (unsigned int i=0; i<iface->GetMethodCount(); i++)
{ {
const wxMethod& m = iface->GetMethod(i); const wxMethod& m = iface->GetMethod(i);
const wxString& tofind = m.GetAsString();
int matches = 0; int matches = 0;
// search in the methods of the api classes provided // search in the methods of the api classes provided
for (unsigned int j=0; j<api.GetCount(); j++) for (unsigned int j=0; j<api.GetCount(); j++)
{ {
real = api[j]->FindMethod(m); real = api[j]->FindMethod(m);
if (real) { if (real)
matches++; // there is a real matching prototype! It's ok!
// there is a matching prototype! It's ok!
//LogMessage("the doxygen method '%s' has a match in the real interface of '%s'!",
// tofind, api[j]->GetName());
matches++;
}
} }
if (matches == 0) if (matches == 0)
@@ -232,33 +225,54 @@ int IfaceCheckApp::CompareClasses(const wxClass* iface, const wxClassPtrArray& a
WX_APPEND_ARRAY(overloads, results); WX_APPEND_ARRAY(overloads, results);
} }
if (overloads.GetCount()>1) if (overloads.GetCount()==0)
{ {
// TODO: decide which of these overloads is the most "similar" to m LogMessage("%s: real '%s' class has no method '%s'",
// and eventually modify it header, searchedclasses, m.GetAsString());
LogWarning("%s: there are %d overloads of method '%s' in the classes '%s' " // we've found no overloads
"all with different signatures; manual fix is required",
header, overloads.GetCount(), tofind, searchedclasses);
}
else if (overloads.GetCount() == 1)
{
wxString tmp;
if (m_modify) tmp = "; fixing it...";
LogWarning("%s: the method '%s' of classes '%s' has a different signature%s",
header, tofind, searchedclasses, tmp);
count++;
// try to modify it!
if (m_modify)
FixMethod(iface->GetHeader(), &m, overloads[0]);
} }
else else
{ {
LogMessage("%s: real '%s' class has no method '%s'", // first, output a warning
header, searchedclasses, tofind); wxString warning = header;
count++; // count this type of warnings if (overloads.GetCount()>1)
warning += wxString::Format(": in the real headers there are %d overloads of '%s' for "
"'%s' all with different signatures:\n",
overloads.GetCount(), m.GetName(), searchedclasses);
else
warning += wxString::Format(": in the real headers there is a method '%s' for '%s'"
" but has different signature:\n",
m.GetName(), searchedclasses);
warning += "\tdoxy header: " + m.GetAsString();
for (unsigned int j=0; j<overloads.GetCount(); j++)
warning += "\n\treal header: " + overloads[j]->GetAsString();
wxPrint(warning + "\n");
count++;
if (overloads.GetCount()>1)
{
// TODO: decide which of these overloads is the most "similar" to m
// and eventually modify it
if (m_modify)
wxPrint("\tmanual fix is required\n");
}
else
{
wxASSERT(overloads.GetCount() == 1);
if (m_modify)
{
wxPrint("\tfixing it...\n");
// try to modify it!
FixMethod(iface->GetHeader(), &m, overloads[0]);
}
}
} }
count++;
} }
} }
@@ -283,11 +297,17 @@ void IfaceCheckApp::FixMethod(const wxString& header, const wxMethod* iface, con
return; return;
} }
if (!file.GetLine(end).Contains(iface->GetName())) {
LogWarning("invalid location info for method '%s': %d.",
iface->GetAsString(), iface->GetLocation());
return;
}
// find the start point of this prototype declaration: // find the start point of this prototype declaration:
int start = end; int start = end-1;
while (start > 0 && while (start > 0 &&
!file.GetLine(start).Contains(";") && !file.GetLine(start).Contains(";") &&
!file.GetLine(start).Contains("*/")) !file.GetLine(start).Contains("*/"))
start--; start--;
if (start <= 0) if (start <= 0)
@@ -297,6 +317,10 @@ void IfaceCheckApp::FixMethod(const wxString& header, const wxMethod* iface, con
return; return;
} }
// start-th line contains either the declaration of another prototype
// or the closing tag */ of a doxygen comment; start one line below
start++;
// remove the old prototype // remove the old prototype
for (int i=start; i<=end; i++) for (int i=start; i<=end; i++)
file.RemoveLine(start); // remove (end-start)-nth times the start-th line file.RemoveLine(start); // remove (end-start)-nth times the start-th line

View File

@@ -49,10 +49,30 @@ wxType wxEmptyType;
void wxType::SetFromString(const wxString& t) void wxType::SetFromString(const wxString& t)
{ {
m_strType = t.Strip(wxString::both); /*
TODO: optimize the following code writing a single function
which works at char-level and does everything in a single pass
*/
m_strType = t;
// [] is the same as * for gccxml // [] is the same as * for gccxml
m_strType.Replace("[]", "*"); m_strType.Replace("[]", "*");
m_strType.Replace("long int", "long"); // in wx typically we never write "long int", just "long"
// make sure the * and & operator always use the same spacing rules
// (to make sure GetAsString() output is always consistent)
m_strType.Replace("*", "* ");
m_strType.Replace("&", "& ");
m_strType.Replace(" *", "*");
m_strType.Replace(" &", "&");
while (m_strType.Contains(" "))
m_strType.Replace(" ", " "); // do it once again
m_strType.Replace(" ,", ",");
m_strType = m_strType.Strip(wxString::both);
} }
bool wxType::IsOk() const bool wxType::IsOk() const
@@ -106,7 +126,7 @@ bool wxMethod::IsOk() const
return false; return false;
// a function can't be both const and static or virtual and static! // a function can't be both const and static or virtual and static!
if ((m_bConst && m_bStatic) || (m_bVirtual && m_bStatic)) { 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); LogError("'%s' method can't be both const/static or virtual/static", m_strName);
return false; return false;
} }
@@ -149,6 +169,7 @@ bool wxMethod::operator==(const wxMethod& m) const
IsConst() != m.IsConst() || IsConst() != m.IsConst() ||
IsStatic() != m.IsStatic() || IsStatic() != m.IsStatic() ||
IsVirtual() != m.IsVirtual() || IsVirtual() != m.IsVirtual() ||
IsPureVirtual() != m.IsPureVirtual() ||
IsDeprecated() != m.IsDeprecated()) IsDeprecated() != m.IsDeprecated())
return false; return false;
@@ -189,8 +210,10 @@ wxString wxMethod::GetAsString() const
ret += " const"; ret += " const";
if (m_bStatic) if (m_bStatic)
ret = "static " + ret; ret = "static " + ret;
if (m_bVirtual) if (m_bVirtual || m_bPureVirtual)
ret = "virtual " + ret; ret = "virtual " + ret;
if (m_bPureVirtual)
ret = ret + " = 0";
// in doxygen headers we don't need wxDEPRECATED: // in doxygen headers we don't need wxDEPRECATED:
//if (m_bDeprecated) //if (m_bDeprecated)
@@ -213,6 +236,8 @@ void wxMethod::Dump(wxTextOutputStream& stream) const
stream << " STATIC"; stream << " STATIC";
if (IsVirtual()) if (IsVirtual())
stream << " VIRTUAL"; stream << " VIRTUAL";
if (IsPureVirtual())
stream << " PURE-VIRTUAL";
if (IsDeprecated()) if (IsDeprecated())
stream << " DEPRECATED"; stream << " DEPRECATED";
@@ -825,6 +850,7 @@ bool wxXmlGccInterface::ParseMethod(const wxXmlNode *p,
m.SetConst(p->GetAttribute("const") == "1"); m.SetConst(p->GetAttribute("const") == "1");
m.SetStatic(p->GetAttribute("static") == "1"); m.SetStatic(p->GetAttribute("static") == "1");
m.SetVirtual(p->GetAttribute("virtual") == "1"); m.SetVirtual(p->GetAttribute("virtual") == "1");
m.SetPureVirtual(p->GetAttribute("pure_virtual") == "1");
m.SetDeprecated(p->GetAttribute("attributes") == "deprecated"); m.SetDeprecated(p->GetAttribute("attributes") == "deprecated");
if (!m.IsOk()) { if (!m.IsOk()) {
@@ -1110,6 +1136,7 @@ bool wxXmlDoxygenInterface::ParseMethod(const wxXmlNode* p, wxMethod& m, wxStrin
m.SetConst(p->GetAttribute("const")=="yes"); m.SetConst(p->GetAttribute("const")=="yes");
m.SetStatic(p->GetAttribute("static")=="yes"); m.SetStatic(p->GetAttribute("static")=="yes");
m.SetVirtual(p->GetAttribute("virt")=="virtual"); m.SetVirtual(p->GetAttribute("virt")=="virtual");
m.SetPureVirtual(p->GetAttribute("virt")=="pure-virtual");
if (!m.IsOk()) { if (!m.IsOk()) {
LogError("The prototype '%s' is not valid!", m.GetAsString()); LogError("The prototype '%s' is not valid!", m.GetAsString());

View File

@@ -71,7 +71,7 @@ class wxMethod
{ {
public: public:
wxMethod() wxMethod()
{ m_bConst=m_bVirtual=m_bStatic=m_bDeprecated=false; m_nLine=-1; } { m_bConst=m_bVirtual=m_bPureVirtual=m_bStatic=m_bDeprecated=false; m_nLine=-1; }
wxMethod(const wxType& rettype, const wxString& name, wxMethod(const wxType& rettype, const wxString& name,
const wxTypeArray& arguments, const wxArrayString& defaults, const wxTypeArray& arguments, const wxArrayString& defaults,
@@ -105,6 +105,8 @@ public: // getters
{ return m_bStatic; } { return m_bStatic; }
bool IsVirtual() const bool IsVirtual() const
{ return m_bVirtual; } { return m_bVirtual; }
bool IsPureVirtual() const
{ return m_bPureVirtual; }
bool IsOk() const; bool IsOk() const;
bool IsCtor() const bool IsCtor() const
@@ -129,6 +131,8 @@ public: // setters
{ m_bStatic=c; } { m_bStatic=c; }
void SetVirtual(bool c = true) void SetVirtual(bool c = true)
{ m_bVirtual=c; } { m_bVirtual=c; }
void SetPureVirtual(bool c = true)
{ m_bPureVirtual=c; }
void SetDeprecated(bool c = true) void SetDeprecated(bool c = true)
{ m_bDeprecated=c; } { m_bDeprecated=c; }
void SetLocation(int lineNumber) void SetLocation(int lineNumber)
@@ -150,6 +154,7 @@ protected:
bool m_bConst; bool m_bConst;
bool m_bStatic; bool m_bStatic;
bool m_bVirtual; bool m_bVirtual;
bool m_bPureVirtual;
bool m_bDeprecated; bool m_bDeprecated;
int m_nLine; int m_nLine;
}; };