Upload
marcelo-de-castro
View
144
Download
1
Embed Size (px)
Citation preview
Semana da Tecnologia 2016
Turbinando o compilador do Java 8
Semana da Tecnologia 2016
Marcelo de [email protected]
@mcastroinfo
Plugin para o javac 8
010101010101111100000000010100111000111000111000000011110101010101100011101001001010000101001010101011010110111
• 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
Este código compila?Teste.java
package br.unip.sicc;
public class Teste {
public static final int var = 0;
public static void main(String[] args) {
int i = 0;
System.out.println("UNIP");
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{}
}
Jogo dos 5 erros(!?)Teste.java
package br.unip.sicc;
public class Teste {
public static final int var = 0;
public static void main(String[] args) {
int i = 0;
System.out.println("UNIP");
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{}
}
Java Code Conventions
Java Code Conventions
Jogo dos 5 erros(!?)Teste.java
package br.unip.sicc;
public class Teste {
public static final int var = 0;
public static void main(String[] args) {
int i = 0;
System.out.println("UNIP");
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{}
}
Inner
Java Code Conventions
Jogo dos 5 erros(!?)Teste.java
package br.unip.sicc;
public class Teste {
public static final int var = 0;
public static void main(String[] args) {
int i = 0;
System.out.println("UNIP");
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{}
}
ex
Java Code Conventions
Jogo dos 5 erros(!?)Teste.java
package br.unip.sicc;
public class Teste {
public static final int var = 0;
public static void main(String[] args) {
int i = 0;
System.out.println("UNIP");
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
Effective Java
Jogo dos 5 erros(!?)Teste.java
package br.unip.sicc;
public class Teste {
public static final int var = 0;
public static void main(String[] args) {
int i = 0;
System.out.println("UNIP");
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{}
}
vazio
Effective Java
Jogo dos 5 erros(!?)Teste.java
package br.unip.sicc;
public class Teste {
public static final int var = 0;
public static void main(String[] args) {
int i = 0;
System.out.println("UNIP");
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{}
}
Muitos
parâmetros
Jogo dos 5 erros(!?)Teste.java
package br.unip.sicc;
public class Teste {
public static final int var = 0;
public static void main(String[] args) {
int i = 0;
System.out.println("UNIP");
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
Compilar ou não compilarTeste.java
package br.unip.sicc;
public class Teste {
public static final int var = 0;
public static void main(String[] args) {
int i = 0;
System.out.println("UNIP");
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{}
}
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
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
DEMO
010101010101111100000000010100111000111000111000000011110101010101100011101001001010000101001010101011010110111
API
010101010101111100000000010100111000111000111000000011110101010101100011101001001010000101001010101011010110111
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
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));
}
}
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) {
}
}
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) {
}
}
TaskEvent.Kind
•PARSE
•ENTER
•ANNOTATION_PROCESSING
•ANNOTATION_PROCESSING_ROUND
•ANALYZE
•GENERATE
Source File
Teste.java
Byte Code
Teste.class
interface SourcePositions
SourcePositions sourcePositions = trees.getSourcePositions();
sourcePositions.getStartPosition
(compilationUnitTree, tree);
sourcePositions.getEndPosition
(compilationUnitTree, tree);
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
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{}
Abstract
Syntax Tree
SHOW ME THE CODE
010101010101111100000000010100111000111000111000000011110101010101100011101001001010000101001010101011010110111
Referências
• OpenJDK 8 http://openjdk.java.net/
• API Specification, The Java Programming Language Compiler http://docs.oracle.com/javase/8/docs/jdk/api/javac/tree/index.html
• Sun Microsystems, Java Code Conventions, 1997
• Compiler Grammar http://openjdk.java.net/projects/compiler-grammar/
• Effective Java by Joshua Block, 2008
• Hacking the Java Compiler for Fun and Profit By Raoul-Gabriel Urma
• “Java Compiler Plugins”, Oracle Java Magazine January/February 2013, Raoul-Gabriel Urma& Jonathan Gibbons http://www.oraclejavamagazine-digital.com/javamagazine/20130102?sub_id=jFwJyABK25xj#pg56