///|
fn document_scan_config(policy : RomanLintPolicy) -> ScanConfig {
{
parse_config: policy.parse_config,
retain_rejected: policy.retain_rejected_candidates,
include_single_symbol: policy.include_single_symbol,
max_candidate_length: policy.max_candidate_length,
}
}
///|
fn scan_rejection_diagnostic(
rejection : RomanScanRejection,
policy : RomanLintPolicy,
) -> RomanDiagnostic {
match rejection.reason {
SingleSymbolExcluded =>
{
code: SingleSymbolExcludedCode,
severity: DiagnosticWarning,
message: diagnostic_message(SingleSymbolExcludedCode),
span: rejection.span,
replacement: None,
}
CandidateTooLong(_) =>
{
code: CandidateTooLongCode,
severity: DiagnosticError,
message: diagnostic_message(CandidateTooLongCode),
span: rejection.span,
replacement: None,
}
CandidateParseFailed(error) =>
shift_roman_diagnostic(
diagnostic_from_report_error(
rejection.source_text,
analysis_content_span(rejection.source_text, policy.parse_config),
error,
),
rejection.span.start,
)
}
}
///|
fn append_global_lint_diagnostics(
target : Array[RomanDiagnostic],
lint : RomanLintReport,
offset : Int,
) -> Unit {
for diagnostic in lint.diagnostics {
target.push(shift_roman_diagnostic(diagnostic, offset))
}
}
///|
/// Lint scanner candidates and return document-global diagnostics.
pub fn lint_roman_document(
text : String,
policy : RomanLintPolicy,
) -> Result[RomanDocumentLintReport, ConfigError] {
match validate_lint_policy(policy) {
Err(error) => return Err(error)
Ok(_) => ()
}
let scan = match scan_roman_text(text, document_scan_config(policy)) {
Ok(report) => report
Err(error) => return Err(error)
}
let candidates : Array[RomanDocumentLintCandidate] = []
let rejected_candidates : Array[RomanDocumentRejectedCandidate] = []
let diagnostics : Array[RomanDiagnostic] = []
for matched in scan.matches {
let lint = match lint_roman(matched.source_text, policy) {
Ok(report) => report
Err(error) => return Err(error)
}
append_global_lint_diagnostics(diagnostics, lint, matched.span.start)
candidates.push({
span: matched.span,
source_text: matched.source_text,
lint,
})
}
for rejection in scan.rejections {
let diagnostic = scan_rejection_diagnostic(rejection, policy)
diagnostics.push(diagnostic)
rejected_candidates.push({
span: rejection.span,
source_text: rejection.source_text,
reason: rejection.reason,
diagnostic,
})
}
let sorted_diagnostics = sort_document_diagnostics(diagnostics)
let counts = count_diagnostic_severity(sorted_diagnostics)
Ok({
original: text,
policy,
candidates,
rejected_candidates,
diagnostics: sorted_diagnostics,
candidates_examined: scan.candidates_examined,
error_count: counts.0,
warning_count: counts.1,
conforms: sorted_diagnostics.length() == 0,
})
}