예제 #1
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)));
        }
예제 #2
0
        public async Task it_returns_completion_list_for_previously_declared_items(Language language)
        {
            var kernel = CreateKernel(language, openTestingNamespaces: true);

            var source = language switch
            {
                Language.FSharp => @"let alpha = new Random()",
                Language.CSharp => @"var alpha = new Random();",
                Language.PowerShell => @"function alpha { 5 }",
            };

            await SubmitCode(kernel, source);

            await kernel.SendAsync(new RequestCompletions("al", new LinePosition(0, 2)));

            KernelEvents
            .OfType <CompletionsProduced>()
            .Single()
            .Completions
            .Should()
            .Contain(i => i.DisplayText == "alpha");
        }
예제 #3
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());
        }
예제 #4
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()));
        }
예제 #5
0
        public async Task it_returns_completion_list_for_types_imported_at_runtime(Language language)
        {
            var kernel = CreateKernel(language);

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

            var code = language switch
            {
                Language.CSharp => $"#r \"{dll}\"",
                Language.FSharp => $"#r @\"{dll}\""
            };

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

            await kernel.SendAsync(new RequestCompletions("Newtonsoft.Json.JsonConvert.", new LinePosition(0, 28)));

            KernelEvents.Single(e => e is CompletionsProduced)
            .As <CompletionsProduced>()
            .Completions
            .Should()
            .Contain(i => i.DisplayText == "SerializeObject");
        }
예제 #6
0
        public async Task it_produces_a_final_value_if_the_code_expression_evaluates()
        {
            var kernel = CreateKernel();

            var kernelCommand = new SubmitCode(@"
Console.Write(""value one"");
Console.Write(""value two"");
Console.Write(""value three"");
5");
            await kernel.SendAsync(kernelCommand);

            KernelEvents.ValuesOnly()
            .OfType <DisplayedValueProduced>()
            .Should()
            .HaveCount(3);

            KernelEvents
            .ValuesOnly()
            .OfType <ReturnValueProduced>()
            .Last()
            .Value.Should().Be(5);
        }
예제 #7
0
        public async Task Value_display_and_update_are_in_right_order(Language language)
        {
            var kernel = CreateKernel(language);

            var submission = language switch
            {
                Language.CSharp => "var d = display(b(\"hello\")); d.Update(b(\"world\"));",
                Language.FSharp => "let d = display(b.innerHTML(\"hello\"))\nd.Update(b.innerHTML(\"world\"))",
            };

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

            var valueEvents =
                KernelEvents
                .OrderBy(e => e.Timestamp)
                .Where(e => e.Value is DisplayedValueProduced || e.Value is DisplayedValueUpdated)
                .Select(e => e.Value)
                .ToList();

            valueEvents.First().Should().BeOfType <DisplayedValueProduced>();
            valueEvents.Last().Should().BeOfType <DisplayedValueUpdated>();
        }
예제 #8
0
        public async Task diagnostics_can_be_produced_from_multiple_subkernels()
        {
            var kernel = CreateCompositeKernel(Language.FSharp);

            var code = @"
#!fsharp
printfnnn """"

#!csharp
Console.WriteLin();
";

            await SubmitCode(kernel, code);

            KernelEvents
            .OfType <DiagnosticsProduced>()
            .SelectMany(dp => dp.Diagnostics)
            .Should()
            .ContainSingle(d => d.Code.StartsWith("CS"))
            .And
            .ContainSingle(d => d.Code.StartsWith("FS"));
        }
예제 #9
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");
        }
예제 #10
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 => !string.IsNullOrEmpty(ci.Documentation) && ci.Documentation.Contains("Represents JavaScript's null as a string. This field is read-only."));
        }
        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}"));
        }
예제 #12
0
        public async Task Display_helper_can_be_called_without_specifying_class_name(Language language)
        {
            var kernel = CreateKernel(language);

            var submission = language switch
            {
                Language.CSharp => "display(b(\"hi!\"));",
                Language.FSharp => "display(b.innerHTML(\"hi!\"));",
            };

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

            var formatted =
                KernelEvents
                .OfType <DisplayedValueProduced>()
                .SelectMany(v => v.FormattedValues);

            formatted
            .Should()
            .ContainSingle(v =>
                           v.MimeType == "text/html" &&
                           v.Value.ToString().Contains("<b>hi!</b>"));
        }
예제 #13
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);
        }
예제 #14
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);
        }
예제 #15
0
        public async Task Displayed_value_can_be_updated()
        {
            var kernel = CreateKernel();

            await kernel.SendAsync(new SubmitCode("var d = display(b(\"hello\")); d.Update(b(\"world\"));"));

            var formatted =
                KernelEvents
                .OrderBy(e => e.Timestamp)
                .ValuesOnly()
                .OfType <ValueProduced>()
                .SelectMany(v => v.FormattedValues);

            formatted
            .Should()
            .ContainSingle(v =>
                           v.MimeType == "text/html" &&
                           v.Value.ToString().Contains("<b>hello</b>"))
            .And
            .ContainSingle(v =>
                           v.MimeType == "text/html" &&
                           v.Value.ToString().Contains("<b>world</b>"));
        }
예제 #16
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);
        }
예제 #17
0
        public async Task it_returns_diagnostics(Language language)
        {
            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 error = language switch
            {
                Language.FSharp => "input.fsx (1,1)-(1,7) typecheck error The value or constructor 'aaaadd' is not defined.",
                Language.CSharp => "(1,1): error CS0103: The name 'aaaadd' does not exist in the current context",
            };

            KernelEvents
            .Where(x => x.GetType() != typeof(KernelIdle) && x.GetType() != typeof(KernelBusy))
            .Last()
            .Should()
            .BeOfType <CommandFailed>()
            .Which
            .Message
            .Should()
            .Be(error);
        }
예제 #18
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!")));
        }
예제 #20
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);
        }
    }
예제 #21
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");
        }
예제 #22
0
        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);
        }
예제 #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 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)
                               ));
        }
예제 #25
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);
        }
예제 #26
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>();
        }
예제 #27
0
 private void ListenForPackagesToScanForExtensions() =>
 RegisterForDisposal(KernelEvents
                     .OfType <PackageAdded>()
                     .Where(pa => pa?.PackageReference.PackageRoot != null)
                     .Distinct(pa => pa.PackageReference.PackageRoot)
                     .Subscribe(added => _packagesToCheckForExtensions.Enqueue(added)));
예제 #28
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);
        }