Beispiel #1
0
        /// <summary>
        /// Gets the of a markup extension at the given position.
        /// </summary>
        /// <param name="info">The markup extension data to parse.</param>
        /// <param name="offset">The offset to look at.</param>
        /// <returns>
        /// A string, if the at offset is the extension type. <br />
        /// An AttributeValue, if at the offset is a positional argument. <br />
        /// A KeyValuePair&lt;string, AttributeValue>, if at the offset is a named argument.
        /// </returns>
        /// <remarks>offset != Caret.Offset, but offset == ValueStartOffset</remarks>
        public static object GetMarkupDataAtPosition(MarkupExtensionInfo info, int offset)
        {
            object previous  = info.ExtensionType;
            int    endOffset = info.StartOffset + info.ExtensionType.Length;

            foreach (var item in info.PositionalArguments)
            {
                if (item.StartOffset <= offset && offset <= item.EndOffset)
                {
                    previous = item.IsString ? item : GetMarkupDataAtPosition(item.ExtensionValue, offset);
                }

                endOffset = item.EndOffset;
            }

            foreach (var pair in info.NamedArguments)
            {
                if (pair.Value.StartOffset <= offset && offset <= pair.Value.EndOffset)
                {
                    previous = pair.Value.IsString ? pair : GetMarkupDataAtPosition(pair.Value.ExtensionValue, offset);
                }
                else if (endOffset <= offset && offset <= pair.Value.StartOffset)
                {
                    previous = pair;
                }

                endOffset = pair.Value.EndOffset;
            }

            return(previous);
        }
        string GetTypeNameFromTypeExtension(MarkupExtensionInfo info, XamlContext context)
        {
            IType type = ResolveExpression(info.ExtensionType, context).Type;

            if (type.Kind == TypeKind.Unknown)
            {
                type = ResolveExpression(info.ExtensionType + "Extension", context).Type;
            }

            if (type.FullName != "System.Windows.Markup.TypeExtension")
            {
                return(string.Empty);
            }

            var item = info.PositionalArguments.FirstOrDefault();

            if (item != null && item.IsString)
            {
                return(item.StringValue);
            }
            if (info.NamedArguments.TryGetValue("typename", out item))
            {
                if (item.IsString)
                {
                    return(item.StringValue);
                }
            }

            return(string.Empty);
        }
        /// <remarks>offset != Caret.Offset, but offset == ValueStartOffset</remarks>
        public static MarkupExtensionInfo GetMarkupExtensionAtPosition(MarkupExtensionInfo info, int offset)
        {
            MarkupExtensionInfo tmp = info;

            foreach (var item in info.PositionalArguments)
            {
                int endOffset = item.EndOffset;
                if (!item.IsClosed)
                {
                    endOffset++;
                }
                if (item.StartOffset < offset && offset < endOffset)
                {
                    tmp = item.IsString ? tmp : GetMarkupExtensionAtPosition(item.ExtensionValue, offset);
                }
            }

            foreach (var pair in info.NamedArguments)
            {
                int endOffset = pair.Value.EndOffset;
                if (!pair.Value.IsClosed)
                {
                    endOffset++;
                }
                if (pair.Value.StartOffset < offset && offset < endOffset)
                {
                    tmp = pair.Value.IsString ? tmp : GetMarkupExtensionAtPosition(pair.Value.ExtensionValue, offset);
                }
            }

            return(tmp);
        }
 static void TryAddNamedArgument(this MarkupExtensionInfo info, string name, AttributeValue value)
 {
     if (!info.NamedArguments.ContainsKey(name))
     {
         info.NamedArguments.Add(name, value);
     }
 }
        public AttributeValue(MarkupExtensionInfo value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            this.extensionValue = value;
        }
Beispiel #6
0
        ResolveResult ResolveMarkupExtension(string expression)
        {
            if (context.AttributeValue.IsString)
            {
                return(null);
            }

            object data = Utils.GetMarkupDataAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset);

            // resolve markup extension type
            if ((data as string) == expression)
            {
                return(ResolveElementName(expression + "Extension") ?? ResolveElementName(expression));
            }
            else
            {
                MarkupExtensionInfo info          = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset);
                TypeResolveResult   extensionType = (ResolveElementName(info.ExtensionType + "Extension") ?? ResolveElementName(info.ExtensionType)) as TypeResolveResult;
                if (extensionType != null && extensionType.ResolvedType != null)
                {
                    var value = data as AttributeValue;

                    switch (extensionType.ResolvedType.FullyQualifiedName)
                    {
                    case "System.Windows.Markup.StaticExtension":
                    case "System.Windows.Markup.TypeExtension":
                        if (value != null && value.IsString)
                        {
                            return(ResolveElementName(expression) ?? ResolveAttribute(expression));
                        }
                        goto default;                                 // "fall through"

                    default:
                        if (data is KeyValuePair <string, AttributeValue> )
                        {
                            var pair   = (KeyValuePair <string, AttributeValue>)data;
                            var member = ResolveNamedAttribute(pair.Key);
                            if (pair.Value.StartOffset + pair.Key.Length >= context.ValueStartOffset)
                            {
                                return(member);
                            }
                            else
                            {
                                if (pair.Value.IsString && member != null)
                                {
                                    return(ResolveAttributeValue(member.ResolvedMember, expression) ?? ResolveElementName(expression));
                                }
                            }
                        }
                        break;
                    }
                }

                return(null);
            }
        }
Beispiel #7
0
        MemberResolveResult ResolveNamedAttribute(string expression)
        {
            MarkupExtensionInfo info          = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset);
            TypeResolveResult   extensionType = (ResolveElementName(info.ExtensionType + "Extension") ?? ResolveElementName(info.ExtensionType)) as TypeResolveResult;

            if (extensionType != null && extensionType.ResolvedType != null)
            {
                return(ResolvePropertyName(extensionType.ResolvedType, expression, false));
            }

            return(null);
        }
        public ResolveResult ResolveAttributeValue(string expression, XamlContext context)
        {
            if (!context.InAttributeValueOrMarkupExtension)
            {
                return(ErrorResolveResult.UnknownError);
            }
            if (context.AttributeValue.IsString)
            {
                return(ResolveExpression(expression, context));
            }
            MarkupExtensionInfo info = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset);
            object data = Utils.GetMarkupDataAtPosition(info, context.ValueStartOffset);

            IType extensionType = ResolveExpression(info.ExtensionType, context).Type;

            if (extensionType.Kind == TypeKind.Unknown)
            {
                extensionType = ResolveExpression(info.ExtensionType + "Extension", context).Type;
            }

            if (data is KeyValuePair <string, AttributeValue> )
            {
                var kv = (KeyValuePair <string, AttributeValue>)data;
                if (kv.Value.StartOffset >= context.ValueStartOffset)
                {
                    IProperty member = extensionType.GetProperties(p => p.Name == expression).FirstOrDefault();
                    if (member != null)
                    {
                        return(new MemberResolveResult(new TypeResolveResult(extensionType), member));
                    }
                    return(new UnknownMemberResolveResult(extensionType, expression, EmptyList <IType> .Instance));
                }
                else
                {
                }
            }

            return(ResolveExpression(expression, context));
        }
Beispiel #9
0
        /// <remarks>returns true if elements from named args completion should be added afterwards.</remarks>
        bool DoPositionalArgsCompletion(XamlCompletionItemList list, XamlCompletionContext context, MarkupExtensionInfo markup, IType type)
        {
            switch (type.FullName)
            {
            case "System.Windows.Markup.ArrayExtension":
            case "System.Windows.Markup.NullExtension":
                // x:Null/x:Array does not need completion, ignore it
                break;

            case "System.Windows.Markup.StaticExtension":
                if (context.AttributeValue.ExtensionValue.PositionalArguments.Count <= 1)
                {
                    return(DoStaticExtensionCompletion(list, context));
                }
                break;

            case "System.Windows.Markup.TypeExtension":
                if (context.AttributeValue.ExtensionValue.PositionalArguments.Count <= 1)
                {
                    list.Items.AddRange(GetClassesFromContext(context).FlattenToList());
                    AttributeValue selItem = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset)
                                             .PositionalArguments.LastOrDefault();
                    string word = context.Editor.GetWordBeforeCaret().TrimEnd();
                    if (selItem != null && selItem.IsString && word == selItem.StringValue)
                    {
                        list.PreselectionLength = selItem.StringValue.Length;
                    }
                }
                break;

            default:
                var ctors = type.GetMethods(m => m.IsPublic && m.IsConstructor && m.Parameters.Count >= markup.PositionalArguments.Count + 1);
                if (context.Forced)
                {
                    return(true);
                }
                if (ctors.Any() || markup.PositionalArguments.Count == 0)
                {
                    return(false);
                }
                break;
            }

            return(true);
        }
Beispiel #10
0
        void DoNamedArgsCompletion(XamlCompletionItemList list, XamlCompletionContext context, IType type, MarkupExtensionInfo markup)
        {
            if (markup.NamedArguments.Count > 0 && !context.Editor.GetWordBeforeCaret().StartsWith(",", StringComparison.OrdinalIgnoreCase))
            {
                int lastStart = markup.NamedArguments.Max(i => i.Value.StartOffset);
                var item      = markup.NamedArguments.First(p => p.Value.StartOffset == lastStart);

                if (context.RawAttributeValue.EndsWith("=", StringComparison.OrdinalIgnoreCase) ||
                    (item.Value.IsString && item.Value.StringValue.EndsWith(context.Editor.GetWordBeforeCaretExtended(), StringComparison.Ordinal)))
                {
                    var resolver            = new XamlResolver(compilation);
                    MemberResolveResult mrr = resolver.ResolveAttributeValue(item.Key, context) as MemberResolveResult;
                    if (mrr != null && mrr.Member != null && mrr.Member.ReturnType != null)
                    {
                        IType memberType = mrr.Member.ReturnType;
                        list.Items.AddRange(MemberCompletion(context, memberType, string.Empty));
                    }
                    return;
                }
            }

            list.Items.AddRange(type.GetProperties().Where(p => p.CanSet && p.IsPublic).Select(p => new XamlCompletionItem(p.Name + "=", p)));
        }
        static MarkupExtensionInfo Parse(string text, int offset)
        {
            var    info         = new MarkupExtensionInfo();
            string argumentName = null;
            MarkupExtensionTokenizer tokenizer = new MarkupExtensionTokenizer(text);

            MarkupExtensionToken token = null;

            try {
                token = tokenizer.NextToken();

                while (token.Kind != MarkupExtensionTokenKind.EndOfFile)
                {
                    switch (token.Kind)
                    {
                    case MarkupExtensionTokenKind.OpenBrace:
                        info.StartOffset = token.StartOffset + offset;
                        break;

                    case MarkupExtensionTokenKind.CloseBrace:
                        info.EndOffset = token.EndOffset + offset;
                        break;

                    case MarkupExtensionTokenKind.TypeName:
                        info.ExtensionType = token.Value;
                        break;

                    case MarkupExtensionTokenKind.MemberName:
                        // if there is an open member without a value add the member name
                        if (argumentName != null)
                        {
                            info.TryAddNamedArgument(argumentName, ParseValue("", token.EndOffset + offset));
                        }
                        argumentName = token.Value;
                        break;

                    case MarkupExtensionTokenKind.String:
                        if (argumentName != null)
                        {
                            info.TryAddNamedArgument(argumentName, ParseValue(token.Value, token.StartOffset + offset));
                            argumentName = null;
                        }
                        else
                        {
                            info.PositionalArguments.Add(ParseValue(token.Value, token.StartOffset + offset));
                        }
                        break;
                    }

                    token = tokenizer.NextToken();
                }
            } catch (MarkupExtensionParseException) {
                // ignore parser errors
            } finally {
                if (token != null && argumentName != null)
                {
                    info.TryAddNamedArgument(argumentName, ParseValue(token.Value, token.StartOffset + offset));
                }
            }

            return(info);
        }