Index: include/clang/Tooling/ASTDiff/ASTDiff.h =================================================================== --- /dev/null +++ include/clang/Tooling/ASTDiff/ASTDiff.h @@ -0,0 +1,181 @@ +//===- ASTDiff.h - AST differencing API -----------------------*- C++ -*- -===// +// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file specifies an interface that can be used to compare C++ syntax +// trees. +// +// We use the gumtree algorithm which combines a heuristic top-down search that +// is able to match large subtrees that are equivalent, with an optimal +// algorithm to match small subtrees. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFF_H +#define LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFF_H + +#include "clang/AST/ASTTypeTraits.h" + +namespace clang { +namespace diff { + +/// Within a tree, this identifies a node by its preorder offset. +using NodeId = int; + +/// Sentinel value for invalid nodes. +const NodeId InvalidNodeId = -1; + +/// Represents a Clang AST node, alongside some additional information. +struct Node { + NodeId Parent, LeftMostDescendant; + int Depth, Height; + ast_type_traits::DynTypedNode ASTNode; + // Maybe there is a better way to store children than this. + SmallVector Children; + + ast_type_traits::ASTNodeKind getType() const { return ASTNode.getNodeKind(); } + bool hasSameType(const Node &Other) const { + return getType().isSame(Other.getType()) || + (getType().isNone() && Other.getType().isNone()); + } + const StringRef getTypeLabel() const { return getType().asStringRef(); } + bool isLeaf() const { return Children.empty(); } +}; + +/// Represents the AST of a TranslationUnit. +class TreeRoot { +private: + /// Nodes in preorder. + std::vector Nodes; + void setRightMostDescendant(); + void setLeftMostDescendant(); + void setSize(size_t Size) { Nodes.resize(Size); } + +public: + ASTContext &AST; + std::vector Leaves; + // Maps preorder indices to postorder ones. + std::vector PostorderIds; + + TreeRoot(ASTContext &AST); + + int getSize() const { return Nodes.size(); } + NodeId root() const { return 0; } + + const Node &getNode(NodeId Id) const { return Nodes[Id]; } + Node &getMutableNode(NodeId Id) { return Nodes[Id]; } + bool isValidNodeId(NodeId Id) const { return Id >= 0 && Id < getSize(); } + void addNode(Node &N) { Nodes.push_back(N); } + template bool discardNode(T *N) const; + + int getSubtreePostorder(std::vector &Ids, NodeId Root) const; + std::vector getSubtreeBfs(NodeId Id) const; + int getNumberOfDescendants(NodeId Id) const; + + /// Returns the value of the node. + std::string label(NodeId Id) const; + /// Return the node as "[: