diff --git a/.clang-tidy b/.clang-tidy index 2d21feb..7c03a92 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,27 +1,27 @@ Checks: - readability-* - - modernize-* - - performance-* - - bugprone-unchecked-optional-access - - bugprone-sizeof-expression - - bugprone-suspicious-missing-comma - - bugprone-suspicious-index - - bugprone-undefined-memory-manipulation - - bugprone-use-after-move - - bugprone-out-of-bound-access +# - modernize-* +# - performance-* +# - bugprone-unchecked-optional-access +# - bugprone-sizeof-expression +# - bugprone-suspicious-missing-comma +# - bugprone-suspicious-index +# - bugprone-undefined-memory-manipulation +# - bugprone-use-after-move +# - bugprone-out-of-bound-access - -readability-identifier-length - -readability-magic-numbers - - -bugprone-narrowing-conversions - - -performance-enum-size - - -performance-inefficient-string-concatenation - - -bugprone-integer-division - - -bugprone-easily-swappable-parameters - - -modernize-avoid-c-arrays,-warnings-as-errors +# - -bugprone-narrowing-conversions +# - -performance-enum-size +# - -performance-inefficient-string-concatenation +# - -bugprone-integer-division +# - -bugprone-easily-swappable-parameters +# - -modernize-avoid-c-arrays,-warnings-as-errors WarningsAsErrors: '*' # Solo incluir archivos de tu código fuente (external tiene su propio .clang-tidy) # Excluye jail_audio.hpp del análisis -HeaderFilterRegex: '^source/(?!core/audio/jail_audio\.hpp).*' +# HeaderFilterRegex: '^source/(?!core/audio/jail_audio\.hpp).*' FormatStyle: file CheckOptions: diff --git a/CMakeLists.txt b/CMakeLists.txt index 877859c..d95210f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,7 @@ set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAK # --- STATIC ANALYSIS TARGETS --- # Buscar herramientas de análisis estático find_program(CLANG_FORMAT_EXE NAMES clang-format) +find_program(CLANG_TIDY_EXE NAMES clang-tidy) # Recopilar todos los archivos fuente para formateo file(GLOB_RECURSE ALL_SOURCE_FILES @@ -127,3 +128,27 @@ if(CLANG_FORMAT_EXE) else() message(STATUS "clang-format no encontrado - targets 'format' y 'format-check' no disponibles") endif() + +# Targets de clang-tidy +if(CLANG_TIDY_EXE) + add_custom_target(tidy + COMMAND ${CLANG_TIDY_EXE} + -p ${CMAKE_BINARY_DIR} + --fix + --fix-errors + ${ALL_SOURCE_FILES} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "Running clang-tidy with auto-fix..." + ) + + add_custom_target(tidy-check + COMMAND ${CLANG_TIDY_EXE} + -p ${CMAKE_BINARY_DIR} + --warnings-as-errors='*' + ${ALL_SOURCE_FILES} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "Checking clang-tidy..." + ) +else() + message(STATUS "clang-tidy no encontrado - targets 'tidy' y 'tidy-check' no disponibles") +endif() diff --git a/source/core/graphics/shape_loader.cpp b/source/core/graphics/shape_loader.cpp index 52edb09..5dbcb8e 100644 --- a/source/core/graphics/shape_loader.cpp +++ b/source/core/graphics/shape_loader.cpp @@ -11,9 +11,9 @@ namespace Graphics { // Inicialització de variables estàtiques std::unordered_map> ShapeLoader::cache_; -std::string ShapeLoader::base_path_ = "data/shapes/"; +std::string ShapeLoader::base_path = "data/shapes/"; -std::shared_ptr ShapeLoader::load(const std::string& filename) { +static std::shared_ptr ShapeLoader::load(const std::string& filename) { // Check cache first auto it = cache_.find(filename); if (it != cache_.end()) { @@ -66,9 +66,9 @@ void ShapeLoader::clear_cache() { cache_.clear(); } -size_t ShapeLoader::get_cache_size() { return cache_.size(); } +size_t ShapeLoader::getCacheSize() { return cache_.size(); } -std::string ShapeLoader::resolve_path(const std::string& filename) { +static std::string ShapeLoader::resolvePath(const std::string& filename) { // Si és un path absolut (comença amb '/'), usar-lo directament if (!filename.empty() && filename[0] == '/') { return filename; diff --git a/tools/linter/com_usar_clang-tidy.txt b/tools/linter/com_usar_clang-tidy.txt deleted file mode 100644 index 349450f..0000000 --- a/tools/linter/com_usar_clang-tidy.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Per a un fitxer, desde l'arrel del projecte executar: -clang-tidy source/fitxer.cpp -p build/ --fix - -# Per a varios fitxers, desde l'arrel: -find source/ \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) | \ -xargs -P4 -I{} bash -c 'echo "Procesando: {}"; clang-tidy {} -p build/ --fix' - - diff --git a/tools/linter/cppcheck_suppressions b/tools/linter/cppcheck_suppressions deleted file mode 100644 index 83863b3..0000000 --- a/tools/linter/cppcheck_suppressions +++ /dev/null @@ -1,2 +0,0 @@ -*:/home/sergio/gitea/jaildoctors_dilemma/source/external/* -*:/usr/include/* \ No newline at end of file diff --git a/tools/linter/generate_compile_commands_json.sh b/tools/linter/generate_compile_commands_json.sh deleted file mode 100755 index 53fdeee..0000000 --- a/tools/linter/generate_compile_commands_json.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# 🏁 Auto-detectar ruta base del proyecto -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" - -# 📁 Ruta al build -BUILD_DIR="$PROJECT_ROOT/build" - -# 📄 Archivo de mapping personalizado -MAPPING_FILE="$SCRIPT_DIR/sdl3_mapping.imp" - -# 📦 Generar compile_commands.json -echo "🔧 Generando compile_commands.json..." -cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -S "$PROJECT_ROOT" -B "$BUILD_DIR" - diff --git a/tools/linter/iwyu_tool.py b/tools/linter/iwyu_tool.py deleted file mode 100644 index 8aa4c7b..0000000 --- a/tools/linter/iwyu_tool.py +++ /dev/null @@ -1,553 +0,0 @@ -#!/usr/bin/env python3 - -##===--- iwyu_tool.py -----------------------------------------------------===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -""" Driver to consume a Clang compilation database and invoke IWYU. - -Example usage with CMake: - - # Unix systems - $ mkdir build && cd build - $ CC="clang" CXX="clang++" cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ... - $ iwyu_tool.py -p . - - # Windows systems - $ mkdir build && cd build - $ cmake -DCMAKE_CXX_COMPILER="%VCINSTALLDIR%/bin/cl.exe" \ - -DCMAKE_C_COMPILER="%VCINSTALLDIR%/VC/bin/cl.exe" \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -G Ninja ... - $ python3 iwyu_tool.py -p . - -See iwyu_tool.py -h for more details on command-line arguments. -""" -from __future__ import print_function -import os -import re -import sys -import json -import time -import shlex -import shutil -import argparse -import tempfile -import subprocess - - -CORRECT_RE = re.compile(r'^\((.*?) has correct #includes/fwd-decls\)$') -SHOULD_ADD_RE = re.compile(r'^(.*?) should add these lines:$') -ADD_RE = re.compile('^(.*?) +// (.*)$') -SHOULD_REMOVE_RE = re.compile(r'^(.*?) should remove these lines:$') -FULL_LIST_RE = re.compile(r'The full include-list for (.*?):$') -END_RE = re.compile(r'^---$') -LINES_RE = re.compile(r'^- (.*?) // lines ([0-9]+)-[0-9]+$') - - -GENERAL, ADD, REMOVE, LIST = range(4) - - -def clang_formatter(output, style): - """ Process iwyu's output into something clang-like. """ - formatted = [] - - state = (GENERAL, None) - for line in output.splitlines(): - match = CORRECT_RE.match(line) - if match: - # See PR#1806 for more info - continue - match = SHOULD_ADD_RE.match(line) - if match: - state = (ADD, match.group(1)) - continue - match = SHOULD_REMOVE_RE.match(line) - if match: - state = (REMOVE, match.group(1)) - continue - match = FULL_LIST_RE.match(line) - if match: - state = (LIST, match.group(1)) - elif END_RE.match(line): - state = (GENERAL, None) - elif not line.strip(): - continue - elif state[0] == GENERAL: - formatted.append(line) - elif state[0] == ADD: - match = ADD_RE.match(line) - if match: - formatted.append("%s:1:1: %s: add '%s' (%s)" % - (state[1], - style, - match.group(1), - match.group(2))) - else: - formatted.append("%s:1:1: %s: add '%s'" % - (state[1], style, line)) - elif state[0] == REMOVE: - match = LINES_RE.match(line) - line_no = match.group(2) if match else '1' - formatted.append("%s:%s:1: %s: superfluous '%s'" % - (state[1], line_no, style, match.group(1))) - - return os.linesep.join(formatted) - - -DEFAULT_FORMAT = 'iwyu' -FORMATTERS = { - 'iwyu': lambda output: output, - 'clang': lambda output: clang_formatter(output, style="error"), - 'clang-warning': lambda output: clang_formatter(output, style="warning"), -} - - -if sys.platform.startswith('win'): - # Case-insensitive match on Windows - def normcase(s): - return s.lower() -else: - def normcase(s): - return s - - -def is_subpath_of(path, parent): - """ Return True if path is equal to or fully contained within parent. - - Assumes both paths are canonicalized with os.path.realpath. - """ - parent = normcase(parent) - path = normcase(path) - - if path == parent: - return True - - if not path.startswith(parent): - return False - - # Now we know parent is a prefix of path, but they only share lineage if the - # difference between them starts with a path separator, e.g. /a/b/c/file - # is not a parent of /a/b/c/file.cpp, but /a/b/c and /a/b/c/ are. - parent = parent.rstrip(os.path.sep) - suffix = path[len(parent):] - return suffix.startswith(os.path.sep) - - -def is_msvc_driver(compile_command): - """ Return True if compile_command matches an MSVC CL-style driver. """ - compile_command = normcase(compile_command) - - if compile_command.endswith('cl.exe'): - # Native MSVC compiler or clang-cl.exe - return True - - if compile_command.endswith('clang-cl'): - # Cross clang-cl on non-Windows - return True - - return False - - -def win_split(cmdline): - """ Minimal implementation of shlex.split for Windows following - https://msdn.microsoft.com/en-us/library/windows/desktop/17w5ykft.aspx. - """ - def split_iter(cmdline): - in_quotes = False - backslashes = 0 - arg = '' - for c in cmdline: - if c == '\\': - # MSDN: Backslashes are interpreted literally, unless they - # immediately precede a double quotation mark. - # Buffer them until we know what comes next. - backslashes += 1 - elif c == '"': - # Quotes can either be an escaped quote or the start of a quoted - # string. Paraphrasing MSDN: - # Before quotes, place one backslash in the arg for every pair - # of leading backslashes. If the number of backslashes is odd, - # retain the double quotation mark, otherwise interpret it as a - # string delimiter and switch state. - arg += '\\' * (backslashes // 2) - if backslashes % 2 == 1: - arg += c - else: - in_quotes = not in_quotes - backslashes = 0 - elif c in (' ', '\t') and not in_quotes: - # MSDN: Arguments are delimited by white space, which is either - # a space or a tab [but only outside of a string]. - # Flush any buffered backslashes and yield arg, unless empty. - arg += '\\' * backslashes - if arg: - yield arg - arg = '' - backslashes = 0 - else: - # Flush buffered backslashes and append. - arg += '\\' * backslashes - arg += c - backslashes = 0 - - if arg: - arg += '\\' * backslashes - yield arg - - return list(split_iter(cmdline)) - - -def split_command(cmdstr): - """ Split a command string into a list, respecting shell quoting. """ - if sys.platform.startswith('win'): - # shlex.split does not work for Windows command-lines, so special-case - # to our own implementation. - cmd = win_split(cmdstr) - else: - cmd = shlex.split(cmdstr) - - return cmd - - -def find_include_what_you_use(): - """ Find IWYU executable and return its full pathname. """ - env_iwyu_path = os.environ.get('IWYU_BINARY') - if env_iwyu_path: - return os.path.realpath(env_iwyu_path) - - # Search in same dir as this script. - iwyu_path = shutil.which('include-what-you-use', - path=os.path.dirname(__file__)) - if iwyu_path: - return os.path.realpath(iwyu_path) - - # Search the system PATH. - iwyu_path = shutil.which('include-what-you-use') - if iwyu_path: - return os.path.realpath(iwyu_path) - - return None - - -IWYU_EXECUTABLE = find_include_what_you_use() - - -class Process(object): - """ Manages an IWYU process in flight """ - def __init__(self, proc, outfile): - self.proc = proc - self.outfile = outfile - self.output = None - - def poll(self): - """ Return the exit code if the process has completed, None otherwise. - """ - return self.proc.poll() - - @property - def returncode(self): - return self.proc.returncode - - def get_output(self): - """ Return stdout+stderr output of the process. - - This call blocks until the process is complete, then returns the output. - """ - if not self.output: - self.proc.wait() - self.outfile.seek(0) - self.output = self.outfile.read().decode("utf-8") - self.outfile.close() - - return self.output - - @classmethod - def start(cls, invocation): - """ Start a Process for the invocation and capture stdout+stderr. """ - outfile = tempfile.TemporaryFile(prefix='iwyu') - process = subprocess.Popen( - invocation.command, - cwd=invocation.cwd, - stdout=outfile, - stderr=subprocess.STDOUT) - return cls(process, outfile) - - -KNOWN_COMPILER_WRAPPERS=frozenset([ - "ccache" -]) - - -class Invocation(object): - """ Holds arguments of an IWYU invocation. """ - def __init__(self, command, cwd): - self.command = command - self.cwd = cwd - - def __str__(self): - return ' '.join(self.command) - - @classmethod - def from_compile_command(cls, entry, extra_args): - """ Parse a JSON compilation database entry into new Invocation. """ - if 'arguments' in entry: - # arguments is a command-line in list form. - command = entry['arguments'] - elif 'command' in entry: - # command is a command-line in string form, split to list. - command = split_command(entry['command']) - else: - raise ValueError('Invalid compilation database entry: %s' % entry) - - if command[0] in KNOWN_COMPILER_WRAPPERS: - # Remove the compiler wrapper from the command. - command = command[1:] - - # Rewrite the compile command for IWYU - compile_command, compile_args = command[0], command[1:] - if is_msvc_driver(compile_command): - # If the compiler is cl-compatible, let IWYU be cl-compatible. - extra_args = ['--driver-mode=cl'] + extra_args - - command = [IWYU_EXECUTABLE] + extra_args + compile_args - return cls(command, entry['directory']) - - def start(self, verbose): - """ Run invocation and collect output. """ - if verbose: - print('# %s' % self, file=sys.stderr) - - return Process.start(self) - - -def fixup_compilation_db(compilation_db): - """ Canonicalize paths in JSON compilation database. """ - for entry in compilation_db: - # Convert relative paths to absolute ones if possible, based on the entry's directory. - if 'directory' in entry and not os.path.isabs(entry['file']): - entry['file'] = os.path.join(entry['directory'], entry['file']) - - # Expand relative paths and symlinks - entry['file'] = os.path.realpath(entry['file']) - - return compilation_db - - -def select_compilation_db(compilation_db, selection): - """ Return a new compilation database reduced to the paths in selection. """ - if not selection: - return compilation_db - - # Canonicalize selection paths to match compilation database. - selection = [os.path.realpath(p) for p in selection] - - new_db = [] - for path in selection: - if not os.path.exists(path): - print('warning: \'%s\' not found on disk.' % path, file=sys.stderr) - continue - - found = [e for e in compilation_db if is_subpath_of(e['file'], path)] - if not found: - print('warning: \'%s\' not found in compilation database.' % path, - file=sys.stderr) - continue - - new_db.extend(found) - - return new_db - -def slice_compilation_db(compilation_db, selection, exclude): - """ Return a new compilation database with filtered entries. """ - - new_db = select_compilation_db(compilation_db, selection) - - # Canonicalize selection paths to match compilation database. - exclude = [os.path.realpath(p) for p in exclude] - - for path in exclude: - if not os.path.exists(path): - print('warning: excluded path \'%s\' not found on disk.' % path, - file=sys.stderr) - continue - - new_db = [e for e in new_db if not is_subpath_of(e['file'], path)] - - return new_db - - -def worst_exit_code(worst, cur): - """Return the most extreme exit code of two. - - Negative exit codes occur if the program exits due to a signal (Unix) or - structured exception (Windows). If we've seen a negative one before, keep - it, as it usually indicates a critical error. - - Otherwise return the biggest positive exit code. - """ - if cur < 0: - # Negative results take precedence, return the minimum - return min(worst, cur) - elif worst < 0: - # We know cur is non-negative, negative worst must be minimum - return worst - else: - # We know neither are negative, return the maximum - return max(worst, cur) - - -def execute(invocations, verbose, formatter, jobs, max_load_average=0): - """ Launch processes described by invocations. """ - exit_code = 0 - if jobs == 1: - for invocation in invocations: - proc = invocation.start(verbose) - print(formatter(proc.get_output())) - exit_code = worst_exit_code(exit_code, proc.returncode) - return exit_code - - pending = [] - while invocations or pending: - # Collect completed IWYU processes and print results. - complete = [proc for proc in pending if proc.poll() is not None] - for proc in complete: - pending.remove(proc) - print(formatter(proc.get_output())) - exit_code = worst_exit_code(exit_code, proc.returncode) - - # Schedule new processes if there's room. - capacity = jobs - len(pending) - - if max_load_average > 0: - one_min_load_average, _, _ = os.getloadavg() - load_capacity = max_load_average - one_min_load_average - if load_capacity < 0: - load_capacity = 0 - if load_capacity < capacity: - capacity = int(load_capacity) - if not capacity and not pending: - # Ensure there is at least one job running. - capacity = 1 - - pending.extend(i.start(verbose) for i in invocations[:capacity]) - invocations = invocations[capacity:] - - # Yield CPU. - time.sleep(0.0001) - return exit_code - - -def main(compilation_db_path, source_files, exclude, verbose, formatter, jobs, - max_load_average, extra_args): - """ Entry point. """ - - if not IWYU_EXECUTABLE: - print('error: include-what-you-use executable not found', - file=sys.stderr) - return 1 - - try: - if os.path.isdir(compilation_db_path): - compilation_db_path = os.path.join(compilation_db_path, - 'compile_commands.json') - - # Read compilation db from disk. - compilation_db_path = os.path.realpath(compilation_db_path) - with open(compilation_db_path, 'r') as fileobj: - compilation_db = json.load(fileobj) - except IOError as why: - print('error: failed to parse compilation database: %s' % why, - file=sys.stderr) - return 1 - - compilation_db = fixup_compilation_db(compilation_db) - compilation_db = slice_compilation_db(compilation_db, source_files, exclude) - - # Transform compilation db entries into a list of IWYU invocations. - invocations = [ - Invocation.from_compile_command(e, extra_args) for e in compilation_db - ] - - return execute(invocations, verbose, formatter, jobs, max_load_average) - - -def _bootstrap(sys_argv): - """ Parse arguments and dispatch to main(). """ - - # This hackery is necessary to add the forwarded IWYU args to the - # usage and help strings. - def customize_usage(parser): - """ Rewrite the parser's format_usage. """ - original_format_usage = parser.format_usage - parser.format_usage = lambda: original_format_usage().rstrip() + \ - ' -- []' + os.linesep - - def customize_help(parser): - """ Rewrite the parser's format_help. """ - original_format_help = parser.format_help - - def custom_help(): - """ Customized help string, calls the adjusted format_usage. """ - helpmsg = original_format_help() - helplines = helpmsg.splitlines() - helplines[0] = parser.format_usage().rstrip() - return os.linesep.join(helplines) + os.linesep - - parser.format_help = custom_help - - # Parse arguments. - parser = argparse.ArgumentParser( - description='Include-what-you-use compilation database driver.', - epilog='Assumes include-what-you-use is available on the PATH.') - customize_usage(parser) - customize_help(parser) - - parser.add_argument('-v', '--verbose', action='store_true', - help='Print IWYU commands') - parser.add_argument('-o', '--output-format', type=str, - choices=FORMATTERS.keys(), default=DEFAULT_FORMAT, - help='Output format (default: %s)' % DEFAULT_FORMAT) - parser.add_argument('-j', '--jobs', type=int, default=1, - nargs='?', const=0, - help=('Number of concurrent subprocesses. If zero, ' - 'will try to match the logical cores of the ' - 'system.')) - parser.add_argument('-l', '--load', type=float, default=0, - help=('Do not start new jobs if the 1min load average ' - 'is greater than the provided value')) - parser.add_argument('-p', metavar='', required=True, - help='Compilation database path', dest='dbpath') - parser.add_argument('-e', '--exclude', action='append', default=[], - help=('Do not run IWYU on source files (or directories) ' - 'below this path.')) - parser.add_argument('source', nargs='*', - help=('Zero or more source files (or directories) to ' - 'run IWYU on. Defaults to all in compilation ' - 'database.')) - - def partition_args(argv): - """ Split around '--' into driver args and IWYU args. """ - try: - double_dash = argv.index('--') - return argv[:double_dash], argv[double_dash+1:] - except ValueError: - return argv, [] - argv, extra_args = partition_args(sys_argv[1:]) - args = parser.parse_args(argv) - - jobs = args.jobs - if jobs == 0: - jobs = os.cpu_count() or 1 - - return main(args.dbpath, args.source, args.exclude, args.verbose, - FORMATTERS[args.output_format], jobs, args.load, extra_args) - - -if __name__ == '__main__': - sys.exit(_bootstrap(sys.argv)) diff --git a/tools/linter/run_clang-tidy.sh b/tools/linter/run_clang-tidy.sh deleted file mode 100755 index e68799d..0000000 --- a/tools/linter/run_clang-tidy.sh +++ /dev/null @@ -1,147 +0,0 @@ -#!/bin/bash - -# Script para ejecutar clang-tidy recursivamente en todo el código fuente -# Uso: -# ./run_clang-tidy.sh [--fix] [--help] [archivos...] -# --fix: Aplica las correcciones automáticamente (opcional) -# --help: Muestra la ayuda -# archivos: Archivos específicos a analizar (opcional, si no se especifica analiza todos) - -# Función de ayuda -show_help() { - cat << EOF -Uso: ./run_clang-tidy.sh [OPCIONES] [ARCHIVOS...] - -Script para ejecutar clang-tidy en el código fuente del proyecto. - -OPCIONES: - --fix Aplica las correcciones automáticamente - --help Muestra este mensaje de ayuda - -ARCHIVOS: - Si no se especifican archivos, se analizan todos los archivos del proyecto - (excluyendo la carpeta external/ y jail_audio.hpp). Si se especifican archivos, - solo se analizan esos archivos específicos. - -EJEMPLOS: - # Analizar todo el proyecto - ./run_clang-tidy.sh - - # Analizar todo el proyecto y aplicar correcciones - ./run_clang-tidy.sh --fix - - # Analizar un archivo específico - ./run_clang-tidy.sh source/game/entities/enemy.cpp - - # Analizar múltiples archivos - ./run_clang-tidy.sh source/game/entities/enemy.cpp source/game/entities/player.cpp - - # Analizar y corregir un archivo específico - ./run_clang-tidy.sh --fix source/game/entities/enemy.cpp - - # Analizar todos los archivos de una carpeta (usando glob) - ./run_clang-tidy.sh source/game/entities/*.cpp - -NOTAS: - - Se requiere que el directorio build/ exista y contenga compile_commands.json - - Los archivos se procesan en paralelo (4 procesos) - - Solo se procesan archivos .cpp, .hpp y .h - - Las rutas pueden ser relativas o absolutas - -EOF - exit 0 -} - -# Auto-detectar la ubicación del script y calcular rutas del proyecto -SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) -PROJECT_DIR=$(cd "$SCRIPT_DIR/../.." && pwd) -SOURCE_DIR="$PROJECT_DIR/source" -BUILD_DIR="$PROJECT_DIR/build" - -# Parsear argumentos: separar --fix, --help de archivos -FIX_FLAG="" -FILES=() - -for arg in "$@"; do - if [[ "$arg" == "--fix" ]]; then - FIX_FLAG="--fix" - elif [[ "$arg" == "--help" || "$arg" == "-h" ]]; then - show_help - else - FILES+=("$arg") - fi -done - -# Mostrar modo -if [[ -n "$FIX_FLAG" ]]; then - echo "Modo: Aplicando correcciones automáticamente (--fix)" -else - echo "Modo: Solo análisis (sin --fix)" -fi -echo - -# Verificar que los directorios existen -if [[ ! -d "$SOURCE_DIR" ]]; then - echo "Error: El directorio source/ no existe en: $SOURCE_DIR" - exit 1 -fi - -if [[ ! -d "$BUILD_DIR" ]]; then - echo "Error: El directorio build/ no existe en: $BUILD_DIR" - echo "Ejecuta primero: cmake -B build && cmake --build build" - exit 1 -fi - -echo "Proyecto: $PROJECT_DIR" -echo "Fuentes: $SOURCE_DIR" -echo "Build: $BUILD_DIR" -echo - -# Si se especificaron archivos, procesarlos directamente -if [[ ${#FILES[@]} -gt 0 ]]; then - echo "=== Procesando ${#FILES[@]} archivo(s) específico(s) ===" - - # Validar y procesar cada archivo - VALID_FILES=() - for file in "${FILES[@]}"; do - # Convertir a ruta absoluta si es relativa - if [[ ! "$file" = /* ]]; then - file="$PROJECT_DIR/$file" - fi - - # Verificar que existe - if [[ ! -f "$file" ]]; then - echo "Advertencia: Archivo no encontrado: $file (omitiendo)" - continue - fi - - # Verificar extensión - if [[ "$file" =~ \.(cpp|hpp|h)$ ]]; then - VALID_FILES+=("$file") - else - echo "Advertencia: Archivo no es C++: $file (omitiendo)" - fi - done - - # Si no hay archivos válidos, salir - if [[ ${#VALID_FILES[@]} -eq 0 ]]; then - echo "Error: No hay archivos válidos para procesar" - exit 1 - fi - - echo - # Procesar archivos en paralelo - printf '%s\n' "${VALID_FILES[@]}" | \ - xargs -P4 -I{} bash -c 'echo "Procesando: {}"; clang-tidy {} -p '"$BUILD_DIR"' '"$FIX_FLAG" - - echo - echo "¡Proceso completado para ${#VALID_FILES[@]} archivo(s)!" -else - # Comportamiento original: procesar todos los archivos - echo "=== Escaneando recursivamente source/ (excluyendo external/ y jail_audio.hpp) ===" - find "$SOURCE_DIR" \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) -not -path "*/external/*" -not -path "*/core/audio/jail_audio.hpp" -print0 | \ - xargs -0 -P4 -I{} bash -c 'echo "Procesando: {}"; clang-tidy {} -p '"$BUILD_DIR"' '"$FIX_FLAG" - - echo - echo "¡Proceso completado para todos los archivos!" -fi diff --git a/tools/linter/run_cppcheck.sh b/tools/linter/run_cppcheck.sh deleted file mode 100755 index 36ca572..0000000 --- a/tools/linter/run_cppcheck.sh +++ /dev/null @@ -1,196 +0,0 @@ -#!/bin/bash - -# ============================================================================ -# CONFIGURACIÓN - Editar estas constantes para personalizar el script -# ============================================================================ - -# Detectar la ubicación del script y la raíz del proyecto -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" - -# Rutas del proyecto -DEFAULT_ANALYSIS_PATH="$PROJECT_ROOT/source" -INCLUDE_PATH="$PROJECT_ROOT/source" -SUPPRESSIONS_FILE="$SCRIPT_DIR/cppcheck_suppressions" -OUTPUT_DIR="$SCRIPT_DIR" -BUILD_DIR="$PROJECT_ROOT/build" -COMPILE_COMMANDS="$BUILD_DIR/compile_commands.json" - -# Parámetros de compilación comunes (fallback para análisis de archivos específicos) -CPPCHECK_STD="--std=c++20" - -# Calcular número de threads (cores - 1, mínimo 1) -THREADS=$(($(nproc) - 1)) -[[ $THREADS -lt 1 ]] && THREADS=1 - -# ============================================================================ - -# Función para asegurar que compile_commands.json existe -ensure_compile_commands() { - if [[ ! -f "$COMPILE_COMMANDS" ]]; then - echo "⚠ compile_commands.json no encontrado en $BUILD_DIR" - echo "Generando compile_commands.json con CMake..." - - # Crear directorio build si no existe - mkdir -p "$BUILD_DIR" - - # Ejecutar CMake para generar compile_commands.json - (cd "$BUILD_DIR" && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. > /dev/null 2>&1) - - if [[ ! -f "$COMPILE_COMMANDS" ]]; then - echo "❌ Error: No se pudo generar compile_commands.json" - echo "Por favor, ejecuta manualmente:" - echo " cd $BUILD_DIR && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .." - exit 1 - fi - - echo "✓ compile_commands.json generado exitosamente" - else - echo "✓ Usando compile_commands.json existente: $COMPILE_COMMANDS" - fi -} - -# Función para mostrar el uso del script -mostrar_uso() { - echo "Uso: $0 [OPCIÓN] [RUTA]" - echo "" - echo "Opciones de análisis:" - echo " -w, --warning Ejecutar cppcheck con warning, style, performance" - echo " -a, --all Ejecutar cppcheck con todas las opciones habilitadas" - echo " -u, --unused Ejecutar cppcheck para unusedFunction" - echo "" - echo "Opciones de ruta:" - echo " -p, --path Especificar ruta a analizar (default: PROJECT_ROOT/source)" - echo " [RUTA] Ruta como último argumento posicional" - echo "" - echo "Ejemplos:" - echo " $0 --warning" - echo " $0 -w --path ../src/" - echo " $0 --all /path/to/code/" - echo " $0 -u ../source/" -} - -# Inicializar las variables -opcion="" -ruta="$DEFAULT_ANALYSIS_PATH" - -# Procesar las opciones -while [[ $# -gt 0 ]]; do - case $1 in - -w|--warning) - opcion="warning" - shift - ;; - -a|--all) - opcion="all" - shift - ;; - -u|--unused) - opcion="unused" - shift - ;; - -p|--path) - if [[ -n "$2" && "$2" != -* ]]; then - ruta="$2" - shift 2 - else - echo "Error: --path requiere un argumento" - mostrar_uso - exit 1 - fi - ;; - -h|--help) - mostrar_uso - exit 0 - ;; - -*) - echo "Error: Opción desconocida: $1" - mostrar_uso - exit 1 - ;; - *) - # Argumento posicional (asumimos que es la ruta) - ruta="$1" - shift - ;; - esac -done - -# Verificar que se haya especificado una opción de análisis -if [[ -z "$opcion" ]]; then - echo "Error: Debe especificar una opción de análisis (-w, -a, o -u)" - mostrar_uso - exit 1 -fi - -# Ejecutar según la opción seleccionada -case $opcion in - warning) - ensure_compile_commands - if [[ "$ruta" == "$DEFAULT_ANALYSIS_PATH" ]]; then - echo "Ejecutando cppcheck con warning, style, performance en proyecto completo (usando $THREADS threads)" - cppcheck --force --enable=warning,style,performance \ - --check-level=exhaustive \ - -j$THREADS \ - --project="$COMPILE_COMMANDS" \ - --suppressions-list="$SUPPRESSIONS_FILE" \ - 2>"$OUTPUT_DIR/cppcheck-result-warning-style-performance.txt" - else - echo "Ejecutando cppcheck con warning, style, performance en: $ruta (usando $THREADS threads)" - cppcheck --force --enable=warning,style,performance $CPPCHECK_STD \ - --check-level=exhaustive \ - -j$THREADS \ - -I "$INCLUDE_PATH" \ - --suppressions-list="$SUPPRESSIONS_FILE" \ - "$ruta" \ - 2>"$OUTPUT_DIR/cppcheck-result-warning-style-performance.txt" - fi - echo "Resultados guardados en: $OUTPUT_DIR/cppcheck-result-warning-style-performance.txt" - ;; - all) - ensure_compile_commands - if [[ "$ruta" == "$DEFAULT_ANALYSIS_PATH" ]]; then - echo "Ejecutando cppcheck con todas las opciones en proyecto completo (usando $THREADS threads)" - cppcheck --force --enable=all \ - -j$THREADS \ - --project="$COMPILE_COMMANDS" \ - --suppress=missingIncludeSystem \ - --suppressions-list="$SUPPRESSIONS_FILE" \ - 2>"$OUTPUT_DIR/cppcheck-result-all.txt" - else - echo "Ejecutando cppcheck con todas las opciones en: $ruta (usando $THREADS threads)" - cppcheck --force --enable=all -I /usr/include -I "$INCLUDE_PATH" $CPPCHECK_STD \ - -j$THREADS \ - --suppress=missingIncludeSystem \ - --suppressions-list="$SUPPRESSIONS_FILE" \ - "$ruta" \ - 2>"$OUTPUT_DIR/cppcheck-result-all.txt" - fi - echo "Resultados guardados en: $OUTPUT_DIR/cppcheck-result-all.txt" - ;; - unused) - ensure_compile_commands - if [[ "$ruta" == "$DEFAULT_ANALYSIS_PATH" ]]; then - echo "Ejecutando cppcheck para unusedFunction en proyecto completo (usando $THREADS threads)" - cppcheck --enable=style \ - -j$THREADS \ - --project="$COMPILE_COMMANDS" \ - --suppressions-list="$SUPPRESSIONS_FILE" \ - 2>"$OUTPUT_DIR/cppcheck-result-unusedFunction.txt" - else - echo "Ejecutando cppcheck para unusedFunction en: $ruta (usando $THREADS threads)" - cppcheck --enable=style $CPPCHECK_STD \ - -j$THREADS \ - -I "$INCLUDE_PATH" \ - --suppressions-list="$SUPPRESSIONS_FILE" \ - "$ruta" \ - 2>"$OUTPUT_DIR/cppcheck-result-unusedFunction.txt" - fi - echo "Resultados guardados en: $OUTPUT_DIR/cppcheck-result-unusedFunction.txt" - ;; - *) - echo "Error: Opción inválida" - mostrar_uso - exit 1 - ;; -esac diff --git a/tools/linter/run_iwyu.sh b/tools/linter/run_iwyu.sh deleted file mode 100755 index b9fdb6d..0000000 --- a/tools/linter/run_iwyu.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# 🏁 Auto-detectar ruta base del proyecto -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" - -# 📁 Ruta al build -BUILD_DIR="$PROJECT_ROOT/build" - -# 📄 Archivo de mapping personalizado -MAPPING_FILE="$SCRIPT_DIR/sdl3_mapping.imp" - -# 📦 Generar compile_commands.json -echo "🔧 Generando compile_commands.json..." -cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -S "$PROJECT_ROOT" -B "$BUILD_DIR" - -# 🛠️ Ejecutar IWYU con fix_includes.py -echo "🚀 Ejecutando IWYU..." -./iwyu_tool.py -p "$BUILD_DIR" -- -Xiwyu --mapping_file="$MAPPING_FILE" -Xiwyu --verbose=3 \ -| fix_include --update_comments --reorder --nosafe_headers - -# 🧹 Reemplazar // for por // Para en líneas de #include -echo "✍️ Corrigiendo comentarios en includes..." -find "$PROJECT_ROOT" -type f \( -name "*.cpp" -o -name "*.h" \) -exec \ -sed -i '/^#include .*\/\/ for/s/\/\/ for/\/\/ Para/' {} + - -echo "✅ Script completado." diff --git a/tools/linter/run_iwyu_dry_run.sh b/tools/linter/run_iwyu_dry_run.sh deleted file mode 100755 index 4b0513f..0000000 --- a/tools/linter/run_iwyu_dry_run.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# 🏁 Auto-detectar ruta base del proyecto -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" - -# 📁 Ruta al build -BUILD_DIR="$PROJECT_ROOT/build" - -# 📄 Archivo de mapping personalizado -MAPPING_FILE="$SCRIPT_DIR/sdl3_mapping.imp" - -# 📦 Generar compile_commands.json -echo "🔧 Generando compile_commands.json..." -cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -S "$PROJECT_ROOT" -B "$BUILD_DIR" - -# 🛠️ Ejecutar IWYU con fix_includes.py -echo "🚀 Ejecutando IWYU..." -iwyu_tool.py -p "$BUILD_DIR" -- -Xiwyu --mapping_file="$MAPPING_FILE" -Xiwyu --verbose=3 \ -| python3 /usr/bin/fix_includes.py --update_comments --reorder --nosafe_headers --dry_run - -# 🧹 Reemplazar // for por // Para en líneas de #include -echo "✍️ Corrigiendo comentarios en includes..." -find "$PROJECT_ROOT" -type f \( -name "*.cpp" -o -name "*.h" \) -exec \ -sed -i '/^#include .*\/\/ for/s/\/\/ for/\/\/ Para/' {} + - -echo "✅ Script completado." diff --git a/tools/linter/run_valgrind.sh b/tools/linter/run_valgrind.sh deleted file mode 100755 index 863469c..0000000 --- a/tools/linter/run_valgrind.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# 🏁 Auto-detectar ruta base del proyecto -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" - -# 📦 Ejecutable (por defecto el del proyecto, o el pasado como argumento) -EXECUTABLE="${1:-$PROJECT_ROOT/build/pollo}" - -# 📄 Archivo de salida -OUTPUT_FILE="$SCRIPT_DIR/valgrind_out.txt" - -if [[ ! -x "$EXECUTABLE" ]]; then - echo "❌ Error: Ejecutable no encontrado o no es ejecutable: $EXECUTABLE" - echo "Uso: $0 [ruta_al_ejecutable]" - exit 1 -fi - -echo "🔍 Ejecutando valgrind en: $EXECUTABLE" -echo "📄 Salida en: $OUTPUT_FILE" - -valgrind --suppressions="$SCRIPT_DIR/valgrind_exceptions" \ - --leak-check=full \ - "$EXECUTABLE" \ - > "$OUTPUT_FILE" 2>&1 - -echo "✅ Valgrind completado. Revisa $OUTPUT_FILE" diff --git a/tools/linter/sdl3_mapping.imp b/tools/linter/sdl3_mapping.imp deleted file mode 100644 index 3e9b996..0000000 --- a/tools/linter/sdl3_mapping.imp +++ /dev/null @@ -1,57 +0,0 @@ -[ - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] }, - { "include": ["", "private", "", "public"] } -] diff --git a/tools/linter/valgrind_exceptions b/tools/linter/valgrind_exceptions deleted file mode 100644 index 88482a1..0000000 --- a/tools/linter/valgrind_exceptions +++ /dev/null @@ -1,12 +0,0 @@ -{ - ignore_unversioned_libs - Memcheck:Leak - ... - obj:*/lib*/lib*.so -} -{ - ignore_versioned_libs - Memcheck:Leak - ... - obj:*/lib*/lib*.so.* -}