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 ) ); } } }
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(); }
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()); } }
public override void Execute(SourceGeneratorContext context) { Debugger.Launch(); var project = context.GetProjectInstance(); context.AddCompilationUnit("Test", "namespace MyGeneratedCode { class TestGeneration { } }"); }
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()}"); } } }
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); } }
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} }} }}" ); }
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}; }} }}"); }
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; }} }}"); }
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); } } }
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} }} }}" ); }
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()); }
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}""; }} }}" ); }
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()); }
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()); } } } }
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()); } } }
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()); }
public override void Execute(SourceGeneratorContext context) { context.AddCompilationUnit("with_dependency", $"/* {NodaTime.DateTimeZone.Utc.Id} */"); }