//===- CIndexUSRs.cpp - Clang-C Source Indexing Library -------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements the generation and use of USRs from CXEntities.
//
//===----------------------------------------------------------------------===//

#include "CIndexer.h"
#include "CXCursor.h"
#include "CXString.h"
#include "CXTranslationUnit.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace clang::index;

//===----------------------------------------------------------------------===//
// API hooks.
//===----------------------------------------------------------------------===//

static inline StringRef extractUSRSuffix(StringRef s) {
  return s.startswith("c:") ? s.substr(2) : "";
}

bool cxcursor::getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf) {
  return generateUSRForDecl(D, Buf);
}

CXString clang_getCursorUSR(CXCursor C) {
  const CXCursorKind &K = clang_getCursorKind(C);

  if (clang_isDeclaration(K)) {
    const Decl *D = cxcursor::getCursorDecl(C);
    if (!D)
      return cxstring::createEmpty();

    CXTranslationUnit TU = cxcursor::getCursorTU(C);
    if (!TU)
      return cxstring::createEmpty();

    cxstring::CXStringBuf *buf = cxstring::getCXStringBuf(TU);
    if (!buf)
      return cxstring::createEmpty();

    bool Ignore = cxcursor::getDeclCursorUSR(D, buf->Data);
    if (Ignore) {
      buf->dispose();
      return cxstring::createEmpty();
    }

    // Return the C-string, but don't make a copy since it is already in
    // the string buffer.
    buf->Data.push_back('\0');
    return createCXString(buf);
  }

  if (K == CXCursor_MacroDefinition) {
    CXTranslationUnit TU = cxcursor::getCursorTU(C);
    if (!TU)
      return cxstring::createEmpty();

    cxstring::CXStringBuf *buf = cxstring::getCXStringBuf(TU);
    if (!buf)
      return cxstring::createEmpty();

    bool Ignore = generateUSRForMacro(cxcursor::getCursorMacroDefinition(C),
                                      cxtu::getASTUnit(TU)->getSourceManager(),
                                      buf->Data);
    if (Ignore) {
      buf->dispose();
      return cxstring::createEmpty();
    }

    // Return the C-string, but don't make a copy since it is already in
    // the string buffer.
    buf->Data.push_back('\0');
    return createCXString(buf);
  }

  return cxstring::createEmpty();
}

CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) {
  SmallString<128> Buf(getUSRSpacePrefix());
  llvm::raw_svector_ostream OS(Buf);
  OS << extractUSRSuffix(clang_getCString(classUSR));
  generateUSRForObjCIvar(name, OS);
  return cxstring::createDup(OS.str());
}

CXString clang_constructUSR_ObjCMethod(const char *name,
                                       unsigned isInstanceMethod,
                                       CXString classUSR) {
  SmallString<128> Buf(getUSRSpacePrefix());
  llvm::raw_svector_ostream OS(Buf);
  OS << extractUSRSuffix(clang_getCString(classUSR));
  generateUSRForObjCMethod(name, isInstanceMethod, OS);
  return cxstring::createDup(OS.str());
}

CXString clang_constructUSR_ObjCClass(const char *name) {
  SmallString<128> Buf(getUSRSpacePrefix());
  llvm::raw_svector_ostream OS(Buf);
  generateUSRForObjCClass(name, OS);
  return cxstring::createDup(OS.str());
}

CXString clang_constructUSR_ObjCProtocol(const char *name) {
  SmallString<128> Buf(getUSRSpacePrefix());
  llvm::raw_svector_ostream OS(Buf);
  generateUSRForObjCProtocol(name, OS);
  return cxstring::createDup(OS.str());
}

CXString clang_constructUSR_ObjCCategory(const char *class_name,
                                         const char *category_name) {
  SmallString<128> Buf(getUSRSpacePrefix());
  llvm::raw_svector_ostream OS(Buf);
  generateUSRForObjCCategory(class_name, category_name, OS);
  return cxstring::createDup(OS.str());
}

CXString clang_constructUSR_ObjCProperty(const char *property,
                                         CXString classUSR) {
  SmallString<128> Buf(getUSRSpacePrefix());
  llvm::raw_svector_ostream OS(Buf);
  OS << extractUSRSuffix(clang_getCString(classUSR));
  generateUSRForObjCProperty(property, /*isClassProp=*/false, OS);
  return cxstring::createDup(OS.str());
}
