[clang-tools-extra] r352875 - [clangd] Lib to compute and represent selection under cursor.

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 1 07:09:41 PST 2019


Author: sammccall
Date: Fri Feb  1 07:09:41 2019
New Revision: 352875

URL: http://llvm.org/viewvc/llvm-project?rev=352875&view=rev
Log:
[clangd] Lib to compute and represent selection under cursor.

Summary:
The primary problem this solves is to expose the codeAction selection to
AST-based refactorings in a way that makes it easy and efficient for them to
bind to the right parts of the AST.

It should also allow us to make XRefs based features (textDocument/definition)
more robust, more easily implement textDocument/typeDefinition etc.
As an example, template parameter references can be identified without special
handling.
There should be slight speedup too: we can prune most of the AST traversal
in most cases.

Elephant in the room: this is similar-but-different to Tooling/Refactoring/ASTSelection.
That captures a smaller set of AST nodes, has a slightly different way of
representing selections, and generally has mare features and does more work.
The overall shape is pretty similar, and yet I can't quite get to behave as I
expect.

Reviewers: ilya-biryukov, kadircet

Subscribers: mgorny, ioeric, MaskRay, jkorous, mgrang, arphaman

Tags: #clang

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

Modified:
    clang-tools-extra/trunk/clangd/Selection.cpp

Modified: clang-tools-extra/trunk/clangd/Selection.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Selection.cpp?rev=352875&r1=352874&r2=352875&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Selection.cpp (original)
+++ clang-tools-extra/trunk/clangd/Selection.cpp Fri Feb  1 07:09:41 2019
@@ -112,9 +112,15 @@ private:
   // An optimization for a common case: nodes outside macro expansions that
   // don't intersect the selection may be recursively skipped.
   bool canSafelySkipNode(SourceRange S) {
+<<<<<<< HEAD
     auto B = SM.getDecomposedLoc(S.getBegin());
     auto E = SM.getDecomposedLoc(S.getEnd());
     if (B.first != SelFile || E.first != SelFile)
+=======
+    auto B = SM.getDecomposedLoc(S.getBegin()),
+         E = SM.getDecomposedLoc(S.getEnd());
+    if (B.first != SM.getMainFileID() || E.first != SM.getMainFileID())
+>>>>>>> [clangd] Lib to compute and represent selection under cursor.
       return false;
     return B.second >= SelEnd || E.second < SelBeginTokenStart;
   }
@@ -156,6 +162,7 @@ private:
     //     LOOP_FOREVER( ++x; )
     //   }
     // Selecting "++x" or "x" will do the right thing.
+<<<<<<< HEAD
     auto B = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getBegin()));
     auto E = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getEnd()));
     // Otherwise, nodes in macro expansions can't be selected.
@@ -164,6 +171,16 @@ private:
     // Cheap test: is there any overlap at all between the selection and range?
     // Note that E.second is the *start* of the last token, which is why we
     // compare against the "rounded-down" SelBegin.
+=======
+    auto B = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getBegin())),
+         E = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getEnd()));
+    // Otherwise, nodes in macro expansions can't be selected.
+    if (B.first != SM.getMainFileID() || E.first != SM.getMainFileID())
+      return SelectionTree::Unselected;
+    // Cheap test: is there any overlap at all between the selection and range?
+    // Note that E.second is the *start* of the last token, which is why we
+    // compare against the "rounded-down" MinOffset.
+>>>>>>> [clangd] Lib to compute and represent selection under cursor.
     if (B.second >= SelEnd || E.second < SelBeginTokenStart)
       return SelectionTree::Unselected;
 
@@ -196,7 +213,11 @@ private:
       CharSourceRange R = SM.getExpansionRange(N->ASTNode.getSourceRange());
       auto B = SM.getDecomposedLoc(R.getBegin());
       auto E = SM.getDecomposedLoc(R.getEnd());
+<<<<<<< HEAD
       if (B.first != SelFile || E.first != SelFile)
+=======
+      if (B.first != SM.getMainFileID() || E.first != SM.getMainFileID())
+>>>>>>> [clangd] Lib to compute and represent selection under cursor.
         continue;
       assert(R.isTokenRange());
       // Try to cover up to the next token, spaces between children don't count.
@@ -222,6 +243,7 @@ private:
   SourceManager &SM;
   const LangOptions &LangOpts;
   std::stack<Node *> Stack;
+<<<<<<< HEAD
   std::deque<Node> Nodes; // Stable pointers as we add more nodes.
   // Half-open selection range.
   unsigned SelBegin;
@@ -233,6 +255,10 @@ private:
   // range.end + measureToken(range.end) < SelBegin (assuming range.end points
   // to a token), and it saves a lex every time.
   unsigned SelBeginTokenStart;
+=======
+  std::deque<Node> Nodes;
+  unsigned SelBegin, SelEnd, SelBeginTokenStart;
+>>>>>>> [clangd] Lib to compute and represent selection under cursor.
 };
 
 } // namespace
@@ -252,9 +278,16 @@ void SelectionTree::print(llvm::raw_ostr
 }
 
 // Decide which selection emulates a "point" query in between characters.
+<<<<<<< HEAD
 static std::pair<unsigned, unsigned> pointBounds(unsigned Offset, FileID FID,
                                                  ASTContext &AST) {
   StringRef Buf = AST.getSourceManager().getBufferData(FID);
+=======
+static std::pair<unsigned, unsigned> pointBounds(unsigned Offset,
+                                                 ASTContext &AST) {
+  StringRef Buf = AST.getSourceManager().getBufferData(
+      AST.getSourceManager().getMainFileID());
+>>>>>>> [clangd] Lib to compute and represent selection under cursor.
   // Edge-cases where the choice is forced.
   if (Buf.size() == 0)
     return {0, 0};
@@ -272,6 +305,7 @@ static std::pair<unsigned, unsigned> poi
 
 SelectionTree::SelectionTree(ASTContext &AST, unsigned Begin, unsigned End)
     : PrintPolicy(AST.getLangOpts()) {
+<<<<<<< HEAD
   // No fundamental reason the selection needs to be in the main file,
   // but that's all clangd has needed so far.
   FileID FID = AST.getSourceManager().getMainFileID();
@@ -286,6 +320,16 @@ SelectionTree::SelectionTree(ASTContext
 SelectionTree::SelectionTree(ASTContext &AST, unsigned Offset)
     : SelectionTree(AST, Offset, Offset) {}
 
+=======
+  if (Begin == End)
+    std::tie(Begin, End) = pointBounds(Begin, AST);
+  PrintPolicy.TerseOutput = true;
+
+  Nodes = SelectionVisitor(AST, Begin, End).take();
+  Root = Nodes.empty() ? nullptr : &Nodes.front();
+}
+
+>>>>>>> [clangd] Lib to compute and represent selection under cursor.
 const Node *SelectionTree::commonAncestor() const {
   if (!Root)
     return nullptr;
@@ -297,5 +341,11 @@ const Node *SelectionTree::commonAncesto
   }
 }
 
+<<<<<<< HEAD
+=======
+SelectionTree::SelectionTree(ASTContext &AST, unsigned Offset)
+    : SelectionTree(AST, Offset, Offset) {}
+
+>>>>>>> [clangd] Lib to compute and represent selection under cursor.
 } // namespace clangd
 } // namespace clang




More information about the cfe-commits mailing list