Commit 77f79edc authored by Lukáš Marek's avatar Lukáš Marek
Browse files

Annotation parser implemented

parent dd3fb0f7
......@@ -50,6 +50,8 @@ public class DiSLDriver implements Instrumentation {
parser.parse(classAsBytes);
}
// TODO support for synthetic local
// initialize fields
snippets = parser.getSnippets();
analyzers = parser.getAnalyzers();
......@@ -110,15 +112,15 @@ public class DiSLDriver implements Instrumentation {
}
@Override
public void instrument(ClassNode clazz) {
public void instrument(ClassNode classNode) {
// instrument all methods in a class
for(Object methodObj : clazz.methods) {
for(Object methodObj : classNode.methods) {
// cast - ASM still uses Java 1.4 interface
MethodNode method = (MethodNode) methodObj;
instrumentMethod(clazz, method);
instrumentMethod(classNode, method);
}
}
......
package ch.usi.dag.disl.annotation;
import ch.usi.dag.disl.snippet.marker.Marker;
public @interface After {
// NOTE if you want to change names, you need to change Parser class
Class<Marker> marker();
String scope();
int order() default 100;
}
package ch.usi.dag.disl.annotation;
import ch.usi.dag.disl.snippet.marker.Marker;
public @interface Before {
// NOTE if you want to change names, you need to change Parser class
Class<Marker> marker();
String scope();
int order() default 100;
}
package ch.usi.dag.disl.parser;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import ch.usi.dag.disl.analyzer.Analyzer;
import ch.usi.dag.disl.annotation.After;
import ch.usi.dag.disl.annotation.Before;
import ch.usi.dag.disl.snippet.Snippet;
import ch.usi.dag.disl.snippet.SnippetImpl;
import ch.usi.dag.disl.snippet.marker.Marker;
import ch.usi.dag.disl.snippet.marker.MarkerFactory;
import ch.usi.dag.disl.snippet.scope.Scope;
import ch.usi.dag.disl.snippet.scope.ScopeImpl;
// The parser takes annotated java files as input and outputs some
// specification for the other three steps.
/**
* The parser takes annotated java file as input and creates Snippet and
* Analyzer classes
*/
public class Parser {
private List<Snippet> snippets = new LinkedList<Snippet>();
private List<Analyzer> analyzers = new LinkedList<Analyzer>();
public void parse(byte [] classAsBytes) {
// TODO! this method can be called many times
// TODO support for synthetic local
// - what if two synthetic local vars with the same name are defined
// in different files ???
// - if we don't want to merge them we should prefix them with class
// - in byte code they are
// NOTE this method can be called many times
ClassReader cr = new ClassReader(classAsBytes);
ClassNode classNode = new ClassNode();
cr.accept(classNode, 0);
parseAnalyzers(classNode.visibleAnnotations);
for(Object methodObj : classNode.methods) {
// cast - ASM still uses Java 1.4 interface
MethodNode method = (MethodNode) methodObj;
parseSnippets(method);
}
}
/**
* Method creates analyzers according to annotations
*
* @param annotations contains specifications for analyzers
*/
protected void parseAnalyzers(List<?> annotations) {
// TODO implement
}
// data holder for parseMethodAnnotation methods
private class MethodAnnotationData {
private boolean known;
private Class<?> type;
private Type marker;
private String scope;
private int order;
public MethodAnnotationData() {
this.known = false;
}
public MethodAnnotationData(Class<?> type, Type marker, String scope, int order) {
super();
this.known = true;
this.type = type;
this.marker = marker;
this.scope = scope;
this.order = order;
}
public boolean isKnown() {
return known;
}
public Class<?> getType() {
return type;
}
public Type getMarker() {
return marker;
}
public String getScope() {
return scope;
}
public int getOrder() {
return order;
}
}
protected void parseSnippets(MethodNode method) {
// more annotations on one snippet
// supported but we will have multiple snippets ;)
for(Object annotationObj : method.visibleAnnotations) {
MethodAnnotationData annotData =
// cast - ASM still uses Java 1.4 interface
parseMethodAnnotation((AnnotationNode) annotationObj);
// if this is unknown annotation skip it
if(! annotData.isKnown()) {
continue;
}
// marker
Marker marker = MarkerFactory.createMarker(annotData.getMarker());
// scope
Scope scope = new ScopeImpl(annotData.getScope());
// whole snippet
snippets.add(new SnippetImpl(annotData.getType(), marker, scope,
annotData.getOrder(), method.instructions));
}
}
protected MethodAnnotationData parseMethodAnnotation(AnnotationNode annotation) {
// TODO is this correct ??
Type annotationType = internalNameToType(annotation.desc);
// after annotation
if(annotationType.equals(Type.getType(After.class))) {
return parseMethodAnnotFields(
After.class, annotation, annotation.values);
}
// before annotation
if(annotationType.equals(Type.getType(Before.class))) {
return parseMethodAnnotFields(
Before.class, annotation, annotation.values);
}
// unknown annotation
return new MethodAnnotationData();
}
private MethodAnnotationData parseMethodAnnotFields(Class<?> type,
AnnotationNode annotation, List<?> annotValues) {
Iterator<?> it = annotValues.iterator();
String name = null;
Type marker = null;
String scope = null;
Integer order = null;
while(it.hasNext()) {
name = (String) it.next();
if(name.equals("marker")) {
marker = (Type) it.next();
continue;
}
if(name.equals("scope")) {
scope = (String) it.next();
continue;
}
if(name.equals("order")) {
order = (Integer) it.next();
continue;
}
throw new RuntimeException(
"Unknow field " + name + " in annotation " + type.toString()
+ ". This may happen if annotation class is changed but"
+ " parser is not.");
}
if(marker == null || scope == null || order == null) {
throw new RuntimeException(
"Missing field in annotation " + type.toString()
+ ". This may happen if annotation class is changed but"
+ " parser is not.");
}
return new MethodAnnotationData(type, marker, scope, order);
}
// TODO needed?
private Type internalNameToType(String classNameInternal) {
final char OBJ_BEGIN = 'L';
final char OBJ_END = ';';
return Type.getType(OBJ_BEGIN + classNameInternal + OBJ_END);
}
public List<Snippet> getSnippets() {
// TODO! implement
return null;
return snippets;
}
public List<Analyzer> getAnalyzers() {
// TODO implement
return null;
return analyzers;
}
}
package ch.usi.dag.disl.snippet;
import org.objectweb.asm.tree.InsnList;
import ch.usi.dag.disl.snippet.marker.Marker;
import ch.usi.dag.disl.snippet.scope.Scope;
public interface Snippet {
public Class<?> getAnnotationClass();
public Marker getMarker();
public Scope getScope();
public int getOrder();
public InsnList getAsmCode();
}
package ch.usi.dag.disl.snippet;
import org.objectweb.asm.tree.InsnList;
import ch.usi.dag.disl.snippet.marker.Marker;
import ch.usi.dag.disl.snippet.scope.Scope;
public class SnippetImpl {
public class SnippetImpl implements Snippet {
protected Class<?> annotationClass;
protected Marker marker;
protected Scope scope;
// TODO! protected ?Code? asmCode;
protected int order;
protected InsnList asmCode;
public SnippetImpl(Class<?> annotationClass, Marker marker, Scope scope,
int order, InsnList asmCode) {
super();
this.annotationClass = annotationClass;
this.marker = marker;
this.scope = scope;
this.order = order;
this.asmCode = asmCode;
}
public Class<?> getAnnotationClass() {
return annotationClass;
}
public Marker getMarker() {
return marker;
}
......@@ -16,4 +35,13 @@ public class SnippetImpl {
public Scope getScope() {
return scope;
}
public int getOrder() {
return order;
}
public InsnList getAsmCode() {
return asmCode;
}
}
package ch.usi.dag.disl.snippet.marker;
import org.objectweb.asm.Type;
public class MarkerFactory {
public static Marker createMarker(Type marker) {
// TODO! implement
// load class according to Type and instantiate
return null;
}
}
......@@ -4,6 +4,10 @@ import org.objectweb.asm.tree.MethodNode;
public class ScopeImpl implements Scope {
public ScopeImpl(String scopeExpression) {
// TODO implement
}
@Override
public boolean matches(MethodNode method) {
......
......@@ -12,6 +12,7 @@ import ch.usi.dag.disl.snippet.marker.MarkedRegion;
public class Weaver {
// TODO include analysis
// TODO support for synthetic local
public void instrument(ClassNode classNode,
Map<Snippet, List<MarkedRegion>> snippetMarkings) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment