When printing diagnostics in c-index-test, also print source ranges
and fix-it information, so we can see everything in one place. Along
the way, fix a few bugs with deserialization and query of diagnostics
in CIndex.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94768 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndexDiagnostic.cpp b/tools/CIndex/CIndexDiagnostic.cpp
index eb039df..52de8bb 100644
--- a/tools/CIndex/CIndexDiagnostic.cpp
+++ b/tools/CIndex/CIndexDiagnostic.cpp
@@ -154,12 +154,21 @@
 CXString clang_getDiagnosticFixItInsertion(CXDiagnostic Diag, 
                                            unsigned FixIt,
                                            CXSourceLocation *Location) {
+  if (Location)
+    *Location = clang_getNullLocation();
+
   CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
   if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints())
     return CIndexer::createCXString("");
   
   const CodeModificationHint &Hint
     = StoredDiag->Info.getCodeModificationHint(FixIt);
+
+  if (Location && StoredDiag->Info.getLocation().isValid())
+    *Location = translateSourceLocation(
+                                    StoredDiag->Info.getLocation().getManager(),
+                                        StoredDiag->LangOpts, 
+                                        Hint.InsertionLoc);
   return CIndexer::createCXString(Hint.CodeToInsert);
 }
 
@@ -180,6 +189,9 @@
 CXString clang_getDiagnosticFixItReplacement(CXDiagnostic Diag, 
                                              unsigned FixIt,
                                              CXSourceRange *Range) {
+  if (Range)
+    *Range = clang_getNullRange();
+
   CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
   if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints() ||
       StoredDiag->Info.getLocation().isInvalid()) {
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index d4bc008..658412c 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -195,8 +195,36 @@
   /* Print file:line:column. */
   clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic),
                                  &file, &line, &column, 0);
-  if (file)
-    fprintf(out, "%s:%d:%d: ", clang_getFileName(file), line, column);
+  if (file) {
+    CXSourceRange *ranges = 0;
+    unsigned num_ranges;
+    unsigned i;
+    unsigned printed_any_ranges = 0;
+    
+    fprintf(out, "%s:%d:%d:", clang_getFileName(file), line, column);
+  
+    clang_getDiagnosticRanges(Diagnostic, &ranges, &num_ranges);
+    for (i = 0; i != num_ranges; ++i) {
+      CXFile start_file, end_file;
+      unsigned start_line, start_column, end_line, end_column;
+      clang_getInstantiationLocation(clang_getRangeStart(ranges[i]),
+                                     &start_file, &start_line, &start_column,0);
+      clang_getInstantiationLocation(clang_getRangeEnd(ranges[i]),
+                                     &end_file, &end_line, &end_column, 0);
+      
+      if (start_file != end_file || start_file != file)
+        continue;
+      
+      fprintf(out, "{%d:%d-%d:%d}", start_line, start_column, end_line, 
+              end_column+1);
+      printed_any_ranges = 1;
+    }
+    clang_disposeDiagnosticRanges(ranges, num_ranges);
+    if (printed_any_ranges)
+      fprintf(out, ":");
+    
+    fprintf(out, " ");
+  }
   
   /* Print warning/error/etc. */
   switch (severity) {
@@ -213,6 +241,61 @@
   else
     fprintf(out, "<no diagnostic text>\n");
   clang_disposeString(text);
+  
+  if (file) {
+    unsigned i, num_fixits = clang_getDiagnosticNumFixIts(Diagnostic);
+    for (i = 0; i != num_fixits; ++i) {
+      switch (clang_getDiagnosticFixItKind(Diagnostic, i)) {
+      case CXFixIt_Insertion: {
+        CXSourceLocation insertion_loc;
+        CXFile insertion_file;
+        unsigned insertion_line, insertion_column;
+        text = clang_getDiagnosticFixItInsertion(Diagnostic, i, &insertion_loc);
+        clang_getInstantiationLocation(insertion_loc, &insertion_file, 
+                                       &insertion_line, &insertion_column, 0);
+        if (insertion_file == file)
+          fprintf(out, "FIX-IT: Insert \"%s\" at %d:%d\n",
+                  clang_getCString(text), insertion_line, insertion_column);
+        clang_disposeString(text);
+        break;
+      }
+
+      case CXFixIt_Removal: {
+        CXFile start_file, end_file;
+        unsigned start_line, start_column, end_line, end_column;
+        CXSourceRange remove_range
+          = clang_getDiagnosticFixItRemoval(Diagnostic, i);
+        clang_getInstantiationLocation(clang_getRangeStart(remove_range),
+                                       &start_file, &start_line, &start_column,
+                                       0);
+        clang_getInstantiationLocation(clang_getRangeEnd(remove_range),
+                                       &end_file, &end_line, &end_column, 0);
+        if (start_file == file && end_file == file)
+          fprintf(out, "FIX-IT: Remove %d:%d-%d:%d\n",
+                  start_line, start_column, end_line, end_column+1);
+        break;
+      }
+          
+      case CXFixIt_Replacement: {
+        CXFile start_file, end_file;
+        unsigned start_line, start_column, end_line, end_column;
+        CXSourceRange remove_range;
+        text = clang_getDiagnosticFixItReplacement(Diagnostic, i,&remove_range);
+        clang_getInstantiationLocation(clang_getRangeStart(remove_range),
+                                       &start_file, &start_line, &start_column,
+                                       0);
+        clang_getInstantiationLocation(clang_getRangeEnd(remove_range),
+                                       &end_file, &end_line, &end_column, 0);
+        if (start_file == end_file)
+          fprintf(out, "FIX-IT: Replace %d:%d-%d:%d with \"%s\"\n",
+                  start_line, start_column, end_line, end_column+1,
+                  clang_getCString(text));
+        clang_disposeString(text);
+        break;
+      }
+      }
+    }
+  }
 }
 
 /******************************************************************************/