using ScadaLink.CentralUI.ScriptAnalysis; namespace ScadaLink.CentralUI.Components.Shared; /// /// Maps the trigger editors' flattened list /// into the metadata the uses to drive C# completion /// inside an expression trigger: /// /// Direct + Inherited choices become s, /// surfaced under Attributes["..."]. /// Composed choices — whose canonical name is dotted, e.g. /// CoolingTank.Temp — are grouped by their composition-instance prefix /// into s, surfaced under /// Children["..."].Attributes["..."]. /// /// public static class TriggerAttributeMapper { /// Direct and inherited attributes, exposed as Attributes["..."]. public static IReadOnlyList SelfAttributes( IReadOnlyList choices) => choices .Where(c => c.Source is "Direct" or "Inherited") .Select(c => new AttributeShape(c.CanonicalName, c.DataType)) .ToList(); /// /// Composed attributes grouped by composition-instance name, exposed as /// Children["X"].Attributes["Y"]. Entries without a dotted prefix /// are skipped (no child scope to attach them to). /// public static IReadOnlyList Children( IReadOnlyList choices) => choices .Where(c => c.Source == "Composed" && c.CanonicalName.Contains('.')) .Select(c => new { Child = c.CanonicalName[..c.CanonicalName.IndexOf('.')], Member = c.CanonicalName[(c.CanonicalName.IndexOf('.') + 1)..], c.DataType }) .GroupBy(x => x.Child, StringComparer.Ordinal) .Select(g => new CompositionContext( g.Key, g.Select(x => new AttributeShape(x.Member, x.DataType)).ToList(), Array.Empty())) .ToList(); }