private void GenerateType(IndentedStringBuilder writer, INamedTypeSymbol ownerType)
        {
            if (_typeMap.ContainsKey(ownerType))
            {
                return;
            }

            var ownerTypeName = GetGlobalQualifier(ownerType) + ownerType.ToString();

            var flattenedProperties =
                from property in ownerType.GetAllProperties()
                where !property.IsStatic &&
                !IsIgnoredType(property.ContainingSymbol as INamedTypeSymbol) &&
                !IsNonBindable(property) &&
                !IsOverride(property.GetMethod)
                select property;

            var properties =
                from property in ownerType.GetProperties()
                where !property.IsStatic &&
                !IsNonBindable(property) &&
                HasPublicGetter(property) &&
                !IsOverride(property.GetMethod)
                select property;

            var propertyDependencyProperties =
                from property in ownerType.GetProperties()
                where property.IsStatic &&
                Equals(property.Type, _dependencyPropertySymbol)
                select property.Name;

            var fieldDependencyProperties =
                from field in ownerType.GetFields()
                where field.IsStatic &&
                Equals(field.Type, _dependencyPropertySymbol)
                select field.Name;

            var dependencyProperties = fieldDependencyProperties
                                       .Concat(propertyDependencyProperties)
                                       .ToArray();

            properties = from prop in properties.Distinct(new PropertyNameEqualityComparer())
                         where !dependencyProperties.Contains(prop.Name + "Property")
                         select prop;

            properties = properties
                         .ToArray();

            var typeInfo = new GeneratedTypeInfo(
                index: _typeMap.Count,
                hasProperties: properties.Any() || dependencyProperties.Any()
                );

            _typeMap.Add(ownerType, typeInfo);

            var baseType = GetBaseType(ownerType);

            // Call the builders for the base types
            if (baseType != null)
            {
                GenerateType(writer, baseType);
            }

            writer.AppendLineInvariant("/// <summary>");
            writer.AppendLineInvariant("/// Builder for {0}", ownerType.GetFullName());
            writer.AppendLineInvariant("/// </summary>");
            writer.AppendLineInvariant("[System.Runtime.CompilerServices.CompilerGeneratedAttribute]");
            writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1502:AvoidExcessiveComplexity\", Justification=\"Must be ignored even if generated code is checked.\")]");
            writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1506:AvoidExcessiveClassCoupling\", Justification = \"Must be ignored even if generated code is checked.\")]");

            AnalyzerSuppressionsGenerator.Generate(writer, AnalyzerSuppressions);
            using (writer.BlockInvariant("static class MetadataBuilder_{0:000}", typeInfo.Index))
            {
                var postWriter = new IndentedStringBuilder();
                postWriter.Indent(writer.CurrentLevel);

                // Generate a parameter-less build to avoid generating a lambda during registration (avoids creating a caching backing field)
                writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1502:AvoidExcessiveComplexity\", Justification=\"Must be ignored even if generated code is checked.\")]");
                writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1506:AvoidExcessiveClassCoupling\", Justification = \"Must be ignored even if generated code is checked.\")]");
                writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1505:AvoidUnmaintainableCode\", Justification = \"Must be ignored even if generated code is checked.\")]");
                using (writer.BlockInvariant("internal static global::Uno.UI.DataBinding.IBindableType Build()"))
                {
                    writer.AppendLineInvariant("return Build(null);");
                }

                writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1502:AvoidExcessiveComplexity\", Justification=\"Must be ignored even if generated code is checked.\")]");
                writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1506:AvoidExcessiveClassCoupling\", Justification = \"Must be ignored even if generated code is checked.\")]");
                writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1505:AvoidUnmaintainableCode\", Justification = \"Must be ignored even if generated code is checked.\")]");
                using (writer.BlockInvariant("internal static global::Uno.UI.DataBinding.IBindableType Build(global::Uno.UI.DataBinding.BindableType parent)"))
                {
                    writer.AppendLineInvariant(
                        @"var bindableType = parent ?? new global::Uno.UI.DataBinding.BindableType({0}, typeof({1}));",
                        flattenedProperties
                        .Where(p => !IsStringIndexer(p) && HasPublicGetter(p))
                        .Count()
                        , ExpandType(ownerType)
                        );

                    // Call the builders for the base types
                    if (baseType != null)
                    {
                        var baseTypeMapped = _typeMap.UnoGetValueOrDefault(baseType);

                        writer.AppendLineInvariant(@"MetadataBuilder_{0:000}.Build(bindableType); // {1}", baseTypeMapped.Index, ExpandType(baseType));
                    }

                    var ctor = ownerType.GetMethods().FirstOrDefault(m => m.MethodKind == MethodKind.Constructor && !m.Parameters.Any() && m.IsLocallyPublic(_currentModule));

                    if (ctor != null && IsCreateable(ownerType))
                    {
                        using (writer.BlockInvariant("if(parent == null)"))
                        {
                            writer.AppendLineInvariant(@"bindableType.AddActivator(CreateInstance);");
                            postWriter.AppendLineInvariant($@"private static object CreateInstance() => new {ownerTypeName}();");
                        }
                    }

                    foreach (var property in properties)
                    {
                        var propertyTypeName = property.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
                        var propertyName     = property.Name;

                        if (IsStringIndexer(property))
                        {
                            writer.AppendLineInvariant("bindableType.AddIndexer(GetIndexer, SetIndexer);");

                            postWriter.AppendLineInvariant($@"private static object GetIndexer(object instance, string name) => (({ownerTypeName})instance)[name];");

                            if (property.SetMethod != null)
                            {
                                postWriter.AppendLineInvariant($@"private static void SetIndexer(object instance, string name, object value) => (({ownerTypeName})instance)[name] = ({propertyTypeName})value;");
                            }
                            else
                            {
                                postWriter.AppendLineInvariant("private static void SetIndexer(object instance, string name, object value) {{}}");
                            }

                            continue;
                        }

                        if (property.IsIndexer)
                        {
                            // Other types of indexers are currently not supported.
                            continue;
                        }

                        if (
                            property.SetMethod != null &&
                            property.SetMethod != null &&
                            property.SetMethod.IsLocallyPublic(_currentModule)
                            )
                        {
                            if (property.Type.IsValueType)
                            {
                                writer.AppendLineInvariant($@"bindableType.AddProperty(""{propertyName}"", typeof({propertyTypeName}), Get{propertyName}, Set{propertyName});");

                                postWriter.AppendLineInvariant($@"private static object Get{propertyName}(object instance, Windows.UI.Xaml.DependencyPropertyValuePrecedences? precedence) => (({ownerTypeName})instance).{propertyName};");

                                using (postWriter.BlockInvariant($@"private static void Set{propertyName}(object instance, object value, Windows.UI.Xaml.DependencyPropertyValuePrecedences? precedence)"))
                                {
                                    using (postWriter.BlockInvariant($"if(value != null)"))
                                    {
                                        postWriter.AppendLineInvariant($"(({ownerTypeName})instance).{propertyName} = ({propertyTypeName})value;");
                                    }
                                }
                            }
                            else
                            {
                                writer.AppendLineInvariant($@"bindableType.AddProperty(""{propertyName}"", typeof({propertyTypeName}), Get{propertyName}, Set{propertyName});");

                                postWriter.AppendLineInvariant($@"private static object Get{propertyName}(object instance,  Windows.UI.Xaml.DependencyPropertyValuePrecedences? precedence) => (({ownerTypeName})instance).{propertyName};");
                                postWriter.AppendLineInvariant($@"private static void Set{propertyName}(object instance, object value, Windows.UI.Xaml.DependencyPropertyValuePrecedences? precedence) => (({ownerTypeName})instance).{propertyName} = ({propertyTypeName})value;");
                            }
                        }
                        else if (HasPublicGetter(property))
                        {
                            writer.AppendLineInvariant($@"bindableType.AddProperty(""{propertyName}"", typeof({propertyTypeName}), Get{propertyName});");

                            postWriter.AppendLineInvariant($@"private static object Get{propertyName}(object instance, Windows.UI.Xaml.DependencyPropertyValuePrecedences? precedence) => (({ownerTypeName})instance).{propertyName};");
                        }
                    }

                    foreach (var dependencyProperty in dependencyProperties)
                    {
                        var propertyName = dependencyProperty.TrimEnd("Property");

                        var getMethod = ownerType.GetMethods().FirstOrDefault(m => m.Name == "Get" + propertyName && m.Parameters.Length == 1 && m.IsLocallyPublic(_currentModule));
                        var setMethod = ownerType.GetMethods().FirstOrDefault(m => m.Name == "Set" + propertyName && m.Parameters.Length == 2 && m.IsLocallyPublic(_currentModule));

                        if (getMethod == null)
                        {
                            getMethod = ownerType
                                        .GetProperties()
                                        .FirstOrDefault(p => p.Name == propertyName && (p.GetMethod?.IsLocallyPublic(_currentModule) ?? false))
                                        ?.GetMethod;
                        }

                        if (getMethod != null)
                        {
                            var getter = $"{XamlConstants.Types.DependencyObjectExtensions}.GetValue(instance, {ownerTypeName}.{propertyName}Property, precedence)";
                            var setter = $"{XamlConstants.Types.DependencyObjectExtensions}.SetValue(instance, {ownerTypeName}.{propertyName}Property, value, precedence)";

                            var propertyType = GetGlobalQualifier(getMethod.ReturnType) + SanitizeTypeName(getMethod.ReturnType.ToString());

                            writer.AppendLineInvariant($@"bindableType.AddProperty(""{propertyName}"", typeof({propertyType}),  Get{propertyName}, Set{propertyName});");

                            postWriter.AppendLineInvariant($@"private static object Get{propertyName}(object instance,  Windows.UI.Xaml.DependencyPropertyValuePrecedences? precedence) => {getter};");
                            postWriter.AppendLineInvariant($@"private static void Set{propertyName}(object instance, object value, Windows.UI.Xaml.DependencyPropertyValuePrecedences? precedence) => {setter};");
                        }
                    }

                    writer.AppendLineInvariant(@"return bindableType;");
                }

                writer.Append(postWriter.ToString());
            }

            writer.AppendLine();
        }
        private void GenerateProviderTable(IEnumerable <INamedTypeSymbol> q, IndentedStringBuilder writer)
        {
            writer.AppendLineInvariant("[System.Runtime.CompilerServices.CompilerGeneratedAttribute]");
            writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1502:AvoidExcessiveComplexity\", Justification=\"Must be ignored even if generated code is checked.\")]");
            writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1506:AvoidExcessiveClassCoupling\", Justification = \"Must be ignored even if generated code is checked.\")]");

            AnalyzerSuppressionsGenerator.Generate(writer, AnalyzerSuppressions);
            using (writer.BlockInvariant("public class BindableMetadataProvider : global::Uno.UI.DataBinding.IBindableMetadataProvider"))
            {
                writer.AppendLineInvariant(@"static global::System.Collections.Hashtable _bindableTypeCacheByFullName = new global::System.Collections.Hashtable({0});", q.Count());

                writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1502:AvoidExcessiveComplexity\", Justification=\"Must be ignored even if generated code is checked.\")]");
                writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1506:AvoidExcessiveClassCoupling\", Justification = \"Must be ignored even if generated code is checked.\")]");
                writer.AppendLineInvariant("[System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1505:AvoidUnmaintainableCode\", Justification = \"Must be ignored even if generated code is checked.\")]");

                writer.AppendLineInvariant("private delegate global::Uno.UI.DataBinding.IBindableType TypeBuilderDelegate();");

                using (writer.BlockInvariant("private static TypeBuilderDelegate CreateMemoized(TypeBuilderDelegate builder)"))
                {
                    writer.AppendLineInvariant(@"global::Uno.UI.DataBinding.IBindableType value = null;
						return () => {{
							if (value == null)
							{{
								value = builder();
							}}

							return value;
						}};"
                                               );
                }

                using (writer.BlockInvariant("static BindableMetadataProvider()"))
                {
                    GenerateTypeTable(writer, q);
                }

                writer.AppendLineInvariant(@"#if DEBUG");
                writer.AppendLineInvariant(@"private global::System.Collections.Generic.List<global::System.Type> _knownMissingTypes = new global::System.Collections.Generic.List<global::System.Type>();");
                writer.AppendLineInvariant(@"#endif");

                using (writer.BlockInvariant("public void ForceInitialize()"))
                {
                    using (writer.BlockInvariant(@"foreach(TypeBuilderDelegate item in _bindableTypeCacheByFullName.Values)"))
                    {
                        writer.AppendLineInvariant(@"item();");
                    }
                }

                using (writer.BlockInvariant("public global::Uno.UI.DataBinding.IBindableType GetBindableTypeByFullName(string fullName)"))
                {
                    writer.AppendLineInvariant(@"var selector = _bindableTypeCacheByFullName[fullName] as TypeBuilderDelegate;");

                    using (writer.BlockInvariant(@"if(selector != null)"))
                    {
                        writer.AppendLineInvariant(@"return selector();");
                    }
                    using (writer.BlockInvariant(@"else"))
                    {
                        writer.AppendLineInvariant(@"return null;");
                    }
                }

                using (writer.BlockInvariant("public global::Uno.UI.DataBinding.IBindableType GetBindableTypeByType(Type type)"))
                {
                    writer.AppendLineInvariant(@"var selector = _bindableTypeCacheByFullName[type.FullName] as TypeBuilderDelegate;");

                    using (writer.BlockInvariant(@"if(selector != null)"))
                    {
                        writer.AppendLineInvariant(@"return selector();");
                    }

                    writer.AppendLineInvariant(@"#if DEBUG");
                    using (writer.BlockInvariant(@"else"))
                    {
                        using (writer.BlockInvariant(@"lock(_knownMissingTypes)"))
                        {
                            using (writer.BlockInvariant(@"if(!_knownMissingTypes.Contains(type) || !type.IsGenericType)"))
                            {
                                writer.AppendLineInvariant(@"_knownMissingTypes.Add(type);");
                                writer.AppendLineInvariant(@"Debug.WriteLine($""The Bindable attribute is missing and the type [{{type.FullName}}] is not known by the MetadataProvider. Reflection was used instead of the binding engine and generated static metadata. Add the Bindable attribute to prevent this message and performance issues."");");
                            }
                        }
                    }
                    writer.AppendLineInvariant(@"#endif");

                    writer.AppendLineInvariant(@"return null;");
                }
            }
        }
Пример #3
0
        private string GenerateGlobalResources(IEnumerable <XamlFileDefinition> files)
        {
            var outputFile = Path.Combine(_targetPath, "GlobalStaticResources.g.cs");

            var writer = new IndentedStringBuilder();

            writer.AppendLineInvariant("// <autogenerated />");
            writer.AppendLineInvariant("#pragma warning disable 618 // Ignore obsolete members warnings");
            writer.AppendLineInvariant("#pragma warning disable 105 // Ignore duplicate namespaces");
            writer.AppendLineInvariant("using System;");
            writer.AppendLineInvariant("using System.Linq;");
            writer.AppendLineInvariant("using System.Collections.Generic;");
            writer.AppendLineInvariant("using Uno.Extensions;");
            writer.AppendLineInvariant("using Uno;");
            writer.AppendLineInvariant("using System.Diagnostics;");

            //TODO Determine the list of namespaces to use
            writer.AppendLineInvariant($"using {XamlConstants.BaseXamlNamespace};");
            writer.AppendLineInvariant($"using {XamlConstants.Namespaces.Controls};");
            writer.AppendLineInvariant($"using {XamlConstants.Namespaces.Data};");
            writer.AppendLineInvariant($"using {XamlConstants.Namespaces.Documents};");
            writer.AppendLineInvariant($"using {XamlConstants.Namespaces.Media};");
            writer.AppendLineInvariant($"using {XamlConstants.Namespaces.MediaAnimation};");
            writer.AppendLineInvariant("using {0};", _defaultNamespace);
            writer.AppendLineInvariant("");

            using (writer.BlockInvariant("namespace {0}", _defaultNamespace))
            {
                writer.AppendLineInvariant("/// <summary>");
                writer.AppendLineInvariant("/// Contains all the static resources defined for the application");
                writer.AppendLineInvariant("/// </summary>");

                AnalyzerSuppressionsGenerator.Generate(writer, _analyzerSuppressions);
                using (writer.BlockInvariant("public sealed partial class GlobalStaticResources"))
                {
                    writer.AppendLineInvariant("static bool _initialized;");

                    using (writer.BlockInvariant("static GlobalStaticResources()"))
                    {
                        writer.AppendLineInvariant("Initialize();");
                    }

                    using (writer.BlockInvariant("public static void Initialize()"))
                    {
                        using (writer.BlockInvariant("if(!_initialized)"))
                        {
                            writer.AppendLineInvariant("_initialized = true;");

                            foreach (var ambientResource in _ambientGlobalResources)
                            {
                                if (ambientResource.GetMethods().Any(m => m.Name == "Initialize"))
                                {
                                    writer.AppendLineInvariant("global::{0}.Initialize();", ambientResource.GetFullName());
                                }

                                writer.AppendLineInvariant("AddResolver(global::{0}.FindResource);", ambientResource.GetFullName());
                            }

                            foreach (var file in files)
                            {
                                writer.AppendLineInvariant("RegisterResources_{0}();", file.UniqueID);
                                writer.AppendLineInvariant("RegisterImplicitStylesResources_{0}();", file.UniqueID);
                            }
                        }
                    }

                    // Generate all the partial methods, even if they don't exist. That avoids
                    // having to sync the generation of the files with this global table.
                    foreach (var file in files)
                    {
                        writer.AppendLineInvariant("static partial void RegisterResources_{0}();", file.UniqueID);
                        writer.AppendLineInvariant("static partial void RegisterImplicitStylesResources_{0}();", file.UniqueID);
                    }

                    writer.AppendLineInvariant("");

                    writer.AppendLineInvariant("/// <summary>");
                    writer.AppendLineInvariant("/// Finds a resource instance in the Global Static Resources");
                    writer.AppendLineInvariant("/// </summary>");
                    writer.AppendLineInvariant("/// <param name=\"name\">The name of the resource</param>");
                    writer.AppendLineInvariant("/// <returns>The instance of the resources, otherwise null.</returns>");
                    using (writer.BlockInvariant("public static object FindResource(string name)"))
                    {
                        using (writer.BlockInvariant("foreach(var resolver in _resolvers)"))
                        {
                            writer.AppendLineInvariant("var resource = resolver(name);");
                            writer.AppendLineInvariant("if(resource != null){{ return resource; }}");
                        }
                        writer.AppendLineInvariant("return null;");
                    }

                    writer.AppendLineInvariant("");

                    writer.AppendLineInvariant("private static List<Func<string, object>> _resolvers = new List<Func<string, object>>();");

                    using (writer.BlockInvariant("private static void AddResolver(Func<string, object> resolver)"))
                    {
                        writer.AppendLineInvariant("_resolvers.Add(resolver);");
                    }
                }
            }

            return(writer.ToString());
        }
Пример #4
0
        private string GenerateGlobalResources(IEnumerable <XamlFileDefinition> files, XamlGlobalStaticResourcesMap map)
        {
            var outputFile = Path.Combine(_targetPath, "GlobalStaticResources.g.cs");

            var writer = new IndentedStringBuilder();

            writer.AppendLineInvariant("// <autogenerated />");
            writer.AppendLineInvariant("#pragma warning disable 618  // Ignore obsolete members warnings");
            writer.AppendLineInvariant("#pragma warning disable 105  // Ignore duplicate namespaces");
            writer.AppendLineInvariant("#pragma warning disable 1591 // Ignore missing XML comment warnings");
            writer.AppendLineInvariant("using System;");
            writer.AppendLineInvariant("using System.Linq;");
            writer.AppendLineInvariant("using System.Collections.Generic;");
            writer.AppendLineInvariant("using Uno.Extensions;");
            writer.AppendLineInvariant("using Uno;");
            writer.AppendLineInvariant("using System.Diagnostics;");

            //TODO Determine the list of namespaces to use
            writer.AppendLineInvariant($"using {XamlConstants.BaseXamlNamespace};");
            writer.AppendLineInvariant($"using {XamlConstants.Namespaces.Controls};");
            writer.AppendLineInvariant($"using {XamlConstants.Namespaces.Data};");
            writer.AppendLineInvariant($"using {XamlConstants.Namespaces.Documents};");
            writer.AppendLineInvariant($"using {XamlConstants.Namespaces.Media};");
            writer.AppendLineInvariant($"using {XamlConstants.Namespaces.MediaAnimation};");
            writer.AppendLineInvariant("using {0};", _defaultNamespace);
            writer.AppendLineInvariant("");

            using (writer.BlockInvariant("namespace {0}", _defaultNamespace))
            {
                writer.AppendLineInvariant("/// <summary>");
                writer.AppendLineInvariant("/// Contains all the static resources defined for the application");
                writer.AppendLineInvariant("/// </summary>");

                AnalyzerSuppressionsGenerator.Generate(writer, _analyzerSuppressions);
                using (writer.BlockInvariant("public sealed partial class GlobalStaticResources"))
                {
                    writer.AppendLineInvariant("static bool _initialized;");
                    writer.AppendLineInvariant("private static bool _stylesRegistered;");
                    writer.AppendLineInvariant("private static bool _dictionariesRegistered;");

                    using (writer.BlockInvariant("internal static {0} {1} {{get; }} = new {0}()", ParseContextPropertyType, ParseContextPropertyName))
                    {
                        writer.AppendLineInvariant("AssemblyName = \"{0}\",", _projectInstance.GetPropertyValue("AssemblyName"));
                    }

                    writer.AppendLineInvariant(";");
                    writer.AppendLine();

                    using (writer.BlockInvariant("static GlobalStaticResources()"))
                    {
                        writer.AppendLineInvariant("Initialize();");
                    }

                    using (writer.BlockInvariant("public static void Initialize()"))
                    {
                        using (writer.BlockInvariant("if (!_initialized)"))
                        {
                            using (IsUnoAssembly ? writer.BlockInvariant("using (ResourceResolver.WriteInitiateGlobalStaticResourcesEventActivity())") : null)
                            {
                                writer.AppendLineInvariant("_initialized = true;");

                                foreach (var ambientResource in _ambientGlobalResources)
                                {
                                    if (ambientResource.GetMethods().Any(m => m.Name == "Initialize"))
                                    {
                                        writer.AppendLineInvariant("global::{0}.Initialize();", ambientResource.GetFullName());
                                    }
                                }

                                foreach (var ambientResource in _ambientGlobalResources)
                                {
                                    // Note: we do *not* call RegisterDefaultStyles for the current assembly, because those styles are treated as implicit styles, not default styles
                                    if (ambientResource.GetMethods().Any(m => m.Name == "RegisterDefaultStyles"))
                                    {
                                        writer.AppendLineInvariant("global::{0}.RegisterDefaultStyles();", ambientResource.GetFullName());
                                    }
                                }

                                foreach (var ambientResource in _ambientGlobalResources)
                                {
                                    if (ambientResource.GetMethods().Any(m => m.Name == "RegisterResourceDictionariesBySource"))
                                    {
                                        writer.AppendLineInvariant("global::{0}.RegisterResourceDictionariesBySource();", ambientResource.GetFullName());
                                    }
                                }

                                if (IsUnoAssembly && _xamlSourceFiles.Any())
                                {
                                    // Build master dictionary
                                    foreach (var dictProperty in map.GetAllDictionaryProperties(_baseResourceDependencies, _nonSystemResources))
                                    {
                                        writer.AppendLineInvariant("MasterDictionary.MergedDictionaries.Add({0});", dictProperty);
                                    }
                                }
                            }
                        }
                    }

                    using (writer.BlockInvariant("public static void RegisterDefaultStyles()"))
                    {
                        using (writer.BlockInvariant("if(!_stylesRegistered)"))
                        {
                            writer.AppendLineInvariant("_stylesRegistered = true;");
                            foreach (var file in files.Where(f => IsIncludedResource(f, map)).Select(f => f.UniqueID).Distinct())
                            {
                                writer.AppendLineInvariant("RegisterDefaultStyles_{0}();", file);
                            }
                        }
                    }

                    writer.AppendLineInvariant("// Register ResourceDictionaries using ms-appx:/// syntax, this is called for external resources");
                    using (writer.BlockInvariant("public static void RegisterResourceDictionariesBySource()"))
                    {
                        using (writer.BlockInvariant("if(!_dictionariesRegistered)"))
                        {
                            writer.AppendLineInvariant("_dictionariesRegistered = true;");

                            if (!IsUnoAssembly && !IsUnoFluentAssembly)
                            {
                                // For third-party libraries, expose all files using standard uri
                                foreach (var file in files.Where(IsResourceDictionary))
                                {
                                    var url = "{0}/{1}".InvariantCultureFormat(_metadataHelper.AssemblyName, map.GetSourceLink(file));
                                    RegisterForFile(file, url);
                                }
                            }
                            else if (files.Any())                             // The NETSTD reference assembly contains no Xaml files
                            {
                                // For Uno assembly, we expose WinUI resources using same uri as on Windows
                                RegisterForFile(files.FirstOrDefault(f => map.GetSourceLink(f).EndsWith(WinUIThemeResourcePathSuffix)), XamlFilePathHelper.WinUIThemeResourceURL);
                                RegisterForFile(files.FirstOrDefault(f => map.GetSourceLink(f).EndsWith(WinUICompactPathSuffix)), XamlFilePathHelper.WinUICompactURL);
                            }

                            void RegisterForFile(XamlFileDefinition file, string url)
                            {
                                if (file != null)
                                {
                                    writer.AppendLineInvariant("global::Uno.UI.ResourceResolver.RegisterResourceDictionaryBySource(uri: \"ms-appx:///{0}\", context: {1}, dictionary: () => {2}_ResourceDictionary);",
                                                               url,
                                                               ParseContextPropertyName,
                                                               file.UniqueID
                                                               );
                                }
                            }
                        }
                    }

                    writer.AppendLineInvariant("// Register ResourceDictionaries using ms-resource:/// syntax, this is called for local resources");
                    using (writer.BlockInvariant("internal static void RegisterResourceDictionariesBySourceLocal()"))
                    {
                        foreach (var file in files.Where(IsResourceDictionary))
                        {
                            // We leave context null because local resources should be found through Application.Resources
                            writer.AppendLineInvariant("global::Uno.UI.ResourceResolver.RegisterResourceDictionaryBySource(uri: \"{0}{1}\", context: null, dictionary: () => {2}_ResourceDictionary);",
                                                       XamlFilePathHelper.LocalResourcePrefix,
                                                       map.GetSourceLink(file),
                                                       file.UniqueID
                                                       );
                            // Local resources can also be found through the ms-appx:/// prefix
                            writer.AppendLineInvariant("global::Uno.UI.ResourceResolver.RegisterResourceDictionaryBySource(uri: \"{0}{1}\", context: null, dictionary: () => {2}_ResourceDictionary);",
                                                       XamlFilePathHelper.AppXIdentifier,
                                                       map.GetSourceLink(file),
                                                       file.UniqueID
                                                       );
                        }
                    }

                    if (IsUnoAssembly)
                    {
                        // Declare master dictionary
                        writer.AppendLine();
                        writer.AppendLineInvariant("internal static ResourceDictionary MasterDictionary {{get; }} = new ResourceDictionary();");
                    }

                    // Generate all the partial methods, even if they don't exist. That avoids
                    // having to sync the generation of the files with this global table.
                    foreach (var file in files.Select(f => f.UniqueID).Distinct())
                    {
                        writer.AppendLineInvariant("static partial void RegisterDefaultStyles_{0}();", file);
                    }

                    writer.AppendLineInvariant("[global::System.Obsolete(\"This method is provided for binary backward compatibility. It will always return null.\")]");
                    writer.AppendLineInvariant("[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]");
                    writer.AppendLineInvariant("public static object FindResource(string name) => null;");

                    writer.AppendLineInvariant("");
                }
            }

            return(writer.ToString());
        }
Пример #5
0
            private void ProcessType(INamedTypeSymbol typeSymbol)
            {
                _context.CancellationToken.ThrowIfCancellationRequested();

                if (typeSymbol.TypeKind != TypeKind.Class)
                {
                    return;
                }

                var isDependencyObject = typeSymbol.Interfaces.Any(t => SymbolEqualityComparer.Default.Equals(t, _dependencyObjectSymbol)) &&
                                         (typeSymbol.BaseType?.GetAllInterfaces().None(t => SymbolEqualityComparer.Default.Equals(t, _dependencyObjectSymbol)) ?? true);

                if (isDependencyObject)
                {
                    if (!_isUnoSolution)
                    {
                        if (typeSymbol.Is(_iosViewSymbol))
                        {
                            throw new InvalidOperationException("A 'UIKit.UIView' shouldn't implement 'DependencyObject'. Inherit 'FrameworkElement' instead.");
                        }
                        else if (typeSymbol.Is(_androidViewSymbol))
                        {
                            throw new InvalidOperationException("An 'Android.Views.View' shouldn't implement 'DependencyObject'. Inherit 'FrameworkElement' instead.");
                        }
                        else if (typeSymbol.Is(_macosViewSymbol))
                        {
                            throw new InvalidOperationException("An 'AppKit.NSView' shouldn't implement 'DependencyObject'. Inherit 'FrameworkElement' instead.");
                        }
                    }

                    var builder = new IndentedStringBuilder();
                    builder.AppendLineInvariant("// <auto-generated>");
                    builder.AppendLineInvariant("// ******************************************************************");
                    builder.AppendLineInvariant("// This file has been generated by Uno.UI (DependencyObjectGenerator)");
                    builder.AppendLineInvariant("// ******************************************************************");
                    builder.AppendLineInvariant("// </auto-generated>");
                    builder.AppendLine();
                    builder.AppendLineInvariant("#pragma warning disable 1591 // Ignore missing XML comment warnings");
                    builder.AppendLineInvariant($"using System;");
                    builder.AppendLineInvariant($"using System.Linq;");
                    builder.AppendLineInvariant($"using System.Collections.Generic;");
                    builder.AppendLineInvariant($"using System.Collections;");
                    builder.AppendLineInvariant($"using System.Diagnostics.CodeAnalysis;");
                    builder.AppendLineInvariant($"using Uno.Disposables;");
                    builder.AppendLineInvariant($"using System.Runtime.CompilerServices;");
                    builder.AppendLineInvariant($"using Uno.UI;");
                    builder.AppendLineInvariant($"using Uno.UI.Controls;");
                    builder.AppendLineInvariant($"using Uno.UI.DataBinding;");
                    builder.AppendLineInvariant($"using Windows.UI.Xaml;");
                    builder.AppendLineInvariant($"using Windows.UI.Xaml.Data;");
                    builder.AppendLineInvariant($"using Uno.Diagnostics.Eventing;");
                    builder.AppendLineInvariant("#if __MACOS__");
                    builder.AppendLineInvariant("using AppKit;");
                    builder.AppendLineInvariant("#endif");

                    using (builder.BlockInvariant($"namespace {typeSymbol.ContainingNamespace}"))
                    {
                        using (GenerateNestingContainers(builder, typeSymbol))
                        {
                            if (_bindableAttributeSymbol != null && typeSymbol.FindAttribute(_bindableAttributeSymbol) == null)
                            {
                                builder.AppendLineInvariant(@"[global::Windows.UI.Xaml.Data.Bindable]");
                            }

                            AnalyzerSuppressionsGenerator.Generate(builder, _analyzerSuppressions);

                            var internalDependencyObject = _isUnoSolution && !typeSymbol.IsSealed ? ", IDependencyObjectInternal" : "";

                            using (builder.BlockInvariant($"partial class {typeSymbol.Name} : IDependencyObjectStoreProvider, IWeakReferenceProvider{internalDependencyObject}"))
                            {
                                GenerateDependencyObjectImplementation(typeSymbol, builder);
                                GenerateIBinderImplementation(typeSymbol, builder);
                            }
                        }
                    }

                    _context.AddSource(HashBuilder.BuildIDFromSymbol(typeSymbol), builder.ToString());
                }
            }