Compound? parseCompoundDeclaration()

in lib/src/header_parser/sub_parsers/compounddecl_parser.dart [74:187]


Compound? parseCompoundDeclaration(
  clang_types.CXCursor cursor,
  CompoundType compoundType, {

  /// Option to ignore declaration filter (Useful in case of extracting
  /// declarations when they are passed/returned by an included function.)
  bool ignoreFilter = false,

  /// To track if the declaration was used by reference(i.e T*). (Used to only
  /// generate these as opaque if `dependency-only` was set to opaque).
  bool pointerReference = false,
}) {
  _stack.push(_ParsedCompound());

  // Set includer functions according to compoundType.
  final bool Function(String, String) shouldIncludeDecl;
  final bool Function(String) isSeenDecl;
  final Compound? Function(String) getSeenDecl;
  final void Function(String, Compound) addDeclToSeen;
  final Declaration configDecl;
  final String className;
  switch (compoundType) {
    case CompoundType.struct:
      shouldIncludeDecl = shouldIncludeStruct;
      isSeenDecl = bindingsIndex.isSeenStruct;
      getSeenDecl = bindingsIndex.getSeenStruct;
      addDeclToSeen = bindingsIndex.addStructToSeen;
      configDecl = config.structDecl;
      className = 'Struct';
      break;
    case CompoundType.union:
      shouldIncludeDecl = shouldIncludeUnion;
      isSeenDecl = bindingsIndex.isSeenUnion;
      getSeenDecl = bindingsIndex.getSeenUnion;
      addDeclToSeen = bindingsIndex.addUnionToSeen;
      configDecl = config.unionDecl;
      className = 'Union';
      break;
  }

  // Parse the cursor definition instead, if this is a forward declaration.
  if (isForwardDeclaration(cursor)) {
    cursor = clang.clang_getCursorDefinition(cursor);
  }
  final declUsr = cursor.usr();
  final String declName;

  // Only set name using USR if the type is not Anonymous (A struct is anonymous
  // if it has no name, is not inside any typedef and declared inline inside
  // another declaration).
  if (clang.clang_Cursor_isAnonymous(cursor) == 0) {
    // This gives the significant name, i.e name of the struct if defined or
    // name of the first typedef declaration that refers to it.
    declName = declUsr.split('@').last;
  } else {
    // Empty names are treated as inline declarations.
    declName = '';
  }

  if (declName.isEmpty) {
    if (ignoreFilter) {
      // This declaration is defined inside some other declaration and hence
      // must be generated.
      _stack.top.compound = Compound.fromType(
        type: compoundType,
        name: incrementalNamer.name('Unnamed$className'),
        usr: declUsr,
        dartDoc: getCursorDocComment(cursor),
      );
      _setMembers(cursor, className);
    } else {
      _logger.finest('unnamed $className declaration');
    }
  } else if ((ignoreFilter || shouldIncludeDecl(declUsr, declName)) &&
      (!isSeenDecl(declUsr))) {
    _logger.fine(
        '++++ Adding $className: Name: $declName, ${cursor.completeStringRepr()}');
    _stack.top.compound = Compound.fromType(
      type: compoundType,
      usr: declUsr,
      originalName: declName,
      name: configDecl.renameUsingConfig(declName),
      dartDoc: getCursorDocComment(cursor),
    );
    // Adding to seen here to stop recursion if a declaration has itself as a
    // member, members are updated later.
    addDeclToSeen(declUsr, _stack.top.compound!);
  }

  if (isSeenDecl(declUsr)) {
    _stack.top.compound = getSeenDecl(declUsr);

    // Skip dependencies if already seen OR user has specified `dependency-only`
    // as opaque AND this is a pointer reference AND the declaration was not
    // included according to config (ignoreFilter).
    final skipDependencies = _stack.top.compound!.parsedDependencies ||
        (pointerReference &&
            ignoreFilter &&
            ((compoundType == CompoundType.struct &&
                    config.structDependencies == CompoundDependencies.opaque) ||
                (compoundType == CompoundType.union &&
                    config.unionDependencies == CompoundDependencies.opaque)));

    if (!skipDependencies) {
      // Prevents infinite recursion if struct has a pointer to itself.
      _stack.top.compound!.parsedDependencies = true;
      _setMembers(cursor, className);
    } else if (!_stack.top.compound!.parsedDependencies) {
      _logger.fine('Skipped dependencies.');
    }
  }

  return _stack.pop().compound;
}