コード例 #1
0
        public static Metadata ConvertMetadata(IMetadataReaderSession provider)
        {
            var types        = new Dictionary <string, MetadataType>();
            var typeDefs     = new Dictionary <MetadataType, ITypeInformation>();
            var metadata     = new Metadata();
            var resourceUrls = new List <string>();
            var avaresValues = new List <AvaresInfo>();

            var ignoredResExt = new[] { ".resources", ".rd.xml", "!AvaloniaResources" };

            bool skipRes(string res) => ignoredResExt.Any(r => res.EndsWith(r, StringComparison.OrdinalIgnoreCase));

            PreProcessTypes(types, metadata);

            foreach (var asm in provider.Assemblies)
            {
                var aliases = new Dictionary <string, string[]>();

                ProcessWellKnownAliases(asm, aliases);
                ProcessCustomAttributes(asm, aliases);

                var asmTypes = asm.Types.ToArray();

                foreach (var type in asmTypes.Where(x => !x.IsInterface && x.IsPublic))
                {
                    var mt = types[type.FullName] = ConvertTypeInfomation(type);
                    typeDefs[mt] = type;
                    metadata.AddType("clr-namespace:" + type.Namespace + ";assembly=" + asm.Name, mt);
                    string[] nsAliases      = null;
                    string   usingNamespace = $"using:{type.Namespace}";
                    if (!aliases.TryGetValue(type.Namespace, out nsAliases))
                    {
                        nsAliases = new string[] { usingNamespace };
                        aliases[type.Namespace] = nsAliases;
                    }
                    else if (!nsAliases.Contains(usingNamespace))
                    {
                        aliases[type.Namespace] = nsAliases.Union(new string[] { usingNamespace }).ToArray();
                    }

                    foreach (var alias in nsAliases)
                    {
                        metadata.AddType(alias, mt);
                    }
                }

                ProcessAvaloniaResources(asm, asmTypes, avaresValues);

                resourceUrls.AddRange(asm.ManifestResourceNames.Where(r => !skipRes(r)).Select(r => $"resm:{r}?assembly={asm.Name}"));
            }

            foreach (var type in types.Values)
            {
                ITypeInformation typeDef;
                typeDefs.TryGetValue(type, out typeDef);

                var ctors = typeDef?.Methods
                            .Where(m => m.IsPublic && !m.IsStatic && m.Name == ".ctor" && m.Parameters.Count == 1);

                if (typeDef?.IsEnum ?? false)
                {
                    foreach (var value in typeDef.EnumValues)
                    {
                        var p = new MetadataProperty(value, type, type, false, true, true, false);

                        type.Properties.Add(p);
                    }
                }

                int level = 0;
                while (typeDef != null)
                {
                    var currentType = types.GetValueOrDefault(typeDef.FullName);
                    foreach (var prop in typeDef.Properties)
                    {
                        if (!prop.HasPublicGetter && !prop.HasPublicSetter)
                        {
                            continue;
                        }

                        var p = new MetadataProperty(prop.Name, types.GetValueOrDefault(prop.TypeFullName),
                                                     currentType, false, prop.IsStatic, prop.HasPublicGetter,
                                                     prop.HasPublicSetter);

                        type.Properties.Add(p);
                    }

                    foreach (var eventDef in typeDef.Events)
                    {
                        var e = new MetadataEvent(eventDef.Name, types.GetValueOrDefault(eventDef.TypeFullName),
                                                  types.GetValueOrDefault(typeDef.FullName), false);

                        type.Events.Add(e);
                    }

                    //check for attached properties only on top level
                    if (level == 0)
                    {
                        foreach (var methodDef in typeDef.Methods)
                        {
                            if (methodDef.Name.StartsWith("Set", StringComparison.OrdinalIgnoreCase) && methodDef.IsStatic && methodDef.IsPublic &&
                                methodDef.Parameters.Count == 2)
                            {
                                var name = methodDef.Name.Substring(3);
                                type.Properties.Add(new MetadataProperty(name,
                                                                         types.GetValueOrDefault(methodDef.Parameters[1].TypeFullName),
                                                                         types.GetValueOrDefault(typeDef.FullName),
                                                                         true, false, true, true));
                            }
                        }

                        foreach (var fieldDef in typeDef.Fields)
                        {
                            if (fieldDef.IsStatic && fieldDef.IsPublic)
                            {
                                if ((fieldDef.IsRoutedEvent || fieldDef.Name.EndsWith("Event", StringComparison.OrdinalIgnoreCase)))
                                {
                                    var name = fieldDef.Name;
                                    if (fieldDef.Name.EndsWith("Event", StringComparison.OrdinalIgnoreCase))
                                    {
                                        name = name.Substring(0, name.Length - "Event".Length);
                                    }

                                    type.Events.Add(new MetadataEvent(name,
                                                                      types.GetValueOrDefault(fieldDef.ReturnTypeFullName),
                                                                      types.GetValueOrDefault(typeDef.FullName),
                                                                      true));
                                }
                                else if (type.IsStatic)
                                {
                                    type.Properties.Add(new MetadataProperty(fieldDef.Name, null, type, false, true, true, false));
                                }
                            }
                        }
                    }

                    if (typeDef.FullName == "Avalonia.AvaloniaObject")
                    {
                        type.IsAvaloniaObjectType = true;
                    }

                    typeDef = typeDef.GetBaseType();
                    level++;
                }

                type.HasAttachedProperties  = type.Properties.Any(p => p.IsAttached);
                type.HasAttachedEvents      = type.Events.Any(e => e.IsAttached);
                type.HasStaticGetProperties = type.Properties.Any(p => p.IsStatic && p.HasGetter);
                type.HasSetProperties       = type.Properties.Any(p => !p.IsStatic && p.HasSetter);

                if (ctors?.Any() == true)
                {
                    bool supportType   = ctors.Any(m => m.Parameters[0].TypeFullName == "System.Type");
                    bool supportObject = ctors.Any(m => m.Parameters[0].TypeFullName == "System.Object" ||
                                                   m.Parameters[0].TypeFullName == "System.String");

                    if (types.TryGetValue(ctors.First().Parameters[0].TypeFullName, out MetadataType parType) &&
                        parType.HasHintValues)
                    {
                        type.SupportCtorArgument = MetadataTypeCtorArgument.HintValues;
                        type.HasHintValues       = true;
                        type.HintValues          = parType.HintValues;
                    }
                    else if (supportType && supportObject)
                    {
                        type.SupportCtorArgument = MetadataTypeCtorArgument.TypeAndObject;
                    }
                    else if (supportType)
                    {
                        type.SupportCtorArgument = MetadataTypeCtorArgument.Type;
                    }
                    else if (supportObject)
                    {
                        type.SupportCtorArgument = MetadataTypeCtorArgument.Object;
                    }
                }
            }

            PostProcessTypes(types, metadata, resourceUrls, avaresValues);

            return(metadata);
        }
コード例 #2
0
        private static void PostProcessTypes(Dictionary <string, MetadataType> types, Metadata metadata, IEnumerable <string> resourceUrls, List <AvaresInfo> avaResValues)
        {
            bool rhasext(string resource, string ext) => resource.StartsWith("resm:") ? resource.Contains(ext + "?assembly=") : resource.EndsWith(ext);

            var allresourceUrls = avaResValues.Select(v => v.GlobalUrl).Concat(resourceUrls).ToArray();

            var resType = new MetadataType()
            {
                Name          = "avares://,resm:",
                IsStatic      = true,
                HasHintValues = true,
                HintValues    = allresourceUrls
            };

            types.Add(resType.Name, resType);

            var xamlResType = new MetadataType()
            {
                Name          = "avares://*.xaml,resm:*.xaml",
                HasHintValues = true,
                HintValues    = resType.HintValues.Where(r => rhasext(r, ".xaml") || rhasext(r, ".paml") || rhasext(r, ".axaml")).ToArray()
            };

            var styleResType = new MetadataType()
            {
                Name          = "Style avares://*.xaml,resm:*.xaml",
                HasHintValues = true,
                HintValues    = avaResValues.Where(v => v.ReturnTypeFullName.StartsWith("Avalonia.Styling.Style"))
                                .Select(v => v.GlobalUrl)
                                .Concat(resourceUrls.Where(r => rhasext(r, ".xaml") || rhasext(r, ".paml") || rhasext(r, ".axaml")))
                                .ToArray()
            };

            types.Add(styleResType.Name, styleResType);

            IEnumerable <string> filterLocalRes(MetadataType type, string currentAssemblyName)
            {
                var localResPrefix = $"avares://{currentAssemblyName}";
                var resmSuffix     = $"?assembly={currentAssemblyName}";

                foreach (var hint in type.HintValues ?? Array.Empty <string>())
                {
                    if (hint.StartsWith("avares://"))
                    {
                        if (hint.StartsWith(localResPrefix))
                        {
                            yield return(hint.Substring(localResPrefix.Length));
                        }
                    }
                    else if (hint.StartsWith("resm:"))
                    {
                        if (hint.EndsWith(resmSuffix))
                        {
                            yield return(hint.Substring(0, hint.Length - resmSuffix.Length));
                        }
                    }
                }
            }

            resType.XamlContextHintValuesFunc      = (a, t, p) => filterLocalRes(xamlResType, a);
            xamlResType.XamlContextHintValuesFunc  = (a, t, p) => filterLocalRes(xamlResType, a);
            styleResType.XamlContextHintValuesFunc = (a, t, p) => filterLocalRes(styleResType, a);

            types.Add(xamlResType.Name, xamlResType);

            var allProps = new Dictionary <string, MetadataProperty>();

            foreach (var type in types.Where(t => t.Value.IsAvaloniaObjectType))
            {
                foreach (var v in type.Value.Properties.Where(p => p.HasSetter && p.HasGetter))
                {
                    allProps[v.Name] = v;
                }
            }

            string[] allAvaloniaProps = allProps.Keys.ToArray();

            if (!types.TryGetValue("Avalonia.Markup.Xaml.MarkupExtensions.BindingExtension", out MetadataType bindingExtType))
            {
                if (types.TryGetValue("Avalonia.Data.Binding", out MetadataType origBindingType))
                {
                    //avalonia 0.10 has implicit binding extension
                    bindingExtType = origBindingType.CloneAs("BindingExtension",
                                                             "Avalonia.Markup.Xaml.MarkupExtensions.BindingExtension");
                    bindingExtType.IsMarkupExtension = true;

                    types.Add(bindingExtType.FullName, bindingExtType);
                    metadata.AddType(Utils.AvaloniaNamespace, bindingExtType);
                }
            }

            types.TryGetValue("Avalonia.Controls.Control", out MetadataType controlType);
            types.TryGetValue(typeof(Type).FullName, out MetadataType typeType);

            var dataContextType = new MetadataType()
            {
                Name          = "{BindingPath}",
                FullName      = "{BindingPath}",
                HasHintValues = true,
                HintValues    = new[] { "$parent", "$parent[", "$self" },
            };

            //bindings related hints
            if (types.TryGetValue("Avalonia.Markup.Xaml.MarkupExtensions.BindingExtension", out MetadataType bindingType))
            {
                bindingType.SupportCtorArgument = MetadataTypeCtorArgument.None;
                var pathProp = bindingType.Properties.FirstOrDefault(p => p.Name == "Path");
                if (pathProp != null)
                {
                    pathProp.Type = dataContextType;
                }

                bindingType.Properties.Add(new MetadataProperty("", dataContextType, bindingType, false, false, true, true));
            }

            if (types.TryGetValue("Avalonia.Data.TemplateBinding", out MetadataType templBinding))
            {
                var tbext = new MetadataType()
                {
                    Name = "TemplateBindingExtension",
                    IsMarkupExtension   = true,
                    Properties          = templBinding.Properties,
                    SupportCtorArgument = MetadataTypeCtorArgument.HintValues,
                    HasHintValues       = allAvaloniaProps?.Any() ?? false,
                    HintValues          = allAvaloniaProps
                };

                types["TemplateBindingExtension"] = tbext;
                metadata.AddType(Utils.AvaloniaNamespace, tbext);
            }

            if (types.TryGetValue("Portable.Xaml.Markup.TypeExtension", out MetadataType typeExtension))
            {
                typeExtension.SupportCtorArgument = MetadataTypeCtorArgument.Type;
            }

            //TODO: may be make it to load from assembly resources
            string[] commonResKeys = new string[] {
//common brushes
                "ThemeBackgroundBrush", "ThemeBorderLowBrush", "ThemeBorderMidBrush", "ThemeBorderHighBrush",
                "ThemeControlLowBrush", "ThemeControlMidBrush", "ThemeControlHighBrush",
                "ThemeControlHighlightLowBrush", "ThemeControlHighlightMidBrush", "ThemeControlHighlightHighBrush",
                "ThemeForegroundBrush", "ThemeForegroundLowBrush", "HighlightBrush",
                "ThemeAccentBrush", "ThemeAccentBrush2", "ThemeAccentBrush3", "ThemeAccentBrush4",
                "ErrorBrush", "ErrorLowBrush",
//some other usefull
                "ThemeBorderThickness", "ThemeDisabledOpacity",
                "FontSizeSmall", "FontSizeNormal", "FontSizeLarge"
            };

            if (types.TryGetValue("Avalonia.Markup.Xaml.MarkupExtensions.DynamicResourceExtension", out MetadataType dynRes))
            {
                dynRes.SupportCtorArgument = MetadataTypeCtorArgument.HintValues;
                dynRes.HasHintValues       = true;
                dynRes.HintValues          = commonResKeys;
            }

            if (types.TryGetValue("Avalonia.Markup.Xaml.MarkupExtensions.StaticResourceExtension", out MetadataType stRes))
            {
                stRes.SupportCtorArgument = MetadataTypeCtorArgument.HintValues;
                stRes.HasHintValues       = true;
                stRes.HintValues          = commonResKeys;
            }

            //brushes
            if (types.TryGetValue("Avalonia.Media.IBrush", out MetadataType brushType) &&
                types.TryGetValue("Avalonia.Media.Brushes", out MetadataType brushes))
            {
                brushType.HasHintValues = true;
                brushType.HintValues    = brushes.Properties.Where(p => p.IsStatic && p.HasGetter).Select(p => p.Name).ToArray();
            }

            if (types.TryGetValue("Avalonia.Styling.Selector", out MetadataType styleSelector))
            {
                styleSelector.HasHintValues    = true;
                styleSelector.IsCompositeValue = true;

                List <string> hints = new List <string>();

                //some reserved words
                hints.AddRange(new[] { "/template/", ":is()", ">", "#", "." });

                //some pseudo classes
                hints.AddRange(new[]
                {
                    ":pointerover", ":pressed", ":disabled", ":focus",
                    ":selected", ":vertical", ":horizontal",
                    ":checked", ":unchecked", ":indeterminate"
                });

                hints.AddRange(types.Where(t => t.Value.IsAvaloniaObjectType).Select(t => t.Value.Name.Replace(":", "|")));

                styleSelector.HintValues = hints.ToArray();
            }

            string[] bitmaptypes = new[] { ".jpg", ".bmp", ".png", ".ico" };

            bool isbitmaptype(string resource) => bitmaptypes.Any(ext => rhasext(resource, ext));

            if (types.TryGetValue("Avalonia.Media.Imaging.IBitmap", out MetadataType ibitmapType))
            {
                ibitmapType.HasHintValues             = true;
                ibitmapType.HintValues                = allresourceUrls.Where(r => isbitmaptype(r)).ToArray();
                ibitmapType.XamlContextHintValuesFunc = (a, t, p) => filterLocalRes(ibitmapType, a);
            }

            if (types.TryGetValue("Avalonia.Media.IImage", out MetadataType iImageType))
            {
                iImageType.HasHintValues             = true;
                iImageType.HintValues                = allresourceUrls.Where(r => isbitmaptype(r)).ToArray();
                iImageType.XamlContextHintValuesFunc = (a, t, p) => filterLocalRes(ibitmapType, a);
            }

            if (types.TryGetValue("Avalonia.Controls.WindowIcon", out MetadataType winIcon))
            {
                winIcon.HasHintValues             = true;
                winIcon.HintValues                = allresourceUrls.Where(r => rhasext(r, ".ico")).ToArray();
                winIcon.XamlContextHintValuesFunc = (a, t, p) => filterLocalRes(winIcon, a);
            }

            if (types.TryGetValue("Avalonia.Markup.Xaml.Styling.StyleInclude", out MetadataType styleIncludeType))
            {
                var source = styleIncludeType.Properties.FirstOrDefault(p => p.Name == "Source");

                if (source != null)
                {
                    source.Type = styleResType;
                }
            }

            if (types.TryGetValue("Avalonia.Markup.Xaml.Styling.StyleIncludeExtension", out MetadataType styleIncludeExtType))
            {
                var source = styleIncludeExtType.Properties.FirstOrDefault(p => p.Name == "Source");

                if (source != null)
                {
                    source.Type = xamlResType;
                }
            }

            if (types.TryGetValue(typeof(Uri).FullName, out MetadataType uriType))
            {
                uriType.HasHintValues             = true;
                uriType.HintValues                = allresourceUrls.ToArray();
                uriType.XamlContextHintValuesFunc = (a, t, p) => filterLocalRes(uriType, a);
            }

            if (typeType != null)
            {
                var typeArguments = new MetadataType()
                {
                    Name                      = "TypeArguments",
                    IsXamlDirective           = true,
                    IsValidForXamlContextFunc = (a, t, p) => t?.IsGeneric == true,
                    Properties                = { new MetadataProperty("", typeType, null, false, false, false, true) }
                };

                metadata.AddType(Utils.Xaml2006Namespace, typeArguments);
            }
        }
コード例 #3
0
        private static void PreProcessTypes(Dictionary <string, MetadataType> types, Metadata metadata)
        {
            MetadataType xDataType, xCompiledBindings, boolType, typeType;
            var          toAdd = new List <MetadataType>
            {
                (boolType = new MetadataType()
                {
                    Name = typeof(bool).FullName,
                    HasHintValues = true,
                    HintValues = new[] { "True", "False" }
                }),
                new MetadataType()
                {
                    Name = typeof(System.Uri).FullName
                },
                (typeType = new MetadataType()
                {
                    Name = typeof(System.Type).FullName
                }),
                new MetadataType()
                {
                    Name = "Avalonia.Media.IBrush"
                },
                new MetadataType()
                {
                    Name = "Avalonia.Media.Imaging.IBitmap"
                },
                new MetadataType()
                {
                    Name = "Avalonia.Media.IImage"
                },
            };

            foreach (var t in toAdd)
            {
                types.Add(t.Name, t);
            }

            var portableXamlExtTypes = new[]
            {
                new MetadataType()
                {
                    Name = "StaticExtension",
                    SupportCtorArgument = MetadataTypeCtorArgument.Object,
                    HasSetProperties    = true,
                    IsMarkupExtension   = true,
                },
                new MetadataType()
                {
                    Name = "TypeExtension",
                    SupportCtorArgument = MetadataTypeCtorArgument.TypeAndObject,
                    HasSetProperties    = true,
                    IsMarkupExtension   = true,
                },
                new MetadataType()
                {
                    Name              = "NullExtension",
                    HasSetProperties  = true,
                    IsMarkupExtension = true,
                },
                new MetadataType()
                {
                    Name            = "Class",
                    IsXamlDirective = true
                },
                new MetadataType()
                {
                    Name            = "Name",
                    IsXamlDirective = true
                },
                new MetadataType()
                {
                    Name            = "Key",
                    IsXamlDirective = true
                },
                xDataType = new MetadataType()
                {
                    Name            = "DataType",
                    IsXamlDirective = true,
                    Properties      = { new MetadataProperty("", typeType, null, false, false, false, true) },
                },
                xCompiledBindings = new MetadataType()
                {
                    Name            = "CompileBindings",
                    IsXamlDirective = true,
                    Properties      = { new MetadataProperty("", boolType, null, false, false, false, true) },
                },
            };

            //as in avalonia 0.9 Portablexaml is missing we need to hardcode some extensions
            foreach (var t in portableXamlExtTypes)
            {
                metadata.AddType(Utils.Xaml2006Namespace, t);
            }

            types.Add(xDataType.Name, xDataType);
            types.Add(xCompiledBindings.Name, xCompiledBindings);

            metadata.AddType("", new MetadataType()
            {
                Name = "xmlns", IsXamlDirective = true
            });
        }
コード例 #4
0
        public static Metadata ConvertMetadata(IMetadataReaderSession provider)
        {
            var types        = new Dictionary <string, MetadataType>();
            var typeDefs     = new Dictionary <MetadataType, ITypeInformation>();
            var metadata     = new Metadata();
            var resourceUrls = new List <string>();
            var avaresValues = new List <AvaresInfo>();

            var ignoredResExt = new[] { ".resources", ".rd.xml" };

            bool skipRes(string res) => ignoredResExt.Any(r => res.EndsWith(r, StringComparison.OrdinalIgnoreCase));

            PreProcessTypes(types, metadata);

            foreach (var asm in provider.Assemblies)
            {
                var aliases = new Dictionary <string, string[]>();

                ProcessWellKnownAliases(asm, aliases);
                ProcessCustomAttributes(asm, aliases);

                foreach (var type in asm.Types.Where(x => !x.IsInterface && x.IsPublic))
                {
                    var mt = types[type.FullName] = ConvertTypeInfomation(type);
                    typeDefs[mt] = type;
                    metadata.AddType("clr-namespace:" + type.Namespace + ";assembly=" + asm.Name, mt);
                    string[] nsAliases = null;
                    if (aliases.TryGetValue(type.Namespace, out nsAliases))
                    {
                        foreach (var alias in nsAliases)
                        {
                            metadata.AddType(alias, mt);
                        }
                    }
                }

                const string avaresToken = "Build:"; //or "Populate:" should work both ways

                foreach (var resType in asm.Types.Where(t => t.FullName == "CompiledAvaloniaXaml.!AvaloniaResources" || t.Name == "CompiledAvaloniaXaml.!AvaloniaResources"))
                {
                    foreach (var res in resType.Methods.Where(m => m.Name.StartsWith(avaresToken)))
                    {
                        var localUrl = res.Name.Replace(avaresToken, "");

                        var avres = new AvaresInfo
                        {
                            Assembly           = asm,
                            LocalUrl           = localUrl,
                            GlobalUrl          = $"avares://{asm.Name}{localUrl}",
                            ReturnTypeFullName = res.ReturnTypeFullName ?? ""
                        };

                        avaresValues.Add(avres);
                    }
                }

                resourceUrls.AddRange(asm.ManifestResourceNames.Where(r => !skipRes(r)).Select(r => $"resm:{r}?assembly={asm.Name}"));
            }

            foreach (var type in types.Values)
            {
                ITypeInformation typeDef;
                typeDefs.TryGetValue(type, out typeDef);

                var ctors = typeDef?.Methods
                            .Where(m => m.IsPublic && !m.IsStatic && m.Name == ".ctor" && m.Parameters.Count == 1);

                int level = 0;
                while (typeDef != null)
                {
                    foreach (var prop in typeDef.Properties)
                    {
                        if (!prop.HasPublicGetter && !prop.HasPublicSetter)
                        {
                            continue;
                        }

                        var p = new MetadataProperty(prop.Name, types.GetValueOrDefault(prop.TypeFullName),
                                                     types.GetValueOrDefault(typeDef.FullName), false, prop.IsStatic, prop.HasPublicGetter,
                                                     prop.HasPublicSetter);

                        type.Properties.Add(p);
                    }

                    //check for attached properties only on top level
                    if (level == 0)
                    {
                        foreach (var methodDef in typeDef.Methods)
                        {
                            if (methodDef.Name.StartsWith("Set") && methodDef.IsStatic && methodDef.IsPublic &&
                                methodDef.Parameters.Count == 2)
                            {
                                var name = methodDef.Name.Substring(3);
                                type.Properties.Add(new MetadataProperty(name,
                                                                         types.GetValueOrDefault(methodDef.Parameters[1].TypeFullName),
                                                                         types.GetValueOrDefault(typeDef.FullName),
                                                                         true, false, true, true));
                            }
                        }
                    }

                    if (typeDef.FullName == "Avalonia.AvaloniaObject")
                    {
                        type.IsAvaloniaObjectType = true;
                    }

                    typeDef = typeDef.GetBaseType();
                    level++;
                }

                type.HasAttachedProperties  = type.Properties.Any(p => p.IsAttached);
                type.HasStaticGetProperties = type.Properties.Any(p => p.IsStatic && p.HasGetter);
                type.HasSetProperties       = type.Properties.Any(p => !p.IsStatic && p.HasSetter);

                if (ctors?.Any() == true)
                {
                    bool supportType   = ctors.Any(m => m.Parameters[0].TypeFullName == "System.Type");
                    bool supportObject = ctors.Any(m => m.Parameters[0].TypeFullName == "System.Object" ||
                                                   m.Parameters[0].TypeFullName == "System.String");

                    if (types.TryGetValue(ctors.First().Parameters[0].TypeFullName, out MetadataType parType) &&
                        parType.HasHintValues)
                    {
                        type.SupportCtorArgument = MetadataTypeCtorArgument.HintValues;
                        type.HasHintValues       = true;
                        type.HintValues          = parType.HintValues;
                    }
                    else if (supportType && supportObject)
                    {
                        type.SupportCtorArgument = MetadataTypeCtorArgument.TypeAndObject;
                    }
                    else if (supportType)
                    {
                        type.SupportCtorArgument = MetadataTypeCtorArgument.Type;
                    }
                    else if (supportObject)
                    {
                        type.SupportCtorArgument = MetadataTypeCtorArgument.Object;
                    }
                }
            }

            PostProcessTypes(types, metadata, resourceUrls, avaresValues);

            return(metadata);
        }
コード例 #5
0
        private static void PostProcessTypes(Dictionary <string, MetadataType> types, Metadata metadata, IEnumerable <string> resourceUrls)
        {
            bool rhasext(string resource, string ext) => resource.Contains(ext + "?assembly=");

            var resmType = new MetadataType()
            {
                Name          = "resm:",
                IsStatic      = true,
                HasHintValues = true,
                HintValues    = resourceUrls.ToArray()
            };

            types.Add(resmType.Name, resmType);
            metadata.AddType(Utils.AvaloniaNamespace, resmType);

            var xamlResmType = new MetadataType()
            {
                Name          = "resm:*.xaml",
                HasHintValues = true,
                HintValues    = resourceUrls.Where(r => rhasext(r, ".xaml") || rhasext(r, ".paml")).ToArray()
            };

            types.Add(xamlResmType.Name, xamlResmType);
            metadata.AddType(Utils.AvaloniaNamespace, xamlResmType);

            MetadataType avProperty;

            if (types.TryGetValue("Avalonia.AvaloniaProperty", out avProperty))
            {
                var allProps = new Dictionary <string, MetadataProperty>();

                foreach (var type in types.Where(t => t.Value.IsAvaloniaObjectType))
                {
                    foreach (var v in type.Value.Properties.Where(p => p.HasSetter && p.HasGetter))
                    {
                        allProps[v.Name] = v;
                    }
                }

                avProperty.HasHintValues = true;
                avProperty.HintValues    = allProps.Keys.ToArray();
            }

            //bindings related hints
            if (types.TryGetValue("Avalonia.Markup.Xaml.MarkupExtensions.BindingExtension", out MetadataType bindingType))
            {
                bindingType.SupportCtorArgument = MetadataTypeCtorArgument.None;
            }

            if (types.TryGetValue("Avalonia.Data.TemplateBinding", out MetadataType templBinding))
            {
                var tbext = new MetadataType()
                {
                    Name = "TemplateBindingExtension",
                    IsMarkupExtension   = true,
                    Properties          = templBinding.Properties,
                    SupportCtorArgument = MetadataTypeCtorArgument.HintValues,
                    HasHintValues       = avProperty?.HasHintValues ?? false,
                    HintValues          = avProperty?.HintValues
                };

                types["TemplateBindingExtension"] = tbext;
                metadata.AddType(Utils.AvaloniaNamespace, tbext);
            }

            if (types.TryGetValue("Portable.Xaml.Markup.TypeExtension", out MetadataType typeExtension))
            {
                typeExtension.SupportCtorArgument = MetadataTypeCtorArgument.Type;
            }

            //TODO: may be make it to load from assembly resources
            string[] commonResKeys = new string[] {
//common brushes
                "ThemeBackgroundBrush", "ThemeBorderLowBrush", "ThemeBorderMidBrush", "ThemeBorderHighBrush",
                "ThemeControlLowBrush", "ThemeControlMidBrush", "ThemeControlHighBrush",
                "ThemeControlHighlightLowBrush", "ThemeControlHighlightMidBrush", "ThemeControlHighlightHighBrush",
                "ThemeForegroundBrush", "ThemeForegroundLowBrush", "HighlightBrush",
                "ThemeAccentBrush", "ThemeAccentBrush2", "ThemeAccentBrush3", "ThemeAccentBrush4",
                "ErrorBrush", "ErrorLowBrush",
//some other usefull
                "ThemeBorderThickness", "ThemeDisabledOpacity",
                "FontSizeSmall", "FontSizeNormal", "FontSizeLarge"
            };

            if (types.TryGetValue("Avalonia.Markup.Xaml.MarkupExtensions.DynamicResourceExtension", out MetadataType dynRes))
            {
                dynRes.SupportCtorArgument = MetadataTypeCtorArgument.HintValues;
                dynRes.HasHintValues       = true;
                dynRes.HintValues          = commonResKeys;
            }

            if (types.TryGetValue("Avalonia.Markup.Xaml.MarkupExtensions.StaticResourceExtension", out MetadataType stRes))
            {
                stRes.SupportCtorArgument = MetadataTypeCtorArgument.HintValues;
                stRes.HasHintValues       = true;
                stRes.HintValues          = commonResKeys;
            }

            //brushes
            if (types.TryGetValue("Avalonia.Media.IBrush", out MetadataType brushType) &&
                types.TryGetValue("Avalonia.Media.Brushes", out MetadataType brushes))
            {
                brushType.HasHintValues = true;
                brushType.HintValues    = brushes.Properties.Where(p => p.IsStatic && p.HasGetter).Select(p => p.Name).ToArray();
            }

            if (types.TryGetValue("Avalonia.Styling.Selector", out MetadataType styleSelector))
            {
                styleSelector.HasHintValues    = true;
                styleSelector.IsCompositeValue = true;

                List <string> hints = new List <string>();

                //some reserved words
                hints.AddRange(new[] { "/template/", ":is()", ">", "#", "." });

                //some pseudo classes
                hints.AddRange(new[]
                {
                    ":pointerover", ":pressed", ":disabled", ":focus",
                    ":selected", ":vertical", ":horizontal",
                    ":checked", ":unchecked", ":indeterminate"
                });

                hints.AddRange(types.Where(t => t.Value.IsAvaloniaObjectType).Select(t => t.Value.Name.Replace(":", "|")));

                styleSelector.HintValues = hints.ToArray();
            }

            string[] bitmaptypes = new[] { ".jpg", ".bmp", ".png", ".ico" };

            bool isbitmaptype(string resource) => bitmaptypes.Any(ext => rhasext(resource, ext));

            if (types.TryGetValue("Avalonia.Media.Imaging.IBitmap", out MetadataType ibitmapType))
            {
                ibitmapType.HasHintValues = true;
                ibitmapType.HintValues    = resourceUrls.Where(r => isbitmaptype(r)).ToArray();
            }

            if (types.TryGetValue("Avalonia.Controls.WindowIcon", out MetadataType winIcon))
            {
                winIcon.HasHintValues = true;
                winIcon.HintValues    = resourceUrls.Where(r => rhasext(r, ".ico")).ToArray();
            }

            if (types.TryGetValue("Avalonia.Markup.Xaml.Styling.StyleInclude", out MetadataType styleIncludeType))
            {
                var source = styleIncludeType.Properties.FirstOrDefault(p => p.Name == "Source");

                if (source != null)
                {
                    source.Type = xamlResmType;
                }
            }

            if (types.TryGetValue("Avalonia.Markup.Xaml.Styling.StyleIncludeExtension", out MetadataType styleIncludeExtType))
            {
                var source = styleIncludeExtType.Properties.FirstOrDefault(p => p.Name == "Source");

                if (source != null)
                {
                    source.Type = xamlResmType;
                }
            }

            if (types.TryGetValue(typeof(Uri).FullName, out MetadataType uriType))
            {
                uriType.HasHintValues = true;
                uriType.HintValues    = resourceUrls.ToArray();
            }
        }
コード例 #6
0
        public static Metadata ConvertMetadata(IMetadataReaderSession provider)
        {
            var types    = new Dictionary <string, MetadataType>();
            var typeDefs = new Dictionary <MetadataType, ITypeInformation>();
            var metadata = new Metadata();

            types.Add(typeof(bool).FullName, new MetadataType()
            {
                Name       = typeof(bool).FullName,
                IsEnum     = true,
                EnumValues = new[] { "True", "False" }
            });


            foreach (var asm in provider.Assemblies)
            {
                var aliases = new Dictionary <string, string>();
                foreach (
                    var attr in
                    asm.CustomAttributes.Where(a => a.TypeFullName == "Avalonia.Metadata.XmlnsDefinitionAttribute"))
                {
                    aliases[attr.ConstructorArguments[1].Value.ToString()] =
                        attr.ConstructorArguments[0].Value.ToString();
                }

                foreach (var type in asm.Types.Where(x => !x.IsInterface && x.IsPublic))
                {
                    var mt = types[type.FullName] = ConvertTypeInfomation(type);
                    typeDefs[mt] = type;
                    metadata.AddType("clr-namespace:" + type.Namespace + ";assembly=" + asm.Name, mt);
                    string alias = null;
                    if (aliases.TryGetValue(type.Namespace, out alias))
                    {
                        metadata.AddType(alias, mt);
                    }
                }
            }

            foreach (var type in types.Values)
            {
                ITypeInformation typeDef;
                typeDefs.TryGetValue(type, out typeDef);
                while (typeDef != null)
                {
                    foreach (var prop in typeDef.Properties)
                    {
                        if (prop.IsStatic || !prop.HasPublicSetter)
                        {
                            continue;
                        }

                        var p = new MetadataProperty {
                            Name = prop.Name
                        };

                        p.Type = types.GetValueOrDefault(prop.TypeFullName);

                        type.Properties.Add(p);
                    }
                    foreach (var methodDef in typeDef.Methods)
                    {
                        if (methodDef.Name.StartsWith("Set") && methodDef.IsStatic && methodDef.IsPublic &&
                            methodDef.Parameters.Count == 2)
                        {
                            type.Properties.Add(new MetadataProperty()
                            {
                                Name       = methodDef.Name.Substring(3),
                                IsAttached = true,
                                Type       = types.GetValueOrDefault(methodDef.Parameters[1].TypeFullName)
                            });
                        }
                    }
                    typeDef = typeDef.GetBaseType();
                }
                type.HasAttachedProperties = type.Properties.Any(p => p.IsAttached);
            }

            return(metadata);
        }