1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
//===--- ASTSlice.h - Represents a portion of the AST ---------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_TOOLING_REFACTOR_ASTSLICE_H
#define LLVM_CLANG_LIB_TOOLING_REFACTOR_ASTSLICE_H
#include "clang/AST/DeclBase.h"
#include "clang/AST/Stmt.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {
class NamedDecl;
namespace tooling {
/// Represents a set of statements that overlap with the selection range.
struct SelectedStmtSet {
/// The outermost statement that contains the start of the selection range.
const Stmt *containsSelectionRangeStart = nullptr;
/// The outermost statement that contains the end of the selection range.
const Stmt *containsSelectionRangeEnd = nullptr;
/// The innermost statement that contains the entire selection range.
const Stmt *containsSelectionRange = nullptr;
/// The index of the innermost statement that contains the entire selection
/// range. The index points into the NodeTree stored in the \c ASTSlice.
std::optional<unsigned> containsSelectionRangeIndex;
static SelectedStmtSet createFromEntirelySelected(const Stmt *S,
unsigned Index);
/// Returns true if the compound statement is not fully selected.
bool isCompoundStatementPartiallySelected() const {
assert(containsSelectionRange && "No statement selected");
return isa<CompoundStmt>(containsSelectionRange) &&
(containsSelectionRangeStart || containsSelectionRangeEnd);
}
};
/// A portion of the AST that is located around the location and/or source
/// range of interest.
class ASTSlice {
public:
struct Node {
enum SelectionRangeOverlapKind {
UnknownOverlap,
ContainsSelectionRangeStart,
ContainsSelectionRangeEnd,
ContainsSelectionRange
};
llvm::PointerUnion<const Stmt *, const Decl *> StmtOrDecl;
const Stmt *ParentStmt;
const Decl *ParentDecl;
SourceRange Range;
SelectionRangeOverlapKind SelectionRangeOverlap = UnknownOverlap;
const Stmt *getStmtOrNull() const {
return StmtOrDecl.dyn_cast<const Stmt *>();
}
const Decl *getDeclOrNull() const {
return StmtOrDecl.dyn_cast<const Decl *>();
}
Node(const Stmt *S, const Stmt *ParentStmt, const Decl *ParentDecl,
SourceRange Range)
: StmtOrDecl(S), ParentStmt(ParentStmt), ParentDecl(ParentDecl),
Range(Range) {}
Node(const Decl *D, const Decl *ParentDecl, SourceRange Range)
: StmtOrDecl(D), ParentStmt(nullptr), ParentDecl(ParentDecl),
Range(Range) {}
};
/// Represents a statement that overlaps with the selection range/point.
class SelectedStmt {
ASTSlice &Slice;
const Stmt *S;
unsigned Index;
friend class ASTSlice;
SelectedStmt(ASTSlice &Slice, const Stmt *S, unsigned Index);
public:
const Stmt *getStmt() { return S; }
const Decl *getParentDecl();
};
/// Represents a declaration that overlaps with the selection range/point.
class SelectedDecl {
const Decl *D;
friend class ASTSlice;
SelectedDecl(const Decl *D);
public:
const Decl *getDecl() { return D; }
};
ASTSlice(SourceLocation Location, SourceRange SelectionRange,
ASTContext &Context);
/// Returns true if the given source range overlaps with the selection.
bool isSourceRangeSelected(CharSourceRange Range) const;
enum SelectionSearchOptions {
/// Search with-in the innermost declaration only, including the declaration
/// itself without inspecting any other outer declarations.
InnermostDeclOnly = 1
};
/// Returns the statement that results in true when passed into \p Predicate
/// that's nearest to the location of interest, or \c None if such statement
/// isn't found.
std::optional<SelectedStmt>
nearestSelectedStmt(llvm::function_ref<bool(const Stmt *)> Predicate);
/// Returns the statement of the given class that's nearest to the location
/// of interest, or \c None if such statement isn't found.
std::optional<SelectedStmt> nearestSelectedStmt(Stmt::StmtClass Class);
/// TODO: Remove in favour of nearestStmt that returns \c SelectedStmt
const Stmt *nearestStmt(Stmt::StmtClass Class);
/// Returns the declaration that overlaps with the selection range, is
/// nearest to the location of interest and that results in true when passed
/// into \p Predicate, or \c None if such declaration isn't found.
std::optional<SelectedDecl>
innermostSelectedDecl(llvm::function_ref<bool(const Decl *)> Predicate,
unsigned Options = 0);
/// Returns the declaration closest to the location of interest whose decl
/// kind is in \p Classes, or \c None if no such decl can't be found.
std::optional<SelectedDecl>
innermostSelectedDecl(ArrayRef<Decl::Kind> Classes, unsigned Options = 0);
/// Returns the set of statements that overlap with the selection range.
std::optional<SelectedStmtSet> getSelectedStmtSet();
/// Returns true if the statement with the given index is contained in a
/// compound statement that overlaps with the selection range.
bool isContainedInCompoundStmt(unsigned Index);
/// Returns the declaration that contains the statement at the given index.
const Decl *parentDeclForIndex(unsigned Index);
/// Returns the statement that contains the statement at the given index.
const Stmt *parentStmtForIndex(unsigned Index);
private:
std::optional<SelectedStmtSet> computeSelectedStmtSet();
/// Returns the innermost declaration that contains both the start and the
/// end of the selection range.
std::optional<SelectedDecl> getInnermostCompletelySelectedDecl();
/// The lowest element is the top of the hierarchy
SmallVector<Node, 16> NodeTree;
ASTContext &Context;
SourceLocation SelectionLocation;
SourceRange SelectionRange;
std::optional<std::optional<SelectedStmtSet>> CachedSelectedStmtSet;
std::optional<std::optional<SelectedDecl>> CachedSelectedInnermostDecl;
};
} // end namespace tooling
} // end namespace clang
#endif // LLVM_CLANG_LIB_TOOLING_REFACTOR_ASTSLICE_H
|