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
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
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.