//===--- Selection.cpp ----------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "Selection.h"
#include "ClangdUnit.h"
#include "clang/AST/RecursiveASTVisitor.h"

namespace clang {
namespace clangd {
namespace {
using Node = SelectionTree::Node;
using ast_type_traits::DynTypedNode;

// We find the selection by visiting written nodes in the AST, looking for nodes
// that intersect with the selected character range.
//
// While traversing, we maintain a parent stack. As nodes pop off the stack,
// we decide whether to keep them or not. To be kept, they must either be
// selected or contain some nodes that are.
//
// For simple cases (not inside macros) we prune subtrees that don't intersect.
class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
public:
  // Runs the visitor to gather selected nodes and their ancestors.
  // If there is any selection, the root (TUDecl) is the first node.
  static std::deque<Node> collect(ASTContext &AST, unsigned Begin,
                                  unsigned End, FileID File) {
    SelectionVisitor V(AST, Begin, End, File);
    V.TraverseAST(AST);
    assert(V.Stack.size() == 1 && "Unpaired push/pop?");
    assert(V.Stack.top() == &V.Nodes.front());
    if (V.Nodes.size() == 1) // TUDecl, but no nodes under it.
      V.Nodes.clear();
    return std::move(V.Nodes);
  }

  // We traverse all "well-behaved" nodes the same way:
  //  - push the node onto the stack
  //  - traverse its children recursively
  //  - pop it from the stack
  //  - hit testing: is intersection(node, selection) - union(children) empty?
  //  - attach it to the tree if it or any children hit the selection
  //
  // Two categories of nodes are not "well-behaved":
  //  - those without source range information, we don't record those
  //  - those that can't be stored in DynTypedNode.
  // We're missing some interesting things like Attr due to the latter.
  bool TraverseDecl(Decl *X) {
    if (X && isa<TranslationUnitDecl>(X))
      return Base::TraverseDecl(X); // Already pushed by constructor.
    return traverseNode(X, [&] { return Base::TraverseDecl(X); });
  }
  bool TraverseTypeLoc(TypeLoc X) {
    return traverseNode(&X, [&] { return Base::TraverseTypeLoc(X); });
  }
  bool TraverseTypeNestedNameSpecifierLoc(NestedNameSpecifierLoc X) {
    return traverseNode(
        &X, [&] { return Base::TraverseNestedNameSpecifierLoc(X); });
  }
  bool TraverseConstructorInitializer(CXXCtorInitializer *X) {
    return traverseNode(
        X, [&] { return Base::TraverseConstructorInitializer(X); });
  }
  // Stmt is the same, but this form allows the data recursion optimization.
  bool dataTraverseStmtPre(Stmt *X) {
    if (!X || canSafelySkipNode(X->getSourceRange()))
      return false;
    push(DynTypedNode::create(*X));
    return true;
  }
  bool dataTraverseStmtPost(Stmt *X) {
    pop();
    return true;
  }
  // Uninteresting parts of the AST that don't have locations within them.
  bool TraverseNestedNameSpecifier(NestedNameSpecifier *) { return true; }
  bool TraverseType(QualType) { return true; }

private:
  using Base = RecursiveASTVisitor<SelectionVisitor>;
  SelectionVisitor(ASTContext &AST, unsigned SelBegin, unsigned SelEnd,
                   FileID SelFile)
      : SM(AST.getSourceManager()), LangOpts(AST.getLangOpts()),
        SelBegin(SelBegin), SelEnd(SelEnd), SelFile(SelFile),
        SelBeginTokenStart(SM.getFileOffset(Lexer::GetBeginningOfToken(
            SM.getComposedLoc(SelFile, SelBegin), SM, LangOpts))) {
    // Ensure we have a node for the TU decl, regardless of traversal scope.
    Nodes.emplace_back();
    Nodes.back().ASTNode = DynTypedNode::create(*AST.getTranslationUnitDecl());
    Nodes.back().Parent = nullptr;
    Nodes.back().Selected = SelectionTree::Unselected;
    Stack.push(&Nodes.back());
  }

  // Generic case of TraverseFoo. Func should be the call to Base::TraverseFoo.
  // Node is always a pointer so the generic code can handle any null checks.
  template <typename T, typename Func>
  bool traverseNode(T *Node, const Func &Body) {
    if (Node == nullptr || canSafelySkipNode(Node->getSourceRange()))
      return true;
    push(DynTypedNode::create(*Node));
    bool Ret = Body();
    pop();
    return Ret;
  }

  // An optimization for a common case: nodes outside macro expansions that
  // don't intersect the selection may be recursively skipped.
  bool canSafelySkipNode(SourceRange S) {
    auto B = SM.getDecomposedLoc(S.getBegin());
    auto E = SM.getDecomposedLoc(S.getEnd());
    if (B.first != SelFile || E.first != SelFile)
      return false;
    return B.second >= SelEnd || E.second < SelBeginTokenStart;
  }

  // Pushes a node onto the ancestor stack. Pairs with pop().
  void push(DynTypedNode Node) {
    Nodes.emplace_back();
    Nodes.back().ASTNode = std::move(Node);
    Nodes.back().Parent = Stack.top();
    Nodes.back().Selected = SelectionTree::Unselected;
    Stack.push(&Nodes.back());
  }

  // Pops a node off the ancestor stack, and finalizes it. Pairs with push().
  void pop() {
    Node &N = *Stack.top();
    N.Selected = computeSelection(N);
    if (N.Selected || !N.Children.empty()) {
      // Attach to the tree.
      N.Parent->Children.push_back(&N);
    } else {
      // Neither N any children are selected, it doesn't belong in the tree.
      assert(&N == &Nodes.back());
      Nodes.pop_back();
    }
    Stack.pop();
  }

  // Perform hit-testing of a complete Node against the selection.
  // This runs for every node in the AST, and must be fast in common cases.
  // This is called from pop(), so we can take children into account.
  SelectionTree::Selection computeSelection(const Node &N) {
    SourceRange S = N.ASTNode.getSourceRange();
    if (!S.isValid())
      return SelectionTree::Unselected;
    // getTopMacroCallerLoc() allows selection of constructs in macro args. e.g:
    //   #define LOOP_FOREVER(Body) for(;;) { Body }
    //   void IncrementLots(int &x) {
    //     LOOP_FOREVER( ++x; )
    //   }
    // Selecting "++x" or "x" will do the right thing.
    auto B = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getBegin()));
    auto E = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getEnd()));
    // Otherwise, nodes in macro expansions can't be selected.
    if (B.first != SelFile || E.first != SelFile)
      return SelectionTree::Unselected;
    // Cheap test: is there any overlap at all between the selection and range?
    // Note that E.second is the *start* of the last token, which is why we
    // compare against the "rounded-down" SelBegin.
    if (B.second >= SelEnd || E.second < SelBeginTokenStart)
      return SelectionTree::Unselected;

    // We hit something, need some more precise checks.
    // Adjust [B, E) to be a half-open character range.
    E.second += Lexer::MeasureTokenLength(S.getEnd(), SM, LangOpts);
    // This node's own selected text is (this range ^ selection) - child ranges.
    // If that's empty, then we've only collided with children.
    if (nodesCoverRange(N.Children, std::max(SelBegin, B.second),
                        std::min(SelEnd, E.second)))
      return SelectionTree::Unselected; // Hit children only.
    // Some of our own characters are covered, this is a true hit.
    return (B.second >= SelBegin && E.second <= SelEnd)
               ? SelectionTree::Complete
               : SelectionTree::Partial;
  }

  // Is the range [Begin, End) entirely covered by the union of the Nodes?
  // (The range is a parent node's extent, and the covering nodes are children).
  bool nodesCoverRange(llvm::ArrayRef<const Node *> Nodes, unsigned Begin,
                       unsigned End) {
    if (Begin >= End)
      return true;
    if (Nodes.empty())
      return false;

    // Collect all the expansion ranges, as offsets.
    SmallVector<std::pair<unsigned, unsigned>, 8> ChildRanges;
    for (const Node *N : Nodes) {
      CharSourceRange R = SM.getExpansionRange(N->ASTNode.getSourceRange());
      auto B = SM.getDecomposedLoc(R.getBegin());
      auto E = SM.getDecomposedLoc(R.getEnd());
      if (B.first != SelFile || E.first != SelFile)
        continue;
      // Try to cover up to the next token, spaces between children don't count.
      if (auto Tok = Lexer::findNextToken(R.getEnd(), SM, LangOpts))
        E.second = SM.getFileOffset(Tok->getLocation());
      else if (R.isTokenRange())
        E.second += Lexer::MeasureTokenLength(R.getEnd(), SM, LangOpts);
      ChildRanges.push_back({B.second, E.second});
    }
    llvm::sort(ChildRanges);

    // Scan through the child ranges, removing as we go.
    for (const auto R : ChildRanges) {
      if (R.first > Begin)
        return false;   // [Begin, R.first) is not covered.
      Begin = R.second; // Eliminate [R.first, R.second).
      if (Begin >= End)
        return true; // Remaining range is empty.
    }
    return false; // Went through all children, trailing characters remain.
  }

  SourceManager &SM;
  const LangOptions &LangOpts;
  std::stack<Node *> Stack;
  std::deque<Node> Nodes; // Stable pointers as we add more nodes.
  // Half-open selection range.
  unsigned SelBegin;
  unsigned SelEnd;
  FileID SelFile;
  // If the selection start slices a token in half, the beginning of that token.
  // This is useful for checking whether the end of a token range overlaps
  // the selection: range.end < SelBeginTokenStart is equivalent to
  // range.end + measureToken(range.end) < SelBegin (assuming range.end points
  // to a token), and it saves a lex every time.
  unsigned SelBeginTokenStart;
};

} // namespace

void SelectionTree::print(llvm::raw_ostream &OS, const SelectionTree::Node &N,
                          int Indent) const {
  if (N.Selected)
    OS.indent(Indent - 1) << (N.Selected == SelectionTree::Complete ? '*'
                                                                    : '.');
  else
    OS.indent(Indent);
  OS << N.ASTNode.getNodeKind().asStringRef() << " ";
  N.ASTNode.print(OS, PrintPolicy);
  OS << "\n";
  for (const Node *Child : N.Children)
    print(OS, *Child, Indent + 2);
}

// Decide which selection emulates a "point" query in between characters.
static std::pair<unsigned, unsigned> pointBounds(unsigned Offset, FileID FID,
                                                 ASTContext &AST) {
  StringRef Buf = AST.getSourceManager().getBufferData(FID);
  // Edge-cases where the choice is forced.
  if (Buf.size() == 0)
    return {0, 0};
  if (Offset == 0)
    return {0, 1};
  if (Offset == Buf.size())
    return {Offset - 1, Offset};
  // We could choose either this byte or the previous. Usually we prefer the
  // character on the right of the cursor (or under a block cursor).
  // But if that's whitespace, we likely want the token on the left.
  if (isWhitespace(Buf[Offset]) && !isWhitespace(Buf[Offset - 1]))
    return {Offset - 1, Offset};
  return {Offset, Offset + 1};
}

SelectionTree::SelectionTree(ASTContext &AST, unsigned Begin, unsigned End)
    : PrintPolicy(AST.getLangOpts()) {
  // No fundamental reason the selection needs to be in the main file,
  // but that's all clangd has needed so far.
  FileID FID = AST.getSourceManager().getMainFileID();
  if (Begin == End)
    std::tie(Begin, End) = pointBounds(Begin, FID, AST);
  PrintPolicy.TerseOutput = true;

  Nodes = SelectionVisitor::collect(AST, Begin, End, FID);
  Root = Nodes.empty() ? nullptr : &Nodes.front();
}

SelectionTree::SelectionTree(ASTContext &AST, unsigned Offset)
    : SelectionTree(AST, Offset, Offset) {}

const Node *SelectionTree::commonAncestor() const {
  if (!Root)
    return nullptr;
  for (const Node *Ancestor = Root;; Ancestor = Ancestor->Children.front()) {
    if (Ancestor->Selected || Ancestor->Children.size() > 1)
      return Ancestor;
    // The tree only contains ancestors of the interesting nodes.
    assert(!Ancestor->Children.empty() && "bad node in selection tree");
  }
}

} // namespace clangd
} // namespace clang
