Skip to content

Commit 084b45d

Browse files
ci: add clang-tidy check (#5)
1 parent 6ebb6a8 commit 084b45d

File tree

10 files changed

+180
-53
lines changed

10 files changed

+180
-53
lines changed

.clang-tidy

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
Checks: >
3+
# It follows https://github.com/googleapis/google-cloud-cpp/blob/main/.clang-tidy
4+
-*,
5+
abseil-*,
6+
bugprone-*,
7+
google-*,
8+
misc-*,
9+
modernize-*,
10+
performance-*,
11+
portability-*,
12+
readability-*,
13+
-google-readability-braces-around-statements,
14+
-google-readability-namespace-comments,
15+
-google-runtime-references,
16+
-misc-non-private-member-variables-in-classes,
17+
-misc-const-correctness,
18+
-misc-include-cleaner,
19+
-modernize-return-braced-init-list,
20+
-modernize-use-trailing-return-type,
21+
-modernize-concat-nested-namespaces,
22+
-modernize-use-nodiscard,
23+
-modernize-avoid-c-arrays,
24+
-modernize-type-traits,
25+
-modernize-unary-static-assert,
26+
-performance-move-const-arg,
27+
-performance-avoid-endl,
28+
-performance-enum-size,
29+
-readability-braces-around-statements,
30+
-readability-identifier-length,
31+
-readability-magic-numbers,
32+
-readability-named-parameter,
33+
-readability-redundant-declaration,
34+
-readability-avoid-return-with-void-value,
35+
-readability-function-cognitive-complexity,
36+
-bugprone-narrowing-conversions,
37+
-bugprone-easily-swappable-parameters,
38+
-bugprone-inc-dec-in-conditions,
39+
-bugprone-implicit-widening-of-multiplication-result,
40+
-bugprone-unchecked-optional-access,
41+
-bugprone-unused-local-non-trivial-variable,
42+
-bugprone-unused-return-value
43+
WarningsAsErrors: '*'
44+
HeaderFileExtensions:
45+
- ''
46+
- h
47+
ImplementationFileExtensions:
48+
- cc
49+
HeaderFilterRegex: '.*'
50+
FormatStyle: none
51+
User: xuyunze
52+
CheckOptions:
53+
cert-err33-c.CheckedFunctions: '^::aligned_alloc;^::asctime_s;^::at_quick_exit;^::atexit;^::bsearch;^::bsearch_s;^::btowc;^::c16rtomb;^::c32rtomb;^::calloc;^::clock;^::cnd_broadcast;^::cnd_init;^::cnd_signal;^::cnd_timedwait;^::cnd_wait;^::ctime_s;^::fclose;^::fflush;^::fgetc;^::fgetpos;^::fgets;^::fgetwc;^::fopen;^::fopen_s;^::fprintf;^::fprintf_s;^::fputc;^::fputs;^::fputwc;^::fputws;^::fread;^::freopen;^::freopen_s;^::fscanf;^::fscanf_s;^::fseek;^::fsetpos;^::ftell;^::fwprintf;^::fwprintf_s;^::fwrite;^::fwscanf;^::fwscanf_s;^::getc;^::getchar;^::getenv;^::getenv_s;^::gets_s;^::getwc;^::getwchar;^::gmtime;^::gmtime_s;^::localtime;^::localtime_s;^::malloc;^::mbrtoc16;^::mbrtoc32;^::mbsrtowcs;^::mbsrtowcs_s;^::mbstowcs;^::mbstowcs_s;^::memchr;^::mktime;^::mtx_init;^::mtx_lock;^::mtx_timedlock;^::mtx_trylock;^::mtx_unlock;^::printf_s;^::putc;^::putwc;^::raise;^::realloc;^::remove;^::rename;^::scanf;^::scanf_s;^::setlocale;^::setvbuf;^::signal;^::snprintf;^::snprintf_s;^::sprintf;^::sprintf_s;^::sscanf;^::sscanf_s;^::strchr;^::strerror_s;^::strftime;^::strpbrk;^::strrchr;^::strstr;^::strtod;^::strtof;^::strtoimax;^::strtok;^::strtok_s;^::strtol;^::strtold;^::strtoll;^::strtoul;^::strtoull;^::strtoumax;^::strxfrm;^::swprintf;^::swprintf_s;^::swscanf;^::swscanf_s;^::thrd_create;^::thrd_detach;^::thrd_join;^::thrd_sleep;^::time;^::timespec_get;^::tmpfile;^::tmpfile_s;^::tmpnam;^::tmpnam_s;^::tss_create;^::tss_get;^::tss_set;^::ungetc;^::ungetwc;^::vfprintf;^::vfprintf_s;^::vfscanf;^::vfscanf_s;^::vfwprintf;^::vfwprintf_s;^::vfwscanf;^::vfwscanf_s;^::vprintf_s;^::vscanf;^::vscanf_s;^::vsnprintf;^::vsnprintf_s;^::vsprintf;^::vsprintf_s;^::vsscanf;^::vsscanf_s;^::vswprintf;^::vswprintf_s;^::vswscanf;^::vswscanf_s;^::vwprintf_s;^::vwscanf;^::vwscanf_s;^::wcrtomb;^::wcschr;^::wcsftime;^::wcspbrk;^::wcsrchr;^::wcsrtombs;^::wcsrtombs_s;^::wcsstr;^::wcstod;^::wcstof;^::wcstoimax;^::wcstok;^::wcstok_s;^::wcstol;^::wcstold;^::wcstoll;^::wcstombs;^::wcstombs_s;^::wcstoul;^::wcstoull;^::wcstoumax;^::wcsxfrm;^::wctob;^::wctrans;^::wctype;^::wmemchr;^::wprintf_s;^::wscanf;^::wscanf_s;'
54+
cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor: 'true'
55+
cppcoreguidelines-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted: 'true'
56+
performance-move-const-arg.CheckTriviallyCopyableMove: 'false'
57+
readability-identifier-naming.LocalVariableCase: 'lower_case'
58+
readability-identifier-naming.LocalConstantCase: 'lower_case'
59+
readability-identifier-naming.StructCase: 'CamelCase'
60+
readability-identifier-naming.ClassCase: 'CamelCase'
61+
readability-identifier-naming.ParameterCase: 'lower_case'
62+
readability-identifier-naming.MethodCase: 'lower_case'
63+
readability-identifier-naming.FunctionCase: 'lower_case'
64+
readability-identifier-naming.MemberCase: 'lower_case'
65+
readability-identifier-naming.PrivateMemberSuffix: '_'
66+
readability-identifier-naming.PublicMemberSuffix: ''
67+
SystemHeaders: false

.github/workflows/lint.yaml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Copyright 2025 Yunze Xu
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
name: Lint
16+
17+
on:
18+
push:
19+
branches:
20+
- main
21+
pull_request:
22+
branches:
23+
- main
24+
25+
concurrency:
26+
group: ${{ github.workflow }}-${{ github.ref }}
27+
cancel-in-progress: true
28+
29+
jobs:
30+
31+
lint:
32+
name: Lint check
33+
runs-on: ubuntu-latest
34+
timeout-minutes: 60
35+
36+
steps:
37+
- uses: actions/checkout@v3
38+
with:
39+
fetch-depth: 0
40+
submodules: recursive
41+
42+
- name: Install necessary tools
43+
run: |
44+
sudo apt-get install -y clang-tidy
45+
46+
- name: Build
47+
run: |
48+
cmake -B build
49+
cmake --build build -j4
50+
51+
- name: Tidy
52+
run: |
53+
run-clang-tidy -p build
54+
if [[ $? -ne 0 ]]; then
55+
echo "clang-tidy failed"
56+
exit 1
57+
fi

include/snctl-cpp/configs.h

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
struct KafkaConfigs {
2828
std::string bootstrap_servers = "localhost:9092";
29-
std::string token = "";
29+
std::string token;
3030
};
3131

3232
struct LogConfigs {
@@ -39,7 +39,7 @@ struct LogConfigs {
3939

4040
class Configs : public SubCommand {
4141
public:
42-
Configs(argparse::ArgumentParser &parent) : SubCommand("configs") {
42+
explicit Configs(argparse::ArgumentParser &parent) : SubCommand("configs") {
4343
update_command_.add_description("Update key-value from the INI section");
4444
update_command_.add_argument("--kafka-url")
4545
.help("The Kafka bootstrap.servers");
@@ -55,15 +55,15 @@ class Configs : public SubCommand {
5555
if (!std::filesystem::exists(file)) {
5656
continue;
5757
}
58-
if (loadFile(file)) {
58+
if (load_file(file)) {
5959
break;
6060
}
6161
}
6262
if (config_file_.empty()) {
6363
config_file_ = std::filesystem::current_path() / "sncloud.ini";
6464
std::cout << "No config file found. Creating " << config_file_
6565
<< " with the default configs" << std::endl;
66-
saveFile();
66+
save_file();
6767
}
6868
}
6969

@@ -98,7 +98,7 @@ class Configs : public SubCommand {
9898
}
9999
}
100100
if (updated) {
101-
saveFile();
101+
save_file();
102102
std::cout << "Updated config file " << config_file_ << std::endl;
103103
} else {
104104
std::cout << "No config updated" << std::endl;
@@ -122,16 +122,16 @@ class Configs : public SubCommand {
122122
KafkaConfigs kafka_configs_;
123123
LogConfigs log_configs_;
124124

125-
std::optional<std::string> getValue(const std::string &section,
126-
const std::string &key) {
127-
auto value = ini_.GetValue(section.c_str(), key.c_str());
125+
std::optional<std::string> get_value(const std::string &section,
126+
const std::string &key) {
127+
const auto *value = ini_.GetValue(section.c_str(), key.c_str());
128128
if (value == nullptr) {
129129
return std::nullopt;
130130
}
131131
return std::optional(value);
132132
}
133133

134-
bool loadFile(const std::string &file) {
134+
bool load_file(const std::string &file) {
135135
if (auto rc = ini_.LoadFile(file.c_str()); rc != SI_OK) {
136136
std::cerr << "Failed to load existing file " << file << ": " << rc
137137
<< std::endl;
@@ -143,20 +143,20 @@ class Configs : public SubCommand {
143143
log_configs_ = {};
144144

145145
// load configs from the INI file
146-
if (auto value = getValue("kafka", "bootstrap.servers"); value) {
146+
if (auto value = get_value("kafka", "bootstrap.servers"); value) {
147147
kafka_configs_.bootstrap_servers = *value;
148148
} else {
149149
std::cerr << "No bootstrap.servers found in the kafka section. Use the "
150150
"default value: "
151151
<< kafka_configs_.bootstrap_servers << std::endl;
152152
}
153-
if (auto value = getValue("kafka", "token"); value) {
153+
if (auto value = get_value("kafka", "token"); value) {
154154
kafka_configs_.token = *value;
155155
}
156-
if (auto value = getValue("log", "enabled"); value) {
156+
if (auto value = get_value("log", "enabled"); value) {
157157
log_configs_.enabled = std::string(*value) != "false";
158158
if (log_configs_.enabled) {
159-
if (auto value = getValue("log", "path"); value) {
159+
if (auto value = get_value("log", "path"); value) {
160160
log_configs_.path = *value;
161161
}
162162
}
@@ -166,7 +166,7 @@ class Configs : public SubCommand {
166166
return true;
167167
}
168168

169-
void saveFile() {
169+
void save_file() {
170170
ini_.SetValue("kafka", "bootstrap.servers",
171171
kafka_configs_.bootstrap_servers.c_str());
172172
ini_.SetValue("kafka", "token", kafka_configs_.token.c_str());

include/snctl-cpp/rk_event_wrapper.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020

2121
class RdKafkaEvent final {
2222
public:
23-
static RdKafkaEvent poll(rd_kafka_t *rk, rd_kafka_queue_t *rkqu) {
24-
auto event = rd_kafka_queue_poll(rkqu, -1 /* infinite timeout */);
25-
if (rd_kafka_event_error(event)) {
23+
static RdKafkaEvent poll(rd_kafka_queue_t *rkqu) {
24+
auto *event = rd_kafka_queue_poll(rkqu, -1 /* infinite timeout */);
25+
if (rd_kafka_event_error(event) != RD_KAFKA_RESP_ERR_NO_ERROR) {
2626
throw std::runtime_error(rd_kafka_event_error_string(event));
2727
}
2828
return RdKafkaEvent(event);
@@ -45,5 +45,5 @@ class RdKafkaEvent final {
4545
private:
4646
rd_kafka_event_t *event_;
4747

48-
RdKafkaEvent(rd_kafka_event_t *event) : event_(event) {}
48+
explicit RdKafkaEvent(rd_kafka_event_t *event) : event_(event) {}
4949
};

include/snctl-cpp/subcommand.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222

2323
class SubCommand {
2424
public:
25-
SubCommand(const std::string &name) : name_(name), handle_(name) {}
25+
explicit SubCommand(const std::string &name) : name_(name), handle_(name) {}
2626

27-
bool used_by_parent(argparse::ArgumentParser &parent) const noexcept {
27+
bool used_by_parent(argparse::ArgumentParser &parent) const {
2828
return parent.is_subcommand_used(handle_);
2929
}
3030

include/snctl-cpp/topics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
class Topics : public SubCommand {
2828
public:
29-
Topics(argparse::ArgumentParser &parent) : SubCommand("topics") {
29+
explicit Topics(argparse::ArgumentParser &parent) : SubCommand("topics") {
3030
create_command_.add_description("Create a topic");
3131
create_command_.add_argument("topic").help("Topic to create").required();
3232
create_command_.add_argument("-p")

include/snctl-cpp/topics/create_topic.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
inline void create_topic(rd_kafka_t *rk, rd_kafka_queue_t *rkqu,
2929
const std::string &topic, int num_partitions) {
3030
std::array<char, 512> errstr;
31-
auto rk_topic = rd_kafka_NewTopic_new(topic.c_str(), num_partitions, 1,
32-
errstr.data(), errstr.size());
31+
auto *rk_topic = rd_kafka_NewTopic_new(topic.c_str(), num_partitions, 1,
32+
errstr.data(), errstr.size());
3333
if (rk_topic == nullptr) {
3434
throw std::runtime_error("Failed to create topic: " +
3535
std::string(errstr.data()));
@@ -39,7 +39,7 @@ inline void create_topic(rd_kafka_t *rk, rd_kafka_queue_t *rkqu,
3939
rd_kafka_CreateTopics(rk, &rk_topic, 1, nullptr, rkqu);
4040

4141
try {
42-
RdKafkaEvent::poll(rk, rkqu);
42+
RdKafkaEvent::poll(rkqu);
4343
std::cout << R"(Created topic ")" << topic << R"(" with )" << num_partitions
4444
<< " partition" << (num_partitions == 1 ? "" : "s") << std::endl;
4545
} catch (const std::runtime_error &e) {

include/snctl-cpp/topics/delete_topic.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,21 @@
2626

2727
inline void delete_topic(rd_kafka_t *rk, rd_kafka_queue_t *rkqu,
2828
const std::string &topic) {
29-
auto rk_topic = rd_kafka_DeleteTopic_new(topic.c_str());
29+
auto *rk_topic = rd_kafka_DeleteTopic_new(topic.c_str());
3030
GUARD(rk_topic, rd_kafka_DeleteTopic_destroy);
3131

3232
rd_kafka_DeleteTopics(rk, &rk_topic, 1, nullptr, rkqu);
3333

3434
try {
35-
auto event = RdKafkaEvent::poll(rk, rkqu);
36-
auto result = rd_kafka_event_DeleteTopics_result(event.handle());
35+
auto event = RdKafkaEvent::poll(rkqu);
36+
const auto *result = rd_kafka_event_DeleteTopics_result(event.handle());
3737
size_t cntp;
38-
auto topics = rd_kafka_DeleteTopics_result_topics(result, &cntp);
38+
const auto *topics = rd_kafka_DeleteTopics_result_topics(result, &cntp);
3939
if (cntp != 1) {
4040
throw std::runtime_error("DeleteTopics response has " +
4141
std::to_string(cntp) + " topics");
4242
}
43-
if (auto error = rd_kafka_topic_result_error_string(topics[0]);
43+
if (const char *error = rd_kafka_topic_result_error_string(topics[0]);
4444
error == nullptr) {
4545
std::cout << R"(Deleted topic ")" << topic << R"(")" << std::endl;
4646
} else {

include/snctl-cpp/topics/describe_topic.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,36 +25,37 @@
2525
inline void describe_topic(rd_kafka_t *rk, rd_kafka_queue_t *rkqu,
2626
const std::string &topic) {
2727
const char *topics[] = {topic.c_str()};
28-
auto topic_names = rd_kafka_TopicCollection_of_topic_names(topics, 1);
28+
auto *topic_names = rd_kafka_TopicCollection_of_topic_names(topics, 1);
2929
GUARD(topic_names, rd_kafka_TopicCollection_destroy);
3030

3131
rd_kafka_DescribeTopics(rk, topic_names, nullptr, rkqu);
3232

3333
try {
34-
auto event = RdKafkaEvent::poll(rk, rkqu);
35-
auto result = rd_kafka_event_DescribeTopics_result(event.handle());
34+
auto event = RdKafkaEvent::poll(rkqu);
35+
const auto *result = rd_kafka_event_DescribeTopics_result(event.handle());
3636
size_t result_topics_cnt;
37-
auto result_topics =
37+
auto *result_topics =
3838
rd_kafka_DescribeTopics_result_topics(result, &result_topics_cnt);
3939
for (size_t i = 0; i < result_topics_cnt; i++) {
40-
auto result_topic = result_topics[i];
41-
auto topic_name = rd_kafka_TopicDescription_name(result_topic);
42-
auto error = rd_kafka_TopicDescription_error(result_topic);
43-
if (rd_kafka_error_code(error)) {
40+
const auto *result_topic = result_topics[i];
41+
const char *topic_name = rd_kafka_TopicDescription_name(result_topic);
42+
const auto *error = rd_kafka_TopicDescription_error(result_topic);
43+
if (rd_kafka_error_code(error) != RD_KAFKA_RESP_ERR_NO_ERROR) {
4444
std::cout << "Topic: " << topic_name
4545
<< " has error: " << rd_kafka_error_string(error) << "\n";
4646
continue;
4747
}
4848

4949
size_t partition_cnt;
50-
auto partitions =
50+
auto *partitions =
5151
rd_kafka_TopicDescription_partitions(result_topic, &partition_cnt);
5252
for (size_t i = 0; i < partition_cnt; i++) {
53-
auto result_partition = partitions[i];
53+
const auto *result_partition = partitions[i];
5454
auto id = rd_kafka_TopicPartitionInfo_partition(result_partition);
55-
auto leader = rd_kafka_TopicPartitionInfo_leader(result_partition);
56-
if (leader) {
57-
std::cout << "Partition[" << i << "] "
55+
const auto *leader =
56+
rd_kafka_TopicPartitionInfo_leader(result_partition);
57+
if (leader != nullptr) {
58+
std::cout << "Partition[" << id << "] "
5859
<< R"(leader: {"id": )" << rd_kafka_Node_id(leader)
5960
<< R"(, url: ")" << rd_kafka_Node_host(leader) << ':'
6061
<< rd_kafka_Node_port(leader) << R"("})" << std::endl;

0 commit comments

Comments
 (0)