collectSymbols function

List<SymbolInfo> collectSymbols(
  1. ASTRoot root
)

Walks root and returns every top-level and class-member declaration.

Implementation

List<SymbolInfo> collectSymbols(ASTRoot root) {
  final out = <SymbolInfo>[];

  // Top-level functions.
  for (final set in root.functions) {
    for (final f in set.functions) {
      out.add(
        _invocable(f, container: null, category: SymbolCategory.function),
      );
    }
  }

  // Classes / enums and their members.
  for (final clazz in root.classes) {
    final isEnum = clazz is ASTClassEnum;
    out.add(
      SymbolInfo(
        name: clazz.name,
        category: isEnum ? SymbolCategory.enumSym : SymbolCategory.classSym,
        signature: _classSignature(clazz),
        typeName: clazz.name,
        modifiers: clazz.isAbstract ? const ['abstract'] : const [],
      ),
    );

    for (final field in clazz.fields) {
      out.add(
        SymbolInfo(
          name: field.name,
          category: SymbolCategory.field,
          container: clazz.name,
          signature: '${_typeName(field.type)} ${field.name}',
          typeName: _typeName(field.type),
          modifiers: field.modifiers.modifiers,
        ),
      );
    }

    for (final set in clazz.constructors) {
      for (final c in set.functions) {
        out.add(
          _invocable(
            c,
            container: clazz.name,
            category: SymbolCategory.constructor,
          ),
        );
      }
    }

    for (final set in clazz.functions) {
      for (final m in set.functions) {
        out.add(
          _invocable(m, container: clazz.name, category: SymbolCategory.method),
        );
      }
    }

    for (final g in clazz.getter) {
      out.add(
        SymbolInfo(
          name: g.name,
          category: SymbolCategory.getter,
          container: clazz.name,
          signature: '${_typeName(g.returnType)} get ${g.name}',
          typeName: _typeName(g.returnType),
          modifiers: g.modifiers.modifiers,
        ),
      );
    }

    if (clazz is ASTClassEnum) {
      for (final e in clazz.entries) {
        out.add(
          SymbolInfo(
            name: e.name,
            category: SymbolCategory.enumMember,
            container: clazz.name,
            signature: '${clazz.name}.${e.name}',
            typeName: clazz.name,
          ),
        );
      }
    }
  }

  // Extensions and their members. An unnamed extension has no symbol of its
  // own, but its members are still listed, contained by the extended type.
  for (final extension in root.extensions) {
    final targetName = extension.targetType.name;
    final container = extension.name ?? targetName;

    if (extension.name != null) {
      out.add(
        SymbolInfo(
          name: extension.name!,
          category: SymbolCategory.classSym,
          signature: 'extension ${extension.name} on $targetName',
          typeName: targetName,
        ),
      );
    }

    for (final set in extension.functions) {
      for (final m in set.functions) {
        out.add(
          _invocable(m, container: container, category: SymbolCategory.method),
        );
      }
    }

    for (final g in extension.getter) {
      out.add(
        SymbolInfo(
          name: g.name,
          category: SymbolCategory.getter,
          container: container,
          signature: '${_typeName(g.returnType)} get ${g.name}',
          typeName: _typeName(g.returnType),
          modifiers: g.modifiers.modifiers,
        ),
      );
    }
  }

  return out;
}