private Map executeScanners()

in doc-architect/doc-architect-cli/src/main/java/com/docarchitect/cli/ScanCommand.java [201:288]


    private Map<String, ScanResult> executeScanners(List<Scanner> scanners, ProjectConfig config) {
        log.debug("Executing scanners on project: {}", projectPath);

        // Determine scanner selection mode
        ProjectConfig.ScannerMode mode = config.scanners() != null
            ? config.scanners().getEffectiveMode()
            : ProjectConfig.ScannerMode.AUTO;

        log.info("Scanner selection mode: {}", mode);
        System.out.println("Scanner mode: " + mode);

        // Validate config and warn about unknown scanner IDs (EXPLICIT mode only)
        if (mode == ProjectConfig.ScannerMode.EXPLICIT) {
            validateScannerConfig(scanners, config);
        }

        Map<String, ScanResult> results = new LinkedHashMap<>();
        ScanContext context = createScanContext(results);

        int disabledByConfigCount = 0;
        int notApplicableCount = 0;

        for (Scanner scanner : scanners) {
            try {
                // Step 1: Check if scanner passes mode-based filtering
                boolean enabledByMode = isScannerEnabledByMode(scanner.getId(), mode, config);
                if (!enabledByMode) {
                    log.debug("Scanner {} disabled by {} mode", scanner.getId(), mode);
                    disabledByConfigCount++;
                    continue;
                }

                // Step 2: Check if scanner applies to this project (applicability strategy)
                boolean applies = scanner.appliesTo(context);
                if (applies) {
                    log.info("Running scanner: {} ({})", scanner.getDisplayName(), scanner.getId());
                    System.out.println("  → " + scanner.getDisplayName());

                    ScanResult result = scanner.scan(context);
                    results.put(scanner.getId(), result);

                    if (result.hasFindings()) {
                        log.debug("Scanner {} found: {} components, {} dependencies, {} endpoints, {} entities",
                            scanner.getId(),
                            result.components().size(),
                            result.dependencies().size(),
                            result.apiEndpoints().size(),
                            result.dataEntities().size());
                    }
                } else {
                    log.debug("Scanner {} does not apply to this project (applicability check failed)", scanner.getId());
                    if (log.isTraceEnabled()) {
                        log.trace("Scanner {} applicability details:", scanner.getId());
                        log.trace("  - Supported file patterns: {}", scanner.getSupportedFilePatterns());
                        log.trace("  - Has applicability strategy: {}", scanner.getApplicabilityStrategy() != null);
                        log.trace("  - Previous scan results available: {}", !context.previousResults().isEmpty());
                    }
                    notApplicableCount++;
                }
            } catch (Exception e) {
                log.error("Scanner {} failed: {}", scanner.getId(), e.getMessage(), e);
                results.put(scanner.getId(), ScanResult.failed(scanner.getId(), List.of(e.getMessage())));
            }
        }

        log.info("Scanner execution summary: {} executed, {} disabled by config, {} not applicable",
            results.size(), disabledByConfigCount, notApplicableCount);

        // Warn if no scanners executed
        if (results.isEmpty()) {
            System.err.println();
            System.err.println("⚠ WARNING: 0 scanners executed!");
            System.err.println("  Possible causes:");
            if (mode == ProjectConfig.ScannerMode.EXPLICIT) {
                System.err.println("  - Scanner IDs in config don't match available scanners");
            } else if (mode == ProjectConfig.ScannerMode.GROUPS) {
                System.err.println("  - No scanners match the configured groups");
            }
            System.err.println("  - No files match scanner patterns (applicability check)");
            System.err.println("  - All scanners failed");
            System.err.println();
            System.err.println("  Available scanner IDs:");
            scanners.forEach(s -> System.err.println("    - " + s.getId()));
            System.err.println();
        }

        return results;
    }