Skip to content

Add source-generated Program entry point when no Main() is defined#183

Merged
Tyrrrz merged 14 commits into
primefrom
copilot/add-auto-main-generator
Apr 1, 2026
Merged

Add source-generated Program entry point when no Main() is defined#183
Tyrrrz merged 14 commits into
primefrom
copilot/add-auto-main-generator

Conversation

Copilot AI commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

When a user creates a console app with CliFx commands but no entry point, the generator now produces one automatically.

What's generated

For executable projects (OutputKind.ConsoleApplication/WindowsApplication) with no existing entry point, the generator emits AutoGeneratedCommandLineProgram.g.cs:

namespace CliFx;

/// <summary>
/// Auto-generated entry point for the CliFx-based command-line application.
/// This class is emitted by the source generator when the project does not define
/// a <c>Main</c> method or top-level statements.
/// </summary>
public static class AutoGeneratedCommandLineProgram
{
    /// <summary>
    /// Builds and runs the command-line application using all commands detected in the current assembly.
    /// </summary>
    public static async global::System.Threading.Tasks.Task<int> Main() =>
        await new global::CliFx.CommandLineApplicationBuilder()
            .AddCommandsFromThisAssembly()
            .Build()
            .RunAsync();
}

Generator conditions (all must hold)

  • Output kind is ConsoleApplication or WindowsApplication — suppresses generation for library projects
  • compilation.GetEntryPoint(cancellationToken) returns null — uses the Roslyn semantic API to detect existing entry points, covering explicit Main methods, top-level statement programs, and entry points emitted by other source generators

Implementation

  • ProgramEntryPointGenerator.cs — standalone [Generator] class (ProgramEntryPointGenerator) responsible solely for detecting and emitting the Program entry point; uses compilation.GetEntryPoint() instead of syntax-based heuristics; checks OutputKind internally so no external conditional registration is required
  • ProgramEntryPoint.cs — standalone internal static class ProgramEntryPoint with the source emission logic (ProgramEntryPoint.Emit(...)); generates AutoGeneratedCommandLineProgram with XML docs
  • CommandDescriptorGenerator.cs — standalone [Generator] class (CommandDescriptorGenerator) responsible for emitting command descriptors and the AddCommandsFromThisAssembly() extension method
  • CliFx.Generators/Binding/CommandDescriptor.cs — descriptor emitter logic in CliFx.Generators.Binding namespace as internal static class CommandDescriptor (call site: CommandDescriptor.Emit(...))
  • CliFx.Generators/CommandRegistration.cs — registration emitter logic in root CliFx.Generators namespace as internal static class CommandRegistration (call site: CommandRegistration.Emit(...))
  • CommandCompiler — extended with an outputKind parameter (second position, default DynamicallyLinkedLibrary); both CommandDescriptorGenerator and ProgramEntryPointGenerator are always registered — the entry-point generator handles the output-kind guard itself
  • ApplicationSpecs — new test I_can_create_an_application_without_a_configuration verifies that the generated entry point is present (commands[0].Type.Assembly.EntryPoint != null) when compiling as a console application

@Tyrrrz

Tyrrrz commented Apr 1, 2026

Copy link
Copy Markdown
Owner

@copilot we probably don't need to check whether there's at least one command. Also, this new generator can be separate from the existing one. Maybe move the emitters out of partials into separate classes to make things cleaner.

Copilot AI commented Apr 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot we probably don't need to check whether there's at least one command. Also, this new generator can be separate from the existing one. Maybe move the emitters out of partials into separate cla...

Done in 14cbdc6:

  • Removed the commands.Length > 0 check — the entry point is now generated for any executable project without an existing Main or top-level statements
  • Created ProgramEntryPointGenerator as its own [Generator] class separate from Generator
  • Moved all emitters out of partial class Generator partials into standalone internal static classes: CommandDescriptorEmitter, CommandRegistrationEmitter, ProgramEntryPointEmitter

Copilot AI requested a review from Tyrrrz April 1, 2026 18:51
Comment thread CliFx.Generators/Generator.cs Outdated
Comment thread CliFx.Generators/Generator.ProgramEntryPointEmitter.cs Outdated
Comment thread CliFx.Generators/ProgramEntryPointGenerator.cs Outdated
Comment thread CliFx.Generators/Generator.ProgramEntryPointEmitter.cs Outdated
Comment thread CliFx.Generators/Generator.cs Outdated
Comment thread CliFx.Generators/Generator.ProgramEntryPointEmitter.cs Outdated
Comment thread CliFx.Generators/ProgramEntryPointGenerator.cs Outdated
@Tyrrrz Tyrrrz marked this pull request as ready for review April 1, 2026 19:25
Copilot AI review requested due to automatic review settings April 1, 2026 19:25
@codecov

codecov Bot commented Apr 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.48%. Comparing base (8439c3d) to head (f6c6879).
⚠️ Report is 1 commits behind head on prime.

Additional details and impacted files
@@            Coverage Diff             @@
##            prime     #183      +/-   ##
==========================================
+ Coverage   88.26%   88.48%   +0.21%     
==========================================
  Files          77       79       +2     
  Lines        2326     2370      +44     
  Branches      293      295       +2     
==========================================
+ Hits         2053     2097      +44     
  Misses        203      203              
  Partials       70       70              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new source generator that emits an executable entry point for CliFx-based console apps when the project doesn’t already define one, and refactors existing generator emission logic into standalone emitter classes.

Changes:

  • Introduces ProgramEntryPointGenerator to detect missing entry points via compilation.GetEntryPoint() and emit Program.g.cs for executable output kinds.
  • Adds ProgramEntryPointEmitter to generate the AutoGeneratedCommandLineProgram source (with XML docs) that runs CommandLineApplicationBuilder.
  • Refactors the existing generator by extracting command descriptor/registration emission into CommandDescriptor and CommandRegistration.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
CliFx.Generators/ProgramEntryPointGenerator.cs New incremental generator that conditionally emits a program entry point for executable projects lacking one.
CliFx.Generators/Generator.ProgramEntryPointEmitter.cs Source emission for the auto-generated Main() entry point.
CliFx.Generators/Generator.cs Updates generator to delegate emission to extracted helper classes (no longer partial).
CliFx.Generators/CommandRegistration.cs Extracts command registration emission into a standalone emitter.
CliFx.Generators/Binding/CommandDescriptor.cs Moves descriptor emission into CliFx.Generators.Binding and updates validator type references used in generated code.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread CliFx.Generators/ProgramEntryPointGenerator.cs
Agent-Logs-Url: https://github.com/Tyrrrz/CliFx/sessions/6c360b75-ebd5-4d95-8bf1-7765512b19d6

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Comment thread CliFx.Tests/ProgramEntryPointGeneratorSpecs.cs Outdated
…tryPoint for assertions

Agent-Logs-Url: https://github.com/Tyrrrz/CliFx/sessions/b1a767e6-ce8d-444c-8f1d-bf0ae095123f

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Comment thread CliFx.Tests/Utils/CommandCompiler.cs Outdated
Comment thread CliFx.Tests/Utils/CommandCompiler.cs Outdated
Comment thread CliFx.Tests/ApplicationSpecs.cs Outdated
Comment thread CliFx.Tests/ApplicationSpecs.cs Outdated
Removed redundant 'Arrange' comment in test method.
@Tyrrrz Tyrrrz merged commit 709a5f8 into prime Apr 1, 2026
7 checks passed
@Tyrrrz Tyrrrz deleted the copilot/add-auto-main-generator branch April 1, 2026 20:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants