clang-tools  11.0.0git
SemanticSelection.cpp
Go to the documentation of this file.
1 //===--- SemanticSelection.cpp -----------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "SemanticSelection.h"
9 #include "ParsedAST.h"
10 #include "Protocol.h"
11 #include "Selection.h"
12 #include "SourceCode.h"
13 #include "clang/AST/DeclBase.h"
14 #include "clang/Basic/SourceLocation.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/Support/Error.h"
17 
18 namespace clang {
19 namespace clangd {
20 namespace {
21 // Adds Range \p R to the Result if it is distinct from the last added Range.
22 // Assumes that only consecutive ranges can coincide.
23 void addIfDistinct(const Range &R, std::vector<Range> &Result) {
24  if (Result.empty() || Result.back() != R) {
25  Result.push_back(R);
26  }
27 }
28 } // namespace
29 
30 llvm::Expected<SelectionRange> getSemanticRanges(ParsedAST &AST, Position Pos) {
31  std::vector<Range> Ranges;
32  const auto &SM = AST.getSourceManager();
33  const auto &LangOpts = AST.getLangOpts();
34 
35  auto FID = SM.getMainFileID();
36  auto Offset = positionToOffset(SM.getBufferData(FID), Pos);
37  if (!Offset) {
38  return Offset.takeError();
39  }
40 
41  // Get node under the cursor.
43  AST.getASTContext(), AST.getTokens(), *Offset, *Offset);
44  for (const auto *Node = ST.commonAncestor(); Node != nullptr;
45  Node = Node->Parent) {
46  if (const Decl *D = Node->ASTNode.get<Decl>()) {
47  if (llvm::isa<TranslationUnitDecl>(D)) {
48  break;
49  }
50  }
51 
52  auto SR = toHalfOpenFileRange(SM, LangOpts, Node->ASTNode.getSourceRange());
53  if (!SR.hasValue() || SM.getFileID(SR->getBegin()) != SM.getMainFileID()) {
54  continue;
55  }
56  Range R;
57  R.start = sourceLocToPosition(SM, SR->getBegin());
58  R.end = sourceLocToPosition(SM, SR->getEnd());
59  addIfDistinct(R, Ranges);
60  }
61 
62  if (Ranges.empty()) {
63  // LSP provides no way to signal "the point is not within a semantic range".
64  // Return an empty range at the point.
66  Empty.range.start = Empty.range.end = Pos;
67  return std::move(Empty);
68  }
69 
70  // Convert to the LSP linked-list representation.
72  Head.range = std::move(Ranges.front());
74  for (auto &Range :
75  llvm::makeMutableArrayRef(Ranges.data(), Ranges.size()).drop_front()) {
76  Tail->parent = std::make_unique<SelectionRange>();
77  Tail = Tail->parent.get();
78  Tail->range = std::move(Range);
79  }
80 
81  return std::move(Head);
82 }
83 
84 } // namespace clangd
85 } // namespace clang
const FunctionDecl * Decl
Position start
The range&#39;s start position.
Definition: Protocol.h:175
const LangOptions & getLangOpts() const
Definition: ParsedAST.h:81
const syntax::TokenBuffer & getTokens() const
Tokens recorded while parsing the main file.
Definition: ParsedAST.h:103
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
Definition: ParsedAST.cpp:471
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
Definition: SourceCode.cpp:175
static SelectionTree createRight(ASTContext &AST, const syntax::TokenBuffer &Tokens, unsigned Begin, unsigned End)
Definition: Selection.cpp:784
Position Pos
Definition: SourceCode.cpp:649
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
Definition: SourceCode.cpp:220
Stores and provides access to parsed AST.
Definition: ParsedAST.h:48
llvm::Optional< SourceRange > toHalfOpenFileRange(const SourceManager &SM, const LangOptions &LangOpts, SourceRange R)
Turns a token range into a half-open range and checks its correctness.
Definition: SourceCode.cpp:428
SourceManager & getSourceManager()
Definition: ParsedAST.h:74
size_t Offset
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Range range
The range of this selection range.
Definition: Protocol.h:1471
CharSourceRange Range
SourceRange for the file name.
llvm::Expected< SelectionRange > getSemanticRanges(ParsedAST &AST, Position Pos)
Returns the list of all interesting ranges around the Position Pos.
const Node * commonAncestor() const
Definition: Selection.cpp:814
Position end
The range&#39;s end position.
Definition: Protocol.h:178