Browse Source

Merge pull request #1595 from jkoritzinsky/fixes/1566-indexer-binding-start

Allow indexer bindings to be at the start of a binding path.
pull/1596/merge
Jeremy Koritzinsky 9 years ago
committed by GitHub
parent
commit
fee5f204d6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/Markup/Avalonia.Markup/Data/Parsers/ArgumentListParser.cs
  2. 42
      src/Markup/Avalonia.Markup/Data/Parsers/ExpressionParser.cs
  3. 12
      tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Indexer.cs

4
src/Markup/Avalonia.Markup/Data/Parsers/ArgumentListParser.cs

@ -51,10 +51,10 @@ namespace Avalonia.Markup.Data.Parsers
} }
} }
throw new ExpressionParseException(r.Position, "Expected ']'."); throw new ExpressionParseException(r.Position, $"Expected '{close}'.");
} }
return null; throw new ExpressionParseException(r.Position, $"Expected '{open}'.");
} }
} }
} }

42
src/Markup/Avalonia.Markup/Data/Parsers/ExpressionParser.cs

@ -40,6 +40,10 @@ namespace Avalonia.Markup.Data.Parsers
case State.AttachedProperty: case State.AttachedProperty:
state = ParseAttachedProperty(r, nodes); state = ParseAttachedProperty(r, nodes);
break; break;
case State.Indexer:
state = ParseIndexer(r, nodes);
break;
} }
} }
@ -67,6 +71,10 @@ namespace Avalonia.Markup.Data.Parsers
{ {
return State.AttachedProperty; return State.AttachedProperty;
} }
else if (PeekOpenBracket(r))
{
return State.Indexer;
}
else else
{ {
var identifier = IdentifierParser.Parse(r); var identifier = IdentifierParser.Parse(r);
@ -92,20 +100,9 @@ namespace Avalonia.Markup.Data.Parsers
nodes.Add(new StreamNode()); nodes.Add(new StreamNode());
return State.AfterMember; return State.AfterMember;
} }
else else if (PeekOpenBracket(r))
{ {
var args = ArgumentListParser.Parse(r, '[', ']'); return State.Indexer;
if (args != null)
{
if (args.Count == 0)
{
throw new ExpressionParseException(r.Position, "Indexer may not be empty.");
}
nodes.Add(new IndexerNode(args));
return State.AfterMember;
}
} }
return State.End; return State.End;
@ -151,6 +148,19 @@ namespace Avalonia.Markup.Data.Parsers
return State.AfterMember; return State.AfterMember;
} }
private State ParseIndexer(Reader r, List<ExpressionNode> nodes)
{
var args = ArgumentListParser.Parse(r, '[', ']');
if (args.Count == 0)
{
throw new ExpressionParseException(r.Position, "Indexer may not be empty.");
}
nodes.Add(new IndexerNode(args));
return State.AfterMember;
}
private static bool ParseNot(Reader r) private static bool ParseNot(Reader r)
{ {
return !r.End && r.TakeIf('!'); return !r.End && r.TakeIf('!');
@ -166,6 +176,11 @@ namespace Avalonia.Markup.Data.Parsers
return !r.End && r.TakeIf('('); return !r.End && r.TakeIf('(');
} }
private static bool PeekOpenBracket(Reader r)
{
return !r.End && r.Peek == '[';
}
private static bool ParseStreamOperator(Reader r) private static bool ParseStreamOperator(Reader r)
{ {
return !r.End && r.TakeIf('^'); return !r.End && r.TakeIf('^');
@ -177,6 +192,7 @@ namespace Avalonia.Markup.Data.Parsers
AfterMember, AfterMember,
BeforeMember, BeforeMember,
AttachedProperty, AttachedProperty,
Indexer,
End, End,
} }
} }

12
tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Indexer.cs

@ -338,6 +338,18 @@ namespace Avalonia.Markup.UnitTests.Data
GC.KeepAlive(data); GC.KeepAlive(data);
} }
[Fact]
public async Task Indexer_Only_Binding_Works()
{
var data = new[] { 1, 2, 3 };
var target = new ExpressionObserver(data, "[1]");
var value = await target.Take(1);
Assert.Equal(data[1], value);
}
private class NonIntegerIndexer : NotifyingBase private class NonIntegerIndexer : NotifyingBase
{ {
private readonly Dictionary<string, string> _storage = new Dictionary<string, string>(); private readonly Dictionary<string, string> _storage = new Dictionary<string, string>();

Loading…
Cancel
Save