public static ExpressionNode Find(this ExpressionNode node, int offset) { return(node.ContainsOffset(offset) ? FindInternal(node, offset) : null); }
static ExpressionNode FindInternal(this ExpressionNode node, int offset) { switch (node) { case Expression expr: //TODO: binary search? foreach (var c in expr.Nodes) { if (c.ContainsOffset(offset)) { return(c.FindInternal(offset)); } } break; case ExpressionItem item: if (item.HasTransform && item.Transform.ContainsOffset(offset)) { return(item.Transform.FindInternal(offset)); } break; case ExpressionProperty prop: if (prop.Expression != null && prop.Expression.ContainsOffset(offset)) { return(prop.Expression.FindInternal(offset)); } break; case IncompleteExpressionError err: if (err.IncompleteNode != null && err.IncompleteNode.ContainsOffset(offset)) { return(err.IncompleteNode.FindInternal(offset)); } break; case ExpressionPropertyFunctionInvocation prop: if (prop.Target != null && prop.Target.ContainsOffset(offset)) { return(prop.Target.FindInternal(offset)); } if (prop.Arguments != null && prop.Arguments.ContainsOffset(offset)) { return(prop.Arguments.FindInternal(offset)); } break; case ExpressionArgumentList argumentList: if (argumentList.Arguments != null) { //TODO: binary search? foreach (var c in argumentList.Arguments) { if (c.ContainsOffset(offset)) { return(c.FindInternal(offset)); } } } break; } return(node); }
public static IEnumerable <ExpressionNode> WithAllDescendants(this ExpressionNode node) { yield return(node); switch (node) { case Expression expr: foreach (var c in expr.Nodes) { foreach (var n in c.WithAllDescendants()) { yield return(n); } } break; case ExpressionItem item: if (item.HasTransform) { foreach (var n in item.Transform.WithAllDescendants()) { yield return(n); } } break; case ExpressionProperty property: if (property.Expression != null) { foreach (var n in property.Expression.WithAllDescendants()) { yield return(n); } } break; case ExpressionPropertyFunctionInvocation invocation: if (invocation.Target != null) { foreach (var n in invocation.Target.WithAllDescendants()) { yield return(n); } } if (invocation.Arguments != null) { foreach (var n in invocation.Arguments.WithAllDescendants()) { yield return(n); } } break; case ExpressionArgumentList argumentList: if (argumentList.Arguments != null) { foreach (var a in argumentList.Arguments) { foreach (var n in a.WithAllDescendants()) { yield return(n); } } } break; } }
public static bool ContainsOffset(this ExpressionNode node, int offset) { return(node.Offset <= offset && node.End >= offset); }
public IncompleteExpressionError(int offset, bool wasEOF, ExpressionErrorKind kind, ExpressionNode incompleteNode) : base(offset, wasEOF? 0 : 1, kind) { IncompleteNode = incompleteNode; }
internal void SetParent(ExpressionNode parent) => Parent = parent;
public ExpressionItem(int offset, int length, string name, ExpressionNode transform) : base(offset, length) { Transform = transform; transform?.SetParent(this); Name = name; }
public ExpressionProperty(int offset, int length, ExpressionNode expression) : base(offset, length) { Expression = expression; }
protected override void VisitValueExpression( XElement element, XAttribute attribute, MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute, ValueInfo info, MSBuildValueKind kind, ExpressionNode node) { switch (node.Find(offset)) { case ExpressionItem ei: rr.ReferenceKind = MSBuildReferenceKind.Item; rr.ReferenceOffset = ei.NameOffset; rr.ReferenceLength = ei.Name.Length; rr.Reference = ei.Name; break; case ExpressionPropertyName propName: rr.ReferenceKind = MSBuildReferenceKind.Property; rr.ReferenceOffset = propName.Offset; rr.Reference = propName.Name; rr.ReferenceLength = propName.Length; break; case ExpressionMetadata em: if (em.ItemName == null || offset >= em.MetadataNameOffset) { rr.ReferenceKind = MSBuildReferenceKind.Metadata; rr.ReferenceOffset = em.MetadataNameOffset; rr.Reference = (em.GetItemName(), em.MetadataName); rr.ReferenceLength = em.MetadataName.Length; } else { rr.ReferenceKind = MSBuildReferenceKind.Item; rr.ReferenceOffset = em.ItemNameOffset; rr.Reference = em.ItemName; rr.ReferenceLength = em.ItemName.Length; } break; case ExpressionText lit: kind = kind.GetScalarType(); if (lit.IsPure) { VisitPureLiteral(info, kind, lit); if (kind == MSBuildValueKind.TaskOutputParameterName) { rr.ReferenceKind = MSBuildReferenceKind.TaskParameter; rr.ReferenceOffset = lit.Offset; rr.ReferenceLength = lit.Value.Length; rr.Reference = (element.ParentElement().Name.Name, lit.Value); break; } } switch (kind) { case MSBuildValueKind.File: case MSBuildValueKind.FileOrFolder: case MSBuildValueKind.ProjectFile: case MSBuildValueKind.TaskAssemblyFile: var pathNode = lit.Parent as Expression ?? (ExpressionNode)lit; var path = MSBuildNavigation.GetPathFromNode(pathNode, (MSBuildRootDocument)Document); if (path != null) { rr.ReferenceKind = MSBuildReferenceKind.FileOrFolder; rr.ReferenceOffset = path.Offset; rr.ReferenceLength = path.Length; rr.Reference = path.Paths; } break; } break; } }
protected override void VisitValueExpression( XElement element, XAttribute attribute, MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute, ValueInfo info, MSBuildValueKind kind, ExpressionNode node) { switch (node.Find(offset)) { case ExpressionItemName ei: rr.ReferenceKind = MSBuildReferenceKind.Item; rr.ReferenceOffset = ei.Offset; rr.ReferenceLength = ei.Name.Length; rr.Reference = ei.Name; break; case ExpressionPropertyName propName: rr.ReferenceKind = MSBuildReferenceKind.Property; rr.ReferenceOffset = propName.Offset; rr.Reference = propName.Name; rr.ReferenceLength = propName.Length; break; case ExpressionMetadata em: if (em.ItemName == null || offset >= em.MetadataNameOffset) { rr.ReferenceKind = MSBuildReferenceKind.Metadata; rr.ReferenceOffset = em.MetadataNameOffset; rr.Reference = (em.GetItemName(), em.MetadataName); rr.ReferenceLength = em.MetadataName.Length; } else { rr.ReferenceKind = MSBuildReferenceKind.Item; rr.ReferenceOffset = em.ItemNameOffset; rr.Reference = em.ItemName; rr.ReferenceLength = em.ItemName.Length; } break; case ExpressionFunctionName name: rr.ReferenceOffset = name.Offset; rr.ReferenceLength = name.Name.Length; if (name.Parent is ExpressionItemNode item) { rr.ReferenceKind = MSBuildReferenceKind.ItemFunction; rr.Reference = name.Name; } else if (name.Parent is ExpressionPropertyFunctionInvocation prop) { if (prop.Target is ExpressionClassReference classRef) { rr.ReferenceKind = MSBuildReferenceKind.StaticPropertyFunction; rr.Reference = (classRef.Name, name.Name); } else { var type = FunctionCompletion.ResolveType(prop.Target); rr.ReferenceKind = MSBuildReferenceKind.PropertyFunction; rr.Reference = (type, name.Name); } } break; case ExpressionClassReference cr: if (!string.IsNullOrEmpty(cr.Name)) { if (cr.Parent is ExpressionArgumentList) { rr.ReferenceKind = MSBuildReferenceKind.Enum; } else if (cr.Parent is ExpressionPropertyFunctionInvocation) { rr.ReferenceKind = MSBuildReferenceKind.ClassName; } else { break; } rr.ReferenceOffset = cr.Offset; rr.Reference = cr.Name; rr.ReferenceLength = cr.Length; } break; case ExpressionText lit: kind = kind.GetScalarType(); if (lit.IsPure) { VisitPureLiteral(element, info, kind, lit); if (kind == MSBuildValueKind.TaskOutputParameterName) { rr.ReferenceKind = MSBuildReferenceKind.TaskParameter; rr.ReferenceOffset = lit.Offset; rr.ReferenceLength = lit.Value.Length; rr.Reference = (element.ParentElement().Name.Name, lit.Value); break; } } switch (kind) { case MSBuildValueKind.File: case MSBuildValueKind.FileOrFolder: case MSBuildValueKind.ProjectFile: case MSBuildValueKind.TaskAssemblyFile: var pathNode = lit.Parent as Expression ?? (ExpressionNode)lit; var path = MSBuildNavigation.GetPathFromNode(pathNode, (MSBuildRootDocument)Document); if (path != null) { rr.ReferenceKind = MSBuildReferenceKind.FileOrFolder; rr.ReferenceOffset = path.Offset; rr.ReferenceLength = path.Length; rr.Reference = path.Paths; } break; } break; } }
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; } }