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)
{
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 ());
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)
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
{
class ExpressionParserManual
{
+ // FIXME: we are going to not need ExpressionValidationType for this; always LaxString.
public ExpressionParserManual (string source, ExpressionValidationType validationType)
{
this.source = source;
token_value = null;
current_token_position = pos;
+ SkipSpaces ();
+ if (pos == source.Length)
+ return false;
+
switch (source [pos++]) {
case '.':
TokenForItemPropertyValue (".", Token.DOT);
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 ();
class NameToken : Location
{
public string Name { get; set; }
+
+ public override string ToString ()
+ {
+ return string.Format ("[NameToken: Value={0}]", Name);
+ }
}
class ErrorToken : Location
[Test]
[ExpectedException (typeof (InvalidProjectFileException))]
- [Category ("NotWorking")]
public void LoadInvalidProjectForBadCondition ()
{
string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
"'%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
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);
+ }
}
}