2525#endif
2626
2727#include < sstream>
28+ #include < string>
29+ #include < algorithm>
30+ #include < cctype>
2831
2932namespace vix ::cli::errors
3033{
34+ namespace
35+ {
36+ std::string trim_copy (std::string s)
37+ {
38+ while (!s.empty () &&
39+ (s.back () == ' \n ' || s.back () == ' \r ' || s.back () == ' ' || s.back () == ' \t ' ))
40+ {
41+ s.pop_back ();
42+ }
43+
44+ std::size_t i = 0 ;
45+ while (i < s.size () &&
46+ (s[i] == ' \n ' || s[i] == ' \r ' || s[i] == ' ' || s[i] == ' \t ' ))
47+ {
48+ ++i;
49+ }
50+
51+ s.erase (0 , i);
52+ return s;
53+ }
54+
55+ std::string strip_ansi (std::string s)
56+ {
57+ static const std::regex ansiRe (R"( \x1B\[[0-9;?]*[ -/]*[@-~])" );
58+ return std::regex_replace (s, ansiRe, " " );
59+ }
60+ }
61+
3162 std::vector<CompilerError> ClangGccParser::parse (const std::string &buildLog)
3263 {
3364 std::vector<CompilerError> out;
3465
35- // Example :
66+ // GCC / Clang examples :
3667 // /path/main.cpp:3:5: error: use of undeclared identifier 'std'
3768 // /path/foo.hpp:1:10: fatal error: 'h.hpp' file not found
38- std::regex re (R"( (.+?):(\d+):(\d+):\s*(fatal error|error|warning):\s*(.+))" );
69+ // /path/main.cpp:2:10: fatal error: huh.hpp: No such file or directory
70+ static const std::regex re (
71+ R"( ^(.+?):([0-9]+):([0-9]+):\s*(fatal error|error|warning):\s*(.+)$)" );
3972
4073 std::istringstream iss (buildLog);
4174 std::string line;
75+
4276 while (std::getline (iss, line))
4377 {
44- // Ignore make/ninja noise
78+ line = strip_ansi (trim_copy (line));
79+
80+ if (line.empty ())
81+ continue ;
82+
4583 if (line.rfind (" gmake" , 0 ) == 0 ||
4684 line.rfind (" make" , 0 ) == 0 ||
4785 line.rfind (" ninja" , 0 ) == 0 )
@@ -50,20 +88,21 @@ namespace vix::cli::errors
5088 }
5189
5290 std::smatch m;
53- if (std::regex_match (line, m, re))
91+ if (std::regex_search (line, m, re))
5492 {
5593 CompilerError e;
56- e.file = m[1 ].str ();
94+ e.file = trim_copy ( m[1 ].str () );
5795 e.line = std::stoi (m[2 ].str ());
5896 e.column = std::stoi (m[3 ].str ());
59- // m[4] = "fatal error" | "error" | "warning"
60- e.message = m[5 ].str ();
97+
98+ const std::string severity = m[4 ].str ();
99+ const std::string message = trim_copy (m[5 ].str ());
100+
101+ e.message = severity + " : " + message;
61102 e.raw = line;
62103
63- if (m[4 ].str () == " error" || m[4 ].str () == " fatal error" )
64- {
104+ if (severity == " error" || severity == " fatal error" )
65105 out.push_back (std::move (e));
66- }
67106 }
68107 }
69108
0 commit comments