diff clang-tools-extra/clangd/SemanticSelection.cpp @ 150:1d019706d866

LLVM10
author anatofuz
date Thu, 13 Feb 2020 15:10:13 +0900
parents
children 0572611fdcc8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/clang-tools-extra/clangd/SemanticSelection.cpp	Thu Feb 13 15:10:13 2020 +0900
@@ -0,0 +1,64 @@
+//===--- SemanticSelection.cpp -----------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "SemanticSelection.h"
+#include "ParsedAST.h"
+#include "Protocol.h"
+#include "Selection.h"
+#include "SourceCode.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+// Adds Range \p R to the Result if it is distinct from the last added Range.
+// Assumes that only consecutive ranges can coincide.
+void addIfDistinct(const Range &R, std::vector<Range> &Result) {
+  if (Result.empty() || Result.back() != R) {
+    Result.push_back(R);
+  }
+}
+} // namespace
+
+llvm::Expected<std::vector<Range>> getSemanticRanges(ParsedAST &AST,
+                                                     Position Pos) {
+  std::vector<Range> Result;
+  const auto &SM = AST.getSourceManager();
+  const auto &LangOpts = AST.getLangOpts();
+
+  auto FID = SM.getMainFileID();
+  auto Offset = positionToOffset(SM.getBufferData(FID), Pos);
+  if (!Offset) {
+    return Offset.takeError();
+  }
+
+  // Get node under the cursor.
+  SelectionTree ST(AST.getASTContext(), AST.getTokens(), *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 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, Result);
+  }
+  return Result;
+}
+
+} // namespace clangd
+} // namespace clang