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); }
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); }
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); }