diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..096a55e87 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,39 @@ +# Checks: 'boost-*,bugprone-*,clang-diagnostic*,cppcoreguidelines-*,modernize-*,misc-*,performance-*,readability-*,-bugprone-easily-swappable-parameters,-cppcoreguidelines-avoid-do-while,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-vararg,-modernize-use-trailing-return-type,-misc-include-cleaner,-misc-non-private-member-variables-in-classes' +WarningsAsErrors: "*" +HeaderFilterRegex: '.*\/(olp-cpp-sdk-core|olp-cpp-sdk-authentication|olp-cpp-sdk-dataservice-read|olp-cpp-sdk-dataservice-write)\/.*' +FormatStyle: "file" +CheckOptions: + - key: readability-function-cognitive-complexity.IgnoreMacros + value: true + - key: readability-identifier-naming.ClassCase + value: CamelCase + - key: readability-identifier-naming.MethodCase + value: CamelCase + - key: readability-identifier-naming.MemberCase + value: lower_case + - key: readability-identifier-naming.PrivateMemberSuffix + value: _ + - key: readability-identifier-naming.ProtectedMemberSuffix + value: _ + - key: readability-identifier-naming.FunctionCase + value: CamelCase + - key: readability-identifier-naming.ConstexprVariableCase + value: CamelCase + - key: readability-identifier-naming.ConstexprVariablePrefix + value: k + - key: readability-identifier-naming.StaticConstantCase + value: CamelCase + - key: readability-identifier-naming.StaticConstantPrefix + value: k + - key: readability-identifier-naming.GlobalConstantCase + value: CamelCase + - key: readability-identifier-naming.GlobalConstantPrefix + value: k + - key: readability-identifier-naming.EnumConstantCase + value: CamelCase + - key: readability-identifier-naming.EnumConstantPrefix + value: k + - key: readability-identifier-naming.ParameterCase + value: lower_case + - key: readability-identifier-naming.VariableCase + value: lower_case diff --git a/.github/workflows/psv_pipelines.yml b/.github/workflows/psv_pipelines.yml index e88dfcd69..fd178651d 100644 --- a/.github/workflows/psv_pipelines.yml +++ b/.github/workflows/psv_pipelines.yml @@ -26,6 +26,24 @@ jobs: run: ./scripts/misc/cpplint_ci.sh shell: bash + psv-linux-24-04-clang17-build-clang-tidy: + name: PSV.Linux.24.04.clang17.ClangTidy + if: github.event_name == 'pull_request' + runs-on: ubuntu-24.04 + steps: + - name: Check out repository + uses: actions/checkout@v7 + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + libboost-all-dev \ + libcurl4-openssl-dev + shell: bash + - name: Run clang-tidy + run: ./scripts/misc/clang-tidy-17-check.sh + shell: bash + psv-linux-22-04-gcc9-build-test-codecov: name: PSV.Linux.22.04.gcc9.Tests.CodeCov runs-on: ubuntu-22.04 @@ -377,4 +395,4 @@ jobs: echo "Then run: git apply $CLANG_FORMAT_FILE" exit 1 fi - shell: bash + shell: bash \ No newline at end of file diff --git a/olp-cpp-sdk-authentication/src/Crypto.cpp b/olp-cpp-sdk-authentication/src/Crypto.cpp index 52ae764a9..04ae869fb 100644 --- a/olp-cpp-sdk-authentication/src/Crypto.cpp +++ b/olp-cpp-sdk-authentication/src/Crypto.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2023 HERE Europe B.V. + * Copyright (C) 2019-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -168,7 +168,7 @@ Crypto::Sha256Digest ComputeSha256(const std::vector& src) { auto v3 = (unsigned char)value; auto v2 = (unsigned char)(value >>= 8); auto v1 = (unsigned char)(value >>= 8); - ret[j + 0] = (unsigned char)(value >>= 8); + ret[j + 0] = (unsigned char)(value >> 8); ret[j + 1] = v1; ret[j + 2] = v2; ret[j + 3] = v3; diff --git a/olp-cpp-sdk-authentication/src/SignInResultImpl.cpp b/olp-cpp-sdk-authentication/src/SignInResultImpl.cpp index 334de6cb1..8440bb85e 100644 --- a/olp-cpp-sdk-authentication/src/SignInResultImpl.cpp +++ b/olp-cpp-sdk-authentication/src/SignInResultImpl.cpp @@ -92,7 +92,7 @@ SignInResultImpl::SignInResultImpl( // Extra response data if no errors reported if (!HasError()) { - if (!IsValid()) { + if (!is_valid_) { status_ = http::HttpStatusCode::SERVICE_UNAVAILABLE; error_.message = Constants::ERROR_HTTP_SERVICE_UNAVAILABLE; } else { diff --git a/olp-cpp-sdk-authentication/src/TokenEndpointImpl.cpp b/olp-cpp-sdk-authentication/src/TokenEndpointImpl.cpp index a3808009a..d30fb9e05 100644 --- a/olp-cpp-sdk-authentication/src/TokenEndpointImpl.cpp +++ b/olp-cpp-sdk-authentication/src/TokenEndpointImpl.cpp @@ -192,6 +192,7 @@ client::CancellationToken TokenEndpointImpl::RequestToken( properties.scope = scope_; return auth_client_.SignInClient( credentials_, properties, + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false [callback]( const AuthenticationClient::SignInClientResponse& sign_in_response) { if (!sign_in_response) { diff --git a/olp-cpp-sdk-dataservice-write/src/IndexLayerClientImpl.cpp b/olp-cpp-sdk-dataservice-write/src/IndexLayerClientImpl.cpp index 0ee6b00f1..4764d8d3d 100644 --- a/olp-cpp-sdk-dataservice-write/src/IndexLayerClientImpl.cpp +++ b/olp-cpp-sdk-dataservice-write/src/IndexLayerClientImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2024 HERE Europe B.V. + * Copyright (C) 2019-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -242,6 +242,7 @@ client::CancellationToken IndexLayerClientImpl::DeleteIndexData( auto cancel_context = std::make_shared(); auto self = shared_from_this(); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto cancel_function = [=]() { self->tokenList_.RemoveTask(op_id); callback(DeleteIndexDataResponse(client::ApiError( @@ -302,12 +303,14 @@ client::CancellationToken IndexLayerClientImpl::UpdateIndex( auto self = shared_from_this(); auto op_id = tokenList_.GetNextId(); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto cancel_function = [=]() { self->tokenList_.RemoveTask(op_id); callback(UpdateIndexResponse(client::ApiError( client::ErrorCode::Cancelled, "Operation cancelled.", true))); }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto updateIndex_callback = [=](UpdateIndexResponse update_index_response) { self->tokenList_.RemoveTask(op_id); if (!update_index_response.IsSuccessful()) { diff --git a/olp-cpp-sdk-dataservice-write/src/StreamLayerClientImpl.cpp b/olp-cpp-sdk-dataservice-write/src/StreamLayerClientImpl.cpp index 6a0047023..0763784a8 100644 --- a/olp-cpp-sdk-dataservice-write/src/StreamLayerClientImpl.cpp +++ b/olp-cpp-sdk-dataservice-write/src/StreamLayerClientImpl.cpp @@ -214,6 +214,7 @@ olp::client::CancellationToken StreamLayerClientImpl::Flush( // invocation: one during execution phase and other when `Flush` is cancelled. auto exec_started = std::make_shared(false); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto task_context = client::TaskContext::Create( [=](client::CancellationContext context) -> EmptyFlushApiResponse { exec_started->exchange(true); @@ -249,6 +250,7 @@ olp::client::CancellationToken StreamLayerClientImpl::Flush( callback(responses); return EmptyFlushApiResponse{}; }, + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false [=](EmptyFlushApiResponse /*response*/) { // we don't need to notify user 2 times, cause we already invoke a // callback in the execution function: diff --git a/olp-cpp-sdk-dataservice-write/src/VersionedLayerClientImpl.cpp b/olp-cpp-sdk-dataservice-write/src/VersionedLayerClientImpl.cpp index ecefefa47..b4b1618fc 100644 --- a/olp-cpp-sdk-dataservice-write/src/VersionedLayerClientImpl.cpp +++ b/olp-cpp-sdk-dataservice-write/src/VersionedLayerClientImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2021 HERE Europe B.V. + * Copyright (C) 2019-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -224,6 +224,7 @@ olp::client::CancellationToken VersionedLayerClientImpl::GetBaseVersion( auto cancel_context = std::make_shared(); auto id = tokenList_.GetNextId(); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto cancel_function = [=]() { self->tokenList_.RemoveTask(id); callback(client::ApiError(client::ErrorCode::Cancelled, @@ -231,6 +232,7 @@ olp::client::CancellationToken VersionedLayerClientImpl::GetBaseVersion( }; auto getBaseVersion_callback = + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false [=](MetadataApi::CatalogVersionResponse response) { self->tokenList_.RemoveTask(id); if (!response.IsSuccessful()) { @@ -247,12 +249,14 @@ olp::client::CancellationToken VersionedLayerClientImpl::GetBaseVersion( } }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto getBaseVersion_function = [=]() -> client::CancellationToken { return MetadataApi::GetLatestCatalogVersion(*self->apiclient_metadata_, -1, olp::porting::none, getBaseVersion_callback); }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false cancel_context->ExecuteOrCancelled( [=]() -> client::CancellationToken { return self->InitApiClients( @@ -298,6 +302,7 @@ olp::client::CancellationToken VersionedLayerClientImpl::GetBatch( auto cancel_context = std::make_shared(); auto id = tokenList_.GetNextId(); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto cancel_function = [=]() { self->tokenList_.RemoveTask(id); callback(client::ApiError(client::ErrorCode::Cancelled, @@ -305,6 +310,7 @@ olp::client::CancellationToken VersionedLayerClientImpl::GetBatch( }; auto getPublication_callback = + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false [=](GetPublicationResponse getPublicationResponse) { self->tokenList_.RemoveTask(id); if (!getPublicationResponse.IsSuccessful()) { @@ -314,12 +320,14 @@ olp::client::CancellationToken VersionedLayerClientImpl::GetBatch( } }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto getPublication_function = [=]() -> client::CancellationToken { return PublishApi::GetPublication(*self->apiclient_publish_, publicationId, olp::porting::none, getPublication_callback); }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false cancel_context->ExecuteOrCancelled( [=]() -> client::CancellationToken { return self->InitApiClients( @@ -567,6 +575,7 @@ client::CancellationToken VersionedLayerClientImpl::CheckDataExists( auto id = tokenList_.GetNextId(); auto check_data_exists_callback = + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false [=](CheckDataExistsResponse check_data_exists_response) { self->tokenList_.RemoveTask(id); if (!check_data_exists_response.IsSuccessful()) { @@ -576,17 +585,20 @@ client::CancellationToken VersionedLayerClientImpl::CheckDataExists( } }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto check_data_exists_function = [=]() -> client::CancellationToken { return BlobApi::checkBlobExists(*self->apiclient_blob_, layer_id, data_handle, olp::porting::none, check_data_exists_callback); }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto cancel_function = [callback]() { callback(client::ApiError(client::ErrorCode::Cancelled, "Operation cancelled.", true)); }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false cancel_context->ExecuteOrCancelled( [=]() -> client::CancellationToken { return self->InitApiClients( diff --git a/olp-cpp-sdk-dataservice-write/src/VolatileLayerClientImpl.cpp b/olp-cpp-sdk-dataservice-write/src/VolatileLayerClientImpl.cpp index 332d7c043..d64b04c9c 100644 --- a/olp-cpp-sdk-dataservice-write/src/VolatileLayerClientImpl.cpp +++ b/olp-cpp-sdk-dataservice-write/src/VolatileLayerClientImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2021 HERE Europe B.V. + * Copyright (C) 2019-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -193,6 +193,7 @@ client::CancellationToken VolatileLayerClientImpl::GetBaseVersion( }; auto getBaseVersion_callback = + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false [=](MetadataApi::CatalogVersionResponse response) { self->tokenList_.RemoveTask(id); if (!response.IsSuccessful()) { @@ -209,12 +210,14 @@ client::CancellationToken VolatileLayerClientImpl::GetBaseVersion( } }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto getBaseVersion_function = [=]() -> client::CancellationToken { return MetadataApi::GetLatestCatalogVersion(*self->apiclient_metadata_, -1, olp::porting::none, getBaseVersion_callback); }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false cancel_context->ExecuteOrCancelled( [=]() -> client::CancellationToken { return self->InitApiClients( @@ -264,6 +267,7 @@ client::CancellationToken VolatileLayerClientImpl::StartBatch( } }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto init_publication_function = [=]() -> client::CancellationToken { model::Publication pub; pub.SetLayerIds(request.GetLayers().value_or(std::vector())); @@ -275,12 +279,14 @@ client::CancellationToken VolatileLayerClientImpl::StartBatch( init_publication_callback); }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto cancel_function = [=]() { self->tokenList_.RemoveTask(id); callback(client::ApiError(client::ErrorCode::Cancelled, "Operation cancelled.", true)); }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false cancel_context->ExecuteOrCancelled( [=]() -> client::CancellationToken { return self->InitApiClients( @@ -426,6 +432,7 @@ client::CancellationToken VolatileLayerClientImpl::GetBatch( }; auto getPublication_callback = + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false [=](GetPublicationResponse getPublicationResponse) { self->tokenList_.RemoveTask(id); if (!getPublicationResponse.IsSuccessful()) { @@ -435,12 +442,14 @@ client::CancellationToken VolatileLayerClientImpl::GetBatch( } }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto getPublication_function = [=]() -> client::CancellationToken { return PublishApi::GetPublication(*self->apiclient_publish_, publicationId, olp::porting::none, getPublication_callback); }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false cancel_context->ExecuteOrCancelled( [=]() -> client::CancellationToken { return self->InitApiClients( @@ -572,6 +581,7 @@ client::CancellationToken VolatileLayerClientImpl::PublishToBatch( auto self = shared_from_this(); auto id = tokenList_.GetNextId(); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto cancel_function = [=]() { self->tokenList_.RemoveTask(id); callback(client::ApiError(client::ErrorCode::Cancelled, @@ -579,6 +589,7 @@ client::CancellationToken VolatileLayerClientImpl::PublishToBatch( }; auto upload_partitions_callback = + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false [=](UploadPartitionsResponse upload_partitions_response) { self->tokenList_.RemoveTask(id); if (!upload_partitions_response.IsSuccessful()) { @@ -588,6 +599,7 @@ client::CancellationToken VolatileLayerClientImpl::PublishToBatch( } }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto upload_partitions_function = [=]() -> client::CancellationToken { std::vector pub_partition_list; for (const auto& partition_request : partitions) { @@ -610,6 +622,7 @@ client::CancellationToken VolatileLayerClientImpl::PublishToBatch( upload_partitions_callback); }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false cancel_context->ExecuteOrCancelled( [=]() -> client::CancellationToken { return self->InitApiClients( @@ -654,6 +667,7 @@ client::CancellationToken VolatileLayerClientImpl::CompleteBatch( auto self = shared_from_this(); auto cancel_context = std::make_shared(); auto id = tokenList_.GetNextId(); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto cancel_function = [=]() { self->tokenList_.RemoveTask(id); callback(client::ApiError(client::ErrorCode::Cancelled, @@ -661,6 +675,7 @@ client::CancellationToken VolatileLayerClientImpl::CompleteBatch( }; auto completePublication_callback = + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false [=](SubmitPublicationResponse submitPublicationResponse) { self->tokenList_.RemoveTask(id); if (!submitPublicationResponse.IsSuccessful()) { @@ -670,12 +685,14 @@ client::CancellationToken VolatileLayerClientImpl::CompleteBatch( } }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false auto completePublication_function = [=]() -> client::CancellationToken { return PublishApi::SubmitPublication(*self->apiclient_publish_, publicationId, olp::porting::none, completePublication_callback); }; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks): false cancel_context->ExecuteOrCancelled( [=]() -> client::CancellationToken { return self->InitApiClients( diff --git a/scripts/misc/clang-tidy-17-check.sh b/scripts/misc/clang-tidy-17-check.sh new file mode 100755 index 000000000..162eb07b8 --- /dev/null +++ b/scripts/misc/clang-tidy-17-check.sh @@ -0,0 +1,41 @@ +#!/bin/bash -ex +# +# Copyright (C) 2026 HERE Europe B.V. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# License-Filename: LICENSE + +BUILD_DIR="build-clang-tidy" + +rm -rf "${BUILD_DIR}" +mkdir "${BUILD_DIR}" + +cmake -S . -B "${BUILD_DIR}" -G Ninja \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DCMAKE_CXX_COMPILER=clang++-17 \ + -DCMAKE_C_COMPILER=clang-17 \ + -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" \ + -DOLP_SDK_ENABLE_TESTING=OFF \ + -DOLP_SDK_BUILD_EXAMPLES=OFF + +cmake --build "${BUILD_DIR}" -- -j"$(nproc)" + +run-clang-tidy-17.py -p "${BUILD_DIR}" \ + -config-file="${PWD}/.clang-tidy" \ + "${PWD}/olp-cpp-sdk-core/.*" \ + "${PWD}/olp-cpp-sdk-authentication/.*" \ + "${PWD}/olp-cpp-sdk-dataservice-read/.*" \ + "${PWD}/olp-cpp-sdk-dataservice-write/.*" \ No newline at end of file