in doc-architect/doc-architect-core/src/main/java/com/docarchitect/core/scanner/impl/ruby/RailsApiScanner.java [158:217]
public ScanResult scan(ScanContext context) {
log.info("Scanning Rails API endpoints in: {}", context.rootPath());
List<Component> components = new ArrayList<>();
List<ApiEndpoint> apiEndpoints = new ArrayList<>();
ScanStatistics.Builder statsBuilder = new ScanStatistics.Builder();
Path rootPath = context.rootPath();
// Find controller files
List<Path> controllerFiles = context.findFiles(PATTERN_RUBY_CONTROLLERS).toList();
statsBuilder.filesDiscovered(controllerFiles.size());
if (controllerFiles.isEmpty()) {
log.debug("No Rails controller files found");
return emptyResult();
}
int skippedFiles = 0;
// Parse each controller with three-tier fallback
for (Path controllerFile : controllerFiles) {
if (!shouldScanFile(controllerFile)) {
skippedFiles++;
continue;
}
statsBuilder.incrementFilesScanned();
// Use three-tier parsing with fallback
FileParseResult<ControllerData> result = parseWithFallback(
controllerFile,
classes -> extractControllerDataFromAST(classes, controllerFile, rootPath),
createFallbackStrategy(rootPath),
statsBuilder
);
if (result.isSuccess()) {
for (ControllerData data : result.getData()) {
components.add(data.component);
apiEndpoints.addAll(data.endpoints);
}
}
}
ScanStatistics statistics = statsBuilder.build();
log.info("Found {} Rails components and {} API endpoints (success rate: {:.1f}%, overall parse rate: {:.1f}%, skipped {} files)",
components.size(), apiEndpoints.size(), statistics.getSuccessRate(),
statistics.getOverallParseRate(), skippedFiles);
return buildSuccessResult(
components,
List.of(), // No dependencies
apiEndpoints,
List.of(), // No message flows
List.of(), // No data entities
List.of(), // No relationships
List.of(), // No warnings
statistics
);
}