From 90fcf10a282ba37747176276ebb11014bf183af0 Mon Sep 17 00:00:00 2001 From: alandefreitas Date: Fri, 17 Jan 2025 16:28:59 -0300 Subject: [PATCH] support source paths in Location objects Location objects only contained the full path and the path relative to the search directories. This commit includes a new field for the source path, which contains the path relative to the `source-root`. #feat fix #798 --- CMakeLists.txt | 2 +- docs/modules/ROOT/pages/generators.adoc | 20 +- docs/mrdocs.schema.json | 2 +- include/mrdocs/Metadata/Source.hpp | 22 +- mrdocs.rnc | 4 +- .../common/partials/location/source.hbs | 8 +- src/lib/AST/ASTVisitor.cpp | 26 +- src/lib/AST/ASTVisitor.hpp | 3 + src/lib/Gen/xml/XMLWriter.cpp | 14 +- src/lib/Lib/ConfigOptions.json | 2 +- src/lib/Metadata/Reduce.cpp | 8 +- src/lib/Metadata/Source.cpp | 5 +- test-files/golden-tests/core/libcxx.xml | 2 +- test-files/golden-tests/core/utf-8.xml | 2 +- .../filters/file/include-self.xml | 2 +- .../filters/symbol-name/blacklist_0.xml | 10 +- .../symbol-name/excluded-namespace-alias.xml | 2 +- .../filters/symbol-name/extraction-mode.xml | 52 +- .../symbol-name/impl-defined-member.xml | 8 +- .../filters/symbol-name/whitelist_0.xml | 6 +- .../symbol-type/nested-private-template.xml | 6 +- test-files/golden-tests/javadoc/brief-1.xml | 4 +- test-files/golden-tests/javadoc/brief-2.xml | 14 +- test-files/golden-tests/javadoc/brief-3.xml | 8 +- test-files/golden-tests/javadoc/code.xml | 56 +- test-files/golden-tests/javadoc/commands.xml | 2 +- .../golden-tests/javadoc/duplicate-jdoc.xml | 12 +- test-files/golden-tests/javadoc/li.xml | 2 +- test-files/golden-tests/javadoc/par-1.xml | 8 +- test-files/golden-tests/javadoc/para-1.xml | 8 +- test-files/golden-tests/javadoc/para-2.xml | 2 +- test-files/golden-tests/javadoc/para-3.xml | 2 +- .../golden-tests/javadoc/param-direction.xml | 26 +- test-files/golden-tests/javadoc/param.xml | 8 +- test-files/golden-tests/javadoc/pre-post.xml | 2 +- test-files/golden-tests/javadoc/ref.xml | 104 +-- test-files/golden-tests/javadoc/styled.xml | 110 +-- test-files/golden-tests/javadoc/throw.xml | 2 +- .../golden-tests/metadata/alias-template.xml | 10 +- .../golden-tests/metadata/attributes_1.xml | 2 +- .../metadata/class-private-alias.xml | 4 +- .../metadata/class-template-partial-spec.xml | 8 +- .../metadata/class-template-spec.xml | 36 +- .../class-template-specializations-1.xml | 844 +++++++++--------- .../class-template-specializations-2.xml | 50 +- .../class-template-specializations-3.xml | 130 +-- .../golden-tests/metadata/class-template.xml | 46 +- test-files/golden-tests/metadata/concept.xml | 6 +- .../metadata/decay-to-primary.xml | 22 +- .../metadata/dependency-propagation.xml | 10 +- test-files/golden-tests/metadata/enum.xml | 24 +- .../metadata/explicit-conv-operator.xml | 16 +- .../golden-tests/metadata/explicit-ctor.xml | 40 +- .../metadata/explicit-deduct-guide.xml | 10 +- .../metadata/explicit-object-parameter.xml | 6 +- test-files/golden-tests/metadata/friend-1.xml | 6 +- test-files/golden-tests/metadata/friend-2.xml | 8 +- test-files/golden-tests/metadata/friend-3.xml | 14 +- test-files/golden-tests/metadata/friend-4.xml | 14 +- test-files/golden-tests/metadata/friend-5.xml | 14 +- test-files/golden-tests/metadata/friend-6.xml | 16 +- .../metadata/function-parm-decay.xml | 36 +- .../metadata/function-template-template.xml | 36 +- .../metadata/function-template.xml | 24 +- .../metadata/function-tparm-decay.xml | 36 +- .../implicit-instantiation-member-ref.xml | 22 +- .../golden-tests/metadata/local-class.xml | 4 +- test-files/golden-tests/metadata/mem-fn.xml | 76 +- .../metadata/namespace-alias-1.xml | 2 +- .../metadata/namespace-alias-2.xml | 4 +- .../metadata/namespace-alias-3.xml | 4 +- .../golden-tests/metadata/namespace.xml | 24 +- .../metadata/no_unique_address.xml | 8 +- test-files/golden-tests/metadata/noreturn.xml | 10 +- .../golden-tests/metadata/ns-variables.xml | 24 +- .../metadata/out-of-line-record-def.xml | 4 +- .../golden-tests/metadata/overloaded-op-1.xml | 4 +- .../golden-tests/metadata/overloaded-op-2.xml | 4 +- .../golden-tests/metadata/overloads.xml | 28 +- test-files/golden-tests/metadata/record-1.xml | 18 +- .../golden-tests/metadata/record-access.xml | 24 +- .../golden-tests/metadata/record-data.xml | 42 +- .../metadata/record-inheritance.xml | 34 +- .../golden-tests/metadata/requires-clause.xml | 16 +- test-files/golden-tests/metadata/sfinae.xml | 26 +- .../spec-mem-implicit-instantiation.xml | 70 +- .../metadata/static-data-def-constexpr.xml | 12 +- .../golden-tests/metadata/static-data-def.xml | 38 +- .../metadata/static-data-template.xml | 8 +- .../template-specialization-inheritance.xml | 28 +- .../golden-tests/metadata/type-resolution.xml | 100 +-- test-files/golden-tests/metadata/union.xml | 14 +- test-files/golden-tests/metadata/using-2.xml | 8 +- test-files/golden-tests/metadata/using-3.xml | 14 +- .../metadata/var-inline-constexpr.xml | 20 +- .../golden-tests/metadata/var-template.xml | 14 +- .../metadata/variadic-function.xml | 10 +- .../golden-tests/output/canonical_1.xml | 16 +- test-files/golden-tests/snippets/distance.xml | 2 +- test-files/golden-tests/snippets/is_prime.xml | 2 +- test-files/golden-tests/snippets/sqrt.xml | 2 +- .../golden-tests/snippets/terminate.xml | 2 +- .../templates/c_mct_expl_inline.xml | 10 +- .../templates/c_mct_expl_outside.xml | 10 +- .../templates/c_mft_expl_inline.xml | 6 +- .../templates/c_mft_expl_outside.xml | 6 +- test-files/golden-tests/templates/ct_expl.xml | 8 +- test-files/golden-tests/templates/ct_mc.xml | 6 +- .../templates/ct_mc_expl_outside.xml | 14 +- test-files/golden-tests/templates/ct_mct.xml | 6 +- .../templates/ct_mct_expl_inline.xml | 10 +- .../templates/ct_mct_expl_outside.xml | 14 +- test-files/golden-tests/templates/ct_mf.xml | 4 +- .../templates/ct_mf_expl_outside.xml | 10 +- test-files/golden-tests/templates/ct_mft.xml | 4 +- .../templates/ct_mft_expl_inline.xml | 6 +- .../templates/ct_mft_expl_outside.xml | 10 +- test-files/golden-tests/templates/ft_expl.xml | 4 +- 118 files changed, 1467 insertions(+), 1443 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a628b7e5..a31af70c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -440,7 +440,7 @@ if (MRDOCS_BUILD_TESTS) DEPENDS mrdocs.rnc) add_custom_target(mrdocs_rng ALL DEPENDS mrdocs.rng) - file(GLOB_RECURSE XML_SOURCES CONFIGURE_DEPENDS test-files/*.xml) + file(GLOB_RECURSE XML_SOURCES CONFIGURE_DEPENDS test-files/golden-tests/*.xml) add_test(NAME xml-lint COMMAND ${LIBXML2_XMLLINT_EXECUTABLE} --dropdtd --noout --relaxng ${CMAKE_CURRENT_BINARY_DIR}/mrdocs.rng ${XML_SOURCES} diff --git a/docs/modules/ROOT/pages/generators.adoc b/docs/modules/ROOT/pages/generators.adoc index 94f711059..7d057bc98 100644 --- a/docs/modules/ROOT/pages/generators.adoc +++ b/docs/modules/ROOT/pages/generators.adoc @@ -862,25 +862,25 @@ The location object has the following properties: |=== |Property |Type| Description -| `path` +| `fullPath` | `string` -| The path of the source file. +| The full path of the source file. -| `file` +| `shortPath` | `string` -| The filename of the source file. +| The path of the source file relative to the search directories. + +| `sourcePath` +| `string` +| The path of the source file relative to the `source-root`. | `line` | `integer` -| The line number of the symbol. - -| `kind` -| `string` -| The kind of file (e.g., `source`, `system`, `other`). +| The line number of the symbol at this location. | `documented` | `bool` -| Whether the symbol is documented. +| Whether the symbol is documented at this location. |=== [#tparam-fields] diff --git a/docs/mrdocs.schema.json b/docs/mrdocs.schema.json index 281d13994..17ff4f5e8 100644 --- a/docs/mrdocs.schema.json +++ b/docs/mrdocs.schema.json @@ -225,7 +225,7 @@ }, "source-root": { "default": "", - "description": "Path to the root directory of the source code. This path is used as a default for input files and a base for relative paths formed from absolute paths.", + "description": "Path to the root directory of the source code. This path is used as a default for input files and a base for relative paths formed from absolute paths. This should typically be the root directory of the git project, as relative paths formed from it can be used to create links to these source files in the repository. Templates use the `base-url` option to create links to the source code.", "title": "Path to the root directory of the source code", "type": "string" }, diff --git a/include/mrdocs/Metadata/Source.hpp b/include/mrdocs/Metadata/Source.hpp index 65f9be68e..b331958e1 100644 --- a/include/mrdocs/Metadata/Source.hpp +++ b/include/mrdocs/Metadata/Source.hpp @@ -51,11 +51,15 @@ struct MRDOCS_DECL { /** The full file path */ - std::string Path; + std::string FullPath; - /** Name of the file + /** The file path relative to one of the search directories */ - std::string Filename; + std::string ShortPath; + + /** The file path relative to the source-root directory + */ + std::string SourcePath; /** Line number within the file */ @@ -68,12 +72,14 @@ struct MRDOCS_DECL //-------------------------------------------- Location( - std::string_view const filepath = {}, - std::string_view const filename = {}, + std::string_view const full_path = {}, + std::string_view const short_path = {}, + std::string_view const source_path = {}, unsigned const line = 0, bool const documented = false) - : Path(filepath) - , Filename(filename) + : FullPath(full_path) + , ShortPath(short_path) + , SourcePath(source_path) , LineNumber(line) , Documented(documented) { @@ -92,7 +98,7 @@ struct LocationEmptyPredicate constexpr bool operator()( Location const& loc) const noexcept { - return loc.Filename.empty(); + return loc.ShortPath.empty(); } }; diff --git a/mrdocs.rnc b/mrdocs.rnc index baa8e5974..bf0aee028 100644 --- a/mrdocs.rnc +++ b/mrdocs.rnc @@ -326,7 +326,9 @@ grammar Location = element file { - attribute path {text}, + # attribute full-path {text}, + attribute short-path {text}, + attribute source-path {text}, attribute line {text}, attribute class {"def"} ?, empty diff --git a/share/mrdocs/addons/generator/common/partials/location/source.hbs b/share/mrdocs/addons/generator/common/partials/location/source.hbs index dc7cf379f..094c4fbad 100644 --- a/share/mrdocs/addons/generator/common/partials/location/source.hbs +++ b/share/mrdocs/addons/generator/common/partials/location/source.hbs @@ -11,9 +11,9 @@ --}} Declared in {{#>markup/code~}} - {{ str "<" }}{{#unless (and @root.config.base-url (eq dcl.kind "source"))~}} - {{dcl.file}} + {{ str "<" }}{{#if (and @root.config.base-url dcl.shortPath dcl.sourcePath)~}} + {{#>markup/a href=(concat @root.config.base-url dcl.sourcePath '#L' dcl.line)}}{{dcl.shortPath}}{{/markup/a}} {{~else~}} - {{#>markup/a href=(concat @root.config.base-url dcl.file '#L' dcl.line)}}{{dcl.file}}{{/markup/a}} - {{~/unless~}}{{ str ">" }} + {{dcl.shortPath}} + {{~/if~}}{{ str ">" }} {{~/markup/code}} diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp index 551ee2c09..1ab9e0f5a 100644 --- a/src/lib/AST/ASTVisitor.cpp +++ b/src/lib/AST/ASTVisitor.cpp @@ -696,7 +696,7 @@ populate( { return; } - I.DefLoc.emplace(file->full_path, file->short_path, line, documented); + I.DefLoc.emplace(file->full_path, file->short_path, file->source_path, line, documented); } else { @@ -705,13 +705,13 @@ populate( [line, file](const Location& l) { return l.LineNumber == line && - l.Path == file->full_path; + l.FullPath == file->full_path; }); if (existing != I.Loc.end()) { return; } - I.Loc.emplace_back(file->full_path, file->short_path, line, documented); + I.Loc.emplace_back(file->full_path, file->short_path, file->source_path, line, documented); } } @@ -2762,6 +2762,15 @@ buildFileInfo(std::string_view const file_path) return tryGetRelativePosixPath(posixPrefix); }; + // Populate file relative to source-root + if (files::isAbsolute(config_->sourceRoot)) + { + if (auto shortPath = tryGetRelativePath(config_->sourceRoot)) + { + file_info.source_path = std::string(*shortPath); + } + } + // Find the best match for the file path in the search directories for (HeaderSearch& HS = sema_.getPreprocessor().getHeaderSearchInfo(); DirectoryLookup const& DL : HS.search_dir_range()) @@ -2780,14 +2789,11 @@ buildFileInfo(std::string_view const file_path) } } - // Fallback to sourceRoot - if (files::isAbsolute(config_->sourceRoot)) + // Fallback to the source root + if (!file_info.source_path.empty()) { - if (auto shortPath = tryGetRelativePath(config_->sourceRoot)) - { - file_info.short_path = std::string(*shortPath); - return file_info; - } + file_info.short_path = file_info.source_path; + return file_info; } // Fallback to system search paths in PATH diff --git a/src/lib/AST/ASTVisitor.hpp b/src/lib/AST/ASTVisitor.hpp index 1d290b126..fec2b9aee 100644 --- a/src/lib/AST/ASTVisitor.hpp +++ b/src/lib/AST/ASTVisitor.hpp @@ -95,6 +95,9 @@ class ASTVisitor // The file path relative to a search directory. std::string short_path; + // The file path relative to the source-root directory. + std::string source_path; + // Whether this file passes the file filters std::optional passesFilters; }; diff --git a/src/lib/Gen/xml/XMLWriter.cpp b/src/lib/Gen/xml/XMLWriter.cpp index fa6f2c068..a950dba8d 100644 --- a/src/lib/Gen/xml/XMLWriter.cpp +++ b/src/lib/Gen/xml/XMLWriter.cpp @@ -626,10 +626,14 @@ XMLWriter:: writeSourceInfo( SourceInfo const& I) { - if(I.DefLoc) + if (I.DefLoc) + { writeLocation(*I.DefLoc, true); - for(auto const& loc : I.Loc) + } + for (auto const& loc: I.Loc) + { writeLocation(loc, false); + } } void @@ -639,9 +643,11 @@ writeLocation( bool def) { tags_.write("file", {}, { - { "path", loc.Filename }, + // { "full-path", loc.FullPath }, + { "short-path", loc.ShortPath }, + { "source-path", loc.SourcePath }, { "line", std::to_string(loc.LineNumber) }, - { "class", "def", def } }); + { "class", "def", def }}); } //------------------------------------------------ diff --git a/src/lib/Lib/ConfigOptions.json b/src/lib/Lib/ConfigOptions.json index dee5e87e5..6e76d703b 100644 --- a/src/lib/Lib/ConfigOptions.json +++ b/src/lib/Lib/ConfigOptions.json @@ -42,7 +42,7 @@ { "name": "source-root", "brief": "Path to the root directory of the source code", - "details": "Path to the root directory of the source code. This path is used as a default for input files and a base for relative paths formed from absolute paths.", + "details": "Path to the root directory of the source code. This path is used as a default for input files and a base for relative paths formed from absolute paths. This should typically be the root directory of the git project, as relative paths formed from it can be used to create links to these source files in the repository. Templates use the `base-url` option to create links to the source code.", "type": "dir-path", "default": "", "relative-to": "", diff --git a/src/lib/Metadata/Reduce.cpp b/src/lib/Metadata/Reduce.cpp index 8f58d6af1..877a413dc 100644 --- a/src/lib/Metadata/Reduce.cpp +++ b/src/lib/Metadata/Reduce.cpp @@ -27,8 +27,8 @@ struct LocationEqual Location const& L1) const noexcept { return - std::tie(L0.LineNumber, L0.Filename) == - std::tie(L1.LineNumber, L1.Filename); + std::tie(L0.LineNumber, L0.FullPath) == + std::tie(L1.LineNumber, L1.FullPath); } }; @@ -43,8 +43,8 @@ struct LocationLess Location const& L1) const noexcept { return - std::tie(L0.LineNumber, L0.Filename) < - std::tie(L1.LineNumber, L1.Filename); + std::tie(L0.LineNumber, L0.FullPath) < + std::tie(L1.LineNumber, L1.FullPath); } }; diff --git a/src/lib/Metadata/Source.cpp b/src/lib/Metadata/Source.cpp index 27ca99857..f3878036f 100644 --- a/src/lib/Metadata/Source.cpp +++ b/src/lib/Metadata/Source.cpp @@ -39,8 +39,9 @@ tag_invoke( IO& io, Location const& loc) { - io.map("path", loc.Path); - io.map("file", loc.Filename); + io.map("fullPath", loc.FullPath); + io.map("shortPath", loc.ShortPath); + io.map("sourcePath", loc.SourcePath); io.map("line", loc.LineNumber); io.map("documented", loc.Documented); } diff --git a/test-files/golden-tests/core/libcxx.xml b/test-files/golden-tests/core/libcxx.xml index fd7382674..f961338fb 100644 --- a/test-files/golden-tests/core/libcxx.xml +++ b/test-files/golden-tests/core/libcxx.xml @@ -5,7 +5,7 @@