From 92d886c144ff38bf19431f60e63934ff7779d75c Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Wed, 9 Oct 2024 14:54:44 -0700 Subject: [PATCH 1/7] rename AddKernelConnector to AddConnectDirective --- ...ibilityTests.Interactive_api_is_not_changed.approved.txt | 2 +- .../JupyterKernelTestBase.cs | 2 +- src/Microsoft.DotNet.Interactive.Kql/KqlKernelExtension.cs | 2 +- .../NamedPipeConnectionTests.cs | 4 ++-- .../SQLiteConnectionTests.cs | 4 ++-- src/Microsoft.DotNet.Interactive.SQLite/SQLiteKernel.cs | 2 +- .../MsSqlKernelConnector.cs | 1 + .../MsSqlKernelExtension.cs | 2 +- .../ConnectDirectiveTests.cs | 4 ++-- src/Microsoft.DotNet.Interactive.Tests/DirectiveTests.cs | 4 ++-- .../LanguageServices/CompletionTests.MagicCommands.cs | 6 +++--- .../LanguageServices/HoverTextTests.cs | 2 +- src/Microsoft.DotNet.Interactive/CompositeKernel.cs | 2 +- .../Directives/KernelDirectiveCompletionContext.cs | 4 ---- .../CommandLine/CommandLineParserTests.cs | 2 +- src/dotnet-interactive.Tests/HttpApiTests.cs | 2 +- src/dotnet-interactive.Tests/StdioConnectionTests.cs | 2 +- src/dotnet-interactive/KernelBuilder.cs | 6 +++--- 18 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/Microsoft.DotNet.Interactive.ApiCompatibility.Tests/ApiCompatibilityTests.Interactive_api_is_not_changed.approved.txt b/src/Microsoft.DotNet.Interactive.ApiCompatibility.Tests/ApiCompatibilityTests.Interactive_api_is_not_changed.approved.txt index 2668b6ff42..7f09babed6 100644 --- a/src/Microsoft.DotNet.Interactive.ApiCompatibility.Tests/ApiCompatibilityTests.Interactive_api_is_not_changed.approved.txt +++ b/src/Microsoft.DotNet.Interactive.ApiCompatibility.Tests/ApiCompatibilityTests.Interactive_api_is_not_changed.approved.txt @@ -19,7 +19,7 @@ Microsoft.DotNet.Interactive public System.String DefaultKernelName { get; set;} public KernelHost Host { get;} public System.Void Add(Kernel kernel, System.Collections.Generic.IEnumerable aliases = null) - public System.Void AddKernelConnector(ConnectKernelDirective connectDirective) + public System.Void AddConnectDirective(ConnectKernelDirective connectDirective) public System.Collections.Generic.IEnumerator GetEnumerator() Kernel GetHandlingKernel(Microsoft.DotNet.Interactive.Commands.KernelCommand command, KernelInvocationContext context) System.Threading.Tasks.Task HandleRequestKernelInfoAsync(Microsoft.DotNet.Interactive.Commands.RequestKernelInfo command, KernelInvocationContext context) diff --git a/src/Microsoft.DotNet.Interactive.Jupyter.Tests/JupyterKernelTestBase.cs b/src/Microsoft.DotNet.Interactive.Jupyter.Tests/JupyterKernelTestBase.cs index 29de3f70f4..05b1c0242a 100644 --- a/src/Microsoft.DotNet.Interactive.Jupyter.Tests/JupyterKernelTestBase.cs +++ b/src/Microsoft.DotNet.Interactive.Jupyter.Tests/JupyterKernelTestBase.cs @@ -50,7 +50,7 @@ protected CompositeKernel CreateCompositeKernelAsync(params IJupyterKernelConnec jupyterKernelCommand.AddConnectionOptions(options); } - kernel.AddKernelConnector(jupyterKernelCommand); + kernel.AddConnectDirective(jupyterKernelCommand); _disposables.Add(kernel); return kernel; } diff --git a/src/Microsoft.DotNet.Interactive.Kql/KqlKernelExtension.cs b/src/Microsoft.DotNet.Interactive.Kql/KqlKernelExtension.cs index 6b315ba576..2b2e4067e2 100644 --- a/src/Microsoft.DotNet.Interactive.Kql/KqlKernelExtension.cs +++ b/src/Microsoft.DotNet.Interactive.Kql/KqlKernelExtension.cs @@ -20,7 +20,7 @@ public static async Task LoadAsync(Kernel kernel) var kqlToolPath = Path.Combine(Paths.DotnetToolsPath, kqlToolName); compositeKernel - .AddKernelConnector(new ConnectKqlDirective(kqlToolPath)); + .AddConnectDirective(new ConnectKqlDirective(kqlToolPath)); KernelInvocationContext.Current?.Display( new HtmlString(@"
Query Microsoft Kusto Server databases. diff --git a/src/Microsoft.DotNet.Interactive.NamedPipeConnector.Tests/NamedPipeConnectionTests.cs b/src/Microsoft.DotNet.Interactive.NamedPipeConnector.Tests/NamedPipeConnectionTests.cs index 4e5b789222..17a32b0b2e 100644 --- a/src/Microsoft.DotNet.Interactive.NamedPipeConnector.Tests/NamedPipeConnectionTests.cs +++ b/src/Microsoft.DotNet.Interactive.NamedPipeConnector.Tests/NamedPipeConnectionTests.cs @@ -31,7 +31,7 @@ public void connect_command_is_available_when_a_user_adds_a_kernel_connection_ty { using var compositeKernel = new CompositeKernel(); - compositeKernel.AddKernelConnector(new ConnectNamedPipeDirective()); + compositeKernel.AddConnectDirective(new ConnectNamedPipeDirective()); compositeKernel .KernelInfo @@ -60,7 +60,7 @@ protected override void AddConnectDirectiveTo(CompositeKernel compositeKernel) { CreateRemoteKernelTopology(_pipeName); - compositeKernel.AddKernelConnector(new ConnectNamedPipeDirective()); + compositeKernel.AddConnectDirective(new ConnectNamedPipeDirective()); } private void CreateRemoteKernelTopology(string pipeName) diff --git a/src/Microsoft.DotNet.Interactive.SQLite.Tests/SQLiteConnectionTests.cs b/src/Microsoft.DotNet.Interactive.SQLite.Tests/SQLiteConnectionTests.cs index dfff74d326..7e2e0dea4a 100644 --- a/src/Microsoft.DotNet.Interactive.SQLite.Tests/SQLiteConnectionTests.cs +++ b/src/Microsoft.DotNet.Interactive.SQLite.Tests/SQLiteConnectionTests.cs @@ -25,7 +25,7 @@ public async Task SQLKernel_suggests_SQLite_connection_when_statements_are_submi new KeyValueStoreKernel() }; - kernel.AddKernelConnector(new ConnectSQLiteDirective()); + kernel.AddConnectDirective(new ConnectSQLiteDirective()); using var _ = CreateInMemorySQLiteDb(out var connectionString); @@ -67,7 +67,7 @@ public async Task It_can_connect_and_query_data() new KeyValueStoreKernel() }; - kernel.AddKernelConnector(new ConnectSQLiteDirective()); + kernel.AddConnectDirective(new ConnectSQLiteDirective()); using var _ = CreateInMemorySQLiteDb(out var connectionString); diff --git a/src/Microsoft.DotNet.Interactive.SQLite/SQLiteKernel.cs b/src/Microsoft.DotNet.Interactive.SQLite/SQLiteKernel.cs index f98cc50feb..1576e1f880 100644 --- a/src/Microsoft.DotNet.Interactive.SQLite/SQLiteKernel.cs +++ b/src/Microsoft.DotNet.Interactive.SQLite/SQLiteKernel.cs @@ -112,7 +112,7 @@ void ResolveColumnNameClashes(string[] names) public static void AddSQLiteKernelConnectorTo(CompositeKernel kernel) { - kernel.AddKernelConnector(new ConnectSQLiteDirective()); + kernel.AddConnectDirective(new ConnectSQLiteDirective()); KernelInvocationContext.Current?.Display( new HtmlString(@"
Query SQLite databases. diff --git a/src/Microsoft.DotNet.Interactive.SqlServer/MsSqlKernelConnector.cs b/src/Microsoft.DotNet.Interactive.SqlServer/MsSqlKernelConnector.cs index c110d835e0..4080462aaa 100644 --- a/src/Microsoft.DotNet.Interactive.SqlServer/MsSqlKernelConnector.cs +++ b/src/Microsoft.DotNet.Interactive.SqlServer/MsSqlKernelConnector.cs @@ -8,6 +8,7 @@ namespace Microsoft.DotNet.Interactive.SqlServer; internal class MsSqlKernelConnector { + // FIX: (MsSqlKernelConnector) dead code? public MsSqlKernelConnector(bool createDbContext, string connectionString) { CreateDbContext = createDbContext; diff --git a/src/Microsoft.DotNet.Interactive.SqlServer/MsSqlKernelExtension.cs b/src/Microsoft.DotNet.Interactive.SqlServer/MsSqlKernelExtension.cs index fcfe6a2495..7a98f97bbb 100644 --- a/src/Microsoft.DotNet.Interactive.SqlServer/MsSqlKernelExtension.cs +++ b/src/Microsoft.DotNet.Interactive.SqlServer/MsSqlKernelExtension.cs @@ -19,7 +19,7 @@ public static async Task LoadAsync(Kernel kernel) var sqlToolPath = Path.Combine(Paths.DotnetToolsPath, sqlToolName); compositeKernel - .AddKernelConnector(new ConnectMsSqlDirective(sqlToolPath)); + .AddConnectDirective(new ConnectMsSqlDirective(sqlToolPath)); KernelInvocationContext.Current?.Display( new HtmlString(@"
Query Microsoft SQL Server databases. diff --git a/src/Microsoft.DotNet.Interactive.Tests/ConnectDirectiveTests.cs b/src/Microsoft.DotNet.Interactive.Tests/ConnectDirectiveTests.cs index 42ae3cd038..dc146d954c 100644 --- a/src/Microsoft.DotNet.Interactive.Tests/ConnectDirectiveTests.cs +++ b/src/Microsoft.DotNet.Interactive.Tests/ConnectDirectiveTests.cs @@ -114,7 +114,7 @@ public async Task Multiple_connections_can_be_created_using_the_same_connection_ { using var compositeKernel = new CompositeKernel(); - compositeKernel.AddKernelConnector( + compositeKernel.AddConnectDirective( new ConnectFakeKernelDirective("fake", "Connects the fake kernel", name => Task.FromResult(new FakeKernel(name)))); await compositeKernel.SubmitCodeAsync("#!connect fake --kernel-name fake1"); @@ -131,7 +131,7 @@ private static Kernel CreateKernelWithConnectableFakeKernel(FakeKernel fakeKerne { var compositeKernel = new CompositeKernel(); - compositeKernel.AddKernelConnector( + compositeKernel.AddConnectDirective( new ConnectFakeKernelDirective("fake", "Connects the fake kernel", _ => Task.FromResult(fakeKernel))); return compositeKernel; diff --git a/src/Microsoft.DotNet.Interactive.Tests/DirectiveTests.cs b/src/Microsoft.DotNet.Interactive.Tests/DirectiveTests.cs index ea7e8366ae..706ec3cf13 100644 --- a/src/Microsoft.DotNet.Interactive.Tests/DirectiveTests.cs +++ b/src/Microsoft.DotNet.Interactive.Tests/DirectiveTests.cs @@ -457,12 +457,12 @@ public async Task Partial_match_does_not_invoke_incorrect_subcommand() var firstWasCalledWith = ""; var secondWasCalledWith = ""; - compositeKernel.AddKernelConnector(new ConnectCustomDirective(s => + compositeKernel.AddConnectDirective(new ConnectCustomDirective(s => { firstWasCalledWith = s; return Task.FromResult(new FakeKernel(s)); })); - compositeKernel.AddKernelConnector(new ConnectCustomKernelTwoDirective(s => + compositeKernel.AddConnectDirective(new ConnectCustomKernelTwoDirective(s => { secondWasCalledWith = s; return Task.FromResult(new FakeKernel(s)); diff --git a/src/Microsoft.DotNet.Interactive.Tests/LanguageServices/CompletionTests.MagicCommands.cs b/src/Microsoft.DotNet.Interactive.Tests/LanguageServices/CompletionTests.MagicCommands.cs index f1172b63f3..a8b791882d 100644 --- a/src/Microsoft.DotNet.Interactive.Tests/LanguageServices/CompletionTests.MagicCommands.cs +++ b/src/Microsoft.DotNet.Interactive.Tests/LanguageServices/CompletionTests.MagicCommands.cs @@ -66,7 +66,7 @@ public async Task Completions_are_available_for_magic_commands( string expected) { var kernel = CreateKernel(); - kernel.AddKernelConnector(new ConnectSignalRDirective()); + kernel.AddConnectDirective(new ConnectSignalRDirective()); var completions = await markupCode .ParseMarkupCode() @@ -101,7 +101,7 @@ public async Task Completion_documentation_is_available_for_magic_commands( fakeKernel.KernelInfo.SupportedKernelCommands.Add(new(nameof(RequestValueInfos))); kernel.Add(fakeKernel); - kernel.AddKernelConnector(new ConnectJupyterKernelDirective()); + kernel.AddConnectDirective(new ConnectJupyterKernelDirective()); (await markupCode .ParseMarkupCode() @@ -198,7 +198,7 @@ public async Task Completions_include_magic_commands_from_all_kernels() public async Task Inner_symbol_completions_do_not_include_top_level_symbols(string markupCode) { var kernel = CreateCompositeKernel(); - kernel.AddKernelConnector(new ConnectSignalRDirective()); + kernel.AddConnectDirective(new ConnectSignalRDirective()); var completions = await markupCode .ParseMarkupCode() diff --git a/src/Microsoft.DotNet.Interactive.Tests/LanguageServices/HoverTextTests.cs b/src/Microsoft.DotNet.Interactive.Tests/LanguageServices/HoverTextTests.cs index 2cb8f3eed6..38dc6e394b 100644 --- a/src/Microsoft.DotNet.Interactive.Tests/LanguageServices/HoverTextTests.cs +++ b/src/Microsoft.DotNet.Interactive.Tests/LanguageServices/HoverTextTests.cs @@ -74,7 +74,7 @@ public async Task hover_request_returns_expected_result_for_magic_commands( string expectedContent) { using var kernel = CreateKernel(); - kernel.AddKernelConnector(new ConnectSignalRDirective()); + kernel.AddConnectDirective(new ConnectSignalRDirective()); MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character); var commandResult = await SendHoverRequest(kernel, code, line, character); diff --git a/src/Microsoft.DotNet.Interactive/CompositeKernel.cs b/src/Microsoft.DotNet.Interactive/CompositeKernel.cs index dc4a9809d9..6ecded1c0f 100644 --- a/src/Microsoft.DotNet.Interactive/CompositeKernel.cs +++ b/src/Microsoft.DotNet.Interactive/CompositeKernel.cs @@ -217,7 +217,7 @@ private protected override async Task HandleRequestKernelInfoAsync( IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public void AddKernelConnector(ConnectKernelDirective connectDirective) + public void AddConnectDirective(ConnectKernelDirective connectDirective) where T : ConnectKernelCommand { if (_rootConnectDirective is null) diff --git a/src/Microsoft.DotNet.Interactive/Directives/KernelDirectiveCompletionContext.cs b/src/Microsoft.DotNet.Interactive/Directives/KernelDirectiveCompletionContext.cs index a1a72484bc..4ed943743f 100644 --- a/src/Microsoft.DotNet.Interactive/Directives/KernelDirectiveCompletionContext.cs +++ b/src/Microsoft.DotNet.Interactive/Directives/KernelDirectiveCompletionContext.cs @@ -9,9 +9,5 @@ namespace Microsoft.DotNet.Interactive.Directives; public class KernelDirectiveCompletionContext { - public KernelDirectiveCompletionContext() - { - } - public IList Completions { get; } = new List(); } \ No newline at end of file diff --git a/src/dotnet-interactive.Tests/CommandLine/CommandLineParserTests.cs b/src/dotnet-interactive.Tests/CommandLine/CommandLineParserTests.cs index cb9b410f48..3ab3ae8604 100644 --- a/src/dotnet-interactive.Tests/CommandLine/CommandLineParserTests.cs +++ b/src/dotnet-interactive.Tests/CommandLine/CommandLineParserTests.cs @@ -118,7 +118,7 @@ public async Task stdio_mode_honors_log_path() using (var kernel = new CompositeKernel()) { - kernel.AddKernelConnector(new ConnectStdIoDirective(new Uri("kernel://test-kernel"))); + kernel.AddConnectDirective(new ConnectStdIoDirective(new Uri("kernel://test-kernel"))); string[] args = [Dotnet.Path.FullName, typeof(Program).Assembly.Location, "stdio", "--log-path", logPath.Directory.FullName, "--verbose"]; diff --git a/src/dotnet-interactive.Tests/HttpApiTests.cs b/src/dotnet-interactive.Tests/HttpApiTests.cs index fa99ec12d2..d1e38e1e6f 100644 --- a/src/dotnet-interactive.Tests/HttpApiTests.cs +++ b/src/dotnet-interactive.Tests/HttpApiTests.cs @@ -403,7 +403,7 @@ public async Task stdio_mode_returns_javascript_api_via_http() using var kernel = new CompositeKernel(); - kernel.AddKernelConnector(new ConnectStdIoDirective(new Uri("kernel://test-kernel"))); + kernel.AddConnectDirective(new ConnectStdIoDirective(new Uri("kernel://test-kernel"))); string[] args = [Dotnet.Path.FullName, typeof(Program).Assembly.Location, "stdio", "--http-port", port.ToString()]; diff --git a/src/dotnet-interactive.Tests/StdioConnectionTests.cs b/src/dotnet-interactive.Tests/StdioConnectionTests.cs index c2fc8576c2..1e13a332be 100644 --- a/src/dotnet-interactive.Tests/StdioConnectionTests.cs +++ b/src/dotnet-interactive.Tests/StdioConnectionTests.cs @@ -122,7 +122,7 @@ protected override SubmitCode CreateSubmitCodeToConnectProxyAs(string localKerne protected override void AddConnectDirectiveTo(CompositeKernel compositeKernel) { - compositeKernel.AddKernelConnector(new ConnectStdIoDirective(new Uri("kernel://test-kernel"))); + compositeKernel.AddConnectDirective(new ConnectStdIoDirective(new Uri("kernel://test-kernel"))); } } diff --git a/src/dotnet-interactive/KernelBuilder.cs b/src/dotnet-interactive/KernelBuilder.cs index ff2ee8a702..cbe69e0c8b 100644 --- a/src/dotnet-interactive/KernelBuilder.cs +++ b/src/dotnet-interactive/KernelBuilder.cs @@ -84,10 +84,10 @@ internal static CompositeKernel CreateKernel( .UseFormsForMultipleInputs(secretManager) .UseNuGetExtensions(telemetrySender); - kernel.AddKernelConnector(new ConnectSignalRDirective()); - kernel.AddKernelConnector(new ConnectStdIoDirective(startupOptions.KernelHost)); + kernel.AddConnectDirective(new ConnectSignalRDirective()); + kernel.AddConnectDirective(new ConnectStdIoDirective(startupOptions.KernelHost)); - kernel.AddKernelConnector( + kernel.AddConnectDirective( new ConnectJupyterKernelDirective() .AddConnectionOptions(new JupyterHttpKernelConnectionOptions()) .AddConnectionOptions(new JupyterLocalKernelConnectionOptions())); From 707e99260d52dcb06cca5e098509095f73f72409 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 22 Oct 2024 12:47:39 -0700 Subject: [PATCH 2/7] code cleanup --- .../HttpKernelTests.NamedRequest.cs | 4 ++-- .../HttpKernel.cs | 2 +- .../Model/HttpNamedRequest.cs | 16 ++++++---------- .../Model/HttpResponse.cs | 2 +- .../Model/PartialHttpResponse.cs | 2 +- .../JupyterKernelCommandHandlers.cs | 12 ++++++------ 6 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/Microsoft.DotNet.Interactive.Http.Tests/HttpKernelTests.NamedRequest.cs b/src/Microsoft.DotNet.Interactive.Http.Tests/HttpKernelTests.NamedRequest.cs index 740504d38a..bbe5457086 100644 --- a/src/Microsoft.DotNet.Interactive.Http.Tests/HttpKernelTests.NamedRequest.cs +++ b/src/Microsoft.DotNet.Interactive.Http.Tests/HttpKernelTests.NamedRequest.cs @@ -556,7 +556,7 @@ public async Task json_with_xml_content_type_produces_errors() [Fact] public async Task xml_with_json_content_type_produces_errors() { - using var kernel = new HttpKernel(); + using var kernel = new HttpKernel("http"); var firstCode = """ @baseUrl = https://httpbin.org/anything @@ -594,7 +594,7 @@ public async Task xml_with_json_content_type_produces_errors() var diagnostics = secondResult.Events.Should().ContainSingle().Which; - diagnostics.Diagnostics.First().Message.Should().Be($$$"""The supplied named request has content type of 'application/json' which differs from the required content type of 'application/xml'."""); + diagnostics.Diagnostics.First().Message.Should().Be("""The supplied named request has content type of 'application/json' which differs from the required content type of 'application/xml'."""); } [Theory] diff --git a/src/Microsoft.DotNet.Interactive.Http/HttpKernel.cs b/src/Microsoft.DotNet.Interactive.Http/HttpKernel.cs index 6ccde7fb52..b3a8d9fb89 100644 --- a/src/Microsoft.DotNet.Interactive.Http/HttpKernel.cs +++ b/src/Microsoft.DotNet.Interactive.Http/HttpKernel.cs @@ -144,6 +144,7 @@ async Task IKernelCommandHandler.HandleAsync(SubmitCode command, Ker { var docVariableNodes = parsedDoc.SyntaxTree.RootNode.ChildNodes.OfType(); var docVariableNames = docVariableNodes.Where(n => n.Span.Start < lastSpan?.Start).Select(n => n.DeclarationNode?.VariableName).ToHashSet(); + foreach (DeclaredVariable dv in parsedDoc.SyntaxTree.RootNode.TryGetDeclaredVariables(BindExpressionValues).declaredVariables.Values) { if (docVariableNames.Contains(dv.Name)) @@ -152,7 +153,6 @@ async Task IKernelCommandHandler.HandleAsync(SubmitCode command, Ker } } } - } else { diff --git a/src/Microsoft.DotNet.Interactive.Http/Model/HttpNamedRequest.cs b/src/Microsoft.DotNet.Interactive.Http/Model/HttpNamedRequest.cs index 872ccd5b91..ed6bbb86ea 100644 --- a/src/Microsoft.DotNet.Interactive.Http/Model/HttpNamedRequest.cs +++ b/src/Microsoft.DotNet.Interactive.Http/Model/HttpNamedRequest.cs @@ -1,21 +1,17 @@ -#nullable enable +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#nullable enable -using Microsoft.CodeAnalysis.Text; -using System; using Microsoft.DotNet.Interactive.Http.Parsing; -using Microsoft.CodeAnalysis; +using System; using System.Linq; using System.Text.Json; using System.Text.Json.Nodes; -using System.Reactive.Concurrency; -using System.Xml.XPath; using System.Xml; -using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Microsoft.DotNet.Interactive.Http; -using Diagnostic = CodeAnalysis.Diagnostic; - internal class HttpNamedRequest { internal HttpNamedRequest(HttpRequestNode httpRequestNode, HttpResponse response) @@ -25,7 +21,7 @@ internal HttpNamedRequest(HttpRequestNode httpRequestNode, HttpResponse response Response = response; } - public string? Name { get; private set; } + public string? Name { get; } private readonly HttpRequestNode RequestNode; diff --git a/src/Microsoft.DotNet.Interactive.Http/Model/HttpResponse.cs b/src/Microsoft.DotNet.Interactive.Http/Model/HttpResponse.cs index 702a52fc82..27d16a97a7 100644 --- a/src/Microsoft.DotNet.Interactive.Http/Model/HttpResponse.cs +++ b/src/Microsoft.DotNet.Interactive.Http/Model/HttpResponse.cs @@ -8,7 +8,7 @@ namespace Microsoft.DotNet.Interactive.Http; [TypeFormatterSource( typeof(HttpResponseFormatterSource), - PreferredMimeTypes = new[] { HtmlFormatter.MimeType })] + PreferredMimeTypes = [HtmlFormatter.MimeType])] public sealed class HttpResponse : PartialHttpResponse { public Dictionary Headers { get; } diff --git a/src/Microsoft.DotNet.Interactive.Http/Model/PartialHttpResponse.cs b/src/Microsoft.DotNet.Interactive.Http/Model/PartialHttpResponse.cs index 898c5f0896..5514d5dc60 100644 --- a/src/Microsoft.DotNet.Interactive.Http/Model/PartialHttpResponse.cs +++ b/src/Microsoft.DotNet.Interactive.Http/Model/PartialHttpResponse.cs @@ -7,7 +7,7 @@ namespace Microsoft.DotNet.Interactive.Http; [TypeFormatterSource( typeof(HttpResponseFormatterSource), - PreferredMimeTypes = new[] { HtmlFormatter.MimeType })] + PreferredMimeTypes = [HtmlFormatter.MimeType])] public class PartialHttpResponse : EmptyHttpResponse { public int StatusCode { get; } diff --git a/src/Microsoft.DotNet.Interactive.Jupyter/JupyterKernelCommandHandlers.cs b/src/Microsoft.DotNet.Interactive.Jupyter/JupyterKernelCommandHandlers.cs index 068f3f87ac..64f9f74aa1 100644 --- a/src/Microsoft.DotNet.Interactive.Jupyter/JupyterKernelCommandHandlers.cs +++ b/src/Microsoft.DotNet.Interactive.Jupyter/JupyterKernelCommandHandlers.cs @@ -190,7 +190,7 @@ private async Task HandleExecuteReplyMessageAsync(Protocol.Message message, Subm { switch (message) { - case (DisplayData displayData): + case DisplayData displayData: context.Publish(new DisplayedValueProduced(displayData.Data, command, GetFormattedValuesFromMimeBundle(displayData.Data), @@ -198,18 +198,18 @@ private async Task HandleExecuteReplyMessageAsync(Protocol.Message message, Subm )); break; - case (UpdateDisplayData updateDisplayData): + case UpdateDisplayData updateDisplayData: context.Publish(new DisplayedValueUpdated(updateDisplayData.Data, GetDisplayIdFromTransientData(updateDisplayData.Transient), command, GetFormattedValuesFromMimeBundle(updateDisplayData.Data))); break; - case (ExecuteResult result): + case ExecuteResult result: context.Publish(new ReturnValueProduced(result.Data, command, GetFormattedValuesFromMimeBundle(result.Data))); break; - case (Stream streamResult): + case Stream streamResult: if (streamResult.Name == Stream.StandardOutput) { context.Publish( @@ -226,7 +226,7 @@ private async Task HandleExecuteReplyMessageAsync(Protocol.Message message, Subm new[] { new FormattedValue(PlainTextFormatter.MimeType, streamResult.Text) })); } break; - case (Error error): + case Error error: StringBuilder builder = new StringBuilder(); foreach (var item in error.Traceback) @@ -243,7 +243,7 @@ private async Task HandleExecuteReplyMessageAsync(Protocol.Message message, Subm context.Fail(command, null, error.EName); break; - case (InputRequest inputRequest): + case InputRequest inputRequest: string input = await GetInputAsync(inputRequest, context); var reply = new InputReply(input); From 561f5709705d535327bbad3f953a030e84b601bb Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 22 Oct 2024 13:04:43 -0700 Subject: [PATCH 3/7] simplify magic command completions API --- ...nteractive_api_is_not_changed.approved.txt | 7 ++- .../DataFrameKernelExtension.cs | 12 +++-- .../InspectExtension.cs | 2 +- .../ConnectJupyterKernelDirective.cs | 26 +++++----- .../JupyterLocalKernelConnectionOptions.cs | 2 +- .../PolyglotSyntaxParserTests.Completions.cs | 10 ++-- .../KernelDirectiveCompletionContext.cs | 2 +- .../Directives/KernelDirectiveParameter.cs | 37 +++++++-------- .../KernelExtensions.cs | 47 +++++++++++-------- 9 files changed, 79 insertions(+), 66 deletions(-) diff --git a/src/Microsoft.DotNet.Interactive.ApiCompatibility.Tests/ApiCompatibilityTests.Interactive_api_is_not_changed.approved.txt b/src/Microsoft.DotNet.Interactive.ApiCompatibility.Tests/ApiCompatibilityTests.Interactive_api_is_not_changed.approved.txt index 7f09babed6..1d1269a9c6 100644 --- a/src/Microsoft.DotNet.Interactive.ApiCompatibility.Tests/ApiCompatibilityTests.Interactive_api_is_not_changed.approved.txt +++ b/src/Microsoft.DotNet.Interactive.ApiCompatibility.Tests/ApiCompatibilityTests.Interactive_api_is_not_changed.approved.txt @@ -562,7 +562,7 @@ Microsoft.DotNet.Interactive.Directives public System.String ToString() public class KernelDirectiveCompletionContext .ctor() - public System.Collections.Generic.IList Completions { get;} + public System.Collections.Generic.IList CompletionItems { get;} public class KernelDirectiveParameter .ctor(System.String name, System.String description = null) public System.Boolean AllowImplicitName { get; set;} @@ -572,9 +572,8 @@ Microsoft.DotNet.Interactive.Directives public System.String Name { get;} public System.Boolean Required { get; set;} public System.String TypeHint { get; set;} - public KernelDirectiveParameter AddCompletions(System.Func> getCompletions) - public KernelDirectiveParameter AddCompletions(System.Func>> getCompletions) - public KernelDirectiveParameter AddCompletions(System.Func> getCompletions) + public KernelDirectiveParameter AddCompletions(System.Func getCompletions) + public KernelDirectiveParameter AddCompletions(System.Func> getCompletions) public System.Threading.Tasks.Task> GetValueCompletionsAsync() public System.String ToString() public class KernelSpecifierDirective : KernelDirective diff --git a/src/Microsoft.DotNet.Interactive.ExtensionLab/DataFrameKernelExtension.cs b/src/Microsoft.DotNet.Interactive.ExtensionLab/DataFrameKernelExtension.cs index 8c0ff01b2e..2a6d62101d 100644 --- a/src/Microsoft.DotNet.Interactive.ExtensionLab/DataFrameKernelExtension.cs +++ b/src/Microsoft.DotNet.Interactive.ExtensionLab/DataFrameKernelExtension.cs @@ -43,10 +43,14 @@ public static Task LoadAsync(Kernel rootKernel) AllowImplicitName = true }; - variableNameParameter.AddCompletions(_ => cSharpKernel.ScriptState - .Variables - .Where(v => v.Value is DataFrame) - .Select(v => new CompletionItem(v.Name, WellKnownTags.Parameter))); + variableNameParameter.AddCompletions(_ => + { + var completionItems = cSharpKernel.ScriptState + .Variables + .Where(v => v.Value is DataFrame) + .Select(v => new CompletionItem(v.Name, WellKnownTags.Parameter)); + return Task.FromResult(completionItems); + }); var directive = new KernelActionDirective("#!linqify") { diff --git a/src/Microsoft.DotNet.Interactive.ExtensionLab/InspectExtension.cs b/src/Microsoft.DotNet.Interactive.ExtensionLab/InspectExtension.cs index 16e342572d..e48e419ee8 100644 --- a/src/Microsoft.DotNet.Interactive.ExtensionLab/InspectExtension.cs +++ b/src/Microsoft.DotNet.Interactive.ExtensionLab/InspectExtension.cs @@ -28,7 +28,7 @@ public static Task LoadAsync(Kernel kernel) inspect.Parameters.Add(new KernelDirectiveParameter("--configuration") { Description = "Build configuration to use. Debug or Release." - }.AddCompletions(_ => [ "Debug", "Release" ])); + }.AddCompletions(() => [ "Debug", "Release" ])); inspect.Parameters.Add(new KernelDirectiveParameter("--kind") { Description = "Source code kind. Script or Regular." diff --git a/src/Microsoft.DotNet.Interactive.Jupyter/ConnectJupyterKernelDirective.cs b/src/Microsoft.DotNet.Interactive.Jupyter/ConnectJupyterKernelDirective.cs index fc932c6bb4..450b657f5a 100644 --- a/src/Microsoft.DotNet.Interactive.Jupyter/ConnectJupyterKernelDirective.cs +++ b/src/Microsoft.DotNet.Interactive.Jupyter/ConnectJupyterKernelDirective.cs @@ -5,6 +5,7 @@ using Microsoft.DotNet.Interactive.Jupyter.Connection; using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.DotNet.Interactive.Directives; using Microsoft.DotNet.Interactive.Events; @@ -89,28 +90,31 @@ private IJupyterConnection GetJupyterConnection(ConnectJupyterKernel connectComm return null; } - private async Task> GetKernelSpecsCompletionsAsync(KernelDirectiveCompletionContext ctx) + private async Task GetKernelSpecsCompletionsAsync(KernelDirectiveCompletionContext context) { - var hash = GetParseResultHash(ctx); + var hash = GetParseResultHash(context); if (_mruKernelSpecSuggestions.Key == hash) { - return _mruKernelSpecSuggestions.Value; - } + foreach (var item in _mruKernelSpecSuggestions.Value) + { + context.CompletionItems.Add(item); + } - IEnumerable completions = []; + return; + } var connection = GetJupyterConnection(new ConnectJupyterKernel("")); using (connection as IDisposable) { - completions = await GetKernelSpecsCompletionsAsync(connection); - } + var completions = (await GetKernelSpecsCompletionsAsync(connection)).ToArray(); - if (completions is not null) - { _mruKernelSpecSuggestions = new(hash, completions); - } - return completions; + foreach (var item in completions) + { + context.CompletionItems.Add(item); + } + } } private async Task> GetKernelSpecsCompletionsAsync(IJupyterConnection connection) diff --git a/src/Microsoft.DotNet.Interactive.Jupyter/JupyterLocalKernelConnectionOptions.cs b/src/Microsoft.DotNet.Interactive.Jupyter/JupyterLocalKernelConnectionOptions.cs index e5b7433016..d74abd6d9c 100644 --- a/src/Microsoft.DotNet.Interactive.Jupyter/JupyterLocalKernelConnectionOptions.cs +++ b/src/Microsoft.DotNet.Interactive.Jupyter/JupyterLocalKernelConnectionOptions.cs @@ -14,7 +14,7 @@ public sealed class JupyterLocalKernelConnectionOptions : IJupyterKernelConnecti public JupyterLocalKernelConnectionOptions() { - CondaEnv.AddCompletions(_ => CondaEnvironment.GetEnvironments()); + CondaEnv.AddCompletions(CondaEnvironment.GetEnvironments); _parameters = new List { diff --git a/src/Microsoft.DotNet.Interactive.Parsing.Tests/PolyglotSyntaxParserTests.Completions.cs b/src/Microsoft.DotNet.Interactive.Parsing.Tests/PolyglotSyntaxParserTests.Completions.cs index 9227ad828d..01622ccf3e 100644 --- a/src/Microsoft.DotNet.Interactive.Parsing.Tests/PolyglotSyntaxParserTests.Completions.cs +++ b/src/Microsoft.DotNet.Interactive.Parsing.Tests/PolyglotSyntaxParserTests.Completions.cs @@ -127,8 +127,10 @@ public async Task produce_completions_for_parameter_values_when_parameter_allows Parameters = [ new KernelDirectiveParameter("--parameter") - { AllowImplicitName = true } - .AddCompletions(_ => ["one", "two", "three"]), + { + AllowImplicitName = true + } + .AddCompletions(() => ["one", "two", "three"]), new("--other-parameter") ] } @@ -271,7 +273,7 @@ public async Task produce_completions_for_parameter_values_when_parameter_allows [ new KernelDirectiveParameter("--parameter") { AllowImplicitName = true } - .AddCompletions(_ => ["one", "two", "three"]), + .AddCompletions(() => ["one", "two", "three"]), new("--other-parameter") ] } @@ -314,7 +316,7 @@ public async Task produce_completions_for_parameter_values() { Parameters = [ - new KernelDirectiveParameter("--parameter").AddCompletions(_ => ["one", "two", "three"]) + new KernelDirectiveParameter("--parameter").AddCompletions(() => ["one", "two", "three"]) ] } ] diff --git a/src/Microsoft.DotNet.Interactive/Directives/KernelDirectiveCompletionContext.cs b/src/Microsoft.DotNet.Interactive/Directives/KernelDirectiveCompletionContext.cs index 4ed943743f..8b33d90750 100644 --- a/src/Microsoft.DotNet.Interactive/Directives/KernelDirectiveCompletionContext.cs +++ b/src/Microsoft.DotNet.Interactive/Directives/KernelDirectiveCompletionContext.cs @@ -9,5 +9,5 @@ namespace Microsoft.DotNet.Interactive.Directives; public class KernelDirectiveCompletionContext { - public IList Completions { get; } = new List(); + public IList CompletionItems { get; } = new List(); } \ No newline at end of file diff --git a/src/Microsoft.DotNet.Interactive/Directives/KernelDirectiveParameter.cs b/src/Microsoft.DotNet.Interactive/Directives/KernelDirectiveParameter.cs index 89c1cb0108..49827cb537 100644 --- a/src/Microsoft.DotNet.Interactive/Directives/KernelDirectiveParameter.cs +++ b/src/Microsoft.DotNet.Interactive/Directives/KernelDirectiveParameter.cs @@ -13,7 +13,7 @@ namespace Microsoft.DotNet.Interactive.Directives; public class KernelDirectiveParameter { - List>>>? _completionSources; + List>? _completionSources; public KernelDirectiveParameter(string name, string? description = null) { @@ -35,16 +35,8 @@ public KernelDirectiveParameter(string name, string? description = null) public bool Flag { get; set; } - public KernelDirectiveParameter AddCompletions(Func> getCompletions) - { - _completionSources ??= new(); - - _completionSources.Add(context => Task.FromResult(getCompletions(context))); - - return this; - } - - public KernelDirectiveParameter AddCompletions(Func>> getCompletions) + public KernelDirectiveParameter AddCompletions( + Func getCompletions) { _completionSources ??= new(); @@ -53,13 +45,20 @@ public KernelDirectiveParameter AddCompletions(Func> getCompletions) + public KernelDirectiveParameter AddCompletions(Func> getCompletions) { _completionSources ??= new(); _completionSources.Add(context => - Task.FromResult(getCompletions(context) - .Select(s => new CompletionItem(s, WellKnownTags.Parameter)))); + { + var completionItems = getCompletions().Select(s => new CompletionItem(s, WellKnownTags.Parameter)); + foreach (var item in completionItems) + { + context.CompletionItems.Add(item); + } + + return Task.CompletedTask; + }); return this; } @@ -75,20 +74,16 @@ public async Task> GetValueCompletionsAsync() foreach (var source in _completionSources) { - var completionItems = await source(context); - foreach (var item in completionItems) - { - context.Completions.Add(item); - } + await source(context); } - foreach (var completion in context.Completions) + foreach (var completion in context.CompletionItems) { completion.AssociatedSymbol = this; completion.Documentation = Description; } - return context.Completions.ToArray(); + return context.CompletionItems.ToArray(); } public override string ToString() => Name; diff --git a/src/Microsoft.DotNet.Interactive/KernelExtensions.cs b/src/Microsoft.DotNet.Interactive/KernelExtensions.cs index c588d9c4e2..285ffca82a 100644 --- a/src/Microsoft.DotNet.Interactive/KernelExtensions.cs +++ b/src/Microsoft.DotNet.Interactive/KernelExtensions.cs @@ -185,7 +185,7 @@ private static void ConfigureAndAddSetDirective(T destinationKernel) where T { Description = LocalizationResources.Magics_set_value_Description(), Required = true - }.AddCompletions(async _ => + }.AddCompletions(async context => { if (destinationKernel.ParentKernel is { } composite) { @@ -197,7 +197,7 @@ private static void ConfigureAndAddSetDirective(T destinationKernel) where T var tasks = await Task.WhenAll(getValueTasks); - var x = tasks + var completionItems = tasks .Select(t => t.Events.OfType()) .SelectMany(events => events.Select(e => new { e.Command, e.ValueInfos })) .SelectMany(x => @@ -218,10 +218,11 @@ destinationKernel.RootKernel is CompositeKernel root && .Select(n => new CompletionItem(n, WellKnownTags.Parameter)) .ToArray(); - return x; + foreach (var item in completionItems) + { + context.CompletionItems.Add(item); + } } - - return Array.Empty(); }), new("--byref") { @@ -232,7 +233,7 @@ destinationKernel.RootKernel is CompositeKernel root && { Description = LocalizationResources.Magics_set_mime_type_Description() }.AddCompletions( - _ => + () => [ JsonFormatter.MimeType, HtmlFormatter.MimeType, @@ -258,7 +259,7 @@ private static void ConfigureAndAddShareDirective(T kernel) where T : Kernel { AllowImplicitName = true, Description = LocalizationResources.Magics_share_name_Description(), - }.AddCompletions(async _ => + }.AddCompletions(async context => { if (kernel.ParentKernel is { } composite) { @@ -270,34 +271,42 @@ private static void ConfigureAndAddShareDirective(T kernel) where T : Kernel var tasks = await Task.WhenAll(getValueTasks); - return tasks + var completionItems = tasks .Select(t => t.Events.OfType()) .SelectMany(events => events.SelectMany(e => e.ValueInfos)) .Select(vi => vi.Name) .OrderBy(x => x) .Select(n => new CompletionItem(n, WellKnownTags.Parameter)) .ToArray(); - } - return Array.Empty(); + foreach (var item in completionItems) + { + context.CompletionItems.Add(item); + } + } }), new KernelDirectiveParameter("--from") { Description = LocalizationResources.Magics_share_from_Description(), Required = true - }.AddCompletions(ctx => + }.AddCompletions(context => { if (kernel.ParentKernel is { } composite) { - return composite.ChildKernels - .Where(k => - k != kernel && - k.KernelInfo.SupportsCommand(nameof(RequestValueInfos)) && - k.KernelInfo.SupportsCommand(nameof(RequestValue))) - .Select(k => new CompletionItem(k.Name, WellKnownTags.Parameter)); + var completionItems = composite.ChildKernels + .Where(k => + k != kernel && + k.KernelInfo.SupportsCommand(nameof(RequestValueInfos)) && + k.KernelInfo.SupportsCommand(nameof(RequestValue))) + .Select(k => new CompletionItem(k.Name, WellKnownTags.Parameter)); + + foreach (var item in completionItems) + { + context.CompletionItems.Add(item); + } } - return Array.Empty(); + return Task.CompletedTask; }), new("--as") { @@ -307,7 +316,7 @@ private static void ConfigureAndAddShareDirective(T kernel) where T : Kernel { Description = LocalizationResources.Magics_share_mime_type_Description() }.AddCompletions( - _ => + () => [ JsonFormatter.MimeType, HtmlFormatter.MimeType, From 2e48bb6ba7edceee03cac1806674935cfa73cecf Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 22 Oct 2024 17:15:18 -0700 Subject: [PATCH 4/7] update call to new API --- .../ConnectNamedPipeDirective.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Interactive.NamedPipeConnector/ConnectNamedPipeDirective.cs b/src/Microsoft.DotNet.Interactive.NamedPipeConnector/ConnectNamedPipeDirective.cs index 567e997a2c..df7d43359e 100644 --- a/src/Microsoft.DotNet.Interactive.NamedPipeConnector/ConnectNamedPipeDirective.cs +++ b/src/Microsoft.DotNet.Interactive.NamedPipeConnector/ConnectNamedPipeDirective.cs @@ -43,7 +43,7 @@ public static void AddToRootKernel() if (KernelInvocationContext.Current is { } context && context.HandlingKernel.RootKernel is CompositeKernel root) { - root.AddKernelConnector(new ConnectNamedPipeDirective()); + root.AddConnectDirective(new ConnectNamedPipeDirective()); } } } \ No newline at end of file From e32c23624eff4556b3dd01982c7a445b7e55ec1e Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Wed, 23 Oct 2024 15:37:31 -0700 Subject: [PATCH 5/7] fix #!linqify completions --- .../DataFrameKernelExtension.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Interactive.ExtensionLab/DataFrameKernelExtension.cs b/src/Microsoft.DotNet.Interactive.ExtensionLab/DataFrameKernelExtension.cs index 2a6d62101d..3dcac844de 100644 --- a/src/Microsoft.DotNet.Interactive.ExtensionLab/DataFrameKernelExtension.cs +++ b/src/Microsoft.DotNet.Interactive.ExtensionLab/DataFrameKernelExtension.cs @@ -43,13 +43,19 @@ public static Task LoadAsync(Kernel rootKernel) AllowImplicitName = true }; - variableNameParameter.AddCompletions(_ => + variableNameParameter.AddCompletions(context => { var completionItems = cSharpKernel.ScriptState .Variables .Where(v => v.Value is DataFrame) .Select(v => new CompletionItem(v.Name, WellKnownTags.Parameter)); - return Task.FromResult(completionItems); + + foreach (var item in completionItems) + { + context.CompletionItems.Add(item); + } + + return Task.CompletedTask; }); var directive = new KernelActionDirective("#!linqify") From ba9a7c4f8e2d839698d139ea7d391d53a263b3a8 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Thu, 24 Oct 2024 15:44:53 -0700 Subject: [PATCH 6/7] fix missing added references in CSharpKernel --- .../CSharpKernelTests.cs | 40 ++++++++++++++++ .../InteractiveWorkspace.cs | 48 ++++++++++++------- 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.DotNet.Interactive.CSharp.Tests/CSharpKernelTests.cs b/src/Microsoft.DotNet.Interactive.CSharp.Tests/CSharpKernelTests.cs index 9c9b8649c3..b4b295ee35 100644 --- a/src/Microsoft.DotNet.Interactive.CSharp.Tests/CSharpKernelTests.cs +++ b/src/Microsoft.DotNet.Interactive.CSharp.Tests/CSharpKernelTests.cs @@ -1,9 +1,11 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Linq; using System.Threading.Tasks; using FluentAssertions; using Microsoft.DotNet.Interactive.Commands; +using Microsoft.DotNet.Interactive.Events; using Microsoft.DotNet.Interactive.Tests; using Microsoft.DotNet.Interactive.Tests.Utility; using Xunit; @@ -56,4 +58,42 @@ public async Task GetValueInfos_only_returns_non_shadowed_values() .Should() .ContainSingle(v => v.Name == "x"); } + + [Fact] + public async Task Use_of_interactive_API_in_submitted_code_does_not_produce_diagnostics() + { + using var kernel = new CSharpKernel(); + + var result1 = await kernel.SendAsync( + new SubmitCode( + """ + using Microsoft.DotNet.Interactive; + using Microsoft.DotNet.Interactive.Commands; + using Microsoft.DotNet.Interactive.Events; + + Kernel.Root.GetType() + """)); + + result1.Events.Should().NotContainErrors(); + result1.Events.OfType() + .SelectMany(d => d.FormattedDiagnostics) + .Should().BeEmpty(); + + var result2 = await kernel.SendAsync( + new RequestDiagnostics( + """ + using Microsoft.DotNet.Interactive; + using Microsoft.DotNet.Interactive.Commands; + using Microsoft.DotNet.Interactive.Events; + + + + Kernel.Root.GetType() + """)); + + result2.Events.Should().NotContainErrors(); + result2.Events.OfType() + .SelectMany(d => d.FormattedDiagnostics) + .Should().BeEmpty(); + } } \ No newline at end of file diff --git a/src/Microsoft.DotNet.Interactive.CSharp/InteractiveWorkspace.cs b/src/Microsoft.DotNet.Interactive.CSharp/InteractiveWorkspace.cs index 8ad38fa349..f708639fa4 100644 --- a/src/Microsoft.DotNet.Interactive.CSharp/InteractiveWorkspace.cs +++ b/src/Microsoft.DotNet.Interactive.CSharp/InteractiveWorkspace.cs @@ -29,22 +29,7 @@ internal class InteractiveWorkspace : Workspace private readonly List _packageManagerReferences = new(); private readonly SemaphoreSlim _workspaceLock = new(1, 1); - public InteractiveWorkspace() : base(MefHostServices.DefaultHost, WorkspaceKind.Interactive) - { - _parseOptions = new CSharpParseOptions( - LanguageVersion.Latest, - DocumentationMode.Parse, - SourceCodeKind.Script); - - _referenceAssemblies = ResolveRefAssemblies(); - - _disposables.Add(Disposable.Create(() => - { - _currentCompilation = null; - })); - } - - private static string ResolveRefAssemblyPath() + private static readonly Lazy _referenceAssembliesPath = new(() => { var runtimeDir = Path.GetDirectoryName(typeof(object).Assembly.Location); var refAssemblyDir = runtimeDir; // if any of the below path probing fails, fall back to the runtime so we can still run @@ -75,6 +60,21 @@ private static string ResolveRefAssemblyPath() } return refAssemblyDir; + }); + + public InteractiveWorkspace() : base(MefHostServices.DefaultHost, WorkspaceKind.Interactive) + { + _parseOptions = new CSharpParseOptions( + LanguageVersion.Latest, + DocumentationMode.Parse, + SourceCodeKind.Script); + + _referenceAssemblies = ResolveRefAssemblies(); + + _disposables.Add(Disposable.Create(() => + { + _currentCompilation = null; + })); } private static bool TryParseVersion(string versionString, out Version v) @@ -92,7 +92,7 @@ private static bool TryParseVersion(string versionString, out Version v) private static IReadOnlyCollection ResolveRefAssemblies() { var assemblyRefs = new List(); - foreach (var assemblyRef in Directory.EnumerateFiles(ResolveRefAssemblyPath(), "*.dll")) + foreach (var assemblyRef in Directory.EnumerateFiles(_referenceAssembliesPath.Value, "*.dll")) { try { @@ -149,7 +149,19 @@ private IReadOnlyCollection GetReferenceSet(Compilation compi _referenceAssemblies .Concat(_packageManagerReferences) .Concat(compilation.DirectiveReferences) - .ToArray(); + .ToHashSet(); + + foreach (var reference in compilation.ExternalReferences.Distinct()) + { + if (reference.Display is { } display) + { + if (!display.Contains("Microsoft.NETCore.App")) + { + references.Add(reference); + } + } + } + return references; } From 3c0671d3ba179813d39d9c48a61e0770157cc9f9 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Thu, 24 Oct 2024 16:19:33 -0700 Subject: [PATCH 7/7] add Kernel.GetInputsAsync method --- ...nteractive_api_is_not_changed.approved.txt | 1 + .../RequestInputTests.cs | 39 ++++++++++++++++++- .../Kernel.Static.cs | 27 ++++++++++++- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Interactive.ApiCompatibility.Tests/ApiCompatibilityTests.Interactive_api_is_not_changed.approved.txt b/src/Microsoft.DotNet.Interactive.ApiCompatibility.Tests/ApiCompatibilityTests.Interactive_api_is_not_changed.approved.txt index 1d1269a9c6..b17f7caa74 100644 --- a/src/Microsoft.DotNet.Interactive.ApiCompatibility.Tests/ApiCompatibilityTests.Interactive_api_is_not_changed.approved.txt +++ b/src/Microsoft.DotNet.Interactive.ApiCompatibility.Tests/ApiCompatibilityTests.Interactive_api_is_not_changed.approved.txt @@ -94,6 +94,7 @@ Microsoft.DotNet.Interactive public static System.Void CSS(System.String content) public static DisplayedValue display(System.Object value, System.String[] mimeTypes) public static System.Threading.Tasks.Task GetInputAsync(System.String prompt = , System.String typeHint = text) + public static System.Threading.Tasks.Task> GetInputsAsync(System.Collections.Generic.IEnumerable inputDescriptions) public static System.Threading.Tasks.Task GetPasswordAsync(System.String prompt = ) public static Microsoft.AspNetCore.Html.IHtmlContent HTML(System.String content) public static System.Void Javascript(System.String scriptContent) diff --git a/src/Microsoft.DotNet.Interactive.Tests/RequestInputTests.cs b/src/Microsoft.DotNet.Interactive.Tests/RequestInputTests.cs index cccbef60c0..fb3fe79396 100644 --- a/src/Microsoft.DotNet.Interactive.Tests/RequestInputTests.cs +++ b/src/Microsoft.DotNet.Interactive.Tests/RequestInputTests.cs @@ -110,7 +110,7 @@ public async Task When_a_saved_value_is_used_then_the_user_is_notified() } [Fact] - public async Task Multiple_inputs_can_be_requested_together() + public async Task Multiple_inputs_can_be_requested_together_using_command() { var requestInputs = new RequestInputs { @@ -142,6 +142,43 @@ public async Task Multiple_inputs_can_be_requested_together() .Which.Values.Should().BeEquivalentTo(formValues); } + [Fact] + public async Task Multiple_inputs_can_be_requested_together_using_GetInputsAsync() + { + using var kernel = CreateKernel() + .UseFormsForMultipleInputs(); + + var formValues = new Dictionary + { + ["Fruit"] = "cherry", + ["Tastiness"] = "9000", + ["Color"] = "red" + }; + + kernel.RespondToRequestInputsFormWith(formValues); + + var result = await kernel.SendAsync( + new SubmitCode( + """ + using Microsoft.DotNet.Interactive; + + var inputResult = await Kernel.GetInputsAsync( + [ + new("Fruit"), + new("Tastiness"), + new("Color") + ]); + """, "csharp")); + + result.Events.Should().NotContainErrors(); + + var csharpKernel = (CSharpKernel)kernel.FindKernelByName("csharp"); + + csharpKernel.TryGetValue>("inputResult", out var inputResult).Should().BeTrue(); + + inputResult.Should().BeEquivalentTo(formValues); + } + private static CompositeKernel CreateKernel() { var powerShellKernel = new PowerShellKernel(); diff --git a/src/Microsoft.DotNet.Interactive/Kernel.Static.cs b/src/Microsoft.DotNet.Interactive/Kernel.Static.cs index 163df7cd74..cee07a36cb 100644 --- a/src/Microsoft.DotNet.Interactive/Kernel.Static.cs +++ b/src/Microsoft.DotNet.Interactive/Kernel.Static.cs @@ -44,7 +44,32 @@ public static async Task GetInputAsync( { return await GetInputAsync(prompt, false, typeHint); } - + + public static async Task> GetInputsAsync( + IEnumerable inputDescriptions) + { + if (inputDescriptions is null || inputDescriptions.Count() is 0) + { + throw new ArgumentException("You must provide at least one input description."); + } + + var command = new RequestInputs(); + + foreach (var inputDescription in inputDescriptions) + { + command.Inputs.Add(inputDescription); + } + + var result = await Root.SendAsync(command, CancellationToken.None); + + if (result.Events.OfType().SingleOrDefault() is { } inputsProduced) + { + return inputsProduced.Values; + } + + throw new OperationCanceledException("Input request canceled."); + } + public static async Task GetPasswordAsync(string prompt = "") { var password = await GetInputAsync(prompt, true);