From f50f08fe6518ad5373181f18e3668253c26b84b0 Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Mon, 1 Sep 2025 18:47:58 -0500 Subject: [PATCH 1/4] chore: git ignore IDE config files --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 41b06ce12f..098519ed92 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,7 @@ /docs/ui/public /share/mrdocs/libcxx/ /share/mrdocs/clang/ -/docs/modules/reference \ No newline at end of file +/docs/modules/reference +/.clang-format +/.gdbinit +/.lldbinit \ No newline at end of file From b2c0028bd34431e03d66a5148dd5a6b0f7f85b6f Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Mon, 1 Sep 2025 18:49:37 -0500 Subject: [PATCH 2/4] fix: clang helpers tracing print class header only --- src/lib/AST/ClangHelpers.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/lib/AST/ClangHelpers.cpp b/src/lib/AST/ClangHelpers.cpp index 9528c77c33..f63d3bedde 100644 --- a/src/lib/AST/ClangHelpers.cpp +++ b/src/lib/AST/ClangHelpers.cpp @@ -278,9 +278,32 @@ Decl const* decayToPrimaryTemplate(Decl const* D) { #ifndef NDEBUG + // Print only the class header (name and template args if specialization) SmallString<128> symbolName; + if (const auto* ND = dyn_cast(D)) + { + if (const auto* CTS = dyn_cast(ND)) { + llvm::raw_svector_ostream os(symbolName); + CTS->getSpecializedTemplate()->printQualifiedName(os, CTS->getASTContext().getPrintingPolicy()); + const TemplateArgumentList& args = CTS->getTemplateArgs(); + os << '<'; + for (unsigned i = 0, e = args.size(); i != e; ++i) + { + if (i) os << ", "; + args[i].print(CTS->getASTContext().getPrintingPolicy(), os, true); + } + os << '>'; + } else if (ND) { + llvm::raw_svector_ostream os(symbolName); + ND->printQualifiedName(os, ND->getASTContext().getPrintingPolicy()); + } + } + else + { + llvm::raw_svector_ostream os(symbolName); + os << "Decl::getDeclKindName() << ">"; + } llvm::raw_svector_ostream os(symbolName); - D->print(os); report::trace("symbolName: ", std::string_view(os.str())); #endif From 528e76d1117f9a5d28bfe1b90edb141e962f5f17 Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Mon, 1 Sep 2025 18:50:21 -0500 Subject: [PATCH 3/4] fix(handlebars): recursively traversed namespaces do not include description --- share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs | 2 ++ share/mrdocs/addons/generator/html/partials/symbol.html.hbs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs index 01181cfcb3..24581104d2 100644 --- a/share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs +++ b/share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs @@ -128,8 +128,10 @@ {{/if}} {{! Description }} {{#if symbol.doc.description}} +{{#unless traversing-global-namespace}} {{#> markup/dynamic-level-h }}Description{{/markup/dynamic-level-h}} {{> javadoc/description symbol.doc.description }} +{{/unless}} {{/if}} {{! Using symbols }} {{#if symbol.shadows}} diff --git a/share/mrdocs/addons/generator/html/partials/symbol.html.hbs b/share/mrdocs/addons/generator/html/partials/symbol.html.hbs index 190dab3ae0..ca7cb04133 100644 --- a/share/mrdocs/addons/generator/html/partials/symbol.html.hbs +++ b/share/mrdocs/addons/generator/html/partials/symbol.html.hbs @@ -174,10 +174,12 @@ {{/if}} {{! Description }} {{#if symbol.doc.description}} +{{#unless traversing-global-namespace}}
{{#> markup/dynamic-level-h level=2 }}Description{{/markup/dynamic-level-h}} {{> javadoc/description symbol.doc.description }}
+{{/unless}} {{/if}} {{! Using symbols }} {{#if symbol.shadows}} From 4408d64eec227c31cfd62f1a9a97c6f0c19ac95f Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Mon, 1 Sep 2025 19:01:33 -0500 Subject: [PATCH 4/4] build(bootstrap): include pretty printers configuration --- bootstrap.py | 76 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 10 deletions(-) diff --git a/bootstrap.py b/bootstrap.py index 8148a094ca..1b4f3c8401 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -101,7 +101,7 @@ class InstallOptions: # Libxml2 libxml2_src_dir: str = "/libxml2" - libxml2_build_type: str = "Release" # purposefully does not depend on mrdocs-build-type because we only need the executable + libxml2_build_type: str = "Release" # purposefully does not depend on mrdocs-build-type because we only need the executable libxml2_build_dir: str = "/build/<\"-\":if(cc)>" libxml2_install_dir: str = "/install/<\"-\":if(cc)>" libxml2_repo: str = "https://github.com/GNOME/libxml2" @@ -115,6 +115,9 @@ class InstallOptions: generate_vscode_run_configs: bool = field(default_factory=lambda: os.name != "nt") generate_vs_run_configs: bool = field(default_factory=lambda: os.name == "nt") + # Information to create pretty printer configs + generate_pretty_printer_configs: bool = field(default_factory=lambda: running_from_mrdocs_source_dir()) + # Command line arguments non_interactive: bool = False refresh_all: bool = False @@ -167,6 +170,7 @@ class InstallOptions: "generate_clion_run_configs": "Whether to generate run configurations for CLion.", "generate_vscode_run_configs": "Whether to generate run configurations for Visual Studio Code.", "generate_vs_run_configs": "Whether to generate run configurations for Visual Studio.", + "generate_pretty_printer_configs": "Whether to generate pretty printer configurations for debuggers.", "non_interactive": "Whether to use all default options without interactive prompts.", "refresh_all": "Call the command to refresh dependencies for all configurations", "force_rebuild": "Whether to force a rebuild of all dependencies, even if they are already built.", @@ -514,7 +518,7 @@ def cmake_workflow(self, src_dir, build_type, build_dir, install_dir, extra_args elif extra_arg.startswith('-DCMAKE_CXX_FLAGS='): cxx_flags += ' ' + extra_arg.split('=', 1)[1] extra_args_remove_idx.append(i) - elif i != 0 and extra_args[i-1].strip() == '-D': + elif i != 0 and extra_args[i - 1].strip() == '-D': if extra_arg.startswith('CMAKE_C_FLAGS='): cc_flags += ' ' + extra_arg.split('=', 1)[1] extra_args_remove_idx.append(i - 1) @@ -553,7 +557,8 @@ def cmake_workflow(self, src_dir, build_type, build_dir, install_dir, extra_args # Maybe adjust build type based on the options for the main project if not self.is_abi_compatible(self.options.mrdocs_build_type, build_type): - print(f"Warning: The build type '{build_type}' is not ABI compatible with the MrDocs build type '{self.options.mrdocs_build_type}'.") + print( + f"Warning: The build type '{build_type}' is not ABI compatible with the MrDocs build type '{self.options.mrdocs_build_type}'.") if self.options.mrdocs_build_type.lower() == "debug": # User asked for Release dependency, so we do the best we can and change it to # an optimized debug build. @@ -925,7 +930,8 @@ def probe_compilers(self): shutil.rmtree(probe_dir) # Print default C++ compiler path - print(f"Default C++ compiler: {self.compiler_info.get('CMAKE_CXX_COMPILER_ID', 'unknown')} ({self.compiler_info.get('CMAKE_CXX_COMPILER', 'unknown')})") + print( + f"Default C++ compiler: {self.compiler_info.get('CMAKE_CXX_COMPILER_ID', 'unknown')} ({self.compiler_info.get('CMAKE_CXX_COMPILER', 'unknown')})") print(f"Default C++ build system: {self.compiler_info.get('CMAKE_GENERATOR', 'unknown')}") @lru_cache(maxsize=1) @@ -983,7 +989,6 @@ def probe_msvc_dev_env(self): self.env[key] = value print("MSVC development environment variables extracted successfully.") - @lru_cache(maxsize=1) def is_homebrew_clang(self): self.probe_compilers() @@ -1894,7 +1899,8 @@ def vs_config_type(config): return "default" def rel_to_mrdocs_dir(script_path): - is_subdir_of_mrdocs_src_dir = script_path.replace('\\', '/').rstrip('/').startswith(self.options.mrdocs_src_dir.replace('\\', '/').rstrip('/')) + is_subdir_of_mrdocs_src_dir = script_path.replace('\\', '/').rstrip('/').startswith( + self.options.mrdocs_src_dir.replace('\\', '/').rstrip('/')) if is_subdir_of_mrdocs_src_dir: return os.path.relpath(script_path, self.options.mrdocs_src_dir) return script_path @@ -1981,7 +1987,6 @@ def vs_config_project_target(config): with open(tasks_path, "w") as f: json.dump(tasks_data, f, indent=4) - def generate_vscode_run_configs(self, configs): if not self.prompt_option("generate_run_configs"): return @@ -2477,6 +2482,56 @@ def generate_run_configs(self): print("Generating Visual Studio run configurations for MrDocs...") self.generate_visual_studio_run_configs(configs) + def generate_pretty_printer_configs(self): + # Generate a .lldbinit file (if it doesn't exist) for LLDB pretty printers + lldbinit_path = os.path.join(self.options.mrdocs_src_dir, ".lldbinit") + if not os.path.exists(lldbinit_path): + home_lldbinit_path = os.path.join(os.path.expanduser("~"), ".lldbinit") + lldbinit_enabled = False + if os.path.exists(home_lldbinit_path): + with open(home_lldbinit_path, "r") as f: + home_lldbinit_content = f.read() + if "settings set target.load-cwd-lldbinit true" in home_lldbinit_content: + lldbinit_enabled = True + # The content of the file should be: + # # echo 'settings set target.load-cwd-lldbinit true' >> ~/.lldbinit + # command script import /Users/alandefreitas/Documents/Code/C++/mrdocs/build/third-party/llvm-project/llvm/utils/lldbDataFormatters.py + lldbinit_content = f"# LLDB pretty printers for MrDocs\n" + lldbinit_content += f"# Generated by bootstrap.py\n" + lldbinit_content += f"# \n" + if not lldbinit_enabled: + lldbinit_content += f"# To enable this file, also add this to your ~/.lldbinit file:\n" + lldbinit_content += f"# settings set target.load-cwd-lldbinit true\n" + lldbinit_content += f"# \n" + lldbinit_content += f"# Or run the following bash command:\n" + lldbinit_content += f"# echo 'settings set target.load-cwd-lldbinit true' >> ~/.lldbinit\n" + lldbinit_content += f"# \n" + lldbinit_content += f"command script import {os.path.join(self.options.llvm_src_dir, 'llvm', 'utils', 'lldbDataFormatters.py').replace(os.sep, '/')}\n" + with open(lldbinit_path, "w") as f: + f.write(lldbinit_content) + print(f"Generated LLDB pretty printer configuration at '{lldbinit_path}'") + else: + print(f"LLDB pretty printer configuration already exists at '{lldbinit_path}', skipping generation.") + + # Do the same logic for GDB pretty printers, generating a .gdbinit file + # The pretty printer is at: .../third-party/llvm-project/llvm/utils/gdb-scripts/prettyprinters.py + gdbinit_path = os.path.join(self.options.mrdocs_src_dir, ".gdbinit") + if not os.path.exists(gdbinit_path): + gdbinit_content = f"# GDB pretty printers for MrDocs\n" + gdbinit_content += f"# Generated by bootstrap.py\n" + gdbinit_content += f"# \n" + gdbinit_content += f"python\n" + gdbinit_content += f"import sys\n" + gdbinit_content += f"sys.path.insert(0, '{os.path.join(self.options.llvm_src_dir, 'llvm', 'utils', 'gdb-scripts', 'prettyprinters.py').replace(os.sep, '/')}')\n" + gdbinit_content += f"from prettyprinters import register_pretty_printers\n" + gdbinit_content += f"register_pretty_printers(gdb)\n" + gdbinit_content += f"end\n" + with open(gdbinit_path, "w") as f: + f.write(gdbinit_content) + print(f"Generated GDB pretty printer configuration at '{gdbinit_path}'") + else: + print(f"GDB pretty printer configuration already exists at '{gdbinit_path}', skipping generation.") + def install_all(self): self.check_compilers() self.probe_msvc_dev_env() @@ -2493,8 +2548,8 @@ def install_all(self): self.install_mrdocs() if self.prompt_option("generate_run_configs"): self.generate_run_configs() - else: - print("Skipping run configurations generation as per user preference.") + if self.prompt_option("generate_pretty_printer_configs"): + self.generate_pretty_printer_configs() def refresh_all(self): # 1. Read all configurations in .vscode/launch.json @@ -2519,7 +2574,8 @@ def refresh_all(self): # 2. Filter configurations whose name starts with "MrDocs Bootstrap Refresh (" bootstrap_refresh_configs = [ - cfg for cfg in configs if cfg.get("name", "").startswith("MrDocs Bootstrap Refresh (") and cfg.get("name", "").endswith(")") + cfg for cfg in configs if + cfg.get("name", "").startswith("MrDocs Bootstrap Refresh (") and cfg.get("name", "").endswith(")") ] if not bootstrap_refresh_configs: print("No bootstrap refresh configurations found in Visual Studio Code launch configurations.")