File: ASTSlice.h

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (181 lines) | stat: -rw-r--r-- 6,483 bytes parent folder | download
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