public MSBuildPropertyFunctionReferenceCollector(MSBuildValueKind valueKind, string functionName, IFunctionTypeProvider functionTypeProvider) : base(StripGetPrefix(functionName)) { if (valueKind == MSBuildValueKind.Unknown) { valueKind = MSBuildValueKind.String; } this.valueKind = valueKind; this.functionTypeProvider = functionTypeProvider; }
public static IEnumerable <ISymbol> GetCompletionInfos( MSBuildResolveResult rr, TriggerState trigger, MSBuildValueKind kind, ExpressionNode triggerExpression, int triggerLength, MSBuildRootDocument doc, IFunctionTypeProvider functionTypeProvider) { switch (trigger) { case TriggerState.Value: return(MSBuildCompletionExtensions.GetValueCompletions(kind, doc, rr, triggerExpression)); case TriggerState.ItemName: return(doc.GetItems()); case TriggerState.MetadataName: return(doc.GetMetadata(null, true)); case TriggerState.PropertyName: return(doc.GetProperties(true)); case TriggerState.MetadataOrItemName: return(((IEnumerable <ISymbol>)doc.GetItems()).Concat(doc.GetMetadata(null, true))); case TriggerState.DirectorySeparator: return(MSBuildCompletionExtensions.GetFilenameCompletions(kind, doc, triggerExpression, triggerLength, rr)); case TriggerState.PropertyFunctionName: return(functionTypeProvider.GetPropertyFunctionNameCompletions(triggerExpression)); case TriggerState.ItemFunctionName: return(functionTypeProvider.GetItemFunctionNameCompletions()); case TriggerState.PropertyFunctionClassName: return(functionTypeProvider.GetClassNameCompletions()); case TriggerState.None: break; case TriggerState.BareFunctionArgumentValue: //FIXME: enum completion etc return(MSBuildValueKind.Bool.GetSimpleValues(true)); case TriggerState.ConditionFunctionName: return(Builtins.ConditionFunctions.Values); } throw new InvalidOperationException($"Unhandled trigger type {trigger}"); }
public static MSBuildResolveResult Resolve( XmlSpineParser spineParser, ITextSource textSource, MSBuildDocument context, IFunctionTypeProvider functionTypeProvider, CancellationToken cancellationToken = default) { int offset = spineParser.Position; var nodePath = spineParser.AdvanceToNodeEndAndGetNodePath(textSource); nodePath.ConnectParents(); //need to look up element by walking how the path, since at each level, if the parent has special children, //then that gives us information to identify the type of its children MSBuildElementSyntax languageElement = null; MSBuildAttributeSyntax languageAttribute = null; XElement el = null; XAttribute att = null; foreach (var node in nodePath) { if (node is XAttribute xatt && xatt.Name.Prefix == null) { att = xatt; languageAttribute = languageElement?.GetAttribute(att.Name.Name); break; } //if children of parent is known to be arbitrary data, don't go into it if (languageElement != null && languageElement.ValueKind == MSBuildValueKind.Data) { break; } //code completion is forgiving, all we care about best guess resolve for deepest child if (node is XElement xel && xel.Name.Prefix == null) { el = xel; languageElement = MSBuildElementSyntax.Get(el.Name.Name, languageElement); if (languageElement != null) { continue; } } if (node is XText) { continue; } if (node is XClosingTag ct && ct == el.ClosingTag) { continue; } languageElement = null; } if (languageElement == null) { return(null); } var rr = new MSBuildResolveResult { ElementSyntax = languageElement, AttributeSyntax = languageAttribute, Element = el, Attribute = att }; var rv = new MSBuildResolveVisitor(offset, rr, functionTypeProvider); try { rv.Run(el, languageElement, textSource, context, token: cancellationToken); } catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested) { // callers always have to handle the possibility this returns null // so this means callers don't need to handle cancellation exceptions explciitly return(null); } return(rr); }
public MSBuildResolveVisitor(int offset, MSBuildResolveResult rr, IFunctionTypeProvider functionTypeProvider) { this.offset = offset; this.rr = rr; this.functionTypeProvider = functionTypeProvider; }
public MSBuildPropertyFunctionReferenceCollector( MSBuildValueKind valueKind, string functionName, IFunctionTypeProvider functionTypeProvider, Action <(int Offset, int Length, ReferenceUsage Usage)> reportResult)
public static ISymbol GetResolvedReference(this MSBuildResolveResult rr, MSBuildRootDocument doc, IFunctionTypeProvider functionTypeProvider) { switch (rr.ReferenceKind) { case MSBuildReferenceKind.Item: return(doc.GetItem((string)rr.Reference)); case MSBuildReferenceKind.Metadata: var m = rr.ReferenceAsMetadata; return(doc.GetMetadata(m.itemName, m.metaName, true)); case MSBuildReferenceKind.Property: return(doc.GetProperty((string)rr.Reference, true)); case MSBuildReferenceKind.Task: return(doc.GetTask((string)rr.Reference)); case MSBuildReferenceKind.Target: return(doc.GetTarget((string)rr.Reference)); case MSBuildReferenceKind.Keyword: return((ISymbol)rr.Reference); case MSBuildReferenceKind.KnownValue: return((ISymbol)rr.Reference); case MSBuildReferenceKind.TargetFramework: return(ResolveFramework((string)rr.Reference)); case MSBuildReferenceKind.TargetFrameworkIdentifier: return(BestGuessResolveFrameworkIdentifier((string)rr.Reference, doc.Frameworks)); case MSBuildReferenceKind.TargetFrameworkVersion: return(BestGuessResolveFrameworkVersion((string)rr.Reference, doc.Frameworks)); case MSBuildReferenceKind.TargetFrameworkProfile: return(BestGuessResolveFrameworkProfile((string)rr.Reference, doc.Frameworks)); case MSBuildReferenceKind.TaskParameter: var p = rr.ReferenceAsTaskParameter; return(doc.GetTaskParameter(p.taskName, p.paramName)); case MSBuildReferenceKind.ItemFunction: //FIXME: attempt overload resolution return(functionTypeProvider.GetItemFunctionInfo((string)rr.Reference)); case MSBuildReferenceKind.StaticPropertyFunction: //FIXME: attempt overload resolution (string className, string name) = ((string, string))rr.Reference; return(functionTypeProvider.GetStaticPropertyFunctionInfo(className, name)); case MSBuildReferenceKind.PropertyFunction: //FIXME: attempt overload resolution (MSBuildValueKind kind, string funcName) = ((MSBuildValueKind, string))rr.Reference; return(functionTypeProvider.GetPropertyFunctionInfo(kind, funcName)); case MSBuildReferenceKind.ClassName: return(functionTypeProvider.GetClassInfo((string)rr.Reference)); case MSBuildReferenceKind.Enum: return(functionTypeProvider.GetEnumInfo((string)rr.Reference)); case MSBuildReferenceKind.ConditionFunction: if (Builtins.ConditionFunctions.TryGetValue((string)rr.Reference, out var conditionFunctionName)) { return(conditionFunctionName); } return(null); } return(null); }
public static MSBuildResolveResult Resolve( XmlParser parser, ITextSource textSource, MSBuildDocument context, IFunctionTypeProvider functionTypeProvider) { int offset = parser.Position; //clones and connects nodes to their parents parser = parser.GetTreeParser(); var nodePath = parser.Nodes.ToList(); nodePath.Reverse(); //capture incomplete names, attributes and element values int i = offset; if (parser.CurrentState is XmlRootState && parser.Nodes.Peek() is XElement unclosedEl) { while (i < textSource.Length && InRootOrClosingTagState() && !unclosedEl.IsClosed) { parser.Push(textSource.GetCharAt(i++)); } } else { while (i < textSource.Length && InNameOrAttributeState()) { parser.Push(textSource.GetCharAt(i++)); } } //if nodes are incomplete, they won't get connected //HACK: the only way to reconnect them is reflection if (nodePath.Count > 1) { for (int idx = 1; idx < nodePath.Count; idx++) { var node = nodePath[idx]; if (node.Parent == null) { var parent = nodePath[idx - 1]; ParentProp.SetValue(node, parent); } } } //need to look up element by walking how the path, since at each level, if the parent has special children, //then that gives us information to identify the type of its children MSBuildLanguageElement languageElement = null; MSBuildLanguageAttribute languageAttribute = null; XElement el = null; XAttribute att = null; foreach (var node in nodePath) { if (node is XAttribute xatt && xatt.Name.Prefix == null) { att = xatt; languageAttribute = languageElement?.GetAttribute(att.Name.Name); break; } //if children of parent is known to be arbitrary data, don't go into it if (languageElement != null && languageElement.ValueKind == MSBuildValueKind.Data) { break; } //code completion is forgiving, all we care about best guess resolve for deepest child if (node is XElement xel && xel.Name.Prefix == null) { el = xel; languageElement = MSBuildLanguageElement.Get(el.Name.Name, languageElement); if (languageElement != null) { continue; } } languageElement = null; } if (languageElement == null) { return(null); } var rr = new MSBuildResolveResult { LanguageElement = languageElement, LanguageAttribute = languageAttribute, XElement = el, XAttribute = att }; var rv = new MSBuildResolveVisitor(offset, rr, functionTypeProvider); rv.Run(el, languageElement, textSource, context); return(rr); bool InNameOrAttributeState() => parser.CurrentState is XmlNameState || parser.CurrentState is XmlAttributeState || parser.CurrentState is XmlAttributeValueState; bool InRootOrClosingTagState() => parser.CurrentState is XmlRootState || parser.CurrentState is XmlNameState || parser.CurrentState is XmlClosingTagState; }