//===--- Merge.h ------------------------------------------------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
#include "Merge.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
namespace clangd {
namespace {
using namespace llvm;

class MergedIndex : public SymbolIndex {
 public:
   MergedIndex(const SymbolIndex *Dynamic, const SymbolIndex *Static)
       : Dynamic(Dynamic), Static(Static) {}

   // FIXME: Deleted symbols in dirty files are still returned (from Static).
   //        To identify these eliminate these, we should:
   //          - find the generating file from each Symbol which is Static-only
   //          - ask Dynamic if it has that file (needs new SymbolIndex method)
   //          - if so, drop the Symbol.
   bool fuzzyFind(const FuzzyFindRequest &Req,
                  function_ref<void(const Symbol &)> Callback) const override {
     // We can't step through both sources in parallel. So:
     //  1) query all dynamic symbols, slurping results into a slab
     //  2) query the static symbols, for each one:
     //    a) if it's not in the dynamic slab, yield it directly
     //    b) if it's in the dynamic slab, merge it and yield the result
     //  3) now yield all the dynamic symbols we haven't processed.
     bool More = false; // We'll be incomplete if either source was.
     SymbolSlab::Builder DynB;
     More |= Dynamic->fuzzyFind(Req, [&](const Symbol &S) { DynB.insert(S); });
     SymbolSlab Dyn = std::move(DynB).build();

     DenseSet<SymbolID> SeenDynamicSymbols;
     Symbol::Details Scratch;
     More |= Static->fuzzyFind(Req, [&](const Symbol &S) {
       auto DynS = Dyn.find(S.ID);
       if (DynS == Dyn.end())
         return Callback(S);
       SeenDynamicSymbols.insert(S.ID);
       Callback(mergeSymbol(*DynS, S, &Scratch));
     });
     for (const Symbol &S : Dyn)
       if (!SeenDynamicSymbols.count(S.ID))
         Callback(S);
     return More;
  }

  void
  lookup(const LookupRequest &Req,
         llvm::function_ref<void(const Symbol &)> Callback) const override {
    SymbolSlab::Builder B;

    Dynamic->lookup(Req, [&](const Symbol &S) { B.insert(S); });

    auto RemainingIDs = Req.IDs;
    Symbol::Details Scratch;
    Static->lookup(Req, [&](const Symbol &S) {
      const Symbol *Sym = B.find(S.ID);
      RemainingIDs.erase(S.ID);
      if (!Sym)
        Callback(S);
      else
        Callback(mergeSymbol(*Sym, S, &Scratch));
    });
    for (const auto &ID : RemainingIDs)
      if (const Symbol *Sym = B.find(ID))
        Callback(*Sym);
  }

private:
  const SymbolIndex *Dynamic, *Static;
};
}

Symbol
mergeSymbol(const Symbol &L, const Symbol &R, Symbol::Details *Scratch) {
  assert(L.ID == R.ID);
  // We prefer information from TUs that saw the definition.
  // Classes: this is the def itself. Functions: hopefully the header decl.
  // If both did (or both didn't), continue to prefer L over R.
  bool PreferR = R.Definition && !L.Definition;
  Symbol S = PreferR ? R : L;        // The target symbol we're merging into.
  const Symbol &O = PreferR ? L : R; // The "other" less-preferred symbol.

  // For each optional field, fill it from O if missing in S.
  // (It might be missing in O too, but that's a no-op).
  if (!S.Definition)
    S.Definition = O.Definition;
  if (!S.CanonicalDeclaration)
    S.CanonicalDeclaration = O.CanonicalDeclaration;
  S.References += O.References;
  if (S.CompletionLabel == "")
    S.CompletionLabel = O.CompletionLabel;
  if (S.CompletionFilterText == "")
    S.CompletionFilterText = O.CompletionFilterText;
  if (S.CompletionPlainInsertText == "")
    S.CompletionPlainInsertText = O.CompletionPlainInsertText;
  if (S.CompletionSnippetInsertText == "")
    S.CompletionSnippetInsertText = O.CompletionSnippetInsertText;

  if (O.Detail) {
    if (S.Detail) {
      // Copy into scratch space so we can merge.
      *Scratch = *S.Detail;
      if (Scratch->Documentation == "")
        Scratch->Documentation = O.Detail->Documentation;
      if (Scratch->CompletionDetail == "")
        Scratch->CompletionDetail = O.Detail->CompletionDetail;
      if (Scratch->IncludeHeader == "")
        Scratch->IncludeHeader = O.Detail->IncludeHeader;
      S.Detail = Scratch;
    } else
      S.Detail = O.Detail;
  }
  return S;
}

std::unique_ptr<SymbolIndex> mergeIndex(const SymbolIndex *Dynamic,
                                        const SymbolIndex *Static) {
  return llvm::make_unique<MergedIndex>(Dynamic, Static);
}
} // namespace clangd
} // namespace clang
