示例#1
0
 public MSBuildPropertyFunctionReferenceCollector(MSBuildValueKind valueKind, string functionName, IFunctionTypeProvider functionTypeProvider)
     : base(StripGetPrefix(functionName))
 {
     if (valueKind == MSBuildValueKind.Unknown)
     {
         valueKind = MSBuildValueKind.String;
     }
     this.valueKind            = valueKind;
     this.functionTypeProvider = functionTypeProvider;
 }
示例#2
0
        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}");
        }
示例#3
0
        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);
        }
示例#4
0
 public MSBuildResolveVisitor(int offset, MSBuildResolveResult rr, IFunctionTypeProvider functionTypeProvider)
 {
     this.offset = offset;
     this.rr     = rr;
     this.functionTypeProvider = functionTypeProvider;
 }
示例#5
0
 public MSBuildPropertyFunctionReferenceCollector(
     MSBuildValueKind valueKind, string functionName, IFunctionTypeProvider functionTypeProvider,
     Action <(int Offset, int Length, ReferenceUsage Usage)> reportResult)
示例#6
0
        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;
        }