Roslyn CTP

For the past year and a half or so I’ve been working on the QA team for the Roslyn project. The goal of our project is (simply put) to make our managed compilers and language services actually managed :-)

I’m happy to announce that we’ve released our first CTP today and it is available for immediate download at https://msdn.com/roslyn.

I’ve posted a more detailed overview of the release over on the Visual Studio blog. Now that we can actually talk about our work, I expect to blog more about Roslyn and otherwise keep in touch with the developer community. I’ll be also tweeting more about Roslyn (@KirillOsenkov). I suggest that we use the #RoslynCTP hashtag on Twitter for Roslyn-related discussions (#Roslyn is already taken by the actual city of Roslyn).

We will also be participating on the Roslyn forum, and closely monitoring the Connect bugs and suggestions.

Below I want to show a few demos of what Roslyn can do. I’ll start with excerpts from one of the samples that we ship (APISampleUnitTests) – a set of unit-tests that demonstrates the usage of the compiler API. To me, there’s no better way to learn an API surface than by reading the unit-tests that cover it.

Have you ever needed a full-fidelity, high performance C# parser?

 [TestMethod]
public void TextParseTreeRoundtrip()
{
    string text = "class C { void M() { } } // exact text round trip, including comments and whitespace";
    SyntaxTree tree = SyntaxTree.ParseCompilationUnit(text);
    Assert.AreEqual(text, tree.ToString());
}

Or perhaps you prefer VB?

 <TestMethod()>
Sub TextParseTreeRoundtrip()
    Dim code =
<code>
Class C
  Sub M()
  End Sub
End Class ' exact text round trip, including comments and whitespace
</code>.GetCode()
 
    Dim tree = SyntaxTree.ParseCompilationUnit(code)
    Assert.AreEqual(code, tree.Text.ToString())
End Sub

You can also parse a stand-alone expression:

 ExpressionSyntax expression = Syntax.ParseExpression("1 + 2");

Want to do LINQ queries over your code?

 [TestMethod]
public void FindNodeUsingQuery()
{
    string text = "class C { void M(int i) { } }";
    SyntaxNode root = Syntax.ParseCompilationUnit(text);
    var parameterDeclaration = root
        .DescendentNodes()
        .OfType<ParameterSyntax>()
        .First();
    Assert.AreEqual("i", parameterDeclaration.Identifier.ValueText);
}

Or transform your code using Visitors?

 [TestMethod]
public void TransformTreeUsingSyntaxRewriter()
{
    string text = "class C { void M() { } int field; }";
    SyntaxTree tree = SyntaxTree.ParseCompilationUnit(text);
    SyntaxNode newRoot = new RemoveMethodsRewriter().Visit(tree.Root);
    Assert.AreEqual("class C { int field; }", newRoot.GetFullText());
}
 
private class RemoveMethodsRewriter : SyntaxRewriter
{
    protected override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
    {
        return null;
    }
}

What about executing custom code (scripting)?

 [TestMethod]
public void SimpleEvaluationUsingScriptEngine()
{
    ScriptEngine engine = new ScriptEngine();
    int result = engine.Execute<int>("1 + 2");
    Assert.AreEqual(3, result);
}

Or compiling a program end-to-end?

 [TestMethod]
public void EndToEndCompileAndRun()
{
    var expression = "6 * 7";
    var text = @"public class Calculator
{
public static object Evaluate()
{
return $;
} 
}".Replace("$", expression);
 
    var tree = SyntaxTree.ParseCompilationUnit(text);
    var compilation = Compilation.Create(
        "calc.dll",
        options: new CompilationOptions(assemblyKind: AssemblyKind.DynamicallyLinkedLibrary),
        syntaxTrees: new[] { tree },
        references: new[] { new AssemblyFileReference(typeof(object).Assembly.Location) });
 
    Assembly compiledAssembly;
    using (var stream = new MemoryStream())
    {
        EmitResult compileResult = compilation.Emit(stream);
        compiledAssembly = Assembly.Load(stream.GetBuffer());
    }
 
    Type calculator = compiledAssembly.GetType("Calculator");
    MethodInfo evaluate = calculator.GetMethod("Evaluate");
    string answer = evaluate.Invoke(null, null).ToString();
 
    Assert.AreEqual("42", answer);
}

Have you ever wanted to write your .bat files in C#, with IntelliSense and full compiler support?

image

image

There’s more. Stay tuned!