in doc-architect/doc-architect-core/src/main/java/com/docarchitect/core/scanner/impl/dotnet/AspNetCoreApiScanner.java [291:388]
protected boolean shouldScanFile(Path file) {
// Priority 1: Filename convention (fastest check, no I/O)
String fileName = file.getFileName().toString();
if (fileName.endsWith("Controller.cs") ||
fileName.endsWith("Resource.cs") ||
fileName.endsWith("Api.cs") ||
fileName.contains("Controller") ||
fileName.contains("Api") ||
// Razor Pages typically use *Model.cs or *.cshtml.cs
(fileName.endsWith("Model.cs") && !fileName.contains("ViewModel")) ||
fileName.endsWith(".cshtml.cs") ||
// Minimal APIs often in Program.cs or *Endpoints.cs
fileName.equals("Program.cs") ||
fileName.endsWith("Endpoints.cs")) {
log.trace("Including file by naming convention: {}", fileName);
return true;
}
// Skip test files unless they contain ASP.NET patterns
String filePath = file.toString();
boolean isTestFile = filePath.contains("/test/") || filePath.contains("\\test\\") ||
filePath.contains(".test.") || filePath.contains(".Test.");
try {
String content = readFileContent(file);
// Priority 2: Check for ASP.NET Core imports (expanded)
boolean hasAspNetMvcImport =
(content.contains("Microsoft.AspNetCore") && content.contains("Mvc")) ||
(content.contains("using") && content.contains("AspNetCore") && content.contains("Mvc"));
boolean hasAspNetBuilderImport =
content.contains("Microsoft.AspNetCore.Builder") ||
(content.contains("using") && content.contains("AspNetCore") && content.contains("Builder"));
boolean hasAspNetRazorImport =
content.contains("Microsoft.AspNetCore.Mvc.RazorPages") ||
(content.contains("using") && content.contains("RazorPages"));
// Priority 3: Check for HTTP method attributes
boolean hasHttpMethodAttributes =
content.contains("[HttpGet") ||
content.contains("[HttpPost") ||
content.contains("[HttpPut") ||
content.contains("[HttpDelete") ||
content.contains("[HttpPatch");
// Priority 4: Check for controller attributes
boolean hasControllerAttributes =
content.contains("[ApiController]") ||
content.contains("[Route(") ||
content.contains("[Route \"");
// Priority 5: Check for controller base classes
boolean hasControllerBase =
(content.contains("ControllerBase") || content.contains(": Controller")) &&
(hasAspNetMvcImport || hasHttpMethodAttributes);
// Priority 6: Check for Minimal API patterns (ASP.NET Core 6+)
boolean hasMinimalApiPatterns =
content.contains("app.Map") ||
content.contains(".MapGet(") ||
content.contains(".MapPost(") ||
content.contains(".MapPut(") ||
content.contains(".MapDelete(") ||
content.contains(".MapPatch(");
// Priority 7: Check for Razor Pages patterns
boolean hasRazorPagePatterns =
content.contains(": PageModel") ||
content.contains("OnGet(") ||
content.contains("OnPost(") ||
content.contains("OnPut(") ||
content.contains("OnDelete(");
boolean hasAspNetPatterns = hasAspNetMvcImport || hasAspNetBuilderImport || hasAspNetRazorImport ||
hasHttpMethodAttributes || hasControllerAttributes || hasControllerBase ||
hasMinimalApiPatterns || hasRazorPagePatterns;
if (hasAspNetPatterns) {
log.debug("Including file with ASP.NET Core patterns: {} (mvcImport={}, builderImport={}, razorImport={}, httpAttrs={}, ctrlAttrs={}, ctrlBase={}, minimalApi={}, razorPages={})",
fileName, hasAspNetMvcImport, hasAspNetBuilderImport, hasAspNetRazorImport, hasHttpMethodAttributes,
hasControllerAttributes, hasControllerBase, hasMinimalApiPatterns, hasRazorPagePatterns);
} else {
log.trace("Skipping file without ASP.NET Core patterns: {}", fileName);
}
// For test files, require ASP.NET patterns
if (isTestFile) {
return hasAspNetPatterns;
}
return hasAspNetPatterns;
} catch (IOException e) {
log.debug("Failed to read file for pre-filtering: {}", file);
return false;
}
}