Skip to content

introduced --use-program-main option for console template to disable top-level program #4520

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
"langVersion": {
"longName": "langVersion",
"shortName": ""
},
"UseProgramMain": {
"longName": "use-program-main",
"shortName": ""
}
},
"usageExamples": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,11 @@
"add": [],
"remove": [ "Common" ]
}
],
"symbolInfo": [
{
"id": "UseProgramMain",
"isVisible": "true"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "Verze jazyka",
"symbols/skipRestore/description": "Pokud se tato možnost zadá, přeskočí automatické obnovení projektu při vytvoření.",
"symbols/skipRestore/displayName": "Přeskočit obnovení",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "Obnoví balíčky NuGet vyžadované tímto projektem.",
"postActions/restore/manualInstructions/default/text": "Spustit dotnet restore",
"postActions/open-file/description": "Otevře Program.cs v editoru."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "Sprachversion",
"symbols/skipRestore/description": "Wenn angegeben, wird die automatische Wiederherstellung des Projekts beim Erstellen übersprungen.",
"symbols/skipRestore/displayName": "Wiederherstellung überspringen",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "Stellt die NuGet-Pakete wieder her, die für dieses Projekt erforderlich sind.",
"postActions/restore/manualInstructions/default/text": "„dotnet restore“ ausführen",
"postActions/open-file/description": "Öffnet „Program.cs“ im Editor"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "Language version",
"symbols/skipRestore/description": "If specified, skips the automatic restore of the project on create.",
"symbols/skipRestore/displayName": "Skip restore",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "Restore NuGet packages required by this project.",
"postActions/restore/manualInstructions/default/text": "Run 'dotnet restore'",
"postActions/open-file/description": "Opens Program.cs in the editor"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "Versión de lenguaje",
"symbols/skipRestore/description": "Si se especifica, se omite la restauración automática del proyecto durante la creación.",
"symbols/skipRestore/displayName": "Omitir restauración",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "Restaure los paquetes NuGet necesarios para este proyecto.",
"postActions/restore/manualInstructions/default/text": "Ejecutar \"dotnet restore\"",
"postActions/open-file/description": "Abre Program.cs en el editor"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
{
"author": "Microsoft",
"name": "Application console",
"description": "Projet de création d'une application en ligne de commande pouvant s'exécuter sur .NET sur Windows, Linux et macOS",
Expand All @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "Version du langage",
"symbols/skipRestore/description": "S’il est spécifié, ignore la restauration automatique du projet lors de la création.",
"symbols/skipRestore/displayName": "Ignorer la restauration",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "Restaurez les packages NuGet requis par ce projet.",
"postActions/restore/manualInstructions/default/text": "Exécuter « dotnet restore »",
"postActions/open-file/description": "Ouvre Program.cs dans l’éditeur"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "Versione del linguaggio",
"symbols/skipRestore/description": "Se specificato, ignora il ripristino automatico del progetto durante la creazione.",
"symbols/skipRestore/displayName": "Salta ripristino",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "Ripristina i pacchetti NuGet richiesti da questo progetto.",
"postActions/restore/manualInstructions/default/text": "Esegui 'dotnet restore'",
"postActions/open-file/description": "Apre Program.cs nell'editor"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "言語バージョン",
"symbols/skipRestore/description": "指定した場合、作成時にプロジェクトの自動復元がスキップされます。",
"symbols/skipRestore/displayName": "復元のスキップ",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "このプロジェクトに必要な NuGet パッケージを復元します。",
"postActions/restore/manualInstructions/default/text": "'dotnet restore' を実行する",
"postActions/open-file/description": "エディターで Program.cs を開きます"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "언어 버전",
"symbols/skipRestore/description": "지정된 경우, 프로젝트 생성 시 자동 복원을 건너뜁니다.",
"symbols/skipRestore/displayName": "복원 건너뛰기",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "이 프로젝트에 필요한 NuGet 패키지를 복원합니다.",
"postActions/restore/manualInstructions/default/text": "'dotnet restore' 실행",
"postActions/open-file/description": "편집기에서 Program.cs를 엽니다"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
{
"author": "Microsoft",
"name": "Aplikacja konsoli",
"description": "Projekt służący do tworzenia aplikacji wiersza polecenia, która może działać na platformie .NET w systemach Windows, Linux i macOS",
Expand All @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "Wersja języka",
"symbols/skipRestore/description": "Jeśli ta opcja jest określona, pomija automatyczne przywracanie projektu podczas tworzenia.",
"symbols/skipRestore/displayName": "Pomiń przywracanie",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "Przywróć pakiety NuGet wymagane przez ten projekt.",
"postActions/restore/manualInstructions/default/text": "Uruchom polecenie \"dotnet restore\"",
"postActions/open-file/description": "Otwiera plik Program.cs w edytorze"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
{
"author": "Microsoft",
"name": "Aplicativo do Console",
"description": "Um projeto para criar um aplicativo de linha de comando que pode ser executado no .NET no Windows, Linux e macOS",
Expand All @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "Versão do idioma",
"symbols/skipRestore/description": "Se especificado, ignora a restauração automática do projeto sendo criado.",
"symbols/skipRestore/displayName": "Ignorar restauração",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "Restaura os pacotes do NuGet exigidos por este projeto.",
"postActions/restore/manualInstructions/default/text": "Executar 'dotnet restore'",
"postActions/open-file/description": "Abrir Program.cs no editor"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
{
"author": "Microsoft",
"name": "Консольное приложение",
"description": "Проект для создания приложения командной строки, которое может выполняться в среде .NET в Windows, Linux и macOS",
Expand All @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "Версия языка",
"symbols/skipRestore/description": "Если установлено, автоматическое восстановление проекта при создании пропускается.",
"symbols/skipRestore/displayName": "Пропустить восстановление",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "Восстановление пакетов NuGet, необходимых для этого проекта.",
"postActions/restore/manualInstructions/default/text": "Выполнить команду \"dotnet restore\"",
"postActions/open-file/description": "Открывает файл Program.cs в редакторе"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "Dil sürümü",
"symbols/skipRestore/description": "Belirtilmişse, oluşturulmakta olan projenin otomatik geri yüklenmesini atlar.",
"symbols/skipRestore/displayName": "Geri yüklemeyi atla",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "Bu projenin gerektirdiği NuGet paketlerini geri yükleyin.",
"postActions/restore/manualInstructions/default/text": "'dotnet restore' çalıştır",
"postActions/open-file/description": "Düzenleyicide Program.cs dosyasını açar"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "语言版本",
"symbols/skipRestore/description": "如果指定,则在创建时跳过项目的自动还原。",
"symbols/skipRestore/displayName": "跳过还原",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "还原此项目所需的 NuGet 包。",
"postActions/restore/manualInstructions/default/text": "运行 \"dotnet restore\"",
"postActions/open-file/description": "在编辑器中打开 Program.cs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"symbols/langVersion/displayName": "語言版本",
"symbols/skipRestore/description": "若指定,會在建立時跳過專案的自動還原。",
"symbols/skipRestore/displayName": "略過還原",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/UseProgramMain/displayName": "Do not use top-level statements",
"postActions/restore/description": "還原此專案所需的 NuGet 套件。",
"postActions/restore/manualInstructions/default/text": "執行 'dotnet restore'",
"postActions/open-file/description": "在編輯器中開啟 Program.cs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@
"defaultValue": "false",
"displayName": "Skip restore"
},
"UseProgramMain": {
"type": "parameter",
"datatype": "bool",
"defaultValue": "false",
"description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"displayName": "Do not use top-level statements"
},
"csharp10orLater": {
"type": "generated",
"generator": "regexMatch",
Expand Down Expand Up @@ -98,7 +105,11 @@
},
"csharpFeature_TopLevelProgram": {
"type": "computed",
"value": "csharp9orLater == \"true\""
"value": "(csharp9orLater == \"true\" && UseProgramMain != \"true\")"
},
"csharpFeature_FileScopedNamespaces": {
"type": "computed",
"value": "csharp10orLater == \"true\""
}
},
"primaryOutputs": [
Expand Down Expand Up @@ -136,4 +147,4 @@
"continueOnError": true
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
#if (csharpFeature_TopLevelProgram)
Console.WriteLine("Hello, World!");
#else
#if (csharpFeature_FileScopedNamespaces)
namespace Company.ConsoleApplication1;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
#else
namespace Company.ConsoleApplication1
{
class Program
Expand All @@ -19,3 +29,4 @@ static void Main(string[] args)
}
}
#endif
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ Default: false
InsertText: --type,
Detail: Specifies the template type to instantiate.
},
{
Label: --use-program-main,
Kind: Keyword,
SortText: --use-program-main,
InsertText: --use-program-main,
Detail:
Whether to generate an explicit Program class and Main method instead of top-level statements.
Type: bool
Default: false

},
{
Label: -?,
Kind: Keyword,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ Template options:
--no-restore If specified, skips the automatic restore of the project on create.
Type: bool
Default: false
--use-program-main Whether to generate an explicit Program class and Main method instead of top-level statements.
Type: bool
Default: false

To see help for other template languages (F#, VB), use --language option:
dotnet-new3 new3 console -h --language F#
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ Template options:
--no-restore If specified, skips the automatic restore of the project on create.
Type: bool
Default: false
--use-program-main Whether to generate an explicit Program class and Main method instead of top-level statements.
Type: bool
Default: false

To see help for other template languages (F#, VB), use --language option:
dotnet-new3 new3 console -h --language F#
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ Template options:
--no-restore If specified, skips the automatic restore of the project on create.
Type: bool
Default: false
--use-program-main Whether to generate an explicit Program class and Main method instead of top-level statements.
Type: bool
Default: false

To see help for other template languages (F#, VB), use --language option:
dotnet-new3 new3 console -h --language F#
93 changes: 92 additions & 1 deletion test/dotnet-new3.UnitTests/CommonTemplatesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ public void EditorConfigTests()
"5.0.200",
"--roll-forward",
"major")]
public void GlobalJsonTests( string expectedContent, params string[] parameters)
public void GlobalJsonTests(string expectedContent, params string[] parameters)
{
string workingDir = TestUtils.CreateTemporaryFolder();

Expand Down Expand Up @@ -398,6 +398,97 @@ static void Main(string[] args)
}
}

[Theory]
[InlineData("10.0")]
[InlineData("10")]
[InlineData("preview")]
[InlineData("latest")]
[InlineData("default")]
[InlineData("latestMajor")]
[InlineData(null)]
public void TopLevelProgramSupport_WhenFlagIsEnabled(string? langVersion)
{
string workingDir = TestUtils.CreateTemporaryFolder();

List<string> args = new List<string>() { "console", "-o", "MyProject", "--use-program-main" };
if (!string.IsNullOrEmpty(langVersion))
{
args.Add("--langVersion");
args.Add(langVersion);
}

new DotnetNewCommand(_log, args.ToArray())
.WithCustomHive(_fixture.HomeDirectory)
.WithWorkingDirectory(workingDir)
.Execute()
.Should()
.ExitWith(0)
.And.NotHaveStdErr();

var buildResult = new DotnetCommand(_log, "build", "MyProject")
.WithWorkingDirectory(workingDir)
.Execute()
.Should().ExitWith(0).And.NotHaveStdErr();

string programFileContent = File.ReadAllText(Path.Combine(workingDir, "MyProject", "Program.cs"));
string expectedTopLevelContent =
@"namespace MyProject;
class Program
{
static void Main(string[] args)
{
Console.WriteLine(""Hello, World!"");
}
}
";
Assert.DoesNotContain("// See https://aka.ms/new-console-template for more information", programFileContent);
Assert.Contains(expectedTopLevelContent, programFileContent);
}

[Theory]
[InlineData("9.0")]
[InlineData("9")]
public void TopLevelProgramSupport_WhenFlagIsEnabled_NoFileScopedNamespaces(string? langVersion)
{
string workingDir = TestUtils.CreateTemporaryFolder();

List<string> args = new List<string>() { "console", "-o", "MyProject", "--use-program-main" };
if (!string.IsNullOrEmpty(langVersion))
{
args.Add("--langVersion");
args.Add(langVersion);
}

new DotnetNewCommand(_log, args.ToArray())
.WithCustomHive(_fixture.HomeDirectory)
.WithWorkingDirectory(workingDir)
.Execute()
.Should()
.ExitWith(0)
.And.NotHaveStdErr();

var buildResult = new DotnetCommand(_log, "build", "MyProject")
.WithWorkingDirectory(workingDir)
.Execute()
.Should().ExitWith(0).And.NotHaveStdErr();

string programFileContent = File.ReadAllText(Path.Combine(workingDir, "MyProject", "Program.cs"));
string expectedTopLevelContent =
@"namespace MyProject
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(""Hello, World!"");
}
}
}
";
Assert.DoesNotContain("// See https://aka.ms/new-console-template for more information", programFileContent);
Assert.Contains(expectedTopLevelContent, programFileContent);
}

/// <summary>
/// Creates all possible combinations for supported templates, language versions and frameworks.
/// </summary>
Expand Down