public async Task <IActionResult> SignatureHelp( [FromBody] WorkspaceRequest request, [FromHeader(Name = "Timeout")] string timeoutInMilliseconds = "15000") { if (Debugger.IsAttached && !(Clock.Current is VirtualClock)) { _disposables.Add(VirtualClock.Start()); } using (var operation = Log.OnEnterAndConfirmOnExit()) { operation.Info("Processing workspaceType {workspaceType}", request.Workspace.WorkspaceType); if (!int.TryParse(timeoutInMilliseconds, out var timeoutMs)) { return(BadRequest()); } var runTimeout = TimeSpan.FromMilliseconds(timeoutMs); var budget = new TimeBudget(runTimeout); var server = GetServerForWorkspace(request.Workspace); var result = await server.GetSignatureHelp(request, budget); budget.RecordEntry(); operation.Succeed(); return(Ok(result)); } }
private async Task WarmUpRoutes() { using (var operation = Log.OnEnterAndExit()) { await WarmUpRoute("/workspace/run"); await WarmUpRoute("/workspace/completion"); await WarmUpRoute("/workspace/diagnostics"); await WarmUpRoute("/workspace/signaturehelp"); async Task WarmUpRoute(string relativeUri) { const string code = "Console.WriteLine(42);"; var workspaceRequest = new WorkspaceRequest( activeBufferId: "Program.cs", workspace: new Workspace( workspaceType: "console", buffers: new[] { new Buffer("Program.cs", code, 0) })); var response = await Post(relativeUri, workspaceRequest); operation.Info("WarmUp response from {relativeUri} {response}", relativeUri, response); } } }
public async Task When_Run_times_out_in_user_code_then_the_response_code_is_417( string workspaceType, string code) { await Default.ConsoleWorkspace(); Clock.Reset(); Workspace workspace = null; if (workspaceType == "script") { workspace = Workspace.FromSource(code, "script"); } else { var package = Create.EmptyWorkspace(); var build = await Create.NewPackage(package.Name, package.Directory, Create.ConsoleConfiguration); workspace = Workspace.FromSource(code, build.Name); } var requestJson = new WorkspaceRequest(workspace).ToJson(); var response = await CallRun(requestJson, 10000); Log.Info("{response}", await response.Content.ReadAsStringAsync()); response.StatusCode.Should().Be(HttpStatusCode.ExpectationFailed); }
public async Task Can_get_signatureHelp_for_workspace_with_buffers() { var container = @"class A { #region nesting #endregion void Operation() { var instance = new C(); } }"; var markup = @"class C { public void Foo() { Foo($$ } }"; var(processed, markLocation) = CodeManipulation.ProcessMarkup(markup); var ws = new Workspace( files: new[] { new File("program.cs", container.EnforceLF()) }, buffers: new[] { new Buffer("program.cs@nesting", processed, markLocation) }); var request = new WorkspaceRequest(ws, activeBufferId: "program.cs@nesting"); var server = GetLanguageService(); var result = await server.GetSignatureHelp(request); result.Signatures.Should().NotBeEmpty(); result.Signatures.First().Label.Should().Be("void C.Foo()"); }
public async Task A_script_snippet_workspace_can_be_used_to_get_completions() { var(processed, position) = WorkspaceServer.Tests.CodeManipulation.ProcessMarkup("Console.$$"); using (var agent = new AgentService()) { var json = new WorkspaceRequest( requestId: "TestRun", activeBufferId: "default.cs", workspace: Workspace.FromSource( processed, "script", id: "default.cs", position: position)) .ToJson(); var request = new HttpRequestMessage( HttpMethod.Post, @"/workspace/completion") { Content = new StringContent( json, Encoding.UTF8, "application/json") }; var response = await agent.SendAsync(request); var result = await response .EnsureSuccess() .DeserializeAs <CompletionResult>(); result.Items.Should().ContainSingle(item => item.DisplayText == "WriteLine"); } }
public async Task When_aspnet_webapi_workspace_request_succeeds_then_output_shows_web_response() { var workspace = new Workspace(workspaceType: "aspnet.webapi", buffers: new[] { new Buffer("empty.cs", "") }); var request = new WorkspaceRequest(workspace, httpRequest: new HttpRequest("/api/values", "get"), requestId: "TestRun"); var json = request.ToJson(); var response = await CallRun(json); var result = await response .EnsureSuccess() .DeserializeAs <RunResult>(); Log.Info("output: {x}", result.Output); result.ShouldSucceedWithOutput( "Status code: 200 OK", "Content headers:", " Date:*", // the order of these two varies for some reason " *", // e.g. Transfer-Encoding: chunked " *", // e.g. Server: Kestrel " Content-Type: application/json; charset=utf-8", "Content:", "[", " \"value1\",", " \"value2\"", "]"); }
public HistoryRequest(WorkspaceRequest request, DateTime lastUsed) { this.LastUsedDate = lastUsed; this.Name = request.Name; this.MethodIndex = request.MethodIndex; this.BaseUrl = request.BaseUrl; this.Body = request.Body.DeepClone() as RequestBody; this.Authentication = request.Authentication.DeepClone() as Authentication; this.Status = ModifiedStatus.New; foreach (Parameter p in request.Queries) { this.Queries.Add(p.DeepClone() as Parameter); } foreach (Parameter h in request.Headers) { this.Headers.Add(h.DeepClone() as Parameter); } foreach (ApiTest t in request.ApiTests) { this.ApiTests.Add(t.DeepClone() as ApiTest); } foreach (Parameter chainingRule in request.ChainingRules) { this.ChainingRules.Add(chainingRule.DeepClone() as Parameter); } }
public async Task The_Run_contract_for_noncompiling_code_has_not_been_broken() { await EnsureConsoleWorkspaceCreated(); var viewport = ViewportCode("doesn't compile"); var request = new WorkspaceRequest( new Workspace( workspaceType: "console", buffers: new[] { EntrypointCode(), viewport }), activeBufferId: viewport.Id, requestId: "TestRun"); var requestBody = request.ToJson(); var response = await CallRun(requestBody); var result = await response.Content.ReadAsStringAsync(); this.Assent(RemoveMachineSpecificPaths(result).FormatJson(), configuration); }
public async Task Get_autocompletion_for_console_methods() { #region bufferSources var program = @"using System; using System.Linq; namespace FibonacciTest { public class Program { public static void Main() { foreach (var i in FibonacciGenerator.Fibonacci().Take(20)) { Console.WriteLine(i); } } } }".EnforceLF(); var generator = @"using System.Collections.Generic; using System; namespace FibonacciTest { public static class FibonacciGenerator { public static IEnumerable<int> Fibonacci() { int current = 1, next = 1; while (true) { yield return current; next = current + (current = next); Console.$$ } } } }".EnforceLF(); #endregion var(processed, position) = CodeManipulation.ProcessMarkup(generator); var workspace = new Workspace(workspaceType: "console", buffers: new[] { new Buffer("Program.cs", program.EnforceLF()), new Buffer("generators/FibonacciGenerator.cs", processed, position) }); var request = new WorkspaceRequest(workspace, activeBufferId: "generators/FibonacciGenerator.cs"); var server = GetLanguageService(); var result = await server.GetCompletionList(request); result.Items.Should().NotBeNullOrEmpty(); result.Items.Should().NotContain(signature => string.IsNullOrEmpty(signature.Kind)); result.Items.Should().Contain(completion => completion.SortText == "Beep"); var hasDuplicatedEntries = HasDuplicatedCompletionItems(result); hasDuplicatedEntries.Should().BeFalse(); }
public async Task The_Compile_contract_for_compiling_code_has_not_been_broken() { var viewport = ViewportCode(); var requestJson = new WorkspaceRequest( new Workspace( workspaceType: "console", buffers: new[] { EntrypointCode(), viewport }), activeBufferId: viewport.Id, requestId: "TestRun"); var response = await CallCompile(requestJson.ToJson()); var result = await response.Content.ReadAsStringAsync(); var compileResult = result.FromJsonTo <CompileResult>(); compileResult.Base64Assembly.Should().NotBeNullOrWhiteSpace(); compileResult = new CompileResult( compileResult.Succeeded, "", compileResult.GetFeature <Diagnostics>(), compileResult.RequestId); result = compileResult.ToJson().FormatJson(); this.Assent(result, configuration); }
public async Task <DiagnosticResult> GetDiagnostics(WorkspaceRequest request, Budget budget) { budget ??= new TimeBudget(TimeSpan.FromSeconds(defaultBudgetInSeconds)); var package = await _packageFinder.Find <ICreateWorkspace>(request.Workspace.WorkspaceType); var workspace = await request.Workspace.InlineBuffersAsync(); var sourceFiles = workspace.GetSourceFiles(); var(_, documents) = await package.GetCompilationForLanguageServices(sourceFiles, GetSourceCodeKind(request), GetUsings(request.Workspace), budget); var selectedDocument = documents.FirstOrDefault(doc => doc.IsMatch(request.ActiveBufferId.FileName)) ?? (documents.Count == 1 ? documents.Single() : null); if (selectedDocument == null) { return(new DiagnosticResult(requestId: request.RequestId)); } var diagnostics = await DiagnosticsExtractor.ExtractSerializableDiagnosticsFromDocument(request.ActiveBufferId, budget, selectedDocument, workspace); var result = new DiagnosticResult(diagnostics, request.RequestId); return(result); }
public async Task <CompletionResult> GetCompletionList(WorkspaceRequest request, Budget budget) { budget ??= new TimeBudget(TimeSpan.FromSeconds(defaultBudgetInSeconds)); var package = await _packageFinder.Find <ICreateWorkspace>(request.Workspace.WorkspaceType); var workspace = await request.Workspace.InlineBuffersAsync(); var sourceFiles = workspace.GetSourceFiles(); var(_, documents) = await package.GetCompilationForLanguageServices( sourceFiles, GetSourceCodeKind(request), GetUsings(request.Workspace), budget); var file = workspace.GetFileFromBufferId(request.ActiveBufferId); var(_, _, absolutePosition) = workspace.GetTextLocation(request.ActiveBufferId); var selectedDocument = documents.First(doc => doc.IsMatch(file)); var service = CompletionService.GetService(selectedDocument); var completionList = await service.GetCompletionsAsync(selectedDocument, absolutePosition); var semanticModel = await selectedDocument.GetSemanticModelAsync(); var diagnostics = DiagnosticsExtractor.ExtractSerializableDiagnosticsFromSemanticModel(request.ActiveBufferId, budget, semanticModel, workspace); var symbols = await Recommender.GetRecommendedSymbolsAtPositionAsync( semanticModel, absolutePosition, selectedDocument.Project.Solution.Workspace); var symbolToSymbolKey = new Dictionary <(string, int), ISymbol>(); foreach (var symbol in symbols) { var key = (symbol.Name, (int)symbol.Kind); if (!symbolToSymbolKey.ContainsKey(key)) { symbolToSymbolKey[key] = symbol; } } if (completionList == null) { return(new CompletionResult(requestId: request.RequestId, diagnostics: diagnostics)); } var completionItems = completionList.Items .Where(i => i != null) .Select(item => item.ToModel(symbolToSymbolKey, selectedDocument)); return(new CompletionResult(completionItems .Deduplicate() .ToArray(), requestId: request.RequestId, diagnostics: diagnostics)); }
public async Task Project_file_path_workspace_can_be_discovered_and_run_with_buffer_inlining() { var package = Create.EmptyWorkspace("a space"); var build = await Create.NewPackage(package.Name, package.Directory, Create.ConsoleConfiguration) as IHaveADirectory; var workspace = build.Directory; var csproj = workspace.GetFiles("*.csproj")[0]; var programCs = workspace.GetFiles("*.cs")[0]; var output = Guid.NewGuid().ToString(); var ws = new Workspace( files: new[] { new File(programCs.FullName, SourceCodeProvider.ConsoleProgramSingleRegion) }, buffers: new[] { new Buffer(new BufferId(programCs.FullName, "alpha"), $"Console.WriteLine(\"{output}\");") }, workspaceType: csproj.FullName); var requestJson = new WorkspaceRequest(ws, requestId: "TestRun").ToJson(); var response = await CallRun(requestJson); var result = await response .EnsureSuccess() .DeserializeAs <RunResult>(); result.ShouldSucceedWithOutput(output); }
/// <summary> /// Creates new workspace. /// </summary> public Task <IRestResponse <WorkspaceDto> > CreateWorkspaceAsync(WorkspaceRequest workspaceRequest) { var request = new RestRequest("workspaces", Method.POST); request.AddJsonBody(workspaceRequest); return(_client.ExecutePostTaskAsync <WorkspaceDto>(request)); }
public async Task <IActionResult> Compile( [FromBody] WorkspaceRequest request, [FromHeader(Name = "Timeout")] string timeoutInMilliseconds = "45000") { using (var operation = Log.OnEnterAndConfirmOnExit()) { var workspaceType = request.Workspace.WorkspaceType; operation.Info("Compiling workspaceType {workspaceType}", workspaceType); if (!int.TryParse(timeoutInMilliseconds, out var timeoutMs)) { return(BadRequest()); } if (string.Equals(workspaceType, "script", StringComparison.OrdinalIgnoreCase)) { return(BadRequest()); } var runTimeout = TimeSpan.FromMilliseconds(timeoutMs); var budget = new TimeBudget(runTimeout); var result = await _workspaceServer.Compile(request, budget); budget.RecordEntry(); operation.Succeed(); return(Ok(result)); } }
public async Task When_diagnostics_are_outside_of_active_file_then_they_are_omitted() { #region bufferSources const string program = @" using System; using System.Linq; namespace FibonacciTest { public class Program { public static void Main() { foreach (var i in FibonacciGenerator.Fibonacci().Take(20)) { Console.WriteLine(i); } } } }"; const string generator = @" using Newtonsoft.Json; using System.Collections.Generic; namespace FibonacciTest { public static class FibonacciGenerator { public static IEnumerable<int> Fibonacci() { int current = 1, next = 1; while (true) { yield return current; next = current + (current = next); } } } }"; #endregion var server = GetCodeRunner(); var request = new WorkspaceRequest( new Workspace( workspaceType: "console", buffers: new[] { new Buffer("Program.cs", program, 0), new Buffer("FibonacciGenerator.cs", generator, 0) }, includeInstrumentation: true), new BufferId("Program.cs")); var result = await server.Run(request); result.GetFeature <Diagnostics>().Should().BeEmpty(); }
public async Task Get_diagnostics() { #region bufferSources var program = @"using System; using System.Linq; namespace FibonacciTest { public class Program { public static void Main() { foreach (var i in FibonacciGenerator.Fibonacci().Take(20)) { Console.WriteLine(i); } } } }".EnforceLF(); var generator = @"using System.Collections.Generic; using System; namespace FibonacciTest { public static class FibonacciGenerator { public static IEnumerable<int> Fibonacci() { int current = 1, next = 1; while (true) { yield return current; next = current + (current = next); adddd Console.WriteLine($$); } } } }".EnforceLF(); #endregion var(processed, position) = CodeManipulation.ProcessMarkup(generator); var workspace = new Workspace(workspaceType: "console", buffers: new[] { new Buffer("Program.cs", program), new Buffer("generators/FibonacciGenerator.cs", processed, position) }); var request = new WorkspaceRequest(workspace, activeBufferId: "generators/FibonacciGenerator.cs"); var server = await GetLanguageServiceAsync(); var result = await server.GetDiagnostics(request); result.Diagnostics.Should().NotBeNullOrEmpty(); result.Diagnostics.Should().Contain(diagnostics => diagnostics.Message == "generators/FibonacciGenerator.cs(14,17): error CS0246: The type or namespace name \'adddd\' could not be found (are you missing a using directive or an assembly reference?)"); }
public async Task Response_with_multi_buffer_workspace_with_instrumentation() { #region bufferSources const string program = @"using System; using System.Linq; namespace FibonacciTest { public class Program { public static void Main() { foreach (var i in FibonacciGenerator.Fibonacci().Take(20)) { Console.WriteLine(i); } } } }"; const string generator = @"using System.Collections.Generic; namespace FibonacciTest { public static class FibonacciGenerator { public static IEnumerable<int> Fibonacci() { int current = 1, next = 1; while (true) { yield return current; next = current + (current = next); } } } }"; #endregion var server = GetCodeRunner(); var request = new WorkspaceRequest( new Workspace( workspaceType: "console", buffers: new[] { new Buffer("Program.cs", program, 0), new Buffer("FibonacciGenerator.cs", generator, 0) }, includeInstrumentation: true), new BufferId("Program.cs")); var result = await server.Run(request); result.Succeeded.Should().BeTrue(); result.Output.Count.Should().Be(21); result.Output.Should().BeEquivalentTo("1", "1", "2", "3", "5", "8", "13", "21", "34", "55", "89", "144", "233", "377", "610", "987", "1597", "2584", "4181", "6765", ""); }
public async Task Get_signature_help_for_invalid_location_return_empty() { #region bufferSources var program = @"using System; using System.Linq; namespace FibonacciTest { public class Program { public static void Main() { foreach (var i in FibonacciGenerator.Fibonacci().Take(20)) { Console.WriteLine(i); } } } }".EnforceLF(); var generator = @"using System.Collections.Generic; using System; namespace FibonacciTest { public static class FibonacciGenerator { public static IEnumerable<int> Fibonacci() { int current = 1, next = 1; while (true) { yield return current; next = current + (current = next); Console.WriteLine();$$ } } } }".EnforceLF(); #endregion var(processed, position) = CodeManipulation.ProcessMarkup(generator); var workspace = new Workspace(workspaceType: "console", buffers: new[] { new Buffer("Program.cs", program), new Buffer("generators/FibonacciGenerator.cs", processed, position) }); var request = new WorkspaceRequest(workspace, activeBufferId: "generators/FibonacciGenerator.cs"); var server = await GetLanguageServiceAsync(); var result = await server.GetSignatureHelp(request); result.Should().NotBeNull(); result.Signatures.Should().BeNullOrEmpty(); }
public async Task When_Run_times_out_in_script_workspace_server_code_then_the_response_code_is_504(string code) { var workspace = Workspace.FromSource(code.EnforceLF(), "script"); var requestJson = new WorkspaceRequest(workspace).ToJson(); var response = await CallRun(requestJson, timeoutMs : 1); response.StatusCode.Should().Be(HttpStatusCode.GatewayTimeout); }
public async Task Can_show_completions() { var(processed, markLocation) = CodeManipulation.ProcessMarkup("var xa = 3;\n$$a"); var ws = new Workspace(buffers: new[] { new Buffer("default.cs", processed, markLocation) }); var request = new WorkspaceRequest(ws, activeBufferId: "default.cs"); var server = GetLanguageService(); var result = await server.GetCompletionList(request); result.Items.Should().NotBeNullOrEmpty(); result.Items.Should().Contain(i => i.DisplayText == "xa"); }
public void When_ActiveBufferId_is_not_specified_and_there_is_only_one_buffer_then_it_returns_that_buffers_id() { var request = new WorkspaceRequest( new Workspace( buffers: new[] { new Buffer("the.only.buffer.cs", "its content", 123) }), requestId: "TestRun"); request.ActiveBufferId.Should().Be(BufferId.Parse("the.only.buffer.cs")); }
public async Task Get_completion_for_console() { var ws = new Workspace(workspaceType: "script", buffers: new[] { new Buffer("program.cs", "Console.", 8) }); var request = new WorkspaceRequest(ws, activeBufferId: "program.cs"); var server = GetLanguageService(); var result = await server.GetCompletionList(request); result.Items.Should().ContainSingle(item => item.DisplayText == "WriteLine"); }
public async Task <CompileResult> Compile(WorkspaceRequest request, Budget budget = null) { var workspace = request.Workspace; var package = await _packageFinder.Find <Package>(workspace.WorkspaceType); var(packageWithChanges, compileResult) = await Compile(package, workspace, request.RequestId); using (packageWithChanges) { return(compileResult); } }
public async Task Can_show_KeyValuePair_because_it_uses_the_right_reference_assemblies() { var(processed, markLocation) = CodeManipulation.ProcessMarkup("System.Collections.Generic.$$"); var ws = new Workspace(buffers: new[] { new Buffer("default.cs", processed, markLocation) }); var request = new WorkspaceRequest(ws, activeBufferId: "default.cs"); var server = GetLanguageService(); var result = await server.GetCompletionList(request); result.Items.Should().NotBeNullOrEmpty(); result.Items.Should().Contain(i => i.DisplayText == "KeyValuePair"); }
public async Task <DiagnosticResult> GetDiagnostics(WorkspaceRequest request, Budget budget = null) { //var workspace = request.Workspace; //var package = await _packageFinder.Find<Package>(workspace.WorkspaceType); //workspace = await _transformer.TransformAsync(workspace); //var packageWithChanges = await CreatePackageWithChanges(package, workspace); //var packageFiles = packageWithChanges.GetFiles(); //var diagnostics = await Shim.GetDiagnostics(packageWithChanges.Name, packageFiles, packageWithChanges.Directory.FullName, package.Directory.FullName); //var serializableDiagnostics = workspace.MapDiagnostics(request.ActiveBufferId, diagnostics, budget).DiagnosticsInActiveBuffer; //return new DiagnosticResult(serializableDiagnostics, request.RequestId); throw new NotImplementedException(); }
public async Task Get_signature_help_for_console_writeline() { var ws = new Workspace(workspaceType: "script", buffers: new[] { new Buffer("program.cs", "Console.WriteLine()", 18) }); var request = new WorkspaceRequest(ws, activeBufferId: "program.cs"); var server = GetLanguageService(); var result = await server.GetSignatureHelp(request); result.Signatures.Should().NotBeNullOrEmpty(); result.Signatures.Should().Contain(signature => signature.Label == "void Console.WriteLine(string format, params object[] arg)"); }
public async Task <RunResult> Run(WorkspaceRequest request, Budget budget = null) { var workspace = request.Workspace; budget = budget ?? new TimeBudget(TimeSpan.FromSeconds(defaultBudgetInSeconds)); using (Log.OnEnterAndExit()) using (await locks.GetOrAdd(workspace.WorkspaceType, s => new AsyncLock()).LockAsync()) { var package = await _packageFinder.Find <Package>(workspace.WorkspaceType); var result = await CompileWorker(request.Workspace, request.ActiveBufferId, budget); if (result.ProjectDiagnostics.ContainsError()) { var errorMessagesToDisplayInOutput = result.DiagnosticsWithinBuffers.Any() ? result.DiagnosticsWithinBuffers.GetCompileErrorMessages() : result.ProjectDiagnostics.GetCompileErrorMessages(); var runResult = new RunResult( false, errorMessagesToDisplayInOutput, diagnostics: result.DiagnosticsWithinBuffers, requestId: request.RequestId); runResult.AddFeature(new ProjectDiagnostics(result.ProjectDiagnostics)); return(runResult); } await EmitCompilationAsync(result.Compilation, package); if (package.IsWebProject) { return(RunWebRequest(package, request.RequestId)); } if (package.IsUnitTestProject) { return(await RunUnitTestsAsync(package, result.DiagnosticsWithinBuffers, budget, request.RequestId)); } return(await RunConsoleAsync( package, result.DiagnosticsWithinBuffers, budget, request.RequestId, workspace.IncludeInstrumentation, request.RunArgs)); } }
public async Task Can_show_all_completion_properties_for_Class_Task() { var ws = new Workspace(buffers: new[] { new Buffer("default.cs", "System.Threading.Tasks.", 23) }); var request = new WorkspaceRequest(ws, activeBufferId: "default.cs"); var server = GetLanguageService(); var result = await server.GetCompletionList(request); var taskCompletionItem = result.Items.First(i => i.DisplayText == "Task"); taskCompletionItem.DisplayText.Should().Be("Task"); taskCompletionItem.FilterText.Should().Be("Task"); taskCompletionItem.Kind.Should().Be("Class"); taskCompletionItem.SortText.Should().Be("Task"); }
public async Task When_Run_times_out_in_console_workspace_server_code_then_the_response_code_is_504() { await Default.ConsoleWorkspace(); var code = @"public class Program { public static void Main() { Console.WriteLine(); } }"; var workspace = Workspace.FromSource(code.EnforceLF(), "console"); var requestJson = new WorkspaceRequest(workspace).ToJson(); var response = await CallRun(requestJson, timeoutMs : 1); response.StatusCode.Should().Be(HttpStatusCode.GatewayTimeout); }