示例#1
0
        public async Task new_commands_issued_after_cancel_are_executed()
        {
            var kernel = CreateKernel()
                         .LogCommandsToPocketLogger()
                         .LogEventsToPocketLogger();

            var commandToCancel = new SubmitCode(@"
using Microsoft.DotNet.Interactive;

while(!KernelInvocationContext.Current.CancellationToken.IsCancellationRequested){ await Task.Delay(10); }", targetKernelName: "csharp");

            var _ = kernel.SendAsync(commandToCancel);
            await kernel.SendAsync(new Cancel());

            var followingCommand = new SubmitCode("1");
            await kernel.SendAsync(followingCommand);

            KernelEvents
            .Should()
            .ContainSingle <CommandSucceeded>(c => c.Command == followingCommand);
        }
示例#2
0
        public async Task it_returns_completion_list_for_types_imported_at_runtime()
        {
            var kernel = CreateKernel();

            var dll = new FileInfo(typeof(JsonConvert).Assembly.Location).FullName;

            await kernel.SendAsync(
                new SubmitCode($"#r \"{dll}\""));

            await kernel.SendAsync(new RequestCompletion("Newtonsoft.Json.JsonConvert.", 28));

            KernelEvents.Should()
            .ContainSingle(e => e.Value is CompletionRequestReceived);

            KernelEvents.Single(e => e.Value is CompletionRequestCompleted)
            .Value
            .As <CompletionRequestCompleted>()
            .CompletionList
            .Should()
            .Contain(i => i.DisplayText == "SerializeObject");
        }
示例#3
0
        public async Task can_cancel_user_loop_using_CancellationToken()
        {
            var kernel = CreateKernel();

            var cancelCommand = new Cancel();

            var commandToCancel = new SubmitCode(@"
using Microsoft.DotNet.Interactive;

while(!KernelInvocationContext.Current.CancellationToken.IsCancellationRequested){ await Task.Delay(10); }", targetKernelName: "csharp");

            var resultForCommandToCancel = kernel.SendAsync(commandToCancel);

            await kernel.SendAsync(cancelCommand);

            await resultForCommandToCancel;

            KernelEvents
            .Should()
            .ContainSingle <CommandFailed>(c => c.Command == commandToCancel);
        }
示例#4
0
        public async Task Should_load_extension_in_directory()
        {
            var directory = Create.EmptyWorkspace().Directory;

            const string nugetPackageName      = "myNugetPackage";
            var          nugetPackageDirectory = new InMemoryDirectoryAccessor(
                directory.Subdirectory($"{nugetPackageName}/2.0.0"))
                                                 .CreateFiles();

            var extensionsDir =
                (FileSystemDirectoryAccessor)nugetPackageDirectory.GetDirectoryAccessorForRelativePath(new RelativeDirectoryPath("interactive-extensions/dotnet/cs"));

            var extensionDll = await KernelExtensionTestHelper.CreateExtensionInDirectory(
                directory, @"await kernel.SendAsync(new SubmitCode(""using System.Reflection;""));",
                extensionsDir);

            var kernel = CreateKernel();

            await kernel.SendAsync(new LoadExtensionsInDirectory(nugetPackageDirectory));


            KernelEvents.Should()
            .ContainSingle(e => e.Value is ExtensionLoaded &&
                           e.Value.As <ExtensionLoaded>().ExtensionPath.FullName.Equals(extensionDll.FullName));

            KernelEvents.Should()
            .ContainSingle(e => e.Value is CommandHandled &&
                           e.Value
                           .As <CommandHandled>()
                           .Command
                           .As <SubmitCode>()
                           .Code
                           .Contains("using System.Reflection;"));

            KernelEvents.Should().ContainSingle(e => e.Value is DisplayedValueProduced &&
                                                e.Value.As <DisplayedValueProduced>()
                                                .Value
                                                .ToString()
                                                .Contains($"Loaded kernel extension TestKernelExtension from assembly {extensionDll.FullName}"));
        }
        public async Task correct_signature_help_is_displayed(Language language, string submittedCode, string markupCode, int activeSignature, string signaureLabel, int activeParameter, string parameterName)
        {
            var kernel = CreateKernel(language);

            await kernel.SubmitCodeAsync(submittedCode);

            MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var column);

            await kernel.SendAsync(new RequestSignatureHelp(code, new LinePosition(line, column)));

            KernelEvents
            .Should()
            .ContainSingle <SignatureHelpProduced>()
            .Which
            .Signatures
            .Should()
            .HaveCountGreaterThan(activeSignature)
            .And
            .ContainSingle(signatureInfo => signatureInfo.Label == signaureLabel &&
                           signatureInfo.Parameters.Count > activeParameter &&
                           signatureInfo.Parameters[activeParameter].Label == parameterName);
        }
示例#6
0
        public async Task Completions_are_available_for_symbols_members(Language language)
        {
            var declaration = language switch
            {
                Language.CSharp => new SubmitCode("var fileInfo = new System.IO.FileInfo(\"temp.file\");"),
                Language.FSharp => new SubmitCode("let fileInfo = new System.IO.FileInfo(\"temp.file\")")
            };

            var kernel = CreateKernel(language);
            await kernel.SendAsync(declaration);

            MarkupTestFile.GetLineAndColumn("fileInfo.$$", out var useInput, out var line, out var column);
            await kernel.SendAsync(new RequestCompletions(useInput, new LinePosition(line, column)));

            KernelEvents
            .Should()
            .ContainSingle <CompletionsProduced>()
            .Which
            .Completions
            .Should()
            .Contain(item => item.DisplayText == "AppendText");
        }
示例#7
0
        public async Task completion_commands_and_events_have_offsets_normalized_when_switching_languages()
        {
            // switch to PowerShell from an F# kernel/cell
            using var kernel = CreateCompositeKernel(Language.FSharp);
            var fullMarkupCode = string.Join("\r\n", new[]
            {
                "let x = 1",
                "#!pwsh",
                "Get-$$"
            });

            MarkupTestFile.GetLineAndColumn(fullMarkupCode, out var code, out var line, out var character);
            await kernel.SendAsync(new RequestCompletions(code, new LinePosition(line, character)));

            KernelEvents
            .Should()
            .ContainSingle <CompletionsProduced>()
            .Which
            .LinePositionSpan
            .Should()
            .Be(new LinePositionSpan(new LinePosition(line, 0), new LinePosition(line, 4)));
        }
        public async Task csharp_signature_help_can_read_doc_comments_from_nuget_packages_after_forcing_the_assembly_to_load()
        {
            using var kernel = CreateKernel(Language.CSharp);

            await SubmitCode(kernel, "#r \"nuget: Newtonsoft.Json, 12.0.3\"");

            // The following line forces the assembly and the doc comments to be loaded
            await SubmitCode(kernel, "var _unused = Newtonsoft.Json.JsonConvert.Null;");

            var markupCode = "Newtonsoft.Json.JsonConvert.DeserializeObject($$";

            MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character);
            await kernel.SendAsync(new RequestSignatureHelp(code, new LinePosition(line, character)));

            KernelEvents
            .Should()
            .ContainSingle <SignatureHelpProduced>()
            .Which
            .Signatures
            .Should()
            .ContainSingle(sh => sh.Documentation.Value.Contains("Deserializes the JSON to a .NET object."));
        }
示例#9
0
        public async Task csharp_completions_can_read_doc_comments_from_nuget_packages_after_forcing_the_assembly_to_load()
        {
            using var kernel = CreateKernel(Language.CSharp);

            await SubmitCode(kernel, "#r \"nuget: Newtonsoft.Json, 12.0.3\"");

            // The following line forces the assembly and the doc comments to be loaded
            await SubmitCode(kernel, "var _unused = Newtonsoft.Json.JsonConvert.Null;");

            var markupCode = "Newtonsoft.Json.JsonConvert.Nu$$";

            MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character);
            await kernel.SendAsync(new RequestCompletions(code, new LinePosition(line, character)));

            KernelEvents
            .Should()
            .ContainSingle <CompletionsProduced>()
            .Which
            .Completions
            .Should()
            .ContainSingle(ci => ci.Documentation != null && ci.Documentation.Contains("Represents JavaScript's null as a string. This field is read-only."));
        }
示例#10
0
        public async Task it_can_load_assembly_references_using_r_directive_separate_submissions(Language language)
        {
            var kernel = CreateKernel(language);

            // F# strings treat \ as an escape character.  So do C# strings, except #r in C# is special, and doesn't.  F# usually uses @ strings for paths @"c:\temp\...."
            var dllPath = new FileInfo(typeof(JsonConvert).Assembly.Location).FullName.Replace('\\', '/');

            var source = language switch
            {
                Language.FSharp => new[]
                {
                    $"#r \"{dllPath}\"",
                    "open Newtonsoft.Json",
                    @"let json = JsonConvert.SerializeObject( struct {| value = ""hello"" |} )",
                    "json"
                },

                Language.CSharp => new[]
                {
                    $"#r \"{dllPath}\"",
                    "using Newtonsoft.Json;",
                    @"var json = JsonConvert.SerializeObject(new { value = ""hello"" });",
                    "json"
                }
            };

            await SubmitCode(kernel, source);

            KernelEvents
            .Should()
            .ContainSingle(e => e is ReturnValueProduced);

            KernelEvents
            .OfType <ReturnValueProduced>()
            .Single()
            .Value
            .Should()
            .Be(new { value = "hello" }.ToJson());
        }
示例#11
0
        public async Task Display_indicates_when_a_value_is_null(Language language)
        {
            var kernel = CreateKernel(language);

            var submission = language switch
            {
                Language.CSharp => "display(null);",
                Language.FSharp => "display(null)"
            };

            await kernel.SendAsync(new SubmitCode(submission));

            KernelEvents.Should().NotContainErrors();

            KernelEvents
            .OfType <DisplayedValueProduced>()
            .SelectMany(v => v.FormattedValues)
            .Should()
            .ContainSingle(v =>
                           v.MimeType == "text/html" &&
                           v.Value.ToString().Contains(Formatter.NullString.HtmlEncode().ToString()));
        }
        public async Task Should_load_extension_in_directory()
        {
            var directory = DirectoryUtility.CreateDirectory();

            const string nugetPackageName      = "myNugetPackage";
            var          nugetPackageDirectory = new DirectoryInfo(
                Path.Combine(
                    directory.FullName,
                    nugetPackageName,
                    "2.0.0"));

            var extensionsDir =
                new DirectoryInfo(
                    Path.Combine(
                        nugetPackageDirectory.FullName,
                        "interactive-extensions", "dotnet", "cs"));

            var extensionDll = await KernelExtensionTestHelper.CreateExtensionInDirectory(
                directory,
                @"await kernel.SendAsync(new SubmitCode(""using System.Reflection;""));",
                extensionsDir);

            var kernel = CreateKernel();

            await kernel.SendAsync(new LoadExtensionsInDirectory(nugetPackageDirectory));

            KernelEvents.Should()
            .ContainSingle(e => e is ExtensionLoaded &&
                           e.As <ExtensionLoaded>().ExtensionPath.FullName.Equals(extensionDll.FullName));

            KernelEvents.Should()
            .ContainSingle(e => e is DisplayedValueProduced &&
                           e
                           .As <DisplayedValueProduced>()
                           .Value
                           .ToString()
                           .Contains($"Loaded kernel extension TestKernelExtension from assembly {extensionDll.FullName}"));
        }
示例#13
0
        // [InlineData(Language.FSharp)]                         // Todo: do 1 returns a value it shouldn't
        public async Task it_does_not_return_a_result_for_a_statement(Language language)
        {
            var kernel = CreateKernel(language);

            var source = language switch
            {
                // Closest F# has to a statement do discards the result
                Language.FSharp => "do 1",

                // if is a statement in C#
                Language.CSharp => "var x = 1;"
            };

            await SubmitCode(kernel, source, submissionType : SubmissionType.Run);

            KernelEvents
            .Should()
            .NotContain(e => e.Value is StandardOutputValueProduced);

            KernelEvents
            .Should()
            .NotContain(e => e.Value is ReturnValueProduced);
        }
示例#14
0
        public async Task requested_diagnostics_are_remapped_to_the_appropriate_span(Language language, string languageSpecificCode)
        {
            var kernel = CreateKernel(language);

            var fullCode = $@"

#!time

$${languageSpecificCode}
";

            MarkupTestFile.GetLineAndColumn(fullCode, out var code, out var line, out var _column);

            await kernel.SendAsync(new RequestDiagnostics(code));

            KernelEvents
            .Should()
            .ContainSingle <DiagnosticsProduced>(d => d.Diagnostics.Count == 1)
            .Which
            .Diagnostics
            .Should()
            .ContainSingle(diag => diag.LinePositionSpan.Start.Line == line);
        }
示例#15
0
        public async Task CSharp_generic_type_completions_are_returned_as_a_snippet()
        {
            // in general F# prefers to infer generic types, not specify them

            var kernel = CreateKernel(Language.CSharp);

            var markupCode = "System.Collections.Generic.IEnu$$";

            MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character);

            await kernel.SendAsync(new RequestCompletions(code, new LinePosition(line, character)));

            KernelEvents
            .Should()
            .ContainSingle <CompletionsProduced>()
            .Which
            .Completions
            .Should()
            .Contain(item =>
                     item.DisplayText == "IEnumerable<>" &&
                     item.InsertText == "IEnumerable<$1>" &&
                     item.InsertTextFormat == InsertTextFormat.Snippet);
        }
示例#16
0
        public async Task when_code_contains_compile_time_warnings_diagnostics_are_produced(Language language, string diagnosticMessage)
        {
            var kernel = CreateKernel(language);

            var source = language switch
            {
                Language.FSharp => new[]
                {
                    "System.AppDomain.GetCurrentThreadId()"
                },

                Language.CSharp => new[]
                {
                    "System.AppDomain.GetCurrentThreadId()",
                }
            };

            await SubmitCode(kernel, source);

            using var _ = new AssertionScope();

            KernelEvents
            .Should()
            .ContainSingle <ReturnValueProduced>();

            KernelEvents
            .Should()
            .ContainSingle <DiagnosticsProduced>(d => d.Diagnostics.Count > 0)
            .Which
            .Diagnostics
            .Should()
            .ContainSingle(diagnostic => true)
            .Which
            .Message
            .Should()
            .StartWith(diagnosticMessage);
        }
        //Not implemented: [InlineData(Language.FSharp)]
        public async Task it_can_load_script_files_using_load_directive_with_relative_path_after_command_changeWorkingDirectory(Language language)
        {
            var currentDirectory = Directory.GetCurrentDirectory();

            DisposeAfterTest(() => Directory.SetCurrentDirectory(currentDirectory));

            var kernel = CreateKernel(language);
            var absolutePathOneLevelHigher = Directory.GetParent(currentDirectory).FullName;
            await kernel.SendAsync(new ChangeWorkingDirectory(absolutePathOneLevelHigher));

            var relativePath = Path.GetRelativePath(absolutePathOneLevelHigher, currentDirectory);

            var code = language switch
            {
                Language.CSharp => $"#load \"{relativePath}/RelativeLoadingSample.csx\"",
                Language.FSharp => $"#load \"{relativePath}/RelativeLoadingSample.fsx\""
            };

            var command = new SubmitCode(code);
            await kernel.SendAsync(command);

            KernelEvents.Should()
            .ContainSingle <StandardOutputValueProduced>(e => e.FormattedValues.Any(v => v.Value.Contains("hello!")));
        }
示例#18
0
        //        [InlineData(Language.FSharp)]                 // Todo: need to generate CompletionRequestReceived event ... perhaps
        public async Task it_returns_completion_list_for_types(Language language)
        {
            var kernel = CreateKernel(language);

            var source = language switch
            {
                Language.FSharp => @"System.Console.",

                Language.CSharp => @"System.Console."
            };

            await kernel.SendAsync(new RequestCompletion(source, 15));

            KernelEvents
            .Should()
            .ContainSingle(e => e is CompletionRequestReceived);

            KernelEvents
            .OfType <CompletionRequestCompleted>()
            .Single()
            .CompletionList
            .Should()
            .Contain(i => i.DisplayText == "ReadLine");
        }
示例#19
0
        // [InlineData(Language.FSharp)]    TODO -- Uncomment when FSharp is inserted
        public async Task it_can_load_assembly_referenced_from_refs_folder_in_nugetpackage(Language language)
        {
            var kernel = CreateKernel(language);

            var source = language switch
            {
                Language.FSharp => @"
#r ""nuget:Microsoft.ML.OnnxTransformer,1.4.0""

open System
open System.Numerics.Tensors
let inputValues = [| 12.0; 10.0; 17.0; 5.0 |]
let tInput = new DenseTensor<float>(inputValues.AsMemory(), new ReadOnlySpan<int>([|4|]))
tInput.Length
",
                Language.CSharp => @"
#r ""nuget:Microsoft.ML.OnnxTransformer,1.4.0""

using System;
using System.Numerics.Tensors;
var inputValues = new[] { 12f, 10f, 17f, 5f };
var tInput = new DenseTensor<float>(inputValues.AsMemory(), new ReadOnlySpan<int>(new[] { 4 }));
tInput.Length"
            };

            await SubmitCode(kernel, source);

            KernelEvents
            .Should()
            .ContainSingle <ReturnValueProduced>()
            .Which
            .Value
            .Should()
            .Be(4);
        }
    }
        public async Task it_returns_a_similarly_shaped_error(Language language)
        {
            var kernel = CreateKernel(language, openTestingNamespaces: true);

            var(source, errorFragments) = language switch
            {
                Language.CSharp => ("using Not.A.Namespace;", new[] { "(1,7): error CS0246:", "Not", "using" }),
                Language.FSharp => ("open Not.A.Namespace", new[] { @"input.fsx (1,6)-(1,9) typecheck error", "Not" })
            };

            await SubmitCode(kernel, source);

            KernelEvents
            .Should()
            .ContainSingle <DiagnosticsProduced>(d => d.Diagnostics.Count > 0)
            .Which
            .FormattedDiagnostics
            .Should()
            .ContainSingle(fv => true)
            .Which
            .Value
            .Should()
            .ContainAll(errorFragments);
        }
示例#21
0
        public async Task Completions_are_available_for_symbols_declared_in_the_previous_submission(Language language)
        {
            var variableName = "aaaaaaa";

            var declarationSubmission = language switch
            {
                Language.CSharp => $"var {variableName} = 123;",
                Language.FSharp => $"let {variableName} = 123"
            };

            var kernel = CreateKernel(language);

            await kernel.SubmitCodeAsync(declarationSubmission);

            await kernel.SendAsync(new RequestCompletions("aaa", new LinePosition(0, 3)));

            KernelEvents
            .Should()
            .ContainSingle <CompletionsProduced>()
            .Which
            .Completions
            .Should()
            .Contain(item => item.DisplayText == variableName);
        }
        public async Task diagnostics_are_produced_on_command_succeeded(Language language, string code, string errorCode, params string[] diagnosticMessageFragments)
        {
            var kernel = CreateKernel(language);

            await kernel.SubmitCodeAsync(code);

            using var _ = new AssertionScope();

            KernelEvents
            .Should()
            .ContainSingle <CommandSucceeded>();

            KernelEvents
            .Should()
            .ContainSingle <DiagnosticsProduced>(d => d.Diagnostics.Count > 0)
            .Which
            .Diagnostics
            .Should()
            .ContainSingle(diag =>
                           diag.Code == errorCode &&
                           diagnosticMessageFragments.All(
                               frag => diag.Message.Contains(frag)
                               ));
        }
示例#23
0
        public async Task Null_return_value_is_formatted_as_null(Language language)
        {
            var kernel = CreateKernel(language);

            var submission = language switch
            {
                Language.CSharp => "null",
                Language.FSharp => "let o : obj = null\no"
            };

            await kernel.SendAsync(new SubmitCode(submission));

            KernelEvents.Should().NotContainErrors();

            KernelEvents
            .Should()
            .ContainSingle <ReturnValueProduced>()
            .Which
            .FormattedValues
            .Should()
            .ContainSingle(v =>
                           v.MimeType == "text/html" &&
                           v.Value.ToString().Contains(Formatter.NullString.HtmlEncode().ToString()));
        }
示例#24
0
        public async Task quit_command_fails_when_not_configured()
        {
            var kernel = CreateKernel();

            var quit = new Quit();

            await kernel.SendAsync(quit);

            using var _ = new AssertionScope();

            KernelEvents
            .Should().ContainSingle <CommandFailed>()
            .Which
            .Command
            .Should()
            .Be(quit);

            KernelEvents
            .Should().ContainSingle <CommandFailed>()
            .Which
            .Exception
            .Should()
            .BeOfType <InvalidOperationException>();
        }
示例#25
0
        public async Task when_code_contains_compile_time_error_diagnostics_are_produced(Language language, string code, string diagnosticMessage, string errorMessage)
        {
            var kernel = CreateKernel(language);

            var source = language switch
            {
                Language.FSharp => new[]
                {
                    "open System",
                    "aaaadd"
                },

                Language.CSharp => new[]
                {
                    "using System;",
                    "aaaadd"
                }
            };

            await SubmitCode(kernel, source);

            var diagnosticRange = new LinePositionSpan(
                new LinePosition(0, 0),
                new LinePosition(0, 6));

            using var _ = new AssertionScope();

            // The CommandFailed message is populated
            KernelEvents
            .Should()
            .ContainSingle <CommandFailed>()
            .Which
            .Message
            .Should()
            .Be(errorMessage);

            // The Diagnostics of DiagnosticsProduced event are populated
            KernelEvents
            .Should()
            .ContainSingle <DiagnosticsProduced>(d => d.Diagnostics.Count > 0)
            .Which
            .Diagnostics
            .Should()
            .ContainSingle(diag =>
                           diag.LinePositionSpan == diagnosticRange &&
                           diag.Code == code &&
                           diag.Message == diagnosticMessage);

            // The FormattedValues are populated of DiagnosticsProduced event are populated
            KernelEvents
            .Should()
            .ContainSingle <DiagnosticsProduced>(d => d.Diagnostics.Count > 0)
            .Which
            .FormattedDiagnostics
            .Should()
            .ContainSingle(fv => true)
            .Which
            .Value
            .Should()
            .Be(errorMessage);
        }