reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
//===-- Generators.cpp - Generator Registry ----------------------*- 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 "Generators.h"

LLVM_INSTANTIATE_REGISTRY(clang::doc::GeneratorRegistry)

namespace clang {
namespace doc {

llvm::Expected<std::unique_ptr<Generator>>
findGeneratorByName(llvm::StringRef Format) {
  for (auto I = GeneratorRegistry::begin(), E = GeneratorRegistry::end();
       I != E; ++I) {
    if (I->getName() != Format)
      continue;
    return I->instantiate();
  }
  return createStringError(llvm::inconvertibleErrorCode(),
                           "can't find generator: " + Format);
}

// Enum conversion

std::string getAccess(AccessSpecifier AS) {
  switch (AS) {
  case AccessSpecifier::AS_public:
    return "public";
  case AccessSpecifier::AS_protected:
    return "protected";
  case AccessSpecifier::AS_private:
    return "private";
  case AccessSpecifier::AS_none:
    return {};
  }
  llvm_unreachable("Unknown AccessSpecifier");
}

std::string getTagType(TagTypeKind AS) {
  switch (AS) {
  case TagTypeKind::TTK_Class:
    return "class";
  case TagTypeKind::TTK_Union:
    return "union";
  case TagTypeKind::TTK_Interface:
    return "interface";
  case TagTypeKind::TTK_Struct:
    return "struct";
  case TagTypeKind::TTK_Enum:
    return "enum";
  }
  llvm_unreachable("Unknown TagTypeKind");
}

llvm::Error Generator::createResources(ClangDocContext &CDCtx) {
  return llvm::Error::success();
}

// A function to add a reference to Info in Idx.
// Given an Info X with the following namespaces: [B,A]; a reference to X will
// be added in the children of a reference to B, which should be also a child of
// a reference to A, where A is a child of Idx.
//   Idx
//    |-- A
//        |--B
//           |--X
// If the references to the namespaces do not exist, they will be created. If
// the references already exist, the same one will be used.
void Generator::addInfoToIndex(Index &Idx, const doc::Info *Info) {
  // Index pointer that will be moving through Idx until the first parent
  // namespace of Info (where the reference has to be inserted) is found.
  Index *I = &Idx;
  // The Namespace vector includes the upper-most namespace at the end so the
  // loop will start from the end to find each of the namespaces.
  for (const auto &R : llvm::reverse(Info->Namespace)) {
    // Look for the current namespace in the children of the index I is
    // pointing.
    auto It = std::find(I->Children.begin(), I->Children.end(), R.USR);
    if (It != I->Children.end()) {
      // If it is found, just change I to point the namespace refererence found.
      I = &*It;
    } else {
      // If it is not found a new reference is created
      I->Children.emplace_back(R.USR, R.Name, R.RefType, R.Path);
      // I is updated with the reference of the new namespace reference
      I = &I->Children.back();
    }
  }
  // Look for Info in the vector where it is supposed to be; it could already
  // exist if it is a parent namespace of an Info already passed to this
  // function.
  auto It = std::find(I->Children.begin(), I->Children.end(), Info->USR);
  if (It == I->Children.end()) {
    // If it is not in the vector it is inserted
    I->Children.emplace_back(Info->USR, Info->extractName(), Info->IT,
                             Info->Path);
  } else {
    // If it not in the vector we only check if Path and Name are not empty
    // because if the Info was included by a namespace it may not have those
    // values.
    if (It->Path.empty())
      It->Path = Info->Path;
    if (It->Name.empty())
      It->Name = Info->extractName();
  }
}

// This anchor is used to force the linker to link in the generated object file
// and thus register the generators.
extern volatile int YAMLGeneratorAnchorSource;
extern volatile int MDGeneratorAnchorSource;
extern volatile int HTMLGeneratorAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED YAMLGeneratorAnchorDest =
    YAMLGeneratorAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED MDGeneratorAnchorDest =
    MDGeneratorAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED HTMLGeneratorAnchorDest =
    HTMLGeneratorAnchorSource;

} // namespace doc
} // namespace clang