File: Frontend.cs
Web Access
Project: src\src\runtime\src\tools\hotreload-delta-gen\Microsoft.DotNet.HotReload.Utils.Generator.Frontend\Microsoft.DotNet.HotReload.Utils.Generator.Frontend.csproj (Microsoft.DotNet.HotReload.Utils.Generator.Frontend)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;

namespace Microsoft.DotNet.HotReload.Utils.Generator.Frontend;
public static class Frontend
{

    public static int Main(string[] args)
    {
        if (!ParseArgs (args, out var config))
            return 2;

        return RunWithExitStatus(config).Result;

    }

    static async Task<int> RunWithExitStatus(Microsoft.DotNet.HotReload.Utils.Generator.Config config)
    {
        try {
            await Run(config);
            return 0;
        } catch (Microsoft.DotNet.HotReload.Utils.Generator.DiffyException exn) {
            Console.Error.WriteLine ($"Error: {exn.Message}");
            if (exn.ExitStatus == 0)
                return 1; /* really shouldn't happen, but just in case */
            return exn.ExitStatus;
        }
    }
    static async Task Run (Microsoft.DotNet.HotReload.Utils.Generator.Config config)
    {
        var runner = Microsoft.DotNet.HotReload.Utils.Generator.Runner.Make (config);
        await runner.Run ();
        Console.WriteLine ("done");
    }




    private static void PrintUsage() {
        Console.WriteLine("hotreload-delta-gen.exe -msbuild:project.csproj [-p:Key=Value ...] [-live|-script:script.json [-outputSummary:results.json]]");
    }
    static bool ParseArgs (string[] args, [NotNullWhen(true)] out Microsoft.DotNet.HotReload.Utils.Generator.Config? config)
    {
        // FIXME: not all these options make sense together
        var builder = Microsoft.DotNet.HotReload.Utils.Generator.Config.Builder();

        config = null;

        for (int i = 0; i < args.Length; i++) {
            const string msbuildOptPrefix = "-msbuild:";
            const string scriptOptPrefix = "-script:";
            const string outputSummaryPrefix = "-outputSummary:";
            const string capabilitiesPrefix = "-capabilities:";
            string fn = args [i];
            if (fn.StartsWith(msbuildOptPrefix)) {
                builder.ProjectPath = fn[msbuildOptPrefix.Length..];
            } else if (fn == "-live") {
                builder.Live = true;
            } else if (fn.StartsWith("-p:")) {
                var s = fn[3..];
                if (s.IndexOf('=') is int j && j > 0 && j+1 < s.Length) {
                    var k = s[0..j];
                    var v = s[(j + 1)..];
                    // Console.WriteLine ($"got <{k}>=<{v}>");
                    builder.Properties.Add(KeyValuePair.Create(k,v));
                } else {
                    PrintUsage ();
                    Console.WriteLine("\t-p option needs a key=value pair");
                    return false;
                }
            } else if (fn.StartsWith(scriptOptPrefix)) {
                builder.ScriptPath = fn[scriptOptPrefix.Length..];
            } else if (fn.StartsWith(outputSummaryPrefix)) {
                builder.OutputSummaryPath = fn[outputSummaryPrefix.Length..];
            } else if (fn.StartsWith(capabilitiesPrefix)) {
                builder.EditAndContinueCapabilities.Add (fn[capabilitiesPrefix.Length..]);
            } else {
                PrintUsage();
                Console.WriteLine ($"\tUnexpected trailing option {fn}");
                return false;
            }
        }

        if (String.IsNullOrEmpty(builder.ProjectPath)) {
            PrintUsage();
            Console.WriteLine ("\tmsbuild project is required");
            return false;
        }

        if (!Xor(builder.Live, !String.IsNullOrEmpty(builder.ScriptPath))) {
            PrintUsage();
            Console.WriteLine("\tExactly one of -live or -script:script.json is required");
            return false;
        }

        if (builder.Live && !String.IsNullOrEmpty(builder.OutputSummaryPath)) {
            PrintUsage();
            Console.WriteLine ("-outputSummary and -live cannot be used at the same time");
        }

        config = builder.Bake();
        return true;
    }

    private static bool Xor (bool a, bool b) {
        return !(a == b);
    }

}