예제 #1
0
        private static async Task EmitCompilationAsync(Compilation compilation, Package package)
        {
            if (package == null)
            {
                throw new ArgumentNullException(nameof(package));
            }

            {
                var numberOfAttempts = 100;
                for (var attempt = 1; attempt < numberOfAttempts; attempt++)
                {
                    try
                    {
                        compilation.Emit(package.EntryPointAssemblyPath.FullName);
                        break;
                    }
                    catch (IOException)
                    {
                        if (attempt == numberOfAttempts - 1)
                        {
                            throw;
                        }

                        await Task.Delay(10);
                    }
                }
            }
        }
예제 #2
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());
        }
예제 #3
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.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);

            var result = new RunResult(
                commandLineResult.ExitCode == 0,
                tRexResult.Output,
                diagnostics: diagnostics,
                requestId: requestId);

            result.AddFeature(new UnitTestRun(new[]
            {
                new UnitTestResult()
            }));

            return(result);
        }
예제 #4
0
        internal 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.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);
        }
예제 #5
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);
        }
예제 #6
0
        private static RunResult RunWebRequest(Package package, string requestId)
        {
            var runResult = new RunResult(succeeded: true, requestId: requestId);

            return(runResult);
        }
예제 #7
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);
        }
예제 #8
0
 public static Task <(Compilation compilation, IReadOnlyCollection <Document> documents)> GetCompilationForRun(
     this Package package,
     IReadOnlyCollection <SourceFile> sources,
     SourceCodeKind sourceCodeKind,
     IEnumerable <string> defaultUsings,
     Budget budget) =>