private static IEnumerable<Snippet> BuildSnippets(Binding binding, BindingPrefixReference prefix, ElementNode element) { // this reference can use all attributes that start with it's prefix var candidates = element.Attributes .Where(attr => attr.Name.StartsWith(prefix.Prefix ?? "")); // attributes that are matched by name, or by a longer prefix, no longer remain var remaining = candidates .Where(attr => binding.Nodes.Any(compare => TestBetterMatch(attr.Name, prefix.Prefix, compare)) == false); // remaining attributes have a name that doesn't include the prefix characters var attrs = remaining .Select(attr => new { PropertyName = attr.Name.Substring((prefix.Prefix ?? "").Length), Attribute = attr }); var results = new List<Snippet>(); var first = true; foreach (var attr in attrs) { if (first) first = false; else results.Add(new Snippet { Value = "," }); results.Add(new Snippet { Value = attr.PropertyName + "=" }); if (prefix.AssumeStringValue) { var builder = new ExpressionBuilder(); PopulateBuilder(attr.Attribute.Nodes, builder); results.Add(new Snippet { Value = builder.ToCode() }); } else { results.AddRange(attr.Attribute.AsCode()); } } return results; }
private static Binding ParseBinding(XElement element, BindingGrammar grammar) { var binding = new Binding { ElementName = (string)element.Attribute("name") }; var start = element.Element("start"); var end = element.Element("end"); if (start != null && end != null) { binding.Phrases = new[] { ParsePhrase(start, grammar), ParsePhrase(end, grammar) }; } else { binding.Phrases = new[] { ParsePhrase(element, grammar) }; } binding.HasChildReference = binding.Phrases .SelectMany(phrase => phrase.Nodes) .OfType<BindingChildReference>() .Any(); if (binding.Phrases.Count() > 1 && binding.HasChildReference) { throw new CompilerException("Binding element '" + element.Attribute("name") + "' can not have child::* in start or end phrases."); } return binding; }
private static IEnumerable<Snippet> BuildSnippetsForNode(Binding binding, BindingNode node, ElementNode element) { if (node is BindingLiteral) return BuildSnippets(node as BindingLiteral); if (node is BindingNameReference) return BuildSnippets(node as BindingNameReference, element); if (node is BindingPrefixReference) return BuildSnippets(binding, node as BindingPrefixReference, element); throw new CompilerException("Binding node type " + node.GetType() + " not understood"); }
private static bool RequiredAttributesSatisfied(Binding binding, ElementNode element) { // any xpath targetting a flat name must be present, or the binding doesn't qualify foreach (var reference in binding.Nodes.OfType<BindingNameReference>()) { var nameReference = reference; if (!element.Attributes.Any(attr => attr.Name == nameReference.Name)) return false; } return true; }