Skip to content

Commit 793abe1

Browse files
authored
Process C# directives in file-based programs (#47702)
1 parent 14ff150 commit 793abe1

21 files changed

+1200
-72
lines changed

Diff for: documentation/general/dotnet-run-file.md

+5-6
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,14 @@ Directives `sdk`, `package`, and `property` are translated into `<Project Sdk=".
183183
Other directives result in a warning, reserving them for future use.
184184

185185
```cs
186-
#:sdk Microsoft.NET.Sdk.Web
187-
#:property TargetFramework=net11.0
188-
#:property LangVersion=preview
189-
#:package System.CommandLine=2.0.0-*
186+
#:sdk Microsoft.NET.Sdk.Web
187+
#:property TargetFramework net11.0
188+
#:property LangVersion preview
189+
#:package System.CommandLine 2.0.0-*
190190
```
191191

192192
The value must be separated from the name of the directive by white space and any leading and trailing white space is not considered part of the value.
193-
Any value can optionally have two parts separated by `=` or `/`
194-
(the former is consistent with how properties are usually passed, e.g., `/p:Prop=Value`, and the latter is what the `<Project Sdk="Name/Version">` attribute uses).
193+
Any value can optionally have two parts separated by a space (more whitespace characters could be allowed in the future).
195194
The value of the first `#:sdk` is injected into `<Project Sdk="{0}">` with the separator (if any) replaced with `/`,
196195
and the subsequent `#:sdk` directive values are split by the separator and injected as `<Sdk Name="{0}" Version="{1}" />` elements (or without the `Version` attribute if there is no separator).
197196
It is an error if the first part (name) is empty (the version is allowed to be empty, but that results in empty `Version=""`).

Diff for: src/Cli/dotnet/Commands/Project/Convert/ProjectConvertCommand.cs

+22-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
#nullable enable
55

6+
using System.Collections.Immutable;
67
using System.CommandLine;
8+
using System.IO;
79
using Microsoft.DotNet.Cli;
810
using Microsoft.DotNet.Cli.Utils;
911
using Microsoft.TemplateEngine.Cli.Commands;
@@ -35,13 +37,29 @@ public override int Execute()
3537
throw new GracefulException(LocalizableStrings.DirectoryAlreadyExists, targetDirectory);
3638
}
3739

40+
// Find directives (this can fail, so do this before creating the target directory).
41+
var sourceFile = VirtualProjectBuildingCommand.LoadSourceFile(file);
42+
var directives = VirtualProjectBuildingCommand.FindDirectives(sourceFile);
43+
3844
Directory.CreateDirectory(targetDirectory);
3945

40-
string projectFile = Path.Join(targetDirectory, Path.GetFileNameWithoutExtension(file) + ".csproj");
41-
string projectFileText = VirtualProjectBuildingCommand.GetNonVirtualProjectFileText();
42-
File.WriteAllText(path: projectFile, contents: projectFileText);
46+
var targetFile = Path.Join(targetDirectory, Path.GetFileName(file));
47+
48+
// If there were any directives, remove them from the file.
49+
if (directives.Length != 0)
50+
{
51+
VirtualProjectBuildingCommand.RemoveDirectivesFromFile(directives, sourceFile.Text, targetFile);
52+
File.Delete(file);
53+
}
54+
else
55+
{
56+
File.Move(file, targetFile);
57+
}
4358

44-
File.Move(file, Path.Join(targetDirectory, Path.GetFileName(file)));
59+
string projectFile = Path.Join(targetDirectory, Path.GetFileNameWithoutExtension(file) + ".csproj");
60+
using var stream = File.Open(projectFile, FileMode.Create, FileAccess.Write);
61+
using var writer = new StreamWriter(stream, Encoding.UTF8);
62+
VirtualProjectBuildingCommand.WriteProjectFile(writer, directives);
4563

4664
return 0;
4765
}

Diff for: src/Cli/dotnet/Commands/Run/LocalizableStrings.resx

+16
Original file line numberDiff line numberDiff line change
@@ -244,4 +244,20 @@ Make the profile names distinct.</value>
244244
<data name="LaunchProfileDoesNotExist" xml:space="preserve">
245245
<value>A launch profile with the name '{0}' doesn't exist.</value>
246246
</data>
247+
<data name="UnrecognizedDirective" xml:space="preserve">
248+
<value>Unrecognized directive '{0}' at {1}.</value>
249+
<comment>{0} is the directive name like 'package' or 'sdk', {1} is the file path and line number.</comment>
250+
</data>
251+
<data name="MissingDirectiveName" xml:space="preserve">
252+
<value>Missing name of '{0}' at {1}.</value>
253+
<comment>{0} is the directive name like 'package' or 'sdk', {1} is the file path and line number.</comment>
254+
</data>
255+
<data name="PropertyDirectiveMissingParts" xml:space="preserve">
256+
<value>The property directive needs to have two parts separated by '=' like 'PropertyName=PropertyValue': {0}</value>
257+
<comment>{0} is the file path and line number. {Locked="="}</comment>
258+
</data>
259+
<data name="PropertyDirectiveInvalidName" xml:space="preserve">
260+
<value>Invalid property name at {0}. {1}</value>
261+
<comment>{0} is the file path and line number. {1} is an inner exception message.</comment>
262+
</data>
247263
</root>

Diff for: src/Cli/dotnet/Commands/Run/RunCommand.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public int Execute()
110110
projectFactory = new VirtualProjectBuildingCommand
111111
{
112112
EntryPointFileFullPath = EntryPointFileFullPath,
113-
}.CreateProjectInstance;
113+
}.PrepareProjectInstance().CreateProjectInstance;
114114
}
115115

116116
try

0 commit comments

Comments
 (0)