@@ -47,6 +47,7 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; | |||
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; | |||
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding; | |||
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.PackageBinding; | |||
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; | |||
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; | |||
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; | |||
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits; | |||
@@ -251,8 +252,16 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC | |||
// Look at the supertype first | |||
ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.COLLECTING_ITDS_AND_DECLARES, sourceType.sourceName); | |||
ReferenceBinding superType = sourceType.superclass(); | |||
if (yetToProcess.contains(superType) && superType instanceof SourceTypeBinding) { | |||
collectAllITDsAndDeclares((SourceTypeBinding)superType, yetToProcess); | |||
if (superType instanceof SourceTypeBinding) { | |||
if (yetToProcess.contains(superType)) { | |||
collectAllITDsAndDeclares((SourceTypeBinding)superType, yetToProcess); | |||
} | |||
} else if (superType instanceof ParameterizedTypeBinding) { | |||
// If its a PTB we need to pull the SourceTypeBinding out of it. | |||
ParameterizedTypeBinding ptb = (ParameterizedTypeBinding)superType; | |||
if (ptb.type instanceof SourceTypeBinding && yetToProcess.contains(ptb.type)) { | |||
collectAllITDsAndDeclares((SourceTypeBinding)ptb.type, yetToProcess); | |||
} | |||
} | |||
buildInterTypeAndPerClause(sourceType.scope); | |||
addCrosscuttingStructures(sourceType.scope); |
@@ -1,6 +1,5 @@ | |||
public aspect BlobContainment extends ParentChildRelationship<Blob,Blob> { | |||
public static void main(String []argv) { | |||
Blob a = new Blob(); | |||
Blob b = new Blob(); | |||
@@ -17,12 +16,14 @@ public aspect BlobContainment extends ParentChildRelationship<Blob,Blob> { | |||
// now query the layout | |||
/* | |||
if (!e.getParent().equals(b)) | |||
throw new RuntimeException("why is E not parent of B? "+e.getParent()); | |||
if (!d.getParent().equals(a)) | |||
throw new RuntimeException("why is A not parent of D? "+d.getParent()); | |||
if (a.getChildren().size()!=3) | |||
throw new RuntimeException("A should have 3 children, not:"+a.getChildren().size()); | |||
*/ | |||
} | |||
} |
@@ -1,57 +1,99 @@ | |||
import java.util.*; | |||
import org.aspectj.lang.annotation.*; | |||
abstract aspect ParentChildRelationship<Parent,Child> { | |||
interface ParentHasChildren<C>{} | |||
interface ChildHasParent<P>{} | |||
declare parents: Parent implements ParentHasChildren<Child>; | |||
declare parents: Child implements ChildHasParent<Parent>; | |||
public List<E> ParentHasChildren<E>.children = new ArrayList<E>(); | |||
public P ChildHasParent<P>.parent; | |||
public List<D> ParentHasChildren<D>.getChildren() { | |||
return Collections.unmodifiableList(children); | |||
} | |||
public P ChildHasParent<P>.getParent() { | |||
return parent; | |||
} | |||
public void ChildHasParent<R>.setParent(R parent) { | |||
this.parent = parent; | |||
ParentHasChildren phc = (ParentHasChildren)parent; | |||
if (phc.getChildren().contains(this)) | |||
phc.addChild(this); | |||
} | |||
public void ParentHasChildren<X>.addChild(X child) { | |||
if (((ChildHasParent)child).parent != null) { | |||
((ParentHasChildren)((ChildHasParent)child).parent).removeChild(child); | |||
} else { | |||
((ChildHasParent)child).setParent((ParentHasChildren)this); | |||
} | |||
children.add(child); | |||
} | |||
public void ParentHasChildren<Y>.removeChild(Y child) { | |||
if (children.remove(child)) { | |||
((ChildHasParent)child).parent = null; | |||
} | |||
} | |||
} | |||
/* | |||
abstract aspect ParentChildRelationship<Parent,Child> { | |||
/** interface implemented by parents */ | |||
// interface implemented by parents | |||
interface ParentHasChildren<C>{ | |||
// List<C> getChildren(); | |||
// void addChild(C child); | |||
// void removeChild(C child); | |||
List<C> getChildren(); | |||
void addChild(C child); | |||
void removeChild(C child); | |||
} | |||
/** interface implemented by children */ | |||
// interface implemented by children | |||
interface ChildHasParent<P>{ | |||
// P getParent(); | |||
// void setParent(P parent); | |||
P getParent(); | |||
void setParent(P parent); | |||
} | |||
/** ensure the parent type implements ParentHasChildren<child type> */ | |||
// ensure the parent type implements ParentHasChildren<child type> | |||
declare parents: Parent implements ParentHasChildren<Child>; | |||
/** ensure the child type implements ChildHasParent<parent type> */ | |||
// ensure the child type implements ChildHasParent<parent type> | |||
declare parents: Child implements ChildHasParent<Parent>; | |||
// Inter-type declarations made on the *generic* interface types to provide | |||
// default implementations. | |||
/** list of children maintained by parent */ | |||
// list of children maintained by parent | |||
public List<E> ParentHasChildren<E>.children = new ArrayList<E>(); | |||
/** reference to parent maintained by child */ | |||
// reference to parent maintained by child | |||
public P ChildHasParent<P>.parent; | |||
/** Default implementation of getChildren for the generic type ParentHasChildren */ | |||
// Default implementation of getChildren for the generic | |||
// type ParentHasChildren | |||
public List<D> ParentHasChildren<D>.getChildren() { | |||
return Collections.unmodifiableList(children); | |||
} | |||
/** Default implementation of getParent for the generic type ChildHasParent */ | |||
// Default implementation of getParent for the generic | |||
// type ChildHasParent | |||
public P ChildHasParent<P>.getParent() { | |||
return parent; | |||
} | |||
/** | |||
* Default implementation of setParent for the generic type ChildHasParent. | |||
* Ensures that this child is added to the children of the parent too. | |||
*/ | |||
// Default implementation of setParent for the generic type ChildHasParent. | |||
// Ensures that this child is added to the children of the parent too. | |||
public void ChildHasParent<R>.setParent(R parent) { | |||
((ParentHasChildren)parent).addChild(this); | |||
} | |||
/** | |||
* Default implementation of addChild, ensures that parent of child is | |||
* also updated. | |||
*/ | |||
// Default implementation of addChild, ensures that parent of child is | |||
// also updated. | |||
public void ParentHasChildren<X>.addChild(X child) { | |||
if (((ChildHasParent)child).parent != null) { | |||
((ParentHasChildren)((ChildHasParent)child).parent).removeChild(child); | |||
@@ -60,27 +102,23 @@ abstract aspect ParentChildRelationship<Parent,Child> { | |||
((ChildHasParent)child).parent = (ParentHasChildren)this; | |||
} | |||
/** | |||
* Default implementation of removeChild, ensures that parent of | |||
* child is also updated. | |||
*/ | |||
// Default implementation of removeChild, ensures that parent of | |||
// child is also updated. | |||
public void ParentHasChildren<Y>.removeChild(Y child) { | |||
if (children.remove(child)) { | |||
((ChildHasParent)child).parent = null; | |||
} | |||
} | |||
/** | |||
* Matches at an addChild join point for the parent type P and child type C | |||
*/ | |||
// Matches at an addChild join point for the parent type P and child type C | |||
@SuppressAjWarnings | |||
public pointcut addingChild(Parent p, Child c) : | |||
execution(* Parent.addChild(Child)) && this(p) && args(c); | |||
/** | |||
* Matches at a removeChild join point for the parent type P and child type C | |||
*/ | |||
@SuppressAjWarnings | |||
public pointcut removingChild(Parent p, Child c) : | |||
execution(* Parent.removeChild(Child)) && this(p) && args(c); | |||
// Matches at a removeChild join point for the parent type P and child type C | |||
@SuppressAjWarnings | |||
public pointcut removingChild(Parent p, Child c) : | |||
execution(* Parent.removeChild(Child)) && this(p) && args(c); | |||
} | |||
*/ |
@@ -0,0 +1,76 @@ | |||
import java.util.*; | |||
import org.aspectj.lang.annotation.*; | |||
class Blob {} | |||
public aspect TheBigOne extends ParentChildRelationship<Blob,Blob> { | |||
public static void main(String []argv) { | |||
Blob a = new Blob(); | |||
Blob b = new Blob(); | |||
Blob c = new Blob(); | |||
Blob d = new Blob(); | |||
Blob e = new Blob(); | |||
// arrange as follows: A contains B,C,D and B contains E | |||
a.addChild(b); | |||
a.addChild(c); | |||
a.addChild(d); | |||
b.addChild(e); | |||
// now query the layout | |||
if (!e.getParent().equals(b)) | |||
throw new RuntimeException("why is E not parent of B? "+e.getParent()); | |||
if (!d.getParent().equals(a)) | |||
throw new RuntimeException("why is A not parent of D? "+d.getParent()); | |||
if (a.getChildren().size()!=3) | |||
throw new RuntimeException("A should have 3 children, not:"+a.getChildren().size()); | |||
} | |||
} | |||
abstract aspect ParentChildRelationship<Parent,Child> { | |||
interface ParentHasChildren<C>{} | |||
interface ChildHasParent<P>{} | |||
declare parents: Parent implements ParentHasChildren<Child>; | |||
declare parents: Child implements ChildHasParent<Parent>; | |||
public List<E> ParentHasChildren<E>.children = new ArrayList<E>(); | |||
public P ChildHasParent<P>.parent; | |||
public List<D> ParentHasChildren<D>.getChildren() { | |||
return Collections.unmodifiableList(children); | |||
} | |||
public P ChildHasParent<P>.getParent() { | |||
return parent; | |||
} | |||
public void ChildHasParent<R>.setParent(R parent) { | |||
this.parent = parent; | |||
ParentHasChildren phc = (ParentHasChildren)parent; | |||
if (phc.getChildren().contains(this)) | |||
phc.addChild(this); | |||
} | |||
public void ParentHasChildren<X>.addChild(X child) { | |||
if (((ChildHasParent)child).parent != null) { | |||
((ParentHasChildren)((ChildHasParent)child).parent).removeChild(child); | |||
} else { | |||
((ChildHasParent)child).setParent((ParentHasChildren)this); | |||
} | |||
children.add(child); | |||
} | |||
public void ParentHasChildren<Y>.removeChild(Y child) { | |||
if (children.remove(child)) { | |||
((ChildHasParent)child).parent = null; | |||
} | |||
} | |||
} |
@@ -170,10 +170,6 @@ public class GenericsTests extends XMLBasedAjcTestCase { | |||
* TODO exotic class/interface bounds ('? extends List<String>','? super anything') | |||
* TODO signature attributes for generic ITDs (public only?) | |||
* | |||
* | |||
* strangeness: | |||
* | |||
* adding declare precedence into the itds/binaryweaving A2.aj, A3.aj causes a bizarre classfile inconsistent message | |||
*/ | |||
public static Test suite() { | |||
@@ -221,8 +217,8 @@ public class GenericsTests extends XMLBasedAjcTestCase { | |||
public void testPR96220_GenericAspects2() {runTest("generic aspects - 2");} | |||
public void testPR96220_GenericAspects3() {runTest("generic aspects - 3");} | |||
public void testGenericAspects4() {runTest("generic aspects - 4");} | |||
// TODO FREAKYGENERICASPECTPROBLEM why does everything have to be in one source file? | |||
// public void testGenericAspects5() {runTest("generic aspects - 5 (ajdk)");} | |||
public void testGenericAspects5() {runTest("generic aspects - 5 (ajdk)");} // in separate files | |||
public void testGenericAspects6() {runTest("generic aspects - 6 (ajdk)");} // all in one file | |||
public void testTypeVariablesInDeclareWarning() { runTest("generic aspect with declare warning using type vars");} | |||
public void testTypeVariablesInExecutionAdvice() { runTest("generic aspect with execution advice using type vars");} | |||
public void testTypeVariablesInAnonymousPointcut() { runTest("generic aspect with anonymous pointcut");} |
@@ -3081,6 +3081,12 @@ | |||
<run class="BlobContainment"/> | |||
</ajc-test> | |||
<!-- same as above but all types in one file --> | |||
<ajc-test dir="java5/generics/genericaspects" title="generic aspects - 6 (ajdk)"> | |||
<compile files="TheBigOne.java" options="-1.5"/> | |||
<run class="TheBigOne"/> | |||
</ajc-test> | |||
<!-- end of generic aspects --> | |||
<!-- generic ITDs --> |
@@ -1288,10 +1288,10 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl | |||
for (int i = 0; i < superIs.length; i++) { | |||
ResolvedType superI = superIs[i]; | |||
if (superI.genericTypeEquals(lookingFor)) return superI; | |||
ResolvedType checkTheSuperI = discoverActualOccurrenceOfTypeInHierarchy(lookingFor); | |||
ResolvedType checkTheSuperI = superI.discoverActualOccurrenceOfTypeInHierarchy(lookingFor); | |||
if (checkTheSuperI!=null) return checkTheSuperI; | |||
} | |||
return discoverActualOccurrenceOfTypeInHierarchy(superT); | |||
return superT.discoverActualOccurrenceOfTypeInHierarchy(lookingFor); | |||
} | |||
/** |