Thanks to visit codestin.com
Credit goes to github.com

Skip to content
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
4 changes: 2 additions & 2 deletions src/sdk/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -511,11 +511,11 @@ dotnet_diagnostic.IDE0040.severity = warning
insert_final_newline = false

# Verify settings
[*.{received,verified}.{txt,xml,json}]
[*.{received,verified}.{txt,xml,json,sh,zsh,nu,fish,ps1}]
charset = "utf-8-bom"
end_of_line = lf
indent_size = unset
indent_style = unset
insert_final_newline = false
tab_width = unset
trim_trailing_whitespace = false
trim_trailing_whitespace = false
4 changes: 4 additions & 0 deletions src/sdk/.gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,7 @@
*.verified.txt text eol=lf working-tree-encoding=UTF-8
*.verified.xml text eol=lf working-tree-encoding=UTF-8
*.verified.json text eol=lf working-tree-encoding=UTF-8
*.verified.sh text eol=lf working-tree-encoding=UTF-8
*.verified.zsh text eol=lf working-tree-encoding=UTF-8
*.verified.nu text eol=lf working-tree-encoding=UTF-8
*.verified.fish text eol=lf working-tree-encoding=UTF-8
9 changes: 8 additions & 1 deletion src/sdk/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
{
"dotnet.testWindow.disableAutoDiscovery": true,
"dotnet.defaultSolution": "sdk.slnx"
"dotnet.testWindow.disableBuildOnRun": true,
"dotnet.defaultSolution": "cli.slnf",
"files.associations": {
"*.slnf": "json",
"*.props": "xml",
"*.targets": "xml",
"*.*proj": "xml"
}
}
15 changes: 15 additions & 0 deletions src/sdk/cli.slnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"solution": {
"path": "sdk.slnx",
"projects": [
"src\\BuiltInTools\\dotnet-watch\\dotnet-watch.csproj",
"src\\Cli\\dotnet\\dotnet.csproj",
"src\\Cli\\Microsoft.DotNet.Cli.Utils\\Microsoft.DotNet.Cli.Utils.csproj",
"test\\dotnet-new.IntegrationTests\\dotnet-new.IntegrationTests.csproj",
"test\\dotnet-watch.Tests\\dotnet-watch.Tests.csproj",
"test\\dotnet.Tests\\dotnet.Tests.csproj",
"test\\Microsoft.DotNet.Cli.Utils.Tests\\Microsoft.DotNet.Cli.Utils.Tests.csproj",
"test\\Microsoft.NET.TestFramework\\Microsoft.NET.TestFramework.csproj"
]
}
}
1 change: 1 addition & 0 deletions src/sdk/sdk.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
</Folder>
<Folder Name="/src/Cli/">
<Project Path="src/Cli/dotnet/dotnet.csproj" />
<Project Path="src/Cli/Microsoft.DotNet.Cli.CommandLine/Microsoft.DotNet.Cli.CommandLine.csproj" />
<Project Path="src/Cli/Microsoft.DotNet.Cli.Utils/Microsoft.DotNet.Cli.Utils.csproj" />
<Project Path="src/Cli/Microsoft.DotNet.Configurer/Microsoft.DotNet.Configurer.csproj" />
<Project Path="src/Cli/Microsoft.DotNet.FileBasedPrograms/Microsoft.DotNet.FileBasedPrograms.Package.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,10 @@
</ItemGroup>

<Import Project="..\Web.Middleware\Microsoft.DotNet.HotReload.Web.Middleware.projitems" Label="Shared" />

<ItemGroup>
<EmbeddedResource Update="@(EmbeddedResource)">
<LogicalName>%(FileName)%(Extension)</LogicalName>
</EmbeddedResource>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public async Task InvokeAsync(HttpContext context)
// for backwards compat only
internal static ReadOnlyMemory<byte> GetBlazorHotReloadJS()
{
var jsFileName = "Microsoft.AspNetCore.Watch.BrowserRefresh.BlazorHotReload.js";
var jsFileName = "BlazorHotReload.js";
using var stream = new MemoryStream();
var manifestStream = typeof(BrowserScriptMiddleware).Assembly.GetManifestResourceStream(jsFileName)!;
manifestStream.CopyTo(stream);
Expand All @@ -66,7 +66,7 @@ internal static ReadOnlyMemory<byte> GetBrowserRefreshJS()

internal static ReadOnlyMemory<byte> GetWebSocketClientJavaScript(string hostString, string serverKey)
{
var jsFileName = "Microsoft.AspNetCore.Watch.BrowserRefresh.WebSocketScriptInjection.js";
var jsFileName = "WebSocketScriptInjection.js";
using var reader = new StreamReader(typeof(BrowserScriptMiddleware).Assembly.GetManifestResourceStream(jsFileName)!);
var script = reader.ReadToEnd()
.Replace("{{hostString}}", hostString)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,19 @@
<ItemGroup>
<Using Remove="@(Using)" />
</ItemGroup>

<PropertyGroup>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);_AddJSFilesToSourcePackage</TargetsForTfmSpecificContentInPackage>
</PropertyGroup>

<!--
Add .js files as embedded resources in the source package.
-->
<Target Name="_AddJSFilesToSourcePackage">
<ItemGroup>
<!-- Must be in 'cs' directory since NuGet filters the files based on consuming project language -->
<_File Include="$(MSBuildProjectDirectory)\**\*.js" TargetDir="contentFiles/cs/$(TargetFramework)" BuildAction="EmbeddedResource" />
<TfmSpecificPackageFile Include="@(_File)" PackagePath="%(_File.TargetDir)/%(_File.RecursiveDir)%(_File.FileName)%(_File.Extension)"/>
</ItemGroup>
</Target>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Diagnostics;
using Microsoft.Build.Logging;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Commands.Run;
using Microsoft.DotNet.Cli.Extensions;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -119,7 +120,7 @@ internal sealed class CommandLineOptions
// determine subcommand:
var explicitCommand = TryGetSubcommand(parseResult);
var command = explicitCommand ?? RunCommandParser.GetCommand();
var buildOptions = command.Options.Where(o => o is IForwardedOption);
var buildOptions = command.Options.Where(o => o.ForwardingFunction is not null);

foreach (var buildOption in buildOptions)
{
Expand Down Expand Up @@ -161,7 +162,7 @@ internal sealed class CommandLineOptions
var commandArguments = GetCommandArguments(parseResult, watchOptions, explicitCommand, out var binLogToken, out var binLogPath);

// We assume that forwarded options, if any, are intended for dotnet build.
var buildArguments = buildOptions.Select(option => ((IForwardedOption)option).GetForwardingFunction()(parseResult)).SelectMany(args => args).ToList();
var buildArguments = buildOptions.Select(option => option.ForwardingFunction!(parseResult)).SelectMany(args => args).ToList();

if (binLogToken != null)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.CommandLine;
using System.CommandLine.Completions;

namespace Microsoft.DotNet.Cli.CommandLine;

/// <summary>
/// Extension methods that make it easier to chain argument configuration methods when building arguments.
/// </summary>
public static class ArgumentBuilderExtensions
{
extension<T>(Argument<T> argument)
{
public Argument<T> AddCompletions(Func<CompletionContext, IEnumerable<CompletionItem>> completionSource)
{
argument.CompletionSources.Add(completionSource);
return argument;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
using System.CommandLine;
using System.CommandLine.Parsing;

namespace Microsoft.DotNet.Cli.CommandLine;

/// <summary>
/// Extensions for tracking and invoking forwarding functions on options and arguments.
/// Forwarding functions are used to translate the parsed value of an option or argument
/// into a set of zero or more string values that will be passed to an inner command.
/// </summary>
public static class ForwardedOptionExtensions
{
private static readonly Dictionary<Symbol, Func<ParseResult, IEnumerable<string>>> s_forwardingFunctions = [];
private static readonly Lock s_lock = new();

extension(Option option)
{
/// <summary>
/// If this option has a forwarding function, this property will return it; otherwise, it will be null.
/// </summary>
/// <remarks>
/// This getter is on the untyped Option because much of the _processing_ of option forwarding
/// is done at the ParseResult level, where we don't have the generic type parameter.
/// </remarks>
public Func<ParseResult, IEnumerable<string>>? ForwardingFunction => s_forwardingFunctions.GetValueOrDefault(option);
}

extension<TValue>(Option<TValue> option)
{
/// <summary>
/// Internal-only helper function that ensures the provided forwarding function is only called
/// if the option actually has a value.
/// </summary>
private Func<ParseResult, IEnumerable<string>> GetForwardingFunction(Func<TValue, IEnumerable<string>> func)
{
return (ParseResult parseResult) =>
{
if (parseResult.GetResult(option) is OptionResult r)
{
if (r.GetValueOrDefault<TValue>() is TValue value)
{
return func(value);
}
else
{
return [];
}
}
return [];
};
}

/// <summary>
/// Internal-only helper function that ensures the provided forwarding function is only called
/// if the option actually has a value.
/// </summary>
private Func<ParseResult, IEnumerable<string>> GetForwardingFunction(Func<TValue, ParseResult, IEnumerable<string>> func)
{
return (ParseResult parseResult) =>
{
if (parseResult.GetResult(option) is OptionResult r)
{
if (r.GetValueOrDefault<TValue>() is TValue value)
{
return func(value, parseResult);
}
else
{
return [];
}
}
return [];
};
}

/// <summary>
/// Forwards the option using the provided function to convert the option's value to zero or more string values.
/// The function will only be called if the option has a value.
/// </summary>
public Option<TValue> SetForwardingFunction(Func<TValue?, IEnumerable<string>> func)
{
lock (s_lock)
{
s_forwardingFunctions[option] = option.GetForwardingFunction(func);
}
return option;
}

/// <summary>
/// Forward the option using the provided function to convert the option's value to a single string value.
/// The function will only be called if the option has a value.
/// </summary>
public Option<TValue> SetForwardingFunction(Func<TValue, string> format)
{
lock (s_lock)
{
s_forwardingFunctions[option] = option.GetForwardingFunction(o => [format(o)]);
}
return option;
}

/// <summary>
/// Forward the option using the provided function to convert the option's value to a single string value.
/// The function will only be called if the option has a value.
/// </summary>
public Option<TValue> SetForwardingFunction(Func<TValue?, ParseResult, IEnumerable<string>> func)
{
lock (s_lock)
{
s_forwardingFunctions[option] = option.GetForwardingFunction(func);
}
return option;
}

/// <summary>
/// Forward the option as multiple calculated string values from whatever the option's value is.
/// </summary>
/// <param name="format"></param>
/// <returns></returns>
public Option<TValue> ForwardAsMany(Func<TValue?, IEnumerable<string>> format) => option.SetForwardingFunction(format);

/// <summary>
/// Forward the option as its own name.
/// </summary>
/// <returns></returns>
public Option<TValue> Forward() => option.SetForwardingFunction((TValue? o) => [option.Name]);

/// <summary>
/// Forward the option as a string value. This value will be forwarded as long as the option has a OptionResult - which means that
/// any implicit value calculation will cause the string value to be forwarded.
/// </summary>
public Option<TValue> ForwardAs(string value) => option.SetForwardingFunction((TValue? o) => [value]);

/// <summary>
/// Forward the option as a singular calculated string value.
/// </summary>
public Option<TValue> ForwardAsSingle(Func<TValue, string> format) => option.SetForwardingFunction(format);
}

extension(Option<bool> option)
{
/// <summary>
/// Forward the boolean option as a string value. This value will be forwarded as long as the option has a OptionResult - which means that
/// any implicit value calculation will cause the string value to be forwarded. For boolean options specifically, if the option is zero arity
/// and has no default value factory, S.CL will synthesize a true or false value based on whether the option was provided or not, so we need to
/// add an additional implicit 'value is true' check to prevent accidentally forwarding the option for flags that are absent..
/// </summary>
public Option<bool> ForwardIfEnabled(string value) => option.SetForwardingFunction((bool o) => o ? [value] : []);
/// <summary>
/// Forward the boolean option as a string value. This value will be forwarded as long as the option has a OptionResult - which means that
/// any implicit value calculation will cause the string value to be forwarded. For boolean options specifically, if the option is zero arity
/// and has no default value factory, S.CL will synthesize a true or false value based on whether the option was provided or not, so we need to
/// add an additional implicit 'value is true' check to prevent accidentally forwarding the option for flags that are absent..
/// </summary>
public Option<bool> ForwardIfEnabled(string[] value) => option.SetForwardingFunction((bool o) => o ? value : []);

/// <summary>
/// Forward the boolean option as a string value. This value will be forwarded as long as the option has a OptionResult - which means that
/// any implicit value calculation will cause the string value to be forwarded. For boolean options specifically, if the option is zero arity
/// and has no default value factory, S.CL will synthesize a true or false value based on whether the option was provided or not, so we need to
/// add an additional implicit 'value is true' check to prevent accidentally forwarding the option for flags that are absent..
/// </summary>
public Option<bool> ForwardAs(string value) => option.ForwardIfEnabled(value);
}

extension(Option<IEnumerable<string>> option)
{
/// <summary>
/// Foreach argument in the option's value, yield the <paramref name="alias"/> followed by the argument.
/// </summary>
public Option<IEnumerable<string>> ForwardAsManyArgumentsEachPrefixedByOption(string alias) =>
option.ForwardAsMany(o => ForwardedArguments(alias, o));
}

extension(ParseResult parseResult)
{
/// <summary>
/// Calls the forwarding functions for all options that have declared a forwarding function (via <see cref="ForwardedOptionExtensions"/>'s extension members) in the provided <see cref="ParseResult"/>.
/// </summary>
/// <param name="parseResult"></param>
/// <param name="command">If not provided, uses the <see cref="ParseResult.CommandResult" />'s <see cref="CommandResult.Command"/>.</param>
/// <returns></returns>
public IEnumerable<string> OptionValuesToBeForwarded(Command? command = null) =>
(command ?? parseResult.CommandResult.Command)
.Options
.Select(o => o.ForwardingFunction)
.SelectMany(f => f is not null ? f(parseResult) : []);

/// <summary>
/// Tries to find the first option named <paramref name="alias"/> in <paramref name="command"/>, and if found,
/// invokes its forwarding function (if any) and returns the result. If no option with that name is found, or if the option
/// has no forwarding function, returns an empty enumeration.
/// </summary>
/// <param name="command"></param>
/// <param name="alias"></param>
/// <returns></returns>
public IEnumerable<string> ForwardedOptionValues(Command command, string alias)
{
var func = command.Options?
.Where(o =>
(o.Name.Equals(alias) || o.Aliases.Contains(alias))
&& o.ForwardingFunction is not null)
.FirstOrDefault()?.ForwardingFunction;
return func?.Invoke(parseResult) ?? [];
}
}

/// <summary>
/// For each argument in <paramref name="arguments"/>, yield the <paramref name="alias"/> followed by the argument.
/// </summary>
private static IEnumerable<string> ForwardedArguments(string alias, IEnumerable<string>? arguments)
{
foreach (string arg in arguments ?? [])
{
yield return alias;
yield return arg;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(SdkTargetFramework)</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<StrongNameKeyId>MicrosoftAspNetCore</StrongNameKeyId>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$([MSBuild]::IsOSPlatform(`Windows`))' == 'false' ">true</PublicSign>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.CommandLine" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="../../System.CommandLine.StaticCompletions/System.CommandLine.StaticCompletions.csproj" />
</ItemGroup>
</Project>
Loading