[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