}
}
}
// Create "ClassFile" object.
ClassFile cf = new ClassFile(
(short) (cd.getModifiers() | Mod.SUPER), // accessFlags
iClass.getDescriptor(), // thisClassFD
iClass.getSuperclass().getDescriptor(), // superClassFD
IClass.getDescriptors(iClass.getInterfaces()) // interfaceFDs
);
// Add InnerClasses attribute entry for this class declaration.
if (cd.getEnclosingScope() instanceof Java.CompilationUnit) {
;
} else
if (cd.getEnclosingScope() instanceof Java.Block) {
short innerClassInfoIndex = cf.addConstantClassInfo(iClass.getDescriptor());
short innerNameIndex = (
this instanceof Java.NamedTypeDeclaration ?
cf.addConstantUtf8Info(((Java.NamedTypeDeclaration) this).getName()) :
(short) 0
);
cf.addInnerClassesAttributeEntry(new ClassFile.InnerClassesAttribute.Entry(
innerClassInfoIndex, // innerClassInfoIndex
(short) 0, // outerClassInfoIndex
innerNameIndex, // innerNameIndex
cd.getModifiers() // innerClassAccessFlags
));
} else
if (cd.getEnclosingScope() instanceof Java.TypeDeclaration) {
short innerClassInfoIndex = cf.addConstantClassInfo(iClass.getDescriptor());
short outerClassInfoIndex = cf.addConstantClassInfo(
this.resolve(((Java.TypeDeclaration) cd.getEnclosingScope())).getDescriptor()
);
short innerNameIndex = cf.addConstantUtf8Info(((Java.MemberTypeDeclaration) cd).getName());
cf.addInnerClassesAttributeEntry(new ClassFile.InnerClassesAttribute.Entry(
innerClassInfoIndex, // innerClassInfoIndex
outerClassInfoIndex, // outerClassInfoIndex
innerNameIndex, // innerNameIndex
cd.getModifiers() // innerClassAccessFlags
));
}
// Set "SourceFile" attribute.
if (this.debugSource) {
String sourceFileName;
{
String s = cd.getLocation().getFileName();
if (s != null) {
sourceFileName = new File(s).getName();
} else if (cd instanceof Java.NamedTypeDeclaration) {
sourceFileName = ((Java.NamedTypeDeclaration) cd).getName() + ".java";
} else {
sourceFileName = "ANONYMOUS.java";
}
}
cf.addSourceFileAttribute(sourceFileName);
}
// Add "Deprecated" attribute (JVMS 4.7.10)
if (cd instanceof Java.DocCommentable) {
if (((Java.DocCommentable) cd).hasDeprecatedDocTag()) cf.addDeprecatedAttribute();
}
// Optional: Generate and compile class initialization method.
{
List/*<BlockStatement>*/ statements = new ArrayList();
for (Iterator it = cd.variableDeclaratorsAndInitializers.iterator(); it.hasNext();) {
Java.TypeBodyDeclaration tbd = (Java.TypeBodyDeclaration) it.next();
if (tbd.isStatic()) statements.add((Java.BlockStatement) tbd);
}
this.maybeCreateInitMethod(cd, cf, statements);
}
this.compileDeclaredMethods(cd, cf);
// Compile declared constructors.
// As a side effect of compiling methods and constructors, synthetic "class-dollar"
// methods (which implement class literals) are generated on-the fly.
// We need to note how many we have here so we can compile the extras.
int declaredMethodCount = cd.getMethodDeclarations().size();
{
int syntheticFieldCount = cd.syntheticFields.size();
Java.ConstructorDeclarator[] cds = cd.getConstructors();
for (int i = 0; i < cds.length; ++i) {
this.compile(cds[i], cf);
if (syntheticFieldCount != cd.syntheticFields.size()) {
throw new JaninoRuntimeException(
"SNO: Compilation of constructor \""
+ cds[i]
+ "\" ("
+ cds[i].getLocation()
+ ") added synthetic fields!?"
);
}
}
}
// A side effect of this call may create synthetic functions to access
// protected parent variables
this.compileDeclaredMemberTypes(cd, cf);
// Compile the aforementioned extras.
this.compileDeclaredMethods(cd, cf, declaredMethodCount);
{
// for every method look for bridge methods that need to be supplied
// this is used to correctly dispatch into covariant return types
// from existing code
IMethod[] ms = iClass.getIMethods();
for (int i = 0; i < ms.length; ++i) {
IMethod base = ms[i];
if (! base.isStatic()) {
IMethod override = iClass.findIMethod(base.getName(), base.getParameterTypes());
// if we overrode the method but with a DIFFERENT return type
if (override != null &&
! base.getReturnType().equals(override.getReturnType())) {
this.compileBridgeMethod(cf, base, override);
}
}
}
}
// Class and instance variables.
for (Iterator it = cd.variableDeclaratorsAndInitializers.iterator(); it.hasNext();) {
Java.TypeBodyDeclaration tbd = (Java.TypeBodyDeclaration) it.next();
if (!(tbd instanceof Java.FieldDeclaration)) continue;
this.addFields((Java.FieldDeclaration) tbd, cf);
}
// Synthetic fields.
for (Iterator it = cd.syntheticFields.values().iterator(); it.hasNext();) {
IClass.IField f = (IClass.IField) it.next();
cf.addFieldInfo(
Mod.PACKAGE, // modifiers,
f.getName(), // fieldName,
f.getType().getDescriptor(), // fieldTypeFD,
null // optionalConstantValue
);