Serialize index to binary (#273)
This commit is contained in:
@@ -1,836 +0,0 @@
|
||||
#include "Test/Tester.h"
|
||||
#include "Index/HeaderIndex.h"
|
||||
|
||||
namespace clice::testing {
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace clice::index::memory;
|
||||
|
||||
struct DumpConfig {
|
||||
bool enable_total = false;
|
||||
bool enable_contexts = false;
|
||||
bool enable_symbol = false;
|
||||
bool enable_occurrence = false;
|
||||
};
|
||||
|
||||
auto dump = [](HeaderIndex& index, DumpConfig config) {
|
||||
if(config.enable_total) {
|
||||
std::println("\n---------------------------Total Info---------------------------");
|
||||
std::println("file count: {}", index.file_count());
|
||||
std::println("header context count: {}", index.header_context_count());
|
||||
std::println("canonical context count: {}", index.canonical_context_count());
|
||||
std::println("symbol count: {}", index.symbols.size());
|
||||
std::println("occurrence count: {}", index.occurrences.size());
|
||||
}
|
||||
|
||||
if(config.enable_contexts) {
|
||||
std::println("\n--------------------------Contexts Info-------------------------");
|
||||
for(auto& [path, contents]: index.header_contexts) {
|
||||
std::println("{}:", path);
|
||||
for(auto& context: contents) {
|
||||
std::println(" include: {}, hctx_id: {}, cctx_id: {}",
|
||||
context.include,
|
||||
context.hctx_id,
|
||||
context.cctx_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(config.enable_symbol) {
|
||||
std::println("\n-------------------------Symbols Info--------------------------");
|
||||
for(auto& [symbol_id, symbol]: index.symbols) {
|
||||
std::println("symbol: {}, kind: {}", symbol.name, symbol.kind.name());
|
||||
for(auto& relation: symbol.relations) {
|
||||
if(relation.ctx.is_dependent()) {
|
||||
auto context = index.dependent_elem_states[relation.ctx.offset()];
|
||||
std::println(" kind: {}, context: {:#b}",
|
||||
relation.kind.name(),
|
||||
context.to_ulong());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(config.enable_occurrence) {
|
||||
std::println("\n-------------------------Occurrences Info--------------------------");
|
||||
for(auto& [range, occurrences]: index.occurrences) {
|
||||
std::println("occurrence: {} {}", range.begin, range.end);
|
||||
for(auto& occurrence: occurrences) {
|
||||
if(occurrence.ctx.is_dependent()) {
|
||||
auto context = index.dependent_elem_states[occurrence.ctx.offset()];
|
||||
std::println(" target: {}, context: {:#b}",
|
||||
occurrence.target_symbol,
|
||||
context.to_ulong());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// TODO: We should have a more clean way to save test data(like json), rather than out put code
|
||||
/// directly.
|
||||
auto test_code = [](HeaderIndex& index, std::uint32_t id) {
|
||||
std::string code;
|
||||
std::string index_name = std::format("index{}", id);
|
||||
code += std::format("RawIndex {};", index_name);
|
||||
auto& [path, contexts] = *index.header_contexts.begin();
|
||||
code += std::format(R"({}.add_context("{}", {});)", index_name, path, contexts[0].include);
|
||||
code += "\n";
|
||||
|
||||
for(auto& [symbol_id, symbol]: index.symbols) {
|
||||
code += "{";
|
||||
code += std::format(R"(
|
||||
auto& symbol = {}.get_symbol({}ull);
|
||||
symbol.name = "{}";
|
||||
symbol.kind = SymbolKind::{};
|
||||
)",
|
||||
index_name,
|
||||
symbol_id,
|
||||
symbol.name,
|
||||
symbol.kind.name());
|
||||
code += "\n";
|
||||
|
||||
for(auto& relation: symbol.relations) {
|
||||
code += std::format(R"({}.add_relation(
|
||||
symbol,
|
||||
Relation{{
|
||||
.kind = RelationKind::{},
|
||||
.range = {{ {}, {} }},
|
||||
.target_symbol = {}ull,
|
||||
}}
|
||||
);)",
|
||||
index_name,
|
||||
relation.kind.name(),
|
||||
relation.range.begin,
|
||||
relation.range.end,
|
||||
relation.target_symbol);
|
||||
}
|
||||
code += "}\n";
|
||||
}
|
||||
|
||||
// for(auto& [range, occurrence_group]: index.occurrences) {
|
||||
// code += "{";
|
||||
// code += std::format("LocalSourceRange range{{ {}, {} }};\n", range.begin, range.end);
|
||||
// for(auto& occurrence: occurrence_group) {
|
||||
// code += std::format("index.add_occurrence(range, {});\n",
|
||||
// occurrence.target_symbol);
|
||||
// }
|
||||
// code += "}";
|
||||
// }
|
||||
|
||||
return code;
|
||||
};
|
||||
|
||||
suite<"HeaderIndex"> header_index = [] {
|
||||
test("AddRemoveContext") = [&] {
|
||||
HeaderIndex index;
|
||||
|
||||
{
|
||||
auto context = index.add_context("test.h", 1);
|
||||
expect(that % context.cctx_id == 0);
|
||||
expect(that % context.hctx_id == 0);
|
||||
expect(that % index.header_context_count() == 1);
|
||||
expect(that % index.canonical_context_count() == 1);
|
||||
}
|
||||
|
||||
{
|
||||
auto context = index.add_context("test.h", 2);
|
||||
expect(that % context.cctx_id == 1);
|
||||
expect(that % context.hctx_id == 1);
|
||||
expect(that % index.header_context_count() == 2);
|
||||
expect(that % index.canonical_context_count() == 2);
|
||||
}
|
||||
|
||||
expect(that % index.file_count() == 1);
|
||||
|
||||
{
|
||||
auto context = index.add_context("test2.h", 1);
|
||||
expect(that % context.cctx_id == 2);
|
||||
expect(that % context.hctx_id == 2);
|
||||
expect(that % index.header_context_count() == 3);
|
||||
expect(that % index.canonical_context_count() == 3);
|
||||
}
|
||||
|
||||
expect(that % index.file_count() == 2);
|
||||
|
||||
index.remove("test.h");
|
||||
|
||||
expect(that % index.header_context_count() == 1);
|
||||
expect(that % index.canonical_context_count() == 1);
|
||||
|
||||
/// Test reuse context id and context ref.
|
||||
{
|
||||
auto context = index.add_context("test3.h", 1);
|
||||
expect(that % context.cctx_id == 0);
|
||||
expect(that % context.hctx_id == 0);
|
||||
expect(that % index.header_context_count() == 2);
|
||||
expect(that % index.canonical_context_count() == 2);
|
||||
}
|
||||
|
||||
{
|
||||
index.add_context("test4.h", 1);
|
||||
expect(that % index.header_context_count() == 3);
|
||||
expect(that % index.canonical_context_count() == 3);
|
||||
}
|
||||
|
||||
{
|
||||
index.add_context("test5.h", 1);
|
||||
expect(that % index.header_context_count() == 4);
|
||||
expect(that % index.canonical_context_count() == 4);
|
||||
}
|
||||
|
||||
expect(that % index.file_count() == 4);
|
||||
};
|
||||
|
||||
test("SymbolInsert") = [&] {
|
||||
HeaderIndex index;
|
||||
index.add_context("test.h", 1);
|
||||
index.add_occurrence({1, 2}, 1);
|
||||
};
|
||||
|
||||
test("MergeEmpty") = [&] {
|
||||
HeaderIndex base;
|
||||
|
||||
RawIndex index;
|
||||
index.add_occurrence({1, 2}, 1);
|
||||
base.merge("test.h", 1, index);
|
||||
expect(that % base.header_context_count() == 1);
|
||||
expect(that % base.canonical_context_count() == 1);
|
||||
expect(that % base.file_count() == 1);
|
||||
|
||||
RawIndex index2;
|
||||
base.merge("test2.h", 1, index2);
|
||||
expect(that % base.header_context_count() == 2);
|
||||
expect(that % base.canonical_context_count() == 2);
|
||||
expect(that % base.file_count() == 2);
|
||||
|
||||
RawIndex index3;
|
||||
base.merge("test3.h", 1, index3);
|
||||
expect(that % base.header_context_count() == 3);
|
||||
expect(that % base.canonical_context_count() == 2);
|
||||
expect(that % base.file_count() == 3);
|
||||
};
|
||||
|
||||
test("MergeOccurrence") = [&] {
|
||||
HeaderIndex base;
|
||||
|
||||
RawIndex index;
|
||||
index.add_occurrence({1, 2}, 1);
|
||||
base.merge("test.h", 1, index);
|
||||
|
||||
RawIndex index2;
|
||||
index2.add_occurrence({1, 2}, 1);
|
||||
base.merge("test2.h", 1, index2);
|
||||
expect(that % base.header_context_count() == 2);
|
||||
expect(that % base.canonical_context_count() == 1);
|
||||
expect(that % base.file_count() == 2);
|
||||
|
||||
RawIndex index3;
|
||||
index3.add_occurrence({1, 2}, 2);
|
||||
base.merge("test3.h", 1, index3);
|
||||
expect(that % base.header_context_count() == 3);
|
||||
expect(that % base.canonical_context_count() == 2);
|
||||
expect(that % base.file_count() == 3);
|
||||
};
|
||||
|
||||
test("MergeSymbol") = [&] {
|
||||
LocalSourceRange range = {0, 0};
|
||||
|
||||
HeaderIndex base;
|
||||
{
|
||||
RawIndex index;
|
||||
auto& symbol = index.get_symbol(1);
|
||||
index.add_relation(symbol, Relation{.kind = RelationKind::Reference, .range = range});
|
||||
base.merge("test.h", 1, index);
|
||||
}
|
||||
|
||||
/// Same canonical context.
|
||||
{
|
||||
RawIndex index;
|
||||
auto& symbol = index.get_symbol(1);
|
||||
index.add_relation(symbol, Relation{.kind = RelationKind::Reference, .range = range});
|
||||
auto context = base.merge("test2.h", 1, index);
|
||||
expect(that % context.hctx_id == 1);
|
||||
expect(that % context.cctx_id == 0);
|
||||
expect(that % base.header_context_count() == 2);
|
||||
expect(that % base.canonical_context_count() == 1);
|
||||
expect(that % base.file_count() == 2);
|
||||
}
|
||||
|
||||
/// New canonical context.
|
||||
{
|
||||
RawIndex index;
|
||||
auto& symbol = index.get_symbol(1);
|
||||
index.add_relation(symbol, Relation{.kind = RelationKind::Definition, .range = range});
|
||||
|
||||
auto context = base.merge("test3.h", 1, index);
|
||||
expect(that % context.hctx_id == 2);
|
||||
expect(that % context.cctx_id == 1);
|
||||
expect(that % base.header_context_count() == 3);
|
||||
expect(that % base.canonical_context_count() == 2);
|
||||
expect(that % base.file_count() == 3);
|
||||
}
|
||||
|
||||
/// New canonical context.
|
||||
{
|
||||
RawIndex index;
|
||||
auto& symbol = index.get_symbol(1);
|
||||
index.add_relation(symbol, Relation{.kind = RelationKind::Definition, .range = range});
|
||||
index.add_relation(symbol, Relation{.kind = RelationKind::Declaration, .range = range});
|
||||
|
||||
auto context = base.merge("test4.h", 1, index);
|
||||
expect(that % context.hctx_id == 3);
|
||||
expect(that % context.cctx_id == 2);
|
||||
expect(that % base.header_context_count() == 4);
|
||||
expect(that % base.canonical_context_count() == 3);
|
||||
expect(that % base.file_count() == 4);
|
||||
}
|
||||
};
|
||||
|
||||
test("MergeReuse") = [&] {
|
||||
LocalSourceRange range = {0, 0};
|
||||
HeaderIndex base;
|
||||
|
||||
RawIndex index;
|
||||
index.add_occurrence(range, 1);
|
||||
base.merge("test.h", 1, index);
|
||||
|
||||
/// Same context
|
||||
RawIndex index2;
|
||||
index2.add_occurrence(range, 1);
|
||||
base.merge("test.h", 2, index2);
|
||||
expect(that % base.canonical_context_count() == 1);
|
||||
|
||||
/// New Context
|
||||
RawIndex index3;
|
||||
index3.add_occurrence(range, 2);
|
||||
base.merge("test.h", 3, index3);
|
||||
expect(that % base.canonical_context_count() == 2);
|
||||
|
||||
/// Same Context
|
||||
RawIndex index4;
|
||||
index4.add_occurrence(range, 1);
|
||||
base.merge("test.h", 4, index4);
|
||||
expect(that % base.canonical_context_count() == 2);
|
||||
};
|
||||
|
||||
test("MergeComplex") = [] {
|
||||
RawIndex index1;
|
||||
{
|
||||
auto& symbol = index1.get_symbol(5617328926567294902ull);
|
||||
symbol.name = "__need_wchar_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {1948, 1962},
|
||||
.target_symbol = 8426725836700ull,
|
||||
});
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4100, 4114},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index1.get_symbol(17660704465322401956ull);
|
||||
symbol.name = "__need_offsetof";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4720, 4735},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {3433, 3448},
|
||||
.target_symbol = 14809047240041ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index1.get_symbol(12199573421319547529ull);
|
||||
symbol.name = "__need_size_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3867, 3880},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {1734, 1747},
|
||||
.target_symbol = 7503307867846ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index1.get_symbol(447841485290421751ull);
|
||||
symbol.name = "__need_max_align_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {3399, 3417},
|
||||
.target_symbol = 14675903253831ull,
|
||||
});
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4592, 4610},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index1.get_symbol(3892980363519083943ull);
|
||||
symbol.name = "__need_nullptr_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {3138, 3154},
|
||||
.target_symbol = 13546326854722ull,
|
||||
});
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4328, 4344},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index1.get_symbol(6389328935281374692ull);
|
||||
symbol.name = "__need_NULL";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4212, 4223},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {3005, 3016},
|
||||
.target_symbol = 12953621367741ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index1.get_symbol(13138966718646481517ull);
|
||||
symbol.name = "__cplusplus";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3367, 3378},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index1.get_symbol(4048786579988097027ull);
|
||||
symbol.name = "__need_ptrdiff_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {1709, 1725},
|
||||
.target_symbol = 7408818587309ull,
|
||||
});
|
||||
index1.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3747, 3763},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
|
||||
RawIndex index2;
|
||||
{
|
||||
auto& symbol = index2.get_symbol(12199573421319547529ull);
|
||||
symbol.name = "__need_size_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index2.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3867, 3880},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index2.get_symbol(6389328935281374692ull);
|
||||
symbol.name = "__need_NULL";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index2.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4212, 4223},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
|
||||
RawIndex index3;
|
||||
|
||||
{
|
||||
auto& symbol = index3.get_symbol(5617328926567294902ull);
|
||||
symbol.name = "__need_wchar_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index3.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4100, 4114},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index3.get_symbol(12199573421319547529ull);
|
||||
symbol.name = "__need_size_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index3.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3867, 3880},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index3.get_symbol(6389328935281374692ull);
|
||||
symbol.name = "__need_NULL";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index3.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4212, 4223},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
|
||||
RawIndex index4;
|
||||
{
|
||||
auto& symbol = index4.get_symbol(12199573421319547529ull);
|
||||
symbol.name = "__need_size_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index4.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3867, 3880},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index4.get_symbol(6389328935281374692ull);
|
||||
symbol.name = "__need_NULL";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index4.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4212, 4223},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
|
||||
RawIndex index5;
|
||||
{
|
||||
auto& symbol = index5.get_symbol(12199573421319547529ull);
|
||||
symbol.name = "__need_size_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index5.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3867, 3880},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
|
||||
RawIndex index6;
|
||||
{
|
||||
auto& symbol = index6.get_symbol(12199573421319547529ull);
|
||||
symbol.name = "__need_size_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index6.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3867, 3880},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index6.get_symbol(6389328935281374692ull);
|
||||
symbol.name = "__need_NULL";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index6.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4212, 4223},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
|
||||
RawIndex index7;
|
||||
{
|
||||
auto& symbol = index7.get_symbol(5617328926567294902ull);
|
||||
symbol.name = "__need_wchar_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {1948, 1962},
|
||||
.target_symbol = 8426725836700ull,
|
||||
});
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4100, 4114},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index7.get_symbol(17660704465322401956ull);
|
||||
symbol.name = "__need_offsetof";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4720, 4735},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {3433, 3448},
|
||||
.target_symbol = 14809047240041ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index7.get_symbol(12199573421319547529ull);
|
||||
symbol.name = "__need_size_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3867, 3880},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {1734, 1747},
|
||||
.target_symbol = 7503307867846ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index7.get_symbol(447841485290421751ull);
|
||||
symbol.name = "__need_max_align_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {3399, 3417},
|
||||
.target_symbol = 14675903253831ull,
|
||||
});
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4592, 4610},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index7.get_symbol(3892980363519083943ull);
|
||||
symbol.name = "__need_nullptr_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {3138, 3154},
|
||||
.target_symbol = 13546326854722ull,
|
||||
});
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4328, 4344},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index7.get_symbol(6389328935281374692ull);
|
||||
symbol.name = "__need_NULL";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4212, 4223},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {3005, 3016},
|
||||
.target_symbol = 12953621367741ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index7.get_symbol(13138966718646481517ull);
|
||||
symbol.name = "__cplusplus";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3367, 3378},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index7.get_symbol(4048786579988097027ull);
|
||||
symbol.name = "__need_ptrdiff_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Definition,
|
||||
.range = {1709, 1725},
|
||||
.target_symbol = 7408818587309ull,
|
||||
});
|
||||
index7.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3747, 3763},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
|
||||
RawIndex index8;
|
||||
{
|
||||
auto& symbol = index8.get_symbol(5617328926567294902ull);
|
||||
symbol.name = "__need_wchar_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index8.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4100, 4114},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index8.get_symbol(12199573421319547529ull);
|
||||
symbol.name = "__need_size_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index8.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3867, 3880},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& symbol = index8.get_symbol(6389328935281374692ull);
|
||||
symbol.name = "__need_NULL";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index8.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4212, 4223},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
|
||||
RawIndex index9;
|
||||
{
|
||||
auto& symbol = index9.get_symbol(6389328935281374692ull);
|
||||
symbol.name = "__need_NULL";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index9.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {4212, 4223},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
|
||||
RawIndex index10;
|
||||
{
|
||||
auto& symbol = index10.get_symbol(12199573421319547529ull);
|
||||
symbol.name = "__need_size_t";
|
||||
symbol.kind = SymbolKind::Macro;
|
||||
|
||||
index10.add_relation(symbol,
|
||||
Relation{
|
||||
.kind = RelationKind::Reference,
|
||||
.range = {3867, 3880},
|
||||
.target_symbol = 0ull,
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
HeaderIndex base;
|
||||
auto context = base.merge("main.cpp", 56, index1);
|
||||
expect(refl::equal(context, HeaderIndex::HeaderContext{56, 0, 0}));
|
||||
|
||||
context = base.merge("main.cpp", 83, index2);
|
||||
expect(refl::equal(context, HeaderIndex::HeaderContext{83, 1, 1}));
|
||||
|
||||
context = base.merge("main.cpp", 87, index3);
|
||||
expect(refl::equal(context, HeaderIndex::HeaderContext{87, 2, 2}));
|
||||
|
||||
context = base.merge("main.cpp", 118, index4);
|
||||
expect(refl::equal(context, HeaderIndex::HeaderContext{118, 3, 1}));
|
||||
|
||||
context = base.merge("main.cpp", 135, index5);
|
||||
expect(refl::equal(context, HeaderIndex::HeaderContext{135, 4, 3}));
|
||||
|
||||
context = base.merge("main.cpp", 147, index6);
|
||||
expect(refl::equal(context, HeaderIndex::HeaderContext{147, 5, 1}));
|
||||
|
||||
context = base.merge("main.cpp", 150, index7);
|
||||
expect(refl::equal(context, HeaderIndex::HeaderContext{150, 6, 0}));
|
||||
|
||||
context = base.merge("main.cpp", 178, index8);
|
||||
expect(refl::equal(context, HeaderIndex::HeaderContext{178, 7, 2}));
|
||||
|
||||
context = base.merge("main.cpp", 212, index9);
|
||||
expect(refl::equal(context, HeaderIndex::HeaderContext{212, 8, 4}));
|
||||
|
||||
context = base.merge("main.cpp", 226, index10);
|
||||
expect(refl::equal(context, HeaderIndex::HeaderContext{226, 9, 3}));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
} // namespace clice::testing
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "Test/Tester.h"
|
||||
#include "Index/MergedIndex.h"
|
||||
#include "Async/Async.h"
|
||||
|
||||
namespace clice::testing {
|
||||
|
||||
@@ -43,21 +44,33 @@ suite<"MergedIndex"> suite = [] {
|
||||
expect(eq(dump(it->range), dump(range)), location);
|
||||
};
|
||||
|
||||
test("Assert") = [&] {
|
||||
test("Serialization") = [&] {
|
||||
build_index(R"(
|
||||
#include <iostream>
|
||||
|
||||
int main () {
|
||||
std::cout << "Hello world!" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
)");
|
||||
|
||||
std::println("{}", tu_index.file_indices.size());
|
||||
|
||||
index::MergedIndex merged;
|
||||
|
||||
llvm::StringMap<index::MergedIndex> merged_indices;
|
||||
auto& graph = tu_index.graph;
|
||||
for(auto& [fid, index]: tu_index.file_indices) {
|
||||
auto path = tester.unit->file_path(fid);
|
||||
llvm::StringRef path = graph.paths[graph.path_id(fid)];
|
||||
merged_indices[path].merge("main.cpp", graph.include_location_id(fid), index);
|
||||
}
|
||||
|
||||
if(path.ends_with("stddef.h")) {
|
||||
merged.merge(path, tu_index.graph.getInclude(fid), index);
|
||||
}
|
||||
for(auto& [path, merged]: merged_indices) {
|
||||
llvm::SmallString<1024> s;
|
||||
llvm::raw_svector_ostream os(s);
|
||||
|
||||
merged.serialize(os);
|
||||
|
||||
index::MergedIndexView view(s.data());
|
||||
auto merged2 = view.deserialize();
|
||||
|
||||
expect(merged == merged2);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -18,13 +18,9 @@ suite<"TUIndex"> suite = [] {
|
||||
tu_index = index::TUIndex::build(*tester.unit);
|
||||
};
|
||||
|
||||
auto expect_select = [&](llvm::StringRef pos,
|
||||
llvm::StringRef expect_range,
|
||||
llvm::StringRef file = "",
|
||||
std::source_location location = std::source_location::current()) {
|
||||
auto select = [&](llvm::StringRef pos,
|
||||
llvm::StringRef file = "") -> std::vector<index::Occurrence> {
|
||||
auto offset = tester.point(pos, file);
|
||||
auto range = tester.range(expect_range, file);
|
||||
|
||||
auto fid = file.empty() ? tester.unit->interested_file() : tester.unit->file_id(file);
|
||||
auto& index = tu_index.file_indices[fid];
|
||||
|
||||
@@ -34,13 +30,63 @@ suite<"TUIndex"> suite = [] {
|
||||
{},
|
||||
[](index::Occurrence& occurrence) { return occurrence.range.end; });
|
||||
|
||||
auto err =
|
||||
std::format("Fail to find symbol for offser: {} range: range: {}", offset, dump(range));
|
||||
std::vector<index::Occurrence> occurrences;
|
||||
while(it != index.occurrences.end()) {
|
||||
if(it->range.contains(offset)) {
|
||||
occurrences.emplace_back(*it);
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
fatal / expect(it != index.occurrences.end(), location) << err;
|
||||
break;
|
||||
}
|
||||
return occurrences;
|
||||
};
|
||||
|
||||
auto expect_select = [&](llvm::StringRef pos,
|
||||
llvm::StringRef expect_range,
|
||||
llvm::StringRef file = "",
|
||||
std::source_location location = std::source_location::current()) {
|
||||
auto offset = tester.point(pos, file);
|
||||
auto range = tester.range(expect_range, file);
|
||||
auto occurrences = select(pos, file);
|
||||
|
||||
fatal / expect(!occurrences.empty(), location)
|
||||
<< std::format("Fail to find symbol for offset: {}, target range: {}",
|
||||
offset,
|
||||
dump(range));
|
||||
|
||||
/// FIXME: Make eq pretty print reflectable struct.
|
||||
expect(eq(dump(it->range), dump(range)), location);
|
||||
expect(eq(dump(occurrences.front().range), dump(range)), location);
|
||||
};
|
||||
|
||||
auto go_to_definition = [&](llvm::StringRef pos,
|
||||
llvm::StringRef definition,
|
||||
llvm::StringRef file = "",
|
||||
std::source_location location = std::source_location::current()) {
|
||||
auto offset = tester.point(pos, file);
|
||||
auto range = tester.range(definition, file);
|
||||
auto occurrences = select(pos, file);
|
||||
|
||||
fatal / expect(occurrences.size() == 1, location)
|
||||
<< std::format("Fail to find symbol for offset: {}, target range: {}",
|
||||
offset,
|
||||
dump(range));
|
||||
|
||||
auto fid = file.empty() ? tester.unit->interested_file() : tester.unit->file_id(file);
|
||||
auto& index = tu_index.file_indices[fid];
|
||||
|
||||
auto it = index.relations.find(occurrences.front().target);
|
||||
fatal / expect(it != index.relations.end(), location)
|
||||
<< std::format("Cannot find target: {}", occurrences.front().target);
|
||||
|
||||
auto& relations = it->second;
|
||||
auto target =
|
||||
std::ranges::find(relations, RelationKind::Definition, &index::Relation::kind);
|
||||
|
||||
fatal / expect(target != relations.end(), location)
|
||||
<< std::format("Fail to find definition in {}", dump(relations));
|
||||
expect(eq(dump(target->range), dump(range)), location);
|
||||
};
|
||||
|
||||
test("Basic") = [&] {
|
||||
@@ -61,6 +107,144 @@ suite<"TUIndex"> suite = [] {
|
||||
expect_select("2", "2");
|
||||
expect_select("3", "3");
|
||||
};
|
||||
|
||||
test("ClassTemplate") = [&] {
|
||||
build_index(R"(
|
||||
template <typename T, typename U>
|
||||
struct $(primary_decl)foo;
|
||||
|
||||
/// using type = $(forward_full)foo<int, int>;
|
||||
|
||||
template <typename T, typename U>
|
||||
struct @primary[foo] {};
|
||||
|
||||
template <typename T>
|
||||
struct $(partial_spec_decl)foo<T, T>;
|
||||
|
||||
template <typename T>
|
||||
struct @partial_spec[foo]<T, T> {};
|
||||
|
||||
template <>
|
||||
struct $(full_spec_decl)foo<int, int>;
|
||||
|
||||
template <>
|
||||
struct @full_spec[foo]<int, int> {};
|
||||
|
||||
template struct $(explicit_primary)foo<char, int>;
|
||||
|
||||
template struct $(explicit_partial)foo<char, char>;
|
||||
|
||||
$(implicit_primary_1)foo<int, char> b;
|
||||
$(implicit_primary_2)foo<char, int> c;
|
||||
$(implicit_partial)foo<char, char> d;
|
||||
$(implicit_full)foo<int, int> a;
|
||||
)");
|
||||
|
||||
go_to_definition("primary_decl", "primary");
|
||||
go_to_definition("explicit_primary", "primary");
|
||||
go_to_definition("implicit_primary_1", "primary");
|
||||
go_to_definition("implicit_primary_2", "primary");
|
||||
go_to_definition("partial_spec_decl", "partial_spec");
|
||||
go_to_definition("explicit_partial", "partial_spec");
|
||||
go_to_definition("implicit_partial", "partial_spec");
|
||||
/// FIXME: Figure forward template declaration.
|
||||
/// go_to_definition("forward_full", "full_spec");
|
||||
go_to_definition("full_spec_decl", "full_spec");
|
||||
go_to_definition("implicit_full", "full_spec");
|
||||
};
|
||||
|
||||
test("FunctionTemplate") = [&] {
|
||||
build_index(R"(
|
||||
template <typename T> void $(primary_decl)foo();
|
||||
|
||||
template <typename T> void @primary[foo]() {}
|
||||
|
||||
template <> void $(spec_decl)foo<int>();
|
||||
|
||||
template <> void @spec[foo]<int>() {}
|
||||
|
||||
template void $(explicit_primary)foo<char>();
|
||||
|
||||
int main() {
|
||||
$(implicit_primary)foo<char>();
|
||||
$(implicit_spec)foo<int>();
|
||||
}
|
||||
)");
|
||||
|
||||
go_to_definition("primary_decl", "primary");
|
||||
/// FIXME: clang doen't record location info of explicit function instantiation/
|
||||
/// See https://github.com/llvm/llvm-project/issues/115418.
|
||||
/// go_to_definition("explicit_primary", "primary");
|
||||
go_to_definition("implicit_primary", "primary");
|
||||
go_to_definition("spec_decl", "spec");
|
||||
go_to_definition("implicit_spec", "spec");
|
||||
};
|
||||
|
||||
test("AliasTemplate") = [&] {
|
||||
build_index(R"(
|
||||
template <typename T>
|
||||
using @primary[foo] = T;
|
||||
|
||||
$(implicit_primary)foo<int> a;
|
||||
)");
|
||||
|
||||
go_to_definition("implicit_primary", "primary");
|
||||
};
|
||||
|
||||
test("VarTemplate") = [&] {
|
||||
build_index(R"(
|
||||
template <typename T, typename U>
|
||||
extern int $(primary_decl)foo;
|
||||
|
||||
template <typename T, typename U>
|
||||
int @primary[foo] = 1;
|
||||
|
||||
template <typename T>
|
||||
extern int $(partial_spec_decl)foo<T, T>;
|
||||
|
||||
template <typename T>
|
||||
int @partial_spec[foo]<T, T> = 2;
|
||||
|
||||
template <>
|
||||
float @full_spec[foo]<int, int> = 1.0f;
|
||||
|
||||
template int $(explicit_primary)foo<char, int>;
|
||||
|
||||
template int $(explicit_partial)foo<char, char>;
|
||||
|
||||
int main() {
|
||||
$(implicit_primary_1)foo<int, char> = 1;
|
||||
$(implicit_primary_2)foo<char, int> = 2;
|
||||
$(implicit_partial)foo<char, char> = 3;
|
||||
$(implicit_full)foo<int, int> = 4;
|
||||
return 0;
|
||||
}
|
||||
)");
|
||||
|
||||
go_to_definition("primary_decl", "primary");
|
||||
/// go_to_definition("explicit_primary", "primary");
|
||||
go_to_definition("implicit_primary_1", "primary");
|
||||
go_to_definition("implicit_primary_2", "primary");
|
||||
go_to_definition("partial_spec_decl", "partial_spec");
|
||||
/// tester.GotoDefinition("explicit_partial", "partial_spec");
|
||||
go_to_definition("implicit_partial", "partial_spec");
|
||||
go_to_definition("implicit_full", "full_spec");
|
||||
};
|
||||
|
||||
test("Concept") = [&] {
|
||||
build_index(R"(
|
||||
template <typename T>
|
||||
concept @primary[$(primary)foo] = true;
|
||||
|
||||
static_assert($(implicit)foo<int>);
|
||||
|
||||
$(implicit2)foo auto bar = 1;
|
||||
)");
|
||||
|
||||
go_to_definition("primary", "primary");
|
||||
go_to_definition("implicit", "primary");
|
||||
go_to_definition("implicit2", "primary");
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
/// #include "Test/IndexTester.h"
|
||||
///
|
||||
/// namespace clice::testing {
|
||||
///
|
||||
/// namespace {
|
||||
///
|
||||
/// TEST(Index, ClassTemplate) {
|
||||
/// const char* code = R"cpp(
|
||||
/// template <typename T, typename U>
|
||||
/// struct $(primary_decl)foo;
|
||||
///
|
||||
/// /// using type = $(forward_full)foo<int, int>;
|
||||
///
|
||||
/// template <typename T, typename U>
|
||||
/// struct $(primary)foo {};
|
||||
///
|
||||
/// template <typename T>
|
||||
/// struct $(partial_spec_decl)foo<T, T>;
|
||||
///
|
||||
/// template <typename T>
|
||||
/// struct $(partial_spec)foo<T, T> {};
|
||||
///
|
||||
/// template <>
|
||||
/// struct $(full_spec_decl)foo<int, int>;
|
||||
///
|
||||
/// template <>
|
||||
/// struct $(full_spec)foo<int, int> {};
|
||||
///
|
||||
/// template struct $(explicit_primary)foo<char, int>;
|
||||
///
|
||||
/// template struct $(explicit_partial)foo<char, char>;
|
||||
///
|
||||
/// $(implicit_primary_1)foo<int, char> b;
|
||||
/// $(implicit_primary_2)foo<char, int> c;
|
||||
/// $(implicit_partial)foo<char, char> d;
|
||||
/// $(implicit_full)foo<int, int> a;
|
||||
///)cpp";
|
||||
///
|
||||
/// IndexTester tester("main.cpp", code);
|
||||
/// tester.run();
|
||||
/// tester.GotoDefinition("primary_decl", "primary");
|
||||
/// tester.GotoDefinition("explicit_primary", "primary");
|
||||
/// tester.GotoDefinition("implicit_primary_1", "primary");
|
||||
/// tester.GotoDefinition("implicit_primary_2", "primary");
|
||||
/// tester.GotoDefinition("partial_spec_decl", "partial_spec");
|
||||
/// tester.GotoDefinition("explicit_partial", "partial_spec");
|
||||
/// tester.GotoDefinition("implicit_partial", "partial_spec");
|
||||
/// /// FIXME: Figure forward template declaration.
|
||||
/// /// tester.GotoDefinition("forward_full", "full_spec");
|
||||
/// tester.GotoDefinition("full_spec_decl", "full_spec");
|
||||
/// tester.GotoDefinition("implicit_full", "full_spec");
|
||||
///
|
||||
/// /// TODO: add more tests, FunctionTemplate, VarTemplate, ..., Dependent Name, ..., etc.
|
||||
/// /// add tests for find references ..., !test symbol count.
|
||||
/// }
|
||||
///
|
||||
/// TEST(Index, FunctionTemplate) {
|
||||
/// /// Function template doesn't have partial specialization.
|
||||
/// const char* code = R"cpp(
|
||||
/// template <typename T> void $(primary_decl)foo();
|
||||
///
|
||||
/// template <typename T> void $(primary)foo() {}
|
||||
///
|
||||
/// template <> void $(spec_decl)foo<int>();
|
||||
///
|
||||
/// template <> void $(spec)foo<int>() {}
|
||||
///
|
||||
/// template void $(explicit_primary)foo<char>();
|
||||
///
|
||||
/// int main() {
|
||||
/// $(implicit_primary)foo<char>();
|
||||
/// $(implicit_spec)foo<int>();
|
||||
/// }
|
||||
///)cpp";
|
||||
///
|
||||
/// IndexTester tester("main.cpp", code);
|
||||
/// tester.run();
|
||||
///
|
||||
/// tester.GotoDefinition("primary_decl", "primary");
|
||||
/// /// FIXME:
|
||||
/// /// tester.GotoDefinition("explicit_primary", "primary");
|
||||
/// tester.GotoDefinition("implicit_primary", "primary");
|
||||
///
|
||||
/// tester.GotoDefinition("spec_decl", "spec");
|
||||
/// tester.GotoDefinition("implicit_spec", "spec");
|
||||
/// }
|
||||
///
|
||||
/// TEST(Index, AliasTemplate) {
|
||||
/// const char* code = R"cpp(
|
||||
/// template <typename T>
|
||||
/// using $(primary)foo = T;
|
||||
///
|
||||
/// $(implicit_primary)foo<int> a;
|
||||
///)cpp";
|
||||
///
|
||||
/// IndexTester tester("main.cpp", code);
|
||||
/// tester.run();
|
||||
/// tester.GotoDefinition("implicit_primary", "primary");
|
||||
/// }
|
||||
///
|
||||
/// TEST(Index, VarTemplate) {
|
||||
/// const char* code = R"cpp(
|
||||
/// template <typename T, typename U>
|
||||
/// extern int $(primary_decl)foo;
|
||||
///
|
||||
/// template <typename T, typename U>
|
||||
/// int $(primary)foo = 1;
|
||||
///
|
||||
/// template <typename T>
|
||||
/// extern int $(partial_spec_decl)foo<T, T>;
|
||||
///
|
||||
/// template <typename T>
|
||||
/// int $(partial_spec)foo<T, T> = 2;
|
||||
///
|
||||
/// template <>
|
||||
/// float $(full_spec)foo<int, int> = 1.0f;
|
||||
///
|
||||
/// template int $(explicit_primary)foo<char, int>;
|
||||
///
|
||||
/// template int $(explicit_partial)foo<char, char>;
|
||||
///
|
||||
/// int main() {
|
||||
/// $(implicit_primary_1)foo<int, char> = 1;
|
||||
/// $(implicit_primary_2)foo<char, int> = 2;
|
||||
/// $(implicit_partial)foo<char, char> = 3;
|
||||
/// $(implicit_full)foo<int, int> = 4;
|
||||
/// return 0;
|
||||
/// }
|
||||
///)cpp";
|
||||
///
|
||||
/// IndexTester tester("main.cpp", code);
|
||||
/// tester.run();
|
||||
///
|
||||
/// tester.GotoDefinition("primary_decl", "primary");
|
||||
/// /// tester.GotoDefinition("explicit_primary", "primary");
|
||||
/// tester.GotoDefinition("implicit_primary_1", "primary");
|
||||
/// tester.GotoDefinition("implicit_primary_2", "primary");
|
||||
///
|
||||
/// tester.GotoDefinition("partial_spec_decl", "partial_spec");
|
||||
/// /// tester.GotoDefinition("explicit_partial", "partial_spec");
|
||||
/// tester.GotoDefinition("implicit_partial", "partial_spec");
|
||||
///
|
||||
/// tester.GotoDefinition("implicit_full", "full_spec");
|
||||
/// }
|
||||
///
|
||||
/// TEST(Index, Concept) {
|
||||
/// const char* code = R"cpp(
|
||||
/// template <typename T>
|
||||
/// concept $(primary)foo = true;
|
||||
///
|
||||
/// static_assert($(implicit)foo<int>);
|
||||
///
|
||||
/// $(implicit2)foo auto bar = 1;
|
||||
///)cpp";
|
||||
///
|
||||
/// IndexTester tester("main.cpp", code);
|
||||
/// tester.run();
|
||||
///
|
||||
/// tester.GotoDefinition("primary", "primary");
|
||||
/// tester.GotoDefinition("implicit", "primary");
|
||||
/// tester.GotoDefinition("implicit2", "primary");
|
||||
/// }
|
||||
///
|
||||
/// } // namespace
|
||||
///
|
||||
/// } // namespace clice::testing
|
||||
Reference in New Issue
Block a user