Skip to content
Draft
Show file tree
Hide file tree
Changes from 7 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
24 changes: 24 additions & 0 deletions documentation/general/dotnet-run-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ which are [ignored][ignored-directives] by the C# language but recognized by the
#:property TargetFramework=net11.0
#:property LangVersion=preview
#:package System.CommandLine@2.0.0-*
#:package Microsoft.Build@17.0.0 ExcludeAssets=runtime PrivateAssets=all
#:project ../MyLibrary
#:ref ../lib/lib.cs
#:include ./**/*.cs
Expand All @@ -190,6 +191,25 @@ The value is required for `#:property`, optional for `#:package`/`#:sdk`, and di
The name must be separated from the kind of the directive by whitespace
and any leading and trailing white space is not considered part of the name and value.

The remainder of a directive (after the kind) is split into whitespace-separated tokens.
Whitespace inside a value is not allowed unless the value is enclosed in double quotes (`"`).
A value is written either bare or wrapped entirely in double quotes; the quotes are removed and the
quoted text (which may contain whitespace) becomes the value, e.g., `#:property Description="Hello World"`
sets the value to `Hello World`. Quotes can only enclose a whole value, so `#:property A=B` and
`#:property A="B"` are allowed, but `#:property A=B"C"` is an error.
It is an error if a quote is left unterminated.

For backward compatibility, a directive whose value contains no double quotes is still accepted in a
*legacy mode*: the entire remainder after the name and separator is taken verbatim as a single value
(including any internal whitespace), matching how these directives behaved before quoting and metadata
were supported. Analyzer [CA2267](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2267)
flags such legacy directives and offers a code fix to rewrite them into the quoted form.

`#:package`, `#:project`, and `#:ref` directives can specify additional MSBuild item metadata as trailing `Name=Value` tokens,
e.g., `#:package Microsoft.Build@17.0.0 ExcludeAssets=runtime PrivateAssets=all`.
Each metadata name must be a valid XML element name; each metadata value can be quoted to contain whitespace.
The other directive kinds do not support trailing metadata and it is an error to specify extra tokens for them.

The directives are processed as follows:

- The name and value of the first `#:sdk` is injected into `<Project Sdk="{0}/{1}">` (or just `<Project Sdk="{0}">` if it has no value),
Expand All @@ -201,13 +221,16 @@ The directives are processed as follows:

- Each `#:package` is injected as `<PackageReference Include="{0}" Version="{1}">` (or without the `Version` attribute if it has no value) in an `<ItemGroup>`.
It is an error if its name is empty (the value, i.e., package version, is allowed to be empty, but that results in empty `Version=""`).
Any trailing `Name=Value` metadata is injected as child elements, e.g.,
`<PackageReference Include="{0}" Version="{1}"><ExcludeAssets>runtime</ExcludeAssets></PackageReference>`.

It is valid to have a `#:package` directive without a version.
That's useful when central package management (CPM) is used.
NuGet will report an appropriate error if the version is missing and CPM is not enabled.

- Each `#:project` is injected as `<ProjectReference Include="{0}" />` in an `<ItemGroup>`.
It is an error if the value is empty.
Any trailing `Name=Value` metadata is injected as child elements of the `<ProjectReference>`.
If the path points to an existing directory, a project file is found inside that directory and its path is used instead
(because `ProjectReference` items don't support directory paths).
An error is reported if zero or more than one projects are found in the directory, just like `dotnet reference add` would do.
Expand All @@ -216,6 +239,7 @@ The directives are processed as follows:
A virtual project is created for the referenced file (e.g., `lib.cs` produces a virtual `lib.cs.csproj`),
and a `<ProjectReference Include="lib.cs.csproj" />` is injected in an `<ItemGroup>`.
It is an error if the name is empty or if the referenced file does not exist.
Any trailing `Name=Value` metadata is injected as child elements of the `<ProjectReference>`.
Unlike `#:project`, `#:ref` points to a `.cs` file (not a `.csproj` file or directory).

The referenced file is itself a file-based program with its own virtual project (defaulting to `OutputType=Exe`).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,24 @@
<value>Duplicate directives are not supported: {0}</value>
<comment>{0} is the directive type and name.</comment>
</data>
<data name="QuoteInDirective" xml:space="preserve">
<value>Directives currently cannot contain double quotes (").</value>
<data name="UnterminatedQuoteInDirective" xml:space="preserve">
<value>Unterminated double quote (") in directive.</value>
</data>
<data name="InvalidQuoteInDirective" xml:space="preserve">
<value>Double quotes (") in a directive must enclose an entire value, for example: 'Name="a b"' or '"a b"'.</value>
<comment>{Locked="Name=&quot;a b&quot;"}{Locked="&quot;a b&quot;"}</comment>
</data>
<data name="InvalidDirectiveMetadata" xml:space="preserve">
<value>Directive metadata must be in the form 'Name=Value'. Invalid metadata: '{0}'.</value>
<comment>{Locked="'Name=Value'"}{0} is the offending metadata text.</comment>
</data>
<data name="DirectiveMetadataInvalidName" xml:space="preserve">
<value>Invalid directive metadata name: {0}</value>
<comment>{0} is an inner exception message.</comment>
</data>
<data name="UnexpectedDirectiveText" xml:space="preserve">
<value>The '{0}' directive has unexpected content. To include whitespace in a value, enclose it in double quotes (").</value>
<comment>{0} is the directive kind like 'property' or 'sdk'.</comment>
</data>
<data name="InvalidProjectDirective" xml:space="preserve">
<value>The '#:project' directive is invalid: {0}</value>
Expand Down
Loading
Loading