runWithReporter method
Override this method to implement your lint rule.
Use context to register callbacks for AST node types:
context.addMethodInvocation((node) {
if (condition) {
reporter.atNode(node);
}
});
Implementation
@override
void runWithReporter(
SaropaDiagnosticReporter reporter,
SaropaContext context,
) {
context.addInstanceCreationExpression((InstanceCreationExpression node) {
final String typeName = node.constructorName.type.name.lexeme;
// Check for WebView widgets
if (typeName != 'WebView' &&
typeName != 'WebViewWidget' &&
typeName != 'InAppWebView') {
return;
}
final String nodeSource = node.toSource();
// Check for data URL with HTML content
if (!nodeSource.contains('data:text/html') &&
!nodeSource.contains('loadHtml') &&
!nodeSource.contains('loadData')) {
return;
}
// Check if content has interpolation (user content)
if (nodeSource.contains(r'$')) {
// Check for escaping/sanitization
if (nodeSource.contains('htmlEscape') ||
nodeSource.contains('sanitize') ||
nodeSource.contains('escape') ||
nodeSource.contains('HtmlUnescape')) {
return; // Has escaping
}
reporter.atNode(node);
}
});
// Also check for direct loadHtml calls
context.addMethodInvocation((MethodInvocation node) {
final String methodName = node.methodName.name;
if (methodName != 'loadHtml' &&
methodName != 'loadHtmlString' &&
methodName != 'loadData') {
return;
}
final String nodeSource = node.toSource();
// Check for interpolation without escaping
if (nodeSource.contains(r'$') &&
!nodeSource.contains('htmlEscape') &&
!nodeSource.contains('sanitize') &&
!nodeSource.contains('escape')) {
reporter.atNode(node);
}
});
}