diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -131,6 +131,13 @@ return Definition; } +const char *getMarkdownLanguage(const ASTContext &Ctx) { + const auto &LangOpts = Ctx.getLangOpts(); + if (LangOpts.ObjC && LangOpts.CPlusPlus) + return "objective-cpp"; + return LangOpts.ObjC ? "objective-c" : "cpp"; +} + std::string printType(QualType QT, const PrintingPolicy &PP) { // TypePrinter doesn't resolve decltypes, so resolve them here. // FIXME: This doesn't handle composite types that contain a decltype in them. @@ -1007,6 +1014,7 @@ if (auto Formatted = tooling::applyAllReplacements(HI->Definition, Replacements)) HI->Definition = *Formatted; + HI->DefinitionLanguage = getMarkdownLanguage(AST.getASTContext()); HI->SymRange = halfOpenToRange(SM, HighlightRange); return HI; diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -939,6 +939,39 @@ } } +TEST(Hover, DefinitionLanuage) { + struct { + const char *const Code; + const std::string ClangLanguageFlag; + const char *const ExpectedDefinitionLanguage; + } Cases[] = {{R"cpp( + void [[some^Global]]() {} + )cpp", + "", "cpp"}, + {R"cpp( + void [[some^Global]]() {} + )cpp", + "-xobjective-c++", "objective-cpp"}, + {R"cpp( + void [[some^Global]]() {} + )cpp", + "-xobjective-c", "objective-c"}}; + for (const auto &Case : Cases) { + SCOPED_TRACE(Case.Code); + + Annotations T(Case.Code); + TestTU TU = TestTU::withCode(T.code()); + if (!Case.ClangLanguageFlag.empty()) + TU.ExtraArgs.push_back(Case.ClangLanguageFlag); + auto AST = TU.build(); + + auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); + ASSERT_TRUE(H); + + EXPECT_STREQ(H->DefinitionLanguage, Case.ExpectedDefinitionLanguage); + } +} + TEST(Hover, CallPassType) { const llvm::StringRef CodePrefix = R"cpp( class Base {};