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()); }
/// <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); } }