|
| 1 | +#pragma once |
| 2 | + |
| 3 | +#include <string> |
| 4 | +#include <vector> |
| 5 | +#include <filesystem> |
| 6 | + |
| 7 | +namespace vix::cli |
| 8 | +{ |
| 9 | + namespace fs = std::filesystem; |
| 10 | + |
| 11 | + /// Represents a single compiler error extracted from the build log. |
| 12 | + struct CompilerError |
| 13 | + { |
| 14 | + /// Full path to the source file reported by the compiler. |
| 15 | + std::string file; |
| 16 | + |
| 17 | + /// 1-based line number in the source file. |
| 18 | + int line = 0; |
| 19 | + |
| 20 | + /// 1-based column number in the source file. |
| 21 | + int column = 0; |
| 22 | + |
| 23 | + /// Human-readable error message (without the file:line:column prefix). |
| 24 | + std::string message; |
| 25 | + |
| 26 | + /// Raw line as seen in the compiler output (for debugging/fallbacks). |
| 27 | + std::string raw; |
| 28 | + }; |
| 29 | + |
| 30 | + /// High-level error reporting helper for the Vix CLI. |
| 31 | + /// |
| 32 | + /// The ErrorHandler is responsible for: |
| 33 | + /// - Parsing raw compiler / linker logs (Clang/GCC-style). |
| 34 | + /// - Detecting "known" patterns and replacing them with very friendly, |
| 35 | + /// colored explanations (especially in script mode: `vix run main.cpp`). |
| 36 | + /// - Falling back to a compact list of errors when no special pattern matches. |
| 37 | + class ErrorHandler |
| 38 | + { |
| 39 | + public: |
| 40 | + /// Parse a build log and print a friendly summary to stderr. |
| 41 | + /// |
| 42 | + /// This method: |
| 43 | + /// - Extracts structured compiler errors (file, line, column, message). |
| 44 | + /// - Handles special cases (common C++ mistakes) with educational messages. |
| 45 | + /// - Optionally detects linker and sanitizer errors from the raw log. |
| 46 | + /// |
| 47 | + /// \param buildLog |
| 48 | + /// Full textual output captured from the build command |
| 49 | + /// (stdout + stderr). |
| 50 | + /// |
| 51 | + /// \param sourceFile |
| 52 | + /// The main source file for the script or target being built. |
| 53 | + /// Used only for display (e.g., `Source file: main.cpp`). |
| 54 | + /// |
| 55 | + /// \param contextMessage |
| 56 | + /// Short label describing the context (defaults to "Script build failed"). |
| 57 | + /// This is used in generic error headers when no special case applies. |
| 58 | + static void printBuildErrors( |
| 59 | + const std::string &buildLog, |
| 60 | + const fs::path &sourceFile, |
| 61 | + const std::string &contextMessage = "Script build failed"); |
| 62 | + |
| 63 | + private: |
| 64 | + /// Parse Clang/GCC-style errors from the build log. |
| 65 | + /// |
| 66 | + /// Expected format (simplified): |
| 67 | + /// /path/to/file.cpp:line:column: error: message... |
| 68 | + /// /path/to/file.hpp:line:column: fatal error: message... |
| 69 | + /// |
| 70 | + /// Only "error" and "fatal error" entries are returned (warnings are ignored). |
| 71 | + static std::vector<CompilerError> parseClangGccErrors( |
| 72 | + const std::string &buildLog); |
| 73 | + |
| 74 | + /// Print a single compiler error in a compact, human-friendly format. |
| 75 | + /// |
| 76 | + /// Typically used for generic build output (non–special-case handling), |
| 77 | + /// for example: |
| 78 | + /// |
| 79 | + /// main.cpp:17:5 |
| 80 | + /// error: use of undeclared identifier 'foo' |
| 81 | + static void printSingleError(const CompilerError &err); |
| 82 | + |
| 83 | + /// Print small, generic hints for common error messages. |
| 84 | + /// |
| 85 | + /// Examples: |
| 86 | + /// - Missing `std` namespace. |
| 87 | + /// - Missing semicolon. |
| 88 | + /// - No matching function for a given call. |
| 89 | + static void printHints(const CompilerError &err); |
| 90 | + |
| 91 | + /// Handle "known" error patterns with very friendly, high-level messages. |
| 92 | + /// |
| 93 | + /// This is where we turn cryptic compiler diagnostics into something like: |
| 94 | + /// |
| 95 | + /// ❌ ERROR: Cannot print std::vector<int> using operator<< |
| 96 | + /// |
| 97 | + /// 💡 Tip: |
| 98 | + /// std::cout << value; // ❌ invalid |
| 99 | + /// for (auto x : value) // ✔ correct |
| 100 | + /// std::cout << x << std::endl; |
| 101 | + /// |
| 102 | + /// 📍 Source: main.cpp:18 |
| 103 | + /// |
| 104 | + /// If a pattern is recognized and a custom message is printed, this |
| 105 | + /// function returns true and the generic error printing pipeline is skipped. |
| 106 | + /// |
| 107 | + /// \return true if the error set has already been handled and printed |
| 108 | + /// with a custom message; false otherwise. |
| 109 | + static bool handleSpecialCases( |
| 110 | + const std::vector<CompilerError> &errors, |
| 111 | + const fs::path &sourceFile, |
| 112 | + const std::string &contextMessage); |
| 113 | + }; |
| 114 | + |
| 115 | +} // namespace vix::cli |
0 commit comments