protected override void VisitValueExpression( XElement element, XAttribute attribute, MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute, ValueInfo info, MSBuildValueKind kind, ExpressionNode node) { bool allowExpressions = kind.AllowExpressions(); bool allowLists = kind.AllowListsOrCommaLists(); foreach (var n in node.WithAllDescendants()) { switch (n) { case ExpressionList list: if (!allowLists) { AddListWarning(list.Nodes [0].End, 1); } break; case ExpressionError err: var msg = err.Kind.GetMessage(info, out bool isWarning); AddError( isWarning? ErrorType.Warning : ErrorType.Error, msg, err.Offset, Math.Max(1, err.Length) ); break; case ExpressionMetadata meta: case ExpressionProperty prop: case ExpressionItem item: if (!allowExpressions) { AddExpressionWarning(node); } //TODO: can we validate property/metadata/items refs? //maybe warn if they're not used anywhere outside of this expression? break; case ExpressionText lit: VisitPureLiteral(info, kind, lit.GetUnescapedValue(), lit.Offset); break; } } string Name() => info.GetTitleCaseKindName(); void AddExpressionWarning(ExpressionNode n) => AddWarning($"{Name ()} does not expect expressions", n.Offset, n.Length); void AddListWarning(int start, int length) => AddWarning($"{Name ()} does not expect lists", start, length); }
protected override void VisitValue( XElement element, XAttribute attribute, MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute, ValueInfo info, string value, int offset) { if (info.DefaultValue != null && string.Equals(info.DefaultValue, value)) { AddWarning($"{info.GetTitleCaseKindName ()} has default value", offset, value.Length); } // we skip calling base, and instead parse the expression with more options enabled // so that we can warn if the user is doing something likely invalid var kind = MSBuildCompletionExtensions.InferValueKindIfUnknown(info); var options = kind.GetExpressionOptions() | ExpressionOptions.ItemsMetadataAndLists; var node = ExpressionParser.Parse(value, options, offset); VisitValueExpression(element, attribute, resolvedElement, resolvedAttribute, info, kind, node); }