//===---- QueryParser.cpp - clang-query command parser --------------------===//
//
// 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 "QueryParser.h"
#include "Query.h"
#include "QuerySession.h"
#include "clang/ASTMatchers/Dynamic/Parser.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include <set>

using namespace llvm;
using namespace clang::ast_matchers::dynamic;

namespace clang {
namespace query {

// Lex any amount of whitespace followed by a "word" (any sequence of
// non-whitespace characters) from the start of region [Begin,End).  If no word
// is found before End, return StringRef().  Begin is adjusted to exclude the
// lexed region.
StringRef QueryParser::lexWord() {
  Line = Line.drop_while([](char c) {
    // Don't trim newlines.
    return StringRef(" \t\v\f\r").contains(c);
  });

  if (Line.empty())
    // Even though the Line is empty, it contains a pointer and
    // a (zero) length. The pointer is used in the LexOrCompleteWord
    // code completion.
    return Line;

  StringRef Word;
  if (Line.front() == '#')
    Word = Line.substr(0, 1);
  else
    Word = Line.take_until(isWhitespace);

  Line = Line.drop_front(Word.size());
  return Word;
}

// This is the StringSwitch-alike used by lexOrCompleteWord below. See that
// function for details.
template <typename T> struct QueryParser::LexOrCompleteWord {
  StringRef Word;
  StringSwitch<T> Switch;

  QueryParser *P;
  // Set to the completion point offset in Word, or StringRef::npos if
  // completion point not in Word.
  size_t WordCompletionPos;

  // Lexes a word and stores it in Word. Returns a LexOrCompleteWord<T> object
  // that can be used like a llvm::StringSwitch<T>, but adds cases as possible
  // completions if the lexed word contains the completion point.
  LexOrCompleteWord(QueryParser *P, StringRef &OutWord)
      : Word(P->lexWord()), Switch(Word), P(P),
        WordCompletionPos(StringRef::npos) {
    OutWord = Word;
    if (P->CompletionPos && P->CompletionPos <= Word.data() + Word.size()) {
      if (P->CompletionPos < Word.data())
        WordCompletionPos = 0;
      else
        WordCompletionPos = P->CompletionPos - Word.data();
    }
  }

  LexOrCompleteWord &Case(llvm::StringLiteral CaseStr, const T &Value,
                          bool IsCompletion = true) {

    if (WordCompletionPos == StringRef::npos)
      Switch.Case(CaseStr, Value);
    else if (CaseStr.size() != 0 && IsCompletion && WordCompletionPos <= CaseStr.size() &&
             CaseStr.substr(0, WordCompletionPos) ==
                 Word.substr(0, WordCompletionPos))
      P->Completions.push_back(LineEditor::Completion(
          (CaseStr.substr(WordCompletionPos) + " ").str(), CaseStr));
    return *this;
  }

  T Default(T Value) { return Switch.Default(Value); }
};

QueryRef QueryParser::parseSetBool(bool QuerySession::*Var) {
  StringRef ValStr;
  unsigned Value = LexOrCompleteWord<unsigned>(this, ValStr)
                       .Case("false", 0)
                       .Case("true", 1)
                       .Default(~0u);
  if (Value == ~0u) {
    return new InvalidQuery("expected 'true' or 'false', got '" + ValStr + "'");
  }
  return new SetQuery<bool>(Var, Value);
}

template <typename QueryType> QueryRef QueryParser::parseSetOutputKind() {
  StringRef ValStr;
  unsigned OutKind = LexOrCompleteWord<unsigned>(this, ValStr)
                         .Case("diag", OK_Diag)
                         .Case("print", OK_Print)
                         .Case("detailed-ast", OK_DetailedAST)
                         .Case("dump", OK_DetailedAST)
                         .Default(~0u);
  if (OutKind == ~0u) {
    return new InvalidQuery(
        "expected 'diag', 'print', 'detailed-ast' or 'dump', got '" + ValStr +
        "'");
  }

  switch (OutKind) {
  case OK_DetailedAST:
    return new QueryType(&QuerySession::DetailedASTOutput);
  case OK_Diag:
    return new QueryType(&QuerySession::DiagOutput);
  case OK_Print:
    return new QueryType(&QuerySession::PrintOutput);
  }

  llvm_unreachable("Invalid output kind");
}

QueryRef QueryParser::endQuery(QueryRef Q) {
  StringRef Extra = Line;
  StringRef ExtraTrimmed = Extra.drop_while(
      [](char c) { return StringRef(" \t\v\f\r").contains(c); });

  if ((!ExtraTrimmed.empty() && ExtraTrimmed[0] == '\n') ||
      (ExtraTrimmed.size() >= 2 && ExtraTrimmed[0] == '\r' &&
       ExtraTrimmed[1] == '\n'))
    Q->RemainingContent = Extra;
  else {
    StringRef TrailingWord = lexWord();
    if (!TrailingWord.empty() && TrailingWord.front() == '#') {
      Line = Line.drop_until([](char c) { return c == '\n'; });
      Line = Line.drop_while([](char c) { return c == '\n'; });
      return endQuery(Q);
    }
    if (!TrailingWord.empty()) {
      return new InvalidQuery("unexpected extra input: '" + Extra + "'");
    }
  }
  return Q;
}

namespace {

enum ParsedQueryKind {
  PQK_Invalid,
  PQK_Comment,
  PQK_NoOp,
  PQK_Help,
  PQK_Let,
  PQK_Match,
  PQK_Set,
  PQK_Unlet,
  PQK_Quit,
  PQK_Enable,
  PQK_Disable
};

enum ParsedQueryVariable {
  PQV_Invalid,
  PQV_Output,
  PQV_BindRoot,
  PQV_PrintMatcher
};

QueryRef makeInvalidQueryFromDiagnostics(const Diagnostics &Diag) {
  std::string ErrStr;
  llvm::raw_string_ostream OS(ErrStr);
  Diag.printToStreamFull(OS);
  return new InvalidQuery(OS.str());
}

} // namespace

QueryRef QueryParser::completeMatcherExpression() {
  std::vector<MatcherCompletion> Comps = Parser::completeExpression(
      Line, CompletionPos - Line.begin(), nullptr, &QS.NamedValues);
  for (auto I = Comps.begin(), E = Comps.end(); I != E; ++I) {
    Completions.push_back(LineEditor::Completion(I->TypedText, I->MatcherDecl));
  }
  return QueryRef();
}

QueryRef QueryParser::doParse() {
  StringRef CommandStr;
  ParsedQueryKind QKind = LexOrCompleteWord<ParsedQueryKind>(this, CommandStr)
                              .Case("", PQK_NoOp)
                              .Case("#", PQK_Comment, /*IsCompletion=*/false)
                              .Case("help", PQK_Help)
                              .Case("l", PQK_Let, /*IsCompletion=*/false)
                              .Case("let", PQK_Let)
                              .Case("m", PQK_Match, /*IsCompletion=*/false)
                              .Case("match", PQK_Match)
                              .Case("q", PQK_Quit,  /*IsCompletion=*/false)
                              .Case("quit", PQK_Quit)
                              .Case("set", PQK_Set)
                              .Case("enable", PQK_Enable)
                              .Case("disable", PQK_Disable)
                              .Case("unlet", PQK_Unlet)
                              .Default(PQK_Invalid);

  switch (QKind) {
  case PQK_Comment:
  case PQK_NoOp:
    Line = Line.drop_until([](char c) { return c == '\n'; });
    Line = Line.drop_while([](char c) { return c == '\n'; });
    if (Line.empty())
      return new NoOpQuery;
    return doParse();

  case PQK_Help:
    return endQuery(new HelpQuery);

  case PQK_Quit:
    return endQuery(new QuitQuery);

  case PQK_Let: {
    StringRef Name = lexWord();

    if (Name.empty())
      return new InvalidQuery("expected variable name");

    if (CompletionPos)
      return completeMatcherExpression();

    Diagnostics Diag;
    ast_matchers::dynamic::VariantValue Value;
    if (!Parser::parseExpression(Line, nullptr, &QS.NamedValues, &Value,
                                 &Diag)) {
      return makeInvalidQueryFromDiagnostics(Diag);
    }

    auto *Q = new LetQuery(Name, Value);
    Q->RemainingContent = Line;
    return Q;
  }

  case PQK_Match: {
    if (CompletionPos)
      return completeMatcherExpression();

    Diagnostics Diag;
    auto MatcherSource = Line.ltrim();
    auto OrigMatcherSource = MatcherSource;
    Optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression(
        MatcherSource, nullptr, &QS.NamedValues, &Diag);
    if (!Matcher) {
      return makeInvalidQueryFromDiagnostics(Diag);
    }
    auto ActualSource = OrigMatcherSource.slice(0, OrigMatcherSource.size() -
                                                       MatcherSource.size());
    auto *Q = new MatchQuery(ActualSource, *Matcher);
    Q->RemainingContent = MatcherSource;
    return Q;
  }

  case PQK_Set: {
    StringRef VarStr;
    ParsedQueryVariable Var =
        LexOrCompleteWord<ParsedQueryVariable>(this, VarStr)
            .Case("output", PQV_Output)
            .Case("bind-root", PQV_BindRoot)
            .Case("print-matcher", PQV_PrintMatcher)
            .Default(PQV_Invalid);
    if (VarStr.empty())
      return new InvalidQuery("expected variable name");
    if (Var == PQV_Invalid)
      return new InvalidQuery("unknown variable: '" + VarStr + "'");

    QueryRef Q;
    switch (Var) {
    case PQV_Output:
      Q = parseSetOutputKind<SetExclusiveOutputQuery>();
      break;
    case PQV_BindRoot:
      Q = parseSetBool(&QuerySession::BindRoot);
      break;
    case PQV_PrintMatcher:
      Q = parseSetBool(&QuerySession::PrintMatcher);
      break;
    case PQV_Invalid:
      llvm_unreachable("Invalid query kind");
    }

    return endQuery(Q);
  }
  case PQK_Enable:
  case PQK_Disable: {
    StringRef VarStr;
    ParsedQueryVariable Var =
        LexOrCompleteWord<ParsedQueryVariable>(this, VarStr)
            .Case("output", PQV_Output)
            .Default(PQV_Invalid);
    if (VarStr.empty())
      return new InvalidQuery("expected variable name");
    if (Var == PQV_Invalid)
      return new InvalidQuery("unknown variable: '" + VarStr + "'");

    QueryRef Q;

    if (QKind == PQK_Enable)
      Q = parseSetOutputKind<EnableOutputQuery>();
    else if (QKind == PQK_Disable)
      Q = parseSetOutputKind<DisableOutputQuery>();
    else
      llvm_unreachable("Invalid query kind");
    return endQuery(Q);
  }

  case PQK_Unlet: {
    StringRef Name = lexWord();

    if (Name.empty())
      return new InvalidQuery("expected variable name");

    return endQuery(new LetQuery(Name, VariantValue()));
  }

  case PQK_Invalid:
    return new InvalidQuery("unknown command: " + CommandStr);
  }

  llvm_unreachable("Invalid query kind");
}

QueryRef QueryParser::parse(StringRef Line, const QuerySession &QS) {
  return QueryParser(Line, QS).doParse();
}

std::vector<LineEditor::Completion>
QueryParser::complete(StringRef Line, size_t Pos, const QuerySession &QS) {
  QueryParser P(Line, QS);
  P.CompletionPos = Line.data() + Pos;

  P.doParse();
  return P.Completions;
}

} // namespace query
} // namespace clang
