diff --git a/documentation/general/dotnet-run-file.md b/documentation/general/dotnet-run-file.md index a3458a90f72d..b40d2dabf1ba 100644 --- a/documentation/general/dotnet-run-file.md +++ b/documentation/general/dotnet-run-file.md @@ -186,7 +186,7 @@ Other directives result in a warning, reserving them for future use. #:sdk Microsoft.NET.Sdk.Web #:property TargetFramework net11.0 #:property LangVersion preview -#:package System.CommandLine 2.0.0-* +#:package System.CommandLine@2.0.0-* ``` 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. diff --git a/src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs b/src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs index f245749c5681..0723c09dfd0d 100644 --- a/src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs +++ b/src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs @@ -3,6 +3,7 @@ #nullable enable +using System.Buffers; using System.Collections.Immutable; using System.Diagnostics; using System.Security; @@ -814,9 +815,11 @@ public static CSharpDirective Parse(SourceFile sourceFile, TextSpan span, string }; } - private static (string, string?) ParseOptionalTwoParts(SourceFile sourceFile, TextSpan span, string directiveKind, string directiveText) + private static (string, string?) ParseOptionalTwoParts(SourceFile sourceFile, TextSpan span, string directiveKind, string directiveText, SearchValues? separators = null) { - var i = directiveText.IndexOf(' ', StringComparison.Ordinal); + var i = separators != null + ? directiveText.AsSpan().IndexOfAny(separators) + : directiveText.IndexOf(' ', StringComparison.Ordinal); var firstPart = checkFirstPart(i < 0 ? directiveText : directiveText[..i]); var secondPart = i < 0 ? [] : directiveText.AsSpan((i + 1)..).TrimStart(); if (i < 0 || secondPart.IsWhiteSpace()) @@ -912,6 +915,8 @@ private Property() { } /// public sealed class Package : CSharpDirective { + private static readonly SearchValues s_separators = SearchValues.Create(' ', '@'); + private Package() { } public required string Name { get; init; } @@ -919,7 +924,7 @@ private Package() { } public static new Package Parse(SourceFile sourceFile, TextSpan span, string directiveKind, string directiveText) { - var (packageName, packageVersion) = ParseOptionalTwoParts(sourceFile, span, directiveKind, directiveText); + var (packageName, packageVersion) = ParseOptionalTwoParts(sourceFile, span, directiveKind, directiveText, s_separators); return new Package { diff --git a/test/dotnet.Tests/CommandTests/Project/Convert/DotnetProjectConvertTests.cs b/test/dotnet.Tests/CommandTests/Project/Convert/DotnetProjectConvertTests.cs index 3aa8e534640e..a45a57bc3f08 100644 --- a/test/dotnet.Tests/CommandTests/Project/Convert/DotnetProjectConvertTests.cs +++ b/test/dotnet.Tests/CommandTests/Project/Convert/DotnetProjectConvertTests.cs @@ -407,6 +407,7 @@ public void Directives_Separators() #:sdk Third 3.0=a/b #:package P1 1.0/a=b #:package P2 2.0/a=b + #:package P3@1.0 ab """, expectedProject: $""" @@ -429,6 +430,7 @@ public void Directives_Separators() +