Selaa lähdekoodia

Add tests for malformed binding expressions.

Steven Kirk 10 vuotta sitten
vanhempi
sitoutus
034d3691d0

+ 6 - 2
src/Markup/Perspex.Markup/Binding/Parsers/ArgumentListParser.cs

@@ -16,7 +16,7 @@ namespace Perspex.Markup.Binding.Parsers
 
                 r.Take();
 
-                while (!r.End && r.Peek != close)
+                while (!r.End)
                 {
                     var literal = LiteralParser.Parse(r);
 
@@ -35,7 +35,11 @@ namespace Perspex.Markup.Binding.Parsers
                     {
                         throw new ExpressionParseException(r, "Expected ','.");
                     }
-                    if (r.Peek != close)
+                    else if (r.TakeIf(close))
+                    {
+                        return result;
+                    }
+                    else
                     {
                         if (r.Take() != ',')
                         {

+ 9 - 36
src/Markup/Perspex.Markup/Binding/Parsers/ExpressionParser.cs

@@ -3,6 +3,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Linq;
 
 namespace Perspex.Markup.Binding.Parsers
 {
@@ -28,19 +29,20 @@ namespace Perspex.Markup.Binding.Parsers
                     case State.BeforeMember:
                         state = ParseBeforeMember(r, nodes);
                         break;
-
-                    default:
-                        state = State.End;
-                        break;
                 }
             }
 
+            if (state == State.BeforeMember)
+            {
+                throw new ExpressionParseException(r, "Unexpected end of expression.");
+            }
+
             for (int n = 0; n < nodes.Count - 1; ++n)
             {
                 nodes[n].Next = nodes[n + 1];
             }
 
-            return nodes[0];
+            return nodes.FirstOrDefault();
         }
 
         private static State ParseStart(Reader r, IList<ExpressionNode> nodes)
@@ -104,41 +106,12 @@ namespace Perspex.Markup.Binding.Parsers
 
         private static bool ParseNot(Reader r)
         {
-            if (!r.End && r.Peek == '!')
-            {
-                r.Take();
-                return true;
-            }
-            else
-            {
-                return false;
-            }
+            return !r.End && r.TakeIf('!');
         }
 
         private static bool ParseMemberAccessor(Reader r)
         {
-            if (!r.End && r.Peek == '.')
-            {
-                r.Take();
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        private static bool ParseIndexer(Reader r)
-        {
-            if (!r.End && r.Peek == '[')
-            {
-                r.Take();
-                return true;
-            }
-            else
-            {
-                return false;
-            }
+            return !r.End && r.TakeIf('.');
         }
 
         private enum State

+ 13 - 0
src/Markup/Perspex.Markup/Binding/Parsers/Reader.cs

@@ -27,5 +27,18 @@ namespace Perspex.Markup.Binding.Parsers
                 Take();
             }
         }
+
+        public bool TakeIf(char c)
+        {
+            if (Peek == c)
+            {
+                Take();
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
     }
 }

+ 9 - 2
tests/Perspex.Markup.UnitTests/Binding/ExpressionNodeBuilderTests.cs

@@ -15,8 +15,15 @@ namespace Perspex.Markup.UnitTests.Binding
         {
             var result = ToList(ExpressionNodeBuilder.Build("Foo"));
 
-            Assert.Equal(1, result.Count);
-            Assert.IsType<PropertyAccessorNode>(result[0]);
+            AssertIsProperty(result[0], "Foo");
+        }
+
+        [Fact]
+        public void Should_Build_Underscored_Property()
+        {
+            var result = ToList(ExpressionNodeBuilder.Build("_Foo"));
+
+            AssertIsProperty(result[0], "_Foo");
         }
 
         [Fact]

+ 74 - 0
tests/Perspex.Markup.UnitTests/Binding/ExpressionNodeBuilderTests_Errors.cs

@@ -0,0 +1,74 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Perspex.Markup.Binding;
+using Xunit;
+
+namespace Perspex.Markup.UnitTests.Binding
+{
+    public class ExpressionNodeBuilderTests_Errors
+    {
+        [Fact]
+        public void Identifier_Cannot_Start_With_Digit()
+        {
+            Assert.Throws<ExpressionParseException>(
+                () => ExpressionNodeBuilder.Build("1Foo"));
+        }
+
+        [Fact]
+        public void Identifier_Cannot_Start_With_Symbol()
+        {
+            Assert.Throws<ExpressionParseException>(
+                () => ExpressionNodeBuilder.Build("Foo.%Bar"));
+        }
+
+        [Fact]
+        public void Expression_Cannot_End_With_Period()
+        {
+            Assert.Throws<ExpressionParseException>(
+                () => ExpressionNodeBuilder.Build("Foo.Bar."));
+        }
+
+        [Fact]
+        public void Expression_Cannot_Have_Empty_Indexer()
+        {
+            Assert.Throws<ExpressionParseException>(
+                () => ExpressionNodeBuilder.Build("Foo.Bar[]"));
+        }
+
+        [Fact]
+        public void Expression_Cannot_Have_Extra_Comma_At_Start_Of_Indexer()
+        {
+            Assert.Throws<ExpressionParseException>(
+                () => ExpressionNodeBuilder.Build("Foo.Bar[,3,4]"));
+        }
+
+        [Fact]
+        public void Expression_Cannot_Have_Extra_Comma_In_Indexer()
+        {
+            Assert.Throws<ExpressionParseException>(
+                () => ExpressionNodeBuilder.Build("Foo.Bar[3,,4]"));
+        }
+
+        [Fact]
+        public void Expression_Cannot_Have_Extra_Comma_At_End_Of_Indexer()
+        {
+            Assert.Throws<ExpressionParseException>(
+                () => ExpressionNodeBuilder.Build("Foo.Bar[3,4,]"));
+        }
+
+        [Fact]
+        public void Expression_Cannot_Have_Digit_After_Indexer()
+        {
+            Assert.Throws<ExpressionParseException>(
+                () => ExpressionNodeBuilder.Build("Foo.Bar[3,4]5"));
+        }
+
+        [Fact]
+        public void Expression_Cannot_Have_Letter_After_Indexer()
+        {
+            Assert.Throws<ExpressionParseException>(
+                () => ExpressionNodeBuilder.Build("Foo.Bar[3,4]A"));
+        }
+    }
+}