further improve the automatic modify mode: wrap correctly inserted prototypes at comma boundaries, add @deprecated only if needed, update the locations of the methods below the fixed one
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@52816 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -324,34 +324,39 @@ void IfaceCheckApp::FixMethod(const wxString& header, const wxMethod* iface, con
|
|||||||
|
|
||||||
wxTextFile file;
|
wxTextFile file;
|
||||||
if (!file.Open(header)) {
|
if (!file.Open(header)) {
|
||||||
LogError("can't open the '%s' header file.", header);
|
LogError("\tcan't open the '%s' header file.", header);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLocation() returns the line where the last part of the prototype is placed:
|
// GetLocation() returns the line where the last part of the prototype is placed:
|
||||||
int end = iface->GetLocation()-1;
|
int end = iface->GetLocation()-1;
|
||||||
if (end <= 0 || end >= (int)file.GetLineCount()) {
|
if (end <= 0 || end >= (int)file.GetLineCount()) {
|
||||||
LogWarning("invalid location info for method '%s': %d.",
|
LogWarning("\tinvalid location info for method '%s': %d.",
|
||||||
iface->GetAsString(), iface->GetLocation());
|
iface->GetAsString(), iface->GetLocation());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file.GetLine(end).Contains(iface->GetName())) {
|
if (!file.GetLine(end).Contains(";")) {
|
||||||
LogWarning("invalid location info for method '%s': %d.",
|
LogWarning("\tinvalid location info for method '%s': %d.",
|
||||||
iface->GetAsString(), iface->GetLocation());
|
iface->GetAsString(), iface->GetLocation());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the start point of this prototype declaration:
|
// find the start point of this prototype declaration:
|
||||||
int start = end-1;
|
int start = end-1;
|
||||||
|
bool founddecl = false;
|
||||||
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)
|
founddecl |= file.GetLine(start).Contains(iface->GetName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start <= 0 || !founddecl)
|
||||||
{
|
{
|
||||||
LogError("can't find the beginning of the declaration of '%s' method in '%s' header",
|
LogError("\tcan't find the beginning of the declaration of '%s' method in '%s' header",
|
||||||
iface->GetAsString(), header);
|
iface->GetAsString(), header);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -366,13 +371,18 @@ void IfaceCheckApp::FixMethod(const wxString& header, const wxMethod* iface, con
|
|||||||
|
|
||||||
#define INDENTATION_STR wxString(" ")
|
#define INDENTATION_STR wxString(" ")
|
||||||
|
|
||||||
// if possible, add also the @deprecated tag in the doxygen comment
|
// if possible, add also the @deprecated tag in the doxygen comment if it's missing
|
||||||
if (file.GetLine(start-1).Contains("*/") && api->IsDeprecated())
|
int deprecationOffset = 0;
|
||||||
|
if (file.GetLine(start-1).Contains("*/") &&
|
||||||
|
(api->IsDeprecated() && !iface->IsDeprecated()))
|
||||||
{
|
{
|
||||||
file.RemoveLine(start-1);
|
file.RemoveLine(start-1);
|
||||||
file.InsertLine(INDENTATION_STR + INDENTATION_STR +
|
file.InsertLine(INDENTATION_STR + INDENTATION_STR +
|
||||||
"@deprecated @todo provide deprecation description", start-1);
|
"@deprecated @todo provide deprecation description", start-1);
|
||||||
file.InsertLine(INDENTATION_STR + "*/", start++);
|
file.InsertLine(INDENTATION_STR + "*/", start++);
|
||||||
|
|
||||||
|
// we have added a new line in the final balance
|
||||||
|
deprecationOffset=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMethod tmp(*api);
|
wxMethod tmp(*api);
|
||||||
@@ -389,14 +399,67 @@ void IfaceCheckApp::FixMethod(const wxString& header, const wxMethod* iface, con
|
|||||||
tmp.SetArgumentTypes(realargs);
|
tmp.SetArgumentTypes(realargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert the new one
|
#define WRAP_COLUMN 80
|
||||||
file.InsertLine(INDENTATION_STR + tmp.GetAsString() + ";", start);
|
|
||||||
|
wxArrayString toinsert;
|
||||||
|
toinsert.Add(INDENTATION_STR + tmp.GetAsString() + ";");
|
||||||
|
|
||||||
|
int nStartColumn = toinsert[0].Find('(');
|
||||||
|
wxASSERT(nStartColumn != wxNOT_FOUND);
|
||||||
|
|
||||||
|
// wrap lines too long at comma boundaries
|
||||||
|
for (unsigned int i=0; i<toinsert.GetCount(); i++)
|
||||||
|
{
|
||||||
|
size_t len = toinsert[i].Len();
|
||||||
|
if (len > WRAP_COLUMN)
|
||||||
|
{
|
||||||
|
wxASSERT(i == toinsert.GetCount()-1);
|
||||||
|
|
||||||
|
// break this line
|
||||||
|
wxString tmpleft = toinsert[i].Left(WRAP_COLUMN);
|
||||||
|
int comma = tmpleft.Find(',', true /* from end */);
|
||||||
|
if (comma == wxNOT_FOUND)
|
||||||
|
break; // break out of the for cycle...
|
||||||
|
|
||||||
|
toinsert.Add(wxString(' ', nStartColumn+1) +
|
||||||
|
toinsert[i].Right(len-comma-2)); // exclude the comma and the space after it
|
||||||
|
toinsert[i] = tmpleft.Left(comma+1); // include the comma
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert the new lines
|
||||||
|
for (unsigned int i=0; i<toinsert.GetCount(); i++)
|
||||||
|
file.InsertLine(toinsert[i], start+i);
|
||||||
|
|
||||||
// now save the modification
|
// now save the modification
|
||||||
if (!file.Write()) {
|
if (!file.Write()) {
|
||||||
LogError("can't save the '%s' header file.", header);
|
LogError("\tcan't save the '%s' header file.", header);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// how many lines did we add/remove in total?
|
||||||
|
int nOffset = toinsert.GetCount() + deprecationOffset - (end-start+1);
|
||||||
|
if (nOffset == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_verbose)
|
||||||
|
LogMessage("\tthe final row offset for following methods is %d lines.", nOffset);
|
||||||
|
|
||||||
|
// update the other method's locations for those methods which belong to the modified header
|
||||||
|
// and are placed _below_ the modified method
|
||||||
|
wxClassPtrArray cToUpdate = m_interface.FindClassesDefinedIn(header);
|
||||||
|
for (unsigned int i=0; i < cToUpdate.GetCount(); i++)
|
||||||
|
{
|
||||||
|
for (unsigned int j=0; j < cToUpdate[i]->GetMethodCount(); j++)
|
||||||
|
{
|
||||||
|
wxMethod& m = cToUpdate[i]->GetMethod(j);
|
||||||
|
if (m.GetLocation() > iface->GetLocation())
|
||||||
|
{
|
||||||
|
// update the location of this method
|
||||||
|
m.SetLocation(m.GetLocation()+nOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IfaceCheckApp::PrintStatistics(long secs)
|
void IfaceCheckApp::PrintStatistics(long secs)
|
||||||
|
@@ -412,6 +412,18 @@ bool wxXmlInterface::CheckParseResults() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxClassPtrArray wxXmlInterface::FindClassesDefinedIn(const wxString& headerfile) const
|
||||||
|
{
|
||||||
|
wxClassPtrArray ret;
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<m_classes.GetCount(); i++)
|
||||||
|
if (m_classes[i].GetHeader() == headerfile)
|
||||||
|
ret.Add(&m_classes[i]);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxXmlGccInterface helper declarations
|
// wxXmlGccInterface helper declarations
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -576,7 +588,7 @@ bool wxXmlGccInterface::Parse(const wxString& filename)
|
|||||||
if (ids.IsEmpty())
|
if (ids.IsEmpty())
|
||||||
{
|
{
|
||||||
if (child->GetAttribute("incomplete") != "1") {
|
if (child->GetAttribute("incomplete") != "1") {
|
||||||
LogError("Invalid member IDs for '%s' class node (ID %s)",
|
LogError("Invalid member IDs for '%s' class node: %s",
|
||||||
cname, child->GetAttribute("id"));
|
cname, child->GetAttribute("id"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -587,7 +599,7 @@ bool wxXmlGccInterface::Parse(const wxString& filename)
|
|||||||
{
|
{
|
||||||
// decode the non-empty list of IDs:
|
// decode the non-empty list of IDs:
|
||||||
if (!getMemberIDs(&members, &m_classes.Last(), ids)) {
|
if (!getMemberIDs(&members, &m_classes.Last(), ids)) {
|
||||||
LogError("Invalid member IDs for '%s' class node (ID %s)",
|
LogError("Invalid member IDs for '%s' class node: %s",
|
||||||
cname, child->GetAttribute("id"));
|
cname, child->GetAttribute("id"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -645,7 +657,7 @@ bool wxXmlGccInterface::Parse(const wxString& filename)
|
|||||||
else if (n == "File")
|
else if (n == "File")
|
||||||
{
|
{
|
||||||
if (!child->GetAttribute("id").StartsWith("f")) {
|
if (!child->GetAttribute("id").StartsWith("f")) {
|
||||||
LogError("Unexpected file ID: %s", id);
|
LogError("Unexpected file ID: %s", child->GetAttribute("id"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -670,7 +682,8 @@ bool wxXmlGccInterface::Parse(const wxString& filename)
|
|||||||
// they're never used as return/argument types by wxWidgets methods
|
// they're never used as return/argument types by wxWidgets methods
|
||||||
|
|
||||||
if (g_verbose)
|
if (g_verbose)
|
||||||
LogWarning("Type '%s' with ID '%s' does not have name attribute", n, id);
|
LogWarning("Type node '%s' with ID '%s' does not have name attribute",
|
||||||
|
n, child->GetAttribute("id"));
|
||||||
|
|
||||||
types[id] = "TOFIX";
|
types[id] = "TOFIX";
|
||||||
}
|
}
|
||||||
@@ -797,12 +810,12 @@ bool wxXmlGccInterface::Parse(const wxString& filename)
|
|||||||
|
|
||||||
if (newfunc.IsCtor() && !p->IsValidCtorForThisClass(newfunc)) {
|
if (newfunc.IsCtor() && !p->IsValidCtorForThisClass(newfunc)) {
|
||||||
LogError("The method '%s' does not seem to be a ctor for '%s'",
|
LogError("The method '%s' does not seem to be a ctor for '%s'",
|
||||||
newfunc.GetName(), p->GetName());
|
newfunc.GetName(), p->GetName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (newfunc.IsDtor() && !p->IsValidDtorForThisClass(newfunc)) {
|
if (newfunc.IsDtor() && !p->IsValidDtorForThisClass(newfunc)) {
|
||||||
LogError("The method '%s' does not seem to be a dtor for '%s'",
|
LogError("The method '%s' does not seem to be a dtor for '%s'",
|
||||||
newfunc.GetName(), p->GetName());
|
newfunc.GetName(), p->GetName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -294,6 +294,9 @@ public:
|
|||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pass a full-path header filename:
|
||||||
|
wxClassPtrArray FindClassesDefinedIn(const wxString& headerfile) const;
|
||||||
|
|
||||||
void ShowProgress()
|
void ShowProgress()
|
||||||
{ /*wxPrint(".");*/ }
|
{ /*wxPrint(".");*/ }
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user