fccf
est un outil de ligne de commande qui recherche rapidement dans le code source C/C++ dans un répertoire en fonction d'une chaîne de recherche et imprime les extraits de code pertinents qui correspondent à la requête.
La vidéo suivante montre fccf
recherchant et trouvant des extraits de code dans torvalds/linux.
fccf
(Modern C++) La vidéo suivante montre fccf
recherchant le code source fccf
C++.
Notez que les résultats de recherche incluent ici :
--flag
qui correspond Fournissez une requête vide pour correspondre à n'importe quel --flag
, par exemple, n'importe quelle déclaration enum.
... ou n'importe quel constructeur de classe
for
Utilisez --for-statement
pour rechercher for
instructions. fccf
essaiera for
rechercher les instructions (y compris C++ ranged for
) qui contiennent la chaîne de requête.
Utilisez l'option --include-expressions
pour rechercher les expressions qui correspondent à la requête.
L'exemple suivant montre les appels fccf
find à isdigit()
.
L'exemple suivant montre que fccf
recherche des références à la variable clang_options
.
using
de déclarations Utilisez l'option --using-declaration
pour rechercher des déclarations using
, des directives using
et des déclarations d'alias de type.
namespace
Utilisez l'option --namespace-alias
pour rechercher les alias namespace
.
throw
Utilisez --throw-expression
avec une requête pour rechercher des expressions throw
spécifiques contenant la chaîne de requête.
Comme présenté précédemment, une requête vide tentera ici de correspondre à n'importe quelle expression throw
dans la base de code :
Construisez fccf
en utilisant CMake. Pour plus de détails, voir BUILDING.md.
REMARQUE : fccf
nécessite l'installation libclang
et 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
effectue une recherche récursive dans l'annuaire pour une aiguille dans une botte de foin - comme grep
ou ripgrep
- Il utilise un algorithme SIMD strstr
SSE2
(recherche SIMD Rabin-Karp modifiée ; voir ici) si possible pour trouver rapidement, dans plusieurs threads, un sous-ensemble du fichiers source dans le répertoire qui contiennent une aiguille.libclang
pour analyser l'unité de traduction (construire un arbre de syntaxe abstraite).CXCursor_FunctionDecl
pour les déclarations de fonctions.libclang
du nœud) correspond à la requête de recherche, alors la plage source du nœud AST est identifiée - la plage source est l'index de début et de fin de l'extrait de code dans le tamponinclude_directories
Pour que tout cela fonctionne, fccf identifie d'abord les répertoires candidats qui contiennent des fichiers d'en-tête, par exemple les chemins qui se terminent par include/
. Il ajoute ensuite ces chemins aux options clang (avant d'analyser l'unité de traduction) comme -Ifoo -Ibar/baz
etc. De plus, pour chaque unité de traduction, les chemins parent et grand-parent sont également ajoutés aux répertoires d'inclusion de cette unité afin de augmenter la probabilité d’une analyse réussie.
Des répertoires d'inclusion supplémentaires peuvent également être fournis à fccf
en utilisant l'option -I
ou --include-dir
. En utilisant une sortie détaillée ( --verbose
), les erreurs dans l'analyse de libclang peuvent être identifiées et des correctifs peuvent être tentés (par exemple, en ajoutant les bons répertoires d'inclusion pour que libclang
soit satisfait).
Pour exécuter fccf
sur le code source fccf
sans aucune erreur libclang, j'ai dû fournir explicitement le chemin d'inclusion de LLVM-12 comme ceci :
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);
}