private async Task <(RedirectedPackage, CompileResult)> Compile(Package package, Workspace workspace, string requestId) { var packageWithChanges = await CreatePackageWithChanges(package, workspace); try { await package.FullBuild(); // ensure `package.EntryPointAssemblyPath.FullName` has a value await packageWithChanges.FullBuild(); // copy the entire output directory back await CopyDirectory( Path.GetDirectoryName(packageWithChanges.EntryPointAssemblyPath.FullName), Path.GetDirectoryName(package.EntryPointAssemblyPath.FullName)); return(packageWithChanges, new CompileResult( true, // succeeded Convert.ToBase64String(File.ReadAllBytes(package.EntryPointAssemblyPath.FullName)), diagnostics: null, requestId: requestId)); } catch (Exception e) { packageWithChanges.Clean(); return(null, new CompileResult( false, // succeeded string.Empty, // assembly base64 new SerializableDiagnostic[] { // TODO: populate with real compiler diagnostics new SerializableDiagnostic(0, 0, e.Message, DiagnosticSeverity.Error, "Compile error") }, requestId)); } }
public static async Task <Package> NetstandardWorkspaceCopy( [CallerMemberName] string testName = null, DirectoryInfo parentDirectory = null) => await Package.Copy( await Default.NetstandardWorkspace(), testName, parentDirectory : parentDirectory);
private static async Task EmitCompilationAsync(Compilation compilation, Package package) { if (package == null) { throw new ArgumentNullException(nameof(package)); } using (var operation = Log.OnEnterAndExit()) { var numberOfAttempts = 100; for (var attempt = 1; attempt < numberOfAttempts; attempt++) { try { compilation.Emit(package.EntryPointAssemblyPath.FullName); operation.Info("Emit succeeded on attempt #{attempt}", attempt); break; } catch (IOException) { if (attempt == numberOfAttempts - 1) { throw; } await Task.Delay(10); } } } }
private static RunResult RunWebRequest(Package package, string requestId) { var runResult = new RunResult(succeeded: true, requestId: requestId); runResult.AddFeature(new WebServer(package)); return(runResult); }
public static Package EmptyWorkspace([CallerMemberName] string testName = null, IPackageInitializer initializer = null, bool isRebuildablePackage = false) { if (!isRebuildablePackage) { return(new NonrebuildablePackage(directory: Package.CreateDirectory(testName), initializer: initializer)); } return(new RebuildablePackage(directory: Package.CreateDirectory(testName), initializer: initializer)); }
public async Task Workspaces_can_be_registered_to_be_created_using_dotnet_new() { var packageName = Package.CreateDirectory(nameof(Workspaces_can_be_registered_to_be_created_using_dotnet_new)).Name; registry.Add(packageName, options => options.CreateUsingDotnet("console")); var package = await registry.Get <ICreateWorkspaceForRun>(packageName); var workspace = await package.CreateRoslynWorkspaceForRunAsync(new TimeBudget(30.Seconds())); var project = workspace.CurrentSolution.Projects.First(); project.MetadataReferences.Count.Should().BeGreaterThan(0); }
public static async Task <(Compilation compilation, IReadOnlyCollection <Document> documents)> GetCompilation( this Package package, IReadOnlyCollection <SourceFile> sources, SourceCodeKind sourceCodeKind, IEnumerable <string> defaultUsings, Func <Task <Microsoft.CodeAnalysis.Workspace> > workspaceFactory, Budget budget) { var workspace = await workspaceFactory(); var currentSolution = workspace.CurrentSolution; var project = currentSolution.Projects.First(); var projectId = project.Id; foreach (var source in sources) { if (currentSolution.Projects .SelectMany(p => p.Documents) .FirstOrDefault(d => d.IsMatch(source)) is Document document) { // there's a pre-existing document, so overwrite its contents document = document.WithText(source.Text); document = document.WithSourceCodeKind(sourceCodeKind); currentSolution = document.Project.Solution; } else { var docId = DocumentId.CreateNewId(projectId, $"{package.Name}.Document"); currentSolution = currentSolution.AddDocument(docId, source.Name, source.Text); currentSolution = currentSolution.WithDocumentSourceCodeKind(docId, sourceCodeKind); } } project = currentSolution.GetProject(projectId); var usings = defaultUsings?.ToArray() ?? Array.Empty <string>(); if (usings.Length > 0) { var options = (CSharpCompilationOptions)project.CompilationOptions; project = project.WithCompilationOptions(options.WithUsings(usings)); } var compilation = await project.GetCompilationAsync().CancelIfExceeds(budget); return(compilation, project.Documents.ToArray()); }
private static async Task <RunResult> RunUnitTestsAsync( Package package, IEnumerable <SerializableDiagnostic> diagnostics, Budget budget, string requestId) { var dotnet = new Dotnet(package.Directory); var commandLineResult = await dotnet.VSTest( $@"--logger:trx ""{package.EntryPointAssemblyPath}""", budget); budget.RecordEntry(UserCodeCompleted); if (commandLineResult.ExitCode == 124) { throw new BudgetExceededException(budget); } var trex = new FileInfo( Path.Combine( Paths.DotnetToolsPath, "t-rex".ExecutableName())); if (!trex.Exists) { throw new InvalidOperationException($"t-rex not found in at location {trex}"); } var tRexResult = await CommandLine.Execute( trex, "", workingDir : package.Directory, budget : budget); var result = new RunResult( commandLineResult.ExitCode == 0, tRexResult.Output, diagnostics: diagnostics, requestId: requestId); result.AddFeature(new UnitTestRun(new[] { new UnitTestResult() })); return(result); }
public WebServer(IPackage package) { this.package = (Package)package ?? throw new ArgumentNullException(nameof(package)); _listeningAtUri = new AsyncLazy <Uri>(RunKestrel); _getHttpClient = new AsyncLazy <HttpClient>(async() => { var httpClient = new HttpClient { BaseAddress = await EnsureStarted() }; return(httpClient); }); }
private static async Task <RunResult> RunConsoleAsync( Package package, IEnumerable <SerializableDiagnostic> diagnostics, Budget budget, string requestId, bool includeInstrumentation, string commandLineArgs) { var dotnet = new Dotnet(package.Directory); var commandName = $@"""{package.EntryPointAssemblyPath.FullName}"""; var commandLineResult = await dotnet.Execute( commandName.AppendArgs(commandLineArgs), budget); budget.RecordEntry(UserCodeCompleted); var output = InstrumentedOutputExtractor.ExtractOutput(commandLineResult.Output); if (commandLineResult.ExitCode == 124) { throw new BudgetExceededException(budget); } string exceptionMessage = null; if (commandLineResult.Error.Count > 0) { exceptionMessage = string.Join(Environment.NewLine, commandLineResult.Error); } var runResult = new RunResult( succeeded: true, output: output.StdOut, exception: exceptionMessage, diagnostics: diagnostics, requestId: requestId); if (includeInstrumentation) { runResult.AddFeature(output.ProgramStatesArray); runResult.AddFeature(output.ProgramDescriptor); } return(runResult); }
public async Task Workspace_can_be_registered_in_directory_other_than_the_default() { var parentDirectory = Package.CreateDirectory(nameof(Workspace_can_be_registered_in_directory_other_than_the_default)); var workspaceName = "a"; var childDirectory = parentDirectory.CreateSubdirectory(workspaceName); registry.Add( workspaceName, builder => { builder.Directory = childDirectory; }); var workspace = await registry.Get <IHaveADirectory>(workspaceName); workspace.Directory.Should().Be(childDirectory); }
public static async Task <Compilation> Compile( this Package package, Workspace workspace, Budget budget, BufferId activeBufferId) { var sourceFiles = workspace.GetSourceFiles().ToArray(); var(compilation, documents) = await package.GetCompilationForRun(sourceFiles, SourceCodeKind.Regular, workspace.Usings, budget); var viewports = workspace.ExtractViewPorts(); var diagnostics = compilation.GetDiagnostics(); if (workspace.IncludeInstrumentation && !diagnostics.ContainsError()) { var activeDocument = GetActiveDocument(documents, activeBufferId); compilation = await AugmentCompilationAsync(viewports, compilation, activeDocument, activeBufferId, package); } return(compilation); }
public async Task NuGet_packages_can_be_added_during_initialization() { var workspaceId = Package.CreateDirectory(nameof(NuGet_packages_can_be_added_during_initialization)).Name; registry.Add(workspaceId, options => { options.CreateUsingDotnet("console"); options.AddPackageReference("Twilio", "5.9.2"); }); var workspaceServer = new RoslynWorkspaceServer(registry); var workspace = Workspace.FromSource( @" using System; using Twilio.Clients; using Twilio.Rest.Api.V2010.Account; using Twilio.Types; namespace Twilio_try.dot.net_sample { class Program { static void Main() { var sendFromPhoneNumber = new PhoneNumber(""TWILIO_PHONE_NUMBER""); var sendToPhoneNumber = new PhoneNumber(""RECIPIENT_PHONE_NUMBER""); } } }", workspaceType: workspaceId); var result = await workspaceServer.Run(new WorkspaceRequest(workspace)); result.Succeeded.Should().BeTrue(because: "compilation can't succeed unless the NuGet package has been restored."); }
private static async Task <RedirectedPackage> CreatePackageWithChanges(Package package, Workspace workspace) { // copy project and assets to temporary location var tempDirName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); var packageWithChanges = new RedirectedPackage(workspace, package, Directory.CreateDirectory(tempDirName)); try { await CopyDirectory(package.Directory.FullName, packageWithChanges.Directory.FullName); // overwrite files foreach (var file in workspace.Files) { File.WriteAllText(Path.Combine(packageWithChanges.Directory.FullName, Path.GetFileName(file.Name)), file.Text); } return(packageWithChanges); } catch { packageWithChanges.Clean(); return(null); } }
private static async Task <Compilation> AugmentCompilationAsync( IEnumerable <Viewport> viewports, Compilation compilation, Document document, BufferId activeBufferId, Package build) { var regions = InstrumentationLineMapper.FilterActiveViewport(viewports, activeBufferId) .Where(v => v.Destination?.Name != null) .GroupBy(v => v.Destination.Name, v => v.Region, (name, region) => new InstrumentationMap(name, region)) .ToArray(); var solution = document.Project.Solution; var newCompilation = compilation; foreach (var tree in newCompilation.SyntaxTrees) { var replacementRegions = regions.FirstOrDefault(r => tree.FilePath.EndsWith(r.FileToInstrument))?.InstrumentationRegions; var subdocument = solution.GetDocument(tree); var visitor = new InstrumentationSyntaxVisitor(subdocument, await subdocument.GetSemanticModelAsync(), replacementRegions); var linesWithInstrumentation = visitor.Augmentations.Data.Keys; var activeViewport = viewports.DefaultIfEmpty(null).First(); var(augmentationMap, variableLocationMap) = await InstrumentationLineMapper.MapLineLocationsRelativeToViewportAsync( visitor.Augmentations, visitor.VariableLocations, document, activeViewport); var rewrite = new InstrumentationSyntaxRewriter( linesWithInstrumentation, variableLocationMap, augmentationMap); var newRoot = rewrite.Visit(tree.GetRoot()); var newTree = tree.WithRootAndOptions(newRoot, tree.Options); newCompilation = newCompilation.ReplaceSyntaxTree(tree, newTree); } var instrumentationSyntaxTree = build.GetInstrumentationEmitterSyntaxTree(); newCompilation = newCompilation.AddSyntaxTrees(instrumentationSyntaxTree); var augmentedDiagnostics = newCompilation.GetDiagnostics(); if (augmentedDiagnostics.ContainsError()) { throw new InvalidOperationException( $@"Augmented source failed to compile Diagnostics ----------- {string.Join(NewLine, augmentedDiagnostics)} Source ------ {newCompilation.SyntaxTrees.Select(s => $"// {s.FilePath ?? "(anonymous)"}{NewLine}//---------------------------------{NewLine}{NewLine}{s}").Join(NewLine + NewLine)}"); } return(newCompilation); }
protected override Workspace CreateWorkspaceWithMainContaining(string text, Package package) => Workspace.FromSource(text, workspaceType: "script");
public static async Task <Package> XunitWorkspaceCopy([CallerMemberName] string testName = null) => await Package.Copy( await Default.XunitWorkspace(), testName);
public static async Task <Package> ConsoleWorkspaceCopy([CallerMemberName] string testName = null, bool isRebuildable = false, IScheduler buildThrottleScheduler = null) => await Package.Copy( await Default.ConsoleWorkspace(), testName, isRebuildable, buildThrottleScheduler);
public static Task <(Compilation compilation, IReadOnlyCollection <Document> documents)> GetCompilationForRun( this Package package, IReadOnlyCollection <SourceFile> sources, SourceCodeKind sourceCodeKind, IEnumerable <string> defaultUsings, Budget budget) =>