Trong đợt kiểm tra mã, tôi tìm thấy mã nguồn như thế này:Tự động phát hiện std giống hệt nhau liên tiếp :: string :: tìm() gọi
void f_odd(std::string &className, std::string &testName)
{
if (className.find("::") != std::string::npos)
{
testName = className.substr(className.find("::") + 2);
(void)className.erase(className.find("::"), std::string::npos);
}
}
Trong chức năng này, std :: string :: tìm() được được gọi là ba lần với cùng một mẫu (ở đây "::").
Mã này tất nhiên có thể được refactored để
void f(std::string &className, std::string &testName)
{
const size_t endOfClassNamePos = className.find("::");
if (endOfClassNamePos != std::string::npos)
{
testName = className.substr(endOfClassNamePos + 2);
(void)className.erase(endOfClassNamePos, std::string::npos);
}
}
nơi tìm được gọi là chỉ một lần.
Câu hỏi
Không ai biết một chiến lược để phát hiện như một mô hình như thế này? Tôi đang có một cơ sở mã rất lớn, nơi tôi có ý định phát hiện ra mẫu hình này. Tôi định sử dụng môi trường Windows hoặc Linux.
chiến lược tiềm năng
- Sử dụng/thích ứng một công cụ phân tích mã tĩnh, giống như cppcheck để phát hiện các loại hợp kỳ dị.
- Tìm kiếm trong cơ sở mã với cụm từ thông dụng.
- Sử dụng/điều chỉnh clang-gọn gàng để phát hiện mẫu này.
- Viết trình kiểm tra tùy chỉnh bằng một số ngôn ngữ (ví dụ: Python) phát hiện những vấn đề này. Trong trường hợp này, việc kiểm tra phải được thực hiện trên mã được xử lý trước.
Không Go
- xét Manual
Cập nhật 1
tôi quyết định bắt đầu với chiến lược tiềm năng 1). Tôi có kế hoạch để thích ứng với cppcheck để nắm bắt vấn đề này.
Cppcheck cung cấp khả năng viết các quy tắc tùy chỉnh, dựa trên biểu thức thông thường PCRE. Đối với điều này, cppcheck phải được biên dịch với hỗ trợ PCRE được kích hoạt. Kể từ môi trường thử nghiệm hiện tại được dựa trên Linux, các lệnh sau đây có thể được sử dụng để tải về phiên bản mới nhất của cppcheck:
git clone https://github.com/danmar/cppcheck.git && cd cppcheck
Sau đó, biên dịch và cài đặt công cụ này như sau:
sudo make install HAVE_RULES=yes
Bây giờ, việc thiết lập công cụ cơ bản được thực hiện. Để phát triển một quy tắc cppcheck, tôi đã chuẩn bị một trường hợp thử nghiệm đơn giản (tệp: test.cpp), tương tự như mã mẫu trong phần đầu tiên của bài viết này. Tệp này chứa ba hàm và quy tắc cppcheck sẽ phát ra cảnh báo trên f_odd
và f_odd1
về các lệnh gọi std::string::find
giống hệt nhau liên tiếp.
kiểm tra.cpp:
#include <string>
void f(std::string &className, std::string &testName)
{
const size_t endOfClassNamePos = className.find("::");
if (endOfClassNamePos != std::string::npos)
{
testName = className.substr(endOfClassNamePos + 2);
(void)className.erase(endOfClassNamePos, std::string::npos);
}
}
void f_odd(std::string &className, std::string &testName)
{
if (className.find("::") != std::string::npos)
{
testName = className.substr(className.find("::") + 2);
(void)className.erase(className.find("::"), std::string::npos);
}
}
#define A "::"
#define B "::"
#define C "::"
void f_odd1(std::string &className, std::string &testName)
{
if (className.find(A) != std::string::npos)
{
testName = className.substr(className.find(B) + 2);
(void)className.erase(className.find(C), std::string::npos);
}
}
Cho đến nay rất tốt. Bây giờ cppcheck phải được tinh chỉnh để bắt các cuộc gọi std::string::find
giống hệt nhau liên tiếp. Đối với điều này tôi đã tạo ra một cppcheck_rule-file có chứa một biểu thức chính quy phù hợp với liên tiếp giống hệt std::string::find
cuộc gọi:
<?xml version="1.0"?>
<rule>
<tokenlist>normal</tokenlist>
<pattern><![CDATA[([a-zA-Z][a-zA-Z0-9]*)(\s*\.\s*find)(\s*\(\s*\"[ -~]*\"\s*\))[ -\{\n]*(\1\2\3)+[ -z\n]]]></pattern>
<message>
<severity>style</severity>
<summary>Found identical consecutive std::string::find calls.</summary>
</message>
Tập tin này có thể được sử dụng để mở rộng cppcheck về một tấm séc mới. Cho phép thử:
cppcheck --rule-file=rules/rule.xml test/test.cpp
và đầu ra là
Checking test/test.cpp...
[test/test.cpp:14]: (style) Found identical consecutive std::string::find calls.
[test/test.cpp:26]: (style) Found identical consecutive std::string::find calls.
Bây giờ, giống hệt nhau liên tiếp std::string::find
cuộc gọi có thể được phát hiện trong mã C/C++. Có ai biết một giải pháp tốt hơn/hiệu quả hơn hoặc thông minh hơn không?
Tài liệu tham khảo:
Bạn có thể viết [clang-tidy] của riêng bạn (http://clang.llvm.org/extra/clang-tidy/) kiểm tra để phát hiện điều này. – Jonas
@ Jonas Cảm ơn bạn clang-tidy là một công cụ mạnh khác có thể thực hiện công việc. Tôi sẽ cập nhật phần giải pháp tiềm năng của mình. – orbitcowboy
Bạn có thể đặt lại cụm từ cho câu hỏi của mình sao cho nó không xuất hiện như một yêu cầu đề xuất công cụ? Đây là [chủ đề không rõ ràng] (https://stackoverflow.com/help/on-topic) trên trang web này. – 5gon12eder