resolve method

The fields that apply to scope, in inspector order.

Implementation

List<DiagramPropertyField<Object?>> resolve(DiagramPropertyScope scope) {
  // A group that names its anchor is placed after it, from any source.
  final variants = _commonProperties(scope);
  final standard = [
    ..._standard(scope),
    for (final properties in variants.values) properties.first,
  ];
  final base = [
    for (final property in standard)
      if (property.group.after == null) property,
  ];
  final owners = <DiagramProperty<Object?, Object?>, String>{};
  Iterable<DiagramProperty<Object?, Object?>> contribution(
    DiagramPropertySource source,
  ) sync* {
    for (final property in source.propertiesFor(scope)) {
      owners[property] = source is DiagramExtension
          ? source.id
          : '${source.runtimeType}';
      yield property;
    }
  }

  final contributed = [
    for (final property in standard)
      if (property.group.after != null) property,
    if (!scope.isLocked && scope.creation == null) ...[
      for (final source in _installedSources(scope)) ...contribution(source),
      for (final text in scope.text?.definitions ?? <DiagramTextDefinition>[])
        ...text.properties,
      for (final source in sources) ...contribution(source),
    ],
  ];
  final groups = <String, DiagramPropertyGroup>{
    for (final property in [...base, ...contributed])
      property.group.id: property.group,
  };
  final keys = <String, DiagramProperty<Object?, Object?>>{};
  final fields = <DiagramPropertyField<Object?>>[];
  for (final property in base) {
    if (_field(scope, property, variants[property.key] ?? const [])
        case final field?) {
      if (keys[field.key] case final existing?) {
        if (identical(existing, property)) continue;
        throw StateError(
          'Conflicting property ${field.key} in ${scope.elements.map((e) => e.id).join(', ')}: ${existing.label} and ${property.label}.',
        );
      }
      keys[field.key] = property;
      fields.add(field);
    }
  }
  for (final property in contributed) {
    final field = _field(scope, property, variants[property.key] ?? const []);
    if (field == null) continue;
    if (keys[field.key] case final existing?) {
      if (identical(existing, property)) continue;
      throw StateError(
        'Conflicting property ${field.key}: ${owners[existing] ?? 'core/shape definition'} (${existing.label}) and ${owners[property] ?? 'core/shape definition'} (${property.label}).',
      );
    }
    keys[field.key] = property;
    fields.insert(_position(fields, property.group, groups), field);
  }
  final declarations = [
    visibility,
    for (final shape in [
      ?scope.creation,
      ...scope.elements.whereType<ShapeElement>(),
    ])
      scope.registry.require(shape.type).inspector,
  ];
  return List.unmodifiable([
    for (final field in fields)
      if (declarations.every((d) => d.shows(field.property))) field,
  ]);
}