Ejemplo n.º 1
0
        private int BuildCompletionsForMarkupExtension(MetadataProperty property, List <Completion> completions, string fullText, XmlParser state, string data, string currentAssemblyName)
        {
            int?forcedStart = null;
            var ext         = MarkupExtensionParser.Parse(data);

            var transformedName = (ext.ElementName ?? "").Trim();

            if (_helper.LookupType(transformedName)?.IsMarkupExtension != true)
            {
                transformedName += "Extension";
            }

            if (ext.State == MarkupExtensionParser.ParserStateType.StartElement)
            {
                completions.AddRange(_helper.FilterTypeNames(ext.ElementName, markupExtensionsOnly: true)
                                     .Select(t => t.EndsWith("Extension") ? t.Substring(0, t.Length - "Extension".Length) : t)
                                     .Select(t => new Completion(t, CompletionKind.MarkupExtension)));
            }
            if (ext.State == MarkupExtensionParser.ParserStateType.StartAttribute ||
                ext.State == MarkupExtensionParser.ParserStateType.InsideElement)
            {
                if (ext.State == MarkupExtensionParser.ParserStateType.InsideElement)
                {
                    forcedStart = data.Length;
                }

                completions.AddRange(_helper.FilterPropertyNames(transformedName, ext.AttributeName ?? "", attached: false, hasSetter: true)
                                     .Select(x => new Completion(x, x + "=", x, CompletionKind.Property)));

                var attribName = ext.AttributeName ?? "";
                var t          = _helper.LookupType(transformedName);

                bool ctorArgument = ext.AttributesCount == 0;
                //skip ctor hints when some property is already set
                if (t != null && t.IsMarkupExtension && t.SupportCtorArgument != MetadataTypeCtorArgument.None && ctorArgument)
                {
                    if (t.SupportCtorArgument == MetadataTypeCtorArgument.HintValues)
                    {
                        if (t.HasHintValues)
                        {
                            completions.AddRange(GetHintCompletions(t, attribName));
                        }
                    }
                    else if (attribName.Contains("."))
                    {
                        if (t.SupportCtorArgument != MetadataTypeCtorArgument.Type)
                        {
                            var split = attribName.Split('.');
                            var type  = split[0];
                            var prop  = split[1];

                            var mType = _helper.LookupType(type);
                            if (mType != null && t.SupportCtorArgument == MetadataTypeCtorArgument.HintValues)
                            {
                                var hints = FilterHintValues(mType, prop, currentAssemblyName, state);
                                completions.AddRange(hints.Select(x => new Completion(x, $"{type}.{x}", x, GetCompletionKindForHintValues(mType))));
                            }

                            var props = _helper.FilterPropertyNames(type, prop, attached: false, hasSetter: false, staticGetter: true);
                            completions.AddRange(props.Select(x => new Completion(x, $"{type}.{x}", x, CompletionKind.StaticProperty)));
                        }
                    }
                    else
                    {
                        var types = _helper.FilterTypeNames(attribName,
                                                            staticGettersOnly: t.SupportCtorArgument == MetadataTypeCtorArgument.Object);

                        completions.AddRange(types.Select(x => new Completion(x, x, x, CompletionKind.Class)));

                        if (property?.Type?.HasHintValues == true)
                        {
                            completions.Add(new Completion(property.Type.Name, property.Type.Name + ".", property.Type.Name, CompletionKind.Class));
                        }
                    }
                }
                else
                {
                    var defaultProp = t?.Properties.FirstOrDefault(p => p.Name == "");
                    if (defaultProp?.Type?.HasHintValues ?? false)
                    {
                        completions.AddRange(GetHintCompletions(defaultProp.Type, ext.AttributeName ?? "", currentAssemblyName, fullText, state));
                    }
                }
            }
            if (ext.State == MarkupExtensionParser.ParserStateType.AttributeValue ||
                ext.State == MarkupExtensionParser.ParserStateType.BeforeAttributeValue)
            {
                var prop = _helper.LookupProperty(transformedName, ext.AttributeName);
                if (prop?.Type?.HasHintValues == true)
                {
                    var start = data.Substring(ext.CurrentValueStart);
                    completions.AddRange(GetHintCompletions(prop.Type, start, currentAssemblyName, fullText, state));
                }
            }

            return(forcedStart ?? ext.CurrentValueStart);
        }
Ejemplo n.º 2
0
        public CompletionSet GetCompletions(Metadata metadata, string text, int pos, string currentAssemblyName = null)
        {
            _helper.SetMetadata(metadata, text, currentAssemblyName);

            if (_helper.Metadata == null)
            {
                return(null);
            }

            if (text.Length == 0 || pos == 0)
            {
                return(null);
            }
            text = text.Substring(0, pos);
            var state = XmlParser.Parse(text);

            var completions = new List <Completion>();


            var curStart = state.CurrentValueStart ?? 0;

            if (state.State == XmlParser.ParserState.StartElement)
            {
                var tagName = state.TagName;
                if (tagName.Contains("."))
                {
                    var dotPos   = tagName.IndexOf(".");
                    var typeName = tagName.Substring(0, dotPos);
                    var compName = tagName.Substring(dotPos + 1);
                    curStart = curStart + dotPos + 1;
                    completions.AddRange(_helper.FilterPropertyNames(typeName, compName).Select(p => new Completion(p, CompletionKind.Enum)));
                }
                else
                {
                    completions.AddRange(_helper.FilterTypeNames(tagName).Select(x => new Completion(x, CompletionKind.Class)));
                }
            }
            else if (state.State == XmlParser.ParserState.InsideElement ||
                     state.State == XmlParser.ParserState.StartAttribute)
            {
                if (state.State == XmlParser.ParserState.InsideElement)
                {
                    curStart = pos; //Force completion to be started from current cursor position
                }
                if (state.AttributeName?.Contains(".") == true)
                {
                    var dotPos = state.AttributeName.IndexOf('.');
                    curStart += dotPos + 1;
                    var split = state.AttributeName.Split(new[] { '.' }, 2);
                    completions.AddRange(_helper.FilterPropertyNames(split[0], split[1], true)
                                         .Select(x => new Completion(x, x + "=\"\"", x, CompletionKind.Property, x.Length + 2)));
                }
                else
                {
                    completions.AddRange(_helper.FilterPropertyNames(state.TagName, state.AttributeName)
                                         .Select(x => new Completion(x, x + "=\"\"", x, CompletionKind.Property, x.Length + 2)));

                    var targetType = _helper.LookupType(state.TagName);

                    if (targetType?.IsAvaloniaObjectType == true)
                    {
                        completions.AddRange(
                            _helper.FilterTypeNames(state.AttributeName, true)
                            .Select(v => new Completion(v, v + ".", v, CompletionKind.Property)));
                    }
                }
            }
            else if (state.State == XmlParser.ParserState.AttributeValue)
            {
                MetadataProperty prop;
                if (state.AttributeName.Contains("."))
                {
                    //Attached property
                    var split = state.AttributeName.Split('.');
                    prop = _helper.LookupProperty(split[0], split[1]);
                }
                else
                {
                    prop = _helper.LookupProperty(state.TagName, state.AttributeName);
                }

                //Markup extension, ignore everything else
                if (state.AttributeValue.StartsWith("{"))
                {
                    curStart = state.CurrentValueStart.Value +
                               BuildCompletionsForMarkupExtension(prop, completions,
                                                                  text.Substring(state.CurrentValueStart.Value));
                }
                else
                {
                    if (prop?.Type?.HasHintValues == true)
                    {
                        var search = text.Substring(state.CurrentValueStart.Value);
                        if (prop.Type.IsCompositeValue)
                        {
                            var last = search.Split(' ', ',').LastOrDefault();
                            curStart = curStart + search.Length - last?.Length ?? 0;
                            search   = last;
                        }

                        completions.AddRange(GetHintCompletions(search, prop.Type.HintValues));
                    }
                    else if (state.AttributeName == "xmlns" || state.AttributeName.Contains("xmlns:"))
                    {
                        if (state.AttributeValue.StartsWith("clr-namespace:"))
                        {
                            completions.AddRange(
                                metadata.Namespaces.Keys.Where(v => v.StartsWith(state.AttributeValue))
                                .Select(v => new Completion(v.Substring("clr-namespace:".Length), v, v, CompletionKind.Namespace)));
                        }
                        else
                        {
                            if ("clr-namespace:".StartsWith(state.AttributeValue))
                            {
                                completions.Add(new Completion("clr-namespace:", CompletionKind.Namespace));
                            }
                            completions.AddRange(
                                metadata.Namespaces.Keys.Where(
                                    v =>
                                    v.StartsWith(state.AttributeValue) &&
                                    !v.StartsWith("clr-namespace"))
                                .Select(v => new Completion(v, CompletionKind.Namespace)));
                        }
                    }
                }
            }

            if (completions.Count != 0)
            {
                return new CompletionSet()
                       {
                           Completions = completions, StartPosition = curStart
                       }
            }
            ;
            return(null);
        }

        List <Completion> GetHintCompletions(string entered, string[] values)
        {
            var completions = new List <Completion>();

            foreach (var val in values)
            {
                if (val.StartsWith(entered, StringComparison.OrdinalIgnoreCase))
                {
                    completions.Add(new Completion(val, CompletionKind.Enum));
                }
            }
            return(completions);
        }

        int BuildCompletionsForMarkupExtension(MetadataProperty property, List <Completion> completions, string data)
        {
            int?forcedStart = null;
            var ext         = MarkupExtensionParser.Parse(data);

            var transformedName = (ext.ElementName ?? "").Trim();

            if (_helper.LookupType(transformedName)?.IsMarkupExtension != true)
            {
                transformedName += "Extension";
            }

            if (ext.State == MarkupExtensionParser.ParserStateType.StartElement)
            {
                completions.AddRange(_helper.FilterTypeNames(ext.ElementName, markupExtensionsOnly: true)
                                     .Select(t => t.EndsWith("Extension") ? t.Substring(0, t.Length - "Extension".Length) : t)
                                     .Select(t => new Completion(t, CompletionKind.MarkupExtension)));
            }
            if (ext.State == MarkupExtensionParser.ParserStateType.StartAttribute ||
                ext.State == MarkupExtensionParser.ParserStateType.InsideElement)
            {
                if (ext.State == MarkupExtensionParser.ParserStateType.InsideElement)
                {
                    forcedStart = data.Length;
                }
                completions.AddRange(_helper.FilterPropertyNames(transformedName, ext.AttributeName ?? "")
                                     .Select(x => new Completion(x, x + "=", x, CompletionKind.MarkupExtension)));

                var attribName = ext.AttributeName ?? "";
                var t          = _helper.LookupType(transformedName);

                bool ctorArgument = ext.AttributesCount == 0;
                //skip ctor hints when some property is already set
                if (t != null && t.IsMarkupExtension && t.SupportCtorArgument != MetadataTypeCtorArgument.None && ctorArgument)
                {
                    if (t.SupportCtorArgument == MetadataTypeCtorArgument.HintValues)
                    {
                        if (t.HasHintValues)
                        {
                            completions.AddRange(GetHintCompletions(attribName, t.HintValues));
                        }
                    }
                    else if (attribName.Contains("."))
                    {
                        if (t.SupportCtorArgument != MetadataTypeCtorArgument.Type)
                        {
                            var split = attribName.Split('.');
                            var type  = split[0];
                            var prop  = split[1];
                            var props = _helper.FilterPropertyNames(type, prop, staticGettersOnly: true, hintValues: true);
                            completions.AddRange(props.Select(x => new Completion(x, $"{type}.{x}", x, CompletionKind.MarkupExtension)));
                        }
                    }
                    else
                    {
                        var types = _helper.FilterTypeNames(attribName,
                                                            staticGettersOnly: t.SupportCtorArgument == MetadataTypeCtorArgument.Object);

                        completions.AddRange(types.Select(x => new Completion(x, x, x, CompletionKind.Class)));

                        if (property?.Type?.HasHintValues == true)
                        {
                            completions.Add(new Completion(property.Type.Name, property.Type.Name + ".", property.Type.Name, CompletionKind.Class));
                        }
                    }
                }
            }
            if (ext.State == MarkupExtensionParser.ParserStateType.AttributeValue ||
                ext.State == MarkupExtensionParser.ParserStateType.BeforeAttributeValue)
            {
                var prop = _helper.LookupProperty(transformedName, ext.AttributeName);
                if (prop?.Type?.HasHintValues == true)
                {
                    var enumStart       = data.Substring(ext.CurrentValueStart);
                    var enumCompletions = GetHintCompletions(enumStart, prop.Type.HintValues);
                    completions.AddRange(enumCompletions);
                }
            }

            return(forcedStart ?? ext.CurrentValueStart);
        }
Ejemplo n.º 3
0
        private IEnumerable <Completion> FilterHintValuesForBindingPath(MetadataType bindingPathType, string entered, string currentAssemblyName, string fullText, XmlParser state)
        {
            IEnumerable <Completion> forPropertiesFromType(MetadataType filterType, string filter, Func <string, string> fmtInsertText = null)
            {
                if (filterType != null)
                {
                    foreach (var propertyName in _helper.FilterPropertyNames(filterType, filter, false, false))
                    {
                        yield return(new Completion(propertyName, fmtInsertText?.Invoke(propertyName) ?? propertyName, propertyName, CompletionKind.Property));
                    }
                }
            }

            IEnumerable <Completion> forProperties(string filterType, string filter, Func <string, string> fmtInsertText = null)
            => forPropertiesFromType(_helper.LookupType(filterType ?? ""), filter, fmtInsertText);

            if (string.IsNullOrEmpty(entered))
            {
                return(forProperties(state.FindParentAttributeValue("(x\\:)?DataType"), entered));
            }

            var values = entered.Split('.');

            if (values.Length == 1)
            {
                if (values[0].StartsWith("$parent["))
                {
                    return(_helper.FilterTypes(entered.Substring("$parent[".Length))
                           .Select(v => new Completion(v.Key, $"$parent[{v.Key}].", v.Key, CompletionKind.Class)));
                }
                else if (values[0].StartsWith("#"))
                {
                    var nameMatch = Regex.Matches(fullText, $"\\s(?:(x\\:)?Name)=\"(?<AttribValue>[\\w\\:\\s\\|\\.]+)\"");

                    if (nameMatch.Count > 0)
                    {
                        var result = new List <Completion>();
                        foreach (Match m in nameMatch)
                        {
                            if (m.Success)
                            {
                                var name = m.Groups["AttribValue"].Value;
                                result.Add(new Completion(name, $"#{name}", name, CompletionKind.Class));
                            }
                        }
                        return(result);
                    }

                    return(Array.Empty <Completion>());
                }

                return(forProperties(state.FindParentAttributeValue("(x\\:)?DataType"), entered));
            }

            string type = values[0];

            int i;

            if (values[0].StartsWith("$"))
            {
                i    = 1;
                type = "Control";
                if (values[0] == "$self") //current control type
                {
                    type = state.GetParentTagName(0);
                }
                else if (values[0] == "$parent") //parent control in the xaml
                {
                    type = state.GetParentTagName(1) ?? "Control";
                }
                else if (values[0].StartsWith("$parent[")) //extract parent type
                {
                    type = values[0].Substring("$parent[".Length, values[0].Length - "$parent[".Length - 1);
                }
            }
            else if (values[0].StartsWith("#"))
            {
                i = 1;
                //todo: find the control type etc ???
                type = "Control";
            }
            else
            {
                i    = 0;
                type = state.FindParentAttributeValue("(x\\:)?DataType");
            }

            var mdType = _helper.LookupType(type ?? "");

            while (mdType != null && i < values.Length - 1 && !string.IsNullOrEmpty(values[i]))
            {
                if (i <= 1 && values[i] == "DataContext")
                {
                    //assume parent.datacontext is x:datatype so we have some intelisence
                    type   = state.FindParentAttributeValue("(x\\:)?DataType");
                    mdType = _helper.LookupType(type);
                }
                else
                {
                    mdType = mdType.Properties.FirstOrDefault(p => p.Name == values[i])?.Type;
                    type   = mdType?.FullName;
                }
                i++;
            }

            return(forPropertiesFromType(mdType, values[i], p => $"{string.Join(".", values.Take(i).ToArray())}.{p}"));
        }
Ejemplo n.º 4
0
        private List <Completion> GetHintCompletions(MetadataType type, string entered, string currentAssemblyName = null, string fullText = null, XmlParser state = null)
        {
            var kind = GetCompletionKindForHintValues(type);

            var completions = FilterHintValues(type, entered, currentAssemblyName, state)
                              .Select(val => new Completion(val, kind)).ToList();

            if (type.FullName == "{BindingPath}" && state != null)
            {
                completions.AddRange(FilterHintValuesForBindingPath(type, entered, currentAssemblyName, fullText, state));
            }
            return(completions);
        }
Ejemplo n.º 5
0
        public IEnumerable <string> FilterHintValues(MetadataType type, string entered, string currentAssemblyName, XmlParser state)
        {
            entered = entered ?? "";

            if (type == null)
            {
                yield break;
            }

            if (!string.IsNullOrEmpty(currentAssemblyName) && type.XamlContextHintValuesFunc != null)
            {
                foreach (var v in type.XamlContextHintValuesFunc(currentAssemblyName, type, null).Where(v => v.StartsWith(entered, StringComparison.OrdinalIgnoreCase)))
                {
                    yield return(v);
                }
            }

            foreach (var v in type.HintValues.Where(v => v.StartsWith(entered, StringComparison.OrdinalIgnoreCase)))
            {
                yield return(v);
            }
        }
Ejemplo n.º 6
0
        public CompletionSet GetCompletions(Metadata metadata, string fullText, int pos, string currentAssemblyName = null)
        {
            string textToCursor = fullText.Substring(0, pos);

            _helper.SetMetadata(metadata, textToCursor, currentAssemblyName);

            if (_helper.Metadata == null)
            {
                return(null);
            }

            if (fullText.Length == 0 || pos == 0)
            {
                return(null);
            }
            var state = XmlParser.Parse(textToCursor);

            var completions = new List <Completion>();

            int curStart = state.CurrentValueStart ?? 0;

            if (state.State == XmlParser.ParserState.StartElement)
            {
                var tagName = state.TagName;
                if (tagName.StartsWith("/"))
                {
                    if (textToCursor.Length < 2)
                    {
                        return(null);
                    }
                    var closingState = XmlParser.Parse(textToCursor.Substring(0, textToCursor.Length - 2));

                    var name = closingState.GetParentTagName(0);
                    if (name == null)
                    {
                        return(null);
                    }
                    completions.Add(new Completion("/" + name + ">", CompletionKind.Class));
                }
                else if (tagName.Contains("."))
                {
                    var dotPos   = tagName.IndexOf(".");
                    var typeName = tagName.Substring(0, dotPos);
                    var compName = tagName.Substring(dotPos + 1);
                    curStart = curStart + dotPos + 1;

                    var sameType = state.GetParentTagName(1) == typeName;

                    completions.AddRange(_helper.FilterPropertyNames(typeName, compName, attached: sameType ? (bool?)null : true, hasSetter: false)
                                         .Select(p => new Completion(p, sameType ? CompletionKind.Property : CompletionKind.AttachedProperty)));
                }
                else
                {
                    completions.AddRange(_helper.FilterTypeNames(tagName).Select(x => new Completion(x, CompletionKind.Class)));
                }
            }
            else if (state.State == XmlParser.ParserState.InsideElement ||
                     state.State == XmlParser.ParserState.StartAttribute)
            {
                if (state.State == XmlParser.ParserState.InsideElement)
                {
                    curStart = pos; //Force completion to be started from current cursor position
                }
                string attributeSuffix = "=\"\"";
                int    attributeOffset = 2;
                if (fullText.Length > pos && fullText[pos] == '=')
                {
                    // attribute already has value, we are editing name only
                    attributeSuffix = "";
                    attributeOffset = 0;
                }

                if (state.AttributeName?.Contains(".") == true)
                {
                    var dotPos = state.AttributeName.IndexOf('.');
                    curStart += dotPos + 1;
                    var split = state.AttributeName.Split(new[] { '.' }, 2);
                    completions.AddRange(_helper.FilterPropertyNames(split[0], split[1], attached: true, hasSetter: true)
                                         .Select(x => new Completion(x, x + attributeSuffix, x, CompletionKind.AttachedProperty, x.Length + attributeOffset)));

                    completions.AddRange(_helper.FilterEventNames(split[0], split[1], attached: true)
                                         .Select(v => new Completion(v, v + attributeSuffix, v, CompletionKind.AttachedEvent, v.Length + attributeOffset)));
                }
                else
                {
                    completions.AddRange(_helper.FilterPropertyNames(state.TagName, state.AttributeName, attached: false, hasSetter: true)
                                         .Select(x => new Completion(x, x + attributeSuffix, x, CompletionKind.Property, x.Length + attributeOffset)));

                    completions.AddRange(_helper.FilterEventNames(state.TagName, state.AttributeName, attached: false)
                                         .Select(v => new Completion(v, v + attributeSuffix, v, CompletionKind.Event, v.Length + attributeOffset)));

                    var targetType = _helper.LookupType(state.TagName);
                    completions.AddRange(
                        _helper.FilterTypes(state.AttributeName, xamlDirectiveOnly: true)
                        .Where(t => t.Value.IsValidForXamlContextFunc?.Invoke(currentAssemblyName, targetType, null) ?? true)
                        .Select(v => new Completion(v.Key, v.Key + attributeSuffix, v.Key, CompletionKind.Class, v.Key.Length + attributeOffset)));

                    if (targetType?.IsAvaloniaObjectType == true)
                    {
                        completions.AddRange(
                            _helper.FilterTypeNames(state.AttributeName, withAttachedPropertiesOrEventsOnly: true)
                            .Select(v => new Completion(v, v + ".", v, CompletionKind.Class)));
                    }
                }
            }
            else if (state.State == XmlParser.ParserState.AttributeValue)
            {
                MetadataProperty prop;
                if (state.AttributeName.Contains("."))
                {
                    //Attached property
                    var split = state.AttributeName.Split('.');
                    prop = _helper.LookupProperty(split[0], split[1]);
                }
                else
                {
                    prop = _helper.LookupProperty(state.TagName, state.AttributeName);
                }

                //Markup extension, ignore everything else
                if (state.AttributeValue.StartsWith("{"))
                {
                    curStart = state.CurrentValueStart.Value +
                               BuildCompletionsForMarkupExtension(prop, completions, fullText, state,
                                                                  textToCursor.Substring(state.CurrentValueStart.Value), currentAssemblyName);
                }
                else
                {
                    prop = prop ?? _helper.LookupType(state.AttributeName)?.Properties.FirstOrDefault(p => p.Name == "");

                    if (prop?.Type?.HasHintValues == true)
                    {
                        var search = textToCursor.Substring(state.CurrentValueStart.Value);
                        if (prop.Type.IsCompositeValue)
                        {
                            var last = search.Split(' ', ',').LastOrDefault();
                            curStart = curStart + search.Length - last?.Length ?? 0;
                            search   = last;
                        }

                        completions.AddRange(GetHintCompletions(prop.Type, search, currentAssemblyName));
                    }
                    else if (prop?.Type?.Name == typeof(Type).FullName)
                    {
                        completions.AddRange(_helper.FilterTypeNames(state.AttributeValue).Select(x => new Completion(x, x, x, CompletionKind.Class)));
                    }
                    else if (state.AttributeName == "xmlns" || state.AttributeName.Contains("xmlns:"))
                    {
                        IEnumerable <string> filterNamespaces(Func <string, bool> predicate)
                        {
                            var result = metadata.Namespaces.Keys.Where(predicate).ToList();

                            result.Sort((x, y) => x.CompareTo(y));

                            return(result);
                        }

                        if (state.AttributeValue.StartsWith("clr-namespace:"))
                        {
                            completions.AddRange(
                                filterNamespaces(v => v.StartsWith(state.AttributeValue))
                                .Select(v => new Completion(v.Substring("clr-namespace:".Length), v, v, CompletionKind.Namespace)));
                        }
                        else
                        {
                            if ("using:".StartsWith(state.AttributeValue))
                            {
                                completions.Add(new Completion("using:", CompletionKind.Namespace));
                            }

                            if ("clr-namespace:".StartsWith(state.AttributeValue))
                            {
                                completions.Add(new Completion("clr-namespace:", CompletionKind.Namespace));
                            }

                            completions.AddRange(
                                filterNamespaces(
                                    v =>
                                    v.StartsWith(state.AttributeValue) &&
                                    !v.StartsWith("clr-namespace"))
                                .Select(v => new Completion(v, CompletionKind.Namespace)));
                        }
                    }
                    else if (state.AttributeName.EndsWith(":Class"))
                    {
                        if (_helper.Aliases.TryGetValue(state.AttributeName.Replace(":Class", ""), out var ns) && ns == Utils.Xaml2006Namespace)
                        {
                            var asmKey         = $";assembly={currentAssemblyName}";
                            var fullClassNames = _helper.Metadata.Namespaces.Where(v => v.Key.EndsWith(asmKey))
                                                 .SelectMany(v => v.Value.Values.Where(t => t.IsAvaloniaObjectType))
                                                 .Select(v => v.FullName);
                            completions.AddRange(
                                fullClassNames
                                .Where(v => v.StartsWith(state.AttributeValue))
                                .Select(v => new Completion(v, CompletionKind.Class)));
                        }
                    }
                    else if (state.TagName == "Setter" && (state.AttributeName == "Value" || state.AttributeName == "Property"))
                    {
                        ProcessStyleSetter(state.AttributeName, state, completions, currentAssemblyName);
                    }
                }
            }

            if (completions.Count != 0)
            {
                return new CompletionSet()
                       {
                           Completions = completions, StartPosition = curStart
                       }
            }
            ;
            return(null);
        }
 public CloseXmlTagManipulation(XmlParser state, ReadOnlyMemory <char> text, int position)
 {
     _state    = state;
     _text     = text;
     _position = position;
 }
Ejemplo n.º 8
0
        public CompletionSet GetCompletions(Metadata metadata, string text, int pos)
        {
            _helper.SetMetadata(metadata, text);

            if (_helper.Metadata == null)
            {
                return(null);
            }

            if (text.Length == 0 || pos == 0)
            {
                return(null);
            }
            text = text.Substring(0, pos);
            var state = XmlParser.Parse(text);

            var completions = new List <Completion>();


            var curStart = state.CurrentValueStart ?? 0;

            if (state.State == XmlParser.ParserState.StartElement)
            {
                var tagName = state.TagName;
                if (tagName.Contains("."))
                {
                    var dotPos   = tagName.IndexOf(".");
                    var typeName = tagName.Substring(0, dotPos);
                    var compName = tagName.Substring(dotPos + 1);
                    curStart = curStart + dotPos + 1;
                    completions.AddRange(_helper.FilterPropertyNames(typeName, compName).Select(p => new Completion(p)));
                }
                else
                {
                    completions.AddRange(_helper.FilterTypeNames(tagName).Select(x => new Completion(x)));
                }
            }
            else if (state.State == XmlParser.ParserState.InsideElement ||
                     state.State == XmlParser.ParserState.StartAttribute)
            {
                if (state.State == XmlParser.ParserState.InsideElement)
                {
                    curStart = pos; //Force completion to be started from current cursor position
                }
                if (state.AttributeName?.Contains(".") == true)
                {
                    var dotPos = state.AttributeName.IndexOf('.');
                    curStart += dotPos + 1;
                    var split = state.AttributeName.Split(new[] { '.' }, 2);
                    completions.AddRange(_helper.FilterPropertyNames(split[0], split[1], true)
                                         .Select(x => new Completion(x, x + "=\"\"", x, x.Length + 2)));
                }
                else
                {
                    completions.AddRange(_helper.FilterPropertyNames(state.TagName, state.AttributeName)
                                         .Select(x => new Completion(x, x + "=\"\"", x, x.Length + 2)));
                    completions.AddRange(
                        _helper.FilterTypeNames(state.AttributeName, true)
                        .Select(v => new Completion(v, v + ".", v)));
                }
            }
            else if (state.State == XmlParser.ParserState.AttributeValue)
            {
                MetadataProperty prop;
                if (state.AttributeName.Contains("."))
                {
                    //Attached property
                    var split = state.AttributeName.Split('.');
                    prop = _helper.LookupProperty(split[0], split[1]);
                }
                else
                {
                    prop = _helper.LookupProperty(state.TagName, state.AttributeName);
                }

                //Markup extension, ignore everything else
                if (state.AttributeValue.StartsWith("{"))
                {
                    curStart = state.CurrentValueStart.Value +
                               BuildCompletionsForMarkupExtension(completions,
                                                                  text.Substring(state.CurrentValueStart.Value));
                }
                else
                {
                    if (prop?.Type?.IsEnum == true)
                    {
                        completions.AddRange(GetEnumCompletions(text.Substring(state.CurrentValueStart.Value), prop.Type.EnumValues));
                    }
                    else if (state.AttributeName == "xmlns" || state.AttributeName.Contains("xmlns:"))
                    {
                        if (state.AttributeValue.StartsWith("clr-namespace:"))
                        {
                            completions.AddRange(
                                metadata.Namespaces.Keys.Where(v => v.StartsWith(state.AttributeValue))
                                .Select(v => new Completion(v.Substring("clr-namespace:".Length), v, v)));
                        }
                        else
                        {
                            completions.Add(new Completion("clr-namespace:"));
                            completions.AddRange(
                                metadata.Namespaces.Keys.Where(
                                    v =>
                                    v.StartsWith(state.AttributeValue) &&
                                    !"clr-namespace".StartsWith(state.AttributeValue))
                                .Select(v => new Completion(v)));
                        }
                    }
                }
            }

            if (completions.Count != 0)
            {
                return new CompletionSet()
                       {
                           Completions = completions, StartPosition = curStart
                       }
            }
            ;
            return(null);
        }

        List <Completion> GetEnumCompletions(string entered, string[] enumValues)
        {
            var enumCompletions = new List <Completion>();

            foreach (var val in enumValues)
            {
                if (val.StartsWith(entered, StringComparison.OrdinalIgnoreCase))
                {
                    enumCompletions.Add(new Completion(val));
                }
            }
            return(enumCompletions);
        }

        int BuildCompletionsForMarkupExtension(List <Completion> completions, string data)
        {
            int?forcedStart = null;
            var ext         = MarkupExtensionParser.Parse(data);

            var transformedName = (ext.ElementName ?? "").Trim();

            if (_helper.LookupType(transformedName)?.IsMarkupExtension != true)
            {
                transformedName += "Extension";
            }

            if (ext.State == MarkupExtensionParser.ParserStateType.StartElement)
            {
                completions.AddRange(_helper.FilterTypeNames(ext.ElementName, markupExtensionsOnly: true)
                                     .Select(t => t.EndsWith("Extension") ? t.Substring(0, t.Length - "Extension".Length) : t)
                                     .Select(t => new Completion(t)));
            }
            if (ext.State == MarkupExtensionParser.ParserStateType.StartAttribute ||
                ext.State == MarkupExtensionParser.ParserStateType.InsideElement)
            {
                if (ext.State == MarkupExtensionParser.ParserStateType.InsideElement)
                {
                    forcedStart = data.Length;
                }
                completions.AddRange(_helper.FilterPropertyNames(transformedName, ext.AttributeName ?? "")
                                     .Select(x => new Completion(x, x + "=", x)));
            }
            if (ext.State == MarkupExtensionParser.ParserStateType.AttributeValue ||
                ext.State == MarkupExtensionParser.ParserStateType.BeforeAttributeValue)
            {
                var prop = _helper.LookupProperty(transformedName, ext.AttributeName);
                if (prop?.Type?.IsEnum == true)
                {
                    var enumStart       = data.Substring(ext.CurrentValueStart);
                    var enumCompletions = GetEnumCompletions(enumStart, prop.Type.EnumValues);
                    completions.AddRange(enumCompletions);
                }
            }

            return(forcedStart ?? ext.CurrentValueStart);
        }
Ejemplo n.º 9
0
        public CompletionSet GetCompletions(Metadata metadata, string text, int pos, string currentAssemblyName = null)
        {
            _helper.SetMetadata(metadata, text, currentAssemblyName);

            if (_helper.Metadata == null)
            {
                return(null);
            }

            if (text.Length == 0 || pos == 0)
            {
                return(null);
            }
            text = text.Substring(0, pos);
            var state = XmlParser.Parse(text);

            var completions = new List <Completion>();


            var curStart = state.CurrentValueStart ?? 0;

            if (state.State == XmlParser.ParserState.StartElement)
            {
                var tagName = state.TagName;
                if (tagName.StartsWith("/"))
                {
                    if (text.Length < 2)
                    {
                        return(null);
                    }
                    var closingState = XmlParser.Parse(text.Substring(0, text.Length - 2));

                    var name = closingState.GetParentTagName(0);
                    if (name == null)
                    {
                        return(null);
                    }
                    completions.Add(new Completion("/" + name + ">", CompletionKind.Class));
                }
                else if (tagName.Contains("."))
                {
                    var dotPos   = tagName.IndexOf(".");
                    var typeName = tagName.Substring(0, dotPos);
                    var compName = tagName.Substring(dotPos + 1);
                    curStart = curStart + dotPos + 1;

                    var sameType = state.GetParentTagName(1) == typeName;

                    completions.AddRange(_helper.FilterPropertyNames(typeName, compName, sameType ? (bool?)null : true)
                                         .Select(p => new Completion(p, sameType ? CompletionKind.Property : CompletionKind.AttachedProperty)));
                }
                else
                {
                    completions.AddRange(_helper.FilterTypeNames(tagName).Select(x => new Completion(x, CompletionKind.Class)));
                }
            }
            else if (state.State == XmlParser.ParserState.InsideElement ||
                     state.State == XmlParser.ParserState.StartAttribute)
            {
                if (state.State == XmlParser.ParserState.InsideElement)
                {
                    curStart = pos; //Force completion to be started from current cursor position
                }
                if (state.AttributeName?.Contains(".") == true)
                {
                    var dotPos = state.AttributeName.IndexOf('.');
                    curStart += dotPos + 1;
                    var split = state.AttributeName.Split(new[] { '.' }, 2);
                    completions.AddRange(_helper.FilterPropertyNames(split[0], split[1], true)
                                         .Select(x => new Completion(x, x + "=\"\"", x, CompletionKind.AttachedProperty, x.Length + 2)));
                }
                else
                {
                    completions.AddRange(_helper.FilterPropertyNames(state.TagName, state.AttributeName, false)
                                         .Select(x => new Completion(x, x + "=\"\"", x, CompletionKind.Property, x.Length + 2)));

                    var targetType = _helper.LookupType(state.TagName);

                    if (targetType?.IsAvaloniaObjectType == true)
                    {
                        completions.AddRange(
                            _helper.FilterTypeNames(state.AttributeName, true)
                            .Select(v => new Completion(v, v + ".", v, CompletionKind.Class)));
                    }
                }
            }
            else if (state.State == XmlParser.ParserState.AttributeValue)
            {
                MetadataProperty prop;
                if (state.AttributeName.Contains("."))
                {
                    //Attached property
                    var split = state.AttributeName.Split('.');
                    prop = _helper.LookupProperty(split[0], split[1]);
                }
                else
                {
                    prop = _helper.LookupProperty(state.TagName, state.AttributeName);
                }

                //Markup extension, ignore everything else
                if (state.AttributeValue.StartsWith("{"))
                {
                    curStart = state.CurrentValueStart.Value +
                               BuildCompletionsForMarkupExtension(prop, completions,
                                                                  text.Substring(state.CurrentValueStart.Value));
                }
                else
                {
                    if (prop?.Type?.HasHintValues == true)
                    {
                        var search = text.Substring(state.CurrentValueStart.Value);
                        if (prop.Type.IsCompositeValue)
                        {
                            var last = search.Split(' ', ',').LastOrDefault();
                            curStart = curStart + search.Length - last?.Length ?? 0;
                            search   = last;
                        }

                        completions.AddRange(GetHintCompletions(prop.Type, search));
                    }
                    else if (prop?.Type?.Name == typeof(Type).FullName)
                    {
                        completions.AddRange(_helper.FilterTypeNames(state.AttributeValue).Select(x => new Completion(x, x, x, CompletionKind.Class)));
                    }
                    else if (state.AttributeName == "xmlns" || state.AttributeName.Contains("xmlns:"))
                    {
                        if (state.AttributeValue.StartsWith("clr-namespace:"))
                        {
                            completions.AddRange(
                                metadata.Namespaces.Keys.Where(v => v.StartsWith(state.AttributeValue))
                                .Select(v => new Completion(v.Substring("clr-namespace:".Length), v, v, CompletionKind.Namespace)));
                        }
                        else
                        {
                            if ("clr-namespace:".StartsWith(state.AttributeValue))
                            {
                                completions.Add(new Completion("clr-namespace:", CompletionKind.Namespace));
                            }
                            completions.AddRange(
                                metadata.Namespaces.Keys.Where(
                                    v =>
                                    v.StartsWith(state.AttributeValue) &&
                                    !v.StartsWith("clr-namespace"))
                                .Select(v => new Completion(v, CompletionKind.Namespace)));
                        }
                    }
                }
            }

            if (completions.Count != 0)
            {
                return new CompletionSet()
                       {
                           Completions = completions, StartPosition = curStart
                       }
            }
            ;
            return(null);
        }