The existing check crudely only checked the top level, failing to find nested WildTypePatterns. Resolves #542682tags/V1_9_3RC1
@@ -1,15 +1,11 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). | |||
* Copyright (c) 2002-2019 Contributors | |||
* 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.weaver.patterns; | |||
import java.io.IOException; | |||
@@ -30,15 +26,18 @@ import org.aspectj.weaver.VersionedDataInputStream; | |||
import org.aspectj.weaver.WeaverMessages; | |||
import org.aspectj.weaver.World; | |||
/** | |||
* @author Thomas Kiviaho | |||
* @author Andy Clement | |||
* @author PARC | |||
*/ | |||
public class DeclareParents extends Declare { | |||
protected TypePattern child; | |||
protected TypePatternList parents; | |||
private boolean isWildChild = false; | |||
protected boolean isExtends = true; | |||
// private String[] typeVariablesInScope = new String[0]; // AspectJ 5 extension for generic types | |||
public DeclareParents(TypePattern child, List parents, boolean isExtends) { | |||
public DeclareParents(TypePattern child, List<TypePattern> parents, boolean isExtends) { | |||
this(child, new TypePatternList(parents), isExtends); | |||
} | |||
@@ -46,19 +45,11 @@ public class DeclareParents extends Declare { | |||
this.child = child; | |||
this.parents = parents; | |||
this.isExtends = isExtends; | |||
if (child instanceof WildTypePattern) { | |||
isWildChild = true; | |||
} | |||
WildChildFinder wildChildFinder = new WildChildFinder(); | |||
child.accept(wildChildFinder, null); | |||
isWildChild = wildChildFinder.containedWildChild(); | |||
} | |||
// public String[] getTypeParameterNames() { | |||
// return this.typeVariablesInScope; | |||
// } | |||
// | |||
// public void setTypeParametersInScope(String[] typeParameters) { | |||
// this.typeVariablesInScope = typeParameters; | |||
// } | |||
public boolean match(ResolvedType typeX) { | |||
if (!child.matchesStatically(typeX)) { | |||
return false; | |||
@@ -76,7 +67,7 @@ public class DeclareParents extends Declare { | |||
} | |||
@Override | |||
public Declare parameterizeWith(Map typeVariableBindingMap, World w) { | |||
public Declare parameterizeWith(Map<String,UnresolvedType> typeVariableBindingMap, World w) { | |||
DeclareParents ret = new DeclareParents(child.parameterizeWith(typeVariableBindingMap, w), parents.parameterizeWith( | |||
typeVariableBindingMap, w), isExtends); | |||
ret.copyLocationFrom(this); | |||
@@ -117,22 +108,11 @@ public class DeclareParents extends Declare { | |||
s.writeByte(Declare.PARENTS); | |||
child.write(s); | |||
parents.write(s); | |||
// s.writeInt(typeVariablesInScope.length); | |||
// for (int i = 0; i < typeVariablesInScope.length; i++) { | |||
// s.writeUTF(typeVariablesInScope[i]); | |||
// } | |||
writeLocation(s); | |||
} | |||
public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
DeclareParents ret = new DeclareParents(TypePattern.read(s, context), TypePatternList.read(s, context), true); | |||
// if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) { | |||
// int numTypeVariablesInScope = s.readInt(); | |||
// ret.typeVariablesInScope = new String[numTypeVariablesInScope]; | |||
// for (int i = 0; i < numTypeVariablesInScope; i++) { | |||
// ret.typeVariablesInScope[i] = s.readUTF(); | |||
// } | |||
// } | |||
ret.readLocation(context, s); | |||
return ret; | |||
} | |||
@@ -157,11 +137,14 @@ public class DeclareParents extends Declare { | |||
@Override | |||
public void resolve(IScope scope) { | |||
// ScopeWithTypeVariables resolutionScope = new ScopeWithTypeVariables(typeVariablesInScope,scope); | |||
child = child.resolveBindings(scope, Bindings.NONE, false, false); | |||
isWildChild = (child instanceof WildTypePattern); | |||
TypePattern resolvedChild = child.resolveBindings(scope, Bindings.NONE, false, false); | |||
if (!resolvedChild.equals(child)) { | |||
WildChildFinder wildChildFinder = new WildChildFinder(); | |||
resolvedChild.accept(wildChildFinder, null); | |||
isWildChild = wildChildFinder.containedWildChild(); | |||
this.child = resolvedChild; | |||
} | |||
parents = parents.resolveBindings(scope, Bindings.NONE, false, true); | |||
// Could assert this ... | |||
// for (int i=0; i < parents.size(); i++) { | |||
// parents.get(i).assertExactType(scope.getMessageHandler()); |
@@ -0,0 +1,68 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2019 Contributors | |||
* 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 | |||
* | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.patterns; | |||
/** | |||
* @author Tuomas Kiviaho | |||
*/ | |||
public class WildChildFinder extends AbstractPatternNodeVisitor { | |||
private boolean wildChild; | |||
public WildChildFinder() { | |||
super(); | |||
} | |||
public boolean containedWildChild() { | |||
return wildChild; | |||
} | |||
@Override | |||
public Object visit(WildAnnotationTypePattern node, Object data) { | |||
node.getTypePattern().accept(this, data); | |||
return node; | |||
} | |||
@Override | |||
public Object visit(WildTypePattern node, Object data) { | |||
this.wildChild = true; | |||
return super.visit(node, data); | |||
} | |||
@Override | |||
public Object visit(AndTypePattern node, Object data) { | |||
node.getLeft().accept(this, data); | |||
if (!this.wildChild) { | |||
node.getRight().accept(this, data); | |||
} | |||
return node; | |||
} | |||
@Override | |||
public Object visit(OrTypePattern node, Object data) { | |||
node.getLeft().accept(this, data); | |||
if (!this.wildChild) { | |||
node.getRight().accept(this, data); | |||
} | |||
return node; | |||
} | |||
public Object visit(NotTypePattern node, Object data) { | |||
node.getNegatedPattern().accept(this, data); | |||
return node; | |||
} | |||
@Override | |||
public Object visit(AnyWithAnnotationTypePattern node, Object data) { | |||
node.getAnnotationPattern().accept(this, data); | |||
return node; | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
import java.lang.annotation.*; | |||
import org.aspectj.lang.annotation.*; | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@interface SomeAnnotation {} | |||
@SomeAnnotation | |||
public class CaseA { | |||
public static void main(String[]argv) { | |||
CaseA ca = new CaseA(); | |||
((I)ca).methodOne(); // will only succeed if mixin applied | |||
} | |||
} | |||
@SomeAnnotation | |||
enum Color {R,G,B} | |||
aspect X { | |||
@DeclareMixin("(@SomeAnnotation *)") | |||
public static I createImplementation() { | |||
System.out.println("Delegate factory invoked"); | |||
return new Implementation(); | |||
} | |||
} | |||
interface I { | |||
void methodOne(); | |||
} | |||
class Implementation implements I { | |||
public void methodOne() { | |||
System.out.println("methodOne running"); | |||
} | |||
} | |||
@@ -0,0 +1,12 @@ | |||
import java.lang.annotation.*; | |||
import java.lang.Enum; | |||
public aspect EnumAspect04 { | |||
interface I {}; | |||
//declare parents: SimpleE* implements I; | |||
//declare parents: !*Aspect04 implements I; | |||
declare parents: @Foo * implements I; | |||
} | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@interface Foo {} |
@@ -0,0 +1,2 @@ | |||
@Foo | |||
public class SimpleClass {} |
@@ -0,0 +1,2 @@ | |||
@Foo | |||
public enum SimpleEnum { Red,Orange,Yellow,Green,Blue,Indigo,Violet }; |
@@ -0,0 +1,2 @@ | |||
@Foo | |||
public enum SimpleEnum2 { Black, White }; |
@@ -1,12 +1,9 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2018 Contributors | |||
* Copyright (c) 2018-2019 Contributors | |||
* 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: | |||
* Andy Clement - initial API and implementation | |||
*******************************************************************************/ | |||
package org.aspectj.systemtest.ajc193; | |||
@@ -22,6 +19,15 @@ import junit.framework.Test; | |||
*/ | |||
public class Ajc193Tests extends XMLBasedAjcTestCaseForJava10OrLater { | |||
// Altered version of this test from org.aspectj.systemtest.ajc150.Enums for 542682 | |||
public void decpOnEnumNotAllowed_xlints() { | |||
runTest("wildcard enum match in itd"); | |||
} | |||
public void testEnumDecmixinMessage() { | |||
runTest("declare mixin a"); | |||
} | |||
public void testIsAbstractType() { | |||
runTest("is abstract"); | |||
} | |||
@@ -29,7 +35,7 @@ public class Ajc193Tests extends XMLBasedAjcTestCaseForJava10OrLater { | |||
public void testIsAbstractType2() { | |||
runTest("is abstract - 2"); | |||
} | |||
// --- | |||
public static Test suite() { | |||
@@ -38,7 +44,7 @@ public class Ajc193Tests extends XMLBasedAjcTestCaseForJava10OrLater { | |||
@Override | |||
protected File getSpecFile() { | |||
return getClassResource("ajc193.xml"); | |||
return getClassResource("ajc193.xml"); | |||
} | |||
} |
@@ -2,7 +2,25 @@ | |||
<suite> | |||
<ajc-test dir="bugs193/542682" vm="1.5" title="wildcard enum match in itd"> | |||
<compile files="SimpleEnum.java,SimpleEnum2.java,EnumAspect04.aj" options="-1.5"> | |||
<message kind="warning" line="8" text="enum type SimpleEnum2 matches a declare parents type pattern but is being ignored"/> | |||
<message kind="warning" line="8" text="enum type SimpleEnum matches a declare parents type pattern but is being ignored"/> | |||
</compile> | |||
</ajc-test> | |||
<ajc-test dir="bugs193/542682" title="declare mixin a"> | |||
<compile files="CaseA.java" options="-1.8"> | |||
<message kind="warning" line="1" text="enum type Color matches a declare parents type pattern but is being ignored"/> | |||
</compile> | |||
<run class="CaseA"> | |||
<stdout> | |||
<line text="Delegate factory invoked"/> | |||
<line text="methodOne running"/> | |||
</stdout> | |||
</run> | |||
</ajc-test> | |||
<ajc-test dir="bugs193/isAbstractType" title="is abstract"> | |||
<compile files="Code.java" options="-1.8"/> | |||
<run class="Code"> |