]> source.dussan.org Git - aspectj.git/commitdiff
Fix 461323: around advice on default methods
authorAndy Clement <aclement@pivotal.io>
Thu, 19 Nov 2015 16:54:14 +0000 (08:54 -0800)
committerAndy Clement <aclement@pivotal.io>
Thu, 19 Nov 2015 16:54:14 +0000 (08:54 -0800)
tests/bugs188/defaultMethods/Code.java [new file with mode: 0644]
tests/bugs188/defaultMethods/Code2.java [new file with mode: 0644]
tests/src/org/aspectj/systemtest/ajc188/Ajc188Tests.java
tests/src/org/aspectj/systemtest/ajc188/ajc188.xml
weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
weaver/src/org/aspectj/weaver/bcel/Utility.java
weaver/testsrc/org/aspectj/weaver/bcel/MoveInstructionsWeaveTestCase.java

diff --git a/tests/bugs188/defaultMethods/Code.java b/tests/bugs188/defaultMethods/Code.java
new file mode 100644 (file)
index 0000000..a162fe7
--- /dev/null
@@ -0,0 +1,18 @@
+public class Code implements I {
+  public static void main(String[] argv) {
+    new Code().m();
+  }
+}
+aspect X {
+  void around(): execution(* I.*()) {
+    System.out.println("a");
+    proceed();
+  }
+}
+
+interface I {
+  default void m(){
+    System.out.println("b");
+  }
+}
+
diff --git a/tests/bugs188/defaultMethods/Code2.java b/tests/bugs188/defaultMethods/Code2.java
new file mode 100644 (file)
index 0000000..ea5469e
--- /dev/null
@@ -0,0 +1,18 @@
+public class Code2 implements I {
+  public static void main(String[] argv) {
+    new Code2().m();
+  }
+}
+aspect X {
+  void around(): execution(* I.*()) {
+    System.out.println("a");
+    proceed();
+  }
+}
+
+interface I {
+  default void m(){
+    System.out.println("b");
+  }
+}
+
index 11c503a89c58a5b401b9885f84b0bfd0763b92a0..c2a994855f2cb8d4cbb6909abac5410c41358dc2 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014 Contributors
+ * Copyright (c) 2015 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
@@ -11,9 +11,6 @@
 package org.aspectj.systemtest.ajc188;
 
 import java.io.File;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.net.URLClassLoader;
 
 import junit.framework.Test;
 
@@ -24,6 +21,14 @@ import org.aspectj.testing.XMLBasedAjcTestCase;
  */
 public class Ajc188Tests extends org.aspectj.testing.XMLBasedAjcTestCase {
 
+       public void testDefaultMethodsWithXnoInline() throws Exception {
+               runTest("default methods 1");
+       }
+
+       public void testDefaultMethodsWithoutXnoInline() throws Exception {
+               runTest("default methods 2");
+       }
+       
        public void testCompileError_478003() throws Exception {
                runTest("compile error");
        }
index cc1214c189b754fb7520bc39f4d6902b687dc73a..2e8a8b62f8e62dce2ba00876cf46e6fe50f13815 100644 (file)
@@ -2,6 +2,27 @@
 
 <suite>
 
+<ajc-test dir="bugs188/defaultmethods" title="default methods 1">
+<compile files="Code.java" options="-1.8 -XnoInline"/>
+<run class="Code">
+<stdout>
+<line text="a"/>
+<line text="b"/>
+</stdout>
+</run>
+</ajc-test>
+
+
+<ajc-test dir="bugs188/defaultmethods" title="default methods 2">
+<compile files="Code2.java" options="-1.8"/>
+<run class="Code2">
+<stdout>
+<line text="a"/>
+<line text="b"/>
+</stdout>
+</run>
+</ajc-test>
+
 <ajc-test dir="bugs188/478003" title="compile error">
 <compile files="OrientDBKeyIO.java" options="-1.8"/>
 </ajc-test>
index e6676900fd062dceced30976fecd1dbd3c3d3daf..94462d5ff091a6b8a5544e5aa06afa1188ef1ed2 100644 (file)
@@ -1039,8 +1039,8 @@ public class BcelShadow extends Shadow {
 
        private boolean checkLazyTjp() {
                // check for around advice
-               for (Iterator i = mungers.iterator(); i.hasNext();) {
-                       ShadowMunger munger = (ShadowMunger) i.next();
+               for (Iterator<ShadowMunger> i = mungers.iterator(); i.hasNext();) {
+                       ShadowMunger munger = i.next();
                        if (munger instanceof Advice) {
                                if (((Advice) munger).getKind() == AdviceKind.Around) {
                                        if (munger.getSourceLocation() != null) { // do we know enough to bother reporting?
@@ -2183,8 +2183,10 @@ public class BcelShadow extends Shadow {
                // at the shadow, then tjp
                String extractedShadowMethodName = NameMangler.aroundShadowMethodName(getSignature(), shadowClass.getNewGeneratedNameTag());
                List<String> parameterNames = new ArrayList<String>();
-               LazyMethodGen extractedShadowMethod = extractShadowInstructionsIntoNewMethod(extractedShadowMethodName, Modifier.PRIVATE,
-                               munger.getSourceLocation(), parameterNames);
+               boolean shadowClassIsInterface = shadowClass.isInterface();
+               LazyMethodGen extractedShadowMethod = extractShadowInstructionsIntoNewMethod(extractedShadowMethodName, 
+                               shadowClassIsInterface?Modifier.PUBLIC:Modifier.PRIVATE,
+                               munger.getSourceLocation(), parameterNames,shadowClassIsInterface);
 
                List<BcelVar> argsToCallLocalAdviceMethodWith = new ArrayList<BcelVar>();
                List<BcelVar> proceedVarList = new ArrayList<BcelVar>();
@@ -2205,7 +2207,6 @@ public class BcelShadow extends Shadow {
                        proceedVarList.add(new BcelVar(targetVar.getType(), extraParamOffset));
                        extraParamOffset += targetVar.getType().getSize();
                }
-               int idx = 0;
                for (int i = 0, len = getArgCount(); i < len; i++) {
                        argsToCallLocalAdviceMethodWith.add(argVars[i]);
                        proceedVarList.add(new BcelVar(argVars[i].getType(), extraParamOffset));
@@ -2242,8 +2243,8 @@ public class BcelShadow extends Shadow {
                // Extract the advice into a new method. This will go in the same type as the shadow
                // name will be something like foo_aroundBody1$advice
                String localAdviceMethodName = NameMangler.aroundAdviceMethodName(getSignature(), shadowClass.getNewGeneratedNameTag());
-               LazyMethodGen localAdviceMethod = new LazyMethodGen(Modifier.PRIVATE | (world.useFinal() ? Modifier.FINAL : 0)
-                               | Modifier.STATIC, BcelWorld.makeBcelType(mungerSig.getReturnType()), localAdviceMethodName, parameterTypes,
+               int localAdviceMethodModifiers = Modifier.PRIVATE | (world.useFinal() & !shadowClassIsInterface ? Modifier.FINAL : 0) | Modifier.STATIC;
+               LazyMethodGen localAdviceMethod = new LazyMethodGen(localAdviceMethodModifiers, BcelWorld.makeBcelType(mungerSig.getReturnType()), localAdviceMethodName, parameterTypes,
                                NoDeclaredExceptions, shadowClass);
 
                // Doesnt work properly, so leave it out:
@@ -2833,9 +2834,12 @@ public class BcelShadow extends Shadow {
 
                int linenumber = getSourceLine();
                // MOVE OUT ALL THE INSTRUCTIONS IN MY SHADOW INTO ANOTHER METHOD!
+               
+               // callbackMethod will be something like: "static final void m_aroundBody0(I)"
+               boolean shadowClassIsInterface = getEnclosingClass().isInterface();
                LazyMethodGen callbackMethod = extractShadowInstructionsIntoNewMethod(
-                               NameMangler.aroundShadowMethodName(getSignature(), getEnclosingClass().getNewGeneratedNameTag()), 0,
-                               munger.getSourceLocation(), new ArrayList<String>());
+                               NameMangler.aroundShadowMethodName(getSignature(), getEnclosingClass().getNewGeneratedNameTag()), shadowClassIsInterface?Modifier.PUBLIC:0,
+                               munger.getSourceLocation(), new ArrayList<String>(),shadowClassIsInterface);
 
                BcelVar[] adviceVars = munger.getExposedStateAsBcelVars(true);
 
@@ -3123,15 +3127,16 @@ public class BcelShadow extends Shadow {
         * @param extractedMethodName name for the new method
         * @param extractedMethodVisibilityModifier visibility modifiers for the new method
         * @param adviceSourceLocation source location of the advice affecting the shadow
+        * @param beingPlacedInInterface is this new method going into an interface
         */
        LazyMethodGen extractShadowInstructionsIntoNewMethod(String extractedMethodName, int extractedMethodVisibilityModifier,
-                       ISourceLocation adviceSourceLocation, List<String> parameterNames) {
+                       ISourceLocation adviceSourceLocation, List<String> parameterNames, boolean beingPlacedInInterface) {
                // LazyMethodGen.assertGoodBody(range.getBody(), extractedMethodName);
                if (!getKind().allowsExtraction()) {
                        throw new BCException("Attempt to extract method from a shadow kind (" + getKind()
                                        + ") that does not support this operation");
                }
-               LazyMethodGen newMethod = createShadowMethodGen(extractedMethodName, extractedMethodVisibilityModifier, parameterNames);
+               LazyMethodGen newMethod = createShadowMethodGen(extractedMethodName, extractedMethodVisibilityModifier, parameterNames, beingPlacedInInterface);
                IntMap remapper = makeRemap();
                range.extractInstructionsInto(newMethod, remapper, (getKind() != PreInitialization) && isFallsThrough());
                if (getKind() == PreInitialization) {
@@ -3230,9 +3235,9 @@ public class BcelShadow extends Shadow {
         * The new method always static. It may take some extra arguments: this, target. If it's argsOnStack, then it must take both
         * this/target If it's argsOnFrame, it shares this and target. ??? rewrite this to do less array munging, please
         */
-       private LazyMethodGen createShadowMethodGen(String newMethodName, int visibilityModifier, List<String> parameterNames) {
+       private LazyMethodGen createShadowMethodGen(String newMethodName, int visibilityModifier, List<String> parameterNames, boolean beingPlacedInInterface) {
                Type[] shadowParameterTypes = BcelWorld.makeBcelTypes(getArgTypes());
-               int modifiers = (world.useFinal() ? Modifier.FINAL : 0) | Modifier.STATIC | visibilityModifier;
+               int modifiers = (world.useFinal() && !beingPlacedInInterface ? Modifier.FINAL : 0) | Modifier.STATIC | visibilityModifier;
                if (targetVar != null && targetVar != thisVar) {
                        UnresolvedType targetType = getTargetType();
                        targetType = ensureTargetTypeIsCorrect(targetType);
index 20ec45ad034fee2286354af8c88f92a3faa4ffb6..afbfbc7ef4a8ac51fd8ff6bcaf8cdb571a354f9a 100644 (file)
@@ -198,7 +198,12 @@ public class Utility {
        public static Instruction createInvoke(InstructionFactory fact, LazyMethodGen m) {
                short kind;
                if (m.getEnclosingClass().isInterface()) {
-                       kind = Constants.INVOKEINTERFACE;
+                       if (m.isStatic()) {
+                               // For static methods on interfaces
+                               kind = Constants.INVOKESTATIC;                          
+                       } else {
+                               kind = Constants.INVOKEINTERFACE;
+                       }
                } else if (m.isStatic()) {
                        kind = Constants.INVOKESTATIC;
                } else if (m.isPrivate() || m.getName().equals("<init>")) {
index 0155cb03cd7fdbd22fd89211d7c7682a0ab7fe6f..bd7c2ae656b3a1b0174ee5dc27e8a0edf2b55559 100644 (file)
@@ -39,7 +39,7 @@ public class MoveInstructionsWeaveTestCase extends WeaveTestCase {
                                BcelShadow shadow = (BcelShadow) s;
                                LazyMethodGen newMethod = shadow.extractShadowInstructionsIntoNewMethod(NameMangler.getExtractableName(shadow
                                                .getSignature())
-                                               + "_extracted", 0, this.getSourceLocation(), new ArrayList());
+                                               + "_extracted", 0, this.getSourceLocation(), new ArrayList(),shadow.getEnclosingClass().isInterface());
                                shadow.getRange().append(shadow.makeCallToCallback(newMethod));
 
                                if (!shadow.isFallsThrough()) {
@@ -63,9 +63,10 @@ public class MoveInstructionsWeaveTestCase extends WeaveTestCase {
 
                        public boolean implementOn(Shadow s) {
                                BcelShadow shadow = (BcelShadow) s;
-                               LazyMethodGen newMethod = shadow.extractShadowInstructionsIntoNewMethod(NameMangler.getExtractableName(shadow
+                               LazyMethodGen newMethod = 
+                                               shadow.extractShadowInstructionsIntoNewMethod(NameMangler.getExtractableName(shadow
                                                .getSignature())
-                                               + "_extracted" + counter++, 0, this.getSourceLocation(), new ArrayList());
+                                               + "_extracted" + counter++, 0, this.getSourceLocation(), new ArrayList(),shadow.getEnclosingClass().isInterface());
                                shadow.getRange().append(shadow.makeCallToCallback(newMethod));
 
                                if (!shadow.isFallsThrough()) {