123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- /* *******************************************************************
- * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
- * 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:
- * PARC initial implementation
- * ******************************************************************/
-
- package org.aspectj.ajdt.internal.compiler.ast;
-
- import java.lang.reflect.Modifier;
-
- import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
- import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger;
- import org.aspectj.ajdt.internal.compiler.lookup.PrivilegedFieldBinding;
- import org.aspectj.ajdt.internal.compiler.lookup.PrivilegedHandler;
- import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
- import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
- import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
- import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
- import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
- import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
- import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
- import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
- import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
- import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Statement;
- import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
- import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.CodeStream;
- import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.Opcodes;
- import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
- import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
- import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
- import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
- import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
- import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
- import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
- import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
- import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser;
- import org.aspectj.weaver.AjAttribute;
- import org.aspectj.weaver.AjcMemberMaker;
- import org.aspectj.weaver.Member;
- import org.aspectj.weaver.NameMangler;
- import org.aspectj.weaver.NewFieldTypeMunger;
- import org.aspectj.weaver.ResolvedMember;
- import org.aspectj.weaver.ResolvedMemberImpl;
- import org.aspectj.weaver.ResolvedType;
- import org.aspectj.weaver.Shadow;
- import org.aspectj.weaver.UnresolvedType;
-
- /**
- * An inter-type field declaration.
- *
- * returnType encodes the type of the field selector encodes the name statements is null until resolution when it is filled in from
- * the initializer
- *
- * @author Jim Hugunin
- */
- public class InterTypeFieldDeclaration extends InterTypeDeclaration {
- public Expression initialization;
- private TypeBinding realFieldType;
-
- // public InterTypeFieldBinding interBinding;
-
- public InterTypeFieldDeclaration(CompilationResult result, TypeReference onType) {
- super(result, onType);
- }
-
- public TypeBinding getRealFieldType() {
- return realFieldType;
- }
-
- public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
- // we don't have a body to parse
- }
-
- protected char[] getPrefix() {
- return (NameMangler.ITD_PREFIX + "interField$").toCharArray();
- }
-
- public void resolveOnType(ClassScope classScope) {
- super.resolveOnType(classScope);
- if (ignoreFurtherInvestigation) {
- return;
- }
- if (Modifier.isStatic(declaredModifiers) && onTypeBinding.isInterface()) {
- scope.problemReporter().signalError(sourceStart, sourceEnd, "static inter-type field on interface not supported");
- ignoreFurtherInvestigation = true;
- }
- if (Modifier.isStatic(declaredModifiers) && typeVariableAliases != null && typeVariableAliases.size() > 0
- && onTypeBinding.isGenericType()) {
- scope.problemReporter().signalError(sourceStart, sourceEnd,
- "static intertype field declarations cannot refer to type variables from the target generic type");
- }
-
- }
-
- public void resolve(ClassScope upperScope) {
- if (munger == null) {
- ignoreFurtherInvestigation = true;
- }
- if (ignoreFurtherInvestigation) {
- return;
- }
-
- EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(upperScope);
- ResolvedMember sig = munger.getSignature();
- UnresolvedType aspectType = world.fromBinding(upperScope.referenceContext.binding);
-
- if (sig.getReturnType().equals(UnresolvedType.VOID)
- || (sig.getReturnType().isArray() && (sig.getReturnType().getComponentType().equals(UnresolvedType.VOID)))) {
- upperScope.problemReporter().signalError(sourceStart, sourceEnd, "field type can not be void");
- }
-
- //
- // System.err.println("sig: " + sig);
- // System.err.println("field: " + world.makeFieldBinding(
- // AjcMemberMaker.interFieldClassField(sig, aspectType)));
-
- if (initialization != null && initialization instanceof ArrayInitializer) {
- // System.err.println("got initializer: " + initialization);
- ArrayAllocationExpression aae = new ArrayAllocationExpression();
- aae.initializer = (ArrayInitializer) initialization;
- ArrayBinding arrayType = (ArrayBinding) world.makeTypeBinding(sig.getReturnType());
- aae.type = AstUtil.makeTypeReference(arrayType.leafComponentType());
- aae.sourceStart = initialization.sourceStart;
- aae.sourceEnd = initialization.sourceEnd;
- aae.dimensions = new Expression[arrayType.dimensions];
- initialization = aae;
- } /*
- * else if (initialization!=null) { MethodScope initializationScope = this.scope; TypeBinding fieldType = realFieldType;
- * TypeBinding initializationType; this.initialization.setExpectedType(fieldType); // needed in case of generic method
- * invocation if (this.initialization instanceof ArrayInitializer) {
- *
- * if ((initializationType = this.initialization.resolveTypeExpecting(initializationScope, fieldType)) != null) {
- * ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationType;
- * this.initialization.computeConversion(initializationScope, fieldType, initializationType); } } //
- * System.err.println("i=>"+initialization); // System.err.println("sasuages=>"+initialization.resolvedType); //
- * //initializationType = initialization.resolveType(initializationScope); //
- * System.err.println("scope=>"+initializationScope);
- *
- * else if ((initializationType = this.initialization.resolveType(initializationScope)) != null) {
- *
- * if (fieldType != initializationType) // must call before computeConversion() and typeMismatchError()
- * initializationScope.compilationUnitScope().recordTypeConversion(fieldType, initializationType); if
- * (this.initialization.isConstantValueOfTypeAssignableToType(initializationType, fieldType) || (fieldType.isBaseType() &&
- * BaseTypeBinding.isWidening(fieldType.id, initializationType.id)) || initializationType.isCompatibleWith(fieldType)) {
- * initialization.computeConversion(initializationScope, fieldType, initializationType); if
- * (initializationType.needsUncheckedConversion(fieldType)) {
- * initializationScope.problemReporter().unsafeTypeConversion(this.initialization, initializationType, fieldType); } } else
- * if (initializationScope.isBoxingCompatibleWith(initializationType, fieldType) || (initializationType.isBaseType() //
- * narrowing then boxing ? && initializationScope.compilerOptions().sourceLevel >= JDK1_5 // autoboxing &&
- * !fieldType.isBaseType() && initialization.isConstantValueOfTypeAssignableToType(initializationType,
- * initializationScope.environment().computeBoxingType(fieldType)))) {
- * this.initialization.computeConversion(initializationScope, fieldType, initializationType); } else {
- * initializationScope.problemReporter().typeMismatchError(initializationType, fieldType, this); } // if
- * (this.binding.isFinal()){ // cast from constant actual type to variable type //
- * this.binding.setConstant(this.initialization.constant.castTo((this.binding.returnType.id << 4) +
- * this.initialization.constant.typeID())); // } // } else { // this.binding.setConstant(NotAConstant); } // }
- */
-
- // ////////////////////
-
- if (initialization == null) {
- this.statements = new Statement[] { new ReturnStatement(null, 0, 0), };
- } else if (!onTypeBinding.isInterface()) {
- MethodBinding writeMethod = world.makeMethodBinding(AjcMemberMaker.interFieldSetDispatcher(sig, aspectType),
- munger.getTypeVariableAliases());
- // For the body of an intertype field initalizer, generate a call to the inter field set dispatcher
- // method as that casts the shadow of a field set join point.
- if (Modifier.isStatic(declaredModifiers)) {
- this.statements = new Statement[] { new KnownMessageSend(writeMethod,
- AstUtil.makeNameReference(writeMethod.declaringClass), new Expression[] { initialization }), };
- } else {
- this.statements = new Statement[] { new KnownMessageSend(writeMethod,
- AstUtil.makeNameReference(writeMethod.declaringClass), new Expression[] {
- AstUtil.makeLocalVariableReference(arguments[0].binding), initialization }), };
- }
- } else {
- // XXX something is broken about this logic. Can we write to static interface fields?
- MethodBinding writeMethod = world.makeMethodBinding(
- AjcMemberMaker.interFieldInterfaceSetter(sig, sig.getDeclaringType().resolve(world.getWorld()), aspectType),
- munger.getTypeVariableAliases());
- if (Modifier.isStatic(declaredModifiers)) {
- this.statements = new Statement[] { new KnownMessageSend(writeMethod,
- AstUtil.makeNameReference(writeMethod.declaringClass), new Expression[] { initialization }), };
- } else {
- this.statements = new Statement[] { new KnownMessageSend(writeMethod,
- AstUtil.makeLocalVariableReference(arguments[0].binding), new Expression[] { initialization }), };
- }
- }
-
- super.resolve(upperScope);
- }
-
- public void setInitialization(Expression initialization) {
- this.initialization = initialization;
-
- }
-
- /*
- * public void resolveStatements() { super.resolveStatements();
- *
- * // if (initialization!=null) { // MethodScope initializationScope = this.scope; // TypeBinding fieldType = realFieldType; //
- * TypeBinding initializationType; // this.initialization.setExpectedType(fieldType); // needed in case of generic method
- * invocation // if (this.initialization instanceof ArrayInitializer) { // // if ((initializationType =
- * this.initialization.resolveTypeExpecting(initializationScope, fieldType)) != null) { // ((ArrayInitializer)
- * this.initialization).binding = (ArrayBinding) initializationType; //
- * this.initialization.computeConversion(initializationScope, fieldType, initializationType); // } // } ////
- * System.err.println("i=>"+initialization); //// System.err.println("sasuages=>"+initialization.resolvedType); ////
- * //initializationType = initialization.resolveType(initializationScope); ////
- * System.err.println("scope=>"+initializationScope); // // else if ((initializationType =
- * this.initialization.resolveType(initializationScope)) != null) { // // if (fieldType != initializationType) // must call
- * before computeConversion() and typeMismatchError() //
- * initializationScope.compilationUnitScope().recordTypeConversion(fieldType, initializationType); // if
- * (this.initialization.isConstantValueOfTypeAssignableToType(initializationType, fieldType) // || (fieldType.isBaseType() &&
- * BaseTypeBinding.isWidening(fieldType.id, initializationType.id)) // || initializationType.isCompatibleWith(fieldType)) { //
- * initialization.computeConversion(initializationScope, fieldType, initializationType); // if
- * (initializationType.needsUncheckedConversion(fieldType)) { //
- * initializationScope.problemReporter().unsafeTypeConversion(this.initialization, initializationType, fieldType); // } // }
- * else if (initializationScope.isBoxingCompatibleWith(initializationType, fieldType) // || (initializationType.isBaseType() //
- * narrowing then boxing ? // && initializationScope.compilerOptions().sourceLevel >= JDK1_5 // autoboxing // &&
- * !fieldType.isBaseType() // && initialization.isConstantValueOfTypeAssignableToType(initializationType,
- * initializationScope.environment().computeBoxingType(fieldType)))) { //
- * this.initialization.computeConversion(initializationScope, fieldType, initializationType); // } else { //
- * initializationScope.problemReporter().typeMismatchError(initializationType, fieldType, this); // } // // if
- * (this.binding.isFinal()){ // cast from constant actual type to variable type // //
- * this.binding.setConstant(this.initialization.constant.castTo((this.binding.returnType.id << 4) +
- * this.initialization.constant.typeID())); // // } // // } else { // // this.binding.setConstant(NotAConstant); // }}
- *
- * }
- */
- public EclipseTypeMunger build(ClassScope classScope) {
- EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
- resolveOnType(classScope);
-
- if (ignoreFurtherInvestigation) {
- return null;
- }
-
- binding = classScope.referenceContext.binding.resolveTypesFor(binding);
- if (ignoreFurtherInvestigation) {
- return null;
- }
-
- if (isTargetAnnotation(classScope, "field")) {
- return null; // Error message output in isTargetAnnotation
- }
- if (isTargetEnum(classScope, "field")) {
- return null; // Error message output in isTargetEnum
- }
-
- if (!Modifier.isStatic(declaredModifiers)) {
- super.binding.parameters = new TypeBinding[] { onTypeBinding, };
- this.arguments = new Argument[] { AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding), };
- }
-
- // System.err.println("type: " + binding.returnType + ", " + returnType);
- ResolvedType declaringType = world.fromBinding(onTypeBinding).resolve(world.getWorld());
- if (declaringType.isRawType() || declaringType.isParameterizedType()) {
- declaringType = declaringType.getGenericType();
- }
-
- if (interTypeScope == null) {
- return null; // We encountered a problem building the scope, don't continue - error already reported
- }
-
- // Build a half correct resolvedmember (makeResolvedMember understands tvars) then build a fully correct sig from it
- ResolvedMember sigtemp = world.makeResolvedMemberForITD(binding, onTypeBinding, interTypeScope.getRecoveryAliases());
- UnresolvedType returnType = sigtemp.getReturnType();
- // if (returnType.isParameterizedType() || returnType.isGenericType()) returnType = returnType.getRawType();
- ResolvedMember sig = new ResolvedMemberImpl(Member.FIELD, declaringType, declaredModifiers, returnType, new String(
- declaredSelector), UnresolvedType.NONE);
- sig.setTypeVariables(sigtemp.getTypeVariables());
-
- NewFieldTypeMunger myMunger = new NewFieldTypeMunger(sig, null, typeVariableAliases);
- setMunger(myMunger);
- ResolvedType aspectType = world.fromEclipse(classScope.referenceContext.binding);
- ResolvedMember me = myMunger.getInitMethod(aspectType);
- this.selector = binding.selector = me.getName().toCharArray();
- this.realFieldType = this.binding.returnType;
- this.binding.returnType = TypeBinding.VOID;
- // ??? all other pieces should already match
-
- return new EclipseTypeMunger(world, myMunger, aspectType, this);
- }
-
- private AjAttribute makeAttribute() {
- return new AjAttribute.TypeMunger(munger);
- }
-
- public void generateCode(ClassScope classScope, ClassFile classFile) {
- if (ignoreFurtherInvestigation) {
- return;
- }
-
- classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute()));
- super.generateCode(classScope, classFile);
- generateDispatchMethods(classScope, classFile);
- // interBinding.reader.generateMethod(this, classScope, classFile);
- // interBinding.writer.generateMethod(this, classScope, classFile);
- }
-
- private void generateDispatchMethods(ClassScope classScope, ClassFile classFile) {
- EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
- ResolvedMember sig = munger.getSignature();
- UnresolvedType aspectType = world.fromBinding(classScope.referenceContext.binding);
- generateDispatchMethod(world, sig, aspectType, classScope, classFile, true);
- generateDispatchMethod(world, sig, aspectType, classScope, classFile, false);
- }
-
- private void generateDispatchMethod(EclipseFactory world, ResolvedMember sig, UnresolvedType aspectType, ClassScope classScope,
- ClassFile classFile, boolean isGetter) {
- MethodBinding binding;
- if (isGetter) {
- binding = world.makeMethodBinding(AjcMemberMaker.interFieldGetDispatcher(sig, aspectType),
- munger.getTypeVariableAliases(), munger.getSignature().getDeclaringType());
- } else {
- binding = world.makeMethodBinding(AjcMemberMaker.interFieldSetDispatcher(sig, aspectType),
- munger.getTypeVariableAliases(), munger.getSignature().getDeclaringType());
- }
- classFile.generateMethodInfoHeader(binding);
- int methodAttributeOffset = classFile.contentsOffset;
- int attributeNumber = classFile.generateMethodInfoAttributes(binding, makeEffectiveSignatureAttribute(sig, isGetter ? Shadow.FieldGet : Shadow.FieldSet, false));
- int codeAttributeOffset = classFile.contentsOffset;
- classFile.generateCodeAttributeHeader();
- CodeStream codeStream = classFile.codeStream;
- codeStream.reset(this, classFile);
-
- NewFieldTypeMunger fieldMunger = (NewFieldTypeMunger) munger;
-
- // Force use of version 1 if there is a field with that name on the type already
- if (world.getItdVersion() == 1) {
- fieldMunger.version = NewFieldTypeMunger.VersionOne;
- } else {
- if (!onTypeBinding.isInterface()) {
- FieldBinding[] existingFields = onTypeBinding.fields();
- for (int f = 0; f < existingFields.length; f++) {
- FieldBinding fieldBinding = existingFields[f];
- if (CharOperation.equals(fieldBinding.name, sig.getName().toCharArray())) {
- fieldMunger.version = NewFieldTypeMunger.VersionOne;
- }
- }
- }
- }
-
- FieldBinding classField = world.makeFieldBinding(
- AjcMemberMaker.interFieldClassField(sig, aspectType, fieldMunger.version == NewFieldTypeMunger.VersionTwo),
- munger.getTypeVariableAliases());
-
- codeStream.initializeMaxLocals(binding);
- if (isGetter) {
- if (onTypeBinding.isInterface()) {
- UnresolvedType declaringTX = sig.getDeclaringType();
- ResolvedType declaringRTX = world.getWorld().resolve(declaringTX, munger.getSourceLocation());
- MethodBinding readMethod = world.makeMethodBinding(
- AjcMemberMaker.interFieldInterfaceGetter(sig, declaringRTX, aspectType), munger.getTypeVariableAliases());
- generateInterfaceReadBody(binding, readMethod, codeStream);
- } else {
- generateClassReadBody(binding, classField, codeStream);
- }
- } else {
- if (onTypeBinding.isInterface()) {
- MethodBinding writeMethod = world.makeMethodBinding(
- AjcMemberMaker.interFieldInterfaceSetter(sig,
- world.getWorld().resolve(sig.getDeclaringType(), munger.getSourceLocation()), aspectType),
- munger.getTypeVariableAliases());
- generateInterfaceWriteBody(binding, writeMethod, codeStream);
- } else {
- generateClassWriteBody(binding, classField, codeStream);
- }
- }
- AstUtil.generateReturn(binding.returnType, codeStream);
-
- classFile.completeCodeAttribute(codeAttributeOffset);
- attributeNumber++;
- classFile.completeMethodInfo(binding,methodAttributeOffset, attributeNumber);
- }
-
- private void generateInterfaceReadBody(MethodBinding binding, MethodBinding readMethod, CodeStream codeStream) {
- codeStream.aload_0();
- codeStream.invoke(Opcodes.OPC_invokeinterface,readMethod,null);
- }
-
- private void generateInterfaceWriteBody(MethodBinding binding, MethodBinding writeMethod, CodeStream codeStream) {
- codeStream.aload_0();
- codeStream.load(writeMethod.parameters[0], 1);
- codeStream.invoke(Opcodes.OPC_invokeinterface, writeMethod, null);
- }
-
- private void generateClassReadBody(MethodBinding binding, FieldBinding field, CodeStream codeStream) {
- if (field.isPrivate() || !field.canBeSeenBy(binding.declaringClass.fPackage)) {
-
- PrivilegedHandler handler = (PrivilegedHandler) Scope.findPrivilegedHandler(binding.declaringClass);
- if (handler == null) {
- // one is now required!
- ReferenceBinding typebinding = binding.declaringClass;
- if (typebinding instanceof ReferenceBinding) {
- SourceTypeBinding sourceBinding = (SourceTypeBinding) typebinding;
- handler = new PrivilegedHandler((AspectDeclaration) sourceBinding.scope.referenceContext);
- sourceBinding.privilegedHandler = handler;
- }
- }
- PrivilegedFieldBinding fBinding = (PrivilegedFieldBinding) handler.getPrivilegedAccessField(field, null);
-
- if (field.isStatic()) {
- codeStream.invoke(Opcodes.OPC_invokestatic,fBinding.reader,null);
- } else {
- codeStream.aload_0();
- codeStream.invoke(Opcodes.OPC_invokestatic,fBinding.reader,null);
- }
- return;
- }
- if (field.isStatic()) {
- codeStream.fieldAccess(Opcodes.OPC_getstatic,field,null);
- } else {
- codeStream.aload_0();
- codeStream.fieldAccess(Opcodes.OPC_getfield,field,null);
- }
- }
-
- private void generateClassWriteBody(MethodBinding binding, FieldBinding field, CodeStream codeStream) {
- if (field.isPrivate() || !field.canBeSeenBy(binding.declaringClass.fPackage)) {
- PrivilegedFieldBinding fBinding = (PrivilegedFieldBinding) Scope.findPrivilegedHandler(binding.declaringClass)
- .getPrivilegedAccessField(field, null);
- if (field.isStatic()) {
- codeStream.load(field.type, 0);
- codeStream.invoke(Opcodes.OPC_invokestatic,fBinding.writer,null);
- } else {
- codeStream.aload_0();
- codeStream.load(field.type, 1);
- codeStream.invoke(Opcodes.OPC_invokestatic,fBinding.writer,null);
- }
- return;
- }
- if (field.isStatic()) {
- codeStream.load(field.type, 0);
- codeStream.fieldAccess(Opcodes.OPC_putstatic,field,null);
- } else {
- codeStream.aload_0();
- codeStream.load(field.type, 1);
- codeStream.fieldAccess(Opcodes.OPC_putfield,field,null);
- }
- }
-
- protected Shadow.Kind getShadowKindForBody() {
- return null;
- }
-
- }
|