diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index 5a7581f7..3d4e7b35 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -29,8 +29,8 @@ namespace Cxxi transform.SetupHeaders(headers); var parser = new Parser(options); - parser.HeaderParsed += (file, success) => - Console.WriteLine(success ? " Parsed '" + file + "'." : + parser.HeaderParsed += (file, result) => + Console.WriteLine(result.Success ? " Parsed '" + file + "'." : " Could not parse '" + file + "'."); parser.ParseHeaders(headers); diff --git a/src/Generator/Parser.cs b/src/Generator/Parser.cs index e44375cf..f8bdae2d 100644 --- a/src/Generator/Parser.cs +++ b/src/Generator/Parser.cs @@ -20,7 +20,7 @@ namespace Cxxi ParseHeader(header); } - bool ParseHeader(string file) + public ParserResult ParseHeader(string file) { var parserOptions = new ParserOptions { @@ -38,6 +38,6 @@ namespace Cxxi return result; } - public Action HeaderParsed = delegate {}; + public Action HeaderParsed = delegate {}; } } diff --git a/src/Parser/Main.cpp b/src/Parser/Main.cpp index ae07adca..90d26db4 100644 --- a/src/Parser/Main.cpp +++ b/src/Parser/Main.cpp @@ -12,9 +12,9 @@ public ref class ClangParser { public: - static bool Parse(ParserOptions^ Opts) + static ParserResult^ Parse(ParserOptions^ Opts) { - if (!Opts->FileName) return false; + if (!Opts->FileName) return nullptr; using namespace clix; std::string File = marshalString(Opts->FileName); diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 90deb4ef..a22691c1 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -1389,13 +1389,48 @@ struct ParseConsumer : public clang::ASTConsumer virtual bool HandleTopLevelDecl(clang::DeclGroupRef) { return true; } }; -bool Parser::Parse(const std::string& File) +struct Diagnostic { + clang::SourceLocation Location; + llvm::SmallString<100> Message; +}; + +struct DiagnosticConsumer : public clang::DiagnosticConsumer +{ + virtual ~DiagnosticConsumer() { } + + virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level Level, + const clang::Diagnostic& Info) override { + auto Diag = Diagnostic(); + Diag.Location = Info.getLocation(); + Info.FormatDiagnostic(Diag.Message); + Diagnostics.push_back(Diag); + } + + virtual + DiagnosticConsumer* clone(clang::DiagnosticsEngine& Diags) const override { + return new DiagnosticConsumer(); + } + + std::vector Diagnostics; +}; + +ParserResult^ Parser::Parse(const std::string& File) +{ + auto res = gcnew ParserResult(); + res->Library = Lib; + if (File.empty()) - return false; + { + res->Success = false; + return res; + } C->setASTConsumer(new ParseConsumer()); + auto DiagClient = new DiagnosticConsumer(); + C->getDiagnostics().setClient(DiagClient); + // Create a virtual file that includes the header. This gets rid of some // Clang warnings about parsing an header file as the main file. @@ -1413,15 +1448,29 @@ bool Parser::Parse(const std::string& File) /*SkipFunctionBodies=*/true); client->EndSourceFile(); - if(client->getNumErrors() != 0) + // Convert the diagnostics to the managed types + for(auto& Diag : DiagClient->Diagnostics) { - // We had some errors while parsing the file. - // Report this... - return false; + using namespace clix; + + auto& Source = C->getSourceManager(); + auto FileName = Source.getFilename(Diag.Location); + + auto PDiag = ParserDiagnostic(); + PDiag.FileName = marshalString(FileName.str()); + PDiag.Message = marshalString(Diag.Message.str()); + res->Diagnostics->Add(PDiag); + } + + if(DiagClient->getNumErrors() != 0) + { + res->Success = false; + return res; } AST = &C->getASTContext(); WalkAST(); - return true; + res->Success = true; + return res; } \ No newline at end of file diff --git a/src/Parser/Parser.h b/src/Parser/Parser.h index 5f4827da..bf3c9341 100644 --- a/src/Parser/Parser.h +++ b/src/Parser/Parser.h @@ -55,12 +55,30 @@ public ref struct ParserOptions bool Verbose; }; +public value struct ParserDiagnostic +{ + System::String^ FileName; + System::String^ Message; +}; + +public ref struct ParserResult +{ + ParserResult() + { + Diagnostics = gcnew List(); + } + + bool Success; + Cxxi::Library^ Library; + List^ Diagnostics; +}; + struct Parser { Parser(ParserOptions^ Opts); void Setup(ParserOptions^ Opts); - bool Parse(const std::string& File); + ParserResult^ Parse(const std::string& File); protected: