blob: 18298779e7e2f8390d3bfcc68bb0e2ce6cd60748 [file] [log] [blame]
package org.eclipse.jdt.internal.eval;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.lookup.*;
public class CodeSnippetClassFile extends ClassFile {
/**
* CodeSnippetClassFile constructor comment.
* @param aType org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding
* @param enclosingClassFile org.eclipse.jdt.internal.compiler.ClassFile
* @param creatingProblemType boolean
*/
public CodeSnippetClassFile(
org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding aType,
org.eclipse.jdt.internal.compiler.ClassFile enclosingClassFile,
boolean creatingProblemType) {
/**
* INTERNAL USE-ONLY
* This methods creates a new instance of the receiver.
*
* @param aType org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding
* @param enclosingClassFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
* @param creatingProblemType <CODE>boolean</CODE>
*/
referenceBinding = aType;
header = new byte[INITIAL_HEADER_SIZE];
// generate the magic numbers inside the header
header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
if (((SourceTypeBinding) referenceBinding).scope.environment().options.targetJDK >= CompilerOptions.JDK1_2) {
// Compatible with JDK 1.2
header[headerOffset++] = 0;
// minorVersion = 0 means we just need to offset the current offset by 2
header[headerOffset++] = 0;
header[headerOffset++] = 0;
header[headerOffset++] = 46;
} else {
// Compatible with JDK 1.1
header[headerOffset++] = 0;
header[headerOffset++] = 3;
header[headerOffset++] = 0;
header[headerOffset++] = 45;
}
constantPoolOffset = headerOffset;
headerOffset += 2;
constantPool = new CodeSnippetConstantPool(this);
int accessFlags = aType.getAccessFlags() | AccSuper;
if (aType.isNestedType()) {
if (aType.isStatic()) {
// clear Acc_Static
accessFlags &= ~AccStatic;
}
if (aType.isPrivate()) {
// clear Acc_Private and Acc_Public
accessFlags &= ~(AccPrivate | AccPublic);
}
if (aType.isProtected()) {
// clear Acc_Protected and set Acc_Public
accessFlags &= ~AccProtected;
accessFlags |= AccPublic;
}
}
// clear Acc_Strictfp
accessFlags &= ~AccStrictfp;
this.enclosingClassFile = enclosingClassFile;
// innerclasses get their names computed at code gen time
if (aType.isLocalType()) {
((LocalTypeBinding) aType).constantPoolName(
computeConstantPoolName((LocalTypeBinding) aType));
ReferenceBinding[] memberTypes = aType.memberTypes();
for (int i = 0, max = memberTypes.length; i < max; i++) {
((LocalTypeBinding) memberTypes[i]).constantPoolName(
computeConstantPoolName((LocalTypeBinding) memberTypes[i]));
}
}
contents = new byte[INITIAL_CONTENTS_SIZE];
// now we continue to generate the bytes inside the contents array
contents[contentsOffset++] = (byte) (accessFlags >> 8);
contents[contentsOffset++] = (byte) accessFlags;
int classNameIndex = constantPool.literalIndex(aType);
contents[contentsOffset++] = (byte) (classNameIndex >> 8);
contents[contentsOffset++] = (byte) classNameIndex;
int superclassNameIndex;
if (aType.isInterface()) {
superclassNameIndex = constantPool.literalIndexForJavaLangObject();
} else {
superclassNameIndex =
(aType.superclass == null ? 0 : constantPool.literalIndex(aType.superclass));
}
contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
contents[contentsOffset++] = (byte) superclassNameIndex;
ReferenceBinding[] superInterfacesBinding = aType.superInterfaces();
int interfacesCount = superInterfacesBinding.length;
contents[contentsOffset++] = (byte) (interfacesCount >> 8);
contents[contentsOffset++] = (byte) interfacesCount;
if (superInterfacesBinding != null) {
for (int i = 0; i < interfacesCount; i++) {
int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
contents[contentsOffset++] = (byte) interfaceIndex;
}
}
produceDebugAttributes =
((SourceTypeBinding) referenceBinding)
.scope
.environment()
.options
.produceDebugAttributes;
innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
this.creatingProblemType = creatingProblemType;
codeStream = new CodeSnippetCodeStream(this);
// retrieve the enclosing one guaranteed to be the one matching the propagated flow info
// 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
ClassFile outermostClassFile = this.outerMostEnclosingClassFile();
if (this == outermostClassFile) {
codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
} else {
codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
}
}
/**
* INTERNAL USE-ONLY
* Request the creation of a ClassFile compatible representation of a problematic type
*
* @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
* @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
*/
public static void createProblemType(TypeDeclaration typeDeclaration, CompilationResult unitResult) {
SourceTypeBinding typeBinding = typeDeclaration.binding;
ClassFile classFile = new CodeSnippetClassFile(typeBinding, null, true);
// inner attributes
if (typeBinding.isMemberType())
classFile.recordEnclosingTypeAttributes(typeBinding);
// add its fields
FieldBinding[] fields = typeBinding.fields;
if ((fields != null) && (fields != NoFields)) {
for (int i = 0, max = fields.length; i < max; i++) {
if (fields[i].constant == null) {
FieldReference.getConstantFor(fields[i], false, null, null, 0);
}
}
classFile.addFieldInfos();
} else {
// we have to set the number of fields to be equals to 0
classFile.contents[classFile.contentsOffset++] = 0;
classFile.contents[classFile.contentsOffset++] = 0;
}
// leave some space for the methodCount
classFile.setForMethodInfos();
// add its user defined methods
MethodBinding[] methods = typeBinding.methods;
AbstractMethodDeclaration[] methodDeclarations = typeDeclaration.methods;
int maxMethodDecl = methodDeclarations == null ? 0 : methodDeclarations.length;
int problemsLength;
IProblem[] problems = unitResult.getProblems();
if (problems == null) {
problems = new IProblem[0];
}
IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
if (methods != null) {
if (typeBinding.isInterface()) {
// we cannot create problem methods for an interface. So we have to generate a clinit
// which should contain all the problem
classFile.addProblemClinit(problemsCopy);
for (int i = 0, max = methods.length; i < max; i++) {
MethodBinding methodBinding;
if ((methodBinding = methods[i]) != null) {
// find the corresponding method declaration
for (int j = 0; j < maxMethodDecl; j++) {
if ((methodDeclarations[j] != null) && (methodDeclarations[j].binding == methods[i])) {
if (!methodBinding.isConstructor()) {
classFile.addAbstractMethod(methodDeclarations[j], methodBinding);
}
break;
}
}
}
}
} else {
for (int i = 0, max = methods.length; i < max; i++) {
MethodBinding methodBinding;
if ((methodBinding = methods[i]) != null) {
// find the corresponding method declaration
for (int j = 0; j < maxMethodDecl; j++) {
if ((methodDeclarations[j] != null) && (methodDeclarations[j].binding == methods[i])) {
AbstractMethodDeclaration methodDecl;
if ((methodDecl = methodDeclarations[j]).isConstructor()) {
classFile.addProblemConstructor(methodDecl, methodBinding, problemsCopy);
} else {
classFile.addProblemMethod(methodDecl, methodBinding, problemsCopy);
}
break;
}
}
}
}
}
// add abstract methods
classFile.addDefaultAbstractMethods();
}
// propagate generation of (problem) member types
if (typeDeclaration.memberTypes != null) {
for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
TypeDeclaration memberType = typeDeclaration.memberTypes[i];
if (memberType.binding != null) {
classFile.recordNestedMemberAttribute(memberType.binding);
ClassFile.createProblemType(memberType, unitResult);
}
}
}
classFile.addAttributes();
unitResult.record(typeBinding.constantPoolName(), classFile);
}
}