hokein created this revision.
hokein added a reviewer: bkramer.
hokein added a subscriber: cfe-commits.

And some improvements:
* Show better error messages on unfound symbols.
* Fix a typo.

http://reviews.llvm.org/D20827

Files:
  include-fixer/IncludeFixer.cpp
  include-fixer/IncludeFixerContext.h
  include-fixer/tool/ClangIncludeFixer.cpp
  include-fixer/tool/clang-include-fixer.py
  test/include-fixer/commandline_options.cpp
  test/include-fixer/ranking.cpp

Index: test/include-fixer/ranking.cpp
===================================================================
--- test/include-fixer/ranking.cpp
+++ test/include-fixer/ranking.cpp
@@ -1,6 +1,5 @@
-// RUN: clang-include-fixer -db=yaml -input=%S/Inputs/fake_yaml_db.yaml -output-headers %s -- | FileCheck %s -implicit-check-not=.h
+// RUN: clang-include-fixer -db=yaml -input=%S/Inputs/fake_yaml_db.yaml -output-headers %s -- | FileCheck %s
 
-// CHECK: "../include/bar.h"
-// CHECK-NEXT: "../include/zbar.h"
+// CHECK: Headers: [ '"../include/bar.h"', '"../include/zbar.h"' ]
 
 bar b;
Index: test/include-fixer/commandline_options.cpp
===================================================================
--- test/include-fixer/commandline_options.cpp
+++ test/include-fixer/commandline_options.cpp
@@ -1,7 +1,7 @@
 // REQUIRES: shell
 // RUN: sed -e 's#//.*$##' %s > %t.cpp
 // RUN: clang-include-fixer -db=fixed -input='foo= "foo.h","bar.h"' -output-headers %t.cpp -- | FileCheck %s -check-prefix=CHECK-HEADERS
-// RUN: cat %t.cpp | clang-include-fixer -stdin -insert-header='"foo.h"' %t.cpp | FileCheck %s -check-prefix=CHECK
+// RUN: cat %t.cpp | clang-include-fixer -stdin -insert-header='{SymbolIdentifier: foo, Headers: ["\"foo.h\""]}' %t.cpp | FileCheck %s -check-prefix=CHECK
 //
 // CHECK-HEADERS: "foo.h"
 // CHECK-HEADERS: "bar.h"
Index: include-fixer/tool/clang-include-fixer.py
===================================================================
--- include-fixer/tool/clang-include-fixer.py
+++ include-fixer/tool/clang-include-fixer.py
@@ -19,6 +19,7 @@
 import difflib
 import subprocess
 import vim
+import yaml
 
 # set g:clang_include_fixer_path to the path to clang-include-fixer if it is not
 # on the path.
@@ -49,7 +50,7 @@
 
 
 def InsertHeaderToVimBuffer(header, text):
-  command = [binary, "-stdin", "-insert-header="+header,
+  command = [binary, "-stdin", "-insert-header="+yaml.dump(header),
              vim.current.buffer.name]
   stdout, stderr = execute(command, text)
   if stdout:
@@ -77,30 +78,41 @@
   command = [binary, "-stdin", "-output-headers", "-db="+args.db,
              "-input="+args.input, vim.current.buffer.name]
   stdout, stderr = execute(command, text)
+  include_fixer_context = yaml.load(stdout)
+
   lines = stdout.splitlines()
-  if len(lines) < 2:
-    print "No header is included.\n"
+
+  symbol = include_fixer_context["SymbolIdentifier"]
+  headers = include_fixer_context["Headers"]
+
+  if not symbol:
+    print "The file is fine, no need to add a header.\n"
+    return;
+
+  if not headers:
+    print "Couldn't find a header for {0}.\n".format(symbol)
     return
 
   # The first line is the symbol name.
-  symbol = lines[0]
   # If there is only one suggested header, insert it directly.
-  if len(lines) == 2 or maximum_suggested_headers == 1:
-    InsertHeaderToVimBuffer(lines[1], text)
-    print "Added #include {0} for {1}.\n".format(lines[1], symbol)
+  if len(headers) == 1 or maximum_suggested_headers == 1:
+    InsertHeaderToVimBuffer({"SymbolIdentifier": symbol,
+                             "Headers":[headers[0]]}, text)
+    print "Added #include {0} for {1}.\n".format(header[0], symbol)
     return
 
   choices_message = ""
   index = 1;
-  for header in lines[1:1+maximum_suggested_headers]:
+  for header in headers[0:maximum_suggested_headers]:
     choices_message += "&{0} {1}\n".format(index, header)
     index += 1
 
   select = ShowDialog("choose a header file for {0}.".format(symbol),
                       choices_message)
   # Insert a selected header.
-  InsertHeaderToVimBuffer(lines[select], text)
-  print "Added #include {0} for {1}.\n".format(lines[select], symbol)
+  InsertHeaderToVimBuffer({"SymbolIdentifier": symbol,
+                           "Headers":[headers[select-1]]}, text)
+  print "Added #include {0} for {1}.\n".format(headers[select-1], symbol)
   return;
 
 
Index: include-fixer/tool/ClangIncludeFixer.cpp
===================================================================
--- include-fixer/tool/ClangIncludeFixer.cpp
+++ include-fixer/tool/ClangIncludeFixer.cpp
@@ -18,9 +18,25 @@
 #include "clang/Tooling/CommonOptionsParser.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/YAMLTraits.h"
 
 using namespace clang;
 using namespace llvm;
+using clang::include_fixer::IncludeFixerContext;
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(IncludeFixerContext)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)
+
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits<IncludeFixerContext> {
+  static void mapping(IO &io, IncludeFixerContext &Context) {
+    io.mapRequired("SymbolIdentifier", Context.SymbolIdentifier);
+    io.mapRequired("Headers", Context.Headers);
+  }
+};
+} // namespace yaml
+} // namespace llvm
 
 namespace {
 cl::OptionCategory IncludeFixerCategory("Tool options");
@@ -60,19 +76,21 @@
 
 cl::opt<bool> OutputHeaders(
     "output-headers",
-    cl::desc("Output the symbol being quired and all its relevant headers.\n"
-             "The first line is the symbol name; The other lines\n"
-             "are the headers: \n"
-             "   b::foo\n"
-             "   path/to/foo_a.h\n"
-             "   path/to/foo_b.h\n"),
+    cl::desc("Print the symbol being queried and all its relevant headers in\n"
+             "the YAML format to stdout:\n"
+             "  ---\n"
+             "  SymbolIdentifier: foo\n"
+             "  Headers: ['\"foo_a.h\"', '\"foo_b.h\"']\n"
+             "  ...\n"),
     cl::init(false), cl::cat(IncludeFixerCategory));
 
 cl::opt<std::string> InsertHeader(
     "insert-header",
     cl::desc("Insert a specific header. This should run with STDIN mode.\n"
              "The result is written to stdout. It is currently used for\n"
-             "editor integration."),
+             "editor integration. Support YAML/JSON format:\n"
+             "  -insert-header=\"{SymbolIdentifier: foo\n"
+             "                   Headers: ['\"foo_a.h\"']}\""),
     cl::init(""), cl::cat(IncludeFixerCategory));
 
 cl::opt<std::string>
@@ -168,9 +186,18 @@
       return 1;
     }
 
+    llvm::yaml::Input yin(InsertHeader);
+    IncludeFixerContext Context;
+    yin >> Context;
+
+    if (Context.Headers.empty()) {
+      errs() << "Expect exact one inserted header.\n";
+      return 1;
+    }
+
     tooling::Replacements Replacements =
         clang::include_fixer::createInsertHeaderReplacements(
-            Code->getBuffer(), FilePath, InsertHeader, InsertStyle);
+            Code->getBuffer(), FilePath, Context.Headers[0], InsertStyle);
     tooling::Replacements Replaces(Replacements.begin(), Replacements.end());
     std::string ChangedCode =
         tooling::applyAllReplacements(Code->getBuffer(), Replaces);
@@ -196,10 +223,8 @@
   }
 
   if (OutputHeaders) {
-    // FIXME: Output IncludeFixerContext as YAML.
-    llvm::outs() << Context.SymbolIdentifer << "\n";
-    for (const auto &Header : Context.Headers)
-      llvm::outs() << Header << "\n";
+    llvm::yaml::Output yout(llvm::outs());
+    yout << Context;
     return 0;
   }
 
Index: include-fixer/IncludeFixerContext.h
===================================================================
--- include-fixer/IncludeFixerContext.h
+++ include-fixer/IncludeFixerContext.h
@@ -19,7 +19,7 @@
 /// \brief A context for the symbol being queried.
 struct IncludeFixerContext {
   /// \brief The symbol name.
-  std::string SymbolIdentifer;
+  std::string SymbolIdentifier;
   /// \brief The headers which have SymbolIdentifier definitions.
   std::vector<std::string> Headers;
 };
Index: include-fixer/IncludeFixer.cpp
===================================================================
--- include-fixer/IncludeFixer.cpp
+++ include-fixer/IncludeFixer.cpp
@@ -193,10 +193,7 @@
   getIncludeFixerContext(const clang::SourceManager &SourceManager,
                          clang::HeaderSearch &HeaderSearch) {
     IncludeFixerContext FixerContext;
-    if (SymbolQueryResults.empty())
-      return FixerContext;
-
-    FixerContext.SymbolIdentifer = QuerySymbol;
+    FixerContext.SymbolIdentifier = QuerySymbol;
     for (const auto &Header : SymbolQueryResults)
       FixerContext.Headers.push_back(
           minimizeInclude(Header, SourceManager, HeaderSearch));
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to