* PARC initial implementation
* ******************************************************************/
-
package org.aspectj.ajdt.internal.compiler.ast;
import java.lang.reflect.Modifier;
-import org.aspectj.ajdt.internal.compiler.lookup.*;
+
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation;
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger;
+import org.aspectj.ajdt.internal.compiler.lookup.InterTypeScope;
import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.weaver.*;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
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.*;
+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.CastExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NullLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.*;
+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.LocalVariableBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedMethodBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.Constants;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.NewConstructorTypeMunger;
+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 constructor declaration.
*
- * This will generate two implementation methods in the aspect, the main one for the body
- * of the constructor, and an additional <code>preMethod</code> for the code that
- * runs before the super constructor is called.
+ * This will generate two implementation methods in the aspect, the main one for the body of the constructor, and an additional
+ * <code>preMethod</code> for the code that runs before the super constructor is called.
*
* @author Jim Hugunin
*/
-public class InterTypeConstructorDeclaration extends InterTypeDeclaration {
+public class InterTypeConstructorDeclaration extends InterTypeDeclaration {
private static final String SUPPRESSAJWARNINGS = "Lorg/aspectj/lang/annotation/SuppressAjWarnings;";
private static final String NOEXPLICITCONSTRUCTORCALL = "noExplicitConstructorCall";
private MethodDeclaration preMethod;
private ExplicitConstructorCall explicitConstructorCall = null;
-
+
public InterTypeConstructorDeclaration(CompilationResult result, TypeReference onType) {
super(result, onType);
}
-
+
public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
if (ignoreFurtherInvestigation)
return;
- parser.parse(this, unit);
+ parser.parse(this, unit);
}
-
+
protected char[] getPrefix() {
return (NameMangler.ITD_PREFIX + "interConstructor$").toCharArray();
}
public void resolve(ClassScope upperScope) {
- if (munger == null || binding == null) ignoreFurtherInvestigation = true;
- if (ignoreFurtherInvestigation) return;
+ if (munger == null || binding == null)
+ ignoreFurtherInvestigation = true;
+ if (ignoreFurtherInvestigation)
+ return;
explicitConstructorCall = null;
- if (statements != null && statements.length > 0 &&
- statements[0] instanceof ExplicitConstructorCall)
- {
+ if (statements != null && statements.length > 0 && statements[0] instanceof ExplicitConstructorCall) {
explicitConstructorCall = (ExplicitConstructorCall) statements[0];
statements = AstUtil.remove(0, statements);
}
-
+
preMethod = makePreMethod(upperScope, explicitConstructorCall);
-
- binding.parameters = AstUtil.insert(onTypeBinding, binding.parameters);
- this.arguments = AstUtil.insert(
- AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding),
- this.arguments);
-
+
+ binding.parameters = AstUtil.insert(onTypeBinding, binding.parameters);
+ this.arguments = AstUtil.insert(AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding), this.arguments);
+
super.resolve(upperScope);
-
+
// after annotations have been resolved...
if (explicitConstructorCall == null) {
raiseNoFieldInitializersWarning();
}
/**
- * Warning added in response to PR 62606 - if an ITD constructor does not make an explicit constructor
- * call then field initializers in the target class will not be executed leading to unexpected behaviour.
+ * Warning added in response to PR 62606 - if an ITD constructor does not make an explicit constructor call then field
+ * initializers in the target class will not be executed leading to unexpected behaviour.
*/
private void raiseNoFieldInitializersWarning() {
- if (suppressingNoExplicitConstructorCall()) return;
+ if (suppressingNoExplicitConstructorCall())
+ return;
EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(scope);
- ISourceLocation location =
- new EclipseSourceLocation(scope.problemReporter().referenceContext.compilationResult(),
- sourceStart(),sourceEnd());
+ ISourceLocation location = new EclipseSourceLocation(scope.problemReporter().referenceContext.compilationResult(),
+ sourceStart(), sourceEnd());
world.getWorld().getLint().noExplicitConstructorCall.signal(null, location);
}
-
+
/**
* true iff constructor has @SuppressAjWarnings or @SuppressAjWarnings("xyz,noExplicitConstructorCall,def,...")
+ *
* @return
*/
private boolean suppressingNoExplicitConstructorCall() {
- if (this.annotations == null) return false;
+ if (this.annotations == null)
+ return false;
for (int i = 0; i < this.annotations.length; i++) {
if (new String(this.annotations[i].resolvedType.signature()).equals(SUPPRESSAJWARNINGS)) {
if (this.annotations[i] instanceof MarkerAnnotation) {
return true;
- } else if (this.annotations[i] instanceof SingleMemberAnnotation){
+ } else if (this.annotations[i] instanceof SingleMemberAnnotation) {
SingleMemberAnnotation sma = (SingleMemberAnnotation) this.annotations[i];
if (sma.memberValue instanceof ArrayInitializer) {
ArrayInitializer memberValue = (ArrayInitializer) sma.memberValue;
for (int j = 0; j < memberValue.expressions.length; j++) {
if (memberValue.expressions[j] instanceof StringLiteral) {
StringLiteral val = (StringLiteral) memberValue.expressions[j];
- if (new String(val.source()).equals(NOEXPLICITCONSTRUCTORCALL)) return true;
+ if (new String(val.source()).equals(NOEXPLICITCONSTRUCTORCALL))
+ return true;
}
}
}
}
return false;
}
-
- private MethodDeclaration makePreMethod(ClassScope scope,
- ExplicitConstructorCall explicitConstructorCall)
- {
+
+ private MethodDeclaration makePreMethod(ClassScope scope, ExplicitConstructorCall explicitConstructorCall) {
EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(scope);
-
+
UnresolvedType aspectTypeX = world.fromBinding(binding.declaringClass);
UnresolvedType targetTypeX = world.fromBinding(onTypeBinding);
-
+
ArrayBinding objectArrayBinding = scope.createArrayType(scope.getJavaLangObject(), 1);
-
-
+
MethodDeclaration pre = new MethodDeclaration(compilationResult);
pre.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic;
pre.returnType = AstUtil.makeTypeReference(objectArrayBinding);
pre.selector = NameMangler.postIntroducedConstructor(aspectTypeX, targetTypeX).toCharArray();
-
-
+
pre.arguments = AstUtil.copyArguments(this.arguments);
-
- //XXX should do exceptions
-
+
+ // XXX should do exceptions
+
pre.scope = new MethodScope(scope, pre, true);
- //??? do we need to do anything with scope???
-
-
+ // ??? do we need to do anything with scope???
- // Use the factory to build a semi-correct resolvedmember - then patch it up with
- // reset calls. This is SAFE
+ // Use the factory to build a semi-correct resolvedmember - then patch it up with
+ // reset calls. This is SAFE
ResolvedMember preIntroducedConstructorRM = world.makeResolvedMember(binding);
preIntroducedConstructorRM.resetName(NameMangler.preIntroducedConstructor(aspectTypeX, targetTypeX));
preIntroducedConstructorRM.resetModifiers(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
preIntroducedConstructorRM.resetReturnTypeToObjectArray();
-
+
pre.binding = world.makeMethodBinding(preIntroducedConstructorRM);
-
+
pre.bindArguments();
pre.bindThrownExceptions();
-
-
+
if (explicitConstructorCall == null) {
pre.statements = new Statement[] {};
} else {
- pre.statements = new Statement[] {
- explicitConstructorCall
- };
+ pre.statements = new Statement[] { explicitConstructorCall };
}
-
- InterTypeScope newParent =
- new InterTypeScope(scope, onTypeBinding);
+
+ InterTypeScope newParent = new InterTypeScope(scope, onTypeBinding);
pre.scope.parent = newParent;
- pre.resolveStatements(); //newParent);
-
-
-
+ pre.resolveStatements(); // newParent);
+
int nParams = pre.arguments.length;
MethodBinding explicitConstructor = null;
if (explicitConstructorCall != null) {
explicitConstructor = explicitConstructorCall.binding;
// If it is null then we are going to report something else is wrong with this code!
- if (explicitConstructor!=null && explicitConstructor.alwaysNeedsAccessMethod()) {
+ if (explicitConstructor != null && explicitConstructor.alwaysNeedsAccessMethod()) {
explicitConstructor = explicitConstructor.getAccessMethod(true);
}
}
-
+
int nExprs;
- if (explicitConstructor == null) nExprs = 0;
- else nExprs = explicitConstructor.parameters.length;
-
-
+ if (explicitConstructor == null)
+ nExprs = 0;
+ else
+ nExprs = explicitConstructor.parameters.length;
+
ArrayInitializer init = new ArrayInitializer();
init.expressions = new Expression[nExprs + nParams];
int index = 0;
- for (int i=0; i < nExprs; i++) {
- if (i >= explicitConstructorCall.arguments.length) {
+ for (int i = 0; i < nExprs; i++) {
+ if (i >= (explicitConstructorCall.arguments == null ? 0 : explicitConstructorCall.arguments.length)) {
init.expressions[index++] = new NullLiteral(0, 0);
continue;
}
-
-
+
Expression arg = explicitConstructorCall.arguments[i];
- ResolvedMember conversionMethod =
- AjcMemberMaker.toObjectConversionMethod(world.fromBinding(explicitConstructorCall.binding.parameters[i]));
+ ResolvedMember conversionMethod = AjcMemberMaker.toObjectConversionMethod(world
+ .fromBinding(explicitConstructorCall.binding.parameters[i]));
if (conversionMethod != null) {
- arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod),
- new CastExpression(new NullLiteral(0, 0),
- AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))),
- new Expression[] {arg });
+ arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod), new CastExpression(new NullLiteral(0,
+ 0), AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))),
+ new Expression[] { arg });
}
init.expressions[index++] = arg;
}
-
- for (int i=0; i < nParams; i++) {
+
+ for (int i = 0; i < nParams; i++) {
LocalVariableBinding binding = pre.arguments[i].binding;
Expression arg = AstUtil.makeResolvedLocalVariableReference(binding);
- ResolvedMember conversionMethod =
- AjcMemberMaker.toObjectConversionMethod(world.fromBinding(binding.type));
+ ResolvedMember conversionMethod = AjcMemberMaker.toObjectConversionMethod(world.fromBinding(binding.type));
if (conversionMethod != null) {
- arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod),
- new CastExpression(new NullLiteral(0, 0),
- AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))),
- new Expression[] {arg });
+ arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod), new CastExpression(new NullLiteral(0,
+ 0), AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))),
+ new Expression[] { arg });
}
init.expressions[index++] = arg;
}
-
- init.binding =objectArrayBinding;
-
+
+ init.binding = objectArrayBinding;
+
ArrayAllocationExpression newArray = new ArrayAllocationExpression();
newArray.initializer = init;
newArray.type = AstUtil.makeTypeReference(scope.getJavaLangObject());
newArray.dimensions = new Expression[1];
newArray.constant = Constant.NotAConstant;
-
-
-
- pre.statements = new Statement[] {
- new ReturnStatement(newArray, 0, 0),
- };
+ pre.statements = new Statement[] { new ReturnStatement(newArray, 0, 0), };
return pre;
}
-
-
-
-
-
public EclipseTypeMunger build(ClassScope classScope) {
EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
-
+
resolveOnType(classScope);
- if (ignoreFurtherInvestigation) return null;
-
+ if (ignoreFurtherInvestigation)
+ return null;
+
binding = classScope.referenceContext.binding.resolveTypesFor(binding);
-
- if (isTargetAnnotation(classScope,"constructor")) return null; // Error message output in isTargetAnnotation
- if (isTargetEnum(classScope,"constructor")) return null; // Error message output in isTargetEnum
-
+
+ if (isTargetAnnotation(classScope, "constructor"))
+ return null; // Error message output in isTargetAnnotation
+ if (isTargetEnum(classScope, "constructor"))
+ return null; // Error message output in isTargetEnum
+
if (onTypeBinding.isInterface()) {
- classScope.problemReporter().signalError(sourceStart, sourceEnd,
- "can't define constructors on interfaces");
+ classScope.problemReporter().signalError(sourceStart, sourceEnd, "can't define constructors on interfaces");
ignoreFurtherInvestigation = true;
return null;
}
-
+
if (onTypeBinding.isNestedType()) {
classScope.problemReporter().signalError(sourceStart, sourceEnd,
- "can't define constructors on nested types (compiler limitation)");
+ "can't define constructors on nested types (compiler limitation)");
ignoreFurtherInvestigation = true;
return null;
- }
-
+ }
+
ResolvedType declaringTypeX = world.fromEclipse(onTypeBinding);
ResolvedType aspectType = world.fromEclipse(classScope.referenceContext.binding);
-
- if (interTypeScope==null) return null; // We encountered a problem building the scope, don't continue - error already reported
-
+ if (interTypeScope == null)
+ return null; // We encountered a problem building the scope, don't continue - error already reported
+
// This signature represents what we want consumers of the targetted type to 'see'
- ResolvedMember signature = world.makeResolvedMemberForITD(binding,onTypeBinding,interTypeScope.getRecoveryAliases());
+ ResolvedMember signature = world.makeResolvedMemberForITD(binding, onTypeBinding, interTypeScope.getRecoveryAliases());
signature.resetKind(Member.CONSTRUCTOR);
signature.resetName("<init>");
int resetModifiers = declaredModifiers;
- if (binding.isVarargs()) resetModifiers = resetModifiers | Constants.ACC_VARARGS;
+ if (binding.isVarargs())
+ resetModifiers = resetModifiers | Constants.ACC_VARARGS;
signature.resetModifiers(resetModifiers);
-
- ResolvedMember syntheticInterMember =
- AjcMemberMaker.interConstructor(declaringTypeX, signature, aspectType);
-
- NewConstructorTypeMunger myMunger =
- new NewConstructorTypeMunger(signature, syntheticInterMember, null, null,typeVariableAliases);
+
+ ResolvedMember syntheticInterMember = AjcMemberMaker.interConstructor(declaringTypeX, signature, aspectType);
+
+ NewConstructorTypeMunger myMunger = new NewConstructorTypeMunger(signature, syntheticInterMember, null, null,
+ typeVariableAliases);
setMunger(myMunger);
myMunger.check(world.getWorld());
-
- this.selector = binding.selector =
- NameMangler.postIntroducedConstructor(
- world.fromBinding(binding.declaringClass),
+
+ this.selector = binding.selector = NameMangler.postIntroducedConstructor(world.fromBinding(binding.declaringClass),
declaringTypeX).toCharArray();
-
+
return new EclipseTypeMunger(world, myMunger, aspectType, this);
}
-
-
+
private AjAttribute makeAttribute(EclipseFactory world) {
- if (explicitConstructorCall != null && (explicitConstructorCall.binding!=null) && !(explicitConstructorCall.binding instanceof ProblemMethodBinding)) {
+ if (explicitConstructorCall != null && (explicitConstructorCall.binding != null)
+ && !(explicitConstructorCall.binding instanceof ProblemMethodBinding)) {
MethodBinding explicitConstructor = explicitConstructorCall.binding;
if (explicitConstructor.alwaysNeedsAccessMethod()) {
explicitConstructor = explicitConstructor.getAccessMethod(true);
if (explicitConstructor instanceof ParameterizedMethodBinding) {
explicitConstructor = explicitConstructor.original();
}
- ((NewConstructorTypeMunger)munger).setExplicitConstructor(
- world.makeResolvedMember(explicitConstructor));
+ ((NewConstructorTypeMunger) munger).setExplicitConstructor(world.makeResolvedMember(explicitConstructor));
} else {
- ((NewConstructorTypeMunger)munger).setExplicitConstructor(
- new ResolvedMemberImpl(Member.CONSTRUCTOR,
- world.fromBinding(onTypeBinding.superclass()),
- 0, ResolvedType.VOID, "<init>", UnresolvedType.NONE));
+ ((NewConstructorTypeMunger) munger).setExplicitConstructor(new ResolvedMemberImpl(Member.CONSTRUCTOR, world
+ .fromBinding(onTypeBinding.superclass()), 0, ResolvedType.VOID, "<init>", UnresolvedType.NONE));
}
return new AjAttribute.TypeMunger(munger);
}
-
-
+
public void generateCode(ClassScope classScope, ClassFile classFile) {
- if (ignoreFurtherInvestigation) return;
+ if (ignoreFurtherInvestigation)
+ return;
EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute(world)));
super.generateCode(classScope, classFile);
-// classFile.codeStream.generateAttributes &= ~ClassFileConstants.ATTR_VARS;
+ // classFile.codeStream.generateAttributes &= ~ClassFileConstants.ATTR_VARS;
preMethod.generateCode(classScope, classFile);
}
+
protected Shadow.Kind getShadowKindForBody() {
return Shadow.ConstructorExecution;
}
-
+
}