From 17734cce95ccf770de0bf82c2186bae5e05f5f10 Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Thu, 20 Nov 2025 01:35:43 -0500 Subject: [PATCH 1/4] docs: update packages --- docs/antora-playbook.yml | 2 + docs/package-lock.json | 2670 ++++++++++++++++---------------- docs/package.json | 14 +- docs/website/package-lock.json | 166 +- docs/website/package.json | 4 +- 5 files changed, 1470 insertions(+), 1386 deletions(-) diff --git a/docs/antora-playbook.yml b/docs/antora-playbook.yml index 6e176b30ef..95d4bcc21a 100644 --- a/docs/antora-playbook.yml +++ b/docs/antora-playbook.yml @@ -41,6 +41,8 @@ antora: - require: '@antora/lunr-extension' # https://gitlab.com/antora/antora-lunr-extension index_latest_only: true - require: '@cppalliance/antora-cpp-reference-extension' + auto-base-url: true + breadcrumbs: true asciidoc: attributes: diff --git a/docs/package-lock.json b/docs/package-lock.json index 122af8f916..e8b7ac1c13 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -6,34 +6,36 @@ "": { "dependencies": { "@alandefreitas/antora-playbook-macros-extension": "^0.0.1", - "@antora/lunr-extension": "^1.0.0-alpha.8", - "@asciidoctor/tabs": "^1.0.0-beta.3", - "@cppalliance/antora-cpp-reference-extension": "^0.0.7", - "asciidoctor": "^2.2.6", + "@antora/lunr-extension": "^1.0.0-alpha.12", + "@asciidoctor/tabs": "^1.0.0-beta.6", + "@cppalliance/antora-cpp-reference-extension": "^0.1.0", + "asciidoctor": "^3.0.4", "sync-request": "^6.1.0" }, "devDependencies": { - "@antora/cli": "3.1.3", - "@antora/site-generator": "3.1.3", - "@sntke/antora-mermaid-extension": "^0.0.4" + "@antora/cli": "3.1.14", + "@antora/site-generator": "3.1.14", + "@sntke/antora-mermaid-extension": "^0.0.8" } }, "node_modules/@alandefreitas/antora-playbook-macros-extension": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/@alandefreitas/antora-playbook-macros-extension/-/antora-playbook-macros-extension-0.0.1.tgz", "integrity": "sha512-rBGzR+WErYfW9SIogvdDL2ulNHZgniDlFRg1mjD6J+nlbU4JUv40L2xsL6tAJncSMQxmUIVhSuPM9VlLO0nKaw==", + "license": "BSL-1.0", "dependencies": { "process": "^0.11.10" } }, "node_modules/@antora/asciidoc-loader": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.3.tgz", - "integrity": "sha512-nCmfdxPSBW3rwZ6Aa+xZH9XRDSHOkx28B5VJ2gHlZr8Nl1cx3nvwcP7l/FqYCW/q4mke/ozj/PpjsyC1K5BZVQ==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.14.tgz", + "integrity": "sha512-4xxisnoBFrlLNY6f3xZtyyfgm+tBLsqesTcEStfc8jtXUMYJ4b2DWIzo1vULmxvZ7yY5+Q7YqEvS5o6kIWAG0A==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/logger": "3.1.3", - "@antora/user-require-helper": "~2.0", + "@antora/logger": "3.1.14", + "@antora/user-require-helper": "~3.0", "@asciidoctor/core": "~2.2" }, "engines": { @@ -41,15 +43,16 @@ } }, "node_modules/@antora/cli": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.3.tgz", - "integrity": "sha512-ABngPywk4yZfUE/gaej7ApFeB/0cr5bkW7S4wqObzU5m29q2wDcvrtn/c2mrzFSeSDNAf9y7RCRnudAV5SteBA==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.14.tgz", + "integrity": "sha512-I6WcygMU2bFInjdURJjkYjo7K5M8B3lBB53v9OO0IcY0LhEY8Wa7IlZ7wVinf5qEjHvaYzRGTZVl6RsJtVt7Sw==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/logger": "3.1.3", - "@antora/playbook-builder": "3.1.3", - "@antora/user-require-helper": "~2.0", - "commander": "~9.4" + "@antora/logger": "3.1.14", + "@antora/playbook-builder": "3.1.14", + "@antora/user-require-helper": "~3.0", + "commander": "~11.1" }, "bin": { "antora": "bin/antora" @@ -59,130 +62,153 @@ } }, "node_modules/@antora/content-aggregator": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.3.tgz", - "integrity": "sha512-c+Z+7RVmgu2rvVDRzG8yqSJEmJHnpmTC24aVgvFbb/oU7+YRAVifacgzRl2khOmuky7qKiQxLYmyXJBtRgb37w==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.14.tgz", + "integrity": "sha512-FVuBgnrGPiktYqK1WHbGF8O8l4m5KHlkxoJumrbacgFo8SKuiRFEo31zalxrCUsv8QM3UBEgX+LdHrve/9CGLg==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/expand-path-helper": "~2.0", - "@antora/logger": "3.1.3", - "@antora/user-require-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", + "@antora/logger": "3.1.14", + "@antora/user-require-helper": "~3.0", "braces": "~3.0", "cache-directory": "~2.0", - "glob-stream": "~7.0", - "hpagent": "~1.1", - "isomorphic-git": "~1.21", + "fast-glob": "~3.3", + "hpagent": "~1.2", + "isomorphic-git": "~1.25", "js-yaml": "~4.1", "multi-progress": "~4.0", - "picomatch": "~2.3", + "picomatch": "~4.0", "progress": "~2.0", "should-proxy": "~1.0", "simple-get": "~4.0", - "vinyl": "~2.2" + "vinyl": "~3.0" }, "engines": { "node": ">=16.0.0" } }, + "node_modules/@antora/content-aggregator/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@antora/content-classifier": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.3.tgz", - "integrity": "sha512-auPS1WVRa1khhY7EpEkP+strR+6A6UOm23skEUKzQKESKl6j9KRqxxurvMMKDUmtrAeZ1GqjX5dC/bPfUPNpmw==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.14.tgz", + "integrity": "sha512-y8Fk+KU1lqD3aawOu3ZFK92YfOZ1k3YBJhLI9QIFM6Ck4STPnf7AwYbhfOtjODlwer5/OhFmfhjUB2hn7onGnA==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/asciidoc-loader": "3.1.3", - "@antora/logger": "3.1.3", + "@antora/asciidoc-loader": "3.1.14", + "@antora/logger": "3.1.14", "mime-types": "~2.1", - "vinyl": "~2.2" + "vinyl": "~3.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/document-converter": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.3.tgz", - "integrity": "sha512-9h8jCsf3C1YNMpmKX141kY4WD/W8Roo8T4Y6OToIIKRjNSPnT8KWLFB8NzHXyLNhV1H9EeS/eNdbvxDzBd/VvQ==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.14.tgz", + "integrity": "sha512-f6wFnL+489DI0ZDgoxYWzbxxWqPviRiJ56OHS1NixEfvJ7OpRBDPEbX1xnsIeiyFBgqX4+nY92MsCWKTa+Gf3w==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/asciidoc-loader": "3.1.3" + "@antora/asciidoc-loader": "3.1.14" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/expand-path-helper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-2.0.0.tgz", - "integrity": "sha512-CSMBGC+tI21VS2kGW3PV7T2kQTM5eT3f2GTPVLttwaNYbNxDve08en/huzszHJfxo11CcEs26Ostr0F2c1QqeA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==", + "license": "MPL-2.0", "engines": { - "node": ">=10.17.0" + "node": ">=16.0.0" } }, "node_modules/@antora/file-publisher": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.3.tgz", - "integrity": "sha512-4c2RVaJkLvYXbUZP2VF/hFVSZ6UAPNPgt/iurexr3D7OqKrYJnYqchXsLhut2yCLYVOzedXGMst0y2XaEi52qA==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.14.tgz", + "integrity": "sha512-fTaAnkyKSOlsxQM1TBFCAmiERA6Q67XleDCD2bMPVgfcENmo0Xfx59KwCHaA92IcRSmMftydlXHPaFxNh0UVsg==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/expand-path-helper": "~2.0", - "@antora/user-require-helper": "~2.0", - "gulp-vinyl-zip": "~2.5", - "vinyl": "~2.2", - "vinyl-fs": "~3.0" + "@antora/expand-path-helper": "~3.0", + "@antora/user-require-helper": "~3.0", + "vinyl": "~3.0", + "yazl": "~2.5" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/logger": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.3.tgz", - "integrity": "sha512-6h0PTYHF9C/I9CiYJmlTME7H9dEkMI1luGMQdYhPL9OicbZ5/HsUPKOvGfLNHzw2iyG0yp5bLVvcr9K69ArgtQ==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.14.tgz", + "integrity": "sha512-kVEeGqZbXR903hPIm+BlN97fLdQ3LoUzE/BOPZ6vRp9m9Mmbnm67Kg7fSYkfTMLB0S2UWpAPFg22RdsU5ZoAzA==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/expand-path-helper": "~2.0", - "pino": "~8.7", - "pino-pretty": "~9.1", - "sonic-boom": "~3.2" + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/lunr-extension": { - "version": "1.0.0-alpha.8", - "resolved": "https://registry.npmjs.org/@antora/lunr-extension/-/lunr-extension-1.0.0-alpha.8.tgz", - "integrity": "sha512-vdBgW3rsvbnmA236kT2Dckh9n0Db5za2/WxiLnFLgZ05ZO1KJQa9+R2WHaIFuGE7bKKbY+lqfM/i3KiezbL9YQ==", + "version": "1.0.0-alpha.12", + "resolved": "https://registry.npmjs.org/@antora/lunr-extension/-/lunr-extension-1.0.0-alpha.12.tgz", + "integrity": "sha512-iiEXpJae8tCH22ao7kZ4I+eyQ/3IeFIFK1G5I9QLpkCezaVPotI8eLFY7e0xDI+zsqJEfCOsfoZGYXso6xCYlA==", + "license": "MPL-2.0", + "workspaces": [ + "." + ], "dependencies": { - "cheerio": "1.0.0-rc.10", - "html-entities": "~2.3", + "htmlparser2": "~9.1", "lunr": "~2.3", - "lunr-languages": "~1.9" + "lunr-languages": "~1.10" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/navigation-builder": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.3.tgz", - "integrity": "sha512-t7xHXdK6YjmB79FlsKTGPWHHcEhRzLGZEp9Qjg45S1UphPWWCWEhz6nC/if+MKyoRPGn3aoiSh3n33XC/eYxew==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.14.tgz", + "integrity": "sha512-/637YLGD7oUHGSfEfszXkk4ASfIhDAg5Xs9035J1dV07XYRlGqmtUb15rtapbcECpcQFjCyM5jFQYSNNvLrGcQ==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/asciidoc-loader": "3.1.3" + "@antora/asciidoc-loader": "3.1.14" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/page-composer": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.3.tgz", - "integrity": "sha512-X0qrJ1x6jReNjzPtenbgnxfVMbsc5RbuVzBEOqWnX9i+PI4dSYUJ9dKZW9rXE6Vv7Yq6vjOn7JlgHXcvo/RCzQ==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.14.tgz", + "integrity": "sha512-RfA+67TxCqUPrQbZdrfjgLpHh8MR2z2du7cyF3HGX4N6DpqEBvz81NHHl3rA3fj6BQZPQbGm2OYAMU6wzJ6Pog==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/logger": "3.1.3", + "@antora/logger": "3.1.14", "handlebars": "~4.7", "require-from-string": "~2.0" }, @@ -191,10 +217,11 @@ } }, "node_modules/@antora/playbook-builder": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.3.tgz", - "integrity": "sha512-EjkTrXwFAhFxDFU6eHRuExqvuvoHxyR1IbCAgjyj6Pi6hvGIZoGbH9cu1Gy1sWE6XmZl5yA5Gwi++LMyQPmuuA==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.14.tgz", + "integrity": "sha512-Ss2r7In00u/n9Da+JOxEqIE8NeRosf+f+agzH3Te09JV/mpgZKxEOE5V/VuP+TNNq4ww1eu5aOS8DiU2PYwj4Q==", "dev": true, + "license": "MPL-2.0", "dependencies": { "@iarna/toml": "~2.2", "convict": "~6.2", @@ -206,124 +233,146 @@ } }, "node_modules/@antora/redirect-producer": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.3.tgz", - "integrity": "sha512-SLa8HkDSeH45KUjpID7exv8yvDYcsgup4FKP9xtGJsEH4Ikv4uRmSqrL55jwliCwvuU6Wojt+PFHKtnZVwKKIg==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.14.tgz", + "integrity": "sha512-5koAwRk1cZrvE/qfOWKXqb3jtxrZbWA5EYHYGFEoato5By3cbC42blH4Bre9/48pjyS6znFpbZhYUBpT7PRhZA==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "vinyl": "~2.2" + "vinyl": "~3.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/site-generator": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.3.tgz", - "integrity": "sha512-sT8EWKZd8u6KRgUpTd/8j33+G5mON4VX7C7e2MEI8gVBCaPutUPuYO/2IycmN3n294Nua+szI/1Aqt6uVfksHg==", - "dev": true, - "dependencies": { - "@antora/asciidoc-loader": "3.1.3", - "@antora/content-aggregator": "3.1.3", - "@antora/content-classifier": "3.1.3", - "@antora/document-converter": "3.1.3", - "@antora/file-publisher": "3.1.3", - "@antora/logger": "3.1.3", - "@antora/navigation-builder": "3.1.3", - "@antora/page-composer": "3.1.3", - "@antora/playbook-builder": "3.1.3", - "@antora/redirect-producer": "3.1.3", - "@antora/site-mapper": "3.1.3", - "@antora/site-publisher": "3.1.3", - "@antora/ui-loader": "3.1.3", - "@antora/user-require-helper": "~2.0" + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.14.tgz", + "integrity": "sha512-hQIUVtM9+xwleYWc4fIRZmiKl2p+ItOJuUm2+Hkdh07BZsySxkMOxxCyZsvTn9rc+4R94CYqDQCYElwFwdB2WA==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/asciidoc-loader": "3.1.14", + "@antora/content-aggregator": "3.1.14", + "@antora/content-classifier": "3.1.14", + "@antora/document-converter": "3.1.14", + "@antora/file-publisher": "3.1.14", + "@antora/logger": "3.1.14", + "@antora/navigation-builder": "3.1.14", + "@antora/page-composer": "3.1.14", + "@antora/playbook-builder": "3.1.14", + "@antora/redirect-producer": "3.1.14", + "@antora/site-mapper": "3.1.14", + "@antora/site-publisher": "3.1.14", + "@antora/ui-loader": "3.1.14", + "@antora/user-require-helper": "~3.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/site-mapper": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.3.tgz", - "integrity": "sha512-egyuCTgGVCcvNfH0BaWSsG5zJon3smXDjlRbIODqI6zu99HXsNqrVLMP62Z3lzEibKYXc/7XY/q5Ggm+prh0Sw==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.14.tgz", + "integrity": "sha512-3qbETtwadl+fWREjzrBUxPUorMcMiZ+hdkB1El9z7it9KzKh0Yp7Je0+2uTxGX+Lov9uik48dZJ9e/mr5PeaRQ==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/content-classifier": "3.1.3", - "vinyl": "~2.2" + "@antora/content-classifier": "3.1.14", + "vinyl": "~3.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/site-publisher": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.3.tgz", - "integrity": "sha512-dSHyyKj5l3ZIRo0EjNxmpZ+G3OgPQ4fgwdmA8xOWtX+eiU4sV3MQ9j6tlc4lloAzUVIumt7LOd0n9Quie6yCNA==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.14.tgz", + "integrity": "sha512-8apyEmgepUc7ms9CTEIPwN3tGtWwLqR6fbLMLs7hibqmOSR880Ut/4GRGb97sqcGQXSHdIyWK2oJKzRl1Akb6Q==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/file-publisher": "3.1.3" + "@antora/file-publisher": "3.1.14" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/ui-loader": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.3.tgz", - "integrity": "sha512-xaOUn5vOb9RR6LVsCCwROvvWXTADvC/ITO1yKAiJtV9xNrI08szzmWXjgvb07PpRDRPD5QgYoZFmqFPk+0WE2w==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.14.tgz", + "integrity": "sha512-LVvTdKQOB44CmJ1JQDu8sJf6rrLZMxPAWWackdg2JtGyGHHpd80/MBcv4BSFk7//cJQ13Oqm/7JCbhD51KAFjg==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/expand-path-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", "braces": "~3.0", "cache-directory": "~2.0", - "glob-stream": "~7.0", - "gulp-vinyl-zip": "~2.5", - "hpagent": "~1.1", + "fast-glob": "~3.3", + "hpagent": "~1.2", "js-yaml": "~4.1", - "picomatch": "~2.3", + "picomatch": "~4.0", "should-proxy": "~1.0", "simple-get": "~4.0", - "vinyl": "~2.2" + "vinyl": "~3.0", + "yauzl": "~3.1" }, "engines": { "node": ">=16.0.0" } }, + "node_modules/@antora/ui-loader/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@antora/user-require-helper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-2.0.0.tgz", - "integrity": "sha512-5fMfBZfw4zLoFdDAPMQX6Frik90uvfD8rXOA4UpXPOUikkX4uT1Rk6m0/4oi8oS3fcjiIl0k/7Nc+eTxW5TcQQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@antora/expand-path-helper": "~2.0" + "@antora/expand-path-helper": "~3.0" }, "engines": { - "node": ">=10.17.0" + "node": ">=16.0.0" } }, "node_modules/@asciidoctor/cli": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@asciidoctor/cli/-/cli-3.5.0.tgz", - "integrity": "sha512-/VMHXcZBnZ9vgWfmqk9Hu0x0gMjPLup0YGq/xA8qCQuk11kUIZNMVQwgSsIUzOEwJqIUD7CgncJdtfwv1Ndxuw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@asciidoctor/cli/-/cli-4.0.0.tgz", + "integrity": "sha512-x2T9gW42921Zd90juEagtbViPZHNP2MWf0+6rJEkOzW7E9m3TGJtz+Guye9J0gwrpZsTMGCpfYMQy1We3X7osg==", + "license": "MIT", "dependencies": { - "yargs": "16.2.0" + "yargs": "17.3.1" }, "bin": { "asciidoctor": "bin/asciidoctor", "asciidoctorjs": "bin/asciidoctor" }, "engines": { - "node": ">=8.11", - "npm": ">=5.0.0" + "node": ">=16", + "npm": ">=8.0.0" }, "peerDependencies": { - "@asciidoctor/core": "^2.0.0-rc.1" + "@asciidoctor/core": ">=2 <4" } }, "node_modules/@asciidoctor/core": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-2.2.6.tgz", - "integrity": "sha512-TmB2K5UfpDpSbCNBBntXzKHcAk2EA3/P68jmWvmJvglVUdkO9V6kTAuXVe12+h6C4GK0ndwuCrHHtEVcL5t6pQ==", + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-2.2.8.tgz", + "integrity": "sha512-oozXk7ZO1RAd/KLFLkKOhqTcG4GO3CV44WwOFg2gMcCsqCUTarvMT7xERIoWW2WurKbB0/ce+98r01p8xPOlBw==", + "license": "MIT", + "peer": true, "dependencies": { "asciidoctor-opal-runtime": "0.3.3", "unxhr": "1.0.1" @@ -334,6 +383,69 @@ "yarn": ">=1.1.0" } }, + "node_modules/@asciidoctor/opal-runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@asciidoctor/opal-runtime/-/opal-runtime-3.0.1.tgz", + "integrity": "sha512-iW7ACahOG0zZft4A/4CqDcc7JX+fWRNjV5tFAVkNCzwZD+EnFolPaUOPYt8jzadc0+Bgd80cQTtRMQnaaV1kkg==", + "license": "MIT", + "dependencies": { + "glob": "8.1.0", + "unxhr": "1.2.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@asciidoctor/opal-runtime/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@asciidoctor/opal-runtime/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@asciidoctor/opal-runtime/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@asciidoctor/opal-runtime/node_modules/unxhr": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.2.0.tgz", + "integrity": "sha512-6cGpm8NFXPD9QbSNx0cD2giy7teZ6xOkCUH3U89WKVkL9N9rBrWjlCwhR94Re18ZlAop4MOc3WU1M3Hv/bgpIw==", + "license": "MIT", + "engines": { + "node": ">=8.11" + } + }, "node_modules/@asciidoctor/tabs": { "version": "1.0.0-beta.6", "resolved": "https://registry.npmjs.org/@asciidoctor/tabs/-/tabs-1.0.0-beta.6.tgz", @@ -343,25 +455,71 @@ "node": ">=16.0.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@cppalliance/antora-cpp-reference-extension": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@cppalliance/antora-cpp-reference-extension/-/antora-cpp-reference-extension-0.0.7.tgz", - "integrity": "sha512-tAt6HY1s4E16nKL5gcT52Qa4vMBkBCs3dJcSitM1W6EjmMZXxvKOQ+OvEZpp1w+W8Qj5JmbcwRTuvRuLQdTjBQ==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@cppalliance/antora-cpp-reference-extension/-/antora-cpp-reference-extension-0.1.0.tgz", + "integrity": "sha512-3VD/gAFebR06GiBWAy2PgEHNqyRNrvAE0FfFvotLvA0RQmHn0q+ct+j0z53N64yxuvJVj8Hl0bRRPdhh2BGjXg==", "license": "BSL-1.0", "dependencies": { - "@antora/expand-path-helper": "^2.0.0", - "axios": "^1.7.2", + "@antora/expand-path-helper": "^3.0.0", + "axios": "^1.13.2", "cache-directory": "^2.0.0", - "fast-glob": "^3.3.2", - "isomorphic-git": "^1.27.1", + "fast-glob": "^3.3.3", + "isomorphic-git": "^1.35.0", "js-yaml": "^4.1.0", - "semver": "^7.6.3" + "semver": "^7.7.3" } }, "node_modules/@cppalliance/antora-cpp-reference-extension/node_modules/isomorphic-git": { - "version": "1.33.1", - "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.33.1.tgz", - "integrity": "sha512-Fy5rPAncURJoqL9R+5nJXLl5rQH6YpcjJd7kdCoRJPhrBiLVkLm9b+esRqYQQlT1hKVtKtALbfNtpHjWWJgk6g==", + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.35.0.tgz", + "integrity": "sha512-+pRiwWDld5yAjdTFFh9+668kkz4uzCZBs+mw+ZFxPAxJBX8KCqd/zAP7Zak0BK5BQ+dXVqEurR5DkEnqrLpHlQ==", "license": "MIT", "dependencies": { "async-lock": "^1.4.1", @@ -371,9 +529,8 @@ "ignore": "^5.1.4", "minimisted": "^2.0.0", "pako": "^1.0.10", - "path-browserify": "^1.0.1", "pify": "^4.0.1", - "readable-stream": "^3.4.0", + "readable-stream": "^4.0.0", "sha.js": "^2.4.12", "simple-get": "^4.0.1" }, @@ -384,11 +541,28 @@ "node": ">=14.17" } }, + "node_modules/@cppalliance/antora-cpp-reference-extension/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@iarna/toml": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -426,15 +600,17 @@ } }, "node_modules/@sntke/antora-mermaid-extension": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@sntke/antora-mermaid-extension/-/antora-mermaid-extension-0.0.4.tgz", - "integrity": "sha512-YaGBS/QwXTOAEcZSnoekr4PGhBXtNXX5LOCfSYlj4eLcnjtBte8ARzBcbawjMP/zkC+Gh08rS0UYZZ/I7jcuxA==", - "dev": true + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@sntke/antora-mermaid-extension/-/antora-mermaid-extension-0.0.8.tgz", + "integrity": "sha512-tTGNECQJcJaz2m/W2izgVNLO78LBq1OyNxIpTYU/IslkRjN62ghZfK25sZTfpvJQjKeNTOnx+SmFcCpq/Sn3FQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/concat-stream": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz", "integrity": "sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -443,6 +619,7 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", "integrity": "sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -450,18 +627,26 @@ "node_modules/@types/node": { "version": "10.17.60", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", - "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "license": "MIT" }, "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "license": "MIT" + }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "license": "MIT" }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, + "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" }, @@ -469,10 +654,23 @@ "node": ">=6.5" } }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -481,6 +679,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -491,50 +690,45 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA==", - "dev": true, - "dependencies": { - "buffer-equal": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" }, "node_modules/asciidoctor": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/asciidoctor/-/asciidoctor-2.2.6.tgz", - "integrity": "sha512-EXG3+F2pO21B+COfQmV/WgEgGiy7nG/mJiS/o5DXpaT2q82FRZWPVkbMZrpDvpu4pjXe5c754RbZR9Vz0L0Vtw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/asciidoctor/-/asciidoctor-3.0.4.tgz", + "integrity": "sha512-hIc0Bx73wePxtic+vWBHOIgMfKSNiCmRz7BBfkyykXATrw20YGd5a3CozCHvqEPH+Wxp5qKD4aBsgtokez8nEA==", + "license": "MIT", "dependencies": { - "@asciidoctor/cli": "3.5.0", - "@asciidoctor/core": "2.2.6" + "@asciidoctor/cli": "4.0.0", + "@asciidoctor/core": "3.0.4", + "ejs": "^3.1.2", + "handlebars": "^4.7.6", + "nunjucks": "^3.2.1", + "pug": "^3.0.0" }, "bin": { "asciidoctor": "bin/asciidoctor", "asciidoctorjs": "bin/asciidoctor" }, "engines": { - "node": ">=8.11", - "npm": ">=5.0.0", - "yarn": ">=1.1.0" + "node": ">=16", + "npm": ">=8" } }, "node_modules/asciidoctor-opal-runtime": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/asciidoctor-opal-runtime/-/asciidoctor-opal-runtime-0.3.3.tgz", "integrity": "sha512-/CEVNiOia8E5BMO9FLooo+Kv18K4+4JBFRJp8vUy/N5dMRAg+fRNV4HA+o6aoSC79jVU/aT5XvUpxSxSsTS8FQ==", + "license": "MIT", "dependencies": { "glob": "7.1.3", "unxhr": "1.0.1" @@ -543,6 +737,41 @@ "node": ">=8.11" } }, + "node_modules/asciidoctor/node_modules/@asciidoctor/core": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-3.0.4.tgz", + "integrity": "sha512-41SDMi7iRRBViPe0L6VWFTe55bv6HEOJeRqMj5+E5wB1YPdUPuTucL4UAESPZM6OWmn4t/5qM5LusXomFUVwVQ==", + "license": "MIT", + "dependencies": { + "@asciidoctor/opal-runtime": "3.0.1", + "unxhr": "1.2.0" + }, + "engines": { + "node": ">=16", + "npm": ">=8" + } + }, + "node_modules/asciidoctor/node_modules/unxhr": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.2.0.tgz", + "integrity": "sha512-6cGpm8NFXPD9QbSNx0cD2giy7teZ6xOkCUH3U89WKVkL9N9rBrWjlCwhR94Re18ZlAop4MOc3WU1M3Hv/bgpIw==", + "license": "MIT", + "engines": { + "node": ">=8.11" + } + }, + "node_modules/assert-never": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.4.0.tgz", + "integrity": "sha512-5oJg84os6NMQNl27T9LnZkvvqzvAnHu03ShCnoj6bsJwS7L8AO4lf+C/XjK/nvzEqQB744moC6V128RucQd1jA==", + "license": "MIT" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, "node_modules/async-lock": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", @@ -552,13 +781,15 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, "node_modules/atomic-sleep": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0.0" } @@ -579,9 +810,9 @@ } }, "node_modules/axios": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -589,32 +820,58 @@ "proxy-from-env": "^1.1.0" } }, - "node_modules/axios/node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "node_modules/b4a": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/babel-walk": { + "version": "3.0.0-canary-5", + "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", + "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "@babel/types": "^7.9.6" }, "engines": { - "node": ">= 6" + "node": ">= 10.0.0" } }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -628,17 +885,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + ], + "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -660,7 +914,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, "funding": [ { "type": "github", @@ -675,6 +928,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -685,31 +939,22 @@ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, - "node_modules/buffer-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", - "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", - "dev": true, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" }, "node_modules/cache-directory": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cache-directory/-/cache-directory-2.0.0.tgz", "integrity": "sha512-7YKEapH+2Uikde8hySyfobXBqPKULDyHNl/lhKm7cKf/GJFdG/tU/WpLrOg2y9aUrQrWUilYqawFIiGJPS6gDA==", + "license": "LGPL-3.0+", "dependencies": { "xdg-basedir": "^3.0.0" }, @@ -767,52 +1012,29 @@ "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dependencies": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "license": "Apache-2.0" }, - "node_modules/cheerio-select": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", - "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", + "node_modules/character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", + "license": "MIT", "dependencies": { - "css-select": "^4.3.0", - "css-what": "^6.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.3.1", - "domutils": "^2.8.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "is-regex": "^1.0.3" } }, "node_modules/clean-git-ref": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/clean-git-ref/-/clean-git-ref-2.0.1.tgz", - "integrity": "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==" + "integrity": "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==", + "license": "Apache-2.0" }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -824,92 +1046,41 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8" } }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", - "dev": true, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", - "dev": true - }, - "node_modules/cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "node_modules/cloneable-readable/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/cloneable-readable/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/cloneable-readable/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "node": ">=7.0.0" } }, "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -918,18 +1089,20 @@ } }, "node_modules/commander": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", - "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.20.0 || >=14" + "node": ">=16" } }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" }, "node_modules/concat-stream": { "version": "1.6.2", @@ -938,6 +1111,7 @@ "engines": [ "node >= 0.8" ], + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -945,10 +1119,17 @@ "typedarray": "^0.0.6" } }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, "node_modules/concat-stream/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -962,27 +1143,34 @@ "node_modules/concat-stream/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" }, "node_modules/concat-stream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true + "node_modules/constantinople": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", + "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.1" + } }, "node_modules/convict": { "version": "6.2.4", "resolved": "https://registry.npmjs.org/convict/-/convict-6.2.4.tgz", "integrity": "sha512-qN60BAwdMVdofckX7AlohVJ2x9UvjTNoKVXCL2LxFk1l7757EJqf1nySdMkPQer0bt8kQ5lQiyZ9/2NvrFBuwQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "lodash.clonedeep": "^4.5.0", "yargs-parser": "^20.2.7" @@ -994,12 +1182,14 @@ "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" }, "node_modules/crc-32": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", "bin": { "crc32": "bin/crc32.njs" }, @@ -1007,37 +1197,12 @@ "node": ">=0.8" } }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/dateformat": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -1046,6 +1211,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" }, @@ -1060,6 +1226,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -1072,26 +1239,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -1099,16 +1251,24 @@ "node_modules/diff3": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz", - "integrity": "sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==" + "integrity": "sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==", + "license": "MIT" + }, + "node_modules/doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==", + "license": "MIT" }, "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, "funding": { "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" @@ -1123,14 +1283,16 @@ "type": "github", "url": "https://github.com/sponsors/fb55" } - ] + ], + "license": "BSD-2-Clause" }, "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", "dependencies": { - "domelementtype": "^2.2.0" + "domelementtype": "^2.3.0" }, "engines": { "node": ">= 4" @@ -1140,13 +1302,14 @@ } }, "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" }, "funding": { "url": "https://github.com/fb55/domutils?sponsor=1" @@ -1166,36 +1329,45 @@ "node": ">= 0.4" } }, - "node_modules/duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", - "dev": true, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "license": "Apache-2.0", "dependencies": { - "end-of-stream": "^1.4.1", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" } }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "dev": true, + "license": "MIT", "dependencies": { "once": "^1.4.0" } }, "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -1213,6 +1385,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -1245,9 +1418,10 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -1256,7 +1430,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1265,22 +1439,34 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.x" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } }, "node_modules/fast-copy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", - "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==", - "dev": true + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" }, "node_modules/fast-glob": { "version": "3.3.3", @@ -1298,23 +1484,12 @@ "node": ">=8.6.0" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fast-redact": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.2.tgz", - "integrity": "sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1323,7 +1498,8 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastq": { "version": "1.19.1", @@ -1334,13 +1510,34 @@ "reusify": "^1.0.4" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "license": "Apache-2.0", "dependencies": { - "pend": "~1.2.0" + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, "node_modules/fill-range": { @@ -1355,46 +1552,6 @@ "node": ">=8" } }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/flush-write-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/flush-write-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/flush-write-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/follow-redirects": { "version": "1.15.11", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", @@ -1431,40 +1588,32 @@ } }, "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" + "node": ">= 6" } }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -1473,6 +1622,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -1505,6 +1655,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==", + "license": "MIT", "engines": { "node": ">=4" } @@ -1526,6 +1677,8 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1539,56 +1692,15 @@ } }, "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-stream": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-7.0.0.tgz", - "integrity": "sha512-evR4kvr6s0Yo5t4CD4H171n4T8XcnPFznvsbeN8K9FPzc0Q0wYqcOWyGtck2qcvJSLXKnU6DnDyfmbDDabYvRQ==", - "dev": true, - "dependencies": { - "extend": "^3.0.2", - "glob": "^7.2.0", - "glob-parent": "^6.0.2", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.1", - "pumpify": "^2.0.1", - "readable-stream": "^3.6.0", - "remove-trailing-separator": "^1.1.0", - "to-absolute-glob": "^2.0.2", - "unique-stream": "^2.3.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-stream/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "is-glob": "^4.0.1" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 6" } }, "node_modules/gopd": { @@ -1603,39 +1715,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/gulp-vinyl-zip": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.5.0.tgz", - "integrity": "sha512-KPi5/2SUmkXXDvKU4L2U1dkPOP03SbhONTOgNZlL23l9Yopt+euJ1bBXwWrSMbsyh3JLW/TYuC8CI4c4Kq4qrw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "dependencies": { - "queue": "^4.2.1", - "through": "^2.3.8", - "through2": "^2.0.3", - "vinyl": "^2.0.2", - "vinyl-fs": "^3.0.3", - "yauzl": "^2.2.1", - "yazl": "^2.2.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "license": "MIT", "dependencies": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, @@ -1653,6 +1740,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -1691,6 +1779,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -1699,73 +1788,26 @@ } }, "node_modules/help-me": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "dev": true, - "dependencies": { - "glob": "^8.0.0", - "readable-stream": "^3.6.0" - } - }, - "node_modules/help-me/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/help-me/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/help-me/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } + "license": "MIT" }, "node_modules/hpagent": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.1.0.tgz", - "integrity": "sha512-bgJcBmNTZaJO03xtXOTNfoFEf/3VwoZ/gJ2O4ekTCZu4LSFtfzQFrJ0kjq8ZSS0+IdghXqQIiDUnpp0eUR9IJg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", + "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" } }, - "node_modules/html-entities": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", - "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==" - }, "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -1773,17 +1815,19 @@ "url": "https://github.com/sponsors/fb55" } ], + "license": "MIT", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "entities": "^4.5.0" } }, "node_modules/http-basic": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", "integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==", + "license": "MIT", "dependencies": { "caseless": "^0.12.0", "concat-stream": "^1.6.2", @@ -1798,6 +1842,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", + "license": "MIT", "dependencies": { "@types/node": "^10.0.3" } @@ -1806,7 +1851,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -1820,12 +1864,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", "engines": { "node": ">= 4" } @@ -1834,6 +1880,8 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -1842,26 +1890,8 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/is-callable": { "version": "1.2.7", @@ -1875,10 +1905,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-expression": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", + "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", + "license": "MIT", + "dependencies": { + "acorn": "^7.1.1", + "object-assign": "^4.1.1" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1887,6 +1943,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", "engines": { "node": ">=8" } @@ -1895,6 +1952,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -1902,15 +1960,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -1920,16 +1969,28 @@ "node": ">=0.12.0" } }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", "dependencies": { - "is-unc-path": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-typed-array": { @@ -1947,54 +2008,20 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "dev": true - }, - "node_modules/is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" }, "node_modules/isomorphic-git": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.21.0.tgz", - "integrity": "sha512-ZqCAUM63CYepA3fB8H7NVyPSiOkgzIbQ7T+QPrm9xtYgQypN9JUJ5uLMjB5iTfomdJf3mdm6aSxjZwnT6ubvEA==", + "version": "1.25.10", + "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.25.10.tgz", + "integrity": "sha512-IxGiaKBwAdcgBXwIcxJU6rHLk+NrzYaaPKXXQffcA0GW3IUrQXdUPDXDo+hkGVcYruuz/7JlGBiuaeTCgIgivQ==", "dev": true, + "license": "MIT", "dependencies": { - "async-lock": "^1.1.0", + "async-lock": "^1.4.1", "clean-git-ref": "^2.0.1", "crc-32": "^1.2.0", "diff3": "0.0.3", @@ -2013,19 +2040,44 @@ "node": ">=12" } }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/joycon": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } }, + "node_modules/js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==", + "license": "MIT" + }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -2033,17 +2085,12 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -2051,75 +2098,43 @@ "node": ">=6" } }, - "node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/lazystream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, + "node_modules/jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", + "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "is-promise": "^2.0.0", + "promise": "^7.0.1" } }, - "node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", - "dev": true, + "node_modules/jstransformer/node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "license": "MIT", "dependencies": { - "flush-write-stream": "^1.0.2" - }, - "engines": { - "node": ">= 0.10" + "asap": "~2.0.3" } }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "license": "MIT" }, "node_modules/lunr-languages": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/lunr-languages/-/lunr-languages-1.9.0.tgz", - "integrity": "sha512-Be5vFuc8NAheOIjviCRms3ZqFFBlzns3u9DXpPSZvALetgnydAN0poV71pVLFn0keYy/s4VblMMkqewTLe+KPg==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/lunr-languages/-/lunr-languages-1.10.0.tgz", + "integrity": "sha512-BBjKKcwrieJlzwwc9M5H/MRXGJ2qyOSDx/NXYiwkuKjiLOOoouh0WsDzeqcLoUWcX31y7i8sb8IgsZKObdUCkw==", + "license": "MPL-1.1" }, "node_modules/math-intrinsics": { "version": "1.1.0", @@ -2156,6 +2171,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2164,6 +2180,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -2175,6 +2192,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -2186,6 +2204,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2197,6 +2216,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2205,6 +2225,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/minimisted/-/minimisted-2.0.1.tgz", "integrity": "sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==", + "license": "MIT", "dependencies": { "minimist": "^1.2.5" } @@ -2214,6 +2235,7 @@ "resolved": "https://registry.npmjs.org/multi-progress/-/multi-progress-4.0.0.tgz", "integrity": "sha512-9zcjyOou3FFCKPXsmkbC3ethv51SFPoA4dJD6TscIp2pUmy26kBDZW6h9XofPELrzseSkuD7r0V+emGEeo39Pg==", "dev": true, + "license": "MIT", "peerDependencies": { "progress": "^2.0.0" } @@ -2222,71 +2244,56 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "license": "MIT" }, - "node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, + "node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "license": "BSD-2-Clause", "dependencies": { - "remove-trailing-separator": "^1.0.1" + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "dependencies": { - "once": "^1.3.2" + "bin": { + "nunjucks-precompile": "bin/precompile" }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" + "node": ">= 6.9.0" }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } } }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/nunjucks/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", + "engines": { + "node": ">= 6" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -2295,111 +2302,68 @@ } }, "node_modules/on-exit-leak-free": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", - "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==", - "dev": true + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "dependencies": { "wrappy": "1" } }, - "node_modules/ordered-read-streams": { + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/parse-cache-control": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/ordered-read-streams/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/ordered-read-streams/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/ordered-read-streams/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "node_modules/parse-cache-control": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==" - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "license": "MIT" - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", - "dev": true + "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", + "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==" }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -2411,68 +2375,74 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/pino": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.7.0.tgz", - "integrity": "sha512-l9sA5uPxmZzwydhMWUcm1gI0YxNnYl8MfSr2h8cwLvOAzQLBLewzF247h/vqHe3/tt6fgtXeG9wdjjoetdI/vA==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.2.0.tgz", + "integrity": "sha512-g3/hpwfujK5a4oVbaefoJxezLzsDgLcNJeITvC6yrfwYeT9la+edCK42j5QpEQSQCZgTKapXvnQIdgZwvRaZug==", "dev": true, + "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "v1.0.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^2.0.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^3.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^3.1.0", - "thread-stream": "^2.0.0" + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "node_modules/pino-abstract-transport": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz", - "integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", "dev": true, + "license": "MIT", "dependencies": { "readable-stream": "^4.0.0", "split2": "^4.0.0" } }, "node_modules/pino-abstract-transport/node_modules/readable-stream": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.3.0.tgz", - "integrity": "sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", "dev": true, + "license": "MIT", "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", - "process": "^0.11.10" + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/pino-pretty": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-9.1.1.tgz", - "integrity": "sha512-iJrnjgR4FWQIXZkUF48oNgoRI9BpyMhaEmihonHeCnZ6F50ZHAS4YGfGBT/ZVNsPmd+hzkIPGzjKdY08+/yAXw==", + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", + "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", "dev": true, + "license": "MIT", "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", - "fast-copy": "^3.0.0", + "fast-copy": "^3.0.2", "fast-safe-stringify": "^2.1.1", - "help-me": "^4.0.1", + "help-me": "^5.0.0", "joycon": "^3.1.1", "minimist": "^1.2.6", "on-exit-leak-free": "^2.1.0", @@ -2480,7 +2450,7 @@ "pump": "^3.0.0", "readable-stream": "^4.0.0", "secure-json-parse": "^2.4.0", - "sonic-boom": "^3.0.0", + "sonic-boom": "^4.0.1", "strip-json-comments": "^3.1.1" }, "bin": { @@ -2488,25 +2458,28 @@ } }, "node_modules/pino-pretty/node_modules/readable-stream": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.3.0.tgz", - "integrity": "sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", "dev": true, + "license": "MIT", "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", - "process": "^0.11.10" + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/pino-std-serializers": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.0.tgz", - "integrity": "sha512-IWgSzUL8X1w4BIWTwErRgtV8PyOGOOi60uqv0oKuS/fOA8Nco/OeI6lBuc4dyP8MMfdFwyHqTMcBIA7nDiqEqA==", - "dev": true + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "dev": true, + "license": "MIT" }, "node_modules/possible-typed-array-names": { "version": "1.1.0", @@ -2521,6 +2494,7 @@ "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", "engines": { "node": ">= 0.6.0" } @@ -2528,19 +2502,23 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" }, "node_modules/process-warning": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz", - "integrity": "sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "dev": true, + "license": "MIT" }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, + "license": "MIT", + "peer": true, "engines": { "node": ">=0.4.0" } @@ -2549,6 +2527,7 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "license": "MIT", "dependencies": { "asap": "~2.0.6" } @@ -2559,33 +2538,148 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, - "node_modules/pump": { + "node_modules/pug": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.3.tgz", + "integrity": "sha512-uBi6kmc9f3SZ3PXxqcHiUZLmIXgfgWooKWXcwSGwQd2Zi5Rb0bT14+8CJjJgI8AB+nndLaNgHGrcc6bPIB665g==", + "license": "MIT", + "dependencies": { + "pug-code-gen": "^3.0.3", + "pug-filters": "^4.0.0", + "pug-lexer": "^5.0.1", + "pug-linker": "^4.0.0", + "pug-load": "^3.0.0", + "pug-parser": "^6.0.0", + "pug-runtime": "^3.0.1", + "pug-strip-comments": "^2.0.0" + } + }, + "node_modules/pug-attrs": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", + "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", + "license": "MIT", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "constantinople": "^4.0.1", + "js-stringify": "^1.0.2", + "pug-runtime": "^3.0.0" } }, - "node_modules/pumpify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", - "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", + "node_modules/pug-code-gen": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.3.tgz", + "integrity": "sha512-cYQg0JW0w32Ux+XTeZnBEeuWrAY7/HNE6TWnhiHGnnRYlCgyAUPoyh9KzCMa9WhcJlJ1AtQqpEYHc+vbCzA+Aw==", + "license": "MIT", + "dependencies": { + "constantinople": "^4.0.1", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.2", + "pug-attrs": "^3.0.0", + "pug-error": "^2.1.0", + "pug-runtime": "^3.0.1", + "void-elements": "^3.1.0", + "with": "^7.0.0" + } + }, + "node_modules/pug-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.1.0.tgz", + "integrity": "sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==", + "license": "MIT" + }, + "node_modules/pug-filters": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", + "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", + "license": "MIT", + "dependencies": { + "constantinople": "^4.0.1", + "jstransformer": "1.0.0", + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0", + "resolve": "^1.15.1" + } + }, + "node_modules/pug-lexer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", + "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", + "license": "MIT", + "dependencies": { + "character-parser": "^2.2.0", + "is-expression": "^4.0.0", + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-linker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", + "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", + "license": "MIT", + "dependencies": { + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-load": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", + "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", + "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", + "license": "MIT", + "dependencies": { + "pug-error": "^2.0.0", + "token-stream": "1.0.0" + } + }, + "node_modules/pug-runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", + "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==", + "license": "MIT" + }, + "node_modules/pug-strip-comments": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", + "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", + "license": "MIT", + "dependencies": { + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-walk": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", + "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "dev": true, + "license": "MIT", "dependencies": { - "duplexify": "^4.1.1", - "inherits": "^2.0.3", - "pump": "^3.0.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, "node_modules/qs": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", - "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -2594,15 +2688,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/queue": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/queue/-/queue-4.5.1.tgz", - "integrity": "sha512-AMD7w5hRXcFSb8s9u38acBZ+309u6GsiibP4/0YacJeaurRshogB7v/ZcVPxP5gD5+zIw6ixRHdutiYUJfwKHw==", - "dev": true, - "dependencies": { - "inherits": "~2.0.0" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -2627,12 +2712,15 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -2647,56 +2735,33 @@ "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 12.13.0" } }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA==", - "dev": true, - "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">= 10" } }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2706,20 +2771,29 @@ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", - "dev": true, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", "dependencies": { - "value-or-function": "^3.0.0" + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "engines": { - "node": ">= 0.10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/reusify": { @@ -2772,13 +2846,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safe-stable-stringify": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -2787,12 +2863,13 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -2805,6 +2882,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -2841,17 +2919,73 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/should-proxy/-/should-proxy-1.0.4.tgz", "integrity": "sha512-RPQhIndEIVUCjkfkQ6rs6sOR6pkxJWCNdxtfG5pP0RVgUYbK5911kLTF0TNcCC0G3YCGd492rMollFT2aTd9iQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -2877,7 +3011,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/simple-get": { "version": "4.0.1", @@ -2897,6 +3032,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", @@ -2904,10 +3040,11 @@ } }, "node_modules/sonic-boom": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.2.1.tgz", - "integrity": "sha512-iITeTHxy3B9FGu8aVdiDXUVAcHMF9Ss0cCsAOo2HfCrmVGT3/DT5oYaeu0M/YKZDlKTvChEyPq0zI9Hf33EX6A==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz", + "integrity": "sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==", "dev": true, + "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0" } @@ -2916,7 +3053,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -2926,20 +3063,28 @@ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "dev": true, + "license": "ISC", "engines": { "node": ">= 10.x" } }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } @@ -2948,6 +3093,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -2961,6 +3107,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -2973,6 +3120,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -2980,10 +3128,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/sync-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", "integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==", + "license": "MIT", "dependencies": { "http-response-object": "^3.0.1", "sync-rpc": "^1.2.1", @@ -2997,14 +3158,36 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz", "integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==", + "license": "MIT", "dependencies": { "get-port": "^3.1.0" } }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, "node_modules/then-request": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", + "license": "MIT", "dependencies": { "@types/concat-stream": "^1.6.0", "@types/form-data": "0.0.33", @@ -3025,90 +3208,40 @@ "node_modules/then-request/node_modules/@types/node": { "version": "8.10.66", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", - "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==" - }, - "node_modules/thread-stream": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.3.0.tgz", - "integrity": "sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==", - "dev": true, - "dependencies": { - "real-require": "^0.2.0" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/through2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", + "license": "MIT" }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, + "node_modules/then-request/node_modules/form-data": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz", + "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", + "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" } }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==", + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", "dev": true, + "license": "MIT", "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "real-require": "^0.2.0" } }, "node_modules/to-buffer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", - "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", "license": "MIT", "dependencies": { "isarray": "^2.0.5", @@ -3119,12 +3252,6 @@ "node": ">= 0.4" } }, - "node_modules/to-buffer/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "license": "MIT" - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3137,22 +3264,11 @@ "node": ">=8.0" } }, - "node_modules/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", - "dev": true, - "dependencies": { - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "node_modules/token-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", + "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==", + "license": "MIT" }, "node_modules/typed-array-buffer": { "version": "1.0.3", @@ -3171,13 +3287,14 @@ "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" }, "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "dev": true, + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "license": "BSD-2-Clause", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -3186,29 +3303,11 @@ "node": ">=0.8.0" } }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, "node_modules/unxhr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.0.1.tgz", "integrity": "sha512-MAhukhVHyaLGDjyDYhy8gVjWJyhTECCdNsLwlMoGFoNJ3o79fpQhtQuzmAE4IxCMDwraF4cW8ZjpAV0m9CRQbg==", + "license": "MIT", "engines": { "node": ">=8.11" } @@ -3216,186 +3315,34 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" }, "node_modules/vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs/node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/vinyl-fs/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/vinyl-fs/node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", "dev": true, + "license": "MIT", "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" + "clone": "^2.1.2", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" }, "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, - "node_modules/vinyl-fs/node_modules/is-glob": { + "node_modules/void-elements": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/vinyl-fs/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/vinyl-fs/node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/vinyl-fs/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/vinyl-fs/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/vinyl-fs/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", - "dev": true, - "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/which-typed-array": { "version": "1.1.19", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", @@ -3417,16 +3364,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/with": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", + "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", + "assert-never": "^1.2.1", + "babel-walk": "3.0.0-canary-5" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true + "license": "MIT" }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -3442,66 +3405,76 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" }, "node_modules/xdg-basedir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", "integrity": "sha512-1Dly4xqlulvPD3fZUQJLY+FUIeqN3N2MM3uqe4rCJftAvOjFa3jFGfctOgluGx4ahPbUCsZkmJILiP0Vi4T6lQ==", + "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", + "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.0.0" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.1.3.tgz", + "integrity": "sha512-JCCdmlJJWv7L0q/KylOekyRaUrdEoUxWkWVcgorosTROCFWiS9p2NNPE9Yb91ak7b1N5SxAZEliWpspbZccivw==", "dev": true, + "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "pend": "~1.2.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/yazl": { @@ -3509,6 +3482,7 @@ "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", "dev": true, + "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3" } diff --git a/docs/package.json b/docs/package.json index a627b55151..7cfc263252 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,15 +1,15 @@ { "devDependencies": { - "@antora/cli": "3.1.3", - "@antora/site-generator": "3.1.3", - "@sntke/antora-mermaid-extension": "^0.0.4" + "@antora/cli": "3.1.14", + "@antora/site-generator": "3.1.14", + "@sntke/antora-mermaid-extension": "^0.0.8" }, "dependencies": { "@alandefreitas/antora-playbook-macros-extension": "^0.0.1", - "@antora/lunr-extension": "^1.0.0-alpha.8", - "@asciidoctor/tabs": "^1.0.0-beta.3", - "@cppalliance/antora-cpp-reference-extension": "^0.0.7", - "asciidoctor": "^2.2.6", + "@antora/lunr-extension": "^1.0.0-alpha.12", + "@asciidoctor/tabs": "^1.0.0-beta.6", + "@cppalliance/antora-cpp-reference-extension": "^0.1.0", + "asciidoctor": "^3.0.4", "sync-request": "^6.1.0" } } diff --git a/docs/website/package-lock.json b/docs/website/package-lock.json index 4662823e2d..3d942185a0 100644 --- a/docs/website/package-lock.json +++ b/docs/website/package-lock.json @@ -10,9 +10,9 @@ "license": "Apache-2.0", "dependencies": { "asciidoctor": "^3.0.4", - "cheerio": "^1.0.0-rc.12", + "cheerio": "^1.1.2", "handlebars": "^4.7.8", - "highlight.js": "^11.10.0" + "highlight.js": "^11.11.1" } }, "node_modules/@asciidoctor/cli": { @@ -38,6 +38,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-3.0.4.tgz", "integrity": "sha512-41SDMi7iRRBViPe0L6VWFTe55bv6HEOJeRqMj5+E5wB1YPdUPuTucL4UAESPZM6OWmn4t/5qM5LusXomFUVwVQ==", + "peer": true, "dependencies": { "@asciidoctor/opal-runtime": "3.0.1", "unxhr": "1.2.0" @@ -244,20 +245,25 @@ } }, "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.2.tgz", + "integrity": "sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==", + "license": "MIT", "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.0.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.12.0", + "whatwg-mimetype": "^4.0.0" }, "engines": { - "node": ">= 6" + "node": ">=20.18.1" }, "funding": { "url": "https://github.com/cheeriojs/cheerio?sponsor=1" @@ -413,9 +419,10 @@ } }, "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -444,6 +451,19 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -646,17 +666,18 @@ } }, "node_modules/highlight.js": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.10.0.tgz", - "integrity": "sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==", + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", + "license": "BSD-3-Clause", "engines": { "node": ">=12.0.0" } }, "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", + "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -664,11 +685,36 @@ "url": "https://github.com/sponsors/fb55" } ], + "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" + "domutils": "^3.2.1", + "entities": "^6.0.0" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, "node_modules/inflight": { @@ -864,28 +910,54 @@ } }, "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", "dependencies": { - "entities": "^4.4.0" + "entities": "^6.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" } }, "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "license": "MIT", "dependencies": { - "domhandler": "^5.0.2", + "domhandler": "^5.0.3", "parse5": "^7.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -1035,6 +1107,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -1130,6 +1208,15 @@ "node": ">=0.8.0" } }, + "node_modules/undici": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", + "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/unxhr": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.2.0.tgz", @@ -1146,6 +1233,27 @@ "node": ">=0.10.0" } }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/with": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", diff --git a/docs/website/package.json b/docs/website/package.json index 3dcf455aa1..eae1b8a936 100644 --- a/docs/website/package.json +++ b/docs/website/package.json @@ -15,8 +15,8 @@ "license": "Apache-2.0", "dependencies": { "asciidoctor": "^3.0.4", - "cheerio": "^1.0.0-rc.12", + "cheerio": "^1.1.2", "handlebars": "^4.7.8", - "highlight.js": "^11.10.0" + "highlight.js": "^11.11.1" } } From 63a843b0254fe71419054296dedcc4450b06d7bb Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Wed, 19 Nov 2025 22:26:56 -0500 Subject: [PATCH 2/4] feat(util): run_all_tests script --- CMakeLists.txt | 45 ++- docs/modules/ROOT/pages/contribute.adoc | 29 +- util/README.adoc | 12 + util/run_all_tests.py | 437 ++++++++++++++++++++++++ 4 files changed, 512 insertions(+), 11 deletions(-) create mode 100644 util/run_all_tests.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fc023be48..cd2db0f870 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ option(MRDOCS_INSTALL "Configure install target" ON) option(MRDOCS_PACKAGE "Build install package" ON) option(MRDOCS_BUILD_SHARED "Link shared" ${BUILD_SHARED_LIBS}) option(MRDOCS_BUILD_TESTS "Build tests" ${BUILD_TESTING}) +option(MRDOCS_BUILD_STRICT_TESTS "Enable strict tests" ON) option(MRDOCS_REQUIRE_GIT "Git is required: not being able to extract version build is an error" ON) if (MRDOCS_BUILD_TESTS OR MRDOCS_INSTALL) option(MRDOCS_BUILD_DOCS "Build documentation" ON) @@ -520,10 +521,39 @@ if (MRDOCS_BUILD_TESTS) ) endforeach () + #------------------------------------------------- + # Self-documentation test (always run; warn-as-error toggled by strict flag) + #------------------------------------------------- + set(MRDOCS_SELF_DOC_OUTPUT "${CMAKE_BINARY_DIR}/docs/self-reference") + set(MRDOCS_SELF_DOC_TAGFILE "${MRDOCS_SELF_DOC_OUTPUT}/reference.tag.xml") + + add_test(NAME mrdocs-self-doc + COMMAND + mrdocs + "${CMAKE_SOURCE_DIR}/CMakeLists.txt" + "--config=${CMAKE_SOURCE_DIR}/docs/mrdocs.yml" + "--output=${MRDOCS_SELF_DOC_OUTPUT}" + --generator=adoc + "--addons=${CMAKE_SOURCE_DIR}/share/mrdocs/addons" + "--stdlib-includes=${LIBCXX_DIR}" + "--stdlib-includes=${STDLIB_INCLUDE_DIR}" + "--libc-includes=${CMAKE_SOURCE_DIR}/share/mrdocs/headers/libc-stubs" + "--tagfile=${MRDOCS_SELF_DOC_TAGFILE}" + --multipage=true + --concurrency=16 + --log-level=debug + $<$:--warn-as-error=true> + ) + #------------------------------------------------- # XML lint #------------------------------------------------- - find_package(LibXml2) + if (MRDOCS_BUILD_STRICT_TESTS) + # Strict mode expects xml-lint to run; require LibXml2. + find_package(LibXml2 REQUIRED) + else() + find_package(LibXml2) + endif() if (LibXml2_FOUND) find_package(Java REQUIRED Runtime) # FindJava @@ -541,7 +571,16 @@ if (MRDOCS_BUILD_TESTS) 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} + --relaxng ${CMAKE_CURRENT_BINARY_DIR}/mrdocs.rng ${XML_SOURCES} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + endif() + + #------------------------------------------------- + # YAML schema check + #------------------------------------------------- + if (PYTHON_EXECUTABLE) + add_test(NAME yaml-schema-check + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/util/generate-yaml-schema.py --check WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endif() endif() @@ -589,7 +628,7 @@ if (MRDOCS_BUILD_DOCS) set(DOCS_BUILD_DIR ${DOCS_SOURCE_DIR}/build/site) set(DOCS_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/doc/mrdocs/html) - # Add custom target for generating documentation + # Add a custom target for generating documentation add_custom_target(generate_docs ALL COMMAND ${CMAKE_COMMAND} -E echo "Install npm dependencies" diff --git a/docs/modules/ROOT/pages/contribute.adoc b/docs/modules/ROOT/pages/contribute.adoc index 1d9e2b0d66..a674e1254c 100644 --- a/docs/modules/ROOT/pages/contribute.adoc +++ b/docs/modules/ROOT/pages/contribute.adoc @@ -3,6 +3,11 @@ This page contains information for contributors to the Mr.Docs project. It is intended to provide an overview of the codebase and the process of adding new features. +Before sending changes, run `python util/run_all_tests.py`. +This script is treated as a “source of truth” pass that configures the preferred preset, builds, runs golden + unit + lint/schema/self-doc checks, installs into a local `install/` prefix, and (by default) builds docs using that fresh install. +Not every policy can be enforced programmatically, but this script covers the checks that are automated; prefer it over ad-hoc command sequences. +Use `--skip-docs` to omit docs or `--no-strict` to relax strict warning handling when needed. + == Codebase Overview The Mr.Docs codebase is divided into several modules: @@ -49,11 +54,17 @@ As a last step, `DoGenerateAction` converts the public `Config` settings into a [#representing_symbols] == Representing Symbols -MrDocs has many categories of objects, where we utilize polymorphism with a fixed set of valid derived types, including Symbols (functions, classes, and enums), DocComment blocks, template parameters, template arguments, and data types. For each such family, we follow a consistent file layout. Most of these families are defined in the `mrdocs/Metadata` directory. +MrDocs has many categories of objects, where we utilize polymorphism with a fixed set of valid derived types, including Symbols (functions, classes, and enums), DocComment blocks, template parameters, template arguments, and data types. +For each such family, we follow a consistent file layout. +Most of these families are defined in the `mrdocs/Metadata` directory. -Each base class is defined in its own header and, when necessary, implementation file. Each derived class also has its own header and implementation file. Finally, there is a single aggregator header file that includes all the derived headers. This file centralizes logic that requires knowledge of the full set of variants, such as visitors, comparison operators, and other operations that depend on the discriminator. +Each base class is defined in its own header and, when necessary, implementation file. +Each derived class also has its own header and implementation file. +Finally, there is a single aggregator header file that includes all the derived headers. +This file centralizes logic that requires knowledge of the full set of variants, such as visitors, comparison operators, and other operations that depend on the discriminator. -Suppose we have a polymorphic family of `Symbol` objects, with derived types `Function`, `Class`, and `Enum`. The files would be organized as follows: +Suppose we have a polymorphic family of `Symbol` objects, with derived types `Function`, `Class`, and `Enum`. +The files would be organized as follows: * The `Symbol/SymbolNodes.inc` file defines the possible derived types and is used to generate code via macros. * The `Symbol/SymbolKind.hpp` file defines the `SymbolKind` enum, which is used as a discriminator for the derived types. @@ -61,7 +72,9 @@ Suppose we have a polymorphic family of `Symbol` objects, with derived types `Fu * The available kinds of derived symbols are defined in `Symbol/.hpp` and `Symbol/.cpp` files, e.g., `Symbol/Function.hpp` and `Symbol/Function.cpp`. * The `Symbol.hpp` file includes all derived headers and defines operations that require knowledge of all variants, such as visitors and comparison operators. -This pattern keeps the individual derived types self-contained while making cross-variant operations explicit and localized. When adding a new derived type, contributors should create its header and source file alongside the existing ones and update the corresponding aggregator file to register the new variant. This keeps the codebase predictable, avoids scattering logic, and ensures that operations over polymorphic families remain easy to find and maintain. +This pattern keeps the individual derived types self-contained while making cross-variant operations explicit and localized. +When adding a new derived type, contributors should create its header and source file alongside the existing ones and update the corresponding aggregator file to register the new variant. +This keeps the codebase predictable, avoids scattering logic, and ensures that operations over polymorphic families remain easy to find and maintain. [#extract_symbols] === Extracting Symbols @@ -139,8 +152,7 @@ This is necessary to generate the full interface for user-defined types. After running the AST traversal on all translation units, `CorpusImpl::build` contains finalization steps for the `Corpus` object. At this point, we process C++ constructs that are not directly represented in the AST. -The first finalization step happens in `CorpusImpl::build` (`src/lib/Lib/CorpusImpl.cpp`), where the `Symbol` objects from a single translation unit -are merged into a map containing the merged results from all other TUs. +The first finalization step happens in `CorpusImpl::build` (`src/lib/Lib/CorpusImpl.cpp`), where the `Symbol` objects from a single translation unit are merged into a map containing the merged results from all other TUs. The merging step is necessary as there may be multiple identical definitions of the same entity. For instance, this represents the case where a function is declared at different points in the code base and might have different attributes or comments. At this step, the doc comments are also finalized. @@ -267,7 +279,8 @@ Why This Approach: * Ensures new contributors are not lost when adapting to project style. * Encourages consistency without rigid automation. -General Advice: When in doubt, copy the style of the surrounding code. The `.clang-format` file is a tool to help you, not a rule to enforce blindly. +General Advice: When in doubt, copy the style of the surrounding code. +The `.clang-format` file is a tool to help you, not a rule to enforce blindly. The utility script `./util/reformat.sh` can also be used to check a few project invariants, such as header guards and include order. @@ -277,4 +290,4 @@ If you find a bug or have a feature request, please open an issue on the MrDocs If you would like to contribute a feature or bug fix, please open a pull request on the MrDocs GitHub repository: https://github.com/cppalliance/mrdocs/pulls -If you would like to discuss a feature or bug fix before opening a pull request, discussing happen in the `#mrdocs` channel on the Cpplang Slack: https://cpplang.slack.com/ \ No newline at end of file +If you would like to discuss a feature or bug fix before opening a pull request, discussing happen in the `#mrdocs` channel on the Cpplang Slack: https://cpplang.slack.com/ diff --git a/util/README.adoc b/util/README.adoc index ef2cf828cf..da4afcfe85 100644 --- a/util/README.adoc +++ b/util/README.adoc @@ -1,3 +1,15 @@ = Build tools This directory holds additional scripts and files for building and testing. + +== Test runner + +- Strict tests (self-doc, format check, warn-as-error) are enabled by default; pass `--no-strict` to disable `MRDOCS_BUILD_STRICT_TESTS`. +- Run `python util/run_all_tests.py` to configure the best release/* preset for your OS, build, and execute the full ctest suite (golden tests first, then the rest). +- The runner forces compiler warnings to be treated as errors with CI-matching flags: `-Werror -Wall` for gcc/clang and `/WX /W4` for MSVC, without clobbering preset defaults. +- Add `--update-golden` to refresh golden fixtures before running the test suite when output diffs in error messages are intentional. +- Use `--preset ` to override the automatic selection. The script prefers presets starting with `release/` (or `release-`) that match your OS and compiler, falling back to `debug/*` if needed. +- After tests (and optional docs), the script installs into `install/` under the repo root to keep the prefix scoped to the workspace. +- Docs build runs by default; pass `--skip-docs` to omit the documentation step. Docs are built after install with `MRDOCS_ROOT` pointed at the freshly installed prefix so the generated reference uses that version. +- Strict tests (self-doc, format check, warn-as-error) are enabled by default; pass `--no-strict` to disable `MRDOCS_BUILD_STRICT_TESTS`. +- `util/reformat.py` supports `--check` to validate formatting/include guards without modifying files (used by the strict test suite). diff --git a/util/run_all_tests.py b/util/run_all_tests.py new file mode 100644 index 0000000000..0ecbb87496 --- /dev/null +++ b/util/run_all_tests.py @@ -0,0 +1,437 @@ +#!/usr/bin/env python3 +# +# Licensed under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com) +# +""" +Configure, build, and run all MrDocs tests with sensible preset selection. +""" + +import argparse +import json +import os +import platform +import subprocess +import sys +from pathlib import Path +from typing import Dict, List, Optional + + +ROOT = Path(__file__).resolve().parent.parent +PRESETS_FILE = ROOT / "CMakeUserPresets.json" + +def error(message: str) -> None: + """Print an error message to stderr without exiting.""" + print(f"error: {message}", file=sys.stderr) + + +def load_presets() -> Dict[str, dict]: + """Load CMakeUserPresets.json and return a name->preset map.""" + if not PRESETS_FILE.exists(): + error( + "CMake user presets are missing. Run bootstrap.py to generate " + "CMakeUserPresets.json." + ) + sys.exit(1) + try: + data = json.loads(PRESETS_FILE.read_text()) + except json.JSONDecodeError as exc: + error(f"Could not parse {PRESETS_FILE}: {exc}") + sys.exit(1) + + presets = {preset["name"]: preset for preset in data.get("configurePresets", [])} + if not presets: + error("No configurePresets entries found in CMakeUserPresets.json.") + sys.exit(1) + return presets + + +BUILD_TYPES = {"release", "debug", "relwithdebinfo", "minsizerel", "optimizeddebug"} +OS_ALIASES = { + "darwin": "macos", + "macos": "macos", + "osx": "macos", + "linux": "linux", + "wsl": "linux", + "windows": "windows", + "win": "windows", +} +COMPILER_TOKENS = { + "appleclang": "clang", + "apple-clang": "clang", + "clang": "clang", + "gcc": "gcc", + "g++": "gcc", + "msvc": "msvc", + "cl": "msvc", +} + + +def parse_preset_name(name: str) -> tuple[Optional[str], Optional[str], Optional[str]]: + """ + Extract build type, OS, and compiler tokens from a preset name. + + Returns: + (build_type | None, os | None, compiler | None) + """ + tokens = name.lower().replace("/", "-").split("-") + build = next((t for t in tokens if t in BUILD_TYPES), None) + os_token = next((OS_ALIASES[t] for t in tokens if t in OS_ALIASES), None) + compiler = next((COMPILER_TOKENS[t] for t in tokens if t in COMPILER_TOKENS), None) + return build, os_token, compiler + + +def preset_score( + name: str, preset: dict, host_os: str +) -> tuple[int, int, int, int, int, int, int, int]: + """ + Compute a priority score for a preset based on desirability signals. + + Higher tuples win; each position reflects: + has_llvm, is_release, has_build, os_matches, has_os, + prefers_default_compiler, compiler_absent_flag, name_shortness_hint + """ + build, os_token, compiler = parse_preset_name(name) + cache_vars = preset.get("cacheVariables", {}) or {} + # Reward presets that declare an LLVM path + has_llvm = int(any(k.lower() == "llvm_root" for k in cache_vars)) + # Reward presets that specify any build type + has_build = int(build is not None) + # Prefer Release over other build types + is_release = int(build == "release") + # Reward presets that declare an OS token + has_os = int(os_token is not None) + # Extra reward when the OS token matches the host + os_matches = int(os_token == host_os) + # Track whether a compiler was explicitly named + compiler_present = int(compiler is not None) + # Prefer presets that leave compiler unspecified (use default) + prefers_default_compiler = int(not compiler_present) + # Slightly prefer shorter names when all else is equal + name_penalty = -len(name) + return ( + has_llvm, + is_release, + has_build, + os_matches, + has_os, + prefers_default_compiler, + -compiler_present, + name_penalty, + ) + + +def pick_preset(presets: Dict[str, dict], override: Optional[str]) -> str: + """ + Choose the best preset for the current host (or honor an explicit override). + + Selection is based on parsed build/OS/compiler tokens and signals like + release build, host OS match, absence of custom compiler, and presence of + an LLVM_ROOT cache variable. + """ + if override: + return override + + host = platform.system() + host_os = "macos" if host == "Darwin" else host.lower() + + # Scan every preset and keep the one with the highest score. + best_name: Optional[str] = None + best_score: Optional[tuple[int, int, int, int, int, int, int, int]] = None + + for name, preset in presets.items(): + score = preset_score(name, preset, host_os) + if best_score is None or score > best_score: + best_score = score + best_name = name + + if best_name: + return best_name + + error( + "Could not find a suitable preset. " + "Run bootstrap.py to regenerate presets or provide --preset explicitly." + ) + sys.exit(1) + + +def build_dir_for(preset_name: str) -> Path: + """Return the build directory path for a given preset name.""" + return ROOT / "build" / preset_name + + +def install_dir_for(preset_name: str) -> Path: + """Return the install prefix path for a given preset name.""" + return ROOT / "install" / preset_name + + +def run_command( + command: List[str], + cwd: Optional[Path] = None, + env: Optional[dict] = None, +) -> None: + """ + Run a command, printing it first and raising on failure. + + If env is provided, it is merged over the current environment. + """ + print(f"> {' '.join(command)}") + merged_env = os.environ.copy() + if env: + merged_env.update(env) + completed = subprocess.run(command, cwd=cwd or ROOT, env=merged_env) + if completed.returncode != 0: + raise subprocess.CalledProcessError(completed.returncode, command) + + +def run_ctest(build_dir: Path, regex: Optional[str] = None, exclude: Optional[str] = None) -> int: + """ + Run ctest in a build directory, optionally filtering by regex or exclusion. + + Returns: + ctest exit code + """ + command = ["ctest", "--test-dir", str(build_dir), "--output-on-failure"] + if regex: + command.extend(["-R", regex]) + if exclude: + command.extend(["-E", exclude]) + print(f"> {' '.join(command)}") + result = subprocess.run(command, cwd=build_dir) + return result.returncode + + +def run_ctest_case(build_dir: Path, name: str) -> int: + """Run a single-named ctest case by exact match and return its exit code.""" + command = [ + "ctest", + "--test-dir", + str(build_dir), + "--output-on-failure", + "-R", + f"^{name}$", + ] + print(f"> {' '.join(command)}") + result = subprocess.run(command, cwd=build_dir) + return result.returncode + + +def list_ctest_names(build_dir: Path) -> List[str]: + """Return the list of test names discovered by `ctest -N`.""" + proc = subprocess.run( + ["ctest", "--test-dir", str(build_dir), "-N"], + text=True, + capture_output=True, + cwd=build_dir, + ) + if proc.returncode != 0: + return [] + names: List[str] = [] + for line in proc.stdout.splitlines(): + line = line.strip() + if line.startswith("Test #"): + parts = line.split(": ", 1) + if len(parts) == 2: + names.append(parts[1]) + return names or [] + + +def append_missing_flags(flags: Optional[str], required: List[str]) -> str: + """Append required flags if they are not already present.""" + tokens = (flags.split() if flags else []) + for flag in required: + if flag not in tokens: + tokens.append(flag) + return " ".join(tokens) + + +def infer_warning_flags(preset_name: str, preset: Optional[dict]) -> List[str]: + """Choose the appropriate warning-as-error + level flags for the toolchain.""" + _, _, compiler_token = parse_preset_name(preset_name) + compiler_hint = compiler_token + + if preset: + cache_vars = preset.get("cacheVariables", {}) or {} + cxx_compiler = str(cache_vars.get("CMAKE_CXX_COMPILER", "")).lower() + if cxx_compiler: + if "clang" in cxx_compiler: + compiler_hint = "clang" + elif "g++" in cxx_compiler or "gcc" in cxx_compiler: + compiler_hint = "gcc" + elif "cl" in cxx_compiler: + compiler_hint = "msvc" + + if compiler_hint == "msvc" or platform.system() == "Windows": + return ["/WX", "/W4"] + return ["-Werror", "-Wall"] + + +def main() -> None: + """CLI entry point: choose preset, configure, build, and run tests.""" + parser = argparse.ArgumentParser( + description="Configure, build, and run all MrDocs tests." + ) + parser.add_argument( + "--preset", + help="Configure/build preset to use (defaults to a release/* preset for this OS).", + ) + parser.add_argument( + "--update-golden", + action="store_true", + help="Refresh golden tests before running the test suite.", + ) + parser.add_argument( + "--skip-docs", + action="store_true", + help="Skip building documentation.", + ) + parser.add_argument( + "--no-strict", + action="store_true", + help="Disable MRDOCS_BUILD_STRICT_TESTS.", + ) + parser.add_argument( + "--parallel", + type=int, + default=os.cpu_count() or 1, + help="Number of parallel jobs for cmake --build (default: CPU count).", + ) + args = parser.parse_args() + + presets: Dict[str, dict] = {} + preset_name: str + if args.preset: + preset_name = args.preset + if PRESETS_FILE.exists(): + presets = load_presets() + else: + presets = load_presets() + preset_name = pick_preset(presets, None) + build_dir = build_dir_for(preset_name) + install_dir = install_dir_for(preset_name) + + build_docs = not args.skip_docs + + strict_tests = not args.no_strict + + preset = presets.get(preset_name) + warning_flags = infer_warning_flags(preset_name, preset) + cache_vars = preset.get("cacheVariables", {}) if preset else {} + c_flags = append_missing_flags( + cache_vars.get("CMAKE_C_FLAGS") or os.environ.get("CFLAGS"), warning_flags + ) + cxx_flags = append_missing_flags( + cache_vars.get("CMAKE_CXX_FLAGS") or os.environ.get("CXXFLAGS"), warning_flags + ) + try: + # Configure and build using the chosen preset. + configure_cmd = ["cmake", "--preset", preset_name] + configure_cmd.append(f"-DMRDOCS_BUILD_STRICT_TESTS={'ON' if strict_tests else 'OFF'}") + configure_cmd.append(f"-DCMAKE_C_FLAGS={c_flags}") + configure_cmd.append(f"-DCMAKE_CXX_FLAGS={cxx_flags}") + run_command(configure_cmd) + run_command(["cmake", "--build", str(build_dir), "--parallel", str(args.parallel)]) + + if args.update_golden: + print( + "Updating golden tests before running ctest. " + "Only do this after confirming output diffs are intentional." + ) + run_command( + [ + "cmake", + "--build", + str(build_dir), + "--target", + "mrdocs-update-test-fixtures-all", + "--parallel", + str(args.parallel), + ] + ) + + # Discover all tests up front so we can split golden from everything else. + tests = list_ctest_names(build_dir) + golden_tests = [t for t in tests if "golden" in t] + non_golden_tests = [t for t in tests if "golden" not in t] + + # Run golden tests first to give targeted guidance. + golden_rc = 0 + if golden_tests: + golden_rc = run_ctest(build_dir, regex="mrdocs-golden-tests") + if golden_rc != 0: + error("Golden tests failed.") + print( + "If the failures are only golden output differences, review them for " + "intentionality. If AND ONLY IF they are intentional, rerun with --update-golden " + "to refresh the fixtures." + ) + sys.exit(golden_rc) + + # Run non-golden tests one by one with targeted suggestions. + fixups = { + "mrdocs-unit-tests": ( + "Unit tests failed. Rerun with `ctest --test-dir {build} -V -R mrdocs-unit-tests` " + "to see the exact failures, fix the code/test, then rerun." + ), + "xml-lint": ( + "XML lint failed. Ensure Java and libxml2 are installed and on PATH. " + "Reproduce with `ctest --test-dir {build} -V -R xml-lint`. " + "If trang/rng files are missing, verify util/trang.jar exists." + ), + "yaml-schema-check": ( + "YAML schema check failed. Run `python util/generate-yaml-schema.py --check` from the repo root, " + "update ConfigOptions.json / generated schema if needed, then rerun " + "`ctest --test-dir {build} -V -R yaml-schema-check`." + ), + "mrdocs-self-doc": ( + "Self-doc run failed. Rerun with `ctest --test-dir {build} -V -R mrdocs-self-doc` " + "to inspect mrdocs output. Common issues: wrong stdlib/libc include paths, " + "doc warnings promoted to errors when MRDOCS_BUILD_STRICT_TESTS=ON, or stale docs/mrdocs.yml config." + ), + } + for name in non_golden_tests or ["mrdocs-unit-tests", "xml-lint", "yaml-schema-check", "mrdocs-self-doc"]: + rc = run_ctest_case(build_dir, name) + if rc != 0: + error(f"Test failed: {name}") + msg = fixups.get(name) + if msg: + # allow build dir substitution when present + print(msg.format(build=str(build_dir))) + else: + print( + f"Inspect detailed output with `ctest --test-dir {build_dir} -V -R {name}`; " + f"additional logs: `{build_dir}/Testing/Temporary/LastTest.log`. " + "Address the reported failure, then rerun the same ctest command or this script." + ) + sys.exit(rc) + + # Install into a scoped prefix under the repository root to avoid polluting the system. + install_dir.mkdir(parents=True, exist_ok=True) + run_command(["cmake", "--install", str(build_dir), "--prefix", str(install_dir)]) + + # Optionally build docs via the repository scripts instead of CMake. + if build_docs: + docs_dir = ROOT / "docs" + build_sh = docs_dir / "build_local_docs.sh" + build_bat = docs_dir / "build_local_docs.bat" + # Pick the script that matches the host OS; both files may exist. + if platform.system() == "Windows" and build_bat.exists(): + run_command([str(build_bat)], cwd=docs_dir, env={"MRDOCS_ROOT": str(install_dir)}) + elif platform.system() != "Windows" and build_sh.exists(): + # Call explicitly via bash to avoid exec-format errors when the script lacks a shebang. + run_command(["bash", str(build_sh)], cwd=docs_dir, env={"MRDOCS_ROOT": str(install_dir)}) + else: + error("No docs build script found (expected docs/build_local_docs.sh or docs/build_local_docs.bat).") + + except FileNotFoundError as exc: + error(f"Required tool not found: {exc}") + sys.exit(1) + except subprocess.CalledProcessError as exc: + sys.exit(exc.returncode) + + +if __name__ == "__main__": + main() From 7b498659d77c4484577b6d2ddaa885326bfa53ae Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Thu, 20 Nov 2025 01:29:25 -0500 Subject: [PATCH 3/4] docs(reference): mrdocs comments partial progress toward #1102 --- .github/workflows/ci.yml | 98 ++- include/mrdocs/ADT/ArrayView.hpp | 119 +++ include/mrdocs/ADT/Nullable.hpp | 92 ++- include/mrdocs/ADT/Optional.hpp | 243 +++++- include/mrdocs/ADT/Overload.hpp | 35 +- include/mrdocs/ADT/Polymorphic.hpp | 91 ++- include/mrdocs/ADT/UnorderedStringMap.hpp | 19 + include/mrdocs/Config.hpp | 20 +- .../mrdocs/Config/ReferenceDirectories.hpp | 6 +- include/mrdocs/Corpus.hpp | 94 ++- include/mrdocs/Dom/Array.hpp | 30 +- include/mrdocs/Dom/Function.hpp | 86 +++ include/mrdocs/Dom/LazyArray.hpp | 21 +- include/mrdocs/Dom/LazyObject.hpp | 13 +- include/mrdocs/Dom/Object.hpp | 46 +- include/mrdocs/Dom/String.hpp | 2 + include/mrdocs/Dom/Value.hpp | 116 ++- include/mrdocs/Generators.hpp | 8 + include/mrdocs/Metadata/DocComment.hpp | 35 +- include/mrdocs/Metadata/DocComment/Block.hpp | 30 +- .../DocComment/Block/AdmonitionBlock.hpp | 23 +- .../DocComment/Block/AdmonitionKind.hpp | 6 +- .../Metadata/DocComment/Block/BlockBase.hpp | 75 +- .../Metadata/DocComment/Block/BlockKind.hpp | 13 +- .../Metadata/DocComment/Block/BriefBlock.hpp | 33 +- .../Metadata/DocComment/Block/CodeBlock.hpp | 18 +- .../DocComment/Block/DefinitionListBlock.hpp | 43 ++ .../DocComment/Block/DefinitionListItem.hpp | 11 +- .../Block/FootnoteDefinitionBlock.hpp | 29 +- .../DocComment/Block/HeadingBlock.hpp | 35 +- .../Metadata/DocComment/Block/ListBlock.hpp | 64 +- .../Metadata/DocComment/Block/ListItem.hpp | 11 +- .../Metadata/DocComment/Block/ListKind.hpp | 13 +- .../Metadata/DocComment/Block/MathBlock.hpp | 32 +- .../DocComment/Block/ParagraphBlock.hpp | 23 +- .../Metadata/DocComment/Block/ParamBlock.hpp | 30 +- .../DocComment/Block/ParamDirection.hpp | 4 +- .../DocComment/Block/PostconditionBlock.hpp | 24 +- .../DocComment/Block/PreconditionBlock.hpp | 24 +- .../Metadata/DocComment/Block/QuoteBlock.hpp | 46 +- .../DocComment/Block/ReturnsBlock.hpp | 35 +- .../Metadata/DocComment/Block/SeeBlock.hpp | 33 +- .../Metadata/DocComment/Block/TParamBlock.hpp | 18 +- .../DocComment/Block/TableAlignmentKind.hpp | 15 +- .../Metadata/DocComment/Block/TableBlock.hpp | 26 +- .../Metadata/DocComment/Block/TableCell.hpp | 12 +- .../Metadata/DocComment/Block/TableRow.hpp | 15 +- .../DocComment/Block/ThematicBreakBlock.hpp | 47 +- .../Metadata/DocComment/Block/ThrowsBlock.hpp | 27 +- include/mrdocs/Metadata/DocComment/Inline.hpp | 19 +- .../Metadata/DocComment/Inline/CodeInline.hpp | 28 +- .../DocComment/Inline/CopyDetailsInline.hpp | 24 +- .../Metadata/DocComment/Inline/EmphInline.hpp | 24 +- .../Inline/FootnoteReferenceInline.hpp | 21 +- .../DocComment/Inline/HighlightInline.hpp | 20 +- .../DocComment/Inline/ImageInline.hpp | 28 +- .../Metadata/DocComment/Inline/InlineBase.hpp | 156 +++- .../Metadata/DocComment/Inline/InlineKind.hpp | 13 +- .../DocComment/Inline/LineBreakInline.hpp | 32 +- .../Metadata/DocComment/Inline/LinkInline.hpp | 40 +- .../Metadata/DocComment/Inline/MathInline.hpp | 28 +- .../Metadata/DocComment/Inline/Parts.hpp | 4 +- .../DocComment/Inline/ReferenceInline.hpp | 24 +- .../DocComment/Inline/SoftBreakInline.hpp | 35 +- .../DocComment/Inline/StrikethroughInline.hpp | 30 +- .../DocComment/Inline/StrongInline.hpp | 22 +- .../DocComment/Inline/SubscriptInline.hpp | 20 +- .../DocComment/Inline/SuperscriptInline.hpp | 20 +- .../Metadata/DocComment/Inline/TextInline.hpp | 32 +- include/mrdocs/Metadata/DomCorpus.hpp | 2 +- include/mrdocs/Metadata/Expression.hpp | 24 +- include/mrdocs/Metadata/Name.hpp | 8 + .../mrdocs/Metadata/Name/IdentifierName.hpp | 4 + include/mrdocs/Metadata/Name/NameBase.hpp | 26 +- include/mrdocs/Metadata/Name/NameKind.hpp | 6 + .../Metadata/Name/SpecializationName.hpp | 4 + .../mrdocs/Metadata/Specifiers/AccessKind.hpp | 4 +- .../Metadata/Specifiers/ConstexprKind.hpp | 4 +- .../Metadata/Specifiers/ExplicitInfo.hpp | 4 +- .../Metadata/Specifiers/ExplicitKind.hpp | 2 + .../Metadata/Specifiers/NoexceptInfo.hpp | 9 +- .../Metadata/Specifiers/NoexceptKind.hpp | 2 + .../Metadata/Specifiers/OperatorKind.hpp | 8 +- .../Metadata/Specifiers/ReferenceKind.hpp | 4 +- .../Metadata/Specifiers/StorageClassKind.hpp | 4 +- include/mrdocs/Metadata/Symbol.hpp | 31 +- include/mrdocs/Metadata/Symbol/Concept.hpp | 10 +- include/mrdocs/Metadata/Symbol/Enum.hpp | 14 +- .../mrdocs/Metadata/Symbol/EnumConstant.hpp | 10 +- .../mrdocs/Metadata/Symbol/ExtractionMode.hpp | 10 +- include/mrdocs/Metadata/Symbol/FileKind.hpp | 10 + include/mrdocs/Metadata/Symbol/Friend.hpp | 6 +- include/mrdocs/Metadata/Symbol/Function.hpp | 70 +- .../mrdocs/Metadata/Symbol/FunctionClass.hpp | 7 +- include/mrdocs/Metadata/Symbol/Guide.hpp | 12 +- include/mrdocs/Metadata/Symbol/Location.hpp | 27 +- include/mrdocs/Metadata/Symbol/Namespace.hpp | 59 +- .../mrdocs/Metadata/Symbol/NamespaceAlias.hpp | 10 +- include/mrdocs/Metadata/Symbol/Overloads.hpp | 23 +- include/mrdocs/Metadata/Symbol/Param.hpp | 25 +- include/mrdocs/Metadata/Symbol/Record.hpp | 41 +- include/mrdocs/Metadata/Symbol/RecordBase.hpp | 15 +- .../Metadata/Symbol/RecordInterface.hpp | 15 +- .../mrdocs/Metadata/Symbol/RecordKeyKind.hpp | 4 + .../mrdocs/Metadata/Symbol/RecordTranche.hpp | 31 +- include/mrdocs/Metadata/Symbol/Source.hpp | 17 + include/mrdocs/Metadata/Symbol/SymbolBase.hpp | 43 +- include/mrdocs/Metadata/Symbol/SymbolID.hpp | 35 +- include/mrdocs/Metadata/Symbol/SymbolKind.hpp | 13 +- include/mrdocs/Metadata/Symbol/Typedef.hpp | 19 +- include/mrdocs/Metadata/Symbol/Using.hpp | 17 +- include/mrdocs/Metadata/Symbol/Variable.hpp | 49 +- include/mrdocs/Metadata/TArg.hpp | 6 + include/mrdocs/Metadata/TArg/ConstantTArg.hpp | 7 +- include/mrdocs/Metadata/TArg/TArgBase.hpp | 40 +- include/mrdocs/Metadata/TArg/TArgKind.hpp | 10 +- include/mrdocs/Metadata/TArg/TemplateTArg.hpp | 10 +- include/mrdocs/Metadata/TArg/TypeTArg.hpp | 6 +- include/mrdocs/Metadata/TParam.hpp | 12 + .../mrdocs/Metadata/TParam/ConstantTParam.hpp | 7 +- include/mrdocs/Metadata/TParam/TParamBase.hpp | 45 +- .../mrdocs/Metadata/TParam/TParamKeyKind.hpp | 8 +- include/mrdocs/Metadata/TParam/TParamKind.hpp | 7 +- .../mrdocs/Metadata/TParam/TemplateTParam.hpp | 7 +- include/mrdocs/Metadata/TParam/TypeTParam.hpp | 10 +- include/mrdocs/Metadata/Template.hpp | 23 + include/mrdocs/Metadata/Type.hpp | 57 +- include/mrdocs/Metadata/Type/ArrayType.hpp | 9 + include/mrdocs/Metadata/Type/AutoKind.hpp | 5 + include/mrdocs/Metadata/Type/AutoType.hpp | 8 +- include/mrdocs/Metadata/Type/DecltypeType.hpp | 6 + include/mrdocs/Metadata/Type/FunctionType.hpp | 14 + .../Metadata/Type/FundamentalTypeKind.hpp | 14 +- .../Metadata/Type/LValueReferenceType.hpp | 6 + .../Metadata/Type/MemberPointerType.hpp | 9 + include/mrdocs/Metadata/Type/NamedType.hpp | 8 + include/mrdocs/Metadata/Type/PointerType.hpp | 6 + .../mrdocs/Metadata/Type/QualifierKind.hpp | 4 + .../Metadata/Type/RValueReferenceType.hpp | 6 + include/mrdocs/Metadata/Type/TypeBase.hpp | 55 +- include/mrdocs/Metadata/Type/TypeKind.hpp | 11 +- include/mrdocs/Support/Algorithm.hpp | 14 +- include/mrdocs/Support/Assert.hpp | 14 +- include/mrdocs/Support/Concepts.hpp | 17 +- include/mrdocs/Support/Error.hpp | 26 + include/mrdocs/Support/ExecutorGroup.hpp | 42 +- include/mrdocs/Support/Expected.hpp | 699 +++++++++++++++++- include/mrdocs/Support/Glob.hpp | 71 +- include/mrdocs/Support/Handlebars.hpp | 136 ++-- include/mrdocs/Support/JavaScript.hpp | 121 +-- include/mrdocs/Support/Lua.hpp | 120 ++- include/mrdocs/Support/Parse.hpp | 18 +- include/mrdocs/Support/Path.hpp | 47 +- include/mrdocs/Support/RangeFor.hpp | 78 +- include/mrdocs/Support/Report.hpp | 93 ++- include/mrdocs/Support/ScopeExit.hpp | 31 +- include/mrdocs/Support/SplitLines.hpp | 69 +- include/mrdocs/Support/String.hpp | 114 ++- include/mrdocs/Support/ThreadPool.hpp | 24 +- include/mrdocs/Support/TypeTraits.hpp | 50 ++ include/mrdocs/Support/Visitor.hpp | 8 +- include/mrdocs/Support/any_callable.hpp | 11 + include/mrdocs/Support/source_location.hpp | 14 + src/lib/AST/ASTAction.hpp | 4 +- src/lib/AST/ASTVisitor.cpp | 82 +- src/lib/AST/ASTVisitor.hpp | 8 +- src/lib/AST/ASTVisitorConsumer.hpp | 34 +- src/lib/AST/ClangHelpers.hpp | 44 +- src/lib/AST/InstantiatedFromVisitor.hpp | 2 +- src/lib/AST/MrDocsFileSystem.hpp | 3 +- src/lib/AST/TerminalTypeVisitor.hpp | 56 +- src/lib/AST/TypeBuilder.hpp | 26 +- src/lib/ConfigImpl.hpp | 2 +- src/lib/CorpusImpl.hpp | 4 +- src/lib/Gen/adoc/AdocEscape.hpp | 2 +- src/lib/Gen/hbs/Builder.hpp | 18 +- src/lib/Gen/hbs/HandlebarsCorpus.hpp | 6 +- src/lib/Gen/hbs/HandlebarsGenerator.hpp | 4 +- src/lib/Gen/hbs/TagfileWriter.hpp | 6 +- src/lib/Gen/hbs/VisitorHelpers.hpp | 4 +- .../Finalizers/DocComment/Function.hpp | 12 +- .../Finalizers/DocComment/parseInlines.hpp | 193 ++++- .../Finalizers/DocCommentFinalizer.cpp | 38 +- .../Finalizers/DocCommentFinalizer.hpp | 2 +- src/lib/Metadata/Type.cpp | 38 +- src/lib/MrDocsCompilationDatabase.hpp | 5 +- src/lib/SingleFileDB.hpp | 2 +- src/lib/Support/CMakeExecution.hpp | 2 +- src/lib/Support/Chrono.hpp | 2 +- src/lib/Support/ExecuteAndWaitWithLogging.hpp | 2 +- src/lib/Support/ExecutionContext.hpp | 2 +- src/lib/Support/LegibleNames.hpp | 4 +- src/lib/Support/Path.hpp | 12 +- src/test/lib/MrDocsCompilationDatabase.cpp | 6 +- src/test_suite/diff.hpp | 6 +- src/tool/ToolCompilationDatabase.cpp | 2 +- test-files/golden-tests/mrdocs.yml | 1 + 197 files changed, 5178 insertions(+), 1036 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f1c97eef1..0175e2ecaa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,12 +20,23 @@ concurrency: jobs: cpp-matrix: runs-on: ubuntu-24.04 + container: + image: ubuntu:24.04 name: Generate Test Matrix outputs: matrix: ${{ steps.cpp-matrix.outputs.matrix }} llvm-matrix: ${{ steps.llvm-matrix.outputs.llvm-matrix }} releases-matrix: ${{ steps.releases-matrix.outputs.releases-matrix }} steps: + - name: Install prerequisites + run: | + set -e + apt-get update + apt-get install -y git ca-certificates curl nodejs npm + if ! command -v node >/dev/null 2>&1 && command -v nodejs >/dev/null 2>&1; then + ln -s /usr/bin/nodejs /usr/bin/node + fi + - name: Checkout uses: actions/checkout@v4 @@ -134,6 +145,16 @@ jobs: contents: write steps: + - name: Ensure Node + if: matrix.container != '' && env.ACT == 'true' + run: | + set -e + apt-get update + apt-get install -y nodejs npm + if ! command -v node >/dev/null 2>&1 && command -v nodejs >/dev/null 2>&1; then + ln -s /usr/bin/nodejs /usr/bin/node + fi + # We install git if we are using a container because # containers don't always include git. # We need git to ensure actions/checkout@v4 will use git and @@ -174,6 +195,55 @@ jobs: compiler: ${{ matrix.compiler }} version: ${{ matrix.version }} + - name: Configure symbolizer paths + if: matrix.compiler != 'msvc' + shell: bash + run: | + set -e + candidates=() + # 1) Anything on PATH + if command -v llvm-symbolizer >/dev/null 2>&1; then + candidates+=("$(command -v llvm-symbolizer)") + fi + uname_out="$(uname -s || true)" + # 2) Platform-specific common locations + case "$uname_out" in + Darwin) + if xcrun --find llvm-symbolizer >/dev/null 2>&1; then + candidates+=("$(xcrun --find llvm-symbolizer)") + fi + candidates+=("/opt/homebrew/opt/llvm/bin/llvm-symbolizer") + ;; + Linux) + for dir in /usr/lib/llvm-* /usr/lib/llvm; do + if [ -x "$dir/bin/llvm-symbolizer" ]; then + candidates+=("$dir/bin/llvm-symbolizer") + fi + done + ;; + MINGW*|MSYS*|CYGWIN*) + for dir in "/c/Program Files/LLVM/bin" "/c/ProgramData/chocolatey/lib/llvm/tools/llvm/bin"; do + if [ -x "$dir/llvm-symbolizer.exe" ]; then + candidates+=("$dir/llvm-symbolizer.exe") + fi + done + ;; + esac + sym="" + for c in "${candidates[@]}"; do + if [ -n "$c" ] && [ -x "$c" ]; then + sym="$c" + break + fi + done + if [ -n "$sym" ]; then + echo "Using llvm-symbolizer at: $sym" + echo "LLVM_SYMBOLIZER_PATH=$sym" >> "$GITHUB_ENV" + echo "ASAN_SYMBOLIZER_PATH=$sym" >> "$GITHUB_ENV" + else + echo "Warning: llvm-symbolizer not found; ASan stacks may be unsymbolized." >&2 + fi + # If apple-clang on macos, select the newest Xcode. - name: Select Xcode 16.4 if: matrix.compiler == 'apple-clang' @@ -484,6 +554,9 @@ jobs: - name: CMake Workflow uses: alandefreitas/cpp-actions/cmake-workflow@v1.8.12 + env: + # Bump per-test timeout on Windows to avoid CTest default (1500s) killing slow golden suites. + CTEST_TEST_TIMEOUT: ${{ runner.os == 'Windows' && '3600' || '' }} with: cmake-version: '>=3.26' cxxstd: ${{ matrix.cxxstd }} @@ -619,8 +692,9 @@ jobs: done dir="./build" - lcov --rc lcov_branch_coverage=0 --gcov-tool "$gcov_tool" --directory "$dir" --capture --output-file "$dir/all.info" --ignore-errors inconsistent - lcov --rc lcov_branch_coverage=0 --ignore-errors inconsistent --list "$dir/all.info" + lcov --rc lcov_branch_coverage=0 --gcov-tool "$gcov_tool" --directory "$dir" --capture --output-file "$dir/all.info" --ignore-errors inconsistent,negative --no-external + lcov --rc lcov_branch_coverage=0 --remove "$dir/all.info" "/usr/*" "/lib/*" "/opt/*" --ignore-errors unused,negative --output-file "$dir/all.info" + lcov --rc lcov_branch_coverage=0 --ignore-errors inconsistent,negative --list "$dir/all.info" echo "file=$(realpath "$dir/all.info")" >> $GITHUB_OUTPUT - name: Upload Coverage as Artifact @@ -661,6 +735,16 @@ jobs: contents: write steps: + - name: Ensure Node + if: matrix.container != '' && env.ACT == 'true' + run: | + set -e + apt-get update + apt-get install -y nodejs npm + if ! command -v node >/dev/null 2>&1 && command -v nodejs >/dev/null 2>&1; then + ln -s /usr/bin/nodejs /usr/bin/node + fi + - name: Install packages uses: alandefreitas/cpp-actions/package-install@v1.8.12 id: package-install @@ -1117,6 +1201,16 @@ jobs: contents: write steps: + - name: Ensure Node + if: matrix.container != '' && env.ACT == 'true' + run: | + set -e + apt-get update + apt-get install -y nodejs npm + if ! command -v node >/dev/null 2>&1 && command -v nodejs >/dev/null 2>&1; then + ln -s /usr/bin/nodejs /usr/bin/node + fi + # This calculates a couple of variables, which would normally go in to the regular matrix extra-values # section, but which depend on paths not known at that point. - name: Resolved Matrix diff --git a/include/mrdocs/ADT/ArrayView.hpp b/include/mrdocs/ADT/ArrayView.hpp index 1341c032a3..a6451e8c00 100644 --- a/include/mrdocs/ADT/ArrayView.hpp +++ b/include/mrdocs/ADT/ArrayView.hpp @@ -33,30 +33,67 @@ class ArrayView { public: // types + /** Element type referenced by the view. + */ using value_type = T; + /** Unsigned size type. + */ using size_type = std::size_t; + /** Signed iterator difference type. + */ using difference_type = std::ptrdiff_t; + /** Pointer to constant element. + */ using pointer = const T*; + /** Pointer to constant element. + */ using const_pointer = const T*; + /** Reference to constant element. + */ using reference = const T&; + /** Reference to constant element. + */ using const_reference = const T&; + /** Iterator over elements. + */ using iterator = const T*; + /** Iterator over elements. + */ using const_iterator = const T*; + /** Reverse iterator over the view. + */ using reverse_iterator = std::reverse_iterator; + /** Const reverse iterator over the view. + */ using const_reverse_iterator = std::reverse_iterator; + /** Sentinel used by slicing helpers to indicate “until the end”. + */ static constexpr size_type npos = static_cast(-1); // ctors + /** Construct an empty view. + */ constexpr ArrayView() noexcept = default; + /** Construct a view from a pointer and element count. + @param data Pointer to the first element. + @param count Number of elements in the range. + */ constexpr ArrayView(const T* data, size_type count) noexcept : data_(data), size_(count) {} + /** Construct a view from a C-style array. + @param arr The array to view. + */ template constexpr ArrayView(const T (&arr)[N]) noexcept : data_(arr), size_(N) {} + /** Construct a view from a contiguous iterator range of known size. + @param first Iterator to the first element. + @param count Number of elements starting at `first`. + */ template requires (std::contiguous_iterator && std::same_as>>, T>) @@ -64,63 +101,132 @@ class ArrayView { : data_(std::to_address(first)), size_(count) {} // iterators + /** Return an iterator to the first element. + @return Iterator to the start of the view. + */ constexpr const_iterator begin() const noexcept { return data_; } + /** Return an iterator one past the last element. + @return Iterator to the end sentinel. + */ constexpr const_iterator end() const noexcept { return data_ + size_; } + /** Return a const iterator to the first element. + @return Const iterator to the start of the view. + */ constexpr const_iterator cbegin() const noexcept { return begin(); } + /** Return a const iterator one past the last element. + @return Const iterator to the end sentinel. + */ constexpr const_iterator cend() const noexcept { return end(); } + /** Return a reverse iterator to the last element. + @return Reverse iterator to the last element. + */ constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } + /** Return a reverse iterator one before the first element. + @return Reverse iterator denoting the rend sentinel. + */ constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } // capacity + /** Return the number of elements in the view. + @return Element count. + */ constexpr size_type size() const noexcept { return size_; } + /** Return the number of elements in the view. + @return Element count. + */ constexpr size_type length() const noexcept { return size_; } + /** Return true if the view contains no elements. + @return `true` when size is zero, otherwise `false`. + */ [[nodiscard]] constexpr bool empty() const noexcept { return size_ == 0; } // element access + /** Access the element at the specified index without bounds checking. + @param i Zero-based index. + @return Reference to the element. + */ constexpr const_reference operator[](size_type i) const noexcept { return data_[i]; } + /** Access the element at the specified index with bounds checking. + @param i Zero-based index. + @return Reference to the element. + */ constexpr const_reference at(size_type i) const { assert(i < size_); return data_[i]; } + /** Return a reference to the first element. + */ constexpr const_reference front() const { assert(!empty()); return data_[0]; } + /** Return a reference to the last element. + */ constexpr const_reference back() const { assert(!empty()); return data_[size_ - 1]; } + /** Return a pointer to the underlying data. + @return Pointer to the first element, or nullptr when empty. + */ constexpr const_pointer data() const noexcept { return data_; } // modifiers (adjust the view; do not touch underlying data) + /** Remove `n` elements from the front of the view. + @param n Number of elements to drop. + */ constexpr void remove_prefix(size_type n) noexcept { assert(n <= size_); data_ += n; size_ -= n; } + /** Remove `n` elements from the back of the view. + @param n Number of elements to drop. + */ constexpr void remove_suffix(size_type n) noexcept { assert(n <= size_); size_ -= n; } // slicing + /** Return a subview starting at `pos` with up to `count` elements. + @param pos Starting index within the current view. + @param count Maximum number of elements to include; use npos for the remainder. + @return Subview representing the requested slice. + */ constexpr ArrayView slice(size_type pos, size_type count = npos) const noexcept { assert(pos <= size_); const size_type rcount = (count == npos || pos + count > size_) ? (size_ - pos) : count; return ArrayView(data_ + pos, rcount); } + /** Return a view containing the first `n` elements. + @param n Desired prefix length. + @return Subview of the first `n` elements (clamped to size). + */ constexpr ArrayView take_front(size_type n) const noexcept { return slice(0, n <= size_ ? n : size_); } + /** Return a view containing the last `n` elements. + @param n Desired suffix length. + @return Subview of the last `n` elements (clamped to size). + */ constexpr ArrayView take_back(size_type n) const noexcept { n = (n <= size_) ? n : size_; return slice(size_ - n, n); } + /** Return a view with the first `n` elements removed. + @param n Number of elements to drop from the front. + @return Subview starting after the dropped elements. + */ constexpr ArrayView drop_front(size_type n) const noexcept { return (n >= size_) ? ArrayView() : ArrayView(data_ + n, size_ - n); } + /** Return a view with the last `n` elements removed. + @param n Number of elements to drop from the back. + @return Subview excluding the dropped elements. + */ constexpr ArrayView drop_back(size_type n) const noexcept { return (n >= size_) ? ArrayView() : ArrayView(data_, size_ - n); } @@ -145,18 +251,31 @@ class ArrayView { }; // deduction guides +/** Deduce ArrayView element type from pointer and count. +*/ template ArrayView(const T*, std::size_t) -> ArrayView; +/** Deduce ArrayView element type from C-style array. +*/ template ArrayView(const T (&)[N]) -> ArrayView; // helpers +/** Create an ArrayView from a pointer and count. + @param data Pointer to the first element. + @param count Number of elements. + @return View over the provided range. +*/ template constexpr ArrayView make_array_view(const T* data, std::size_t count) noexcept { return ArrayView(data, count); } +/** Create an ArrayView from a C-style array. + @param arr Array to view. + @return View over the provided array. +*/ template constexpr ArrayView make_array_view(const T (&arr)[N]) noexcept { return ArrayView(arr); diff --git a/include/mrdocs/ADT/Nullable.hpp b/include/mrdocs/ADT/Nullable.hpp index ba659db60c..acc70789b1 100644 --- a/include/mrdocs/ADT/Nullable.hpp +++ b/include/mrdocs/ADT/Nullable.hpp @@ -38,7 +38,7 @@ namespace mrdocs { Notes - Built-in pointer types and std::nullptr_t are pre-specialized to use nullptr as the sentinel. -**/ +*/ template struct sentinel_traits { @@ -48,15 +48,22 @@ struct sentinel_traits /** sentinel_traits specialization for raw pointers. Uses nullptr as the sentinel value. -**/ +*/ template struct sentinel_traits { + /** Return the sentinel pointer value (nullptr). + */ static constexpr T* sentinel() noexcept { return nullptr; } + /** Return true if the pointer equals the sentinel. + + @param p Pointer to test. + @return `true` when @p p is nullptr. + */ static constexpr bool is_sentinel(T const* p) noexcept { @@ -65,16 +72,22 @@ struct sentinel_traits { }; /** sentinel_traits specialization for std::nullptr_t. -**/ +*/ template<> struct sentinel_traits { + /** Return the sentinel value for std::nullptr_t. + */ static constexpr std::nullptr_t sentinel() noexcept { return nullptr; } + /** Return true if the value equals the sentinel. + + @return Always true because the sentinel is unique. + */ static constexpr bool is_sentinel(std::nullptr_t) noexcept { @@ -90,17 +103,24 @@ struct sentinel_traits Uses the maximum representable value (~0u) as the sentinel, which corresponds to -1 when converted. -**/ +*/ template requires (!std::same_as) struct sentinel_traits { + /** Return the sentinel value (~0u). + */ static constexpr T sentinel() noexcept { return static_cast(-1); } + /** Return true if the value equals the sentinel. + + @param v Value to test. + @return `true` when @p v equals the sentinel. + */ static constexpr bool is_sentinel(T v) noexcept { @@ -112,7 +132,9 @@ struct sentinel_traits Uses a quiet NaN as the sentinel value. This assumes that T supports NaN and that it is distinguishable from all ordinary values. -**/ +*/ + /** Return the floating-point NaN sentinel. + */ template struct sentinel_traits { @@ -122,6 +144,11 @@ struct sentinel_traits return std::numeric_limits::quiet_NaN(); } + /** Return true if @p v is the NaN sentinel. + + @param v Value to test. + @return `true` when @p v is NaN. + */ static constexpr bool is_sentinel(T v) noexcept { @@ -134,7 +161,9 @@ struct sentinel_traits If the enum defines Unknown, UNKNOWN, None, or NONE, this trait uses that enumerator as the sentinel. This requires that such an enumerator exists and is accessible from the scope of T. -**/ +*/ + /** Return the enum sentinel value. + */ template requires std::is_enum_v && (requires { T::unknown; } || @@ -158,6 +187,11 @@ struct sentinel_traits return T::NONE; } + /** Return true if @p v equals the sentinel value. + + @param v Value to test. + @return `true` when @p v matches the sentinel enumerator. + */ static constexpr bool is_sentinel(T v) noexcept { @@ -166,7 +200,7 @@ struct sentinel_traits }; /** Concept that is satisfied when sentinel_traits declares a usable sentinel. -**/ +*/ template concept HasSentinel = requires @@ -183,7 +217,7 @@ concept HasSentinel = Common cases of such containers include std::string, std::vector, std::optional, std::unique_ptr, std::shared_ptr, and many more. -**/ +*/ template concept ClearableContainerLike = // ---- nested container typedefs present ---- @@ -238,7 +272,7 @@ concept ClearableContainerLike = Users may explicitly specialize nullable_traits for their types to define the desired semantics. -**/ +*/ template struct nullable_traits { @@ -249,23 +283,36 @@ struct nullable_traits /** nullable_traits for types with a sentinel. Delegates null handling to sentinel_traits. -**/ +*/ template requires HasSentinel struct nullable_traits { + /** Return true if @p v matches the sentinel for @c T. + + @param v Value to test. + @return `true` when @p v equals the sentinel. + */ static constexpr bool is_null(T const& v) noexcept { return sentinel_traits::is_sentinel(v); } + /** Return the sentinel value representing null. + + @return Sentinel value for @c T. + */ static constexpr T null() noexcept { return sentinel_traits::sentinel(); } + /** Overwrite @p v with the sentinel null value. + + @param v Value to clear. + */ static constexpr void make_null(T& v) noexcept { @@ -277,7 +324,12 @@ struct nullable_traits Treats the empty state as null, creates null via default construction, and erases via clear(). -**/ +*/ + /** Return true if @p v is empty. + + @param v Value to test. + @return `true` when the container is empty. + */ template requires (!HasSentinel && ClearableContainerLike) struct nullable_traits @@ -288,12 +340,20 @@ struct nullable_traits return v.empty(); } + /** Construct a null value using the default constructor. + + @return Default-constructed @c T. + */ static constexpr T null() noexcept(std::is_nothrow_default_constructible_v) { return T(); } + /** Clear @p v to its null (empty) state. + + @param v Value to clear. + */ static constexpr void make_null(T& v) noexcept(noexcept(v.clear())) { @@ -301,9 +361,9 @@ struct nullable_traits } }; -/** Utility function that returns true if T has a nullable_traits +/** Utility concept that returns true if T has a nullable_traits specialization enabled. -**/ +*/ template concept has_nullable_traits_v = requires @@ -316,7 +376,7 @@ concept has_nullable_traits_v = /** make_null helper that uses nullable_traits if available. @param v The value to make null. -**/ +*/ template inline void make_null(T& v) noexcept(noexcept(nullable_traits::make_null(v))) @@ -328,7 +388,7 @@ make_null(T& v) noexcept(noexcept(nullable_traits::make_null(v))) @param v The value to test for null. @return true if v is null, false otherwise. -**/ +*/ template inline bool is_null(T const& v) noexcept(noexcept(nullable_traits::is_null(v))) @@ -339,7 +399,7 @@ is_null(T const& v) noexcept(noexcept(nullable_traits::is_null(v))) /** null_of helper that constructs a null T using nullable_traits. @return A null T value. -**/ +*/ template inline T null_of() noexcept(noexcept(nullable_traits::null())) diff --git a/include/mrdocs/ADT/Optional.hpp b/include/mrdocs/ADT/Optional.hpp index 5014344d56..78ca6b9d65 100644 --- a/include/mrdocs/ADT/Optional.hpp +++ b/include/mrdocs/ADT/Optional.hpp @@ -69,7 +69,7 @@ inline constexpr bool isOptionalV> = true; This single implementation uses a conditional storage type plus if constexpr on has_nullable_traits_v to select the appropriate behavior at compile time. -**/ +*/ template class Optional { using storage_t = std::conditional_t< @@ -122,6 +122,8 @@ class Optional { storage_t s_; public: + /** Value type stored by this Optional. + */ using value_type = T; /// Default-constructs to the “null” state. @@ -138,7 +140,7 @@ class Optional { {} /** Construct from std::nullopt - */ + */ constexpr Optional(std::nullopt_t) noexcept(default_ctor_noex_()) : Optional() {} @@ -151,7 +153,7 @@ class Optional { /** Construct from a value. @param u The value to store. It must be convertible to T. - **/ + */ template > requires(!std::is_same_v>) && (!std::is_same_v>) @@ -170,6 +172,10 @@ class Optional { }()) {} + /** Construct from another Optional with a convertible contained value. + + @param t Source optional. + */ template requires(!std::is_same_v) && std::is_constructible_v && ConstructFromContainedValue @@ -192,6 +198,10 @@ class Optional { }()) {} + /** Construct from another Optional rvalue with a convertible value. + + @param t Source optional. + */ template requires(!std::is_same_v) && std::is_constructible_v && ConstructFromContainedValue @@ -214,6 +224,10 @@ class Optional { }()) {} + /** Construct from std::optional lvalue with convertible value. + + @param t Source optional. + */ template requires std::is_constructible_v && @@ -237,6 +251,10 @@ class Optional { }()) {} + /** Construct from std::optional rvalue with convertible value. + + @param t Source optional. + */ template requires std::is_constructible_v && @@ -260,6 +278,10 @@ class Optional { }()) {} + /** In-place construct the contained value. + + @param args Arguments forwarded to T's constructor. + */ template requires std::is_constructible_v explicit constexpr @@ -276,6 +298,11 @@ class Optional { }()) {} + /** In-place construct the contained value from an initializer list. + + @param il Initializer list forwarded to T's constructor. + @param args Additional arguments forwarded to T's constructor. + */ template requires std::is_constructible_v&, Args...> explicit constexpr Optional( @@ -292,14 +319,21 @@ class Optional { }()) {} - /// Copy assignment + /** Copy assignment. + @return *this. + */ constexpr Optional& operator=(Optional const&) = default; - /// Move assignment + /** Move assignment. + @return *this. + */ constexpr Optional& operator=(Optional&&) = default; + /** Reset to disengaged state from nullptr tag. + @return *this. + */ constexpr Optional& operator=(std::nullptr_t) noexcept(reset_noex_()) { @@ -311,7 +345,7 @@ class Optional { /** Assign from a value. @param u The value to store. It must be convertible to T. - **/ + */ template > requires(!std::is_same_v>) && std::is_constructible_v && std::is_assignable_v @@ -331,6 +365,9 @@ class Optional { return *this; } + /** Assign from another Optional with convertible contained value. + @param u Source optional. + */ template requires (!std::is_same_v) && std::is_constructible_v @@ -360,7 +397,43 @@ class Optional { return *this; } + /** Assign from std::optional lvalue with convertible value. + @param u Source optional. + */ + template + requires (!std::is_same_v) + && std::is_constructible_v + && std::is_assignable_v + && (!detail::ConvertsFromOptional::value) + && (!detail::AssignsFromOptional::value) + constexpr Optional& + operator=(std::optional const& u) noexcept( + std::is_nothrow_constructible_v + && std::is_nothrow_assignable_v) + { + if (u) + { + if constexpr (uses_nullable_traits) + { + s_ = *u; + } + else + { + s_ = *u; + } + } + else + { + reset(); + } + return *this; + } + + + /** Assign from another Optional rvalue with convertible contained value. + @param u Source optional. + */ template requires (!std::is_same_v) && std::is_constructible_v @@ -390,7 +463,41 @@ class Optional { return *this; } - /** Reset to the null state. **/ + /** Assign from std::optional rvalue with convertible value. + + @param u Source optional. + */ + template + requires (!std::is_same_v) + && std::is_constructible_v + && std::is_assignable_v + && (!detail::ConvertsFromOptional::value) + && (!detail::AssignsFromOptional::value) + constexpr Optional& + operator=(std::optional&& u) noexcept( + std::is_nothrow_constructible_v + && std::is_nothrow_assignable_v) + { + if (u) + { + if constexpr (uses_nullable_traits) + { + s_ = std::move(*u); + } + else + { + s_ = std::move(*u); + } + } + else + { + reset(); + } + return *this; + } + + /** Reset to the null state. * + */ constexpr void reset() noexcept(reset_noex_()) { @@ -410,7 +517,7 @@ class Optional { @param args The arguments to forward to T's constructor. @return A reference to the newly constructed value. - **/ + */ template requires std::is_constructible_v constexpr value_type& @@ -438,7 +545,7 @@ class Optional { storage is used. @return `true` if the optional uses nullable_traits for storage. - */ + */ static constexpr bool is_inlined() noexcept { @@ -448,7 +555,7 @@ class Optional { /** True if engaged (contains a value). @return `true` if the optional contains a value. - **/ + */ constexpr bool has_value() const noexcept(has_value_noex_()) { @@ -463,7 +570,7 @@ class Optional { } /** Contextual bool. - **/ + */ constexpr explicit operator bool() const noexcept(noexcept(this->has_value())) { @@ -473,7 +580,7 @@ class Optional { /** Value access. Preconditions: has_value() is true. @return A reference to the contained value. - **/ + */ constexpr value_type& value() & noexcept { @@ -536,7 +643,7 @@ class Optional { /** Pointer-like access. @return A pointer to the contained value. - **/ + */ constexpr value_type* operator->() noexcept { @@ -569,7 +676,7 @@ class Optional { /** Dereference-like access. @return A reference to the contained value. - **/ + */ constexpr value_type& operator*() noexcept { @@ -636,6 +743,10 @@ concept isDerivedFromOptional = requires(T const& t) { } // namespace detail +/** Optional reference wrapper that never owns storage. + + Stores a pointer to an externally owned object; the disengaged state is nullptr. +*/ template class Optional { T* p_ = nullptr; @@ -646,21 +757,30 @@ class Optional { && !reference_constructs_from_temporary_v; public: + /// Referenced value type. using value_type = T; + /// Construct an empty optional reference. constexpr Optional() noexcept = default; + /// Copy constructor. constexpr Optional(Optional const&) noexcept = default; + /// Move constructor. constexpr Optional(Optional&&) noexcept = default; + /// Construct disengaged from std::nullopt. constexpr Optional(std::nullopt_t) noexcept : Optional() {} + /** Bind to a referenceable object. + + @param u Object to bind to. + */ template requires( !std::is_same_v, Optional> && @@ -675,6 +795,10 @@ class Optional { p_ = std::addressof(r); } + /** Construct from another Optional holding a related reference. + + @param rhs Optional to bind to if engaged. + */ template requires ok_bind_v constexpr @@ -688,6 +812,10 @@ class Optional { } } + /** Construct from a const Optional holding a related reference. + + @param rhs Optional to bind to if engaged. + */ template requires ok_bind_v constexpr @@ -701,6 +829,10 @@ class Optional { } } + /** Construct from std::optional lvalue. + + @param o Source optional to bind if engaged. + */ template requires ok_bind_v constexpr @@ -713,6 +845,10 @@ class Optional { } } + /** Construct from const std::optional lvalue. + + @param o Source optional to bind if engaged. + */ template requires ok_bind_v constexpr @@ -725,12 +861,15 @@ class Optional { } } + /// Copy assignment. constexpr Optional& operator=(Optional const&) noexcept = default; + /// Move assignment. constexpr Optional& operator=(Optional&&) noexcept = default; + /// Reset from std::nullopt. constexpr Optional& operator=(std::nullopt_t) noexcept { @@ -738,6 +877,11 @@ class Optional { return *this; } + /** Assign from a referenceable value. + + @param u Reference to bind. + @return *this. + */ template requires ok_bind_v constexpr Optional& @@ -749,6 +893,11 @@ class Optional { return *this; } + /** Assign from another Optional reference. + + @param rhs Source optional. + @return *this. + */ template requires ok_bind_v constexpr @@ -760,6 +909,11 @@ class Optional { return *this; } + /** Assign from a const Optional reference. + + @param rhs Source optional. + @return *this. + */ template requires ok_bind_v constexpr @@ -771,6 +925,11 @@ class Optional { return *this; } + /** Assign from a movable Optional reference. + + @param rhs Source optional. + @return *this. + */ template requires ok_bind_v constexpr @@ -782,6 +941,11 @@ class Optional { return *this; } + /** Bind to a new referenced value. + + @param u Referenceable value to bind. + @return Reference to the bound value. + */ template requires ok_bind_v constexpr @@ -797,6 +961,8 @@ class Optional { static constexpr bool + /** Return true because Optional never allocates storage. + */ is_inlined() noexcept { return true; @@ -804,11 +970,17 @@ class Optional { constexpr bool + /** Check whether the optional holds a reference. + + @return `true` if engaged. + */ has_value() const noexcept { return p_ != nullptr; } + /** Return true when the optional holds a reference. + */ constexpr explicit operator bool() const noexcept @@ -818,6 +990,8 @@ class Optional { constexpr void + /** Disengage the optional. + */ reset() noexcept { p_ = nullptr; @@ -825,6 +999,10 @@ class Optional { constexpr value_type* + /** Return pointer to the referenced object. + + @return Pointer to the bound value. + */ operator->() noexcept { MRDOCS_ASSERT(has_value()); @@ -833,6 +1011,10 @@ class Optional { constexpr value_type const* + /** Return pointer to the referenced object. + + @return Pointer to the bound value. + */ operator->() const noexcept { MRDOCS_ASSERT(has_value()); @@ -841,6 +1023,10 @@ class Optional { constexpr value_type& + /** Dereference the referenced object. + + @return Reference to the bound value. + */ operator*() noexcept { MRDOCS_ASSERT(has_value()); @@ -849,6 +1035,10 @@ class Optional { constexpr value_type const& + /** Dereference the referenced object. + + @return Reference to the bound value. + */ operator*() const noexcept { MRDOCS_ASSERT(has_value()); @@ -857,6 +1047,10 @@ class Optional { constexpr value_type& + /** Access the referenced object. + + @return Reference to the bound value. + */ value() & noexcept { MRDOCS_ASSERT(has_value()); @@ -865,6 +1059,10 @@ class Optional { constexpr value_type const& + /** Access the referenced object. + + @return Const reference to the bound value. + */ value() const& noexcept { MRDOCS_ASSERT(has_value()); @@ -873,6 +1071,10 @@ class Optional { constexpr value_type& + /** Access the referenced object (rvalue overload). + + @return Reference to the bound value. + */ value() && noexcept { MRDOCS_ASSERT(has_value()); @@ -881,12 +1083,20 @@ class Optional { constexpr value_type const& + /** Access the referenced object (const rvalue overload). + + @return Const reference to the bound value. + */ value() const&& noexcept { MRDOCS_ASSERT(has_value()); return *p_; } + /** Exchange the contained value with another Optional. + + @param other Optional to swap with. + */ constexpr void swap(Optional& other) noexcept { @@ -895,6 +1105,11 @@ class Optional { } }; +/** Swap two Optional references. + + @param a First optional reference. + @param b Second optional reference. +*/ template constexpr void swap(Optional& a, Optional& b) noexcept diff --git a/include/mrdocs/ADT/Overload.hpp b/include/mrdocs/ADT/Overload.hpp index a94c6a1eac..f7a979c2cf 100644 --- a/include/mrdocs/ADT/Overload.hpp +++ b/include/mrdocs/ADT/Overload.hpp @@ -40,7 +40,7 @@ namespace mrdocs { auto a = f(21); // calls int overload auto b = f(std::string("hello")); // calls string overload @endcode - */ +*/ template struct Overload : Ts... { using Ts::operator()...; @@ -48,7 +48,7 @@ struct Overload : Ts... { /** Constructs an Overload from the given callables. @param xs The callables to store. - */ + */ constexpr explicit Overload(Ts... xs) noexcept((std::is_nothrow_move_constructible_v && ...)) : Ts(std::move(xs))... {} @@ -58,7 +58,7 @@ struct Overload : Ts... { Allows writing Overload{lambda1, lambda2, ...} without specifying template parameters. - */ +*/ template Overload(Ts...) -> Overload; @@ -78,7 +78,7 @@ Overload(Ts...) -> Overload; ); @endcode - */ +*/ template [[nodiscard]] constexpr auto makeOverload(Ts&&... xs) noexcept((std::is_nothrow_constructible_v, Ts&&> && ...)) @@ -105,7 +105,7 @@ template [](const std::string& s) { return s.size(); } ); @endcode - */ +*/ template constexpr decltype(auto) match(Variant&& v, Ts&&... xs) { @@ -138,7 +138,7 @@ constexpr decltype(auto) match(Variant&& v, Ts&&... xs) [](std::size_t i, double d) { return d + i; }, [](std::size_t i, const std::string& s) { return s.size() + i; }); @endcode - */ +*/ template constexpr decltype(auto) visitIndexed(Variant&& v, Ts&&... xs) { @@ -169,14 +169,14 @@ constexpr decltype(auto) visitIndexed(Variant&& v, Ts&&... xs) }); auto r = fact(10); @endcode - */ +*/ template class YCombinator { public: /** Constructs a YCombinator from the given callable. @param f The callable to store. - */ + */ constexpr explicit YCombinator(F f) noexcept(std::is_nothrow_move_constructible_v) : f_(std::move(f)) {} @@ -185,7 +185,7 @@ class YCombinator { @param args The arguments to forward to the callable after the self reference. @return Whatever the callable returns. - */ + */ template constexpr decltype(auto) operator()(Args&&... args) & { @@ -193,7 +193,10 @@ class YCombinator { } /** Const lvalue overload of operator(). - */ + + @param args The arguments to forward to the callable after the self reference. + @return Whatever the callable returns. + */ template constexpr decltype(auto) operator()(Args&&... args) const & { @@ -201,7 +204,10 @@ class YCombinator { } /** Rvalue overload of operator(). - */ + + @param args The arguments to forward to the callable after the self reference. + @return Whatever the callable returns. + */ template constexpr decltype(auto) operator()(Args&&... args) && { @@ -209,7 +215,10 @@ class YCombinator { } /** Const rvalue overload of operator(). - */ + + @param args The arguments to forward to the callable after the self reference. + @return Whatever the callable returns. + */ template constexpr decltype(auto) operator()(Args&&... args) const && { @@ -232,7 +241,7 @@ class YCombinator { [](auto self, int n) -> int { return n <= 1 ? n : self(n - 1) + self(n - 2); }); - */ +*/ template [[nodiscard]] constexpr auto yCombinator(F&& f) noexcept(std::is_nothrow_constructible_v, F&&>) diff --git a/include/mrdocs/ADT/Polymorphic.hpp b/include/mrdocs/ADT/Polymorphic.hpp index e9be2396b1..747f9ff25b 100644 --- a/include/mrdocs/ADT/Polymorphic.hpp +++ b/include/mrdocs/ADT/Polymorphic.hpp @@ -81,14 +81,18 @@ class Polymorphic { // {} public: + /// Base value type. using value_type = T; + /// Mutable pointer to the held object. using pointer = T*; + /// Const pointer to the held object. using const_pointer = T const*; /// Default constructs the value type (never null via public API). /// explicit constexpr Polymorphic() : Polymorphic(std::in_place_type) {} - /** Forwarding constructor from a derived U. */ + /** Forwarding constructor from a derived U. + */ template constexpr explicit Polymorphic(U&& u) requires (!std::same_as>) && @@ -99,22 +103,35 @@ class Polymorphic { /** In-place constructor for a specific derived U. @param ts Arguments to forward to U's constructor. - */ + */ template explicit constexpr Polymorphic(std::in_place_type_t, Ts&&... ts) requires std::same_as, U> && std::constructible_from && std::copy_constructible && std::derived_from - : WB(new Wrapper(std::forward(ts)...)) {} + : WB(new Wrapper(std::forward(ts)...)) + {} + /** Copy constructor. + @param V Source object. + */ constexpr Polymorphic(Polymorphic const& V) : WB(V.WB ? V.WB->clone() : nullptr) {} + /** Move constructor. + @param V Source object (emptied on return). + */ constexpr Polymorphic(Polymorphic&& V) noexcept : WB(std::exchange(V.WB, nullptr)) {} + /** Destructor. + */ constexpr ~Polymorphic() { delete WB; } + /** Copy assignment. + @param V Source object. + @return *this. + */ constexpr Polymorphic& operator=(Polymorphic const& V) { if (this != &V) { Polymorphic Temp(V); @@ -123,6 +140,10 @@ class Polymorphic { return *this; } + /** Move assignment. + @param V Source object (emptied on return). + @return *this. + */ constexpr Polymorphic& operator=(Polymorphic&& V) noexcept { if (this != &V) { delete WB; @@ -131,26 +152,41 @@ class Polymorphic { return *this; } + /** Pointer-like access to the held object. + @return Pointer to the contained value. + */ [[nodiscard]] constexpr pointer operator->() noexcept { MRDOCS_ASSERT(WB != nullptr); return &WB->getValue(); } + /** Pointer-like access to the held object (const). + @return Pointer to the contained value. + */ [[nodiscard]] constexpr const_pointer operator->() const noexcept { MRDOCS_ASSERT(WB != nullptr); return &WB->getValue(); } + /** Dereference to the held object. + @return Reference to the contained value. + */ [[nodiscard]] constexpr T& operator*() noexcept { MRDOCS_ASSERT(WB != nullptr); return WB->getValue(); } + /** Dereference to the held object (const). + @return Const reference to the contained value. + */ [[nodiscard]] constexpr T const& operator*() const noexcept { MRDOCS_ASSERT(WB != nullptr); return WB->getValue(); } + /** Return true if the object has been moved-from and is disengaged. + @return `true` when empty. + */ constexpr bool valueless_after_move() const noexcept { @@ -224,7 +260,7 @@ CompareDerived(Base const& lhs, Base const& rhs) @param lhs The first Polymorphic to compare. @param rhs The second Polymorphic to compare. @return true if the two Polymorphic objects are equal, otherwise false. - */ +*/ template requires detail::CanVisitCompare auto @@ -235,6 +271,9 @@ CompareDerived(Polymorphic const& lhs, Polymorphic const& rhs) return CompareDerived(*lhs, *rhs); } +/** Three-way comparison of two polymorphic objects. + @return strong_ordering comparing held objects. +*/ template requires detail::CanVisitCompare auto @@ -243,6 +282,9 @@ operator<=>(Polymorphic const& lhs, Polymorphic const& rhs) return CompareDerived(lhs, rhs); } +/** Equality comparison of two polymorphic objects. + @return true when objects compare equal. +*/ template requires detail::CanVisitCompare bool @@ -260,12 +302,21 @@ operator==(Polymorphic const& lhs, Polymorphic const& rhs) template struct nullable_traits> { + /** Return true if the polymorphic value is disengaged. + + @param v Value to test. + @return `true` when @p v does not hold an object. + */ static constexpr bool is_null(Polymorphic const& v) noexcept { return v.valueless_after_move(); } + /** Return a null polymorphic instance. + + @return Disengaged Polymorphic. + */ static constexpr Polymorphic null() noexcept { @@ -273,6 +324,10 @@ struct nullable_traits> return Polymorphic(typename Polymorphic::_null_t{0}); } + /** Reset the polymorphic value to null. + + @param v Value to clear. + */ static constexpr void make_null(Polymorphic& v) noexcept { @@ -285,6 +340,8 @@ struct nullable_traits> // isa(p) //------------------------------------------------------------------------------ +/** Return true if the polymorphic object holds a value of type To. +*/ template requires ( std::derived_from, std::remove_cvref_t> ) [[nodiscard]] inline bool @@ -295,6 +352,8 @@ isa(const Polymorphic& p) noexcept return dynamic_cast(std::addressof(*p)) != nullptr; } +/** Return true if pointer is non-null and referent is of type To. +*/ template requires ( std::derived_from, std::remove_cvref_t> ) [[nodiscard]] inline bool @@ -307,6 +366,9 @@ isa_or_null(const Polymorphic* pp) noexcept // dyn_cast(p) → pointer (nullptr if not) //------------------------------------------------------------------------------ +/** Dynamic cast returning pointer or nullptr. + @return Pointer to To if the dynamic cast succeeds, otherwise nullptr. +*/ template requires ( std::derived_from, std::remove_cvref_t> ) [[nodiscard]] inline auto @@ -318,6 +380,9 @@ dyn_cast(Polymorphic& p) noexcept return dynamic_cast(std::addressof(*p)); } +/** Dynamic cast returning pointer or nullptr (const overload). + @return Pointer to To if the dynamic cast succeeds, otherwise nullptr. +*/ template requires ( std::derived_from, std::remove_cvref_t> ) [[nodiscard]] inline auto @@ -329,6 +394,9 @@ dyn_cast(const Polymorphic& p) noexcept return dynamic_cast(std::addressof(*p)); } +/** Dynamic cast if pointer is non-null and engaged, else nullptr. + @return Pointer to To when the cast succeeds, otherwise nullptr. +*/ template requires ( std::derived_from, std::remove_cvref_t> ) [[nodiscard]] inline auto @@ -338,6 +406,9 @@ dyn_cast_or_null(Polymorphic* pp) noexcept return (pp && !pp->valueless_after_move()) ? dyn_cast(*pp) : nullptr; } +/** Dynamic cast if pointer is non-null and engaged, else nullptr (const). + @return Pointer to To when the cast succeeds, otherwise nullptr. +*/ template requires ( std::derived_from, std::remove_cvref_t> ) [[nodiscard]] inline auto @@ -351,6 +422,9 @@ dyn_cast_or_null(const Polymorphic* pp) noexcept // cast(p) → reference (asserts on failure) //------------------------------------------------------------------------------ +/** Dynamic cast returning reference; asserts on failure. + @return Reference to the contained object cast to To. +*/ template requires ( std::derived_from, std::remove_cvref_t> ) [[nodiscard]] inline auto @@ -363,6 +437,9 @@ cast(Polymorphic& p) return *r; } +/** Dynamic cast returning const reference; asserts on failure. + @return Const reference to the contained object cast to To. +*/ template requires ( std::derived_from, std::remove_cvref_t> ) [[nodiscard]] inline auto @@ -379,6 +456,9 @@ cast(const Polymorphic& p) // cast_or_null(pp) → pointer (asserts on bad non-null) //------------------------------------------------------------------------------ +/** Dynamic cast pointer; returns nullptr when pp is null. + @return Pointer to To when the cast succeeds, otherwise nullptr. +*/ template requires ( std::derived_from, std::remove_cvref_t> ) [[nodiscard]] inline auto @@ -391,6 +471,9 @@ cast_or_null(Polymorphic* pp) return r; } +/** Dynamic cast pointer; returns nullptr when pp is null (const). + @return Pointer to To when the cast succeeds, otherwise nullptr. +*/ template requires ( std::derived_from, std::remove_cvref_t> ) [[nodiscard]] inline auto diff --git a/include/mrdocs/ADT/UnorderedStringMap.hpp b/include/mrdocs/ADT/UnorderedStringMap.hpp index e9abc4bfe5..acc010aec1 100644 --- a/include/mrdocs/ADT/UnorderedStringMap.hpp +++ b/include/mrdocs/ADT/UnorderedStringMap.hpp @@ -17,18 +17,37 @@ namespace mrdocs { +/** Transparent hash functor for string-like keys. +*/ struct StringHash { + /** Underlying hash implementation. + */ using hash_type = std::hash; + /** Marker for heterogeneous lookup. + */ using is_transparent = void; + /** Hash C-string input. + @return Hash value of the string. + */ std::size_t operator()(const char* str) const { return hash_type{}(str); } + /** Hash string_view input. + @return Hash value of the string view. + */ std::size_t operator()(std::string_view str) const { return hash_type{}(str); } + /** Hash std::string input. + @return Hash value of the string. + */ std::size_t operator()(std::string const& str) const { return hash_type{}(str); } }; +/** unordered_map keyed by std::string with transparent hashing. +*/ template using UnorderedStringMap = std::unordered_map>; +/** unordered_multimap keyed by std::string with transparent hashing. +*/ template using UnorderedStringMultiMap = std::unordered_multimap>; diff --git a/include/mrdocs/Config.hpp b/include/mrdocs/Config.hpp index 26e00d5717..e688e110f1 100644 --- a/include/mrdocs/Config.hpp +++ b/include/mrdocs/Config.hpp @@ -61,11 +61,14 @@ class MRDOCS_DECL Config { protected: + /** Construct an empty configuration interface. + Implementations populate settings in derived classes. + */ Config() noexcept; public: /** Settings values used to generate the Corpus and Docs - */ + */ struct Settings : public PublicSettings { /** @brief Loads the public configuration settings from the specified YAML file. @@ -78,7 +81,7 @@ class MRDOCS_DECL * @param configYaml A string view representing the YAML file containing the configuration settings. * @param dirs A constant reference to a PublicSettings::ReferenceDirectories object containing the reference directories. * @return An Expected object containing a Config::Settings object if the YAML file was successfully parsed and the configuration settings were loaded, or an error otherwise. - */ + */ static Expected load( @@ -97,7 +100,7 @@ class MRDOCS_DECL @param dirs A constant reference to a PublicSettings::ReferenceDirectories object containing the reference directories. @return An Expected object containing void if the file was successfully read and the configuration settings were loaded, or an error otherwise. - */ + */ static Expected load_file( Config::Settings &s, @@ -105,7 +108,7 @@ class MRDOCS_DECL ReferenceDirectories const& dirs); /** @copydoc PublicSettings::normalize - */ + */ Expected normalize(ReferenceDirectories const& dirs); @@ -175,9 +178,12 @@ class MRDOCS_DECL std::string cwdDir = "."; /** A string holding the complete configuration YAML. - */ + */ std::string configYaml; + /** Provide pointer-like access to settings fields. + @return Pointer to this Settings instance. + */ constexpr Settings const* operator->() const noexcept { @@ -203,7 +209,7 @@ class MRDOCS_DECL threadPool() const noexcept = 0; /** Return the settings used to generate the Corpus and Docs. - */ + */ virtual Settings const& settings() const noexcept = 0; /** Return a DOM object representing the configuration keys. @@ -211,7 +217,7 @@ class MRDOCS_DECL The object is invalidated when the configuration is moved or destroyed. - */ + */ virtual dom::Object const& object() const = 0; /// @copydoc settings() diff --git a/include/mrdocs/Config/ReferenceDirectories.hpp b/include/mrdocs/Config/ReferenceDirectories.hpp index b2616cb79e..2f117cf6af 100644 --- a/include/mrdocs/Config/ReferenceDirectories.hpp +++ b/include/mrdocs/Config/ReferenceDirectories.hpp @@ -24,10 +24,14 @@ namespace mrdocs { All other reference directories come directly from the configuration file. - */ +*/ struct ReferenceDirectories { + /** Absolute path to the current working directory. + */ std::string cwd; + /** Absolute path to the MrDocs repository root. + */ std::string mrdocsRoot; }; diff --git a/include/mrdocs/Corpus.hpp b/include/mrdocs/Corpus.hpp index d323751df3..1d09ef486b 100644 --- a/include/mrdocs/Corpus.hpp +++ b/include/mrdocs/Corpus.hpp @@ -31,6 +31,8 @@ class MRDOCS_VISIBLE Corpus { protected: + /** Create a corpus using the provided configuration. + */ explicit Corpus( Config const& config_) noexcept @@ -183,7 +185,7 @@ class MRDOCS_VISIBLE } /** Options to traverse the members of an Symbol. - */ + */ struct TraverseOptions { /// Whether to traverse in a stable order @@ -338,25 +340,18 @@ class MRDOCS_VISIBLE traverse({}, I, std::forward(f), std::forward(args)...); } - /** Return the fully qualified name of the specified Symbol. - - This function returns the fully qualified name - of the specified Symbol `I` as a string. - - The `Symbol` parents are traversed to construct - the fully qualified name which is stored in - the string `temp`. - + /** Populate `temp` with the fully qualified name of `I`. @param I The Symbol to get the qualified name for. @param temp The string to store the result in. - @return A reference to the string `temp`. - */ + */ virtual void qualifiedName( Symbol const& I, std::string& temp) const = 0; + /** Return the fully qualified name of `I`. + */ std::string qualifiedName(Symbol const& I) const { @@ -365,25 +360,13 @@ class MRDOCS_VISIBLE return temp; } - /** Return a qualified name from the specified context. - - This function returns the qualified name - of the specified Symbol `I` from the context - specified by the SymbolID `context`. - - If the context is a parent of `I`, the - qualified name is constructed relative to - the context. For instance, if `I` is `A::B::C::D` - and context is `A::B`, the result is `C::D`. - - If the context is not a parent of `I`, the - qualified name is constructed relative to - the global namespace with the prefix `::`. - - @param I The Symbol to get the qualified name for. - @param context The context to get the qualified name from. - @param result The string to store the result in. - */ + /** Populate `result` with a qualified name relative to `context`. + If `context` contains `I`, the name is relative; otherwise it + is computed from the global namespace. + @param I The Symbol to name. + @param context The context used to qualify the name. + @param result Output string receiving the name. + */ virtual void qualifiedName( @@ -391,6 +374,8 @@ class MRDOCS_VISIBLE SymbolID const& context, std::string& result) const = 0; + /** Return the qualified name of `I` relative to `context`. + */ std::string qualifiedName(Symbol const& I, SymbolID const& context) const { @@ -430,18 +415,43 @@ class Corpus::iterator Symbol const*(*next_)(Corpus const*, Symbol const*); public: + /** Value type yielded by the iterator. + */ using value_type = const Symbol; + /** Unsigned size type. + */ using size_type = std::size_t; + /** Signed difference type. + */ using difference_type = std::ptrdiff_t; + /** Pointer to value. + */ using pointer = value_type*; + /** Reference to value. + */ using reference = value_type&; + /** Pointer to const value. + */ using const_pointer = value_type const*; + /** Reference to const value. + */ using const_reference = value_type const&; + /** Default constructor. + */ iterator() = default; + /** Copy constructor. + */ iterator(iterator const&) = default; + /** Copy assignment. + */ iterator& operator=(iterator const&) = default; + /** Construct an iterator from corpus storage pointers. + @param corpus The parent corpus. + @param val The current symbol. + @param next Function that advances to the next symbol. + */ iterator( Corpus const* corpus, Symbol const* val, @@ -452,6 +462,9 @@ class Corpus::iterator { } + /** Pre-increment. + @return *this advanced to next element. + */ iterator& operator++() noexcept { MRDOCS_ASSERT(val_); @@ -459,31 +472,46 @@ class Corpus::iterator return *this; } - iterator operator++(int) noexcept + /** Post-increment. + @param dummy Unused postfix increment discriminator. + @return Iterator prior to increment. + */ + iterator operator++(int dummy) noexcept { + (void)dummy; MRDOCS_ASSERT(val_); auto temp = *this; val_ = next_(corpus_, val_); return temp; } + /** Pointer-like access to the current symbol. + @return Pointer to the current Symbol. + */ const_pointer operator->() const noexcept { MRDOCS_ASSERT(val_); return val_; } + /** Dereference to the current symbol. + @return Reference to the current Symbol. + */ const_reference operator*() const noexcept { MRDOCS_ASSERT(val_); return *val_; } + /** Equality comparison. + */ bool operator==(iterator const& other) const noexcept { return val_ == other.val_; } + /** Inequality comparison. + */ bool operator!=(iterator const& other) const noexcept { return val_ != other.val_; @@ -491,7 +519,7 @@ class Corpus::iterator }; /** Return a list of the parent symbols of the specified Symbol. - */ +*/ MRDOCS_DECL std::vector getParents(Corpus const& C, Symbol const& I); diff --git a/include/mrdocs/Dom/Array.hpp b/include/mrdocs/Dom/Array.hpp index ef394c488a..6292a19951 100644 --- a/include/mrdocs/Dom/Array.hpp +++ b/include/mrdocs/Dom/Array.hpp @@ -208,11 +208,11 @@ class MRDOCS_DECL value_type back() const; /** Return an iterator to the beginning of the range of elements. - */ + */ iterator begin() const; /** Return an iterator to the end of the range of elements. - */ + */ iterator end() const; /** Append an element to the end of the array. @@ -268,13 +268,13 @@ class MRDOCS_DECL } /** Compare two arrays for equality. - */ + */ friend bool operator==(Array const&, Array const&) noexcept; /** Compare two arrays for precedence. - */ + */ friend std::strong_ordering operator<=>(Array const&, Array const&) noexcept; @@ -283,7 +283,7 @@ class MRDOCS_DECL */ friend std::string - toString(Array const&); + toString(Array const& arr); /** Return a new array using a custom implementation. @@ -336,7 +336,7 @@ class MRDOCS_DECL /** Set the i-th element, without bounds checking. */ - virtual void set(size_type, Value); + virtual void set(size_type index, Value value); /** Append an element to the end of the array. @@ -370,13 +370,31 @@ class MRDOCS_DECL /// @copydoc Array::storage_type using storage_type = Array::storage_type; + /** Create an empty array implementation. + */ DefaultArrayImpl(); + /** Create an array populated with the given elements. + @param elements Initial contents to take ownership of. + */ explicit DefaultArrayImpl( storage_type elements) noexcept; + /** Return the number of stored elements. + */ size_type size() const override; + /** Retrieve an element at the specified index. + @param i Index of the element to fetch. + */ value_type get(size_type i) const override; + /** Replace the element at the specified index. + @param i Index to update. + @param v New value to store. + */ void set(size_type i, Value v) override; + /** Append a value to the array. + */ void emplace_back(value_type value) override; + /** Return the type key string for this array. + */ char const* type_key() const noexcept override; private: diff --git a/include/mrdocs/Dom/Function.hpp b/include/mrdocs/Dom/Function.hpp index 49db24d6c9..cee2a26581 100644 --- a/include/mrdocs/Dom/Function.hpp +++ b/include/mrdocs/Dom/Function.hpp @@ -29,53 +29,82 @@ class Value; // function_traits // //------------------------------------------------ + +/** Helper traits to extract return and argument types from callables. +*/ template struct function_traits; +/** Traits specialization for free functions. +*/ template struct function_traits { + /// Result type of the callable. using return_type = R; + /// Tuple of argument types accepted by the callable. using args_type = std::tuple; }; +/** Traits specialization for member functions. +*/ template struct function_traits { + /// Result type of the callable. using return_type = R; + /// Tuple of argument types accepted by the callable. using args_type = std::tuple; }; +/** Traits specialization for const member functions. +*/ template struct function_traits { + /// Result type of the callable. using return_type = R; + /// Tuple of argument types accepted by the callable. using args_type = std::tuple; }; +/** Traits specialization for volatile member functions. +*/ template struct function_traits { + /// Result type of the callable. using return_type = R; + /// Tuple of argument types accepted by the callable. using args_type = std::tuple; }; +/** Traits specialization for const volatile member functions. +*/ template struct function_traits { + /// Result type of the callable. using return_type = R; + /// Tuple of argument types accepted by the callable. using args_type = std::tuple; }; // (missing permutations of ref-qualifier and cv-qualifier) +/** Traits specialization for function pointers. +*/ template struct function_traits { + /// Result type of the callable. using return_type = R; + /// Tuple of argument types accepted by the callable. using args_type = std::tuple; }; +/** Traits specialization for functors/lambdas. +*/ template requires requires { &F::operator(); } struct function_traits @@ -83,28 +112,38 @@ struct function_traits { }; +/** Concept true when function_traits is defined for F. +*/ template concept has_function_traits = requires { typename function_traits::return_type; typename function_traits::args_type; }; +/** Concept true when F returns a dom::Value or void. +*/ template concept has_invoke_result_convertible_to_dom_value = std::convertible_to::return_type, Value> || std::same_as::return_type, void>; +/** Concept true when F returns Expected or Expected. +*/ template concept has_invoke_expected_result_convertible_to_dom_value = detail::isExpected::return_type> && (std::convertible_to::return_type::value_type, Value> || std::same_as::return_type::value_type, void>); +/** Concept enabling default function wrapper for supported return types. +*/ template concept has_invoke_result_for_default_function_impl = has_invoke_result_convertible_to_dom_value || has_invoke_expected_result_convertible_to_dom_value; +/** Concept requiring all arguments be convertible to dom::Value. +*/ template concept has_function_args_for_default_function_impl = // All arguments are convertible to dom::Value @@ -117,12 +156,16 @@ concept has_function_args_for_default_function_impl = Value> && ...); }(std::make_index_sequence::args_type>>())); +/** Concept combining argument and return constraints for default wrapper. +*/ template concept has_function_traits_for_default_function_impl = has_invoke_result_for_default_function_impl && has_function_args_for_default_function_impl; +/** Concept selecting callables convertible to dom::Value. +*/ template concept function_traits_convertible_to_value = has_function_traits && @@ -134,11 +177,15 @@ concept function_traits_convertible_to_value = // //------------------------------------------------ +/** Value-semantic wrapper over a callable exposed to the DOM layer. +*/ class FunctionImpl; template class DefaultFunctionImpl; +/** Value-semantic wrapper over a callable exposed to the DOM layer. +*/ class MRDOCS_DECL Function { @@ -186,6 +233,9 @@ class MRDOCS_DECL */ Function(Function const&) noexcept; + /** Construct a Function from any supported callable. + @param f Callable to wrap. + */ template requires function_traits_convertible_to_value> @@ -281,6 +331,8 @@ class MRDOCS_DECL // //------------------------------------------------ +/** Abstract base for function implementations. +*/ class MRDOCS_DECL FunctionImpl { @@ -315,26 +367,39 @@ newFunction(Args&&... args) // //------------------------------------------------ +/** Function implementation that wraps a fixed-arity callable. +*/ template class DefaultFunctionImpl : public FunctionImpl { F f_; public: + /** Result type produced by the callable. + */ using return_type = typename function_traits::return_type; + /** Argument tuple type accepted by the callable. + */ using args_type = typename function_traits::args_type; + /** Construct from any callable convertible to `F`. + @param u Callable to wrap. + */ template DefaultFunctionImpl(U&& u) : f_(std::forward(u)) { } + /** @copydoc FunctionImpl::type_key + */ char const* type_key() const noexcept override { return "Function"; } + /** Invoke the wrapped callable with the given arguments. + */ Expected call(Array const& args) const override; @@ -345,6 +410,10 @@ class DefaultFunctionImpl : public FunctionImpl std::index_sequence) const; }; +/** Create a Function from a fixed-arity invocable. + @param f Callable to wrap. + @return Function that forwards arguments to `f`. +*/ template Function makeInvocable(F&& f) { @@ -352,30 +421,47 @@ Function makeInvocable(F&& f) std::forward(f)); } +/** Function implementation that forwards the entire Array to a callable. +*/ template class VariadicFunctionImpl : public FunctionImpl { F f_; public: + /** Result type produced by the callable. + */ using return_type = typename function_traits::return_type; + /** Argument tuple type accepted by the callable. + */ using args_type = typename function_traits::args_type; + /** Construct from any callable convertible to `F`. + @param u Callable to wrap. + */ template VariadicFunctionImpl(U&& u) : f_(std::forward(u)) { } + /** @copydoc FunctionImpl::type_key + */ char const* type_key() const noexcept override { return "VariadicFunctionImpl"; } + /** Invoke the wrapped callable with the full argument array. + */ Expected call(Array const& args) const override; }; +/** Create a Function that receives the argument Array directly. + @param f Callable invoked with the argument array. + @return Function wrapper for the callable. +*/ template requires std::invocable Function makeVariadicInvocable(F&& f) diff --git a/include/mrdocs/Dom/LazyArray.hpp b/include/mrdocs/Dom/LazyArray.hpp index dd7ac690d1..88d8f9039c 100644 --- a/include/mrdocs/Dom/LazyArray.hpp +++ b/include/mrdocs/Dom/LazyArray.hpp @@ -21,6 +21,12 @@ namespace mrdocs { namespace dom { +/** Internal helpers for lazy DOM arrays. + + These utilities let generators expose large result sets without eagerly + materializing every element, deferring lookups until the DOM is traversed + during rendering or serialization. +*/ namespace detail { struct no_context_tag {}; struct no_size_tag {}; @@ -79,6 +85,8 @@ class LazyArrayImpl : public ArrayImpl MRDOCS_NO_UNIQUE_ADDRESS Context context_; public: + /** Construct from a range of values. + */ explicit LazyArrayImpl(R const& arr) : begin_(std::ranges::begin(arr)) @@ -90,6 +98,10 @@ class LazyArrayImpl : public ArrayImpl } } + /** Construct from a range and a conversion context. + @param arr Range to wrap lazily. + @param ctx Context used to convert elements. + */ explicit LazyArrayImpl(R const& arr, Context const& ctx) : begin_(std::ranges::begin(arr)) @@ -102,6 +114,8 @@ class LazyArrayImpl : public ArrayImpl } } + /** Virtual destructor. + */ ~LazyArrayImpl() override = default; /// @copydoc ObjectImpl::type_key @@ -111,6 +125,8 @@ class LazyArrayImpl : public ArrayImpl return "LazyArray"; } + /** Return the number of elements, computing it lazily if needed. + */ std::size_t size() const noexcept override { @@ -124,6 +140,9 @@ class LazyArrayImpl : public ArrayImpl } } + /** Retrieve the element at index `i`, or nil if out of range. + @param i Index of the element. + */ dom::Value get(std::size_t i) const override { @@ -152,7 +171,7 @@ class LazyArrayImpl : public ArrayImpl @param arr The underlying range of elements. @return A new dom::Array whose elements are the result of converting each element in the underlying range to a dom::Value. - */ +*/ template requires HasStandaloneValueFrom> Array diff --git a/include/mrdocs/Dom/LazyObject.hpp b/include/mrdocs/Dom/LazyObject.hpp index 65767bb574..6554e7b099 100644 --- a/include/mrdocs/Dom/LazyObject.hpp +++ b/include/mrdocs/Dom/LazyObject.hpp @@ -76,7 +76,7 @@ struct LazyObjectMapTag { }; } @endcode - */ +*/ template concept HasLazyObjectMapWithoutContext = requires( detail::ArchetypalIO& io, @@ -95,7 +95,7 @@ concept HasLazyObjectMapWithoutContext = requires( template void tag_invoke( LazyObjectMapTag, IO&, T, Context const& ); @endcode - */ +*/ template concept HasLazyObjectMapWithContext = requires( detail::ArchetypalIO& io, @@ -167,18 +167,27 @@ class LazyObjectImpl : public ObjectImpl MRDOCS_NO_UNIQUE_ADDRESS Context context_{}; public: + /** Wrap an object using the default lazy mapping. + @param obj Object providing the data. + */ explicit LazyObjectImpl(T const& obj) requires HasLazyObjectMapWithoutContext : underlying_(&obj) , context_{} {} + /** Wrap an object using a custom mapping context. + @param obj Object providing the data. + @param context Context that guides the mapping. + */ explicit LazyObjectImpl(T const& obj, Context const& context) requires HasLazyObjectMapWithContext : underlying_(&obj) , context_(context) {} + /** Virtual destructor. + */ ~LazyObjectImpl() override = default; /// @copydoc ObjectImpl::type_key diff --git a/include/mrdocs/Dom/Object.hpp b/include/mrdocs/Dom/Object.hpp index a648a601cf..ee5b606bc2 100644 --- a/include/mrdocs/Dom/Object.hpp +++ b/include/mrdocs/Dom/Object.hpp @@ -18,7 +18,6 @@ #include #include - namespace mrdocs { namespace dom { @@ -258,7 +257,7 @@ class MRDOCS_DECL @return `true` if the visitor returned `true` for all elements, otherwise `false`. - */ + */ template requires std::invocable && @@ -283,7 +282,7 @@ class MRDOCS_DECL return an error for any element, otherwise `E`. - */ + */ template requires std::invocable && @@ -294,7 +293,7 @@ class MRDOCS_DECL /** Invoke the visitor for each key/value pair @param fn The visitor function. - */ + */ template requires std::invocable && @@ -316,13 +315,13 @@ class MRDOCS_DECL } /** Compare two objects for equality. - */ + */ friend bool operator==(Object const& a, Object const& b) noexcept; /** Compare two objects for precedence. - */ + */ friend std::strong_ordering operator<=>(Object const& a, Object const& b) noexcept @@ -338,7 +337,7 @@ class MRDOCS_DECL /** Return a diagnostic string. */ - friend std::string toString(Object const&); + friend std::string toString(Object const& object); }; //------------------------------------------------ @@ -404,7 +403,7 @@ class MRDOCS_DECL visit(std::function fn) const = 0; /** Return the number of properties in the object. - */ + */ virtual std::size_t size() const = 0; @@ -413,7 +412,7 @@ class MRDOCS_DECL @param key The key to check for existence. @return `true` if the key exists, otherwise `false`. - */ + */ virtual bool exists(std::string_view key) const; @@ -448,14 +447,37 @@ class MRDOCS_DECL DefaultObjectImpl : public ObjectImpl { public: + /** Create an empty object implementation. + */ DefaultObjectImpl() noexcept; + /** Create an object pre-populated with entries. + @param entries Key/value storage to take ownership of. + */ explicit DefaultObjectImpl( storage_type entries) noexcept; + /** Return number of elements stored. + */ std::size_t size() const override; - Value get(std::string_view) const override; - void set(String, Value) override; - bool visit(std::function) const override; + /** Retrieve a value by key. + @param key Key to search for. + @return Stored value or undefined if absent. + */ + Value get(std::string_view key) const override; + /** Set a value by key. + @param key Key to set. + @param value New value. + */ + void set(String key, Value value) override; + /** Visit each key/value pair until the visitor returns false. + @param visitor Callback receiving key and value. + @return False if visitor requested stop, otherwise true. + */ + bool visit(std::function visitor) const override; + /** Check whether a key exists in the object. + @param key Key to test. + @return True if the key exists. + */ bool exists(std::string_view key) const override; private: diff --git a/include/mrdocs/Dom/String.hpp b/include/mrdocs/Dom/String.hpp index 60d8601da9..87d81594c8 100644 --- a/include/mrdocs/Dom/String.hpp +++ b/include/mrdocs/Dom/String.hpp @@ -27,6 +27,8 @@ concept StringLikeTy = ! std::is_same_v && std::convertible_to; +/** UTF-8 string value used by the DOM. +*/ class MRDOCS_DECL String final { diff --git a/include/mrdocs/Dom/Value.hpp b/include/mrdocs/Dom/Value.hpp index 06d22cc679..4ac0431876 100644 --- a/include/mrdocs/Dom/Value.hpp +++ b/include/mrdocs/Dom/Value.hpp @@ -46,10 +46,15 @@ namespace mrdocs { @return The safe string wrapper @see https://handlebarsjs.com/api-reference/utilities.html#handlebars-safestring-string - */ +*/ dom::Value safeString(std::string_view str); +/** Mark an existing string-like value as safe to emit without escaping. + + This overload is useful when a helper already produced a `dom::Value` + and only needs to flip the safe-string flag before it is rendered. +*/ dom::Value safeString(dom::Value const& str); @@ -109,11 +114,23 @@ class MRDOCS_DECL union { + /** Boolean payload when the value kind is `Boolean`. + */ bool b_{false}; + /** Integer payload when the value kind is `Integer`. + */ std::int64_t i_; + /** UTF-8 string or safe-string payload. + */ String str_; + /** Array payload; shared with lazy arrays. + */ Array arr_; + /** Object payload; shared with lazy objects. + */ Object obj_; + /** Callable payload used by template helpers. + */ Function fn_; }; @@ -122,18 +139,52 @@ class MRDOCS_DECL friend Value mrdocs::safeString(std::string_view str); public: + /** Destroy the contained value, releasing owned storage. + */ ~Value(); + + /** Construct an undefined value. + */ Value() noexcept; + + /** Copy-construct from another value. + */ Value(Value const& other); + + /** Move-construct from another value, leaving it undefined. + */ Value(Value&& other) noexcept; + + /** Construct an empty value with the specified kind. + */ Value(dom::Kind kind) noexcept; + + /** Construct a null value. + */ Value(std::nullptr_t v) noexcept; + + /** Construct an integer value. + */ Value(std::int64_t v) noexcept; + + /** Construct a string or safe-string value, taking ownership. + */ Value(String str) noexcept; + + /** Construct an array value, taking ownership of the elements. + */ Value(Array arr) noexcept; + + /** Construct an object value, taking ownership of the members. + */ Value(Object obj) noexcept; + + /** Construct a function value that can be invoked by templates. + */ Value(Function fn) noexcept; + /** Construct a function value from a callable object. + */ template requires function_traits_convertible_to_value @@ -141,6 +192,8 @@ class MRDOCS_DECL : Value(Function(f)) {} + /** Construct a boolean value. + */ template Boolean> Value(Boolean const& b) noexcept : kind_(Kind::Boolean) @@ -148,17 +201,25 @@ class MRDOCS_DECL { } + /** Construct an integer value from an integral type other than `bool` or `char`. + */ template requires (!std::same_as) && (!std::same_as) Value(T v) noexcept : Value(std::int64_t(v)) {} + /** Construct an integer value from a floating-point number by truncation. + */ template Value(T v) noexcept : Value(std::int64_t(v)) {} + /** Construct a single-character string value. + */ Value(char c) noexcept : Value(std::string_view(&c, 1)) {} + /** Construct a string value from a string literal. + */ template Value(char const(&sz)[N]) : Value(String(sz)) @@ -166,17 +227,23 @@ class MRDOCS_DECL } // VFALCO Should this be a literal? + /** Construct a string value from a C string. + */ Value(char const* s) : Value(String(s)) { } + /** Construct a string value from any `String`-convertible type. + */ template StringLike> Value(StringLike const& s) : Value(String(s)) { } + /** Construct from `std::optional`, using `Undefined` when empty. + */ template requires std::constructible_from Value(std::optional const& opt) @@ -184,6 +251,8 @@ class MRDOCS_DECL { } + /** Construct from `Optional`, using `Undefined` when empty. + */ template requires std::constructible_from Value(Optional const& opt) @@ -191,12 +260,19 @@ class MRDOCS_DECL { } + /** Construct an array value from raw storage. + */ Value(Array::storage_type elements) : Value(Array(std::move(elements))) { } + /** Copy-assign from another value, replacing the stored payload. + */ Value& operator=(Value const& other); + + /** Move-assign from another value, leaving it undefined. + */ Value& operator=(Value&& other) noexcept; /** Return the type key of the value. @@ -283,7 +359,7 @@ class MRDOCS_DECL @note Behaviour is undefined if `!isBoolean()` - */ + */ bool getBool() const noexcept { MRDOCS_ASSERT(isBoolean()); @@ -351,6 +427,8 @@ class MRDOCS_DECL dom::Value get(std::string_view key) const; + /** @copydoc get(std::string_view) + */ template S> dom::Value get(S const& key) const @@ -389,7 +467,7 @@ class MRDOCS_DECL @param key The key. @param value The value to set. - */ + */ void set(String const& key, Value const& value); @@ -418,7 +496,7 @@ class MRDOCS_DECL is returned. @param args The arguments to the function. - */ + */ template Value operator()(Args&&... args) const { @@ -437,7 +515,7 @@ class MRDOCS_DECL } /** Return the string. - */ + */ explicit operator std::string() const noexcept { @@ -475,7 +553,7 @@ class MRDOCS_DECL @note In JavaScript, this is equivalent to the `===` operator, which does not perform type conversions. - */ + */ friend bool operator==( @@ -483,7 +561,7 @@ class MRDOCS_DECL Value const& rhs) noexcept; /** Compare two values for inequality. - */ + */ friend std::strong_ordering operator<=>( @@ -513,7 +591,7 @@ class MRDOCS_DECL } /** Add or concatenate two values. - */ + */ friend dom::Value operator+(Value const& lhs, Value const& rhs); @@ -537,7 +615,7 @@ class MRDOCS_DECL /** Return the first dom::Value that is truthy, or the last one. This function is equivalent to the JavaScript `||` operator. - */ + */ friend dom::Value operator||(Value const& lhs, Value const& rhs); @@ -561,7 +639,7 @@ class MRDOCS_DECL /** Return the first dom::Value that is not truthy, or the last one. This function is equivalent to the JavaScript `&&` operator. - */ + */ friend dom::Value operator&&(Value const& lhs, Value const& rhs); @@ -591,6 +669,12 @@ class MRDOCS_DECL //------------------------------------------------ +/** JSON serialization helpers for DOM values. + + This namespace wraps the platform JSON encoder/decoder behavior we emulate + inside MrDocs so generators can round-trip DOM `Value` objects to text and + back with predictable spacing, escaping, and cyclic-detection rules. +*/ namespace JSON { /** Stringify a value as JSON @@ -604,7 +688,7 @@ namespace JSON @return A string containing valid JSON. @param value The value to stringify. - */ +*/ MRDOCS_DECL std::string stringify(dom::Value const& value); @@ -683,7 +767,7 @@ struct ValueFromTag { }; @code void tag_invoke( ValueFromTag, dom::Value&, T ); @endcode - */ +*/ template concept HasValueFromWithoutContext = requires( Value& v, @@ -701,7 +785,7 @@ concept HasValueFromWithoutContext = requires( @code void tag_invoke( ValueFromTag, dom::Value&, T, Context const& ); @endcode - */ +*/ template concept HasValueFromWithContext = requires( Value& v, @@ -733,7 +817,7 @@ concept HasValueFrom = conversion to @ref dom::Value that does not require a context or if @ref dom::Value has a constructor that can be used to convert `T` to a @ref dom::Value. - */ +*/ template concept HasStandaloneValueFrom = HasValueFromWithoutContext || @@ -932,6 +1016,10 @@ ValueFrom(T&& t, Context const& ctx) } // dom +/** Return a DOM string ensuring special characters are escaped. + @param str Source string view convertible type. + @return dom::Value containing the safe string. +*/ template SV> dom::Value safeString(SV const& str) { diff --git a/include/mrdocs/Generators.hpp b/include/mrdocs/Generators.hpp index 79657a5e00..8cbe406974 100644 --- a/include/mrdocs/Generators.hpp +++ b/include/mrdocs/Generators.hpp @@ -25,15 +25,23 @@ class MRDOCS_VISIBLE Generators { protected: + /// Construct an empty generator registry; only derived singletons create this. Generators() noexcept = default; public: + /// Pointer type for generator entries. using value_type = Generator const*; + /// Iterator over the registered generators. using iterator = value_type const*; + /// Constant iterator alias. using const_iterator = iterator; + /// Reference to a generator pointer. using reference = value_type const&; + /// Const reference to a generator pointer. using const_reference = value_type const&; + /// Number of registered generators. using size_type = std::size_t; + /// Signed distance type for iterator arithmetic. using difference_type = std::ptrdiff_t; /** Destructor. diff --git a/include/mrdocs/Metadata/DocComment.hpp b/include/mrdocs/Metadata/DocComment.hpp index 636d7c5487..d076ef035d 100644 --- a/include/mrdocs/Metadata/DocComment.hpp +++ b/include/mrdocs/Metadata/DocComment.hpp @@ -50,7 +50,7 @@ namespace mrdocs { Inline content elements contain other inlines but cannot contain blocks. - */ +*/ struct MRDOCS_DECL DocComment { /// The list of text blocks. std::vector> Document; @@ -67,7 +67,7 @@ struct MRDOCS_DECL DocComment { The results are concatenated in the order they appear in the source code. - */ + */ std::vector returns; /// The list of parameters. @@ -92,7 +92,7 @@ struct MRDOCS_DECL DocComment { These references are created with the \\relates command. - */ + */ std::vector relates; /** The list of "related" references. @@ -103,7 +103,7 @@ struct MRDOCS_DECL DocComment { They are calculated automatically by MrDocs and are rendered as Non-Member Functions. - */ + */ std::vector related; /** Constructor. @@ -133,6 +133,8 @@ struct MRDOCS_DECL DocComment { postconditions.empty(); } + /** Three-way comparison on the rendered block sequence. + */ auto operator<=>(DocComment const& other) const noexcept { if (auto const cmp = Document.size() <=> other.Document.size(); !std::is_eq(cmp)) @@ -149,7 +151,13 @@ struct MRDOCS_DECL DocComment { } return std::strong_ordering::equal; } + + /** Equality compares all stored blocks. + */ bool operator==(DocComment const&) const noexcept = default; + + /** Inequality is the negation of equality. + */ bool operator!=(DocComment const&) const noexcept; /** Append blocks from another DocComment to this. @@ -158,6 +166,8 @@ struct MRDOCS_DECL DocComment { append(DocComment&& other); }; +/** Append blocks from `other` into `I`, preserving order. +*/ inline void merge(DocComment& I, DocComment&& other) { @@ -174,11 +184,10 @@ void merge(DocComment& I, DocComment&& other) /** Map the @ref DocComment to a @ref dom::Object. - @param t The tag. @param io The output object. @param I The DocComment to map. @param domCorpus The DOM corpus, or nullptr. - */ +*/ template void tag_invoke( @@ -224,7 +233,7 @@ tag_invoke( } /** Return the @ref DocComment as a @ref dom::Value object. - */ +*/ inline void tag_invoke( @@ -237,7 +246,7 @@ tag_invoke( } /** Concept to check if a type represents a DocComment node. - */ +*/ template concept DocCommentNode = std::derived_from || std::derived_from; @@ -358,12 +367,18 @@ traverseImpl(Polymorphic& node, F&& func) } } +/** Types that can be traversed by DocComment helpers. +*/ template concept DocCommentNodeTraversable = DocCommentNode || std::same_as || (detail::IsPolymorphic && DocCommentNode); +/** Traverse a DocComment tree bottom-up (post-order). + @param node Root node to traverse. + @param func Visitor invoked after children are visited. +*/ template void bottomUpTraverse(T& node, F&& func) @@ -371,6 +386,10 @@ bottomUpTraverse(T& node, F&& func) detail::traverseImpl(node, std::forward(func)); } +/** Traverse a DocComment tree top-down (pre-order). + @param node Root node to traverse. + @param func Visitor invoked before children are visited. +*/ template void topDownTraverse(T& node, F&& func) diff --git a/include/mrdocs/Metadata/DocComment/Block.hpp b/include/mrdocs/Metadata/DocComment/Block.hpp index 464da939f9..56628d88e6 100644 --- a/include/mrdocs/Metadata/DocComment/Block.hpp +++ b/include/mrdocs/Metadata/DocComment/Block.hpp @@ -34,14 +34,16 @@ #include #include +/** Doc-comment enums and helpers that describe admonition kinds. */ namespace mrdocs::doc { + /** Visit a block. - @param block The block to visit. + @param info The block to visit. @param fn The function to call for each block. @param args Additional arguments to pass to the function. @return The result of calling the function. - */ +*/ template< std::derived_from BlockTy, class Fn, @@ -64,10 +66,14 @@ visit( } } +/** Three-way comparison between polymorphic block wrappers. +*/ MRDOCS_DECL std::strong_ordering operator<=>(Polymorphic const& lhs, Polymorphic const& rhs); +/** Equality delegates to the three-way comparison. +*/ inline bool operator==(Polymorphic const& lhs, Polymorphic const& rhs) { @@ -79,7 +85,7 @@ operator==(Polymorphic const& lhs, Polymorphic const& rhs) @param io The output parameter to receive the dom::Object. @param I The polymorphic Block to convert. @param domCorpus The DomCorpus used to resolve references. - */ +*/ template void tag_invoke( @@ -100,10 +106,10 @@ tag_invoke( /** Map the Polymorphic Block as a @ref dom::Value object. - @param io The output parameter to receive the dom::Value. + @param v The output parameter to receive the dom::Value. @param I The polymorphic Block to convert. @param domCorpus The DomCorpus used to resolve references. - */ +*/ inline void tag_invoke( @@ -122,7 +128,11 @@ tag_invoke( }); } - +/** Map an optional polymorphic block into a DOM value, producing null when empty. + @param v Destination value. + @param I Optional block to convert. + @param domCorpus Corpus context for lazy resolution. +*/ inline void tag_invoke( @@ -144,7 +154,7 @@ tag_invoke( @param el The Polymorphic to trim. @return void - */ +*/ inline void ltrim(Polymorphic& el) @@ -156,7 +166,7 @@ ltrim(Polymorphic& el) @param el The Polymorphic to trim. @return void - */ +*/ inline void rtrim(Polymorphic& el) @@ -168,7 +178,7 @@ rtrim(Polymorphic& el) @param el The Polymorphic to trim. @return void - */ +*/ inline void trim(Polymorphic& el) @@ -178,7 +188,7 @@ trim(Polymorphic& el) } /** Determine if the inline is empty - */ +*/ inline bool isEmpty(Polymorphic const& el) diff --git a/include/mrdocs/Metadata/DocComment/Block/AdmonitionBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/AdmonitionBlock.hpp index a8584f6b2b..3c03ee436e 100644 --- a/include/mrdocs/Metadata/DocComment/Block/AdmonitionBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/AdmonitionBlock.hpp @@ -27,6 +27,12 @@ namespace mrdocs::doc { This paragraph represents an admonition, such as a note, tip, important, caution, or warning. + + Syntax: + + @code + @note text + @endcode */ struct AdmonitionBlock final : BlockCommonBase @@ -35,29 +41,36 @@ struct AdmonitionBlock final /** The kind of admonition This is typically a string in other implementations. - */ + */ AdmonitionKind admonish; /// Optional title for the admonition Optional> Title; + /** Construct an admonition with the given kind. + */ explicit AdmonitionBlock( AdmonitionKind const admonish_ = AdmonitionKind::none) noexcept : admonish(admonish_) {} + /** Compare admonitions by kind, title, and contents. + */ auto operator<=>(AdmonitionBlock const&) const = default; + + /** Equality compares the admonition contents. + */ bool operator==(AdmonitionBlock const&) const noexcept = default; }; -/** Map the @ref Admonition to a @ref dom::Object. +/** Map the @ref AdmonitionBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -71,8 +84,8 @@ tag_invoke( io.map("admonish", I.admonish); } -/** Return the @ref Admonition as a @ref dom::Value object. - */ +/** Return the @ref AdmonitionBlock as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/AdmonitionKind.hpp b/include/mrdocs/Metadata/DocComment/Block/AdmonitionKind.hpp index 8957f04a53..980b6a2388 100644 --- a/include/mrdocs/Metadata/DocComment/Block/AdmonitionKind.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/AdmonitionKind.hpp @@ -20,7 +20,7 @@ namespace mrdocs::doc { /** An admonishment style. - */ +*/ enum class AdmonitionKind { /// No admonishment @@ -38,13 +38,13 @@ enum class AdmonitionKind }; /** Return the name of the Admonish as a string. - */ +*/ MRDOCS_DECL dom::String toString(AdmonitionKind kind) noexcept; /** Return the Admonish from a @ref dom::Value string. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/BlockBase.hpp b/include/mrdocs/Metadata/DocComment/Block/BlockBase.hpp index 9b6c19947f..23fff1fdaf 100644 --- a/include/mrdocs/Metadata/DocComment/Block/BlockBase.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/BlockBase.hpp @@ -39,21 +39,33 @@ namespace mrdocs::doc { */ struct MRDOCS_DECL Block { + /** Discriminator identifying which concrete block this instance holds. + */ BlockKind Kind = BlockKind::Paragraph; + /** Virtual to allow deleting through a base pointer. + */ virtual ~Block() = default; + /** Three-way comparison on the block contents. + */ auto operator<=>(Block const& other) const = default; + /** Equality compares the block contents. + */ bool operator==(Block const& other) const noexcept = default; + /** View this object as a `Block` reference. + */ constexpr Block const& asBlock() const noexcept { return *this; } + /** View this object as a mutable `Block` reference. + */ constexpr Block& asBlock() noexcept { return *this; @@ -95,9 +107,13 @@ struct MRDOCS_DECL Block #include protected: + /** Default-construct a paragraph block. + */ constexpr Block() = default; + /** Construct a block with the specified discriminant. + */ explicit Block(BlockKind const kind_) noexcept : Kind(kind_) @@ -117,18 +133,24 @@ struct BlockCommonBase : Block It only distinguishes from `Block::kind` in that it is a constant. - */ + */ static constexpr BlockKind kind_id = K; + /** Virtual to keep dynamic dispatch working for block hierarchies. + */ ~BlockCommonBase() override = default; #define INFO(Kind) \ static constexpr bool is##Kind() noexcept { return K == BlockKind::Kind; } #include + /** Compare two blocks that share the same `kind_id`. + */ auto operator<=>(BlockCommonBase const&) const = default; protected: + /** Construct with the fixed block kind. + */ constexpr explicit BlockCommonBase() : Block(K) {} @@ -136,15 +158,13 @@ struct BlockCommonBase : Block /** Map the @ref Block to a @ref dom::Object. - @param t The tag. @param io The output object. @param I The input object. - @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( - dom::LazyObjectMapTag t, + dom::LazyObjectMapTag, IO& io, Block const& I, DomCorpus const*) @@ -153,7 +173,7 @@ tag_invoke( } /** Return the @ref Block as a @ref dom::Value object. - */ +*/ inline void tag_invoke( @@ -169,7 +189,7 @@ tag_invoke( @param el The Block to trim. @return void - */ +*/ MRDOCS_DECL void ltrim(Block& el); @@ -178,7 +198,7 @@ ltrim(Block& el); @param el The Block to trim. @return void - */ +*/ MRDOCS_DECL void rtrim(Block& el); @@ -187,7 +207,7 @@ rtrim(Block& el); @param el The Block to trim. @return void - */ +*/ inline void trim(Block& el) @@ -197,35 +217,52 @@ trim(Block& el) } /** Determine if the inline is empty - */ +*/ MRDOCS_DECL bool isEmpty(Block const& el); +/** A composite block that stores a sequence of child blocks. +*/ struct MRDOCS_DECL BlockContainer { + /** Child blocks contained within this composite block. + */ std::vector> blocks; + /** Access the container as a mutable view. + */ BlockContainer& asBlockContainer() { return *this; } + /** Access the container as a const view. + */ BlockContainer const& asBlockContainer() const { return *this; } + /** Order containers lexicographically by their children. + */ std::strong_ordering operator<=>(BlockContainer const&) const; + /** Equality compares the stored child blocks. + */ bool operator==(BlockContainer const&) const = default; }; +/** Convert a polymorphic block storage into a DOM value. + @param io Destination value to fill. + @param I Block to convert. + @param domCorpus Corpus context for lazy references. +*/ template BlockTy> void tag_invoke( @@ -234,10 +271,15 @@ tag_invoke( BlockTy const& I, DomCorpus const* domCorpus); +/** Map a block container into a lazily-evaluated DOM object. + @param io Destination object. + @param I Block container to convert. + @param domCorpus Corpus context for lazy references. +*/ template void tag_invoke( - dom::LazyObjectMapTag t, + dom::LazyObjectMapTag, IO& io, BlockContainer const& I, DomCorpus const* domCorpus) @@ -247,6 +289,11 @@ tag_invoke( }); } +/** Return the block container as a DOM value. + @param v Destination value. + @param I Block container to convert. + @param domCorpus Corpus context for lazy references. +*/ inline void tag_invoke( @@ -262,7 +309,7 @@ tag_invoke( @param blocks The BlockContainer to trim. @return void - */ +*/ MRDOCS_DECL void ltrim(BlockContainer& blocks); @@ -271,7 +318,7 @@ ltrim(BlockContainer& blocks); @param blocks The BlockContainer to trim. @return void - */ +*/ MRDOCS_DECL void rtrim(BlockContainer& blocks); @@ -280,7 +327,7 @@ rtrim(BlockContainer& blocks); @param blocks The BlockContainer to trim. @return void - */ +*/ inline void trim(BlockContainer& blocks) diff --git a/include/mrdocs/Metadata/DocComment/Block/BlockKind.hpp b/include/mrdocs/Metadata/DocComment/Block/BlockKind.hpp index b5df094f9d..ee9d6f310a 100644 --- a/include/mrdocs/Metadata/DocComment/Block/BlockKind.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/BlockKind.hpp @@ -16,11 +16,15 @@ namespace mrdocs::doc { +/** Enumerates the different kinds of DocComment blocks. +*/ enum class BlockKind { #define INFO(Type) Type, #include }; +/** Convert a block kind to its kebab-case string name. +*/ inline dom::String toString(BlockKind kind) noexcept @@ -33,15 +37,22 @@ toString(BlockKind kind) noexcept return "Unknown"; } +/** Write a block kind into a DOM value as its string name. + @param v Destination value. + @param kind Block kind to serialize. +*/ inline void tag_invoke( dom::ValueFromTag, - dom::Value& v, BlockKind const kind) + dom::Value& v, + BlockKind const kind) { v = toString(kind); } +/** Return true if the given block kind represents a command block. +*/ constexpr bool isBlockCommand(BlockKind k) noexcept diff --git a/include/mrdocs/Metadata/DocComment/Block/BriefBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/BriefBlock.hpp index 1a9e719a28..4cdc4363a2 100644 --- a/include/mrdocs/Metadata/DocComment/Block/BriefBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/BriefBlock.hpp @@ -21,34 +21,54 @@ namespace mrdocs::doc { /** The brief description + + Syntax: + + @code + @brief summary + @endcode */ struct BriefBlock final : BlockCommonBase , InlineContainer { + /** Names of declarations whose brief text was reused. + */ std::vector copiedFrom; + /** Create an empty brief. + */ BriefBlock() = default; + /** Copy-construct from another brief. + */ BriefBlock(BriefBlock const& other) = default; + /** Inherit inline container constructors. + */ using InlineContainer::InlineContainer; + /** Copy-assign another brief. + */ BriefBlock& operator=(BriefBlock const& other) = default; + /** Reuse inline container assignment operators. + */ using InlineContainer::operator=; + /** Compare briefs by inline content and provenance. + */ auto operator<=>(BriefBlock const&) const = default; }; -/** Map the @ref Brief to a @ref dom::Object. +/** Map the @ref BriefBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -64,8 +84,8 @@ tag_invoke( }); } -/** Return the @ref Brief as a @ref dom::Value object. - */ +/** Return the @ref BriefBlock as a @ref dom::Value object. +*/ inline void tag_invoke( @@ -79,6 +99,11 @@ tag_invoke( Optional o; } +/** Map an optional brief block to a DOM value, yielding null when absent. + @param v Destination value. + @param I Optional brief block to convert. + @param domCorpus Corpus context for lazy references. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/CodeBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/CodeBlock.hpp index c32576514b..9a90709302 100644 --- a/include/mrdocs/Metadata/DocComment/Block/CodeBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/CodeBlock.hpp @@ -20,27 +20,35 @@ namespace mrdocs::doc { /** Preformatted source code. - */ +*/ struct CodeBlock final : BlockCommonBase { + /** Raw code text inside the fenced block. + */ std::string literal; /// Fence info string, e.g. "cpp" std::string info; + /** Construct an empty code block. + */ CodeBlock() noexcept = default; + /** Compare code blocks by literal and info string. + */ auto operator<=>(CodeBlock const&) const = default; + /** Equality compares literal and info string. + */ bool operator==(CodeBlock const&) const noexcept = default; }; -/** Map the @ref Code to a @ref dom::Object. +/** Map the @ref CodeBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -57,8 +65,8 @@ tag_invoke( } } -/** Return the @ref Code as a @ref dom::Value object. - */ +/** Return the @ref CodeBlock as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/DefinitionListBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/DefinitionListBlock.hpp index 6a9ae28f13..63e6044a42 100644 --- a/include/mrdocs/Metadata/DocComment/Block/DefinitionListBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/DefinitionListBlock.hpp @@ -22,11 +22,41 @@ namespace mrdocs::doc { +/** A list of terms paired with definitions. + + Syntax: + + @code + Markdown + : A lightweight markup language + : Created by John Gruber in 2004 + + HTML + : A standard markup language used to create web pages + : Used for structuring content on the internet + @endcode + + In HTML, it looks like: + + @code +
+
First Term
+
This is the definition of the first term.
+
Second Term
+
This is one definition of the second term.
+
This is another definition of the second term.
+
+ @endcode +*/ struct DefinitionListBlock final : BlockCommonBase { + /** Sequence of definition list items. + */ std::vector items; + /** Order items and their definitions lexicographically. + */ auto operator<=>(DefinitionListBlock const& other) const { if (auto const cmp = items.size() <=> other.items.size(); !std::is_eq(cmp)) @@ -44,10 +74,18 @@ struct DefinitionListBlock final return std::strong_ordering::equal; } + /** Equality compares the contained items. + */ bool operator==(DefinitionListBlock const&) const noexcept = default; }; +/** Map a definition list block into a DOM object. + @param t Conversion tag. + @param io Destination object. + @param I Block to convert. + @param domCorpus Corpus context for lazy references. +*/ template void tag_invoke( @@ -62,6 +100,11 @@ tag_invoke( }); } +/** Convert a definition list block to a DOM value. + @param v Destination value. + @param I Block to convert. + @param domCorpus Corpus context for lazy references. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/DefinitionListItem.hpp b/include/mrdocs/Metadata/DocComment/Block/DefinitionListItem.hpp index ce0dc897da..a8d821c009 100644 --- a/include/mrdocs/Metadata/DocComment/Block/DefinitionListItem.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/DefinitionListItem.hpp @@ -24,9 +24,16 @@ namespace mrdocs::doc { struct DefinitionListItem final : BlockContainer { + /** The term being defined. + */ InlineContainer term; + /** Compare items by term and definition blocks. + */ auto operator<=>(DefinitionListItem const&) const = default; + + /** Equality compares term and definitions. + */ bool operator==(DefinitionListItem const&) const noexcept = default; }; @@ -36,7 +43,7 @@ struct DefinitionListItem final @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -50,7 +57,7 @@ tag_invoke( } /** Return the @ref DefinitionListItem as a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/FootnoteDefinitionBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/FootnoteDefinitionBlock.hpp index feaa46dd58..ed5e09561b 100644 --- a/include/mrdocs/Metadata/DocComment/Block/FootnoteDefinitionBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/FootnoteDefinitionBlock.hpp @@ -19,26 +19,43 @@ namespace mrdocs::doc { -/** Preformatted source code. - */ +/** Text defining the content of a footnote reference. + + Syntax: + + @code + This is a sentence with a footnote[^1]. + + [^1]: This is the content of the footnote. It can also have multiple paragraphs. + Here is the second paragraph, which needs to be indented. + @endcode +*/ struct FootnoteDefinitionBlock final : BlockCommonBase , BlockContainer { + /** Footnote label identifier. + */ std::string label; + /** Construct an empty footnote definition. + */ FootnoteDefinitionBlock() noexcept = default; + /** Compare definitions by label and block content. + */ auto operator<=>(FootnoteDefinitionBlock const&) const = default; + /** Equality compares label and block content. + */ bool operator==(FootnoteDefinitionBlock const&) const noexcept = default; }; -/** Map the @ref FootnoteDefinition to a @ref dom::Object. +/** Map the @ref FootnoteDefinitionBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -52,8 +69,8 @@ tag_invoke( io.map("label", I.label); } -/** Return the @ref FootnoteDefinition as a @ref dom::Value object. - */ +/** Return the @ref FootnoteDefinitionBlock as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/HeadingBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/HeadingBlock.hpp index 15ab196d54..28433b75ad 100644 --- a/include/mrdocs/Metadata/DocComment/Block/HeadingBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/HeadingBlock.hpp @@ -19,25 +19,52 @@ namespace mrdocs::doc { /** A manually specified section heading. + + Syntax: + + @code + @par Heading + @endcode + + or in Markdown: + + @code + # Heading 1 + ## Heading 2 + ### Heading 3 + #### Heading 4 + ##### Heading 5 + ###### Heading 6 + @endcode */ struct HeadingBlock final : BlockCommonBase , InlineContainer { + /** Heading depth (1..6). + */ unsigned level = 1; // 1 to 6 + /** Inherit inline container constructors. + */ using InlineContainer::InlineContainer; + + /** Order headings by level and inline content. + */ auto operator<=>(HeadingBlock const&) const = default; + + /** Equality compares level and inline content. + */ bool operator==(HeadingBlock const&) const noexcept = default; }; -/** Map the @ref Heading to a @ref dom::Object. +/** Map the @ref HeadingBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -51,8 +78,8 @@ tag_invoke( io.map("level", I.level); } -/** Return the @ref Heading as a @ref dom::Value object. - */ +/** Return the @ref HeadingBlock as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/ListBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/ListBlock.hpp index 193bdbc41f..6f2ddea92b 100644 --- a/include/mrdocs/Metadata/DocComment/Block/ListBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/ListBlock.hpp @@ -23,13 +23,67 @@ namespace mrdocs::doc { /** A list of list items + + Syntax: + + @code + - item one + - item two + @endcode + + Unordered list: + + @code + - Item 1 + - Item 2 + - Nested item 2.1 + - Nested item 2.2 + * Item 3 + + Item 4 + @endcode + + Ordered list: + + @code + 1. First item + 2. Second item + 1. Nested ordered item 2.1 + 2. Nested ordered item 2.2 + 3. Third item + @endcode + + Task lists (Checklists): + + @code + - [x] Completed task + - [ ] Pending task + - [x] Another completed task + @endcode + + Definition Lists (@ref DefinitionListBlock) + + @code + Term 1 + : Definition of Term 1 + + Term 2 + : Definition of Term 2 + : Another definition for Term 2 + @endcode */ struct ListBlock final : BlockCommonBase { + /** Items contained in the list. + */ std::vector items; + + /** Display style for the list. + */ ListKind listKind = ListKind::Unordered; + /** Order lists by item content and list style. + */ auto operator<=>(ListBlock const& other) const { if (auto const cmp = items.size() <=> other.items.size(); !std::is_eq(cmp)) @@ -47,17 +101,19 @@ struct ListBlock final return std::strong_ordering::equal; } + /** Equality compares the list style and items. + */ bool operator==(ListBlock const&) const noexcept = default; }; -/** Map the @ref UnorderedList to a @ref dom::Object. +/** Map the @ref ListBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -73,8 +129,8 @@ tag_invoke( io.map("listKind", toString(I.listKind)); } -/** Return the @ref UnorderedList as a @ref dom::Value object. - */ +/** Return the @ref ListBlock as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/ListItem.hpp b/include/mrdocs/Metadata/DocComment/Block/ListItem.hpp index 14693d3a35..406aac7fb5 100644 --- a/include/mrdocs/Metadata/DocComment/Block/ListItem.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/ListItem.hpp @@ -19,12 +19,17 @@ namespace mrdocs::doc { -/** An item in a list +/** An item in a @ref ListBlock */ struct ListItem final : BlockContainer { + /** Order list items by their child blocks. + */ auto operator<=>(ListItem const&) const = default; + + /** Equality compares contained blocks. + */ bool operator==(ListItem const&) const noexcept = default; }; @@ -34,7 +39,7 @@ struct ListItem final @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -47,7 +52,7 @@ tag_invoke( } /** Return the @ref ListItem as a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/ListKind.hpp b/include/mrdocs/Metadata/DocComment/Block/ListKind.hpp index 6b56c766ed..6dfb21f790 100644 --- a/include/mrdocs/Metadata/DocComment/Block/ListKind.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/ListKind.hpp @@ -16,11 +16,17 @@ namespace mrdocs { +/** Classification of list ordering. +*/ enum class ListKind { + /// A bulleted list with no inherent ordering. Unordered, + /// A numbered list where item order matters. Ordered }; +/** Convert a list kind enum to its string name. +*/ inline dom::String toString(ListKind kind) noexcept @@ -35,11 +41,16 @@ toString(ListKind kind) noexcept return "Unknown"; } +/** Serialize a list kind into a DOM value. + @param v Destination value. + @param kind List kind to serialize. +*/ inline void tag_invoke( dom::ValueFromTag, - dom::Value& v, ListKind const kind) + dom::Value& v, + ListKind const kind) { v = toString(kind); } diff --git a/include/mrdocs/Metadata/DocComment/Block/MathBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/MathBlock.hpp index 63cc52c512..450b5f491a 100644 --- a/include/mrdocs/Metadata/DocComment/Block/MathBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/MathBlock.hpp @@ -22,25 +22,47 @@ namespace mrdocs::doc { A block of LaTeX math, typically between $$ … $$ or fenced with "math". - */ + + On a new line: + + @code + $$ \int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi} $$ + @endcode + + Or as a code block: + + @code + ```math + \int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi} + ``` + @endcode +*/ struct MathBlock final : BlockCommonBase { /// Raw TeX math source std::string literal; + /** Copy-construct a math block. + */ MathBlock(MathBlock const& other) = default; + + /** Copy-assign a math block. + */ MathBlock& operator=(MathBlock const& other) = default; + + /** Compare math blocks by literal content. + */ auto operator<=>(MathBlock const&) const = default; }; -/** Map the @ref Brief to a @ref dom::Object. +/** Map the @ref MathBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -53,8 +75,8 @@ tag_invoke( io.map("literal", I.literal); } -/** Return the @ref Brief as a @ref dom::Value object. - */ +/** Return the @ref MathBlock as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/ParagraphBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/ParagraphBlock.hpp index 48bc0daa49..9ff999c548 100644 --- a/include/mrdocs/Metadata/DocComment/Block/ParagraphBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/ParagraphBlock.hpp @@ -22,24 +22,39 @@ namespace mrdocs::doc { /** A sequence of text nodes. + + Syntax: + + @code + Plain paragraph text. + + Another paragraph. + @endcode */ struct ParagraphBlock : BlockCommonBase , InlineContainer { + /** Virtual destructor for the polymorphic block hierarchy. + */ ~ParagraphBlock() override = default; + + /** Construct an empty paragraph. + */ ParagraphBlock() noexcept = default; + /** Compare paragraphs by their inline content. + */ auto operator<=>(ParagraphBlock const&) const = default; }; -/** Map the @ref Paragraph to a @ref dom::Object. +/** Map the @ref ParagraphBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -52,8 +67,8 @@ tag_invoke( tag_invoke(t, io, static_cast(I), domCorpus); } -/** Return the @ref Paragraph as a @ref dom::Value object. - */ +/** Return the @ref ParagraphBlock as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/ParamBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/ParamBlock.hpp index 26e7d22616..30e805ca0d 100644 --- a/include/mrdocs/Metadata/DocComment/Block/ParamBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/ParamBlock.hpp @@ -23,24 +23,45 @@ namespace mrdocs::doc { /** Documentation for a function parameter + + Syntax: + + @code + @param name description + @endcode */ struct ParamBlock final : BlockCommonBase , InlineContainer { + /** Name of the parameter being documented. + */ std::string name; + /** Direction (in/out/inout) of the parameter. + */ ParamDirection direction = ParamDirection::none; + /** Inherit inline container constructors. + */ using InlineContainer::InlineContainer; + /** Build from an existing inline container. + */ ParamBlock(InlineContainer const& other) : InlineContainer(other) {} + /** Build from an rvalue inline container. + */ ParamBlock(InlineContainer&& other) noexcept : InlineContainer(std::move(other)) {} + /** Construct from name, text, and direction. + @param name Parameter identifier. + @param text Description text. + @param direction Flow direction of the parameter. + */ ParamBlock( std::string_view name, std::string_view text, @@ -50,7 +71,12 @@ struct ParamBlock final , direction(direction) {} + /** Order parameter docs by name, direction, and text. + */ auto operator<=>(ParamBlock const&) const = default; + + /** Equality compares name, direction, and text. + */ bool operator==(ParamBlock const&) const noexcept = default; }; @@ -61,7 +87,7 @@ struct ParamBlock final @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -77,7 +103,7 @@ tag_invoke( } /** Return the @ref Param as a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/ParamDirection.hpp b/include/mrdocs/Metadata/DocComment/Block/ParamDirection.hpp index 89f66f995c..bff93b938e 100644 --- a/include/mrdocs/Metadata/DocComment/Block/ParamDirection.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/ParamDirection.hpp @@ -34,13 +34,13 @@ enum class ParamDirection }; /** Return the name of the ParamDirection as a string. - */ +*/ MRDOCS_DECL dom::String toString(ParamDirection kind) noexcept; /** Return the ParamDirection from a @ref dom::Value string. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/PostconditionBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/PostconditionBlock.hpp index f882c4686f..c3b15426a5 100644 --- a/include/mrdocs/Metadata/DocComment/Block/PostconditionBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/PostconditionBlock.hpp @@ -20,22 +20,38 @@ namespace mrdocs::doc { +/** Text describing conditions guaranteed on successful exit. + + Syntax: + + @code + @post condition + @endcode +*/ struct PostconditionBlock : BlockCommonBase , InlineContainer { + /** Inherit inline container constructors. + */ using InlineContainer::InlineContainer; + + /** Order postconditions by their inline text. + */ auto operator<=>(PostconditionBlock const&) const = default; + + /** Equality compares the inline text. + */ bool operator==(PostconditionBlock const&) const noexcept = default; }; -/** Map the @ref Postcondition to a @ref dom::Object. +/** Map the @ref PostconditionBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -48,12 +64,12 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref Postcondition as a @ref dom::Value object. +/** Return the @ref PostconditionBlock as a @ref dom::Value object. @param v The value to assign to. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/PreconditionBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/PreconditionBlock.hpp index fbd9a914ec..833b248c93 100644 --- a/include/mrdocs/Metadata/DocComment/Block/PreconditionBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/PreconditionBlock.hpp @@ -20,22 +20,38 @@ namespace mrdocs::doc { +/** Text describing required conditions before entry. + + Syntax: + + @code + @pre condition + @endcode +*/ struct PreconditionBlock final : BlockCommonBase , InlineContainer { + /** Inherit inline container constructors. + */ using InlineContainer::InlineContainer; + + /** Order preconditions by their inline text. + */ auto operator<=>(PreconditionBlock const&) const = default; + + /** Equality compares the inline text. + */ bool operator==(PreconditionBlock const&) const noexcept = default; }; -/** Map the @ref Precondition to a @ref dom::Object. +/** Map the @ref PreconditionBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -48,12 +64,12 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref Precondition as a @ref dom::Value object. +/** Return the @ref PreconditionBlock as a @ref dom::Value object. @param v The value to assign to. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/QuoteBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/QuoteBlock.hpp index 53a7c6bd3c..2159016a7b 100644 --- a/include/mrdocs/Metadata/DocComment/Block/QuoteBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/QuoteBlock.hpp @@ -21,13 +21,53 @@ namespace mrdocs::doc { -/** A list of list items +/** A quoted block of text. + + Syntax: + + @code + > quoted text + @endcode + + Multi-line quotes: + + @code + > This is the first line of a multi-line quote. + > This is the second line. + > And this is the third. + @endcode + + Nested quotes: + + @code + > This is the outer quote. + > + > > This is a nested quote within the outer quote. + > > + > > > This is a further nested quote. + @endcode + + Quotes with other markdown elements: + + @code + > ### Important Note + > + > - This blockquote contains a heading. + > - And a list item. + > + > *Emphasis* and **strong emphasis** also work within blockquotes. + @endcode */ struct QuoteBlock final : BlockCommonBase , BlockContainer { + /** Order quote blocks by their child content. + */ auto operator<=>(QuoteBlock const&) const = default; + + /** Equality compares quoted child content. + */ bool operator==(QuoteBlock const&) const noexcept = default; }; @@ -37,7 +77,7 @@ struct QuoteBlock final @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -51,7 +91,7 @@ tag_invoke( } /** Return the @ref QuoteBlock as a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/ReturnsBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/ReturnsBlock.hpp index 5704e16887..849f93d73b 100644 --- a/include/mrdocs/Metadata/DocComment/Block/ReturnsBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/ReturnsBlock.hpp @@ -22,30 +22,57 @@ namespace mrdocs::doc { /** Documentation for a function return type + + Syntax: + + @code + @return description + @endcode */ struct ReturnsBlock final : BlockCommonBase , InlineContainer { + /** Inherit inline container constructors. + */ using InlineContainer::InlineContainer; + + /** Copy constructor. + */ ReturnsBlock(ReturnsBlock const&) = default; + /** Move constructor. + */ ReturnsBlock(ReturnsBlock&&) noexcept = default; + /** Construct from inline content (copy). + */ ReturnsBlock(InlineContainer const& other) : InlineContainer(other) {} + /** Construct from inline content (move). + */ ReturnsBlock(InlineContainer&& other) noexcept : InlineContainer(other) {} + /** Virtual destructor for polymorphic base. + */ ~ReturnsBlock() override = default; + /** Copy assignment. + */ ReturnsBlock& operator=(ReturnsBlock const&) = default; + /** Move assignment. + */ ReturnsBlock& operator=(ReturnsBlock&&) noexcept = default; + /** Order return docs by inline content. + */ auto operator<=>(ReturnsBlock const&) const = default; + /** Equality compares inline content. + */ bool operator==(ReturnsBlock const&) const noexcept = default; }; -/** Map the @ref Returns to a @ref dom::Object. +/** Map the @ref ReturnsBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -58,8 +85,8 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref Returns as a @ref dom::Value object. - */ +/** Return the @ref ReturnsBlock as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/SeeBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/SeeBlock.hpp index 09f73bb29d..41826dba60 100644 --- a/include/mrdocs/Metadata/DocComment/Block/SeeBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/SeeBlock.hpp @@ -21,24 +21,47 @@ namespace mrdocs::doc { -/** A @see paragraph +/** A @see paragraph listing related symbols or references. + + Syntax: + + @code + @see other_symbol + @endcode + + or + + @code + @see AnotherFunction() + @see MyClass::calculateSomething() + @see MyFile.h + @see "The Doxygen Manual" + @endcode + + */ struct SeeBlock final : BlockCommonBase , InlineContainer { + /** Inherit inline container constructors. + */ using InlineContainer::InlineContainer; + /** Order see-also entries by inline content. + */ auto operator<=>(SeeBlock const&) const = default; + /** Equality compares inline content. + */ bool operator==(SeeBlock const&) const noexcept = default; }; -/** Map the @ref See to a @ref dom::Object. +/** Map the @ref SeeBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -51,8 +74,8 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref See as a @ref dom::Value object. - */ +/** Return the @ref SeeBlock as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/TParamBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/TParamBlock.hpp index 124d1007b7..1e23d0f350 100644 --- a/include/mrdocs/Metadata/DocComment/Block/TParamBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/TParamBlock.hpp @@ -22,15 +22,29 @@ namespace mrdocs::doc { /** Documentation for a template parameter + + Syntax: + + @code + @tparam T description + @endcode */ struct TParamBlock final : BlockCommonBase , InlineContainer { + /** Template parameter name. + */ std::string name; + /** Inherit inline container constructors. + */ using InlineContainer::InlineContainer; + /** Order template parameter docs by name and text. + */ auto operator<=>(TParamBlock const&) const = default; + /** Equality compares name and inline content. + */ bool operator==(TParamBlock const&) const noexcept = default; }; @@ -40,7 +54,7 @@ struct TParamBlock final @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -55,7 +69,7 @@ tag_invoke( } /** Return the @ref TParam as a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/TableAlignmentKind.hpp b/include/mrdocs/Metadata/DocComment/Block/TableAlignmentKind.hpp index 8dd01f6868..e6f7aba461 100644 --- a/include/mrdocs/Metadata/DocComment/Block/TableAlignmentKind.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/TableAlignmentKind.hpp @@ -16,13 +16,21 @@ namespace mrdocs { +/** Horizontal alignment for table columns. +*/ enum class TableAlignmentKind { + /// No explicit alignment; renderer default applies. None, + /// Align content to the left edge. Left, + /// Center the content. Center, + /// Align content to the right edge. Right, }; +/** Convert an alignment enum to its string representation. +*/ inline dom::String toString(TableAlignmentKind kind) noexcept @@ -41,11 +49,16 @@ toString(TableAlignmentKind kind) noexcept return "unknown"; } +/** Serialize an alignment enum into a DOM value. + @param v Destination value. + @param kind Alignment to serialize. +*/ inline void tag_invoke( dom::ValueFromTag, - dom::Value& v, TableAlignmentKind const kind) + dom::Value& v, + TableAlignmentKind const kind) { v = toString(kind); } diff --git a/include/mrdocs/Metadata/DocComment/Block/TableBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/TableBlock.hpp index 3ccb261fd6..899127f203 100644 --- a/include/mrdocs/Metadata/DocComment/Block/TableBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/TableBlock.hpp @@ -23,12 +23,28 @@ namespace mrdocs::doc { /** A table block + + Syntax: + + @code + | Header 1 | Header 2 | Header 3 | + | :------- | :------: | -------: | + | Left | Center | Right | + | Cell 1A | Cell 1B | Cell 1C | + | Cell 2A | Cell 2B | Cell 2C | + @endcode */ struct TableBlock final: BlockCommonBase { + /** Column alignments for each table column. + */ std::vector Alignments; + /** Rows that make up the table body (header first when present). + */ std::vector items; + /** Order tables by row contents and alignments. + */ auto operator<=>(TableBlock const& other) const { if (auto const cmp = items.size() <=> other.items.size(); !std::is_eq(cmp)) @@ -46,17 +62,19 @@ struct TableBlock final: BlockCommonBase return std::strong_ordering::equal; } + /** Equality compares alignments and rows. + */ bool operator==(TableBlock const&) const noexcept = default; }; -/** Map the @ref UnorderedTable to a @ref dom::Object. +/** Map the @ref TableBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -74,8 +92,8 @@ tag_invoke( }); } -/** Return the @ref UnorderedTable as a @ref dom::Value object. - */ +/** Return the @ref TableBlock as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/TableCell.hpp b/include/mrdocs/Metadata/DocComment/Block/TableCell.hpp index 529329f728..d3c5f24986 100644 --- a/include/mrdocs/Metadata/DocComment/Block/TableCell.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/TableCell.hpp @@ -24,9 +24,13 @@ namespace mrdocs::doc { struct TableCell final : InlineContainer { + /** Order cells by their inline content. + */ auto operator<=>(TableCell const&) const = default; - bool - operator==(TableCell const&) const noexcept = default; + + /** Equality compares inline content. + */ + bool operator==(TableCell const&) const noexcept = default; }; /** Map the @ref TableCell to a @ref dom::Object. @@ -35,7 +39,7 @@ struct TableCell final @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -47,7 +51,7 @@ tag_invoke( } /** Return the @ref TableCell as a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/TableRow.hpp b/include/mrdocs/Metadata/DocComment/Block/TableRow.hpp index 76f11d3f84..732a16b8e1 100644 --- a/include/mrdocs/Metadata/DocComment/Block/TableRow.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/TableRow.hpp @@ -25,12 +25,19 @@ namespace mrdocs::doc { */ struct TableRow final { + /** True if this row represents a header. + */ bool is_header = false; + /** Cells contained in the row. + */ std::vector Cells; + /** Order rows by header flag then cell contents. + */ auto operator<=>(TableRow const&) const = default; - bool - operator==(TableRow const&) const noexcept = default; + /** Equality compares header flag and cells. + */ + bool operator==(TableRow const&) const noexcept = default; }; /** Map the @ref TableRow to a @ref dom::Object. @@ -39,7 +46,7 @@ struct TableRow final @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -55,7 +62,7 @@ tag_invoke( } /** Return the @ref TableRow as a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/ThematicBreakBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/ThematicBreakBlock.hpp index a5a9baf36a..cc518af3a4 100644 --- a/include/mrdocs/Metadata/DocComment/Block/ThematicBreakBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/ThematicBreakBlock.hpp @@ -19,23 +19,60 @@ namespace mrdocs::doc { -/** The brief description +/** A horizontal thematic break separating sections. + + Syntax: + + @code + --- + @endcode + + or + + @code + *** + @endcode + + or + + @code + ___ + @endcode + + or + + @code + - - - + @endcode + + - You can use an asterisk (*), dash (-), or underscore (_). + - There must be at least three characters in a row. + - Spaces can be used between the characters, but no other characters. + - The thematic break should be on its own line, separated by blank lines above and below. + - Thematic breaks can also be used inside lists, but the character used for the break must be different from the list marker. + */ struct ThematicBreakBlock final : BlockCommonBase { + /** Copy constructor. + */ ThematicBreakBlock(ThematicBreakBlock const& other) = default; + /** Copy assignment. + */ ThematicBreakBlock& operator=(ThematicBreakBlock const& other) = default; + /** Compare break blocks (trivial as they hold no data). + */ auto operator<=>(ThematicBreakBlock const&) const = default; }; -/** Map the @ref Brief to a @ref dom::Object. +/** Map the @ref ThematicBreakBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -47,8 +84,8 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref Brief as a @ref dom::Value object. - */ +/** Return the @ref ThematicBreakBlock as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Block/ThrowsBlock.hpp b/include/mrdocs/Metadata/DocComment/Block/ThrowsBlock.hpp index 7b74823063..aa9775708a 100644 --- a/include/mrdocs/Metadata/DocComment/Block/ThrowsBlock.hpp +++ b/include/mrdocs/Metadata/DocComment/Block/ThrowsBlock.hpp @@ -21,25 +21,42 @@ namespace mrdocs::doc { -/** Documentation for a function parameter +/** Documentation for a function exception clause + + Syntax: + + @code + @throws Type description + @endcode */ struct ThrowsBlock final : BlockCommonBase , InlineContainer { + /** Exception type being described. + */ ReferenceInline exception; + + /** Inherit inline container constructors. + */ using InlineContainer::InlineContainer; + + /** Order throw clauses by exception and description. + */ auto operator<=>(ThrowsBlock const&) const = default; + + /** Equality compares exception and description. + */ bool operator==(ThrowsBlock const&) const noexcept = default; }; -/** Map the @ref Throws to a @ref dom::Object. +/** Map the @ref ThrowsBlock to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -53,8 +70,8 @@ tag_invoke( io.map("exception", I.exception); } -/** Return the @ref Throws as a @ref dom::Value object. - */ +/** Return the @ref ThrowsBlock as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline.hpp b/include/mrdocs/Metadata/DocComment/Inline.hpp index fe0b503c0a..f42c850f3e 100644 --- a/include/mrdocs/Metadata/DocComment/Inline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline.hpp @@ -35,7 +35,6 @@ #include #include - namespace mrdocs::doc { /** Visit an inline. @@ -44,7 +43,7 @@ namespace mrdocs::doc { @param fn The function to call for each inline. @param args Additional arguments to pass to the function. @return The result of calling the function. - */ +*/ template< class InlineTy, class Fn, @@ -74,7 +73,7 @@ visit( @param list The list of texts to traverse. @param f The function to call for each text. @param args Additional arguments to pass to the function. - */ +*/ template requires std::derived_from void traverse( @@ -92,7 +91,7 @@ void traverse( @param io The output parameter to receive the dom::Object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template InlineTy> void tag_invoke( @@ -111,10 +110,14 @@ tag_invoke( }); } +/** Three-way comparison for polymorphic inline elements. +*/ MRDOCS_DECL std::strong_ordering operator<=>(Polymorphic const& lhs, Polymorphic const& rhs); +/** Equality delegates to the three-way comparison. +*/ inline bool operator==(Polymorphic const& lhs, Polymorphic const& rhs) { @@ -125,7 +128,7 @@ operator==(Polymorphic const& lhs, Polymorphic const& rhs) { @param el The Polymorphic to trim. @return void - */ +*/ MRDOCS_DECL void ltrim(Polymorphic& el); @@ -134,7 +137,7 @@ ltrim(Polymorphic& el); @param el The Polymorphic to trim. @return void - */ +*/ MRDOCS_DECL void rtrim(Polymorphic& el); @@ -143,7 +146,7 @@ rtrim(Polymorphic& el); @param el The Polymorphic to trim. @return void - */ +*/ inline void trim(Polymorphic& el) @@ -157,7 +160,7 @@ trim(Polymorphic& el) This determines if the inline is considered to have no content for the purposes of trimming. - */ +*/ MRDOCS_DECL bool isEmpty(Polymorphic const& el); diff --git a/include/mrdocs/Metadata/DocComment/Inline/CodeInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/CodeInline.hpp index 25ae621d62..9b377a0f8f 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/CodeInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/CodeInline.hpp @@ -19,24 +19,42 @@ namespace mrdocs::doc { -/** A piece of styled text. +/** Inline code (monospaced) used for short snippets within text. + + Syntax: + + @code + @c inline_code + @endcode + + or + + @code + `inline_code` + @endcode */ struct CodeInline final : InlineCommonBase , InlineContainer { + /** Inherit inline container constructors. + */ using InlineContainer::InlineContainer; + /** Order inline code by literal content. + */ auto operator<=>(CodeInline const&) const = default; + /** Equality compares inline content. + */ bool operator==(CodeInline const&) const noexcept = default; }; -/** Map the @ref Code to a @ref dom::Object. +/** Map the @ref CodeInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -49,8 +67,8 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref Code as a @ref dom::Value object. - */ +/** Return the @ref CodeInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/CopyDetailsInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/CopyDetailsInline.hpp index 36c4ffa960..992ec5df8f 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/CopyDetailsInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/CopyDetailsInline.hpp @@ -20,29 +20,45 @@ namespace mrdocs::doc { /** Documentation copied from another symbol. + + Syntax: + + @code + @copydetails other_symbol + @endcode */ struct CopyDetailsInline final : InlineCommonBase { + /** Element to copy the details from + */ std::string string; + /** Symbol to copy details from. + */ SymbolID id = SymbolID::invalid; + /** Construct with optional text payload. + */ CopyDetailsInline(std::string string_ = std::string()) noexcept : string(std::move(string_)) { } + /** Order copy directives by text and symbol id. + */ auto operator<=>(CopyDetailsInline const&) const = default; + /** Equality compares text and symbol id. + */ bool operator==(CopyDetailsInline const&) const noexcept = default; }; -/** Map the @ref CopyDetails to a @ref dom::Object. +/** Map the @ref CopyDetailsInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -56,12 +72,12 @@ tag_invoke( io.map("symbol", I.id); } -/** Return the @ref CopyDetails as a @ref dom::Value object. +/** Return the @ref CopyDetailsInline as a @ref dom::Value object. @param v The output value. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/EmphInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/EmphInline.hpp index 1d78383cc1..0c7e970bbd 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/EmphInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/EmphInline.hpp @@ -19,24 +19,38 @@ namespace mrdocs::doc { -/** A piece of styled text. +/** Emphasized text (typically rendered in italics). + + Syntax: + + @code + @e emphasized or *italic text* or _italic text_ + @endcode */ struct EmphInline final : InlineCommonBase , InlineContainer { + /** Inherit inline container constructors. + */ using InlineContainer::InlineContainer; + + /** Order emphasis spans by their contents. + */ auto operator<=>(EmphInline const&) const = default; + + /** Equality compares contained text. + */ bool operator==(EmphInline const&) const noexcept = default; }; -/** Map the @ref Emph to a @ref dom::Object. +/** Map the @ref EmphInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -49,8 +63,8 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref Emph as a @ref dom::Value object. - */ +/** Return the @ref EmphInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/FootnoteReferenceInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/FootnoteReferenceInline.hpp index c8fe61f5bd..85b051a7db 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/FootnoteReferenceInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/FootnoteReferenceInline.hpp @@ -22,22 +22,35 @@ namespace mrdocs::doc { /** A reference to a symbol. In markdown, this is represented as "[^label]". + + Syntax: + + @code + [^footnote-id] + @endcode */ struct FootnoteReferenceInline : InlineCommonBase { + /** Footnote label that the reference points to. + */ std::string label; + + /** Order references by their label. + */ auto operator<=>(FootnoteReferenceInline const&) const = default; + /** Equality compares labels. + */ bool operator==(FootnoteReferenceInline const&) const noexcept = default; }; -/** Map the @ref FootnoteReference to a @ref dom::Object. +/** Map the @ref FootnoteReferenceInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -50,8 +63,8 @@ tag_invoke( io.map("label", I.label); } -/** Return the @ref FootnoteReference as a @ref dom::Value object. - */ +/** Return the @ref FootnoteReferenceInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/HighlightInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/HighlightInline.hpp index ca1ab3ab27..7d9a278e4d 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/HighlightInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/HighlightInline.hpp @@ -19,23 +19,33 @@ namespace mrdocs::doc { -/** A piece of highlighted text. +/** Highlighted text span used to call out important words. + + Syntax: + + @code + ==highlight== or highlighted + @endcode */ struct HighlightInline final : InlineCommonBase , InlineContainer { + /** Order highlights by their inline content. + */ auto operator<=>(HighlightInline const&) const = default; + /** Equality compares inline content. + */ bool operator==(HighlightInline const&) const noexcept = default; }; -/** Map the @ref Highlight to a @ref dom::Object. +/** Map the @ref HighlightInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -48,8 +58,8 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref Highlight as a @ref dom::Value object. - */ +/** Return the @ref HighlightInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/ImageInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/ImageInline.hpp index 5d4695e653..3a9c441e3c 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/ImageInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/ImageInline.hpp @@ -20,25 +20,45 @@ namespace mrdocs::doc { /** An image. + + Syntax: + + @code + @image html path/to/img "alt text" + @endcode + + or + + @code + ![Alt text](image_url "Optional title text") + @endcode */ struct ImageInline final : InlineCommonBase , InlineContainer { + /** Image source URL or path. + */ std::string src; + /** Alternate text when the image cannot be shown. + */ std::string alt; + /** Order images by source, alt text, and inline children. + */ auto operator<=>(ImageInline const&) const = default; + /** Equality compares source, alt text, and contents. + */ bool operator==(ImageInline const&) const noexcept = default; }; -/** Map the @ref Image to a @ref dom::Object. +/** Map the @ref ImageInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -53,8 +73,8 @@ tag_invoke( io.map("alt", I.alt); } -/** Return the @ref Image as a @ref dom::Value object. - */ +/** Return the @ref ImageInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/InlineBase.hpp b/include/mrdocs/Metadata/DocComment/Inline/InlineBase.hpp index 09b36ea1f9..ca193ece01 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/InlineBase.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/InlineBase.hpp @@ -36,18 +36,30 @@ namespace mrdocs::doc { */ struct MRDOCS_DECL Inline { + /** Discriminator identifying which inline variant is active. + */ InlineKind Kind = InlineKind::Text; + /** Virtual destructor to enable polymorphic deletion. + */ virtual ~Inline() = default; + /** Three-way comparison by active inline kind and data. + */ auto operator<=>(Inline const&) const = default; + /** Equality compares active kind and stored data. + */ bool operator==(Inline const&) const noexcept = default; + /** View as const Inline reference. + */ constexpr Inline const& asInline() const noexcept { return *this; } + /** View as mutable Inline reference. + */ constexpr Inline& asInline() noexcept { return *this; @@ -74,10 +86,14 @@ struct MRDOCS_DECL Inline } #include -#define INFO(Type) \ - constexpr Type##Inline const* as##Type##Ptr() const noexcept { \ - if (Kind == InlineKind::Type) { return reinterpret_cast(this); } \ - return nullptr; \ +#define INFO(Type) \ + constexpr Type##Inline const* as##Type##Ptr() const noexcept \ + { \ + if (Kind == InlineKind::Type) \ + { \ + return reinterpret_cast(this); \ + } \ + return nullptr; \ } #include @@ -89,8 +105,12 @@ struct MRDOCS_DECL Inline #include protected: + /** Default-construct a text inline. + */ constexpr Inline() noexcept = default; + /** Construct with a specific inline kind. + */ Inline( InlineKind kind_) : Kind(kind_) @@ -111,18 +131,24 @@ struct InlineCommonBase : Inline It only distinguishes from `Inline::kind` in that it is a constant. - */ + */ static constexpr InlineKind kind_id = K; + /** Virtual destructor to preserve polymorphic cleanup. + */ virtual ~InlineCommonBase() override = default; #define INFO(Kind) \ static constexpr bool is##Kind() noexcept { return K == InlineKind::Kind; } #include + /** Three-way comparison forwards to the underlying inline. + */ auto operator<=>(InlineCommonBase const&) const = default; protected: + /** Default-construct with the fixed inline kind. + */ constexpr explicit InlineCommonBase() : Inline(K) {} @@ -135,7 +161,7 @@ struct InlineCommonBase : Inline @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -148,7 +174,7 @@ tag_invoke( } /** Return the @ref Inline as a @ref dom::Value object. - */ +*/ inline void tag_invoke( @@ -166,7 +192,7 @@ tag_invoke( @param in The input inline element. @param dst The output string to append to. - */ +*/ MRDOCS_DECL void getAsPlainText(doc::Inline const& in, std::string& dst); @@ -177,7 +203,7 @@ getAsPlainText(doc::Inline const& in, std::string& dst); @param in The input inline element. @return The flattened plain text. - */ +*/ inline std::string getAsPlainText(doc::Inline const& in) @@ -187,17 +213,27 @@ getAsPlainText(doc::Inline const& in) return dst; } -/// An internal node in the inline element tree +/// An internal node in the inline element tree. struct MRDOCS_DECL InlineContainer { + /** Child inline elements contained here. + */ std::vector> children; + /** Virtual destructor for derived containers. + */ virtual ~InlineContainer() = default; + /** Default-construct an empty container. + */ InlineContainer() = default; + /** Copy-construct all child nodes. + */ InlineContainer(InlineContainer const&) = default; + /** Move-construct child nodes. + */ InlineContainer(InlineContainer&&) noexcept = default; /// Construct an InlineContainer with a single TextInline child. @@ -218,9 +254,13 @@ struct MRDOCS_DECL InlineContainer explicit InlineContainer(std::string&& text); + /** Copy-assign child nodes. + */ InlineContainer& operator=(InlineContainer const&) = default; + /** Move-assign child nodes. + */ InlineContainer& operator=(InlineContainer&&) noexcept = default; @@ -228,15 +268,17 @@ struct MRDOCS_DECL InlineContainer InlineContainer& operator=(std::string_view text); - /// Helper function so that derived classes can get a reference to - /// the base class. + /** Return this container as a base-class reference. + + @return A reference to the underlying InlineContainer. + */ InlineContainer& asInlineContainer() { return *this; } - /// @copydoc asInlineContainer + /// @copydoc asInlineContainer() InlineContainer const& asInlineContainer() const { @@ -289,28 +331,46 @@ struct MRDOCS_DECL InlineContainer return children.size(); } - /// Begin iterator forwarding to children + /** Begin iterator forwarding to children. + + @param self The container instance. + @return Iterator to the first child. + */ decltype(auto) begin(this auto&& self) noexcept { return self.children.begin(); } - /// End iterator forwarding to children + /** End iterator forwarding to children. + + @param self The container instance. + @return Iterator past the last child. + */ decltype(auto) end(this auto&& self) noexcept { return self.children.end(); } - /// Erase from children + /** Erase inline children. + + @param self The container instance. + @param args Arguments forwarded to `std::vector::erase`. + @return The iterator returned by `erase`. + */ decltype(auto) erase(this auto&& self, auto&&... args) { return self.children.erase(std::forward(args)...); } - /// Erase from children + /** Insert inline children. + + @param self The container instance. + @param args Arguments forwarded to `std::vector::insert`. + @return The iterator returned by `insert`. + */ decltype(auto) insert(this auto&& self, auto&&... args) { @@ -324,11 +384,20 @@ struct MRDOCS_DECL InlineContainer children.clear(); } - /// Append a TextInline child. + /** Append a TextInline child. + + @param text The text to append. + @return A reference to this container. + */ InlineContainer& append(std::string_view text); - /// Append a child of the specified type. + /** Append a child of the specified type. + + @tparam InlineTy The Inline-derived type to add. + @param args Constructor arguments forwarded to the child. + @return A reference to this container. + */ template InlineTy, class... Args> InlineContainer& append(Args&&... args) @@ -353,7 +422,12 @@ struct MRDOCS_DECL InlineContainer return *this; } - /// Append a child of the specified type. + /** Append a child of the specified type in-place. + + @tparam InlineTy The Inline-derived type to emplace. + @param args Constructor arguments forwarded to the child. + @return A reference to this container. + */ template InlineTy, class... Args> InlineContainer& emplace_back(Args&&... args) @@ -362,15 +436,22 @@ struct MRDOCS_DECL InlineContainer return *this; } - /// Compare two InlineContainers. + /** Compare two InlineContainers. + */ std::strong_ordering operator<=>(InlineContainer const&) const; - /// Compare two InlineContainers. + /** Equality compares child sequences. + */ bool operator==(InlineContainer const&) const = default; }; +/** Serialize a polymorphic inline node into a DOM value. + @param io Destination value. + @param I Inline storage to convert. + @param domCorpus Corpus context for lazy references. +*/ template InlineTy> void tag_invoke( @@ -379,6 +460,13 @@ tag_invoke( InlineTy const& I, DomCorpus const* domCorpus); +/** Map an InlineContainer into a DOM object. + + @param t The mapping tag. + @param io Output object receiving serialized fields. + @param I Inline container to serialize. + @param domCorpus Optional corpus for lazy lookups. +*/ template void tag_invoke( @@ -393,6 +481,8 @@ tag_invoke( } inline +/** Convert an InlineContainer to a DOM value. +*/ void tag_invoke( dom::ValueFromTag, @@ -407,7 +497,7 @@ tag_invoke( @param inlines The InlineContainer to trim. @return void - */ +*/ MRDOCS_DECL void ltrim(InlineContainer& inlines); @@ -416,7 +506,7 @@ ltrim(InlineContainer& inlines); @param inlines The InlineContainer to trim. @return void - */ +*/ MRDOCS_DECL void rtrim(InlineContainer& inlines); @@ -425,7 +515,7 @@ rtrim(InlineContainer& inlines); @param inlines The InlineContainer to trim. @return void - */ +*/ inline void trim(InlineContainer& inlines) @@ -440,7 +530,7 @@ trim(InlineContainer& inlines) @param in The InlineContainer to flatten. @param dst The output string to append to. - */ +*/ MRDOCS_DECL void getAsPlainText(doc::InlineContainer const& in, std::string& dst); @@ -451,7 +541,7 @@ getAsPlainText(doc::InlineContainer const& in, std::string& dst); @param in The InlineContainer to flatten. @return The flattened plain text. - */ +*/ inline std::string getAsPlainText(doc::InlineContainer const& in) @@ -464,24 +554,36 @@ getAsPlainText(doc::InlineContainer const& in) /// A leaf node that stores a string of text. struct MRDOCS_DECL InlineTextLeaf { + /** Raw literal text stored in this leaf node. + */ std::string literal; + /** Construct from a string view. + */ explicit InlineTextLeaf(std::string_view literal_) : literal(literal_) {} + /** Construct from a string copy. + */ explicit InlineTextLeaf(std::string const& literal_) : literal(literal_) {} + /** Construct by moving a string. + */ explicit InlineTextLeaf(std::string&& literal_) noexcept : literal(std::move(literal_)) {} + /** Order text leaves lexicographically by content. + */ auto operator<=>(InlineTextLeaf const&) const = default; + /** Equality compares literal text. + */ bool operator==(InlineTextLeaf const&) const noexcept = default; }; diff --git a/include/mrdocs/Metadata/DocComment/Inline/InlineKind.hpp b/include/mrdocs/Metadata/DocComment/Inline/InlineKind.hpp index 38570e8225..4d88cfbeaf 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/InlineKind.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/InlineKind.hpp @@ -16,11 +16,15 @@ namespace mrdocs::doc { +/** Enumerates the different kinds of inline nodes. +*/ enum class InlineKind { - #define INFO(Type) Type, +#define INFO(Type) Type, #include }; +/** Convert an inline kind to its kebab-case string. +*/ inline dom::String toString(InlineKind kind) noexcept @@ -33,11 +37,16 @@ toString(InlineKind kind) noexcept return "Unknown"; } +/** Serialize an inline kind into a DOM value. + @param v Destination DOM value. + @param kind Kind to serialize. +*/ inline void tag_invoke( dom::ValueFromTag, - dom::Value& v, InlineKind const kind) + dom::Value& v, + InlineKind const kind) { v = toString(kind); } diff --git a/include/mrdocs/Metadata/DocComment/Inline/LineBreakInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/LineBreakInline.hpp index 45e535690a..5822416e31 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/LineBreakInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/LineBreakInline.hpp @@ -19,23 +19,47 @@ namespace mrdocs::doc { /** A hard line break that renders as "
" + + Syntax: + + @code + first line\ + second line + @endcode + + or + + @code + first line
second line + @endcode */ struct LineBreakInline : InlineCommonBase { + /** Virtual destructor for the inline hierarchy. + */ constexpr ~LineBreakInline() override = default; + + /** Construct a line break node. + */ constexpr LineBreakInline() noexcept = default; + + /** Order line breaks (trivial). + */ auto operator<=>(LineBreakInline const&) const = default; + + /** Equality compares line breaks (trivial). + */ bool operator==(LineBreakInline const&) const noexcept = default; }; -/** Map the @ref LineBreak to a @ref dom::Object. +/** Map the @ref LineBreakInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -47,8 +71,8 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref LineBreak as a @ref dom::Value object. - */ +/** Return the @ref LineBreakInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/LinkInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/LinkInline.hpp index 947a51047a..3d3df933db 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/LinkInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/LinkInline.hpp @@ -19,31 +19,63 @@ namespace mrdocs::doc { /** A hyperlink. + + Syntax: + + @code + @link https://example.com label @endlink + @endcode + + Or with markdown syntax: + + @code + [link text](URL) + [link text](URL "title") + @endcode + + Or: + + @code + Visit Example.com + @endcode */ struct LinkInline final : InlineCommonBase , InlineContainer { + /** Destination of the hyperlink. + */ std::string href; + /** Construct an empty link. + */ LinkInline() = default; + /** Construct a link with display text and target. + + @param text Link text to display. + @param href Destination URI. + */ LinkInline(std::string_view text, std::string_view href) : InlineContainer(text) , href(href) {} + /** Order links by href and child content. + */ auto operator<=>(LinkInline const&) const = default; + /** Equality compares href and child content. + */ bool operator==(LinkInline const&) const noexcept = default; }; -/** Map the @ref Link to a @ref dom::Object. +/** Map the @ref LinkInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -57,8 +89,8 @@ tag_invoke( io.map("href", I.href); } -/** Return the @ref Link as a @ref dom::Value object. - */ +/** Return the @ref LinkInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/MathInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/MathInline.hpp index 9ba7aceb13..e4ba880cf9 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/MathInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/MathInline.hpp @@ -21,30 +21,48 @@ namespace mrdocs::doc { /** An inline LaTeX math expression Inline LaTeX math, typically between $…$. - */ + + Syntax: + + @code + $2 + 2 = 4$ or $x_{i+1}^2$ + @endcode +*/ struct MathInline : InlineCommonBase { + /** Raw LaTeX/TeX math content. + */ std::string literal; + /** Virtual destructor for inline hierarchy. + */ constexpr ~MathInline() override = default; + /** Construct an empty math inline. + */ constexpr MathInline() noexcept = default; + /** Construct a math inline from source text. + */ explicit MathInline(std::string string_) noexcept : literal(std::move(string_)) {} + /** Order math spans by their literal content. + */ auto operator<=>(MathInline const&) const = default; + /** Equality compares literal content. + */ bool operator==(MathInline const&) const noexcept = default; }; -/** Map the @ref Math to a @ref dom::Object. +/** Map the @ref MathInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -57,8 +75,8 @@ tag_invoke( io.map("literal", I.literal); } -/** Return the @ref Math as a @ref dom::Value object. - */ +/** Return the @ref MathInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/Parts.hpp b/include/mrdocs/Metadata/DocComment/Inline/Parts.hpp index 9a417e1244..1b1f21c5b4 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/Parts.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/Parts.hpp @@ -36,13 +36,13 @@ enum class Parts }; /** Return the name of the Parts as a string. - */ +*/ MRDOCS_DECL dom::String toString(Parts kind) noexcept; /** Return the Parts from a @ref dom::Value string. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/ReferenceInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/ReferenceInline.hpp index 8cd7db65d2..5534cbf0d8 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/ReferenceInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/ReferenceInline.hpp @@ -22,28 +22,44 @@ namespace mrdocs::doc { /** A reference to a symbol. + + Syntax: + + @code + @ref target "label" + @endcode */ struct ReferenceInline : InlineCommonBase { + /** Display text of the reference. + */ std::string literal; + /** Symbol being referenced. + */ SymbolID id = SymbolID::invalid; + /** Construct a reference with optional display text. + */ explicit ReferenceInline(std::string str = {}) noexcept : literal(std::move(str)) {} + /** Order references by literal and target id. + */ auto operator<=>(ReferenceInline const&) const = default; + /** Equality compares literal and target id. + */ bool operator==(ReferenceInline const&) const noexcept = default; }; -/** Map the @ref Reference to a @ref dom::Object. +/** Map the @ref ReferenceInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -57,8 +73,8 @@ tag_invoke( io.map("symbol", I.id); } -/** Return the @ref Reference as a @ref dom::Value object. - */ +/** Return the @ref ReferenceInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/SoftBreakInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/SoftBreakInline.hpp index 35a77e1664..780e4c9b45 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/SoftBreakInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/SoftBreakInline.hpp @@ -18,24 +18,49 @@ namespace mrdocs::doc { -/** A line break that may render as space +/** A line break that may render as a space + + Syntax: + + @code + This is the first part of a line, + and this is the continuation on the next line. + @endcode + + Placing a backslash (`\`) at the end of a line, + followed by a new line, can also create a soft line break. + This method is often preferred because it is less susceptible + to space-trimming issues. + + @code + This is the first part of a line,\ + and this is the continuation on the next line. + @endcode */ struct SoftBreakInline : InlineCommonBase { + /** Virtual destructor for inline hierarchy. + */ constexpr ~SoftBreakInline() override = default; + /** Construct a soft line break node. + */ constexpr SoftBreakInline() noexcept = default; + /** Order soft breaks (trivial). + */ auto operator<=>(SoftBreakInline const&) const = default; + /** Equality compares soft breaks (trivial). + */ bool operator==(SoftBreakInline const&) const noexcept = default; }; -/** Map the @ref SoftBreak to a @ref dom::Object. +/** Map the @ref SoftBreakInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -47,8 +72,8 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref SoftBreak as a @ref dom::Value object. - */ +/** Return the @ref SoftBreakInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/StrikethroughInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/StrikethroughInline.hpp index f0f38470d4..8ecd944701 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/StrikethroughInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/StrikethroughInline.hpp @@ -19,23 +19,43 @@ namespace mrdocs::doc { -/** A piece of styled text. +/** Strikethrough span to show removed or deprecated text. + + Syntax: + + @code + ~~crossed out~~ + @endcode + + When rendered to HTML, the Markdown syntax above + typically translates into the `del` tag, which + represents content that has been deleted or is no + longer accurate. + + @code + This text is struck through. + @endcode + */ struct StrikethroughInline final : InlineCommonBase , InlineContainer { + /** Order strikethrough spans by their children. + */ auto operator<=>(StrikethroughInline const&) const = default; + /** Equality compares contained inline children. + */ bool operator==(StrikethroughInline const&) const noexcept = default; }; -/** Map the @ref Strikethrough to a @ref dom::Object. +/** Map the @ref StrikethroughInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -48,8 +68,8 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref Strikethrough as a @ref dom::Value object. - */ +/** Return the @ref StrikethroughInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/StrongInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/StrongInline.hpp index 1eb209280d..e7f5981a97 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/StrongInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/StrongInline.hpp @@ -19,24 +19,36 @@ namespace mrdocs::doc { -/** A piece of styled text. +/** Strong emphasis span (typically rendered in bold). + + Syntax: + + @code + @b bold + @endcode */ struct StrongInline final : InlineCommonBase , InlineContainer { + /** Inherit text container constructors. + */ using InlineContainer::InlineContainer; + /** Order strong spans by their children. + */ auto operator<=>(StrongInline const&) const = default; + /** Equality compares contained inline children. + */ bool operator==(StrongInline const&) const noexcept = default; }; -/** Map the @ref Strong to a @ref dom::Object. +/** Map the @ref StrongInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -49,8 +61,8 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref Strong as a @ref dom::Value object. - */ +/** Return the @ref StrongInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/SubscriptInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/SubscriptInline.hpp index 84461d57b6..a03140c99f 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/SubscriptInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/SubscriptInline.hpp @@ -19,23 +19,33 @@ namespace mrdocs::doc { -/** A piece of styled text. +/** Subscript text fragment (lowered baseline). + + Syntax: + + @code + H~2~O + @endcode */ struct SubscriptInline final : InlineCommonBase , InlineContainer { + /** Order subscript spans by their children. + */ auto operator<=>(SubscriptInline const&) const = default; + /** Equality compares contained inline children. + */ bool operator==(SubscriptInline const&) const noexcept = default; }; -/** Map the @ref Subscript to a @ref dom::Object. +/** Map the @ref SubscriptInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -48,8 +58,8 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref Subscript as a @ref dom::Value object. - */ +/** Return the @ref SubscriptInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/SuperscriptInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/SuperscriptInline.hpp index 772c6b4ad8..16617b99f9 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/SuperscriptInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/SuperscriptInline.hpp @@ -19,23 +19,33 @@ namespace mrdocs::doc { -/** A piece of styled text. +/** Superscript text fragment (raised baseline). + + Syntax: + + @code + x^2^ + @endcode */ struct SuperscriptInline final : InlineCommonBase , InlineContainer { + /** Order superscript spans by their children. + */ auto operator<=>(SuperscriptInline const&) const = default; + /** Equality compares contained inline children. + */ bool operator==(SuperscriptInline const&) const noexcept = default; }; -/** Map the @ref Superscript to a @ref dom::Object. +/** Map the @ref SuperscriptInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -48,8 +58,8 @@ tag_invoke( tag_invoke(t, io, dynamic_cast(I), domCorpus); } -/** Return the @ref Superscript as a @ref dom::Value object. - */ +/** Return the @ref SuperscriptInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DocComment/Inline/TextInline.hpp b/include/mrdocs/Metadata/DocComment/Inline/TextInline.hpp index 0df55cae72..7a3859ca76 100644 --- a/include/mrdocs/Metadata/DocComment/Inline/TextInline.hpp +++ b/include/mrdocs/Metadata/DocComment/Inline/TextInline.hpp @@ -23,43 +23,67 @@ namespace mrdocs::doc { There will be no newlines in the text. Otherwise, this would be represented as multiple text nodes within a Paragraph node. + + Syntax: + + @code + plain text + @endcode */ struct TextInline : InlineCommonBase { + /** Plain text carried by this inline node. + */ std::string literal; + /** Virtual destructor for the inline hierarchy. + */ constexpr ~TextInline() override = default; + /** Construct an empty text inline. + */ constexpr TextInline() noexcept = default; + /** Construct from a string view. + */ explicit TextInline(std::string_view str) noexcept : literal(str) {} + /** Construct from a C string. + */ explicit TextInline(char const* str) noexcept : literal(str) {} + /** Construct from a string copy. + */ explicit TextInline(std::string const& str) noexcept : literal(str) {} + /** Construct by moving text storage. + */ explicit TextInline(std::string&& str) noexcept : literal(std::move(str)) {} + /** Order text nodes lexicographically by their literal. + */ auto operator<=>(TextInline const&) const = default; + /** Equality compares literal strings. + */ bool operator==(TextInline const&) const noexcept = default; }; -/** Map the @ref Text to a @ref dom::Object. +/** Map the @ref TextInline to a @ref dom::Object. @param t The tag. @param io The output object. @param I The input object. @param domCorpus The DOM corpus, or nullptr if not part of a corpus. - */ +*/ template void tag_invoke( @@ -72,8 +96,8 @@ tag_invoke( io.map("literal", I.literal); } -/** Return the @ref Text as a @ref dom::Value object. - */ +/** Return the @ref TextInline as a @ref dom::Value object. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/DomCorpus.hpp b/include/mrdocs/Metadata/DomCorpus.hpp index 3eab8ade3e..71cde66fc5 100644 --- a/include/mrdocs/Metadata/DomCorpus.hpp +++ b/include/mrdocs/Metadata/DomCorpus.hpp @@ -107,7 +107,7 @@ class MRDOCS_DECL }; /** Return a list of the parent symbols of the specified Info. - */ +*/ MRDOCS_DECL dom::Array getParents(DomCorpus const& C, Symbol const& I); diff --git a/include/mrdocs/Metadata/Expression.hpp b/include/mrdocs/Metadata/Expression.hpp index e2bc032b87..871cd7447b 100644 --- a/include/mrdocs/Metadata/Expression.hpp +++ b/include/mrdocs/Metadata/Expression.hpp @@ -19,35 +19,47 @@ namespace mrdocs { -/** Represents an expression */ +/** Represents an expression +*/ struct ExprInfo { - /** The expression, as written */ + /** The expression, as written + */ std::string Written; + /** View this object as its base expression. + */ ExprInfo& asExpr() noexcept { return *this; } + /** View this object as its base expression. + */ ExprInfo const& asExpr() const noexcept { return *this; } + /** Order expressions by written form. + */ auto operator<=>(ExprInfo const&) const = default; }; +/** Merge metadata from another expression. +*/ MRDOCS_DECL void merge(ExprInfo& I, ExprInfo&& Other); -/** Represents an expression with a (possibly known) value */ +/** Represents an expression with a (possibly known) value +*/ template struct ConstantExprInfo : ExprInfo { - /** The underlying type of the expression */ + /** The underlying type of the expression + */ using type = T; /** The expressions value, if it is known @@ -57,11 +69,15 @@ struct ConstantExprInfo */ Optional Value; + /** Order constant expressions by written form and value. + */ auto operator<=>(ConstantExprInfo const&) const = default; static_assert(std::integral, "expression type must be integral"); }; +/** Merge metadata from another constant expression. +*/ template static void merge( ConstantExprInfo& I, diff --git a/include/mrdocs/Metadata/Name.hpp b/include/mrdocs/Metadata/Name.hpp index c97340fe84..e816e0cf7b 100644 --- a/include/mrdocs/Metadata/Name.hpp +++ b/include/mrdocs/Metadata/Name.hpp @@ -42,16 +42,22 @@ visit( } } +/** Three-way comparison for polymorphic Name variants. +*/ MRDOCS_DECL std::strong_ordering operator<=>(Polymorphic const& lhs, Polymorphic const& rhs); +/** Equality compare two polymorphic names. +*/ inline bool operator==(Polymorphic const& lhs, Polymorphic const& rhs) { return lhs <=> rhs == std::strong_ordering::equal; } +/** Serialize a polymorphic name into a DOM value. +*/ inline void tag_invoke( @@ -64,6 +70,8 @@ tag_invoke( tag_invoke(dom::ValueFromTag{}, v, *I, domCorpus); } +/** Serialize an optional polymorphic name into a DOM value. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Name/IdentifierName.hpp b/include/mrdocs/Metadata/Name/IdentifierName.hpp index ce4ec36a46..7eef596f23 100644 --- a/include/mrdocs/Metadata/Name/IdentifierName.hpp +++ b/include/mrdocs/Metadata/Name/IdentifierName.hpp @@ -31,11 +31,15 @@ namespace mrdocs { struct IdentifierName final : Name { + /** Default-construct an identifier with kind Identifier. + */ constexpr IdentifierName() noexcept : Name(NameKind::Identifier) {} + /** Compare identifiers by their base name state. + */ auto operator<=>(IdentifierName const& other) const { diff --git a/include/mrdocs/Metadata/Name/NameBase.hpp b/include/mrdocs/Metadata/Name/NameBase.hpp index ea3f0285fd..d7dfa98391 100644 --- a/include/mrdocs/Metadata/Name/NameBase.hpp +++ b/include/mrdocs/Metadata/Name/NameBase.hpp @@ -36,7 +36,7 @@ namespace mrdocs { which contains the arguments for a template specialization without requiring the application to extract an unnecessary symbol. - */ +*/ struct Name { /** The kind of name this is. @@ -48,7 +48,7 @@ struct Name SymbolID id = SymbolID::invalid; /** The unqualified name. - */ + */ std::string Identifier; /** The parent name info, if any. @@ -63,26 +63,35 @@ struct Name In this case, the Prefix will contain this primary template information and the template arguments. - - */ + */ Optional> Prefix = std::nullopt; + /** Virtual destructor for polymorphic cleanup. + */ constexpr virtual ~Name() = default; + /** Order names by kind, identifier, id, and prefix. + */ std::strong_ordering operator<=>(Name const& other) const; + /** Equality compares all fields. + */ bool operator==(Name const& other) const { return std::is_eq(*this <=> other); } + /** View as a const Name reference. + */ constexpr Name const& asName() const noexcept { return *this; } + /** View as a mutable Name reference. + */ constexpr Name& asName() noexcept { return *this; @@ -124,20 +133,29 @@ struct Name #include protected: + /** Construct an identifier name. + */ constexpr Name() noexcept : Kind(NameKind::Identifier) {}; + /** Construct with an explicit name kind. + */ explicit constexpr Name(NameKind const kind) noexcept : Kind(kind) {} }; +/** Convert the name to a human-readable string. + @return The textual form of the name. +*/ MRDOCS_DECL std::string toString(Name const& N); +/** Serialize a name into a DOM value. +*/ MRDOCS_DECL void tag_invoke( diff --git a/include/mrdocs/Metadata/Name/NameKind.hpp b/include/mrdocs/Metadata/Name/NameKind.hpp index 819c230a33..42589c29bd 100644 --- a/include/mrdocs/Metadata/Name/NameKind.hpp +++ b/include/mrdocs/Metadata/Name/NameKind.hpp @@ -16,15 +16,21 @@ namespace mrdocs { +/** Kinds of names that appear in type and symbol metadata. +*/ enum class NameKind { #define INFO(Type) Type, #include }; +/** Convert a NameKind to its string form. +*/ MRDOCS_DECL dom::String toString(NameKind kind) noexcept; +/** Map a NameKind into a DOM value. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Name/SpecializationName.hpp b/include/mrdocs/Metadata/Name/SpecializationName.hpp index a7ad1090e8..7c33ab8e47 100644 --- a/include/mrdocs/Metadata/Name/SpecializationName.hpp +++ b/include/mrdocs/Metadata/Name/SpecializationName.hpp @@ -30,11 +30,15 @@ struct SpecializationName final */ SymbolID specializationID = SymbolID::invalid; + /** Construct an empty specialization name. + */ constexpr SpecializationName() noexcept : Name(NameKind::Specialization) {} + /** Compare specialization names by base name and template arguments. + */ auto operator<=>(SpecializationName const& other) const { diff --git a/include/mrdocs/Metadata/Specifiers/AccessKind.hpp b/include/mrdocs/Metadata/Specifiers/AccessKind.hpp index 430385ec6b..6999e71391 100644 --- a/include/mrdocs/Metadata/Specifiers/AccessKind.hpp +++ b/include/mrdocs/Metadata/Specifiers/AccessKind.hpp @@ -41,12 +41,14 @@ enum class AccessKind Private, }; +/** Convert access specifier to its string form. +*/ MRDOCS_DECL dom::String toString(AccessKind kind) noexcept; /** Return the AccessKind as a @ref dom::Value string. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Specifiers/ConstexprKind.hpp b/include/mrdocs/Metadata/Specifiers/ConstexprKind.hpp index 9ec35ee00b..0375e7bed7 100644 --- a/include/mrdocs/Metadata/Specifiers/ConstexprKind.hpp +++ b/include/mrdocs/Metadata/Specifiers/ConstexprKind.hpp @@ -33,12 +33,14 @@ enum class ConstexprKind Consteval, }; +/** Convert a constexpr/consteval specifier kind to a string. +*/ MRDOCS_DECL dom::String toString(ConstexprKind kind) noexcept; /** Return the ConstexprKind as a @ref dom::Value string. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Specifiers/ExplicitInfo.hpp b/include/mrdocs/Metadata/Specifiers/ExplicitInfo.hpp index ff95626e4a..8b5fdf7fe4 100644 --- a/include/mrdocs/Metadata/Specifiers/ExplicitInfo.hpp +++ b/include/mrdocs/Metadata/Specifiers/ExplicitInfo.hpp @@ -37,6 +37,8 @@ struct ExplicitInfo */ std::string Operand; + /** Compare explicit-specifier info. + */ auto operator<=>(ExplicitInfo const&) const = default; }; @@ -59,7 +61,7 @@ toString( @param v The output parameter to receive the dom::Value. @param I The ExplicitInfo to convert. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Specifiers/ExplicitKind.hpp b/include/mrdocs/Metadata/Specifiers/ExplicitKind.hpp index 19a93923f2..8df1d9e63d 100644 --- a/include/mrdocs/Metadata/Specifiers/ExplicitKind.hpp +++ b/include/mrdocs/Metadata/Specifiers/ExplicitKind.hpp @@ -33,6 +33,8 @@ enum class ExplicitKind Dependent }; +/** Convert an explicit kind to its string form. +*/ MRDOCS_DECL dom::String toString(ExplicitKind kind) noexcept; diff --git a/include/mrdocs/Metadata/Specifiers/NoexceptInfo.hpp b/include/mrdocs/Metadata/Specifiers/NoexceptInfo.hpp index 48a644f90c..e2512d9ed5 100644 --- a/include/mrdocs/Metadata/Specifiers/NoexceptInfo.hpp +++ b/include/mrdocs/Metadata/Specifiers/NoexceptInfo.hpp @@ -22,7 +22,8 @@ namespace mrdocs { -// KRYSTIAN FIXME: this needs to be improved (a lot) +/** Captures a `noexcept` specification and its evaluated form. +*/ struct NoexceptInfo { /** Whether a noexcept-specifier was user-written. @@ -37,6 +38,8 @@ struct NoexceptInfo */ std::string Operand; + /** Compare noexcept-specifier info. + */ auto operator<=>(NoexceptInfo const&) const = default; }; @@ -59,10 +62,12 @@ toString( bool resolved = false, bool implicit = false); +/** Convert a NoexceptInfo to a DOM value. +*/ inline void tag_invoke( - dom::ValueFromTag, + dom::ValueFromTag tag, dom::Value& v, NoexceptInfo const& info) { diff --git a/include/mrdocs/Metadata/Specifiers/NoexceptKind.hpp b/include/mrdocs/Metadata/Specifiers/NoexceptKind.hpp index 4ef3f8f136..0125f3b4a5 100644 --- a/include/mrdocs/Metadata/Specifiers/NoexceptKind.hpp +++ b/include/mrdocs/Metadata/Specifiers/NoexceptKind.hpp @@ -33,6 +33,8 @@ enum class NoexceptKind Dependent }; +/** Convert a noexcept kind to its string form. +*/ MRDOCS_DECL dom::String toString(NoexceptKind kind) noexcept; diff --git a/include/mrdocs/Metadata/Specifiers/OperatorKind.hpp b/include/mrdocs/Metadata/Specifiers/OperatorKind.hpp index fef84be796..669c6f1386 100644 --- a/include/mrdocs/Metadata/Specifiers/OperatorKind.hpp +++ b/include/mrdocs/Metadata/Specifiers/OperatorKind.hpp @@ -120,6 +120,8 @@ enum class OperatorKind Coawait, }; +/** Map an operator kind to a DOM value (its underlying integer). +*/ inline void tag_invoke( @@ -131,13 +133,13 @@ tag_invoke( } /** Determines whether the operator is potentially unary. - */ +*/ MRDOCS_DECL bool isUnaryOperator(OperatorKind kind) noexcept; /** Determines whether the operator is potentially binary. - */ +*/ MRDOCS_DECL bool isBinaryOperator(OperatorKind kind) noexcept; @@ -196,7 +198,7 @@ getSafeOperatorName( @param kind The kind of operator. @param nParams The number of parameters the operator takes. @return The readable name, or nullopt if the operator is not recognized. - */ +*/ Optional getOperatorReadableName( OperatorKind kind, diff --git a/include/mrdocs/Metadata/Specifiers/ReferenceKind.hpp b/include/mrdocs/Metadata/Specifiers/ReferenceKind.hpp index 608e736659..492b8afb2d 100644 --- a/include/mrdocs/Metadata/Specifiers/ReferenceKind.hpp +++ b/include/mrdocs/Metadata/Specifiers/ReferenceKind.hpp @@ -30,10 +30,12 @@ enum class ReferenceKind RValue }; +/** Convert a reference kind to its string representation. +*/ MRDOCS_DECL dom::String toString(ReferenceKind kind) noexcept; /** Return the ReferenceKind as a @ref dom::Value string. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Specifiers/StorageClassKind.hpp b/include/mrdocs/Metadata/Specifiers/StorageClassKind.hpp index 6de36a2780..e09b153c0a 100644 --- a/include/mrdocs/Metadata/Specifiers/StorageClassKind.hpp +++ b/include/mrdocs/Metadata/Specifiers/StorageClassKind.hpp @@ -40,12 +40,14 @@ enum class StorageClassKind Register }; +/** Convert a storage class kind to its string form. +*/ MRDOCS_DECL dom::String toString(StorageClassKind kind) noexcept; /** Return the StorageClassKind as a @ref dom::Value string. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol.hpp b/include/mrdocs/Metadata/Symbol.hpp index d9e9608ed1..19ea837e8b 100644 --- a/include/mrdocs/Metadata/Symbol.hpp +++ b/include/mrdocs/Metadata/Symbol.hpp @@ -28,7 +28,7 @@ namespace mrdocs { @param fn The function object to call @param args Additional arguments to pass to the function object @return The result of calling the function object with the derived type - */ +*/ template< std::derived_from SymbolTy, class Fn, @@ -58,7 +58,7 @@ visit( @param I The Symbol object to merge into. @param Other The Symbol object to merge from. - */ +*/ template SymbolTy> void merge(SymbolTy& I, SymbolTy&& Other) @@ -90,7 +90,7 @@ concept SymbolParent = requires(SymbolTy const& I) @param io The output parameter to receive the dom::Object. @param I The polymorphic Symbol to convert. @param domCorpus The DomCorpus used to resolve references. - */ +*/ template PolymorphicSymbol> requires std::derived_from void @@ -110,31 +110,6 @@ tag_invoke( }); } -/** Map the Polymorphic Symbol as a @ref dom::Value object. - - @param io The output parameter to receive the dom::Value. - @param I The polymorphic Symbol to convert. - @param domCorpus The DomCorpus used to resolve references. - */ -//template SymbolTy> -//requires std::derived_from -//void -//tag_invoke( -// dom::ValueFromTag, -// IO& io, -// SymbolTy const& I, -// DomCorpus const* domCorpus) -//{ -// visit(*I, [&](auto const& U) -// { -// tag_invoke( -// dom::ValueFromTag{}, -// io, -// U, -// domCorpus); -// }); -//} - } // mrdocs #endif // MRDOCS_API_METADATA_SYMBOL_HPP diff --git a/include/mrdocs/Metadata/Symbol/Concept.hpp b/include/mrdocs/Metadata/Symbol/Concept.hpp index 7f3a31f3e2..4cbbf2de73 100644 --- a/include/mrdocs/Metadata/Symbol/Concept.hpp +++ b/include/mrdocs/Metadata/Symbol/Concept.hpp @@ -36,15 +36,21 @@ struct ConceptSymbol final //-------------------------------------------- + /** Construct a concept symbol with its ID. + */ explicit ConceptSymbol(SymbolID const &ID) noexcept : SymbolCommonBase(ID) { } + /** Compare concept symbols by base info, template, and constraint. + */ std::strong_ordering operator<=>(ConceptSymbol const& other) const; }; +/** Merge another ConceptSymbol into this one. +*/ MRDOCS_DECL void merge(ConceptSymbol& I, ConceptSymbol&& Other); @@ -55,7 +61,7 @@ merge(ConceptSymbol& I, ConceptSymbol&& Other); @param io The IO object to use for mapping. @param I The ConceptSymbol to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -73,7 +79,7 @@ tag_invoke( } /** Map the ConceptSymbol to a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/Enum.hpp b/include/mrdocs/Metadata/Symbol/Enum.hpp index 935da1553f..ddcad03dcd 100644 --- a/include/mrdocs/Metadata/Symbol/Enum.hpp +++ b/include/mrdocs/Metadata/Symbol/Enum.hpp @@ -21,6 +21,8 @@ namespace mrdocs { +/** Metadata for an enumeration declaration. +*/ struct EnumSymbol final : SymbolCommonBase { @@ -55,12 +57,16 @@ struct EnumSymbol final //-------------------------------------------- + /** Construct an enum symbol with its ID. + */ explicit EnumSymbol(SymbolID ID) noexcept : SymbolCommonBase(ID) { } }; +/** Return the list of enum constants for this symbol. +*/ inline auto& allMembers(EnumSymbol const& T) @@ -68,6 +74,10 @@ allMembers(EnumSymbol const& T) return T.Constants; } +/** Merge another EnumSymbol into this one. + @param I Destination symbol to update. + @param Other Source symbol providing data. +*/ MRDOCS_DECL void merge(EnumSymbol& I, EnumSymbol&& Other); @@ -78,7 +88,7 @@ merge(EnumSymbol& I, EnumSymbol&& Other); @param io The IO object to use for mapping. @param I The EnumSymbol to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -98,7 +108,7 @@ tag_invoke( @param v The output parameter to receive the dom::Value. @param I The EnumSymbol to convert. @param domCorpus The DomCorpus used to resolve references. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/EnumConstant.hpp b/include/mrdocs/Metadata/Symbol/EnumConstant.hpp index 5ff744f37a..db5f8d699f 100644 --- a/include/mrdocs/Metadata/Symbol/EnumConstant.hpp +++ b/include/mrdocs/Metadata/Symbol/EnumConstant.hpp @@ -28,12 +28,18 @@ struct EnumConstantSymbol final //-------------------------------------------- + /** Construct an enum constant with its ID. + */ explicit EnumConstantSymbol(SymbolID ID) noexcept : SymbolCommonBase(ID) { } }; +/** Merge another EnumConstantSymbol into this one. + @param I Destination symbol to update. + @param Other Source symbol providing data. +*/ MRDOCS_DECL void merge(EnumConstantSymbol& I, EnumConstantSymbol&& Other); @@ -44,7 +50,7 @@ merge(EnumConstantSymbol& I, EnumConstantSymbol&& Other); @param io The IO object to use for mapping. @param I The EnumConstantSymbol to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -61,7 +67,7 @@ tag_invoke( } /** Map the EnumConstantSymbol to a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/ExtractionMode.hpp b/include/mrdocs/Metadata/Symbol/ExtractionMode.hpp index b0db5f48eb..dde53bade7 100644 --- a/include/mrdocs/Metadata/Symbol/ExtractionMode.hpp +++ b/include/mrdocs/Metadata/Symbol/ExtractionMode.hpp @@ -22,7 +22,7 @@ namespace mrdocs { the least specific at the beginning and the most specific at the end. - */ +*/ enum class ExtractionMode { /// We're extracting the current symbol because it passes @@ -55,7 +55,7 @@ enum class ExtractionMode }; /** Return the name of the SymbolKind as a string. - */ +*/ constexpr std::string_view toString(ExtractionMode kind) noexcept @@ -75,7 +75,7 @@ toString(ExtractionMode kind) noexcept } /** Return the SymbolKind from a @ref dom::Value string. - */ +*/ inline void tag_invoke( @@ -95,7 +95,7 @@ tag_invoke( as `a`, then it also passes the filter that categorizes it as `b` (or vice-versa), then this function will return the final category for the symbol. - */ +*/ constexpr ExtractionMode leastSpecific(ExtractionMode const a, ExtractionMode const b) noexcept @@ -109,7 +109,7 @@ leastSpecific(ExtractionMode const a, ExtractionMode const b) noexcept This function returns the most specific of the two ExtractionModes in terms of number of filters passed. - */ +*/ constexpr ExtractionMode mostSpecific(ExtractionMode const a, ExtractionMode const b) noexcept diff --git a/include/mrdocs/Metadata/Symbol/FileKind.hpp b/include/mrdocs/Metadata/Symbol/FileKind.hpp index 87f9669561..f697b8d73e 100644 --- a/include/mrdocs/Metadata/Symbol/FileKind.hpp +++ b/include/mrdocs/Metadata/Symbol/FileKind.hpp @@ -20,6 +20,8 @@ namespace mrdocs { +/** Classifies where a file originates from. +*/ enum class FileKind { /// File in the source directory @@ -30,10 +32,18 @@ enum class FileKind Other }; +/** Convert a FileKind to its string form. + @param kind File category to stringify. + @return String view describing the kind. +*/ MRDOCS_DECL std::string_view toString(FileKind kind); +/** Map a FileKind into a DOM value. + @param v Destination value to populate. + @param kind File category to serialize. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/Friend.hpp b/include/mrdocs/Metadata/Symbol/Friend.hpp index 6dabb0c382..3d1056afb2 100644 --- a/include/mrdocs/Metadata/Symbol/Friend.hpp +++ b/include/mrdocs/Metadata/Symbol/Friend.hpp @@ -43,6 +43,8 @@ struct FriendInfo final }; MRDOCS_DECL +/** Merge another FriendInfo into this one. +*/ void merge(FriendInfo& I, FriendInfo&& Other); @@ -52,7 +54,7 @@ merge(FriendInfo& I, FriendInfo&& Other); @param io The IO object to use for mapping. @param I The FriendInfo to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -78,7 +80,7 @@ tag_invoke( } /** Map the FriendInfo to a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/Function.hpp b/include/mrdocs/Metadata/Symbol/Function.hpp index 17ca2953ba..080bc720d4 100644 --- a/include/mrdocs/Metadata/Symbol/Function.hpp +++ b/include/mrdocs/Metadata/Symbol/Function.hpp @@ -25,8 +25,8 @@ namespace mrdocs { -// TODO: Expand to allow for documenting templating and default args. -// Info for functions. +/** Metadata for a function or method. +*/ struct FunctionSymbol final : SymbolCommonBase { @@ -37,7 +37,7 @@ struct FunctionSymbol final By default, we also use `auto` in the member to indicate an unknown return type. - */ + */ Polymorphic ReturnType = Polymorphic(AutoType{}); /// List of parameters. @@ -49,45 +49,103 @@ struct FunctionSymbol final /// The class of function this is FunctionClass Class = FunctionClass::Normal; + /** Exception specification for the function. + */ NoexceptInfo Noexcept; + /** Constrained requires-clause if present. + */ ExprInfo Requires; + /** True when the function is variadic. + */ bool IsVariadic = false; + /** True when this declaration is implicitly defaulted. + */ bool IsDefaulted = false; + /** True when explicitly defaulted with `= default`. + */ bool IsExplicitlyDefaulted = false; + /** True when this declaration is deleted. + */ bool IsDeleted = false; + /** True when deleted as written (vs deduced). + */ bool IsDeletedAsWritten = false; + /** True when marked [[noreturn]] or equivalent. + */ bool IsNoReturn = false; + /** True when annotated with override. + */ bool HasOverrideAttr = false; + /** True when using a trailing return type. + */ bool HasTrailingReturn = false; + /** True when declared [[nodiscard]]. + */ bool IsNodiscard = false; + /** True when explicit object parameter syntax is used. + */ bool IsExplicitObjectMemberFunction = false; + /** constexpr/consteval specifier. + */ ConstexprKind Constexpr = ConstexprKind::None; + /** Overloaded operator kind, if any. + */ OperatorKind OverloadedOperator = OperatorKind::None; + /** Storage class specifier. + */ StorageClassKind StorageClass = StorageClassKind::None; + /** Collected attributes attached to the declaration. + */ std::vector Attributes; // CXXMethodDecl + /** True when this is a non-static member function. + */ bool IsRecordMethod = false; + /** True when declared virtual (after overrides). + */ bool IsVirtual = false; + /** True when explicitly written virtual. + */ bool IsVirtualAsWritten = false; + /** True when the function is pure virtual. + */ bool IsPure = false; + /** True when qualified const. + */ bool IsConst = false; + /** True when qualified volatile. + */ bool IsVolatile = false; + /** True when final-qualified. + */ bool IsFinal = false; + /** Reference qualifier on the member function, if any. + */ ReferenceKind RefQualifier = ReferenceKind::None; + /** explicit-specifier information. + */ ExplicitInfo Explicit; //-------------------------------------------- + /** Construct a function symbol with its ID. + */ explicit FunctionSymbol(SymbolID const& ID) noexcept : SymbolCommonBase(ID) { } + /** Compare functions by signature, qualifiers, and metadata. + */ std::strong_ordering operator<=>(FunctionSymbol const& other) const; }; +/** Merge metadata from another function symbol. + @param I Destination symbol to update. + @param Other Source symbol providing additional data. +*/ MRDOCS_DECL void merge(FunctionSymbol& I, FunctionSymbol&& Other); @@ -98,7 +156,7 @@ merge(FunctionSymbol& I, FunctionSymbol&& Other); @param io The IO object to use for mapping. @param I The FunctionSymbol to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -155,7 +213,7 @@ tag_invoke( @param v The output parameter to receive the dom::Value. @param I The FunctionSymbol to convert. @param domCorpus The DomCorpus used to resolve references. - */ +*/ inline void tag_invoke( @@ -171,7 +229,7 @@ tag_invoke( @param base The base function @param derived The derived function - */ +*/ MRDOCS_DECL bool overrides(FunctionSymbol const& base, FunctionSymbol const& derived); diff --git a/include/mrdocs/Metadata/Symbol/FunctionClass.hpp b/include/mrdocs/Metadata/Symbol/FunctionClass.hpp index b3f0f17436..e4ba48a5b8 100644 --- a/include/mrdocs/Metadata/Symbol/FunctionClass.hpp +++ b/include/mrdocs/Metadata/Symbol/FunctionClass.hpp @@ -19,7 +19,8 @@ namespace mrdocs { -/** Function classifications */ +/** Function classifications +*/ enum class FunctionClass { /// The function is a normal function. @@ -32,12 +33,14 @@ enum class FunctionClass Destructor }; +/** Convert a function class to string form. +*/ MRDOCS_DECL dom::String toString(FunctionClass kind) noexcept; /** Return the FunctionClass from a @ref dom::Value string. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/Guide.hpp b/include/mrdocs/Metadata/Symbol/Guide.hpp index 402ccb469f..cc4a0e0d9e 100644 --- a/include/mrdocs/Metadata/Symbol/Guide.hpp +++ b/include/mrdocs/Metadata/Symbol/Guide.hpp @@ -48,14 +48,22 @@ struct GuideSymbol final //-------------------------------------------- + /** Construct a deduction guide symbol with its ID. + */ explicit GuideSymbol(SymbolID ID) noexcept : SymbolCommonBase(ID) {} + /** Compare guides by params/deduced/template/explicit. + */ std::strong_ordering operator<=>(GuideSymbol const& other) const; }; +/** Merge another GuideSymbol into this one. + @param I Destination symbol to update. + @param Other Source symbol providing data. +*/ MRDOCS_DECL void merge(GuideSymbol& I, GuideSymbol&& Other); @@ -66,7 +74,7 @@ merge(GuideSymbol& I, GuideSymbol&& Other); @param io The IO object to use for mapping. @param I The GuideSymbol to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -83,7 +91,7 @@ tag_invoke( } /** Map the GuideSymbol to a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/Location.hpp b/include/mrdocs/Metadata/Symbol/Location.hpp index d9e15c53be..48c1c6d960 100644 --- a/include/mrdocs/Metadata/Symbol/Location.hpp +++ b/include/mrdocs/Metadata/Symbol/Location.hpp @@ -20,6 +20,8 @@ namespace mrdocs { +/** Source location of a symbol or entity. +*/ struct MRDOCS_DECL Location { @@ -32,7 +34,7 @@ struct MRDOCS_DECL std::string ShortPath; /** The file path relative to the source-root directory - */ + */ std::string SourcePath; /** Line number within the file @@ -49,6 +51,14 @@ struct MRDOCS_DECL //-------------------------------------------- + /** Construct a location with optional fields. + @param full_path Absolute path to the file on disk. + @param short_path Repository- or search-root relative path, may be empty. + @param source_path Path relative to the documented source root. + @param line Line number within the file. + @param col Column number within the line. + @param documented Whether the location already carries user documentation. + */ constexpr Location( std::string_view const full_path = {}, @@ -66,9 +76,13 @@ struct MRDOCS_DECL { } + /** Compare locations by file paths and coordinates. + */ auto operator<=>(Location const&) const = default; }; +/** Serialize a location into a DOM value. +*/ MRDOCS_DECL void tag_invoke( @@ -88,16 +102,22 @@ tag_invoke( Rationale - This mirrors the old LocationEmptyPredicate, which treated an empty ShortPath as “empty/null.” -**/ +*/ template<> struct nullable_traits { + /** Test if the location is null (empty ShortPath). + @return True when `ShortPath` is empty. + */ static constexpr bool is_null(Location const& v) noexcept { return v.ShortPath.empty(); } + /** Create a null location sentinel. + @return Location with every field cleared. + */ static constexpr Location null() noexcept { @@ -110,6 +130,8 @@ struct nullable_traits }; } + /** Reset a location to the null sentinel state. + */ static constexpr void make_null(Location& v) noexcept { @@ -117,6 +139,7 @@ struct nullable_traits v.ShortPath.clear(); // sentinel condition v.SourcePath.clear(); v.LineNumber = 0; + v.ColumnNumber = 0; v.Documented = false; } }; diff --git a/include/mrdocs/Metadata/Symbol/Namespace.hpp b/include/mrdocs/Metadata/Symbol/Namespace.hpp index 06a5e5683f..5f80e3f5f8 100644 --- a/include/mrdocs/Metadata/Symbol/Namespace.hpp +++ b/include/mrdocs/Metadata/Symbol/Namespace.hpp @@ -20,27 +20,54 @@ namespace mrdocs { -/** The members of a Namespace - */ +/** Buckets the members that appear inside a namespace. +*/ struct NamespaceTranche { + /** Nested namespaces. + */ std::vector Namespaces; + /** Namespace aliases declared here. + */ std::vector NamespaceAliases; + /** Typedef or using declarations. + */ std::vector Typedefs; + /** Record types (classes/structs). + */ std::vector Records; + /** Enumerations. + */ std::vector Enums; + /** Functions and overload sets. + */ std::vector Functions; + /** Variables. + */ std::vector Variables; + /** Concepts. + */ std::vector Concepts; + /** Deduction guides. + */ std::vector Guides; + /** Using-declarations that introduce members. + */ std::vector Usings; + /** Compare tranches field-by-field. + */ auto operator<=>(NamespaceTranche const&) const = default; }; +/** Merge two tranches, appending members from the right-hand side. +*/ MRDOCS_DECL void merge(NamespaceTranche& I, NamespaceTranche&& Other); +/** Join all tranche member lists into a single view. + @return Lazy view spanning every category stored in the tranche. +*/ inline auto allMembers(NamespaceTranche const& T) @@ -70,8 +97,8 @@ allMembers(NamespaceTranche const& T) @param io The IO object to use for mapping. @param I The NamespaceTranche to map. - @param domCorpus The DomCorpus used to create - */ + @param domCorpus The DomCorpus used to create the DOM values. +*/ template void tag_invoke( @@ -93,7 +120,7 @@ tag_invoke( } /** Map the NamespaceTranche to a @ref dom::Value object. - */ +*/ inline void tag_invoke( @@ -105,12 +132,16 @@ tag_invoke( v = dom::LazyObject(I, domCorpus); } -/** Describes a namespace. +/** Describes a namespace and its members. */ struct NamespaceSymbol final : SymbolCommonBase { + /** Whether this declaration is inline. + */ bool IsInline = false; + /** Whether this represents an unnamed namespace. + */ bool IsAnonymous = false; /** Namespaces nominated by using-directives. @@ -121,19 +152,29 @@ struct NamespaceSymbol final */ NamespaceTranche Members; + /** Create a namespace symbol bound to an ID. + */ explicit NamespaceSymbol(SymbolID const &ID) noexcept : SymbolCommonBase(ID) { } + /** Compare namespaces by attributes and member lists. + */ std::strong_ordering operator<=>(NamespaceSymbol const&) const; }; +/** Merge two namespaces, keeping existing members stable. +*/ MRDOCS_DECL -void merge(NamespaceSymbol& I, NamespaceSymbol&& Other); +void +merge(NamespaceSymbol& I, NamespaceSymbol&& Other); +/** View all members of the namespace across tranches. + @return Lazy view across every member bucket. +*/ inline auto allMembers(NamespaceSymbol const& T) @@ -147,7 +188,7 @@ allMembers(NamespaceSymbol const& T) @param io The IO object to use for mapping. @param I The NamespaceSymbol to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -164,7 +205,7 @@ tag_invoke( } /** Map the NamespaceSymbol to a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/NamespaceAlias.hpp b/include/mrdocs/Metadata/Symbol/NamespaceAlias.hpp index 8ede49e96e..a590ab7414 100644 --- a/include/mrdocs/Metadata/Symbol/NamespaceAlias.hpp +++ b/include/mrdocs/Metadata/Symbol/NamespaceAlias.hpp @@ -27,17 +27,21 @@ struct NamespaceAliasSymbol final This is another namespace that might or might not be in the same project. - */ + */ IdentifierName AliasedSymbol; //-------------------------------------------- + /** Create an alias symbol bound to an ID. + */ explicit NamespaceAliasSymbol(SymbolID const &ID) noexcept : SymbolCommonBase(ID) { } }; +/** Merge two alias symbols, preferring existing fields when present. +*/ MRDOCS_DECL void merge(NamespaceAliasSymbol& I, NamespaceAliasSymbol&& Other); @@ -48,7 +52,7 @@ merge(NamespaceAliasSymbol& I, NamespaceAliasSymbol&& Other); @param io The IO object to use for mapping. @param I The NamespaceAliasSymbol to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -62,7 +66,7 @@ tag_invoke( } /** Map the NamespaceAliasSymbol to a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/Overloads.hpp b/include/mrdocs/Metadata/Symbol/Overloads.hpp index 4912a6e345..98022eed39 100644 --- a/include/mrdocs/Metadata/Symbol/Overloads.hpp +++ b/include/mrdocs/Metadata/Symbol/Overloads.hpp @@ -18,7 +18,7 @@ namespace mrdocs { /** Represents a set of function overloads. - */ +*/ struct OverloadsSymbol final : SymbolCommonBase { @@ -36,23 +36,36 @@ struct OverloadsSymbol final If all overloads have the same return type, this contains that type. Otherwise, it contains `auto` to indicate that the return type varies according to the parameters. - */ + */ Polymorphic ReturnType = Polymorphic(AutoType{}); //-------------------------------------------- + /** Create an empty overload set for the given ID. + */ explicit OverloadsSymbol(SymbolID const& ID) noexcept : SymbolCommonBase(ID) { } + /** Create an overload set under the given parent and name. + @param Parent Owning symbol ID. + @param Name Unqualified name shared by the overloads. + @param Access Access specifier when the overloads are members. + @param isStatic Whether the overload set refers to static functions. + */ explicit OverloadsSymbol(SymbolID const& Parent, std::string_view Name, AccessKind Access, bool isStatic) noexcept; }; +/** Merge overload sets, preserving ordering in `Members`. +*/ MRDOCS_DECL void merge(OverloadsSymbol& I, OverloadsSymbol&& Other); +/** Access the list of overload members. + @return Reference to the ID list backing this set. +*/ inline auto& allMembers(OverloadsSymbol const& T) @@ -60,6 +73,8 @@ allMembers(OverloadsSymbol const& T) return T.Members; } +/** Append a new function overload to the set. +*/ MRDOCS_DECL void addMember(OverloadsSymbol& I, FunctionSymbol const& Member); @@ -70,7 +85,7 @@ addMember(OverloadsSymbol& I, FunctionSymbol const& Member); @param io The IO object to use for mapping. @param I The OverloadsSymbol to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -86,7 +101,7 @@ tag_invoke( } /** Map the OverloadsSymbol to a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/Param.hpp b/include/mrdocs/Metadata/Symbol/Param.hpp index a37e50f784..f4c4920d1a 100644 --- a/include/mrdocs/Metadata/Symbol/Param.hpp +++ b/include/mrdocs/Metadata/Symbol/Param.hpp @@ -22,26 +22,31 @@ namespace mrdocs { -/** Represents a single function parameter */ +/** Represents a single function parameter +*/ struct Param final { /** The type of this parameter - */ + */ Polymorphic Type = Polymorphic(AutoType{}); /** The parameter name. - */ + */ Optional Name; /** The default argument for this parameter, if any - */ + */ Optional Default; - // KRYSTIAN TODO: attributes (nodiscard, deprecated, and carries_dependency) - // KRYSTIAN TODO: flag to indicate whether this is a function parameter pack - + /** Create an empty parameter with an `auto` type. + */ Param() = default; + /** Construct a parameter with type, name, and default expression. + @param type Parameter type. + @param name Parameter identifier. + @param def_arg Default argument expression, if present. + */ Param( Polymorphic&& type, std::string&& name, @@ -51,16 +56,20 @@ struct Param final , Default(std::move(def_arg)) {} + /** Compare parameters by type, name, and default. + */ auto operator<=>(Param const&) const = default; }; +/** Merge two parameters, filling missing pieces from `Other`. +*/ MRDOCS_DECL void merge(Param& I, Param&& Other); /** Return the Param as a @ref dom::Value object. - */ +*/ MRDOCS_DECL void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/Record.hpp b/include/mrdocs/Metadata/Symbol/Record.hpp index 56cae709c7..0f1df06316 100644 --- a/include/mrdocs/Metadata/Symbol/Record.hpp +++ b/include/mrdocs/Metadata/Symbol/Record.hpp @@ -34,14 +34,26 @@ struct RecordSymbol final /// When present, this record is a template or specialization. Optional Template; - // Indicates if the record was declared using a typedef. - // Things like anonymous structs in a typedef: - // typedef struct { ... } foo_t; - // are converted into records with the typedef as the Name + this flag set. - // KRYSTIAN FIXME: this does not account for alias-declarations + /** Whether the record originated from a typedef-style declaration. + + Things like anonymous structs in a typedef: + + @code + typedef struct { ... } foo_t; + @endcode + + are converted into records with the typedef as the Name + this flag set. + + @note Alias-declarations are not yet distinguished here. + */ bool IsTypeDef = false; + /** Whether the class is marked `final`. + */ bool IsFinal = false; + + /** Whether the destructor is marked `final`. + */ bool IsFinalDestructor = false; /** List of immediate bases. @@ -49,11 +61,11 @@ struct RecordSymbol final std::vector Bases; /** List of derived classes - */ + */ std::vector Derived; /** Lists of members. - */ + */ RecordInterface Interface; /** List of friends. @@ -62,15 +74,21 @@ struct RecordSymbol final //-------------------------------------------- + /** Create a record symbol bound to an ID. + */ explicit RecordSymbol(SymbolID const& ID) noexcept : SymbolCommonBase(ID) { } + /** Compare records including bases, members, and flags. + */ std::strong_ordering operator<=>(RecordSymbol const& other) const; }; +/** Return the default accessibility for a record key kind. +*/ constexpr std::string_view getDefaultAccessString( @@ -88,6 +106,9 @@ getDefaultAccessString( } } +/** View all record members across access levels. + @return Lazy view traversing every tranche. +*/ inline auto allMembers(RecordSymbol const& T) @@ -95,6 +116,8 @@ allMembers(RecordSymbol const& T) return allMembers(T.Interface); } +/** Merge metadata from another record of the same identity. +*/ MRDOCS_DECL void merge(RecordSymbol& I, RecordSymbol&& Other); @@ -105,7 +128,7 @@ merge(RecordSymbol& I, RecordSymbol&& Other); @param io The IO object to use for mapping. @param I The RecordSymbol to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -127,7 +150,7 @@ tag_invoke( } /** Map the RecordSymbol to a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/RecordBase.hpp b/include/mrdocs/Metadata/Symbol/RecordBase.hpp index 8045a2753d..ecd70071b3 100644 --- a/include/mrdocs/Metadata/Symbol/RecordBase.hpp +++ b/include/mrdocs/Metadata/Symbol/RecordBase.hpp @@ -27,19 +27,26 @@ struct BaseInfo This is typically a `NamedType` that refers to a `RecordSymbol`, but it could also be a more complex type such as a `decltype`. - */ + */ Polymorphic Type; /** The access specifier for the base. - */ + */ AccessKind Access = AccessKind::Public; /** Whether the base is virtual. - */ + */ bool IsVirtual = false; + /** Bases must be explicitly described. + */ BaseInfo() = delete; + /** Create a base description. + @param type The base type. + @param access Declared access specifier. + @param is_virtual Whether the base is virtual. + */ BaseInfo( Polymorphic&& type, AccessKind const access, @@ -51,6 +58,8 @@ struct BaseInfo } }; +/** Serialize a base description into a DOM value. +*/ MRDOCS_DECL void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/RecordInterface.hpp b/include/mrdocs/Metadata/Symbol/RecordInterface.hpp index 022b92ca4c..7c16c36735 100644 --- a/include/mrdocs/Metadata/Symbol/RecordInterface.hpp +++ b/include/mrdocs/Metadata/Symbol/RecordInterface.hpp @@ -41,7 +41,7 @@ class RecordInterface This tranche contains all public members of a record or namespace. - */ + */ RecordTranche Public; /** The aggregated protected interfaces. @@ -49,7 +49,7 @@ class RecordInterface This tranche contains all protected members of a record or namespace. - */ + */ RecordTranche Protected; /** The aggregated private interfaces. @@ -57,10 +57,12 @@ class RecordInterface This tranche contains all private members of a record or namespace. - */ + */ RecordTranche Private; }; +/** Merge two interfaces, combining matching tranches. +*/ MRDOCS_DECL void merge(RecordInterface& I, RecordInterface&& Other); @@ -69,7 +71,7 @@ merge(RecordInterface& I, RecordInterface&& Other); @param io The output parameter to receive the dom::Object. @param I The RecordInterface to convert. - */ +*/ template void tag_invoke( @@ -84,7 +86,7 @@ tag_invoke( } /** Map the RecordInterface to a @ref dom::Value object. - */ +*/ inline void tag_invoke( @@ -97,6 +99,9 @@ tag_invoke( } +/** Flatten all public/protected/private members. + @return View concatenating the three access tranches. +*/ inline auto allMembers(RecordInterface const& T) diff --git a/include/mrdocs/Metadata/Symbol/RecordKeyKind.hpp b/include/mrdocs/Metadata/Symbol/RecordKeyKind.hpp index 14a673ec1d..85238be811 100644 --- a/include/mrdocs/Metadata/Symbol/RecordKeyKind.hpp +++ b/include/mrdocs/Metadata/Symbol/RecordKeyKind.hpp @@ -30,10 +30,14 @@ enum class RecordKeyKind Union }; +/** Convert the key kind to its canonical string form. +*/ MRDOCS_DECL dom::String toString(RecordKeyKind kind) noexcept; +/** Serialize the record key kind into a DOM value. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/RecordTranche.hpp b/include/mrdocs/Metadata/Symbol/RecordTranche.hpp index 8a3b88bfca..962ed707e9 100644 --- a/include/mrdocs/Metadata/Symbol/RecordTranche.hpp +++ b/include/mrdocs/Metadata/Symbol/RecordTranche.hpp @@ -31,23 +31,50 @@ namespace mrdocs { */ struct RecordTranche { + /** Namespace aliases declared with this access. + */ std::vector NamespaceAliases; + /** Typedefs and using aliases. + */ std::vector Typedefs; + /** Nested records. + */ std::vector Records; + /** Enumerations. + */ std::vector Enums; + /** Member functions. + */ std::vector Functions; + /** Static member functions. + */ std::vector StaticFunctions; + /** Data members. + */ std::vector Variables; + /** Static data members. + */ std::vector StaticVariables; + /** Member concepts. + */ std::vector Concepts; + /** Deduction guides in the class scope. + */ std::vector Guides; + /** Using-declarations that pull members into the class. + */ std::vector Usings; }; +/** Merge two tranches with the same access level. +*/ MRDOCS_DECL void merge(RecordTranche& I, RecordTranche&& Other); +/** Join every member list into a single view. + @return Lazy view spanning all member categories. +*/ inline auto allMembers(RecordTranche const& T) @@ -80,7 +107,7 @@ allMembers(RecordTranche const& T) @param io The output parameter to receive the dom::Object. @param I The RecordTranche to convert. @param domCorpus The DomCorpus used to resolve references. - */ +*/ template void tag_invoke( @@ -103,7 +130,7 @@ tag_invoke( } /** Map the RecordTranche to a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/Source.hpp b/include/mrdocs/Metadata/Symbol/Source.hpp index 910a991f27..69d2422948 100644 --- a/include/mrdocs/Metadata/Symbol/Source.hpp +++ b/include/mrdocs/Metadata/Symbol/Source.hpp @@ -26,6 +26,8 @@ namespace mrdocs { struct MRDOCS_DECL SourceInfo { + /** Construct with no locations. + */ constexpr SourceInfo() = default; /** Location where the entity was defined @@ -43,23 +45,38 @@ struct MRDOCS_DECL */ std::vector Loc; + /** Polymorphic base needs a virtual destructor. + */ constexpr virtual ~SourceInfo() = default; + /** Compare sources by definition and declaration locations. + */ auto operator<=>(SourceInfo const&) const = default; }; +/** Merge the location sets, preferring existing def/primary. +*/ MRDOCS_DECL void merge(SourceInfo& I, SourceInfo const& Other); +/** Merge, transferring ownership from the right-hand side. +*/ MRDOCS_DECL void merge(SourceInfo& I, SourceInfo&& Other); +/** Choose the best location to display for a symbol. + @param I Source info to examine. + @param preferDefinition If true, favor a definition location. + @return The preferred location if available. +*/ MRDOCS_DECL Optional getPrimaryLocation(SourceInfo const& I, bool preferDefinition); +/** Serialize source locations into a DOM value. +*/ void tag_invoke( dom::ValueFromTag, diff --git a/include/mrdocs/Metadata/Symbol/SymbolBase.hpp b/include/mrdocs/Metadata/Symbol/SymbolBase.hpp index 9769f645fd..6ff2116d8b 100644 --- a/include/mrdocs/Metadata/Symbol/SymbolBase.hpp +++ b/include/mrdocs/Metadata/Symbol/SymbolBase.hpp @@ -31,11 +31,11 @@ namespace mrdocs { */ struct MRDOCS_VISIBLE Symbol { /** The unqualified name. - */ + */ std::string Name; /** The source location information. - */ + */ SourceInfo Loc; /** Kind of declaration. @@ -43,7 +43,7 @@ struct MRDOCS_VISIBLE Symbol { SymbolKind Kind = SymbolKind::None; /** The unique identifier for this symbol. - */ + */ SymbolID id; /** Declaration access. @@ -75,15 +75,17 @@ struct MRDOCS_VISIBLE Symbol { This is the parent namespace or record where the symbol is defined. - */ + */ SymbolID Parent; /** The extracted documentation for this declaration. - */ + */ Optional doc; //-------------------------------------------- + /** Polymorphic base needs a virtual destructor. + */ virtual ~Symbol() = default; #define INFO(Type) constexpr bool is##Type() const noexcept { \ @@ -91,11 +93,15 @@ struct MRDOCS_VISIBLE Symbol { } #include + /** View this instance as a const Symbol reference. + */ constexpr Symbol const& asInfo() const noexcept { return *this; } + /** View this instance as a mutable Symbol reference. + */ constexpr Symbol& asInfo() noexcept { return *this; @@ -131,18 +137,24 @@ struct MRDOCS_VISIBLE Symbol { } #include + /** Compare symbols by structural fields. + */ auto operator<=>(Symbol const&) const = default; protected: + /** Default constructor for derived types. + */ constexpr Symbol() = default; + /** Copy constructor. + */ Symbol(Symbol const& Other) = default; /** Move constructor. - */ + */ Symbol(Symbol&& Other) = default; - /** Construct an Symbol. + /** Construct a Symbol. @param kind The kind of symbol @param ID The unique identifier for this symbol @@ -172,18 +184,24 @@ struct SymbolCommonBase : Symbol It only distinguishes from `Symbol::kind` in that it is a constant. - */ + */ static constexpr SymbolKind kind_id = K; #define INFO(Kind) \ static constexpr bool is##Kind() noexcept { return K == SymbolKind::Kind; } #include + /** Compare symbols that share the same kind. + */ auto operator<=>(SymbolCommonBase const&) const = default; protected: + /** Default constructor. + */ SymbolCommonBase() = default; + /** Construct bound to an ID. + */ constexpr explicit SymbolCommonBase(SymbolID const& ID) : Symbol(K, ID) { @@ -203,6 +221,9 @@ MRDOCS_DECL void merge(Symbol& I, Symbol&& Other); +/** Check whether two symbols may be merged. + @return True when kinds and IDs match. +*/ inline bool canMerge(Symbol const& I, Symbol const& Other) @@ -217,7 +238,7 @@ canMerge(Symbol const& I, Symbol const& Other) @param io The output parameter to receive the dom::Object. @param I The Symbol to convert. @param domCorpus The DomCorpus used to resolve references. - */ +*/ template void tag_invoke( @@ -252,7 +273,7 @@ tag_invoke( } /** Return the Symbol as a @ref dom::Value object. - */ +*/ inline void tag_invoke( @@ -264,6 +285,8 @@ tag_invoke( v = dom::LazyObject(I, domCorpus); } +/** Determine a location to use when none is explicitly chosen. +*/ inline Optional getPrimaryLocation(Symbol const& I) diff --git a/include/mrdocs/Metadata/Symbol/SymbolID.hpp b/include/mrdocs/Metadata/Symbol/SymbolID.hpp index dde44b50d2..44656569ca 100644 --- a/include/mrdocs/Metadata/Symbol/SymbolID.hpp +++ b/include/mrdocs/Metadata/Symbol/SymbolID.hpp @@ -40,11 +40,20 @@ class SymbolID std::uint8_t data_[20]{}; public: + /** Sentinel ID used to represent “no symbol.” + */ static const SymbolID invalid; + + /** Sentinel ID representing the global namespace. + */ static const SymbolID global; + /** Underlying byte storage. + */ using value_type = std::uint8_t; + /** Construct a zero-initialized identifier. + */ constexpr SymbolID() = default; /** Construct a SymbolID from a null-terminated string. @@ -71,20 +80,20 @@ class SymbolID @param input The string to hash. @return The SymbolID created by hashing the string. - */ + */ static SymbolID createFromString(std::string_view input); /** Return true if this is a valid SymbolID. - */ + */ explicit operator bool() const noexcept { return *this != SymbolID::invalid; } /** Return the raw data for this SymbolID. - */ + */ constexpr auto data() const noexcept { return data_; @@ -94,28 +103,28 @@ class SymbolID The size of a SymbolID is always 20. - */ + */ constexpr std::size_t size() const noexcept { return 20; } /** Return an iterator to the first byte of the SymbolID. - */ + */ constexpr auto begin() const noexcept { return data_; } /** Return an iterator to one past the last byte of the SymbolID. - */ + */ constexpr auto end() const noexcept { return data_ + size(); } /** Return a string view of the SymbolID. - */ + */ operator std::string_view() const noexcept { return {reinterpret_cast< @@ -123,7 +132,7 @@ class SymbolID } /** Compare two SymbolIDs with strong ordering. - */ + */ auto operator<=>( SymbolID const& other) const noexcept { @@ -134,7 +143,7 @@ class SymbolID } /** Compare two SymbolIDs for equality. - */ + */ bool operator==( SymbolID const& other) const noexcept = default; }; @@ -155,7 +164,7 @@ constexpr inline SymbolID SymbolID::global = @param id The SymbolID to convert. @return The base16 string representation of the SymbolID. - */ +*/ MRDOCS_DECL std::string toBase16Str(SymbolID const& id); @@ -180,7 +189,7 @@ compareSymbolNames( std::string_view symbolName1) noexcept; /** Convert SymbolID to dom::Value string in the DOM using toBase16 - */ +*/ MRDOCS_DECL void tag_invoke( @@ -189,7 +198,7 @@ tag_invoke( SymbolID const& id); /** Convert SymbolID to dom::Value object in the DOM using Corpus - */ +*/ MRDOCS_DECL void tag_invoke( @@ -205,7 +214,7 @@ tag_invoke( dom::Value is set to null. @param domCorpus The DomCorpus to use, or nullptr. If null, the SymbolID is converted to a base16 string. - */ +*/ MRDOCS_DECL void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/SymbolKind.hpp b/include/mrdocs/Metadata/Symbol/SymbolKind.hpp index 5e3f254bd7..ca5d47af1d 100644 --- a/include/mrdocs/Metadata/Symbol/SymbolKind.hpp +++ b/include/mrdocs/Metadata/Symbol/SymbolKind.hpp @@ -20,20 +20,20 @@ namespace mrdocs { /** Info variant discriminator */ enum class SymbolKind { - /// Kind is not specified. - None = 0, - #define INFO(Type) Type, + /// Kind is not specified. + None = 0, +#define INFO(Type) Type, #include }; /** Return the name of the SymbolKind as a string. - */ +*/ MRDOCS_DECL dom::String toString(SymbolKind kind) noexcept; /** Return the SymbolKind from a @ref dom::Value string. - */ +*/ inline void tag_invoke( @@ -43,6 +43,9 @@ tag_invoke( v = toString(kind); } +/** Count the number of SymbolKind enumerators. + @return Number of `SymbolKind` values generated from SymbolNodes.inc. +*/ consteval std::underlying_type_t countSymbolKind() diff --git a/include/mrdocs/Metadata/Symbol/Typedef.hpp b/include/mrdocs/Metadata/Symbol/Typedef.hpp index 94af07d2c3..a34275331d 100644 --- a/include/mrdocs/Metadata/Symbol/Typedef.hpp +++ b/include/mrdocs/Metadata/Symbol/Typedef.hpp @@ -22,10 +22,13 @@ namespace mrdocs { -// Info for typedef and using statements. +/** Info for typedef and using declarations. +*/ struct TypedefSymbol final : SymbolCommonBase { + /** The aliased type. + */ Polymorphic Type = Polymorphic(NamedType{}); /** Indicates if this is a new C++ "using"-style typedef @@ -39,23 +42,31 @@ struct TypedefSymbol final @code typedef std::vector MyVector; @endcode - */ + */ bool IsUsing = false; + /** Template information when the alias is templated. + */ Optional Template; //-------------------------------------------- + /** Create a typedef symbol bound to an ID. + */ explicit TypedefSymbol(SymbolID ID) noexcept : SymbolCommonBase(ID) { } + /** Compare typedef symbols, including alias target and template. + */ std::strong_ordering operator<=>(TypedefSymbol const& other) const; }; +/** Merge typedef symbols, keeping existing info when present. +*/ MRDOCS_DECL void merge(TypedefSymbol& I, TypedefSymbol&& Other); @@ -66,7 +77,7 @@ merge(TypedefSymbol& I, TypedefSymbol&& Other); @param io The IO object to use for mapping. @param I The TypedefSymbol to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -86,7 +97,7 @@ tag_invoke( @param v The output parameter to receive the dom::Value. @param I The TypedefSymbol to convert. @param domCorpus The DomCorpus used to resolve references. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Symbol/Using.hpp b/include/mrdocs/Metadata/Symbol/Using.hpp index bc2daca435..b9465f6854 100644 --- a/include/mrdocs/Metadata/Symbol/Using.hpp +++ b/include/mrdocs/Metadata/Symbol/Using.hpp @@ -54,7 +54,7 @@ toString(UsingClass const& value) @param v The output value. @param kind The UsingClass to convert. - */ +*/ inline void tag_invoke( @@ -82,7 +82,7 @@ tag_invoke( or to introduce enumerators into namespaces, block, and class scopes. - */ +*/ struct UsingSymbol final : SymbolCommonBase { @@ -97,7 +97,7 @@ struct UsingSymbol final Note that this can be a qualified name, such as `A::f` in the example above. - */ + */ Polymorphic IntroducedName = Polymorphic(std::in_place_type); /** The shadow declarations. @@ -131,12 +131,16 @@ struct UsingSymbol final //-------------------------------------------- + /** Create a using-declaration symbol bound to an ID. + */ explicit UsingSymbol(SymbolID ID) noexcept : SymbolCommonBase(ID) { } }; +/** Merge two using-declarations with the same identity. +*/ MRDOCS_DECL void merge(UsingSymbol& I, UsingSymbol&& Other); @@ -146,7 +150,7 @@ void merge(UsingSymbol& I, UsingSymbol&& Other); @param io The IO object to use for mapping. @param I The UsingSymbol to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -162,7 +166,7 @@ tag_invoke( } /** Map the UsingSymbol to a @ref dom::Value object. - */ +*/ inline void tag_invoke( @@ -174,6 +178,9 @@ tag_invoke( v = dom::LazyObject(I, domCorpus); } +/** Access declarations introduced by this using-declaration. + @return Reference to the underlying shadow list. +*/ inline auto& allMembers(UsingSymbol const& T) diff --git a/include/mrdocs/Metadata/Symbol/Variable.hpp b/include/mrdocs/Metadata/Symbol/Variable.hpp index 0772b80b64..07162c2785 100644 --- a/include/mrdocs/Metadata/Symbol/Variable.hpp +++ b/include/mrdocs/Metadata/Symbol/Variable.hpp @@ -31,62 +31,93 @@ namespace mrdocs { struct VariableSymbol final : SymbolCommonBase { - /** The type of the variable */ + /** The type of the variable + */ Polymorphic Type = Polymorphic(NamedType{}); /** The template information, if any. - */ + */ Optional Template; /** The default member initializer, if any. - */ + */ ExprInfo Initializer; + /** Storage class specifier applied to the variable. + */ StorageClassKind StorageClass = StorageClassKind::None; + /** Whether the variable is declared `inline`. + */ bool IsInline = false; + /** Whether the variable is `constexpr`. + */ bool IsConstexpr = false; + /** Whether the variable is `constinit`. + */ bool IsConstinit = false; + /** Whether the variable is `thread_local`. + */ bool IsThreadLocal = false; + /** Raw attribute spellings attached to the variable. + */ std::vector Attributes; + /** Whether the variable carries `[[maybe_unused]]`. + */ bool IsMaybeUnused = false; + /** Whether the variable is marked deprecated. + */ bool IsDeprecated = false; + /** Whether the variable uses [[no_unique_address]]. + */ bool HasNoUniqueAddress = false; //-------------------------------------------- // Record fields + /** True if this variable is a data member of a record. + */ bool IsRecordField = false; - /** Whether the field is declared mutable */ + /** Whether the field is declared mutable + */ bool IsMutable = false; - /** Whether the field is a variant member */ + /** Whether the field is a variant member + */ bool IsVariant = false; - /** Whether the field is a bitfield */ + /** Whether the field is a bitfield + */ bool IsBitfield = false; - /** The width of the bitfield */ + /** The width of the bitfield + */ ConstantExprInfo BitfieldWidth; //-------------------------------------------- + /** Create a variable symbol bound to an ID. + */ explicit VariableSymbol(SymbolID const &ID) noexcept : SymbolCommonBase(ID) { } + /** Compare variables by type, flags, and initializer. + */ std::strong_ordering operator<=>(VariableSymbol const& other) const; }; +/** Merge variable metadata, preserving existing values when set. +*/ MRDOCS_DECL void merge(VariableSymbol& I, VariableSymbol&& Other); @@ -97,7 +128,7 @@ merge(VariableSymbol& I, VariableSymbol&& Other); @param io The IO object to use for mapping. @param I The VariableSymbol to map. @param domCorpus The DomCorpus used to create - */ +*/ template void tag_invoke( @@ -137,7 +168,7 @@ tag_invoke( } /** Map the VariableSymbol to a @ref dom::Value object. - */ +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/TArg.hpp b/include/mrdocs/Metadata/TArg.hpp index 97813035ca..76522f83ae 100644 --- a/include/mrdocs/Metadata/TArg.hpp +++ b/include/mrdocs/Metadata/TArg.hpp @@ -22,6 +22,8 @@ namespace mrdocs { +/** Visit a template argument, dispatching on its concrete kind. +*/ template< std::derived_from TArgTy, class F, @@ -52,10 +54,14 @@ visit( } } +/** Compare polymorphic template arguments. +*/ MRDOCS_DECL std::strong_ordering operator<=>(Polymorphic const& lhs, Polymorphic const& rhs); +/** Serialize a polymorphic template argument into a DOM value. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/TArg/ConstantTArg.hpp b/include/mrdocs/Metadata/TArg/ConstantTArg.hpp index 8bcf0d8a16..07a5b8faa0 100644 --- a/include/mrdocs/Metadata/TArg/ConstantTArg.hpp +++ b/include/mrdocs/Metadata/TArg/ConstantTArg.hpp @@ -20,12 +20,17 @@ namespace mrdocs { +/** Non-type template argument. +*/ struct ConstantTArg final : TArgCommonBase { - /** Template argument expression. */ + /** Template argument expression. + */ ExprInfo Value; + /** Compare constant arguments by expression. + */ auto operator<=>(ConstantTArg const&) const = default; }; diff --git a/include/mrdocs/Metadata/TArg/TArgBase.hpp b/include/mrdocs/Metadata/TArg/TArgBase.hpp index 8f957351f8..1d7c8a142e 100644 --- a/include/mrdocs/Metadata/TArg/TArgBase.hpp +++ b/include/mrdocs/Metadata/TArg/TArgBase.hpp @@ -24,23 +24,35 @@ namespace mrdocs { #define INFO(Type) struct Type##TArg; #include +/** Base class for any template argument. +*/ struct TArg { - /** The kind of template argument this is. */ + /** The kind of template argument this is. + */ TArgKind Kind = TArgKind::Type; - /** Whether this template argument is a parameter expansion. */ + /** Whether this template argument is a parameter expansion. + */ bool IsPackExpansion = false; + /** Polymorphic base needs a virtual destructor. + */ constexpr virtual ~TArg() = default; + /** Compare arguments by stored data. + */ auto operator<=>(TArg const&) const = default; + /** View this object as a TArg reference. + */ constexpr TArg const& asTArg() const noexcept { return *this; } + /** View this object as a mutable TArg reference. + */ constexpr TArg& asTArg() noexcept { return *this; @@ -82,8 +94,12 @@ struct TArg #include protected: + /** Defaulted base constructor. + */ constexpr TArg() noexcept = default; + /** Construct with a specific argument kind. + */ constexpr TArg( TArgKind kind) noexcept @@ -92,16 +108,31 @@ struct TArg } }; +/** CRTP base that fixes the argument kind. +*/ template struct TArgCommonBase : TArg { + /** Static discriminator for the concrete argument. + */ static constexpr TArgKind kind_id = K; + /** Test whether the kind is a type argument. + @return `true` if `kind_id` equals `TypeKind::Type`. + */ static constexpr bool isType() noexcept { return K == TArgKind::Type; } + /** Test whether the kind is a non-type constant argument. + @return `true` if `kind_id` equals `TypeKind::Constant`. + */ static constexpr bool isConstant() noexcept { return K == TArgKind::Constant; } + /** Test whether the kind is a template argument. + @return `true` if `kind_id` equals `TypeKind::Template`. + */ static constexpr bool isTemplate() noexcept { return K == TArgKind::Template; } protected: + /** Construct with the fixed kind. + */ constexpr TArgCommonBase() noexcept : TArg(K) @@ -109,10 +140,15 @@ struct TArgCommonBase : TArg } }; +/** Convert a template argument to a human-readable string. + @return Descriptive text for the argument. +*/ MRDOCS_DECL std::string toString(TArg const& arg) noexcept; +/** Serialize the argument to a DOM value. +*/ MRDOCS_DECL void tag_invoke( diff --git a/include/mrdocs/Metadata/TArg/TArgKind.hpp b/include/mrdocs/Metadata/TArg/TArgKind.hpp index a7f45272e0..cf63868971 100644 --- a/include/mrdocs/Metadata/TArg/TArgKind.hpp +++ b/include/mrdocs/Metadata/TArg/TArgKind.hpp @@ -22,16 +22,20 @@ namespace mrdocs { /** The kind of template argument. */ -enum class TArgKind : int -{ - #define INFO(Type) Type, +enum class TArgKind : int { +#define INFO(Type) Type, #include }; +/** Convert a template-argument kind to a string. + @return String view naming the argument kind. +*/ MRDOCS_DECL std::string_view toString(TArgKind kind) noexcept; +/** Serialize a template-argument kind into a DOM value. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/TArg/TemplateTArg.hpp b/include/mrdocs/Metadata/TArg/TemplateTArg.hpp index 64bd3db20d..4bb495ad52 100644 --- a/include/mrdocs/Metadata/TArg/TemplateTArg.hpp +++ b/include/mrdocs/Metadata/TArg/TemplateTArg.hpp @@ -21,15 +21,21 @@ namespace mrdocs { +/** Template template argument. +*/ struct TemplateTArg final : TArgCommonBase { - /** SymbolID of the referenced template. */ + /** SymbolID of the referenced template. + */ SymbolID Template; - /** Name of the referenced template. */ + /** Name of the referenced template. + */ std::string Name; + /** Compare template arguments by referenced template. + */ auto operator<=>(TemplateTArg const&) const = default; }; diff --git a/include/mrdocs/Metadata/TArg/TypeTArg.hpp b/include/mrdocs/Metadata/TArg/TypeTArg.hpp index 432641439f..59653c3ed8 100644 --- a/include/mrdocs/Metadata/TArg/TypeTArg.hpp +++ b/include/mrdocs/Metadata/TArg/TypeTArg.hpp @@ -20,13 +20,17 @@ namespace mrdocs { +/** Type template argument. +*/ struct TypeTArg final : TArgCommonBase { /** Template argument type. - */ + */ Polymorphic Type = Polymorphic(AutoType{}); + /** Compare type arguments by referenced type. + */ auto operator<=>(TypeTArg const&) const = default; }; diff --git a/include/mrdocs/Metadata/TParam.hpp b/include/mrdocs/Metadata/TParam.hpp index ee1fe6613b..3319fd4aeb 100644 --- a/include/mrdocs/Metadata/TParam.hpp +++ b/include/mrdocs/Metadata/TParam.hpp @@ -22,6 +22,12 @@ namespace mrdocs { +/** Visit a template parameter, dispatching to its concrete type. + @param P Parameter to visit. + @param f Callable to receive the concrete parameter. + @param args Additional arguments forwarded to the callable. + @return Whatever the callable returns. +*/ template< typename TParamTy, typename F, @@ -53,16 +59,22 @@ visit( } } +/** Compare polymorphic template parameters. +*/ MRDOCS_DECL std::strong_ordering operator<=>(Polymorphic const& lhs, Polymorphic const& rhs); +/** Equality helper for polymorphic template parameters. +*/ inline bool operator==(Polymorphic const& lhs, Polymorphic const& rhs) { return lhs <=> rhs == std::strong_ordering::equal; } +/** Serialize a polymorphic template parameter. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/TParam/ConstantTParam.hpp b/include/mrdocs/Metadata/TParam/ConstantTParam.hpp index 51b3547369..27a8e11cfc 100644 --- a/include/mrdocs/Metadata/TParam/ConstantTParam.hpp +++ b/include/mrdocs/Metadata/TParam/ConstantTParam.hpp @@ -27,13 +27,16 @@ namespace mrdocs { Before C++26, constant template parameters were called non-type template parameter in the standard wording. The terminology was changed by P2841R6 / PR#7587. - */ +*/ struct ConstantTParam final : TParamCommonBase { - /** Type of the non-type template parameter */ + /** Type of the non-type template parameter + */ Polymorphic Type = Polymorphic(AutoType{}); + /** Compare constant parameters by type and defaults. + */ std::strong_ordering operator<=>(ConstantTParam const&) const; }; diff --git a/include/mrdocs/Metadata/TParam/TParamBase.hpp b/include/mrdocs/Metadata/TParam/TParamBase.hpp index c6a2692893..1e0f40da63 100644 --- a/include/mrdocs/Metadata/TParam/TParamBase.hpp +++ b/include/mrdocs/Metadata/TParam/TParamBase.hpp @@ -29,32 +29,43 @@ class DomCorpus; #define INFO(Type) struct Type##TParam; #include +/** Base class for a template parameter declaration. +*/ struct TParam { /** The kind of template parameter this is - */ + */ TParamKind Kind = TParamKind::Type; /** The template parameters name, if any - */ + */ std::string Name; - /** Whether this template parameter is a parameter pack */ + /** Whether this template parameter is a parameter pack + */ bool IsParameterPack = false; /** The default template argument, if any - */ + */ Optional> Default = std::nullopt; + /** Polymorphic base needs a virtual destructor. + */ constexpr virtual ~TParam() = default; + /** Compare parameters by kind, name, pack flag, and default. + */ std::strong_ordering operator<=>(TParam const&) const; + /** View this object as a TParam reference. + */ constexpr TParam const& asTParam() const noexcept { return *this; } + /** View this object as a mutable TParam reference. + */ constexpr TParam& asTParam() noexcept { return *this; @@ -95,11 +106,14 @@ struct TParam } #include - protected: + /** Defaulted base constructor. + */ constexpr TParam() noexcept = default; + /** Construct with a fixed parameter kind. + */ constexpr TParam( TParamKind kind) noexcept @@ -108,6 +122,8 @@ struct TParam } }; +/** Serialize a template parameter into a DOM value. +*/ void tag_invoke( dom::ValueFromTag, @@ -115,18 +131,37 @@ tag_invoke( TParam const& I, DomCorpus const* domCorpus); +/** CRTP base that fixes the parameter kind. +*/ template struct TParamCommonBase : TParam { + /** Static discriminator for the concrete parameter. + */ static constexpr TParamKind kind_id = K; + /** True if the parameter is a type parameter. + @return `true` when `kind_id` equals `TParamKind::Type`. + */ static constexpr bool isType() noexcept { return K == TParamKind::Type; } + + /** True if the parameter is a non-type parameter. + @return `true` when `kind_id` equals `TParamKind::Constant`. + */ static constexpr bool isConstant() noexcept { return K == TParamKind::Constant; } + + /** True if the parameter is a template template parameter. + @return `true` when `kind_id` equals `TParamKind::Template`. + */ static constexpr bool isTemplate() noexcept { return K == TParamKind::Template; } + /** Compare parameters by their fields. + */ auto operator<=>(TParamCommonBase const&) const = default; protected: + /** Construct with the fixed kind. + */ constexpr TParamCommonBase() noexcept : TParam(K) diff --git a/include/mrdocs/Metadata/TParam/TParamKeyKind.hpp b/include/mrdocs/Metadata/TParam/TParamKeyKind.hpp index a897eb7c45..75fe328878 100644 --- a/include/mrdocs/Metadata/TParam/TParamKeyKind.hpp +++ b/include/mrdocs/Metadata/TParam/TParamKeyKind.hpp @@ -20,7 +20,8 @@ namespace mrdocs { -/** The keyword a template parameter was declared with */ +/** The keyword a template parameter was declared with +*/ enum class TParamKeyKind : int { /// Class keyword @@ -29,10 +30,15 @@ enum class TParamKeyKind : int Typename }; +/** Convert the keyword kind to its string form. + @return String view naming the keyword. +*/ MRDOCS_DECL std::string_view toString(TParamKeyKind kind) noexcept; +/** Serialize the keyword kind into a DOM value. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/TParam/TParamKind.hpp b/include/mrdocs/Metadata/TParam/TParamKind.hpp index 7a6088b2ed..8ca91607f2 100644 --- a/include/mrdocs/Metadata/TParam/TParamKind.hpp +++ b/include/mrdocs/Metadata/TParam/TParamKind.hpp @@ -19,12 +19,17 @@ namespace mrdocs { +/** Discriminates the different template parameter categories. +*/ enum class TParamKind : int { - #define INFO(Type) Type, +#define INFO(Type) Type, #include }; +/** Convert a parameter kind to a readable string. + @return String view naming the parameter category. +*/ MRDOCS_DECL std::string_view toString(TParamKind kind) noexcept; diff --git a/include/mrdocs/Metadata/TParam/TemplateTParam.hpp b/include/mrdocs/Metadata/TParam/TemplateTParam.hpp index 9114ad7db8..37e9e05beb 100644 --- a/include/mrdocs/Metadata/TParam/TemplateTParam.hpp +++ b/include/mrdocs/Metadata/TParam/TemplateTParam.hpp @@ -21,12 +21,17 @@ namespace mrdocs { +/** Template template parameter. +*/ struct TemplateTParam final : TParamCommonBase { - /** Template parameters for the template-template parameter */ + /** Template parameters for the template-template parameter + */ std::vector> Params; + /** Compare template parameters including inner parameter lists. + */ std::strong_ordering operator<=>(TemplateTParam const& other) const; }; diff --git a/include/mrdocs/Metadata/TParam/TypeTParam.hpp b/include/mrdocs/Metadata/TParam/TypeTParam.hpp index 73750ec1ba..8cd35337c7 100644 --- a/include/mrdocs/Metadata/TParam/TypeTParam.hpp +++ b/include/mrdocs/Metadata/TParam/TypeTParam.hpp @@ -23,15 +23,21 @@ namespace mrdocs { +/** Type template parameter. +*/ struct TypeTParam final : TParamCommonBase { - /** Keyword (class/typename) the parameter uses */ + /** Keyword (class/typename) the parameter uses + */ TParamKeyKind KeyKind = TParamKeyKind::Class; - /** The type-constraint for the parameter, if any. */ + /** The type-constraint for the parameter, if any. + */ Optional> Constraint = std::nullopt; + /** Compare type parameters by keyword and constraint. + */ std::strong_ordering operator<=>(TypeTParam const&) const; }; diff --git a/include/mrdocs/Metadata/Template.hpp b/include/mrdocs/Metadata/Template.hpp index 5675d96ad0..8cfa827037 100644 --- a/include/mrdocs/Metadata/Template.hpp +++ b/include/mrdocs/Metadata/Template.hpp @@ -36,6 +36,9 @@ enum class TemplateSpecKind Partial }; +/** Convert the specialization kind to a readable string. + @return String view naming the specialization category. +*/ MRDOCS_DECL std::string_view toString(TemplateSpecKind kind); @@ -45,7 +48,12 @@ toString(TemplateSpecKind kind); */ struct TemplateInfo final { + /** Template parameter list. + */ std::vector> Params; + + /** Bound arguments for specializations. + */ std::vector> Args; /** The requires-clause for the template parameter list, if any. @@ -60,6 +68,9 @@ struct TemplateInfo final // to determine the specialization kind *should* work. // emphasis on should. TemplateSpecKind + + /** Deduce which specialization category this info represents. + */ specializationKind() const noexcept { if (Params.empty()) @@ -73,14 +84,20 @@ struct TemplateInfo final return TemplateSpecKind::Partial; } + /** Compare templates by parameters, arguments, and primary. + */ std::strong_ordering operator<=>(TemplateInfo const& other) const; }; +/** Merge partial template info, filling missing pieces. +*/ MRDOCS_DECL void merge(TemplateInfo& I, TemplateInfo&& Other); +/** Compare optional template infos, treating disengaged as ordered before engaged. +*/ inline auto operator<=>(Optional const& lhs, Optional const& rhs) @@ -100,6 +117,8 @@ operator<=>(Optional const& lhs, Optional const& rhs return *lhs <=> *rhs; } +/** Equality helper for optional template info. +*/ inline bool operator==(Optional const& lhs, Optional const& rhs) @@ -107,6 +126,8 @@ operator==(Optional const& lhs, Optional const& rhs) return lhs <=> rhs == std::strong_ordering::equal; } +/** Serialize template info into a DOM value. +*/ MRDOCS_DECL void tag_invoke( @@ -115,6 +136,8 @@ tag_invoke( TemplateInfo const& I, DomCorpus const* domCorpus); +/** Serialize an optional template info into a DOM value. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Type.hpp b/include/mrdocs/Metadata/Type.hpp index 9cc7e084b0..1e15a439e3 100644 --- a/include/mrdocs/Metadata/Type.hpp +++ b/include/mrdocs/Metadata/Type.hpp @@ -28,53 +28,60 @@ namespace mrdocs { +/** Visit a @ref Type with the provided callable. + + @param info The type instance to visit. + @param fn The callable to dispatch to the concrete type. + @param args Additional arguments forwarded to the callable. + @return Whatever the callable returns. +*/ template< std::derived_from TypeTy, class F, class... Args> decltype(auto) visit( - TypeTy& I, - F&& f, + TypeTy& info, + F&& fn, Args&&... args) { - add_cv_from_t& II = I; - switch(I.Kind) + add_cv_from_t& II = info; + switch(info.Kind) { case TypeKind::Named: - return f(static_cast&>(II), std::forward(args)...); case TypeKind::Decltype: - return f(static_cast&>(II), std::forward(args)...); case TypeKind::Auto: - return f(static_cast&>(II), std::forward(args)...); case TypeKind::LValueReference: - return f(static_cast&>(II), std::forward(args)...); case TypeKind::RValueReference: - return f(static_cast&>(II), std::forward(args)...); case TypeKind::Pointer: - return f(static_cast&>(II), std::forward(args)...); case TypeKind::MemberPointer: - return f(static_cast&>(II), std::forward(args)...); case TypeKind::Array: - return f(static_cast&>(II), std::forward(args)...); case TypeKind::Function: - return f(static_cast&>(II), std::forward(args)...); default: @@ -82,16 +89,22 @@ visit( } } +/** Compare two polymorphic types for ordering. +*/ MRDOCS_DECL std::strong_ordering operator<=>(Polymorphic const& lhs, Polymorphic const& rhs); +/** Equality helper for polymorphic types. +*/ inline bool operator==(Polymorphic const& lhs, Polymorphic const& rhs) { return lhs <=> rhs == std::strong_ordering::equal; } +/** Compare optional polymorphic types, treating disengaged as less. +*/ inline std::strong_ordering operator<=>( Optional> const& lhs, @@ -108,6 +121,8 @@ operator<=>( return bool(lhs) <=> bool(rhs); } +/** Equality helper for optional polymorphic types. +*/ inline bool operator==( Optional> const& lhs, @@ -155,17 +170,25 @@ MRDOCS_DECL Polymorphic const& innermostType(Polymorphic const& TI) noexcept; -/// @copydoc innermostType(Polymorphic const&) +/** Return the innermost type (mutable overload). +*/ MRDOCS_DECL Polymorphic& innermostType(Polymorphic& TI) noexcept; -// VFALCO maybe we should rename this to `renderType` or something? +/** Render a type to a human-readable string. + @param T Type to render. + @param Name Optional identifier to append. + @return Text representation of the type. +*/ MRDOCS_DECL std::string -toString(Type const& T, +toString( + Type const& T, std::string_view Name = ""); +/** Serialize a polymorphic type into a DOM value. +*/ inline void tag_invoke( @@ -178,6 +201,8 @@ tag_invoke( tag_invoke(dom::ValueFromTag{}, v, *I, domCorpus); } +/** Serialize an optional polymorphic type into a DOM value. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Type/ArrayType.hpp b/include/mrdocs/Metadata/Type/ArrayType.hpp index 2fcadb608c..34a5325a10 100644 --- a/include/mrdocs/Metadata/Type/ArrayType.hpp +++ b/include/mrdocs/Metadata/Type/ArrayType.hpp @@ -19,12 +19,21 @@ namespace mrdocs { +/** C++ array type (bounded or unbounded). +*/ struct ArrayType final : TypeCommonBase { + /** Element type held by the array. + */ Polymorphic ElementType = Polymorphic(AutoType{}); + + /** Optional bound; empty means unknown or dependent. + */ ConstantExprInfo Bounds; + /** Compare arrays by element type and bound. + */ std::strong_ordering operator<=>(ArrayType const&) const; }; diff --git a/include/mrdocs/Metadata/Type/AutoKind.hpp b/include/mrdocs/Metadata/Type/AutoKind.hpp index 2193c40df8..3f2c36a157 100644 --- a/include/mrdocs/Metadata/Type/AutoKind.hpp +++ b/include/mrdocs/Metadata/Type/AutoKind.hpp @@ -28,10 +28,15 @@ enum class AutoKind DecltypeAuto }; +/** Convert an auto-kind to its spelling. + @return String naming the keyword. +*/ MRDOCS_DECL dom::String toString(AutoKind kind) noexcept; +/** Serialize the auto kind into a DOM value. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Type/AutoType.hpp b/include/mrdocs/Metadata/Type/AutoType.hpp index 11ce16cf00..6d06c8ca3e 100644 --- a/include/mrdocs/Metadata/Type/AutoType.hpp +++ b/include/mrdocs/Metadata/Type/AutoType.hpp @@ -19,15 +19,21 @@ namespace mrdocs { +/** Represents `auto` or `decltype(auto)` placeholder type. +*/ struct AutoType final : TypeCommonBase { + /** Which placeholder keyword appears (`auto` or `decltype(auto)`). + */ AutoKind Keyword = AutoKind::Auto; /** Constraint on the auto type, if any. - */ + */ Optional> Constraint = std::nullopt; + /** Compare auto placeholders by keyword and constraint. + */ std::strong_ordering operator<=>(AutoType const&) const; }; diff --git a/include/mrdocs/Metadata/Type/DecltypeType.hpp b/include/mrdocs/Metadata/Type/DecltypeType.hpp index 79202c4081..3afe2438df 100644 --- a/include/mrdocs/Metadata/Type/DecltypeType.hpp +++ b/include/mrdocs/Metadata/Type/DecltypeType.hpp @@ -16,11 +16,17 @@ namespace mrdocs { +/** `decltype(expr)` type wrapper. +*/ struct DecltypeType final : TypeCommonBase { + /** Operand expression for decltype. + */ ExprInfo Operand; + /** Compare decltype operands. + */ auto operator<=>(DecltypeType const&) const = default; }; diff --git a/include/mrdocs/Metadata/Type/FunctionType.hpp b/include/mrdocs/Metadata/Type/FunctionType.hpp index e869665a08..b2c1b05fe4 100644 --- a/include/mrdocs/Metadata/Type/FunctionType.hpp +++ b/include/mrdocs/Metadata/Type/FunctionType.hpp @@ -20,15 +20,29 @@ namespace mrdocs { +/** Function type with parameters, qualifiers, and noexcept info. +*/ struct FunctionType final : TypeCommonBase { + /** Return type, defaults to `auto` when unknown. + */ Polymorphic ReturnType = Polymorphic(AutoType{}); + /** Parameter types in declaration order. + */ std::vector> ParamTypes; + /** Reference qualifier (if present). + */ ReferenceKind RefQualifier = ReferenceKind::None; + /** Exception specification information. + */ NoexceptInfo ExceptionSpec; + /** True when this function type is variadic. + */ bool IsVariadic = false; + /** Compare function types by return, params, and qualifiers. + */ std::strong_ordering operator<=>(FunctionType const&) const; }; diff --git a/include/mrdocs/Metadata/Type/FundamentalTypeKind.hpp b/include/mrdocs/Metadata/Type/FundamentalTypeKind.hpp index 7687a4b06f..df3e7f74ee 100644 --- a/include/mrdocs/Metadata/Type/FundamentalTypeKind.hpp +++ b/include/mrdocs/Metadata/Type/FundamentalTypeKind.hpp @@ -72,7 +72,7 @@ enum class FundamentalTypeKind the shortest canonical string representing the type. @return The string representation of the kind - */ +*/ MRDOCS_DECL std::string_view toString(FundamentalTypeKind kind) noexcept; @@ -90,7 +90,7 @@ toString(FundamentalTypeKind kind) noexcept; @param[out] kind The resulting FundamentalTypeKind @return true if the string was successfully converted - */ +*/ MRDOCS_DECL bool fromString(std::string_view str, FundamentalTypeKind& kind) noexcept; @@ -106,7 +106,7 @@ fromString(std::string_view str, FundamentalTypeKind& kind) noexcept; @param[in/out] kind The type to modify @return Whether the operation was successful - */ +*/ MRDOCS_DECL bool makeLong(FundamentalTypeKind& kind) noexcept; @@ -122,7 +122,7 @@ makeLong(FundamentalTypeKind& kind) noexcept; @param[in/out] kind The type to modify @return Whether the operation was successful - */ +*/ MRDOCS_DECL bool makeShort(FundamentalTypeKind& kind) noexcept; @@ -148,7 +148,7 @@ makeShort(FundamentalTypeKind& kind) noexcept; @param[in/out] kind The type to modify @return Whether the operation was successful - */ +*/ MRDOCS_DECL bool makeSigned(FundamentalTypeKind& kind) noexcept; @@ -167,7 +167,7 @@ makeSigned(FundamentalTypeKind& kind) noexcept; @param[in/out] kind The type to modify @return Whether the operation was successful - */ +*/ MRDOCS_DECL bool makeUnsigned(FundamentalTypeKind& kind) noexcept; @@ -186,7 +186,7 @@ makeUnsigned(FundamentalTypeKind& kind) noexcept; @param[in/out] kind The type to modify @return Whether the operation was successful - */ +*/ MRDOCS_DECL bool makeChar(FundamentalTypeKind& kind) noexcept; diff --git a/include/mrdocs/Metadata/Type/LValueReferenceType.hpp b/include/mrdocs/Metadata/Type/LValueReferenceType.hpp index 0899d107d9..98350df48d 100644 --- a/include/mrdocs/Metadata/Type/LValueReferenceType.hpp +++ b/include/mrdocs/Metadata/Type/LValueReferenceType.hpp @@ -18,11 +18,17 @@ namespace mrdocs { +/** An lvalue reference type. +*/ struct LValueReferenceType final : TypeCommonBase { + /** The referenced type. + */ Polymorphic PointeeType = Polymorphic(AutoType{}); + /** Compare references by pointee type. + */ std::strong_ordering operator<=>(LValueReferenceType const&) const; }; diff --git a/include/mrdocs/Metadata/Type/MemberPointerType.hpp b/include/mrdocs/Metadata/Type/MemberPointerType.hpp index ed620cb366..3ca1541b7a 100644 --- a/include/mrdocs/Metadata/Type/MemberPointerType.hpp +++ b/include/mrdocs/Metadata/Type/MemberPointerType.hpp @@ -18,12 +18,21 @@ namespace mrdocs { +/** Pointer-to-member type (object or function). +*/ struct MemberPointerType final : TypeCommonBase { + /** Containing class type. + */ Polymorphic ParentType = Polymorphic(AutoType{}); + + /** Pointee type being referenced. + */ Polymorphic PointeeType = Polymorphic(AutoType{}); + /** Compare member pointers by parent and pointee. + */ std::strong_ordering operator<=>(MemberPointerType const&) const; }; diff --git a/include/mrdocs/Metadata/Type/NamedType.hpp b/include/mrdocs/Metadata/Type/NamedType.hpp index 9328565937..f7c434217e 100644 --- a/include/mrdocs/Metadata/Type/NamedType.hpp +++ b/include/mrdocs/Metadata/Type/NamedType.hpp @@ -22,13 +22,21 @@ namespace mrdocs { +/** A type identified by name (possibly fundamental). +*/ struct NamedType final : TypeCommonBase { + /** The name of the type (identifier or specialization). + */ Polymorphic Name = Polymorphic(std::in_place_type); + /** Fundamental kind if this named type is a built-in. + */ Optional FundamentalType; + /** Compare named types by name and fundamental kind. + */ std::strong_ordering operator<=>(NamedType const& other) const; }; diff --git a/include/mrdocs/Metadata/Type/PointerType.hpp b/include/mrdocs/Metadata/Type/PointerType.hpp index b7a6b3e0d2..30680582a7 100644 --- a/include/mrdocs/Metadata/Type/PointerType.hpp +++ b/include/mrdocs/Metadata/Type/PointerType.hpp @@ -18,11 +18,17 @@ namespace mrdocs { +/** Pointer type wrapper. +*/ struct PointerType final : TypeCommonBase { + /** The pointee type, defaults to `auto` when unknown. + */ Polymorphic PointeeType = Polymorphic(AutoType{}); + /** Compare pointer types by pointee. + */ std::strong_ordering operator<=>(PointerType const&) const; }; diff --git a/include/mrdocs/Metadata/Type/QualifierKind.hpp b/include/mrdocs/Metadata/Type/QualifierKind.hpp index 05ed091a8c..d3d968cdcc 100644 --- a/include/mrdocs/Metadata/Type/QualifierKind.hpp +++ b/include/mrdocs/Metadata/Type/QualifierKind.hpp @@ -36,10 +36,14 @@ enum QualifierKind Volatile }; +/** Convert a cv/ref qualifier kind to its string form. +*/ MRDOCS_DECL dom::String toString(QualifierKind kind) noexcept; +/** Map a QualifierKind into a DOM value. +*/ inline void tag_invoke( diff --git a/include/mrdocs/Metadata/Type/RValueReferenceType.hpp b/include/mrdocs/Metadata/Type/RValueReferenceType.hpp index 57703d2236..ed62f73818 100644 --- a/include/mrdocs/Metadata/Type/RValueReferenceType.hpp +++ b/include/mrdocs/Metadata/Type/RValueReferenceType.hpp @@ -18,11 +18,17 @@ namespace mrdocs { +/** An rvalue reference type. +*/ struct RValueReferenceType final : TypeCommonBase { + /** The referenced type, defaults to `auto` when unknown. + */ Polymorphic PointeeType = Polymorphic(AutoType{}); + /** Compare rvalue references by pointee. + */ std::strong_ordering operator<=>(RValueReferenceType const&) const; }; diff --git a/include/mrdocs/Metadata/Type/TypeBase.hpp b/include/mrdocs/Metadata/Type/TypeBase.hpp index 5f6ae86b2e..fdf2b4816d 100644 --- a/include/mrdocs/Metadata/Type/TypeBase.hpp +++ b/include/mrdocs/Metadata/Type/TypeBase.hpp @@ -33,7 +33,7 @@ namespace mrdocs { This base class is used to store the kind of type. Derived classes are used to store the type information according to the kind. - */ +*/ struct Type { /** The kind of Type this is */ @@ -44,11 +44,11 @@ struct Type { bool IsPackExpansion = false; /** The const qualifier - */ + */ bool IsConst = false; /** The volatile qualifier - */ + */ bool IsVolatile = false; /** The constraints associated with the type @@ -60,7 +60,7 @@ struct Type { expression `std::enable_if_t, T>` will have type `T` (NamedType) and constraints `{std::is_integral_v}`. - */ + */ std::vector Constraints; /** Return the symbol named by this type. @@ -68,13 +68,19 @@ struct Type { SymbolID namedSymbol() const noexcept; + /** Three-way comparison by kind, qualifiers, and concrete data. + */ auto operator<=>(Type const&) const = default; + /** View as const Type. + */ constexpr Type const& asType() const noexcept { return *this; } + /** View as mutable Type. + */ constexpr Type& asType() noexcept { return *this; @@ -116,8 +122,12 @@ struct Type { #include protected: + /** Virtual destructor for polymorphic base. + */ constexpr virtual ~Type() = default; + /** Construct with a concrete type kind. + */ constexpr Type( TypeKind kind) noexcept : Kind(kind) @@ -125,6 +135,8 @@ struct Type { } }; +/** Serialize a Type into a DOM value. +*/ MRDOCS_DECL void tag_invoke( @@ -133,23 +145,58 @@ tag_invoke( Type const& I, DomCorpus const* domCorpus); +/** CRTP base that ties a concrete type to a fixed TypeKind. +*/ template struct TypeCommonBase : Type { + /** Static discriminator for the concrete type. + */ static constexpr TypeKind kind_id = K; + /** True when this concrete kind is a named type. + @return `true` if `kind_id` is `TypeKind::Named`. + */ static constexpr bool isNamed() noexcept { return K == TypeKind::Named; } + /** True when this concrete kind is decltype. + @return `true` if `kind_id` is `TypeKind::Decltype`. + */ static constexpr bool isDecltype() noexcept { return K == TypeKind::Decltype; } + /** True when this concrete kind is auto. + @return `true` if `kind_id` is `TypeKind::Auto`. + */ static constexpr bool isAuto() noexcept { return K == TypeKind::Auto; } + /** True when this is an lvalue reference. + @return `true` if `kind_id` is `TypeKind::LValueReference`. + */ static constexpr bool isLValueReference() noexcept { return K == TypeKind::LValueReference; } + /** True when this is an rvalue reference. + @return `true` if `kind_id` is `TypeKind::RValueReference`. + */ static constexpr bool isRValueReference() noexcept { return K == TypeKind::RValueReference; } + /** True when this is a pointer type. + @return `true` if `kind_id` is `TypeKind::Pointer`. + */ static constexpr bool isPointer() noexcept { return K == TypeKind::Pointer; } + /** True when this is a member pointer. + @return `true` if `kind_id` is `TypeKind::MemberPointer`. + */ static constexpr bool isMemberPointer() noexcept { return K == TypeKind::MemberPointer; } + /** True when this is an array type. + @return `true` if `kind_id` is `TypeKind::Array`. + */ static constexpr bool isArray() noexcept { return K == TypeKind::Array; } + /** True when this is a function type. + @return `true` if `kind_id` is `TypeKind::Function`. + */ static constexpr bool isFunction() noexcept { return K == TypeKind::Function; } + /** Compare type bases by kind-specific payload. + */ auto operator<=>(TypeCommonBase const&) const = default; protected: + /** Construct the base with the fixed kind. + */ constexpr TypeCommonBase() noexcept : Type(K) { diff --git a/include/mrdocs/Metadata/Type/TypeKind.hpp b/include/mrdocs/Metadata/Type/TypeKind.hpp index af01dcb1b8..dc1221192b 100644 --- a/include/mrdocs/Metadata/Type/TypeKind.hpp +++ b/include/mrdocs/Metadata/Type/TypeKind.hpp @@ -16,17 +16,22 @@ namespace mrdocs { -enum class TypeKind -{ - #define INFO(Type) Type, +/** Variants of C++ types captured in metadata. +*/ +enum class TypeKind { +#define INFO(Type) Type, #include }; +/** Convert a TypeKind to its string representation. +*/ MRDOCS_DECL dom::String toString(TypeKind kind) noexcept; inline +/** Map a TypeKind into a DOM value. +*/ void tag_invoke( dom::ValueFromTag, diff --git a/include/mrdocs/Support/Algorithm.hpp b/include/mrdocs/Support/Algorithm.hpp index d1eeacd787..2e28e794d2 100644 --- a/include/mrdocs/Support/Algorithm.hpp +++ b/include/mrdocs/Support/Algorithm.hpp @@ -21,7 +21,7 @@ namespace mrdocs { @param range The range to search. @param el The element to search for. @return True if the element is found, false otherwise. - */ +*/ template requires std::equality_comparable_with> bool @@ -36,7 +36,7 @@ contains(Range&& range, El const& el) @param range The range to search. @param el The element to search for. @return True if the element is found, false otherwise. - */ +*/ template requires std::equality_comparable_with bool @@ -52,7 +52,7 @@ contains(std::initializer_list const& range, U const& el) @param el The element to search for. @param range The range to search. @return True if the element is found, false otherwise. - */ +*/ template requires std::equality_comparable_with, El> bool @@ -74,7 +74,7 @@ is_one_of(U const& el, std::initializer_list const& range) @param range The range to search. @param els The elements to search for. @return True if any of the elements are found, false otherwise. - */ +*/ template requires std::equality_comparable_with, std::ranges::range_value_t> bool @@ -97,7 +97,7 @@ contains_any(Range const& range, std::initializer_list const& els) @param el The element to search for. @param n The number of instances to search for. @return True if the element is found, false otherwise. - */ +*/ template requires std::equality_comparable_with> bool @@ -122,7 +122,7 @@ contains_n(Range const& range, El const& el, std::size_t n) @param els The elements to search for. @param n The number of instances to search for. @return True if the element is found, false otherwise. - */ +*/ template requires std::equality_comparable_with, std::ranges::range_value_t> bool @@ -167,7 +167,7 @@ contains_n_any(Range const& range, std::initializer_list const& els, std::si @param range The range to search. @param els The elements to search for. @return An iterator to the last element found, or std::ranges::end(range) if not found. - */ +*/ template requires std::equality_comparable_with, std::ranges::range_value_t> auto diff --git a/include/mrdocs/Support/Assert.hpp b/include/mrdocs/Support/Assert.hpp index 77a97604d2..8748b2ab16 100644 --- a/include/mrdocs/Support/Assert.hpp +++ b/include/mrdocs/Support/Assert.hpp @@ -13,6 +13,12 @@ #include +/** Core MrDocs support utilities. + + The public `mrdocs` namespace here centralizes assert/assume hooks so we can + swap behavior (terminate, throw, debugbreak) in one place without leaking + platform specifics into the rest of the codebase. +*/ namespace mrdocs { #ifdef NDEBUG @@ -29,6 +35,12 @@ namespace mrdocs { #define MRDOCS_UNREACHABLE() static_cast(__debugbreak(), __assume(false)) #endif + /** Handler invoked when `MRDOCS_ASSERT` fails. + + @param msg Expression string that failed. + @param file Source file where the assertion triggered. + @param line Line within the source file. + */ void assert_failed( char const* msg, @@ -42,4 +54,4 @@ namespace mrdocs { } // mrdocs -#endif \ No newline at end of file +#endif diff --git a/include/mrdocs/Support/Concepts.hpp b/include/mrdocs/Support/Concepts.hpp index bc31d07db4..054547e807 100644 --- a/include/mrdocs/Support/Concepts.hpp +++ b/include/mrdocs/Support/Concepts.hpp @@ -15,7 +15,8 @@ namespace mrdocs { -/** Concept to check if a type is a range of T */ +/** Concept to check if a type is a range of T +*/ template concept range_of = std::ranges::range && std::same_as, T>; @@ -30,7 +31,7 @@ concept range_of = std::ranges::range && std::same_as` should be available and return a reference to the Base class. - */ +*/ template concept polymorphic_storage_for = requires(T const& t) { @@ -46,7 +47,7 @@ concept polymorphic_storage_for = requires(T const& t) Examples of such types are std::optional, std::unique_ptr, std::shared_ptr, Polymorphic, pointers, etc. - */ +*/ template concept dereferenceable = requires(T const& t) { @@ -99,7 +100,7 @@ struct all_tuple_elements::value>> { Examples of such types are std::tuple, std::pair, std::array, and user-defined types that provide specializations for std::tuple_size and std::tuple_element. - */ +*/ template concept tuple_like = detail::has_tuple_size::value && @@ -115,7 +116,7 @@ concept tuple_like = types that provide specializations for std::tuple_size and std::tuple_element with exactly two elements. - */ +*/ template concept pair_like = tuple_like && @@ -130,7 +131,7 @@ concept pair_like = std::list>, and user-defined types that provide specializations for std::tuple_size and std::tuple_element for their element type. - */ +*/ template concept range_of_tuple_like = std::ranges::range && tuple_like>; @@ -139,6 +140,8 @@ concept range_of_tuple_like = using std::reference_constructs_from_temporary_v; using std::reference_converts_from_temporary_v; #else + /** True when binding `To` from `From` would require a temporary conversion. + */ template concept reference_converts_from_temporary_v = std::is_reference_v @@ -151,6 +154,8 @@ concept range_of_tuple_like = && std::is_convertible_v&&> && !std::is_convertible_v&>) ); + /** Like `reference_converts_from_temporary_v`, but for construction. + */ template concept reference_constructs_from_temporary_v = reference_converts_from_temporary_v; diff --git a/include/mrdocs/Support/Error.hpp b/include/mrdocs/Support/Error.hpp index 8d8cf92ce7..84346408f4 100644 --- a/include/mrdocs/Support/Error.hpp +++ b/include/mrdocs/Support/Error.hpp @@ -192,6 +192,8 @@ class MRDOCS_DECL */ [[noreturn]] void Throw() &&; + /** Swap the contents with another error. + */ constexpr void swap(Error& rhs) noexcept @@ -292,24 +294,38 @@ class MRDOCS_DECL std::string_view func_; public: + /** Build a location wrapper from a `source_location`. + */ SourceLocation( source_location const& loc) noexcept; + /** File name associated with the location. + @return Path of the source file. + */ std::string_view file_name() const noexcept { return file_; } + /** Line number (1-based) within the file. + @return One-based line index. + */ std::uint_least32_t line() const noexcept { return line_; } + /** Column number (1-based) within the file. + @return One-based column index. + */ std::uint_least32_t column() const noexcept { return col_; } + /** Function name captured at the location. + @return Name of the function where the location was recorded. + */ std::string_view function_name() const noexcept { return func_; @@ -321,6 +337,11 @@ class MRDOCS_DECL template struct FormatString { + /** Capture a format string and its originating location. + + @param fs_ The format string to copy. + @param loc_ Source location where formatting is requested. + */ template FormatString( T const& fs_, @@ -333,7 +354,12 @@ struct FormatString std::string_view, T const&>); } + /** Format string view. + */ std::string_view fs; + + /** Originating source location for diagnostics. + */ source_location loc; }; diff --git a/include/mrdocs/Support/ExecutorGroup.hpp b/include/mrdocs/Support/ExecutorGroup.hpp index 0ef56bcf70..805fff4cb6 100644 --- a/include/mrdocs/Support/ExecutorGroup.hpp +++ b/include/mrdocs/Support/ExecutorGroup.hpp @@ -23,34 +23,61 @@ namespace mrdocs { -class MRDOCS_DECL - ExecutorGroupBase +/** Base class that owns a pool of execution agents and a shared work queue. +*/ +class MRDOCS_DECL ExecutorGroupBase { class scoped_agent; protected: + /** Opaque implementation shared by all ExecutorGroup instantiations. + */ struct Impl; - struct MRDOCS_DECL - AnyAgent + /** Type-erased agent holder used by the base class. + */ + struct MRDOCS_DECL AnyAgent { + /** Virtual destructor to allow deleting through the base pointer. + */ virtual ~AnyAgent() = 0; + /** Return a pointer to the stored agent object. + */ virtual void* get() noexcept = 0; }; + /** Opaque implementation pointer shared by all ExecutorGroup instantiations. + */ std::unique_ptr impl_; + /** Agents owned by the group. + */ std::vector> agents_; + /** Pending work posted to the group. + */ std::deque> work_; + /** Construct with a backing thread pool. + */ explicit ExecutorGroupBase(ThreadPool&); - void post(any_callable); - void run(std::unique_lock); + /** Queue work to run on the group agents. + */ + void post(any_callable work); + /** Execute queued work until empty. + @param lock Held lock protecting the work queue. + */ + void run(std::unique_lock lock); public: template + /** Argument wrapper propagated from ThreadPool. + */ using arg_t = ThreadPool::arg_t; + /** Destroy the executor group, waiting for outstanding work. + */ ~ExecutorGroupBase(); + /** Move-construct from another group. + */ ExecutorGroupBase(ExecutorGroupBase&&) noexcept; /** Block until all work has completed. @@ -87,6 +114,9 @@ class ExecutorGroup : public ExecutorGroupBase }; public: + /** Construct a new executor group bound to a thread pool. + @param threadPool Pool that owns the worker threads. + */ explicit ExecutorGroup( ThreadPool& threadPool) diff --git a/include/mrdocs/Support/Expected.hpp b/include/mrdocs/Support/Expected.hpp index 589e1ca780..a8f7e60be2 100644 --- a/include/mrdocs/Support/Expected.hpp +++ b/include/mrdocs/Support/Expected.hpp @@ -40,27 +40,39 @@ class Expected; template class Unexpected; +/** Base class for accessing an empty Expected. +*/ template class BadExpectedAccess; +/** Exception thrown when reading the value of an empty Expected. +*/ template <> class BadExpectedAccess : public std::exception { protected: + /// Default constructor. BadExpectedAccess() noexcept = default; + /// Copy constructor. BadExpectedAccess(BadExpectedAccess const&) = default; + /// Move constructor. BadExpectedAccess(BadExpectedAccess&&) = default; + /// Copy assignment. BadExpectedAccess& operator=(BadExpectedAccess const&) = default; + /// Move assignment. BadExpectedAccess& operator=(BadExpectedAccess&&) = default; + /// Virtual destructor. ~BadExpectedAccess() override = default; public: + /** Return a diagnostic string. + */ [[nodiscard]] char const* what() const noexcept override @@ -69,14 +81,21 @@ class BadExpectedAccess : public std::exception } }; +/** Exception thrown when reading the error of an Expected with a value. +*/ template class BadExpectedAccess : public BadExpectedAccess { E unex_; public: + /** Construct with the unexpected error value. + */ explicit BadExpectedAccess(E e) : unex_(std::move(e)) { } + /** Access the contained error by lvalue reference. + @return Reference to the stored unexpected value. + */ [[nodiscard]] E& error() & noexcept @@ -84,6 +103,9 @@ class BadExpectedAccess : public BadExpectedAccess { return unex_; } + /** Access the contained error by const lvalue reference. + @return Const reference to the stored unexpected value. + */ [[nodiscard]] E const& error() const & noexcept @@ -91,6 +113,9 @@ class BadExpectedAccess : public BadExpectedAccess { return unex_; } + /** Access the contained error by rvalue reference. + @return Rvalue reference to the stored unexpected value. + */ [[nodiscard]] E&& error() && noexcept @@ -98,6 +123,9 @@ class BadExpectedAccess : public BadExpectedAccess { return std::move(unex_); } + /** Access the contained error by const rvalue reference. + @return Const rvalue reference to the stored unexpected value. + */ [[nodiscard]] E const&& error() const && noexcept @@ -106,11 +134,16 @@ class BadExpectedAccess : public BadExpectedAccess { } }; +/** Tag type used to select unexpected construction. +*/ struct unexpect_t { + /// Default constructor. explicit unexpect_t() = default; }; +/** Tag object to request unexpected construction. +*/ inline constexpr unexpect_t unexpect{}; namespace detail @@ -152,6 +185,8 @@ namespace detail && !reference_constructs_from_temporary_v; } +/** Holds an unexpected error value for Expected. +*/ template class Unexpected { @@ -159,12 +194,17 @@ class Unexpected E unex_; public: + /// Copy constructor. constexpr Unexpected(Unexpected const&) = default; + /// Move constructor. constexpr Unexpected(Unexpected&&) = default; + /** Construct from an error value convertible to `E`. + @param e Error value to store. + */ template requires (!std::is_same_v, Unexpected>) && @@ -175,29 +215,47 @@ class Unexpected : unex_(std::forward(e)) {} + /** In-place construct the error value with arguments. + @param in_place Tag selecting in-place construction. + @param args Arguments forwarded to `E`'s constructor. + */ template requires std::is_constructible_v constexpr explicit - Unexpected(std::in_place_t, Args&&... args) + Unexpected(std::in_place_t in_place, Args&&... args) noexcept(std::is_nothrow_constructible_v) : unex_(std::forward(args)...) - {} + { + (void)in_place; + } + /** In-place construct the error value from an initializer list. + @param in_place Tag selecting in-place construction. + @param il Initializer list for the error. + @param args Additional constructor arguments. + */ template requires std::is_constructible_v&, Args...> constexpr explicit Unexpected( - std::in_place_t, + std::in_place_t in_place, std::initializer_list il, Args&&... args) noexcept(std::is_nothrow_constructible_v< E, std::initializer_list&, Args...>) : unex_(il, std::forward(args)...) - {} + { + (void)in_place; + } + /// Copy assignment. constexpr Unexpected& operator=(Unexpected const&) = default; + /// Move assignment. constexpr Unexpected& operator=(Unexpected&&) = default; + /** Return a const reference to the stored error. + @return Const reference to `E`. + */ [[nodiscard]] constexpr E const& error() const & noexcept @@ -205,6 +263,9 @@ class Unexpected return unex_; } + /** Return a reference to the stored error. + @return Reference to `E`. + */ [[nodiscard]] constexpr E& error() & noexcept @@ -212,6 +273,9 @@ class Unexpected return unex_; } + /** Return a const rvalue reference to the stored error. + @return Const rvalue reference to `E`. + */ [[nodiscard]] constexpr E const&& error() const && noexcept @@ -219,6 +283,9 @@ class Unexpected return std::move(unex_); } + /** Return a rvalue reference to the stored error. + @return Rvalue reference to `E`. + */ [[nodiscard]] constexpr E&& error() && noexcept @@ -226,6 +293,8 @@ class Unexpected return std::move(unex_); } + /** Swap the contained error with another instance. + */ constexpr void swap(Unexpected& other) noexcept(std::is_nothrow_swappable_v) @@ -256,7 +325,10 @@ class Unexpected } }; -template Unexpected(E) -> Unexpected; +/** Deduction guide for Unexpected, forwarding the error type. +*/ +template +Unexpected(E) -> Unexpected; namespace detail { @@ -378,7 +450,6 @@ namespace detail #endif -/// @cond undocumented namespace detail { template @@ -443,10 +514,11 @@ namespace detail } } } -/// @endcond /** A container holding an error or a value. - */ +*/ +/** Monadic result type holding either a value `T` or an unexpected error `E`. +*/ template class Expected { @@ -488,20 +560,28 @@ class Expected template friend class Expected; union { + /// Storage for the engaged value. T val_; + /// Storage for the unexpected error. E unex_; }; + /// True when the value alternative is active. bool has_value_; public: + /// Type produced on success. using value_type = T; + /// Type produced on failure. using error_type = E; + /// Convenience alias for an Unexpected containing the error type. using unexpected_type = Unexpected; template + /// Rebind to an `Expected` with a different value type and the same error type. using rebind = Expected; + /// Construct an engaged Expected with a default-initialized value. constexpr Expected() noexcept(std::is_nothrow_default_constructible_v) @@ -510,8 +590,13 @@ class Expected , has_value_(true) {} + /// Default copy constructor. Expected(Expected const&) = default; + /** Copy-construct, handling non-trivial alternatives. + */ + /** Copy-construct from another void Expected. + */ constexpr Expected(Expected const& x) noexcept( @@ -534,8 +619,14 @@ class Expected } } + /// Default move constructor. + /// Default move constructor. Expected(Expected&&) = default; + /** Move-construct, handling non-trivial alternatives. + */ + /** Move-construct from another void Expected. + */ constexpr Expected(Expected&& x) noexcept( @@ -558,6 +649,8 @@ class Expected } } + /** Construct from another Expected with potentially different types. + */ template requires std::is_constructible_v && @@ -581,6 +674,8 @@ class Expected } } + /** Move-construct from another Expected with potentially different types. + */ template requires std::is_constructible_v && @@ -604,6 +699,8 @@ class Expected } } + /** Construct an engaged Expected from a convertible value. + */ template requires (!std::is_same_v, Expected>) && @@ -618,6 +715,8 @@ class Expected , has_value_(true) { } + /** Construct a disengaged Expected from an unexpected error (copy). + */ template requires std::is_constructible_v constexpr @@ -628,6 +727,8 @@ class Expected , has_value_(false) { } + /** Construct a disengaged Expected from an unexpected error (move). + */ template requires std::is_constructible_v constexpr @@ -638,6 +739,9 @@ class Expected , has_value_(false) { } + /** Construct an engaged Expected in-place. + @param args Arguments forwarded to the value constructor. + */ template requires std::is_constructible_v constexpr explicit @@ -645,8 +749,13 @@ class Expected noexcept(std::is_nothrow_constructible_v) : val_(std::forward(args)...) , has_value_(true) - { } + { + } + /** Construct an engaged Expected from an initializer list. + @param il Initializer list forwarded to the value constructor. + @param args Additional arguments forwarded to the value constructor. + */ template requires std::is_constructible_v&, Args...> @@ -660,8 +769,12 @@ class Expected T, std::initializer_list&, Args...>) : val_(il, std::forward(args)...) , has_value_(true) - { } + { + } + /** Construct a disengaged Expected holding an error. + @param args Arguments forwarded to the error constructor. + */ template requires std::is_constructible_v constexpr explicit @@ -669,8 +782,13 @@ class Expected noexcept(std::is_nothrow_constructible_v) : unex_(std::forward(args)...) , has_value_(false) - { } + { + } + /** Construct a disengaged Expected from an initializer list. + @param il Initializer list forwarded to the error constructor. + @param args Additional arguments forwarded to the error constructor. + */ template requires std::is_constructible_v&, Args...> constexpr explicit @@ -683,10 +801,14 @@ class Expected E, std::initializer_list&, Args...>) : unex_(il, std::forward(args)...) , has_value_(false) - { } + { + } + /// Defaulted trivial destructor when both alternatives are trivial. constexpr ~Expected() = default; + /** Destroy the active alternative when a non-trivial destructor is required. + */ constexpr ~Expected() requires (!std::is_trivially_destructible_v) @@ -702,9 +824,13 @@ class Expected } } + /** Copy-assign from another Expected. + */ Expected& operator=(Expected const&) = delete; + /** Assign from another Expected with compatible value/error types. + */ constexpr Expected& operator=(Expected const& x) @@ -732,6 +858,8 @@ class Expected return *this; } + /** Move-assign from another Expected with compatible value/error types. + */ constexpr Expected& operator=(Expected&& x) @@ -759,6 +887,8 @@ class Expected return *this; } + /** Assign a new value, reconstructing if currently disengaged. + */ template requires (!std::is_same_v>) && @@ -776,6 +906,8 @@ class Expected return *this; } + /** Assign a new unexpected error from lvalue. + */ template requires std::is_constructible_v && @@ -791,6 +923,8 @@ class Expected return *this; } + /** Assign a new unexpected error from rvalue. + */ template requires std::is_constructible_v && @@ -806,6 +940,10 @@ class Expected return *this; } + /** Reconstruct the value in-place, discarding any current state. + @param args Arguments forwarded to the value constructor. + @return Reference to the newly emplaced value. + */ template requires std::is_nothrow_constructible_v constexpr @@ -827,6 +965,11 @@ class Expected return val_; } + /** Reconstruct the value from an initializer list. + @param il Initializer list forwarded to the value constructor. + @param args Additional constructor arguments. + @return Reference to the newly emplaced value. + */ template requires std::is_nothrow_constructible_v< @@ -850,6 +993,8 @@ class Expected return val_; } + /** Swap the stored state with another Expected. + */ constexpr void swap(Expected& x) @@ -894,6 +1039,9 @@ class Expected // observers + /** Access value members through pointer syntax. + @return Pointer to the contained value. + */ [[nodiscard]] constexpr T const* @@ -903,6 +1051,9 @@ class Expected return std::addressof(val_); } + /** Access value members through pointer syntax. + @return Pointer to the contained value. + */ [[nodiscard]] constexpr T* @@ -912,6 +1063,9 @@ class Expected return std::addressof(val_); } + /** Dereference to a const lvalue value reference. + @return Reference to the contained value. + */ [[nodiscard]] constexpr T const& @@ -921,6 +1075,9 @@ class Expected return val_; } + /** Dereference to an lvalue value reference. + @return Reference to the contained value. + */ [[nodiscard]] constexpr T& @@ -930,6 +1087,9 @@ class Expected return val_; } + /** Dereference to a const rvalue value reference. + @return Reference to the contained value. + */ [[nodiscard]] constexpr T const&& @@ -939,6 +1099,9 @@ class Expected return std::move(val_); } + /** Dereference to an rvalue value reference. + @return Reference to the contained value. + */ [[nodiscard]] constexpr T&& @@ -948,6 +1111,8 @@ class Expected return std::move(val_); } + /** Return true when the Expected contains a value. + */ [[nodiscard]] constexpr explicit operator bool() const noexcept @@ -955,12 +1120,17 @@ class Expected return has_value_; } + /** Return true when the Expected contains a value. + */ [[nodiscard]] constexpr bool has_value() const noexcept { return has_value_; } + /** Access the stored value or throw BadExpectedAccess. + @return Reference to the contained value. + */ constexpr T const& value() const & { @@ -971,6 +1141,9 @@ class Expected throw BadExpectedAccess(unex_); } + /** Access the stored value or throw BadExpectedAccess. + @return Reference to the contained value. + */ constexpr T& value() & { @@ -982,6 +1155,9 @@ class Expected throw BadExpectedAccess(unex); } + /** Access the stored value or throw BadExpectedAccess (rvalue overload). + @return Rvalue reference to the contained value. + */ constexpr T const&& value() const && { @@ -992,6 +1168,9 @@ class Expected throw BadExpectedAccess(std::move(unex_)); } + /** Access the stored value or throw BadExpectedAccess (rvalue overload). + @return Rvalue reference to the contained value. + */ constexpr T&& value() && { @@ -1002,6 +1181,9 @@ class Expected throw BadExpectedAccess(std::move(unex_)); } + /** Access the stored error; precondition: !has_value(). + @return Reference to the contained error. + */ constexpr E const& error() const & noexcept { @@ -1009,6 +1191,9 @@ class Expected return unex_; } + /** Access the stored error; precondition: !has_value(). + @return Reference to the contained error. + */ constexpr E& error() & noexcept { @@ -1016,6 +1201,9 @@ class Expected return unex_; } + /** Access the stored error; precondition: !has_value(). + @return Rvalue reference to the contained error. + */ constexpr E const&& error() const && noexcept { @@ -1023,6 +1211,9 @@ class Expected return std::move(unex_); } + /** Access the stored error; precondition: !has_value(). + @return Rvalue reference to the contained error. + */ constexpr E&& error() && noexcept { @@ -1030,6 +1221,10 @@ class Expected return std::move(unex_); } + /** Return the contained value or a fallback copy. + @param v Fallback value to use when disengaged. + @return Contained value or the fallback converted to `T`. + */ template constexpr T @@ -1047,6 +1242,10 @@ class Expected return static_cast(std::forward(v)); } + /** Return the contained value or a fallback move. + @param v Fallback value to use when disengaged. + @return Contained value or the fallback converted to `T`. + */ template constexpr T @@ -1064,6 +1263,10 @@ class Expected return static_cast(std::forward(v)); } + /** Return the contained error or a fallback copy. + @param e Fallback error to use when engaged. + @return Contained error or the fallback converted to `E`. + */ template constexpr E @@ -1078,6 +1281,10 @@ class Expected return unex_; } + /** Return the contained error or a fallback move. + @param e Fallback error to use when engaged. + @return Contained error or the fallback converted to `E`. + */ template constexpr E error_or(G&& e) && @@ -1091,6 +1298,10 @@ class Expected return std::move(unex_); } + /** Invoke `f` when engaged, propagate error otherwise. + @param f Continuation that returns another Expected. + @return Result of `f` or this error. + */ template requires std::is_constructible_v constexpr @@ -1111,6 +1322,10 @@ class Expected } } + /** Invoke `f` when engaged (const lvalue), propagate error otherwise. + @param f Continuation that returns another Expected. + @return Result of `f` or this error. + */ template requires std::is_constructible_v constexpr @@ -1131,6 +1346,10 @@ class Expected } } + /** Invoke `f` when engaged (rvalue), propagate error otherwise. + @param f Continuation that returns another Expected. + @return Result of `f` or this error. + */ template requires std::is_constructible_v constexpr @@ -1152,6 +1371,10 @@ class Expected } + /** Invoke `f` when engaged (const rvalue), propagate error otherwise. + @param f Continuation that returns another Expected. + @return Result of `f` or this error. + */ template requires std::is_constructible_v constexpr @@ -1172,6 +1395,10 @@ class Expected } } + /** Invoke `f` when in error, otherwise return current value. + @param f Recovery function returning an Expected. + @return Current value or result of `f`. + */ template requires std::is_constructible_v constexpr @@ -1192,6 +1419,10 @@ class Expected } } + /** Invoke `f` when in error (const lvalue). + @param f Recovery function returning an Expected. + @return Current value or result of `f`. + */ template requires std::is_constructible_v constexpr @@ -1212,6 +1443,10 @@ class Expected } } + /** Invoke `f` when in error (rvalue). + @param f Recovery function returning an Expected. + @return Current value or result of `f`. + */ template requires std::is_constructible_v constexpr @@ -1232,6 +1467,10 @@ class Expected } } + /** Invoke `f` when in error (const rvalue). + @param f Recovery function returning an Expected. + @return Current value or result of `f`. + */ template requires std::is_constructible_v constexpr @@ -1252,6 +1491,10 @@ class Expected } } + /** Map the contained value, propagate error. + @param f Mapping function applied to the value. + @return Expected holding the mapped value or the original error. + */ template requires std::is_constructible_v constexpr @@ -1274,6 +1517,10 @@ class Expected } } + /** Map the contained value (const overload), propagate error. + @param f Mapping function applied to the value. + @return Expected holding the mapped value or the original error. + */ template requires std::is_constructible_v constexpr @@ -1296,6 +1543,10 @@ class Expected } } + /** Map the contained value (rvalue), propagate error. + @param f Mapping function applied to the value. + @return Expected holding the mapped value or the original error. + */ template requires std::is_constructible_v constexpr @@ -1318,6 +1569,10 @@ class Expected } } + /** Map the contained value (const rvalue), propagate error. + @param f Mapping function applied to the value. + @return Expected holding the mapped value or the original error. + */ template requires std::is_constructible_v constexpr @@ -1340,6 +1595,10 @@ class Expected } } + /** Map the contained error, preserve value. + @param f Mapping function applied to the error. + @return Expected holding the original value or mapped error. + */ template requires std::is_constructible_v constexpr @@ -1362,6 +1621,10 @@ class Expected } } + /** Map the contained error (const lvalue), preserve value. + @param f Mapping function applied to the error. + @return Expected holding the original value or mapped error. + */ template requires std::is_constructible_v constexpr @@ -1384,6 +1647,10 @@ class Expected } } + /** Map the contained error (rvalue), preserve value. + @param f Mapping function applied to the error. + @return Expected holding the original value or mapped error. + */ template requires std::is_constructible_v constexpr @@ -1406,6 +1673,10 @@ class Expected } } + /** Map the contained error (const rvalue), preserve value. + @param f Mapping function applied to the error. + @return Expected holding the original value or mapped error. + */ template requires std::is_constructible_v constexpr @@ -1467,6 +1738,8 @@ class Expected return !x.has_value() && bool(x.error() == e.error()); } + /** Swap contents with another Expected. + */ friend constexpr void @@ -1563,6 +1836,9 @@ class Expected { } }; +/** Expected specialization for `void` values. + Holds either success (no payload) or an unexpected error `E`. +*/ template requires std::is_void_v class Expected @@ -1586,29 +1862,44 @@ class Expected template friend class Expected; + struct engaged_state { }; + union { - struct { } void_; + /** Placeholder for the engaged state. + */ + engaged_state void_; + /** Stored unexpected error. + */ E unex_; }; + /// True when the expected is engaged. bool has_value_; public: + /// Value type for this specialization (always void). using value_type = T; + /// Error type stored when disengaged. using error_type = E; + /// Alias for the unexpected wrapper. using unexpected_type = Unexpected; + /// Rebind to another value type with the same error type. template using rebind = Expected; + /// Construct an engaged Expected. constexpr Expected() noexcept : void_() , has_value_(true) { } + /// Default copy constructor. Expected(Expected const&) = default; + /** Copy-construct with explicit error handling for non-trivial `E`. + */ constexpr Expected(Expected const& x) noexcept(std::is_nothrow_copy_constructible_v) @@ -1624,8 +1915,11 @@ class Expected } } + /// Default move constructor. Expected(Expected&&) = default; + /** Move-construct with explicit error handling for non-trivial `E`. + */ constexpr Expected(Expected&& x) noexcept(std::is_nothrow_move_constructible_v) @@ -1640,6 +1934,8 @@ class Expected } } + /** Copy-construct from a compatible Expected carrying void. + */ template requires std::is_void_v && @@ -1658,6 +1954,8 @@ class Expected } } + /** Move-construct from a compatible Expected carrying void. + */ template requires std::is_void_v && @@ -1676,6 +1974,8 @@ class Expected } } + /** Construct a disengaged Expected from an unexpected error (copy). + */ template requires std::is_constructible_v constexpr @@ -1686,6 +1986,8 @@ class Expected , has_value_(false) { } + /** Construct a disengaged Expected from an unexpected error (move). + */ template requires std::is_constructible_v constexpr @@ -1695,11 +1997,17 @@ class Expected : unex_(std::move(u).error()), has_value_(false) { } + /** Construct an engaged Expected with in-place tag. + */ constexpr explicit Expected(std::in_place_t) noexcept : Expected() - { } + { + } + /** Construct a disengaged Expected from error arguments. + @param args Arguments forwarded to the error constructor. + */ template requires std::is_constructible_v constexpr explicit @@ -1707,20 +2015,31 @@ class Expected noexcept(std::is_nothrow_constructible_v) : unex_(std::forward(args)...) , has_value_(false) - { } + { + } + /** Construct a disengaged Expected from an initializer list of errors. + @param il Initializer list forwarded to the error constructor. + @param args Additional arguments forwarded to the error constructor. + */ template requires std::is_constructible_v&, Args...> constexpr explicit - Expected(unexpect_t, std::initializer_list il, Args&&... args) + Expected( + unexpect_t, + std::initializer_list il, + Args&&... args) noexcept( std::is_nothrow_constructible_v< E, std::initializer_list&, Args...>) : unex_(il, std::forward(args)...), has_value_(false) - { } + { + } + /// Defaulted trivial destructor. constexpr ~Expected() = default; + /// Destroy the stored error when non-trivial. constexpr ~Expected() requires (!std::is_trivially_destructible_v) { @@ -1730,8 +2049,11 @@ class Expected } } + /// Copy assignment disabled to keep semantics explicit. Expected& operator=(Expected const&) = delete; + /** Copy-assign from another void Expected. + */ constexpr Expected& operator=(Expected const& x) @@ -1753,6 +2075,8 @@ class Expected return *this; } + /** Move-assign from another void Expected. + */ constexpr Expected& operator=(Expected&& x) @@ -1774,6 +2098,8 @@ class Expected return *this; } + /** Assign a new unexpected error (lvalue). + */ template requires std::is_constructible_v && @@ -1786,6 +2112,8 @@ class Expected return *this; } + /** Assign a new unexpected error (rvalue). + */ template requires std::is_constructible_v && @@ -1798,6 +2126,8 @@ class Expected return *this; } + /** Reset to engaged state (no error). + */ constexpr void emplace() noexcept @@ -1809,6 +2139,9 @@ class Expected } } + /** Swap states with another void Expected. + @param x Other instance to exchange with. + */ constexpr void swap(Expected& x) @@ -1850,6 +2183,8 @@ class Expected } } + /** Return true when the Expected holds a value. + */ [[nodiscard]] constexpr explicit @@ -1858,6 +2193,8 @@ class Expected return has_value_; } + /** Return true when the Expected holds a value. + */ [[nodiscard]] constexpr bool has_value() const noexcept @@ -1865,12 +2202,16 @@ class Expected return has_value_; } + /** Ensure the Expected is engaged; throws if it holds an error. + */ constexpr void operator*() const noexcept { MRDOCS_ASSERT(has_value_); } + /** Ensure the Expected is engaged; throws BadExpectedAccess if not. + */ constexpr void value() const& @@ -1882,6 +2223,8 @@ class Expected throw BadExpectedAccess(unex_); } + /** Ensure the Expected is engaged; throws BadExpectedAccess if not (rvalue overload). + */ constexpr void value() && @@ -1893,6 +2236,8 @@ class Expected throw BadExpectedAccess(std::move(unex_)); } + /** Return a const reference to the contained error; precondition: disengaged. + */ constexpr E const& error() const & noexcept { @@ -1900,6 +2245,8 @@ class Expected return unex_; } + /** Return a reference to the contained error; precondition: disengaged. + */ constexpr E& error() & noexcept { @@ -1907,6 +2254,8 @@ class Expected return unex_; } + /** Return an rvalue reference to the contained error; precondition: disengaged. + */ constexpr E const&& error() const && noexcept { @@ -1914,6 +2263,8 @@ class Expected return std::move(unex_); } + /** Return an rvalue reference to the contained error; precondition: disengaged. + */ constexpr E&& error() && noexcept { @@ -1921,6 +2272,10 @@ class Expected return std::move(unex_); } + /** Return the error or a fallback copy. + @param e Fallback to return if engaged. + @return Contained error or the fallback converted to `E`. + */ template constexpr E error_or(G&& e) const& @@ -1935,6 +2290,10 @@ class Expected return unex_; } + /** Return the error or a fallback move. + @param e Fallback to return if engaged. + @return Contained error or the fallback converted to `E`. + */ template constexpr E error_or(G&& e) && @@ -1949,6 +2308,10 @@ class Expected return std::move(unex_); } + /** Invoke `f` when engaged, propagate error otherwise. + @param f Continuation returning another Expected. + @return Result of `f` or this error. + */ template requires std::is_constructible_v constexpr @@ -1969,6 +2332,10 @@ class Expected } } + /** Invoke `f` when engaged (const lvalue), propagate error otherwise. + @param f Continuation returning another Expected. + @return Result of `f` or this error. + */ template requires std::is_constructible_v constexpr @@ -1989,6 +2356,10 @@ class Expected } } + /** Invoke `f` when engaged (rvalue), propagate error otherwise. + @param f Continuation returning another Expected. + @return Result of `f` or this error. + */ template requires std::is_constructible_v constexpr @@ -2009,6 +2380,10 @@ class Expected } } + /** Invoke `f` when engaged (const rvalue), propagate error otherwise. + @param f Continuation returning another Expected. + @return Result of `f` or this error. + */ template requires std::is_constructible_v constexpr @@ -2029,6 +2404,10 @@ class Expected } } + /** Invoke `f` when in error, otherwise return current value. + @param f Recovery function returning an Expected. + @return Current value or result of `f`. + */ template constexpr auto @@ -2048,6 +2427,10 @@ class Expected } } + /** Invoke `f` when in error (const lvalue), otherwise return current value. + @param f Recovery function returning an Expected. + @return Current value or result of `f`. + */ template constexpr auto @@ -2067,6 +2450,10 @@ class Expected } } + /** Invoke `f` when in error (rvalue), otherwise return current value. + @param f Recovery function returning an Expected. + @return Current value or result of `f`. + */ template constexpr auto @@ -2086,6 +2473,10 @@ class Expected } } + /** Invoke `f` when in error (const rvalue), otherwise return current value. + @param f Recovery function returning an Expected. + @return Current value or result of `f`. + */ template constexpr auto @@ -2105,6 +2496,10 @@ class Expected } } + /** Transform the contained error type when engaged (lvalue). + @param f Transformation to apply. + @return New Expected produced from `f` or the existing error. + */ template requires std::is_constructible_v constexpr @@ -2124,6 +2519,10 @@ class Expected } } + /** Transform the contained error type when engaged (const lvalue). + @param f Transformation to apply. + @return New Expected produced from `f` or the existing error. + */ template requires std::is_constructible_v constexpr @@ -2143,6 +2542,10 @@ class Expected } } + /** Transform the contained error type when engaged (rvalue). + @param f Transformation to apply. + @return New Expected produced from `f` or the existing error. + */ template requires std::is_constructible_v constexpr @@ -2162,6 +2565,10 @@ class Expected } } + /** Transform the contained error type when engaged (const rvalue). + @param f Transformation to apply. + @return New Expected produced from `f` or the existing error. + */ template requires std::is_constructible_v constexpr @@ -2181,6 +2588,10 @@ class Expected } } + /** Transform the stored error value when disengaged. + @param f Transformation to apply. + @return Expected containing the transformed error or the current value. + */ template constexpr auto @@ -2202,6 +2613,10 @@ class Expected } } + /** Transform the stored error value when disengaged (const lvalue). + @param f Transformation to apply. + @return Expected containing the transformed error or the current value. + */ template constexpr auto @@ -2223,6 +2638,10 @@ class Expected } } + /** Transform the stored error value when disengaged (rvalue). + @param f Transformation to apply. + @return Expected containing the transformed error or the current value. + */ template constexpr auto @@ -2244,6 +2663,10 @@ class Expected } } + /** Transform the stored error value when disengaged (const rvalue). + @param f Transformation to apply. + @return Expected containing the transformed error or the current value. + */ template constexpr auto @@ -2342,15 +2765,24 @@ class Expected { } }; +/** Expected specialization for lvalue references. + Holds either a bound reference to `T` or an unexpected error `E`. +*/ template class Expected { static_assert(detail::can_beUnexpected); // Storage: either a bound pointer to T, or an error E. union { + /** Pointer to the referenced value when engaged. + */ T* p_; + /** Stored unexpected error when disengaged. + */ E unex_; }; + /** True when the Expected currently binds a reference. + */ bool has_value_ = false; // Short aliases @@ -2359,10 +2791,18 @@ class Expected { static constexpr bool ok_bind_v = detail::ok_bind_ref_v; public: + /** Referenced value type. + */ using value_type = T&; + /** Error type carried when disengaged. + */ using error_type = E; + /** Convenience alias for the unexpected wrapper. + */ using unexpected_type = Unexpected; + /** Rebind the reference to another value type while keeping `E`. + */ template using rebind = Expected; @@ -2371,11 +2811,15 @@ class Expected { // ---------------------------------- // Disengaged by default + /** Construct a disengaged Expected with no bound reference. + */ constexpr Expected() noexcept : p_(nullptr), has_value_(false) {} // Success from lvalue: bind + /** Bind to an lvalue result, marking the expected engaged. + */ template requires(!std::is_same_v, Expected> && !std::is_same_v, std::in_place_t> @@ -2388,29 +2832,38 @@ class Expected { {} // Deleted when binding would be from a temporary / disallowed + /** Deleted: binding a reference Expected from a temporary would dangle. + @param u Temporary value (deleted). + */ template requires(!std::is_same_v, Expected> && !std::is_same_v, std::in_place_t> && !detail::isUnexpected> && !ok_bind_v) - constexpr - Expected(U&&) = delete; + constexpr Expected(U&& u) = delete; // In-place: bind to an lvalue argument + /** Bind in-place to an existing lvalue. + @param tag Tag selecting in-place construction. + @param u Lvalue to bind this Expected to. + */ template requires ok_bind_v constexpr explicit - Expected(std::in_place_t, U& u) noexcept + Expected(std::in_place_t tag, U& u) noexcept : p_(std::addressof(static_cast(u))) , has_value_(true) {} // In-place via invocation result (mirrors your in_place_inv) + /** Invoke a factory to obtain the bound reference in-place. + @param fn Callable that returns a bindable lvalue. + */ template explicit constexpr - Expected(detail::in_place_inv, Fn&& fn) + Expected(detail::in_place_inv tag, Fn&& fn) { // Expect fn() to yield something bindable to R (i.e. an lvalue of T) auto&& r = std::forward(fn)(); @@ -2420,6 +2873,9 @@ class Expected { } // Error ctors (same rules as primary) + /** Construct from an unexpected error (copy). + @param u Unexpected wrapper to copy. + */ template requires std::is_constructible_v constexpr @@ -2430,6 +2886,9 @@ class Expected { , has_value_(false) {} + /** Construct from an unexpected error (move). + @param u Unexpected wrapper to move from. + */ template requires std::is_constructible_v constexpr @@ -2441,10 +2900,13 @@ class Expected { {} // Error via invocation-result (mirrors your unexpect_inv) + /** Construct an unexpected state by invoking a factory. + @param fn Callable that produces an error value. + */ template explicit constexpr - Expected(detail::unexpect_inv, Fn&& fn) + Expected(detail::unexpect_inv tag, Fn&& fn) : unex_(std::forward(fn)()) , has_value_(false) {} @@ -2452,6 +2914,9 @@ class Expected { // Converting ctors from other Expected ----------------------- // From Expected: safe to bind for any value category + /** Copy-construct from another reference Expected. + @param other Source instance to bind to. + */ template requires detail::ok_bind_ref_v constexpr @@ -2470,6 +2935,9 @@ class Expected { } } + /** Move-construct from another reference Expected. + @param other Source instance to bind to. + */ template requires detail::ok_bind_ref_v constexpr @@ -2489,6 +2957,9 @@ class Expected { } // From Expected (non-ref): only from lvalue object; forbid rvalue + /** Bind to the result stored inside another Expected value. + @param other Source instance providing the lvalue. + */ template requires detail::ok_bind_ref_v constexpr @@ -2507,37 +2978,54 @@ class Expected { } } + /** Deleted: rebinding from a temporary Expected would dangle. + */ template constexpr Expected(Expected&&) = delete; // would dangle // Copy/move/dtor + /** Copy-construct from another reference Expected. + */ constexpr Expected(Expected const&) = default; + /** Move-construct from another reference Expected. + */ constexpr Expected(Expected&&) = default; + /** Construct a disengaged Expected from error arguments. + @param tag Tag selecting unexpected construction. + @param args Arguments forwarded to the error constructor. + */ template requires std::is_constructible_v constexpr explicit - Expected(unexpect_t, Args&&... args) + Expected(unexpect_t tag, Args&&... args) noexcept(std::is_nothrow_constructible_v) : unex_(std::forward(args)...) , has_value_(false) {} + /** Construct a disengaged Expected from an initializer list. + @param tag Tag selecting unexpected construction. + @param il Initializer list forwarded to the error constructor. + @param args Additional arguments forwarded to the error constructor. + */ template requires std::is_constructible_v&, Args...> constexpr explicit - Expected(unexpect_t, std::initializer_list il, Args&&... args) + Expected(unexpect_t tag, std::initializer_list il, Args&&... args) noexcept(std::is_nothrow_constructible_v&, Args...>) : unex_(il, std::forward(args)...) , has_value_(false) {} + /** Destroy the held error when disengaged. + */ constexpr ~Expected() { @@ -2551,15 +3039,21 @@ class Expected { // assignment (always rebind) // ---------------------------------- + /** Copy-assign, rebinding or copying the error. + */ constexpr Expected& operator=(Expected const&) = default; + /** Move-assign, rebinding or moving the error. + */ constexpr Expected& operator=(Expected&&) = default; // Assign from lvalue -> rebind + /** Assign a new binding from an lvalue. + */ template requires ok_bind_v constexpr @@ -2577,13 +3071,17 @@ class Expected { } // Deleted for temporaries + /** Deleted: rebinding from a temporary would dangle. + @param u Temporary value (deleted). + */ template requires(!ok_bind_v) - constexpr - Expected& - operator=(U&&) = delete; + constexpr Expected& operator=(U&& u) = delete; // Assign from Expected -> rebind or store error + /** Assign from another reference Expected (copy). + @param other Source instance to bind to or copy error from. + */ template requires detail::ok_bind_ref_v constexpr @@ -2612,6 +3110,9 @@ class Expected { return *this; } + /** Assign from another reference Expected (move). + @param other Source instance to bind to or move error from. + */ template requires detail::ok_bind_ref_v constexpr @@ -2644,6 +3145,9 @@ class Expected { // Assign from Expected lvalue only (non-ref). Rvalue deleted to avoid // dangling. + /** Bind to the value contained in another Expected instance. + @param other Source lvalue Expected to bind to. + */ template requires detail::ok_bind_ref_v constexpr @@ -2672,12 +3176,17 @@ class Expected { return *this; } + /** Deleted: cannot bind to a temporary Expected holding a value. + */ template constexpr Expected& operator=(Expected&&) = delete; // Assign error + /** Replace the stored state with an unexpected error (copy). + @param e Unexpected wrapper to copy from. + */ template requires std::is_constructible_v && std::is_assignable_v @@ -2696,6 +3205,9 @@ class Expected { return *this; } + /** Replace the stored state with an unexpected error (move). + @param e Unexpected wrapper to move from. + */ template requires std::is_constructible_v && std::is_assignable_v constexpr @@ -2714,6 +3226,10 @@ class Expected { } // Emplace: bind to an lvalue + /** Rebind to a new lvalue, returning the stored reference. + @param u Reference to bind to. + @return Bound reference. + */ template requires ok_bind_v constexpr @@ -2729,13 +3245,16 @@ class Expected { return *p_; } + /** Deleted: cannot bind reference Expected to a temporary. + */ template requires(!ok_bind_v) - constexpr - T& - emplace(U&&) = delete; + constexpr T& emplace(U&& u) = delete; // swap + /** Swap state with another reference Expected. + @param x Other instance to exchange with. + */ constexpr void swap(Expected& x) @@ -2786,6 +3305,8 @@ class Expected { // ---------------------------------- // observers // ---------------------------------- + /** Return true when a reference is bound. + */ [[nodiscard]] constexpr explicit @@ -2794,6 +3315,9 @@ class Expected { return has_value_; } + /** Check whether the Expected currently contains a reference. + @return `true` if a reference is bound. + */ [[nodiscard]] constexpr bool @@ -2802,6 +3326,9 @@ class Expected { return has_value_; } + /** Access the bound reference pointer; undefined if disengaged. + @return Pointer to the bound value. + */ [[nodiscard]] constexpr T* @@ -2811,6 +3338,9 @@ class Expected { return p_; } + /** Access the bound reference pointer; undefined if disengaged. + @return Pointer to the bound value. + */ [[nodiscard]] constexpr T const* @@ -2820,6 +3350,9 @@ class Expected { return p_; } + /** Dereference the bound reference. + @return Reference to the bound value. + */ [[nodiscard]] constexpr T& @@ -2829,6 +3362,9 @@ class Expected { return *p_; } + /** Dereference the bound reference (const). + @return Reference to the bound value. + */ [[nodiscard]] constexpr T const& @@ -2838,6 +3374,9 @@ class Expected { return *p_; } + /** Dereference the bound reference, preserving value category. + @return Reference to the bound value. + */ [[nodiscard]] constexpr T&& @@ -2847,6 +3386,9 @@ class Expected { return std::move(*p_); } + /** Dereference the bound reference, preserving value category (const rvalue). + @return Reference to the bound value. + */ [[nodiscard]] constexpr T const&& @@ -2856,6 +3398,8 @@ class Expected { return std::move(*p_); } + /** Return the bound reference or throw on disengaged state. + */ constexpr T& value() & @@ -2867,6 +3411,8 @@ class Expected { throw BadExpectedAccess(error()); } + /** Return the bound reference or throw on disengaged state (const lvalue). + */ constexpr T const& value() const& @@ -2878,6 +3424,8 @@ class Expected { throw BadExpectedAccess(error()); } + /** Return the bound reference or throw on disengaged state (rvalue). + */ constexpr T&& value() && @@ -2889,6 +3437,8 @@ class Expected { throw BadExpectedAccess(std::move(error())); } + /** Return the bound reference or throw on disengaged state (const rvalue). + */ constexpr T const&& value() const&& @@ -2900,6 +3450,9 @@ class Expected { throw BadExpectedAccess(std::move(error())); } + /** Access the stored error; requires disengaged state. + @return Reference to the stored error. + */ [[nodiscard]] constexpr E& @@ -2909,6 +3462,9 @@ class Expected { return unex_; } + /** Access the stored error (const lvalue). + @return Reference to the stored error. + */ [[nodiscard]] constexpr E const& @@ -2918,6 +3474,9 @@ class Expected { return unex_; } + /** Access the stored error (rvalue). + @return Rvalue reference to the stored error. + */ [[nodiscard]] constexpr E&& @@ -2927,6 +3486,9 @@ class Expected { return std::move(unex_); } + /** Access the stored error (const rvalue). + @return Rvalue reference to the stored error. + */ [[nodiscard]] constexpr E const&& @@ -2937,6 +3499,10 @@ class Expected { } // value_or: return by value (copy/move), like your non-ref primary + /** Return the bound value or a fallback copy when disengaged. + @param u Fallback value to return if no reference is bound. + @return Bound value or fallback copy. + */ template constexpr std::remove_reference_t @@ -2948,6 +3514,10 @@ class Expected { return has_value_ ? *p_ : static_cast(std::forward(u)); } + /** Return the bound value or a fallback move when disengaged. + @param u Fallback value to move if no reference is bound. + @return Bound value or fallback. + */ template constexpr std::remove_reference_t @@ -2961,6 +3531,10 @@ class Expected { } // error_or: identical to primary + /** Return the stored error or the provided fallback (copy). + @param g Fallback error to return when engaged. + @return Error value. + */ template constexpr E @@ -2969,6 +3543,10 @@ class Expected { return has_value_ ? static_cast(std::forward(g)) : unex_; } + /** Return the stored error or the provided fallback (move). + @param g Fallback error to move when engaged. + @return Error value. + */ template constexpr E @@ -2983,6 +3561,10 @@ class Expected { // ---------------------------------- // and_then: F(T&) -> Expected<*, E> + /** Invoke `f` with the bound reference when engaged. + @param f Continuation producing another Expected. + @return Result of `f` or current error. + */ template constexpr auto @@ -2998,6 +3580,10 @@ class Expected { return U(unexpect, unex_); } + /** Invoke `f` with the bound reference when engaged (const lvalue). + @param f Continuation producing another Expected. + @return Result of `f` or current error. + */ template constexpr auto @@ -3013,6 +3599,10 @@ class Expected { return U(unexpect, unex_); } + /** Invoke `f` with the bound reference when engaged (rvalue). + @param f Continuation producing another Expected. + @return Result of `f` or current error. + */ template constexpr auto @@ -3028,6 +3618,10 @@ class Expected { return U(unexpect, std::move(unex_)); } + /** Invoke `f` with the bound reference when engaged (const rvalue). + @param f Continuation producing another Expected. + @return Result of `f` or current error. + */ template constexpr auto @@ -3045,6 +3639,9 @@ class Expected { // or_else: same signature/behavior as primary; when engaged, return // self-type with same binding + /** Recover with `f` if disengaged, otherwise return this value. + @param f Recovery function returning an Expected. + */ template constexpr Expected @@ -3060,6 +3657,9 @@ class Expected { return g; } + /** Recover with `f` if disengaged (const lvalue). + @param f Recovery function returning an Expected. + */ template constexpr Expected @@ -3075,6 +3675,9 @@ class Expected { return g; } + /** Recover with `f` if disengaged (rvalue). + @param f Recovery function returning an Expected. + */ template constexpr Expected @@ -3090,6 +3693,9 @@ class Expected { return g; } + /** Recover with `f` if disengaged (const rvalue). + @param f Recovery function returning an Expected. + */ template constexpr Expected @@ -3106,6 +3712,10 @@ class Expected { } // transform: F(T&) -> U ; returns Expected + /** Transform the bound value when engaged. + @param f Transformation applied to the bound reference. + @return Expected containing transformed value or current error. + */ template constexpr auto @@ -3122,6 +3732,10 @@ class Expected { return Res(unexpect, unex_); } + /** Transform the bound value when engaged (const lvalue). + @param f Transformation applied to the bound reference. + @return Expected containing transformed value or current error. + */ template constexpr auto @@ -3138,6 +3752,10 @@ class Expected { return Res(unexpect, unex_); } + /** Transform the bound value when engaged (rvalue). + @param f Transformation applied to the bound reference. + @return Expected containing transformed value or current error. + */ template constexpr auto @@ -3154,6 +3772,10 @@ class Expected { return Res(unexpect, std::move(unex_)); } + /** Transform the bound value when engaged (const rvalue). + @param f Transformation applied to the bound reference. + @return Expected containing transformed value or current error. + */ template constexpr auto @@ -3171,6 +3793,10 @@ class Expected { } // transform_error: identical to primary + /** Transform the stored error when disengaged. + @param f Transformation applied to the error. + @return Expected with transformed error or current value. + */ template constexpr auto @@ -3187,6 +3813,10 @@ class Expected { }); } + /** Transform the stored error when disengaged (const lvalue). + @param f Transformation applied to the error. + @return Expected with transformed error or current value. + */ template constexpr auto @@ -3203,6 +3833,10 @@ class Expected { }); } + /** Transform the stored error when disengaged (rvalue). + @param f Transformation applied to the error. + @return Expected with transformed error or current value. + */ template constexpr auto @@ -3219,6 +3853,10 @@ class Expected { }); } + /** Transform the stored error when disengaged (const rvalue). + @param f Transformation applied to the error. + @return Expected with transformed error or current value. + */ template constexpr auto @@ -3275,6 +3913,7 @@ class Expected { } }; // class Expected + } // mrdocs #endif diff --git a/include/mrdocs/Support/Glob.hpp b/include/mrdocs/Support/Glob.hpp index 333500c044..9d1fa08d60 100644 --- a/include/mrdocs/Support/Glob.hpp +++ b/include/mrdocs/Support/Glob.hpp @@ -31,7 +31,7 @@ namespace mrdocs { @li "\" escapes the next character so it is treated as a literal. Nested brace expansions "{,"{,...}",...}" are not supported. - */ +*/ class GlobPattern { struct Impl; std::unique_ptr impl_; @@ -43,11 +43,15 @@ class GlobPattern { If the pattern contains more subpatterns than this value, an error is returned. If not specified, there is no limit. @return The constructed GlobPattern, or an error if the pattern is invalid. - */ + */ static Expected create(std::string_view pattern, Optional maxSubGlobs); + /** Create a glob pattern without limiting subpattern count. + @param pattern Glob expression to compile. + @return Compiled pattern or an error. + */ static Expected create(std::string_view pattern) @@ -55,26 +59,31 @@ class GlobPattern { return create(pattern, std::nullopt); } - /** Destructor */ + /** Destructor + */ ~GlobPattern(); /** Construct an empty GlobPattern. An empty GlobPattern will never match any string. - */ + */ GlobPattern(); - /** Copy constructor */ + /** Copy constructor + */ GlobPattern(GlobPattern const& other); - /** Move constructor */ + /** Move constructor + */ GlobPattern(GlobPattern&& other) noexcept; - /** Copy assignment */ + /** Copy assignment + */ GlobPattern& operator=(GlobPattern const& other); - /** Move assignment */ + /** Move assignment + */ GlobPattern& operator=(GlobPattern&& other) noexcept; @@ -83,7 +92,7 @@ class GlobPattern { @param str The string to match against the pattern. @param delimiter The character that `*` does not match. @return true if the string matches the pattern, false otherwise. - */ + */ bool match(std::string_view str, char delimiter) const; @@ -100,7 +109,7 @@ class GlobPattern { @param prefix The string to match against the pattern. @param delimiter The character that `*` does not match. @return true if the string prefix matches the pattern, false otherwise. - */ + */ bool matchPatternPrefix(std::string_view prefix, char delimiter) const; @@ -110,14 +119,14 @@ class GlobPattern { any special characters. In other words, it matches a single string. @return true if the glob pattern is a literal string, false otherwise. - */ + */ bool isLiteral() const; /** Returns the glob pattern. @return The glob pattern as a string view. - */ + */ std::string_view pattern() const; }; @@ -126,7 +135,7 @@ class GlobPattern { A glob pattern matcher where "*" does not match path separators. The pattern "**" can be used to match any number of path separators. - */ +*/ class PathGlobPattern { GlobPattern glob_; public: @@ -134,7 +143,7 @@ class PathGlobPattern { @param pattern The glob pattern to use for matching. @param maxSubGlobs The maximum number of subpatterns allowed. - */ + */ static Expected create( @@ -148,7 +157,7 @@ class PathGlobPattern { /** Constructs a PathGlobPattern with the given pattern. @param pattern The glob pattern to use for matching. - */ + */ static Expected create(std::string_view const pattern) @@ -160,13 +169,13 @@ class PathGlobPattern { /** Construct an empty PathGlobPattern. An empty PathGlobPattern will never match any string. - */ + */ PathGlobPattern() = default; /** Construct an empty PathGlobPattern. An empty PathGlobPattern will never match any string. - */ + */ explicit PathGlobPattern(GlobPattern glob) : glob_{std::move(glob)} @@ -176,7 +185,7 @@ class PathGlobPattern { @param str The string to match against the pattern. @return true if the string matches the pattern, false otherwise. - */ + */ bool match(std::string_view const str) const { @@ -195,7 +204,7 @@ class PathGlobPattern { @param prefix The string to match against the pattern. @return true if the string prefix matches the pattern, false otherwise. - */ + */ bool matchPatternPrefix(std::string_view prefix) const { @@ -208,7 +217,7 @@ class PathGlobPattern { any special characters. In other words, it matches a single string. @return true if the glob pattern is a literal string, false otherwise. - */ + */ bool isLiteral() const { @@ -218,7 +227,7 @@ class PathGlobPattern { /** Returns the glob pattern. @return The glob pattern as a string view. - */ + */ std::string_view pattern() const { @@ -230,7 +239,7 @@ class PathGlobPattern { A glob pattern matcher where "*" does not match "::". The pattern "**" can be used to match any number of "::". - */ +*/ class SymbolGlobPattern { GlobPattern glob_; public: @@ -238,7 +247,7 @@ class SymbolGlobPattern { @param pattern The glob pattern to use for matching. @param maxSubGlobs The maximum number of subpatterns allowed. - */ + */ static Expected create( @@ -252,7 +261,7 @@ class SymbolGlobPattern { /** Constructs a SymbolGlobPattern with the given pattern. @param pattern The glob pattern to use for matching. - */ + */ static Expected create(std::string_view const pattern) @@ -264,13 +273,13 @@ class SymbolGlobPattern { /** Construct an empty SymbolGlobPattern. An empty SymbolGlobPattern will never match any string. - */ + */ SymbolGlobPattern() = default; /** Construct an empty SymbolGlobPattern. An empty SymbolGlobPattern will never match any string. - */ + */ explicit SymbolGlobPattern(GlobPattern glob) : glob_{std::move(glob)} @@ -280,7 +289,7 @@ class SymbolGlobPattern { @param str The string to match against the pattern. @return true if the string matches the pattern, false otherwise. - */ + */ bool match(std::string_view const str) const { @@ -299,7 +308,7 @@ class SymbolGlobPattern { @param prefix The string to match against the pattern. @return true if the string prefix matches the pattern, false otherwise. - */ + */ bool matchPatternPrefix(std::string_view prefix) const { @@ -312,7 +321,7 @@ class SymbolGlobPattern { any special characters. In other words, it matches a single string. @return true if the glob pattern is a literal string, false otherwise. - */ + */ bool isLiteral() const { @@ -322,7 +331,7 @@ class SymbolGlobPattern { /** Returns the glob pattern. @return The glob pattern as a string view. - */ + */ std::string_view pattern() const { @@ -332,4 +341,4 @@ class SymbolGlobPattern { } // mrdocs -#endif // MRDOCS_API_SUPPORT_GLOB_HPP \ No newline at end of file +#endif // MRDOCS_API_SUPPORT_GLOB_HPP diff --git a/include/mrdocs/Support/Handlebars.hpp b/include/mrdocs/Support/Handlebars.hpp index b53ce81ac6..ccdc506423 100644 --- a/include/mrdocs/Support/Handlebars.hpp +++ b/include/mrdocs/Support/Handlebars.hpp @@ -35,17 +35,32 @@ namespace mrdocs { The object will also contain the line, column and position of the error in the template. These can be used to by the caller to provide more detailed error messages. - */ +*/ struct HandlebarsError : public std::runtime_error { + /** Line number in the template where the error occurred. + */ std::size_t line = static_cast(-1); + /** Column of the error in the template. + */ std::size_t column = static_cast(-1); + /** Absolute character position of the error. + */ std::size_t pos = static_cast(-1); + /** Construct an error with a message. + @param msg Description of the failure. + */ HandlebarsError(std::string_view msg) : std::runtime_error(std::string(msg)) {} + /** Construct an error with location information. + @param msg Description of the failure. + @param line_ Line number where it occurred. + @param column_ Column number where it occurred. + @param pos_ Absolute character position. + */ HandlebarsError(std::string_view msg, std::size_t line_, std::size_t column_, std::size_t pos_) : std::runtime_error(std::format("{} - {}:{}", msg, line_, column_)), @@ -82,7 +97,7 @@ namespace detail { It allows many types to be used as output streams, including std::string, std::ostream, llvm::raw_string_ostream, and others. - */ +*/ class MRDOCS_DECL OutputRef { friend class Handlebars; @@ -137,7 +152,7 @@ class MRDOCS_DECL OutputRef /** Constructor for std::string output @param st The string to append to - */ + */ template requires std::same_as OutputRef( St& st ) @@ -149,7 +164,7 @@ class MRDOCS_DECL OutputRef /** Constructor for llvm::raw_string_ostream output @param os The output stream to write to - */ + */ template requires std::is_convertible_v OutputRef( Os& os ) @@ -161,7 +176,7 @@ class MRDOCS_DECL OutputRef /** Constructor for std::ostream& output @param os The output stream to write to - */ + */ template requires std::is_convertible_v && @@ -177,7 +192,7 @@ class MRDOCS_DECL OutputRef @param os The output stream reference @param sv The string to write @return A reference to this object - */ + */ friend OutputRef& operator<<( OutputRef& os, std::string_view sv ) @@ -190,7 +205,7 @@ class MRDOCS_DECL OutputRef @param os The output stream reference @param c The character to write @return A reference to this object - */ + */ friend OutputRef& operator<<( OutputRef& os, char c ) @@ -203,7 +218,7 @@ class MRDOCS_DECL OutputRef @param os The output stream reference @param c The string to write @return A reference to this object - */ + */ friend OutputRef& operator<<( OutputRef& os, char const * c ) @@ -216,7 +231,7 @@ class MRDOCS_DECL OutputRef @param os The output stream reference @param v The character to write @return A reference to this object - */ + */ template requires std::formattable friend OutputRef &operator<<(OutputRef &os, T v) { @@ -224,12 +239,17 @@ class MRDOCS_DECL OutputRef return os.write_impl(s); } + /** Set the indentation level applied to writes. + @param indent Number of spaces to indent. + */ void setIndent(std::size_t indent) { indent_ = indent; } + /** Return the current indentation level. + */ std::size_t getIndent() const noexcept { @@ -260,7 +280,7 @@ class MRDOCS_DECL OutputRef @param out The output stream reference where the escaped string will be written. @param str The string to escape. - */ +*/ MRDOCS_DECL void HTMLEscape( @@ -285,7 +305,7 @@ HTMLEscape( * * \param str The string to escape. * \return The escaped string. - */ +*/ MRDOCS_DECL std::string HTMLEscape(std::string_view str); @@ -296,11 +316,11 @@ HTMLEscape(std::string_view str); @see https://handlebarsjs.com/api-reference/compilation.html - */ +*/ struct HandlebarsOptions { /** Escape HTML entities or entities defined by the escape function - */ + */ bool noEscape = false; /** Function to escape entities @@ -310,7 +330,7 @@ struct HandlebarsOptions replaced with a custom function that escapes entities in a different way. - */ + */ std::function escapeFunction = static_cast(HTMLEscape); @@ -319,14 +339,14 @@ struct HandlebarsOptions Run in strict mode. In this mode, templates will throw rather than silently ignore missing fields. - */ + */ bool strict = false; /** Removes object existence checks when traversing paths This is a subset of strict mode that generates optimized templates when the data inputs are known to be safe. - */ + */ bool assumeObjects = false; /** Disable the auto-indent feature @@ -374,7 +394,7 @@ struct HandlebarsOptions - */ + */ bool preventIndent = false; /** Disables standalone tag removal when set to true @@ -425,14 +445,14 @@ struct HandlebarsOptions When set, blocks and partials that are on their own line will not remove the whitespace on that line. - */ + */ bool ignoreStandalone = false; /** Disables implicit context for partials When enabled, partials that are not passed a context value will execute against an empty object. - */ + */ bool explicitPartialContext = false; /** Enable recursive field lookup @@ -442,7 +462,7 @@ struct HandlebarsOptions This mode should be used to enable complete compatibility with Mustache templates. - */ + */ bool compat = false; /** Enable tracking of ids @@ -453,14 +473,14 @@ struct HandlebarsOptions Helpers often use this information to update the context path to the current expression, which can later be used to look up the value of the expression with ".." segments. - */ + */ bool trackIds = false; /** Custom private data object This variable can be used to pass in an object to define custom private variables. - */ + */ dom::Value data = nullptr; }; @@ -629,7 +649,7 @@ namespace detail { helpers. @see https://handlebarsjs.com/ - */ +*/ class Handlebars { using helpers_map = std::unordered_map< std::string, dom::Function, detail::string_hash, std::equal_to<>>; @@ -650,7 +670,7 @@ class Handlebars { helpers or partials. @see helpers::registerBuiltinHelpers - */ + */ Handlebars(); /** Render a handlebars template @@ -667,7 +687,7 @@ class Handlebars { @param context The data to render @param options The options to use @return The rendered text - */ + */ std::string render( std::string_view templateText, @@ -718,11 +738,12 @@ class Handlebars { The output stream can be any type convertible to OutputRef, which is a reference to a stream that can be written to with the << operator. + @param out The output stream reference @param templateText The handlebars template text @param context The data to render @param options The options to use @return The rendered text - */ + */ void render_to( OutputRef& out, @@ -766,7 +787,7 @@ class Handlebars { } /** @copydoc render_to(OutputRef&, std::string_view, dom::Value const&, HandlebarsOptions const&) const - */ + */ Expected try_render( std::string_view templateText, @@ -808,11 +829,12 @@ class Handlebars { The output stream can be any type convertible to OutputRef, which is a reference to a stream that can be written to with the << operator. + @param out The output stream reference @param templateText The handlebars template text @param context The data to render @param options The options to use @return The rendered text - */ + */ Expected try_render_to( OutputRef& out, @@ -868,7 +890,7 @@ class Handlebars { @see https://handlebarsjs.com/guide/partials.html - */ + */ void registerPartial(std::string_view name, std::string_view text); @@ -877,7 +899,7 @@ class Handlebars { This function unregisters a partial with the handlebars environment. @param name The name of the partial - */ + */ void unregisterPartial(std::string_view name) { auto it = partials_.find(name); @@ -915,7 +937,7 @@ class Handlebars { @see https://handlebarsjs.com/guide/expressions.html @see https://handlebarsjs.com/guide/block-helpers.html @see https://handlebarsjs.com/guide/builtin-helpers.html - */ + */ void registerHelper(std::string_view name, dom::Function const& helper); @@ -924,7 +946,7 @@ class Handlebars { This function unregisters a helper with the handlebars environment. @param name The name of the helper - */ + */ void unregisterHelper(std::string_view name); @@ -941,10 +963,12 @@ class Handlebars { current level and a `dom::Array` containing values to be logged. @param fn The logger function - */ + */ void registerLogger(dom::Function fn); + /** Internal representation of a parsed Handlebars tag. + */ struct Tag; private: @@ -1049,7 +1073,7 @@ class Handlebars { @return True if the value is empty, false otherwise @see https://mustache.github.io/mustache.5.html#Sections - */ +*/ MRDOCS_DECL bool isEmpty(dom::Value const& arg); @@ -1075,7 +1099,7 @@ isEmpty(dom::Value const& arg); @return The overlay object @see https://mustache.github.io/mustache.5.html#Sections - */ +*/ MRDOCS_DECL dom::Object createFrame(dom::Object const& parent); @@ -1097,6 +1121,12 @@ escapeExpression( std::string_view str, HandlebarsOptions const& opt); +/** Handlebars helper registry for templates. + + Everything under `helpers` mirrors the runtime helper registry shipped with + our bundled Handlebars engine so templates can call the same helpers in + both Node-based dev mode and the embedded C++ rendering pipeline. +*/ namespace helpers { /** Register all the built-in helpers into a Handlebars instance @@ -1112,7 +1142,7 @@ namespace helpers { @see https://handlebarsjs.com/guide/builtin-helpers.html @param hbs The Handlebars instance to register the helpers into - */ +*/ MRDOCS_DECL void registerBuiltinHelpers(Handlebars& hbs); @@ -1124,7 +1154,7 @@ registerBuiltinHelpers(Handlebars& hbs); literals in the template. @param hbs The Handlebars instance to register the helpers into - */ +*/ MRDOCS_DECL void registerConstructorHelpers(Handlebars& hbs); @@ -1145,7 +1175,7 @@ registerConstructorHelpers(Handlebars& hbs); @see https://gitlab.com/antora/antora-ui-default/-/tree/master/src/helpers @param hbs The Handlebars instance to register the helpers into - */ +*/ MRDOCS_DECL void registerAntoraHelpers(Handlebars& hbs); @@ -1156,7 +1186,7 @@ registerAntoraHelpers(Handlebars& hbs); logical operations. @param hbs The Handlebars instance to register the helpers into - */ +*/ MRDOCS_DECL void registerLogicalHelpers(Handlebars& hbs); @@ -1167,7 +1197,7 @@ registerLogicalHelpers(Handlebars& hbs); mathemathical operations. @param hbs The Handlebars instance to register the helpers into - */ +*/ MRDOCS_DECL void registerMathHelpers(Handlebars& hbs); @@ -1192,7 +1222,7 @@ registerMathHelpers(Handlebars& hbs); cannot be registered individually. @param hbs The Handlebars instance to register the helpers into - */ +*/ MRDOCS_DECL void registerStringHelpers(Handlebars& hbs); @@ -1213,7 +1243,7 @@ registerStringHelpers(Handlebars& hbs); cannot be registered individually. @param hbs The Handlebars instance to register the helpers into - */ +*/ MRDOCS_DECL void registerContainerHelpers(Handlebars& hbs); @@ -1224,7 +1254,7 @@ registerContainerHelpers(Handlebars& hbs); types, such as identity, type checking, and type conversion. @param hbs The Handlebars instance to register the helpers into - */ +*/ MRDOCS_DECL void registerTypeHelpers(Handlebars& hbs); @@ -1235,7 +1265,7 @@ registerTypeHelpers(Handlebars& hbs); @param args The values to test @return True if all of the values are truthy, false otherwise. - */ +*/ MRDOCS_DECL bool and_fn(dom::Array const& args); @@ -1243,7 +1273,7 @@ and_fn(dom::Array const& args); /** "or" helper function * * The "or" helper returns true if any of the values are truthy. - */ +*/ MRDOCS_DECL dom::Value or_fn(dom::Array const& args); @@ -1254,7 +1284,7 @@ or_fn(dom::Array const& args); @param args The values to compare @return True if all of the values are equal, false otherwise. - */ +*/ MRDOCS_DECL bool eq_fn(dom::Array const& args); @@ -1265,7 +1295,7 @@ eq_fn(dom::Array const& args); @param args The values to compare @return True if any of the values are not equal, false otherwise. - */ +*/ MRDOCS_DECL bool ne_fn(dom::Array const& args); @@ -1275,7 +1305,7 @@ ne_fn(dom::Array const& args); The "not" helper returns true if not all of the values are truthy. @return True if not all of the values are truthy, false otherwise. - */ +*/ MRDOCS_DECL bool not_fn(dom::Array const& arg); @@ -1284,7 +1314,7 @@ not_fn(dom::Array const& arg); * * The "select" helper returns the second argument if the first argument is * truthy, and the third argument otherwise. - */ +*/ MRDOCS_DECL dom::Value select_fn( @@ -1296,7 +1326,7 @@ select_fn( * * The "increment" helper adds 1 to the value if it's an integer and converts * booleans to `true`. Other values are returned as-is. - */ +*/ MRDOCS_DECL dom::Value increment_fn(dom::Value const& value); @@ -1305,7 +1335,7 @@ increment_fn(dom::Value const& value); * * The "detag" helper applies the regex expression "<[^>]+>" to the * input to remove all HTML tags. - */ +*/ MRDOCS_DECL dom::Value detag_fn(dom::Value html); @@ -1313,7 +1343,7 @@ detag_fn(dom::Value html); /** "relativize" helper function * * The "relativize" helper makes the first path relative to the second path. - */ +*/ MRDOCS_DECL dom::Value relativize_fn(dom::Value to, dom::Value from, dom::Value context); @@ -1323,7 +1353,7 @@ relativize_fn(dom::Value to, dom::Value from, dom::Value context); The "year" helper returns the current year as an integer. @return The current year as an integer. - */ +*/ MRDOCS_DECL int year_fn(); diff --git a/include/mrdocs/Support/JavaScript.hpp b/include/mrdocs/Support/JavaScript.hpp index b3391a6502..cb9c4daedb 100644 --- a/include/mrdocs/Support/JavaScript.hpp +++ b/include/mrdocs/Support/JavaScript.hpp @@ -18,21 +18,40 @@ #include #include - namespace mrdocs { class Handlebars; +/** JavaScript interop helpers for the embedded runtime. + + These functions abstract over the embedded JavaScript engine so that + scripts and helpers can be bound, invoked, and marshalled without leaking + engine-specific types into the rest of the codebase. +*/ namespace js { +/** Opaque tag that allows bridge classes to reach JS internals. +*/ +/** Grants friend-level access to internal scopes. +*/ struct Access; class Context; class Scope; +/** Lightweight handle to a JavaScript array. +*/ class Array; +/** Boolean wrapper for JavaScript values. +*/ class Boolean; +/** Object wrapper for JavaScript values. +*/ class Object; +/** String wrapper for JavaScript values. +*/ class String; +/** Generic JavaScript value wrapper. +*/ class Value; //------------------------------------------------ @@ -61,23 +80,31 @@ enum class Type //------------------------------------------------ +/** Represents either a property name or array index when addressing JS objects. +*/ class Prop { unsigned int index_; std::string_view name_; public: + /** Create a property by name. + */ constexpr Prop(std::string_view name) noexcept : index_(0) , name_(name) { } + /** Create a property by numeric index. + */ constexpr Prop(unsigned int index) noexcept : index_(index) { } + /** Return true if this property refers to an array index. + */ constexpr bool isIndex() const noexcept { @@ -157,7 +184,7 @@ class MRDOCS_DECL @copydetails Context(Context const&) - */ + */ Context& operator=(Context const&) = delete; }; @@ -183,7 +210,7 @@ class MRDOCS_DECL same context heap cannot be manipulated at the same time. - */ +*/ class Scope { Context ctx_; @@ -221,7 +248,7 @@ class Scope There should be no @ref Value objects associated with this scope when it is destroyed. - */ + */ MRDOCS_DECL ~Scope(); @@ -229,7 +256,7 @@ class Scope @param value The integer value to push. @return A Value representing the integer. - */ + */ MRDOCS_DECL Value pushInteger(std::int64_t value); @@ -238,7 +265,7 @@ class Scope @param value The double value to push. @return A Value representing the double. - */ + */ MRDOCS_DECL Value pushDouble(double value); @@ -247,7 +274,7 @@ class Scope @param value The boolean value to push. @return A Value representing the boolean. - */ + */ MRDOCS_DECL Value pushBoolean(bool value); @@ -258,19 +285,19 @@ class Scope The string is copied to the internal heap. @return A Value representing the string. - */ + */ MRDOCS_DECL Value pushString(std::string_view value); /** Push a new object to the stack - */ + */ MRDOCS_DECL Value pushObject(); /** Push a new array to the stack - */ + */ MRDOCS_DECL Value pushArray(); @@ -287,7 +314,7 @@ class Scope @param jsCode The JavaScript code to execute. - */ + */ MRDOCS_DECL Expected script(std::string_view jsCode); @@ -304,7 +331,7 @@ class Scope @param jsCode The JavaScript code to execute. - */ + */ MRDOCS_DECL Expected eval(std::string_view jsCode); @@ -395,7 +422,7 @@ class Scope If the global object does not exist, an error is returned. - */ + */ MRDOCS_DECL Value getGlobalObject(); @@ -430,12 +457,18 @@ class Scope class MRDOCS_DECL Value { protected: + /** Scope that owns the value stack entry. + */ Scope* scope_; + /** Index of the value within the scope stack. + */ int idx_; friend struct Access; - Value(int, Scope&) noexcept; + /** Construct a value bound to a stack position in the given scope. + */ + Value(int position, Scope& scope) noexcept; public: /** Destructor @@ -448,7 +481,7 @@ class MRDOCS_DECL Value defined in that scope are popped via `Scope::reset`. - */ + */ MRDOCS_DECL ~Value(); /** Constructor @@ -458,7 +491,7 @@ class MRDOCS_DECL Value The value is undefined. - */ + */ MRDOCS_DECL Value() noexcept; /** Constructor @@ -466,28 +499,28 @@ class MRDOCS_DECL Value The function pushes a duplicate of value to the stack and associates the new value the top of the stack. - */ + */ MRDOCS_DECL Value(Value const&); /** Constructor The function associates the existing value with this object. - */ + */ MRDOCS_DECL Value(Value&&) noexcept; /** Copy assignment. @copydetails Value(Value const&) - */ + */ MRDOCS_DECL Value& operator=(Value const&); /** Move assignment. @copydetails Value(Value&&) - */ + */ MRDOCS_DECL Value& operator=(Value&&) noexcept; /** Return the type of the value. @@ -510,27 +543,27 @@ class MRDOCS_DECL Value A function is an object with the internal ECMAScript class `Function`. - */ + */ MRDOCS_DECL Type type() const noexcept; /** Check if the value is undefined. @return `true` if the value is undefined, `false` otherwise - */ + */ bool isUndefined() const noexcept; /** Check if the value is null. @return `true` if the value is null, `false` otherwise - */ + */ bool isNull() const noexcept; /** Check if the value is a boolean. @return `true` if the value is a boolean, `false` otherwise - */ + */ bool isBoolean() const noexcept; @@ -548,7 +581,7 @@ class MRDOCS_DECL Value their exact non-normalized form. @return `true` if the value is a number, `false` otherwise - */ + */ bool isNumber() const noexcept; @@ -570,28 +603,28 @@ class MRDOCS_DECL Value where `d` is the result of `toDouble()`. @return `true` if the value is a number with no fractional part, `false` otherwise - */ + */ bool isInteger() const noexcept; /** Check if the value is a floating point number. @return `true` if the value is a number but not an integer, `false` otherwise - */ + */ bool isDouble() const noexcept; /** Check if the value is a string. @return `true` if the value is a string, `false` otherwise - */ + */ bool isString() const noexcept; /** Check if the value is an array. @return `true` if the value is an array, `false` otherwise - */ + */ bool isArray() const noexcept; @@ -610,14 +643,14 @@ class MRDOCS_DECL Value @return `true` if the value is an object, `false` otherwise - */ + */ bool isObject() const noexcept; /** Check if the value is a function. @return `true` if the value is a function, `false` otherwise - */ + */ bool isFunction() const noexcept; @@ -642,7 +675,7 @@ class MRDOCS_DECL Value @note Behaviour is undefined if `!isString()` - */ + */ std::string_view getString() const; @@ -650,7 +683,7 @@ class MRDOCS_DECL Value @note Behaviour is undefined if `!isBoolean()` - */ + */ bool getBool() const noexcept; @@ -701,7 +734,7 @@ class MRDOCS_DECL Value reference semantics to access the underlying DOM object is returned. - */ + */ dom::Value getDom() const; /** Set "log" property @@ -721,7 +754,7 @@ class MRDOCS_DECL Value two arguments to report a message to the console. - */ + */ void setlog(); @@ -739,6 +772,8 @@ class MRDOCS_DECL Value Value get(std::string_view key) const; + /** @copydoc get(std::string_view) + */ template S> Value get(S const& key) const @@ -780,7 +815,7 @@ class MRDOCS_DECL Value @param key The key to set. @param value The value to set. - */ + */ MRDOCS_DECL void set( @@ -791,7 +826,7 @@ class MRDOCS_DECL Value @param key The key to set. @param value The value to set. - */ + */ MRDOCS_DECL void set( @@ -875,7 +910,7 @@ class MRDOCS_DECL Value } /** Return the string. - */ + */ explicit operator std::string() const noexcept { @@ -913,7 +948,7 @@ class MRDOCS_DECL Value @note In JavaScript, this is equivalent to the `===` operator, which does not perform type conversions. - */ + */ friend bool operator==( @@ -962,7 +997,7 @@ class MRDOCS_DECL Value } /** Compare two values for inequality. - */ + */ friend std::strong_ordering operator<=>( @@ -972,7 +1007,7 @@ class MRDOCS_DECL Value /** Return the first Value that is truthy, or the last one. This function is equivalent to the JavaScript `||` operator. - */ + */ friend Value operator||(Value const& lhs, Value const& rhs); @@ -996,7 +1031,7 @@ class MRDOCS_DECL Value /** Return the first Value that is not truthy, or the last one. This function is equivalent to the JavaScript `&&` operator. - */ + */ friend Value operator&&(Value const& lhs, Value const& rhs); @@ -1116,7 +1151,7 @@ isFunction() const noexcept @param name The name of the helper function @param ctx The JavaScript context to use @param script The JavaScript code that defines the helper function - */ +*/ MRDOCS_DECL Expected registerHelper( diff --git a/include/mrdocs/Support/Lua.hpp b/include/mrdocs/Support/Lua.hpp index c737dde21d..ab9f873a77 100644 --- a/include/mrdocs/Support/Lua.hpp +++ b/include/mrdocs/Support/Lua.hpp @@ -20,10 +20,17 @@ #include #include - namespace mrdocs { +/** Lua interop helpers for the optional scripting/backend integration. + + This namespace contains glue for pushing/popping values, registering + functions, and safely executing snippets so embedders can enable Lua + without duplicating binding code. +*/ namespace lua { +/** Internal tag granting access to lua internals. +*/ struct Access; class Context; @@ -33,6 +40,8 @@ class Table; class Value; class Function; +/** Pointer to a Lua-callable function returning Value. +*/ using FunctionPtr = Value (*)(std::vector); //------------------------------------------------ @@ -45,22 +54,33 @@ class zstring char const* c_str_; public: + /** Construct from a C-string pointer. + @param s Null-terminated string. + */ zstring(char const* s) noexcept : c_str_(s) { } + /** Construct from string_view (stores an owned copy). + @param s String view to copy. + */ zstring(std::string_view s) : s_(s) , c_str_(s_.c_str()) { } + /** Construct from std::string without copying. + @param s Source string. + */ zstring(std::string const& s) : c_str_(s.c_str()) { } + /** Return the underlying C-string pointer. + */ char const* c_str() const noexcept { return c_str_; @@ -101,6 +121,10 @@ class MRDOCS_DECL //------------------------------------------------ +/** Stack scope guard for Lua calls. +*/ +/** Helper that balances the Lua stack for a Context scope. +*/ class Scope { Context ctx_; @@ -113,9 +137,14 @@ class Scope public: MRDOCS_DECL + /** Create a scope that manages Lua stack references. + @param ctx Lua context to guard. + */ Scope(Context const& ctx) noexcept; MRDOCS_DECL + /** Pop any pending stack references on destruction. + */ ~Scope(); /** Load a Lua chunk @@ -201,11 +230,23 @@ class MRDOCS_DECL union { + /** Stored boolean value when kind_ == boolean. + */ bool b_; + /** Stored integer value when kind_ == integer. + */ int i_; + /** Stack index when kind_ == value. + */ int index_; // for Value + /** Stored string view when kind_ == string. + */ std::string_view s_; + /** Stored array when kind_ == domArray. + */ dom::Array arr_; + /** Stored object when kind_ == domObject. + */ dom::Object obj_; }; @@ -215,18 +256,41 @@ class MRDOCS_DECL Param(Param&&) noexcept; public: + /** Destroy the stored value without throwing. + */ ~Param(); + + /** Construct a nil parameter. + */ Param(std::nullptr_t) noexcept; + /** Construct an integer parameter. + */ Param(std::int64_t) noexcept; + /** Construct a string parameter (non-owning). + */ Param(std::string_view s) noexcept; + /** Construct from a Lua Value already on the stack. + */ Param(Value const& value) noexcept; + /** Construct from a DOM array. + */ Param(dom::Array arr) noexcept; + /** Construct from a DOM object. + */ Param(dom::Object obj) noexcept; + /** Construct from a generic DOM value. + */ Param(dom::Value const& value) noexcept; + /** Deleted copy constructor to avoid double pops. + */ Param(Param const&) = delete; + /** Deleted copy assignment to avoid double pops. + */ Param& operator=(Param const&) = delete; + /** Construct a boolean parameter from a bool-like type. + */ template requires std::is_same_v Param(Boolean const& b) noexcept @@ -235,11 +299,15 @@ class MRDOCS_DECL { } + /** Construct a string parameter from C-string. + */ Param(char const* s) noexcept : Param(std::string_view(s)) { } + /** Construct a string parameter from a convertible string type. + */ template requires std::is_convertible_v< String, std::string_view> @@ -248,6 +316,8 @@ class MRDOCS_DECL { } + /** Construct an integral parameter from an enum. + */ template requires std::is_enum_v Param(Enum v) noexcept @@ -283,12 +353,18 @@ class MRDOCS_DECL Value { protected: + /** Scope that owns the stack slot for this value. + */ Scope* scope_; + /** Stack index where the value is stored. + */ int index_; friend struct Access; - Value(int, Scope&) noexcept; + /** Create a value referring to a stack slot within a scope. + */ + Value(int position, Scope& scope) noexcept; public: /** Destructor. @@ -324,13 +400,27 @@ class MRDOCS_DECL */ Value(Value const& other); + /** Return the Lua type of this value. + */ Type type() const noexcept; + /** Return true if the value is nil. + */ bool isNil() const noexcept; + /** Return true if the value is a boolean. + */ bool isBoolean() const noexcept; + /** Return true if the value is numeric. + */ bool isNumber() const noexcept; + /** Return true if the value is a string. + */ bool isString() const noexcept; + /** Return true if the value is a function. + */ bool isFunction() const noexcept; + /** Return true if the value is a table. + */ bool isTable() const noexcept; /** Return a string representation. @@ -422,16 +512,28 @@ class String : public Value String(int index, Scope&) noexcept; public: + /** Wrap an existing Lua value as a string. + */ MRDOCS_DECL String(Value value); + /** Create a new Lua string from the given view. + */ MRDOCS_DECL explicit String(std::string_view s); + /** Retrieve the underlying string view. + @return View of the Lua string contents. + */ MRDOCS_DECL std::string_view get() const noexcept; + /** Dereference to the underlying string view. + @return View of the Lua string contents. + */ std::string_view operator*() const noexcept { return get(); } + /** Implicit conversion to string view. + */ operator std::string_view() const noexcept { return get(); @@ -450,6 +552,8 @@ class MRDOCS_DECL Function(int index, Scope&) noexcept; public: + /** Construct a function wrapper from an existing value. + */ Function(Value value); }; @@ -470,12 +574,22 @@ class Table : public Value std::size_t size) const; public: - MRDOCS_DECL Table(Scope&, dom::Object const& obj); + /** Construct a table by copying fields from a DOM object. + */ + MRDOCS_DECL Table(Scope& scope, dom::Object const& obj); + /** Wrap an existing Lua value as a table. + */ MRDOCS_DECL Table(Value value); + /** Create an empty table in the given scope. + */ MRDOCS_DECL explicit Table(Scope& scope); //MRDOCS_DECL Value get(zstring key) const; + /** Retrieve a table entry by key; returns nil if missing. + @param key Table key to look up. + @return Value stored at key or nil if absent. + */ MRDOCS_DECL Value get( diff --git a/include/mrdocs/Support/Parse.hpp b/include/mrdocs/Support/Parse.hpp index a9ad549bd7..fdfcdcbbf8 100644 --- a/include/mrdocs/Support/Parse.hpp +++ b/include/mrdocs/Support/Parse.hpp @@ -41,9 +41,13 @@ namespace mrdocs { where more parameters can be defined as needed for parsing options. - */ +*/ struct ParseResult { + /** Pointer to the first unparsed character. + */ const char* ptr; + /** Error status for the parse operation. + */ Error ec; friend @@ -52,6 +56,10 @@ struct ParseResult { const ParseResult&, const ParseResult& ) = default; + /** Return true if parsing succeeded. + + @return `true` when `ec` is not a failure. + */ constexpr explicit operator bool() const noexcept @@ -72,7 +80,7 @@ struct ParseResult { char const* last, T& value); @endcode - */ +*/ template concept HasParse = requires( char const* first, @@ -100,7 +108,7 @@ concept HasParse = requires( @param sv The string view to parse @param value The value to store the result - */ +*/ template ParseResult parse(std::string_view sv, T& value) @@ -128,7 +136,7 @@ parse(std::string_view sv, T& value) @copydetails parse(std::string_view, T&) - */ +*/ template Expected parse(std::string_view sv) @@ -147,4 +155,4 @@ parse(std::string_view sv) } // mrdocs -#endif \ No newline at end of file +#endif diff --git a/include/mrdocs/Support/Path.hpp b/include/mrdocs/Support/Path.hpp index f60b74f5a2..78bc218cee 100644 --- a/include/mrdocs/Support/Path.hpp +++ b/include/mrdocs/Support/Path.hpp @@ -21,12 +21,20 @@ namespace mrdocs { //------------------------------------------------ +/** Polymorphic visitor for files discovered during traversal. +*/ struct MRDOCS_VISIBLE AnyFileVisitor { + /** Virtual destructor. + */ virtual ~AnyFileVisitor() = 0; + /** Visit a single file path. + @param fileName Path to the file being visited. + @return Success or error from visitor. + */ virtual Expected visitFile(std::string_view fileName) = 0; @@ -106,6 +114,11 @@ forEachFile( //------------------------------------------------ +/** Filesystem helpers (join, temp, canonicalize) used throughout MrDocs. + + The `files` namespace centralizes cross-platform path manipulation so CLI, + generators, and tests can share the same normalization and staging logic. +*/ namespace files { /** The type of a file. @@ -343,12 +356,25 @@ withExtension( std::string_view fileName, std::string_view ext); +/** Append a component to a base path using the native separator. + + @param basePath Base path. + @param name Component to append. + @return Combined path string. +*/ MRDOCS_DECL std::string appendPath( std::string_view basePath, std::string_view name); +/** Append two components to a base path using the native separator. + + @param basePath Base path. + @param name1 First component to append. + @param name2 Second component to append. + @return Combined path string. +*/ MRDOCS_DECL std::string appendPath( @@ -356,6 +382,14 @@ appendPath( std::string_view name1, std::string_view name2); +/** Append three components to a base path using the native separator. + + @param basePath Base path. + @param name1 First component to append. + @param name2 Second component to append. + @param name3 Third component to append. + @return Combined path string. +*/ MRDOCS_DECL std::string appendPath( @@ -364,6 +398,15 @@ appendPath( std::string_view name2, std::string_view name3); +/** Append four components to a base path using the native separator. + + @param basePath Base path. + @param name1 First component to append. + @param name2 Second component to append. + @param name3 Third component to append. + @param name4 Fourth component to append. + @return Combined path string. +*/ MRDOCS_DECL std::string appendPath( @@ -462,7 +505,7 @@ createDirectory( @param pathName A string view representing the path to be checked. @param prefix A string view representing the prefix to be checked against the path. @return A boolean value. Returns true if `pathName` starts with `prefix`, false otherwise. - */ +*/ MRDOCS_DECL bool startsWith( @@ -473,4 +516,4 @@ startsWith( } // mrdocs -#endif \ No newline at end of file +#endif diff --git a/include/mrdocs/Support/RangeFor.hpp b/include/mrdocs/Support/RangeFor.hpp index 0f7af07621..db0c524ac5 100644 --- a/include/mrdocs/Support/RangeFor.hpp +++ b/include/mrdocs/Support/RangeFor.hpp @@ -14,10 +14,9 @@ #include - namespace mrdocs { -/** Range to help range-for loops identify first and last. +/** Range adapter to expose first/last flags inside range-for loops. */ template class RangeFor @@ -25,35 +24,68 @@ class RangeFor Container const& C_; public: + /** Proxy describing an element plus first/last flags. + */ struct value_type; + /** Unsigned size type. + */ using size_type = std::size_t; + /** Signed distance type. + */ using difference_type = std::ptrdiff_t; + /** Pointer to proxy. + */ using pointer = value_type*; + /** Reference to proxy. + */ using reference = value_type&; + /** Pointer to const proxy. + */ using const_pointer = value_type const*; + /** Reference to const proxy. + */ using const_reference = value_type const&; class iterator; + /** Construct a range wrapper over a container. + @param C Container to iterate. + */ explicit RangeFor(Container const& C) noexcept : C_(C) { } + /** Iterator to first element. + */ iterator begin() const noexcept; + /** Iterator past the last element. + */ iterator end() const noexcept; }; //------------------------------------------------ +/** Reference to current element. +*/ template struct RangeFor::value_type { + /// The contained value. typename Container::value_type const& value; + + /** True if this element is the first in the range. + */ bool const first; + + /** True if this element is the last in the range. + */ bool const last; + /** Access members through pointer syntax. + @return Pointer to this proxy. + */ value_type const* operator->() const noexcept { return this; @@ -62,6 +94,8 @@ struct RangeFor::value_type //------------------------------------------------ +/** Iterator yielding RangeFor::value_type proxies with first/last flags. +*/ template class RangeFor::iterator { @@ -88,31 +122,57 @@ class RangeFor::iterator } public: + /** Proxy value type. + */ using value_type = typename RangeFor::value_type; + /** Pointer type (unused). + */ using pointer = void; + /** Reference type. + */ using reference = value_type; + /** Size type alias. + */ using size_type = std::size_t; + /** Iterator category forwarded from container. + */ using iterator_category = typename std::iterator_traits::iterator_category; + /** Default constructor. + */ iterator() = default; + /** Copy constructor. + */ iterator(iterator const&) = default; + /** Copy assignment. + */ iterator& operator=( iterator const&) = default; + /** Pre-increment. + @return *this advanced to next element. + */ iterator& operator++() noexcept { ++it_; return *this; } - iterator operator++(int) noexcept + /** Post-increment. + @param unused Dummy parameter for postfix form. + @return Iterator prior to increment. + */ + iterator operator++(int unused) noexcept { + (void)unused; auto temp = *this; ++temp; return temp; } + /** Return proxy for current element. + */ reference operator->() const noexcept { return value_type{ @@ -121,6 +181,8 @@ class RangeFor::iterator it_ == last_ }; } + /** Dereference to proxy value. + */ reference operator*() const noexcept { return value_type{ @@ -129,11 +191,15 @@ class RangeFor::iterator it_ == last_ }; } + /** Equality comparison. + */ bool operator==(iterator const& it) const noexcept { return it_ == it.it_; } + /** Inequality comparison. + */ bool operator!=(iterator const& it) const noexcept { return it_ != it.it_; @@ -142,6 +208,10 @@ class RangeFor::iterator //------------------------------------------------ +/** Deduction guide for RangeFor. +*/ +/** Deduction guide for RangeFor. +*/ template RangeFor(Container const&) -> RangeFor; @@ -162,4 +232,4 @@ auto RangeFor::end() const noexcept -> } // mrdocs -#endif \ No newline at end of file +#endif diff --git a/include/mrdocs/Support/Report.hpp b/include/mrdocs/Support/Report.hpp index 8cddc7035b..becd50d1e3 100644 --- a/include/mrdocs/Support/Report.hpp +++ b/include/mrdocs/Support/Report.hpp @@ -26,6 +26,12 @@ #include #include +/** Reporting utilities (messages, statistics, sinks). + + The `report` namespace owns severity enums, message structs, and output + sinks so tooling and libraries emit diagnostics in a uniform, testable + format regardless of UI. +*/ namespace mrdocs::report { /** Severity levels attached to reported messags. @@ -50,11 +56,23 @@ enum class Level */ struct Results { + /** Number of trace-level messages. + */ std::size_t traceCount; + /** Number of debug-level messages. + */ std::size_t debugCount; + /** Number of info-level messages. + */ std::size_t infoCount; + /** Number of warning-level messages. + */ std::size_t warnCount; + /** Number of error-level messages. + */ std::size_t errorCount; + /** Number of fatal-level messages. + */ std::size_t fatalCount; }; @@ -78,6 +96,10 @@ setMinimumLevel(Level level) noexcept; MRDOCS_DECL Level +/** Get the minimum threshold level for reporting. + + @return Current minimum Level that will be emitted. +*/ getMinimumLevel() noexcept; /** If true, source location information will be @@ -127,9 +149,18 @@ print( template struct Located { + /** Wrapped value. + */ T value; + /** Source location of the value. + */ source_location where; + /** Construct a Located wrapper. + + @param arg Value to wrap. + @param loc Source location to associate (defaults to current). + */ template requires std::is_constructible_v Located( @@ -142,6 +173,11 @@ struct Located } }; +/** Internal helpers for report rendering and formatting. + + These are kept in `detail` to isolate formatting glue (color, alignment, + column widths) from the public reporting API. +*/ namespace detail { template requires (!std::same_as, Error>) @@ -214,12 +250,10 @@ log( std::forward(args)...); } -/** Report a message to the console. - - @param format The format string. - @param args Optional additional arguments - - */ +/** Emit a trace-level diagnostic (verbose, off by default). + @param format fmt-style format string. + @param args Arguments substituted into the format string. +*/ template void trace( @@ -229,12 +263,10 @@ trace( return log(Level::trace, format, std::forward(args)...); } -/** Report a message to the console. - - @param format The format string. - @param args Optional additional arguments - - */ +/** Emit a debug-level diagnostic for troubleshooting. + @param format fmt-style format string. + @param args Arguments substituted into the format string. +*/ template void debug( @@ -244,12 +276,10 @@ debug( return log(Level::debug, format, std::forward(args)...); } -/** Report a message to the console. - - @param format The format string. - @param args Optional additional arguments - - */ +/** Emit an informational message for users. + @param format fmt-style format string. + @param args Arguments substituted into the format string. +*/ template void info( @@ -259,12 +289,10 @@ info( return log(Level::info, format, std::forward(args)...); } -/** Report a message to the console. - - @param format The format string. - @param args Optional additional arguments - - */ +/** Emit a warning that does not stop execution. + @param format fmt-style format string. + @param args Arguments substituted into the format string. +*/ template void warn( @@ -274,12 +302,10 @@ warn( return log(Level::warn, format, std::forward(args)...); } -/** Report a message to the console. - - @param format The format string. - @param args Optional additional arguments - - */ +/** Emit an error that indicates failure but allows continuation. + @param format fmt-style format string. + @param args Arguments substituted into the format string. +*/ template void error( @@ -289,10 +315,9 @@ error( return log(Level::error, format, std::forward(args)...); } -/** Report a message to the console. - - @param format The format string. - @param args Optional additional arguments +/** Emit a fatal error and mark the report as the highest severity. + @param format fmt-style format string. + @param args Arguments substituted into the format string. */ template void diff --git a/include/mrdocs/Support/ScopeExit.hpp b/include/mrdocs/Support/ScopeExit.hpp index 3574414e49..a6a1d07368 100644 --- a/include/mrdocs/Support/ScopeExit.hpp +++ b/include/mrdocs/Support/ScopeExit.hpp @@ -15,29 +15,43 @@ namespace mrdocs { +/** Execute a callable when the enclosing scope exits unless dismissed. +*/ template class ScopeExit { F onExitScope_; bool dismissed_{false}; public: + /** Construct with a callable to invoke on scope exit. + + @param onExitScope Callable executed unless dismissed. + */ explicit ScopeExit(F onExitScope) : onExitScope_(std::move(onExitScope)) {} + /** Invoke the stored callable if the guard was not dismissed. + */ ~ScopeExit() { if (!dismissed_) { onExitScope_(); } } + /** Prevent the callable from running on destruction. + */ void dismiss() { dismissed_ = true; } }; +/** Deduction guide for ScopeExit. +*/ template ScopeExit(F) -> ScopeExit; +/** RAII helper that restores a referenced value on scope exit. +*/ template class ScopeExitRestore { T prev_; @@ -49,7 +63,7 @@ class ScopeExitRestore { Store the current value of `ref` and restore it when this object goes out of scope, unless `dismiss()` is called. - */ + */ explicit ScopeExitRestore(T& ref) : prev_(ref), ref_(ref) @@ -57,10 +71,13 @@ class ScopeExitRestore { /** Temporarily set `ref` to `next` and restore it when the scope ends + @param ref The variable to modify and eventually restore. + @param next The temporary value assigned to `ref` for the scope. + Store the current value of `ref`, set it to `next`, and restore the previous value when this object goes out of scope, unless `dismiss()` is called. - */ + */ template T2> explicit ScopeExitRestore(T& ref, T2 next) @@ -69,6 +86,8 @@ class ScopeExitRestore { ref_ = next; } + /** Restore the previous value unless dismissed. + */ ~ScopeExitRestore() { if (!dismissed_) { @@ -76,18 +95,24 @@ class ScopeExitRestore { } } + /** Prevent restoration on destruction. + */ void dismiss() { dismissed_ = true; } }; +/** Deduction guide for ScopeExitRestore taking a reference. +*/ template ScopeExitRestore(T&) -> ScopeExitRestore; +/** Deduction guide for ScopeExitRestore taking a reference and new value. +*/ template T2> ScopeExitRestore(T&, T2) -> ScopeExitRestore; } -#endif // MRDOCS_API_SUPPORT_SCOPEEXIT_HPP \ No newline at end of file +#endif // MRDOCS_API_SUPPORT_SCOPEEXIT_HPP diff --git a/include/mrdocs/Support/SplitLines.hpp b/include/mrdocs/Support/SplitLines.hpp index 2c63399231..7be3cc9087 100644 --- a/include/mrdocs/Support/SplitLines.hpp +++ b/include/mrdocs/Support/SplitLines.hpp @@ -70,20 +70,44 @@ lbLen(std::string_view s, std::size_t i) noexcept } } -// A lazy input range of std::string_view lines split on all known line breaks. +/** A lazy input range of std::string_view lines split on all known line breaks. +*/ struct SplitLinesView : std::ranges::view_interface { + /** Underlying string to split. + */ std::string_view sv_; + /** Construct an empty view. + */ constexpr SplitLinesView() = default; + /** Construct a view over @p sv. + @param sv String to split into lines. + */ explicit constexpr SplitLinesView(std::string_view sv) : sv_(sv) {} + /** Iterator over lines produced by SplitLinesView. + */ struct Iterator { + /** Reference to the source string. + */ std::string_view sv{}; + /** Start of the current line. + */ std::size_t cur = 0; // start of current line + /** Index of the next break delimiter or npos. + */ std::size_t nextBreak = 0; // index of current break (or npos) + /** Flag indicating the end iterator. + */ bool atEnd = false; + /** Construct an end iterator. + */ constexpr Iterator() = default; + /** Construct a begin or end iterator. + @param s Source string. + @param begin If true, position at the first line; otherwise create end iterator. + */ explicit constexpr Iterator(std::string_view s, bool begin) : sv(s) { if (!begin) @@ -94,6 +118,10 @@ struct SplitLinesView : std::ranges::view_interface { nextBreak = findBreak(cur); } + /** Compute the next line break position. + @param from Index to start searching. + @return Offset of the next break or npos. + */ constexpr std::size_t findBreak(std::size_t from) const noexcept { @@ -107,9 +135,16 @@ struct SplitLinesView : std::ranges::view_interface { return std::string_view::npos; } + /** Line view type exposed by the iterator. + */ using value_type = std::string_view; + /** Signed distance type for the iterator. + */ using difference_type = std::ptrdiff_t; + /** Return the current line segment. + @return View of the current line. + */ constexpr value_type operator*() const noexcept { @@ -119,6 +154,9 @@ struct SplitLinesView : std::ranges::view_interface { return sv.substr(cur, end - cur); } + /** Advance to the next line. + @return Reference to this iterator. + */ constexpr Iterator& operator++() noexcept { @@ -137,9 +175,13 @@ struct SplitLinesView : std::ranges::view_interface { return *this; } + /** Advance to the next line (post-increment). + @param unused Dummy parameter for postfix form. + */ constexpr void - operator++(int) + operator++(int unused) { + (void)unused; ++*this; } @@ -150,11 +192,17 @@ struct SplitLinesView : std::ranges::view_interface { } }; + /** Return an iterator to the first line. + @return Iterator positioned at the first line. + */ constexpr Iterator begin() const noexcept { return Iterator{ sv_, true }; } + /** Return the end sentinel for the view. + @return Default sentinel representing the end. + */ constexpr std::default_sentinel_t end() const noexcept { @@ -165,8 +213,14 @@ struct SplitLinesView : std::ranges::view_interface { // Pipeable range adaptor object: // - s | text::views::splitLines // - text::views::splitLines(s) +/** Range adaptor that constructs a SplitLinesView. +*/ struct SplitLinesAdaptor { // Call-style + /** Split a string view into lines. + @param sv Source string. + @return View over the lines in @p sv. + */ constexpr auto operator()(std::string_view sv) const { @@ -177,6 +231,10 @@ struct SplitLinesAdaptor { template requires std::same_as>, char> + /** Split any contiguous character range into lines. + @param r Range of characters. + @return View over the lines in the range. + */ constexpr auto operator()(R&& r) const { @@ -190,6 +248,11 @@ struct SplitLinesAdaptor { requires std::ranges::contiguous_range && std::same_as>, char> + /** Pipe a contiguous character range into the adaptor. + @param r Range to split. + @param a SplitLines adaptor instance. + @return View over the lines in @p r. + */ friend constexpr auto operator|(R&& r, SplitLinesAdaptor const& a) { @@ -200,7 +263,7 @@ struct SplitLinesAdaptor { /** Split a string view into lines, recognizing all common line breaks This is a convenience function for creating a SplitLinesView. - */ +*/ inline constexpr SplitLinesAdaptor splitLines{}; } // mrdocs diff --git a/include/mrdocs/Support/String.hpp b/include/mrdocs/Support/String.hpp index 8262577984..8096ee1240 100644 --- a/include/mrdocs/Support/String.hpp +++ b/include/mrdocs/Support/String.hpp @@ -23,7 +23,7 @@ namespace mrdocs { @param s The string to trim. @param chars The characters to remove. @return The modified string. - */ +*/ constexpr std::string_view ltrim( @@ -37,7 +37,7 @@ ltrim( @param s The string to trim. @return The modified string. - */ +*/ constexpr std::string_view ltrim( @@ -51,7 +51,7 @@ ltrim( @param s The string to trim. @param chars The characters to remove. @return The modified string. - */ +*/ constexpr std::string_view rtrim( @@ -70,7 +70,7 @@ rtrim( @param s The string to trim. @return The modified string. - */ +*/ constexpr std::string_view rtrim(std::string_view const s) noexcept @@ -82,7 +82,7 @@ rtrim(std::string_view const s) noexcept @param s The string to trim. @return The modified string. - */ +*/ constexpr std::string_view trim(std::string_view const s) noexcept @@ -95,7 +95,7 @@ trim(std::string_view const s) noexcept @param s The string to trim. @param chars The characters to remove. @return The modified string. - */ +*/ constexpr std::string_view trim( @@ -123,7 +123,7 @@ replace(std::string& s, std::string_view from, std::string_view to); @return true if the string is empty or contains only whitespace characters (space, tab, newline, vertical tab, form feed, carriage return). false otherwise. - */ +*/ constexpr bool isWhitespace(std::string_view s) noexcept @@ -131,6 +131,11 @@ isWhitespace(std::string_view s) noexcept return s.find_first_not_of(" \t\n\v\f\r") == std::string::npos; } +/** Determine if a character is whitespace. + + @param c Character to inspect. + @return `true` if `c` is a horizontal or vertical whitespace character. +*/ constexpr bool isWhitespace(char c) noexcept @@ -143,7 +148,7 @@ isWhitespace(char c) noexcept @param s The string to check. @param chars The characters to check for. - */ +*/ constexpr bool startsWithOneOf(std::string_view s, std::string_view chars) noexcept @@ -155,7 +160,7 @@ startsWithOneOf(std::string_view s, std::string_view chars) noexcept @param s The string to check. @param chars The characters to check for. - */ +*/ constexpr bool endsWithOneOf(std::string_view s, std::string_view chars) noexcept @@ -163,6 +168,11 @@ endsWithOneOf(std::string_view s, std::string_view chars) noexcept return !s.empty() && chars.find(s.back()) != std::string_view::npos; } +/** Determine if a character is a lowercase ASCII letter. + + @param c Character to inspect. + @return `true` if `c` is in the range 'a' to 'z'. +*/ constexpr bool isLowerCase(char const c) noexcept @@ -170,6 +180,11 @@ isLowerCase(char const c) noexcept return c >= 'a' && c <= 'z'; } +/** Determine if every character in a string is lowercase ASCII. + + @param s String to inspect. + @return `true` if all characters are lowercase ASCII letters. +*/ constexpr bool isLowerCase(std::string_view const s) noexcept @@ -184,6 +199,11 @@ isLowerCase(std::string_view const s) noexcept return true; } +/** Determine if a character is an uppercase ASCII letter. + + @param c Character to inspect. + @return `true` if `c` is in the range 'A' to 'Z'. +*/ constexpr bool isUpperCase(char const c) noexcept @@ -191,6 +211,11 @@ isUpperCase(char const c) noexcept return c >= 'A' && c <= 'Z'; } +/** Determine if every character in a string is uppercase ASCII. + + @param s String to inspect. + @return `true` if all characters are uppercase ASCII letters. +*/ constexpr bool isUpperCase(std::string_view const s) noexcept @@ -205,6 +230,11 @@ isUpperCase(std::string_view const s) noexcept return true; } +/** Convert a character to lowercase ASCII without locale. + + @param c Character to convert. + @return Lowercase version of `c` if it is uppercase; otherwise `c`. +*/ constexpr char toLowerCase(char const c) noexcept @@ -212,6 +242,11 @@ toLowerCase(char const c) noexcept return isUpperCase(c) ? static_cast(c - 'A' + 'a') : c; } +/** Return a lowercase copy of the string without locale. + + @param s Input string. + @return Lowercase copy of `s`. +*/ constexpr std::string toLowerCase(std::string_view const s) noexcept @@ -225,6 +260,11 @@ toLowerCase(std::string_view const s) noexcept return result; } +/** Convert a character to uppercase ASCII without locale. + + @param c Character to convert. + @return Uppercase version of `c` if it is lowercase; otherwise `c`. +*/ constexpr char toUpperCase(char const c) noexcept @@ -232,6 +272,11 @@ toUpperCase(char const c) noexcept return isLowerCase(c) ? static_cast(c - 'a' + 'A') : c; } +/** Return an uppercase copy of the string without locale. + + @param s Input string. + @return Uppercase copy of `s`. +*/ constexpr std::string toUpperCase(std::string_view const s) noexcept @@ -245,6 +290,11 @@ toUpperCase(std::string_view const s) noexcept return result; } +/** Determine if a character is an ASCII digit. + + @param c Character to inspect. + @return `true` if `c` is between '0' and '9'. +*/ constexpr bool isDigit(char const c) noexcept @@ -252,6 +302,11 @@ isDigit(char const c) noexcept return c >= '0' && c <= '9'; } +/** Determine if every character in a string is an ASCII digit. + + @param s String to inspect. + @return `true` if all characters are digits. +*/ constexpr bool isDigit(std::string_view const s) noexcept @@ -266,6 +321,11 @@ isDigit(std::string_view const s) noexcept return true; } +/** Determine if a character is an ASCII letter. + + @param c Character to inspect. + @return `true` if `c` is in the ranges 'a'-'z' or 'A'-'Z'. +*/ constexpr bool isAlphabetic(char const c) noexcept @@ -273,6 +333,11 @@ isAlphabetic(char const c) noexcept return isLowerCase(c) || isUpperCase(c); } +/** Determine if every character in a string is an ASCII letter. + + @param s String to inspect. + @return `true` if all characters are alphabetic. +*/ constexpr bool isAlphabetic(std::string_view const s) noexcept @@ -287,6 +352,11 @@ isAlphabetic(std::string_view const s) noexcept return true; } +/** Determine if a character is ASCII alphanumeric. + + @param c Character to inspect. + @return `true` if `c` is an ASCII letter or digit. +*/ constexpr bool isAlphaNumeric(char const c) noexcept @@ -294,6 +364,11 @@ isAlphaNumeric(char const c) noexcept return isAlphabetic(c) || isDigit(c); } +/** Determine if every character in a string is ASCII alphanumeric. + + @param s String to inspect. + @return `true` if all characters are ASCII letters or digits. +*/ constexpr bool isAlphaNumeric(std::string_view const s) noexcept @@ -308,6 +383,11 @@ isAlphaNumeric(std::string_view const s) noexcept return true; } +/** Convert a string to `kebab-case` using ASCII letter rules. + + @param input Source string. + @return New string converted to kebab-case. +*/ constexpr std::string toKebabCase(std::string_view const input) @@ -341,6 +421,11 @@ toKebabCase(std::string_view const input) return result; } +/** Convert a string to `snake_case` using ASCII letter rules. + + @param input Source string. + @return New string converted to snake_case. +*/ constexpr std::string toSnakeCase(std::string_view const input) @@ -376,6 +461,11 @@ toSnakeCase(std::string_view const input) return result; } +/** Convert a string to `camelCase` using ASCII letter rules. + + @param input Source string. + @return New string converted to camelCase. +*/ constexpr std::string toCamelCase(std::string_view const input) @@ -410,6 +500,11 @@ toCamelCase(std::string_view const input) return result; } +/** Convert a string to `PascalCase` using ASCII letter rules. + + @param input Source string. + @return New string converted to PascalCase. +*/ constexpr std::string toPascalCase(std::string_view const input) @@ -442,6 +537,7 @@ toPascalCase(std::string_view const input) /** Reindent code by removing the common leading spaces and adding the specified indent. @param code The code block to unindent. + @param indent The number of spaces to insert in front of each line after trimming. @return The modified code block. */ MRDOCS_DECL diff --git a/include/mrdocs/Support/ThreadPool.hpp b/include/mrdocs/Support/ThreadPool.hpp index 4cd651e338..46979436d8 100644 --- a/include/mrdocs/Support/ThreadPool.hpp +++ b/include/mrdocs/Support/ThreadPool.hpp @@ -42,9 +42,27 @@ class MRDOCS_VISIBLE friend class TaskGroup; public: - template struct arg_ty { using type = T; }; - template struct arg_ty { using type = - std::conditional_t< std::is_const_v, T, T&>; }; + /** Helper that preserves lvalue-ref and constness for references. + */ + template + struct arg_ty { + /// Resulting adjusted type. + using type = T; + }; + + /** Alias returning the preserved argument type. + + @tparam T Original argument type. + @return Argument type with reference/const qualifiers preserved. + */ + template + struct arg_ty { + /// Resulting adjusted type. + using type = std::conditional_t, T, T&>; + }; + + /** Helper that forwards argument qualifiers. + */ template using arg_t = typename arg_ty::type; /** Destructor. diff --git a/include/mrdocs/Support/TypeTraits.hpp b/include/mrdocs/Support/TypeTraits.hpp index ba076db251..503f859e01 100644 --- a/include/mrdocs/Support/TypeTraits.hpp +++ b/include/mrdocs/Support/TypeTraits.hpp @@ -34,89 +34,139 @@ to_underlying( // ---------------------------------------------------------------- +/** Dependent alias of `T`, useful for delaying instantiation. +*/ template struct make_dependent { + /** Make a type dependent on another template parameter. + */ using type = T; }; +/** Alias for `make_dependent::type`. + @tparam T Type to make dependent. + @tparam U Dependent parameter. +*/ template using make_dependent_t = make_dependent::type; // ---------------------------------------------------------------- +/** Propagate lvalue-reference from `From` to `To` if present. +*/ template struct add_lvalue_reference_from : std::conditional< std::is_lvalue_reference_v, std::add_lvalue_reference_t, To> { }; +/** Alias for `add_lvalue_reference_from::type`. + @tparam From Source type providing reference qualifier. + @tparam To Destination type to adjust. +*/ template using add_lvalue_reference_from_t = add_lvalue_reference_from::type; // ---------------------------------------------------------------- +/** Propagate rvalue-reference from `From` to `To` if present. +*/ template struct add_rvalue_reference_from : std::conditional< std::is_rvalue_reference_v, std::add_rvalue_reference_t, To> { }; +/** Alias for `add_rvalue_reference_from::type`. + @tparam From Source type providing reference qualifier. + @tparam To Destination type to adjust. +*/ template using add_rvalue_reference_from_t = add_rvalue_reference_from::type; // ---------------------------------------------------------------- +/** Propagate reference qualification from `From` to `To`. +*/ template struct add_reference_from : add_lvalue_reference_from> { }; +/** Alias for `add_reference_from::type`. + @tparam From Source type providing reference qualifier. + @tparam To Destination type to adjust. +*/ template using add_reference_from_t = add_reference_from::type; // ---------------------------------------------------------------- +/** Propagate const qualification from `From` to `To`, keeping references. +*/ template struct add_const_from : std::conditional< std::is_const_v>, add_reference_from_t>, To> { }; +/** Alias for `add_const_from::type`. + @tparam From Source type providing const qualifier. + @tparam To Destination type to adjust. +*/ template using add_const_from_t = add_const_from::type; // ---------------------------------------------------------------- +/** Propagate volatile qualification from `From` to `To`, keeping references. +*/ template struct add_volatile_from : std::conditional< std::is_volatile_v>, add_reference_from_t>, To> { }; +/** Alias for `add_volatile_from::type`. + @tparam From Source type providing volatile qualifier. + @tparam To Destination type to adjust. +*/ template using add_volatile_from_t = add_volatile_from::type; // ---------------------------------------------------------------- +/** Propagate both const and volatile qualifiers from `From` to `To`. +*/ template struct add_cv_from : add_const_from> { }; +/** Alias for `add_cv_from::type`. + @tparam From Source type providing cv qualifiers. + @tparam To Destination type to adjust. +*/ template using add_cv_from_t = add_cv_from::type; // ---------------------------------------------------------------- +/** Propagate cv-qualification and reference category from `From` to `To`. +*/ template struct add_cvref_from : add_reference_from> { }; +/** Alias for `add_cvref_from::type`. + @tparam From Source type providing cv-ref qualifiers. + @tparam To Destination type to adjust. +*/ template using add_cvref_from_t = add_cvref_from::type; diff --git a/include/mrdocs/Support/Visitor.hpp b/include/mrdocs/Support/Visitor.hpp index 7cdc9e5ad2..a4934281e3 100644 --- a/include/mrdocs/Support/Visitor.hpp +++ b/include/mrdocs/Support/Visitor.hpp @@ -38,7 +38,7 @@ namespace mrdocs { @tparam Base The base type of the object @tparam Fn The function object type @tparam Args The argument types - */ +*/ template< typename Base, typename Fn, @@ -55,7 +55,7 @@ class Visitor @param obj The object to visit @param fn The function object to call @param args The arguments to pass to the function object - */ + */ Visitor(Base&& obj, Fn&& fn, Args&&... args) : obj_(std::forward(obj)) , fn_(std::forward(fn)) @@ -72,7 +72,7 @@ class Visitor @tparam Derived The derived type to visit @return The result of calling the function object - */ + */ template > Derived> decltype(auto) visit() @@ -103,7 +103,7 @@ class Visitor @param args The arguments to pass to the function object @return The common return type of `fn` when called with a derived type of `obj` and `args` - */ +*/ template< typename BaseTy, typename ObjectTy, diff --git a/include/mrdocs/Support/any_callable.hpp b/include/mrdocs/Support/any_callable.hpp index 98698a5548..f8f439bf46 100644 --- a/include/mrdocs/Support/any_callable.hpp +++ b/include/mrdocs/Support/any_callable.hpp @@ -29,6 +29,8 @@ namespace mrdocs { template class any_callable; +/** Type-erased callable wrapper for signature `R(Args...)`. +*/ template class any_callable { @@ -41,8 +43,13 @@ class any_callable std::unique_ptr p_; public: + /** Deleted default constructor to prevent empty call targets. + */ any_callable() = delete; + /** Construct from a callable object matching the signature. + @param f Callable to store; must satisfy `R(Args...)`. + */ template requires std::is_invocable_r_v any_callable(Callable&& f) @@ -66,6 +73,10 @@ class any_callable p_ = std::make_unique(std::forward(f)); } + /** Invoke the stored callable. + @param args Arguments forwarded to the callable. + @return Result of the wrapped callable. + */ R operator()(Args&&...args) const { return p_->invoke(std::forward(args)...); diff --git a/include/mrdocs/Support/source_location.hpp b/include/mrdocs/Support/source_location.hpp index 60ee3dc494..b0ab01960f 100644 --- a/include/mrdocs/Support/source_location.hpp +++ b/include/mrdocs/Support/source_location.hpp @@ -17,14 +17,20 @@ __has_include() # include namespace mrdocs { + /** Alias to `std::source_location` when available. + */ using std::source_location; } // mrdocs #else # include namespace mrdocs { + /** Lightweight backport of `std::source_location`. + */ struct source_location { + /** Capture the current source location. + */ static constexpr source_location @@ -43,12 +49,16 @@ namespace mrdocs { return result; } + /** Return the file name. + */ constexpr char const* file_name() const noexcept { return file_; } + /** Return the function name. + */ constexpr char const* function_name() const noexcept @@ -56,12 +66,16 @@ namespace mrdocs { return function_; } + /** Return the source line number. + */ constexpr std::uint_least32_t line() const noexcept { return line_; } + /** Return the source column number. + */ constexpr std::uint_least32_t column() const noexcept diff --git a/src/lib/AST/ASTAction.hpp b/src/lib/AST/ASTAction.hpp index fd87e63aa8..2063c4b24f 100644 --- a/src/lib/AST/ASTAction.hpp +++ b/src/lib/AST/ASTAction.hpp @@ -65,7 +65,7 @@ class ASTAction This `clang::ASTConsumer` then creates an @ref ASTVisitor that will convert the AST into a set of MrDocs Info objects. - */ + */ void ExecuteAction() override; @@ -81,7 +81,7 @@ class ASTAction The main function of the ASTVisitorConsumer is the `HandleTranslationUnit` function, which is called to traverse the AST with the @ref ASTVisitor. - */ + */ std::unique_ptr CreateASTConsumer( clang::CompilerInstance& Compiler, diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp index a73e29d067..5df1fa2e2a 100644 --- a/src/lib/AST/ASTVisitor.cpp +++ b/src/lib/AST/ASTVisitor.cpp @@ -3551,28 +3551,62 @@ checkUndocumented( SymbolID const& id, DeclTy const* D) { - // If `extract-all` is enabled, we don't need to - // check for undocumented symbols - MRDOCS_CHECK_OR(!config_->extractAll, {}); - // If the symbol is a namespace, the `extract-all` - // doesn't apply to it - MRDOCS_CHECK_OR((!std::same_as), {}); + // If the symbol is in the global namespace, it doesn't + // need documentation + MRDOCS_CHECK_OR(!isa(D), {}); + + // If `extract-all` is disabled, we don't need to + // warn for undocumented symbols because that's + // the expected behavior. We use this to fail early. + bool const hasDoc = isDocumented(D); + if (!config_->extractAll && + !hasDoc) + { + return Unexpected(Error("Undocumented")); + } + + // If `warn-if-undocumented` is disabled, we don't + // need to check for anything else because the + // logic below is only used to populate the + // set of undocumented symbols for warning purposes. + MRDOCS_CHECK_OR(config_->warnIfUndocumented, {}); + // If the symbol is not being extracted as a Regular // symbol, we don't need to check for undocumented symbols // These are expected to be potentially undocumented MRDOCS_CHECK_OR(mode_ == Regular, {}); + + if constexpr (std::same_as) + { + // Respect implementation-defined filters: symbols that match those patterns + // are intentionally kept undocumented. We re-check here to avoid emitting + // warnings even though extraction proceeds in regular mode for these + // namespaces to extract their children. + if (!config_->implementationDefined.empty()) + { + llvm::SmallString<256> const qn = qualifiedName(D); + auto qns = qn.str(); + if (checkSymbolFiltersImpl(config_->implementationDefined, qns) || + checkSymbolFiltersImpl(config_->implementationDefined, qns)) + { + return {}; + } + } + } + // Check if the symbol is documented, ensure this symbol is not in the set // of undocumented symbols in this translation unit and return // without an error if it is - if (isDocumented(D)) + if (hasDoc) { - if (config_->warnIfUndocumented) + auto const it = undocumented_.find(id); + if (it != undocumented_.end()) { - auto const it = undocumented_.find(id); undocumented_.erase(it); } return {}; } + // If the symbol is undocumented, check if we haven't seen a // documented version before. if (auto const infoIt = info_.find(id); @@ -3581,22 +3615,28 @@ checkUndocumented( { return {}; } + // If the symbol is undocumented, and we haven't seen a documented // version before, store this symbol in the set of undocumented // symbols we've seen so far in this translation unit. - if (config_->warnIfUndocumented) + auto undocIt = undocumented_.find(id); + if (undocIt == undocumented_.end()) { - auto const undocIt = undocumented_.find(id); - if (undocIt == undocumented_.end()) - { - SymbolKind const kind = InfoTy::kind_id; - undocumented_.insert(UndocumentedSymbol{id, extractName(D), kind}); - } - // Populate the location - auto handle = undocumented_.extract(undocIt); - UndocumentedSymbol& UI = handle.value(); - populate(UI.Loc, D); - undocumented_.insert(std::move(handle)); + SymbolKind const kind = InfoTy::kind_id; + auto [newIt, inserted] = undocumented_.insert(UndocumentedSymbol{id, extractName(D), kind}); + MRDOCS_ASSERT(inserted); + undocIt = newIt; + } + + // Populate the location + auto handle = undocumented_.extract(undocIt); + UndocumentedSymbol& UI = handle.value(); + populate(UI.Loc, D); + undocumented_.insert(std::move(handle)); + + if (config_->extractAll) + { + return {}; } return Unexpected(Error("Undocumented")); } diff --git a/src/lib/AST/ASTVisitor.hpp b/src/lib/AST/ASTVisitor.hpp index 1b8093a124..c36c87839c 100644 --- a/src/lib/AST/ASTVisitor.hpp +++ b/src/lib/AST/ASTVisitor.hpp @@ -271,7 +271,7 @@ class ASTVisitor @param compiler The compiler instance. @param context The AST context. @param sema The clang::Sema object. - */ + */ ASTVisitor( ConfigImpl const& config, Diagnostics const& diags, @@ -298,7 +298,7 @@ class ASTVisitor is not set to `never`, a second pass is made to extract referenced declarations. The `buildDependencies` function is responsible for this second pass. - */ + */ void build(); @@ -308,7 +308,7 @@ class ASTVisitor declarations that have been extracted by the ASTVisitor. @return A reference to the SymbolSet containing the extracted Info declarations. - */ + */ SymbolSet& results() { @@ -321,7 +321,7 @@ class ASTVisitor declarations that have been extracted by the ASTVisitor. @return A reference to the SymbolSet containing the extracted Info declarations. - */ + */ UndocumentedSymbolSet& undocumented() { diff --git a/src/lib/AST/ASTVisitorConsumer.hpp b/src/lib/AST/ASTVisitorConsumer.hpp index 8a15796e17..ed13878725 100644 --- a/src/lib/AST/ASTVisitorConsumer.hpp +++ b/src/lib/AST/ASTVisitorConsumer.hpp @@ -35,7 +35,7 @@ namespace mrdocs { `clang::SemaConsumer` class. The main function this class overrides is `HandleTranslationUnit`, which is called when the translation unit is complete. - */ +*/ class ASTVisitorConsumer : public clang::SemaConsumer { @@ -60,7 +60,7 @@ class ASTVisitorConsumer Initialize the semantic consumer with the Sema instance being used to perform semantic analysis on the abstract syntax tree. - */ + */ void InitializeSema(clang::Sema& S) override { @@ -72,7 +72,7 @@ class ASTVisitorConsumer /** Inform the semantic consumer that Sema is no longer available. This is called when the Sema instance is no longer available. - */ + */ void ForgetSema() override { @@ -91,7 +91,7 @@ class ASTVisitorConsumer All other `Handle*` methods called by when a specific type of declaration or definition is found is left as an empty stub. - */ + */ void HandleTranslationUnit(clang::ASTContext& Context) override; @@ -101,7 +101,7 @@ class ASTVisitorConsumer top-level Decl*. @returns `true` to always continue parsing - */ + */ bool HandleTopLevelDecl(clang::DeclGroupRef) override { @@ -121,7 +121,7 @@ class ASTVisitorConsumer returns false for these VarDecls, so we manually set it here. @param D The declaration of the static member variable - */ + */ void HandleCXXStaticMemberVarInstantiation(clang::VarDecl* D) override { @@ -145,7 +145,7 @@ class ASTVisitorConsumer false for these clang::FunctionDecls, so we manually set it here. @param D The declaration of the function - */ + */ void HandleCXXImplicitFunctionInstantiation(clang::FunctionDecl* D) override { @@ -160,7 +160,7 @@ class ASTVisitorConsumer The implementation is an empty stub. @param D The declaration of the function - */ + */ void HandleInlineFunctionDefinition(clang::FunctionDecl*) override { } /** Handle a tag declaration definition. @@ -171,7 +171,7 @@ class ASTVisitorConsumer The implementation is an empty stub. @param D The declaration of the tag - */ + */ void HandleTagDeclDefinition(clang::TagDecl*) override { } /** Handle a tag declaration required definition. @@ -182,7 +182,7 @@ class ASTVisitorConsumer The implementation is an empty stub. @param D The declaration of the tag - */ + */ void HandleTagDeclRequiredDefinition(clang::TagDecl const*) override { } /** Handle an interesting declaration. @@ -195,7 +195,7 @@ class ASTVisitorConsumer The implementation is an empty stub. @param D The declaration - */ + */ void HandleInterestingDecl(clang::DeclGroupRef) override { } /** Handle a tentative definition. @@ -205,7 +205,7 @@ class ASTVisitorConsumer The implementation is an empty stub. @param D The declaration - */ + */ void CompleteTentativeDefinition(clang::VarDecl*) override { } /** Handle a tentative definition. @@ -215,7 +215,7 @@ class ASTVisitorConsumer The implementation is an empty stub. @param D The declaration - */ + */ void CompleteExternalDeclaration(clang::DeclaratorDecl*) override { } /** Handle a vtable. @@ -225,7 +225,7 @@ class ASTVisitorConsumer The implementation is an empty stub. @param D The declaration - */ + */ void AssignInheritanceModel(clang::CXXRecordDecl*) override { } /** Handle an implicit import declaration. @@ -235,7 +235,7 @@ class ASTVisitorConsumer The implementation is an empty stub. @param D The declaration - */ + */ void HandleVTable(clang::CXXRecordDecl*) override { } /** Handle an implicit import declaration. @@ -245,7 +245,7 @@ class ASTVisitorConsumer The implementation is an empty stub. @param D The declaration - */ + */ void HandleImplicitImportDecl(clang::ImportDecl*) override { } /** Handle a top-level declaration in an Objective-C container. @@ -256,7 +256,7 @@ class ASTVisitorConsumer The implementation is an empty stub. @param D The declaration - */ + */ void HandleTopLevelDeclInObjCContainer(clang::DeclGroupRef) override { } }; diff --git a/src/lib/AST/ClangHelpers.hpp b/src/lib/AST/ClangHelpers.hpp index 1b8554ac79..e9a0ff2a5a 100644 --- a/src/lib/AST/ClangHelpers.hpp +++ b/src/lib/AST/ClangHelpers.hpp @@ -43,7 +43,7 @@ namespace mrdocs { @param DeclInfo The template comparison information for the new declaration. @param ConstrExpr The constraint expression to be substituted. @return The substituted constraint expression, or nullptr if an error occurs. - */ +*/ clang::Expr const* SubstituteConstraintExpressionWithoutSatisfaction( clang::Sema &S, @@ -65,7 +65,7 @@ SubstituteConstraintExpressionWithoutSatisfaction( When there's no direct correspondence, this trait returns the base Info type. - */ +*/ template struct InfoTypeFor {}; @@ -203,7 +203,7 @@ template using InfoTypeFor_t = typename InfoTypeFor::type; /** Convert a Clang AccessSpecifier into a MrDocs AccessKind - */ +*/ inline AccessKind toAccessKind(clang::AccessSpecifier const spec) @@ -220,7 +220,7 @@ toAccessKind(clang::AccessSpecifier const spec) } /** Convert a Clang StorageClass into a MrDocs StorageClassKind - */ +*/ inline StorageClassKind toStorageClassKind(clang::StorageClass const spec) @@ -240,7 +240,7 @@ toStorageClassKind(clang::StorageClass const spec) } /** Convert a Clang ConstexprSpecKind into a MrDocs ConstexprKind - */ +*/ inline ConstexprKind toConstexprKind(clang::ConstexprSpecKind const spec) @@ -261,7 +261,7 @@ toConstexprKind(clang::ConstexprSpecKind const spec) } /** Convert a Clang ExplicitSpecKind into a MrDocs ExplicitKind - */ +*/ inline ExplicitKind toExplicitKind(clang::ExplicitSpecifier const& spec) @@ -283,7 +283,7 @@ toExplicitKind(clang::ExplicitSpecifier const& spec) } /** Convert a Clang ExceptionSpecificationType into a MrDocs NoexceptKind - */ +*/ inline NoexceptKind toNoexceptKind(clang::ExceptionSpecificationType const spec) @@ -315,7 +315,7 @@ toNoexceptKind(clang::ExceptionSpecificationType const spec) } /** Convert a Clang clang::OverloadedOperatorKind into a MrDocs OperatorKind - */ +*/ inline OperatorKind toOperatorKind(clang::OverloadedOperatorKind const kind) @@ -420,7 +420,7 @@ toOperatorKind(clang::OverloadedOperatorKind const kind) } /** Convert a Clang ReferenceKind into a MrDocs ReferenceKind - */ +*/ inline ReferenceKind toReferenceKind(clang::RefQualifierKind const kind) @@ -439,7 +439,7 @@ toReferenceKind(clang::RefQualifierKind const kind) } /** Convert a Clang clang::TagTypeKind into a MrDocs RecordKeyKind - */ +*/ inline RecordKeyKind toRecordKeyKind(clang::TagTypeKind const kind) @@ -456,7 +456,7 @@ toRecordKeyKind(clang::TagTypeKind const kind) } /** Convert a Clang unsigned qualifier kind into a MrDocs QualifierKind - */ +*/ inline QualifierKind toQualifierKind(unsigned const quals) @@ -475,7 +475,7 @@ toQualifierKind(unsigned const quals) } /** Convert a Clang Decl::Kind into a MrDocs FunctionClass - */ +*/ inline FunctionClass toFunctionClass(clang::Decl::Kind const kind) @@ -493,7 +493,7 @@ toFunctionClass(clang::Decl::Kind const kind) } /** Convert a Clang clang::AutoTypeKeyword into a MrDocs AutoKind - */ +*/ inline AutoKind toAutoKind(clang::AutoTypeKeyword const kind) @@ -511,7 +511,7 @@ toAutoKind(clang::AutoTypeKeyword const kind) } /** Convert a Clang clang::clang::BuiltinType into a MrDocs AutoKind - */ +*/ inline Optional toFundamentalTypeKind(clang::BuiltinType::Kind const kind) @@ -570,7 +570,7 @@ toFundamentalTypeKind(clang::BuiltinType::Kind const kind) // ---------------------------------------------------------------- /** Visit a Decl and call the appropriate visitor function. - */ +*/ template< typename DeclTy, typename Visitor, @@ -618,7 +618,7 @@ DeclToKindImpl() = delete; #include /** Get the clang::Decl::Kind for a type DeclTy derived from Decl. - */ +*/ template consteval clang::Decl::Kind @@ -631,7 +631,7 @@ DeclToKind() // ---------------------------------------------------------------- /** Visit a Type and call the appropriate visitor function. - */ +*/ template< typename TypeTy, typename Visitor, @@ -689,7 +689,7 @@ TypeToKind() // ---------------------------------------------------------------- /** Visit a TypeLoc and call the appropriate visitor function. - */ +*/ template< typename TypeLocTy, typename Visitor, @@ -736,7 +736,7 @@ TypeLocToKindImpl() = delete; #include /** Get the clang::TypeLoc::TypeLocClass for a type TypeLocTy derived from TypeLoc. - */ +*/ template consteval clang::TypeLoc::TypeLocClass @@ -818,7 +818,7 @@ getInstantiatedFrom(DeclTy const* D) Given a `Decl`, this function will analyze the parent context and return the access specifier for the declaration. - */ +*/ MRDOCS_DECL clang::AccessSpecifier getAccess(clang::Decl const* D); @@ -846,7 +846,7 @@ getDeclaratorType(clang::DeclaratorDecl const* DD); the function will return the clang::NonTypeTemplateParmDecl corresponding to `x`, which is the template parameter of the function `f`. - */ +*/ MRDOCS_DECL clang::NonTypeTemplateParmDecl const* getNTTPFromExpr(clang::Expr const* E, unsigned Depth); @@ -1086,7 +1086,7 @@ namespace detail { /** Determine whether the driver mode is ClangCL. @param cc The compilation command to insepct. - */ +*/ bool isClangCL(clang::tooling::CompileCommand const& cc); diff --git a/src/lib/AST/InstantiatedFromVisitor.hpp b/src/lib/AST/InstantiatedFromVisitor.hpp index 2a7d9651a2..17e0e82386 100644 --- a/src/lib/AST/InstantiatedFromVisitor.hpp +++ b/src/lib/AST/InstantiatedFromVisitor.hpp @@ -22,7 +22,7 @@ namespace mrdocs { This class provides methods to visit various template declarations and retrieve the original declarations from which they were instantiated. - */ +*/ class InstantiatedFromVisitor : public clang::ConstDeclVisitor { diff --git a/src/lib/AST/MrDocsFileSystem.hpp b/src/lib/AST/MrDocsFileSystem.hpp index 5aa2a5535f..7e1323a4fb 100644 --- a/src/lib/AST/MrDocsFileSystem.hpp +++ b/src/lib/AST/MrDocsFileSystem.hpp @@ -149,7 +149,8 @@ class MrDocsFileSystem : public llvm::vfs::FileSystem { if (!Mem->exists(Path)) { auto Buf = llvm::MemoryBuffer::getMemBufferCopy(Contents, Path); - Mem->addFile(Path, /*ModTime*/ 0, std::move(Buf)); + Mem->addFile(Path, /*ModTime + */ 0, std::move(Buf)); } } diff --git a/src/lib/AST/TerminalTypeVisitor.hpp b/src/lib/AST/TerminalTypeVisitor.hpp index aad5faad71..2ea358e40e 100644 --- a/src/lib/AST/TerminalTypeVisitor.hpp +++ b/src/lib/AST/TerminalTypeVisitor.hpp @@ -68,7 +68,7 @@ namespace mrdocs { we reach a terminal type, such as `VisitPointerType`. @tparam Derived The derived class type. - */ +*/ template class TerminalTypeVisitor : public clang::TypeVisitor, bool> @@ -96,7 +96,7 @@ class TerminalTypeVisitor @param Visitor The ASTVisitor instance. @param NNS The optional NestedNameSpecifier. - */ + */ explicit TerminalTypeVisitor( ASTVisitor& Visitor) @@ -108,7 +108,7 @@ class TerminalTypeVisitor This function casts the given Type to the derived class type and calls the corresponding `VisitXXXType` function. - */ + */ using TerminalTypeVisitor::TypeVisitor::Visit; /** Visit a Qualified Type. @@ -120,7 +120,7 @@ class TerminalTypeVisitor Example: - Wrapped type: `const int` - Unwrapped type: `int` - */ + */ bool Visit(clang::QualType const QT) { @@ -136,7 +136,7 @@ class TerminalTypeVisitor This function returns a reference to the ASTVisitor instance. @return A reference to the ASTVisitor instance. - */ + */ ASTVisitor& getASTVisitor() const { @@ -147,7 +147,7 @@ class TerminalTypeVisitor This function is an empty placeholder for `buildPointer` when not defined by the `Derived` visitor. - */ + */ static void buildPointer @@ -160,7 +160,7 @@ class TerminalTypeVisitor This function is an empty placeholder for `buildLValueReference` when not defined by the `Derived` visitor. - */ + */ void buildLValueReference( clang::LValueReferenceType const*) @@ -171,7 +171,7 @@ class TerminalTypeVisitor This function is an empty placeholder for `buildRValueReference` when not defined by the `Derived` visitor. - */ + */ void buildRValueReference( clang::RValueReferenceType const*) @@ -182,7 +182,7 @@ class TerminalTypeVisitor This function is an empty placeholder for `buildMemberPointer` when not defined by the `Derived` visitor. - */ + */ void buildMemberPointer( clang::MemberPointerType const*, unsigned) @@ -193,7 +193,7 @@ class TerminalTypeVisitor This function is an empty placeholder for `buildArray` when not defined by the `Derived` visitor. - */ + */ void buildArray( clang::ArrayType const*) @@ -210,7 +210,7 @@ class TerminalTypeVisitor This function is an empty placeholder for `buildDecltype` when not defined by the `Derived` visitor. - */ + */ void buildDecltype( clang::DecltypeType const*, @@ -223,7 +223,7 @@ class TerminalTypeVisitor This function is an empty placeholder for `buildAuto` when not defined by the `Derived` visitor. - */ + */ void buildAuto( clang::AutoType const*, @@ -236,7 +236,7 @@ class TerminalTypeVisitor This function is an empty placeholder for `buildTerminal` when not defined by the `Derived` visitor. - */ + */ void buildTerminal( clang::NestedNameSpecifier, @@ -250,7 +250,7 @@ class TerminalTypeVisitor This function is an empty placeholder for `buildTerminal` when not defined by the `Derived` visitor. - */ + */ void buildTerminal( clang::NestedNameSpecifier, @@ -265,7 +265,7 @@ class TerminalTypeVisitor This function is an empty placeholder for `buildTerminal` when not defined by the `Derived` visitor. - */ + */ void buildTerminal( clang::NestedNameSpecifier, @@ -283,7 +283,7 @@ class TerminalTypeVisitor This function casts the current instance to the derived class type. @return A reference to the derived class instance. - */ + */ Derived& getDerived() { @@ -297,7 +297,7 @@ class TerminalTypeVisitor Example: - Wrapped type: `(int)` - Unwrapped type: `int` - */ + */ bool VisitParenType(clang::ParenType const* T) { @@ -312,7 +312,7 @@ class TerminalTypeVisitor Example: - Wrapped type: `MACRO_QUALIFIED(int)` - Unwrapped type: `int` - */ + */ bool VisitMacroQualified( clang::MacroQualifiedType const* T) @@ -328,7 +328,7 @@ class TerminalTypeVisitor Example: - Wrapped type: `[[attribute]] int` - Unwrapped type: `int` - */ + */ bool VisitAttributedType( clang::AttributedType const* T) @@ -344,7 +344,7 @@ class TerminalTypeVisitor Example: - Wrapped type: adjusted/decayed `int*` - Unwrapped type: original `int[4]` - */ + */ bool VisitAdjustedType(clang::AdjustedType const* T) { @@ -359,7 +359,7 @@ class TerminalTypeVisitor Example: - Wrapped type: `using TypeAlias = int` - Unwrapped type: `int` - */ + */ bool VisitUsingType(clang::UsingType const* T) { @@ -374,7 +374,7 @@ class TerminalTypeVisitor Example: - Wrapped type: `T` - Unwrapped type: `int` (if `T` is substituted with `int`) - */ + */ bool VisitSubstTemplateTypeParmType( clang::SubstTemplateTypeParmType const* T) @@ -392,7 +392,7 @@ class TerminalTypeVisitor Example: - Wrapped type: `int...` - Unwrapped type: `int` - */ + */ bool VisitPackExpansionType( clang::PackExpansionType const* T) @@ -411,7 +411,7 @@ class TerminalTypeVisitor Example: - Wrapped type: `int*` - Unwrapped type: `int` - */ + */ bool VisitPointerType( clang::PointerType const* T) @@ -428,7 +428,7 @@ class TerminalTypeVisitor Example: - Wrapped type: `int&` - Unwrapped type: `int` - */ + */ bool VisitLValueReferenceType( clang::LValueReferenceType const* T) @@ -446,7 +446,7 @@ class TerminalTypeVisitor Example: - Wrapped type: `int&&` - Unwrapped type: `int` - */ + */ bool VisitRValueReferenceType( clang::RValueReferenceType const* T) @@ -464,7 +464,7 @@ class TerminalTypeVisitor Example: - Wrapped type: `int Class::*` - Unwrapped type: `int` - */ + */ bool VisitMemberPointerType( clang::MemberPointerType const* T) @@ -490,7 +490,7 @@ class TerminalTypeVisitor Example: - Wrapped type: `int[10]` - Unwrapped type: `int` - */ + */ bool VisitArrayType( clang::ArrayType const* T) diff --git a/src/lib/AST/TypeBuilder.hpp b/src/lib/AST/TypeBuilder.hpp index e868e0987f..33ffdd7625 100644 --- a/src/lib/AST/TypeBuilder.hpp +++ b/src/lib/AST/TypeBuilder.hpp @@ -30,7 +30,7 @@ namespace mrdocs { Builder.Visit(qt); std::unique_ptr typeInfo = Builder.result(); @endcode - */ +*/ class TypeBuilder : public TerminalTypeVisitor { @@ -72,7 +72,7 @@ class TypeBuilder as a unique pointer to the `Type` object. @return A unique pointer to the `Type` object. - */ + */ Polymorphic result() { @@ -86,7 +86,7 @@ class TypeBuilder @param T The pointer type to build. @param quals The qualifiers for the pointer type. - */ + */ void buildPointer(clang::PointerType const* T, unsigned quals); /** Build type information for a lvalue reference type. @@ -95,7 +95,7 @@ class TypeBuilder the pointee type. @param T The lvalue reference type to build. - */ + */ void buildLValueReference(clang::LValueReferenceType const* T); /** Build type information for an rvalue reference type. @@ -104,7 +104,7 @@ class TypeBuilder the pointee type. @param T The rvalue reference type to build. - */ + */ void buildRValueReference(clang::RValueReferenceType const* T); /** Build type information for a member pointer type. @@ -117,7 +117,7 @@ class TypeBuilder @param T The member pointer type to build. @param quals The qualifiers for the member pointer type. - */ + */ void buildMemberPointer(clang::MemberPointerType const* T, unsigned quals); /** Build type information for an array type. @@ -130,7 +130,7 @@ class TypeBuilder and the expression defining the array bounds. @param T The array type to build. - */ + */ void buildArray(clang::ArrayType const* T); /** Populate type information for a function type. @@ -142,7 +142,7 @@ class TypeBuilder It includes the return type and the parameter types. @param T The function type to populate. - */ + */ void populate(clang::FunctionType const* T); /** Build type information for a decltype type. @@ -156,7 +156,7 @@ class TypeBuilder @param T The decltype type to build. @param quals The qualifiers for the decltype type. @param pack Whether the decltype type is a pack. - */ + */ void buildDecltype(clang::DecltypeType const* T, unsigned quals, bool pack); /** Build type information for an auto type. @@ -171,7 +171,7 @@ class TypeBuilder @param T The auto type to build. @param quals The qualifiers for the auto type. @param pack Whether the auto type is a pack. - */ + */ void buildAuto(clang::AutoType const* T, unsigned quals, bool pack); /** Build type information for a terminal type. @@ -187,7 +187,7 @@ class TypeBuilder @param T The terminal type to build. @param quals The qualifiers for the terminal type. @param pack Whether the terminal type is a pack. - */ + */ void buildTerminal( clang::Type const* T, unsigned quals, @@ -207,7 +207,7 @@ class TypeBuilder @param TArgs The template arguments. @param quals The qualifiers for the terminal type. @param pack Whether the terminal type is a pack. - */ + */ void buildTerminal( clang::NestedNameSpecifier NNS, clang::IdentifierInfo const* II, @@ -229,7 +229,7 @@ class TypeBuilder @param TArgs The template arguments. @param quals The qualifiers for the terminal type. @param pack Whether the terminal type is a pack. - */ + */ void buildTerminal( clang::NestedNameSpecifier NNS, clang::NamedDecl* D, diff --git a/src/lib/ConfigImpl.hpp b/src/lib/ConfigImpl.hpp index 05d8d0b6ed..146c1e4022 100644 --- a/src/lib/ConfigImpl.hpp +++ b/src/lib/ConfigImpl.hpp @@ -74,7 +74,7 @@ class ConfigImpl settings are loaded or modified to update the DOM object representing the configuration keys. - */ + */ void updateConfigDom(); diff --git a/src/lib/CorpusImpl.hpp b/src/lib/CorpusImpl.hpp index 571fb8fb37..f779d62699 100644 --- a/src/lib/CorpusImpl.hpp +++ b/src/lib/CorpusImpl.hpp @@ -96,7 +96,7 @@ class CorpusImpl final : public Corpus find(SymbolID const& id) const noexcept override; /** Return a range of Info objects for the specified Symbol IDs. - */ + */ template R> auto find(R&& range) @@ -120,7 +120,7 @@ class CorpusImpl final : public Corpus } /** Return a range of constant Info objects for the specified Symbol IDs. - */ + */ template R> auto find(R&& range) const diff --git a/src/lib/Gen/adoc/AdocEscape.hpp b/src/lib/Gen/adoc/AdocEscape.hpp index f01cfbdd8b..ef98bb133b 100644 --- a/src/lib/Gen/adoc/AdocEscape.hpp +++ b/src/lib/Gen/adoc/AdocEscape.hpp @@ -20,7 +20,7 @@ namespace mrdocs::adoc { /** Escape a string for use in AsciiDoc - */ +*/ MRDOCS_DECL void AdocEscape(OutputRef& os, std::string_view str); diff --git a/src/lib/Gen/hbs/Builder.hpp b/src/lib/Gen/hbs/Builder.hpp index 3f64e6f8ad..b1866aabdc 100644 --- a/src/lib/Gen/hbs/Builder.hpp +++ b/src/lib/Gen/hbs/Builder.hpp @@ -56,7 +56,7 @@ class Builder If the output is multi-page and not embedded, this function renders the wrapper template with the index template as the contents. - */ + */ template T> Expected operator()(std::ostream& os, T const&); @@ -71,7 +71,7 @@ class Builder will be executed to render the contents of the page. - */ + */ Expected renderWrapped( std::ostream& os, @@ -79,27 +79,27 @@ class Builder private: /** The directory with the all templates. - */ + */ std::string templatesDir() const; /** A subdirectory of the templates dir - */ + */ std::string templatesDir(std::string_view subdir) const; /** The directory with the common templates. - */ + */ std::string commonTemplatesDir() const; /** A subdirectory of the common templates dir - */ + */ std::string commonTemplatesDir(std::string_view subdir) const; /** The directory with the layout templates. - */ + */ std::string layoutDir() const; @@ -110,12 +110,12 @@ class Builder It also includes a sectionref helper that describes the section where the symbol is located. - */ + */ dom::Object createContext(Symbol const& I); /** Render a Handlebars template from the templates directory. - */ + */ Expected callTemplate( std::ostream& os, diff --git a/src/lib/Gen/hbs/HandlebarsCorpus.hpp b/src/lib/Gen/hbs/HandlebarsCorpus.hpp index 4d11b5091a..cd0d77066d 100644 --- a/src/lib/Gen/hbs/HandlebarsCorpus.hpp +++ b/src/lib/Gen/hbs/HandlebarsCorpus.hpp @@ -30,10 +30,12 @@ namespace mrdocs::hbs { class HandlebarsCorpus final : public DomCorpus { public: - /** Legible names for the Handlebars corpus. */ + /** Legible names for the Handlebars corpus. + */ LegibleNames names_; - /** File extension for the markup files. */ + /** File extension for the markup files. + */ std::string fileExtension; /** Constructor. diff --git a/src/lib/Gen/hbs/HandlebarsGenerator.hpp b/src/lib/Gen/hbs/HandlebarsGenerator.hpp index f077f400ac..c2cd030892 100644 --- a/src/lib/Gen/hbs/HandlebarsGenerator.hpp +++ b/src/lib/Gen/hbs/HandlebarsGenerator.hpp @@ -39,14 +39,14 @@ class HandlebarsGenerator Corpus const& corpus) const override; /** Build a tagfile for the corpus. - */ + */ Expected buildTagfile( std::ostream& os, Corpus const& corpus) const; /** Build a tagfile for the corpus and store the result in a file. - */ + */ Expected buildTagfile( std::string_view fileName, diff --git a/src/lib/Gen/hbs/TagfileWriter.hpp b/src/lib/Gen/hbs/TagfileWriter.hpp index 43b82ddc1e..2ac8d054e4 100644 --- a/src/lib/Gen/hbs/TagfileWriter.hpp +++ b/src/lib/Gen/hbs/TagfileWriter.hpp @@ -59,7 +59,7 @@ class TagfileWriter is provided. Typically, the relative path to a single page output file. This parameter is ignored in multipage mode. @return An Expected object containing the TagfileWriter instance or an error. - */ + */ static Expected create( @@ -79,7 +79,7 @@ class TagfileWriter @param corpus The HandlebarsCorpus to use for the writer. @param os The output stream to write the tagfile to. @return An Expected object containing the TagfileWriter instance or an error. - */ + */ static Expected create( @@ -94,7 +94,7 @@ class TagfileWriter This function builds the tagfile by initializing the output, traversing the global namespace of the corpus, and finalizing the output. - */ + */ void build(); diff --git a/src/lib/Gen/hbs/VisitorHelpers.hpp b/src/lib/Gen/hbs/VisitorHelpers.hpp index 48ba983b02..5597ff956a 100644 --- a/src/lib/Gen/hbs/VisitorHelpers.hpp +++ b/src/lib/Gen/hbs/VisitorHelpers.hpp @@ -21,7 +21,7 @@ namespace mrdocs::hbs { This filters Info types for which the generator should not generate independent pages or sections. - */ +*/ MRDOCS_DECL bool shouldGenerate(Symbol const& I, Config const& config); @@ -39,7 +39,7 @@ shouldGenerate(Symbol const& I, Config const& config); template. For record and enum members, we look for the parent record or enum. For other Info types, we return nullptr. - */ +*/ MRDOCS_DECL Symbol const* findAlternativeURLInfo(Corpus const& c, Symbol const& I); diff --git a/src/lib/Metadata/Finalizers/DocComment/Function.hpp b/src/lib/Metadata/Finalizers/DocComment/Function.hpp index dd01684724..17e60423aa 100644 --- a/src/lib/Metadata/Finalizers/DocComment/Function.hpp +++ b/src/lib/Metadata/Finalizers/DocComment/Function.hpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include namespace mrdocs { @@ -499,17 +501,19 @@ populateFunctionReturns(FunctionSymbol& I, CorpusImpl const& corpus) a list of parameters separated by commas. This function returns a list of all parameter names in the doc. */ -llvm::SmallVector +llvm::SmallVector getDocCommentParamNames(DocComment const& doc) { - llvm::SmallVector result; + llvm::SmallVector result; for (auto const& docParam: doc.params) { auto const& paramNamesStr = docParam.name; for (auto paramNames = std::views::split(paramNamesStr, ','); auto const& paramName: paramNames) { - result.push_back(trim(std::string_view(paramName.begin(), paramName.end()))); + auto const trimmed = + trim(std::string_view(paramName.begin(), paramName.end())); + result.emplace_back(trimmed); } } return result; @@ -772,7 +776,7 @@ populateFunctionParam( FunctionSymbol& I, Param& param, std::size_t const index, - llvm::SmallVector& documentedParams, + llvm::SmallVector& documentedParams, CorpusImpl const& corpus) { if (!param.Name) diff --git a/src/lib/Metadata/Finalizers/DocComment/parseInlines.hpp b/src/lib/Metadata/Finalizers/DocComment/parseInlines.hpp index 36b76f165b..1904081311 100644 --- a/src/lib/Metadata/Finalizers/DocComment/parseInlines.hpp +++ b/src/lib/Metadata/Finalizers/DocComment/parseInlines.hpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include namespace mrdocs::doc { @@ -306,11 +308,22 @@ emit_text(doc::InlineContainer& out, std::string&& text) out.emplace_back(std::move(text)); } +// Emit without attempting to merge with a previous text node. +inline +void +emit_text_unmerged(doc::InlineContainer& out, std::string&& text) +{ + if (!text.empty()) + { + out.emplace_back(std::move(text)); + } +} + // Start a new inline container of kind k, appending it to out. // Returns a reference to the new container for appending children. inline doc::InlineContainer& -start_container(doc::InlineContainer& out, doc::InlineKind k) +start_container(doc::InlineContainer& out, doc::InlineKind k, std::size_t reserve_hint) { // Create k and return its child container. switch (k) @@ -341,6 +354,10 @@ start_container(doc::InlineContainer& out, doc::InlineKind k) } auto* ic = dynamic_cast(&*out.back()); MRDOCS_ASSERT(ic != nullptr); // container types must derive InlineContainer + if (reserve_hint) + { + ic->children.reserve(reserve_hint); + } return *ic; } @@ -368,6 +385,7 @@ start_link(doc::InlineContainer& out, std::string&& href) { link.href = std::move(href); auto* ic = dynamic_cast(&*out.back()); MRDOCS_ASSERT(ic != nullptr); + ic->children.reserve(href.size() + 8); return *ic; } @@ -381,6 +399,7 @@ emit_image(doc::InlineContainer& out, std::string&& src, std::string&& alt) img.alt = std::move(alt); auto* ic = dynamic_cast(&*out.back()); MRDOCS_ASSERT(ic != nullptr); + ic->children.reserve(8); return *ic; } @@ -427,7 +446,7 @@ struct Frame { // where the finished node will be inserted doc::InlineContainer* parent; // children collected while open - doc::InlineContainer scratch; + doc::InlineContainer* scratch; // literal open token (for fallback) std::string open_tok; }; @@ -438,9 +457,38 @@ struct Bracket { // where link/image will be emitted doc::InlineContainer* parent = nullptr; // label/alt children - doc::InlineContainer label; + doc::InlineContainer* label; }; +inline +bool +frame_has_ancestor( + Frame const& f, + doc::InlineContainer const* target, + std::vector const& frames) +{ + doc::InlineContainer const* ancestor = f.parent; + while (ancestor) + { + if (ancestor == target) + { + return true; + } + auto it = std::find_if( + frames.begin(), + frames.end(), + [ancestor](Frame const& candidate) { + return candidate.scratch == ancestor; + }); + if (it == frames.end()) + { + return false; + } + ancestor = it->parent; + } + return false; +} + // HTML parsing helpers --------------------------------------------------------- inline @@ -587,9 +635,15 @@ html_get_attr(std::string const& attrs, std::string_view key) } // Minimal state holder to replace lots of lambdas in parse() +inline constexpr std::size_t kMaxReserve = 1'000'000; + struct ParserState { // input std::string_view s; + // hint to reserve child storage + std::size_t reserve_hint = 0; + // arena to keep temporary containers alive for the full parse + std::vector> arena; // stack of open frames std::vector frames; // stack of open [label] or ![alt] @@ -601,6 +655,13 @@ struct ParserState { // whether the next char is escaped bool escape_next{ false }; + doc::InlineContainer* + make_container() + { + arena.push_back(std::make_unique()); + return arena.back().get(); + } + void flush_text() { @@ -621,8 +682,24 @@ struct ParserState { push_frame(TagRule const* r) { flush_text(); - frames.push_back(Frame{ r->kind, r, cur, {}, std::string(r->open) }); - cur = &frames.back().scratch; + if (reserve_hint) + { + // Keep the parent stable while this frame is open. + auto const desired = std::min( + cur->children.size() + reserve_hint, + kMaxReserve); + cur->children.reserve(desired); + } + auto* scratch = make_container(); + frames.push_back(Frame{ + r->kind, + r, + cur, + scratch, + std::string(r->open) + }); + scratch->children.reserve(reserve_hint); + cur = scratch; } // Emit the opening token + flattened contents as literal text into its @@ -630,12 +707,26 @@ struct ParserState { void fallback_unclosed(Frame& f) { + MRDOCS_ASSERT(f.scratch); std::string literal(f.open_tok); - for (auto& el: f.scratch) + for (auto& el: *f.scratch) { getAsPlainText(*el, literal); } - emit_text(*f.parent, std::move(literal)); + try + { + emit_text_unmerged(*f.parent, std::move(literal)); + } + catch (std::length_error const&) + { + // Drop the fallback text if it would overflow the container; + // better to keep processing than terminate the doc build. + } + catch (std::bad_alloc const&) + { + // Drop the fallback text if it would overflow the container; + // better to keep processing than terminate the doc build. + } } // Materialize a finished frame to its parent @@ -643,6 +734,7 @@ struct ParserState { void materialize_and_pop(Frame f) { + MRDOCS_ASSERT(f.scratch); // Line breaks are leaf inlines if (f.kind == doc::InlineKind::LineBreak) { @@ -662,7 +754,7 @@ struct ParserState { { // We recorded its body into f.scratch (as Text children) while inside the barrier. // Flatten to a single string and emit a MathInline leaf. - std::string lit = flatten_text(f.scratch); + std::string lit = flatten_text(*f.scratch); f.parent->emplace_back(); f.parent->back()->asMath().literal = std::move(lit); cur = f.parent; @@ -674,14 +766,14 @@ struct ParserState { && has(f.rule->flags, RuleFlags::Html)) { doc::InlineContainer& outC = start_link(*f.parent, std::move(f.open_tok)); - move_children(outC, f.scratch); + move_children(outC, *f.scratch); cur = f.parent; return; } // All remaining supported formatting kinds are containers - doc::InlineContainer* outC = &start_container(*f.parent, f.kind); - move_children(*outC, f.scratch); + doc::InlineContainer* outC = &start_container(*f.parent, f.kind, reserve_hint); + move_children(*outC, *f.scratch); cur = f.parent; } @@ -742,6 +834,7 @@ struct ParserState { Bracket b = std::move(brackets.back()); brackets.pop_back(); + MRDOCS_ASSERT(b.label); // After ']', expect optional spaces then '(' dest [title] ')' std::size_t j = i + 1; @@ -750,9 +843,9 @@ struct ParserState { { // Not a link/image — emit literal "[...]" back to parent push_text_node(*b.parent, b.is_image ? "![" : "["); - if (!b.label.empty()) + if (!b.label->empty()) { - move_children(*b.parent, b.label); + move_children(*b.parent, *b.label); } push_text_node(*b.parent, "]"); cur = b.parent; @@ -809,9 +902,9 @@ struct ParserState { { // Invalid link — degrade to literal push_text_node(*b.parent, b.is_image ? "![" : "["); - if (!b.label.empty()) + if (!b.label->empty()) { - move_children(*b.parent, b.label); + move_children(*b.parent, *b.label); } push_text_node(*b.parent, "]"); cur = b.parent; @@ -822,12 +915,12 @@ struct ParserState { // Materialize if (b.is_image) { - emit_image(*b.parent, std::move(dest), flatten_text(b.label)); + emit_image(*b.parent, std::move(dest), flatten_text(*b.label)); } else { doc::InlineContainer& linkC = start_link(*b.parent, std::move(dest)); - move_children(linkC, b.label); + move_children(linkC, *b.label); } cur = b.parent; return j - i; @@ -876,9 +969,12 @@ ParseResult parse(char const* first, char const* last, doc::InlineContainer& out_root) { std::string_view s(first, static_cast(last - first)); + std::size_t const hint = std::min(s.size() + 8, kMaxReserve); ParserState st{ .s = s, + .reserve_hint = hint, + .arena = {}, .frames = {}, .brackets = {}, .cur = &out_root, @@ -888,6 +984,7 @@ parse(char const* first, char const* last, doc::InlineContainer& out_root) st.frames.reserve(8); st.brackets.reserve(4); st.text.reserve(64); + out_root.children.reserve(st.reserve_hint); for (std::size_t i = 0; i < s.size();) { // If inside a barrier (e.g. backticks), only look for its own closer @@ -919,15 +1016,23 @@ parse(char const* first, char const* last, doc::InlineContainer& out_root) // Markdown link/image openers if (c == '!' && i + 1 < s.size() && s[i + 1] == '[') { st.flush_text(); - st.brackets.push_back(Bracket{ true, st.cur, {} }); - st.cur = &st.brackets.back().label; + st.brackets.push_back(Bracket{ + true, + st.cur, + st.make_container() + }); + st.cur = st.brackets.back().label; i += 2; continue; } if (c == '[') { st.flush_text(); - st.brackets.push_back(Bracket{ false, st.cur, {} }); - st.cur = &st.brackets.back().label; + st.brackets.push_back(Bracket{ + false, + st.cur, + st.make_container() + }); + st.cur = st.brackets.back().label; ++i; continue; } @@ -971,8 +1076,15 @@ parse(char const* first, char const* last, doc::InlineContainer& out_root) } else { auto href = html_get_attr(tag->attrs, "href").value_or(std::string{}); st.flush_text(); - st.frames.push_back(Frame{ doc::InlineKind::Link, &kHtmlRule, st.cur, {}, std::string{} }); - st.cur = &st.frames.back().scratch; + auto* scratch = st.make_container(); + st.frames.push_back(Frame{ + doc::InlineKind::Link, + &kHtmlRule, + st.cur, + scratch, + std::string{} + }); + st.cur = scratch; st.frames.back().open_tok = std::move(href); // own the href bytes } i = tag->end; @@ -988,8 +1100,15 @@ parse(char const* first, char const* last, doc::InlineContainer& out_root) } } else { st.flush_text(); - st.frames.push_back(Frame{ *kind, &kHtmlRule, st.cur, {}, "" }); - st.cur = &st.frames.back().scratch; + auto* scratch = st.make_container(); + st.frames.push_back(Frame{ + *kind, + &kHtmlRule, + st.cur, + scratch, + "" + }); + st.cur = scratch; } i = tag->end; continue; @@ -1032,9 +1151,29 @@ parse(char const* first, char const* last, doc::InlineContainer& out_root) while (!st.brackets.empty()) { Bracket b = std::move(st.brackets.back()); st.brackets.pop_back(); + MRDOCS_ASSERT(b.label); + + // Frames opened inside the dangling label still hold pointers into the + // label container; unwind them before we destroy the label to avoid + // writing to freed storage. Frames tied to this label form a suffix on + // the stack because we switched `cur` to the label when it opened. + auto const* label_ptr = static_cast(b.label); + while (!st.frames.empty() && frame_has_ancestor(st.frames.back(), label_ptr, st.frames)) { + Frame f = std::move(st.frames.back()); + st.frames.pop_back(); + if (f.rule && has(f.rule->flags, RuleFlags::Html)) + { + st.materialize_and_pop(std::move(f)); + } + else + { + st.fallback_unclosed(f); + st.cur = f.parent; + } + } ParserState::push_text_node(*b.parent, b.is_image ? "![" : "["); - if (!b.label.empty()) - move_children(*b.parent, b.label); + if (!b.label->empty()) + move_children(*b.parent, *b.label); ParserState::push_text_node(*b.parent, "]"); st.cur = b.parent; } diff --git a/src/lib/Metadata/Finalizers/DocCommentFinalizer.cpp b/src/lib/Metadata/Finalizers/DocCommentFinalizer.cpp index 68d7414102..cbeaeed93f 100644 --- a/src/lib/Metadata/Finalizers/DocCommentFinalizer.cpp +++ b/src/lib/Metadata/Finalizers/DocCommentFinalizer.cpp @@ -989,6 +989,7 @@ setAutoRelates(Symbol& ctx) auto toRecordOrEnum = [&](Polymorphic const& type) -> Symbol* { MRDOCS_CHECK_OR(type, nullptr); + MRDOCS_CHECK_OR(!type.valueless_after_move(), nullptr); auto& innermost = innermostType(type); MRDOCS_CHECK_OR(innermost, nullptr); MRDOCS_CHECK_OR(innermost->isNamed(), nullptr); @@ -1329,6 +1330,25 @@ parseInlines(DocComment& doc) bottomUpTraverse(doc, [] NodeTy>(NodeTy& node) { if constexpr (requires { { node.children } -> range_of>; }) { + // Reserve enough capacity up-front so child inserts during parsing + // cannot reallocate and invalidate InlineContainer pointers held + // by the parser state. + std::size_t extra = 0; + for (auto const& child : node.children) + { + if (child->isText()) + { + extra += child->asText().literal.size(); + } + } + if (extra > 0) + { + // Over-reserve generously to avoid any reallocation while the + // parser keeps pointers into these containers. + node.children.reserve( + node.children.size() + 2 * extra + 16); + } + auto it = node.children.begin(); while (it != node.children.end()) { @@ -1342,7 +1362,18 @@ parseInlines(DocComment& doc) auto& textEl = el->asText(); doc::InlineContainer v; - ParseResult r = parse(textEl.literal, v); + ParseResult r; + try + { + r = parse(textEl.literal, v); + } + catch (std::bad_alloc const&) + { + // Skip parsing this text node if it explodes memory; + // leave the raw text in place. + ++it; + continue; + } // advance on parse failure if (!r) @@ -1706,8 +1737,9 @@ DocCommentFinalizer::warnUndocumented() undocI.kind, {SymbolKind::Record, SymbolKind::Enum}); this->warn( *getPrimaryLocation(undocI.Loc, prefer_definition), - "{}: Symbol is undocumented", - undocI.name); + "{}: {} is undocumented", + undocI.name, + toString(undocI.kind)); } corpus_.undocumented_.clear(); } diff --git a/src/lib/Metadata/Finalizers/DocCommentFinalizer.hpp b/src/lib/Metadata/Finalizers/DocCommentFinalizer.hpp index a80d87c54c..f203487fe6 100644 --- a/src/lib/Metadata/Finalizers/DocCommentFinalizer.hpp +++ b/src/lib/Metadata/Finalizers/DocCommentFinalizer.hpp @@ -95,7 +95,7 @@ class DocCommentFinalizer { } /** Finalize the doc for all symbols - */ + */ void build(); diff --git a/src/lib/Metadata/Type.cpp b/src/lib/Metadata/Type.cpp index 6e8e48f0be..e746ed4c30 100644 --- a/src/lib/Metadata/Type.cpp +++ b/src/lib/Metadata/Type.cpp @@ -830,38 +830,30 @@ innerTypePtrImpl(TypeTy&& TI) noexcept return nullptr; } -// Get the innermost type -// If there's an internal type, return it -// If there's no internal type, return the current type +// Walk to the deepest nested type, preserving constness. template < - class PolymorphicTypeTy, - bool isMutable = !std::is_const_v>, + class PolyRef, + bool isMutable = !std::is_const_v>, class Ref = std::conditional_t&, Polymorphic const&>> -requires std::same_as, Polymorphic> +requires std::same_as, Polymorphic> Ref -innermostTypeImpl(PolymorphicTypeTy&& TI) noexcept +innermostTypeImpl(PolyRef&& TI) noexcept { - MRDOCS_ASSERT(!TI.valueless_after_move()); - Optional inner = innerTypeImpl(*TI); - if (!inner) - { - return TI; - } + auto* current = std::addressof(TI); + Optional inner = innerTypeImpl(**current); while (inner) { - Ref ref = *inner; - MRDOCS_ASSERT(!ref.valueless_after_move()); - if (ref->isNamed()) - { - return ref; - } - inner = innerTypeImpl(*ref); + current = std::addressof(*inner); + if (current->valueless_after_move()) + break; + if ((*current)->isNamed()) + break; + inner = innerTypeImpl(**current); } - Ref ref = *inner; - return ref; + return *current; } -} +} // namespace Optional const&> innerType(Type const& TI) noexcept diff --git a/src/lib/MrDocsCompilationDatabase.hpp b/src/lib/MrDocsCompilationDatabase.hpp index 8fd29414f4..786a9ccca5 100644 --- a/src/lib/MrDocsCompilationDatabase.hpp +++ b/src/lib/MrDocsCompilationDatabase.hpp @@ -53,7 +53,7 @@ class MrDocsCompilationDatabase * @param config The shared configuration object. * @param implicitIncludeDirectories A map from compiler executable paths to their respective * implicit include directories, as determined by the system's compiler. - */ + */ MrDocsCompilationDatabase( llvm::StringRef workingDir, CompilationDatabase const& inner, @@ -82,7 +82,8 @@ class MrDocsCompilationDatabase std::vector getAllCompileCommands() const override; - /** Whether the driver mode for the compilation database is ClangCL */ + /** Whether the driver mode for the compilation database is ClangCL + */ bool isClangCL() const noexcept { diff --git a/src/lib/SingleFileDB.hpp b/src/lib/SingleFileDB.hpp index 2146b7b8bb..6ce8ca469c 100644 --- a/src/lib/SingleFileDB.hpp +++ b/src/lib/SingleFileDB.hpp @@ -20,7 +20,7 @@ namespace mrdocs { /** Compilation database for a single file. - */ +*/ class SingleFileDB : public clang::tooling::CompilationDatabase { diff --git a/src/lib/Support/CMakeExecution.hpp b/src/lib/Support/CMakeExecution.hpp index 9d44394322..237475c93b 100644 --- a/src/lib/Support/CMakeExecution.hpp +++ b/src/lib/Support/CMakeExecution.hpp @@ -29,7 +29,7 @@ namespace mrdocs { * @param tempDir The path to the temporary directory to use for CMake execution. * @return An `Expected` object containing the path to the generated `compile_commands.json` file if successful. * Returns `Unexpected` if the project path is not found or if CMake execution fails. - */ +*/ Expected executeCmakeExportCompileCommands(llvm::StringRef projectPath, llvm::StringRef cmakeArgs, llvm::StringRef tempDir); diff --git a/src/lib/Support/Chrono.hpp b/src/lib/Support/Chrono.hpp index 1ec6a9a1c9..d04b32b65d 100644 --- a/src/lib/Support/Chrono.hpp +++ b/src/lib/Support/Chrono.hpp @@ -28,7 +28,7 @@ namespace mrdocs { @param delta The duration to format. @return A string representing the formatted duration. - */ +*/ template std::string format_duration( diff --git a/src/lib/Support/ExecuteAndWaitWithLogging.hpp b/src/lib/Support/ExecuteAndWaitWithLogging.hpp index 1e9ddd68d5..a39a3da102 100644 --- a/src/lib/Support/ExecuteAndWaitWithLogging.hpp +++ b/src/lib/Support/ExecuteAndWaitWithLogging.hpp @@ -24,7 +24,7 @@ namespace mrdocs { * * \par Preconditions * `args.size() >= 1`. - */ +*/ int ExecuteAndWaitWithLogging( llvm::StringRef program, llvm::ArrayRef args, diff --git a/src/lib/Support/ExecutionContext.hpp b/src/lib/Support/ExecutionContext.hpp index 11ef036a6e..e9a11ae4cd 100644 --- a/src/lib/Support/ExecutionContext.hpp +++ b/src/lib/Support/ExecutionContext.hpp @@ -117,7 +117,7 @@ class ExecutionContext It stores the `SymbolSet` and `Diagnostics` objects, and returns them when `results` is called. - */ +*/ class InfoExecutionContext : public ExecutionContext { diff --git a/src/lib/Support/LegibleNames.hpp b/src/lib/Support/LegibleNames.hpp index 1bd7babac4..2e04887c06 100644 --- a/src/lib/Support/LegibleNames.hpp +++ b/src/lib/Support/LegibleNames.hpp @@ -47,11 +47,11 @@ class LegibleNames bool enabled); /** Destructor. - */ + */ ~LegibleNames() noexcept; /** Return the legible name for a symbol name. - */ + */ std::string getUnqualified(SymbolID const& id) const; diff --git a/src/lib/Support/Path.hpp b/src/lib/Support/Path.hpp index 9781402c3d..9da73071d8 100644 --- a/src/lib/Support/Path.hpp +++ b/src/lib/Support/Path.hpp @@ -52,7 +52,7 @@ class ScopedTempFile If a file was created, it is deleted. - */ + */ ~ScopedTempFile(); /** Constructor @@ -77,7 +77,7 @@ class ScopedTempFile operator bool() const { return ok_; } /** Returns the path to the temporary file. - */ + */ llvm::StringRef path() const { return path_; } }; @@ -100,7 +100,7 @@ class ScopedTempDirectory If a directory was created, it is deleted. - */ + */ ~ScopedTempDirectory(); /** Constructor @@ -151,15 +151,15 @@ class ScopedTempDirectory } /** Returns the path to the temporary directory. - */ + */ std::string_view path() const { return static_cast(path_); } /** Returns the error status of the directory. - */ + */ Error error() const; /** Convert temp directory to a std::string_view - */ + */ operator std::string_view() const { return path(); } }; diff --git a/src/test/lib/MrDocsCompilationDatabase.cpp b/src/test/lib/MrDocsCompilationDatabase.cpp index 8bfad9b9a9..12670208ec 100644 --- a/src/test/lib/MrDocsCompilationDatabase.cpp +++ b/src/test/lib/MrDocsCompilationDatabase.cpp @@ -9,9 +9,9 @@ // Official repository: https://github.com/cppalliance/mrdocs // -#include "lib/MrDocsCompilationDatabase.hpp" -#include "lib/ConfigImpl.hpp" -#include "lib/SingleFileDB.hpp" +#include +#include +#include #include #include #include diff --git a/src/test_suite/diff.hpp b/src/test_suite/diff.hpp index 4af4e4c60d..78f288a492 100644 --- a/src/test_suite/diff.hpp +++ b/src/test_suite/diff.hpp @@ -15,7 +15,7 @@ namespace test_suite { /** Result of a diff between two strings - */ +*/ struct DiffStringsResult { /** The diff between the two strings @@ -24,7 +24,7 @@ struct DiffStringsResult * strings. * * New lines are prefixed with '+' and removed lines are prefixed with '-'. - */ + */ std::string diff; /// The number of lines added in the contents @@ -66,7 +66,7 @@ diffStrings( @param expected_contents_path The path to the expected contents file @param rendered_contents The rendered contents of the file @param error_output_path The path to the error output file - */ +*/ void BOOST_TEST_DIFF( std::string_view expected_contents, diff --git a/src/tool/ToolCompilationDatabase.cpp b/src/tool/ToolCompilationDatabase.cpp index 6872f602bd..7c756cd2d7 100644 --- a/src/tool/ToolCompilationDatabase.cpp +++ b/src/tool/ToolCompilationDatabase.cpp @@ -32,7 +32,7 @@ namespace { * @param cmakeArgs The arguments to pass to CMake when generating the compilation database. * @return An `Expected` object containing the path to the `compile_commands.json` file if the database is generated, or the provided path if it is already the `compile_commands.json` file. * Returns an `Unexpected` object in case of failure (e.g., file not found, CMake execution failure). - */ +*/ Expected generateCompileCommandsFile(llvm::StringRef inputPath, llvm::StringRef cmakeArgs, llvm::StringRef buildDir) { diff --git a/test-files/golden-tests/mrdocs.yml b/test-files/golden-tests/mrdocs.yml index 3342a7ec21..2403b801b3 100644 --- a/test-files/golden-tests/mrdocs.yml +++ b/test-files/golden-tests/mrdocs.yml @@ -1,3 +1,4 @@ concurrency: 1 source-root: . single-page: true +warn-if-undocumented: false \ No newline at end of file From c822298837ead55510c94933f7ad3ca69a57cc42 Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Fri, 21 Nov 2025 01:57:09 -0500 Subject: [PATCH 4/4] ci(cpp-matrix): remove the optimized-debug factor --- .github/workflows/ci.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0175e2ecaa..1f7c7c4432 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,7 +51,6 @@ jobs: apple-clang * standards: '20' latest-factors: | - msvc Optimized-Debug gcc UBSan Coverage clang UBSan ASan MSan apple-clang UBSan ASan @@ -66,11 +65,6 @@ jobs: clang: Release apple-clang: Release msvc: RelWithDebInfo - msvc Optimized-Debug: Debug - ccflags: | - msvc Optimized-Debug: /Ob1 /O2 /Zi - cxxflags: | - msvc Optimized-Debug: /Ob1 /O2 /Zi install: | gcc: git build-essential pkg-config python3 curl openjdk-11-jdk pkg-config libncurses-dev libxml2-utils libxml2-dev gcc Coverage: git build-essential pkg-config python3 curl openjdk-11-jdk pkg-config libncurses-dev libxml2-utils libxml2-dev lcov @@ -81,7 +75,7 @@ jobs: libcxx-runtimes: libcxx{{#if (ne compiler 'msvc')}};libcxxabi{{/if}} llvm-runtimes: {{#if (ine use-libcxx 'true') }}{{{ libcxx-runtimes }}}{{/if}} llvm-hash: dc4cef81d47c7bc4a3c4d58fbacf8a6359683fae - llvm-build-preset-prefix: {{#if optimized-debug}}optimizeddebug{{else}}{{{lowercase build-type}}}{{/if}} + llvm-build-preset-prefix: {{{lowercase build-type}}} llvm-build-preset-os: {{#if (ieq os 'windows') }}win{{else}}unix{{/if}} llvm-sanitizer: {{#if (eq compiler 'gcc')}}{{else if ubsan}}-UBSan{{else if asan}}-ASan{{else if msan}}-MSan{{/if}} llvm-build-preset: {{{ llvm-build-preset-prefix }}}-{{{ llvm-build-preset-os }}}