fccf
es una herramienta de línea de comandos que busca rápidamente en el código fuente C/C++ en un directorio basándose en una cadena de búsqueda e imprime fragmentos de código relevantes que coinciden con la consulta.
El siguiente vídeo muestra fccf
buscando y encontrando fragmentos de código en torvalds/linux.
fccf
(C++ moderno) El siguiente vídeo muestra fccf
buscando el código fuente fccf
C++.
Tenga en cuenta que los resultados de búsqueda aquí incluyen:
--flag
que coincida Proporcione una consulta vacía para que coincida con cualquier --flag
, por ejemplo, cualquier declaración de enumeración.
... o cualquier constructor de clase
for
Utilice --for-statement
para for
declaraciones. fccf
intentará buscar declaraciones for
(incluidas las de C++ con rango for
) que contengan la cadena de consulta.
Utilice la opción --include-expressions
para buscar expresiones que coincidan con la consulta.
El siguiente ejemplo muestra llamadas fccf
find a isdigit()
.
El siguiente ejemplo muestra cómo fccf
encuentra referencias a la variable clang_options
.
using
Utilice la opción --using-declaration
para buscar declaraciones using
, directivas using
y declaraciones de alias de tipo.
namespace
Utilice la opción --namespace-alias
para buscar alias namespace
.
throw
Utilice --throw-expression
con una consulta para buscar expresiones throw
específicas que contengan la cadena de consulta.
Como se presentó anteriormente, una consulta vacía aquí intentará hacer coincidir cualquier expresión throw
en la base del código:
Compile fccf
usando CMake. Para obtener más detalles, consulte BUILDING.md.
NOTA: fccf
requiere libclang
y LLVM
instalados.
# 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
realiza una búsqueda recursiva en el directorio de una aguja en un pajar, como grep
o ripgrep
. Utiliza un algoritmo SIMD strstr
SSE2
(búsqueda SIMD Rabin-Karp modificada; consulte aquí) si es posible para encontrar rápidamente, en varios subprocesos, un subconjunto del archivos fuente en el directorio que contiene una aguja.libclang
para analizar la unidad de traducción (construir un árbol de sintaxis abstracta).CXCursor_FunctionDecl
para declaraciones de funciones.libclang
para el nodo) coincide con la consulta de búsqueda, entonces se identifica el rango de origen del nodo AST; el rango de origen es el índice inicial y final del fragmento de código en el bufferinclude_directories
Para que todo esto funcione, fccf primero identifica los directorios candidatos que contienen archivos de encabezado, por ejemplo, rutas que terminan en include/
. Luego agrega estas rutas a las opciones de clang (antes de analizar la unidad de traducción) como -Ifoo -Ibar/baz
, etc. Además, para cada unidad de traducción, las rutas principal y principal también se agregan a los directorios de inclusión de esa unidad para poder aumentar la probabilidad de un análisis exitoso.
También se pueden proporcionar directorios de inclusión adicionales a fccf
usando la opción -I
o --include-dir
. Usando salida detallada ( --verbose
), se pueden identificar errores en el análisis de libclang y se pueden intentar corregirlos (por ejemplo, agregar los directorios de inclusión correctos para que libclang
esté satisfecho).
Para ejecutar fccf
en el código fuente fccf
sin errores de libclang, tuve que proporcionar explícitamente la ruta de inclusión desde LLVM-12 de esta manera:
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);
}