private static string GetMessageAndLocation(string rootContent, CXDiagnostic diagnostic, out CppSourceLocation location) { var builder = new StringBuilder(); builder.Append(diagnostic.ToString()); location = CppModelBuilder.GetSourceLocation(diagnostic.Location); if (location.File == CppAstRootFileName) { var reader = new StringReader(rootContent); var lines = new List <string>(); string line; while ((line = reader.ReadLine()) != null) { lines.Add(line); } var lineIndex = location.Line - 1; if (lineIndex < lines.Count) { builder.AppendLine(); builder.AppendLine(lines[lineIndex]); for (int i = 0; i < location.Column - 1; i++) { builder.Append(i + 1 == location.Column - 1 ? "-" : " "); } builder.AppendLine("^-"); } } return(builder.ToString()); }
private bool DealingWithDiagnostic(CXDiagnostic d) { // error spelling string spelling = clang.getDiagnosticSpelling(d).ToString(); // category text string categoryText = clang.getDiagnosticCategoryText(d).ToString(); // severity text CXDiagnosticSeverity severity = clang.getDiagnosticSeverity(d); string severityStr = ClangTraits.ToString(severity); // source location CXSourceLocation location = clang.getDiagnosticLocation(d); CXFile file = new CXFile(IntPtr.Zero); clang.getInstantiationLocation( location, out file, out uint line, out uint column, out uint offset); string fileName = clang.getFileName(file).ToString(); clang.disposeDiagnostic(d); string errorString = string.Format("{0}: {1}-{2}, IN {3}, line: {4}, column: {5}", severityStr, spelling, categoryText, fileName, line, column); return(ClangTraits.IsFatal(severity)); }
/// <summary> /// Reparse the Translation Unit contained by this instance. /// Updates Symbol Database /// Places error markers on document /// </summary> public void ParseAndDiagnose(CancellationToken cancellationToken) { lock (Manager.SyncRoot) { var unsavedFilesArray = unsavedFiles.ToArray(); TU = Manager.Reparse(FileName, unsavedFilesArray, cancellationToken); uint numDiag = clang.getNumDiagnostics(TU); for (uint i = 0; i < numDiag; i++) { CXDiagnostic diag = clang.getDiagnostic(TU, i); string spelling = diag.ToString(); uint numRanges = clang.getDiagnosticNumRanges(diag); if (numRanges != 0) { for (uint j = 0; j < numRanges; j++) { try { SourceLocation begin = Manager.GetSourceLocation(clang.getRangeStart(clang.getDiagnosticRange(diag, j))); SourceLocation end = Manager.GetSourceLocation(clang.getRangeEnd(clang.getDiagnosticRange(diag, j))); Add(new Error(ErrorType.Error, spelling, new DocumentRegion(begin.Line, begin.Column, end.Line, end.Column))); } catch { //it seems sometimes "expression result unused" diagnostics appear multiple times //for the same problem, when there is only e.g. //an '1;' line in the code, and not every indicator has a valid filename in their location //this crashes the thread, so we ignore it } } } else { try { SourceLocation loc = Manager.GetSourceLocation(clang.getDiagnosticLocation(diag)); Add(new Error(ErrorType.Error, spelling, new DocumentRegion(loc.Line, loc.Column, loc.Line, loc.Column + 1))); } catch { //same goes here } } clang.disposeDiagnostic(diag); } Manager.UpdateDatabase(FileName, TU, cancellationToken, true); } }
internal static extern CXString clang_formatDiagnostic(CXDiagnostic diagnostic, uint options);
internal unsafe static extern CXString clang_getDiagnosticFixIt(CXDiagnostic diagnostic, uint fixIt, CXSourceRange* replacementRange);
internal static extern CXSourceRange clang_getDiagnosticRange(CXDiagnostic diagnostic, uint rangeIdx);
internal static extern CXString clang_getDiagnosticCategoryText(CXDiagnostic diagnostic);
internal unsafe static extern CXString clang_getDiagnosticOption(CXDiagnostic diagnostic, CXString* disable);
internal static extern uint clang_getDiagnosticNumRanges(CXDiagnostic diagnostic);
internal static extern uint clang_getDiagnosticCategory(CXDiagnostic diagnostic);
internal static extern CXString clang_getDiagnosticOption(CXDiagnostic diagnostic, out CXString disable);
internal static extern CXString clang_getDiagnosticSpelling(CXDiagnostic diagnostic);
internal static extern CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic diagnostic);
internal static extern DiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic diagnostic);
internal static extern CXString clang_formatDiagnostic(CXDiagnostic diagnostic, DiagnosticDisplayOptions options);
internal static extern CXSourceRange clang_getDiagnosticRange(CXDiagnostic diagnostic, uint range);
internal static extern uint clang_getDiagnosticNumFixIts(CXDiagnostic diagnostic);
internal static extern CXString clang_getDiagnosticFixIt(CXDiagnostic diagnostic, uint fix_it, out CXSourceRange replacement_range);
internal static extern CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic diagnostic);
internal static extern void clang_disposeDiagnostic(CXDiagnostic dianostic);
public Diagnostic(CXDiagnostic d) { this.Core = d; }
internal static extern CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic diag);
internal static extern Diagnostic.Severity clang_getDiagnosticSeverity(CXDiagnostic diagnostic);
public static string ToString(this CXDiagnostic o) { return(clang.getDiagnosticSpelling(o).ToString()); }
public unsafe void GenerateTypes(string libraryName = "imobiledevice") { string[] arguments = { // Use the C++ backend "-x", "c++", // Parse the doxygen comments "-Wdocumentation", // Target 32-bit OS "-m32" }; arguments = arguments.Concat(this.IncludeDirectories.Select(x => "-I" + x)).ToArray(); FunctionVisitor functionVisitor; using (var createIndex = ClangSharp.Index.Create(false, true)) using (var translationUnit = CXTranslationUnit.Parse(createIndex.Handle, this.InputFile, arguments, null, CXTranslationUnit_Flags.CXTranslationUnit_None)) { StringWriter errorWriter = new StringWriter(); var set = translationUnit.DiagnosticSet; var numDiagnostics = set.NumDiagnostics; bool hasError = false; bool hasWarning = false; for (uint i = 0; i < numDiagnostics; ++i) { CXDiagnostic diagnostic = set.GetDiagnostic(i); var severity = diagnostic.Severity; switch (severity) { case CXDiagnosticSeverity.CXDiagnostic_Error: case CXDiagnosticSeverity.CXDiagnostic_Fatal: hasError = true; break; case CXDiagnosticSeverity.CXDiagnostic_Warning: hasWarning = true; break; } var location = diagnostic.Location; location.GetFileLocation(out CXFile file, out uint line, out _, out _); var fileName = file.Name.CString; var message = diagnostic.Spelling.CString; errorWriter.WriteLine($"{severity}: {fileName}:{line} {message}"); } if (hasError) { throw new Exception(errorWriter.ToString()); } if (hasWarning) { // Dump the warnings to the console output. Console.WriteLine(errorWriter.ToString()); } // Generate the marhaler types for string arrays (char **) var arrayMarshalerGenerator = new ArrayMarshalerGenerator(this); arrayMarshalerGenerator.Generate(); // Creates enums var enumVisitor = new EnumVisitor(this); var realEnumVisitor = new DelegatingCXCursorVisitor(enumVisitor.Visit); translationUnit.Cursor.VisitChildren(realEnumVisitor.Visit, new CXClientData()); // Creates structs var structVisitor = new StructVisitor(this); var realStructVisitor = new DelegatingCXCursorVisitor(structVisitor.Visit); translationUnit.Cursor.VisitChildren(realStructVisitor.Visit, new CXClientData()); // Creates safe handles & delegates var typeDefVisitor = new TypeDefVisitor(this); var realTypeDefVisitor = new DelegatingCXCursorVisitor(typeDefVisitor.Visit); translationUnit.Cursor.VisitChildren(realTypeDefVisitor.Visit, new CXClientData()); // Creates functions in a NativeMethods class functionVisitor = new FunctionVisitor(this, libraryName); var realFunctionVisitor = new DelegatingCXCursorVisitor(functionVisitor.Visit); translationUnit.Cursor.VisitChildren(realFunctionVisitor.Visit, new CXClientData()); createIndex.Dispose(); } // Update the SafeHandle to call the _free method var handles = this.Types.Where(t => t.Name.EndsWith("Handle")); foreach (var handle in handles) { var freeMethod = functionVisitor.NativeMethods.Members .OfType <CodeMemberMethod>() .Where(m => (m.Name.EndsWith("_free") || m.Name.EndsWith("_disconnect")) && m.Parameters.Count == 1 && m.Parameters[0].Type.BaseType == handle.Name) .SingleOrDefault(); if (freeMethod == null) { continue; } var type = (HandleType)((NustacheGeneratedType)handle).Type; type.ReleaseMethodName = freeMethod.Name; type.ReleaseMethodReturnsValue = freeMethod.ReturnType.BaseType != "System.Void"; // Directly pass the IntPtr, becuase the handle itself will already be in the 'closed' state // when this method is called. freeMethod.Parameters[0].Type = new CodeTypeReference(typeof(IntPtr)); freeMethod.Parameters[0].Direction = FieldDirection.In; } // Extract the API interface and class, as well as the Exception class. Used for DI. ApiExtractor extractor = new ApiExtractor(this, functionVisitor); extractor.Generate(); // Add the 'Error' extension IsError and ThrowOnError extension methods var extensionsExtractor = new ErrorExtensionExtractor(this, functionVisitor); extensionsExtractor.Generate(); // Patch the native methods to be compatible with .NET Core - basically, // do the marshalling ourselves NativeMethodOverloadGenerator.Generate(this); }
internal static extern void clang_disposeDiagnostic(CXDiagnostic diagnostic);