xref: /openbsd-src/gnu/llvm/clang/include/clang/Tooling/ASTDiff/ASTDiff.h (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- ASTDiff.h - AST differencing API -----------------------*- C++ -*- -===//
2e5dd7070Spatrick //
3e5dd7070Spatrick //
4e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
6e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7e5dd7070Spatrick //
8e5dd7070Spatrick //===----------------------------------------------------------------------===//
9e5dd7070Spatrick //
10e5dd7070Spatrick // This file specifies an interface that can be used to compare C++ syntax
11e5dd7070Spatrick // trees.
12e5dd7070Spatrick //
13e5dd7070Spatrick // We use the gumtree algorithm which combines a heuristic top-down search that
14e5dd7070Spatrick // is able to match large subtrees that are equivalent, with an optimal
15e5dd7070Spatrick // algorithm to match small subtrees.
16e5dd7070Spatrick //
17e5dd7070Spatrick //===----------------------------------------------------------------------===//
18e5dd7070Spatrick 
19e5dd7070Spatrick #ifndef LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFF_H
20e5dd7070Spatrick #define LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFF_H
21e5dd7070Spatrick 
22e5dd7070Spatrick #include "clang/Tooling/ASTDiff/ASTDiffInternal.h"
23*12c85518Srobert #include <optional>
24e5dd7070Spatrick 
25e5dd7070Spatrick namespace clang {
26e5dd7070Spatrick namespace diff {
27e5dd7070Spatrick 
28e5dd7070Spatrick enum ChangeKind {
29e5dd7070Spatrick   None,
30e5dd7070Spatrick   Delete,    // (Src): delete node Src.
31e5dd7070Spatrick   Update,    // (Src, Dst): update the value of node Src to match Dst.
32e5dd7070Spatrick   Insert,    // (Src, Dst, Pos): insert Src as child of Dst at offset Pos.
33e5dd7070Spatrick   Move,      // (Src, Dst, Pos): move Src to be a child of Dst at offset Pos.
34e5dd7070Spatrick   UpdateMove // Same as Move plus Update.
35e5dd7070Spatrick };
36e5dd7070Spatrick 
37e5dd7070Spatrick /// Represents a Clang AST node, alongside some additional information.
38e5dd7070Spatrick struct Node {
39e5dd7070Spatrick   NodeId Parent, LeftMostDescendant, RightMostDescendant;
40e5dd7070Spatrick   int Depth, Height, Shift = 0;
41ec727ea7Spatrick   DynTypedNode ASTNode;
42e5dd7070Spatrick   SmallVector<NodeId, 4> Children;
43e5dd7070Spatrick   ChangeKind Change = None;
44e5dd7070Spatrick 
45ec727ea7Spatrick   ASTNodeKind getType() const;
46e5dd7070Spatrick   StringRef getTypeLabel() const;
isLeafNode47e5dd7070Spatrick   bool isLeaf() const { return Children.empty(); }
48*12c85518Srobert   std::optional<StringRef> getIdentifier() const;
49*12c85518Srobert   std::optional<std::string> getQualifiedIdentifier() const;
50e5dd7070Spatrick };
51e5dd7070Spatrick 
52e5dd7070Spatrick /// SyntaxTree objects represent subtrees of the AST.
53e5dd7070Spatrick /// They can be constructed from any Decl or Stmt.
54e5dd7070Spatrick class SyntaxTree {
55e5dd7070Spatrick public:
56e5dd7070Spatrick   /// Constructs a tree from a translation unit.
57e5dd7070Spatrick   SyntaxTree(ASTContext &AST);
58e5dd7070Spatrick   /// Constructs a tree from any AST node.
59e5dd7070Spatrick   template <class T>
SyntaxTree(T * Node,ASTContext & AST)60e5dd7070Spatrick   SyntaxTree(T *Node, ASTContext &AST)
61e5dd7070Spatrick       : TreeImpl(std::make_unique<Impl>(this, Node, AST)) {}
62e5dd7070Spatrick   SyntaxTree(SyntaxTree &&Other) = default;
63e5dd7070Spatrick   ~SyntaxTree();
64e5dd7070Spatrick 
65e5dd7070Spatrick   const ASTContext &getASTContext() const;
66e5dd7070Spatrick   StringRef getFilename() const;
67e5dd7070Spatrick 
68e5dd7070Spatrick   int getSize() const;
69e5dd7070Spatrick   NodeId getRootId() const;
70e5dd7070Spatrick   using PreorderIterator = NodeId;
71e5dd7070Spatrick   PreorderIterator begin() const;
72e5dd7070Spatrick   PreorderIterator end() const;
73e5dd7070Spatrick 
74e5dd7070Spatrick   const Node &getNode(NodeId Id) const;
75e5dd7070Spatrick   int findPositionInParent(NodeId Id) const;
76e5dd7070Spatrick 
77e5dd7070Spatrick   // Returns the starting and ending offset of the node in its source file.
78e5dd7070Spatrick   std::pair<unsigned, unsigned> getSourceRangeOffsets(const Node &N) const;
79e5dd7070Spatrick 
80e5dd7070Spatrick   /// Serialize the node attributes to a string representation. This should
81e5dd7070Spatrick   /// uniquely distinguish nodes of the same kind. Note that this function just
82e5dd7070Spatrick   /// returns a representation of the node value, not considering descendants.
83e5dd7070Spatrick   std::string getNodeValue(NodeId Id) const;
84e5dd7070Spatrick   std::string getNodeValue(const Node &Node) const;
85e5dd7070Spatrick 
86e5dd7070Spatrick   class Impl;
87e5dd7070Spatrick   std::unique_ptr<Impl> TreeImpl;
88e5dd7070Spatrick };
89e5dd7070Spatrick 
90e5dd7070Spatrick struct ComparisonOptions {
91e5dd7070Spatrick   /// During top-down matching, only consider nodes of at least this height.
92e5dd7070Spatrick   int MinHeight = 2;
93e5dd7070Spatrick 
94e5dd7070Spatrick   /// During bottom-up matching, match only nodes with at least this value as
95e5dd7070Spatrick   /// the ratio of their common descendants.
96e5dd7070Spatrick   double MinSimilarity = 0.5;
97e5dd7070Spatrick 
98e5dd7070Spatrick   /// Whenever two subtrees are matched in the bottom-up phase, the optimal
99e5dd7070Spatrick   /// mapping is computed, unless the size of either subtrees exceeds this.
100e5dd7070Spatrick   int MaxSize = 100;
101e5dd7070Spatrick 
102e5dd7070Spatrick   bool StopAfterTopDown = false;
103e5dd7070Spatrick 
104e5dd7070Spatrick   /// Returns false if the nodes should never be matched.
isMatchingAllowedComparisonOptions105e5dd7070Spatrick   bool isMatchingAllowed(const Node &N1, const Node &N2) const {
106e5dd7070Spatrick     return N1.getType().isSame(N2.getType());
107e5dd7070Spatrick   }
108e5dd7070Spatrick };
109e5dd7070Spatrick 
110*12c85518Srobert class ASTDiff {
111*12c85518Srobert public:
112*12c85518Srobert   ASTDiff(SyntaxTree &Src, SyntaxTree &Dst, const ComparisonOptions &Options);
113*12c85518Srobert   ~ASTDiff();
114*12c85518Srobert 
115*12c85518Srobert   // Returns the ID of the node that is mapped to the given node in SourceTree.
116*12c85518Srobert   NodeId getMapped(const SyntaxTree &SourceTree, NodeId Id) const;
117*12c85518Srobert 
118*12c85518Srobert   class Impl;
119*12c85518Srobert 
120*12c85518Srobert private:
121*12c85518Srobert   std::unique_ptr<Impl> DiffImpl;
122*12c85518Srobert };
123*12c85518Srobert 
124e5dd7070Spatrick } // end namespace diff
125e5dd7070Spatrick } // end namespace clang
126e5dd7070Spatrick 
127e5dd7070Spatrick #endif
128