public static string GetAssemblyMetadata(this GeneratorExecutionContext context, string key) { foreach (var a in context.FindAttributes("AssemblyMetadataAttribute")) { if (a.ConstructorArguments.Length == 2 && a.ConstructorArguments[0].Value?.ToString() == key) { return(a.ConstructorArguments[1].Value?.ToString()); } } return(null); }
public void Execute(GeneratorExecutionContext context) { var isIos = context.IsiOS(); var isAndroid = context.IsAndroid(); if (!isIos && !isAndroid) { return; } var syntaxReceiver = (AppStartupSyntaxReceiver)context.SyntaxReceiver; var namespaceName = context.Compilation.GlobalNamespace.Name; if (string.IsNullOrEmpty(namespaceName)) { namespaceName = context.Compilation.AssemblyName ?? "GeneratedMauiApp"; } if (context.IsAppHead()) { // Look for a `[assembly: MauiStartup(typeof(StartupClass))]` attribute var startupAttributes = context.FindAttributes("MauiStartupAttribute")?.ToList(); // If we have multiple, throw an error if ((startupAttributes?.Count ?? 0) > 1) { context.ReportDiagnostic(Diagnostic.Create("MAUI1010", "Compiler", "More than one MauiStartupAttribute found.", DiagnosticSeverity.Error, DiagnosticSeverity.Error, true, 0)); return; } var startupAttribute = startupAttributes.FirstOrDefault(); // If we don't have any, if (startupAttribute != null) { // Get the constructor arg which we expect to be the startup class type name var ctorTypeArg = startupAttribute.ConstructorArguments.FirstOrDefault(); var startupClassName = ctorTypeArg.Value?.ToString(); if (!string.IsNullOrEmpty(startupClassName)) { // Prefix with global:: when we generate code to be safe if (!startupClassName.StartsWith("global::")) { startupClassName = $"global::{startupClassName}"; } if (isIos) { // Prefix with global:: when we generate code to be safe var appDelegateClassName = $"{namespaceName}.AppDelegate"; if (!appDelegateClassName.StartsWith("global::")) { appDelegateClassName = $"global::{appDelegateClassName}"; } // Create an app delegate // We check to see if there's already an app delegate // If there is, if it's partial and the same name as the one we generate, that's fine too if (!syntaxReceiver.HasiOSAppDelegateSubclass || syntaxReceiver.iOSPartialAppDelegateSubclassType.Equals(appDelegateClassName)) { context.AddSource("Maui_Generated_MauiGeneratedAppDelegate.cs", GenerateiOSAppDelegate(namespaceName, startupClassName)); } else { context.ReportDiagnostic(Diagnostic.Create("MAUI1020", "Compiler", "UIApplicationDelegate implementation already exists, not generating one.", DiagnosticSeverity.Warning, DiagnosticSeverity.Warning, true, 3)); } // Create a main method if (!syntaxReceiver.HasiOSMainMethod) { context.AddSource("Maui_Generated_MauiGeneratedMain.cs", GenerateiOSMain(namespaceName, appDelegateClassName)); } else { context.ReportDiagnostic(Diagnostic.Create("MAUI1021", "Compiler", "Main method implementation already exists, not generating one.", DiagnosticSeverity.Warning, DiagnosticSeverity.Warning, true, 3)); } } else if (isAndroid) { var appName = context.GetMSBuildProperty("ApplicationTitle") ?? "App1"; context.AddSource("Maui_Generated_MauiGeneratedAndroidActivity.cs", GenerateAndroidMainActivity(appName, namespaceName, startupClassName)); if (!syntaxReceiver.HasAndroidMainLauncher) { context.AddSource("Maui_Generated_MauiGeneratedAndroidApplication.cs", GenerateAndroidApplication(namespaceName, startupClassName)); } else { context.ReportDiagnostic(Diagnostic.Create("MAUI1021", "Compiler", "Activity with MainLauncher=true already exists, not generating one.", DiagnosticSeverity.Warning, DiagnosticSeverity.Warning, true, 3)); } } } } } }