runWithReporter method

  1. @override
void runWithReporter(
  1. SaropaDiagnosticReporter reporter,
  2. SaropaContext context
)
override

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,
) {
  // Check for gql() function calls with string literals
  context.addMethodInvocation((MethodInvocation node) {
    final String methodName = node.methodName.name;

    // Check for gql() or parseString() calls (common GraphQL parsing functions)
    if (methodName != 'gql' && methodName != 'parseString') return;

    // Check if the argument is a string literal
    final NodeList<Expression> args = node.argumentList.arguments;
    if (args.isEmpty) return;

    final Expression firstArg = args.first;
    if (firstArg is NamedExpression) {
      // Skip named arguments
      return;
    }

    // Check if it's a string literal (simple, multiline, or adjacent)
    if (_isStringLiteral(firstArg)) {
      reporter.atNode(node);
    }
  });

  // Also check for InstanceCreationExpression with document parameter
  context.addInstanceCreationExpression((InstanceCreationExpression node) {
    final String typeName = node.constructorName.type.name.lexeme;

    // Check for common GraphQL options classes
    if (typeName != 'QueryOptions' &&
        typeName != 'MutationOptions' &&
        typeName != 'SubscriptionOptions' &&
        typeName != 'WatchQueryOptions') {
      return;
    }

    // Check for document parameter with gql() call
    for (final Expression arg in node.argumentList.arguments) {
      if (arg is NamedExpression && arg.name.label.name == 'document') {
        final Expression value = arg.expression;
        if (value is MethodInvocation) {
          final String methodName = value.methodName.name;
          if (methodName == 'gql' || methodName == 'parseString') {
            // Check if gql() has a string literal
            final NodeList<Expression> gqlArgs = value.argumentList.arguments;
            if (gqlArgs.isNotEmpty && _isStringLiteral(gqlArgs.first)) {
              reporter.atNode(arg);
            }
          }
        }
      }
    }
  });
}