check method

  1. @override
void check(
  1. DcqRegistry registry
)

Implementation

@override
void check(
  DcqRegistry registry,
) {
  registry.addClassDeclaration((node) {
    final superclass = node.extendsClause?.superclass;
    if (superclass == null) return;
    if (superclass.name.lexeme != 'State') return;

    final classBody = node.body;
    if (classBody is! BlockClassBody) return;
    final disposableFields = <String, VariableDeclaration>{};
    MethodDeclaration? disposeMethod;

    for (final member in classBody.members) {
      if (member is FieldDeclaration) {
        if (member.isStatic) continue;
        final typeName = member.fields.type?.beginToken.lexeme;
        if (typeName == null) continue;
        if (!_isDisposableType(typeName)) continue;
        if ((configStringList(ruleConfig, 'ignored-instances') ?? const [])
            .contains(typeName)) {
          continue;
        }
        for (final variable in member.fields.variables) {
          final initializer = variable.initializer;
          if (initializer is MethodInvocation &&
              (configStringList(ruleConfig, 'ignored-invocations') ??
                      const [])
                  .contains(initializer.methodName.name)) {
            continue;
          }
          disposableFields[variable.name.lexeme] = variable;
        }
      } else if (member is MethodDeclaration &&
          member.name.lexeme == 'dispose') {
        disposeMethod = member;
      }
    }

    if (disposableFields.isEmpty) return;

    final disposedNames = <String>{};
    if (disposeMethod != null) {
      final visitor = _DisposalCallVisitor();
      disposeMethod.accept(visitor);
      disposedNames.addAll(visitor.disposedNames);
    }

    for (final entry in disposableFields.entries) {
      if (!disposedNames.contains(entry.key)) {
        reportAtToken(entry.value.name);
      }
    }
  });
}