[clang-tools-extra] r280824 - [include-fixer] Support finding headers for the symbol under cursor.

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 7 09:34:36 PDT 2016


Author: hokein
Date: Wed Sep  7 11:34:35 2016
New Revision: 280824

URL: http://llvm.org/viewvc/llvm-project?rev=280824&view=rev
Log:
[include-fixer] Support finding headers for the symbol under cursor.

Summary:
* Add a `query-symbol` option to query symbol without parsing the source file.
* Update Vim & Emacs integration scripts.

Reviewers: bkramer, massberg

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D24075

Added:
    clang-tools-extra/trunk/test/include-fixer/query_symbol.cpp
Modified:
    clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h
    clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp
    clang-tools-extra/trunk/include-fixer/tool/clang-include-fixer.el
    clang-tools-extra/trunk/include-fixer/tool/clang-include-fixer.py

Modified: clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h?rev=280824&r1=280823&r2=280824&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h (original)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h Wed Sep  7 11:34:35 2016
@@ -54,6 +54,8 @@ public:
              int LineNumber, const std::vector<Context> &Contexts,
              unsigned NumOccurrences = 0);
 
+  void SetFilePath(llvm::StringRef Path) { FilePath = Path; }
+
   /// \brief Get symbol name.
   llvm::StringRef getName() const { return Name; }
 

Modified: clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp?rev=280824&r1=280823&r2=280824&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp (original)
+++ clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp Wed Sep  7 11:34:35 2016
@@ -98,6 +98,12 @@ cl::opt<std::string> Input("input",
                            cl::desc("String to initialize the database"),
                            cl::cat(IncludeFixerCategory));
 
+cl::opt<std::string>
+    QuerySymbol("query-symbol",
+                 cl::desc("Query a given symbol (e.g. \"a::b::foo\") in\n"
+                          "database directly without parsing the file."),
+                 cl::cat(IncludeFixerCategory));
+
 cl::opt<bool>
     MinimizeIncludePaths("minimize-paths",
                          cl::desc("Whether to minimize added include paths"),
@@ -236,6 +242,7 @@ int includeFixerMain(int argc, const cha
   tooling::ClangTool tool(options.getCompilations(),
                           options.getSourcePathList());
 
+  llvm::StringRef SourceFilePath = options.getSourcePathList().front();
   // In STDINMode, we override the file content with the <stdin> input.
   // Since `tool.mapVirtualFile` takes `StringRef`, we define `Code` outside of
   // the if-block so that `Code` is not released after the if-block.
@@ -253,7 +260,7 @@ int includeFixerMain(int argc, const cha
     if (Code->getBufferSize() == 0)
       return 0;  // Skip empty files.
 
-    tool.mapVirtualFile(options.getSourcePathList().front(), Code->getBuffer());
+    tool.mapVirtualFile(SourceFilePath, Code->getBuffer());
   }
 
   if (!InsertHeader.empty()) {
@@ -314,10 +321,31 @@ int includeFixerMain(int argc, const cha
 
   // Set up data source.
   std::unique_ptr<include_fixer::SymbolIndexManager> SymbolIndexMgr =
-      createSymbolIndexManager(options.getSourcePathList().front());
+      createSymbolIndexManager(SourceFilePath);
   if (!SymbolIndexMgr)
     return 1;
 
+  // Query symbol mode.
+  if (!QuerySymbol.empty()) {
+    auto MatchedSymbols = SymbolIndexMgr->search(QuerySymbol);
+    for (auto &Symbol : MatchedSymbols) {
+      std::string HeaderPath = Symbol.getFilePath().str();
+      Symbol.SetFilePath(((HeaderPath[0] == '"' || HeaderPath[0] == '<')
+                              ? HeaderPath
+                              : "\"" + HeaderPath + "\""));
+    }
+
+    // We leave an empty symbol range as we don't know the range of the symbol
+    // being queried in this mode. include-fixer won't add namespace qualifiers
+    // if the symbol range is empty, which also fits this case.
+    IncludeFixerContext::QuerySymbolInfo Symbol;
+    Symbol.RawIdentifier = QuerySymbol;
+    auto Context =
+        IncludeFixerContext(SourceFilePath, {Symbol}, MatchedSymbols);
+    writeToJson(llvm::outs(), Context);
+    return 0;
+  }
+
   // Now run our tool.
   std::vector<include_fixer::IncludeFixerContext> Contexts;
   include_fixer::IncludeFixerActionFactory Factory(*SymbolIndexMgr, Contexts,

Modified: clang-tools-extra/trunk/include-fixer/tool/clang-include-fixer.el
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/tool/clang-include-fixer.el?rev=280824&r1=280823&r2=280824&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/tool/clang-include-fixer.el (original)
+++ clang-tools-extra/trunk/include-fixer/tool/clang-include-fixer.el Wed Sep  7 11:34:35 2016
@@ -36,11 +36,17 @@
 
 (defcustom clang-include-fixer-init-string
   ""
-  "clang-include-fixer input format."
+  "clang-include-fixer init string."
   :group 'clang-include-fixer
   :type 'string
   :risky t)
 
+(defcustom clang-include-fixer-query-mode
+  nil
+  "clang-include-fixer query mode."
+  :group 'clang-include-fixer
+  :type 'boolean
+  :risky t)
 
 (defun clang-include-fixer-call-executable (callee
                                             include-fixer-parameter-a
@@ -197,11 +203,28 @@
   (message (concat "Calling the include fixer. "
            "This might take some seconds. Please wait."))
 
-  (clang-include-fixer-call-executable
-   'clang-include-fixer-add-header
-   (concat "-db=" clang-include-fixer-input-format)
-   (concat "-input=" clang-include-fixer-init-string)
-   "-output-headers"))
+  (if clang-include-fixer-query-mode
+      (let (p1 p2)
+      (save-excursion
+        (skip-chars-backward "-a-zA-Z0-9_:")
+        (setq p1 (point))
+        (skip-chars-forward "-a-zA-Z0-9_:")
+        (setq p2 (point))
+        (setq query-symbol (buffer-substring-no-properties p1 p2))
+        (if (string= "" query-symbol)
+            (message "Skip querying empty symbol.")
+          (clang-include-fixer-call-executable
+            'clang-include-fixer-add-header
+            (concat "-db=" clang-include-fixer-input-format)
+            (concat "-input=" clang-include-fixer-init-string)
+            (concat "-query-symbol=" (thing-at-point 'symbol))
+          ))))
+    (clang-include-fixer-call-executable
+      'clang-include-fixer-add-header
+      (concat "-db=" clang-include-fixer-input-format)
+      (concat "-input=" clang-include-fixer-init-string)
+      "-output-headers"))
+  )
 
 (provide 'clang-include-fixer)
 ;;; clang-include-fixer.el ends here

Modified: clang-tools-extra/trunk/include-fixer/tool/clang-include-fixer.py
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/tool/clang-include-fixer.py?rev=280824&r1=280823&r2=280824&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/tool/clang-include-fixer.py (original)
+++ clang-tools-extra/trunk/include-fixer/tool/clang-include-fixer.py Wed Sep  7 11:34:35 2016
@@ -17,9 +17,10 @@
 
 import argparse
 import difflib
+import json
+import re
 import subprocess
 import vim
-import json
 
 # set g:clang_include_fixer_path to the path to clang-include-fixer if it is not
 # on the path.
@@ -44,6 +45,10 @@ jump_to_include = False
 if vim.eval('exists("g:clang_include_fixer_jump_to_include")') == "1":
   jump_to_include = vim.eval('g:clang_include_fixer_jump_to_include') != "0"
 
+query_mode = True
+if vim.eval('exists("g:clang_include_fixer_query_mode")') == "1":
+  query_mode = vim.eval('g:clang_include_fixer_query_mode') != "0"
+
 
 def GetUserSelection(message, headers, maximum_suggested_headers):
   eval_message = message + '\n'
@@ -105,6 +110,25 @@ def InsertHeaderToVimBuffer(header, text
       vim.current.window.cursor = (line_num, 0)
 
 
+# The vim internal implementation (expand("cword"/"cWORD")) doesn't support
+# our use case very well, we re-implement our own one.
+def get_symbol_under_cursor():
+  line = vim.eval("line(\".\")")
+  # column number in vim is 1-based.
+  col = int(vim.eval("col(\".\")")) - 1
+  line_text = vim.eval("getline({0})".format(line))
+  if len(line_text) == 0: return ""
+  symbol_pos_begin = col
+  p = re.compile('[a-zA-Z0-9:_]')
+  while symbol_pos_begin >= 0 and p.match(line_text[symbol_pos_begin]):
+    symbol_pos_begin -= 1
+
+  symbol_pos_end = col
+  while symbol_pos_end < len(line_text) and p.match(line_text[symbol_pos_end]):
+    symbol_pos_end += 1
+  return line_text[symbol_pos_begin+1:symbol_pos_end]
+
+
 def main():
   parser = argparse.ArgumentParser(
       description='Vim integration for clang-include-fixer')
@@ -118,9 +142,18 @@ def main():
   buf = vim.current.buffer
   text = '\n'.join(buf)
 
-  # Run command to get all headers.
-  command = [binary, "-stdin", "-output-headers", "-db=" + args.db,
-             "-input=" + args.input, vim.current.buffer.name]
+  if query_mode:
+    symbol = get_symbol_under_cursor()
+    if len(symbol) == 0:
+      print "Skip querying empty symbol."
+      return
+    command = [binary, "-stdin", "-query-symbol="+get_symbol_under_cursor(),
+               "-db=" + args.db, "-input=" + args.input,
+               vim.current.buffer.name]
+  else:
+    # Run command to get all headers.
+    command = [binary, "-stdin", "-output-headers", "-db=" + args.db,
+               "-input=" + args.input, vim.current.buffer.name]
   stdout, stderr = execute(command, text)
   if stderr:
     print >> sys.stderr, "Error while running clang-include-fixer: " + stderr

Added: clang-tools-extra/trunk/test/include-fixer/query_symbol.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/include-fixer/query_symbol.cpp?rev=280824&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/include-fixer/query_symbol.cpp (added)
+++ clang-tools-extra/trunk/test/include-fixer/query_symbol.cpp Wed Sep  7 11:34:35 2016
@@ -0,0 +1,13 @@
+// RUN: clang-include-fixer -db=fixed -input='foo= "foo.h","bar.h"' -query-symbol="foo" test.cpp -- | FileCheck %s
+
+// CHECK:     "FilePath": "test.cpp",
+// CHECK-NEXT:"QuerySymbolInfos": [
+// CHECK-NEXT:   {"RawIdentifier": "foo",
+// CHECK-NEXT:    "Range":{"Offset":0,"Length":0}}
+// CHECK-NEXT:],
+// CHECK-NEXT:"HeaderInfos": [
+// CHECK-NEXT:  {"Header": "\"foo.h\"",
+// CHECK-NEXT:   "QualifiedName": "foo"},
+// CHECK-NEXT:  {"Header": "\"bar.h\"",
+// CHECK-NEXT:   "QualifiedName": "foo"}
+// CHECK-NEXT:]




More information about the cfe-commits mailing list