couple of tokenization fixes with more tests.
authorAtsushi Eno <atsushieno@veritas-vos-liberabit.com>
Mon, 21 Oct 2013 13:28:49 +0000 (22:28 +0900)
committerAtsushi Eno <atsushieno@veritas-vos-liberabit.com>
Fri, 29 Nov 2013 09:20:51 +0000 (18:20 +0900)
mcs/class/Microsoft.Build/Microsoft.Build.Evaluation/Project.cs
mcs/class/Microsoft.Build/Microsoft.Build.Internal/ExpressionEvaluator.cs
mcs/class/Microsoft.Build/Microsoft.Build.Internal/ExpressionParserManual.cs
mcs/class/Microsoft.Build/Microsoft.Build.Internal/ExpressionTokenizer.cs
mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectTest.cs
mcs/class/Microsoft.Build/Test/Microsoft.Build.Internal/ExpressionParserTest.cs

index d8d806812391859b930b1e5de6012c2b546ada48..faeb2102fbaec782fded16477f5f4d4b0eb7bd7c 100644 (file)
@@ -322,12 +322,17 @@ namespace Microsoft.Build.Evaluation
                
                bool ShouldInclude (string unexpandedValue)
                {
-                       return string.IsNullOrWhiteSpace (unexpandedValue) || new ExpressionEvaluator (this).EvaluateAsBoolean (ExpandString (unexpandedValue));
+                       return string.IsNullOrWhiteSpace (unexpandedValue) || new ExpressionEvaluator (this, null).EvaluateAsBoolean (ExpandString (unexpandedValue, "''"));
                }
 
                public string ExpandString (string unexpandedValue)
                {
-                       return new ExpressionEvaluator (this).Evaluate (unexpandedValue);
+                       return ExpandString (unexpandedValue, null);
+               }
+               
+               string ExpandString (string unexpandedValue, string replacementForMissingStuff)
+               {
+                       return new ExpressionEvaluator (this, replacementForMissingStuff).Evaluate (unexpandedValue);
                }
 
                public static string GetEvaluatedItemIncludeEscaped (ProjectItem item)
index c3a48a04825f4e83c74abee1bd671de8de0cb80a..1dba5caa5523d85354977e9838a116a5e95dc230 100644 (file)
@@ -8,13 +8,16 @@ namespace Microsoft.Build.Internal
 {
        class ExpressionEvaluator
        {
-               public ExpressionEvaluator (Project project)
+               public ExpressionEvaluator (Project project, string replacementForMissingPropertyAndItem)
                {
                        this.Project = project;
+                       ReplacementForMissingPropertyAndItem = replacementForMissingPropertyAndItem;
                }
                
                public Project Project { get; private set; }
                
+               public string ReplacementForMissingPropertyAndItem { get; set; }
+               
                public string Evaluate (string source)
                {
                        return Evaluate (source, new ExpressionParserManual (source, ExpressionValidationType.LaxString).Parse ());
@@ -206,7 +209,7 @@ namespace Microsoft.Build.Internal
                public override string EvaluateAsString (EvaluationContext context)
                {
                        var ret = EvaluateAsObject (context);
-                       return ret == null ? null : ret.ToString ();
+                       return ret == null ? context.Evaluator.ReplacementForMissingPropertyAndItem : ret.ToString ();
                }
                
                public override object EvaluateAsObject (EvaluationContext context)
@@ -238,6 +241,8 @@ namespace Microsoft.Build.Internal
                public override string EvaluateAsString (EvaluationContext context)
                {
                        var items = context.Project.GetItems (Application.Name.Name);
+                       if (!items.Any ())
+                               return context.Evaluator.ReplacementForMissingPropertyAndItem;
                        if (Application.Expressions == null)
                                return string.Join (";", items.Select (item => context.EvaluateItem (item)).Select (inc => !string.IsNullOrWhiteSpace (inc)));
                        else
index d981c054add8fe9cdd2925d4943fd6534ad3b030..fd33314b8957606aee1baf8006e7f7d4c17cff03 100644 (file)
@@ -7,6 +7,7 @@ namespace Microsoft.Build.Internal
 {
        class ExpressionParserManual
        {
+               // FIXME: we are going to not need ExpressionValidationType for this; always LaxString.
                public ExpressionParserManual (string source, ExpressionValidationType validationType)
                {
                        this.source = source;
index 94ad2c9940ed099e157a5079c1f913ad74933b71..470bbed5d2d757a648813a8ce215e90aaddba2f5 100644 (file)
@@ -48,6 +48,10 @@ namespace Microsoft.Build.Internal
                        token_value = null;
                        current_token_position = pos;
 
+                       SkipSpaces ();
+                       if (pos == source.Length)
+                               return false;
+
                        switch (source [pos++]) {
                        case '.':
                                TokenForItemPropertyValue (".", Token.DOT);
@@ -162,17 +166,22 @@ namespace Microsoft.Build.Internal
                                        token_value = ProjectCollection.Unescape (val);
                                        break;
                                }
+                               Console.Error.WriteLine ("@@@@@ [{0}]", val);
                                break;
                        }
-                       while (pos < source.Length) {
-                               if (spaces.IndexOf (source [pos]) > 0)
-                                       pos++;
+                       return true;
+               }
+               string spaces = " \t\r\n";
+               
+               void SkipSpaces ()
+               {
+                       while (current_token_position < source.Length) {
+                               if (spaces.IndexOf (source [current_token_position]) > 0)
+                                       current_token_position++;
                                else
                                        break;
                        }
-                       return true;
                }
-               string spaces = " \t\r\n";
 
                static readonly char [] token_starter_chars = ".,)-=:!><$@%\"' ".ToCharArray ();
                
@@ -229,6 +238,11 @@ namespace Microsoft.Build.Internal
        class NameToken : Location
        {
                public string Name { get; set; }
+               
+               public override string ToString ()
+               {
+                       return string.Format ("[NameToken: Value={0}]", Name);
+               }
        }
 
        class ErrorToken : Location
index 5aaf4530cc02feb4bab81a64cc823060d653f8d8..fbace5b9fbe0101e79389dae20f0ab0622426d45 100644 (file)
@@ -78,7 +78,6 @@ namespace MonoTests.Microsoft.Build.Evaluation
                
                [Test]
                [ExpectedException (typeof (InvalidProjectFileException))]
-               [Category ("NotWorking")]
                public void LoadInvalidProjectForBadCondition ()
                {
                        string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
index c4dbabbeb15fe3a7e4ec1308c168626c6f62614c..e5600994eebaa5565eee30a1bf6d3f97d13c8345 100644 (file)
@@ -39,7 +39,13 @@ namespace MonoTests.Microsoft.Build.Internal
                                "'%24' == 0",
                                "true",
                                "fAlSe",
-                               "(false)"
+                               "(false)",
+                               "A=A",
+                               "A =A",
+                               "A= A",
+                               "A='A'",
+                               "A=\tA",
+                               "\tA= A",
                        };
                        string [] depends = {
                                // valid only if evaluated to boolean
@@ -209,6 +215,22 @@ namespace MonoTests.Microsoft.Build.Internal
                        var root = ProjectRootElement.Create (xml);
                        new Project (root);
                }
+               
+               [Test]
+               [ExpectedException (typeof (InvalidProjectFileException))]
+               public void SequentialPropertyReferenceNotAllowed ()
+               {
+                       string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+  <PropertyGroup>
+    <A>x</A>
+    <B>y</B>
+    <C Condition=""$(A)$(B)==''"">z</C>
+  </PropertyGroup>
+</Project>";
+                       var reader = XmlReader.Create (new StringReader (xml));
+                       var root = ProjectRootElement.Create (reader);
+                       new Project (root);
+               }
        }
 }