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 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
//===-- TestIndex.cpp -------------------------------------------*- 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 "TestIndex.h"
#include "clang/Index/IndexSymbol.h"
#include "llvm/Support/Regex.h"
namespace clang {
namespace clangd {
Symbol symbol(llvm::StringRef QName) {
Symbol Sym;
Sym.ID = SymbolID(QName.str());
size_t Pos = QName.rfind("::");
if (Pos == llvm::StringRef::npos) {
Sym.Name = QName;
Sym.Scope = "";
} else {
Sym.Name = QName.substr(Pos + 2);
Sym.Scope = QName.substr(0, Pos + 2);
}
return Sym;
}
static std::string replace(llvm::StringRef Haystack, llvm::StringRef Needle,
llvm::StringRef Repl) {
llvm::SmallVector<llvm::StringRef> Parts;
Haystack.split(Parts, Needle);
return llvm::join(Parts, Repl);
}
// Helpers to produce fake index symbols for memIndex() or completions().
// USRFormat is a regex replacement string for the unqualified part of the USR.
Symbol sym(llvm::StringRef QName, index::SymbolKind Kind,
llvm::StringRef USRFormat) {
Symbol Sym;
std::string USR = "c:"; // We synthesize a few simple cases of USRs by hand!
size_t Pos = QName.rfind("::");
if (Pos == llvm::StringRef::npos) {
Sym.Name = QName;
Sym.Scope = "";
} else {
Sym.Name = QName.substr(Pos + 2);
Sym.Scope = QName.substr(0, Pos + 2);
USR += "@N@" + replace(QName.substr(0, Pos), "::", "@N@"); // ns:: -> @N@ns
}
USR += llvm::Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func#
Sym.ID = SymbolID(USR);
Sym.SymInfo.Kind = Kind;
Sym.Flags |= Symbol::IndexedForCodeCompletion;
Sym.Origin = SymbolOrigin::Static;
return Sym;
}
Symbol func(llvm::StringRef Name) { // Assumes the function has no args.
return sym(Name, index::SymbolKind::Function, "@F@\\0#"); // no args
}
Symbol cls(llvm::StringRef Name) {
return sym(Name, index::SymbolKind::Class, "@S@\\0");
}
Symbol enm(llvm::StringRef Name) {
return sym(Name, index::SymbolKind::Enum, "@E@\\0");
}
Symbol var(llvm::StringRef Name) {
return sym(Name, index::SymbolKind::Variable, "@\\0");
}
Symbol ns(llvm::StringRef Name) {
return sym(Name, index::SymbolKind::Namespace, "@N@\\0");
}
Symbol conceptSym(llvm::StringRef Name) {
return sym(Name, index::SymbolKind::Concept, "@CT@\\0");
}
Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind,
llvm::StringRef USRPrefix) {
Symbol Sym;
std::string USR = USRPrefix.str() + Name.str();
Sym.Name = Name;
Sym.Scope = "";
Sym.ID = SymbolID(USR);
Sym.SymInfo.Kind = Kind;
Sym.SymInfo.Lang = index::SymbolLanguage::ObjC;
Sym.Flags |= Symbol::IndexedForCodeCompletion;
Sym.Origin = SymbolOrigin::Static;
return Sym;
}
Symbol objcClass(llvm::StringRef Name) {
return objcSym(Name, index::SymbolKind::Class, "objc(cs)");
}
Symbol objcProtocol(llvm::StringRef Name) {
return objcSym(Name, index::SymbolKind::Protocol, "objc(pl)");
}
SymbolSlab generateSymbols(std::vector<std::string> QualifiedNames) {
SymbolSlab::Builder Slab;
for (llvm::StringRef QName : QualifiedNames)
Slab.insert(symbol(QName));
return std::move(Slab).build();
}
SymbolSlab generateNumSymbols(int Begin, int End) {
std::vector<std::string> Names;
for (int I = Begin; I <= End; I++)
Names.push_back(std::to_string(I));
return generateSymbols(Names);
}
std::string getQualifiedName(const Symbol &Sym) {
return (Sym.Scope + Sym.Name + Sym.TemplateSpecializationArgs).str();
}
std::vector<std::string> match(const SymbolIndex &I,
const FuzzyFindRequest &Req, bool *Incomplete) {
std::vector<std::string> Matches;
bool IsIncomplete = I.fuzzyFind(Req, [&](const Symbol &Sym) {
Matches.push_back(clang::clangd::getQualifiedName(Sym));
});
if (Incomplete)
*Incomplete = IsIncomplete;
return Matches;
}
// Returns qualified names of symbols with any of IDs in the index.
std::vector<std::string> lookup(const SymbolIndex &I,
llvm::ArrayRef<SymbolID> IDs) {
LookupRequest Req;
Req.IDs.insert(IDs.begin(), IDs.end());
std::vector<std::string> Results;
I.lookup(Req, [&](const Symbol &Sym) {
Results.push_back(getQualifiedName(Sym));
});
return Results;
}
} // namespace clangd
} // namespace clang
|