blob: 825ad2e7fb18891acf1e90dbebd3fd3703d7f8fc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.api.tools.internal.comparator;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.pde.api.tools.internal.provisional.Factory;
import org.eclipse.pde.api.tools.internal.util.Util;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.util.TraceAnnotationVisitor;
/**
* Class adapter used to create all elements from a class file.
*/
class ClassFileDescriptorBuilder extends ClassAdapter {
TypeDescriptor descriptor;
ClassFileDescriptorBuilder(ClassVisitor cv, TypeDescriptor descriptor) {
super(cv);
this.descriptor = descriptor;
}
private void addDescriptor(Map map, String name, Object descriptor) {
Object object = map.get(name);
if (object != null) {
// already a method with the same descriptor
if (object instanceof List) {
((List) object).add(descriptor);
} else {
ArrayList list = new ArrayList();
list.add(object);
list.add(descriptor);
map.put(name, list);
}
} else {
map.put(name, descriptor);
}
}
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
this.descriptor.initialize(version, access, name, signature, superName, interfaces);
super.visit(version, access, name, signature, superName, interfaces);
}
public void visitInnerClass(String name, String outerName, String innerName, int access) {
super.visitInnerClass(name, outerName, innerName, access);
String currentName = name.replace('/', '.');
if (currentName.equals(this.descriptor.name)) {
this.descriptor.access = access;
// this is a nested type
if (outerName == null) {
// this is a local or an anonymous type
if (innerName == null) {
this.descriptor.setAnonymous();
} else {
this.descriptor.setLocal();
}
} else {
this.descriptor.setMember();
}
} else if (outerName != null && innerName != null) {
// technically speaking innerName != null is not necessary, but this is a workaround for some
// boggus synthetic types created by another compiler
String currentOuterName = outerName.replace('/', '.');
if (currentOuterName.equals(this.descriptor.name)) {
// this is a real type member defined in the descriptor (not just a reference to a type member)
this.descriptor.addTypeMember(currentName, access);
}
}
}
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
FieldDescriptor fieldDescriptor = new FieldDescriptor(access, name, desc, signature, value);
fieldDescriptor.handle = Factory.fieldDescriptor(this.descriptor.name, name);
addDescriptor(this.descriptor.fields, name, fieldDescriptor);
return null;
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
final MethodDescriptor methodDescriptor = new MethodDescriptor(access, name, desc, signature, exceptions);
methodDescriptor.handle = Factory.methodDescriptor(this.descriptor.name, name, Util.dequalifySignature(desc));
addDescriptor(this.descriptor.methods, name, methodDescriptor);
return new MethodAdapter(super.visitMethod(access, name, desc, signature, exceptions)) {
public AnnotationVisitor visitAnnotationDefault() {
return new TraceAnnotationVisitor() {
public void visitEnd() {
super.visitEnd();
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
print(writer);
writer.flush();
writer.close();
methodDescriptor.defaultValue = String.valueOf(stringWriter.getBuffer());
}
};
}
};
}
}