public async Task Syntax_Tree_Has_Locals_When_Augmentation_Has_Locals()
        {
            // arrange
            var document   = Sources.GetDocument(Sources.withMultipleMethodsAndComplexLayout);
            var syntaxTree = await document.GetSyntaxTreeAsync();

            var statement = (StatementSyntax)syntaxTree.GetRoot().DescendantNodes().Single(n => n.ToString() == @"Console.WriteLine(""Entry Point"");");

            var locals        = (await document.GetSemanticModelAsync()).LookupSymbols(310).Where(s => s.Kind == SymbolKind.Local);
            var augmentations = new[] { new Augmentation(statement, locals, null, null, null) };

            var augMap   = new AugmentationMap(augmentations.ToArray());
            var rewriter = new InstrumentationSyntaxRewriter(
                augMap.Data.Keys,
                new VariableLocationMap(),
                augMap
                );

            // act
            var newTree    = rewriter.ApplyToTree(syntaxTree);
            var treeString = newTree.ToString();

            // assert
            Assert.Contains("\\\"name\\\":\\\"j\\\"", treeString);
            Assert.Contains("\\\"name\\\":\\\"k\\\"", treeString);
            Assert.Contains("\\\"name\\\":\\\"p\\\"", treeString);
        }
        public async Task Syntax_Tree_Has_A_Single_Extra_Statement_When_There_Is_One_Augmentation()
        {
            // arrange
            var document   = Sources.GetDocument(Sources.simple);
            var syntaxTree = await document.GetSyntaxTreeAsync();

            var statementCount = syntaxTree.GetRoot().DescendantNodes().Count(n => n is StatementSyntax);
            var statement      = (StatementSyntax)syntaxTree.GetRoot().DescendantNodes().Single(n => n.ToString() == @"Console.WriteLine(""Entry Point"");");

            var augmentation = new Augmentation(statement, null, null, null, null);
            var augMap       = new AugmentationMap(augmentation);

            var rewriter = new InstrumentationSyntaxRewriter(
                augMap.Data.Keys,
                new VariableLocationMap(),
                augMap
                );

            // act
            var newTree           = rewriter.ApplyToTree(syntaxTree);
            var newStatementCount = newTree.GetRoot().DescendantNodes().Count(n => n is StatementSyntax);

            // assert
            Assert.Equal(statementCount + 1, newStatementCount);
        }
        public async Task Syntax_Tree_Has_Extra_Statements_When_Everything_Is_Augmented()
        {
            // arrange
            var document   = Sources.GetDocument(Sources.withMultipleMethodsAndComplexLayout);
            var syntaxTree = await document.GetSyntaxTreeAsync();

            var augmentations = syntaxTree.GetRoot()
                                .DescendantNodes()
                                .Where(n => n is StatementSyntax)
                                .Select(n => new Augmentation((StatementSyntax)n, null, null, null, null));
            var augMap = new AugmentationMap(augmentations.ToArray());

            var rewriter = new InstrumentationSyntaxRewriter(
                augMap.Data.Keys,
                new VariableLocationMap(),
                augMap
                );

            // act
            var newTree           = rewriter.ApplyToTree(syntaxTree);
            var newStatementCount = newTree.GetRoot().DescendantNodes().Count(n => n is StatementSyntax);

            // assert
            Assert.Equal(24, newStatementCount);
        }
        public void CreateSyntaxNode_works_correctly()
        {
            var a  = new { foo = 3 };
            var vi = new VariableInfo
            {
                Name         = nameof(a),
                Value        = JToken.FromObject(a),
                RangeOfLines = new LineRange
                {
                    Start = 10,
                    End   = 11
                }
            };
            var filePosition = new FilePosition
            {
                Line      = 1,
                Character = 1,
                File      = "test.cs"
            };

            var result = InstrumentationSyntaxRewriter.CreateSyntaxNode(filePosition, vi).ToString();

            var emitterTypeName = typeof(InstrumentationEmitter).FullName;

            var expected =
                $"{emitterTypeName}.EmitProgramState({emitterTypeName}.GetProgramState(\"{{\\\"line\\\":1,\\\"character\\\":1,\\\"file\\\":\\\"test.cs\\\"}}\",(\"{{\\\"name\\\":\\\"a\\\",\\\"value\\\":{{\\\"foo\\\":3}},\\\"declaredAt\\\":{{\\\"start\\\":10,\\\"end\\\":11}}}}\",a)));";

            result.Should().Be(expected);
        }
Beispiel #5
0
        private async Task <string> RewriteCodeWithInstrumentation(string text)
        {
            var document  = Sources.GetDocument(text, true);
            var visitor   = new InstrumentationSyntaxVisitor(document, await document.GetSemanticModelAsync());
            var rewritten = new InstrumentationSyntaxRewriter(
                visitor.Augmentations.Data.Keys,
                visitor.VariableLocations,
                visitor.Augmentations
                );

            return(rewritten.ApplyToTree(document.GetSyntaxTreeAsync().Result).GetText().ToString().EnforceLF());
        }
        public async Task Syntax_Tree_Is_Unchanged_When_Given_No_Augmentations()
        {
            // arrange
            var document   = Sources.GetDocument(Sources.simple);
            var syntaxTree = await document.GetSyntaxTreeAsync();

            var rewriter = new InstrumentationSyntaxRewriter
                           (
                Enumerable.Empty <SyntaxNode>(),
                new VariableLocationMap(),
                new AugmentationMap()
                           );

            // act
            var newTree = rewriter.ApplyToTree(syntaxTree);

            // assert
            Assert.True(syntaxTree.IsEquivalentTo(newTree));
        }
        public RewriterVariableLocationTests()
        {
            MarkupTestFile.GetSpans(Sources.withNonAssignedLocals, out var code, out ImmutableArray <TextSpan> _);
            var document          = Sources.GetDocument(code, true);
            var syntaxTree        = document.GetSyntaxTreeAsync().Result;
            var instrumentedNodes = syntaxTree.GetRoot()
                                    .DescendantNodes()
                                    .Where(n => n is StatementSyntax);

            var symbols = document.GetSemanticModelAsync().Result.LookupSymbols(250)
                          .Where(symbol => symbol.Kind == SymbolKind.Local);

            var a          = symbols.First(symbol => symbol.Name == "a");
            var aLocations = new[]
            {
                new VariableLocation(a, 12, 12, 12, 13),
                new VariableLocation(a, 9, 9, 16, 21)
            };

            var s          = symbols.First(symbol => symbol.Name == "s");
            var sLocations = new[]
            {
                new VariableLocation(s, 8, 8, 19, 20),
                new VariableLocation(s, 11, 11, 12, 13)
            };
            var locationMap = new VariableLocationMap();

            locationMap.AddLocations(a, aLocations);
            locationMap.AddLocations(s, sLocations);

            var rewriter = new InstrumentationSyntaxRewriter(
                instrumentedNodes,
                locationMap,
                new AugmentationMap()
                );

            var rewrittenProgramWithWhitespace = rewriter.ApplyToTree(syntaxTree).ToString();

            rewrittenProgram = TestUtils.RemoveWhitespace(rewrittenProgramWithWhitespace);
        }
Beispiel #8
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);
        }