//===-- IncludeFixerContext.cpp - Include fixer context ---------*- C++ -*-===//
//
// 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 "IncludeFixerContext.h"
#include "llvm/ADT/STLExtras.h"

namespace clang {
namespace include_fixer {

namespace {

// Splits a multiply qualified names (e.g. a::b::c).
llvm::SmallVector<llvm::StringRef, 8>
SplitQualifiers(llvm::StringRef StringQualifiers) {
  llvm::SmallVector<llvm::StringRef, 8> Qualifiers;
  StringQualifiers.split(Qualifiers, "::");
  return Qualifiers;
}

std::string createQualifiedNameForReplacement(
    llvm::StringRef RawSymbolName,
    llvm::StringRef SymbolScopedQualifiersName,
    const find_all_symbols::SymbolInfo &MatchedSymbol) {
  // No need to add missing qualifiers if SymbolIdentifier has a global scope
  // operator "::".
  if (RawSymbolName.startswith("::"))
    return std::string(RawSymbolName);

  std::string QualifiedName = MatchedSymbol.getQualifiedName();

  // For nested classes, the qualified name constructed from database misses
  // some stripped qualifiers, because when we search a symbol in database,
  // we strip qualifiers from the end until we find a result. So append the
  // missing stripped qualifiers here.
  //
  // Get stripped qualifiers.
  auto SymbolQualifiers = SplitQualifiers(RawSymbolName);
  std::string StrippedQualifiers;
  while (!SymbolQualifiers.empty() &&
         !llvm::StringRef(QualifiedName).endswith(SymbolQualifiers.back())) {
    StrippedQualifiers =
        "::" + SymbolQualifiers.back().str() + StrippedQualifiers;
    SymbolQualifiers.pop_back();
  }
  // Append the missing stripped qualifiers.
  std::string FullyQualifiedName = QualifiedName + StrippedQualifiers;

  // Try to find and skip the common prefix qualifiers.
  auto FullySymbolQualifiers = SplitQualifiers(FullyQualifiedName);
  auto ScopedQualifiers = SplitQualifiers(SymbolScopedQualifiersName);
  auto FullySymbolQualifiersIter = FullySymbolQualifiers.begin();
  auto SymbolScopedQualifiersIter = ScopedQualifiers.begin();
  while (FullySymbolQualifiersIter != FullySymbolQualifiers.end() &&
         SymbolScopedQualifiersIter != ScopedQualifiers.end()) {
    if (*FullySymbolQualifiersIter != *SymbolScopedQualifiersIter)
      break;
    ++FullySymbolQualifiersIter;
    ++SymbolScopedQualifiersIter;
  }
  std::string Result;
  for (; FullySymbolQualifiersIter != FullySymbolQualifiers.end();
       ++FullySymbolQualifiersIter) {
    if (!Result.empty())
      Result += "::";
    Result += *FullySymbolQualifiersIter;
  }
  return Result;
}

} // anonymous namespace

IncludeFixerContext::IncludeFixerContext(
    StringRef FilePath, std::vector<QuerySymbolInfo> QuerySymbols,
    std::vector<find_all_symbols::SymbolInfo> Symbols)
    : FilePath(FilePath), QuerySymbolInfos(std::move(QuerySymbols)),
      MatchedSymbols(std::move(Symbols)) {
  // Remove replicated QuerySymbolInfos with the same range.
  //
  // QuerySymbolInfos may contain replicated elements. Because CorrectTypo
  // callback doesn't always work as we expected. In somecases, it will be
  // triggered at the same position or unidentified symbol multiple times.
  llvm::sort(QuerySymbolInfos,
             [&](const QuerySymbolInfo &A, const QuerySymbolInfo &B) {
               return std::make_pair(A.Range.getOffset(), A.Range.getLength()) <
                      std::make_pair(B.Range.getOffset(), B.Range.getLength());
             });
  QuerySymbolInfos.erase(
      std::unique(QuerySymbolInfos.begin(), QuerySymbolInfos.end(),
                  [](const QuerySymbolInfo &A, const QuerySymbolInfo &B) {
                    return A.Range == B.Range;
                  }),
      QuerySymbolInfos.end());
  for (const auto &Symbol : MatchedSymbols) {
    HeaderInfos.push_back(
        {Symbol.getFilePath().str(),
         createQualifiedNameForReplacement(
             QuerySymbolInfos.front().RawIdentifier,
             QuerySymbolInfos.front().ScopedQualifiers, Symbol)});
  }
  // Deduplicate header infos.
  HeaderInfos.erase(std::unique(HeaderInfos.begin(), HeaderInfos.end(),
                                [](const HeaderInfo &A, const HeaderInfo &B) {
                                  return A.Header == B.Header &&
                                         A.QualifiedName == B.QualifiedName;
                                }),
                    HeaderInfos.end());
}

} // include_fixer
} // clang
