[PATCH] D84975: [clangd][WIP] Make use of SyntaxTrees for SemanticSelection

Kadir Cetinkaya via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 30 12:45:05 PDT 2020


kadircet created this revision.
Herald added subscribers: cfe-commits, usaxena95, arphaman, jkorous.
Herald added a project: clang.
kadircet requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

This patch is not intended for production, it is merely an experiment
to see how SyntaxTrees can be used inside clangd.

Depends on D84973 <https://reviews.llvm.org/D84973>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D84975

Files:
  clang-tools-extra/clangd/SemanticSelection.cpp


Index: clang-tools-extra/clangd/SemanticSelection.cpp
===================================================================
--- clang-tools-extra/clangd/SemanticSelection.cpp
+++ clang-tools-extra/clangd/SemanticSelection.cpp
@@ -11,9 +11,15 @@
 #include "Protocol.h"
 #include "Selection.h"
 #include "SourceCode.h"
+#include "support/Logger.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Tooling/Syntax/BuildTree.h"
+#include "clang/Tooling/Syntax/Tokens.h"
+#include "clang/Tooling/Syntax/Tree.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/Error.h"
 
 namespace clang {
@@ -41,12 +47,31 @@
     collectFoldingRanges(Child, Result);
 }
 
+syntax::Leaf *leafContaining(const syntax::Token *Tok, syntax::Tree *Root,
+                             syntax::Arena &A, const SourceManager &SM) {
+  if (!Tok)
+    return nullptr;
+  vlog("searching for {0} in:\n{1}", Tok->text(SM), Root->dump(A));
+  for (auto *C = Root->firstChild(); C; C = C->nextSibling()) {
+    if (auto *L = llvm::dyn_cast<syntax::Leaf>(C)) {
+      if (L->token() == Tok)
+        return L;
+    } else if (auto *T = llvm::dyn_cast<syntax::Tree>(C)) {
+      if (T->firstLeaf()->token() <= Tok && Tok <= T->lastLeaf()->token())
+        return leafContaining(Tok, T, A, SM);
+    }
+  }
+  return nullptr;
+}
+
 } // namespace
 
 llvm::Expected<SelectionRange> getSemanticRanges(ParsedAST &AST, Position Pos) {
+  syntax::Arena A(AST.getSourceManager(), AST.getLangOpts(), AST.getTokens());
+  auto *STree =
+      syntax::buildSyntaxTree(A, *AST.getASTContext().getTranslationUnitDecl());
   std::vector<Range> Ranges;
   const auto &SM = AST.getSourceManager();
-  const auto &LangOpts = AST.getLangOpts();
 
   auto FID = SM.getMainFileID();
   auto Offset = positionToOffset(SM.getBufferData(FID), Pos);
@@ -55,24 +80,23 @@
   }
 
   // Get node under the cursor.
-  SelectionTree ST = SelectionTree::createRight(
-      AST.getASTContext(), AST.getTokens(), *Offset, *Offset);
-  for (const auto *Node = ST.commonAncestor(); Node != nullptr;
-       Node = Node->Parent) {
-    if (const Decl *D = Node->ASTNode.get<Decl>()) {
-      if (llvm::isa<TranslationUnitDecl>(D)) {
-        break;
+  auto Toks = AST.getTokens().expandedForSpelled(syntax::spelledTokensTouching(
+      SM.getComposedLoc(FID, *Offset), AST.getTokens()));
+  Toks.push_back({});
+  for (const auto &Tok : Toks.front()) {
+    if (auto *L = leafContaining(&Tok, STree, A, SM)) {
+      for (const syntax::Tree *Node = L->parent(); Node != nullptr;
+           Node = Node->parent()) {
+        SourceRange SR(Node->firstLeaf()->token()->location(),
+                       Node->lastLeaf()->token()->location());
+        auto FR = toHalfOpenFileRange(SM, AST.getLangOpts(), SR);
+        if (!FR || SM.getFileID(SR.getBegin()) != SM.getMainFileID())
+          continue;
+        addIfDistinct(halfOpenToRange(SM, CharSourceRange::getCharRange(*FR)),
+                      Ranges);
       }
+      break;
     }
-
-    auto SR = toHalfOpenFileRange(SM, LangOpts, Node->ASTNode.getSourceRange());
-    if (!SR.hasValue() || SM.getFileID(SR->getBegin()) != SM.getMainFileID()) {
-      continue;
-    }
-    Range R;
-    R.start = sourceLocToPosition(SM, SR->getBegin());
-    R.end = sourceLocToPosition(SM, SR->getEnd());
-    addIfDistinct(R, Ranges);
   }
 
   if (Ranges.empty()) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D84975.282020.patch
Type: text/x-patch
Size: 3471 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200730/05751afc/attachment-0001.bin>


More information about the cfe-commits mailing list