Files
clice/tests/unit/Feature/SemanticToken.cpp
2025-08-03 17:43:42 +08:00

227 lines
5.0 KiB
C++

#include "Test/Tester.h"
#include "Feature/SemanticToken.h"
namespace clice::testing {
namespace {
struct SemanticToken : TestFixture {
feature::SemanticTokens tokens;
using Self = SemanticToken;
void run(llvm::StringRef code) {
add_main("main.cpp", code);
Tester::compile_with_pch();
tokens = feature::semantic_tokens(*unit);
}
void EXPECT_TOKEN(this Self& self,
llvm::StringRef pos,
SymbolKind kind,
uint32_t length,
LocationChain chain = LocationChain()) {
bool visited = false;
auto offset = self["main.cpp", pos];
for(auto& token: self.tokens) {
if(token.range.begin == offset) {
EXPECT_EQ(token.kind, kind, chain);
EXPECT_EQ(token.range.end - token.range.begin, length, chain);
visited = true;
break;
}
}
EXPECT_EQ(visited, true, chain);
}
void EXPECT_TOKEN(this Self& self,
llvm::StringRef pos,
SymbolKind kind,
SymbolModifiers modifiers,
uint32_t length,
LocationChain chain = LocationChain()) {
bool visited = false;
auto offset = self["main.cpp", pos];
for(auto& token: self.tokens) {
if(token.range.begin == offset) {
EXPECT_EQ(token.kind, kind, chain);
EXPECT_EQ(token.range.end - token.range.begin, length, chain);
EXPECT_EQ(token.modifiers, modifiers, chain);
visited = true;
break;
}
}
EXPECT_EQ(visited, true, chain);
}
void dump_result() {
for(auto& token: tokens) {
clice::println("token: {}", dump(token));
}
}
};
using enum SymbolKind::Kind;
using enum SymbolModifiers::Kind;
TEST_F(SemanticToken, Include) {
run(R"cpp(
$(0)#include $(1)<stddef.h>
$(2)#include $(3)"stddef.h"
$(4)# $(5)include $(6)"stddef.h"
)cpp");
/// FIXME: Included file could be macro.
EXPECT_TOKEN("0", Directive, 8);
EXPECT_TOKEN("1", Header, 10);
EXPECT_TOKEN("2", Directive, 8);
EXPECT_TOKEN("3", Header, 10);
EXPECT_TOKEN("4", Directive, 1);
EXPECT_TOKEN("5", Directive, 7);
EXPECT_TOKEN("6", Header, 10);
}
TEST_F(SemanticToken, Comment) {
run(R"cpp(
$(line)/// line comment
int x = 1;
)cpp");
EXPECT_TOKEN("line", Comment, 16);
}
TEST_F(SemanticToken, Keyword) {
run(R"cpp(
$(int)int main() {
$(return)return 0;
}
)cpp");
EXPECT_TOKEN("int", Keyword, 3);
EXPECT_TOKEN("return", Keyword, 6);
}
TEST_F(SemanticToken, Macro) {
run(R"cpp(
$(0)#define $(macro)FOO
)cpp");
EXPECT_TOKEN("0", Directive, 7);
EXPECT_TOKEN("macro", Macro, 3);
}
TEST_F(SemanticToken, FinalAndOverride) {
run(R"cpp(
struct A $(0)final {};
struct B {
virtual void foo();
};
struct C : B {
void foo() $(1)override;
};
struct D : C {
void foo() $(2)final;
};
)cpp");
EXPECT_TOKEN("0", Keyword, 5);
EXPECT_TOKEN("1", Keyword, 8);
EXPECT_TOKEN("2", Keyword, 5);
}
TEST_F(SemanticToken, VarDecl) {
run(R"cpp(
extern int $(0)x;
int $(1)x = 1;
template <typename T, typename U>
extern int $(2)y;
template <typename T, typename U>
int $(3)y = 2;
template<typename T>
extern int $(4)y<T, int>;
template<typename T>
int $(5)y<T, int> = 4;
template<>
int $(6)y<int, int> = 5;
int main() {
$(7)x = 6;
}
)cpp");
EXPECT_TOKEN("0", Variable, Declaration, 1);
EXPECT_TOKEN("1", Variable, Definition, 1);
EXPECT_TOKEN("2", Variable, SymbolModifiers(Declaration, Templated), 1);
EXPECT_TOKEN("3", Variable, SymbolModifiers(Definition, Templated), 1);
EXPECT_TOKEN("4", Variable, SymbolModifiers(Declaration, Templated), 1);
EXPECT_TOKEN("5", Variable, SymbolModifiers(Definition, Templated), 1);
EXPECT_TOKEN("6", Variable, Definition, 1);
EXPECT_TOKEN("7", Variable, SymbolModifiers(), 1);
}
TEST_F(SemanticToken, FunctionDecl) {
run(R"cpp(
extern int $(0)foo();
int $(1)foo() {
return 0;
}
template <typename T>
extern int $(2)bar();
template <typename T>
int $(3)bar() {
return 1;
}
)cpp");
EXPECT_TOKEN("0", Function, Declaration, 3);
EXPECT_TOKEN("1", Function, Definition, 3);
EXPECT_TOKEN("2", Function, SymbolModifiers(Declaration, Templated), 3);
EXPECT_TOKEN("3", Function, SymbolModifiers(Definition, Templated), 3);
}
TEST_F(SemanticToken, RecordDecl) {
run(R"cpp(
class $(0)A;
class $(1)A {};
struct $(2)B;
struct $(3)B {};
union $(4)C;
union $(5)C {};
)cpp");
EXPECT_TOKEN("0", Class, Declaration, 1);
EXPECT_TOKEN("1", Class, Definition, 1);
EXPECT_TOKEN("2", Struct, Declaration, 1);
EXPECT_TOKEN("3", Struct, Definition, 1);
EXPECT_TOKEN("4", Union, Declaration, 1);
EXPECT_TOKEN("5", Union, Definition, 1);
/// FIXME: Add more tests.
}
} // namespace
} // namespace clice::testing