Turbinando o compilador do Java 8

Preview:

Citation preview

Semana da Tecnologia 2016

Turbinando o compilador do Java 8

Semana da Tecnologia 2016

Marcelo de Castromarcelo@castro.eti.br

@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

Marcelo de Castromarcelo@castro.eti.br

@mcastroinfo

OBRIGADO

Recommended