11#include " Feature/Hover.h"
22
33#include " AST/Selection.h"
4- #include " AST/Semantic.h"
54#include " AST/Utility.h"
65#include " Compiler/CompilationUnit.h"
76#include " Index/Shared.h"
8- #include " Support/Compare .h"
7+ #include " Support/Doxygen .h"
98#include " Support/Logging.h"
10- #include " Support/Ranges .h"
9+ #include " Support/StructedText .h"
1110
1211#include " clang/AST/ASTDiagnostic.h"
12+ #include " clang/AST/RecursiveASTVisitor.h"
1313#include " clang/Lex/Lexer.h"
1414#include " clang/Sema/HeuristicResolver.h"
1515
@@ -27,6 +27,15 @@ static auto to_proto_range(clang::SourceManager& sm, clang::SourceRange range) -
2727 return {begin, end};
2828};
2929
30+ clang::PrintingPolicy proxy_print_policy (clang::PrintingPolicy Base) {
31+ Base.AnonymousTagLocations = false ;
32+ Base.TerseOutput = true ;
33+ Base.PolishForDeclaration = true ;
34+ Base.ConstantsAsWritten = true ;
35+ Base.SuppressTemplateArgsInCXXConstructors = true ;
36+ return Base;
37+ }
38+
3039// Print type and optionally desuguared type
3140static std::string print_type (clang::ASTContext& ctx,
3241 clang::QualType qt,
@@ -100,7 +109,7 @@ static std::vector<HoverItem> get_hover_items(CompilationUnitRef unit,
100109 const clang::NamedDecl* decl,
101110 const config::HoverOptions& opt) {
102111 clang::ASTContext& ctx = unit.context ();
103- const auto pp = ctx.getPrintingPolicy ();
112+ const auto pp = proxy_print_policy ( ctx.getPrintingPolicy () );
104113 std::vector<HoverItem> items;
105114
106115 auto add_item = [&items](HoverItem::HoverKind kind, std::string&& val) {
@@ -169,8 +178,8 @@ static std::string get_document(CompilationUnitRef unit,
169178 return " " ;
170179 }
171180 auto raw_string = comment->getFormattedText (Ctx.getSourceManager (), Ctx.getDiagnostics ());
172- LOG_WARN (" Got comment:\n ```\n {}\n ```\n " , raw_string);
173- return " " ;
181+ // LOG_WARN("Got comment:\n```\n{}\n```\n", raw_string);
182+ return raw_string ;
174183}
175184
176185static std::string get_qualifier (CompilationUnitRef unit,
@@ -397,28 +406,36 @@ static std::optional<clang::QualType> getDeducedType(clang::ASTContext& ASTCtx,
397406 return V.DeducedType ;
398407}
399408
400- // TODO: How does clangd put together decl, name, scope and sometimes initialized value?
401- // ```
402- // // scope
403- // <Access specifier> <type> <name> <initialized value>
404- // ```
405- static std::string get_source_code (CompilationUnitRef unit,
406- const clang::NamedDecl* decl,
407- config::HoverOptions opt) {
408- clang::SourceRange range = decl->getSourceRange ();
409- return get_source_code (unit, range);
409+ static std::string get_source_code (const clang::Decl* decl,
410+ clang::PrintingPolicy pp,
411+ const clang::syntax::TokenBuffer& tb) {
412+ if (auto * vd = llvm::dyn_cast<clang::VarDecl>(decl)) {
413+ if (auto * ie = vd->getInit ()) {
414+ // Initializers might be huge and result in lots of memory allocations in
415+ // some catostrophic cases. Such long lists are not useful in hover cards
416+ // anyway.
417+ if (200 < tb.expandedTokens (ie->getSourceRange ()).size ()) {
418+ pp.SuppressInitializers = true ;
419+ }
420+ }
421+ }
422+ std::string def;
423+ llvm::raw_string_ostream os (def);
424+ decl->print (os, pp);
425+ return def;
410426}
411427
412428static std::optional<Hover> hover (CompilationUnitRef unit,
413429 const clang::NamedDecl* decl,
414430 const config::HoverOptions& opt) {
431+ auto pp = proxy_print_policy (unit.context ().getPrintingPolicy ());
415432 return Hover{
416433 .kind = SymbolKind::from (decl),
417434 .name = ast::name_of (decl),
418435 .items = get_hover_items (unit, decl, opt),
419436 .document = get_document (unit, decl, opt),
420437 .qualifier = get_qualifier (unit, decl, opt),
421- .source = get_source_code (unit, decl, opt ),
438+ .source = get_source_code (llvm::dyn_cast< const clang::Decl>( decl), pp, unit. token_buffer () ),
422439 };
423440}
424441
@@ -428,7 +445,7 @@ static std::optional<Hover> hover(CompilationUnitRef unit,
428445 // TODO: Hover for type
429446 // TODO: Add source code
430447 auto & ctx = unit.context ();
431- auto pp = ctx.getPrintingPolicy ();
448+ auto pp = proxy_print_policy ( ctx.getPrintingPolicy () );
432449 return Hover{.kind = SymbolKind::Type, .name = print_type (ctx, ty, pp, opt)};
433450}
434451
@@ -526,12 +543,41 @@ static std::optional<Hover> hover(CompilationUnitRef unit,
526543 return std::nullopt ;
527544}
528545
546+ // TODO: A better way to get current unit lang? e.g. clang::InputKind
547+ const char * get_guessed_lang_name (CompilationUnitRef unit) {
548+ const auto & langopt = unit.lang_options ();
549+ if (langopt.ObjC ) {
550+ if (langopt.CPlusPlus ) {
551+ return " objcpp" ;
552+ }
553+ return " objc" ;
554+ }
555+ if (langopt.CPlusPlus || langopt.HIP ) {
556+ return " cpp" ;
557+ }
558+ if (langopt.CUDA ) {
559+ return " cuda" ;
560+ }
561+ if (langopt.SYCLIsDevice || langopt.SYCLIsHost ) {
562+ return " sycl" ;
563+ }
564+ // Editor Support?
565+ // if(langopt.OpenCL) {
566+ // return "opencl";
567+ // }
568+ if (langopt.HLSL ) {
569+ return " hlsl" ;
570+ }
571+ return " c" ;
572+ }
573+
529574} // namespace
530575
531576std::optional<Hover> hover (CompilationUnitRef unit,
532577 std::uint32_t offset,
533578 const config::HoverOptions& opt) {
534579 auto & sm = unit.context ().getSourceManager ();
580+ auto lang_name = get_guessed_lang_name (unit);
535581
536582 auto src_loc_in_main_file = [&sm, &unit](uint32_t off) -> std::optional<clang::SourceLocation> {
537583 auto fid = sm.getMainFileID ();
@@ -564,6 +610,7 @@ std::optional<Hover> hover(CompilationUnitRef unit,
564610 auto raw_name = get_source_code (unit, inclusion.filename_range );
565611 auto file_name = llvm::StringRef{raw_name}.trim (" <>\" " );
566612 Hover hi;
613+ hi.lang = lang_name;
567614 hi.kind = SymbolKind::Directive;
568615 hi.name = file_name;
569616 auto dir = sm.getFileEntryForID (inclusion.fid )->tryGetRealPathName ();
@@ -587,6 +634,7 @@ std::optional<Hover> hover(CompilationUnitRef unit,
587634 auto macro_name = get_source_code (unit, name_range);
588635 macro_name.pop_back ();
589636 Hover hi;
637+ hi.lang = lang_name;
590638 hi.kind = SymbolKind::Macro;
591639 hi.name = macro_name;
592640 auto source = " #define " + get_source_code (unit,
@@ -620,6 +668,7 @@ std::optional<Hover> hover(CompilationUnitRef unit,
620668 if (auto node = tree.common_ancestor ()) {
621669 LOG_WARN (" Got node: {}" , node->kind ());
622670 if (auto info = hover (unit, node, opt)) {
671+ info->lang = lang_name;
623672 info->hl_range = to_proto_range (sm, hl_range);
624673 return info;
625674 }
@@ -644,20 +693,43 @@ std::optional<std::string> Hover::display(config::HoverOptions opt) {
644693 std::string content;
645694 llvm::raw_string_ostream os (content);
646695 // TODO: generate markdown
647- os << std::format (" {}: {}\n " , this ->kind .name (), this ->name );
648- os << std::format (" Contains {} items\n " , this ->items .size ());
649- for (auto & hi: this ->items ) {
650- os << std::format (" - {}: {}\n " , clice::refl::enum_name (hi.kind ), hi.value );
696+ StructedText out{};
697+ StructedText head_segment{};
698+ head_segment.add_heading (3 ).append_text (std::format (" {}: {}" , this ->kind .name (), this ->name ));
699+ // TODO: provider
700+ head_segment.add_ruler ();
701+ // FIX: Delete later
702+ head_segment.add_paragraph ()
703+ .append_text (std::format (" Contains {} items" , this ->items .size ()))
704+ .append_newline_char ();
705+ if (this ->items .size ()) {
706+ auto & bl = head_segment.add_bullet_list ();
707+ for (auto & hi: this ->items ) {
708+ bl.add_item ().add_paragraph ().append_text (
709+ std::format (" {}: {}" , clice::refl::enum_name (hi.kind ), hi.value ));
710+ }
651711 }
652- if (this ->document ) {
653- os << " ---\n " ;
654- os << " Document:\n ```text\n " << *this ->document << " \n ```\n " ;
712+ out.append (head_segment);
713+ if (this ->document && opt.enable_doxygen_parsing ) {
714+ StructedText st{};
715+ auto & raw = *this ->document ;
716+ auto [di, rest_] = strip_doxygen_info (raw);
717+ if (auto rest = llvm::StringRef (rest_); !rest.trim ().empty ()) {
718+ st.add_paragraph ().append_text (rest.rtrim ().str ());
719+ st.add_ruler ();
720+ }
721+ auto bcc = di.get_block_command_comments ();
722+ for (const auto [tag, content]: bcc) {
723+ st.add_paragraph ().append_text (tag.str (), Paragraph::Kind::Bold);
724+ st.add_ruler ();
725+ }
726+ st.add_ruler ();
727+ out.append (st);
655728 }
656- if (!this ->source .empty ()) {
657- os << " ---\n " ;
658- os << " Source code:\n ```cpp\n " << this ->source << " \n ```\n " ;
729+ if (!source.empty ()) {
730+ out.add_code_block (source + ' \n ' , lang);
659731 }
660- return os. str ();
732+ return out. as_markdown ();
661733}
662734
663735} // namespace clice::feature
0 commit comments