public async Task csharp_signature_help_contains_doc_comments_from_individually_referenced_assemblies_with_xml_files() { using var assembly = new TestAssemblyReference("Project", "netstandard2.0", "Program.cs", @" public class SampleClass { /// <summary>A sample class constructor.</summary> public SampleClass() { } } "); var assemblyPath = await assembly.BuildAndGetPathToAssembly(); using var kernel = CreateKernel(Language.CSharp); await SubmitCode(kernel, $"#r \"{assemblyPath}\""); var markupCode = "new SampleClass($$"; 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() .ContainSingle(sh => sh.Documentation.Value.Contains("A sample class constructor.")); }
public async Task signature_help_can_return_doc_comments_from_source(Language language, string submittedCode, string markupCode, int activeSignature, string expectedMethodDocumentation) { 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 .Subject .Should() .ContainSingle() .Which .Documentation.Value .Should() .Be(expectedMethodDocumentation); }
public async Task hover_text_can_read_doc_comments_from_individually_referenced_assemblies_with_xml_files(Language language, string markupCode) { using var assembly = new TestAssemblyReference("Project", "netstandard2.0", "Program.cs", @" public class SampleClass { /// <summary>A sample class constructor.</summary> public SampleClass() { } } "); var assemblyPath = await assembly.BuildAndGetPathToAssembly(); var assemblyReferencePath = language switch { Language.CSharp => assemblyPath, Language.FSharp => assemblyPath.Replace("\\", "\\\\") }; using var kernel = CreateKernel(language); await SubmitCode(kernel, $"#r \"{assemblyReferencePath}\""); MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character); var commandResult = await SendHoverRequest(kernel, code, line, character); var events = commandResult.KernelEvents.ToSubscribedList(); events .Should() .ContainSingle <HoverTextProduced>() .Which .Content .Should() .ContainSingle(fv => fv.Value.Contains("A sample class constructor.")); }
public async Task fast_path_commands_over_proxy_can_be_handled() { var connector = new StdIoKernelConnector(new[] { Dotnet.Path.FullName, typeof(App.Program).Assembly.Location, "stdio", "--default-kernel", "csharp", }); using var kernel = await connector.ConnectKernelAsync(new KernelInfo ("proxy")); var markedCode = "var x = 12$$34;"; MarkupTestFile.GetLineAndColumn(markedCode, out var code, out var line, out var column); var result = await kernel.SendAsync(new RequestHoverText(code, new LinePosition(line, column))); var events = result.KernelEvents.ToSubscribedList(); events .Should() .EventuallyContainSingle <HoverTextProduced>(); }
public async Task produced_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 SubmitCode(kernel, code); KernelEvents .Should() .ContainSingle <DiagnosticsProduced>(d => d.Diagnostics.Count > 0) .Which .Diagnostics .Should() .ContainSingle() .Which .LinePositionSpan.Start.Line .Should() .Be(line); }
public async Task CompletionsProduced_is_returned_when_a_region_is_set() { var kernel = new CSharpProjectKernel("csharp"); await kernel.SendAsync(new OpenProject(new Project(new[] { new ProjectFile("Program.cs", @" public class Program { public static void Main(string[] args) { var fileInfo = new System.IO.FileInfo(""test.file""); #region TEST_REGION #endregion } } ") }))); await kernel.SendAsync(new OpenDocument("Program.cs", regionName : "TEST_REGION")); var markedCode = @"fileInfo.$$"; MarkupTestFile.GetLineAndColumn(markedCode, out var code, out var line, out var character); var result = await kernel.SendAsync(new RequestCompletions(code, new LinePosition(line, character))); var kernelEvents = result.KernelEvents.ToSubscribedList(); kernelEvents .Should() .ContainSingle <CompletionsProduced>() .Which .Completions .Should() .Contain(ci => ci.DisplayText == "AppendText"); }
public async Task requested_diagnostics_does_not_execute_directives_handlers(Language language, string languageSpecificCode) { var kernel = CreateKernel(language); var handlerInvoked = false; kernel.AddDirective(new Command("#!custom") { Handler = CommandHandler.Create(() => { handlerInvoked = true; }) }); var fullCode = $@" #!time #!custom $${languageSpecificCode} "; MarkupTestFile.GetLineAndColumn(fullCode, out var code, out var line, out var _column); await kernel.SendAsync(new RequestDiagnostics(code)); handlerInvoked .Should() .BeFalse(); }
public async Task completion_commands_have_offsets_normalized_after_switching_to_the_same_language(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); var completionCode = string.Join("\r\n", new[] { "", // blank line to force offsets to be wrong $"#!{language.LanguageName()}", "aaa$$" }); MarkupTestFile.GetLineAndColumn(completionCode, out var output, out var line, out var column); await kernel.SendAsync(new RequestCompletions(output, new LinePosition(line, column))); KernelEvents .Should() .ContainSingle <CompletionsProduced>() .Which .Completions .Should() .Contain(item => item.DisplayText == variableName); }
public async Task completion_contains_doc_comments_from_individually_referenced_assemblies_with_xml_files(Language language) { using var assembly = new TestAssemblyReference("Project", "netstandard2.0", "Program.cs", @" public class C { /// <summary>This is the answer.</summary> public static int TheAnswer => 42; } "); var assemblyPath = await assembly.BuildAndGetPathToAssembly(); var assemblyReferencePath = language switch { Language.CSharp => assemblyPath, Language.FSharp => assemblyPath.Replace("\\", "\\\\") }; using var kernel = CreateKernel(language); await SubmitCode(kernel, $"#r \"{assemblyReferencePath}\""); var markupCode = "C.TheAns$$"; 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("This is the answer.")); }
public async Task signature_help_can_return_doc_comments_from_bcl_types(Language language, string markupCode, int activeSignature, string expectedDocumentationSubstring) { using var kernel = CreateKernel(language); 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() .HaveCountGreaterThan(activeSignature) .And .Subject .LastOrDefault() .Should() .NotBeNull() .And .Subject .As <SignatureInformation>() .Documentation.Value .Should() .Contain(expectedDocumentationSubstring); }
public async Task invalid_hover_request_returns_no_result(Language language, string markupCode) { using var kernel = CreateKernel(language); MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character); var commandResult = await SendHoverRequest(kernel, code, line, character); commandResult .KernelEvents .ToSubscribedList() .Should() .NotContain(kv => kv.GetType().IsSubclassOf(typeof(HoverTextProduced))); }
public async Task hover_request_over_comments_succeeds(Language language, string markupCode) { using var kernel = CreateKernel(language); MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character); var commandResult = await SendHoverRequest(kernel, code, line, character); var events = commandResult .KernelEvents .ToSubscribedList(); events .Should() .ContainSingle <CommandSucceeded>(); }
public async Task completion_doc_comments_can_be_loaded_from_bcl_types(Language language, string markupCode, string expectedCompletionSubstring) { using var kernel = CreateKernel(language); 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(expectedCompletionSubstring)); }
public async Task unimplemented_lsp_handlers_return_404(Language language, string markupCode) { // something that's a valid LSP method, just not for the given kernel var methodName = "textDocument/hover"; MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character); var request = new HoverParams( TextDocument.FromDocumentContents(code), new Lsp.Position(line, character)); var response = await GetServer(language).HttpClient.PostObjectAsJsonAsync($"/lsp/{methodName}", request); response.StatusCode.Should().Be(HttpStatusCode.NotFound); var content = await response.Content.ReadAsStringAsync(); content.Should().StartWith($"method '{methodName}' not found on kernel '{language.LanguageName()}'"); }
public async Task completion_doc_comments_can_be_loaded_from_source_in_a_previous_submission(Language language, string previousSubmission, string markupCode, string expectedCompletionSubString) { using var kernel = CreateKernel(language); await SubmitCode(kernel, previousSubmission); 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(expectedCompletionSubString)); }
public async Task hover_request_returns_expected_result(Language language, string markupCode, string expectedMimeType, string expectedContent) { using var kernel = CreateKernel(language); MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character); var commandResult = await SendHoverRequest(kernel, code, line, character); commandResult .KernelEvents .ToSubscribedList() .Should() .ContainSingle <HoverTextProduced>() .Which .Content .Should() .ContainEquivalentOf(new FormattedValue(expectedMimeType, expectedContent)); }
public async Task RequestCompletions_before_OpenProject_fails() { var markedCode = @"in$$t x = 1;"; MarkupTestFile.GetLineAndColumn(markedCode, out var code, out var line, out var character); var kernel = new CSharpProjectKernel("csharp"); var result = await kernel.SendAsync(new RequestCompletions(code, new LinePosition(line, character))); var kernelEvents = result.KernelEvents.ToSubscribedList(); kernelEvents .Should() .ContainSingle <CommandFailed>() .Which .Message .Should() .Contain($"Project must be opened, send the command '{nameof(OpenProject)}' first"); }
public async Task csharp_hover_text_is_returned_for_shadowing_variables(Language language) { SubmitCode declaration = null; SubmitCode shadowingDeclaration = null; using var kernel = CreateKernel(language); string expected = ""; switch (language) { case Language.CSharp: declaration = new SubmitCode("var identifier = 1234;"); shadowingDeclaration = new SubmitCode("var identifier = \"one-two-three-four\";"); expected = "(field) string identifier"; break; case Language.FSharp: declaration = new SubmitCode("let identifier = 1234"); shadowingDeclaration = new SubmitCode("let identifier = \"one-two-three-four\""); expected = "```fsharp\nval identifier : string\n```\n\n----\n*Full name: identifier*"; break; } await kernel.SendAsync(declaration); await kernel.SendAsync(shadowingDeclaration); var markupCode = "ident$$ifier"; MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var column); var commandResult = await SendHoverRequest(kernel, code, line, column); commandResult .KernelEvents .ToSubscribedList() .Should() .ContainSingle <HoverTextProduced>() .Which .Content .Should() .ContainSingle(fv => fv.Value == expected); }
public async Task fsharp_completions_can_read_doc_comments_from_nuget_packages() { using var kernel = CreateKernel(Language.FSharp); await SubmitCode(kernel, "#r \"nuget: Newtonsoft.Json, 12.0.3\""); 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.")); }
public async Task hover_text_doc_comments_can_be_loaded_from_source_in_a_previous_submission(Language language, string previousSubmission, string markupCode, string expectedHoverTextSubString) { using var kernel = CreateKernel(language); await SubmitCode(kernel, previousSubmission); MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character); var commandResult = await SendHoverRequest(kernel, code, line, character); var events = commandResult.KernelEvents.ToSubscribedList(); events .Should() .ContainSingle <HoverTextProduced>() .Which .Content .Should() .ContainSingle(fv => fv.Value.Contains(expectedHoverTextSubString)); }
public async Task csharp_signature_help_can_read_doc_comments_from_nuget_packages() { using var kernel = CreateKernel(Language.CSharp); await SubmitCode(kernel, "#r \"nuget: Newtonsoft.Json, 12.0.3\""); 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.")); }
public async Task magic_command_completion_commands_and_events_have_offsets_normalized_when_the_submission_was_parsed_and_split() { using var kernel = CreateKernel(Language.CSharp); var fullMarkupCode = @" var x = 1; var y = x + 2; #!w$$ "; 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, 3))); }
public async Task language_service_methods_run_deferred_commands(Language language, string deferredCode, string markupCode, string expectedMimeType, string expectedContent) { // declare a variable in deferred code using var kernel = CreateKernel(language); kernel.DeferCommand(new SubmitCode(deferredCode)); // send the actual language service request that depends on the deferred code MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character); var commandResult = await SendHoverRequest(kernel, code, line, character); commandResult .KernelEvents .ToSubscribedList() .Should() .ContainSingle <HoverTextProduced>() .Which .Content .Should() .ContainEquivalentOf(new FormattedValue(expectedMimeType, expectedContent)); }
public async Task hover_text_doc_comments_can_be_loaded_from_bcl_types(Language language, string markupCode, string expectedHoverTextSubString) { using var kernel = CreateKernel(language); MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character); await SendHoverRequest(kernel, code, line, character); KernelEvents .Should() .ContainSingle <HoverTextProduced>() .Which .Content .Should() .ContainSingle() .Which .Value .Should() .Contain(expectedHoverTextSubString); }
public async Task FSharp_module_functions_are_returned_as_plain_text() { var kernel = CreateKernel(Language.FSharp); var markupCode = "[1;2;3] |> List.ma$$"; 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 == "map" && item.InsertText == "map" && item.InsertTextFormat == null); }
public async Task Non_generic_type_completions_are_returned_as_plain_text(Language language) { var kernel = CreateKernel(language); var markupCode = "System.Cons$$"; 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 == "Console" && item.InsertText == "Console" && item.InsertTextFormat == null); }
public async Task fsharp_hover_text_can_read_doc_comments_from_nuget_packages() { using var kernel = CreateKernel(Language.FSharp); await SubmitCode(kernel, "#r \"nuget: Newtonsoft.Json, 12.0.3\""); var markupCode = "Newtonsoft.Json.JsonConvert.Nu$$ll"; MarkupTestFile.GetLineAndColumn(markupCode, out var code, out var line, out var character); var commandResult = await SendHoverRequest(kernel, code, line, character); var events = commandResult.KernelEvents.ToSubscribedList(); events .Should() .ContainSingle <HoverTextProduced>() .Which .Content .Should() .ContainSingle(fv => fv.Value.Contains("Represents JavaScript's `null` as a string. This field is read-only.")); }
public async Task Method_completions_are_returned_as_a_snippet(Language language) { var kernel = CreateKernel(language); var markupCode = "Console.Wri$$"; 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 == "WriteLine" && item.InsertText == "WriteLine($1)" && item.InsertTextFormat == InsertTextFormat.Snippet); }
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"); }
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))); }