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));
            }
        }
Exemple #2
0
 public static async Task <Package> NetstandardWorkspaceCopy(
     [CallerMemberName] string testName = null,
     DirectoryInfo parentDirectory      = null) =>
 await Package.Copy(
     await Default.NetstandardWorkspace(),
     testName,
     parentDirectory : parentDirectory);
Exemple #3
0
        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);
                    }
                }
            }
        }
Exemple #4
0
        private static RunResult RunWebRequest(Package package, string requestId)
        {
            var runResult = new RunResult(succeeded: true, requestId: requestId);

            runResult.AddFeature(new WebServer(package));
            return(runResult);
        }
Exemple #5
0
        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);
        }
Exemple #7
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());
        }
Exemple #8
0
        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);
        }
Exemple #9
0
        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);
            });
        }
Exemple #10
0
        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);
        }
Exemple #12
0
        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);
            }
        }
Exemple #15
0
        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);
        }
Exemple #16
0
 protected override Workspace CreateWorkspaceWithMainContaining(string text, Package package) =>
 Workspace.FromSource(text, workspaceType: "script");
Exemple #17
0
 public static async Task <Package> XunitWorkspaceCopy([CallerMemberName] string testName = null) =>
 await Package.Copy(
     await Default.XunitWorkspace(),
     testName);
Exemple #18
0
 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);
Exemple #19
0
 public static Task <(Compilation compilation, IReadOnlyCollection <Document> documents)> GetCompilationForRun(
     this Package package,
     IReadOnlyCollection <SourceFile> sources,
     SourceCodeKind sourceCodeKind,
     IEnumerable <string> defaultUsings,
     Budget budget) =>