visitInstanceCreationExpression method

  1. @override
void visitInstanceCreationExpression(
  1. InstanceCreationExpression node
)
override

Implementation

@override
void visitInstanceCreationExpression(InstanceCreationExpression node) {
  final typeName = node.constructorName.type.name.lexeme;

  if (typeName == 'ChangeNotifierProvider') {
    String? providedClass;
    int? childOffset;
    int? childLength;
    for (final arg in node.argumentList.arguments) {
      if (arg is NamedExpression) {
        if (arg.name.label.name == 'create') {
          if (arg.expression is FunctionExpression) {
            final func = arg.expression as FunctionExpression;
            final body = func.body;
            if (body is ExpressionFunctionBody) {
              if (body.expression is InstanceCreationExpression) {
                providedClass =
                    (body.expression as InstanceCreationExpression)
                        .constructorName
                        .type
                        .name
                        .lexeme;
              }
            }
          }
        } else if (arg.name.label.name == 'child') {
          childOffset = arg.expression.offset;
          childLength = arg.expression.length;
        }
      }
    }
    nodes.add(
      ProviderDeclarationNode(
        providerType: typeName,
        providedClass: providedClass ?? 'Unknown',
        childOffset: childOffset,
        childLength: childLength,
        filePath: filePath,
        offset: node.offset,
        length: node.length,
      ),
    );
  } else if (typeName == 'Consumer') {
    final typeArgs = node.constructorName.type.typeArguments;
    if (typeArgs != null && typeArgs.arguments.isNotEmpty) {
      final consumedType = typeArgs.arguments.first.beginToken.lexeme;
      int? builderOffset;
      int? builderLength;
      int? childOffset;
      int? childLength;

      for (final arg in node.argumentList.arguments) {
        if (arg is! NamedExpression) continue;
        if (arg.name.label.name == 'builder') {
          builderOffset = arg.expression.offset;
          builderLength = arg.expression.length;
        } else if (arg.name.label.name == 'child') {
          childOffset = arg.expression.offset;
          childLength = arg.expression.length;
        }
      }

      nodes.add(
        ConsumerNode(
          consumedClass: consumedType,
          builderOffset: builderOffset,
          builderLength: builderLength,
          childOffset: childOffset,
          childLength: childLength,
          filePath: filePath,
          offset: node.offset,
          length: node.length,
        ),
      );
    }
  } else if (typeName == 'MultiProvider') {
    int? childOffset;
    int? childLength;
    for (final arg in node.argumentList.arguments) {
      if (arg is NamedExpression && arg.name.label.name == 'child') {
        childOffset = arg.expression.offset;
        childLength = arg.expression.length;
      }
    }
    nodes.add(
      MultiProviderNode(
        childOffset: childOffset,
        childLength: childLength,
        filePath: filePath,
        offset: node.offset,
        length: node.length,
      ),
    );
  } else if (typeName == 'Selector') {
    final typeArgs = node.constructorName.type.typeArguments;
    if (typeArgs != null && typeArgs.arguments.length >= 2) {
      final consumedType = typeArgs.arguments[0].beginToken.lexeme;
      final selectedType = typeArgs.arguments[1].beginToken.lexeme;
      String selectorSnippet = '(state) => state';
      int? builderOffset;
      int? builderLength;
      int? childOffset;
      int? childLength;
      for (final arg in node.argumentList.arguments) {
        if (arg is! NamedExpression) continue;
        if (arg.name.label.name == 'selector') {
          selectorSnippet = arg.expression.toSource();
        } else if (arg.name.label.name == 'builder') {
          builderOffset = arg.expression.offset;
          builderLength = arg.expression.length;
        } else if (arg.name.label.name == 'child') {
          childOffset = arg.expression.offset;
          childLength = arg.expression.length;
        }
      }
      nodes.add(
        SelectorNode(
          consumedClass: consumedType,
          selectedType: selectedType,
          selectorSnippet: selectorSnippet,
          builderOffset: builderOffset,
          builderLength: builderLength,
          childOffset: childOffset,
          childLength: childLength,
          filePath: filePath,
          offset: node.offset,
          length: node.length,
        ),
      );
    }
  } else if (typeName == 'FutureProvider' || typeName == 'StreamProvider') {
    String providedType = 'Unknown';
    int? childOffset;
    int? childLength;
    final typeArgs = node.constructorName.type.typeArguments;
    if (typeArgs != null && typeArgs.arguments.isNotEmpty) {
      providedType = typeArgs.arguments.first.beginToken.lexeme;
    }
    for (final arg in node.argumentList.arguments) {
      if (arg is NamedExpression && arg.name.label.name == 'child') {
        childOffset = arg.expression.offset;
        childLength = arg.expression.length;
      }
    }
    nodes.add(
      AsyncProviderNode(
        providerType: typeName,
        providedType: providedType,
        childOffset: childOffset,
        childLength: childLength,
        filePath: filePath,
        offset: node.offset,
        length: node.length,
      ),
    );
  } else if (typeName == 'ProxyProvider' ||
      typeName == 'ChangeNotifierProxyProvider') {
    _handleProxyProvider(node, typeName);
  } else if (typeName == 'ValueListenableBuilder') {
    final typeArgs = node.constructorName.type.typeArguments;
    final valueType = (typeArgs != null && typeArgs.arguments.isNotEmpty)
        ? typeArgs.arguments.first.toSource()
        : 'dynamic';
    int? builderOffset;
    int? builderLength;
    for (final arg in node.argumentList.arguments) {
      if (arg is NamedExpression && arg.name.label.name == 'builder') {
        builderOffset = arg.expression.offset;
        builderLength = arg.expression.length;
      }
    }
    nodes.add(
      ConsumerNode(
        consumedClass: valueType,
        builderOffset: builderOffset,
        builderLength: builderLength,
        filePath: filePath,
        offset: node.offset,
        length: node.length,
      ),
    );
  }

  super.visitInstanceCreationExpression(node);
}