public void Execute(GeneratorExecutionContext context)
        {
            var receiver = context.SyntaxContextReceiver as ParserSyntaxReceiver;

            if (receiver?.Root?.Class is not null && receiver.Namespace is not null)
            {
                defaultLanguage = context.GetMSBuildProperty("DefaultLanguage");
                defaultLanguage = string.IsNullOrWhiteSpace(defaultLanguage) ? "en" : defaultLanguage;
                var semanticModel = context.Compilation.GetSemanticModel(receiver.Root.Class.SyntaxTree);
                var cmds          = GetCommands(receiver.Root.Class, semanticModel, out CommandInfoBase? defaultCommand);
                var rootDoc       = GetXmlDocumentation(receiver.Root.Class);

                var rh = rootDoc.Descendants("summary").FirstOrDefault();
                if (rh is not null)
                {
                    receiver.Root.HelpText = HelpText.FromXElement(rh, defaultLanguage);
                }
                receiver.Root.Children = cmds;
                receiver.Root.Default  = defaultCommand;

                var enums =
                    GetEnumsInfo(defaultCommand is null ? cmds : cmds.Append(defaultCommand))
                    .Select(x => (x.type.GetMembers().Select(y => y.Name).ToArray(), x.typeName, x.displayTypeName))
                    .ToArray();
                Queue <string> errors     = new();
                var            ctx        = CreateContext(CreateParserTemplateModel(receiver), errors);
                string         ep         = parserTemplate.Render(ctx);
                string         completion = completionTemplate.Render(ctx);
                ctx = CreateContext(CreateHelpTextsModel(receiver), errors);
                string ht = helpTextsTemplate.Render(ctx);
                ctx = CreateContext(CreateEnumsModel(receiver.Namespace, enums), errors);
                string enp = enumParserTemplate.Render(ctx);

                var logPath = context.GetMSBuildProperty("LogGeneratedParser");
                if (string.IsNullOrWhiteSpace(logPath) is not true)
                {
                    File.WriteAllText(Path.Combine(logPath, "EntryPoint.cs"), ep);
                    File.WriteAllText(Path.Combine(logPath, "HelpTexts.cs"), ht);
                    File.WriteAllText(Path.Combine(logPath, "EnumParser.cs"), enp);
                    File.WriteAllText(Path.Combine(logPath, "Completer.cs"), completion);
                }
                foreach (var item in errors)
                {
                    context.ReportDiagnostic(Diagnostic.Create(GenerationError, null, item));
                }
                context.AddSource("EntryPoint.cs", ep);
                context.AddSource("HelpTexts.cs", ht);
                context.AddSource("EnumParser.cs", enp);
                context.AddSource("Completer.cs", completion);
            }
        }
        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));
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 3
0
 public static bool IsAndroid(this GeneratorExecutionContext context)
 => (context.GetMSBuildProperty("TargetFrameworkIdentifier")?.Contains("MonoAndroid") ?? false) ||
 (context.GetCompilationContextTFM()?.Contains("MonoAndroid") ?? false);
Ejemplo n.º 4
0
 public static bool IsAppHead(this GeneratorExecutionContext context)
 => context.GetMSBuildProperty("OutputType")?.Equals("Exe", StringComparison.OrdinalIgnoreCase) ?? false;