Home | History | Annotate | Line # | Download | only in Refactoring
      1 //===--- ASTSelection.h - Clang refactoring library -----------------------===//
      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 
      9 #ifndef LLVM_CLANG_TOOLING_REFACTOR_AST_SELECTION_H
     10 #define LLVM_CLANG_TOOLING_REFACTOR_AST_SELECTION_H
     11 
     12 #include "clang/AST/ASTTypeTraits.h"
     13 #include "clang/AST/Stmt.h"
     14 #include "clang/Basic/LLVM.h"
     15 #include "clang/Basic/SourceLocation.h"
     16 #include "llvm/Support/raw_ostream.h"
     17 #include <vector>
     18 
     19 namespace clang {
     20 
     21 class ASTContext;
     22 
     23 namespace tooling {
     24 
     25 enum class SourceSelectionKind {
     26   /// A node that's not selected.
     27   None,
     28 
     29   /// A node that's considered to be selected because the whole selection range
     30   /// is inside of its source range.
     31   ContainsSelection,
     32   /// A node that's considered to be selected because the start of the selection
     33   /// range is inside its source range.
     34   ContainsSelectionStart,
     35   /// A node that's considered to be selected because the end of the selection
     36   /// range is inside its source range.
     37   ContainsSelectionEnd,
     38 
     39   /// A node that's considered to be selected because the node is entirely in
     40   /// the selection range.
     41   InsideSelection,
     42 };
     43 
     44 /// Represents a selected AST node.
     45 ///
     46 /// AST selection is represented using a tree of \c SelectedASTNode. The tree
     47 /// follows the top-down shape of the actual AST. Each selected node has
     48 /// a selection kind. The kind might be none as the node itself might not
     49 /// actually be selected, e.g. a statement in macro whose child is in a macro
     50 /// argument.
     51 struct SelectedASTNode {
     52   DynTypedNode Node;
     53   SourceSelectionKind SelectionKind;
     54   std::vector<SelectedASTNode> Children;
     55 
     56   SelectedASTNode(const DynTypedNode &Node, SourceSelectionKind SelectionKind)
     57       : Node(Node), SelectionKind(SelectionKind) {}
     58   SelectedASTNode(SelectedASTNode &&) = default;
     59   SelectedASTNode &operator=(SelectedASTNode &&) = default;
     60 
     61   void dump(llvm::raw_ostream &OS = llvm::errs()) const;
     62 
     63   using ReferenceType = std::reference_wrapper<const SelectedASTNode>;
     64 };
     65 
     66 /// Traverses the given ASTContext and creates a tree of selected AST nodes.
     67 ///
     68 /// \returns None if no nodes are selected in the AST, or a selected AST node
     69 /// that corresponds to the TranslationUnitDecl otherwise.
     70 Optional<SelectedASTNode> findSelectedASTNodes(const ASTContext &Context,
     71                                                SourceRange SelectionRange);
     72 
     73 /// An AST selection value that corresponds to a selection of a set of
     74 /// statements that belong to one body of code (like one function).
     75 ///
     76 /// For example, the following selection in the source.
     77 ///
     78 /// \code
     79 /// void function() {
     80 ///  // selection begin:
     81 ///  int x = 0;
     82 ///  {
     83 ///     // selection end
     84 ///     x = 1;
     85 ///  }
     86 ///  x = 2;
     87 /// }
     88 /// \endcode
     89 ///
     90 /// Would correspond to a code range selection of statements "int x = 0"
     91 /// and the entire compound statement that follows it.
     92 ///
     93 /// A \c CodeRangeASTSelection value stores references to the full
     94 /// \c SelectedASTNode tree and should not outlive it.
     95 class CodeRangeASTSelection {
     96 public:
     97   CodeRangeASTSelection(CodeRangeASTSelection &&) = default;
     98   CodeRangeASTSelection &operator=(CodeRangeASTSelection &&) = default;
     99 
    100   /// Returns the parent hierarchy (top to bottom) for the selected nodes.
    101   ArrayRef<SelectedASTNode::ReferenceType> getParents() { return Parents; }
    102 
    103   /// Returns the number of selected statements.
    104   size_t size() const {
    105     if (!AreChildrenSelected)
    106       return 1;
    107     return SelectedNode.get().Children.size();
    108   }
    109 
    110   const Stmt *operator[](size_t I) const {
    111     if (!AreChildrenSelected) {
    112       assert(I == 0 && "Invalid index");
    113       return SelectedNode.get().Node.get<Stmt>();
    114     }
    115     return SelectedNode.get().Children[I].Node.get<Stmt>();
    116   }
    117 
    118   /// Returns true when a selected code range is in a function-like body
    119   /// of code, like a function, method or a block.
    120   ///
    121   /// This function can be used to test against selected expressions that are
    122   /// located outside of a function, e.g. global variable initializers, default
    123   /// argument values, or even template arguments.
    124   ///
    125   /// Use the \c getFunctionLikeNearestParent to get the function-like parent
    126   /// declaration.
    127   bool isInFunctionLikeBodyOfCode() const;
    128 
    129   /// Returns the nearest function-like parent declaration or null if such
    130   /// declaration doesn't exist.
    131   const Decl *getFunctionLikeNearestParent() const;
    132 
    133   static Optional<CodeRangeASTSelection>
    134   create(SourceRange SelectionRange, const SelectedASTNode &ASTSelection);
    135 
    136 private:
    137   CodeRangeASTSelection(SelectedASTNode::ReferenceType SelectedNode,
    138                         ArrayRef<SelectedASTNode::ReferenceType> Parents,
    139                         bool AreChildrenSelected)
    140       : SelectedNode(SelectedNode), Parents(Parents.begin(), Parents.end()),
    141         AreChildrenSelected(AreChildrenSelected) {}
    142 
    143   /// The reference to the selected node (or reference to the selected
    144   /// child nodes).
    145   SelectedASTNode::ReferenceType SelectedNode;
    146   /// The parent hierarchy (top to bottom) for the selected noe.
    147   llvm::SmallVector<SelectedASTNode::ReferenceType, 8> Parents;
    148   /// True only when the children of the selected node are actually selected.
    149   bool AreChildrenSelected;
    150 };
    151 
    152 } // end namespace tooling
    153 } // end namespace clang
    154 
    155 #endif // LLVM_CLANG_TOOLING_REFACTOR_AST_SELECTION_H
    156