fccf
是一个命令行工具,可以根据搜索字符串快速搜索目录中的 C/C++ 源代码,并打印与查询匹配的相关代码片段。
以下视频展示了fccf
在 torvalds/linux 中搜索和查找代码片段。
fccf
源代码树(现代 C++)以下视频显示了fccf
搜索fccf
C++ 源代码。
请注意,此处的搜索结果包括:
--flag
提供一个空查询来匹配任何--flag
,例如任何枚举声明。
...或任何类构造函数
for
语句使用--for-statement
for
语句。 fccf
将尝试查找包含查询字符串的for
语句(包括 C++ 范围内的for
)。
使用--include-expressions
选项查找与查询匹配的表达式。
以下示例显示了fccf
find 对isdigit()
调用。
以下示例显示fccf
查找对clang_options
变量的引用。
using
声明使用--using-declaration
选项查找using
声明、 using
指令和类型别名声明。
namespace
别名使用--namespace-alias
选项查找namespace
别名。
throw
表达式将--throw-expression
与查询一起使用可搜索包含查询字符串的特定throw
表达式。
如前所述,这里的空查询将尝试匹配代码库中的任何throw
表达式:
使用 CMake 构建fccf
。有关更多详细信息,请参阅 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/
结尾的路径。然后,它将这些路径添加到 clang 选项中(在解析翻译单元之前),如-Ifoo -Ibar/baz
等。此外,对于每个翻译单元,父路径和祖父路径也会添加到该单元的包含目录中,以便增加成功解析的可能性。
还可以使用-I
或--include-dir
选项向fccf
提供其他包含目录。使用详细输出( --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);
}