createClassProperty static method

ClassProperty createClassProperty({
  1. required ClassPropertyName fieldName,
  2. ClassPropertyName? fieldAlias,
  3. required TypeNode fieldType,
  4. List<DirectiveNode>? fieldDirectives,
  5. required Context context,
  6. required void onNewClassFound(
    1. Context
    ),
  7. bool markAsUsed = true,
})

Core method to create a class property (extracted from main generator)

Implementation

static ClassProperty createClassProperty({
  required ClassPropertyName fieldName,
  ClassPropertyName? fieldAlias,
  required TypeNode fieldType,
  List<DirectiveNode>? fieldDirectives,
  required Context context,
  required void Function(Context) onNewClassFound,
  bool markAsUsed = true,
}) {
  // Handle __typename field
  if (fieldName.name == context.schemaMap.typeNameField) {
    return ClassProperty(
      type: TypeName(name: 'String'),
      name: fieldName,
      annotations: ['JsonKey(name: \'${context.schemaMap.typeNameField}\')'],
      isResolveType: true,
    );
  }

  final nextType = gql.getTypeByName(
    context.typeDefinitionNodeVisitor,
    fieldType,
  );

  final aliasedContext = context.withAlias(
    nextFieldName: fieldName,
    nextClassName: ClassName(name: nextType.name.value),
    alias: fieldAlias,
  );

  final nextClassName = aliasedContext.fullPathName();

  final dartTypeName = gql.buildTypeName(
    fieldType,
    context.options,
    replaceLeafWith: ClassName.fromPath(path: nextClassName),
    typeDefinitionNodeVisitor: context.typeDefinitionNodeVisitor,
  );

  logFn(
    context,
    aliasedContext.align + 1,
    '${aliasedContext.path}[${aliasedContext.currentType!.name.value}][${aliasedContext.currentClassName} ${aliasedContext.currentFieldName}] ${fieldAlias == null ? '' : '($fieldAlias) '}-> ${dartTypeName.namePrintable}',
  );

  // Handle complex types that need class generation
  if (nextType is ObjectTypeDefinitionNode ||
      nextType is UnionTypeDefinitionNode ||
      nextType is InterfaceTypeDefinitionNode) {
    onNewClassFound(
      aliasedContext.next(
        nextType: nextType,
        nextFieldName: fieldName,
        nextClassName: ClassName(name: nextType.name.value),
        alias: fieldAlias,
        ofUnion: Nullable<TypeDefinitionNode?>(null),
      ),
    );
  }

  final name = fieldAlias ?? fieldName;

  // Handle annotations
  final jsonKeyAnnotation = <String, String>{};
  if (name.namePrintable != name.name) {
    jsonKeyAnnotation['name'] = '\'${name.name}\'';
  }

  // Handle custom scalars
  if (nextType is ScalarTypeDefinitionNode) {
    final scalar = gql.getSingleScalarMap(
      context.options,
      nextType.name.value,
    );

    if (scalar?.customParserImport != null &&
        nextType.name.value == scalar?.graphQLType) {
      final graphqlTypeName = gql.buildTypeName(
        fieldType,
        context.options,
        dartType: false,
        typeDefinitionNodeVisitor: context.typeDefinitionNodeVisitor,
      );

      jsonKeyAnnotation['fromJson'] =
          'fromGraphQL${graphqlTypeName.parserSafe}ToDart${dartTypeName.parserSafe}';
      jsonKeyAnnotation['toJson'] =
          'fromDart${dartTypeName.parserSafe}ToGraphQL${graphqlTypeName.parserSafe}';
    }
  }
  // Handle enums
  else if (nextType is EnumTypeDefinitionNode) {
    if (markAsUsed) {
      context.usedEnums.add(EnumName(name: nextType.name.value));
    }

    if (context.schemaMap.convertEnumToString) {
      // If convertEnumToString is enabled, we'll return a String instead of an enum
      return EnumGenerator.handleEnumToStringConversion(
        fieldType: fieldType,
        dartTypeName: dartTypeName,
        name: name,
        jsonKeyAnnotation: jsonKeyAnnotation,
      );
    } else {
      // Original behavior when convertEnumToString is false
      EnumGenerator.addUnknownEnumValueAnnotation(
        fieldType: fieldType,
        dartTypeName: dartTypeName,
        jsonKeyAnnotation: jsonKeyAnnotation,
      );
    }
  }

  final annotations = <String>[];

  if (jsonKeyAnnotation.isNotEmpty) {
    // Create the JSON key annotation string with consistent ordering
    final orderedEntries = <String>[];
    if (jsonKeyAnnotation.containsKey('name')) {
      orderedEntries.add('name: ${jsonKeyAnnotation['name']}');
    }
    if (jsonKeyAnnotation.containsKey('unknownEnumValue')) {
      orderedEntries.add(
        'unknownEnumValue: ${jsonKeyAnnotation['unknownEnumValue']}',
      );
    }
    // Add any other entries
    for (final entry in jsonKeyAnnotation.entries) {
      if (entry.key != 'name' && entry.key != 'unknownEnumValue') {
        orderedEntries.add('${entry.key}: ${entry.value}');
      }
    }
    final jsonKey = orderedEntries.join(', ');
    annotations.add('JsonKey($jsonKey)');
  }
  annotations.addAll(proceedDeprecated(fieldDirectives));

  return ClassProperty(
    type: dartTypeName,
    name: name,
    annotations: annotations,
  );
}