public void ExpressionRewriter_CanRewriteExpression_ChainedMemberAccessExpression() { // Arrange var source = @" using System; using System.Linq.Expressions; public class Program { public static void CalledWithExpression(Expression<Func<Person, int>> expression) { } public static void Main(string[] args) { CalledWithExpression(x => x.Name.Length); } } public class Person { public string Name { get; set; } } "; var tree = CSharpSyntaxTree.ParseText(source); var compilation = Compile(tree); var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true); var rewriter = new ExpressionRewriter(semanticModel); // Act var result = rewriter.Visit(tree.GetRoot()); // Assert var fields = FindFields(result); var field = Assert.Single(fields); Assert.Collection( field.Modifiers, m => Assert.Equal("private", m.ToString()), m => Assert.Equal("static", m.ToString()), m => Assert.Equal("readonly", m.ToString())); var declaration = field.Declaration; Assert.Equal( "global::System.Linq.Expressions.Expression<global::System.Func<global::Person, int>>", declaration.Type.ToString()); var variable = Assert.Single(declaration.Variables); Assert.Equal("__h0", variable.Identifier.ToString()); Assert.Equal("x => x.Name.Length", variable.Initializer.Value.ToString()); var arguments = FindArguments(result); var argument = Assert.IsType <IdentifierNameSyntax>(Assert.Single(arguments.Arguments).Expression); Assert.Equal("__h0", argument.Identifier.ToString()); }
public void ExpressionRewriter_CannotRewriteExpression_NestedClass() { // Arrange var source = @" using System; using System.Linq.Expressions; public class Program { private class Nested { public static void CalledWithExpression(Expression<Func<object, int>> expression) { } public static void Main(string[] args) { Expression<Func<object, int>> expr = x => x.GetHashCode(); CalledWithExpression(expr); } } } "; var tree = CSharpSyntaxTree.ParseText(source); var compilation = Compile(tree); var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true); var rewriter = new ExpressionRewriter(semanticModel); // Act var result = rewriter.Visit(tree.GetRoot()); // Assert Assert.Empty(FindFields(result)); }
public void ExpressionRewriter_CanRewriteExpression_IdentityExpression() { // Arrange var source = @" using System; using System.Linq.Expressions; public class Program { public static void CalledWithExpression(Expression<Func<object, object>> expression) { } public static void Main(string[] args) { CalledWithExpression(x => x); } } "; var tree = CSharpSyntaxTree.ParseText(source); var compilation = Compile(tree); var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true); var rewriter = new ExpressionRewriter(semanticModel); // Act var result = rewriter.Visit(tree.GetRoot()); // Assert var fields = FindFields(result); var field = Assert.Single(fields); Assert.Collection( field.Modifiers, m => Assert.Equal("private", m.ToString()), m => Assert.Equal("static", m.ToString()), m => Assert.Equal("readonly", m.ToString())); var declaration = field.Declaration; Assert.Equal( "global::System.Linq.Expressions.Expression<global::System.Func<object, object>>", declaration.Type.ToString()); var variable = Assert.Single(declaration.Variables); Assert.Equal("__h0", variable.Identifier.ToString()); Assert.Equal("x => x", variable.Initializer.Value.ToString()); var arguments = FindArguments(result); var argument = Assert.IsType<IdentifierNameSyntax>(Assert.Single(arguments.Arguments).Expression); Assert.Equal("__h0", argument.Identifier.ToString()); }
private CSharpCompilation Rewrite(CSharpCompilation compilation) { var rewrittenTrees = new List <SyntaxTree>(); foreach (var tree in compilation.SyntaxTrees) { var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true); var rewriter = new ExpressionRewriter(semanticModel); var rewrittenTree = tree.WithRootAndOptions(rewriter.Visit(tree.GetRoot()), tree.Options); rewrittenTrees.Add(rewrittenTree); } return(compilation.RemoveAllSyntaxTrees().AddSyntaxTrees(rewrittenTrees)); }
public void ExpressionRewriter_CanRewriteExpression_ComplexFormatting() { // Arrange var source = @" using System; using System.Linq.Expressions; public class Program { public static void CalledWithExpression(int z, Expression<Func<Person, int>> expression) { } public static void Main(string[] args) { CalledWithExpression( 17, x => x.Name. Length ); } } public class Person { public string Name { get; set; } } "; var tree = CSharpSyntaxTree.ParseText(source); var originalArguments = FindArguments(tree.GetRoot()); var originalSpan = originalArguments.GetLocation().GetMappedLineSpan(); var compilation = Compile(tree); var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true); var rewriter = new ExpressionRewriter(semanticModel); // Act var result = rewriter.Visit(tree.GetRoot()); // Assert var arguments = FindArguments(result); Assert.Equal(originalSpan, arguments.GetLocation().GetMappedLineSpan()); }
public void ExpressionRewriter_DoesNotThrowsOnUnknownTypes() { // Arrange var source = @" using System.Threading.Tasks; using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc.Razor; public class ExamplePage : RazorPage { public IViewComponentHelper Component { get; set; } public override async Task ExecuteAsync() { Write( await Component.InvokeAsync( ""SomeComponent"", item => new HelperResult((__razor_template_writer) => WriteLiteralTo(__razor_template_writer, ""Hello World"")))); } } "; var tree = CSharpSyntaxTree.ParseText(source); // Allow errors here because of an anomaly where Roslyn (depending on code sample) will finish compilation // without diagnostic errors. This test case replicates that scenario by allowing a semantic model with // errors to be visited by the expression rewriter to validate unexpected exceptions aren't thrown. // Error created: "Cannot convert lambda expression to type 'object' because it is not a delegate type." var compilation = Compile(tree, allowErrors: true); var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true); var rewriter = new ExpressionRewriter(semanticModel); var root = tree.GetRoot(); // Act var result = rewriter.Visit(root); // Assert Assert.True(root.IsEquivalentTo(result)); }
private CSharpCompilation Rewrite(CSharpCompilation compilation) { var rewrittenTrees = new List<SyntaxTree>(); foreach (var tree in compilation.SyntaxTrees) { var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true); var rewriter = new ExpressionRewriter(semanticModel); var rewrittenTree = tree.WithRootAndOptions(rewriter.Visit(tree.GetRoot()), tree.Options); rewrittenTrees.Add(rewrittenTree); } return compilation.RemoveAllSyntaxTrees().AddSyntaxTrees(rewrittenTrees); }