https://github.com/Decodetalkers updated https://github.com/llvm/llvm-project/pull/204511
>From fe14332bfc0507e85cb9fa86c6b8b9acb979950c Mon Sep 17 00:00:00 2001 From: ShootingStarDragons <[email protected]> Date: Thu, 18 Jun 2026 18:08:05 +0900 Subject: [PATCH 1/4] feat: highlight for keyword of import, export in CXX module This pr aims to add highlight for import and export keyword And induced new SemanticHighlight `keyword` --- .../clangd/SemanticHighlighting.cpp | 17 +++++++++++++++++ clang-tools-extra/clangd/SemanticHighlighting.h | 1 + 2 files changed, 18 insertions(+) diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index 856904bc810d1..19b5af7e58f30 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -582,6 +582,19 @@ class CollectExtraHighlightings return true; } + bool VisitImportDecl(const ImportDecl *D) { + H.addToken(D->getLocation(), HighlightingKind::Keyword); + for (const auto ModuleLoc : D->getIdentifierLocs()) { + H.addToken(ModuleLoc, HighlightingKind::Namespace) + .addModifier(HighlightingModifier::DependentName); + } + return true; + } + bool VisitExportDecl(const ExportDecl *D) { + H.addToken(D->getLocation(), HighlightingKind::Keyword); + return true; + } + bool VisitTagDecl(TagDecl *D) { for (TemplateParameterList *TPL : D->getTemplateParameterLists()) H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc()); @@ -1120,6 +1133,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K) { return OS << "Function"; case HighlightingKind::Method: return OS << "Method"; + case HighlightingKind::Keyword: + return OS << "Keyword"; case HighlightingKind::StaticMethod: return OS << "StaticMethod"; case HighlightingKind::Field: @@ -1323,6 +1338,8 @@ llvm::StringRef toSemanticTokenType(HighlightingKind Kind) { return "function"; case HighlightingKind::Method: return "method"; + case HighlightingKind::Keyword: + return "keyword"; case HighlightingKind::StaticMethod: // FIXME: better method with static modifier? return "function"; diff --git a/clang-tools-extra/clangd/SemanticHighlighting.h b/clang-tools-extra/clangd/SemanticHighlighting.h index 59d742b83ee52..3b1c12418becb 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.h +++ b/clang-tools-extra/clangd/SemanticHighlighting.h @@ -34,6 +34,7 @@ enum class HighlightingKind { Parameter, Function, Method, + Keyword, StaticMethod, Field, StaticField, >From 5d2a238864c0d7b18290316497f93d1b976226d0 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons <[email protected]> Date: Sat, 20 Jun 2026 18:49:58 +0900 Subject: [PATCH 2/4] chore: add highlight for export in CXX Module since I cannot fix the build for cxx module, so I cannot test import, so I test export first --- .../clangd/unittests/SemanticHighlightingTests.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp index f8b7c242be9ff..569760294e455 100644 --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -1123,6 +1123,18 @@ sizeof...($TemplateParameter[[Elements]]); )cpp"}}, ~ScopeModifierMask); + checkHighlightings(R"cpp( + module; + export module highlight; + $Keyword[[export]] void $Function_def[[foo]]() { + } + )cpp", + {{"imp.h", R"cpp( + module; + export module ABC; + )cpp"}}, + ~ScopeModifierMask); + // A separate test for macros in headers. checkHighlightings(R"cpp( #include "imp.h" >From b6d04465c79eff731835d726e2405ab082570fab Mon Sep 17 00:00:00 2001 From: ShootingStarDragons <[email protected]> Date: Mon, 22 Jun 2026 22:31:42 +0900 Subject: [PATCH 3/4] chore: remove keyword and reuse Modifier instead --- clang-tools-extra/clangd/SemanticHighlighting.cpp | 11 +++-------- clang-tools-extra/clangd/SemanticHighlighting.h | 1 - .../clangd/unittests/SemanticHighlightingTests.cpp | 4 ++-- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index 19b5af7e58f30..0be505ba12f59 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -583,15 +583,14 @@ class CollectExtraHighlightings } bool VisitImportDecl(const ImportDecl *D) { - H.addToken(D->getLocation(), HighlightingKind::Keyword); + H.addToken(D->getLocation(), HighlightingKind::Modifier); for (const auto ModuleLoc : D->getIdentifierLocs()) { - H.addToken(ModuleLoc, HighlightingKind::Namespace) - .addModifier(HighlightingModifier::DependentName); + H.addToken(ModuleLoc, HighlightingKind::Namespace); } return true; } bool VisitExportDecl(const ExportDecl *D) { - H.addToken(D->getLocation(), HighlightingKind::Keyword); + H.addToken(D->getLocation(), HighlightingKind::Modifier); return true; } @@ -1133,8 +1132,6 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K) { return OS << "Function"; case HighlightingKind::Method: return OS << "Method"; - case HighlightingKind::Keyword: - return OS << "Keyword"; case HighlightingKind::StaticMethod: return OS << "StaticMethod"; case HighlightingKind::Field: @@ -1338,8 +1335,6 @@ llvm::StringRef toSemanticTokenType(HighlightingKind Kind) { return "function"; case HighlightingKind::Method: return "method"; - case HighlightingKind::Keyword: - return "keyword"; case HighlightingKind::StaticMethod: // FIXME: better method with static modifier? return "function"; diff --git a/clang-tools-extra/clangd/SemanticHighlighting.h b/clang-tools-extra/clangd/SemanticHighlighting.h index 3b1c12418becb..59d742b83ee52 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.h +++ b/clang-tools-extra/clangd/SemanticHighlighting.h @@ -34,7 +34,6 @@ enum class HighlightingKind { Parameter, Function, Method, - Keyword, StaticMethod, Field, StaticField, diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp index 569760294e455..2fdabb1462b46 100644 --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -1126,10 +1126,10 @@ sizeof...($TemplateParameter[[Elements]]); checkHighlightings(R"cpp( module; export module highlight; - $Keyword[[export]] void $Function_def[[foo]]() { + $Modifier[[export]] void $Function_def[[foo]]() { } )cpp", - {{"imp.h", R"cpp( + {{"imp.cxx", R"cpp( module; export module ABC; )cpp"}}, >From b340d378943e17bf648f21e37f7ab90b5078606e Mon Sep 17 00:00:00 2001 From: ShootingStarDragons <[email protected]> Date: Sat, 27 Jun 2026 22:39:20 +0900 Subject: [PATCH 4/4] chore: move sematichighlight to module MockDirectoryCompilationDataBase can handle the task for module, so the highttest can be finished there --- .../unittests/PrerequisiteModulesTest.cpp | 88 +++++++++++++++++++ .../unittests/SemanticHighlightingTests.cpp | 12 --- 2 files changed, 88 insertions(+), 12 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/PrerequisiteModulesTest.cpp b/clang-tools-extra/clangd/unittests/PrerequisiteModulesTest.cpp index b88213decea44..f3bc52c6e9e08 100644 --- a/clang-tools-extra/clangd/unittests/PrerequisiteModulesTest.cpp +++ b/clang-tools-extra/clangd/unittests/PrerequisiteModulesTest.cpp @@ -9,6 +9,7 @@ /// FIXME: Skip testing on windows temporarily due to the different escaping /// code mode. +#include "SemanticHighlighting.h" #ifndef _WIN32 #include "Annotations.h" @@ -1612,7 +1613,94 @@ struct TypeFromHeader {}; testing::UnorderedElementsAre(named("TypeFromModule"), named("TypeFromHeader"))); } +/// Annotates the input code with provided semantic highlightings. Results look +/// something like: +/// class $Class[[X]] { +/// $Primitive[[int]] $Field[[a]] = 0; +/// }; +std::string annotate(llvm::StringRef Input, + llvm::ArrayRef<HighlightingToken> Tokens) { + assert(llvm::is_sorted( + Tokens, [](const HighlightingToken &L, const HighlightingToken &R) { + return L.R.start < R.R.start; + })); + + std::string Buf; + llvm::raw_string_ostream OS(Buf); + unsigned NextChar = 0; + for (auto &T : Tokens) { + unsigned StartOffset = llvm::cantFail(positionToOffset(Input, T.R.start)); + unsigned EndOffset = llvm::cantFail(positionToOffset(Input, T.R.end)); + assert(StartOffset <= EndOffset); + assert(NextChar <= StartOffset); + + bool hasDef = + T.Modifiers & (1 << uint32_t(HighlightingModifier::Definition)); + bool hasDecl = + T.Modifiers & (1 << uint32_t(HighlightingModifier::Declaration)); + EXPECT_TRUE(!hasDef || hasDecl); + + OS << Input.substr(NextChar, StartOffset - NextChar); + OS << '$' << T.Kind; + for (unsigned I = 0; + I <= static_cast<uint32_t>(HighlightingModifier::LastModifier); ++I) { + if (T.Modifiers & (1 << I)) { + // _decl_def is common and redundant, just print _def instead. + if (I != uint32_t(HighlightingModifier::Declaration) || !hasDef) + OS << '_' << static_cast<HighlightingModifier>(I); + } + } + OS << "[[" << Input.substr(StartOffset, EndOffset - StartOffset) << "]]"; + NextChar = EndOffset; + } + OS << Input.substr(NextChar); + return std::move(OS.str()); +} + +TEST_F(PrerequisiteModulesTests, ModuleSemanticHighlighting) { + MockDirectoryCompilationDatabase CDB(TestDir, FS); + llvm::StringRef AnnotatedCode = R"cpp( + module; + $Modifier[[import]] $Namespace[[M]]; + export module highlight; + $Modifier[[export]] void $Function_def_globalScope[[foo]]() { + } +)cpp"; + uint32_t ModifierMask = -1; + Annotations UseCpp(AnnotatedCode); + + CDB.addFile("M.cppm", R"cpp( +export module M; +export struct TypeFromModule {}; +)cpp"); + + CDB.addFile("Use.cpp", UseCpp.code()); + + ModulesBuilder Builder(CDB); + + auto Inputs = getInputs("Use.cpp", CDB); + Inputs.ModulesManager = &Builder; + Inputs.Opts.SkipPreambleBuild = true; + + auto CI = buildCompilerInvocation(Inputs, DiagConsumer); + ASSERT_TRUE(CI); + + auto Preamble = + buildPreamble(getFullPath("Use.cpp"), *CI, Inputs, /*StoreInMemory=*/true, + /*PeambleCallback=*/nullptr); + ASSERT_TRUE(Preamble); + EXPECT_EQ(Preamble->Preamble.getBounds().Size, 0u); + + auto AST = ParsedAST::build(getFullPath("Use.cpp"), Inputs, std::move(CI), {}, + Preamble); + auto Actual = getSemanticHighlightings(AST.value(), + /*IncludeInactiveRegionTokens=*/true); + for (auto &Token : Actual) + Token.Modifiers &= ModifierMask; + + EXPECT_EQ(AnnotatedCode, annotate(UseCpp.code(), Actual)); +} } // namespace } // namespace clang::clangd diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp index 2fdabb1462b46..f8b7c242be9ff 100644 --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -1123,18 +1123,6 @@ sizeof...($TemplateParameter[[Elements]]); )cpp"}}, ~ScopeModifierMask); - checkHighlightings(R"cpp( - module; - export module highlight; - $Modifier[[export]] void $Function_def[[foo]]() { - } - )cpp", - {{"imp.cxx", R"cpp( - module; - export module ABC; - )cpp"}}, - ~ScopeModifierMask); - // A separate test for macros in headers. checkHighlightings(R"cpp( #include "imp.h" _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
