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 VisitValueExpression(XElement element, XAttribute attribute, MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute, ValueInfo info, MSBuildValueKind kind, ExpressionNode node) { switch (kind.GetScalarType()) { case MSBuildValueKind.TargetName: foreach (var n in node.WithAllDescendants()) { if (n is ExpressionText lit && lit.IsPure) { Navigations.Add(new MSBuildNavigationResult( MSBuildReferenceKind.Target, lit.Value, lit.Offset, lit.Length )); } } break; case MSBuildValueKind.File: case MSBuildValueKind.FileOrFolder: case MSBuildValueKind.ProjectFile: case MSBuildValueKind.TaskAssemblyFile: case MSBuildValueKind.Unknown: if (node is ExpressionList list) { foreach (var n in list.Nodes) { var p = GetPathFromNode(n, (MSBuildRootDocument)Document); if (p != null) { Navigations.Add(p); } } } var path = GetPathFromNode(node, (MSBuildRootDocument)Document); if (path != null) { Navigations.Add(path); } break; } }