diff --git a/.github/config/REUSE.toml b/.github/config/REUSE.toml new file mode 100644 index 00000000..83d96113 --- /dev/null +++ b/.github/config/REUSE.toml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2006-2024 Knut Reinert & Freie Universität Berlin +# SPDX-FileCopyrightText: 2016-2024 Knut Reinert & MPI für molekulare Genetik +# SPDX-License-Identifier: CC0-1.0 + +version = 1 +SPDX-PackageName = "Raptor" +SPDX-PackageDownloadLocation = "https://github.com/seqan/raptor/" + +[[annotations]] +path = "cppcheck" +precedence = "aggregate" +SPDX-FileCopyrightText = ["2006-2024, Knut Reinert & Freie Universität Berlin", "2016-2024, Knut Reinert & MPI für molekulare Genetik"] +SPDX-License-Identifier = "CC0-1.0" + diff --git a/.github/config/codechecker.skip b/.github/config/codechecker.skip new file mode 100644 index 00000000..2abc2f18 --- /dev/null +++ b/.github/config/codechecker.skip @@ -0,0 +1,6 @@ +# SPDX-FileCopyrightText: 2006-2024, Knut Reinert & Freie Universität Berlin +# SPDX-FileCopyrightText: 2016-2024, Knut Reinert & MPI für molekulare Genetik +# SPDX-License-Identifier: CC0-1.0 + ++${GITHUB_WORKSPACE}/* +-* diff --git a/.github/config/codechecker.yml b/.github/config/codechecker.yml new file mode 100644 index 00000000..6d454f63 --- /dev/null +++ b/.github/config/codechecker.yml @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2006-2024, Knut Reinert & Freie Universität Berlin +# SPDX-FileCopyrightText: 2016-2024, Knut Reinert & MPI für molekulare Genetik +# SPDX-License-Identifier: CC0-1.0 + +analyze: + - --enable=performance + - --cppcheckargs=${GITHUB_WORKSPACE}/.github/config/cppcheck + - --enable=bugprone + - --disable=bugprone-easily-swappable-parameters + - --disable=bugprone-narrowing-conversions + - --disable=clang-diagnostic-implicit-int-float-conversion + - --disable=clang-diagnostic-float-conversion + - --disable=clang-diagnostic-implicit-int-conversion + - --skip=${GITHUB_WORKSPACE}/.github/config/codechecker.skip + - --clean + +parse: + - --export=html + - --output=./html + - --skip=${GITHUB_WORKSPACE}/.github/config/codechecker.skip + - --trim-path-prefix=${GITHUB_WORKSPACE}/ diff --git a/.github/config/cppcheck b/.github/config/cppcheck new file mode 100644 index 00000000..8299c66b --- /dev/null +++ b/.github/config/cppcheck @@ -0,0 +1 @@ +--check-level=exhaustive diff --git a/.github/workflows/ci_codechecker.yml b/.github/workflows/ci_codechecker.yml new file mode 100644 index 00000000..5847af45 --- /dev/null +++ b/.github/workflows/ci_codechecker.yml @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2006-2024, Knut Reinert & Freie Universität Berlin +# SPDX-FileCopyrightText: 2016-2024, Knut Reinert & MPI für molekulare Genetik +# SPDX-License-Identifier: CC0-1.0 + +name: CodeChecker + +on: + schedule: + - cron: "0 4 * * THU" + workflow_dispatch: + +env: + TZ: Europe/Berlin + +defaults: + run: + shell: bash -Eexuo pipefail {0} + +jobs: + build: + name: CodeChecker + runs-on: ubuntu-latest + if: github.repository_owner == 'seqan' || github.event_name == 'workflow_dispatch' + container: + image: ghcr.io/seqan/clang-19 + volumes: + - /home/runner:/home/runner + steps: + - name: Run CodeChecker + uses: seqan/actions/codechecker@main + with: + deploy_host: ${{ secrets.DEPLOY_HOST }} + deploy_user: ${{ secrets.DEPLOY_USER }} + deploy_ssh_key: ${{ secrets.DEPLOY_SSH_KEY }} + deploy_path: ${{ secrets.DEPLOY_CODECHECKER_PATH }} diff --git a/include/raptor/argument_parsing/formatted_bytes.hpp b/include/raptor/argument_parsing/formatted_bytes.hpp index ae0d861f..29fdfe50 100644 --- a/include/raptor/argument_parsing/formatted_bytes.hpp +++ b/include/raptor/argument_parsing/formatted_bytes.hpp @@ -39,8 +39,8 @@ namespace raptor decimal >>= (iterations - 1u) * 10u; // Shift to next smallest unit, e.g. 800MiB decimal = decimal * 1000u / 1024u; // Account for using decimal system, i.e. 800MiB != 0.8GiB size_t const diff{decimal - (decimal / 100u) * 100u}; // We want to round up to 1 decimal position - uint32_t const round_up{diff >= 50u}; - decimal += round_up * 100u - diff; + bool const round_up{diff >= 50u}; + decimal += static_cast(round_up * 100u) - diff; decimal /= 100u; return decimal; }; diff --git a/include/raptor/argument_parsing/formatted_index_size.hpp b/include/raptor/argument_parsing/formatted_index_size.hpp index d6a1c00f..97082ba0 100644 --- a/include/raptor/argument_parsing/formatted_index_size.hpp +++ b/include/raptor/argument_parsing/formatted_index_size.hpp @@ -19,7 +19,7 @@ namespace raptor { -[[nodiscard]] inline size_t index_size_in_KiB(std::filesystem::path index_path, uint8_t const parts) +[[nodiscard]] inline size_t index_size_in_KiB(std::filesystem::path const & index_path, uint8_t const parts) { size_t index_size_in_bytes{}; if (parts == 1u) @@ -37,7 +37,7 @@ namespace raptor return index_size_in_bytes >> 10; } -[[nodiscard]] inline std::string formatted_index_size(std::filesystem::path index_path, uint8_t const parts) +[[nodiscard]] inline std::string formatted_index_size(std::filesystem::path const & index_path, uint8_t const parts) { return formatted_bytes(index_size_in_KiB(index_path, parts) << 10); } diff --git a/include/raptor/argument_parsing/validators.hpp b/include/raptor/argument_parsing/validators.hpp index 8b2de094..41673e17 100644 --- a/include/raptor/argument_parsing/validators.hpp +++ b/include/raptor/argument_parsing/validators.hpp @@ -48,7 +48,11 @@ static inline std::vector combined_extensions{ { result.push_back(sequence_extension); for (auto && compression_extension : compression_extensions) - result.push_back(sequence_extension + std::string{'.'} + compression_extension); + { + result.push_back(sequence_extension); + result.back() += '.'; + result.back() += compression_extension; + } } } return result; diff --git a/include/raptor/file_reader.hpp b/include/raptor/file_reader.hpp index 3eb22337..f2efda84 100644 --- a/include/raptor/file_reader.hpp +++ b/include/raptor/file_reader.hpp @@ -18,7 +18,7 @@ namespace raptor { -enum class file_types +enum class file_types : uint8_t { sequence, minimiser diff --git a/include/raptor/prepare/cutoff.hpp b/include/raptor/prepare/cutoff.hpp index aaa2d975..b51224af 100644 --- a/include/raptor/prepare/cutoff.hpp +++ b/include/raptor/prepare/cutoff.hpp @@ -44,22 +44,25 @@ class cutoff { case cutoff_kinds::filesize_dependent: return impl(filename); - default: - { - assert(cutoff_kind == cutoff_kinds::fixed); + case cutoff_kinds::fixed: return fixed_cutoff; - } + default: // GCOVR_EXCL_LINE +#ifndef NDEBUG + assert(false); // GCOVR_EXCL_LINE +#else + __builtin_unreachable(); +#endif } } - static inline bool file_is_compressed(std::filesystem::path const & filepath) + static inline bool file_is_compressed(std::filesystem::path const & filepath) noexcept { std::filesystem::path const extension = filepath.extension(); return extension == ".gz" || extension == ".bgzf" || extension == ".bz2"; } private: - enum class cutoff_kinds + enum class cutoff_kinds : uint8_t { fixed, filesize_dependent @@ -80,7 +83,7 @@ class cutoff 1'073'741'824ULL, 3'221'225'472ULL}; - uint8_t impl(std::filesystem::path const & filename) const + uint8_t impl(std::filesystem::path const & filename) const noexcept { bool const is_compressed = file_is_compressed(filename); bool const is_fasta = check_for_fasta_format(filename); @@ -103,9 +106,10 @@ class cutoff return cutoff; } - static inline bool - check_for_fasta_format(std::filesystem::path const & filepath, - std::vector const & valid_extensions = seqan3::format_fasta::file_extensions) + // NOLINTNEXTLINE(bugprone-exception-escape) + static inline bool check_for_fasta_format( + std::filesystem::path const & filepath, + std::vector const & valid_extensions = seqan3::format_fasta::file_extensions) noexcept { std::string const extension = file_is_compressed(filepath) ? filepath.stem() : filepath.extension(); diff --git a/include/raptor/threshold/logspace.hpp b/include/raptor/threshold/logspace.hpp index f2fe3999..38338909 100644 --- a/include/raptor/threshold/logspace.hpp +++ b/include/raptor/threshold/logspace.hpp @@ -15,7 +15,7 @@ namespace raptor::logspace { -constexpr double ln_2{0.693147180559945309417232121458176568L}; +constexpr double ln_2{0.693147180559945}; constexpr double negative_inf{-std::numeric_limits::infinity()}; //!\brief The log of a sum of two log terms. @@ -31,7 +31,7 @@ constexpr double negative_inf{-std::numeric_limits::infinity()}; template [[nodiscard]] double add(double const log_x, double const log_y, types... logs) noexcept { - return add(add(log_y, log_x), logs...); + return add(add(log_x, log_y), logs...); } //!\brief The log of a difference of two log terms. (log_x - log_y) diff --git a/include/raptor/threshold/threshold.hpp b/include/raptor/threshold/threshold.hpp index 830e146b..d2ef029a 100644 --- a/include/raptor/threshold/threshold.hpp +++ b/include/raptor/threshold/threshold.hpp @@ -30,7 +30,7 @@ class threshold size_t get(size_t const minimiser_count) const noexcept; private: - enum class threshold_kinds + enum class threshold_kinds : uint8_t { probabilistic, lemma, diff --git a/src/argument_parsing/compute_bin_size.cpp b/src/argument_parsing/compute_bin_size.cpp index bfaeaaea..56d747cb 100644 --- a/src/argument_parsing/compute_bin_size.cpp +++ b/src/argument_parsing/compute_bin_size.cpp @@ -31,13 +31,13 @@ size_t kmer_count_from_minimiser_files(std::vector> con size_t max_filesize{}; std::filesystem::path biggest_file{}; - auto callback = [&callback_mutex, &biggest_file, &max_filesize](std::filesystem::path const path, size_t const size) + auto callback = [&callback_mutex, &biggest_file, &max_filesize](std::filesystem::path path, size_t const size) { std::lock_guard guard{callback_mutex}; if (size > max_filesize) { max_filesize = size; - biggest_file = path; + biggest_file = std::move(path); } }; @@ -61,7 +61,7 @@ size_t kmer_count_from_minimiser_files(std::vector> con } } - callback(biggest_file, max_filesize); + callback(std::move(biggest_file), max_filesize); }; call_parallel_on_bins(worker, bin_path, threads); diff --git a/src/raptor.cpp b/src/raptor.cpp index 8548f5a1..c25aa5ab 100644 --- a/src/raptor.cpp +++ b/src/raptor.cpp @@ -48,7 +48,7 @@ int main(int argc, char ** argv) if (sub_parser.info.app_name == std::string_view{"Raptor-upgrade"}) raptor::upgrade_parsing(sub_parser); } - catch (sharg::parser_error const & ext) + catch (std::exception const & ext) { std::cerr << "[Error] " << ext.what() << '\n'; std::exit(-1); diff --git a/src/threshold/threshold.cpp b/src/threshold/threshold.cpp index 5c388c89..140c2b96 100644 --- a/src/threshold/threshold.cpp +++ b/src/threshold/threshold.cpp @@ -14,7 +14,7 @@ namespace raptor::threshold threshold::threshold(threshold_parameters const & arguments) { - uint8_t const kmer_size{arguments.shape.size()}; + size_t const kmer_size{arguments.shape.size()}; size_t const kmers_per_window = arguments.window_size - kmer_size + 1; if (!std::isnan(arguments.percentage)) @@ -48,13 +48,18 @@ size_t threshold::get(size_t const minimiser_count) const noexcept return kmer_lemma; case threshold_kinds::percentage: return std::max(1u, minimiser_count * threshold_percentage); - default: + case threshold_kinds::probabilistic: { - assert(threshold_kind == threshold_kinds::probabilistic); size_t const index = std::clamp(minimiser_count, minimal_number_of_minimizers, maximal_number_of_minimizers) - minimal_number_of_minimizers; return std::max(1u, precomp_thresholds[index] + precomp_correction[index]); } + default: // GCOVR_EXCL_LINE +#ifndef NDEBUG + assert(false); // GCOVR_EXCL_LINE +#else + __builtin_unreachable(); +#endif } }