diff --git a/README.md b/README.md
index c97a7f1..4cd2218 100644
--- a/README.md
+++ b/README.md
@@ -130,7 +130,7 @@ Here instead, we're saying "If condition is met, return some view. Otherwise, ad
#####Grammar definition
-Valid logical expressions handled by EA parser comply with syntax defined by the following grammar:
+Valid expressions handled by EA parser comply with syntax defined by the following grammar:
```
exp => cond-exp
diff --git a/build/test.ps1 b/build/test.ps1
index 7080267..c7c1e73 100644
--- a/build/test.ps1
+++ b/build/test.ps1
@@ -24,8 +24,9 @@ $testdlls = "`"`"$eatestdll`"`" `"`"$vatestdll`"`" `"`"$uitestdll`"`""
$webmvcbin = "$rootdir\src\ExpressiveAnnotations.MvcWebSample\bin"
# collect JS tests
-$maintest = "$rootdir\src\expressive.annotations.validate.test.js"
-$formtest = "$rootdir\src\tests.html"
+$maintest = "$rootdir\src\expressive.annotations.validate.test.js"
+$formtest = "$rootdir\src\form.tests.harness.html"
+$formtestnew = "$rootdir\src\form.tests.harness.latestdeps.html"
# run tests and analyze code coverage
& $opencover -register:user "-target:$xunit" "-targetargs:$testdlls -nologo -noshadow -appveyor" "-targetdir:$webmvcbin" "-filter:+[ExpressiveAnnotations(.MvcUnobtrusive)?]*" -output:csharp-coverage.xml -hideskipped:All -mergebyhash -returntargetcode
@@ -37,7 +38,7 @@ if($LastExitCode -ne 0) {
throw "C# tests failed"
}
-& $chutzpah /nologo /path $maintest /path $formtest /junit chutzpah-tests.xml /coverage /coverageIgnores "*test*, *jquery*" /coveragehtml javascript-coverage.htm /lcov javascript-coverage.lcov
+& $chutzpah /nologo /path $maintest /path $formtest /path $formtestnew /junit chutzpah-tests.xml /coverage /coverageIgnores "*test*, *jquery*" /coveragehtml javascript-coverage.htm /lcov javascript-coverage.lcov
if($LastExitCode -ne 0) {
if($env:APPVEYOR -eq $true) {
diff --git a/doc/api/api.chm b/doc/api/api.chm
index f1a9100..ca92125 100644
Binary files a/doc/api/api.chm and b/doc/api/api.chm differ
diff --git a/src/.nuget/packages.config b/src/.nuget/packages.config
index 642de3c..421810a 100644
--- a/src/.nuget/packages.config
+++ b/src/.nuget/packages.config
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/ExpressiveAnnotations.MvcUnobtrusive.Tests.csproj b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/ExpressiveAnnotations.MvcUnobtrusive.Tests.csproj
index 6c1866c..a9e5bc9 100644
--- a/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/ExpressiveAnnotations.MvcUnobtrusive.Tests.csproj
+++ b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/ExpressiveAnnotations.MvcUnobtrusive.Tests.csproj
@@ -39,13 +39,17 @@
4
+
+ ..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll
+ True
+
..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
True
-
- ..\packages\Moq.4.2.1409.1722\lib\net40\Moq.dll
+
+ ..\packages\Moq.4.5.10\lib\net45\Moq.dll
True
@@ -127,7 +131,9 @@
-
+
+ Designer
+
diff --git a/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/packages.config b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/packages.config
index 85d12c9..4f1a5c6 100644
--- a/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/packages.config
+++ b/src/ExpressiveAnnotations.MvcUnobtrusive.Tests/packages.config
@@ -1,10 +1,11 @@
+
-
+
diff --git a/src/ExpressiveAnnotations.MvcUnobtrusive/Properties/AssemblyInfo.cs b/src/ExpressiveAnnotations.MvcUnobtrusive/Properties/AssemblyInfo.cs
index 385add6..69a1e90 100644
--- a/src/ExpressiveAnnotations.MvcUnobtrusive/Properties/AssemblyInfo.cs
+++ b/src/ExpressiveAnnotations.MvcUnobtrusive/Properties/AssemblyInfo.cs
@@ -37,5 +37,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.4.7.0")]
-[assembly: AssemblyFileVersion("2.4.7.0")]
+[assembly: AssemblyVersion("2.4.8.0")]
+[assembly: AssemblyFileVersion("2.4.8.0")]
diff --git a/src/ExpressiveAnnotations.Tests/ExpressiveAnnotations.Tests.csproj b/src/ExpressiveAnnotations.Tests/ExpressiveAnnotations.Tests.csproj
index b9a48af..2511e52 100644
--- a/src/ExpressiveAnnotations.Tests/ExpressiveAnnotations.Tests.csproj
+++ b/src/ExpressiveAnnotations.Tests/ExpressiveAnnotations.Tests.csproj
@@ -40,8 +40,12 @@
4
-
- ..\packages\Moq.4.2.1409.1722\lib\net40\Moq.dll
+
+ ..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll
+ True
+
+
+ ..\packages\Moq.4.5.10\lib\net45\Moq.dll
True
@@ -93,7 +97,9 @@
-
+
+ Designer
+
diff --git a/src/ExpressiveAnnotations.Tests/ParserTest.cs b/src/ExpressiveAnnotations.Tests/ParserTest.cs
index 272c2ec..25586a5 100644
--- a/src/ExpressiveAnnotations.Tests/ParserTest.cs
+++ b/src/ExpressiveAnnotations.Tests/ParserTest.cs
@@ -1522,6 +1522,26 @@ public void verify_various_parsing_errors()
e = Assert.Throws(() => parser.Parse("GetObject()[0]").Invoke(null));
Assert.Equal("Indexing operation not supported. Subscript operator can be applied to either an array or a type declaring indexer.", e.Error);
Assert.Equal(new Location(1, 12), e.Location, new LocationComparer());
+
+ e = Assert.Throws(() => parser.Parse("SubModel.Unknown1.Unknown2 == 1").Invoke(new Model()));
+ Assert.Equal("Only public properties, constants and enums are accepted. Identifier 'Unknown1' not known.", e.Error);
+ Assert.Equal(new Location(1, 10), e.Location, new LocationComparer());
+
+ e = Assert.Throws(() => parser.Parse("GetObject().Unknown1.Unknown2 == 1").Invoke(new Model()));
+ Assert.Equal("Only public properties, constants and enums are accepted. Identifier 'Unknown1' not known.", e.Error);
+ Assert.Equal(new Location(1, 13), e.Location, new LocationComparer());
+
+ e = Assert.Throws(() => parser.Parse("[SubModel][0].Unknown1.Unknown2 == 1").Invoke(new Model()));
+ Assert.Equal("Only public properties, constants and enums are accepted. Identifier 'Unknown1' not known.", e.Error);
+ Assert.Equal(new Location(1, 15), e.Location, new LocationComparer());
+
+ e = Assert.Throws(() => parser.Parse("[1").Invoke(new Model()));
+ Assert.Equal("Expected comma or closing bracket. Unexpected end of expression.", e.Error);
+ Assert.Equal(new Location(1, 3), e.Location, new LocationComparer());
+
+ e = Assert.Throws(() => parser.Parse("[1)").Invoke(new Model()));
+ Assert.Equal("Expected comma or closing bracket. Unexpected token: ')'.", e.Error);
+ Assert.Equal(new Location(1, 3), e.Location, new LocationComparer());
}
[Fact]
diff --git a/src/ExpressiveAnnotations.Tests/UtilsTest.cs b/src/ExpressiveAnnotations.Tests/UtilsTest.cs
index 807db91..0d9c8f9 100644
--- a/src/ExpressiveAnnotations.Tests/UtilsTest.cs
+++ b/src/ExpressiveAnnotations.Tests/UtilsTest.cs
@@ -210,6 +210,13 @@ public void throw_when_non_positive_parameters_are_provided_for_error_message_co
Assert.Equal("Column number should be positive.\r\nParameter name: column", e.Message);
}
+ [Fact]
+ public void print_token_for_debug_purposes()
+ {
+ var token = new Token(TokenType.FLOAT, 1.0, "1.0", new Location(1, 2));
+ Assert.Equal(@"""1.0"" FLOAT (1, 2)", token.ToString());
+ }
+
private class Model
{
[Display(Name = "Value_1")]
diff --git a/src/ExpressiveAnnotations.Tests/packages.config b/src/ExpressiveAnnotations.Tests/packages.config
index 9ceb64e..d16ec29 100644
--- a/src/ExpressiveAnnotations.Tests/packages.config
+++ b/src/ExpressiveAnnotations.Tests/packages.config
@@ -1,6 +1,7 @@
-
+
+
diff --git a/src/ExpressiveAnnotations.sln b/src/ExpressiveAnnotations.sln
index e02a2e1..3066cf5 100644
--- a/src/ExpressiveAnnotations.sln
+++ b/src/ExpressiveAnnotations.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
-VisualStudioVersion = 14.0.24720.0
+VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExpressiveAnnotations", "ExpressiveAnnotations\ExpressiveAnnotations.csproj", "{70DD327B-F37C-4291-9388-212AA541E970}"
EndProject
@@ -18,7 +18,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{5908
expressive.annotations.validate.js = expressive.annotations.validate.js
expressive.annotations.validate.min.js = expressive.annotations.validate.min.js
expressive.annotations.validate.test.js = expressive.annotations.validate.test.js
- tests.html = tests.html
+ form.tests.harness.html = form.tests.harness.html
+ form.tests.harness.latestdeps.html = form.tests.harness.latestdeps.html
+ form.tests.js = form.tests.js
EndProjectSection
ProjectSection(FolderStartupServices) = postProject
{82A7F48D-3B50-4B1E-B82E-3ADA8210C358} = {82A7F48D-3B50-4B1E-B82E-3ADA8210C358}
diff --git a/src/ExpressiveAnnotations/Analysis/Parser.cs b/src/ExpressiveAnnotations/Analysis/Parser.cs
index 36a20fa..0d2fbdb 100644
--- a/src/ExpressiveAnnotations/Analysis/Parser.cs
+++ b/src/ExpressiveAnnotations/Analysis/Parser.cs
@@ -371,7 +371,7 @@ private Expression ParseEqualityExp()
var type1 = arg1.Type;
var type2 = arg2.Type;
- Helper.MakeTypesCompatible(arg1, arg2, out arg1, out arg2, oper.Type);
+ TypeAdapter.MakeTypesCompatible(arg1, arg2, out arg1, out arg2, oper.Type);
Wall.Eq(arg1, arg2, type1, type2, oper);
switch (oper.Type)
@@ -399,7 +399,7 @@ private Expression ParseRelationalExp()
var type1 = arg1.Type;
var type2 = arg2.Type;
- Helper.MakeTypesCompatible(arg1, arg2, out arg1, out arg2, oper.Type);
+ TypeAdapter.MakeTypesCompatible(arg1, arg2, out arg1, out arg2, oper.Type);
Wall.Rel(arg1, arg2, type1, type2, oper);
switch (oper.Type)
@@ -459,7 +459,7 @@ private Expression ParseAdditiveExp()
var type1 = arg1.Type;
var type2 = arg2.Type;
- Helper.MakeTypesCompatible(arg1, arg2, out arg1, out arg2, oper.Type);
+ TypeAdapter.MakeTypesCompatible(arg1, arg2, out arg1, out arg2, oper.Type);
Wall.Add(arg1, arg2, type1, type2, oper);
switch (oper.Type)
@@ -491,7 +491,7 @@ private Expression ParseMultiplicativeExp()
var arg2 = ParseUnaryExp();
Wall.Mul(arg1, arg2, oper);
- Helper.MakeTypesCompatible(arg1, arg2, out arg1, out arg2, oper.Type);
+ TypeAdapter.MakeTypesCompatible(arg1, arg2, out arg1, out arg2, oper.Type);
switch (oper.Type)
{
diff --git a/src/ExpressiveAnnotations/Analysis/TypeAdapter.cs b/src/ExpressiveAnnotations/Analysis/TypeAdapter.cs
new file mode 100644
index 0000000..a957d04
--- /dev/null
+++ b/src/ExpressiveAnnotations/Analysis/TypeAdapter.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Diagnostics;
+using System.Linq.Expressions;
+
+namespace ExpressiveAnnotations.Analysis
+{
+ internal static class TypeAdapter
+ {
+ public static void MakeTypesCompatible(Expression e1, Expression e2, out Expression oute1, out Expression oute2, TokenType operation)
+ {
+ Debug.Assert(e1 != null);
+ Debug.Assert(e2 != null);
+
+ oute1 = e1;
+ oute2 = e2;
+
+ if (oute1.Type.IsEnum && oute2.Type.IsEnum
+ && oute1.Type.UnderlyingType() != oute2.Type.UnderlyingType()) // various enum types
+ return;
+
+ if (operation != TokenType.DIV // do not promote integral numeric values to double - exception for division operation, e.g. 1/2 should evaluate to 0.5 double like in JS
+ && !oute1.Type.IsEnum && !oute2.Type.IsEnum
+ && oute1.Type.IsNumeric() && oute2.Type.IsNumeric()
+ && !oute1.Type.IsFloatingPointNumeric() && !oute2.Type.IsFloatingPointNumeric())
+ return;
+
+ // promote numeric values to double - do computations with higher precision (to be compatible with JavaScript, e.g. 1/2 should evaluate to 0.5 double not 0 int)
+ if (oute1.Type != typeof (double) && oute1.Type != typeof (double?) && oute1.Type.IsNumeric())
+ oute1 = oute1.Type.IsNullable()
+ ? Expression.Convert(oute1, typeof (double?))
+ : Expression.Convert(oute1, typeof (double));
+ if (oute2.Type != typeof (double) && oute2.Type != typeof (double?) && oute2.Type.IsNumeric())
+ oute2 = oute2.Type.IsNullable()
+ ? Expression.Convert(oute2, typeof (double?))
+ : Expression.Convert(oute2, typeof (double));
+
+ // non-nullable operand is converted to nullable if necessary, and the lifted-to-nullable form of the comparison is used (C# rule, which is currently not followed by expression trees)
+ if (oute1.Type.UnderlyingType() == oute2.Type.UnderlyingType())
+ {
+ if (oute1.Type.IsNullable() && !oute2.Type.IsNullable())
+ oute2 = Expression.Convert(oute2, oute1.Type);
+ else if (!oute1.Type.IsNullable() && oute2.Type.IsNullable())
+ oute1 = Expression.Convert(oute1, oute2.Type);
+ }
+
+ // make DateTime and TimeSpan compatible (also do not care when first argument is TimeSpan and second DateTime because it is not allowed)
+ if (oute1.Type.IsDateTime() && oute2.Type.IsTimeSpan())
+ {
+ if (oute1.Type.IsNullable() && !oute2.Type.IsNullable())
+ oute2 = Expression.Convert(oute2, typeof (TimeSpan?));
+ else if (!oute1.Type.IsNullable() && oute2.Type.IsNullable())
+ oute1 = Expression.Convert(oute1, typeof (DateTime?));
+ }
+ }
+ }
+}
diff --git a/src/ExpressiveAnnotations/ExpressiveAnnotations.csproj b/src/ExpressiveAnnotations/ExpressiveAnnotations.csproj
index c3babd9..2ca0925 100644
--- a/src/ExpressiveAnnotations/ExpressiveAnnotations.csproj
+++ b/src/ExpressiveAnnotations/ExpressiveAnnotations.csproj
@@ -61,6 +61,7 @@
+
diff --git a/src/ExpressiveAnnotations/Helper.cs b/src/ExpressiveAnnotations/Helper.cs
index 3e74252..f5c25bb 100644
--- a/src/ExpressiveAnnotations/Helper.cs
+++ b/src/ExpressiveAnnotations/Helper.cs
@@ -32,53 +32,6 @@ public AssemblyTypeProvider(Assembly assembly)
internal static class Helper
{
- public static void MakeTypesCompatible(Expression e1, Expression e2, out Expression oute1, out Expression oute2, TokenType operation)
- {
- Debug.Assert(e1 != null);
- Debug.Assert(e2 != null);
-
- oute1 = e1;
- oute2 = e2;
-
- if (oute1.Type.IsEnum && oute2.Type.IsEnum
- && oute1.Type.UnderlyingType() != oute2.Type.UnderlyingType()) // various enum types
- return;
-
- if (operation != TokenType.DIV // do not promote integral numeric values to double - exception for division operation, e.g. 1/2 should evaluate to 0.5 double like in JS
- && !oute1.Type.IsEnum && !oute2.Type.IsEnum
- && oute1.Type.IsNumeric() && oute2.Type.IsNumeric()
- && !oute1.Type.IsFloatingPointNumeric() && !oute2.Type.IsFloatingPointNumeric())
- return;
-
- // promote numeric values to double - do computations with higher precision (to be compatible with JavaScript, e.g. 1/2 should evaluate to 0.5 double not 0 int)
- if (oute1.Type != typeof (double) && oute1.Type != typeof (double?) && oute1.Type.IsNumeric())
- oute1 = oute1.Type.IsNullable()
- ? Expression.Convert(oute1, typeof (double?))
- : Expression.Convert(oute1, typeof (double));
- if (oute2.Type != typeof (double) && oute2.Type != typeof (double?) && oute2.Type.IsNumeric())
- oute2 = oute2.Type.IsNullable()
- ? Expression.Convert(oute2, typeof (double?))
- : Expression.Convert(oute2, typeof (double));
-
- // non-nullable operand is converted to nullable if necessary, and the lifted-to-nullable form of the comparison is used (C# rule, which is currently not followed by expression trees)
- if (oute1.Type.UnderlyingType() == oute2.Type.UnderlyingType())
- {
- if (oute1.Type.IsNullable() && !oute2.Type.IsNullable())
- oute2 = Expression.Convert(oute2, oute1.Type);
- else if (!oute1.Type.IsNullable() && oute2.Type.IsNullable())
- oute1 = Expression.Convert(oute1, oute2.Type);
- }
-
- // make DateTime and TimeSpan compatible (also do not care when first argument is TimeSpan and second DateTime because it is not allowed)
- if (oute1.Type.IsDateTime() && oute2.Type.IsTimeSpan())
- {
- if (oute1.Type.IsNullable() && !oute2.Type.IsNullable())
- oute2 = Expression.Convert(oute2, typeof (TimeSpan?));
- else if (!oute1.Type.IsNullable() && oute2.Type.IsNullable())
- oute1 = Expression.Convert(oute1, typeof (DateTime?));
- }
- }
-
public static object ExtractValue(object source, string property)
{
Debug.Assert(source != null);
diff --git a/src/ExpressiveAnnotations/Properties/AssemblyInfo.cs b/src/ExpressiveAnnotations/Properties/AssemblyInfo.cs
index 6f3cd44..166e6a8 100644
--- a/src/ExpressiveAnnotations/Properties/AssemblyInfo.cs
+++ b/src/ExpressiveAnnotations/Properties/AssemblyInfo.cs
@@ -42,5 +42,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.5.1.0")]
-[assembly: AssemblyFileVersion("2.5.1.0")]
+[assembly: AssemblyVersion("2.6.0.0")]
+[assembly: AssemblyFileVersion("2.6.0.0")]
diff --git a/src/tests.html b/src/form.tests.harness.html
similarity index 55%
rename from src/tests.html
rename to src/form.tests.harness.html
index 63106c5..f837fbc 100644
--- a/src/tests.html
+++ b/src/form.tests.harness.html
@@ -35,48 +35,12 @@
-
+
-
-
-
-
-
+