getAllInterfaceMembers method
Returns a map representing all members required by the interfaces implemented by this class and its superclasses, including those from super-interfaces. Key: member name, Value: String indicating type ('method', 'getter', 'setter')
Implementation
Map<String, String> getAllInterfaceMembers() {
final requiredMembers = <String, String>{};
final Set<InterpretedClass> visited = {}; // To avoid cycles/redundancy
final List<InterpretedClass> queue = [];
// Start with directly implemented interfaces
queue.addAll(interfaces);
// Also consider interfaces/abstract members from superclasses
var currentSuper = superclass;
while (currentSuper != null) {
queue.add(
currentSuper); // Add superclass to check its interfaces/abstract members
currentSuper = currentSuper.superclass;
}
while (queue.isNotEmpty) {
final currentClass = queue.removeAt(0);
if (!visited.add(currentClass)) {
continue; // Already processed this class/interface
}
// Add members defined directly in this interface/class
// We only care about the *signature* required, not the implementation.
// Note: Static members are NOT part of the interface contract.
currentClass.methods.forEach((name, func) {
// Abstract methods from superclasses also count as required signatures
requiredMembers.putIfAbsent(
name, () => func.isAbstract ? 'method' : 'method');
});
currentClass.getters.forEach((name, func) {
requiredMembers.putIfAbsent(
name, () => func.isAbstract ? 'getter' : 'getter');
});
currentClass.setters.forEach((name, func) {
requiredMembers.putIfAbsent(
name, () => func.isAbstract ? 'setter' : 'setter');
});
// Add interfaces implemented by this class to the queue
queue.addAll(currentClass.interfaces);
// Also add its superclass to the queue (if not already visited)
if (currentClass.superclass != null &&
!visited.contains(currentClass.superclass)) {
// No, superclass was added initially. We traverse the interface graph here.
// We need to get members from the superclass chain separately potentially.
// Let's reconsider. The check needs *all* members required by interfaces
// AND *all* abstract members from superclasses.
}
}
// Re-think: The above mixes inherited abstract members and interface members.
// Let's separate concerns.
// 1. Get all members required ONLY by interfaces.
// 2. Get all abstract members inherited via `extends` (already done).
// 3. The class needs to satisfy BOTH.
final requiredInterfaceMembers = <String, String>{};
final Set<InterpretedClass> visitedInterfaces = {};
final List<InterpretedClass> interfaceQueue = [];
interfaceQueue.addAll(interfaces);
// Add interfaces from superclasses as well
currentSuper = superclass;
while (currentSuper != null) {
interfaceQueue.addAll(currentSuper.interfaces);
currentSuper = currentSuper.superclass;
}
while (interfaceQueue.isNotEmpty) {
final currentInterface = interfaceQueue.removeAt(0);
if (!visitedInterfaces.add(currentInterface)) {
continue;
}
// Add members from the current interface
currentInterface.methods.forEach((name, func) {
requiredInterfaceMembers.putIfAbsent(name, () => 'method');
});
currentInterface.getters.forEach((name, func) {
requiredInterfaceMembers.putIfAbsent(name, () => 'getter');
});
currentInterface.setters.forEach((name, func) {
requiredInterfaceMembers.putIfAbsent(name, () => 'setter');
});
// Add its super-interfaces to the queue
interfaceQueue.addAll(currentInterface.interfaces);
// IMPORTANT: Also add the interface's OWN superclass to the queue,
// as the implementing class must satisfy members from the entire hierarchy.
if (currentInterface.superclass != null) {
interfaceQueue.add(currentInterface.superclass!); // Non-null asserted
}
}
return requiredInterfaceMembers;
}