Palestra realizada, no dia 8/6/13, no JustJava 2013, visando apresentar esta novidade poderosa do Java 8 que permite criar análises personalizadas de código fonte, além da adição de checagens extras em tempo de compilação e transformações de código.
3. Plugin para o javac 8
0101010101011111000000000101001110001
1100011100000001111010101010110001110
1001001010000101001010101011010110111
4. • Por quê, para quê, desenvolver
plugins para o compilador do
Java?
– Adicionar checagem extras em tempo
de compilação
– Adicionar transformações de código
– Customizar análise do código fonte
5. Este código compila?
Teste.java
public class Teste {
public static final int var = 0;
public static void main(String[] args) {
int i = 0; System.out.println("#JustJava2013");
try{
i++;
}catch(Exception Ex){
}
}
public static void method(int a, int b, int c, int d,
int e, int f, int g, int h, int i, int j, int k){
}
class inner{}
}
6. Jogo dos 5 erros(!?)
public class Teste {
public static final int var = 0;
public static void main(String[] args) {
int i = 0; System.out.println("#JustJava2013");
try{
i++;
}catch(Exception Ex){
}
}
public static void method(int a, int b, int c, int d,
int e, int f, int g, int h, int i, int j, int k){
}
class inner{}
}
VAR
ex
Inner
vazio
Muitos
parâmetros
7. Compilar ou não compilar
?????
public class Teste {
public static final int var = 0;
public static void main(String[] args) {
int i = 0; System.out.println("#JustJava2013");
try{
i++;
}catch(Exception Ex){
}
}
public static void method(int a, int b, int c, int d,
int e, int f, int g, int h, int i, int j, int k){
}
class inner{}
}
8. Alterando o
comportamento do javac
1. Usar Java 8 (tools.jar no CLASSPATH)
2. Implementar Plugin(*)
3. Implementar TaskListener
4. Implementar a lógica desejada
– (TreePathScanner, TreeScanner, TreeVisitor)
– Ex: Não aceitar bloco catch vazio
5. Gerar o jar do Plugin
– META-INF/services/
• com.sun.source.util.Plugin
– NomeTotalmenteQualificadoDoPlugin(*)
6. Compilar usando o plugin
– javac -processorpath CodeCheckPlugin.jar -
Xplugin:CodeCheckPlugin Teste.java
10. interfaces
com.sun.source.util
• Plugin
– permite definir um plugin para o
compilador
• SourcePositions
– fornece métodos para obter a
posição corrente da compilação
• TaskListener
– fornece um listener para monitorar
atividades do javac
11. interface Plugin
public class CodeCheckPlugin implements Plugin {
@Override
public String getName() {
return "CodeCheckPlugin";
}
@Override
public void init(JavacTask task, String... strings) {
System.out.println("Iniciando plugin!");
task.setTaskListener(new CheckTaskListener(task));
}
}
12. interface TaskListener
public class CheckTaskListener implements TaskListener{
@Override
public void started(TaskEvent taskEvent) {
if(taskEvent.getKind().equals(TaskEvent.Kind.ANALYZE)) {
CompilationUnitTree compUnit =
taskEvent.getCompilationUnit();
TreePathScanner emptyCacthVisitor =
new EmptyCacthVisitor(task);
emptyCacthVisitor.scan(compUnit, null);
}
}
@Override
public void finished(TaskEvent te) {
}
}
14. Abstract Syntax Trees
Exemplo da Gramática da Linguagem Java
normalClassDeclaration
: 'class' Identifier typeParameters?
('extends' type)?
('implements' typeList)?
classBody
public class Teste
extends TesteBase{
}
class TesteBase{}
*AST: abstract syntax tree
16. Classes (Syntax Trees)
com.sun.source.util
com.sun.source.tree
• public abstract class Trees
• public abstract class DocTrees extends Trees
• public interface Tree
• public enum Tree.Kind
• public interface CompilationUnitTree extends Tree
• public interface MethodTree extends Tree
• public interface BlockTree extends Tree
• public interface CatchTree extends Tree
• public interface StatementTree extends Tree
• public interface ModifiersTree extends Tree
• public interface VariableTree extends Tree
• public interface PrimitiveTypeTree extends Tree
• + um montão de Tree