]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
enhance: Add utility to get path length in compiler diagnostics messages
authorhuangqinjin <huangqinjin@gmail.com>
Mon, 26 Aug 2024 15:03:09 +0000 (23:03 +0800)
committerJoel Rosdahl <joel@rosdahl.net>
Tue, 10 Sep 2024 18:06:09 +0000 (20:06 +0200)
src/ccache/core/common.cpp
src/ccache/core/common.hpp
unittest/test_core_common.cpp

index 6e0ab656d1e18977ceffbbc54fc3a59a7c34fd46..7072f83eb835e57ac7fdf3e8f44f461c4d56ba68 100644 (file)
@@ -174,4 +174,53 @@ strip_ansi_csi_seqs(std::string_view string)
   return result;
 }
 
+std::size_t
+get_diagnostics_path_length(std::string_view line)
+{
+  std::size_t path_end = 0;
+
+#ifdef _WIN32
+  // Check if the path starts with a drive letter.
+  if (line.size() >= 3 && line[1] == ':' && (line[2] == '\\' || line[2] == '/')
+      && ((line[0] >= 'A' && line[0] <= 'Z')
+          || (line[0] >= 'a' && line[0] <= 'z'))) {
+    path_end = line.find(':', 3);
+    if (path_end == std::string_view::npos) {
+      // Treat the dirve letter as "path".
+      path_end = 1;
+    }
+  } else {
+    path_end = line.find(':');
+  }
+#else
+  path_end = line.find(':');
+#endif
+
+  if (path_end == std::string_view::npos || path_end == 0) {
+    return 0;
+  }
+
+  line = line.substr(0, path_end);
+  // There could be an extra space before ':'.
+  // https://developercommunity.visualstudio.com/t/10729549
+  if (line.back() == ' ') {
+    line.remove_suffix(1);
+    path_end -= 1;
+  }
+
+  // MSVC: Strip "(line[,column])" component.
+  if (!line.empty() && line.back() == ')') {
+    do {
+      line.remove_suffix(1);
+    } while (!line.empty() && line.back() != '('
+             && (std::isdigit(line.back()) || line.back() == ','));
+
+    if (!line.empty() && line.back() == '(') {
+      path_end = line.size() - 1;
+    }
+  }
+
+  return path_end;
+}
+
 } // namespace core
index 78734a8fa8b5ee063e938f8fed11c9e85c850a14..1265609ecc2106d044816c9f9906cf3cebca75e3 100644 (file)
@@ -50,4 +50,10 @@ void send_to_console(const Context& ctx, std::string_view text, int fd);
 // Returns a copy of string with the specified ANSI CSI sequences removed.
 [[nodiscard]] std::string strip_ansi_csi_seqs(std::string_view string);
 
+// Get the length of paths in compiler diagnostics messages in following forms:
+// 1. <path>:
+// 2. <path>(line[,column]):    // MSVC
+// 3. <path>(line[,column]) :   // MSVC
+std::size_t get_diagnostics_path_length(std::string_view line);
+
 } // namespace core
index 74a37ffb75c6a38eedd9a1bb2eac83544c4fcc57..ad2bbc7f8beda08381f1ce4b3350ed4474c4bb4b 100644 (file)
@@ -83,4 +83,21 @@ TEST_CASE("core::strip_ansi_csi_seqs")
   CHECK(core::strip_ansi_csi_seqs(input) == "Normal, bold, red, bold green.\n");
 }
 
+TEST_CASE("core::get_diagnostics_path_length")
+{
+  CHECK(core::get_diagnostics_path_length("a:1:") == 1);
+  CHECK(core::get_diagnostics_path_length("a(1):") == 1);
+  CHECK(core::get_diagnostics_path_length("a(1) :") == 1);
+  CHECK(core::get_diagnostics_path_length("a(1,2):") == 1);
+  CHECK(core::get_diagnostics_path_length("a(1,2) :") == 1);
+
+#ifdef _WIN32
+  CHECK(core::get_diagnostics_path_length("C:\\a:1:") == 4);
+  CHECK(core::get_diagnostics_path_length("C:\\a(1):") == 4);
+  CHECK(core::get_diagnostics_path_length("C:\\a(1) :") == 4);
+  CHECK(core::get_diagnostics_path_length("C:\\a(1,2):") == 4);
+  CHECK(core::get_diagnostics_path_length("C:\\a(1,2) :") == 4);
+#endif
+}
+
 TEST_SUITE_END();