Slides

Transcrição

Slides
Compiladores como Serviço
Hoje: Garantia de Códigos
mais Limpos, Rápidos e Leves
Elemar Jr
@elemarjr
linkedin.com/in/elemarjr
Disclaimer
Como vemos compiladores hoje
Compilador
Como vemos compiladores hoje
Código
Compilador
Como vemos compiladores hoje
Código
Compilador
Como vemos compiladores hoje
Código
Compilador
Executável
Como vemos compiladores hoje
Código
Compilador
Executável
Como vemos compiladores hoje
Código
Compilador
Executável
Como vemos compiladores hoje
Código
Compilador
Executável
Como vemos compiladores hoje
IntelliSense
Refactoring
Go To Definition
Código
Compilador
Executável
Code Analysis
Find All References
Metrics
Como vemos compiladores hoje
IntelliSense
Refactoring
Go To Definition
Código
Compilador
Executável
Code Analysis
Find All References
Metrics
Uma visão mais “madura”
E se existisse uma API?
E se a IDE consumisse essa API?
E se a IDE consumisse essa API?
Hello World!
Obtendo a árvore sintática
var script = @"using System;
using System.Collections.Generic;
using System.Text;
public static class Program
{
public static void Main()
{
Console.WriteLine(""Hello World"");
}
}";
// Parse the script to a SyntaxTree
var syntaxTree = CSharpSyntaxTree.ParseText(script);
Gerando a compilação
// Parse the script to a SyntaxTree
var syntaxTree = CSharpSyntaxTree.ParseText(script);
// Compile the SyntaxTree to a CSharpCompilation
var compilation = CSharpCompilation.Create("Script",
new[] { syntaxTree },
defaultReferences.Select(x =>
MetadataReference.CreateFromFile(Path.Combine(assemblyPath, x))),
new CSharpCompilationOptions(OutputKind.ConsoleApplication));
Saída e execução
using (var outputStream = new MemoryStream())
using (var pdbStream = new MemoryStream())
{
// Emit assembly to streams.
var result = compilation.Emit(outputStream, pdbStream: pdbStream);
if (!result.Success)
{
return;
}
// Load the emitted assembly.
var assembly = Assembly.Load(outputStream.ToArray(), pdbStream.ToArray());
// Invoke the entry point.
assembly.EntryPoint.Invoke(null, null);
}
Análise Sintática
SyntaxTree tree = CSharpSyntaxTree.ParseText(
@"
using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(""Hello, World!"");
}
}
}");
var
var
var
var
var
var
root = (CompilationUnitSyntax)tree.GetRoot();
firstMember = root.Members[0];
helloWorldDeclaration = (NamespaceDeclarationSyntax)firstMember;
programDeclaration = (ClassDeclarationSyntax)helloWorldDeclaration.Members[0];
mainDeclaration = (MethodDeclarationSyntax)programDeclaration.Members[0];
argsParameter = mainDeclaration.ParameterList.Parameters[0];
Linq To Code
var declarations =
root.DescendantNodes().OfType<MethodDeclarationSyntax>();
var firstParameters = from methodDeclaration in declarations
where methodDeclaration.Identifier.ValueText == "Main"
select methodDeclaration.ParameterList.Parameters.First();
var argsParameter2 = firstParameters.Single();
Análise Semântica
O que há no Namespace
var
var
var
var
root = (CompilationUnitSyntax)syntaxTree.GetRoot();
model = compilation.GetSemanticModel(syntaxTree);
nameInfo = model.GetSymbolInfo(root.Usings[0].Name);
systemSymbol = (INamespaceSymbol)nameInfo.Symbol;
foreach (var ns in systemSymbol.GetNamespaceMembers())
{
Console.WriteLine(ns.Name);
}
O que há em uma String
var helloWorldString = root.DescendantNodes()
.OfType<LiteralExpressionSyntax>()
.First();
var literalInfo = model.GetTypeInfo(helloWorldString);
var stringTypeSymbol = (INamedTypeSymbol)literalInfo.Type;
var stringMethodsNames =
(from method in stringTypeSymbol.GetMembers().OfType<IMethodSymbol>()
where method.ReturnType.Equals(stringTypeSymbol) &&
method.DeclaredAccessibility == Accessibility.Public
select method.Name).Distinct();
foreach (var name in stringMethodsNames)
{
Console.WriteLine(name);
}
Transformações
Transformação
SyntaxTree tree = CSharpSyntaxTree.ParseText(
@"using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(""Hello, World!"");
}
}
}");
NameSyntax name = SyntaxFactory.IdentifierName("System");
name = SyntaxFactory.QualifiedName(name, SyntaxFactory.IdentifierName("Collections"));
name = SyntaxFactory.QualifiedName(name, SyntaxFactory.IdentifierName("Generic"));
var root = (CompilationUnitSyntax)tree.GetRoot();
var oldUsing = root.Usings[1];
var newUsing = oldUsing.WithName(name);
root = root.ReplaceNode(oldUsing, newUsing);
Expandindo o VS
https://github.com/code-cracker/code-cracker
https://github.com/dotnet/roslyn
Obrigado!