diff --git a/cmake/common/targets/clang-format.config b/.clang-format similarity index 100% rename from cmake/common/targets/clang-format.config rename to .clang-format diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..faf7bcf01 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,20 @@ +--- +# See https://clang.llvm.org/extra/clang-tidy/index.html +# First disable all default checks (with -*) +Checks: '-*, + modernize-*' +# TODO(bavulapati): iterate through the rules and enable them incrementally inorder to send smaller PRs + # bugprone-*,-bugprone-branch-clone,-bugprone-easily-swappable-parameters,-bugprone-empty-catch, + # clang-analyzer-*, + # clang-diagnostic-*, + # modernize-*, + # concurrency-*, + # cppcoreguidelines-*,-cppcoreguidelines-rvalue-reference-param-not-moved, + # performance-*,-performance-enum-size, + # portability-*, + # objc-*, + # misc-*,-misc-no-recursion,-misc-unused-parameters,-misc-const-correctness' +WarningsAsErrors: '*' +FormatStyle: none +UseColor: true +SystemHeaders: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d8aa7586..95fab6b00 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -161,3 +161,24 @@ jobs: alert-threshold: '5%' comment-always: true fail-on-alert: false + + clang-tidy: + runs-on: ubuntu-latest + env: + CC: clang + CXX: clang++ + steps: + - uses: actions/checkout@v4 + - run: cmake --version + - name: Install llvm + run: sudo apt update && sudo apt install llvm + - run: > + cmake -S . -B ./build + -DCMAKE_BUILD_TYPE:STRING=Release + -DSOURCEMETA_CORE_TESTS:BOOL=OFF + -DSOURCEMETA_CORE_BENCHMARK:BOOL=OFF + -DSOURCEMETA_CORE_DOCS:BOOL=OFF + -DBUILD_SHARED_LIBS:BOOL=OFF + -DCMAKE_COMPILE_WARNING_AS_ERROR:BOOL=ON + -DSOURCEMETA_CORE_CLANG_TIDY:BOOL=ON + - run: cmake --build ./build --config Release diff --git a/CMakeLists.txt b/CMakeLists.txt index ce03c9756..4e91f8c34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ option(SOURCEMETA_CORE_CONTRIB_ZLIB "Build the ZLIB library for downstream consu option(SOURCEMETA_CORE_CONTRIB_BEARSSL "Build the BearSSL library for downstream consumers" OFF) option(SOURCEMETA_CORE_CONTRIB_GOOGLETEST "Build the GoogleTest library for downstream consumers" OFF) option(SOURCEMETA_CORE_CONTRIB_GOOGLEBENCHMARK "Build the GoogleBenchmark library for downstream consumers" OFF) +option(SOURCEMETA_CORE_CLANG_TIDY "Run clang-tidy checks" OFF) include(Sourcemeta) @@ -33,6 +34,10 @@ if(PROJECT_IS_TOP_LEVEL) sourcemeta_enable_simd() endif() +if(SOURCEMETA_CORE_CLANG_TIDY) + sourcemeta_set_clang_tidy_config(HEADER_FILTER "${PROJECT_SOURCE_DIR}/src/*") +endif() + # TODO: Turn this into a re-usable utility CMake function if(SOURCEMETA_CORE_INSTALL) include(GNUInstallDirs) @@ -120,7 +125,6 @@ if(PROJECT_IS_TOP_LEVEL) src/*.h src/*.cc benchmark/*.h benchmark/*.cc test/*.h test/*.cc) - sourcemeta_target_clang_tidy(SOURCES src/*.cc) endif() # Testing diff --git a/Makefile b/Makefile index d447bd57a..9c166e3fd 100644 --- a/Makefile +++ b/Makefile @@ -25,9 +25,6 @@ compile: .always $(CMAKE) --install ./build --prefix ./build/dist --config $(PRESET) --verbose \ --component sourcemeta_core_dev -lint: .always - $(CMAKE) --build ./build --config $(PRESET) --target clang_tidy - test: .always $(CMAKE) -E env UBSAN_OPTIONS=print_stacktrace=1 \ $(CTEST) --test-dir ./build --build-config $(PRESET) \ diff --git a/cmake/common/targets/clang-format.cmake b/cmake/common/targets/clang-format.cmake index 55fbb6cdc..5aee2edea 100644 --- a/cmake/common/targets/clang-format.cmake +++ b/cmake/common/targets/clang-format.cmake @@ -101,7 +101,7 @@ function(sourcemeta_target_clang_format) file(GLOB_RECURSE SOURCEMETA_TARGET_CLANG_FORMAT_FILES ${SOURCEMETA_TARGET_CLANG_FORMAT_SOURCES}) - set(CLANG_FORMAT_CONFIG "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/clang-format.config") + set(CLANG_FORMAT_CONFIG "${PROJECT_SOURCE_DIR}/.clang-format") if(CMAKE_SYSTEM_NAME STREQUAL "MSYS") # Because `clang-format` is typically a Windows `.exe`, transform the path accordingly execute_process(COMMAND cygpath -w "${CLANG_FORMAT_CONFIG}" diff --git a/cmake/common/targets/clang-tidy.cmake b/cmake/common/targets/clang-tidy.cmake index 47954d1d0..958c4e139 100644 --- a/cmake/common/targets/clang-tidy.cmake +++ b/cmake/common/targets/clang-tidy.cmake @@ -1,130 +1,18 @@ -function(sourcemeta_target_clang_tidy_attempt_install) - cmake_parse_arguments(SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL "" "OUTPUT_DIRECTORY" "" ${ARGN}) - if(NOT SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY) - message(FATAL_ERROR "You must pass the output directory in the OUTPUT_DIRECTORY option") - endif() - - # See https://pypi.org/project/clang-tidy/ - set(CLANG_TIDY_BINARY_VERSION "20.1.0") - set(CLANG_TIDY_BINARY_Windows_AMD64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-win_amd64.whl") - set(CLANG_TIDY_BINARY_MSYS_x86_64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-win_amd64.whl") - set(CLANG_TIDY_BINARY_Darwin_arm64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-macosx_11_0_arm64.whl") - set(CLANG_TIDY_BINARY_Darwin_x86_64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-macosx_10_9_x86_64.whl") - set(CLANG_TIDY_BINARY_Linux_aarch64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl") - set(CLANG_TIDY_BINARY_Linux_x86_64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl") - set(CLANG_TIDY_BINARY_CHECKSUM_Windows_AMD64 "02/f0/dd985d9d9b76f8c39f1995aa475d8d5aabbea0d3e0cf498df44dc7bf1cb0") - set(CLANG_TIDY_BINARY_CHECKSUM_MSYS_x86_64 "02/f0/dd985d9d9b76f8c39f1995aa475d8d5aabbea0d3e0cf498df44dc7bf1cb0") - set(CLANG_TIDY_BINARY_CHECKSUM_Darwin_arm64 "95/02/838baf08764b08327322096bda55e8d1e2344e4a13b9308e5642cfaafd8e") - set(CLANG_TIDY_BINARY_CHECKSUM_Darwin_x86_64 "6d/5b/dcfc84b895d8544e00186738ca85132bbd14db4d11dbe39502630ece5391") - set(CLANG_TIDY_BINARY_CHECKSUM_Linux_aarch64 "be/61/9e1a0797639e81c41d38d7b8b2508a9be4b05b9a23baa9d64e7284d07238") - set(CLANG_TIDY_BINARY_CHECKSUM_Linux_x86_64 "52/76/42c61be1c1fdf8bacdbb265f0cd3e11321fee7362f91fa840717a6a41ad6") - set(CLANG_TIDY_BINARY_NAME_Windows_AMD64 "clang-tidy.exe") - set(CLANG_TIDY_BINARY_NAME_MSYS_x86_64 "clang-tidy.exe") - set(CLANG_TIDY_BINARY_NAME_Darwin_arm64 "clang-tidy") - set(CLANG_TIDY_BINARY_NAME_Darwin_x86_64 "clang-tidy") - set(CLANG_TIDY_BINARY_NAME_Linux_aarch64 "clang-tidy") - set(CLANG_TIDY_BINARY_NAME_Linux_x86_64 "clang-tidy") - - # Determine the pre-built binary URL - string(REPLACE "." "_" CLANG_TIDY_BINARY_SYSTEM "${CMAKE_SYSTEM_NAME}") - string(REPLACE "." "_" CLANG_TIDY_BINARY_ARCH "${CMAKE_SYSTEM_PROCESSOR}") - set(CLANG_TIDY_BINARY_URL_VAR "CLANG_TIDY_BINARY_${CLANG_TIDY_BINARY_SYSTEM}_${CLANG_TIDY_BINARY_ARCH}") - set(CLANG_TIDY_BINARY_CHECKSUM_VAR "CLANG_TIDY_BINARY_CHECKSUM_${CLANG_TIDY_BINARY_SYSTEM}_${CLANG_TIDY_BINARY_ARCH}") - set(CLANG_TIDY_BINARY_NAME_VAR "CLANG_TIDY_BINARY_NAME_${CLANG_TIDY_BINARY_SYSTEM}_${CLANG_TIDY_BINARY_ARCH}") - if(NOT DEFINED ${CLANG_TIDY_BINARY_URL_VAR} OR "${${CLANG_TIDY_BINARY_URL_VAR}}" STREQUAL "") - message(WARNING "Skipping `clang-tidy` download. No known pre-build binary URL") - return() - elseif(NOT DEFINED ${CLANG_TIDY_BINARY_CHECKSUM_VAR} OR "${${CLANG_TIDY_BINARY_CHECKSUM_VAR}}" STREQUAL "") - message(FATAL_ERROR "No known `clang-tidy` pre-build binary checksum") - elseif(NOT DEFINED ${CLANG_TIDY_BINARY_NAME_VAR} OR "${${CLANG_TIDY_BINARY_NAME_VAR}}" STREQUAL "") - message(FATAL_ERROR "No known `clang-tidy` pre-build binary name") - endif() - set(CLANG_TIDY_BINARY_URL "https://files.pythonhosted.org/packages/${${CLANG_TIDY_BINARY_CHECKSUM_VAR}}/${${CLANG_TIDY_BINARY_URL_VAR}}") - - # Download and extract the pre-built binary ZIP if needed - set(CLANG_TIDY_BINARY_NAME "${${CLANG_TIDY_BINARY_NAME_VAR}}") - set(CLANG_TIDY_BINARY_OUTPUT "${SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY}/${CLANG_TIDY_BINARY_NAME}") - if(EXISTS "${CLANG_TIDY_BINARY_OUTPUT}") - message(STATUS "Found existing `clang-tidy` pre-built binary at ${CLANG_TIDY_BINARY_OUTPUT}") - return() - endif() - set(CLANG_TIDY_BINARY_DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/clang-tidy") - file(REMOVE_RECURSE "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}") - file(MAKE_DIRECTORY "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}") - set(CLANG_TIDY_BINARY_WHEEL "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}/clang-tidy.whl") - message(STATUS "Downloading `clang-tidy` pre-built binary from ${CLANG_TIDY_BINARY_URL}") - file(DOWNLOAD "${CLANG_TIDY_BINARY_URL}" "${CLANG_TIDY_BINARY_WHEEL}" - STATUS CLANG_TIDY_BINARY_DOWNLOAD_STATUS SHOW_PROGRESS TLS_VERIFY ON - LOG CLANG_TIDY_BINARY_DOWNLOAD_LOG) - list(GET CLANG_TIDY_BINARY_DOWNLOAD_STATUS 0 _code) - if(NOT _code EQUAL 0) - message(WARNING "Failed to download the `clang-tidy` pre-built binary") - message(WARNING "${CLANG_TIDY_BINARY_DOWNLOAD_LOG}") - file(REMOVE_RECURSE "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}") - return() - endif() - set(CLANG_TIDY_BINARY_EXTRACT_DIR "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}/extracted") - file(MAKE_DIRECTORY "${CLANG_TIDY_BINARY_EXTRACT_DIR}") - file(ARCHIVE_EXTRACT INPUT "${CLANG_TIDY_BINARY_WHEEL}" DESTINATION "${CLANG_TIDY_BINARY_EXTRACT_DIR}") - - # Install the binary - file(MAKE_DIRECTORY "${SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY}") - file(COPY "${CLANG_TIDY_BINARY_EXTRACT_DIR}/clang_tidy/data/bin/${CLANG_TIDY_BINARY_NAME}" - DESTINATION "${SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY}") - file(CHMOD "${CLANG_TIDY_BINARY_OUTPUT}" PERMISSIONS - OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) - message(STATUS "Installed `clang-tidy` pre-built binary to ${CLANG_TIDY_BINARY_OUTPUT}") -endfunction() - -function(sourcemeta_target_clang_tidy) - cmake_parse_arguments(SOURCEMETA_TARGET_CLANG_TIDY "REQUIRED" "" "SOURCES" ${ARGN}) - sourcemeta_target_clang_tidy_attempt_install(OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") - - if(SOURCEMETA_TARGET_CLANG_TIDY_REQUIRED) - find_program(CLANG_TIDY_BIN NAMES clang-tidy NO_DEFAULT_PATH - PATHS "${CMAKE_CURRENT_BINARY_DIR}/bin") - if(NOT CLANG_TIDY_BIN) - find_program(CLANG_TIDY_BIN NAMES clang-tidy REQUIRED) - endif() +function(sourcemeta_find_clang_tidy) + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + find_program(CLANG_TIDY_BIN NAMES clang-tidy REQUIRED) else() - find_program(CLANG_TIDY_BIN NAMES clang-tidy NO_DEFAULT_PATH - PATHS "${CMAKE_CURRENT_BINARY_DIR}/bin") - if(NOT CLANG_TIDY_BIN) - find_program(CLANG_TIDY_BIN NAMES clang-tidy) - endif() - endif() - - - # This covers the empty list too - if(NOT SOURCEMETA_TARGET_CLANG_TIDY_SOURCES) - message(FATAL_ERROR "You must pass file globs to analyze in the SOURCES option") + message(FATAL_ERROR "Incompatible compiler toolchain. Clang-tidy is only tested to be working with clang toolchain") endif() - file(GLOB_RECURSE SOURCEMETA_TARGET_CLANG_TIDY_FILES - ${SOURCEMETA_TARGET_CLANG_TIDY_SOURCES}) - set(CLANG_TIDY_CONFIG "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/clang-tidy.config") - - if(CMAKE_SYSTEM_NAME STREQUAL "MSYS") - # Because `clang-tidy` is typically a Windows `.exe`, transform the path accordingly - execute_process(COMMAND cygpath -w "${CLANG_TIDY_CONFIG}" - OUTPUT_VARIABLE CLANG_TIDY_CONFIG OUTPUT_STRIP_TRAILING_WHITESPACE) - endif() +endfunction() - if(CLANG_TIDY_BIN) - add_custom_target(clang_tidy - WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" - VERBATIM - COMMAND "${CLANG_TIDY_BIN}" -p "${PROJECT_BINARY_DIR}" - --config-file "${CLANG_TIDY_CONFIG}" - ${SOURCEMETA_TARGET_CLANG_TIDY_FILES} - COMMENT "Analyzing sources using ClangTidy") - else() - add_custom_target(clang_tidy - WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" - VERBATIM - COMMAND "${CMAKE_COMMAND}" -E echo "Could not locate ClangTidy" - COMMAND "${CMAKE_COMMAND}" -E false) +function(sourcemeta_set_clang_tidy_config) + cmake_parse_arguments(SOURCEMETA_SET_CLANG_TIDY_CONFIG "" "HEADER_FILTER" "" ${ARGN}) + if(NOT SOURCEMETA_SET_CLANG_TIDY_CONFIG_HEADER_FILTER) + message(FATAL_ERROR "HEADER_FILTER is required for clang-tidy.") endif() - set_target_properties(clang_tidy PROPERTIES FOLDER "Linting") + sourcemeta_find_clang_tidy() + set(SOURCEMETA_CXX_CLANG_TIDY "${CLANG_TIDY_BIN};--config-file=${PROJECT_SOURCE_DIR}/.clang-tidy;-header-filter=${SOURCEMETA_SET_CLANG_TIDY_CONFIG_HEADER_FILTER}" PARENT_SCOPE) endfunction() diff --git a/cmake/common/targets/clang-tidy.config b/cmake/common/targets/clang-tidy.config deleted file mode 100644 index a7de0a47b..000000000 --- a/cmake/common/targets/clang-tidy.config +++ /dev/null @@ -1,22 +0,0 @@ ---- -# See https://clang.llvm.org/extra/clang-tidy/index.html -# First disable all default checks (with -*) -Checks: '-*, - bugprone-*,-bugprone-branch-clone,-bugprone-easily-swappable-parameters,-bugprone-empty-catch, - clang-analyzer-*, - clang-diagnostic-*, - modernize-*, - concurrency-*, - cppcoreguidelines-*,-cppcoreguidelines-rvalue-reference-param-not-moved, - performance-*,-performance-enum-size, - portability-*, - objc-*, - misc-*,-misc-no-recursion,-misc-unused-parameters,-misc-const-correctness' -WarningsAsErrors: '*' -HeaderFilterRegex: '' -FormatStyle: none -CheckOptions: - # See https://clang.llvm.org/extra/clang-tidy/checks/misc/include-cleaner.html - # Otherwise ClangTidy wants us to directly include private headers from our modules - - key: misc-include-cleaner.IgnoreHeaders - value: 'src\/core\/.*;uriparser\/.*' diff --git a/cmake/common/targets/library.cmake b/cmake/common/targets/library.cmake index e2f2ebe60..e5b0957d1 100644 --- a/cmake/common/targets/library.cmake +++ b/cmake/common/targets/library.cmake @@ -1,6 +1,6 @@ function(sourcemeta_library) cmake_parse_arguments(SOURCEMETA_LIBRARY "" - "NAMESPACE;PROJECT;NAME;VARIANT" "PRIVATE_HEADERS;SOURCES" ${ARGN}) + "NAMESPACE;PROJECT;NAME;VARIANT" "PRIVATE_HEADERS;SOURCES;CLANG_TIDY" ${ARGN}) if(NOT SOURCEMETA_LIBRARY_PROJECT) message(FATAL_ERROR "You must pass the project name using the PROJECT option") @@ -115,6 +115,13 @@ function(sourcemeta_library) target_include_directories(${TARGET_NAME} PUBLIC "$") endif() + + if(SOURCEMETA_LIBRARY_CLANG_TIDY) + message(STATUS "setting CXX_CLANG_TIDY target property to ${SOURCEMETA_LIBRARY_CLANG_TIDY} on ${TARGET_NAME}") + set_target_properties(${TARGET_NAME} + PROPERTIES + CXX_CLANG_TIDY "${SOURCEMETA_LIBRARY_CLANG_TIDY}") + endif() endfunction() function(sourcemeta_library_install) diff --git a/src/core/json/include/sourcemeta/core/json_array.h b/src/core/json/include/sourcemeta/core/json_array.h index 5772abac5..d43fdc459 100644 --- a/src/core/json/include/sourcemeta/core/json_array.h +++ b/src/core/json/include/sourcemeta/core/json_array.h @@ -56,31 +56,39 @@ template class JSONArray { /// Get a mutable end iterator on the array auto end() noexcept -> iterator { return this->data.end(); } /// Get a constant begin iterator on the array - auto begin() const noexcept -> const_iterator { return this->data.begin(); } + [[nodiscard]] auto begin() const noexcept -> const_iterator { + return this->data.begin(); + } /// Get a constant end iterator on the array - auto end() const noexcept -> const_iterator { return this->data.end(); } + [[nodiscard]] auto end() const noexcept -> const_iterator { + return this->data.end(); + } /// Get a constant begin iterator on the array - auto cbegin() const noexcept -> const_iterator { return this->data.cbegin(); } + [[nodiscard]] auto cbegin() const noexcept -> const_iterator { + return this->data.cbegin(); + } /// Get a constant end iterator on the array - auto cend() const noexcept -> const_iterator { return this->data.cend(); } + [[nodiscard]] auto cend() const noexcept -> const_iterator { + return this->data.cend(); + } /// Get a mutable reverse begin iterator on the array auto rbegin() noexcept -> reverse_iterator { return this->data.rbegin(); } /// Get a mutable reverse end iterator on the array auto rend() noexcept -> reverse_iterator { return this->data.rend(); } /// Get a constant reverse begin iterator on the array - auto rbegin() const noexcept -> const_reverse_iterator { + [[nodiscard]] auto rbegin() const noexcept -> const_reverse_iterator { return this->data.rbegin(); } /// Get a constant reverse end iterator on the array - auto rend() const noexcept -> const_reverse_iterator { + [[nodiscard]] auto rend() const noexcept -> const_reverse_iterator { return this->data.rend(); } /// Get a constant reverse begin iterator on the array - auto crbegin() const noexcept -> const_reverse_iterator { + [[nodiscard]] auto crbegin() const noexcept -> const_reverse_iterator { return this->data.crbegin(); } /// Get a constant reverse end iterator on the array - auto crend() const noexcept -> const_reverse_iterator { + [[nodiscard]] auto crend() const noexcept -> const_reverse_iterator { return this->data.crend(); } diff --git a/src/core/json/include/sourcemeta/core/json_hash.h b/src/core/json/include/sourcemeta/core/json_hash.h index 14bfe9b35..e4da63e38 100644 --- a/src/core/json/include/sourcemeta/core/json_hash.h +++ b/src/core/json/include/sourcemeta/core/json_hash.h @@ -14,7 +14,7 @@ template struct HashJSON { return value.fast_hash(); } - inline auto is_perfect(const hash_type) const noexcept -> bool { + [[nodiscard]] inline auto is_perfect(const hash_type) const noexcept -> bool { return false; } }; @@ -45,7 +45,8 @@ template struct PropertyHashJSON { } }; - inline auto perfect(const T &value, const std::size_t size) const noexcept + [[nodiscard]] inline auto perfect(const T &value, + const std::size_t size) const noexcept -> hash_type { hash_type result; assert(!value.empty()); @@ -134,7 +135,8 @@ template struct PropertyHashJSON { } } - inline auto is_perfect(const hash_type &hash) const noexcept -> bool { + [[nodiscard]] inline auto is_perfect(const hash_type &hash) const noexcept + -> bool { // If there is anything written past the first byte, // then it is a perfect hash return hash.a > 255; diff --git a/src/core/json/include/sourcemeta/core/json_object.h b/src/core/json/include/sourcemeta/core/json_object.h index c14d6ba9c..0b8f39e0f 100644 --- a/src/core/json/include/sourcemeta/core/json_object.h +++ b/src/core/json/include/sourcemeta/core/json_object.h @@ -46,12 +46,21 @@ template class FlatMap { } } - auto begin() const noexcept -> const_iterator { return this->data.begin(); } - auto end() const noexcept -> const_iterator { return this->data.end(); } - auto cbegin() const noexcept -> const_iterator { return this->data.cbegin(); } - auto cend() const noexcept -> const_iterator { return this->data.cend(); } + [[nodiscard]] auto begin() const noexcept -> const_iterator { + return this->data.begin(); + } + [[nodiscard]] auto end() const noexcept -> const_iterator { + return this->data.end(); + } + [[nodiscard]] auto cbegin() const noexcept -> const_iterator { + return this->data.cbegin(); + } + [[nodiscard]] auto cend() const noexcept -> const_iterator { + return this->data.cend(); + } - inline auto hash(const key_type &key) const noexcept -> hash_type { + [[nodiscard]] inline auto hash(const key_type &key) const noexcept + -> hash_type { return this->hasher(key); } @@ -102,7 +111,8 @@ template class FlatMap { } // As a performance optimisation if the hash is known - inline auto find(const key_type &key, const hash_type key_hash) const + [[nodiscard]] inline auto find(const key_type &key, + const hash_type key_hash) const -> const_iterator { assert(this->hash(key) == key_hash); @@ -129,7 +139,8 @@ template class FlatMap { return this->cend(); } - inline auto try_at(const key_type &key, const hash_type key_hash) const + [[nodiscard]] inline auto try_at(const key_type &key, + const hash_type key_hash) const -> const mapped_type * { assert(this->hash(key) == key_hash); @@ -153,7 +164,8 @@ template class FlatMap { } // As a performance optimisation if the hash is known - auto contains(const key_type &key, const hash_type key_hash) const -> bool { + [[nodiscard]] auto contains(const key_type &key, + const hash_type key_hash) const -> bool { assert(this->hash(key) == key_hash); // Move the perfect hash condition out of the loop for extra performance @@ -176,7 +188,8 @@ template class FlatMap { // As a performance optimisation if the hash is known - inline auto at(const key_type &key, const hash_type key_hash) const + [[nodiscard]] inline auto at(const key_type &key, + const hash_type key_hash) const -> const mapped_type & { assert(this->hash(key) == key_hash); @@ -230,7 +243,8 @@ template class FlatMap { #endif } - inline auto at(const size_type index) const noexcept -> const Entry & { + [[nodiscard]] inline auto at(const size_type index) const noexcept + -> const Entry & { return this->data[index]; } @@ -285,9 +299,13 @@ template class FlatMap { return this->erase(key, this->hash(key)); } - inline auto size() const noexcept -> size_type { return this->data.size(); } + [[nodiscard]] inline auto size() const noexcept -> size_type { + return this->data.size(); + } - inline auto empty() const noexcept -> bool { return this->data.empty(); } + [[nodiscard]] inline auto empty() const noexcept -> bool { + return this->data.empty(); + } inline auto clear() noexcept -> void { this->data.clear(); } @@ -386,44 +404,48 @@ template class JSONObject { using const_pointer = typename Container::const_pointer; using const_iterator = typename Container::const_iterator; - inline auto begin() const noexcept -> const_iterator { + [[nodiscard]] inline auto begin() const noexcept -> const_iterator { return this->data.begin(); } /// Get a constant end iterator on the object - inline auto end() const noexcept -> const_iterator { + [[nodiscard]] inline auto end() const noexcept -> const_iterator { return this->data.end(); } /// Get a constant begin iterator on the object - inline auto cbegin() const noexcept -> const_iterator { + [[nodiscard]] inline auto cbegin() const noexcept -> const_iterator { return this->data.cbegin(); } /// Get a constant end iterator on the object - inline auto cend() const noexcept -> const_iterator { + [[nodiscard]] inline auto cend() const noexcept -> const_iterator { return this->data.cend(); } /// Attempt to find an entry by key - inline auto find(const Key &key) const -> const_iterator { + [[nodiscard]] inline auto find(const Key &key) const -> const_iterator { return this->data.find(key, this->data.hash(key)); } /// Check if an entry with the given key exists - inline auto defines(const Key &key, - const typename Container::hash_type hash) const -> bool { + [[nodiscard]] inline auto + defines(const Key &key, const typename Container::hash_type hash) const + -> bool { return this->data.contains(key, hash); } /// Check the size of the object - inline auto size() const -> std::size_t { return this->data.size(); } + [[nodiscard]] inline auto size() const -> std::size_t { + return this->data.size(); + } /// Access an object entry by its underlying positional index - inline auto at(const size_type index) const noexcept -> const + [[nodiscard]] inline auto at(const size_type index) const noexcept -> const typename Container::Entry & { return this->data.at(index); } // Hash an object property - inline auto hash(const Key &property) const -> typename Container::hash_type { + [[nodiscard]] inline auto hash(const Key &property) const -> + typename Container::hash_type { return this->data.hasher(property); } diff --git a/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_pointer.h b/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_pointer.h index 6c89f85fc..23dc47073 100644 --- a/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_pointer.h +++ b/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_pointer.h @@ -68,31 +68,39 @@ template class GenericPointer { /// Get a mutable end iterator on the pointer auto end() noexcept -> iterator { return this->data.end(); } /// Get a constant begin iterator on the pointer - auto begin() const noexcept -> const_iterator { return this->data.begin(); } + [[nodiscard]] auto begin() const noexcept -> const_iterator { + return this->data.begin(); + } /// Get a constant end iterator on the pointer - auto end() const noexcept -> const_iterator { return this->data.end(); } + [[nodiscard]] auto end() const noexcept -> const_iterator { + return this->data.end(); + } /// Get a constant begin iterator on the pointer - auto cbegin() const noexcept -> const_iterator { return this->data.cbegin(); } + [[nodiscard]] auto cbegin() const noexcept -> const_iterator { + return this->data.cbegin(); + } /// Get a constant end iterator on the pointer - auto cend() const noexcept -> const_iterator { return this->data.cend(); } + [[nodiscard]] auto cend() const noexcept -> const_iterator { + return this->data.cend(); + } /// Get a mutable reverse begin iterator on the pointer auto rbegin() noexcept -> reverse_iterator { return this->data.rbegin(); } /// Get a mutable reverse end iterator on the pointer auto rend() noexcept -> reverse_iterator { return this->data.rend(); } /// Get a constant reverse begin iterator on the pointer - auto rbegin() const noexcept -> const_reverse_iterator { + [[nodiscard]] auto rbegin() const noexcept -> const_reverse_iterator { return this->data.rbegin(); } /// Get a constant reverse end iterator on the pointer - auto rend() const noexcept -> const_reverse_iterator { + [[nodiscard]] auto rend() const noexcept -> const_reverse_iterator { return this->data.rend(); } /// Get a constant reverse begin iterator on the pointer - auto crbegin() const noexcept -> const_reverse_iterator { + [[nodiscard]] auto crbegin() const noexcept -> const_reverse_iterator { return this->data.crbegin(); } /// Get a constant reverse end iterator on the pointer - auto crend() const noexcept -> const_reverse_iterator { + [[nodiscard]] auto crend() const noexcept -> const_reverse_iterator { return this->data.crend(); } @@ -437,7 +445,7 @@ template class GenericPointer { /// assert(left.concat(right) == /// sourcemeta::core::Pointer{"foo", "bar", "baz"}); /// ``` - auto concat(const GenericPointer &other) const + [[nodiscard]] auto concat(const GenericPointer &other) const -> GenericPointer { GenericPointer result{*this}; result.push_back(other); @@ -455,7 +463,8 @@ template class GenericPointer { /// const sourcemeta::core::Pointer prefix{"foo", "bar"}; /// assert(pointer.starts_with(prefix)); /// ``` - auto starts_with(const GenericPointer &other) const -> bool { + [[nodiscard]] auto + starts_with(const GenericPointer &other) const -> bool { return other.data.size() <= this->data.size() && std::equal(other.data.cbegin(), other.data.cend(), this->data.cbegin()); @@ -473,8 +482,8 @@ template class GenericPointer { /// const sourcemeta::core::Pointer prefix{"foo", "bar", "baz"}; /// assert(pointer.starts_with(prefix, tail)); /// ``` - auto starts_with(const GenericPointer &other, - const Token &tail) const -> bool { + [[nodiscard]] auto starts_with(const GenericPointer &other, + const Token &tail) const -> bool { if (other.size() == this->size() + 1) { assert(!other.empty()); return other.starts_with(*this) && other.back() == tail; @@ -494,7 +503,8 @@ template class GenericPointer { /// const sourcemeta::core::Pointer prefix{"foo", "bar", "qux"}; /// assert(pointer.starts_with_initial(prefix)); /// ``` - auto starts_with_initial(const GenericPointer &other) const + [[nodiscard]] auto + starts_with_initial(const GenericPointer &other) const -> bool { const auto prefix_size{other.size()}; if (prefix_size == 0) { @@ -525,8 +535,9 @@ template class GenericPointer { /// assert(pointer.rebase(prefix, replacement) == /// sourcemeta::core::Pointer{"qux", "baz"}); /// ``` - auto rebase(const GenericPointer &prefix, - const GenericPointer &replacement) const + [[nodiscard]] auto + rebase(const GenericPointer &prefix, + const GenericPointer &replacement) const -> GenericPointer { typename Container::size_type index{0}; while (index < prefix.size()) { @@ -560,7 +571,8 @@ template class GenericPointer { /// /// If the JSON Pointer is not relative to the base, a copy of the original /// input pointer is returned. - auto resolve_from(const GenericPointer &base) const + [[nodiscard]] auto + resolve_from(const GenericPointer &base) const -> GenericPointer { typename Container::size_type index{0}; while (index < base.size()) { diff --git a/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_position.h b/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_position.h index 6da8ea21e..2e36acbd5 100644 --- a/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_position.h +++ b/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_position.h @@ -51,8 +51,9 @@ class SOURCEMETA_CORE_JSONPOINTER_EXPORT PointerPositionTracker { auto operator()(const JSON::ParsePhase phase, const JSON::Type, const std::uint64_t line, const std::uint64_t column, const JSON &value) -> void; - auto get(const Pointer &pointer) const -> std::optional; - auto size() const -> std::size_t; + [[nodiscard]] auto get(const Pointer &pointer) const + -> std::optional; + [[nodiscard]] auto size() const -> std::size_t; private: // Exporting symbols that depends on the standard C++ library is considered diff --git a/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_template.h b/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_template.h index c79fb91f9..0a6eb600f 100644 --- a/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_template.h +++ b/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_template.h @@ -85,31 +85,39 @@ template class GenericPointerTemplate { /// Get a mutable end iterator on the pointer auto end() noexcept -> iterator { return this->data.end(); } /// Get a constant begin iterator on the pointer - auto begin() const noexcept -> const_iterator { return this->data.begin(); } + [[nodiscard]] auto begin() const noexcept -> const_iterator { + return this->data.begin(); + } /// Get a constant end iterator on the pointer - auto end() const noexcept -> const_iterator { return this->data.end(); } + [[nodiscard]] auto end() const noexcept -> const_iterator { + return this->data.end(); + } /// Get a constant begin iterator on the pointer - auto cbegin() const noexcept -> const_iterator { return this->data.cbegin(); } + [[nodiscard]] auto cbegin() const noexcept -> const_iterator { + return this->data.cbegin(); + } /// Get a constant end iterator on the pointer - auto cend() const noexcept -> const_iterator { return this->data.cend(); } + [[nodiscard]] auto cend() const noexcept -> const_iterator { + return this->data.cend(); + } /// Get a mutable reverse begin iterator on the pointer auto rbegin() noexcept -> reverse_iterator { return this->data.rbegin(); } /// Get a mutable reverse end iterator on the pointer auto rend() noexcept -> reverse_iterator { return this->data.rend(); } /// Get a constant reverse begin iterator on the pointer - auto rbegin() const noexcept -> const_reverse_iterator { + [[nodiscard]] auto rbegin() const noexcept -> const_reverse_iterator { return this->data.rbegin(); } /// Get a constant reverse end iterator on the pointer - auto rend() const noexcept -> const_reverse_iterator { + [[nodiscard]] auto rend() const noexcept -> const_reverse_iterator { return this->data.rend(); } /// Get a constant reverse begin iterator on the pointer - auto crbegin() const noexcept -> const_reverse_iterator { + [[nodiscard]] auto crbegin() const noexcept -> const_reverse_iterator { return this->data.crbegin(); } /// Get a constant reverse end iterator on the pointer - auto crend() const noexcept -> const_reverse_iterator { + [[nodiscard]] auto crend() const noexcept -> const_reverse_iterator { return this->data.crend(); } @@ -172,7 +180,8 @@ template class GenericPointerTemplate { /// /// assert(left.concat(right) == expected); /// ``` - auto concat(const GenericPointerTemplate &&other) const + [[nodiscard]] auto + concat(const GenericPointerTemplate &&other) const -> GenericPointerTemplate { GenericPointerTemplate result{*this}; result.data.reserve(result.data.size() + other.data.size()); diff --git a/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_walker.h b/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_walker.h index cece2d5ec..9441f564b 100644 --- a/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_walker.h +++ b/src/core/jsonpointer/include/sourcemeta/core/jsonpointer_walker.h @@ -19,10 +19,18 @@ template class GenericPointerWalker { GenericPointerWalker(const JSON &document) { this->walk(document, {}); } using const_iterator = typename internal::const_iterator; - auto begin() const -> const_iterator { return this->pointers.begin(); }; - auto end() const -> const_iterator { return this->pointers.end(); }; - auto cbegin() const -> const_iterator { return this->pointers.cbegin(); }; - auto cend() const -> const_iterator { return this->pointers.cend(); }; + [[nodiscard]] auto begin() const -> const_iterator { + return this->pointers.begin(); + }; + [[nodiscard]] auto end() const -> const_iterator { + return this->pointers.end(); + }; + [[nodiscard]] auto cbegin() const -> const_iterator { + return this->pointers.cbegin(); + }; + [[nodiscard]] auto cend() const -> const_iterator { + return this->pointers.cend(); + }; private: auto walk(const JSON &document, const PointerT &pointer) -> void { diff --git a/src/core/jsonschema/include/sourcemeta/core/jsonschema_frame.h b/src/core/jsonschema/include/sourcemeta/core/jsonschema_frame.h index 5c772f539..38dac4d69 100644 --- a/src/core/jsonschema/include/sourcemeta/core/jsonschema_frame.h +++ b/src/core/jsonschema/include/sourcemeta/core/jsonschema_frame.h @@ -110,7 +110,7 @@ class SOURCEMETA_CORE_JSONSCHEMA_EXPORT SchemaFrame { SchemaFrame(const Mode mode) : mode_{mode} {} // Query the current mode that the schema frame was configured with - auto mode() const noexcept -> Mode { return this->mode_; } + [[nodiscard]] auto mode() const noexcept -> Mode { return this->mode_; } /// A single entry in a JSON Schema reference map struct ReferencesEntry { @@ -182,7 +182,7 @@ class SOURCEMETA_CORE_JSONSCHEMA_EXPORT SchemaFrame { using Paths = std::set; /// Export the frame entries as JSON - auto to_json() const -> JSON; + [[nodiscard]] auto to_json() const -> JSON; /// Analyse a schema or set of schemas from a given root. Passing /// multiple paths that have any overlap is undefined behaviour @@ -194,45 +194,47 @@ class SOURCEMETA_CORE_JSONSCHEMA_EXPORT SchemaFrame { const Paths &paths = {empty_pointer}) -> void; /// Access the analysed schema locations - auto locations() const noexcept -> const Locations &; + [[nodiscard]] auto locations() const noexcept -> const Locations &; /// Access the analysed schema references - auto references() const noexcept -> const References &; + [[nodiscard]] auto references() const noexcept -> const References &; /// Check whether the analysed schema has no external references - auto standalone() const -> bool; + [[nodiscard]] auto standalone() const -> bool; /// Get the vocabularies associated with a location entry - auto vocabularies(const Location &location, - const SchemaResolver &resolver) const -> Vocabularies; + [[nodiscard]] auto vocabularies(const Location &location, + const SchemaResolver &resolver) const + -> Vocabularies; /// Get the URI associated with a location entry - auto uri(const Location &location, - const Pointer &relative_schema_location = empty_pointer) const + [[nodiscard]] auto + uri(const Location &location, + const Pointer &relative_schema_location = empty_pointer) const -> JSON::String; /// Get the location associated by traversing a pointer from another location - auto traverse(const Location &location, - const Pointer &relative_schema_location) const + [[nodiscard]] auto traverse(const Location &location, + const Pointer &relative_schema_location) const -> const Location &; /// Get the location associated with a given URI - auto traverse(const JSON::String &uri) const + [[nodiscard]] auto traverse(const JSON::String &uri) const -> std::optional>; /// Try to dereference a reference location into its destination location - auto + [[nodiscard]] auto dereference(const Location &location, const Pointer &relative_schema_location = empty_pointer) const -> std::pair>>; /// Get the unresolved instance locations associated with a location entry - auto instance_locations(const Location &location) const -> const + [[nodiscard]] auto instance_locations(const Location &location) const -> const typename Instances::mapped_type &; /// Find all references to a given location pointer - auto references_to(const Pointer &pointer) const -> std::vector< + [[nodiscard]] auto references_to(const Pointer &pointer) const -> std::vector< std::reference_wrapper>; private: diff --git a/src/core/jsonschema/include/sourcemeta/core/jsonschema_transform.h b/src/core/jsonschema/include/sourcemeta/core/jsonschema_transform.h index 84f738b79..a496bb375 100644 --- a/src/core/jsonschema/include/sourcemeta/core/jsonschema_transform.h +++ b/src/core/jsonschema/include/sourcemeta/core/jsonschema_transform.h @@ -93,10 +93,11 @@ class SOURCEMETA_CORE_JSONSCHEMA_EXPORT SchemaTransformRule { -> std::pair; /// Check if the rule applies to a schema - auto check(const JSON &schema, const JSON &root, - const Vocabularies &vocabularies, const SchemaWalker &walker, - const SchemaResolver &resolver, const SchemaFrame &frame, - const SchemaFrame::Location &location) const -> Result; + [[nodiscard]] auto + check(const JSON &schema, const JSON &root, const Vocabularies &vocabularies, + const SchemaWalker &walker, const SchemaResolver &resolver, + const SchemaFrame &frame, const SchemaFrame::Location &location) const + -> Result; /// A method to optionally fix any reference location that was affected by the /// transformation. @@ -236,10 +237,11 @@ class SOURCEMETA_CORE_JSONSCHEMA_EXPORT SchemaTransformer { -> bool; /// Report back the rules from the bundle that need to be applied to a schema - auto check(const JSON &schema, const SchemaWalker &walker, - const SchemaResolver &resolver, const Callback &callback, - const std::optional &default_dialect = std::nullopt, - const std::optional &default_id = std::nullopt) const + [[nodiscard]] auto + check(const JSON &schema, const SchemaWalker &walker, + const SchemaResolver &resolver, const Callback &callback, + const std::optional &default_dialect = std::nullopt, + const std::optional &default_id = std::nullopt) const -> bool; private: diff --git a/src/core/jsonschema/include/sourcemeta/core/jsonschema_walker.h b/src/core/jsonschema/include/sourcemeta/core/jsonschema_walker.h index 4083ade59..a953b52fa 100644 --- a/src/core/jsonschema/include/sourcemeta/core/jsonschema_walker.h +++ b/src/core/jsonschema/include/sourcemeta/core/jsonschema_walker.h @@ -65,10 +65,10 @@ class SOURCEMETA_CORE_JSONSCHEMA_EXPORT SchemaIterator { const JSON &input, const SchemaWalker &walker, const SchemaResolver &resolver, const std::optional &default_dialect = std::nullopt); - auto begin() const -> const_iterator; - auto end() const -> const_iterator; - auto cbegin() const -> const_iterator; - auto cend() const -> const_iterator; + [[nodiscard]] auto begin() const -> const_iterator; + [[nodiscard]] auto end() const -> const_iterator; + [[nodiscard]] auto cbegin() const -> const_iterator; + [[nodiscard]] auto cend() const -> const_iterator; private: // Exporting symbols that depends on the standard C++ library is considered @@ -132,10 +132,10 @@ class SOURCEMETA_CORE_JSONSCHEMA_EXPORT SchemaIteratorFlat { const JSON &input, const SchemaWalker &walker, const SchemaResolver &resolver, const std::optional &default_dialect = std::nullopt); - auto begin() const -> const_iterator; - auto end() const -> const_iterator; - auto cbegin() const -> const_iterator; - auto cend() const -> const_iterator; + [[nodiscard]] auto begin() const -> const_iterator; + [[nodiscard]] auto end() const -> const_iterator; + [[nodiscard]] auto cbegin() const -> const_iterator; + [[nodiscard]] auto cend() const -> const_iterator; private: // Exporting symbols that depends on the standard C++ library is considered @@ -189,10 +189,10 @@ class SOURCEMETA_CORE_JSONSCHEMA_EXPORT SchemaKeywordIterator { const JSON &input, const SchemaWalker &walker, const SchemaResolver &resolver, const std::optional &default_dialect = std::nullopt); - auto begin() const -> const_iterator; - auto end() const -> const_iterator; - auto cbegin() const -> const_iterator; - auto cend() const -> const_iterator; + [[nodiscard]] auto begin() const -> const_iterator; + [[nodiscard]] auto end() const -> const_iterator; + [[nodiscard]] auto cbegin() const -> const_iterator; + [[nodiscard]] auto cend() const -> const_iterator; private: // Exporting symbols that depends on the standard C++ library is considered diff --git a/src/core/uri/include/sourcemeta/core/uri.h b/src/core/uri/include/sourcemeta/core/uri.h index 3312a7603..f5a69015f 100644 --- a/src/core/uri/include/sourcemeta/core/uri.h +++ b/src/core/uri/include/sourcemeta/core/uri.h @@ -85,7 +85,7 @@ class SOURCEMETA_CORE_URI_EXPORT URI { /// const sourcemeta::core::URI uri{"urn:example:schema"}; /// assert(uri.is_urn()); /// ``` - auto is_urn() const -> bool; + [[nodiscard]] auto is_urn() const -> bool; /// Check if the URI is a tag as described by RFC 4151. For example: /// @@ -96,7 +96,7 @@ class SOURCEMETA_CORE_URI_EXPORT URI { /// const sourcemeta::core::URI uri{"tag:yaml.org,2002:int"}; /// assert(uri.is_tag()); /// ``` - auto is_tag() const -> bool; + [[nodiscard]] auto is_tag() const -> bool; /// Check if the URI has the `mailto` scheme. For example: /// @@ -107,7 +107,7 @@ class SOURCEMETA_CORE_URI_EXPORT URI { /// const sourcemeta::core::URI uri{"mailto:joe@example.com"}; /// assert(uri.is_mailto()); /// ``` - auto is_mailto() const -> bool; + [[nodiscard]] auto is_mailto() const -> bool; /// Check if the URI only consists of a fragment. For example: /// @@ -118,7 +118,7 @@ class SOURCEMETA_CORE_URI_EXPORT URI { /// const sourcemeta::core::URI uri{"#foo"}; /// assert(uri.is_fragment_only()); /// ``` - auto is_fragment_only() const -> bool; + [[nodiscard]] auto is_fragment_only() const -> bool; /// Check if the URI is relative. For example: /// @@ -129,7 +129,7 @@ class SOURCEMETA_CORE_URI_EXPORT URI { /// sourcemeta::core::URI uri{"./foo"}; /// assert(uri.is_relative()); /// ``` - auto is_relative() const -> bool; + [[nodiscard]] auto is_relative() const -> bool; /// Check if the host is an ipv6 address. For example: /// @@ -140,7 +140,7 @@ class SOURCEMETA_CORE_URI_EXPORT URI { /// sourcemeta::core::URI uri{"http://[::1]"}; /// assert(uri.is_ipv6()); /// ``` - auto is_ipv6() const -> bool; + [[nodiscard]] auto is_ipv6() const -> bool; /// Check if the URI corresponds to the empty URI. For example: /// @@ -151,7 +151,7 @@ class SOURCEMETA_CORE_URI_EXPORT URI { /// sourcemeta::core::URI uri{""}; /// assert(uri.empty()); /// ``` - auto empty() const -> bool; + [[nodiscard]] auto empty() const -> bool; /// Get the scheme part of the URI, if any. For example: /// diff --git a/src/core/uuid/CMakeLists.txt b/src/core/uuid/CMakeLists.txt index 324b05a72..550a41ae1 100644 --- a/src/core/uuid/CMakeLists.txt +++ b/src/core/uuid/CMakeLists.txt @@ -1,4 +1,15 @@ -sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME uuid SOURCES uuid.cc) +if(SOURCEMETA_CXX_CLANG_TIDY) + sourcemeta_library(NAMESPACE sourcemeta + PROJECT core + NAME uuid + SOURCES uuid.cc + CLANG_TIDY "${SOURCEMETA_CXX_CLANG_TIDY}") +else() + sourcemeta_library(NAMESPACE sourcemeta + PROJECT core + NAME uuid + SOURCES uuid.cc) +endif() if(SOURCEMETA_CORE_INSTALL) sourcemeta_library_install(NAMESPACE sourcemeta PROJECT core NAME uuid) diff --git a/test/jsonschema/jsonschema_transformer_test.cc b/test/jsonschema/jsonschema_transformer_test.cc index 90feacd03..f4e31903f 100644 --- a/test/jsonschema/jsonschema_transformer_test.cc +++ b/test/jsonschema/jsonschema_transformer_test.cc @@ -540,9 +540,10 @@ TEST(JSONSchema_transformer, check_throw_if_no_dialect_invalid_default) { "qux": "xxx" })JSON"); - EXPECT_THROW(bundle.check(document, sourcemeta::core::schema_official_walker, - sourcemeta::core::schema_official_resolver, nullptr, - "https://example.com/invalid"), + EXPECT_THROW((void)bundle.check(document, + sourcemeta::core::schema_official_walker, + sourcemeta::core::schema_official_resolver, + nullptr, "https://example.com/invalid"), sourcemeta::core::SchemaResolutionError); }