Ejemplo n.º 1
0
        async Task <CompletionContext> GetExpressionCompletionsAsync(
            IAsyncCompletionSession session,
            ValueInfo info, TriggerState triggerState, ListKind listKind,
            int triggerLength, ExpressionNode triggerExpression,
            IReadOnlyList <ExpressionNode> comparandVariables,
            MSBuildResolveResult rr, SnapshotPoint triggerLocation,
            MSBuildRootDocument doc, CancellationToken token)
        {
            var kind = info.InferValueKindIfUnknown();

            if (!ValidateListPermitted(listKind, kind))
            {
                return(CompletionContext.Empty);
            }

            bool allowExpressions = kind.AllowExpressions();

            kind = kind.GetScalarType();

            if (kind == MSBuildValueKind.Data || kind == MSBuildValueKind.Nothing)
            {
                return(CompletionContext.Empty);
            }

            bool isValue = triggerState == TriggerState.Value;

            var items = new List <CompletionItem> ();

            if (comparandVariables != null && isValue)
            {
                foreach (var ci in ExpressionCompletion.GetComparandCompletions(doc, comparandVariables))
                {
                    items.Add(CreateCompletionItem(ci, XmlCompletionItemKind.AttributeValue));
                }
            }

            if (isValue)
            {
                switch (kind)
                {
                case MSBuildValueKind.NuGetID:
                    if (triggerExpression is ExpressionText t)
                    {
                        var packageNameItems = await GetPackageNameCompletions(session, doc, t.Value, token);

                        if (packageNameItems != null)
                        {
                            items.AddRange(packageNameItems);
                        }
                    }
                    break;

                case MSBuildValueKind.NuGetVersion: {
                    var packageVersionItems = await GetPackageVersionCompletions(doc, rr, token);

                    if (packageVersionItems != null)
                    {
                        items.AddRange(packageVersionItems);
                    }
                    break;
                }

                case MSBuildValueKind.Sdk:
                case MSBuildValueKind.SdkWithVersion: {
                    var sdkItems = await GetSdkCompletions(doc, token);

                    if (sdkItems != null)
                    {
                        items.AddRange(sdkItems);
                    }
                    break;
                }

                case MSBuildValueKind.Guid:
                    items.Add(CreateSpecialItem("New GUID", "Inserts a new GUID", KnownImages.Add, MSBuildSpecialCommitKind.NewGuid));
                    break;

                case MSBuildValueKind.Lcid:
                    items.AddRange(GetLcidCompletions());
                    break;
                }
            }

            //TODO: better metadata support
            IEnumerable <BaseInfo> cinfos;

            if (info.CustomType != null && info.CustomType.Values.Count > 0 && isValue)
            {
                cinfos = info.CustomType.Values;
            }
            else
            {
                //FIXME: can we avoid awaiting this unless we actually need to resolve a function? need to propagate async downwards
                await provider.FunctionTypeProvider.EnsureInitialized(token);

                cinfos = ExpressionCompletion.GetCompletionInfos(rr, triggerState, kind, triggerExpression, triggerLength, doc, provider.FunctionTypeProvider);
            }

            if (cinfos != null)
            {
                foreach (var ci in cinfos)
                {
                    items.Add(CreateCompletionItem(ci, XmlCompletionItemKind.AttributeValue));
                }
            }

            if ((allowExpressions && isValue) || triggerState == TriggerState.BareFunctionArgumentValue)
            {
                items.Add(CreateSpecialItem("$(", "Property reference", KnownImages.MSBuildProperty, MSBuildSpecialCommitKind.PropertyReference));
            }

            if (allowExpressions && isValue)
            {
                items.Add(CreateSpecialItem("@(", "Item reference", KnownImages.MSBuildItem, MSBuildSpecialCommitKind.ItemReference));
                if (IsMetadataAllowed(triggerExpression, rr))
                {
                    items.Add(CreateSpecialItem("%(", "Metadata reference", KnownImages.MSBuildItem, MSBuildSpecialCommitKind.MetadataReference));
                }
            }

            if (items.Count > 0)
            {
                return(CreateCompletionContext(items));
            }

            return(CompletionContext.Empty);
        }
Ejemplo n.º 2
0
        Task <ICompletionDataList> HandleExpressionCompletion(MSBuildResolveResult rr, CancellationToken token)
        {
            var doc = GetDocument();

            if (!ExpressionCompletion.IsPossibleExpressionCompletionContext(Tracker.Engine))
            {
                return(null);
            }

            string expression = GetAttributeOrElementTextToCaret();

            var triggerState = ExpressionCompletion.GetTriggerState(
                expression,
                rr.IsCondition(),
                out int triggerLength,
                out ExpressionNode triggerExpression,
                out IReadOnlyList <ExpressionNode> comparandVariables
                );

            if (triggerState == ExpressionCompletion.TriggerState.None)
            {
                return(null);
            }

            var info = rr.GetElementOrAttributeValueInfo(doc);

            if (info == null)
            {
                return(null);
            }

            var kind = MSBuildCompletionExtensions.InferValueKindIfUnknown(info);

            if (!ExpressionCompletion.ValidateListPermitted(ref triggerState, kind))
            {
                return(null);
            }

            bool allowExpressions = kind.AllowExpressions();

            kind = kind.GetScalarType();

            if (kind == MSBuildValueKind.Data || kind == MSBuildValueKind.Nothing)
            {
                return(null);
            }

            var list = new CompletionDataList {
                TriggerWordLength = triggerLength, AutoSelect = false
            };

            if (comparandVariables != null && triggerState == ExpressionCompletion.TriggerState.Value)
            {
                foreach (var ci in ExpressionCompletion.GetComparandCompletions(doc, comparandVariables))
                {
                    list.Add(new MSBuildCompletionData(ci, doc, rr, XmlCompletionData.DataType.XmlAttributeValue));
                }
            }

            if (triggerState == ExpressionCompletion.TriggerState.Value)
            {
                switch (kind)
                {
                case MSBuildValueKind.NuGetID:
                    return(GetPackageNameCompletions(doc, Editor.CaretOffset - triggerLength, triggerLength));

                case MSBuildValueKind.NuGetVersion:
                    return(GetPackageVersionCompletions(doc, rr, Editor.CaretOffset - triggerLength, triggerLength));

                case MSBuildValueKind.Sdk:
                case MSBuildValueKind.SdkWithVersion:
                    return(GetSdkCompletions(triggerLength, token));

                case MSBuildValueKind.Guid:
                    list.Add(new GenerateGuidCompletionData());
                    break;

                case MSBuildValueKind.Lcid:
                    foreach (var culture in System.Globalization.CultureInfo.GetCultures(System.Globalization.CultureTypes.AllCultures))
                    {
                        string name    = culture.Name;
                        string id      = culture.LCID.ToString();
                        string display = culture.DisplayName;
                        //insert multiple versions for matching on both the name and the number
                        list.Add(new CompletionData(id, null, display));
                        list.Add(new CompletionData(display, null, id, id));
                    }
                    break;
                }
            }

            //TODO: better metadata support

            IEnumerable <BaseInfo> cinfos;

            if (info.Values != null && info.Values.Count > 0 && triggerState == ExpressionCompletion.TriggerState.Value)
            {
                cinfos = info.Values;
            }
            else
            {
                cinfos = ExpressionCompletion.GetCompletionInfos(rr, triggerState, kind, triggerExpression, triggerLength, doc);
            }

            if (cinfos != null)
            {
                foreach (var ci in cinfos)
                {
                    list.Add(new MSBuildCompletionData(ci, doc, rr, XmlCompletionData.DataType.XmlAttributeValue));
                }
            }

            if (allowExpressions && triggerState == ExpressionCompletion.TriggerState.Value)
            {
                list.Add(new CompletionDataWithSkipCharAndRetrigger("$(", "md-variable", "Property value reference", "$(|)", ')'));
                list.Add(new CompletionDataWithSkipCharAndRetrigger("@(", "md-variable", "Item list reference", "@(|)", ')'));
            }

            if (list.Count > 0)
            {
                return(Task.FromResult <ICompletionDataList> (list));
            }

            return(null);
        }