static string Evaluate(this IMSBuildEvaluationContext context, ExpressionNode expression, int depth) { if (depth == maxEvaluationDepth) { throw new Exception("Property evaluation exceeded maximum depth"); } switch (expression) { case ExpressionText text: return(text.Value); case ExpressionProperty prop: { if (!prop.IsSimpleProperty) { LoggingService.LogWarning("Only simple properties are supported in imports"); return(null); } if (context.TryGetProperty(prop.Name, out var value)) { return(Evaluate(context, value.Value, depth + 1)); } return(null); } case ConcatExpression expr: { var sb = new StringBuilder(); foreach (var n in expr.Nodes) { switch (n) { case ExpressionText t: sb.Append(t.Value); continue; case ExpressionProperty p: if (!p.IsSimpleProperty) { LoggingService.LogWarning("Only simple properties are supported in imports"); return(null); } if (context.TryGetProperty(p.Name, out var value)) { sb.Append(Evaluate(context, value.Value, depth + 1)); } continue; default: LoggingService.LogWarning("Only simple properties are supported in imports"); return(null); } } return(sb.ToString()); } default: LoggingService.LogWarning("Only simple properties and expressions are supported in imports"); return(null); } }
public bool TryGetProperty(string name, out MSBuildPropertyValue value) { if (fileContext.TryGetProperty(name, out value)) { return(true); } if (collector.TryGetValues(name, out var values)) { value = new MSBuildPropertyValue(values); return(true); } return(false); }
public bool TryGetProperty(string name, out MSBuildPropertyValue value) => values.TryGetValue(name, out value) || runtimeContext.TryGetProperty(name, out value);
static IEnumerable <string> EvaluateWithPermutation(this IMSBuildEvaluationContext context, string prefix, ExpressionNode expression, int depth) { switch (expression) { // yield plain text case ExpressionText text: yield return(prefix + text.Value); yield break; // recursively yield evaluated property case ExpressionProperty prop: { if (!prop.IsSimpleProperty) { LoggingService.LogWarning("Only simple properties are supported in imports"); break; } if (context.TryGetProperty(prop.Name, out var value)) { if (value.HasMultipleValues) { if (value.IsCollapsed) { foreach (var v in value.GetValues()) { yield return(prefix + ((ExpressionText)v).Value); } } else { foreach (var v in value.GetValues()) { foreach (var evaluated in EvaluateWithPermutation(context, prefix, v, depth + 1)) { yield return(evaluated); } } } } else { if (value.IsCollapsed) { yield return(prefix + ((ExpressionText)value.Value).Value); } else { foreach (var evaluated in EvaluateWithPermutation(context, prefix, value.Value, depth + 1)) { yield return(evaluated); } } } break; } else { yield return(prefix); } yield break; } case ConcatExpression expr: { var nodes = expr.Nodes; if (nodes.Count == 0) { yield break; } if (nodes.Count == 1) { foreach (var evaluated in EvaluateWithPermutation(context, prefix, nodes[0], depth + 1)) { yield return(evaluated); } yield break; } var zero = nodes[0]; var skip = new ExpressionNode[nodes.Count - 1]; for (int i = 1; i < nodes.Count; i++) { skip[i - 1] = nodes[i]; } foreach (var zeroVal in EvaluateWithPermutation(context, prefix, zero, depth + 1)) { ExpressionNode inner = skip.Length == 1 ? skip[0] : new ConcatExpression(0, 0, skip); foreach (var v in EvaluateWithPermutation(context, zeroVal, inner, depth + 1)) { yield return(v); } } yield break; } default: LoggingService.LogWarning("Only simple properties and expressions are supported in imports"); yield break; } }