fccf
เป็นเครื่องมือบรรทัดคำสั่งที่ค้นหาอย่างรวดเร็วผ่านซอร์สโค้ด C/C++ ในไดเร็กทอรีโดยอิงตามสตริงการค้นหา และพิมพ์ข้อมูลโค้ดที่เกี่ยวข้องซึ่งตรงกับคำค้นหา
วิดีโอต่อไปนี้แสดงการค้นหา fccf
และการค้นหาส่วนย่อยของโค้ดใน torvalds/linux
fccf
(Modern C ++) วิดีโอต่อไปนี้แสดง fccf
ค้นหาซอร์สโค้ด fccf
C++
โปรดทราบว่าผลการค้นหาที่นี่ประกอบด้วย:
--flag
ที่ตรงกัน ระบุข้อความค้นหาว่างเพื่อให้ตรงกับ --flag
เช่น การประกาศแจงนับใดๆ
... หรือตัวสร้างคลาสใด ๆ
for
สั่ง ใช้ --for-statement
เพื่อ for
คำสั่ง fccf
จะพยายาม for
คำสั่ง (รวมถึง C++ ranged for
) ที่มีสตริงการสืบค้น
ใช้ตัวเลือก --include-expressions
เพื่อค้นหานิพจน์ที่ตรงกับแบบสอบถาม
ตัวอย่างต่อไปนี้แสดง fccf
ค้นหาการเรียก isdigit()
ตัวอย่างต่อไปนี้แสดงการค้นหา fccf
การอ้างอิงถึงตัวแปร clang_options
using
การประกาศ ใช้ตัวเลือก --using-declaration
เพื่อค้นหา using
การประกาศ using
คำสั่ง และประเภทการประกาศนามแฝง
namespace
ใช้ตัวเลือก --namespace-alias
เพื่อค้นหานามแฝง namespace
throw
ใช้ --throw-expression
กับแบบสอบถามเพื่อค้นหานิพจน์ throw
เฉพาะที่มีสตริงการสืบค้น
ตามที่นำเสนอก่อนหน้านี้ แบบสอบถามที่ว่างเปล่าที่นี่จะพยายามจับคู่นิพจน์ throw
ใดๆ ในฐานโค้ด:
สร้าง fccf
โดยใช้ CMake ดูรายละเอียดเพิ่มเติมที่ BUILDING.md
หมายเหตุ: fccf
ต้องติดตั้ง libclang
และ LLVM
# Install libclang and LLVM
# sudo apt install libclang-dev llvm
git clone https://github.com/p-ranav/fccf
cd fccf
# Build
cmake -S . -B build -D CMAKE_BUILD_TYPE=Release
cmake --build build
# Install
sudo cmake --install build
fccf
foo@bar:~ $ fccf --help
Usage: fccf [--help] [--version] [--help] [--exact-match] [--json] [--filter VAR] [-j VAR] [--enum] [--struct] [--union] [--member-function] [--function] [--function-template] [-F] [--class] [--class-template] [--class-constructor] [--class-destructor] [-C] [--for-statement] [--namespace-alias] [--parameter-declaration] [--typedef] [--using-declaration] [--variable-declaration] [--verbose] [--include-expressions] [--static-cast] [--dynamic-cast] [--reinterpret-cast] [--const-cast] [-c] [--throw-expression] [--ignore-single-line-results] [--include-dir VAR]... [--language VAR] [--std VAR] [--no-color] query [path]...
Positional arguments:
query
path [nargs: 0 or more]
Optional arguments:
-h, --help shows help message and exits
-v, --version prints version information and exits
-h, --help Shows help message and exits
-E, --exact-match Only consider exact matches
--json Print results in JSON format
-f, --filter Only evaluate files that match filter pattern [nargs=0..1] [default: "*.*"]
-j Number of threads [nargs=0..1] [default: 5]
--enum Search for enum declaration
--struct Search for struct declaration
--union Search for union declaration
--member-function Search for class member function declaration
--function Search for function declaration
--function-template Search for function template declaration
-F Search for any function or function template or class member function
--class Search for class declaration
--class-template Search for class template declaration
--class-constructor Search for class constructor declaration
--class-destructor Search for class destructor declaration
-C Search for any class or class template or struct
--for-statement Search for `for` statement
--namespace-alias Search for namespace alias
--parameter-declaration Search for function or method parameter
--typedef Search for typedef declaration
--using-declaration Search for using declarations, using directives, and type alias declarations
--variable-declaration Search for variable declaration
--verbose Request verbose output
--ie, --include-expressions Search for expressions that refer to some value or member, e.g., function, variable, or enumerator.
--static-cast Search for static_cast
--dynamic-cast Search for dynamic_cast
--reinterpret-cast Search for reinterpret_cast
--const-cast Search for const_cast
-c Search for any static_cast, dynamic_cast, reinterpret_cast, orconst_cast expression
--throw-expression Search for throw expression
--isl, --ignore-single-line-results Ignore forward declarations, member function declarations, etc.
-I, --include-dir Additional include directories [nargs=0..1] [default: {}] [may be repeated]
-l, --language Language option used by clang [nargs=0..1] [default: "c++"]
--std C++ standard to be used by clang [nargs=0..1] [default: "c++17"]
--nc, --no-color Stops fccf from coloring the output
fccf
ทำการค้นหาไดเร็กทอรีแบบเรียกซ้ำสำหรับเข็มในกองหญ้า - เช่น grep
หรือ ripgrep
- มันใช้อัลกอริธึม SSE2
strstr
SIMD (แก้ไขการค้นหา Rabin-Karp SIMD; ดูที่นี่) หากเป็นไปได้เพื่อค้นหาอย่างรวดเร็วในหลายเธรด ชุดย่อยของ ไฟล์ต้นฉบับในไดเร็กทอรีที่มีเข็มlibclang
เพื่อแยกวิเคราะห์หน่วยการแปล (สร้างแผนผังไวยากรณ์นามธรรม)CXCursor_FunctionDecl
สำหรับการประกาศฟังก์ชันlibclang
สำหรับโหนด) ตรงกับข้อความค้นหา ช่วงแหล่งที่มาของโหนด AST จะถูกระบุ - ช่วงแหล่งที่มาคือดัชนีเริ่มต้นและสิ้นสุดของข้อมูลโค้ดใน บัฟเฟอร์include_directories
เพื่อให้ทั้งหมดนี้ใช้งานได้ ก่อนอื่น fccf จะระบุไดเร็กทอรีที่มีไฟล์ส่วนหัว เช่น พาธที่ลงท้ายด้วย include/
จากนั้นจะเพิ่มเส้นทางเหล่านี้ให้กับตัวเลือกเสียงดังกราว (ก่อนแยกวิเคราะห์หน่วยการแปล) เป็น -Ifoo -Ibar/baz
เป็นต้น นอกจากนี้ สำหรับแต่ละหน่วยการแปล เส้นทางพาเรนต์และพาเรนต์พาเรนต์จะถูกเพิ่มในไดเร็กทอรีรวมสำหรับหน่วยนั้นด้วยเพื่อที่จะ เพิ่มโอกาสในการแยกวิเคราะห์สำเร็จ
ไดเร็กทอรีรวมเพิ่มเติมสามารถจัดเตรียมให้กับ fccf
ได้โดยใช้อ็อพชัน -I
หรือ --include-dir
การใช้เอาต์พุตแบบ verbose ( --verbose
) จะทำให้สามารถระบุข้อผิดพลาดในการแยกวิเคราะห์ libclang และสามารถลองแก้ไขได้ (เช่น การเพิ่มไดเร็กทอรีรวมสิทธิ์เพื่อให้ libclang
มีความสุข)
หากต้องการรัน fccf
บนซอร์สโค้ด fccf
โดยไม่มีข้อผิดพลาด libclang ฉันต้องระบุเส้นทางรวมจาก LLVM-12 อย่างชัดเจนดังนี้:
foo@bar:~ $ fccf --verbose ' lexer ' . --include-dir /usr/lib/llvm-12/include/
Checking ./source/lexer.cpp
Checking ./source/lexer.hpp
Checking ./source/searcher.cpp
// ./source/lexer.hpp (Line: 14 to 40)
class lexer
{
std::string_view m_input;
fmt::memory_buffer* m_out;
std::size_t m_index {0};
bool m_is_stdout {true};
char previous() const;
char current() const;
char next() const;
void move_forward(std::size_t n = 1);
bool is_line_comment();
bool is_block_comment();
bool is_start_of_identifier();
bool is_start_of_string();
bool is_start_of_number();
void process_line_comment();
void process_block_comment();
bool process_identifier(bool maybe_class_or_struct = false);
void process_string();
std::size_t get_number_of_characters(std::string_view str);
public:
void tokenize_and_pretty_print(std::string_view source,
fmt::memory_buffer* out,
bool is_stdout = true);
}