static RE_RESULT_HANDLING: std::sync::LazyLock<regex::Regex> = std::sync::LazyLock::new(|| {
regex::Regex::new(r"(?m)^\s*(match|if let)\s+.*Result\s*<.*>\s*\{")
.expect("Hardcoded regex pattern must be valid")
});
static RE_DATA_VALIDATION: std::sync::LazyLock<regex::Regex> = std::sync::LazyLock::new(|| {
regex::Regex::new(
r"(?m)if\s+.*\.(is_empty|len|contains|starts_with|ends_with)\(.*(\&\&|\|\||\.len\(\)\s*[<>=])",
)
.expect("Hardcoded regex pattern must be valid")
});
static RE_RESOURCE_MANAGEMENT: std::sync::LazyLock<regex::Regex> = std::sync::LazyLock::new(|| {
regex::Regex::new(r"(?m)\.(open|close|lock|unlock|acquire|release)\(\)")
.expect("Hardcoded regex pattern must be valid")
});
static RE_CONTROL_FLOW: std::sync::LazyLock<regex::Regex> = std::sync::LazyLock::new(|| {
regex::Regex::new(r"(?m)^\s*}\s*else\s+if\s+").expect("Hardcoded regex pattern must be valid")
});
static RE_DATA_TRANSFORMATION: std::sync::LazyLock<regex::Regex> = std::sync::LazyLock::new(|| {
regex::Regex::new(r"\.(map|filter|filter_map|flat_map|fold|reduce)\(")
.expect("Hardcoded regex pattern must be valid")
});
static RE_API_CALL: std::sync::LazyLock<regex::Regex> = std::sync::LazyLock::new(|| {
regex::Regex::new(r"(?m)(client\.|http\.|fetch\(|\.post\(|\.put\(|\.delete\()")
.expect("Hardcoded regex pattern must be valid")
});
impl PatternExtractor {
fn extract_with_threshold(
&self,
regex: ®ex::Regex,
file_path: &Path,
content: &str,
pattern_type: PatternType,
collection: &mut PatternCollection,
) {
let threshold = rust_threshold(pattern_type);
let matches: Vec<_> = regex.find_iter(content).collect();
if matches.len() >= threshold.min_matches_in_file {
self.group_by_structural_hash(
&matches,
content,
file_path,
pattern_type,
threshold.min_identical,
collection,
);
}
}
fn extract_error_handling_patterns(
&self,
file_path: &Path,
content: &str,
collection: &mut PatternCollection,
) -> Result<()> {
self.extract_with_threshold(
&RE_RESULT_HANDLING,
file_path,
content,
PatternType::ErrorHandling,
collection,
);
Ok(())
}
fn extract_data_validation_patterns(
&self,
file_path: &Path,
content: &str,
collection: &mut PatternCollection,
) -> Result<()> {
self.extract_with_threshold(
&RE_DATA_VALIDATION,
file_path,
content,
PatternType::DataValidation,
collection,
);
Ok(())
}
fn extract_resource_management_patterns(
&self,
file_path: &Path,
content: &str,
collection: &mut PatternCollection,
) -> Result<()> {
self.extract_with_threshold(
&RE_RESOURCE_MANAGEMENT,
file_path,
content,
PatternType::ResourceManagement,
collection,
);
Ok(())
}
fn extract_control_flow_patterns(
&self,
file_path: &Path,
content: &str,
collection: &mut PatternCollection,
) -> Result<()> {
self.extract_with_threshold(
&RE_CONTROL_FLOW,
file_path,
content,
PatternType::ControlFlow,
collection,
);
Ok(())
}
fn extract_data_transformation_patterns(
&self,
file_path: &Path,
content: &str,
collection: &mut PatternCollection,
) -> Result<()> {
self.extract_with_threshold(
&RE_DATA_TRANSFORMATION,
file_path,
content,
PatternType::DataTransformation,
collection,
);
Ok(())
}
fn extract_api_call_patterns(
&self,
file_path: &Path,
content: &str,
collection: &mut PatternCollection,
) -> Result<()> {
self.extract_with_threshold(
&RE_API_CALL,
file_path,
content,
PatternType::ApiCall,
collection,
);
Ok(())
}
}