Full Code of adobe/hyde for AI

master 3fdcc772e07a cached
137 files
328.7 KB
75.8k tokens
207 symbols
1 requests
Download .txt
Showing preview only (364K chars total). Download the full file or copy to clipboard to get everything.
Repository: adobe/hyde
Branch: master
Commit: 3fdcc772e07a
Files: 137
Total size: 328.7 KB

Directory structure:
gitextract_uuaa76lr/

├── .clang-format
├── .editorconfig
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── PULL_REQUEST_TEMPLATE/
│   │   ├── bug_fix.md
│   │   └── feature.md
│   └── workflows/
│       └── tagged-release.yml
├── .gitignore
├── .gitmodules
├── .hyde-config
├── CMakeLists.txt
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── docs/
│   ├── Gemfile
│   ├── _config.yml
│   ├── _includes/
│   │   └── head.html
│   ├── _posts/
│   │   └── 2018-10-30-welcome.markdown
│   ├── _sass/
│   │   ├── _overrides-dark.scss
│   │   ├── _overrides-light.scss
│   │   └── _overrides.scss
│   ├── about.md
│   ├── feed.xml
│   ├── index.html
│   ├── libraries/
│   │   ├── classes.cpp/
│   │   │   ├── class_example/
│   │   │   │   ├── color.md
│   │   │   │   ├── index.md
│   │   │   │   ├── m_class_example.md
│   │   │   │   ├── m_deprecated.md
│   │   │   │   ├── m_deprecated_with_message.md
│   │   │   │   ├── m_member_function.md
│   │   │   │   ├── m_member_function_trailing_return_type.md
│   │   │   │   ├── m_overloaded.md
│   │   │   │   ├── m_static_method.md
│   │   │   │   ├── m_template_member_function.md
│   │   │   │   └── nested_class_example/
│   │   │   │       ├── index.md
│   │   │   │       ├── m_nested_class_example.md
│   │   │   │       └── m_~nested_class_example.md
│   │   │   ├── index.md
│   │   │   ├── partial_specialization_.4b7bfe45/
│   │   │   │   └── index.md
│   │   │   ├── partial_specialization_.edfbc14d/
│   │   │   │   └── index.md
│   │   │   ├── specialization_example3.ed9d8cc7/
│   │   │   │   ├── index.md
│   │   │   │   └── m_as_tuple.md
│   │   │   ├── specialization_example3CT3E/
│   │   │   │   ├── index.md
│   │   │   │   └── m_as_tuple.md
│   │   │   └── specialization_example3Cfloat3E/
│   │   │       ├── index.md
│   │   │       └── m_as_tuple.md
│   │   ├── comments.cpp/
│   │   │   ├── compiler_generated/
│   │   │   │   ├── index.md
│   │   │   │   ├── m_assign.md
│   │   │   │   ├── m_compiler_generated.md
│   │   │   │   └── m_operator3D.md
│   │   │   ├── f_template_function.md
│   │   │   ├── index.md
│   │   │   ├── some_other_struct/
│   │   │   │   ├── index.md
│   │   │   │   ├── m_operator3D.md
│   │   │   │   ├── m_some_other_struct.md
│   │   │   │   ├── m_virtual_function.md
│   │   │   │   └── m_~some_other_struct.md
│   │   │   └── some_struct/
│   │   │       ├── index.md
│   │   │       ├── m_operator3D.md
│   │   │       ├── m_some_function.md
│   │   │       ├── m_some_struct.md
│   │   │       ├── m_virtual_function.md
│   │   │       └── m_~some_struct.md
│   │   ├── enums.cpp/
│   │   │   ├── color_channel.md
│   │   │   ├── index.md
│   │   │   └── untyped.md
│   │   ├── functions.cpp/
│   │   │   ├── f_binary_function_example.md
│   │   │   ├── f_nullary_function_example.md
│   │   │   ├── f_overloaded.md
│   │   │   ├── f_static_auto_function_example.md
│   │   │   ├── f_static_function_example.md
│   │   │   ├── f_static_trailing_type_function_example.md
│   │   │   ├── f_template_function_example.md
│   │   │   └── index.md
│   │   ├── index.md
│   │   ├── namespaces.cpp/
│   │   │   ├── f_function.md
│   │   │   └── index.md
│   │   ├── point.cpp/
│   │   │   ├── index.md
│   │   │   └── point3CT3E/
│   │   │       ├── f_operator-.md
│   │   │       ├── f_operator213D.md
│   │   │       ├── f_operator3D3D.md
│   │   │       ├── index.md
│   │   │       ├── m_operator-3D.md
│   │   │       ├── m_origin.md
│   │   │       └── m_point3CT3E.md
│   │   └── typedef_and_alias.cpp/
│   │       ├── index.md
│   │       ├── template_example3CT2C20U3E/
│   │       │   └── index.md
│   │       └── template_example_instantiator/
│   │           └── index.md
│   └── serve.sh
├── emitters/
│   ├── yaml_base_emitter.cpp
│   ├── yaml_base_emitter.hpp
│   ├── yaml_base_emitter_fwd.hpp
│   ├── yaml_class_emitter.cpp
│   ├── yaml_class_emitter.hpp
│   ├── yaml_enum_emitter.cpp
│   ├── yaml_enum_emitter.hpp
│   ├── yaml_function_emitter.cpp
│   ├── yaml_function_emitter.hpp
│   ├── yaml_library_emitter.cpp
│   ├── yaml_library_emitter.hpp
│   ├── yaml_sourcefile_emitter.cpp
│   └── yaml_sourcefile_emitter.hpp
├── generate_test_files.sh
├── include/
│   ├── _clang_include_prefix.hpp
│   ├── _clang_include_suffix.hpp
│   ├── autodetect.hpp
│   ├── config.hpp
│   ├── json.hpp
│   ├── json_fwd.hpp
│   └── output_yaml.hpp
├── matchers/
│   ├── class_matcher.cpp
│   ├── class_matcher.hpp
│   ├── enum_matcher.cpp
│   ├── enum_matcher.hpp
│   ├── function_matcher.cpp
│   ├── function_matcher.hpp
│   ├── matcher_fwd.hpp
│   ├── namespace_matcher.cpp
│   ├── namespace_matcher.hpp
│   ├── typealias_matcher.cpp
│   ├── typealias_matcher.hpp
│   ├── typedef_matcher.cpp
│   ├── typedef_matcher.hpp
│   ├── utilities.cpp
│   └── utilities.hpp
├── sources/
│   ├── autodetect.cpp
│   ├── main.cpp
│   └── output_yaml.cpp
└── test_files/
    ├── classes.cpp
    ├── comments.cpp
    ├── enums.cpp
    ├── functions.cpp
    ├── namespaces.cpp
    ├── point.cpp
    └── typedef_and_alias.cpp

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
# Format style options described here:
#     https://clang.llvm.org/docs/ClangFormatStyleOptions.html

# Many of the alignment and single line changes were made to facilitate setting
# breakpoints on specific expressions.

---
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: false
# AlwaysBreakAfterDefinitionReturnType: TopLevel
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: false
# BraceWrapping:
#  AfterClass: true
#  AfterControlStatement: false
#  AfterEnum: false
#  AfterFunction: false
#  AfterNamespace: false
#  AfterObjCDeclaration: false
#  AfterStruct: false
#  AfterUnion: false
#  BeforeCatch: false
#  BeforeElse: false
#  IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: true
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
    Priority:        2
  - Regex:           '^(<|"(gtest|isl|json)/)'
    Priority:        3
  - Regex:           '.*'
    Priority:        1
IncludeIsMainRegex: '$'
IndentCaseLabels: true
IndentWidth: 4
IndentWrappedFunctionNames: true
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 1000
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: Never
---
Language: Cpp
---
Language: ObjC
PointerAlignment: Right
...


================================================
FILE: .editorconfig
================================================
# According to https://stackoverflow.com/a/33831598/153535, this should improve
# the way code is seen on GitHub (PRs, etc.) by making it respect tabs as being
# four spaces.

root = true

# Matches multiple files with brace expansion notation
[*.{c,cc,cpp,cxx,h,hh,hpp,hxx,mm}]
indent_style = space
indent_size = 4


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
 - OS: [e.g. iOS]
 - Browser [e.g. chrome, safari]
 - Version [e.g. 22]

**Smartphone (please complete the following information):**
 - Device: [e.g. iPhone6]
 - OS: [e.g. iOS8.1]
 - Browser [e.g. stock browser, safari]
 - Version [e.g. 22]

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/PULL_REQUEST_TEMPLATE/bug_fix.md
================================================
---
name: Bug fix
about: Submit a fix for an issue
---

**Fix for issue(s)**
#NNNN

**Diagnosis**
Please include a brief description of the root cause, and the fix(es) applied.

**Additional notes**
Add any other context about the problem here.

_Thank you!_


================================================
FILE: .github/PULL_REQUEST_TEMPLATE/feature.md
================================================
---
name: Feature
about: Provide new functionality
---

**Optional: Related issue(s)**
#NNNN

**What's Changed**
A clear and concise description of what's included in this PR.

**Rationale**
A clear and concise description of why this change is valuable.

**Additional context**
Add any other context here.

_Thank you!_


================================================
FILE: .github/workflows/tagged-release.yml
================================================
name: Tagged Release
on:
  push:
    tags:
      - "v*.*.*"
  workflow_dispatch: null
permissions:
  contents: write
jobs:
  release-mac:
    runs-on: macos-latest
    steps:
      - name: ⬇️ Checkout sources
        uses: actions/checkout@v3
      - name: 🏗️ Setup project files
        run: |
          git submodule update --init
          mkdir build
          cd build
          cmake -GXcode ..
      - name: 🛠️ Build Hyde
        run: |
          cd build
          xcodebuild -quiet -target hyde -configuration Release
      - name: 🗜️ Create archive
        run: |
          cd build/Release
          # "No such xattr: com.apple.quarantine"
          # xattr -d com.apple.quarantine hyde
          strip hyde
          codesign --force -s - hyde
          tar -zcvf hyde-${{github.ref_name}}-macos.tgz hyde
      - name: ✍️ Post archive
        uses: softprops/action-gh-release@v1
        with:
          generate_release_notes: true
          files:
            build/Release/hyde-${{github.ref_name}}-macos.tgz
  release-linux:
    runs-on: ubuntu-latest
    steps:
      - name: ⬇️ Checkout sources
        uses: actions/checkout@v3
      - name: 🏗️ Set up Clang
        uses: egor-tensin/setup-clang@v1
        with:
          version: 18
      - name: 🏗️ Setup project files
        run: |
          sudo apt-get install ninja-build
          git submodule update --init
          mkdir build
          cd build
          cmake -DCMAKE_BUILD_TYPE=Release -GNinja ..
      - name: 🛠️ Build Hyde
        run: |
          cd build
          ninja
      - name: 🗜️ Create archive
        run: |
          cd build
          tar -zcvf hyde-${{github.ref_name}}-linux-${{runner.arch}}.tgz hyde
      - name: ✍️ Post archive
        uses: softprops/action-gh-release@v1
        with:
          generate_release_notes: true
          files:
            build/hyde-${{github.ref_name}}-linux-${{runner.arch}}.tgz


================================================
FILE: .gitignore
================================================
*.sublime-project
*.sublime-workspace
.DS_Store
.vscode/
build/
build*/
docs/_site/
docs/Gemfile.lock


================================================
FILE: .gitmodules
================================================
[submodule "submodules/yaml-cpp"]
	path = submodules/yaml-cpp
	url = https://github.com/jbeder/yaml-cpp.git
[submodule "submodules/json"]
	path = submodules/json
	url = https://github.com/nlohmann/json.git


================================================
FILE: .hyde-config
================================================
{
    "hyde-src-root" : "./test_files",
    "hyde-yaml-dir" : "./docs/libraries",
    "clang_flags": [
        "--std=c++2a",
        "-Wno-everything"
    ]
}


================================================
FILE: CMakeLists.txt
================================================
# Copyright 2018 Adobe
# All Rights Reserved.

# NOTICE: Adobe permits you to use, modify, and distribute this file in
# accordance with the terms of the Adobe license agreement accompanying
# it. If you have received this file from a source other than Adobe,
# then your use, modification, or distribution of it requires the prior
# written permission of Adobe.

cmake_minimum_required(VERSION 3.23)

set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # Avoid overriding normal variables with option()
set(CMAKE_POLICY_DEFAULT_CMP0126 NEW) # Avoid overriding normal variables with set(CACHE)

include(FetchContent)

set(FETCHCONTENT_QUIET FALSE)

set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")

project(hyde)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_XCODE_GENERATE_SCHEME OFF)

message(STATUS "INFO: Setting up LLVM...")

FetchContent_Declare(
    llvm
    GIT_REPOSITORY https://github.com/llvm/llvm-project.git
    GIT_TAG 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff # llvmorg-18.1.8
    GIT_SHALLOW TRUE
    GIT_PROGRESS TRUE
    SOURCE_SUBDIR llvm
)

FetchContent_Declare(
    diff
    GIT_REPOSITORY https://github.com/fosterbrereton/diff.git
    GIT_TAG 2ba1687a30de266416caa141f8be408e72843be0
    GIT_SHALLOW TRUE
    GIT_PROGRESS TRUE
    SOURCE_SUBDIR diff
)

set(LLVM_ENABLE_PROJECTS "clang")
set(LLVM_TARGETS_TO_BUILD "X86;AArch64")
set(LLVM_ENABLE_ZSTD OFF)

FetchContent_MakeAvailable(llvm)
FetchContent_MakeAvailable(diff)

message(STATUS "INFO: LLVM source dir: ${llvm_SOURCE_DIR}")
message(STATUS "INFO: LLVM binary dir: ${llvm_BINARY_DIR}")

add_executable(hyde)

set(SRC_SOURCES
    ${PROJECT_SOURCE_DIR}/sources/autodetect.cpp
    ${PROJECT_SOURCE_DIR}/sources/main.cpp
    ${PROJECT_SOURCE_DIR}/sources/output_yaml.cpp
)

set(SRC_EMITTERS
    ${PROJECT_SOURCE_DIR}/emitters/yaml_base_emitter.cpp
    ${PROJECT_SOURCE_DIR}/emitters/yaml_class_emitter.cpp
    ${PROJECT_SOURCE_DIR}/emitters/yaml_enum_emitter.cpp
    ${PROJECT_SOURCE_DIR}/emitters/yaml_function_emitter.cpp
    ${PROJECT_SOURCE_DIR}/emitters/yaml_library_emitter.cpp
    ${PROJECT_SOURCE_DIR}/emitters/yaml_sourcefile_emitter.cpp
)

set(SRC_MATCHERS
    ${PROJECT_SOURCE_DIR}/matchers/class_matcher.cpp
    ${PROJECT_SOURCE_DIR}/matchers/enum_matcher.cpp
    ${PROJECT_SOURCE_DIR}/matchers/function_matcher.cpp
    ${PROJECT_SOURCE_DIR}/matchers/namespace_matcher.cpp
    ${PROJECT_SOURCE_DIR}/matchers/typealias_matcher.cpp
    ${PROJECT_SOURCE_DIR}/matchers/typedef_matcher.cpp
    ${PROJECT_SOURCE_DIR}/matchers/utilities.cpp
)

set(SRC_YAMLCPP
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/binary.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/convert.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/depthguard.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/directives.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/emit.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/emitfromevents.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/emitter.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/emitterstate.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/emitterutils.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/exceptions.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/exp.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/memory.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/node.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/node_data.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/nodebuilder.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/nodeevents.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/null.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/ostream_wrapper.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/parse.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/parser.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/regex_yaml.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/scanner.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/scanscalar.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/scantag.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/scantoken.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/simplekey.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/singledocparser.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/stream.cpp
    ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/src/tag.cpp
)

target_sources(hyde
    PRIVATE
        ${SRC_SOURCES}
        ${SRC_EMITTERS}
        ${SRC_MATCHERS}
        ${SRC_YAMLCPP}
)

source_group(sources FILES ${SRC_SOURCES})
source_group(emitters FILES ${SRC_EMITTERS})
source_group(matchers FILES ${SRC_MATCHERS})
source_group(yaml-cpp FILES ${SRC_YAMLCPP})

target_include_directories(hyde
    PUBLIC
        ${CMAKE_CURRENT_SOURCE_DIR}
        ${CMAKE_CURRENT_SOURCE_DIR}/include
        ${PROJECT_SOURCE_DIR}/submodules/yaml-cpp/include/
        ${PROJECT_SOURCE_DIR}/submodules/json/include/
        ${llvm_SOURCE_DIR}/clang/include
        ${llvm_BINARY_DIR}/tools/clang/include
        ${llvm_SOURCE_DIR}/llvm/include
        ${llvm_BINARY_DIR}/include
        ${diff_SOURCE_DIR}/include
)

target_compile_options(hyde
    PUBLIC
        -Wall
        -Wno-comment
        -Werror
        -Wno-range-loop-analysis
)

if (NOT LLVM_ENABLE_RTTI)
    target_compile_options(hyde PRIVATE -fno-rtti)
endif()

target_link_libraries(hyde
    clang
    clangAST
    clangASTMatchers
    clangBasic
    clangFrontend
    clangLex
    clangTooling
)

if (PROJECT_IS_TOP_LEVEL)
    set_target_properties(hyde PROPERTIES XCODE_GENERATE_SCHEME ON)
endif()


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Adobe Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
  address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at Grp-opensourceoffice@adobe.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing

Thanks for choosing to contribute!

The following are a set of guidelines to follow when contributing to this project.

## Code Of Conduct

This project adheres to the Adobe [code of conduct](CODE_OF_CONDUCT.md). By participating,
you are expected to uphold this code. Please report unacceptable behavior to
[Grp-opensourceoffice@adobe.com](mailto:Grp-opensourceoffice@adobe.com).

## Have A Question?

Start by filing an issue. The existing committers on this project work to reach
consensus around project direction and issue solutions within issue threads
(when appropriate).

## Contributor License Agreement

All third-party contributions to this project must be accompanied by a signed contributor
license agreement. This gives Adobe permission to redistribute your contributions
as part of the project. [Sign our CLA](http://opensource.adobe.com/cla.html). You
only need to submit an Adobe CLA one time, so if you have submitted one previously,
you are good to go!

## Code Reviews

All submissions should come in the form of pull requests and need to be reviewed
by project committers. Read [GitHub's pull request documentation](https://help.github.com/articles/about-pull-requests/)
for more information on sending pull requests.

## From Contributor To Committer

We love contributions from our community! If you'd like to go a step beyond contributor
and become a committer with full write access and a say in the project, you must
be invited to the project. The existing committers employ an internal nomination
process that must reach lazy consensus (silence is approval) before invitations
are issued. If you feel you are qualified and want to get more deeply involved,
feel free to reach out to existing committers to have a conversation about that.

## Security Issues

Security issues shouldn't be reported on this issue tracker. Instead, [file an issue to our security experts](https://helpx.adobe.com/security/alertus.html)


================================================
FILE: Dockerfile
================================================

FROM --platform=linux/x86_64 ubuntu:latest
RUN apt-get -y update && apt-get install -y

RUN apt-get -y install curl gnupg2 software-properties-common ninja-build  apt-utils make

RUN apt-get -y install wget

RUN apt-get -y install git

# Are the build-essential packages needed? This elminates a CMake error
# about /usr/bin/c++ not being found but seems like overkill.
RUN apt-get -y install build-essential

# Install llvm/clang

# This is nesessary because of an issue with the hyde resource-dir. The
# version of clang installed must exactly match the version of clang used
# to build hyde. This is a temporary fix until hyde installs the necessary
# resource directory and encodes the path in the binary.

# If you get an error message about stddef.h or size_t not being found,
# the issue is here. Check where hyde is looking for it's resoruce
# directory with
# `hyde ./test.hpp -- -x c++ -print-resource-dir`

# FROM base AS full

ENV LLVM_VERSION=15

RUN apt-get -y install clang-${LLVM_VERSION}
RUN apt-get -y install libc++-${LLVM_VERSION}-dev

# set clang ${LLVM_VERSION} to be the version of clang we use when clang/clang++ is invoked
RUN update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${LLVM_VERSION} 100
RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${LLVM_VERSION} 100

ADD https://cmake.org/files/v3.24/cmake-3.24.0-linux-x86_64.sh /cmake-3.24.0-linux-x86_64.sh
RUN mkdir /opt/cmake
RUN sh /cmake-3.24.0-linux-x86_64.sh --prefix=/opt/cmake --skip-license
RUN ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake

#install hyde dependencies
RUN apt-get -y install libyaml-cpp-dev libboost-system-dev libboost-filesystem-dev

COPY . /usr/src/hyde

# build hyde and run the generate_test_files
WORKDIR /usr/src/hyde
RUN mkdir -p build \
    && cd build \
    && rm -rf *  \
    && cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release \
    && ninja

# install hyde
RUN cp ./build/hyde /usr/bin

# RUN apt-get -y install clang-15

CMD ["./generate_test_files.sh"]

# Experimenting with publishing the container and linking it to the hyde repo:

LABEL org.opencontainers.image.source=https://github.com/adobe/hyde


================================================
FILE: LICENSE
================================================
MIT License

© Copyright 2018 Adobe. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# What is `hyde`

`hyde` is a utility that facilitates documenting C++. The tool is unique from existing documentation utilities in the following ways:

- **Clang based**: In order to properly document your C++, `hyde` compiles it using Clang's excellent [libTooling](https://clang.llvm.org/docs/LibTooling.html) library. Therefore, as the C++ language evolves, so too will `hyde`.
- **Out-of-line**: Many tools rely on documentation placed inline within source as long-form comments. While these seem appealing at first blush, they suffer from two big drawbacks. First, there is nothing keeping the comments from falling out of sync from the elements they document. Secondly (and ironically), experienced users of these libraries eventually find inline documentation to be more of a distraction than a help, cluttering code with comments they no longer read.
- **Jekyll compatible**: `hyde` does not produce pretty-printed output. Rather, it produces well structured Markdown files that contain YAML front-matter. These files can then be consumed by other tools (like Jekyll) to customize the structure and layout of the final documentation.
- **Schema enforcement**: Because of the highly structured nature of the output, `hyde` is able to compare pre-existing documentation files against the current state of your C++ sources. Library developers can use `hyde`'s _update_ mode to facilitate updating documentation against the state of sources. Build engineers can use `hyde`'s _validate_ mode to make sure changes to a code base are accurately reflected in the latest documentation. In the end, the documentation stays true to the code with minimal effort.
- **Adaptable**: While `hyde`'s primary purpose at this point is to output and enforce documentation, the tool can also be used to output AST-based information about your code as a JSON-based IR. This makes room for additional tools to be build atop what `hyde` is able to produce, or additional emitters can be added natively to the tool.

# Example Output

`hyde` produces intermediate documentation files that the developer then fills in with additional details as necessary. The files are then fed through a static site generation tool (like Jekyll) to produce [output like this](https://stlab.cc/includes/stlab/copy_on_write.hpp/copy_on_write3CT3E/).

# Requirements

## macOS

- Homebrew
    - `brew install cmake`
    - `brew install ninja` (optional)

## Linux

(Note: only tested on ubuntu bionic so far)

- Apt
    - `sudo apt-get install libyaml-cpp-dev`

# How to Build

- clone this repo
- `cd hyde`
- `git submodule update --init`
- `mkdir build`
- `cd build`
- `cmake .. -GNinja` (or `-GXcode`, etc.)
- `ninja` (or whatever your IDE does)

LLVM/Clang are declared as a dependency in the project's `CMakeLists.txt` file, and will be downloaded and made available to the project automatically.

# How to run from Docker

```sh
docker pull ghcr.io/adobe/hyde:latest

docker run --platform linux/x86_64 --mount type=bind,source="$(pwd)",target=/mnt/host \
    --tty --interactive \
    ghcr.io/adobe/hyde:latest bash
```

You can then run the examples as below, except don't prefix `hyde` with `./`.

# Building the Docker image

You may need to increase your docker resources to build the image. (2.0.1 successfully built with 16GB RAM and 4GB swap)

```sh
docker build --tag hyde .

docker run --platform linux/x86_64 --mount type=bind,source="$(pwd)",target=/mnt/host \
    --tty --interactive \
    hyde bash
```

# Publishing the docker image (requires write access to the `adobe` GitHub organization)

Instructions for publishing a GitHub package can be found [here](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry).
Instructions for associating the with the `adobe/hyde` repository can be found [here](https://docs.github.com/en/packages/learn-github-packages/connecting-a-repository-to-a-package#connecting-a-repository-to-a-container-image-using-the-command-line).

```sh
VERSION=2.0.1
docker tag hyde ghcr.io/adobe/hyde:$VERSION
docker tag hyde ghcr.io/adobe/hyde:latest
docker push ghcr.io/adobe/hyde:$VERSION
docker push ghcr.io/adobe/hyde:latest
```


# Parameters and Flags

There are several modes under which the tool can run:

- `-hyde-json` - (default) Output an analysis dump of the input file as JSON
- `-hyde-validate` - Validate existing YAML documentation
- `-hyde-update` - Write updated YAML documentation

- `-hyde-src-root = <path>` - The root path to the header file(s) being analyzed. Affects `defined_in_file` output values by taking out the root path.
- `-hyde-yaml-dir = <path>` - Root directory for YAML validation / update. Required for either hyde-validate or hyde-update modes.

- `--use-system-clang` - Autodetect and use necessary resource directories and include paths

- `--fixup-hyde-subfield` - As of Hyde v0.1.5, all hyde fields are under a top-level `hyde` subfield in YAML output. This flag will update older hyde documentation that does not have this subfield by creating it, then moving all top-level fields except `title` and `layout` under it. This flag is intended to be used only once during the migration of older documentation from the non-subfield structure to the subfield structure.

This tool parses the passed header using Clang. To pass arguments to the compiler (e.g., include directories), append them after the `--` token on the command line. For example:

    hyde input_file.hpp -hyde-json -use-system-clang -- -x c++ -I/path/to/includes

Alternatively, if you have a compilation database and would like to pass that instead of command-line compiler arguments, you can pass that with `-p`.

While compiling the source file, the non-function macro `ADOBE_TOOL_HYDE` is defined to the value `1`. This can be useful to explicitly omit code from the documentation.

# Examples:

To output JSON:
```./hyde -use-system-clang ../test_files/classes.cpp --```

To validate pre-existing YAML:
```./hyde -use-system-clang -hyde-yaml-dir=/path/to/output -hyde-validate ../test_files/classes.cpp```

To output updated YAML:
```./hyde -use-system-clang -hyde-yaml-dir=/path/to/output -hyde-update ../test_files/classes.cpp```

# Hyde 1 to Hyde 2 Format Conversion

As of the Hyde 2 work, all subfields in the YAML output (except the Jekyll-required `layout` and `title` fields) must go under a top-level `hyde` subfield. This allows for other tools to include additional (possibly same-named) fields under their own top-level subfields in the YAML.

Here is an example of updating from Hyde 1 to Hyde 2 formatted docs by scanning a directory for markdown-formatted files and passing them to `hyde` with the new `-hyde-fixup-subfield` mode:

    find . -name '*.md' | xargs -I % -L 1 /path/to/hyde -hyde-fixup-subfield % --

# Sass Updates

Sometimes it may be necessary to clean up or "lint" the sass files. You can do so with:

    bundle exec sass-convert -i /path/to/file.scss


================================================
FILE: docs/Gemfile
================================================
source "https://rubygems.org"

# Manage our dependency on the version of the github-pages gem here.
gem "github-pages", "= 228"

# Explicitly include this gem here.
# It is not directly included in the github-pages gem list of dependencies,
# even though it is included in the original GitHub Pages build infrastructure.
gem "jekyll-include-cache", "= 0.2.1"
gem "jekyll-octicons", "~> 14.2"


================================================
FILE: docs/_config.yml
================================================
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely need to edit after that.
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'jekyll serve'. If you change this file, please restart the server process.

# Site settings
title: Hyde Example Docs
subtitle: Website showing a possible Jekyll-formatted hyde output.
email: noreply@adobe.com
baseurl: /hyde
url: "https://opensource.adobe.com/" # the base hostname & protocol for your site
repository: adobe/hyde
remote_theme: adobe/hyde-theme@v2.0.0
exclude:
    - "*.sh"
    - vendor # For Travis-CI (see https://jekyllrb.com/docs/continuous-integration/)

adobe_hyde:
    header_image: /images/site/hyde.svg

# Build settings
markdown: kramdown

plugins:
  - jekyll-redirect-from
  - jekyll-remote-theme


================================================
FILE: docs/_includes/head.html
================================================
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}</title>
  <meta name="description" content="{% if page.excerpt %}{{ page.excerpt | strip_html | strip_newlines | truncate: 160 }}{% else %}{{ site.description }}{% endif %}">
  <noscript>
    <link rel="stylesheet" href="{{ "assets/css/main-light.css" | prepend: site.baseurl }}">
  </noscript>
  <link rel="stylesheet" id="main-style">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
  <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro|Source+Sans+Pro|Source+Serif+Pro" rel="stylesheet">
  <link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}">
  <script type="text/x-mathjax-config">
    MathJax.Hub.Config({
      tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}
    });
  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script>
  <script src="{{ '/assets/scripts/indices.js' | relative_url }}"></script>
</head>


================================================
FILE: docs/_posts/2018-10-30-welcome.markdown
================================================
---
layout: post
title:  Welcome!
excerpt_separator: <!--more-->
---

This is the landing page for the `hyde` sample files example site. Poke around in the `Libraries` section, above.


================================================
FILE: docs/_sass/_overrides-dark.scss
================================================
// Copy this file to you site and use it to override CSS variables that apply to the dark CSS
// definitions. See `main-dark.scss` in the theme for a complete list of variables you can override
// with this file.

// @debug "Old link-color: #{$link-color}";
// $hyde-primary: $stlab-purple;
// $link-color: $stlab-purple;
// @debug "New link-color: #{$link-color}";


================================================
FILE: docs/_sass/_overrides-light.scss
================================================
// Copy this file to you site and use it to override CSS variables that apply to the light CSS
// definitions. See `main-light.scss` in the theme for a complete list of variables you can override
// with this file.

// @debug "Old hyde-primary: #{$link-color}";
// $hyde-primary: $stlab-purple;
// $link-color: $stlab-purple;
// @debug "New link-color: #{$link-color}";


================================================
FILE: docs/_sass/_overrides.scss
================================================
// Copy this file to you site and use it to override CSS variables that apply to both the light and
// dark CSS definitions, such as font families, content widths, etc. See `_main.scss` in the theme
// for a complete list of variables you can override with this file.

// @debug "Old base-font-family: #{$base-font-family}";
// $base-font-family: "Georgia";
// @debug "New base-font-family: #{$base-font-family}";


================================================
FILE: docs/about.md
================================================
---
layout: page
title: About
tab: About
permalink: /about/
---

This is the about page. There are many like it, but this one is mine.


================================================
FILE: docs/feed.xml
================================================
---
layout: null
---
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>{{ site.title | xml_escape }}</title>
    <description>{{ site.description | xml_escape }}</description>
    <link>{{ site.url }}{{ site.baseurl }}/</link>
    <atom:link href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}" rel="self" type="application/rss+xml"/>
    <pubDate>{{ site.time | date_to_rfc822 }}</pubDate>
    <lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
    <generator>Jekyll v{{ jekyll.version }}</generator>
    {% for post in site.posts limit:10 %}
      <item>
        <title>{{ post.title | xml_escape }}</title>
        <description>{{ post.content | xml_escape }}</description>
        <pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
        <link>{{ post.url | prepend: site.baseurl | prepend: site.url }}</link>
        <guid isPermaLink="true">{{ post.url | prepend: site.baseurl | prepend: site.url }}</guid>
        {% for tag in post.tags %}
        <category>{{ tag | xml_escape }}</category>
        {% endfor %}
        {% for cat in post.categories %}
        <category>{{ cat | xml_escape }}</category>
        {% endfor %}
      </item>
    {% endfor %}
  </channel>
</rss>


================================================
FILE: docs/index.html
================================================
---
layout: default
---

<div class="home">

  <table class='icon-table'>
  <tr>
    <td>
        <a href='libraries/'>
        <div class='icon-box'>
            <div class='top'><i class="fa fa-inverse fa-book"></i></div>
            <div class='bottom'>Libraries</div>
        </div>
        </a>
    </td>
  </tr>
  </table>

  <h1>Posts</h1>

  <ul class="post-list">
    {% for post in site.posts %}
      <li>
        <span class="post-meta">{{ post.date | date: "%b %-d, %Y" }}</span>

        <h2>
          <a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
        </h2>
      {{ post.excerpt }}
      </li>
    {% endfor %}
  </ul>

  <p class="rss-subscribe">subscribe <a href="{{ "/feed.xml" | prepend: site.baseurl }}">via RSS</a></p>

</div>


================================================
FILE: docs/libraries/classes.cpp/class_example/color.md
================================================
---
layout: enumeration
title: color
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - enumeration
  inline:
    brief: an example enumeration within the class.
    description:
      - Note that nested classes will not inherit their ownership from the class that contains them, so thus need their own `hyde-owner`.
    owner: sean-parent
  defined_in_file: classes.cpp
  values:
    - description: __INLINED__
      inline:
        description:
          - this is an example description for the `red` value.
      name: red
    - description: __INLINED__
      inline:
        description:
          - this is an example description for the `green` value.
      name: green
    - description: __INLINED__
      inline:
        description:
          - this is an example description for the `blue` value.
      name: blue
---


================================================
FILE: docs/libraries/classes.cpp/class_example/index.md
================================================
---
layout: class
title: class_example
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: an example class that demonstrates what Hyde documents.
    owner: fosterbrereton
  defined_in_file: classes.cpp
  declaration: "\nclass class_example;"
  dtor: unspecified
  typedefs:
    typedef_example:
      definition: std::string
      description: __INLINED__
      inline:
        description:
          - a nested `typedef` expression.
    using_example:
      definition: std::string
      description: __INLINED__
      inline:
        description:
          - a nested `using` expression.
  fields:
    _deprecated_member:
      annotation:
        - private
        - deprecated("example deprecation message")
      description: __INLINED__
      inline:
        description:
          - a deprecated member variable that contains a message. Apparently this works?!
      type: int
    _nested:
      annotation:
        - private
      description: __INLINED__
      inline:
        description:
          - an instance of the nested class example defined earlier.
      type: class_example::nested_class_example
    _static_member:
      description: __INLINED__
      inline:
        description:
          - static member variable.
      type: const int
    _x:
      annotation:
        - private
      description: __INLINED__
      inline:
        description:
          - some variable that holds an integer.
      type: int
---


================================================
FILE: docs/libraries/classes.cpp/class_example/m_class_example.md
================================================
---
layout: method
title: class_example
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief: _multiple descriptions_
    owner: fosterbrereton
  defined_in_file: classes.cpp
  is_ctor: true
  overloads:
    class_example():
      annotation:
        - defaulted
      description: __INLINED__
      inline:
        description:
          - default constructor.
      signature_with_names: class_example()
    explicit class_example(int):
      arguments:
        - description: __OPTIONAL__
          name: x
          type: int
      description: __INLINED__
      inline:
        arguments:
          x:
            description: The one integer parameter this routine takes
        description:
          - an explicit constructor that takes a single `int`.
      signature_with_names: explicit class_example(int x)
---


================================================
FILE: docs/libraries/classes.cpp/class_example/m_deprecated.md
================================================
---
layout: method
title: deprecated
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief:
      - deprecated member function.
    owner: fosterbrereton
  defined_in_file: classes.cpp
  overloads:
    void deprecated(const std::string &, class_example *):
      annotation:
        - deprecated
      arguments:
        - description: __OPTIONAL__
          name: first
          type: const std::string &
        - description: __OPTIONAL__
          name: second
          type: class_example *
      description: __INLINED__
      inline:
        arguments:
          first:
            description: the first parameter
          second:
            description: the second parameter
        description:
          - deprecated member function.
      return: __OPTIONAL__
      signature_with_names: void deprecated(const std::string & first, class_example * second)
---


================================================
FILE: docs/libraries/classes.cpp/class_example/m_deprecated_with_message.md
================================================
---
layout: method
title: deprecated_with_message
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief:
      - deprecated member function that contains a compile-time deprecation message.
    owner: fosterbrereton
  defined_in_file: classes.cpp
  overloads:
    void deprecated_with_message(const std::string &, class_example *):
      annotation:
        - deprecated("example deprecation message")
      arguments:
        - description: __OPTIONAL__
          name: s
          type: const std::string &
        - description: __OPTIONAL__
          name: f
          type: class_example *
      description: __INLINED__
      inline:
        arguments:
          f:
            description: the second parameter
          s:
            description: the first parameter
        description:
          - deprecated member function that contains a compile-time deprecation message.
      return: __OPTIONAL__
      signature_with_names: void deprecated_with_message(const std::string & s, class_example * f)
---


================================================
FILE: docs/libraries/classes.cpp/class_example/m_member_function.md
================================================
---
layout: method
title: member_function
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief:
      - example member function.
    owner: fosterbrereton
  defined_in_file: classes.cpp
  overloads:
    int member_function():
      description: __INLINED__
      inline:
        description:
          - example member function.
        return: double the value of `_x`.
      return: __OPTIONAL__
      signature_with_names: int member_function()
---


================================================
FILE: docs/libraries/classes.cpp/class_example/m_member_function_trailing_return_type.md
================================================
---
layout: method
title: member_function_trailing_return_type
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief:
      - member function with a trailing return type.
    owner: fosterbrereton
  defined_in_file: classes.cpp
  overloads:
    auto member_function_trailing_return_type() const -> int:
      description: __INLINED__
      inline:
        description:
          - member function with a trailing return type.
        return: "\"`_x`\""
      return: __OPTIONAL__
      signature_with_names: auto member_function_trailing_return_type() const -> int
---


================================================
FILE: docs/libraries/classes.cpp/class_example/m_overloaded.md
================================================
---
layout: method
title: overloaded
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief: _multiple descriptions_
    owner: fosterbrereton
  defined_in_file: classes.cpp
  overloads:
    void overloaded():
      annotation:
        - deprecated
      description: __INLINED__
      inline:
        description:
          - a deprecated overload that takes zero parameters.
      return: __OPTIONAL__
      signature_with_names: void overloaded()
    void overloaded(const std::string &):
      arguments:
        - description: __OPTIONAL__
          name: first
          type: const std::string &
      description: __INLINED__
      inline:
        arguments:
          first:
            description: the first parameter of the first overload.
        brief: A series of overloaded functions.
        description:
          - an overloaded member function that takes one parameter.
      return: __OPTIONAL__
      signature_with_names: void overloaded(const std::string & first)
    void overloaded(const std::string &, class_example *, int):
      arguments:
        - description: __OPTIONAL__
          name: unnamed-0
          type: const std::string &
          unnamed: true
        - description: __OPTIONAL__
          name: unnamed-1
          type: class_example *
          unnamed: true
        - description: __OPTIONAL__
          name: unnamed-2
          type: int
          unnamed: true
      description: __INLINED__
      inline:
        description:
          - an overloaded member function that takes three unnamed parameters. Let it be known that Doxygen doesn't support documenting unnamed parameters at this time. There is a [bug open on the issue](https://github.com/doxygen/doxygen/issues/6926), but as of this writing does not appear to be progressing.
      return: __OPTIONAL__
      signature_with_names: void overloaded(const std::string &, class_example *, int)
    void overloaded(const std::string &, class_example *, int, bool, std::size_t):
      arguments:
        - description: __OPTIONAL__
          name: first
          type: const std::string &
        - description: __OPTIONAL__
          name: second
          type: class_example *
        - description: __OPTIONAL__
          name: third
          type: int
        - description: __OPTIONAL__
          name: fourth
          type: bool
        - description: __OPTIONAL__
          name: fifth
          type: std::size_t
      description: __INLINED__
      inline:
        arguments:
          fifth:
            description: the fifth parameter of the fourth overload.
          first:
            description: the first parameter of the fourth overload.
          fourth:
            description: the fourth parameter of the fourth overload.
          second:
            description: the second parameter of the fourth overload.
          third:
            description: the third parameter of the fourth overload.
        description:
          - an overloaded member function that takes _five_ parameters.
      return: __OPTIONAL__
      signature_with_names: void overloaded(const std::string & first, class_example * second, int third, bool fourth, std::size_t fifth)
    void overloaded(const std::string &, const std::string &) volatile:
      arguments:
        - description: __OPTIONAL__
          name: first
          type: const std::string &
        - description: __OPTIONAL__
          name: second
          type: const std::string &
      description: __INLINED__
      inline:
        arguments:
          first:
            description: the first parameter of the second overload.
          second:
            description: the second parameter of the second overload.
        brief: Another brief describing one of the overloaded functions.
        description:
          - an overloaded member function that takes two parameters.
      return: __OPTIONAL__
      signature_with_names: void overloaded(const std::string & first, const std::string & second) volatile
    void overloaded(const std::string &, std::vector<int>) const:
      arguments:
        - description: __OPTIONAL__
          name: first
          type: const std::string &
        - description: __OPTIONAL__
          name: second
          type: std::vector<int>
      description: __INLINED__
      inline:
        arguments:
          first:
            description: the first parameter of the third overload.
          second:
            description: the second parameter of the third overload.
        description:
          - another overloaded member function that takes two parameters.
      return: __OPTIONAL__
      signature_with_names: void overloaded(const std::string & first, std::vector<int> second) const
---


================================================
FILE: docs/libraries/classes.cpp/class_example/m_static_method.md
================================================
---
layout: method
title: static_method
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief: static member function.
    owner: fosterbrereton
  defined_in_file: classes.cpp
  overloads:
    static int static_method():
      description: __OPTIONAL__
      inline:
        brief: static member function.
        return: Zero. By which I mean `0`. In the sources, this comment is on multiple lines.
      return: __OPTIONAL__
      signature_with_names: static int static_method()
---


================================================
FILE: docs/libraries/classes.cpp/class_example/m_template_member_function.md
================================================
---
layout: method
title: template_member_function
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief: _multiple descriptions_
    owner: fosterbrereton
  defined_in_file: classes.cpp
  overloads:
    "template <typename U>\nvoid template_member_function()":
      description: __INLINED__
      inline:
        description:
          - templatized member function.
      return: __OPTIONAL__
      signature_with_names: "template <typename U>\nvoid template_member_function()"
    void template_member_function():
      description: __INLINED__
      inline:
        description:
          - specialization of the above templatized member function.
      return: __OPTIONAL__
      signature_with_names: void template_member_function()
---


================================================
FILE: docs/libraries/classes.cpp/class_example/nested_class_example/index.md
================================================
---
layout: class
title: nested_class_example
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: a class definition contained within `example_class`.
    description:
      - Note that nested classes will not inherit their ownership from the class that contains them, so thus need their own `hyde-owner`.
    owner: sean-parent
  defined_in_file: classes.cpp
  declaration: "\nstruct class_example::nested_class_example;"
  ctor: unspecified
  dtor: unspecified
  fields:
    _x:
      description: __INLINED__
      inline:
        description:
          - member field `_x` within the nested class example.
      type: int
    _y:
      description: __INLINED__
      inline:
        description:
          - member field `_y` within the nested class example.
      type: int
---


================================================
FILE: docs/libraries/classes.cpp/class_example/nested_class_example/m_nested_class_example.md
================================================
---
layout: method
title: nested_class_example
hyde:
  owner: __INLINED__
  brief: __OPTIONAL__
  tags:
    - method
  inline:
    owner: sean-parent
  defined_in_file: classes.cpp
  is_ctor: true
  overloads:
    nested_class_example():
      annotation:
        - implicit
      description: __OPTIONAL__
      signature_with_names: nested_class_example()
    nested_class_example(class_example::nested_class_example &&):
      annotation:
        - implicit
      arguments:
        - description: __OPTIONAL__
          name: unnamed-0
          type: class_example::nested_class_example &&
          unnamed: true
      description: __OPTIONAL__
      signature_with_names: nested_class_example(class_example::nested_class_example &&)
    nested_class_example(const class_example::nested_class_example &):
      annotation:
        - implicit
      arguments:
        - description: __OPTIONAL__
          name: unnamed-0
          type: const class_example::nested_class_example &
          unnamed: true
      description: __OPTIONAL__
      signature_with_names: nested_class_example(const class_example::nested_class_example &)
---


================================================
FILE: docs/libraries/classes.cpp/class_example/nested_class_example/m_~nested_class_example.md
================================================
---
layout: method
title: ~nested_class_example
hyde:
  owner: __INLINED__
  brief: __OPTIONAL__
  tags:
    - method
  inline:
    owner: sean-parent
  defined_in_file: classes.cpp
  is_dtor: true
  overloads:
    ~nested_class_example():
      annotation:
        - implicit
      description: __OPTIONAL__
      signature_with_names: ~nested_class_example()
---


================================================
FILE: docs/libraries/classes.cpp/index.md
================================================
---
layout: library
title: classes.cpp
hyde:
  owner: __MISSING__
  brief: __MISSING__
  tags:
    - sourcefile
  library-type: sourcefile
---


================================================
FILE: docs/libraries/classes.cpp/partial_specialization_.4b7bfe45/index.md
================================================
---
layout: class
title: partial_specialization_example<int, T>
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: an example `int, T` partial specialization
    owner: fosterbrereton
  defined_in_file: classes.cpp
  declaration: "\nclass partial_specialization_example;"
  ctor: unspecified
  dtor: unspecified
  fields:
    _first:
      annotation:
        - private
      description: __MISSING__
      type: std::string
    _second:
      annotation:
        - private
      description: __MISSING__
      type: T
---


================================================
FILE: docs/libraries/classes.cpp/partial_specialization_.edfbc14d/index.md
================================================
---
layout: class
title: partial_specialization_example<T1, T2>
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: an example template class with a partial specialization.
    owner: fosterbrereton
  defined_in_file: classes.cpp
  declaration: "template <class T1, class T2>\nclass partial_specialization_example;"
  ctor: unspecified
  dtor: unspecified
  fields:
    _first:
      annotation:
        - private
      description: __MISSING__
      type: T1
    _second:
      annotation:
        - private
      description: __MISSING__
      type: T2
---


================================================
FILE: docs/libraries/classes.cpp/specialization_example3.ed9d8cc7/index.md
================================================
---
layout: class
title: specialization_example<std::int32_t>
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: an example `std::int32` specialization
    owner: fosterbrereton
  defined_in_file: classes.cpp
  declaration: "\nstruct specialization_example;"
  ctor: unspecified
  dtor: unspecified
  typedefs:
    value_type:
      definition: std::int32_t
      description: __INLINED__
      inline:
        description:
          - An example typedef
  fields:
    _first:
      description: __INLINED__
      inline:
        description:
          - An example field used in `as_tuple`
      type: specialization_example<int>::value_type
---


================================================
FILE: docs/libraries/classes.cpp/specialization_example3.ed9d8cc7/m_as_tuple.md
================================================
---
layout: method
title: as_tuple
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief:
      - An example function
    owner: fosterbrereton
  defined_in_file: classes.cpp
  overloads:
    constexpr tuple<const int &> as_tuple() const:
      description: __INLINED__
      inline:
        description:
          - An example function
        return: a tuple of the fields of this class
      return: __OPTIONAL__
      signature_with_names: constexpr tuple<const int &> as_tuple() const
---


================================================
FILE: docs/libraries/classes.cpp/specialization_example3CT3E/index.md
================================================
---
layout: class
title: specialization_example<T>
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: an example template class with some specializations
    owner: fosterbrereton
  defined_in_file: classes.cpp
  declaration: "template <typename T>\nstruct specialization_example;"
  ctor: unspecified
  dtor: unspecified
---


================================================
FILE: docs/libraries/classes.cpp/specialization_example3CT3E/m_as_tuple.md
================================================
---
layout: method
title: as_tuple
hyde:
  owner: __INLINED__
  brief: __MISSING__
  tags:
    - method
  inline:
    owner: fosterbrereton
  defined_in_file: classes.cpp
  overloads:
    constexpr auto as_tuple() const:
      description: __OPTIONAL__
      return: __OPTIONAL__
      signature_with_names: constexpr auto as_tuple() const
---


================================================
FILE: docs/libraries/classes.cpp/specialization_example3Cfloat3E/index.md
================================================
---
layout: class
title: specialization_example<float>
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: an example `float` specialization
    owner: fosterbrereton
  defined_in_file: classes.cpp
  declaration: "\nstruct specialization_example;"
  ctor: unspecified
  dtor: unspecified
  typedefs:
    value_type:
      definition: float
      description: __MISSING__
  fields:
    _first:
      description: __INLINED__
      inline:
        description:
          - An example field used in `as_tuple`
      type: specialization_example<float>::value_type
---


================================================
FILE: docs/libraries/classes.cpp/specialization_example3Cfloat3E/m_as_tuple.md
================================================
---
layout: method
title: as_tuple
hyde:
  owner: __INLINED__
  brief: __MISSING__
  tags:
    - method
  inline:
    owner: fosterbrereton
  defined_in_file: classes.cpp
  overloads:
    constexpr tuple<const float &> as_tuple() const:
      description: __OPTIONAL__
      return: __OPTIONAL__
      signature_with_names: constexpr tuple<const float &> as_tuple() const
---


================================================
FILE: docs/libraries/comments.cpp/compiler_generated/index.md
================================================
---
layout: class
title: compiler_generated
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: Sample class intended to exhibit docs for compiler-generated routines
    owner: fosterbrereton
  defined_in_file: comments.cpp
  declaration: "\nstruct compiler_generated;"
  dtor: unspecified
---


================================================
FILE: docs/libraries/comments.cpp/compiler_generated/m_assign.md
================================================
---
layout: method
title: assign
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief:
      - This definition will force the compiler to auto-generate this class' assignment operator.
    owner: fosterbrereton
  defined_in_file: comments.cpp
  overloads:
    void assign(const compiler_generated &):
      arguments:
        - description: __OPTIONAL__
          name: rhs
          type: const compiler_generated &
      description: __INLINED__
      inline:
        description:
          - This definition will force the compiler to auto-generate this class' assignment operator.
      return: __OPTIONAL__
      signature_with_names: void assign(const compiler_generated & rhs)
---


================================================
FILE: docs/libraries/comments.cpp/compiler_generated/m_compiler_generated.md
================================================
---
layout: method
title: compiler_generated
hyde:
  owner: __INLINED__
  brief: __OPTIONAL__
  tags:
    - method
  inline:
    owner: fosterbrereton
  defined_in_file: comments.cpp
  is_ctor: true
  overloads:
    compiler_generated():
      annotation:
        - deleted
      description: __OPTIONAL__
      signature_with_names: compiler_generated()
    compiler_generated(const compiler_generated &):
      annotation:
        - defaulted
      arguments:
        - description: __OPTIONAL__
          name: unnamed-0
          type: const compiler_generated &
          unnamed: true
      description: __OPTIONAL__
      signature_with_names: compiler_generated(const compiler_generated &)
---


================================================
FILE: docs/libraries/comments.cpp/compiler_generated/m_operator3D.md
================================================
---
layout: method
title: operator=
hyde:
  owner: __INLINED__
  brief: __OPTIONAL__
  tags:
    - method
  inline:
    owner: fosterbrereton
  defined_in_file: comments.cpp
  overloads:
    constexpr compiler_generated & operator=(const compiler_generated &):
      annotation:
        - implicit
      arguments:
        - description: __OPTIONAL__
          name: unnamed-0
          type: const compiler_generated &
          unnamed: true
      description: __OPTIONAL__
      return: __OPTIONAL__
      signature_with_names: constexpr compiler_generated & operator=(const compiler_generated &)
---


================================================
FILE: docs/libraries/comments.cpp/f_template_function.md
================================================
---
layout: function
title: template_function
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - function
  inline:
    brief: some template function
  defined_in_file: comments.cpp
  overloads:
    "template <class T>\nT template_function()":
      description: __OPTIONAL__
      inline:
        brief: some template function
        return: an instance of type `T`
      return: __OPTIONAL__
      signature_with_names: "template <class T>\nT template_function()"
---


================================================
FILE: docs/libraries/comments.cpp/index.md
================================================
---
layout: library
title: comments.cpp
hyde:
  owner: __MISSING__
  brief: __MISSING__
  tags:
    - sourcefile
  library-type: sourcefile
---


================================================
FILE: docs/libraries/comments.cpp/some_other_struct/index.md
================================================
---
layout: class
title: some_other_struct
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: This is a sample brief for `some_other_struct`
    description:
      - Notice how many of the comments for this structure are inherited from its superclass.
  defined_in_file: comments.cpp
  declaration: "\nstruct some_other_struct;"
  ctor: unspecified
  dtor: unspecified
---


================================================
FILE: docs/libraries/comments.cpp/some_other_struct/m_operator3D.md
================================================
---
layout: method
title: operator=
hyde:
  owner: __OPTIONAL__
  brief: __OPTIONAL__
  tags:
    - method
  defined_in_file: comments.cpp
  overloads:
    some_other_struct & operator=(const some_other_struct &):
      annotation:
        - implicit
      arguments:
        - description: __OPTIONAL__
          name: unnamed-0
          type: const some_other_struct &
          unnamed: true
      description: __OPTIONAL__
      return: __OPTIONAL__
      signature_with_names: some_other_struct & operator=(const some_other_struct &)
    some_other_struct & operator=(some_other_struct &&):
      annotation:
        - implicit
      arguments:
        - description: __OPTIONAL__
          name: unnamed-0
          type: some_other_struct &&
          unnamed: true
      description: __OPTIONAL__
      return: __OPTIONAL__
      signature_with_names: some_other_struct & operator=(some_other_struct &&)
---


================================================
FILE: docs/libraries/comments.cpp/some_other_struct/m_some_other_struct.md
================================================
---
layout: method
title: some_other_struct
hyde:
  owner: __OPTIONAL__
  brief: __OPTIONAL__
  tags:
    - method
  defined_in_file: comments.cpp
  is_ctor: true
  overloads:
    some_other_struct(const some_other_struct &):
      annotation:
        - implicit
      arguments:
        - description: __OPTIONAL__
          name: unnamed-0
          type: const some_other_struct &
          unnamed: true
      description: __OPTIONAL__
      signature_with_names: some_other_struct(const some_other_struct &)
    some_other_struct(some_other_struct &&):
      annotation:
        - implicit
      arguments:
        - description: __OPTIONAL__
          name: unnamed-0
          type: some_other_struct &&
          unnamed: true
      description: __OPTIONAL__
      signature_with_names: some_other_struct(some_other_struct &&)
---


================================================
FILE: docs/libraries/comments.cpp/some_other_struct/m_virtual_function.md
================================================
---
layout: method
title: virtual_function
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief:
      - A virtual function that intends to be overridden.
  defined_in_file: comments.cpp
  overloads:
    void virtual_function():
      description: __INLINED__
      inline:
        description:
          - A virtual function that intends to be overridden.
      return: __OPTIONAL__
      signature_with_names: void virtual_function()
---


================================================
FILE: docs/libraries/comments.cpp/some_other_struct/m_~some_other_struct.md
================================================
---
layout: method
title: ~some_other_struct
hyde:
  owner: __OPTIONAL__
  brief: __OPTIONAL__
  tags:
    - method
  defined_in_file: comments.cpp
  is_dtor: true
  overloads:
    ~some_other_struct():
      annotation:
        - implicit
      description: __OPTIONAL__
      signature_with_names: ~some_other_struct()
---


================================================
FILE: docs/libraries/comments.cpp/some_struct/index.md
================================================
---
layout: class
title: some_struct
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: This is a sample brief.
    description:
      - An example struct from which these commands will hang.
    owner: fosterbrereton
    par: header This is a sample paragraph.
    see: "[Slides](https://llvm.org/devmtg/2012-11/Gribenko_CommentParsing.pdf) from an LLVM dev meeting chat on the comment parsing feature"
    warning: This is a sample warning.
  defined_in_file: comments.cpp
  declaration: "\nstruct some_struct;"
  ctor: unspecified
  fields:
    _x:
      description: __INLINED__
      inline:
        description:
          - A trailing comment that documents `_x`.
      type: int
---


================================================
FILE: docs/libraries/comments.cpp/some_struct/m_operator3D.md
================================================
---
layout: method
title: operator=
hyde:
  owner: __INLINED__
  brief: __OPTIONAL__
  tags:
    - method
  inline:
    owner: fosterbrereton
  defined_in_file: comments.cpp
  overloads:
    some_struct & operator=(const some_struct &):
      annotation:
        - implicit
      arguments:
        - description: __OPTIONAL__
          name: unnamed-0
          type: const some_struct &
          unnamed: true
      description: __OPTIONAL__
      return: __OPTIONAL__
      signature_with_names: some_struct & operator=(const some_struct &)
---


================================================
FILE: docs/libraries/comments.cpp/some_struct/m_some_function.md
================================================
---
layout: method
title: some_function
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief: A function that does a thing, and does it well.
    owner: fosterbrereton
  defined_in_file: comments.cpp
  overloads:
    int some_function(int, int &, int &):
      arguments:
        - description: __OPTIONAL__
          name: input
          type: int
        - description: __OPTIONAL__
          name: input_output
          type: int &
        - description: __OPTIONAL__
          name: output
          type: int &
      description: __INLINED__
      inline:
        arguments:
          input:
            description: an input parameter
            direction: in
          input_output:
            description: a bidirectional parameter
            direction: inout
          output:
            description: an output parameter
            direction: out
        brief: A function that does a thing, and does it well.
        description:
          - This is a longer description of this function that does things as well as it does. Notice how long this comment is! So impressive. 💥
        post: An example postcondition.
        pre: An example precondition.
        return: Some additional value.
        throw: "`std::runtime_error` if the function actually _can't_ do the thing. Sorry!"
        todo: This really could use some cleanup. Although, its implementation doesn't exist...
        warning: This function may be very expensive to run. Do not call it inside a loop.
      return: __OPTIONAL__
      signature_with_names: int some_function(int input, int & input_output, int & output)
---


================================================
FILE: docs/libraries/comments.cpp/some_struct/m_some_struct.md
================================================
---
layout: method
title: some_struct
hyde:
  owner: __INLINED__
  brief: __OPTIONAL__
  tags:
    - method
  inline:
    owner: fosterbrereton
  defined_in_file: comments.cpp
  is_ctor: true
  overloads:
    some_struct(const some_struct &):
      annotation:
        - implicit
      arguments:
        - description: __OPTIONAL__
          name: unnamed-0
          type: const some_struct &
          unnamed: true
      description: __OPTIONAL__
      signature_with_names: some_struct(const some_struct &)
---


================================================
FILE: docs/libraries/comments.cpp/some_struct/m_virtual_function.md
================================================
---
layout: method
title: virtual_function
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief:
      - A virtual function that intends to be overridden.
    owner: fosterbrereton
  defined_in_file: comments.cpp
  overloads:
    void virtual_function():
      description: __INLINED__
      inline:
        description:
          - A virtual function that intends to be overridden.
      return: __OPTIONAL__
      signature_with_names: void virtual_function()
---


================================================
FILE: docs/libraries/comments.cpp/some_struct/m_~some_struct.md
================================================
---
layout: method
title: ~some_struct
hyde:
  owner: __INLINED__
  brief: __OPTIONAL__
  tags:
    - method
  inline:
    owner: fosterbrereton
  defined_in_file: comments.cpp
  is_dtor: true
  overloads:
    ~some_struct():
      annotation:
        - deleted
      description: __OPTIONAL__
      signature_with_names: ~some_struct()
---


================================================
FILE: docs/libraries/enums.cpp/color_channel.md
================================================
---
layout: enumeration
title: color_channel
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - enumeration
  inline:
    brief: An example typed enumeration with three values.
    owner: fosterbrereton
  defined_in_file: enums.cpp
  values:
    - description: __INLINED__
      inline:
        description:
          - Red commentary
      name: red
    - description: __INLINED__
      inline:
        description:
          - Green commentary. Note this enum has a pre-set value.
      name: green
    - description: __INLINED__
      inline:
        description:
          - Blue commentary
      name: blue
---


================================================
FILE: docs/libraries/enums.cpp/index.md
================================================
---
layout: library
title: enums.cpp
hyde:
  owner: __MISSING__
  brief: __MISSING__
  tags:
    - sourcefile
  library-type: sourcefile
---


================================================
FILE: docs/libraries/enums.cpp/untyped.md
================================================
---
layout: enumeration
title: untyped
hyde:
  owner: __INLINED__
  brief: __INLINED__
  tags:
    - enumeration
  inline:
    brief: An example untyped enumeration with three values.
    owner: fosterbrereton
  defined_in_file: enums.cpp
  values:
    - description: __INLINED__
      inline:
        description:
          - Apple commentary
      name: apple
    - description: __INLINED__
      inline:
        description:
          - Orange commentary
      name: orange
    - description: __INLINED__
      inline:
        description:
          - Banana commentary
      name: banana
---


================================================
FILE: docs/libraries/functions.cpp/f_binary_function_example.md
================================================
---
layout: function
title: binary_function_example
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - function
  inline:
    brief:
      - an example binary function.
  defined_in_file: functions.cpp
  overloads:
    int binary_function_example(int, int):
      arguments:
        - description: __OPTIONAL__
          name: first
          type: int
        - description: __OPTIONAL__
          name: second
          type: int
      description: __INLINED__
      inline:
        arguments:
          first:
            description: the first input
          second:
            description: the second input
        description:
          - an example binary function.
        return: The sum of the two input parameters.
      return: __OPTIONAL__
      signature_with_names: int binary_function_example(int first, int second)
---


================================================
FILE: docs/libraries/functions.cpp/f_nullary_function_example.md
================================================
---
layout: function
title: nullary_function_example
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - function
  inline:
    brief:
      - an example nullary function.
  defined_in_file: functions.cpp
  overloads:
    int nullary_function_example():
      description: __INLINED__
      inline:
        description:
          - an example nullary function.
        return: "`0`"
      return: __OPTIONAL__
      signature_with_names: int nullary_function_example()
---


================================================
FILE: docs/libraries/functions.cpp/f_overloaded.md
================================================
---
layout: function
title: overloaded
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - function
  inline:
    brief: _multiple descriptions_
  defined_in_file: functions.cpp
  overloads:
    auto overloaded(int) -> float:
      arguments:
        - description: __OPTIONAL__
          name: first
          type: int
      description: __INLINED__
      inline:
        arguments:
          first:
            description: the first input parameter
        description:
          - an example unary overloaded function
        return: "`first`"
      return: __OPTIONAL__
      signature_with_names: auto overloaded(int first) -> float
    auto overloaded(int, int) -> double:
      arguments:
        - description: __OPTIONAL__
          name: first
          type: int
        - description: __OPTIONAL__
          name: second
          type: int
      description: __INLINED__
      inline:
        arguments:
          first:
            description: the first input parameter
          second:
            description: the second input parameter
        description:
          - an example binary overloaded function
        return: the product of `first` and `second`
      return: __OPTIONAL__
      signature_with_names: auto overloaded(int first, int second) -> double
    auto overloaded(int, int, int) -> float:
      arguments:
        - description: __OPTIONAL__
          name: first
          type: int
        - description: __OPTIONAL__
          name: second
          type: int
        - description: __OPTIONAL__
          name: third
          type: int
      description: __INLINED__
      inline:
        arguments:
          first:
            description: the first input parameter
          second:
            description: the second input parameter
          third:
            description: the third input parameter
        description:
          - an example tertiary overloaded function
        return: the product of `first`, `second`, and `third`
      return: __OPTIONAL__
      signature_with_names: auto overloaded(int first, int second, int third) -> float
---


================================================
FILE: docs/libraries/functions.cpp/f_static_auto_function_example.md
================================================
---
layout: function
title: static_auto_function_example
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - function
  inline:
    brief:
      - an example static function with `auto` return type
  defined_in_file: functions.cpp
  overloads:
    static int static_auto_function_example():
      description: __INLINED__
      inline:
        description:
          - an example static function with `auto` return type
        return: "`0`"
      return: __OPTIONAL__
      signature_with_names: static int static_auto_function_example()
---


================================================
FILE: docs/libraries/functions.cpp/f_static_function_example.md
================================================
---
layout: function
title: static_function_example
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - function
  inline:
    brief:
      - an example static function
  defined_in_file: functions.cpp
  overloads:
    static int static_function_example():
      description: __INLINED__
      inline:
        description:
          - an example static function
        return: "`0`"
      return: __OPTIONAL__
      signature_with_names: static int static_function_example()
---


================================================
FILE: docs/libraries/functions.cpp/f_static_trailing_type_function_example.md
================================================
---
layout: function
title: static_trailing_type_function_example
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - function
  inline:
    brief:
      - an example static function with trailing return type
  defined_in_file: functions.cpp
  overloads:
    static auto static_trailing_type_function_example() -> int:
      description: __INLINED__
      inline:
        description:
          - an example static function with trailing return type
        return: "`0`"
      return: __OPTIONAL__
      signature_with_names: static auto static_trailing_type_function_example() -> int
---


================================================
FILE: docs/libraries/functions.cpp/f_template_function_example.md
================================================
---
layout: function
title: template_function_example
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - function
  inline:
    brief: _multiple descriptions_
  defined_in_file: functions.cpp
  overloads:
    int template_function_example():
      description: __INLINED__
      inline:
        description:
          - an example specialization of the template function example
        return: Forty-two
      return: __OPTIONAL__
      signature_with_names: int template_function_example()
    "template <class T>\nT template_function_example()":
      description: __INLINED__
      inline:
        description:
          - an example template function, deleted by default
        return: Not applicable, seeing that the default definition has been deleted.
      return: __OPTIONAL__
      signature_with_names: "template <class T>\nT template_function_example()"
---


================================================
FILE: docs/libraries/functions.cpp/index.md
================================================
---
layout: library
title: functions.cpp
hyde:
  owner: __MISSING__
  brief: __MISSING__
  tags:
    - sourcefile
  library-type: sourcefile
---


================================================
FILE: docs/libraries/index.md
================================================
---
layout: library
title: Hyde Sample Docs
hyde:
  owner: fosterbrereton
  brief: Sample Hyde Documentation
  tags:
    - library
  library-type: library
  icon: book
  short_title: Sample Docs
  tab: Docs
---


================================================
FILE: docs/libraries/namespaces.cpp/f_function.md
================================================
---
layout: function
title: function
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - function
  inline:
    brief: _multiple descriptions_
  defined_in_file: namespaces.cpp
  overloads:
    void function():
      description: __INLINED__
      inline:
        description:
          - function contained within namespace `foo`.
      return: __OPTIONAL__
      signature_with_names: void function()
  namespace:
    - foo
    - bar
    - baz
---


================================================
FILE: docs/libraries/namespaces.cpp/index.md
================================================
---
layout: library
title: namespaces.cpp
hyde:
  owner: __MISSING__
  brief: __MISSING__
  tags:
    - sourcefile
  library-type: sourcefile
---


================================================
FILE: docs/libraries/point.cpp/index.md
================================================
---
layout: library
title: point.cpp
hyde:
  owner: __MISSING__
  brief: __MISSING__
  tags:
    - sourcefile
  library-type: sourcefile
---


================================================
FILE: docs/libraries/point.cpp/point3CT3E/f_operator-.md
================================================
---
layout: function
title: operator-
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - function
  inline:
    brief:
      - Subtraction operator.
  defined_in_file: point.cpp
  overloads:
    constexpr point<T> operator-(const point<T> &, const point<T> &):
      arguments:
        - description: __OPTIONAL__
          name: a
          type: const point<T> &
        - description: __OPTIONAL__
          name: b
          type: const point<T> &
      description: __INLINED__
      inline:
        arguments:
          a:
            description: The point to be subtracted from.
          b:
            description: The point to subtract.
        description:
          - Subtraction operator.
        return: A new point whose axis values are subtractions of the two inputs' axis values.
      return: __OPTIONAL__
      signature_with_names: constexpr point<T> operator-(const point<T> & a, const point<T> & b)
---


================================================
FILE: docs/libraries/point.cpp/point3CT3E/f_operator213D.md
================================================
---
layout: function
title: operator!=
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - function
  inline:
    brief:
      - Inequality operator.
  defined_in_file: point.cpp
  overloads:
    constexpr bool operator!=(const point<T> &, const point<T> &):
      arguments:
        - description: __OPTIONAL__
          name: a
          type: const point<T> &
        - description: __OPTIONAL__
          name: b
          type: const point<T> &
      description: __INLINED__
      inline:
        description:
          - Inequality operator.
        return: "`true` iff the two points' `x` or `y` coordinates are memberwise inequal."
      return: __OPTIONAL__
      signature_with_names: constexpr bool operator!=(const point<T> & a, const point<T> & b)
---


================================================
FILE: docs/libraries/point.cpp/point3CT3E/f_operator3D3D.md
================================================
---
layout: function
title: operator==
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - function
  inline:
    brief:
      - Equality operator.
  defined_in_file: point.cpp
  overloads:
    constexpr bool operator==(const point<T> &, const point<T> &):
      arguments:
        - description: __OPTIONAL__
          name: a
          type: const point<T> &
        - description: __OPTIONAL__
          name: b
          type: const point<T> &
      description: __INLINED__
      inline:
        description:
          - Equality operator.
        return: "`true` iff the two points' `x` and `y` coordinates are memberwise equal."
      return: __OPTIONAL__
      signature_with_names: constexpr bool operator==(const point<T> & a, const point<T> & b)
---


================================================
FILE: docs/libraries/point.cpp/point3CT3E/index.md
================================================
---
layout: class
title: point<T>
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: An example point class
  defined_in_file: point.cpp
  declaration: "template <class T>\nstruct point;"
  dtor: unspecified
  fields:
    x:
      description: __INLINED__
      inline:
        description:
          - The `x` coordinate of the point.
      type: T
    y:
      description: __INLINED__
      inline:
        description:
          - The `y` coordinate of the point.
      type: T
---


================================================
FILE: docs/libraries/point.cpp/point3CT3E/m_operator-3D.md
================================================
---
layout: method
title: operator-=
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief:
      - Subtraction-assignment operator.
  defined_in_file: point.cpp
  overloads:
    constexpr point<T> & operator-=(const point<T> &):
      arguments:
        - description: __OPTIONAL__
          name: a
          type: const point<T> &
      description: __INLINED__
      inline:
        arguments:
          a:
            description: The point to subtract from this point
        description:
          - Subtraction-assignment operator.
        return: A reference to `this`.
      return: __OPTIONAL__
      signature_with_names: constexpr point<T> & operator-=(const point<T> & a)
---


================================================
FILE: docs/libraries/point.cpp/point3CT3E/m_origin.md
================================================
---
layout: method
title: origin
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief:
      - A static routine that returns the origin point.
  defined_in_file: point.cpp
  overloads:
    constexpr static auto origin():
      description: __INLINED__
      inline:
        description:
          - A static routine that returns the origin point.
        return: The point `(0, 0)`
      return: __OPTIONAL__
      signature_with_names: constexpr static auto origin()
---


================================================
FILE: docs/libraries/point.cpp/point3CT3E/m_point3CT3E.md
================================================
---
layout: method
title: point<T>
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - method
  inline:
    brief: _multiple descriptions_
  defined_in_file: point.cpp
  is_ctor: true
  overloads:
    point<T>():
      annotation:
        - defaulted
      description: __INLINED__
      inline:
        description:
          - Default constructor of default definition.
      signature_with_names: point<T>()
    point<T>(T, T):
      arguments:
        - description: __OPTIONAL__
          name: _x
          type: T
        - description: __OPTIONAL__
          name: _y
          type: T
      description: __INLINED__
      inline:
        arguments:
          _x:
            description: The `x` coordinate to sink.
          _y:
            description: The `y` coordinate to sink.
        description:
          - Value-based constructor that takes `x` and `y` values and sinks them into place.
      signature_with_names: point<T>(T _x, T _y)
---


================================================
FILE: docs/libraries/typedef_and_alias.cpp/index.md
================================================
---
layout: library
title: typedef_and_alias.cpp
hyde:
  owner: __MISSING__
  brief: __MISSING__
  tags:
    - sourcefile
  library-type: sourcefile
  typedefs:
    typedef_example:
      definition: int
      description: __INLINED__
      inline:
        description:
          - Example typedef expression whose underlying type is `int`.
    typedef_full_specialization_example:
      definition: using_partial_specialization_example<double>
      description: __INLINED__
      inline:
        description:
          - Using typedef to define another full specialization of the above partial specialization
    using_example:
      definition: int
      description: __INLINED__
      inline:
        description:
          - Example using expression whose underlying type is `int`.
    using_full_specialization_example:
      definition: using_partial_specialization_example<bool>
      description: __INLINED__
      inline:
        description:
          - Full specialization of the above partial specialization
    using_partial_specialization_example:
      definition: template_example<bool, U>
      description: __INLINED__
      inline:
        description:
          - Partial specialization of the above `template_example` template
---


================================================
FILE: docs/libraries/typedef_and_alias.cpp/template_example3CT2C20U3E/index.md
================================================
---
layout: class
title: template_example<T, U>
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: Example class with two type definitions
  defined_in_file: typedef_and_alias.cpp
  declaration: "template <typename T, typename U>\nstruct template_example;"
  ctor: unspecified
  dtor: unspecified
  typedefs:
    typedef_from_T:
      definition: T
      description: __INLINED__
      inline:
        description:
          - Type derived from the first template parameter.
    using_from_U:
      definition: U
      description: __INLINED__
      inline:
        description:
          - Type derived from the second template parameter.
---


================================================
FILE: docs/libraries/typedef_and_alias.cpp/template_example_instantiator/index.md
================================================
---
layout: class
title: template_example_instantiator
hyde:
  owner: __MISSING__
  brief: __INLINED__
  tags:
    - class
  inline:
    brief: Example struct that leverages type aliases defined above.
  defined_in_file: typedef_and_alias.cpp
  declaration: "\nstruct template_example_instantiator;"
  ctor: unspecified
  dtor: unspecified
  typedefs:
    typedef_full_specialization_example:
      definition: using_partial_specialization_example<double>
      description: __INLINED__
      inline:
        description:
          - Example partial specialization using `typedef`
    using_full_specialization_example:
      definition: using_partial_specialization_example<bool>
      description: __INLINED__
      inline:
        description:
          - Example full specialization
---


================================================
FILE: docs/serve.sh
================================================
#!/bin/bash

bundle exec jekyll serve --watch


================================================
FILE: emitters/yaml_base_emitter.cpp
================================================
/*
Copyright 2018 Adobe
All Rights Reserved.

NOTICE: Adobe permits you to use, modify, and distribute this file in
accordance with the terms of the Adobe license agreement accompanying
it. If you have received this file from a source other than Adobe,
then your use, modification, or distribution of it requires the prior
written permission of Adobe.
*/

// identity
#include "yaml_base_emitter.hpp"

// stdc++
#include <fstream>
#include <iostream>

// yaml-cpp
#include "yaml-cpp/yaml.h"

// application
#include "emitters/yaml_base_emitter_fwd.hpp"
#include "json.hpp"
#include "matchers/utilities.hpp"

/**************************************************************************************************/

namespace {

/**************************************************************************************************/

static const hyde::json no_json_k;
static const hyde::json inline_json_k(hyde::tag_value_inlined_k);

/**************************************************************************************************/

YAML::Node update_cleanup(const YAML::Node& node) {
    YAML::Node result;

    if (node.IsScalar() && node.Scalar() != hyde::tag_value_deprecated_k) {
        result = node;
    } else if (node.IsSequence()) {
        const auto count = node.size();
        for (std::size_t i{0}; i < count; ++i) {
            YAML::Node subnode = update_cleanup(node[i]);
            if (!subnode.IsNull()) {
                result.push_back(std::move(subnode));
            }
        }
    } else if (node.IsMap()) {
        for (const auto& pair : node) {
            const auto& key = pair.first.Scalar();
            YAML::Node subnode = update_cleanup(node[key]);
            if (!subnode.IsNull()) {
                result[key] = std::move(subnode);
            }
        }
    }

    return result;
}

/**************************************************************************************************/

hyde::json yaml_to_json(const YAML::Node& yaml) {
    switch (yaml.Type()) {
        case YAML::NodeType::Null: {
            return hyde::json();
        } break;
        case YAML::NodeType::Scalar: {
            return yaml.Scalar();
        } break;
        case YAML::NodeType::Sequence: {
            hyde::json result = hyde::json::array();
            for (std::size_t i{0}, count{yaml.size()}; i < count; ++i) {
                result.emplace_back(yaml_to_json(yaml[i]));
            }
            return result;
        } break;
        case YAML::NodeType::Map: {
            hyde::json result = hyde::json::object();
            for (auto iter{yaml.begin()}, last{yaml.end()}; iter != last; ++iter) {
                if (!iter->first.IsScalar()) throw std::runtime_error("key is not scalar?");
                result[iter->first.Scalar()] = yaml_to_json(iter->second);
            }
            return result;
        } break;
        case YAML::NodeType::Undefined: {
            throw std::runtime_error("YAML is not defined!");
        } break;
    }
    return hyde::json();
}

/**************************************************************************************************/

YAML::Node json_to_yaml(const hyde::json& json) {
    switch (json.type()) {
        case hyde::json::value_t::null: {
            return YAML::Node();
        } break;
        case hyde::json::value_t::string: {
            return YAML::Node(static_cast<const std::string&>(json));
        } break;
        case hyde::json::value_t::array: {
            YAML::Node result;
            for (const auto& n : json) {
                result.push_back(json_to_yaml(n));
            }
            return result;
        } break;
        case hyde::json::value_t::object: {
            YAML::Node result;
            for (auto it = json.begin(); it != json.end(); ++it) {
                result[it.key()] = json_to_yaml(it.value());
            }
            return result;
        } break;
        case hyde::json::value_t::boolean: {
            return YAML::Node(json.get<bool>());
        } break;
        case hyde::json::value_t::number_integer: {
            return YAML::Node(json.get<int>());
        } break;
        case hyde::json::value_t::number_unsigned: {
            return YAML::Node(json.get<unsigned int>());
        } break;
        case hyde::json::value_t::number_float: {
            return YAML::Node(json.get<float>());
        } break;
        case hyde::json::value_t::binary: {
            throw std::runtime_error("Binary JSON value unsupported");
        } break;
        case hyde::json::value_t::discarded: {
            throw std::runtime_error("Discarded JSON value");
        } break;
    }
    return YAML::Node();
}

/**************************************************************************************************/

YAML::Node json_to_yaml_ordered(hyde::json j) {
    // YAML preserves the order of addition, while JSON orders lexicographically
    // by key value. We want the values common to all jekyll pages to appear
    // higher in the YAML than other keys, so we do a specific ordering here.

    YAML::Node result;

    const auto move_key = [&](const std::string& key) {
        if (!j.count(key)) return;
        result[key] = json_to_yaml(j[key]);
        j.erase(key);
    };

    // These are in some ROUGH order/grouping from generic to specific fields.

    move_key("layout");
    move_key("title");
    move_key("owner");
    move_key("brief");
    move_key("tags");
    move_key("inline");
    move_key("library-type");
    move_key("defined_in_file");
    move_key("declaration");
    move_key("annotation");

    move_key("ctor");
    move_key("dtor");
    move_key("is_ctor");
    move_key("is_dtor");

    move_key("typedefs");
    move_key("fields");
    move_key("methods");
    move_key("overloads");

    if (j.count("hyde")) {
        result["hyde"] = json_to_yaml_ordered(j["hyde"]);
        j.erase("hyde");
    }

    // copy over the remainder of the keys.
    for (auto it = j.begin(); it != j.end(); ++it) {
        result[it.key()] = json_to_yaml(it.value());
    }

    return result;
}

/**************************************************************************************************/
// See Issue #75 and PR #80. Take the relevant hyde fields and move them under a top-level
// `hyde` subfield. Only do this when we're asked to, in case this has already been done and those
// high-level fields are used by something else. When we do this fixup, we don't know which fields
// hyde actually uses, so this will move _all_ fields that are not `layout` and `title`.
hyde::json fixup_hyde_subfield(hyde::json&& j) {
    hyde::json result;

    if (j.count("layout")) {
        result["layout"] = std::move(j.at("layout"));
        j.erase("layout");
    }

    if (j.count("title")) {
        result["title"] = std::move(j.at("title"));
        j.erase("title");
    }

    // If a fixup has already been done, or there are already fields in the `hyde` subobject,
    // move them before going on to the next step.
    if (j.count("hyde")) {
        result["hyde"] = std::move(j.at("hyde"));
        j.erase("hyde");
    }

    // For any keys that are left over in `j`, move them under the `hyde` subobject. Note that
    // this will overwrite any conflicting keys that may already exist there.
    for (auto& entry : j.items()) {
        result["hyde"][entry.key()] = std::move(entry.value());
    }

    return result;
}

/**************************************************************************************************/

static const std::string front_matter_begin_k("---\n");

// Using a string wrapped in newlines because some YAML data may contain "---" in them
// (e.g., inline comments that have sucked up a horizontal delimiter.)
static const std::string front_matter_end_k("\n---\n");

/**************************************************************************************************/

} // namespace

/**************************************************************************************************/

namespace hyde {

/**************************************************************************************************/

file_checker yaml_base_emitter::checker_s; // REVISIT (fbrereto) : Global. Bad programmer. No donut.

/**************************************************************************************************/

json yaml_base_emitter::base_emitter_node(std::string layout,
                                          std::string title,
                                          std::string tag,
                                          bool implicit) {
    json node;

    node["layout"] = std::move(layout);
    node["title"] = std::move(title);

    const auto& default_tag_value = implicit ? tag_value_optional_k : tag_value_missing_k;

    node["hyde"]["owner"] = default_tag_value;
    node["hyde"]["tags"].emplace_back(std::move(tag));
    node["hyde"]["brief"] = default_tag_value;
    node["hyde"]["version"] = hyde_version();

    return node;
}

/**************************************************************************************************/

void yaml_base_emitter::insert_doxygen(const json& j, json& node) {
    if (!j.count("comments")) return;

    const auto& comments = j.at("comments");
    auto& output = node["inline"];

    if (comments.count("command")) {
        for (const auto& item : comments.at("command").items()) {
            const auto& command = item.value();
            std::string key = command["name"].get<std::string>();
            if (key.starts_with("hyde-")) {
                key = key.substr(5);
            }
            output[key] = command["text"].get<std::string>();
        }
    }

    if (comments.count("paragraph")) {
        json::array_t paragraphs;
        for (const auto& paragraph : comments.at("paragraph").items()) {
            paragraphs.push_back(paragraph.value().at("text"));
        }
        output["description"] = std::move(paragraphs);
    }

    if (comments.count("param")) {
        json::object_t arguments;
        for (const auto& item : comments.at("param").items()) {
            const auto& param = item.value();
            const auto& name = param["name"].get<std::string>();
            json::object_t argument;
            if (param["direction_explicit"].get<bool>()) {
                argument["direction"] = param["direction"];
            }
            argument["description"] = param["text"];
            arguments[name] = std::move(argument);
        }
        output["arguments"] = std::move(arguments);
    }
}

/**************************************************************************************************/

void yaml_base_emitter::insert_typedefs(const json& j, json& node, const json& inherited) {
    if (j.count("typedefs")) {
        for (const auto& type_def : j["typedefs"]) {
            const std::string& key = type_def["name"];
            auto& type_node = node["hyde"]["typedefs"][key];
            insert_inherited(inherited, type_node);
            insert_annotations(type_def, type_node);
            insert_doxygen(type_def, type_node);

            type_node["definition"] = static_cast<const std::string&>(type_def["type"]);
            type_node["description"] = has_inline_field(type_node, "description") ?
                                           tag_value_inlined_k :
                                           tag_value_missing_k;
        }
    }

    if (j.count("typealiases")) {
        for (const auto& type_def : j["typealiases"]) {
            const std::string& key = type_def["name"];
            auto& type_node = node["hyde"]["typedefs"][key];
            insert_inherited(inherited, type_node);
            insert_annotations(type_def, type_node);
            insert_doxygen(type_def, type_node);

            type_node["definition"] = static_cast<const std::string&>(type_def["type"]);
            type_node["description"] = has_inline_field(type_node, "description") ?
                                           tag_value_inlined_k :
                                           tag_value_missing_k;
        }
    }
}

/**************************************************************************************************/

void yaml_base_emitter::check_inline_comments(const json& expected, json& out_merged) {
    // inline comments *always* come from the sources. Therefore, they are always overwritten in the
    // merge.
    if (expected.count("inline")) {
        out_merged["inline"] = expected.at("inline");
    }
}

/**************************************************************************************************/

bool yaml_base_emitter::check_typedefs(const std::string& filepath,
                                       const json& have_node,
                                       const json& expected_node,
                                       const std::string& nodepath,
                                       json& merged_node) {
    return check_map(
        filepath, have_node, expected_node, nodepath, merged_node, "typedefs",
        [this](const std::string& filepath, const json& have, const json& expected,
               const std::string& nodepath, json& out_merged) {
            bool failure{false};

            failure |= check_scalar(filepath, have, expected, nodepath, out_merged, "name");
            failure |= check_scalar(filepath, have, expected, nodepath, out_merged, "definition");
            failure |= check_editable_scalar(filepath, have, expected, nodepath, out_merged,
                                             "description");
            failure |=
                check_scalar_array(filepath, have, expected, nodepath, out_merged, "annotation");

            check_inline_comments(expected, out_merged);

            return failure;
        });
}

/**************************************************************************************************/

void yaml_base_emitter::check_notify(const std::string& filepath,
                                     const std::string& nodepath,
                                     const std::string& key,
                                     const std::string& validate_message,
                                     const std::string& update_message) {
    std::string escaped_nodepath = hyde::ReplaceAll(nodepath, "\n", "\\n");
    std::string escaped_key = hyde::ReplaceAll(key, "\n", "\\n");

    switch (_mode) {
        case yaml_mode::validate: {
            std::cerr << filepath << "@" << escaped_nodepath << "['" << escaped_key
                      << "']: " << validate_message << "\n";
        } break;
        case yaml_mode::transcribe:
        case yaml_mode::update: {
            std::cout << filepath << "@" << escaped_nodepath << "['" << escaped_key
                      << "']: " << update_message << "\n";
        } break;
    }
}

/**************************************************************************************************/

bool yaml_base_emitter::check_removed(const std::string& filepath,
                                      const json& have_node,
                                      const std::string& nodepath,
                                      const std::string& key) {
    if (!have_node.count(key)) {
        // Removed key not present in have. Do nothing, no error.
        return false;
    } else {
        check_notify(filepath, nodepath, key, "value present for removed key", "value removed");
        return true;
    }
}

/**************************************************************************************************/

bool yaml_base_emitter::check_scalar(const std::string& filepath,
                                     const json& have_node,
                                     const json& expected_node,
                                     const std::string& nodepath,
                                     json& merged_node,
                                     const std::string& key) {
    const auto notify = [&](const std::string& validate_message,
                            const std::string& update_message) {
        check_notify(filepath, nodepath, key, validate_message, update_message);
    };

    if (!expected_node.count(key)) {
        return check_removed(filepath, have_node, nodepath, key);
    }

    const json& expected = expected_node[key];

    if (!expected.is_primitive()) {
        throw std::runtime_error("expected type mismatch?");
    }

    json& result = merged_node[key];

    if (!have_node.count(key)) {
        notify("value missing", "value inserted");
        result = expected;
        return true;
    }

    const json& have = have_node[key];

    if (have != expected) {
        result = expected;

        // Since yaml <-> json type conversions aren't perfect (at least with the libraries we are
        // currently using), we will only report a failure if the yaml-serialized value is different
        auto have_yaml = json_to_yaml(have).as<std::string>();
        auto expected_yaml = json_to_yaml(expected).as<std::string>();
        if (have_yaml != expected_yaml) {
            notify("value mismatch; have `" + have.dump() + "`, expected `" + expected.dump() + "`",
                   "value updated from `" + have.dump() + "` to `" + expected.dump() + "`");
            return true;
        }
    }

    // both have and expected are both scalar and are the same value
    result = have;
    return false;
}

/**************************************************************************************************/
// The intent of this routine is to arrive at the ideal output given the various bits of state the
// engine has available to it. The two major players are `have` (the data that has been parsed out
// of documentation that already exists) and `expected` (the data derived by the engine from
// compiling the source file). In addition to user-entered values in the `have` data, there are a
// handful of predefined values for the key that also play a part (missing, inlined, deprecated,
// etc.) Both `have` and `expected` come in as json blobs that might contain an entry under `key`.
// The goal is to affect `merged_node` (which is also a json blob) under that same `key`. I
// say "affect" because it doesn't always mean setting a value to the output - sometimes it's
// the _removal_ of said key. Hopefully this all is made more clear by the path outlined below.
//
// It's worth adding a comment about "associated inline" values. To start, this is data extracted
// from the source file's Doxygen-formatted inline comments (hence the term). Therefore, this data
// is _always_ derived, and _never_ modified by `have`. Thus, if inline values exist, they are
// always copied from `expected` into the merged output. In order for an inline value to be
// considered "associated" with a given entry `expected[key]`, the value must exist under `expected
// ["inline"][key]`. The associated value type is not always a string (for example, inline comments
// can be an array of strings _or_ a single string. Those value type differences need to be
// accounted for in the Jekyll theme that will be displaying that data - we don't care about them
// here.)
//
// A word on the "special" values. These are placeholder string values that, depending on their
// individual semantics, will affect how the final documentation is displayed:
//     - __MISSING__: This is the value most developers will be familiar with. In order for the
//         documentation to pass validation, all __MISSING__ fields must be manually filled in.
//     - __OPTIONAL__: This field's value is not required for validation and will be shown if
//         manually filled in. Among other cases, this value is used when a declaration is implicit
//         (e.g., compiler-implemented, v. defined in the source code.)
//     - __DEPRECATED__: This field will be found in `expected`, and will cause the equivalent field
//         in `have` to be removed.
//     - __INLINED__: The value _would_ be __MISSING__ except that there is an associated inline
//         value for the field, and thus the minimum requirement for documentation has been met,
//         and validation will pass for this field. Users are allowed to replace this value should
//         they want to add further documentation.
//
// These `check_` routines are used for both the validation and update phases. Their logic is the
// same, but how they behave will differ (e.g., inserting a value [updating] v. reporting a value
// missing [validating].)
//
// The logical gist of this routine is as follows:
//     - If `expected[key]` doesn't exist, make sure `have[key]` doesn't either. Done.
//     - If `expected[key]` isn't a string, we're in the wrong routine. Done. In other words, all
//       hyde scalars are strings.
//     - If `expected[key]` has an associated inline value, set `default_value` to __INLINED__
//         - Otherwise, set `default_value` to __MISSING__
//     - If `have[key]` does not exist, the result is `default_value`. Done.
//     - If `have[key]` is not a scalar, the result is `default_value`. Done.
//     - If both `expected[key]` and `have[key]` are __MISSING__, the result is
//       `default_value`. Done.
//     - If `expected[key]` is __DEPRECATED__, result is no output. Done.
//     - If `expected[key]` and `have[key]` are both __OPTIONAL__, result is __OPTIONAL__. Done.
//     - If `have[key]` is a special tag value, result is `default_value`. Done.
//     - Otherwise, result is `have[key]`. Done.

bool yaml_base_emitter::check_editable_scalar(const std::string& filepath,
                                              const json& have_node,
                                              const json& expected_node,
                                              const std::string& nodepath,
                                              json& merged_node,
                                              const std::string& key) {
    const auto notify = [&](const std::string& validate_message,
                            const std::string& update_message) {
        check_notify(filepath, nodepath, key, validate_message, update_message);
    };

    if (!expected_node.count(key)) {
        return check_removed(filepath, have_node, nodepath, key);
    }

    const json& expected = expected_node[key];
    const bool has_associated_inline_value = has_inline_field(expected_node, key.c_str());

    if (!expected.is_string()) {
        throw std::runtime_error("expected type mismatch?");
    }

    const std::string& expected_scalar(expected);
    const bool expected_set_to_missing = expected_scalar == tag_value_missing_k;
    const bool use_inline_value = expected_set_to_missing && has_associated_inline_value;
    const json& default_value = use_inline_value ? inline_json_k : expected;
    const std::string& default_value_scalar(default_value);

    json& result = merged_node[key];

    if (!have_node.count(key)) {
        if (expected_scalar == tag_value_deprecated_k) {
            // deprecated key not present in have. Do nothing, no error.
            return false;
        } else {
            notify("value missing", "value inserted");
            result = default_value;
            return true;
        }
    }

    const json& have = have_node[key];

    if (!have.is_string()) {
        notify("value not scalar; expected `" + default_value_scalar + "`",
               "value not scalar; updated to `" + default_value_scalar + "`");
        result = default_value;
        return true;
    }

    const std::string& have_scalar(have);

    if (default_value_scalar == tag_value_missing_k && have_scalar == tag_value_missing_k) {
        result = default_value;
        if (_mode == yaml_mode::validate) {
            notify("value not documented", "");
        }
        return true;
    }

    if (expected_scalar == tag_value_deprecated_k) {
        notify("key is deprecated", "deprecated key removed");
        return true;
    }

    // If the scalars are identical, they're both equal tags at this point. Done.
    if (default_value_scalar == have_scalar) {
        result = have;
        return false;
    }

    // Among other cases, this check will handle when tags go from __MISSING__ to __INLINED__ and
    // vice versa.
    if (hyde::is_tag(have_scalar)) {
        notify("found unexpected tag `" + have_scalar + "`",
               "tag updated from `" + have_scalar + "` to `" + default_value_scalar + "`");
        // Replace unexpected tag?
        result = default_value;
        return true;
    }

    // The docs have *something*, so we're good.
    result = have;
    return false;
}

/**************************************************************************************************/

bool yaml_base_emitter::check_editable_scalar_array(const std::string& filepath,
                                                    const json& have_node,
                                                    const json& expected_node,
                                                    const std::string& nodepath,
                                                    json& merged_node,
                                                    const std::string& key) {
    const auto notify = [&](const std::string& validate_message,
                            const std::string& update_message) {
        check_notify(filepath, nodepath, key, validate_message, update_message);
    };

    const auto notify_fail = [&](const std::string& message) {
        check_notify(filepath, nodepath, key, message, message);
    };

    if (!expected_node.count(key)) {
        return check_removed(filepath, have_node, nodepath, key);
    }

    const json& expected = expected_node[key];

    if (!expected.is_string()) {
        throw std::runtime_error("expected type mismatch?");
    }

    const std::string& expected_scalar(expected);
    json& result = merged_node[key];

    if (!have_node.count(key)) {
        if (expected_scalar == tag_value_deprecated_k) {
            // deprecated key not present in have. Do nothing, no error.
            return false;
        } else {
            notify("value missing", "value inserted");
            result = expected;
            return true;
        }
    }

    const json& have = have_node[key];

    if (have.is_string()) {
        const std::string& have_scalar(have);

        if (expected_scalar == tag_value_missing_k && have_scalar == tag_value_missing_k) {
            result = have;
            if (_mode == yaml_mode::validate) {
                notify("value not documented", "");
            }

            return true;
        }

        if (expected_scalar == tag_value_deprecated_k) {
            notify("key is deprecated", "deprecated key removed");
            return true;
        }

        if (expected_scalar == tag_value_optional_k && have_scalar == tag_value_optional_k) {
            result = have;
            return false;
        }

        if (hyde::is_tag(have_scalar)) {
            notify("value is unexpected tag `" + have_scalar + "`",
                   "value updated from `" + have_scalar + "` to `" + expected_scalar + "`");
            result = expected; // Replace unexpected tag
            return true;
        }
    }

    if (!have.is_array()) {
        notify_fail("value not an array; expected an array of scalar values");
        result = have;
        return true;
    }

    result = have;

    // We have an array; make sure its elements are scalar
    std::size_t index{0};
    bool failure{false};
    for (const auto& have_element : have) {
        if (!have_element.is_string()) {
            failure = true;
            notify_fail("non-scalar array element at index " + std::to_string(index));
        } else if (hyde::is_tag(have_element)) {
            failure = true;
            notify_fail("invalid value at index " + std::to_string(index));
        }
    }

    return failure;
}

/**************************************************************************************************/

bool yaml_base_emitter::check_scalar_array(const std::string& filepath,
                                           const json& have_node,
                                           const json& expected_node,
                                           const std::string& nodepath,
                                           json& merged_node,
                                           const std::string& key) {
    const auto notify = [&](const std::string& validate_message,
                            const std::string& update_message) {
        check_notify(filepath, nodepath, key, validate_message, update_message);
    };

    const auto notify_fail = [&](const std::string& message) {
        check_notify(filepath, nodepath, key, message, message);
    };

    if (!expected_node.count(key)) {
        if (!have_node.count(key)) {
            // Removed key not present in have. Do nothing, no error.
            return false;
        } else {
            notify("value present for removed key", "value removed");
            return true;
        }
    }

    const json& expected = expected_node[key];

    if (!expected.is_array()) {
        notify_fail("expected type mismatch");
        throw std::runtime_error("Merge scalar array failure");
    }

    json& result = merged_node[key];

    if (!have_node.count(key)) {
        notify("value missing", "value inserted");
        result = expected;
        return true;
    }

    if (!have_node[key].is_array()) {
        notify("value not an array", "non-array value replaced");
        result = expected;
        return true;
    }

    const json& have = have_node[key];

    // How does one merge an array of scalars? The solution is to use scalar value
    // as the "key", and treat the array like a dictionary. This does create the
    // possibility that multiple objects will resolve to the same key, and/or the
    // key value may not be a string, so we establish those requirements as function
    // preconditions.
    //
    // As for the actual merge, we have a `have` array, and an `expected` array.
    // The resulting merge will be built up in a resulting array, then moved
    // into `result.`
    //
    // First we build up a sorted vector of key/position pairs of the `have`
    // array. This will let us find elements in that array in log(N) time.
    //
    // Then we iterate the expected array from first to last. We pull out the
    // expected key and search for it in the have array. If it is missing, copy
    // the expected element into the result array, and move on. If it is found,
    // make sure they are in the same index in both arrays, otherwise it's a
    // validation error. The result array is then moved into the resulting json.
    //
    // If `have` has extraneous keys, they will be skipped during the iteration
    // of `expected` and subsequently dropped.
    //
    // The entire merge process should be O(N log N) time, bounded on the sort
    // of the have key vector. Thanks to Jared Wyles for the tip on how to solve
    // this one.

    std::vector<std::pair<std::string, std::size_t>> have_map;
    std::size_t count{0};
    bool failure{false};
    for (const auto& have_element : have) {
        const std::string& have_str = have_element;
        have_map.push_back(std::make_pair(have_str, count++));
    }

    std::sort(have_map.begin(), have_map.end());

    // Now go one by one through the expected list, and reorganize.
    std::size_t index{0};
    json result_array;
    for (const auto& expected_element : expected) {
        const std::string& expected_str = expected_element;
        const auto have_found_iter =
            std::lower_bound(have_map.begin(), have_map.end(), expected_str,
                             [](const auto& a, const auto& b) { return a.first < b; });
        bool have_found =
            have_found_iter != have_map.end() && have_found_iter->first == expected_str;
        std::string index_str(std::to_string(index));
        if (!have_found) {
            notify("missing required string at index " + index_str,
                   "required string inserted at index " + index_str);
            result_array.push_back(expected_str);
            failure = true;
        } else {
            std::size_t have_index = have_found_iter->second;
            if (have_index != index) {
                std::string have_index_str(std::to_string(have_index));
                notify("bad item location for item `" + expected_str +
                           "`; have: " + have_index_str + ", expected: " + index_str,
                       "moved item `" + expected_str + "` at index " + have_index_str +
                           " to index " + index_str);
                failure = true;
            }
            result_array.push_back(expected_str);
            have_map.erase(have_found_iter);
        }
        ++index;
    }

    for (const auto& have_iter : have_map) {
        const std::string& have_str = have_iter.first;
        std::string have_index_str(std::to_string(have_iter.second));
        auto message = "extraneous item `" + have_str + "` at index `" + have_index_str + "`";
        notify(message, "removed " + message);
        failure = true;
    }

    result = std::move(result_array);

    return failure;
}

/**************************************************************************************************/

bool yaml_base_emitter::check_object_array(const std::string& filepath,
                                           const json& have_node,
                                           const json& expected_node,
                                           const std::string& nodepath,
                                           json& merged_node,
                                           const std::string& key,
                                           const std::string& object_key,
                                           const check_proc& proc) {
    const auto notify = [&](const std::string& validate_message,
                            const std::string& update_message) {
        check_notify(filepath, nodepath, key, validate_message, update_message);
    };

    const auto notify_fail = [&](const std::string& message) {
        check_notify(filepath, nodepath, key, message, message);
    };

    if (!expected_node.count(key)) {
        return check_removed(filepath, have_node, nodepath, key);
    }

    const json& expected = expected_node[key];

    if (!expected.is_array()) {
        notify_fail("expected type mismatch");
        throw std::runtime_error("Merge object array failure");
    }

    json& result = merged_node[key];

    if (!have_node.count(key)) {
        notify("value missing", "value inserted");
        result = expected;
        return true;
    }

    if (!have_node[key].is_array()) {
        notify("value not an array", "non-array value replaced");
        result = expected;
        return true;
    }

    const json& have = have_node[key];

    // How does one merge an array of objects? The solution is to use one of the
    // elements in each object as the object's "key", and treat the array like a
    // dictionary. This does create the possibility that multiple objects will
    // resolve to the same key, and/or the key value may not be a string, so we
    // establish those requirements as function preconditions.
    //
    // As for the actual merge, we have a `have` array, and an `expected` array.
    // The resulting merge will be built up in a resulting array, then moved
    // into `result.`
    //
    // First we build up a sorted vector of key/position pairs of the `have`
    // array. This will let us find elements in that array in log(N) time.
    //
    // Then we iterate the expected array from first to last. We pull out the
    // expected key and search for it in the have array. If it is missing, copy
    // the expected element into the result array, and move on. If it is found,
    // make sure they are in the same index in both arrays, otherwise it's a
    // validation error. Once that is done, merge the two objects together with
    // the user callback. The merged result is then pushed onto the back of the
    // result array. The result array is then moved into the resulting json.
    //
    // If `have` has extraneous keys, they will be skipped during the iteration
    // of `expected` and subsequently dropped.
    //
    // The entire merge process should be O(N log N) time, bounded on the sort
    // of the have key vector. Thanks to Jared Wyles for the tip on how to solve
    // this one.

    std::vector<std::pair<std::string, std::size_t>> have_map;
    std::size_t count{0};
    bool failure{false};
    for (const auto& have_elements : have) {
        if (have_elements.count(object_key) == 0) {
            std::string count_str(std::to_string(count));
            std::string message("object at index " + count_str + " has no key");
            notify(message, message + "; skipped");
            // preserve object indices for merging below. Name is irrelevant as
            // long as it's unique. Prefix with '.' to prevent actual key
            // conflicts.
            have_map.push_back(std::make_pair(".unnamed-" + count_str, count++));
            failure = true;
        } else {
            const std::string& key = have_elements[object_key];
            have_map.push_back(std::make_pair(key, count++));
        }
    }

    std::sort(have_map.begin(), have_map.end());

    // Now go one by one through the expected list, and reorganize.
    std::size_t index{0};
    json result_array;
    for (const auto& expected_object : expected) {
        const std::string& expected_key = expected_object[object_key];
        const auto have_found_iter =
            std::lower_bound(have_map.begin(), have_map.end(), expected_key,
                             [](const auto& a, const auto& b) { return a.first < b; });
        bool have_found =
            have_found_iter != have_map.end() && have_found_iter->first == expected_key;
        std::string index_str(std::to_string(index));
        if (!have_found) {
            notify("missing required object at index " + index_str,
                   "required object inserted at index " + index_str);
            result_array.push_back(expected_object);
            failure = true;
        } else {
            std::size_t have_index = have_found_iter->second;
            if (have_index != index) {
                std::string have_index_str(std::to_string(have_index));
                notify("bad item location for key `" + expected_key + "`; have: " + have_index_str +
                           ", expected: " + index_str,
                       "moved item with key `" + expected_key + "` at index " + have_index_str +
                           " to index " + index_str);
                failure = true;
            }
            std::string nodepath = "['" + key + "'][" + index_str + "]";
            json merged;
            failure |= proc(filepath, have[have_index], expected_object, nodepath, merged);
            result_array.push_back(std::move(merged));
            have_map.erase(have_found_iter);
        }
        ++index;
    }

    for (const auto& have_iter : have_map) {
        const std::string& have_key = have_iter.first;
        std::string have_index_str(std::to_string(have_iter.second));
        auto message =
            "extraneous item with key `" + have_key + "` at index `" + have_index_str + "`";
        notify(message, "removed " + message);
        failure = true;
    }

    result = std::move(result_array);

    return failure;
}

/**************************************************************************************************/

std::vector<std::string> object_keys(const json& j) {
    std::vector<std::string> result;

    for (auto iter{j.begin()}, last{j.end()}; iter != last; ++iter) {
        result.push_back(static_cast<const std::string&>(iter.key()));
    }

    return result;
}

template <class T>
inline void move_append(T& dst, T&& src) {
    dst.insert(dst.end(), std::make_move_iterator(src.begin()), std::make_move_iterator(src.end()));
}

struct transcribe_pair {
    std::string src;
    std::string dst;
};

using transcribe_pairs = std::vector<transcribe_pair>;

// This is O(N^2), where N is the size of both `src` and `dst`. Therefore transcription
// should only be run when it is shown to be necessary. At the same time, if your code base
// has enough overrides to really slow this algorithm down, hyde's performance is the least
// of your concerns.
transcribe_pairs derive_transcribe_pairs(const json& src, const json& dst) {
    std::vector<std::string> src_keys = object_keys(src);
    std::vector<std::string> dst_keys = object_keys(dst);

    if (src_keys.size() != dst_keys.size()) {
        std::cerr << "WARNING: transcription key count mismatch\n";
    }

    transcribe_pairs result;

    while (!src_keys.empty()) {
        transcribe_pair cur_pair;

        // pop a key off the old name set
        cur_pair.src = std::move(src_keys.back());
        src_keys.pop_back();

        // find the best match of the dst keys to the src key
        std::size_t best_match = std::numeric_limits<std::size_t>::max();
        std::size_t best_index = 0;
        for (std::size_t i = 0; i < dst_keys.size(); ++i) {
            // generate the diff score of the src key and the candidate dst
            std::size_t cur_match = diff_score(cur_pair.src, dst_keys[i]);

            if (cur_match > best_match) {
                continue;
            }

            // if this dst candidate is better than what we've seen, remember that.
            best_match = cur_match;
            best_index = i;
        }

        // pair the best match dst and src keys and remove dst
        cur_pair.dst = std::move(dst_keys[best_index]);
        dst_keys.erase(dst_keys.begin() + best_index);

        // save off the pair and repeat
        result.emplace_back(std::move(cur_pair));
    }

    return result;
}

/**************************************************************************************************/

bool yaml_base_emitter::check_map(const std::string& filepath,
                                  const json& have_node,
                                  const json& expected_node,
                                  const std::string& nodepath,
                                  json& merged_node,
                                  const std::string& key,
                                  const check_proc& proc) {
    const bool at_root = key == "<root>";

    const auto notify = [&](const std::string& validate_message,
                            const std::string& update_message) {
        check_notify(filepath, nodepath, key, validate_message, update_message);
    };

    if (!expected_node.count(key)) {
        return check_removed(filepath, have_node, nodepath, key);
    }

    const json& expected = expected_node[key];

    if (!expected.is_object()) {
        throw std::runtime_error("expected type mismatch?");
    }

    json& result = merged_node[key];

    if (!have_node.count(key) || !have_node[key].is_object()) {
        notify("value not a map", "non-map value replaced");
        result = expected;
        return true;
    }

    const json& have = have_node[key];
    bool failure{false};
    json result_map;

    if (key == "overloads" && _mode == yaml_mode::transcribe) {
        /*
        It is common during the upgrade from one version of hyde to another that the underlying
        clang tooling will output different symbol names for a given symbol (e.g., a namespace
        may get removed or added.) Although the symbol is unchanged, because its `expected` name
        differs from the `have` name, hyde will consider the symbols different, remove the old name
        and insert the new one. This wipes out any previous documentation under the old name that
        should have been migrated to the new name.

        The solution here is very specialized. For the "overloads" key only, we gather the name
        of each overload in both the `have` and `expected` set. We then pair them up according
        to how well they match to one another (using the Meyers' string diff algorithm; two strings
        with less "patchwork" between them are considered a better match). Ideally this results in
        key pairs that represent the same symbol, just with different names. Then we call the
        `proc` with `have[old_name]` and `expected[new_name]` which will migrate any documentation
        from the old name to the new.

        This capability assumes the overload count of both `have` and `expected` are the same.
        If any new functions are created or removed between upgrades in the clang driver (e.g.,
        a new compiler-generated routine is created and documented) that will have to be managed
        manually. Assuming the count is the same, it also assumes there is a 1:1 mapping from the
        set of old names to the set of new names. This implies the transcription mode should be
        done as a separate step from an update. In other words, a transcription assumes the
        documentation is actually the same between the `have` and `expected` sets, it is _just the
        overload names_ that have changed, so map the old-named documentation to the new-named
        documentation as reasonably as possible.
        */
        for (const auto& pair : derive_transcribe_pairs(have, expected)) {
            const std::string curnodepath = nodepath + "['" + pair.dst + "']";
            failure |= proc(filepath, have[pair.src], expected[pair.dst], curnodepath,
                            result_map[pair.dst]);
        }
    } else {
        std::vector<std::string> keys;

        move_append(keys, object_keys(have));
        move_append(keys, object_keys(expected));

        std::sort(keys.begin(), keys.end());
        keys.erase(std::unique(keys.begin(), keys.end()), keys.end());

        for (const auto& subkey : keys) {
            const std::string curnodepath = nodepath + "['" + subkey + "']";

            if (!expected.count(subkey)) {
                // Issue #75: only remove non-root keys to allow non-hyde YAML into the file.
                if (!at_root) {
                    notify("extraneous map key: `" + subkey + "`",
                           "map key removed: `" + subkey + "`");
                    failure = true;
                }
            } else if (!have.count(subkey)) {
                notify("map key missing: `" + subkey + "`", "map key inserted: `" + subkey + "`");
                result_map[subkey] = expected[subkey];
                failure = true;
            } else {
                failure |=
                    proc(filepath, have[subkey], expected[subkey], curnodepath, result_map[subkey]);
            }
        }
    }

    result = std::move(result_map);

    return failure;
}

/**************************************************************************************************/

bool yaml_base_emitter::has_inline_field(const json& j, const char* field) {
    return j.count("inline") && j.at("inline").count(field);
}

/**************************************************************************************************/

std::pair<bool, json> yaml_base_emitter::merge(const std::string& filepath,
                                               const json& have,
                                               const json& expected) {
    bool failure{false};

    // Create a temporary object with the json to merge as a value so we can use `check_map`
    // to make sure removed keys are handled
    static const auto root_key = "<root>";
    json have_root;
    have_root[root_key] = have;
    json expected_root;
    expected_root[root_key] = expected;
    json merged_root;
    failure |= check_map(filepath, have_root, expected_root, "", merged_root, root_key,
                         [](const std::string& filepath, const json& have, const json& expected,
                            const std::string& nodepath, json& out_merged) { return false; });
    json& merged = merged_root[root_key];

    // we can probably get rid of `have` in the check
    // routines; I don't think we can keep it from being an
    // out-arg, though, because we need to preserve the
    // values in `have` that are not managed by the
    // `expected` schema.

    failure |= check_scalar(filepath, have, expected, "", merged, "layout");
    if (_editable_title) {
        failure |= check_editable_scalar(filepath, have, expected, "", merged, "title");
    } else {
        failure |= check_scalar(filepath, have, expected, "", merged, "title");
    }

    {
        const hyde::json& expected_hyde = expected.at("hyde");
        const hyde::json& have_hyde = have.count("hyde") ? have.at("hyde") : no_json_k;
        hyde::json& merged_hyde = merged["hyde"];

        failure |=
            check_editable_scalar(filepath, have_hyde, expected_hyde, "", merged_hyde, "owner");
        failure |=
            check_editable_scalar(filepath, have_hyde, expected_hyde, "", merged_hyde, "brief");
        failure |= check_scalar_array(filepath, have_hyde, expected_hyde, "", merged_hyde, "tags");

        // We don't want to use `check_scalar` on the version key. If the versions mismatch its not
        // necessarily a validation error (as the docs may match OK), but something we want to warn
        // about. Then in transcription/update we want to hard-set the value to the version of this
        // tool.

        switch (_mode) {
            case yaml_mode::validate: {
                if (!have_hyde.count("version") ||
                    static_cast<const std::string&>(have_hyde["version"]) != hyde_version()) {
                    std::cerr << "INFO: Validation phase with a mismatched version of hyde. Consider updating then/or transcribing.\n";
                }
            } break;
            case yaml_mode::update:
            case yaml_mode::transcribe: {
                merged_hyde["version"] = hyde_version();
            } break;
        }

        failure |= do_merge(filepath, have_hyde, expected_hyde, merged_hyde);
    }

    return std::make_pair(failure, std::move(merged));
}

/**************************************************************************************************/

inline std::uint64_t fnv_1a(const std::string& s) {
    constexpr std::uint64_t prime_k = 0x100000001b3;

    std::uint64_t result(0xcbf29ce484222325);

    for (const auto& c : s) {
        result = (result ^ static_cast<std::uint64_t>(c)) * prime_k;
    }

    return result;
}

/**************************************************************************************************/

std::string yaml_base_emitter::filename_truncate(std::string s) {
    if (s.size() <= 32) return s;

    // We cannot use std::hash here because the hashing algorithm may give
    // different results per-platform. Instead we fall back on an old
    // favorite of mine for this kind of thing: FNV-1a.
    const auto hash = [&_s = s]() {
        auto hash = fnv_1a(_s) & 0xFFFFFFFF;
        std::stringstream stream;
        stream << std::hex << hash;
        return stream.str();
    }();

    // 23 + 1 + 8 = 32 max characters per directory name
    s = s.substr(0, 23) + '.' + hash;

    return s;
}

/**************************************************************************************************/

std::filesystem::path yaml_base_emitter::directory_mangle(std::filesystem::path p) {
    std::filesystem::path result;

    for (const auto& part : p) {
        result /= filename_truncate(filename_filter(part.string()));
    }

    return result;
}

/**************************************************************************************************/

bool yaml_base_emitter::create_directory_stub(std::filesystem::path p) {
    auto stub_name = p / index_filename_k;

    if (exists(stub_name)) return false;

    std::ofstream output(stub_name);

    if (!output) {
        std::cerr << stub_name.string() << ": could not create directory stub\n";
        return true;
    }

    static const auto stub_json_k = json::object_t{
        {"layout", "directory"},
        {"title", p.filename().string()},
    };

    output << front_matter_begin_k;
    output << json_to_yaml_ordered(stub_json_k);
    output << front_matter_end_k;

    return false;
}

/**************************************************************************************************/

bool yaml_base_emitter::create_path_directories(std::filesystem::path p) {
    if (p.has_filename()) p = p.parent_path();

    std::vector<std::filesystem::path> ancestors;
    const auto root_path = p.root_path();

    while (p != root_path) {
        ancestors.push_back(p);
        if (!p.has_parent_path()) break;
        p = p.parent_path();
    }

    std::reverse(ancestors.begin(), ancestors.end());

    for (const auto& ancestor : ancestors) {
        if (checker_s.exists(ancestor)) continue;

        if (_mode == yaml_mode::validate) {
            return true;
        } else {
            std::error_code ec;
            create_directory(ancestor, ec);

            if (ec) {
                static std::map<std::string, bool> bad_path_map_s;
                const auto bad_path = ancestor.string();
                if (!bad_path_map_s.count(bad_path))
                    std::cerr << bad_path << ": directory could not be created (" << ec << ")\n";
                bad_path_map_s[bad_path] = true;
                return true;
            }

            if (create_directory_stub(ancestor)) {
                return true;
            }
        }
    }

    return false;
}

/**************************************************************************************************/

auto load_yaml(const std::filesystem::path& path) try {
    return YAML::LoadFile(path.c_str());
} catch (...) {
    std::cerr << "YAML File: " << path.string() << '\n';
    throw;
}

/**************************************************************************************************/

documentation parse_documentation(const std::filesystem::path& path, bool fixup_subfield) {
    // we have to load the file ourselves and find the place where the
    // front-matter ends and any other relevant documentation begins. We
    // need to do this for the boilerpolate step to keep it from blasting
    // out any extra documentation that's already been added.
    std::ifstream have_file(path);
    std::stringstream have_contents_stream;
    have_contents_stream << have_file.rdbuf();
    std::string have_contents = have_contents_stream.str();
    documentation result;

    if (have_contents.find_first_of(front_matter_begin_k) != 0) {
        std::cerr << "./" << path.string() << ": does not begin with YAML front-matter.\n";
        result._error = true;
        return result;
    }

    const auto contents_end = have_contents.find(front_matter_end_k);

    if (contents_end == std::string::npos) {
        std::cerr << "./" << path.string() << ": could not find end of YAML front-matter.\n";
        result._error = true;
        return result;
    }

    const auto front_matter_end = contents_end + front_matter_end_k.size();
    std::string yaml_src = have_contents.substr(0, front_matter_end);
    have_contents.erase(0, front_matter_end);

    result._remainder = std::move(have_contents);
    result._json = yaml_to_json(load_yaml(path));

    if (fixup_subfield) {
        result._json = fixup_hyde_subfield(std::move(result._json));
    }

    return result;
}

/**************************************************************************************************/

bool write_documentation(const documentation& docs, const std::filesystem::path& path) {
    std::ofstream output(path);
    if (!output) {
        std::cerr << "./" << path.string() << ": could not open file for output\n";
        return true;
    }

    output << front_matter_begin_k;
    output << json_to_yaml_ordered(docs._json);
    output << front_matter_end_k;
    output << docs._remainder;

    return false;
}

/**************************************************************************************************/

bool yaml_base_emitter::reconcile(json expected,
                                  std::filesystem::path root_path,
                                  std::filesystem::path path,
                                  json& out_reconciled) {
    bool failure{false};

    /* begin hack */ {
        // I hope to remove this soon. Paths with '...' in them make Perforce go
        // stir-crazy (it's a special token for the tool), so we remove them.
        static const std::string needle = "...";
        std::string p_str = path.string();
        std::size_t pos = 0;
        auto found = false;
        while (true) {
            pos = p_str.find(needle, pos);
            if (pos == std::string::npos) break;
            found = true;
            p_str.replace(pos, needle.size(), "");
        }
        if (found) {
            path = std::filesystem::path(p_str);
        }
    }

    std::string relative_path(("." / relative(path, root_path)).string());

    failure |= create_path_directories(path);

    if (checker_s.exists(path)) {
        const auto have_docs = parse_documentation(path, true);

        if (have_docs._error) {
            return true;
        }

        const auto& have = have_docs._json;
        const auto& remainder = have_docs._remainder;

        json merged;

        std::tie(failure, merged) = merge(relative_path, have, expected);
        out_reconciled = merged;
        out_reconciled["documentation_path"] = relative_path;

        switch (_mode) {
            case hyde::yaml_mode::validate: {
                // do nothing
            } break;
            case hyde::yaml_mode::transcribe:
            case hyde::yaml_mode::update: {
                failure = write_documentation({std::move(merged), std::move(remainder)}, path);
            } break;
        }
    } else { // file does not exist
        out_reconciled = expected;

        switch (_mode) {
            case hyde::yaml_mode::validate: {
                std::cerr << relative_path << ": required file does not exist\n";
                failure = true;
            } break;
            case hyde::yaml_mode::transcribe:
            case hyde::yaml_mode::update: {
                // Add update. No remainder yet, as above.
                // REVISIT: Refactor all this into a call to write_documentation,
                // though I'm not sure what the call to `update_cleanup` is all about,
                // and which was missing from the prior case when the file existed.
                std::ofstream output(path);
                if (!output) {
                    std::cerr << "./" << path.string() << ": could not open file for output\n";
                    failure = true;
                } else {
                    output << front_matter_begin_k;
                    output << update_cleanup(json_to_yaml_ordered(expected));
                    output << front_matter_end_k;
                }
            } break;
        }
    }

    return failure;
}

/**************************************************************************************************/

std::string yaml_base_emitter::defined_in_file(const std::string& src_path,
                                               const std::filesystem::path& src_root) {
    return relative(std::filesystem::path(src_path), src_root).string();
}

/**************************************************************************************************/

std::filesystem::path yaml_base_emitter::subcomponent(const std::filesystem::path& src_path,
                                                      const std::filesystem::path& src_root) {
    return std::filesystem::relative(src_path, src_root);
}

/**************************************************************************************************/

void yaml_base_emitter::insert_inherited(const json& inherited, json& node) {
    if (inherited.count("owner") && !is_tag(inherited.at("owner").get<std::string>())) {
        node["owner"] = inherited.at("owner");
    }

    if (has_inline_field(inherited, "owner")) {
        node["inline"]["owner"] = inherited.at("inline").at("owner");
    }
}

/**************************************************************************************************/

void yaml_base_emitter::insert_annotations(const json& j, json& node) {
    std::string annotation;

    if (j.count("access")) {
        const std::string& access = j["access"];

        if (access != "public") {
            node["annotation"].push_back(access);
        }
    }

    if (has_json_flag(j, "implicit")) {
        node["annotation"].push_back("implicit");
    }
    if (has_json_flag(j, "defaulted")) {
        node["annotation"].push_back("defaulted");
    }
    if (has_json_flag(j, "deleted")) {
        node["annotation"].push_back("deleted");
    }

    if (has_json_flag(j, "deprecated")) {
        std::string deprecated("deprecated");

        if (j.count("deprecated_message")) {
            const std::string& message_str = j["deprecated_message"];
            if (!message_str.empty()) {
                deprecated = deprecated.append("(\"").append(message_str).append("\")");
            }
        }
        node["annotation"].push_back(deprecated);
    }
}

/**************************************************************************************************/

std::string yaml_base_emitter::format_template_parameters(const hyde::json& json, bool with_types) {
    std::string result;

    if (json.count("template_parameters")) {
        std::size_t count{0};
        if (with_types) result += "template ";
        result += "<";
        for (const auto& param : json["template_parameters"]) {
            if (count++) result += ", ";
            if (with_types) {
                result += static_cast<const std::string&>(param["type"]);
                if (param.count("parameter_pack")) result += "...";
                result += " " + static_cast<const std::string&>(param["name"]);
            } else {
                result += static_cast<const std::string&>(param["name"]);
                if (param.count("parameter_pack")) result += "...";
            }
        }
        result += ">";
    }

    return result;
}

/**************************************************************************************************/

std::string yaml_base_emitter::filename_filter(std::string f) {
    constexpr const char* const uri_equivalent[] = {
        "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E",
        "0F", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D",
        "1E", "1F", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C",
        "-",  ".",  "2F", "0",  "1",  "2",  "3",  "4",  "5",  "6",  "7",  "8",  "9",  "3A", "3B",
        "3C", "3D", "3E", "3F", "40", "A",  "B",  "C",  "D",  "E",  "F",  "G",  "H",  "I",  "J",
        "K",  "L",  "M",  "N",  "O",  "P",  "Q",  "R",  "S",  "T",  "U",  "V",  "W",  "X",  "Y",
        "Z",  "5B", "5C", "5D", "5E", "_",  "60", "a",  "b",  "c",  "d",  "e",  "f",  "g",  "h",
        "i",  "j",  "k",  "l",  "m",  "n",  "o",  "p",  "q",  "r",  "s",  "t",  "u",  "v",  "w",
        "x",  "y",  "z",  "7B", "7C", "7D", "~",  "7F", "80", "81", "82", "83", "84", "85", "86",
        "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F", "90", "91", "92", "93", "94", "95",
        "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F", "A0", "A1", "A2", "A3", "A4",
        "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF", "B0", "B1", "B2", "B3",
        "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF", "C0", "C1", "C2",
        "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", "D0", "D1",
        "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", "E0",
        "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
        "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE",
        "FF",
    };

    std::string result; // preallocate? stringstream?

    std::for_each(f.begin(), f.end(),
                  [&](const auto& c) { result += uri_equivalent[static_cast<int>(c)]; });

    return result;
}

/**************************************************************************************************/

} // namespace hyde

/**************************************************************************************************/


================================================
FILE: emitters/yaml_base_emitter.hpp
================================================
/*
Copyright 2018 Adobe
All Rights Reserved.

NOTICE: Adobe permits you to use, modify, and distribute this file in
accordance with the terms of the Adobe license agreement accompanying
it. If you have received this file from a source other than Adobe,
then your use, modification, or distribution of it requires the prior
written permission of Adobe.
*/

#pragma once

// application
#include "emitters/yaml_base_emitter_fwd.hpp"
#include "json.hpp"
#include "output_yaml.hpp"

/**************************************************************************************************/

namespace hyde {

/**************************************************************************************************/

struct file_checker {
    bool exists(std::filesystem::path p) {
        _files.emplace_back(std::move(p));
        _sorted = false;
        return std::filesystem::exists(_files.back());
    }

    bool checked(const std::filesystem::path& p) {
        if (!_sorted) {
            std::sort(_files.begin(), _files.end());
            _files.erase(std::unique(_files.begin(), _files.end()), _files.end());
            _sorted = true;
        }

        auto found = std::lower_bound(_files.begin(), _files.end(), p);
        return found != _files.end() && *found == p;
    }

private:
    std::vector<std::filesystem::path> _files;
    bool _sorted{false};
};

/**************************************************************************************************/

inline bool has_json_flag(const json& j, const char* k) {
    return j.count(k) && j.at(k).get<bool>();
}

/**************************************************************************************************/

struct yaml_base_emitter {
public:
    yaml_base_emitter(std::filesystem::path src_root,
                      std::filesystem::path dst_root,
                      yaml_mode mode,
                      emit_options options,
                      bool editable_title = false)
        : _src_root(std::move(src_root)), _dst_root(std::move(dst_root)), _mode(mode),
          _options(std::move(options)), _editable_title{editable_title} {}

    /// @param matched The json given to us by the matcher engine
    /// @param output The resulting output of this call
    /// @param inherited Any inherited fields from parent constructs, e.g., passing
    ///                  the owner of a class to its members
    /// @return `true` if an error took place during emit; `false` otherwise.
    virtual bool emit(const json& matched, json& output, const json& inherited) = 0;

protected:
    json base_emitter_node(std::string layout, std::string title, std::string tag, bool implicit);

    bool reconcile(json node,
                   std::filesystem::path root_path,
                   std::filesystem::path path,
                   json& out_reconciled);

    std::string defined_in_file(const std::string& src_path, const std::filesystem::path& src_root);

    std::filesystem::path subcomponent(const std::filesystem::path& src_path,
                                       const std::filesystem::path& src_root);

    // For some reason nlohmann's JSON types aren't happy with my moving them about
    // (they always seem to show up null (~) in the final YAML output)
    // so converting these to out-arg-based routines will have to wait until I can
    // sort that out.
    void insert_inherited(const json& inherited, json& node); // make out arg?
    void insert_annotations(const json& j, json& node);       // make out arg?
    void insert_doxygen(const json& j, json& node);           // make out arg?

    std::string format_template_parameters(const json& json, bool with_types);

    std::string filename_filter(std::string f);
    std::string filename_truncate(std::string s);

    void insert_typedefs(const json& j, json& node, const json& inherited);

    void check_inline_comments(const json& expected, json& out_merged);

    bool check_typedefs(const std::string& filepath,
                        const json& have_node,
                        const json& expected_node,
                        const std::string& nodepath,
                        json& merged_node);

    template <typename... Args>
    std::filesystem::path dst_path(const json& j, Args&&... args);

    bool check_removed(const std::string& filepath,
                       const json& have_node,
                       const std::string& nodepath,
                       const std::string& key);

    bool check_scalar(const std::string& filepath,
                      const json& have_node,
                      const json& expected_node,
                      const std::string& nodepath,
                      json& out_merged,
                      const std::string& key);

    bool check_editable_scalar(const std::string& filepath,
                               const json& have_node,
                               const json& expected_node,
                               const std::string& nodepath,
                               json& out_merged,
                               const std::string& key);

    bool check_editable_scalar_array(const std::string& filepath,
                                     const json& have_node,
                                     const json& expected_node,
                                     const std::string& nodepath,
                                     json& merged_node,
                                     const std::string& key);

    bool check_scalar_array(const std::string& filepath,
                            const json& have_node,
                            const json& expected_node,
                            const std::string& nodepath,
                            json& merged_node,
                            const std::string& key);

    using check_proc = std::function<bool(const std::string& filepath,
                                          const json& have,
                                          const json& expected,
                                          const std::string& nodepath,
                                          json& out_merged)>;

    bool check_object_array(const std::string& filepath,
                            const json& have_node,
                            const json& expected_node,
                            const std::string& nodepath,
                            json& merged_node,
                            const std::string& key,
                            const std::string& object_key,
                            const check_proc& proc);

    bool check_map(const std::string& filepath,
                   const json& have,
                   const json& expected,
                   const std::string& nodepath,
                   json& out_merged,
                   const std::string& key,
                   const check_proc& proc);

    static bool has_inline_field(const json& j, const char* field);

private:
    template <typename Arg, typename... Args>
    std::filesystem::path dst_path_append(std::filesystem::path p, Arg&& arg, Args&&... args);

    template <typename Arg>
    std::filesystem::path dst_path_append(std::filesystem::path, Arg&& arg);

    std::filesystem::path dst_path_append(std::filesystem::path p) { return p; }

    bool create_directory_stub(std::filesystem::path p);
    bool create_path_directories(std::filesystem::path p);

    std::filesystem::path directory_mangle(std::filesystem::path p);

    void check_notify(const std::string& filepath,
                      const std::string& nodepath,
                      const std::string& key,
                      const std::string& validate_message,
                      const std::string& update_message);

    virtual std::pair<bool, json> merge(const std::string& filepath,
                                        const json& have,
                                        const json& expected);

    virtual bool do_merge(const std::string& filepath,
                          const json& have,
                          const json& expected,
                          json& out_merged) = 0;

protected: // make private?
    const std::filesystem::path _src_root;
    const std::filesystem::path _dst_root;
    const yaml_mode _mode;
    const emit_options _options;
    const bool _editable_title{false};

    static file_checker checker_s;
};

/**************************************************************************************************/

template <typename... Args>
std::filesystem::path yaml_base_emitter::dst_path(const json& j, Args&&... args) {
    std::filesystem::path result(_dst_root);

    if (j.count("defined_in_file")) {
        const std::string& defined_in_file = j["defined_in_file"];
        result /= directory_mangle(subcomponent(defined_in_file, _src_root));
    }

    if (j.count("parents")) {
        for (const auto& dir : j["parents"]) {
            std::string dir_str{dir};
            result /= directory_mangle(std::move(dir_str));
        }
    }

    return dst_path_append(std::move(result), std::forward<Args>(args)...);
}

/**************************************************************************************************/

template <typename Arg, typename... Args>
std::filesystem::path yaml_base_emitter::dst_path_append(std::filesystem::path p,
                                                         Arg&& arg,
                                                         Args&&... args) {
    return dst_path_append(dst_path_append(std::move(p), arg), std::forward<Args>(args)...);
}

/**************************************************************************************************/

template <typename Arg>
std::filesystem::path yaml_base_emitter::dst_path_append(std::filesystem::path p, Arg&& arg) {
    p /= directory_mangle(arg);
    return p;
}

/**************************************************************************************************/

} // namespace hyde

/**************************************************************************************************/


================================================
FILE: emitters/yaml_base_emitter_fwd.hpp
================================================
/*
Copyright 2018 Adobe
All Rights Reserved.

NOTICE: Adobe permits you to use, modify, and distribute this file in
accordance with the terms of the Adobe license agreement accompanying
it. If you have received this file from a source other than Adobe,
then your use, modification, or distribution of it requires the prior
written permission of Adobe.
*/

#pragma once

// stdc++
#include <filesystem>
#include <stdexcept>
#include <string>

// application
#include "json.hpp"

/**************************************************************************************************/

namespace hyde {

/**************************************************************************************************/

static constexpr char const* tag_value_missing_k = "__MISSING__";
static constexpr char const* tag_value_optional_k = "__OPTIONAL__";
static constexpr char const* tag_value_deprecated_k = "__DEPRECATED__";
static constexpr char const* tag_value_inlined_k = "__INLINED__";
static constexpr char const* index_filename_k = "index.md";

/**************************************************************************************************/

enum class attribute_category { disabled, required, optional, deprecated, inlined };

static constexpr char const* get_tag(attribute_category c) {
    switch (c) {
        case attribute_category::required:
            return tag_value_missing_k;
        case attribute_category::optional:
            return tag_value_optional_k;
        case attribute_category::deprecated:
            return tag_value_deprecated_k;
        case attribute_category::inlined:
            return tag_value_inlined_k;
        default:
            throw std::invalid_argument("unexpected attribute category");
    }
}

static inline bool is_tag(const std::string& s) { return s.substr(0, 2) == "__"; }

/**************************************************************************************************/

struct emit_options {
    attribute_category _tested_by{attribute_category::disabled};
    bool _ignore_extraneous_files{false};
};

/**************************************************************************************************/

struct documentation {
    json _json;
    std::string _remainder;
    bool _error{false};
};

documentation parse_documentation(const std::filesystem::path& path, bool fixup_subfield);

/// @return `true` on failure to write, `false` otherwise.
bool write_documentation(const documentation& docs, const std::filesystem::path& path);

/**************************************************************************************************/

} // namespace hyde

/**************************************************************************************************/


================================================
FILE: emitters/yaml_class_emitter.cpp
================================================
/*
Copyright 2018 Adobe
All Rights Reserved.

NOTICE: Adobe permits you to use, modify, and distribute this file in
accordance with the terms of the Adobe license agreement accompanying
it. If you have received this file from a source other than Adobe,
then your use, modification, or distribution of it requires the prior
written permission of Adobe.
*/

// identity
#include "yaml_class_emitter.hpp"

// stdc++
#include <iostream>

// application
#include "emitters/yaml_function_emitter.hpp"
#include "matchers/utilities.hpp"

/**************************************************************************************************/

namespace hyde {

/**************************************************************************************************/

bool yaml_class_emitter::do_merge(const std::string& filepath,
                                  const json& have,
                                  const json& expected,
                                  json& out_merged) {
    bool failure{false};

    failure |= check_scalar(filepath, have, expected, "", out_merged, "defined_in_file");
    failure |= check_scalar_array(filepath, have, expected, "", out_merged, "annotation");
    failure |= check_scalar(filepath, have, expected, "", out_merged, "declaration");
    failure |= check_scalar_array(filepath, have, expected, "", out_merged, "namespace");
    failure |= check_scalar(filepath, have, expected, "", out_merged, "ctor");
    failure |= check_scalar(filepath, have, expected, "", out_merged, "dtor");
    failure |= check_map(
        filepath, have, expected, "", out_merged, "fields",
        [this](const std::string& filepath, const json& have, const json& expected,
               const std::string& nodepath, json& out_merged) {
            bool failure{false};

            failure |= check_scalar(filepath, have, expected, nodepath, out_merged, "type");
            failure |= check_editable_scalar(filepath, have, expected, nodepath, out_merged,
                                             "description");
            failure |=
                check_scalar_array(filepath, have, expected, nodepath, out_merged, "annotation");

            check_inline_comments(expected, out_merged);

            return failure;
        });

    failure |= check_typedefs(filepath, have, expected, "", out_merged);

    failure |= check_object_array(
        filepath, have, expected, "", out_merged, "methods", "title",
        [this](const std::string& filepath, const json& have, const json& expected,
               const std::string& nodepath, json& out_merged) {
            yaml_function_emitter function_emitter(_src_root, _dst_root, _mode, _options, true);
            return function_emitter.do_merge(filepath, have, expected, out_merged);
        });

    check_inline_comments(expected, out_merged);

    return failure;
}

/**************************************************************************************************/

bool yaml_class_emitter::emit(const json& j, json& out_emitted, const json& inherited) {
    json node = base_emitter_node("class", j["name"], "class", has_json_flag(j, "implicit"));
    node["hyde"]["defined_in_file"] = defined_in_file(j["defined_in_file"], _src_root);

    insert_inherited(inherited, node["hyde"]);
    insert_annotations(j, node["hyde"]);
    insert_doxygen(j, node["hyde"]);

    std::string declaration = format_template_parameters(j, true) + '\n' +
                              static_cast<const std::string&>(j["kind"]) + " " +
                              static_cast<const std::string&>(j["qualified_name"]) + ";";
    node["hyde"]["declaration"] = std::move(declaration);

    for (const auto& ns : j["namespaces"])
        node["hyde"]["namespace"].push_back(static_cast<const std::string&>(ns));

    if (j.count("ctor")) node["hyde"]["ctor"] = static_cast<const std::string&>(j["ctor"]);
    if (j.count("dtor")) node["hyde"]["dtor"] = static_cast<const std::string&>(j["dtor"]);

    if (j.count("fields")) {
        for (const auto& field : j["fields"]) {
            const std::string& key = field["name"];
            auto& field_node = node["hyde"]["fields"][key];
            insert_annotations(field, field_node);
            insert_doxygen(field, field_node);

            field_node["type"] = static_cast<const std::string&>(field["type"]);
            const bool inline_description_exists =
                field_node.count("inline") && field_node["inline"].count("description");
            field_node["description"] =
                inline_description_exists ? tag_value_inlined_k : tag_value_missing_k;
        }
    }

    insert_typedefs(j, node, inherited);

    auto dst = dst_path(j, static_cast<const std::string&>(j["name"]));

    if (_mode == yaml_mode::transcribe && !exists(dst)) {
        // In this case the symbol name has changed, which has caused a change to the directory name
        // we are now trying to load and reconcile with what we've created. In this case, we can
        // assume the "shape" of the documentation is the same, which means that within the parent
        // folder of `dst` is the actual source folder that holds the old documentation, just under
        // a different name. Find that folder and rename it.

        std::filesystem::rename(derive_transcription_src_path(dst, node["title"]), dst);
    }

    bool failure =
        reconcile(std::move(node), _dst_root, std::move(dst) / index_filename_k, out_emitted);

    yaml_function_emitter function_emitter(_src_root, _dst_root, _mode, _options, true);
    auto emitted_methods = hyde::json::array();
    const auto& methods = j["methods"];

    for (auto it = methods.begin(); it != methods.end(); ++it) {
        function_emitter.set_key(it.key());
        auto function_emitted = hyde::json::object();
        failure |= function_emitter.emit(it.value(), function_emitted, out_emitted.at("hyde"));
        emitted_methods.push_back(std::move(function_emitted));
    }

    out_emitted["methods"] = std::move(emitted_methods);

    return failure;
}

/**************************************************************************************************/

} // namespace hyde

/**************************************************************************************************/


================================================
FILE: emitters/yaml_class_emitter.hpp
================================================
/*
Copyright 2018 Adobe
All Rights Reserved.

NOTICE: Adobe permits you to use, modify, and distribute this file in
accordance with the terms of the Adobe license agreement accompanying
it. If you have received this file from a source other than Adobe,
then your use, modification, or distribution of it requires the prior
written permission of Adobe.
*/

#pragma once

// application
#include "emitters/yaml_base_emitter.hpp"
#include "json.hpp"

/**************************************************************************************************/

namespace hyde {

/**************************************************************************************************/

struct yaml_class_emitter : public yaml_base_emitter {
    explicit yaml_class_emitter(std::filesystem::path src_root,
                                std::filesystem::path dst_root,
                                yaml_mode mode,
                                emit_options options)
        : yaml_base_emitter(std::move(src_root), std::move(dst_root), mode, std::move(options)) {}

    bool emit(const json& matched, json& output, const json& inherited) override;

    bool do_merge(const std::string& filepath,
                  const json& have,
                  const json& expected,
                  json& out_merged) override;
};

/**************************************************************************************************/

} // namespace hyde

/**************************************************************************************************/


================================================
FILE: emitters/yaml_enum_emitter.cpp
================================================
/*
Copyright 2018 Adobe
All Rights Reserved.

NOTICE: Adobe permits you to use, modify, and distribute this file in
accordance with the terms of the Adobe license agreement accompanying
it. If you have received this file from a source other than Adobe,
then your use, modification, or distribution of it requires the prior
written permission of Adobe.
*/

// identity
#include "yaml_enum_emitter.hpp"

// stdc++
#include <iostream>

/**************************************************************************************************/

namespace hyde {

/**************************************************************************************************/

bool yaml_enum_emitter::do_merge(const std::string& filepath,
                                 const json& have,
                                 const json& expected,
                                 json& out_merged) {
    bool failure{false};

    failure |= check_scalar(filepath, have, expected, "", out_merged, "defined_in_file");
    failure |= check_scalar_array(filepath, have, expected, "", out_merged, "annotation");
    failure |= check_scalar_array(filepath, have, expected, "", out_merged, "namespace");

    failure |= check_object_array(
        filepath, have, expected, "", out_merged, "values", "name",
        [this](const std::string& filepath, const json& have, const json& expected,
               const std::string& nodepath, json& out_merged) {
            bool failure{false};

            failure |= check_scalar(filepath, have, expected, nodepath, out_merged, "name");
            failure |= check_editable_scalar(filepath, have, expected, nodepath, out_merged,
                                             "description");
            failure |= check_scalar_array(filepath, have, expected, "", out_merged, "values");

            check_inline_comments(expected, out_merged);

            return failure;
        });

    check_inline_comments(expected, out_merged);

    return failure;
}

/**************************************************************************************************/

bool yaml_enum_emitter::emit(const json& j, json& out_emitted, const json& inherited) {
    const std::string& name = j["name"];

    // Most likely an enum forward declaration. Nothing to document here.
    if (j["values"].empty()) return true;

    json base_node =
        base_emitter_node("enumeration", j["name"], "enumeration", has_json_flag(j, "implicit"));
    json& node = base_node["hyde"];

    insert_inherited(inherited, node);
    insert_annotations(j, node);
    insert_doxygen(j, node);

    if (has_inline_field(node, "owner")) {
        node["owner"] = tag_value_inlined_k;
    }

    if (has_inline_field(node, "brief")) {
        node["brief"] = tag_value_inlined_k;
    }

    node["defined_in_file"] = defined_in_file(j["defined_in_file"], _src_root);

    std::string filename;
    for (const auto& ns : j["namespaces"]) {
        const std::string& namespace_str = ns;
        node["namespace"].push_back(namespace_str);
        filename += namespace_str + "::";
    }
    filename = filename_filter(std::move(filename) + name) + ".md";

    for (const auto& value : j["values"]) {
        json cur_value;
        insert_doxygen(value, cur_value);

        cur_value["name"] = value["name"];
        cur_value["description"] =
            has_inline_field(cur_value, "description") ? tag_value_inlined_k : tag_value_missing_k;
        node["values"].push_back(std::move(cur_value));
    }

    return reconcile(std::move(base_node), _dst_root, dst_path(j) / filename, out_emitted);
}

/**************************************************************************************************/

} // namespace hyde

/**************************************************************************************************/


================================================
FILE: emitters/yaml_enum_emitter.hpp
================================================
/*
Copyright 2018 Adobe
All Rights Reserved.

NOTICE: Adobe permits you to use, modify, and distribute this file in
accordance with the terms of the Adobe license agreement accompanying
it. If you have received this file from a source other than Adobe,
then your use, modification, or distribution of it requires the prior
written permission of Adobe.
*/

#pragma once

// application
#include "emitters/yaml_base_emitter.hpp"
#include "json.hpp"

/**************************************************************************************************/

namespace hyde {

/**************************************************************************************************/

struct yaml_enum_emitter : public yaml_base_emitter {
    explicit yaml_enum_emitter(std::filesystem::path src_root,
                               std::filesystem::path dst_root,
                               yaml_mode mode,
                               emit_options options)
        : yaml_base_emitter(std::move(src_root), std::move(dst_root), mode, std::move(options)) {}

    bool emit(const json& matched, json& output, const json& inherited) override;

    bool do_merge(const std::string& filepath,
                  const json& have,
                  const json& expected,
                  json& out_merged) override;
};

/**************************************************************************************************/

} // namespace hyde

/**************************************************************************************************/


================================================
FILE: emitters/yaml_function_emitter.cpp
================================================
/*
Copyright 2018 Adobe
All Rights Reserved.

NOTICE: Adobe permits you to use, modify, and distribute this file in
accordance with the terms of the Adobe license agreement accompanying
it. If you have received this file from a source other than Adobe,
then your use, modification, or distribution of it requires the prior
written permission of Adobe.
*/

// identity
#include "yaml_function_emitter.hpp"

// stdc++
#include <iostream>

// application
#include "matchers/utilities.hpp"

/**************************************************************************************************/

namespace hyde {

/**************************************************************************************************/

bool yaml_function_emitter::do_merge(const std::string& filepath,
                                     const json& have,
                                     const json& expected,
                                     json& out_merged) {
    bool failure{false};

    failure |= check_scalar(filepath, have, expected, "", out_merged, "defined_in_file");
    failure |= check_scalar_array(filepath, have, expected, "", out_merged, "namespace");
    failure |= check_scalar(filepath, have, expected, "", out_merged, "is_ctor");
    failure |= check_scalar(filepath, have, expected, "", out_merged, "is_dtor");
    failure |= check_map(
        filepath, have, expected, "", out_merged, "overloads",
        [this](const std::string& filepath, const json& have, const json& expected,
               const std::string& nodepath, json& out_merged) {
            bool failure{false};

            failure |= check_editable_scalar(filepath, have, expected, nodepath, out_merged,
                                             "description");
            failure |= check_scalar(filepath, have, expected, nodepath, out_merged,
                                    "signature_with_names");

            if (!has_json_flag(expected, "is_ctor") && !has_json_flag(expected, "is_dtor")) {
                failure |=
                    check_editable_scalar(filepath, have, expected, nodepath, out_merged, "return");
            }

            if (_options._tested_by != hyde::attribute_category::disabled) {
                failure |= check_editable_scalar_array(filepath, have, expected, nodepath,
                                                       out_merged, "tested_by");
            }

            failure |=
                check_scalar_array(filepath, have, expected, nodepath, out_merged, "annotation");

            failure |= check_object_array(
                filepath, have, expected, nodepath, out_merged, "arguments", "name",
                [this](const std::string& filepath, const json& have, const json& expected,
                       const std::string& nodepath, json& out_merged) {
                    bool failure{false};

                    failure |= check_scalar(filepath, have, expected, nodepath, out_merged, "name");
                    failure |= check_scalar(filepath, have, expected, nodepath, out_merged, "type");
                    failure |= check_editable_scalar(filepath, have, expected, nodepath, out_merged,
                                                     "description");
                    failure |=
                        check_scalar(filepath, have, expected, nodepath, out_merged, "unnamed");

                    check_inline_comments(expected, out_merged);

                    return failure;
                });

            check_inline_comments(expected, out_merged);

            return failure;
        });

    // REVISIT (fosterbrereton) : Roll-up the owners and briefs/descriptions to see if we can derive
    // a set of inline values here from inline values used in the function definition(s).

    check_inline_comments(expected, out_merged);

    return failure;
}

/**************************************************************************************************/

bool yaml_function_emitter::emit(const json& jsn, json& out_emitted, const json& inherited) {
    std::filesystem::path dst;
    std::string name;
    std::string filename;
    std::string defined_path;
    json overloads = json::object();
    bool first{true};
    bool is_ctor{false};
    bool is_dtor{false};
    bool all_compiler_managed{true};
    std::size_t count(jsn.size());
    std::size_t inline_description_count{0};
    json last_inline_description;
    std::size_t inline_brief_count{0};
    json last_inline_brief;
    std::vector<std::string> overload_owners;

    for (const auto& overload : jsn) {
        if (first) {
            dst = dst_path(overload);
            // always the unqualified name, as free functions may be defined
            // over different namespaces.
            name = overload["short_name"];
            // prefix to keep free-function from colliding with class member (e.g., `swap`)
            filename = (_as_methods ? "m_" : "f_") + filename_filter(name);
            defined_path = defined_in_file(overload["defined_in_file"], _src_root);
            is_ctor = has_json_flag(overload, "is_ctor");
            is_dtor = has_json_flag(overload, "is_dtor");
            first = false;
        }

        const std::string& key = static_cast<const std::string&>(overload["signature"]);
        auto& destination = overloads[key];

        // If there are any in-source (a.k.a. Doxygen) comments, insert them into
        // the node *first* so we can use them to decide if subsequent Hyde fields
        // can be deferred.
        insert_doxygen(overload, destination);

        // The intent of these checks is to roll up brief/description details that were
        // entered inline to the top-level file that documents this function and all of its
        // overrides. Note that a given override does _not_ require a `brief` value, but
        // _may_ require a `description` value if there is more than one override (otherwise
        // the description is optional, falling back to the top-level `brief` for the functions
        // documentation). I foresee *a lot* of conflation between `brief` and `description`
        // as developers document their code, so we'll have to track both of these values as if
        // they are the same to make it as easy as possible to bubble up information.
        if (destination.count("inline") && destination["inline"].count("brief")) {
            ++inline_brief_count;
            last_inline_brief = destination["inline"]["brief"];
        }
        if (destination.count("inline") && destination["inline"].count("description")) {
            ++inline_description_count;
            last_inline_description = destination["inline"]["description"];
        }
        if (destination.count("inline") && destination["inline"].count("owner")) {
            const auto& owners = destination["inline"]["owner"];
            if (owners.is_string()) {
                overload_owners.push_back(owners.get<std::string>());
            } else if (owners.is_array()) {
                for (const auto& owner : owners) {
                    overload_owners.push_back(owner.get<std::string>());
                }
            }
        }

        destination["signature_with_names"] = overload["signature_with_names"];

        // description is now optional when there is a singular variant, or when the overload
        // is compiler-managed (implicit, =default, or =delete)
        const bool has_associated_inline = has_inline_field(destination, "description");
        const bool is_implicit = has_json_flag(overload, "implicit");
        const bool is_defaulted = has_json_flag(overload, "defaulted");
        const bool is_deleted = has_json_flag(overload, "deleted");
        const bool is_compiler_managed = is_implicit || is_defaulted || is_deleted;
        const bool is_optional = count <= 1 || is_compiler_managed;
        destination["description"] = has_associated_inline ? tag_value_inlined_k :
                                     is_optional           ? tag_value_optional_k :
                                                             tag_value_missing_k;

        if (!is_ctor && !is_dtor) {
            destination["return"] = tag_value_optional_k;
        }

        if (_options._tested_by != hyde::attribute_category::disabled) {
            destination["tested_by"] = is_compiler_managed ? tag_value_optional_k : hyde::get_tag(_options._tested_by);
        }
        insert_annotations(overload, destination);

        all_compiler_managed &= is_compiler_managed;

        if (!overload["arguments"].empty()) {
            std::size_t j{0};
            auto& args = destination["arguments"];
            for (const auto& arg : overload["arguments"]) {
                auto& cur_arg = args[j];
                const std::string& name = arg["name"];
                const bool unnamed = name.empty();
                cur_arg["name"] = unnamed ? "unnamed-" + std::to_string(j) : name;
                cur_arg["type"] = arg["type"];
                cur_arg["description"] = tag_value_optional_k;
                if (unnamed) {
                    cur_arg["unnamed"] = true;
                }
                ++j;
            }
        }
    }

    json node = base_emitter_node(_as_methods ? "method" : "function", name,
                                  _as_methods ? "method" : "function",
                                  all_compiler_managed);

    insert_inherited(inherited, node["hyde"]);

    // If the function being emitted is either the ctor or dtor of a class,
    // the high-level `brief` is optional, as their default implementations
    // should require no additional commenatary beyond that which is provided
    // on an overload-by-overload basis.
    if (is_ctor || is_dtor) {
        node["hyde"]["brief"] = tag_value_optional_k;
    }

    // Here we roll-up the brief(s) and description(s) from the function overloads.
    // The complication here is that `description` may be required for the overloads,
    // but `brief` is not. However at the top level, `brief` _is_ required, and
    // `description` is not. So if there is one brief _or_ description, use that
    // as the inline brief for the top-level docs. (If there is one of each, brief
    // wins.) Beyond that, if there are multiple briefs and multiple descriptions,
    // we'll put some pat statement into the brief indicating as much. Finally, if
    // at least one overload has an inline `brief`, then the top-level `brief` is
    // marked inlined.
    if (inline_brief_count == 1) {
        node["hyde"]["inline"]["brief"] = last_inline_brief;
        node["hyde"]["brief"] = tag_value_inlined_k;
    } else if (inline_description_count == 1) {
        node["hyde"]["inline"]["brief"] = last_inline_description;
        node["hyde"]["brief"] = tag_value_inlined_k;
    } else if (inline_brief_count > 1 || inline_description_count > 1) {
        node["hyde"]["inline"]["brief"] = "_multiple descriptions_";
        node["hyde"]["brief"] = tag_value_inlined_k;
    }

    // Round up any overload owners into an inline top-level owner field,
    // and then set the hyde owner field to inlined.
    if (!overload_owners.empty()) {
        std::sort(overload_owners.begin(), overload_owners.end());
        overload_owners.erase(std::unique(overload_owners.begin(), overload_owners.end()),
                              overload_owners.end());
        json::array_t owners;
        std::copy(overload_owners.begin(), overload_owners.end(), std::back_inserter(owners));
        node["hyde"]["inline"]["owner"] = std::move(owners);
        node["hyde"]["owner"] = tag_value_inlined_k;
    } else if (node["hyde"].count("inline") && node["hyde"]["inline"].count("owner")) {
        node["hyde"]["owner"] = tag_value_inlined_k;
    }

    // All overloads will have the same namespace
    if (!_as_methods && jsn.size() > 0) {
        for (const auto& ns : jsn.front()["namespaces"])
            node["hyde"]["namespace"].push_back(static_cast<const std::string&>(ns));
    }

    node["hyde"]["defined_in_file"] = defined_path;
    node["hyde"]["overloads"] = std::move(overloads);
    if (is_ctor) node["hyde"]["is_ctor"] = true;
    if (is_dtor) node["hyde"]["is_dtor"] = true;

    if (_mode == yaml_mode::transcribe && !exists(dst)) {
        // In this case the symbol name has changed, which has caused a change to the directory name
        // we are now trying to load and reconcile with what we've created. In this case, we can
        // assume the "shape" of the documentation is the same, which means that within the parent
        // folder of `dst` is the actual source folder that holds the old documentation, just under
        // a different name. Find that folder and rename it.

        std::filesystem::rename(derive_transcription_src_path(dst, node["title"]), dst);
    }

    return reconcile(std::move(node), _dst_root, dst / (filename + ".md"), out_emitted);
}

/**************************************************************************************************/

} // namespace hyde

/**************************************************************************************************/


================================================
FILE: emitters/yaml_function_emitter.hpp
================================================
/*
Copyright 2018 Adobe
All Rights Reserved.

NOTICE: Adobe permits you to use, modify, and distribute this file in
accordance with the terms of the Adobe license agreement accompanying
it. If you have received this file from a source other than Adobe,
then your use, modification, or distribution of it requires the prior
written permission of Adobe.
*/

#pragma once

// application
#include "emitters/yaml_base_emitter.hpp"
#include "json.hpp"

/**************************************************************************************************/

namespace hyde {

/**************************************************************************************************/

struct yaml
Download .txt
gitextract_uuaa76lr/

├── .clang-format
├── .editorconfig
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── PULL_REQUEST_TEMPLATE/
│   │   ├── bug_fix.md
│   │   └── feature.md
│   └── workflows/
│       └── tagged-release.yml
├── .gitignore
├── .gitmodules
├── .hyde-config
├── CMakeLists.txt
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── docs/
│   ├── Gemfile
│   ├── _config.yml
│   ├── _includes/
│   │   └── head.html
│   ├── _posts/
│   │   └── 2018-10-30-welcome.markdown
│   ├── _sass/
│   │   ├── _overrides-dark.scss
│   │   ├── _overrides-light.scss
│   │   └── _overrides.scss
│   ├── about.md
│   ├── feed.xml
│   ├── index.html
│   ├── libraries/
│   │   ├── classes.cpp/
│   │   │   ├── class_example/
│   │   │   │   ├── color.md
│   │   │   │   ├── index.md
│   │   │   │   ├── m_class_example.md
│   │   │   │   ├── m_deprecated.md
│   │   │   │   ├── m_deprecated_with_message.md
│   │   │   │   ├── m_member_function.md
│   │   │   │   ├── m_member_function_trailing_return_type.md
│   │   │   │   ├── m_overloaded.md
│   │   │   │   ├── m_static_method.md
│   │   │   │   ├── m_template_member_function.md
│   │   │   │   └── nested_class_example/
│   │   │   │       ├── index.md
│   │   │   │       ├── m_nested_class_example.md
│   │   │   │       └── m_~nested_class_example.md
│   │   │   ├── index.md
│   │   │   ├── partial_specialization_.4b7bfe45/
│   │   │   │   └── index.md
│   │   │   ├── partial_specialization_.edfbc14d/
│   │   │   │   └── index.md
│   │   │   ├── specialization_example3.ed9d8cc7/
│   │   │   │   ├── index.md
│   │   │   │   └── m_as_tuple.md
│   │   │   ├── specialization_example3CT3E/
│   │   │   │   ├── index.md
│   │   │   │   └── m_as_tuple.md
│   │   │   └── specialization_example3Cfloat3E/
│   │   │       ├── index.md
│   │   │       └── m_as_tuple.md
│   │   ├── comments.cpp/
│   │   │   ├── compiler_generated/
│   │   │   │   ├── index.md
│   │   │   │   ├── m_assign.md
│   │   │   │   ├── m_compiler_generated.md
│   │   │   │   └── m_operator3D.md
│   │   │   ├── f_template_function.md
│   │   │   ├── index.md
│   │   │   ├── some_other_struct/
│   │   │   │   ├── index.md
│   │   │   │   ├── m_operator3D.md
│   │   │   │   ├── m_some_other_struct.md
│   │   │   │   ├── m_virtual_function.md
│   │   │   │   └── m_~some_other_struct.md
│   │   │   └── some_struct/
│   │   │       ├── index.md
│   │   │       ├── m_operator3D.md
│   │   │       ├── m_some_function.md
│   │   │       ├── m_some_struct.md
│   │   │       ├── m_virtual_function.md
│   │   │       └── m_~some_struct.md
│   │   ├── enums.cpp/
│   │   │   ├── color_channel.md
│   │   │   ├── index.md
│   │   │   └── untyped.md
│   │   ├── functions.cpp/
│   │   │   ├── f_binary_function_example.md
│   │   │   ├── f_nullary_function_example.md
│   │   │   ├── f_overloaded.md
│   │   │   ├── f_static_auto_function_example.md
│   │   │   ├── f_static_function_example.md
│   │   │   ├── f_static_trailing_type_function_example.md
│   │   │   ├── f_template_function_example.md
│   │   │   └── index.md
│   │   ├── index.md
│   │   ├── namespaces.cpp/
│   │   │   ├── f_function.md
│   │   │   └── index.md
│   │   ├── point.cpp/
│   │   │   ├── index.md
│   │   │   └── point3CT3E/
│   │   │       ├── f_operator-.md
│   │   │       ├── f_operator213D.md
│   │   │       ├── f_operator3D3D.md
│   │   │       ├── index.md
│   │   │       ├── m_operator-3D.md
│   │   │       ├── m_origin.md
│   │   │       └── m_point3CT3E.md
│   │   └── typedef_and_alias.cpp/
│   │       ├── index.md
│   │       ├── template_example3CT2C20U3E/
│   │       │   └── index.md
│   │       └── template_example_instantiator/
│   │           └── index.md
│   └── serve.sh
├── emitters/
│   ├── yaml_base_emitter.cpp
│   ├── yaml_base_emitter.hpp
│   ├── yaml_base_emitter_fwd.hpp
│   ├── yaml_class_emitter.cpp
│   ├── yaml_class_emitter.hpp
│   ├── yaml_enum_emitter.cpp
│   ├── yaml_enum_emitter.hpp
│   ├── yaml_function_emitter.cpp
│   ├── yaml_function_emitter.hpp
│   ├── yaml_library_emitter.cpp
│   ├── yaml_library_emitter.hpp
│   ├── yaml_sourcefile_emitter.cpp
│   └── yaml_sourcefile_emitter.hpp
├── generate_test_files.sh
├── include/
│   ├── _clang_include_prefix.hpp
│   ├── _clang_include_suffix.hpp
│   ├── autodetect.hpp
│   ├── config.hpp
│   ├── json.hpp
│   ├── json_fwd.hpp
│   └── output_yaml.hpp
├── matchers/
│   ├── class_matcher.cpp
│   ├── class_matcher.hpp
│   ├── enum_matcher.cpp
│   ├── enum_matcher.hpp
│   ├── function_matcher.cpp
│   ├── function_matcher.hpp
│   ├── matcher_fwd.hpp
│   ├── namespace_matcher.cpp
│   ├── namespace_matcher.hpp
│   ├── typealias_matcher.cpp
│   ├── typealias_matcher.hpp
│   ├── typedef_matcher.cpp
│   ├── typedef_matcher.hpp
│   ├── utilities.cpp
│   └── utilities.hpp
├── sources/
│   ├── autodetect.cpp
│   ├── main.cpp
│   └── output_yaml.cpp
└── test_files/
    ├── classes.cpp
    ├── comments.cpp
    ├── enums.cpp
    ├── functions.cpp
    ├── namespaces.cpp
    ├── point.cpp
    └── typedef_and_alias.cpp
Download .txt
SYMBOL INDEX (207 symbols across 41 files)

FILE: emitters/yaml_base_emitter.cpp
  function update_cleanup (line 38) | YAML::Node update_cleanup(const YAML::Node& node) {
  function yaml_to_json (line 66) | hyde::json yaml_to_json(const YAML::Node& yaml) {
  function json_to_yaml (line 98) | YAML::Node json_to_yaml(const hyde::json& json) {
  function json_to_yaml_ordered (line 144) | YAML::Node json_to_yaml_ordered(hyde::json j) {
  function fixup_hyde_subfield (line 198) | hyde::json fixup_hyde_subfield(hyde::json&& j) {
  type hyde (line 241) | namespace hyde {
    function json (line 249) | json yaml_base_emitter::base_emitter_node(std::string layout,
    function object_keys (line 985) | std::vector<std::string> object_keys(const json& j) {
    function move_append (line 996) | inline void move_append(T& dst, T&& src) {
    type transcribe_pair (line 1000) | struct transcribe_pair {
    function transcribe_pairs (line 1011) | transcribe_pairs derive_transcribe_pairs(const json& src, const json& ...
    function fnv_1a (line 1236) | inline std::uint64_t fnv_1a(const std::string& s) {
    function load_yaml (line 1352) | auto load_yaml(const std::filesystem::path& path) try {
    function documentation (line 1361) | documentation parse_documentation(const std::filesystem::path& path, b...
    function write_documentation (line 1402) | bool write_documentation(const documentation& docs, const std::filesys...

FILE: emitters/yaml_base_emitter.hpp
  type hyde (line 21) | namespace hyde {
    type file_checker (line 25) | struct file_checker {
      method exists (line 26) | bool exists(std::filesystem::path p) {
      method checked (line 32) | bool checked(const std::filesystem::path& p) {
    function has_json_flag (line 50) | inline bool has_json_flag(const json& j, const char* k) {
    type yaml_base_emitter (line 56) | struct yaml_base_emitter {
      method yaml_base_emitter (line 58) | yaml_base_emitter(std::filesystem::path src_root,
      method dst_path_append (line 177) | std::filesystem::path dst_path_append(std::filesystem::path p) { ret...

FILE: emitters/yaml_base_emitter_fwd.hpp
  type hyde (line 24) | namespace hyde {
    type attribute_category (line 36) | enum class attribute_category { disabled, required, optional, deprecat...
    function is_tag (line 53) | static inline bool is_tag(const std::string& s) { return s.substr(0, 2...
    type emit_options (line 57) | struct emit_options {
    type documentation (line 64) | struct documentation {

FILE: emitters/yaml_class_emitter.cpp
  type hyde (line 24) | namespace hyde {

FILE: emitters/yaml_class_emitter.hpp
  type hyde (line 20) | namespace hyde {
    type yaml_class_emitter (line 24) | struct yaml_class_emitter : public yaml_base_emitter {
      method yaml_class_emitter (line 25) | explicit yaml_class_emitter(std::filesystem::path src_root,

FILE: emitters/yaml_enum_emitter.cpp
  type hyde (line 20) | namespace hyde {

FILE: emitters/yaml_enum_emitter.hpp
  type hyde (line 20) | namespace hyde {
    type yaml_enum_emitter (line 24) | struct yaml_enum_emitter : public yaml_base_emitter {
      method yaml_enum_emitter (line 25) | explicit yaml_enum_emitter(std::filesystem::path src_root,

FILE: emitters/yaml_function_emitter.cpp
  type hyde (line 23) | namespace hyde {

FILE: emitters/yaml_function_emitter.hpp
  type hyde (line 20) | namespace hyde {
    type yaml_function_emitter (line 24) | struct yaml_function_emitter : public yaml_base_emitter {
      method yaml_function_emitter (line 25) | explicit yaml_function_emitter(std::filesystem::path src_root,
      method set_key (line 33) | void set_key(std::string key) { _key = std::move(key); }

FILE: emitters/yaml_library_emitter.cpp
  type hyde (line 20) | namespace hyde {

FILE: emitters/yaml_library_emitter.hpp
  type hyde (line 20) | namespace hyde {
    type yaml_library_emitter (line 24) | struct yaml_library_emitter : public yaml_base_emitter {
      method yaml_library_emitter (line 25) | explicit yaml_library_emitter(std::filesystem::path src_root,

FILE: emitters/yaml_sourcefile_emitter.cpp
  type hyde (line 20) | namespace hyde {

FILE: emitters/yaml_sourcefile_emitter.hpp
  type hyde (line 20) | namespace hyde {
    type yaml_sourcefile_emitter (line 24) | struct yaml_sourcefile_emitter : public yaml_base_emitter {
      method yaml_sourcefile_emitter (line 25) | explicit yaml_sourcefile_emitter(std::filesystem::path src_root,

FILE: include/autodetect.hpp
  type hyde (line 24) | namespace hyde {

FILE: include/json_fwd.hpp
  type hyde (line 22) | namespace hyde {

FILE: include/output_yaml.hpp
  type hyde (line 23) | namespace hyde {
    type yaml_mode (line 27) | enum class yaml_mode {

FILE: matchers/class_matcher.cpp
  class FindDestructor (line 37) | class FindDestructor : public RecursiveASTVisitor<FindDestructor> {
    method VisitDecl (line 39) | bool VisitDecl(const Decl* d) {
  class FindConstructor (line 52) | class FindConstructor : public RecursiveASTVisitor<FindConstructor> {
    method VisitDecl (line 54) | bool VisitDecl(const Decl* d) {
  class FindStaticMembers (line 67) | class FindStaticMembers : public RecursiveASTVisitor<FindStaticMembers> {
    method FindStaticMembers (line 69) | FindStaticMembers(const hyde::processing_options& options)
    method VisitVarDecl (line 71) | bool VisitVarDecl(const VarDecl* d) {
  type hyde (line 95) | namespace hyde {
    function json (line 99) | json fixup_short_name(json&& method) {

FILE: matchers/class_matcher.hpp
  type hyde (line 31) | namespace hyde {
    class ClassInfo (line 35) | class ClassInfo : public MatchFinder::MatchCallback {
      method ClassInfo (line 37) | explicit ClassInfo(processing_options options) : _options(std::move(...
      method json (line 43) | json getJSON() { return _j; }
      method DeclarationMatcher (line 45) | static DeclarationMatcher GetMatcher() { return cxxRecordDecl().bind...

FILE: matchers/enum_matcher.cpp
  type hyde (line 36) | namespace hyde {

FILE: matchers/enum_matcher.hpp
  type hyde (line 31) | namespace hyde {
    class EnumInfo (line 35) | class EnumInfo : public MatchFinder::MatchCallback {
      method EnumInfo (line 37) | EnumInfo(processing_options options) : _options(std::move(options)) {
      method json (line 43) | json getJSON() { return _j; }
      method DeclarationMatcher (line 45) | static DeclarationMatcher GetMatcher() { return enumDecl().bind("enu...

FILE: matchers/function_matcher.cpp
  type hyde (line 37) | namespace hyde {

FILE: matchers/function_matcher.hpp
  type hyde (line 31) | namespace hyde {
    class FunctionInfo (line 35) | class FunctionInfo : public MatchFinder::MatchCallback {
      method FunctionInfo (line 37) | FunctionInfo(processing_options options) : _options(std::move(option...
      method json (line 43) | json getJSON() { return _j; }
      method DeclarationMatcher (line 45) | static DeclarationMatcher GetMatcher() { return functionDecl().bind(...

FILE: matchers/matcher_fwd.hpp
  type hyde (line 20) | namespace hyde {
    type ToolAccessFilter (line 24) | enum ToolAccessFilter {
    type processing_options (line 32) | struct processing_options {

FILE: matchers/namespace_matcher.cpp
  type hyde (line 36) | namespace hyde {

FILE: matchers/namespace_matcher.hpp
  type hyde (line 31) | namespace hyde {
    class NamespaceInfo (line 35) | class NamespaceInfo : public MatchFinder::MatchCallback {
      method NamespaceInfo (line 37) | NamespaceInfo(processing_options options) : _options(std::move(optio...
      method json (line 43) | json getJSON() { return _j; }
      method DeclarationMatcher (line 45) | static DeclarationMatcher GetMatcher() { return namespaceDecl().bind...

FILE: matchers/typealias_matcher.cpp
  type hyde (line 36) | namespace hyde {

FILE: matchers/typealias_matcher.hpp
  type hyde (line 31) | namespace hyde {
    class TypeAliasInfo (line 35) | class TypeAliasInfo : public MatchFinder::MatchCallback {
      method TypeAliasInfo (line 37) | TypeAliasInfo(processing_options options) : _options(std::move(optio...
      method json (line 43) | json getJSON() { return _j; }
      method DeclarationMatcher (line 45) | static DeclarationMatcher GetMatcher() { return typeAliasDecl().bind...

FILE: matchers/typedef_matcher.cpp
  type hyde (line 36) | namespace hyde {

FILE: matchers/typedef_matcher.hpp
  type hyde (line 31) | namespace hyde {
    class TypedefInfo (line 35) | class TypedefInfo : public MatchFinder::MatchCallback {
      method TypedefInfo (line 37) | TypedefInfo(processing_options options) : _options(std::move(options...
      method json (line 43) | json getJSON() { return _j; }
      method DeclarationMatcher (line 45) | static DeclarationMatcher GetMatcher() { return typedefDecl().bind("...

FILE: matchers/utilities.cpp
  function trim_front (line 51) | void trim_front(std::string& text) {
  function trim_back (line 62) | void trim_back(std::string& src) {
  function chomp (line 73) | void chomp(std::string& src) {
  function to_string (line 82) | std::string to_string(const ASTContext* n, SourceRange range, bool as_to...
  function to_string (line 94) | std::string to_string(const ASTContext* n, const clang::TemplateDecl* te...
  function ForEachParent (line 117) | void ForEachParent(const Decl* d, F f) {
  type signature_options (line 141) | enum class signature_options : std::uint8_t {
  function flag_set (line 148) | bool flag_set(const T& value, const T& flag) {
  function GetSignature (line 156) | std::string GetSignature(const ASTContext* n,
  function GetShortName (line 289) | std::string GetShortName(const clang::ASTContext* n, const clang::Functi...
  function GetParents (line 311) | hyde::json GetParents(const ASTContext* n, const Decl* d) {
  function to_string_view (line 352) | inline std::string_view to_string_view(StringRef string) {
  function to_string_view (line 358) | inline std::string_view to_string_view(ParamCommandPassDirection x) {
  function ProcessComment (line 371) | hyde::optional_json ProcessComment(const ASTContext& n,
  function group_comments_by_kind (line 607) | hyde::optional_json group_comments_by_kind(hyde::json comments) {
  type hyde (line 627) | namespace hyde {
    function json (line 631) | json GetParentNamespaces(const ASTContext* n, const Decl* d) {
    function json (line 637) | json GetParentCXXRecords(const ASTContext* n, const Decl* d) {
    function optional_json (line 643) | optional_json DetailCXXRecordDecl(const hyde::processing_options& opti...
    function json (line 664) | json GetTemplateParameters(const ASTContext* n, const clang::TemplateD...
    function optional_json (line 700) | optional_json DetailFunctionDecl(const hyde::processing_options& optio...
    function GetArgumentList (line 791) | std::string GetArgumentList(const llvm::ArrayRef<clang::NamedDecl*> ar...
    function PathCheck (line 809) | bool PathCheck(const std::vector<std::string>& paths, const Decl* d, A...
    function NamespaceBlacklist (line 818) | bool NamespaceBlacklist(const std::vector<std::string>& blacklist, con...
    function AccessCheck (line 832) | bool AccessCheck(ToolAccessFilter hyde_filter, clang::AccessSpecifier ...
    function PostProcessTypeParameter (line 863) | std::string PostProcessTypeParameter(const clang::Decl* decl, std::str...
    function ReplaceAll (line 939) | std::string ReplaceAll(std::string str, const std::string& substr, con...
    function PostProcessSpacing (line 950) | std::string PostProcessSpacing(std::string type) { return ReplaceAll(t...
    function PostProcessType (line 954) | std::string PostProcessType(const clang::Decl* decl, std::string type) {
    function ProcessComments (line 962) | hyde::optional_json ProcessComments(const Decl* d) {
    function derive_transcription_src_path (line 993) | std::filesystem::path derive_transcription_src_path(const std::filesys...
    function diff_score (line 1058) | std::size_t diff_score(std::string_view src, std::string_view dst) {

FILE: matchers/utilities.hpp
  type hyde (line 34) | namespace hyde {
    function to_string (line 83) | inline std::string to_string(clang::AccessSpecifier access) {
    function to_string (line 99) | inline std::string to_string(const clang::Decl* decl, clang::QualType ...
    function optional_json (line 109) | optional_json StandardDeclInfo(const hyde::processing_options& options...

FILE: sources/autodetect.cpp
  function split (line 33) | std::vector<std::string> split(const char* p, std::size_t n) {
  function file_slurp (line 51) | std::vector<std::string> file_slurp(std::filesystem::path p) {
  function trim_front (line 63) | std::string trim_front(std::string s) {
  function trim_back (line 77) | std::string trim_back(std::string s) {
  function chomp (line 90) | std::string chomp(std::string src) { return trim_back(trim_front(std::mo...
  function exec (line 94) | std::string exec(const char* cmd) {
  function autodetect_include_paths (line 115) | std::vector<std::filesystem::path> autodetect_include_paths() {
  type hyde (line 162) | namespace hyde {
    function autodetect_toolchain_paths (line 166) | std::vector<std::filesystem::path> autodetect_toolchain_paths() {
    function autodetect_resource_directory (line 172) | std::filesystem::path autodetect_resource_directory() {
    function autodetect_sysroot_directory (line 178) | std::filesystem::path autodetect_sysroot_directory() {

FILE: sources/main.cpp
  function make_absolute (line 57) | std::filesystem::path make_absolute(std::filesystem::path path) {
  function make_absolute (line 73) | std::string make_absolute(std::string path_string) {
  function make_absolute (line 79) | std::vector<std::string> make_absolute(std::vector<std::string> paths) {
  type ToolMode (line 95) | enum ToolMode { ToolModeJSON, ToolModeYAMLValidate, ToolModeYAMLUpdate, ...
  type ToolDiagnostic (line 96) | enum ToolDiagnostic { ToolDiagnosticQuiet, ToolDiagnosticVerbose, ToolDi...
  function IsVerbose (line 247) | bool IsVerbose() {
  function optional_path_t (line 257) | optional_path_t find_hyde_config(std::filesystem::path src_file) {
  function load_hyde_config (line 296) | std::pair<std::filesystem::path, hyde::json> load_hyde_config(
  type command_line_args (line 318) | struct command_line_args {
  function command_line_args (line 323) | command_line_args integrate_hyde_config(int argc, const char** argv) {
  function CommonOptionsParser (line 407) | CommonOptionsParser MakeOptionsParser(int argc, const char** argv) {
  function fixup_have_file_subfield (line 419) | bool fixup_have_file_subfield(const std::filesystem::path& path) {
  function source_paths (line 437) | std::vector<std::string> source_paths(int argc, const char** argv) {
  function main (line 443) | int main(int argc, const char** argv) try {

FILE: sources/output_yaml.cpp
  type hyde (line 31) | namespace hyde {
    function output_yaml (line 35) | void output_yaml(json j,

FILE: test_files/classes.cpp
  class class_example (line 22) | class class_example {
    type color (line 28) | enum class color {
    type nested_class_example (line 41) | struct nested_class_example {
    method class_example (line 58) | class_example() = default;
    method class_example (line 62) | explicit class_example(int x) : _x(x) {}
    method member_function_trailing_return_type (line 67) | auto member_function_trailing_return_type() const -> int { return _x; }
    method member_function (line 71) | auto member_function() { return _x *= 2; }
    method static_method (line 126) | static int static_method() { return 0; }
    method template_member_function (line 130) | void template_member_function() {}
  type specialization_example (line 152) | struct specialization_example {
    method as_tuple (line 153) | constexpr auto as_tuple() const { return std::forward_as_tuple(); }
  type specialization_example<std::int32_t> (line 159) | struct specialization_example<std::int32_t> {
    method as_tuple (line 165) | constexpr auto as_tuple() const { return std::forward_as_tuple(_first); }
  type specialization_example<float> (line 171) | struct specialization_example<float> {
    method as_tuple (line 174) | constexpr auto as_tuple() const { return std::forward_as_tuple(_first); }
  class partial_specialization_example (line 182) | class partial_specialization_example {
  class partial_specialization_example<int, T> (line 190) | class partial_specialization_example<int, T> {

FILE: test_files/comments.cpp
  type compiler_generated (line 17) | struct compiler_generated {
    method compiler_generated (line 18) | compiler_generated() = delete;
    method compiler_generated (line 19) | compiler_generated(const compiler_generated&) = default;
    method assign (line 22) | void assign(const compiler_generated& rhs) {
  type some_struct (line 33) | struct some_struct {
  type some_other_struct (line 58) | struct some_other_struct : public some_struct {

FILE: test_files/enums.cpp
  type color_channel (line 19) | enum class color_channel {
  type untyped (line 32) | enum untyped {

FILE: test_files/functions.cpp
  function nullary_function_example (line 16) | int nullary_function_example() { return 0; }
  function binary_function_example (line 23) | int binary_function_example(int first, int second) { return 0; }
  function overloaded (line 29) | auto overloaded(int first) -> float { return first; }
  function overloaded (line 35) | auto overloaded(int first, int second) -> double { return first * second; }
  function overloaded (line 42) | auto overloaded(int first, int second, int third) -> float { return firs...
  function static_function_example (line 47) | static int static_function_example() { return 0; }
  function static_auto_function_example (line 52) | static auto static_auto_function_example() { return 0; }
  function static_trailing_type_function_example (line 57) | static auto static_trailing_type_function_example() -> int { return 0; }
  function template_function_example (line 68) | int template_function_example() {

FILE: test_files/namespaces.cpp
  type foo (line 14) | namespace foo {
    type bar::baz (line 18) | namespace bar::baz {

FILE: test_files/point.cpp
  type point (line 21) | struct point {
    method origin (line 29) | static constexpr auto origin() { return point(); }
    method point (line 33) | constexpr point() noexcept = default;
    method point (line 38) | constexpr point(T _x, T _y) noexcept : x(std::move(_x)), y(std::move(_...
    method point (line 54) | inline constexpr point operator-(const point& a, const point& b) {
    method point (line 61) | constexpr point& operator-=(const point& a) {

FILE: test_files/typedef_and_alias.cpp
  type template_example (line 27) | struct template_example {
  type template_example_instantiator (line 49) | struct template_example_instantiator {
Condensed preview — 137 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (359K chars).
[
  {
    "path": ".clang-format",
    "chars": 3048,
    "preview": "# Format style options described here:\n#     https://clang.llvm.org/docs/ClangFormatStyleOptions.html\n\n# Many of the ali"
  },
  {
    "path": ".editorconfig",
    "chars": 316,
    "preview": "# According to https://stackoverflow.com/a/33831598/153535, this should improve\n# the way code is seen on GitHub (PRs, e"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 799,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\n\n---\n\n**Describe the bug**\nA clear and concise descriptio"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 560,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\n\n---\n\n**Is your feature request related to a problem? "
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/bug_fix.md",
    "chars": 259,
    "preview": "---\nname: Bug fix\nabout: Submit a fix for an issue\n---\n\n**Fix for issue(s)**\n#NNNN\n\n**Diagnosis**\nPlease include a brief"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/feature.md",
    "chars": 321,
    "preview": "---\nname: Feature\nabout: Provide new functionality\n---\n\n**Optional: Related issue(s)**\n#NNNN\n\n**What's Changed**\nA clear"
  },
  {
    "path": ".github/workflows/tagged-release.yml",
    "chars": 1920,
    "preview": "name: Tagged Release\non:\n  push:\n    tags:\n      - \"v*.*.*\"\n  workflow_dispatch: null\npermissions:\n  contents: write\njob"
  },
  {
    "path": ".gitignore",
    "chars": 102,
    "preview": "*.sublime-project\n*.sublime-workspace\n.DS_Store\n.vscode/\nbuild/\nbuild*/\ndocs/_site/\ndocs/Gemfile.lock\n"
  },
  {
    "path": ".gitmodules",
    "chars": 206,
    "preview": "[submodule \"submodules/yaml-cpp\"]\n\tpath = submodules/yaml-cpp\n\turl = https://github.com/jbeder/yaml-cpp.git\n[submodule \""
  },
  {
    "path": ".hyde-config",
    "chars": 160,
    "preview": "{\n    \"hyde-src-root\" : \"./test_files\",\n    \"hyde-yaml-dir\" : \"./docs/libraries\",\n    \"clang_flags\": [\n        \"--std=c+"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 5614,
    "preview": "# Copyright 2018 Adobe\n# All Rights Reserved.\n\n# NOTICE: Adobe permits you to use, modify, and distribute this file in\n#"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3223,
    "preview": "# Adobe Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributo"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1959,
    "preview": "# Contributing\n\nThanks for choosing to contribute!\n\nThe following are a set of guidelines to follow when contributing to"
  },
  {
    "path": "Dockerfile",
    "chars": 2162,
    "preview": "\nFROM --platform=linux/x86_64 ubuntu:latest\nRUN apt-get -y update && apt-get install -y\n\nRUN apt-get -y install curl gnu"
  },
  {
    "path": "LICENSE",
    "chars": 1082,
    "preview": "MIT License\n\n© Copyright 2018 Adobe. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person o"
  },
  {
    "path": "README.md",
    "chars": 6965,
    "preview": "# What is `hyde`\n\n`hyde` is a utility that facilitates documenting C++. The tool is unique from existing documentation u"
  },
  {
    "path": "docs/Gemfile",
    "chars": 392,
    "preview": "source \"https://rubygems.org\"\n\n# Manage our dependency on the version of the github-pages gem here.\ngem \"github-pages\", "
  },
  {
    "path": "docs/_config.yml",
    "chars": 882,
    "preview": "# Welcome to Jekyll!\n#\n# This config file is meant for settings that affect your whole blog, values\n# which you are expe"
  },
  {
    "path": "docs/_includes/head.html",
    "chars": 1330,
    "preview": "<head>\n  <meta charset=\"utf-8\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n  <meta name=\"viewport\" content="
  },
  {
    "path": "docs/_posts/2018-10-30-welcome.markdown",
    "chars": 184,
    "preview": "---\nlayout: post\ntitle:  Welcome!\nexcerpt_separator: <!--more-->\n---\n\nThis is the landing page for the `hyde` sample fil"
  },
  {
    "path": "docs/_sass/_overrides-dark.scss",
    "chars": 366,
    "preview": "// Copy this file to you site and use it to override CSS variables that apply to the dark CSS\n// definitions. See `main-"
  },
  {
    "path": "docs/_sass/_overrides-light.scss",
    "chars": 370,
    "preview": "// Copy this file to you site and use it to override CSS variables that apply to the light CSS\n// definitions. See `main"
  },
  {
    "path": "docs/_sass/_overrides.scss",
    "chars": 414,
    "preview": "// Copy this file to you site and use it to override CSS variables that apply to both the light and\n// dark CSS definiti"
  },
  {
    "path": "docs/about.md",
    "chars": 135,
    "preview": "---\nlayout: page\ntitle: About\ntab: About\npermalink: /about/\n---\n\nThis is the about page. There are many like it, but thi"
  },
  {
    "path": "docs/feed.xml",
    "chars": 1291,
    "preview": "---\nlayout: null\n---\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">"
  },
  {
    "path": "docs/index.html",
    "chars": 795,
    "preview": "---\nlayout: default\n---\n\n<div class=\"home\">\n\n  <table class='icon-table'>\n  <tr>\n    <td>\n        <a href='libraries/'>\n"
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/color.md",
    "chars": 840,
    "preview": "---\nlayout: enumeration\ntitle: color\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - enumeration\n  inline:"
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/index.md",
    "chars": 1478,
    "preview": "---\nlayout: class\ntitle: class_example\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - class\n  inline:\n   "
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/m_class_example.md",
    "chars": 859,
    "preview": "---\nlayout: method\ntitle: class_example\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - method\n  inline:\n "
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/m_deprecated.md",
    "chars": 910,
    "preview": "---\nlayout: method\ntitle: deprecated\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - method\n  inline:\n    "
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/m_deprecated_with_message.md",
    "chars": 1051,
    "preview": "---\nlayout: method\ntitle: deprecated_with_message\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - method\n "
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/m_member_function.md",
    "chars": 488,
    "preview": "---\nlayout: method\ntitle: member_function\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - method\n  inline:"
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/m_member_function_trailing_return_type.md",
    "chars": 604,
    "preview": "---\nlayout: method\ntitle: member_function_trailing_return_type\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n "
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/m_overloaded.md",
    "chars": 4772,
    "preview": "---\nlayout: method\ntitle: overloaded\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - method\n  inline:\n    "
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/m_static_method.md",
    "chars": 521,
    "preview": "---\nlayout: method\ntitle: static_method\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - method\n  inline:\n "
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/m_template_member_function.md",
    "chars": 779,
    "preview": "---\nlayout: method\ntitle: template_member_function\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - method\n"
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/nested_class_example/index.md",
    "chars": 820,
    "preview": "---\nlayout: class\ntitle: nested_class_example\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - class\n  inli"
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/nested_class_example/m_nested_class_example.md",
    "chars": 1141,
    "preview": "---\nlayout: method\ntitle: nested_class_example\nhyde:\n  owner: __INLINED__\n  brief: __OPTIONAL__\n  tags:\n    - method\n  i"
  },
  {
    "path": "docs/libraries/classes.cpp/class_example/nested_class_example/m_~nested_class_example.md",
    "chars": 365,
    "preview": "---\nlayout: method\ntitle: ~nested_class_example\nhyde:\n  owner: __INLINED__\n  brief: __OPTIONAL__\n  tags:\n    - method\n  "
  },
  {
    "path": "docs/libraries/classes.cpp/index.md",
    "chars": 143,
    "preview": "---\nlayout: library\ntitle: classes.cpp\nhyde:\n  owner: __MISSING__\n  brief: __MISSING__\n  tags:\n    - sourcefile\n  librar"
  },
  {
    "path": "docs/libraries/classes.cpp/partial_specialization_.4b7bfe45/index.md",
    "chars": 561,
    "preview": "---\nlayout: class\ntitle: partial_specialization_example<int, T>\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n"
  },
  {
    "path": "docs/libraries/classes.cpp/partial_specialization_.edfbc14d/index.md",
    "chars": 596,
    "preview": "---\nlayout: class\ntitle: partial_specialization_example<T1, T2>\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n"
  },
  {
    "path": "docs/libraries/classes.cpp/specialization_example3.ed9d8cc7/index.md",
    "chars": 685,
    "preview": "---\nlayout: class\ntitle: specialization_example<std::int32_t>\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n  "
  },
  {
    "path": "docs/libraries/classes.cpp/specialization_example3.ed9d8cc7/m_as_tuple.md",
    "chars": 529,
    "preview": "---\nlayout: method\ntitle: as_tuple\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - method\n  inline:\n    br"
  },
  {
    "path": "docs/libraries/classes.cpp/specialization_example3CT3E/index.md",
    "chars": 364,
    "preview": "---\nlayout: class\ntitle: specialization_example<T>\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - class\n "
  },
  {
    "path": "docs/libraries/classes.cpp/specialization_example3CT3E/m_as_tuple.md",
    "chars": 344,
    "preview": "---\nlayout: method\ntitle: as_tuple\nhyde:\n  owner: __INLINED__\n  brief: __MISSING__\n  tags:\n    - method\n  inline:\n    ow"
  },
  {
    "path": "docs/libraries/classes.cpp/specialization_example3Cfloat3E/index.md",
    "chars": 602,
    "preview": "---\nlayout: class\ntitle: specialization_example<float>\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - cla"
  },
  {
    "path": "docs/libraries/classes.cpp/specialization_example3Cfloat3E/m_as_tuple.md",
    "chars": 376,
    "preview": "---\nlayout: method\ntitle: as_tuple\nhyde:\n  owner: __INLINED__\n  brief: __MISSING__\n  tags:\n    - method\n  inline:\n    ow"
  },
  {
    "path": "docs/libraries/comments.cpp/compiler_generated/index.md",
    "chars": 331,
    "preview": "---\nlayout: class\ntitle: compiler_generated\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - class\n  inline"
  },
  {
    "path": "docs/libraries/comments.cpp/compiler_generated/m_assign.md",
    "chars": 724,
    "preview": "---\nlayout: method\ntitle: assign\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - method\n  inline:\n    brie"
  },
  {
    "path": "docs/libraries/comments.cpp/compiler_generated/m_compiler_generated.md",
    "chars": 702,
    "preview": "---\nlayout: method\ntitle: compiler_generated\nhyde:\n  owner: __INLINED__\n  brief: __OPTIONAL__\n  tags:\n    - method\n  inl"
  },
  {
    "path": "docs/libraries/comments.cpp/compiler_generated/m_operator3D.md",
    "chars": 604,
    "preview": "---\nlayout: method\ntitle: operator=\nhyde:\n  owner: __INLINED__\n  brief: __OPTIONAL__\n  tags:\n    - method\n  inline:\n    "
  },
  {
    "path": "docs/libraries/comments.cpp/f_template_function.md",
    "chars": 482,
    "preview": "---\nlayout: function\ntitle: template_function\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - function\n  i"
  },
  {
    "path": "docs/libraries/comments.cpp/index.md",
    "chars": 144,
    "preview": "---\nlayout: library\ntitle: comments.cpp\nhyde:\n  owner: __MISSING__\n  brief: __MISSING__\n  tags:\n    - sourcefile\n  libra"
  },
  {
    "path": "docs/libraries/comments.cpp/some_other_struct/index.md",
    "chars": 411,
    "preview": "---\nlayout: class\ntitle: some_other_struct\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - class\n  inline:"
  },
  {
    "path": "docs/libraries/comments.cpp/some_other_struct/m_operator3D.md",
    "chars": 917,
    "preview": "---\nlayout: method\ntitle: operator=\nhyde:\n  owner: __OPTIONAL__\n  brief: __OPTIONAL__\n  tags:\n    - method\n  defined_in_"
  },
  {
    "path": "docs/libraries/comments.cpp/some_other_struct/m_some_other_struct.md",
    "chars": 839,
    "preview": "---\nlayout: method\ntitle: some_other_struct\nhyde:\n  owner: __OPTIONAL__\n  brief: __OPTIONAL__\n  tags:\n    - method\n  def"
  },
  {
    "path": "docs/libraries/comments.cpp/some_other_struct/m_virtual_function.md",
    "chars": 476,
    "preview": "---\nlayout: method\ntitle: virtual_function\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - method\n  inline"
  },
  {
    "path": "docs/libraries/comments.cpp/some_other_struct/m_~some_other_struct.md",
    "chars": 325,
    "preview": "---\nlayout: method\ntitle: ~some_other_struct\nhyde:\n  owner: __OPTIONAL__\n  brief: __OPTIONAL__\n  tags:\n    - method\n  de"
  },
  {
    "path": "docs/libraries/comments.cpp/some_struct/index.md",
    "chars": 728,
    "preview": "---\nlayout: class\ntitle: some_struct\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - class\n  inline:\n    b"
  },
  {
    "path": "docs/libraries/comments.cpp/some_struct/m_operator3D.md",
    "chars": 549,
    "preview": "---\nlayout: method\ntitle: operator=\nhyde:\n  owner: __INLINED__\n  brief: __OPTIONAL__\n  tags:\n    - method\n  inline:\n    "
  },
  {
    "path": "docs/libraries/comments.cpp/some_struct/m_some_function.md",
    "chars": 1646,
    "preview": "---\nlayout: method\ntitle: some_function\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - method\n  inline:\n "
  },
  {
    "path": "docs/libraries/comments.cpp/some_struct/m_some_struct.md",
    "chars": 516,
    "preview": "---\nlayout: method\ntitle: some_struct\nhyde:\n  owner: __INLINED__\n  brief: __OPTIONAL__\n  tags:\n    - method\n  inline:\n  "
  },
  {
    "path": "docs/libraries/comments.cpp/some_struct/m_virtual_function.md",
    "chars": 502,
    "preview": "---\nlayout: method\ntitle: virtual_function\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - method\n  inline"
  },
  {
    "path": "docs/libraries/comments.cpp/some_struct/m_~some_struct.md",
    "chars": 341,
    "preview": "---\nlayout: method\ntitle: ~some_struct\nhyde:\n  owner: __INLINED__\n  brief: __OPTIONAL__\n  tags:\n    - method\n  inline:\n "
  },
  {
    "path": "docs/libraries/enums.cpp/color_channel.md",
    "chars": 627,
    "preview": "---\nlayout: enumeration\ntitle: color_channel\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - enumeration\n "
  },
  {
    "path": "docs/libraries/enums.cpp/index.md",
    "chars": 141,
    "preview": "---\nlayout: library\ntitle: enums.cpp\nhyde:\n  owner: __MISSING__\n  brief: __MISSING__\n  tags:\n    - sourcefile\n  library-"
  },
  {
    "path": "docs/libraries/enums.cpp/untyped.md",
    "chars": 596,
    "preview": "---\nlayout: enumeration\ntitle: untyped\nhyde:\n  owner: __INLINED__\n  brief: __INLINED__\n  tags:\n    - enumeration\n  inlin"
  },
  {
    "path": "docs/libraries/functions.cpp/f_binary_function_example.md",
    "chars": 849,
    "preview": "---\nlayout: function\ntitle: binary_function_example\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - functi"
  },
  {
    "path": "docs/libraries/functions.cpp/f_nullary_function_example.md",
    "chars": 483,
    "preview": "---\nlayout: function\ntitle: nullary_function_example\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - funct"
  },
  {
    "path": "docs/libraries/functions.cpp/f_overloaded.md",
    "chars": 2114,
    "preview": "---\nlayout: function\ntitle: overloaded\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - function\n  inline:\n"
  },
  {
    "path": "docs/libraries/functions.cpp/f_static_auto_function_example.md",
    "chars": 553,
    "preview": "---\nlayout: function\ntitle: static_auto_function_example\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - f"
  },
  {
    "path": "docs/libraries/functions.cpp/f_static_function_example.md",
    "chars": 490,
    "preview": "---\nlayout: function\ntitle: static_function_example\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - functi"
  },
  {
    "path": "docs/libraries/functions.cpp/f_static_trailing_type_function_example.md",
    "chars": 600,
    "preview": "---\nlayout: function\ntitle: static_trailing_type_function_example\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags"
  },
  {
    "path": "docs/libraries/functions.cpp/f_template_function_example.md",
    "chars": 883,
    "preview": "---\nlayout: function\ntitle: template_function_example\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - func"
  },
  {
    "path": "docs/libraries/functions.cpp/index.md",
    "chars": 145,
    "preview": "---\nlayout: library\ntitle: functions.cpp\nhyde:\n  owner: __MISSING__\n  brief: __MISSING__\n  tags:\n    - sourcefile\n  libr"
  },
  {
    "path": "docs/libraries/index.md",
    "chars": 211,
    "preview": "---\nlayout: library\ntitle: Hyde Sample Docs\nhyde:\n  owner: fosterbrereton\n  brief: Sample Hyde Documentation\n  tags:\n   "
  },
  {
    "path": "docs/libraries/namespaces.cpp/f_function.md",
    "chars": 460,
    "preview": "---\nlayout: function\ntitle: function\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - function\n  inline:\n  "
  },
  {
    "path": "docs/libraries/namespaces.cpp/index.md",
    "chars": 146,
    "preview": "---\nlayout: library\ntitle: namespaces.cpp\nhyde:\n  owner: __MISSING__\n  brief: __MISSING__\n  tags:\n    - sourcefile\n  lib"
  },
  {
    "path": "docs/libraries/point.cpp/index.md",
    "chars": 141,
    "preview": "---\nlayout: library\ntitle: point.cpp\nhyde:\n  owner: __MISSING__\n  brief: __MISSING__\n  tags:\n    - sourcefile\n  library-"
  },
  {
    "path": "docs/libraries/point.cpp/point3CT3E/f_operator-.md",
    "chars": 937,
    "preview": "---\nlayout: function\ntitle: operator-\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - function\n  inline:\n "
  },
  {
    "path": "docs/libraries/point.cpp/point3CT3E/f_operator213D.md",
    "chars": 776,
    "preview": "---\nlayout: function\ntitle: operator!=\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - function\n  inline:\n"
  },
  {
    "path": "docs/libraries/point.cpp/point3CT3E/f_operator3D3D.md",
    "chars": 771,
    "preview": "---\nlayout: function\ntitle: operator==\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - function\n  inline:\n"
  },
  {
    "path": "docs/libraries/point.cpp/point3CT3E/index.md",
    "chars": 524,
    "preview": "---\nlayout: class\ntitle: point<T>\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - class\n  inline:\n    brie"
  },
  {
    "path": "docs/libraries/point.cpp/point3CT3E/m_operator-3D.md",
    "chars": 725,
    "preview": "---\nlayout: method\ntitle: operator-=\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - method\n  inline:\n    "
  },
  {
    "path": "docs/libraries/point.cpp/point3CT3E/m_origin.md",
    "chars": 508,
    "preview": "---\nlayout: method\ntitle: origin\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - method\n  inline:\n    brie"
  },
  {
    "path": "docs/libraries/point.cpp/point3CT3E/m_point3CT3E.md",
    "chars": 969,
    "preview": "---\nlayout: method\ntitle: point<T>\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - method\n  inline:\n    br"
  },
  {
    "path": "docs/libraries/typedef_and_alias.cpp/index.md",
    "chars": 1253,
    "preview": "---\nlayout: library\ntitle: typedef_and_alias.cpp\nhyde:\n  owner: __MISSING__\n  brief: __MISSING__\n  tags:\n    - sourcefil"
  },
  {
    "path": "docs/libraries/typedef_and_alias.cpp/template_example3CT2C20U3E/index.md",
    "chars": 682,
    "preview": "---\nlayout: class\ntitle: template_example<T, U>\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - class\n  in"
  },
  {
    "path": "docs/libraries/typedef_and_alias.cpp/template_example_instantiator/index.md",
    "chars": 791,
    "preview": "---\nlayout: class\ntitle: template_example_instantiator\nhyde:\n  owner: __MISSING__\n  brief: __INLINED__\n  tags:\n    - cla"
  },
  {
    "path": "docs/serve.sh",
    "chars": 46,
    "preview": "#!/bin/bash\n\nbundle exec jekyll serve --watch\n"
  },
  {
    "path": "emitters/yaml_base_emitter.cpp",
    "chars": 64752,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "emitters/yaml_base_emitter.hpp",
    "chars": 10021,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "emitters/yaml_base_emitter_fwd.hpp",
    "chars": 2716,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "emitters/yaml_class_emitter.cpp",
    "chars": 6273,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "emitters/yaml_class_emitter.hpp",
    "chars": 1535,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "emitters/yaml_enum_emitter.cpp",
    "chars": 3810,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "emitters/yaml_enum_emitter.hpp",
    "chars": 1530,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "emitters/yaml_function_emitter.cpp",
    "chars": 13145,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "emitters/yaml_function_emitter.hpp",
    "chars": 1753,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "emitters/yaml_library_emitter.cpp",
    "chars": 2115,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "emitters/yaml_library_emitter.hpp",
    "chars": 1566,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "emitters/yaml_sourcefile_emitter.cpp",
    "chars": 3397,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "emitters/yaml_sourcefile_emitter.hpp",
    "chars": 1793,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "generate_test_files.sh",
    "chars": 773,
    "preview": "#!/bin/bash\n\n#very simple for now, look in common locations\nfind_hyde() {\n    BUILD_DIR=$1\n    if [ -f $BUILD_DIR/hyde ]"
  },
  {
    "path": "include/_clang_include_prefix.hpp",
    "chars": 512,
    "preview": "#if __clang__\n    #pragma clang diagnostic push\n    #pragma clang diagnostic ignored \"-Wunknown-pragmas\"\n    #pragma cla"
  },
  {
    "path": "include/_clang_include_suffix.hpp",
    "chars": 142,
    "preview": "#if __clang__\n    #pragma clang diagnostic pop\n#elif __GNUC__ // must follow clang (which defines both)\n    #pragma GCC "
  },
  {
    "path": "include/autodetect.hpp",
    "chars": 1157,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "include/config.hpp",
    "chars": 1089,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "include/json.hpp",
    "chars": 559,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "include/json_fwd.hpp",
    "chars": 973,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "include/output_yaml.hpp",
    "chars": 1589,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/class_matcher.cpp",
    "chars": 9638,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/class_matcher.hpp",
    "chars": 1693,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/enum_matcher.cpp",
    "chars": 2197,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/enum_matcher.hpp",
    "chars": 1676,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/function_matcher.cpp",
    "chars": 2007,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/function_matcher.hpp",
    "chars": 1693,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/matcher_fwd.hpp",
    "chars": 1271,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/namespace_matcher.cpp",
    "chars": 1650,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/namespace_matcher.hpp",
    "chars": 1694,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/typealias_matcher.cpp",
    "chars": 1988,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/typealias_matcher.hpp",
    "chars": 1702,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/typedef_matcher.cpp",
    "chars": 1811,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/typedef_matcher.hpp",
    "chars": 1691,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/utilities.cpp",
    "chars": 40771,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "matchers/utilities.hpp",
    "chars": 5775,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "sources/autodetect.cpp",
    "chars": 6174,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "sources/main.cpp",
    "chars": 27381,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "sources/output_yaml.cpp",
    "chars": 3457,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "test_files/classes.cpp",
    "chars": 7424,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "test_files/comments.cpp",
    "chars": 2856,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "test_files/enums.cpp",
    "chars": 1352,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "test_files/functions.cpp",
    "chars": 2415,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "test_files/namespaces.cpp",
    "chars": 1574,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "test_files/point.cpp",
    "chars": 2492,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  },
  {
    "path": "test_files/typedef_and_alias.cpp",
    "chars": 2709,
    "preview": "/*\nCopyright 2018 Adobe\nAll Rights Reserved.\n\nNOTICE: Adobe permits you to use, modify, and distribute this file in\nacco"
  }
]

About this extraction

This page contains the full source code of the adobe/hyde GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 137 files (328.7 KB), approximately 75.8k tokens, and a symbol index with 207 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!