예제 #1
0
            private void ProcessType(INamedTypeSymbol typeSymbol)
            {
                var isiOSView       = typeSymbol.Is(_iosViewSymbol);
                var ismacOSView     = typeSymbol.Is(_macosViewSymbol);
                var isAndroidView   = typeSymbol.Is(_androidViewSymbol);
                var smallSymbolName = typeSymbol.ToString().Replace(typeSymbol.ContainingNamespace + ".", "");

                if (isiOSView || ismacOSView)
                {
                    var nativeCtor = typeSymbol
                                     .GetMethods()
                                     .Where(m => m.MethodKind == MethodKind.Constructor && Equals(m.Parameters.FirstOrDefault()?.Type, _intPtrSymbol))
                                     .FirstOrDefault();

                    if (nativeCtor == null)
                    {
                        _context.AddCompilationUnit(
                            HashBuilder.BuildIDFromSymbol(typeSymbol),
                            string.Format(
                                BaseClassFormat,
                                typeSymbol.ContainingNamespace,
                                smallSymbolName,
                                NeedsExplicitDefaultCtor(typeSymbol),
                                typeSymbol.Name
                                )
                            );
                    }
                }

                if (isAndroidView)
                {
                    var nativeCtor = typeSymbol
                                     .GetMethods()
                                     .Where(m => m.MethodKind == MethodKind.Constructor && m.Parameters.Select(p => p.Type).SequenceEqual(_javaCtorParams))
                                     .FirstOrDefault();

                    if (nativeCtor == null)
                    {
                        _context.AddCompilationUnit(
                            HashBuilder.BuildIDFromSymbol(typeSymbol),
                            string.Format(
                                BaseClassFormat,
                                typeSymbol.ContainingNamespace,
                                smallSymbolName,
                                NeedsExplicitDefaultCtor(typeSymbol),
                                typeSymbol.Name
                                )
                            );
                    }
                }
            }
예제 #2
0
        private void GenerateCategories(
            SourceGeneratorContext context,
            IEnumerable <INamedTypeSymbol> symbols,
            int bucketCount)
        {
            var sha1 = SHA1.Create();

            foreach (var type in symbols)
            {
                var builder = new IndentedStringBuilder();

                builder.AppendLineInvariant("using System;");

                using (builder.BlockInvariant($"namespace {type.ContainingNamespace}"))
                {
                    // Compute a stable hash of the full metadata name
                    var buffer     = Encoding.UTF8.GetBytes(type.GetFullMetadataName());
                    var hash       = sha1.ComputeHash(buffer);
                    var hashPart64 = BitConverter.ToUInt64(hash, 0);

                    var testCategoryBucket = (hashPart64 % (uint)bucketCount) + 1;

                    builder.AppendLineInvariant($"[global::NUnit.Framework.Category(\"testBucket:{testCategoryBucket}\")]");
                    using (builder.BlockInvariant($"partial class {type.Name}"))
                    {
                    }
                }

                context.AddCompilationUnit(Sanitize(type.GetFullMetadataName()), builder.ToString());
            }
        }
        /// <inheritdoc />
        public override void Execute(SourceGeneratorContext context)
        {
            var output = new StringBuilder();

            output.AppendLine("// This is the list of all external references used to compile this project:");

            var lines = context
                        .Compilation
                        .References
                        .OrderBy(r => r.Display, StringComparer.InvariantCultureIgnoreCase)
                        .Select((r, i) => $"// #{i}: {r.Display}");

            output.AppendLine(string.Join(Environment.NewLine, lines));

            context.AddCompilationUnit(nameof(CompilationReferencesListingGenerator), output.ToString());

            var projectReferences = context
                                    .GetProjectInstance()
                                    .Items
                                    .Where(i => i.ItemType.Equals("PackageReference", StringComparison.OrdinalIgnoreCase))
                                    .ToArray();

            var projectDependencies = context
                                      .GetProjectInstance()
                                      .Items
                                      .Where(i => i.ItemType.Equals("PackageDependencies", StringComparison.OrdinalIgnoreCase))
                                      .ToArray();

            projectReferences.ToString();
        }
예제 #4
0
        public override void Execute(SourceGeneratorContext context)
        {
            if (
                context.GetProjectInstance().GetPropertyValue("Configuration") == "Debug" &&
                IsRemoteControlClientInstalled(context) &&
                IsApplication(context.GetProjectInstance()))
            {
                var sb = new IndentedStringBuilder();

                sb.AppendLineInvariant("// <auto-generated>");
                sb.AppendLineInvariant("// ***************************************************************************************");
                sb.AppendLineInvariant("// This file has been generated by the package Uno.UI.RemoteControl - for Xaml Hot Reload.");
                sb.AppendLineInvariant("// Documentation: https://platform.uno/docs/articles/features/working-with-xaml-hot-reload.html");
                sb.AppendLineInvariant("// ***************************************************************************************");
                sb.AppendLineInvariant("// </auto-generated>");
                sb.AppendLineInvariant("// <autogenerated />");
                sb.AppendLineInvariant("#pragma warning disable // Ignore code analysis warnings");

                sb.AppendLineInvariant("");

                BuildEndPointAttribute(context, sb);
                BuildSearchPaths(context, sb);

                context.AddCompilationUnit("RemoteControl", sb.ToString());
            }
        }
예제 #5
0
        public override void Execute(SourceGeneratorContext context)
        {
            Debugger.Launch();

            var project = context.GetProjectInstance();

            context.AddCompilationUnit("Test", "namespace MyGeneratedCode { class TestGeneration { } }");
        }
예제 #6
0
        public override void Execute(SourceGeneratorContext context)
        {
            var target = new PublicObjectWithDefaultCtor
            {
                Value = new Random().Next()
            };
            var syntax = CacheBuilder.CreateCache(target);

            context.AddCompilationUnit("Test", syntax);
        }
        public override void Execute(SourceGeneratorContext context)
        {
            var project = context.GetProjectInstance();

            var testClasses = context.Compilation.SourceModule.GlobalNamespace.GetNamedTypes().Where(
                t => t.AllInterfaces.Any(i => i.Name == "IContainSimpleTests"));

            foreach (var item in testClasses)
            {
                var members = item.GetMembers()
                              .OfType <IMethodSymbol>()
                              .Where(m => !m.IsAbstract &&
                                     !m.ReturnsVoid &&
                                     !m.Parameters.Any() &&
                                     m.MethodKind != MethodKind.PropertyGet &&
                                     (m.DeclaredAccessibility == Accessibility.Public ||
                                      m.DeclaredAccessibility == Accessibility.Internal));

                var memberText = new StringBuilder();

                foreach (var member in members)
                {
                    var returnType = member.ReturnType;

                    if (returnType.MetadataName.Equals("Boolean"))
                    {
                        memberText.Append(GetTest(item.MetadataName, member.Name, member.IsStatic));
                    }
                    else if (returnType.MetadataName.Equals("Task`1") && returnType is INamedTypeSymbol nts)
                    {
                        if (nts.Arity.Equals(1) && nts.TypeArguments.First().MetadataName.Equals("Boolean"))
                        {
                            memberText.Append(GetAsyncTest(item.MetadataName, member.Name, member.IsStatic));
                        }
                    }
                    else
                    {
                        // output nothing as not an inferred test
                    }
                }

                var memberOutput = memberText.ToString();

                if (!string.IsNullOrWhiteSpace(memberOutput))
                {
                    var classOpening = GetClassOpening(item.ContainingNamespace, item.MetadataName);
                    context.AddCompilationUnit(
                        $"{item.ContainingNamespace}.{item.MetadataName}",
                        $"{classOpening}{memberOutput}{GetClassClosing()}");
                }
            }
        }
예제 #8
0
            private void ProcessType(INamedTypeSymbol typeSymbol)
            {
                var isDependencyObject = typeSymbol.Interfaces.Any(t => t == _dependencyObjectSymbol) &&
                                         (typeSymbol.BaseType?.GetAllInterfaces().None(t => t == _dependencyObjectSymbol) ?? true);

                if (isDependencyObject && typeSymbol.TypeKind == TypeKind.Class)
                {
                    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.Extensions;");
                    builder.AppendLineInvariant($"using Uno.Logging;");
                    builder.AppendLineInvariant($"using Uno.UI;");
                    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;");

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

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

                    _context.AddCompilationUnit(HashBuilder.BuildIDFromSymbol(typeSymbol), builder.ToString());
                }
            }
        public override void Execute(SourceGeneratorContext context)
        {
            try
            {
                if (PlatformHelper.IsValidPlatform(context))
                {
                    var project = context.GetProjectInstance();

                    if (IsApplication(project))
                    {
                        _defaultNamespace = project.GetPropertyValue("RootNamespace");

                        _bindableAttributeSymbol  = FindBindableAttributes(context);
                        _dependencyPropertySymbol = context.Compilation.GetTypeByMetadataName(XamlConstants.Types.DependencyProperty);

                        _objectSymbol      = context.Compilation.GetTypeByMetadataName("System.Object");
                        _javaObjectSymbol  = context.Compilation.GetTypeByMetadataName("Java.Lang.Object");
                        _nsObjectSymbol    = context.Compilation.GetTypeByMetadataName("Foundation.NSObject");
                        _stringSymbol      = context.Compilation.GetTypeByMetadataName("System.String");
                        _nonBindableSymbol = context.Compilation.GetTypeByMetadataName("Windows.UI.Xaml.Data.NonBindableAttribute");

                        _currentModule = context.Compilation.SourceModule;

                        AnalyzerSuppressions = new string[0];

                        var modules = from ext in context.Compilation.ExternalReferences
                                      let sym = context.Compilation.GetAssemblyOrModuleSymbol(ext) as IAssemblySymbol
                                                where sym != null
                                                from module in sym.Modules
                                                select module;

                        modules = modules.Concat(context.Compilation.SourceModule);

                        context.AddCompilationUnit("BindableMetadata", GenerateTypeProviders(modules));
                    }
                }
            }
            catch (Exception e)
            {
                var message = e.Message + e.StackTrace;

                if (e is AggregateException)
                {
                    message = (e as AggregateException).InnerExceptions.Select(ex => ex.Message + e.StackTrace).JoinBy("\r\n");
                }

                this.Log().Error("Failed to generate type providers.", new Exception("Failed to generate type providers." + message, e));
            }
        }
        public override void Execute(SourceGeneratorContext context)
        {
            _project         = context.Project;
            _projectInstance = context.GetProjectInstance();
            _compilation     = context.Compilation;

            // Debugger.Launch();

            GenerateSerializers();

            foreach (var files in _generatedFiles)
            {
                context.AddCompilationUnit(files.Item1, files.Item2);
            }
        }
예제 #11
0
        public override void Execute(SourceGeneratorContext context)
        {
            if (
                context.GetProjectInstance().GetPropertyValue("Configuration") == "Debug" &&
                IsRemoteControlClientInstalled(context) &&
                IsApplication(context.GetProjectInstance()))
            {
                var sb = new IndentedStringBuilder();

                BuildEndPointAttribute(context, sb);
                BuildSearchPaths(context, sb);

                context.AddCompilationUnit("RemoteControl", sb.ToString());
            }
        }
        public override void Execute(SourceGeneratorContext context)
        {
            var project = context.GetProjectInstance();

            context.AddCompilationUnit(
                "Test",
                $@"
namespace Test {{
	class MyGeneratedType 
	{{
		// Project: {project?.FullPath}
	}}
}}"
                );
        }
예제 #13
0
        public override void Execute(SourceGeneratorContext context)
        {
            var project = context.GetProjectInstance();

            context.AddCompilationUnit(
                "Test2",
                $@"
namespace AdditionalPropertiesGeneratorTest {{
	public static class TestType
	{{
		// Project: {project?.FullPath}
		// reusing the compiled code form other generator
		public const int Project = {project.GetProperty("MyTestProperty").EvaluatedValue};
	}}
}}");
        }
예제 #14
0
        public override void Execute(SourceGeneratorContext context)
        {
            var project = context.GetProjectInstance();

            context.AddCompilationUnit(
                "Test2",
                $@"
namespace Test {{
	public static class MyGeneratedType2
	{{
		// Project: {project?.FullPath}
		// reusing the compiled code form other generator
		public const string Project = MyGeneratedType.Project;
	}}
}}");
        }
예제 #15
0
        public override void Execute(SourceGeneratorContext context)
        {
            var gen = new XamlCodeGeneration(
                context.Compilation,
                context.GetProjectInstance(),
                context.Project
                );

            if (PlatformHelper.IsValidPlatform(context))
            {
                var genereratedTrees = gen.Generate();

                foreach (var tree in genereratedTrees)
                {
                    context.AddCompilationUnit(tree.Key, tree.Value);
                }
            }
        }
예제 #16
0
        public override void Execute(SourceGeneratorContext context)
        {
            var project = context.GetProjectInstance();

            context.GetLogger().Debug($"{nameof(MyCustomSourceGenerator)}: This is a DEBUG logging");
            context.GetLogger().Info($"{nameof(MyCustomSourceGenerator)}: This is an INFO logging");

#if DEBUG // Only in DEBUG to prevent breaking the CI build.
            context.GetLogger().Warn($"{nameof(MyCustomSourceGenerator)}: This is a WARN logging");
            context.GetLogger().Error($"{nameof(MyCustomSourceGenerator)}: This is an ERROR logging");
#endif

            // This test ensures that dependent libraries are included in the compilation
            // generated from the AdHoc workspace.
            var dependentString = BuildVariableFromType(context, DependentTypeName, "_dependent");

            // This test ensures that linked files included in the project are included
            // in the Compilation instance used by the generators.
            var linkedString = BuildVariableFromType(context, LinkedTypeName, "_linked");

            // This test validates that some duplicate files do not interfere wi
            var objectString = BuildVariableFromType(context, SystemObject, "_object");

            var stringTypeString = BuildVariableFromType(context, "System.String", "_aString");

            context.AddCompilationUnit(
                "Test",
                $@"
#pragma warning disable 169
namespace Test {{
	public static class MyGeneratedType 
	{{
		// Project: {project?.FullPath}
		public const string Project = @""{ project?.FullPath}"";
		{dependentString}
		{linkedString}
		{objectString}
		{stringTypeString}
	}}
}}"
                );
        }
예제 #17
0
        private void Generate(LifecycleMethods methods)
        {
            var names = methods.Owner.GetSymbolNames();

            var(dispose, appendToConstructor, appendToFinalizer) = methods.Disposes.Any()
                                ? GetDispose(names, methods)
                                : (null, null, null);

            var constructor = methods.Constructors.Any() || appendToConstructor.HasValue()
                                ? GetConstructor(names, methods, appendToConstructor)
                                : null;

            var finalize = methods.Finalizers.Any() || appendToFinalizer.HasValue()
                                ? GetFinalizer(names, methods, appendToFinalizer)
                                : null;

            var code = new StringWriter();

            using (var writer = new IndentedTextWriter(code, "\t"))
            {
                writer.WriteLine("// <auto-generated>");
                writer.WriteLine("// ***************************************************************************************************************************");
                writer.WriteLine("// This file has been generated by Uno.CodeGen (ClassLifecycleGenerator), available at https://github.com/nventive/Uno.CodeGen");
                writer.WriteLine("// ***************************************************************************************************************************");
                writer.WriteLine("// </auto-generated>");
                writer.WriteLine("#pragma warning disable");
                writer.WriteLine();
                writer.WriteLine("using global::System;");

                using (writer.NameSpaceOf(methods.Owner))
                {
                    using (writer.Block($"partial class {names.NameWithGenerics} {(methods.Disposes.Any() ? ": global::System.IDisposable" : "")}"))
                    {
                        writer.WriteLine(constructor);
                        writer.WriteLine(dispose);
                        writer.WriteLine(finalize);
                    }
                }
            }

            _context.AddCompilationUnit(names.FilePath, code.ToString());
        }
예제 #18
0
            private void ProcessType(INamedTypeSymbol type)
            {
                bool        fromSerializable = false;
                ITypeSymbol typeArg          = null;

                foreach (var iface in type.AllInterfaces)
                {
                    if (iface.ConstructedFrom == serializableInterface)
                    {
                        fromSerializable = true;
                        typeArg          = iface.TypeArguments.Single();
                        break;
                    }
                }

                if (fromSerializable)
                {
                    var parseOptions = CSharpParseOptions.Default
                                       .WithFeatures(_comp.SyntaxTrees.First().Options.Features);

                    var source     = SyntaxFactory.ParseSyntaxTree($@"
{GetUsings()}

namespace {GetAllNamespaces(type)}
{{
    {type.DeclaredAccessibility.ToString().ToLower()} partial class {type.Name}
    {{
        public void Serialize(TextWriter writer)
        {{
            {GetSerializeMethod(type)}
        }}
    }}
}}
", encoding: Encoding.UTF8, options: parseOptions);
                    var normalized = source.GetRoot().NormalizeWhitespace();
                    source = SyntaxFactory.SyntaxTree(normalized, parseOptions, encoding: Encoding.UTF8);
                    _context.AddCompilationUnit($"{type.Name}.JsonSerializable", source);
                }
            }
        private void BuildType(SourceGeneratorContext context, INamedTypeSymbol symbol)
        {
            if (_processed.Contains(symbol))
            {
                return;
            }

            _processed.Add(symbol);

            if (!IsWindowsSymbol(symbol))
            {
                return;
            }

            var builder = new IndentedStringBuilder();

            builder.AppendLineInvariant("using Uno;");
            builder.AppendLineInvariant("using System.Runtime.CompilerServices;");

            using (builder.BlockInvariant($"namespace {Relocate(symbol.ContainingNamespace.ToDisplayString())}"))
            {
                AddTypeToQueue(symbol.BaseType);

                var baseType = symbol.BaseType != _objectSymbol && !symbol.IsValueType ? $": {Relocate(symbol.BaseType)}" : "";

                switch (symbol.TypeKind)
                {
                case TypeKind.Enum:
                    GenerateEnum(symbol, builder, baseType);
                    break;

                default:
                    GenerateClass(symbol, builder, baseType);
                    break;
                }
            }

            context.AddCompilationUnit(symbol.Name, builder.ToString());
        }
        public override void Execute(SourceGeneratorContext context)
        {
            var project = context.GetProjectInstance();

            context.GetLogger().Debug($"{nameof(MyCustomSourceGenerator)}: This is a DEBUG logging");
            context.GetLogger().Info($"{nameof(MyCustomSourceGenerator)}: This is an INFO logging");

#if DEBUG // Only in DEBUG to prevent breaking the CI build.
            context.GetLogger().Warn($"{nameof(MyCustomSourceGenerator)}: This is a WARN logging");
            context.GetLogger().Error($"{nameof(MyCustomSourceGenerator)}: This is an ERROR logging");
#endif

            context.AddCompilationUnit(
                "Test",
                $@"
namespace Test {{
	public static class MyGeneratedType 
	{{
		// Project: {project?.FullPath}
		public const string Project = @""{ project?.FullPath}"";
	}}
}}"
                );
        }
예제 #21
0
        private void GenerateSamplesList(SourceGeneratorContext context, IEnumerable <INamedTypeSymbol> query)
        {
            var builder = new IndentedStringBuilder();

            builder.AppendLineInvariant("using System;");

            using (builder.BlockInvariant($"namespace SampleControl.Presentation"))
            {
                using (builder.BlockInvariant($"partial class SampleChooserViewModel"))
                {
                    using (builder.BlockInvariant($"internal Type[] _allSamples = new Type[]"))
                    {
                        foreach (var type in query)
                        {
                            builder.AppendLineInvariant($"typeof({type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}),");
                        }
                    }

                    builder.AppendLineInvariant(";");
                }
            }

            context.AddCompilationUnit("AllSamplesList", builder.ToString());
        }
예제 #22
0
        void GenerateSource(SourceGeneratorContext context)
        {
            logger.Info("Generate the extensions source!");

            foreach (var containerClass in hyperlinqNamespace
                     .GetTypeMembers()
                     .Where(type =>
                            type.IsPublic() &&
                            type.IsStatic &&
                            type.IsReferenceType &&
                            !type.ShouldIgnore(context.Compilation)))
            {
                var assemblyName           = GetType().Assembly.GetName().Name;
                var assemblyVersion        = ((System.Reflection.AssemblyInformationalVersionAttribute)Attribute.GetCustomAttribute(GetType().Assembly, typeof(System.Reflection.AssemblyInformationalVersionAttribute), false))?.InformationalVersion ?? string.Empty;
                var generatedCodeAttribute = $"[GeneratedCode(\"{assemblyName}\", \"{assemblyVersion}\")]";

                foreach (var extendedType in
                         containerClass.GetTypeMembers()
                         .OfType <INamedTypeSymbol>()
                         .Where(type =>
                                !type.IsStatic &&
                                !type.IsInterface()))
                {
                    var valueEnumerableInterface = extendedType.GetAllInterfaces()
                                                   .FirstOrDefault(@interface => @interface.Name == "IValueEnumerable" || @interface.Name == "IAsyncValueEnumerable");
                    if (valueEnumerableInterface is null)
                    {
                        continue;
                    }

                    var enumerableType = extendedType;
                    var enumeratorType = valueEnumerableInterface.TypeArguments[1];
                    var sourceType     = valueEnumerableInterface.TypeArguments[0];

                    var genericsMapping = ImmutableArray.CreateRange(extendedType.GetGenericMappings(context.Compilation));

                    var implementedInstanceMethods = extendedType.GetMembers().OfType <IMethodSymbol>()
                                                     .Select(method => Tuple.Create(
                                                                 method.Name,
                                                                 method.Parameters
                                                                 .Select(parameter => parameter.Type.ToDisplayString())
                                                                 .ToList()));

                    var implementedExtensionMethods = containerClass.GetMembers().OfType <IMethodSymbol>()
                                                      .Where(method =>
                                                             method.IsExtensionMethod &&
                                                             method.Parameters[0].Type.ToDisplayString() == extendedType.ToDisplayString())
                                                      .Select(method => Tuple.Create(
                                                                  method.Name,
                                                                  method.Parameters
                                                                  .Skip(1)
                                                                  .Select(parameter => parameter.Type.ToDisplayString())
                                                                  .ToList()));

                    var implementedMethods = implementedInstanceMethods.Concat(implementedExtensionMethods)
                                             .ToList();

                    var instanceMethods  = new List <IMethodSymbol>();
                    var extensionMethods = new List <IMethodSymbol>();

                    foreach (var implementedType in extendedType.AllInterfaces)
                    {
                        // get the extension methods for this interface
                        var key = implementedType.OriginalDefinition.MetadataName;
                        if (!collectedExtensionMethods.TryGetValue(key, out var implementedTypeMethods))
                        {
                            continue;
                        }

                        foreach (var implementedTypeMethod in implementedTypeMethods)
                        {
                            var methodName       = implementedTypeMethod.Name;
                            var methodParameters = implementedTypeMethod.Parameters
                                                   .Skip(1)
                                                   .Select(parameter => parameter.Type.ToDisplayString(genericsMapping))
                                                   .ToList();

                            // check if already implemented
                            if (!implementedMethods.Any(method =>
                                                        method.Item1 == methodName &&
                                                        Enumerable.SequenceEqual(method.Item2, methodParameters)))
                            {
                                // check there's a collision with a property
                                if (extendedType.GetMembers().OfType <IPropertySymbol>()
                                    .Any(property => property.Name == methodName))
                                {
                                    extensionMethods.Add(implementedTypeMethod);
                                }
                                else
                                {
                                    instanceMethods.Add(implementedTypeMethod);
                                }

                                implementedMethods.Add(Tuple.Create(methodName, methodParameters));
                            }
                        }
                    }

                    if (instanceMethods.Count != 0 || extensionMethods.Count != 0)
                    {
                        var builder = new IndentedStringBuilder();
                        builder.AppendLineInvariant("using System;");
                        builder.AppendLineInvariant("using System.CodeDom.Compiler;");
                        builder.AppendLineInvariant("using System.Diagnostics;");
                        builder.AppendLineInvariant("using System.Diagnostics.Contracts;");
                        builder.AppendLineInvariant("using System.Runtime.CompilerServices;");

                        using (builder.BlockInvariant($"namespace {containerClass.ContainingNamespace}"))
                        {
                            using (builder.BlockInvariant($"public static partial class {containerClass.Name}"))
                            {
                                if (instanceMethods.Count != 0)
                                {
                                    var extendedTypeGenericParameters = string.Empty;
                                    if (extendedType.IsGenericType)
                                    {
                                        var parametersDefinition = new System.Text.StringBuilder();
                                        _ = parametersDefinition.Append($"<{extendedType.TypeParameters.Select(parameter => parameter.ToDisplayString()).ToCommaSeparated()}>");
                                        foreach (var typeParameter in extendedType.TypeParameters.Where(typeParameter => typeParameter.ConstraintTypes.Length != 0))
                                        {
                                            _ = parametersDefinition.Append($" where {typeParameter.Name} : {typeParameter.AsConstraintsStrings().ToCommaSeparated()}");
                                        }
                                        extendedTypeGenericParameters = parametersDefinition.ToString();
                                    }

                                    var entity = extendedType.IsValueType ? "readonly partial struct" : "partial class";
                                    using (builder.BlockInvariant($"public {entity} {extendedType.Name}{extendedTypeGenericParameters}"))
                                    {
                                        foreach (var instanceMethod in instanceMethods)
                                        {
                                            AddInstanceMethod(builder, extendedType, instanceMethod, enumerableType, enumeratorType, generatedCodeAttribute, genericsMapping);
                                        }
                                    }
                                }

                                foreach (var extensionMethod in extensionMethods)
                                {
                                    AddExtensionMethod(builder, extendedType, extensionMethod, enumerableType, enumeratorType, generatedCodeAttribute, genericsMapping);
                                }
                            }
                        }

                        context.AddCompilationUnit(extendedType.ToString(), builder.ToString());
                    }
                }
            }
        }
예제 #23
0
            private void ProcessType(INamedTypeSymbol typeSymbol)
            {
                var isDependencyObject = typeSymbol.GetAllInterfaces().Any(t => Equals(t, _dependencyObjectSymbol));

                if ((isDependencyObject || typeSymbol.IsStatic) && typeSymbol.TypeKind == TypeKind.Class)
                {
                    var hasGeneratedProperties =
                        typeSymbol.GetProperties().Any(p => p.FindAttribute(_generatedDependencyPropertyAttributeSymbol) != null) ||
                        typeSymbol.GetFields().Any(p => p.FindAttribute(_generatedDependencyPropertyAttributeSymbol) != null);

                    if (hasGeneratedProperties)
                    {
                        var builder = new IndentedStringBuilder();
                        builder.AppendLineInvariant("// <auto-generated>");
                        builder.AppendLineInvariant("// ******************************************************************");
                        builder.AppendLineInvariant("// This file has been generated by Uno.UI (DependencyPropertyGenerator)");
                        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.Extensions;");
                        builder.AppendLineInvariant($"using Uno.Logging;");
                        builder.AppendLineInvariant($"using Uno.UI;");
                        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;");

                        var attachedPropertiesBackingFieldStatements = new Dictionary <INamedTypeSymbol, List <string> >();

                        using (builder.BlockInvariant($"namespace {typeSymbol.ContainingNamespace}"))
                        {
                            using (GenerateNestingContainers(builder, typeSymbol))
                            {
                                using (builder.BlockInvariant($"{typeSymbol.GetAccessibilityAsCodeString()} partial class {typeSymbol.Name}"))
                                {
                                    foreach (var memberSymbol in typeSymbol.GetMembers())
                                    {
                                        if (memberSymbol.FindAttribute(_generatedDependencyPropertyAttributeSymbol) is AttributeData attribute)
                                        {
                                            var isAttached = GetBooleanAttributeValue(attribute, "Attached", false);

                                            if (isAttached)
                                            {
                                                GenerateAttachedProperty(builder, typeSymbol, memberSymbol, attribute, attachedPropertiesBackingFieldStatements);
                                            }
                                            else
                                            {
                                                GenerateProperty(builder, typeSymbol, memberSymbol, attribute);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        foreach (var backingFieldType in attachedPropertiesBackingFieldStatements)
                        {
                            using (builder.BlockInvariant($"namespace {backingFieldType.Key.ContainingNamespace}"))
                            {
                                using (GenerateNestingContainers(builder, backingFieldType.Key))
                                {
                                    using (builder.BlockInvariant($"partial class {backingFieldType.Key.Name}"))
                                    {
                                        foreach (var statement in backingFieldType.Value)
                                        {
                                            builder.AppendLineInvariant(statement);
                                        }
                                    }
                                }
                            }
                        }

                        _context.AddCompilationUnit(HashBuilder.BuildIDFromSymbol(typeSymbol), builder.ToString());
                    }
                }
            }
예제 #24
0
        private void GenerateEquality(INamedTypeSymbol typeSymbol)
        {
            var builder = new IndentedStringBuilder();

            var(symbolName, genericArguments, symbolNameWithGenerics, symbolNameForXml, symbolNameDefinition, resultFileName, _) = typeSymbol.GetSymbolNames();
            var(equalityMembers, hashMembers, keyEqualityMembers) = GetEqualityMembers(typeSymbol);
            var baseTypeInfo      = GetBaseTypeInfo(typeSymbol);
            var generateKeyEquals = baseTypeInfo.baseImplementsKeyEquals || baseTypeInfo.baseImplementsKeyEqualsT || keyEqualityMembers.Any();

            builder.AppendLineInvariant("// <auto-generated>");
            builder.AppendLineInvariant("// **********************************************************************************************************************");
            builder.AppendLineInvariant("// This file has been generated by Uno.CodeGen (ImmutableGenerator), available at https://github.com/nventive/Uno.CodeGen");
            builder.AppendLineInvariant("// **********************************************************************************************************************");
            builder.AppendLineInvariant("// </auto-generated>");
            builder.AppendLineInvariant("#pragma warning disable");
            builder.AppendLine();
            builder.AppendLine("using System;");
            builder.AppendLine();

            using (builder.BlockInvariant($"namespace {typeSymbol.ContainingNamespace}"))
            {
                if (!IsFromPartialDeclaration(typeSymbol))
                {
                    builder.AppendLineInvariant($"#warning {nameof(EqualityGenerator)}: you should add the partial modifier to the class {symbolNameWithGenerics}.");
                }

                if (baseTypeInfo.isBaseType && !baseTypeInfo.baseOverridesEquals)
                {
                    builder.AppendLineInvariant($"#warning {nameof(EqualityGenerator)}: base type {typeSymbol.BaseType} does not override .Equals() method. It could lead to erroneous results.");
                }
                if (baseTypeInfo.isBaseType && !baseTypeInfo.baseOverridesGetHashCode)
                {
                    builder.AppendLineInvariant($"#warning {nameof(EqualityGenerator)}: base type {typeSymbol.BaseType} does not override .GetHashCode() method. It could lead to erroneous results.");
                }

                if (generateKeyEquals && !_generateKeyEqualityCode)
                {
                    builder.AppendLineInvariant($"#warning {nameof(EqualityGenerator)}: To use the `KeyEquality` features, you need to add a reference to `Uno.Core` package. https://www.nuget.org/packages/Uno.Core/");
                    generateKeyEquals = false;
                }

                var classOrStruct = typeSymbol.IsReferenceType ? "class" : "struct";

                var keyEqualsInterfaces = generateKeyEquals
                                        ? $", global::Uno.Equality.IKeyEquatable<{symbolNameWithGenerics}>, global::Uno.Equality.IKeyEquatable"
                                        : "";

                using (builder.BlockInvariant($"{typeSymbol.GetAccessibilityAsCSharpCodeString()} partial {classOrStruct} {symbolNameWithGenerics} : IEquatable<{symbolNameWithGenerics}>{keyEqualsInterfaces}"))
                {
                    builder.AppendLineInvariant("/// <summary>");
                    builder.AppendLineInvariant($"/// Checks two instances of {symbolNameForXml} for equality.");
                    builder.AppendLineInvariant("/// </summary>");
                    builder.AppendLineInvariant("/// <remarks>");
                    builder.AppendLineInvariant("/// You can also simply use the overriden '==' and '!=' operators.");
                    builder.AppendLineInvariant("/// </remarks>");
                    builder.AppendLineInvariant("[global::System.Diagnostics.Contracts.Pure]");

                    using (builder.BlockInvariant($"public static bool Equals({symbolNameWithGenerics} a, {symbolNameWithGenerics} b)"))
                    {
                        if (typeSymbol.IsReferenceType)
                        {
                            builder.AppendLineInvariant("if (ReferenceEquals(a, b)) return true; // Same instance or both null");
                            using (builder.BlockInvariant("if (ReferenceEquals(null, a))"))
                            {
                                builder.AppendLineInvariant("return ReferenceEquals(null, b);");
                            }
                            builder.AppendLineInvariant("return !ReferenceEquals(null, b) && a.InnerEquals(b);");
                        }
                        else
                        {
                            builder.AppendLineInvariant("return a.InnerEquals(b);");
                        }
                    }

                    builder.AppendLine();

                    builder.AppendLineInvariant("/// <inheritdoc />");
                    builder.AppendLineInvariant("[global::System.Diagnostics.Contracts.Pure]");
                    using (builder.BlockInvariant($"public bool Equals({symbolNameWithGenerics} other) // Implementation of `IEquatable<{symbolNameWithGenerics}>.Equals()`"))
                    {
                        if (typeSymbol.IsReferenceType)
                        {
                            builder.AppendLineInvariant("if (ReferenceEquals(this, other)) return true;");
                            builder.AppendLineInvariant("if (ReferenceEquals(null, other)) return false;");
                        }
                        builder.AppendLineInvariant("return InnerEquals(other);");
                    }

                    builder.AppendLine();

                    builder.AppendLineInvariant("/// <inheritdoc />");
                    builder.AppendLineInvariant("[global::System.Diagnostics.Contracts.Pure]");
                    using (builder.BlockInvariant("public override bool Equals(object other)  // This one from `System.Object.Equals()`"))
                    {
                        if (typeSymbol.IsReferenceType)
                        {
                            builder.AppendLineInvariant($"return Equals(other as {symbolNameWithGenerics});");
                        }
                        else
                        {
                            builder.AppendLineInvariant($"return other is {symbolNameWithGenerics} ? Equals(({symbolNameWithGenerics})other) : false;");
                        }
                    }

                    builder.AppendLine();

                    builder.AppendLineInvariant("#region \"InnerEquals\" Method -- THIS IS WHERE EQUALITY IS CHECKED");

                    builder.AppendLineInvariant("// private method doing the real .Equals() job");
                    using (builder.BlockInvariant($"private bool InnerEquals({symbolNameWithGenerics} other)"))
                    {
                        builder.AppendLineInvariant("if (other.GetHashCode() != GetHashCode()) return false;");

                        var baseCall = baseTypeInfo.baseOverridesEquals
                                                        ? "base.Equals(other)"
                                                        : null;

                        GenerateEqualLogic(typeSymbol, builder, equalityMembers, baseCall);
                    }

                    builder.AppendLineInvariant("#endregion");
                    builder.AppendLine();

                    builder.AppendLineInvariant("/// <inheritdoc />");
                    using (builder.BlockInvariant($"public static bool operator ==({symbolNameWithGenerics} a, {symbolNameWithGenerics} b)"))
                    {
                        builder.AppendLineInvariant("return Equals(a, b);");
                    }

                    builder.AppendLine();

                    builder.AppendLineInvariant("/// <inheritdoc />");
                    using (builder.BlockInvariant($"public static bool operator !=({symbolNameWithGenerics} a, {symbolNameWithGenerics} b)"))
                    {
                        builder.AppendLineInvariant("return !Equals(a, b);");
                    }

                    builder.AppendLine();
                    builder.AppendLineInvariant("#region \".GetHashCode()\" Section -- THIS IS WHERE HASH CODE IS COMPUTED");

                    builder.AppendLineInvariant("/// <inheritdoc />");
                    builder.AppendLineInvariant("[global::System.Diagnostics.Contracts.Pure]");
                    using (builder.BlockInvariant("public override int GetHashCode()"))
                    {
                        builder.AppendLineInvariant("return _computedHashCode ?? (int)(_computedHashCode = ComputeHashCode());");
                    }

                    builder.AppendLine();

                    builder.AppendLineInvariant("private int? _computedHashCode;");

                    builder.AppendLine();

                    using (builder.BlockInvariant("private int ComputeHashCode()"))
                    {
                        var baseCall = baseTypeInfo.baseOverridesGetHashCode
                                                        ? "base.GetHashCode()"
                                                        : null;
                        GenerateHashLogic(typeSymbol, builder, hashMembers, baseCall);
                    }

                    builder.AppendLineInvariant("#endregion");
                    builder.AppendLine();

                    if (generateKeyEquals)
                    {
                        builder.AppendLineInvariant("#region \"Key Equality\" Section -- THIS IS WHERE KEY EQUALS IS DONE + KEY HASH CODE IS COMPUTED");

                        builder.AppendLineInvariant("/// <inheritdoc />");
                        builder.AppendLineInvariant("[global::System.Diagnostics.Contracts.Pure]");
                        using (builder.BlockInvariant("public bool KeyEquals(object other)"))
                        {
                            if (typeSymbol.IsReferenceType)
                            {
                                builder.AppendLineInvariant($"return KeyEquals(other as {symbolNameWithGenerics});");
                            }
                            else
                            {
                                builder.AppendLineInvariant($"return other is {symbolNameWithGenerics} ? KeyEquals(({symbolNameWithGenerics})other) : false;");
                            }
                        }
                        builder.AppendLine();
                        using (builder.BlockInvariant($"public bool KeyEquals({symbolNameWithGenerics} other)"))
                        {
                            if (typeSymbol.IsReferenceType)
                            {
                                builder.AppendLineInvariant("if (ReferenceEquals(this, other)) return true;");
                                builder.AppendLineInvariant("if (ReferenceEquals(null, other)) return false;");
                            }

                            builder.AppendLineInvariant("return InnerKeyEquals(other);");
                        }

                        builder.AppendLine();

                        builder.AppendLineInvariant("// private method doing the real .KeyEquals() job");
                        using (builder.BlockInvariant($"private bool InnerKeyEquals({symbolNameWithGenerics} other)"))
                        {
                            builder.AppendLineInvariant("if (other.GetKeyHashCode() != GetKeyHashCode()) return false;");

                            var baseCall = baseTypeInfo.baseImplementsKeyEquals || baseTypeInfo.baseImplementsKeyEqualsT
                                                                ? "base.KeyEquals(other)"
                                                                : null;

                            GenerateEqualLogic(typeSymbol, builder, keyEqualityMembers, baseCall);
                        }

                        builder.AppendLine();

                        builder.AppendLineInvariant("/// <inheritdoc />");
                        builder.AppendLineInvariant("[global::System.Diagnostics.Contracts.Pure]");
                        using (builder.BlockInvariant("public int GetKeyHashCode()"))
                        {
                            builder.AppendLineInvariant("return _computedKeyHashCode ?? (int)(_computedKeyHashCode = ComputeKeyHashCode());");
                        }

                        builder.AppendLine();

                        using (builder.BlockInvariant("private int ComputeKeyHashCode()"))
                        {
                            var baseCall = baseTypeInfo.baseImplementsKeyEquals || baseTypeInfo.baseImplementsKeyEqualsT
                                                                ? "base.GetKeyHashCode()"
                                                                : null;
                            GenerateHashLogic(typeSymbol, builder, keyEqualityMembers, baseCall);
                        }

                        builder.AppendLine();

                        builder.AppendLineInvariant("private int? _computedKeyHashCode;");

                        builder.AppendLineInvariant("#endregion");
                        builder.AppendLine();
                    }
                }
            }

            _context.AddCompilationUnit(resultFileName, builder.ToString());
        }
예제 #25
0
 public override void Execute(SourceGeneratorContext context)
 {
     context.AddCompilationUnit("with_dependency", $"/* {NodaTime.DateTimeZone.Utc.Id} */");
 }