From: huangqinjin Date: Mon, 26 Aug 2024 15:03:09 +0000 (+0800) Subject: enhance: Add utility to get path length in compiler diagnostics messages X-Git-Tag: v4.11~82^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5a0f8bbb2ed4bbf1119426f0d98c3b6f57a6df81;p=thirdparty%2Fccache.git enhance: Add utility to get path length in compiler diagnostics messages --- diff --git a/src/ccache/core/common.cpp b/src/ccache/core/common.cpp index 6e0ab656..7072f83e 100644 --- a/src/ccache/core/common.cpp +++ b/src/ccache/core/common.cpp @@ -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 diff --git a/src/ccache/core/common.hpp b/src/ccache/core/common.hpp index 78734a8f..1265609e 100644 --- a/src/ccache/core/common.hpp +++ b/src/ccache/core/common.hpp @@ -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. : +// 2. (line[,column]): // MSVC +// 3. (line[,column]) : // MSVC +std::size_t get_diagnostics_path_length(std::string_view line); + } // namespace core diff --git a/unittest/test_core_common.cpp b/unittest/test_core_common.cpp index 74a37ffb..ad2bbc7f 100644 --- a/unittest/test_core_common.cpp +++ b/unittest/test_core_common.cpp @@ -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();