Patch #2867 2009-12-20 20:10

techy

Try harder when searching file with compilation error
Download
2867-Try_harder_whe.patch (4.7 KB)
Category
Application::Refinement
Status
Accepted
Close date
2009-12-31 14:47
Assigned to
mortenmacfly
Index: src/sdk/globals.cpp
===================================================================
--- src/sdk/globals.cpp    (revision 5986)
+++ src/sdk/globals.cpp    (working copy)
@@ -665,6 +665,64 @@
     return result;
 }
 
+// Checks whether 'suffix' could be a suffix of 'path' and therefore represents 
+// the same path. This is used to check whether a relative path could represent
+// the same path as absolute path. For instance, for 
+// suffix = sdk/globals.cpp
+// path = /home/user/codeblocks/trunk/src/sdk/globals.cpp
+// it returns true. The function expects that 'path' is normalized and compares
+// 'path' with 'suffix' starting from the end of the path. When it reaches .. in 
+// 'suffix' it gives up (there is no way to check relative filename names 
+// exactly) and if the path compared so far is identical, it returns true
+bool IsSuffixOfPath(wxFileName const & suffix, wxFileName const & path)
+{
+    if (path.GetFullName() != suffix.GetFullName())
+    {
+        return false;
+    }
+
+    wxArrayString suffixDirArray = suffix.GetDirs();
+    wxArrayString pathDirArray = path.GetDirs();
+
+    int j = pathDirArray.GetCount() - 1;
+    for (int i = suffixDirArray.GetCount() - 1; i >= 0; i--)
+    {
+        if (suffixDirArray[i] == _T(".") || suffixDirArray[i] == _T(""))
+        {
+            // skip paths like /./././ and ////
+            continue;
+        }
+
+        if (j < 0)
+        {
+            // suffix has more directories than path - cannot represent the same path
+            return false;
+        }
+
+        if (suffixDirArray[i] == _T(".."))
+        {
+            // suffix contains ".." - from now on we cannot precisely determine 
+            // whether suffix and path match - we assume that they do
+            return true;
+        }
+        else if (suffixDirArray[i] != pathDirArray[j])
+        {
+            // the corresponding directories of the two paths differ
+            return false;
+        }
+
+        j--;
+    }
+
+    if (suffix.IsAbsolute() && (j >= 0 || suffix.GetVolume() != path.GetVolume()))
+    {
+        return false;
+    }
+
+    // 'suffix' is a suffix of 'path'
+    return true;
+}
+
 // function to check the common controls version
 // (should it be moved in sdk globals?)
 #ifdef __WXMSW__
Index: src/include/globals.h
===================================================================
--- src/include/globals.h    (revision 5986)
+++ src/include/globals.h    (working copy)
@@ -184,6 +184,7 @@
                                           bool showCreateDirButton = false); // where supported
 
 extern DLLIMPORT bool NormalizePath(wxFileName& f,const wxString& base);
+extern DLLIMPORT bool IsSuffixOfPath(wxFileName const & suffix, wxFileName const & path);
 
 extern DLLIMPORT wxString URLEncode(const wxString &str);
 
Index: src/plugins/compilergcc/compilererrors.cpp
===================================================================
--- src/plugins/compilergcc/compilererrors.cpp    (revision 5986)
+++ src/plugins/compilergcc/compilererrors.cpp    (working copy)
@@ -162,12 +162,52 @@
         }
     }
 
-    // if we reached here and ed is NULL, either the error file doesn't belong to a project,
-    // or can't be found for any other reason.
-    // check if we can open it directly...
+    // if we reached here and ed is NULL, the filename in the output isn't relative
+    // to the project root directory or doesn't belong to the project
+
+    // first check if we can open it directly...
     if (!ed)
         ed = Manager::Get()->GetEditorManager()->Open(error.filename);
 
+    // check if we find the file among opened files (highly probable for error
+    // messages since we are getting error for something we have just screwed up)
+    if (!ed)
+    {
+        for (int i = 0; i < Manager::Get()->GetEditorManager()->GetEditorsCount(); ++i)
+        {
+            cbEditor* edit = Manager::Get()->GetEditorManager()->GetBuiltinEditor(i);
+            if (!edit)
+                continue;
+
+            ProjectFile* pf = edit->GetProjectFile();
+            if (!pf)
+                continue;
+
+            if (IsSuffixOfPath(error.filename, pf->file.GetFullPath()))
+            {
+                ed = Manager::Get()->GetEditorManager()->Open(pf->file.GetFullPath());
+                break;
+            }
+        }
+    }
+
+    // finally go through the project files and try to find the file there
+    if (!ed && project)
+    {
+        for (int i = 0; i < project->GetFilesCount(); ++i)
+        {
+            ProjectFile* pf = project->GetFile(i);
+            if (!pf)
+                continue;
+
+            if (IsSuffixOfPath(error.filename, pf->file.GetFullPath()))
+            {
+                ed = Manager::Get()->GetEditorManager()->Open(pf->file.GetFullPath());
+                break;
+            }
+        }
+    }
+
     if (ed)
     {
         ed->Activate();
techy 2009-12-20 20:18

I guess that codeblocks works very well when it manages the whole project but when using custom makefiles there are several issues. One of them is that it cannot find the file where the compilation error occurred so it cannot open it and mark the line with the error. This is a problem for all automake generated projects where you want to point the make to the topmost project directory with the main make - however, inside the makefile it makes cd to project subdirectories so the compilation errors are without any path so the files cannot be found with codeblocks.

This patch adds more checks to locate the file with errors - it tries to locate the file in the currently opened file list (highly probable that the file will be found there - we probably get this error because we have made some modifications) and then all project files. I added one function to globals.cpp that is used to check whether the reported file could be the same as the opened (or project) file. I put it into globals just because I use the same function in one more patch as well (if there is some better place where to put it, please do it).