Ejemplo n.º 1
0
        protected override void VisitValue(
            XElement element, XAttribute attribute,
            MSBuildElementSyntax resolvedElement, MSBuildAttributeSyntax resolvedAttribute,
            ValueInfo info, string value, int offset)
        {
            if (!IsTargetsFile && !IsPropsFile)
            {
                if (info.DefaultValue != null && string.Equals(info.DefaultValue, value))
                {
                    Document.Diagnostics.Add(CoreDiagnostics.HasDefaultValue, new TextSpan(offset, value.Length), DescriptionFormatter.GetKindNoun(info), info.Name, info.DefaultValue);
                }
            }

            //NOTE: doing this here means we can't check for deprecated constructs that don't have values, but there aren't any yet
            CheckDeprecated(info, (INamedXObject)attribute ?? element);

            // we skip calling base, and instead parse the expression with more options enabled
            // so that we can warn if the user is doing something likely invalid
            var kind    = MSBuildCompletionExtensions.InferValueKindIfUnknown(info);
            var options = kind.GetExpressionOptions() | ExpressionOptions.ItemsMetadataAndLists;

            var node = ExpressionParser.Parse(value, options, offset);

            VisitValueExpression(element, attribute, resolvedElement, resolvedAttribute, info, kind, node);
        }
Ejemplo n.º 2
0
        public static IEnumerable <BaseInfo> GetCompletionInfos(
            MSBuildResolveResult rr,
            TriggerState trigger, MSBuildValueKind kind,
            ExpressionNode triggerExpression, int triggerLength,
            MSBuildRootDocument doc)
        {
            switch (trigger)
            {
            case TriggerState.Value:
                return(MSBuildCompletionExtensions.GetValueCompletions(kind, doc, rr));

            case TriggerState.Item:
                return(doc.GetItems());

            case TriggerState.Metadata:
                return(doc.GetMetadata(null, true));

            case TriggerState.Property:
                return(doc.GetProperties(true));

            case TriggerState.MetadataOrItem:
                return(((IEnumerable <BaseInfo>)doc.GetItems()).Concat(doc.GetMetadata(null, true)));

            case TriggerState.DirectorySeparator:
                return(MSBuildCompletionExtensions.GetFilenameCompletions(kind, doc, triggerExpression, triggerLength));;

            case TriggerState.MethodName:
                return(FunctionCompletion.GetMethodNameCompletions(triggerExpression));
            }
            throw new InvalidOperationException();
        }
Ejemplo n.º 3
0
        protected override void VisitValue(
            XElement element, XAttribute attribute,
            MSBuildElementSyntax resolvedElement, MSBuildAttributeSyntax resolvedAttribute,
            ITypedSymbol valueDescriptor, string value, int offset)
        {
            if (!IsTargetsFile && !IsPropsFile && valueDescriptor is IHasDefaultValue hasDefault)
            {
                if (hasDefault.DefaultValue != null && string.Equals(hasDefault.DefaultValue, value, StringComparison.OrdinalIgnoreCase))
                {
                    Document.Diagnostics.Add(
                        CoreDiagnostics.HasDefaultValue, attribute?.Span ?? element.OuterSpan,
                        ImmutableDictionary <string, object> .Empty.Add("Info", valueDescriptor),
                        DescriptionFormatter.GetKindNoun(valueDescriptor), valueDescriptor.Name, hasDefault.DefaultValue);
                }
            }


            if (valueDescriptor is IDeprecatable deprecatable)
            {
                CheckDeprecated(deprecatable, (INamedXObject)attribute ?? element);
            }

            // we skip calling base, and instead parse the expression with more options enabled
            // so that we can warn if the user is doing something likely invalid
            var kind    = MSBuildCompletionExtensions.InferValueKindIfUnknown(valueDescriptor);
            var options = kind.GetExpressionOptions() | ExpressionOptions.ItemsMetadataAndLists;

            var node = ExpressionParser.Parse(value, options, offset);

            VisitValueExpression(element, attribute, resolvedElement, resolvedAttribute, valueDescriptor, kind, node);
        }
Ejemplo n.º 4
0
        public static IEnumerable <ISymbol> GetComparandCompletions(MSBuildRootDocument doc, IReadOnlyList <ExpressionNode> variables)
        {
            var names = new HashSet <string> ();

            foreach (var variable in variables)
            {
                VariableInfo info;
                switch (variable)
                {
                case ExpressionProperty ep:
                    if (ep.IsSimpleProperty)
                    {
                        info = doc.GetProperty(ep.Name, true) ?? new PropertyInfo(ep.Name, null, false);
                        break;
                    }
                    continue;

                case ExpressionMetadata em:
                    info = doc.GetMetadata(em.ItemName, em.MetadataName, true) ?? new MetadataInfo(em.MetadataName, null, false);
                    break;

                default:
                    continue;
                }

                if (info == null)
                {
                    continue;
                }

                IEnumerable <ISymbol> cinfos;
                if (info.CustomType != null && info.CustomType.Values.Count > 0)
                {
                    cinfos = info.CustomType.Values;
                }
                else
                {
                    var kind = info.InferValueKindIfUnknown();
                    cinfos = MSBuildCompletionExtensions.GetValueCompletions(kind, doc);
                }

                if (cinfos != null)
                {
                    foreach (var ci in cinfos)
                    {
                        if (names.Add(ci.Name))
                        {
                            yield return(ci);
                        }
                    }
                }
            }
        }
Ejemplo n.º 5
0
 public static MSBuildNavigationResult GetPathFromNode(ExpressionNode node, MSBuildRootDocument document)
 {
     try {
         var path = MSBuildCompletionExtensions.EvaluateExpressionAsPaths(node, document).FirstOrDefault();
         if (path != null && File.Exists(path))
         {
             return(new MSBuildNavigationResult(
                        new [] { path }, node.Offset, node.Length
                        ));
         }
     } catch (Exception ex) {
         Core.LoggingService.LogError($"Error checking path for file '{node}'", ex);
     }
     return(null);
 }
Ejemplo n.º 6
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}");
        }
        protected override void VisitValue(
            XElement element, XAttribute attribute,
            MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute,
            ValueInfo info, string value, int offset)
        {
            if (info.DefaultValue != null && string.Equals(info.DefaultValue, value))
            {
                AddWarning($"{info.GetTitleCaseKindName ()} has default value", offset, value.Length);
            }

            // we skip calling base, and instead parse the expression with more options enabled
            // so that we can warn if the user is doing something likely invalid
            var kind    = MSBuildCompletionExtensions.InferValueKindIfUnknown(info);
            var options = kind.GetExpressionOptions() | ExpressionOptions.ItemsMetadataAndLists;

            var node = ExpressionParser.Parse(value, options, offset);

            VisitValueExpression(element, attribute, resolvedElement, resolvedAttribute, info, kind, node);
        }
        protected virtual void VisitValue(
            XElement element, XAttribute attribute,
            MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute,
            ValueInfo info, string value, int offset)
        {
            var kind = MSBuildCompletionExtensions.InferValueKindIfUnknown(info);

            if (!kind.AllowExpressions())
            {
                VisitValueExpression(
                    element, attribute, resolvedElement, resolvedAttribute,
                    info, kind, new ExpressionText(offset, value, true));
                return;
            }

            var expression = ExpressionParser.Parse(value, kind.GetExpressionOptions(), offset);

            VisitValueExpression(
                element, attribute, resolvedElement, resolvedAttribute,
                info, kind, expression);
        }
        protected virtual void VisitValue(
            XElement element, XAttribute attribute,
            MSBuildElementSyntax resolvedElement, MSBuildAttributeSyntax resolvedAttribute,
            ITypedSymbol valueDescriptor, string value, int offset)
        {
            var kind = MSBuildCompletionExtensions.InferValueKindIfUnknown(valueDescriptor);

            if (!kind.AllowExpressions())
            {
                VisitValueExpression(
                    element, attribute, resolvedElement, resolvedAttribute,
                    valueDescriptor, kind, new ExpressionText(offset, value, true));
                return;
            }

            var expression =
                valueDescriptor?.ValueKind == MSBuildValueKind.Condition
                                        ? ExpressionParser.ParseCondition(value, offset)
                                        : ExpressionParser.Parse(value, kind.GetExpressionOptions(), offset);

            VisitValueExpression(
                element, attribute, resolvedElement, resolvedAttribute,
                valueDescriptor, kind, expression);
        }
Ejemplo n.º 10
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);
        }
Ejemplo n.º 11
0
        async Task <CompletionContext> GetExpressionCompletionsAsync(ValueInfo info, ExpressionCompletion.TriggerState triggerState, ExpressionCompletion.ListKind listKind, int triggerLength, ExpressionNode triggerExpression, IReadOnlyList <ExpressionNode> comparandVariables, MSBuildResolveResult rr, SnapshotPoint triggerLocation, MSBuildRootDocument doc, CancellationToken token)
        {
            var kind = MSBuildCompletionExtensions.InferValueKindIfUnknown(info);

            if (!ExpressionCompletion.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 == ExpressionCompletion.TriggerState.Value ||
                           triggerState == ExpressionCompletion.TriggerState.PropertyOrValue ||
                           triggerState == ExpressionCompletion.TriggerState.ItemOrValue ||
                           triggerState == ExpressionCompletion.TriggerState.MetadataOrValue;

            var items = new List <CompletionItem> ();

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

            if (isValue)
            {
                switch (kind)
                {
                case MSBuildValueKind.NuGetID:
                    return(await GetPackageNameCompletions(doc, triggerLocation.Position - triggerLength, triggerLength));

                case MSBuildValueKind.NuGetVersion:
                    return(await GetPackageVersionCompletions(doc, rr));

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

                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.Values != null && info.Values.Count > 0 && isValue)
            {
                cinfos = info.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, doc, rr));
                }
            }

            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));
                //FIXME metadata
            }

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

            return(CompletionContext.Empty);
        }